From b00c77bc644a6be810ed369f1fe6516a014fb55f Mon Sep 17 00:00:00 2001 From: Adam Narozniak <51029327+adam-narozniak@users.noreply.github.com> Date: Thu, 18 Jan 2024 00:13:10 +0100 Subject: [PATCH 001/113] Migrate advanced-pytorch example to use FDS (#2805) Co-authored-by: jafermarq --- examples/advanced-pytorch/README.md | 9 +-- examples/advanced-pytorch/client.py | 41 +++++------- examples/advanced-pytorch/pyproject.toml | 1 + examples/advanced-pytorch/requirements.txt | 1 + examples/advanced-pytorch/run.sh | 9 +-- examples/advanced-pytorch/server.py | 21 +++--- examples/advanced-pytorch/utils.py | 77 +++++++++++----------- 7 files changed, 75 insertions(+), 84 deletions(-) diff --git a/examples/advanced-pytorch/README.md b/examples/advanced-pytorch/README.md index db0245e41453..2527e8e4a820 100644 --- a/examples/advanced-pytorch/README.md +++ b/examples/advanced-pytorch/README.md @@ -1,6 +1,6 @@ # Advanced Flower Example (PyTorch) -This example demonstrates an advanced federated learning setup using Flower with PyTorch. It differs from the quickstart example in the following ways: +This example demonstrates an advanced federated learning setup using Flower with PyTorch. This example uses [Flower Datasets](https://flower.dev/docs/datasets/) and it differs from the quickstart example in the following ways: - 10 clients (instead of just 2) - Each client holds a local dataset of 5000 training examples and 1000 test examples (note that using the `run.sh` script will only select 10 data samples by default, as the `--toy` argument is set). @@ -59,12 +59,13 @@ pip install -r requirements.txt The included `run.sh` will start the Flower server (using `server.py`), sleep for 2 seconds to ensure that the server is up, and then start 10 Flower clients (using `client.py`) with only a small subset of the data (in order to run on any machine), -but this can be changed by removing the `--toy True` argument in the script. You can simply start everything in a terminal as follows: +but this can be changed by removing the `--toy` argument in the script. You can simply start everything in a terminal as follows: ```shell -poetry run ./run.sh +# After activating your environment +./run.sh ``` The `run.sh` script starts processes in the background so that you don't have to open eleven terminal windows. If you experiment with the code example and something goes wrong, simply using `CTRL + C` on Linux (or `CMD + C` on macOS) wouldn't normally kill all these processes, which is why the script ends with `trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT` and `wait`. This simply allows you to stop the experiment using `CTRL + C` (or `CMD + C`). If you change the script and anything goes wrong you can still use `killall python` (or `killall python3`) to kill all background processes (or a more specific command if you have other Python processes running that you don't want to kill). -You can also manually run `poetry run python3 server.py` and `poetry run python3 client.py` for as many clients as you want but you have to make sure that each command is ran in a different terminal window (or a different computer on the network). +You can also manually run `python3 server.py` and `python3 client.py --client-id ` for as many clients as you want but you have to make sure that each command is run in a different terminal window (or a different computer on the network). diff --git a/examples/advanced-pytorch/client.py b/examples/advanced-pytorch/client.py index f9ffb6181fd8..b22cbcd70465 100644 --- a/examples/advanced-pytorch/client.py +++ b/examples/advanced-pytorch/client.py @@ -6,6 +6,7 @@ import argparse from collections import OrderedDict import warnings +import datasets warnings.filterwarnings("ignore") @@ -13,9 +14,9 @@ class CifarClient(fl.client.NumPyClient): def __init__( self, - trainset: torchvision.datasets, - testset: torchvision.datasets, - device: str, + trainset: datasets.Dataset, + testset: datasets.Dataset, + device: torch.device, validation_split: int = 0.1, ): self.device = device @@ -41,17 +42,14 @@ def fit(self, parameters, config): batch_size: int = config["batch_size"] epochs: int = config["local_epochs"] - n_valset = int(len(self.trainset) * self.validation_split) + train_valid = self.trainset.train_test_split(self.validation_split) + trainset = train_valid["train"] + valset = train_valid["test"] - valset = torch.utils.data.Subset(self.trainset, range(0, n_valset)) - trainset = torch.utils.data.Subset( - self.trainset, range(n_valset, len(self.trainset)) - ) + train_loader = DataLoader(trainset, batch_size=batch_size, shuffle=True) + val_loader = DataLoader(valset, batch_size=batch_size) - trainLoader = DataLoader(trainset, batch_size=batch_size, shuffle=True) - valLoader = DataLoader(valset, batch_size=batch_size) - - results = utils.train(model, trainLoader, valLoader, epochs, self.device) + results = utils.train(model, train_loader, val_loader, epochs, self.device) parameters_prime = utils.get_model_params(model) num_examples_train = len(trainset) @@ -73,13 +71,13 @@ def evaluate(self, parameters, config): return float(loss), len(self.testset), {"accuracy": float(accuracy)} -def client_dry_run(device: str = "cpu"): +def client_dry_run(device: torch.device = "cpu"): """Weak tests to check whether all client methods are working as expected.""" model = utils.load_efficientnet(classes=10) trainset, testset = utils.load_partition(0) - trainset = torch.utils.data.Subset(trainset, range(10)) - testset = torch.utils.data.Subset(testset, range(10)) + trainset = trainset.select(range(10)) + testset = testset.select(range(10)) client = CifarClient(trainset, testset, device) client.fit( utils.get_model_params(model), @@ -102,7 +100,7 @@ def main() -> None: help="Do a dry-run to check the client", ) parser.add_argument( - "--partition", + "--client-id", type=int, default=0, choices=range(0, 10), @@ -112,9 +110,7 @@ def main() -> None: ) parser.add_argument( "--toy", - type=bool, - default=False, - required=False, + action='store_true', help="Set to true to quicky run the client using only 10 datasamples. \ Useful for testing purposes. Default: False", ) @@ -136,12 +132,11 @@ def main() -> None: client_dry_run(device) else: # Load a subset of CIFAR-10 to simulate the local data partition - trainset, testset = utils.load_partition(args.partition) + trainset, testset = utils.load_partition(args.client_id) if args.toy: - trainset = torch.utils.data.Subset(trainset, range(10)) - testset = torch.utils.data.Subset(testset, range(10)) - + trainset = trainset.select(range(10)) + testset = testset.select(range(10)) # Start Flower client client = CifarClient(trainset, testset, device) diff --git a/examples/advanced-pytorch/pyproject.toml b/examples/advanced-pytorch/pyproject.toml index a12f3c47de70..89fd5a32a89e 100644 --- a/examples/advanced-pytorch/pyproject.toml +++ b/examples/advanced-pytorch/pyproject.toml @@ -14,6 +14,7 @@ authors = [ [tool.poetry.dependencies] python = ">=3.8,<3.11" flwr = ">=1.0,<2.0" +flwr-datasets = { extras = ["vision"], version = ">=0.0.2,<1.0.0" } torch = "1.13.1" torchvision = "0.14.1" validators = "0.18.2" diff --git a/examples/advanced-pytorch/requirements.txt b/examples/advanced-pytorch/requirements.txt index ba7b284df90e..f4d6a0774162 100644 --- a/examples/advanced-pytorch/requirements.txt +++ b/examples/advanced-pytorch/requirements.txt @@ -1,4 +1,5 @@ flwr>=1.0, <2.0 +flwr-datasets[vision]>=0.0.2, <1.0.0 torch==1.13.1 torchvision==0.14.1 validators==0.18.2 diff --git a/examples/advanced-pytorch/run.sh b/examples/advanced-pytorch/run.sh index 212285f504f9..3367e1680535 100755 --- a/examples/advanced-pytorch/run.sh +++ b/examples/advanced-pytorch/run.sh @@ -2,20 +2,17 @@ set -e cd "$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"/ -# Download the CIFAR-10 dataset -python -c "from torchvision.datasets import CIFAR10; CIFAR10('./dataset', download=True)" - # Download the EfficientNetB0 model python -c "import torch; torch.hub.load( \ 'NVIDIA/DeepLearningExamples:torchhub', \ 'nvidia_efficientnet_b0', pretrained=True)" -python server.py & -sleep 3 # Sleep for 3s to give the server enough time to start +python server.py --toy & +sleep 10 # Sleep for 10s to give the server enough time to start and dowload the dataset for i in `seq 0 9`; do echo "Starting client $i" - python client.py --partition=${i} --toy True & + python client.py --client-id=${i} --toy & done # Enable CTRL+C to stop all background processes diff --git a/examples/advanced-pytorch/server.py b/examples/advanced-pytorch/server.py index 8343e62da69f..fda49b71a311 100644 --- a/examples/advanced-pytorch/server.py +++ b/examples/advanced-pytorch/server.py @@ -10,6 +10,8 @@ import warnings +from flwr_datasets import FederatedDataset + warnings.filterwarnings("ignore") @@ -39,18 +41,13 @@ def evaluate_config(server_round: int): def get_evaluate_fn(model: torch.nn.Module, toy: bool): """Return an evaluation function for server-side evaluation.""" - # Load data and model here to avoid the overhead of doing it in `evaluate` itself - trainset, _, _ = utils.load_data() - - n_train = len(trainset) + # Load data here to avoid the overhead of doing it in `evaluate` itself + centralized_data = utils.load_centralized_data() if toy: # use only 10 samples as validation set - valset = torch.utils.data.Subset(trainset, range(n_train - 10, n_train)) - else: - # Use the last 5k training examples as a validation set - valset = torch.utils.data.Subset(trainset, range(n_train - 5000, n_train)) + centralized_data = centralized_data.select(range(10)) - valLoader = DataLoader(valset, batch_size=16) + val_loader = DataLoader(centralized_data, batch_size=16) # The `evaluate` function will be called after every round def evaluate( @@ -63,7 +60,7 @@ def evaluate( state_dict = OrderedDict({k: torch.tensor(v) for k, v in params_dict}) model.load_state_dict(state_dict, strict=True) - loss, accuracy = utils.test(model, valLoader) + loss, accuracy = utils.test(model, val_loader) return loss, {"accuracy": accuracy} return evaluate @@ -79,9 +76,7 @@ def main(): parser = argparse.ArgumentParser(description="Flower") parser.add_argument( "--toy", - type=bool, - default=False, - required=False, + action='store_true', help="Set to true to use only 10 datasamples for validation. \ Useful for testing purposes. Default: False", ) diff --git a/examples/advanced-pytorch/utils.py b/examples/advanced-pytorch/utils.py index 8788ead90dee..6512010b1f23 100644 --- a/examples/advanced-pytorch/utils.py +++ b/examples/advanced-pytorch/utils.py @@ -1,49 +1,45 @@ import torch -import torchvision.transforms as transforms -from torchvision.datasets import CIFAR10 +from torchvision.transforms import Compose, ToTensor, Normalize, Resize, CenterCrop +from torch.utils.data import DataLoader import warnings -warnings.filterwarnings("ignore") - -# DEVICE = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") +from flwr_datasets import FederatedDataset +warnings.filterwarnings("ignore") -def load_data(): - """Load CIFAR-10 (training and test set).""" - transform = transforms.Compose( - [ - transforms.Resize(256), - transforms.CenterCrop(224), - transforms.ToTensor(), - transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), - ] - ) - trainset = CIFAR10("./dataset", train=True, download=True, transform=transform) - testset = CIFAR10("./dataset", train=False, download=True, transform=transform) +def load_partition(node_id, toy: bool = False): + """Load partition CIFAR10 data.""" + fds = FederatedDataset(dataset="cifar10", partitioners={"train": 10}) + partition = fds.load_partition(node_id) + # Divide data on each node: 80% train, 20% test + partition_train_test = partition.train_test_split(test_size=0.2) + partition_train_test = partition_train_test.with_transform(apply_transforms) + return partition_train_test["train"], partition_train_test["test"] - num_examples = {"trainset": len(trainset), "testset": len(testset)} - return trainset, testset, num_examples +def load_centralized_data(): + fds = FederatedDataset(dataset="cifar10", partitioners={"train": 10}) + centralized_data = fds.load_full("test") + centralized_data = centralized_data.with_transform(apply_transforms) + return centralized_data -def load_partition(idx: int): - """Load 1/10th of the training and test data to simulate a partition.""" - assert idx in range(10) - trainset, testset, num_examples = load_data() - n_train = int(num_examples["trainset"] / 10) - n_test = int(num_examples["testset"] / 10) - train_parition = torch.utils.data.Subset( - trainset, range(idx * n_train, (idx + 1) * n_train) - ) - test_parition = torch.utils.data.Subset( - testset, range(idx * n_test, (idx + 1) * n_test) - ) - return (train_parition, test_parition) +def apply_transforms(batch): + """Apply transforms to the partition from FederatedDataset.""" + pytorch_transforms = Compose([ + Resize(256), + CenterCrop(224), + ToTensor(), + Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), + ]) + batch["img"] = [pytorch_transforms(img) for img in batch["img"]] + return batch -def train(net, trainloader, valloader, epochs, device: str = "cpu"): +def train(net, trainloader, valloader, epochs, + device: torch.device = torch.device("cpu")): """Train the network on the training set.""" print("Starting training...") net.to(device) # move model to GPU if available @@ -53,7 +49,8 @@ def train(net, trainloader, valloader, epochs, device: str = "cpu"): ) net.train() for _ in range(epochs): - for images, labels in trainloader: + for batch in trainloader: + images, labels = batch["img"], batch["label"] images, labels = images.to(device), labels.to(device) optimizer.zero_grad() loss = criterion(net(images), labels) @@ -74,7 +71,8 @@ def train(net, trainloader, valloader, epochs, device: str = "cpu"): return results -def test(net, testloader, steps: int = None, device: str = "cpu"): +def test(net, testloader, steps: int = None, + device: torch.device = torch.device("cpu")): """Validate the network on the entire test set.""" print("Starting evalutation...") net.to(device) # move model to GPU if available @@ -82,7 +80,8 @@ def test(net, testloader, steps: int = None, device: str = "cpu"): correct, loss = 0, 0.0 net.eval() with torch.no_grad(): - for batch_idx, (images, labels) in enumerate(testloader): + for batch_idx, batch in enumerate(testloader): + images, labels = batch["img"], batch["label"] images, labels = images.to(device), labels.to(device) outputs = net(images) loss += criterion(outputs, labels).item() @@ -109,12 +108,14 @@ def load_efficientnet(entrypoint: str = "nvidia_efficientnet_b0", classes: int = entrypoint: EfficientNet model to download. For supported entrypoints, please refer https://pytorch.org/hub/nvidia_deeplearningexamples_efficientnet/ - classes: Number of classes in final classifying layer. Leave as None to get the downloaded + classes: Number of classes in final classifying layer. Leave as None to get + the downloaded model untouched. Returns: EfficientNet Model - Note: One alternative implementation can be found at https://github.com/lukemelas/EfficientNet-PyTorch + Note: One alternative implementation can be found at + https://github.com/lukemelas/EfficientNet-PyTorch """ efficientnet = torch.hub.load( "NVIDIA/DeepLearningExamples:torchhub", entrypoint, pretrained=True From 6cea1c77c0d0540662ac898327a60612bbca2302 Mon Sep 17 00:00:00 2001 From: Adam Narozniak <51029327+adam-narozniak@users.noreply.github.com> Date: Thu, 18 Jan 2024 00:23:09 +0100 Subject: [PATCH 002/113] Migrate advanced TensorFlow to use FDS (#2806) Co-authored-by: jafermarq --- examples/advanced-tensorflow/README.md | 9 +++--- examples/advanced-tensorflow/client.py | 29 ++++++++++--------- examples/advanced-tensorflow/pyproject.toml | 1 + examples/advanced-tensorflow/requirements.txt | 1 + examples/advanced-tensorflow/run.sh | 9 ++---- examples/advanced-tensorflow/server.py | 14 +++++---- 6 files changed, 33 insertions(+), 30 deletions(-) diff --git a/examples/advanced-tensorflow/README.md b/examples/advanced-tensorflow/README.md index 31bf5edb64c6..b21c0d2545ca 100644 --- a/examples/advanced-tensorflow/README.md +++ b/examples/advanced-tensorflow/README.md @@ -1,9 +1,9 @@ # Advanced Flower Example (TensorFlow/Keras) -This example demonstrates an advanced federated learning setup using Flower with TensorFlow/Keras. It differs from the quickstart example in the following ways: +This example demonstrates an advanced federated learning setup using Flower with TensorFlow/Keras. This example uses [Flower Datasets](https://flower.dev/docs/datasets/) and it differs from the quickstart example in the following ways: - 10 clients (instead of just 2) -- Each client holds a local dataset of 5000 training examples and 1000 test examples (note that by default only a small subset of this data is used when running the `run.sh` script) +- Each client holds a local dataset of 1/10 of the train datasets and 80% is training examples and 20% as test examples (note that by default only a small subset of this data is used when running the `run.sh` script) - Server-side model evaluation after parameter aggregation - Hyperparameter schedule using config functions - Custom return values @@ -57,10 +57,11 @@ pip install -r requirements.txt ## Run Federated Learning with TensorFlow/Keras and Flower -The included `run.sh` will call a script to generate certificates (which will be used by server and clients), start the Flower server (using `server.py`), sleep for 2 seconds to ensure the the server is up, and then start 10 Flower clients (using `client.py`). You can simply start everything in a terminal as follows: +The included `run.sh` will call a script to generate certificates (which will be used by server and clients), start the Flower server (using `server.py`), sleep for 10 seconds to ensure the the server is up, and then start 10 Flower clients (using `client.py`). You can simply start everything in a terminal as follows: ```shell -poetry run ./run.sh +# Once you have activated your environment +./run.sh ``` The `run.sh` script starts processes in the background so that you don't have to open eleven terminal windows. If you experiment with the code example and something goes wrong, simply using `CTRL + C` on Linux (or `CMD + C` on macOS) wouldn't normally kill all these processes, which is why the script ends with `trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT` and `wait`. This simply allows you to stop the experiment using `CTRL + C` (or `CMD + C`). If you change the script and anything goes wrong you can still use `killall python` (or `killall python3`) to kill all background processes (or a more specific command if you have other Python processes running that you don't want to kill). diff --git a/examples/advanced-tensorflow/client.py b/examples/advanced-tensorflow/client.py index 1c0b61575635..033f20b1b027 100644 --- a/examples/advanced-tensorflow/client.py +++ b/examples/advanced-tensorflow/client.py @@ -6,6 +6,8 @@ import flwr as fl +from flwr_datasets import FederatedDataset + # Make TensorFlow logs less verbose os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3" @@ -74,7 +76,7 @@ def main() -> None: # Parse command line argument `partition` parser = argparse.ArgumentParser(description="Flower") parser.add_argument( - "--partition", + "--client-id", type=int, default=0, choices=range(0, 10), @@ -84,9 +86,7 @@ def main() -> None: ) parser.add_argument( "--toy", - type=bool, - default=False, - required=False, + action='store_true', help="Set to true to quicky run the client using only 10 datasamples. " "Useful for testing purposes. Default: False", ) @@ -99,7 +99,7 @@ def main() -> None: model.compile("adam", "sparse_categorical_crossentropy", metrics=["accuracy"]) # Load a subset of CIFAR-10 to simulate the local data partition - (x_train, y_train), (x_test, y_test) = load_partition(args.partition) + x_train, y_train, x_test, y_test = load_partition(args.client_id) if args.toy: x_train, y_train = x_train[:10], y_train[:10] @@ -117,15 +117,16 @@ def main() -> None: def load_partition(idx: int): """Load 1/10th of the training and test data to simulate a partition.""" - assert idx in range(10) - (x_train, y_train), (x_test, y_test) = tf.keras.datasets.cifar10.load_data() - return ( - x_train[idx * 5000 : (idx + 1) * 5000], - y_train[idx * 5000 : (idx + 1) * 5000], - ), ( - x_test[idx * 1000 : (idx + 1) * 1000], - y_test[idx * 1000 : (idx + 1) * 1000], - ) + # Download and partition dataset + fds = FederatedDataset(dataset="cifar10", partitioners={"train": 10}) + partition = fds.load_partition(idx) + partition.set_format("numpy") + + # Divide data on each node: 80% train, 20% test + partition = partition.train_test_split(test_size=0.2) + x_train, y_train = partition["train"]["img"] / 255.0, partition["train"]["label"] + x_test, y_test = partition["test"]["img"] / 255.0, partition["test"]["label"] + return x_train, y_train, x_test, y_test if __name__ == "__main__": diff --git a/examples/advanced-tensorflow/pyproject.toml b/examples/advanced-tensorflow/pyproject.toml index 293ba64b3f43..2f16d8a15584 100644 --- a/examples/advanced-tensorflow/pyproject.toml +++ b/examples/advanced-tensorflow/pyproject.toml @@ -11,5 +11,6 @@ authors = ["The Flower Authors "] [tool.poetry.dependencies] python = ">=3.8,<3.11" flwr = ">=1.0,<2.0" +flwr-datasets = { extras = ["vision"], version = ">=0.0.2,<1.0.0" } tensorflow-cpu = {version = ">=2.9.1,<2.11.1 || >2.11.1", markers = "platform_machine == \"x86_64\""} tensorflow-macos = {version = ">=2.9.1,<2.11.1 || >2.11.1", markers = "sys_platform == \"darwin\" and platform_machine == \"arm64\""} diff --git a/examples/advanced-tensorflow/requirements.txt b/examples/advanced-tensorflow/requirements.txt index 7a70c46a8128..0cb5fe8c07af 100644 --- a/examples/advanced-tensorflow/requirements.txt +++ b/examples/advanced-tensorflow/requirements.txt @@ -1,3 +1,4 @@ flwr>=1.0, <2.0 +flwr-datasets = { extras = ["vision"], version = ">=0.0.2,<1.0.0" } tensorflow-cpu>=2.9.1, != 2.11.1 ; platform_machine == "x86_64" tensorflow-macos>=2.9.1, != 2.11.1 ; sys_platform == "darwin" and platform_machine == "arm64" diff --git a/examples/advanced-tensorflow/run.sh b/examples/advanced-tensorflow/run.sh index 8ddb6a252b52..4acef1371571 100755 --- a/examples/advanced-tensorflow/run.sh +++ b/examples/advanced-tensorflow/run.sh @@ -5,14 +5,11 @@ echo "Starting server" python server.py & -sleep 3 # Sleep for 3s to give the server enough time to start +sleep 10 # Sleep for 10s to give the server enough time to start and download the dataset -# Ensure that the Keras dataset used in client.py is already cached. -python -c "import tensorflow as tf; tf.keras.datasets.cifar10.load_data()" - -for i in `seq 0 9`; do +for i in $(seq 0 9); do echo "Starting client $i" - python client.py --partition=${i} --toy True & + python client.py --client-id=${i} --toy & done # This will allow you to use CTRL+C to stop all background processes diff --git a/examples/advanced-tensorflow/server.py b/examples/advanced-tensorflow/server.py index e1eb3d4fd8f7..26dde312bee5 100644 --- a/examples/advanced-tensorflow/server.py +++ b/examples/advanced-tensorflow/server.py @@ -4,6 +4,8 @@ import flwr as fl import tensorflow as tf +from flwr_datasets import FederatedDataset + def main() -> None: # Load and compile model for @@ -43,11 +45,11 @@ def main() -> None: def get_evaluate_fn(model): """Return an evaluation function for server-side evaluation.""" - # Load data and model here to avoid the overhead of doing it in `evaluate` itself - (x_train, y_train), _ = tf.keras.datasets.cifar10.load_data() - - # Use the last 5k training examples as a validation set - x_val, y_val = x_train[45000:50000], y_train[45000:50000] + # Load data here to avoid the overhead of doing it in `evaluate` itself + fds = FederatedDataset(dataset="cifar10", partitioners={"train": 10}) + test = fds.load_full("test") + test.set_format("numpy") + x_test, y_test = test["img"] / 255.0, test["label"] # The `evaluate` function will be called after every round def evaluate( @@ -56,7 +58,7 @@ def evaluate( config: Dict[str, fl.common.Scalar], ) -> Optional[Tuple[float, Dict[str, fl.common.Scalar]]]: model.set_weights(parameters) # Update model with the latest parameters - loss, accuracy = model.evaluate(x_val, y_val) + loss, accuracy = model.evaluate(x_test, y_test) return loss, {"accuracy": accuracy} return evaluate From c30f8b0c4177d9564aaef2916d3b6027dab64b4b Mon Sep 17 00:00:00 2001 From: Javier Date: Thu, 18 Jan 2024 12:45:44 +0000 Subject: [PATCH 003/113] Add `MetricsRecord` (#2802) Co-authored-by: Heng Pan Co-authored-by: Daniel J. Beutel --- src/py/flwr/common/metricsrecord.py | 96 ++++++++++++++++++++++ src/py/flwr/common/recordset.py | 6 +- src/py/flwr/common/recordset_test.py | 114 ++++++++++++++++++++++++++- src/py/flwr/common/typing.py | 5 ++ 4 files changed, 214 insertions(+), 7 deletions(-) create mode 100644 src/py/flwr/common/metricsrecord.py diff --git a/src/py/flwr/common/metricsrecord.py b/src/py/flwr/common/metricsrecord.py new file mode 100644 index 000000000000..68eca732efa2 --- /dev/null +++ b/src/py/flwr/common/metricsrecord.py @@ -0,0 +1,96 @@ +# Copyright 2024 Flower Labs GmbH. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""MetricsRecord.""" + + +from dataclasses import dataclass, field +from typing import Dict, Optional, get_args + +from .typing import MetricsRecordValues, MetricsScalar + + +@dataclass +class MetricsRecord: + """Metrics record.""" + + keep_input: bool + data: Dict[str, MetricsRecordValues] = field(default_factory=dict) + + def __init__( + self, + metrics_dict: Optional[Dict[str, MetricsRecordValues]] = None, + keep_input: bool = True, + ): + """Construct a MetricsRecord object. + + Parameters + ---------- + metrics_dict : Optional[Dict[str, MetricsRecordValues]] + A dictionary that stores basic types (i.e. `int`, `float` as defined + in `MetricsScalar`) and list of such types (see `MetricsScalarList`). + keep_input : bool (default: True) + A boolean indicating whether metrics should be deleted from the input + dictionary immediately after adding them to the record. When set + to True, the data is duplicated in memory. If memory is a concern, set + it to False. + """ + self.keep_input = keep_input + self.data = {} + if metrics_dict: + self.set_metrics(metrics_dict) + + def set_metrics(self, metrics_dict: Dict[str, MetricsRecordValues]) -> None: + """Add metrics to the record. + + Parameters + ---------- + metrics_dict : Dict[str, MetricsRecordValues] + A dictionary that stores basic types (i.e. `int`, `float` as defined + in `MetricsScalar`) and list of such types (see `MetricsScalarList`). + """ + if any(not isinstance(k, str) for k in metrics_dict.keys()): + raise TypeError(f"Not all keys are of valid type. Expected {str}.") + + def is_valid(value: MetricsScalar) -> None: + """Check if value is of expected type.""" + if not isinstance(value, get_args(MetricsScalar)): + raise TypeError( + "Not all values are of valid type." + f" Expected {MetricsRecordValues} but you passed {type(value)}." + ) + + # Check types of values + # Split between those values that are list and those that aren't + # then process in the same way + for value in metrics_dict.values(): + if isinstance(value, list): + # If your lists are large (e.g. 1M+ elements) this will be slow + # 1s to check 10M element list on a M2 Pro + # In such settings, you'd be better of treating such metric as + # an array and pass it to a ParametersRecord. + for list_value in value: + is_valid(list_value) + else: + is_valid(value) + + # Add metrics to record + if self.keep_input: + # Copy + self.data = metrics_dict.copy() + else: + # Add entries to dataclass without duplicating memory + for key in list(metrics_dict.keys()): + self.data[key] = metrics_dict[key] + del metrics_dict[key] diff --git a/src/py/flwr/common/recordset.py b/src/py/flwr/common/recordset.py index dc723a2cea86..a5af909911fe 100644 --- a/src/py/flwr/common/recordset.py +++ b/src/py/flwr/common/recordset.py @@ -17,14 +17,10 @@ from dataclasses import dataclass, field from typing import Dict +from .metricsrecord import MetricsRecord from .parametersrecord import ParametersRecord -@dataclass -class MetricsRecord: - """Metrics record.""" - - @dataclass class ConfigsRecord: """Configs record.""" diff --git a/src/py/flwr/common/recordset_test.py b/src/py/flwr/common/recordset_test.py index 90c06dcdb109..26b2b4976e13 100644 --- a/src/py/flwr/common/recordset_test.py +++ b/src/py/flwr/common/recordset_test.py @@ -15,18 +15,19 @@ """RecordSet tests.""" -from typing import Callable, List, OrderedDict, Type, Union +from typing import Callable, Dict, List, OrderedDict, Type, Union import numpy as np import pytest +from .metricsrecord import MetricsRecord from .parameter import ndarrays_to_parameters, parameters_to_ndarrays from .parametersrecord import Array, ParametersRecord from .recordset_utils import ( parameters_to_parametersrecord, parametersrecord_to_parameters, ) -from .typing import NDArray, NDArrays, Parameters +from .typing import MetricsRecordValues, NDArray, NDArrays, Parameters def get_ndarrays() -> NDArrays: @@ -145,3 +146,112 @@ def test_set_parameters_with_incorrect_types( with pytest.raises(TypeError): p_record.set_parameters(array_dict) # type: ignore + + +@pytest.mark.parametrize( + "key_type, value_fn", + [ + (str, lambda x: int(x.flatten()[0])), # str: int + (str, lambda x: float(x.flatten()[0])), # str: float + (str, lambda x: x.flatten().astype("int").tolist()), # str: List[int] + (str, lambda x: x.flatten().astype("float").tolist()), # str: List[float] + ], +) +def test_set_metrics_to_metricsrecord_with_correct_types( + key_type: Type[str], + value_fn: Callable[[NDArray], MetricsRecordValues], +) -> None: + """Test adding metrics of various types to a MetricsRecord.""" + m_record = MetricsRecord() + + labels = [1, 2.0] + arrays = get_ndarrays() + + my_metrics = OrderedDict( + {key_type(label): value_fn(arr) for label, arr in zip(labels, arrays)} + ) + + # Add metric + m_record.set_metrics(my_metrics) + + # Check metrics are actually added + assert my_metrics == m_record.data + + +@pytest.mark.parametrize( + "key_type, value_fn", + [ + (str, lambda x: str(x.flatten()[0])), # str: str (supported: unsupported) + ( + str, + lambda x: x.flatten().astype("str").tolist(), + ), # str: List[str] (supported: unsupported) + (str, lambda x: x), # str: NDArray (supported: unsupported) + ( + str, + lambda x: {str(v): v for v in x.flatten()}, + ), # str: dict[str: float] (supported: unsupported) + ( + str, + lambda x: [{str(v): v for v in x.flatten()}], + ), # str: List[dict[str: float]] (supported: unsupported) + ( + int, + lambda x: x.flatten().tolist(), + ), # int: List[str] (unsupported: supported) + ( + float, + lambda x: x.flatten().tolist(), + ), # float: List[int] (unsupported: supported) + ], +) +def test_set_metrics_to_metricsrecord_with_incorrect_types( + key_type: Type[Union[str, int, float]], + value_fn: Callable[[NDArray], Union[NDArray, Dict[str, NDArray], List[float]]], +) -> None: + """Test adding metrics of various unsupported types to a MetricsRecord.""" + m_record = MetricsRecord() + + labels = [1, 2.0] + arrays = get_ndarrays() + + my_metrics = OrderedDict( + {key_type(label): value_fn(arr) for label, arr in zip(labels, arrays)} + ) + + with pytest.raises(TypeError): + m_record.set_metrics(my_metrics) # type: ignore + + +@pytest.mark.parametrize( + "keep_input", + [ + (True), + (False), + ], +) +def test_set_metrics_to_metricsrecord_with_and_without_keeping_input( + keep_input: bool, +) -> None: + """Test keep_input functionality for MetricsRecord.""" + m_record = MetricsRecord(keep_input=keep_input) + + # constructing a valid input + labels = [1, 2.0] + arrays = get_ndarrays() + my_metrics = OrderedDict( + {str(label): arr.flatten().tolist() for label, arr in zip(labels, arrays)} + ) + + my_metrics_copy = my_metrics.copy() + + # Add metric + m_record.set_metrics(my_metrics) + + # Check metrics are actually added + # Check that input dict has been emptied when enabled such behaviour + if keep_input: + assert my_metrics == m_record.data + else: + assert my_metrics_copy == m_record.data + assert len(my_metrics) == 0 diff --git a/src/py/flwr/common/typing.py b/src/py/flwr/common/typing.py index 6c0266f5eec8..a8196126ecfc 100644 --- a/src/py/flwr/common/typing.py +++ b/src/py/flwr/common/typing.py @@ -45,6 +45,11 @@ List[str], ] +# Value types for common.MetricsRecord +MetricsScalar = Union[int, float] +MetricsScalarList = Union[List[int], List[float]] +MetricsRecordValues = Union[MetricsScalar, MetricsScalarList] + Metrics = Dict[str, Scalar] MetricsAggregationFn = Callable[[List[Tuple[int, Metrics]]], Metrics] From c83b47b92807716e6075f28a3b880e700b0f35f0 Mon Sep 17 00:00:00 2001 From: Javier Date: Thu, 18 Jan 2024 13:36:22 +0000 Subject: [PATCH 004/113] Add `ConfigsRecord` (#2803) Co-authored-by: Daniel J. Beutel Co-authored-by: Heng Pan --- src/py/flwr/common/configsrecord.py | 98 ++++++++++++++++++++++++++++ src/py/flwr/common/recordset.py | 7 +- src/py/flwr/common/recordset_test.py | 80 ++++++++++++++++++++++- src/py/flwr/common/typing.py | 4 ++ 4 files changed, 183 insertions(+), 6 deletions(-) create mode 100644 src/py/flwr/common/configsrecord.py diff --git a/src/py/flwr/common/configsrecord.py b/src/py/flwr/common/configsrecord.py new file mode 100644 index 000000000000..494cb88586ac --- /dev/null +++ b/src/py/flwr/common/configsrecord.py @@ -0,0 +1,98 @@ +# Copyright 2024 Flower Labs GmbH. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""ConfigsRecord.""" + + +from dataclasses import dataclass, field +from typing import Dict, Optional, get_args + +from .typing import ConfigsRecordValues, ConfigsScalar + + +@dataclass +class ConfigsRecord: + """Configs record.""" + + keep_input: bool + data: Dict[str, ConfigsRecordValues] = field(default_factory=dict) + + def __init__( + self, + configs_dict: Optional[Dict[str, ConfigsRecordValues]] = None, + keep_input: bool = True, + ): + """Construct a ConfigsRecord object. + + Parameters + ---------- + configs_dict : Optional[Dict[str, ConfigsRecordValues]] + A dictionary that stores basic types (i.e. `str`, `int`, `float`, `bytes` as + defined in `ConfigsScalar`) and lists of such types (see + `ConfigsScalarList`). + keep_input : bool (default: True) + A boolean indicating whether config passed should be deleted from the input + dictionary immediately after adding them to the record. When set + to True, the data is duplicated in memory. If memory is a concern, set + it to False. + """ + self.keep_input = keep_input + self.data = {} + if configs_dict: + self.set_configs(configs_dict) + + def set_configs(self, configs_dict: Dict[str, ConfigsRecordValues]) -> None: + """Add configs to the record. + + Parameters + ---------- + configs_dict : Dict[str, ConfigsRecordValues] + A dictionary that stores basic types (i.e. `str`,`int`, `float`, `bytes` as + defined in `ConfigsRecordValues`) and list of such types (see + `ConfigsScalarList`). + """ + if any(not isinstance(k, str) for k in configs_dict.keys()): + raise TypeError(f"Not all keys are of valid type. Expected {str}") + + def is_valid(value: ConfigsScalar) -> None: + """Check if value is of expected type.""" + if not isinstance(value, get_args(ConfigsScalar)): + raise TypeError( + "Not all values are of valid type." + f" Expected {ConfigsRecordValues} but you passed {type(value)}." + ) + + # Check types of values + # Split between those values that are list and those that aren't + # then process in the same way + for value in configs_dict.values(): + if isinstance(value, list): + # If your lists are large (e.g. 1M+ elements) this will be slow + # 1s to check 10M element list on a M2 Pro + # In such settings, you'd be better of treating such config as + # an array and pass it to a ParametersRecord. + for list_value in value: + is_valid(list_value) + else: + is_valid(value) + + # Add configs to record + if self.keep_input: + # Copy + self.data = configs_dict.copy() + else: + # Add entries to dataclass without duplicating memory + for key in list(configs_dict.keys()): + self.data[key] = configs_dict[key] + del configs_dict[key] diff --git a/src/py/flwr/common/recordset.py b/src/py/flwr/common/recordset.py index a5af909911fe..61c880c970b8 100644 --- a/src/py/flwr/common/recordset.py +++ b/src/py/flwr/common/recordset.py @@ -14,18 +14,15 @@ # ============================================================================== """RecordSet.""" + from dataclasses import dataclass, field from typing import Dict +from .configsrecord import ConfigsRecord from .metricsrecord import MetricsRecord from .parametersrecord import ParametersRecord -@dataclass -class ConfigsRecord: - """Configs record.""" - - @dataclass class RecordSet: """Definition of RecordSet.""" diff --git a/src/py/flwr/common/recordset_test.py b/src/py/flwr/common/recordset_test.py index 26b2b4976e13..3f0917d75cf5 100644 --- a/src/py/flwr/common/recordset_test.py +++ b/src/py/flwr/common/recordset_test.py @@ -20,6 +20,7 @@ import numpy as np import pytest +from .configsrecord import ConfigsRecord from .metricsrecord import MetricsRecord from .parameter import ndarrays_to_parameters, parameters_to_ndarrays from .parametersrecord import Array, ParametersRecord @@ -27,7 +28,13 @@ parameters_to_parametersrecord, parametersrecord_to_parameters, ) -from .typing import MetricsRecordValues, NDArray, NDArrays, Parameters +from .typing import ( + ConfigsRecordValues, + MetricsRecordValues, + NDArray, + NDArrays, + Parameters, +) def get_ndarrays() -> NDArrays: @@ -255,3 +262,74 @@ def test_set_metrics_to_metricsrecord_with_and_without_keeping_input( else: assert my_metrics_copy == m_record.data assert len(my_metrics) == 0 + + +@pytest.mark.parametrize( + "key_type, value_fn", + [ + (str, lambda x: str(x.flatten()[0])), # str: str + (str, lambda x: int(x.flatten()[0])), # str: int + (str, lambda x: float(x.flatten()[0])), # str: float + (str, lambda x: x.flatten().tobytes()), # str: bytes + (str, lambda x: x.flatten().astype("str").tolist()), # str: List[str] + (str, lambda x: x.flatten().astype("int").tolist()), # str: List[int] + (str, lambda x: x.flatten().astype("float").tolist()), # str: List[float] + (str, lambda x: [x.flatten().tobytes()]), # str: List[bytes] + ], +) +def test_set_configs_to_configsrecord_with_correct_types( + key_type: Type[str], + value_fn: Callable[[NDArray], ConfigsRecordValues], +) -> None: + """Test adding configs of various types to a ConfigsRecord.""" + labels = [1, 2.0] + arrays = get_ndarrays() + + my_configs = OrderedDict( + {key_type(label): value_fn(arr) for label, arr in zip(labels, arrays)} + ) + + c_record = ConfigsRecord(my_configs) + + # check values are actually there + assert c_record.data == my_configs + + +@pytest.mark.parametrize( + "key_type, value_fn", + [ + (str, lambda x: x), # str: NDArray (supported: unsupported) + ( + str, + lambda x: {str(v): v for v in x.flatten()}, + ), # str: dict[str: float] (supported: unsupported) + ( + str, + lambda x: [{str(v): v for v in x.flatten()}], + ), # str: List[dict[str: float]] (supported: unsupported) + ( + int, + lambda x: x.flatten().tolist(), + ), # int: List[str] (unsupported: supported) + ( + float, + lambda x: x.flatten().tolist(), + ), # float: List[int] (unsupported: supported) + ], +) +def test_set_configs_to_configsrecord_with_incorrect_types( + key_type: Type[Union[str, int, float]], + value_fn: Callable[[NDArray], Union[NDArray, Dict[str, NDArray], List[float]]], +) -> None: + """Test adding configs of various unsupported types to a ConfigsRecord.""" + m_record = ConfigsRecord() + + labels = [1, 2.0] + arrays = get_ndarrays() + + my_metrics = OrderedDict( + {key_type(label): value_fn(arr) for label, arr in zip(labels, arrays)} + ) + + with pytest.raises(TypeError): + m_record.set_configs(my_metrics) # type: ignore diff --git a/src/py/flwr/common/typing.py b/src/py/flwr/common/typing.py index a8196126ecfc..b247a9d2d9b5 100644 --- a/src/py/flwr/common/typing.py +++ b/src/py/flwr/common/typing.py @@ -49,6 +49,10 @@ MetricsScalar = Union[int, float] MetricsScalarList = Union[List[int], List[float]] MetricsRecordValues = Union[MetricsScalar, MetricsScalarList] +# Value types for common.ConfigsRecord +ConfigsScalar = Union[MetricsScalar, str, bytes] +ConfigsScalarList = Union[MetricsScalarList, List[str], List[bytes]] +ConfigsRecordValues = Union[ConfigsScalar, ConfigsScalarList] Metrics = Dict[str, Scalar] MetricsAggregationFn = Callable[[List[Tuple[int, Metrics]]], Metrics] From 1e78c0cf620487914f0215c1c664b2ce1eaa015b Mon Sep 17 00:00:00 2001 From: Charles Beauville Date: Thu, 18 Jan 2024 14:47:13 +0100 Subject: [PATCH 005/113] Update release doc (#2815) --- doc/source/contributor-how-to-release-flower.rst | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/doc/source/contributor-how-to-release-flower.rst b/doc/source/contributor-how-to-release-flower.rst index 2eef165c0ed0..acfac4197ec1 100644 --- a/doc/source/contributor-how-to-release-flower.rst +++ b/doc/source/contributor-how-to-release-flower.rst @@ -3,23 +3,15 @@ Release Flower This document describes the current release process. It may or may not change in the future. -Before the release ------------------- - -Update the changelog (``changelog.md``) with all relevant changes that happened after the last release. If the last release was tagged ``v1.2.0``, you can use the following URL to see all commits that got merged into ``main`` since then: - -`GitHub: Compare v1.2.0...main `_ - -Thank the authors who contributed since the last release. This can be done by running the ``./dev/add-shortlog.sh `` convenience script (it can be ran multiple times and will update the names in the list if new contributors were added in the meantime). - During the release ------------------ The version number of a release is stated in ``pyproject.toml``. To release a new version of Flower, the following things need to happen (in that order): -1. Update the ``changelog.md`` section header ``Unreleased`` to contain the version number and date for the release you are building. Create a pull request with the change. -2. Tag the release commit with the version number as soon as the PR is merged: ``git tag v0.12.3``, then ``git push --tags``. This will create a draft release on GitHub containing the correct artifacts and the relevant part of the changelog. -3. Check the draft release on GitHub, and if everything is good, publish it. +1. Run ``python3 src/py/flwr_tool/update_changelog.py `` in order to add every new change to the changelog (feel free to make manual changes to the changelog afterwards until it looks good). +2. Once the changelog has been updated with all the changes, run ``./dev/prepare-release-changelog.sh v``, where ```` is the version stated in ``pyproject.toml`` (notice the ``v`` added before it). This will replace the ``Unreleased`` header of the changelog by the version and current date, and it will add a thanking message for the contributors. Open a pull request with those changes. +3. Once the pull request is merged, tag the release commit with the version number as soon as the PR is merged: ``git tag v`` (notice the ``v`` added before the version number), then ``git push --tags``. This will create a draft release on GitHub containing the correct artifacts and the relevant part of the changelog. +4. Check the draft release on GitHub, and if everything is good, publish it. After the release ----------------- From f3406c68fa2aebd6887efb3333f63cfb7b366d65 Mon Sep 17 00:00:00 2001 From: Charles Beauville Date: Thu, 18 Jan 2024 14:58:27 +0100 Subject: [PATCH 006/113] Update gRPC and ProtoBuf dependencies (#2814) --- pyproject.toml | 6 +- src/py/flwr/client/app.py | 2 +- src/py/flwr/client/grpc_client/connection.py | 11 +- .../client/grpc_client/connection_test.py | 7 +- .../client/grpc_rere_client/connection.py | 8 +- .../client/message_handler/message_handler.py | 13 +- .../message_handler/message_handler_test.py | 11 +- .../client/message_handler/task_handler.py | 11 +- .../message_handler/task_handler_test.py | 14 +- src/py/flwr/client/middleware/utils_test.py | 2 +- src/py/flwr/client/node_state_tests.py | 2 +- src/py/flwr/client/rest_client/connection.py | 6 +- src/py/flwr/client/typing.py | 2 +- src/py/flwr/common/serde.py | 4 +- src/py/flwr/common/serde_test.py | 10 +- src/py/flwr/driver/app.py | 8 +- src/py/flwr/driver/app_test.py | 7 +- src/py/flwr/driver/driver.py | 6 +- src/py/flwr/driver/driver_client_proxy.py | 39 +- .../flwr/driver/driver_client_proxy_test.py | 162 ++++---- src/py/flwr/driver/driver_test.py | 4 +- src/py/flwr/driver/grpc_driver.py | 4 +- src/py/flwr/proto/driver_pb2.py | 111 ++---- src/py/flwr/proto/fleet_pb2.py | 140 ++----- src/py/flwr/proto/node_pb2.py | 22 +- src/py/flwr/proto/task_pb2.py | 160 ++------ src/py/flwr/proto/transport_pb2.py | 347 ++++-------------- src/py/flwr/server/app.py | 12 +- src/py/flwr/server/driver/driver_servicer.py | 8 +- .../grpc_bidi/flower_service_servicer.py | 7 +- .../grpc_bidi/flower_service_servicer_test.py | 5 +- .../server/fleet/grpc_bidi/grpc_bridge.py | 5 +- .../fleet/grpc_bidi/grpc_bridge_test.py | 5 +- .../fleet/grpc_bidi/grpc_client_proxy.py | 5 +- .../fleet/grpc_bidi/grpc_client_proxy_test.py | 6 +- .../server/fleet/grpc_bidi/grpc_server.py | 4 +- .../server/fleet/grpc_bidi/ins_scheduler.py | 9 +- .../server/fleet/grpc_rere/fleet_servicer.py | 4 +- .../fleet/message_handler/message_handler.py | 6 +- .../message_handler/message_handler_test.py | 6 +- .../flwr/server/fleet/rest_rere/rest_api.py | 2 +- src/py/flwr/server/state/in_memory_state.py | 2 +- src/py/flwr/server/state/sqlite_state.py | 9 +- src/py/flwr/server/state/state.py | 2 +- src/py/flwr/server/state/state_test.py | 9 +- src/py/flwr/server/utils/validator.py | 2 +- src/py/flwr/server/utils/validator_test.py | 14 +- 47 files changed, 448 insertions(+), 793 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index cab083b32325..73a238615d60 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -61,8 +61,8 @@ flower-client = "flwr.client:run_client" python = "^3.8" # Mandatory dependencies numpy = "^1.21.0" -grpcio = "^1.48.2,!=1.52.0" -protobuf = "^3.19.0" +grpcio = "^1.60.0" +protobuf = "^4.25.2" cryptography = "^41.0.2" pycryptodome = "^3.18.0" iterators = "^0.0.2" @@ -93,7 +93,7 @@ flake8 = "==5.0.4" pytest = "==7.4.3" pytest-cov = "==4.1.0" pytest-watch = "==4.2.0" -grpcio-tools = "==1.48.2" +grpcio-tools = "==1.60.0" mypy-protobuf = "==3.2.0" jupyterlab = "==4.0.9" rope = "==1.11.0" diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index 91fa5468ae75..ae5beeae07d6 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -35,7 +35,7 @@ TRANSPORT_TYPES, ) from flwr.common.logger import log, warn_experimental_feature -from flwr.proto.task_pb2 import TaskIns, TaskRes +from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611 from .flower import load_flower_callable from .grpc_client.connection import grpc_connection diff --git a/src/py/flwr/client/grpc_client/connection.py b/src/py/flwr/client/grpc_client/connection.py index 481f32c77859..5f11912c587c 100644 --- a/src/py/flwr/client/grpc_client/connection.py +++ b/src/py/flwr/client/grpc_client/connection.py @@ -25,10 +25,13 @@ from flwr.common import GRPC_MAX_MESSAGE_LENGTH from flwr.common.grpc import create_channel from flwr.common.logger import log -from flwr.proto.node_pb2 import Node -from flwr.proto.task_pb2 import Task, TaskIns, TaskRes -from flwr.proto.transport_pb2 import ClientMessage, ServerMessage -from flwr.proto.transport_pb2_grpc import FlowerServiceStub +from flwr.proto.node_pb2 import Node # pylint: disable=E0611 +from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611 +from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 + ClientMessage, + ServerMessage, +) +from flwr.proto.transport_pb2_grpc import FlowerServiceStub # pylint: disable=E0611 # The following flags can be uncommented for debugging. Other possible values: # https://github.com/grpc/grpc/blob/master/doc/environment_variables.md diff --git a/src/py/flwr/client/grpc_client/connection_test.py b/src/py/flwr/client/grpc_client/connection_test.py index e5944230e5af..bcfa76bb36c0 100644 --- a/src/py/flwr/client/grpc_client/connection_test.py +++ b/src/py/flwr/client/grpc_client/connection_test.py @@ -23,8 +23,11 @@ import grpc -from flwr.proto.task_pb2 import Task, TaskRes -from flwr.proto.transport_pb2 import ClientMessage, ServerMessage +from flwr.proto.task_pb2 import Task, TaskRes # pylint: disable=E0611 +from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 + ClientMessage, + ServerMessage, +) from flwr.server.client_manager import SimpleClientManager from flwr.server.fleet.grpc_bidi.grpc_server import start_grpc_server diff --git a/src/py/flwr/client/grpc_rere_client/connection.py b/src/py/flwr/client/grpc_rere_client/connection.py index 30d407a52c53..cb1a7021dc9d 100644 --- a/src/py/flwr/client/grpc_rere_client/connection.py +++ b/src/py/flwr/client/grpc_rere_client/connection.py @@ -29,15 +29,15 @@ from flwr.common import GRPC_MAX_MESSAGE_LENGTH from flwr.common.grpc import create_channel from flwr.common.logger import log, warn_experimental_feature -from flwr.proto.fleet_pb2 import ( +from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611 CreateNodeRequest, DeleteNodeRequest, PullTaskInsRequest, PushTaskResRequest, ) -from flwr.proto.fleet_pb2_grpc import FleetStub -from flwr.proto.node_pb2 import Node -from flwr.proto.task_pb2 import TaskIns, TaskRes +from flwr.proto.fleet_pb2_grpc import FleetStub # pylint: disable=E0611 +from flwr.proto.node_pb2 import Node # pylint: disable=E0611 +from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611 KEY_NODE = "node" KEY_TASK_INS = "current_task_ins" diff --git a/src/py/flwr/client/message_handler/message_handler.py b/src/py/flwr/client/message_handler/message_handler.py index 3f30db2a4ea2..8cfe909c1738 100644 --- a/src/py/flwr/client/message_handler/message_handler.py +++ b/src/py/flwr/client/message_handler/message_handler.py @@ -32,8 +32,17 @@ from flwr.client.secure_aggregation import SecureAggregationHandler from flwr.client.typing import ClientFn from flwr.common import serde -from flwr.proto.task_pb2 import SecureAggregation, Task, TaskIns, TaskRes -from flwr.proto.transport_pb2 import ClientMessage, Reason, ServerMessage +from flwr.proto.task_pb2 import ( # pylint: disable=E0611 + SecureAggregation, + Task, + TaskIns, + TaskRes, +) +from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 + ClientMessage, + Reason, + ServerMessage, +) class UnexpectedServerMessage(Exception): diff --git a/src/py/flwr/client/message_handler/message_handler_test.py b/src/py/flwr/client/message_handler/message_handler_test.py index cd810ae220e9..194f75fe30ca 100644 --- a/src/py/flwr/client/message_handler/message_handler_test.py +++ b/src/py/flwr/client/message_handler/message_handler_test.py @@ -33,9 +33,14 @@ serde, typing, ) -from flwr.proto.node_pb2 import Node -from flwr.proto.task_pb2 import Task, TaskIns, TaskRes -from flwr.proto.transport_pb2 import ClientMessage, Code, ServerMessage, Status +from flwr.proto.node_pb2 import Node # pylint: disable=E0611 +from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611 +from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 + ClientMessage, + Code, + ServerMessage, + Status, +) from .message_handler import handle, handle_control_message diff --git a/src/py/flwr/client/message_handler/task_handler.py b/src/py/flwr/client/message_handler/task_handler.py index 3599e1dfb254..667cb9c98d46 100644 --- a/src/py/flwr/client/message_handler/task_handler.py +++ b/src/py/flwr/client/message_handler/task_handler.py @@ -17,10 +17,13 @@ from typing import Optional -from flwr.proto.fleet_pb2 import PullTaskInsResponse -from flwr.proto.node_pb2 import Node -from flwr.proto.task_pb2 import Task, TaskIns, TaskRes -from flwr.proto.transport_pb2 import ClientMessage, ServerMessage +from flwr.proto.fleet_pb2 import PullTaskInsResponse # pylint: disable=E0611 +from flwr.proto.node_pb2 import Node # pylint: disable=E0611 +from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611 +from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 + ClientMessage, + ServerMessage, +) def validate_task_ins(task_ins: TaskIns, discard_reconnect_ins: bool) -> bool: diff --git a/src/py/flwr/client/message_handler/task_handler_test.py b/src/py/flwr/client/message_handler/task_handler_test.py index 748ef63e72ef..c1111d0935c0 100644 --- a/src/py/flwr/client/message_handler/task_handler_test.py +++ b/src/py/flwr/client/message_handler/task_handler_test.py @@ -22,9 +22,17 @@ validate_task_res, wrap_client_message_in_task_res, ) -from flwr.proto.fleet_pb2 import PullTaskInsResponse -from flwr.proto.task_pb2 import SecureAggregation, Task, TaskIns, TaskRes -from flwr.proto.transport_pb2 import ClientMessage, ServerMessage +from flwr.proto.fleet_pb2 import PullTaskInsResponse # pylint: disable=E0611 +from flwr.proto.task_pb2 import ( # pylint: disable=E0611 + SecureAggregation, + Task, + TaskIns, + TaskRes, +) +from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 + ClientMessage, + ServerMessage, +) def test_validate_task_ins_no_task() -> None: diff --git a/src/py/flwr/client/middleware/utils_test.py b/src/py/flwr/client/middleware/utils_test.py index aa4358be5a51..006fe6db4799 100644 --- a/src/py/flwr/client/middleware/utils_test.py +++ b/src/py/flwr/client/middleware/utils_test.py @@ -20,7 +20,7 @@ from flwr.client.run_state import RunState from flwr.client.typing import Bwd, FlowerCallable, Fwd, Layer -from flwr.proto.task_pb2 import TaskIns, TaskRes +from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611 from .utils import make_ffn diff --git a/src/py/flwr/client/node_state_tests.py b/src/py/flwr/client/node_state_tests.py index 7a6bfcd31f08..7bc0d77d16cf 100644 --- a/src/py/flwr/client/node_state_tests.py +++ b/src/py/flwr/client/node_state_tests.py @@ -17,7 +17,7 @@ from flwr.client.node_state import NodeState from flwr.client.run_state import RunState -from flwr.proto.task_pb2 import TaskIns +from flwr.proto.task_pb2 import TaskIns # pylint: disable=E0611 def _run_dummy_task(state: RunState) -> RunState: diff --git a/src/py/flwr/client/rest_client/connection.py b/src/py/flwr/client/rest_client/connection.py index 87b06dd0be4e..bb55f130f1a8 100644 --- a/src/py/flwr/client/rest_client/connection.py +++ b/src/py/flwr/client/rest_client/connection.py @@ -29,7 +29,7 @@ from flwr.common import GRPC_MAX_MESSAGE_LENGTH from flwr.common.constant import MISSING_EXTRA_REST from flwr.common.logger import log -from flwr.proto.fleet_pb2 import ( +from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611 CreateNodeRequest, CreateNodeResponse, DeleteNodeRequest, @@ -38,8 +38,8 @@ PushTaskResRequest, PushTaskResResponse, ) -from flwr.proto.node_pb2 import Node -from flwr.proto.task_pb2 import TaskIns, TaskRes +from flwr.proto.node_pb2 import Node # pylint: disable=E0611 +from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611 try: import requests diff --git a/src/py/flwr/client/typing.py b/src/py/flwr/client/typing.py index 1652ee57674a..5291afb83d98 100644 --- a/src/py/flwr/client/typing.py +++ b/src/py/flwr/client/typing.py @@ -18,7 +18,7 @@ from typing import Callable from flwr.client.run_state import RunState -from flwr.proto.task_pb2 import TaskIns, TaskRes +from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611 from .client import Client as Client diff --git a/src/py/flwr/common/serde.py b/src/py/flwr/common/serde.py index 59f5387b0a07..a059d95af833 100644 --- a/src/py/flwr/common/serde.py +++ b/src/py/flwr/common/serde.py @@ -17,8 +17,8 @@ from typing import Any, Dict, List, MutableMapping, cast -from flwr.proto.task_pb2 import Value -from flwr.proto.transport_pb2 import ( +from flwr.proto.task_pb2 import Value # pylint: disable=E0611 +from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 ClientMessage, Code, Parameters, diff --git a/src/py/flwr/common/serde_test.py b/src/py/flwr/common/serde_test.py index ba07890f4658..2c61c28eb0ee 100644 --- a/src/py/flwr/common/serde_test.py +++ b/src/py/flwr/common/serde_test.py @@ -18,7 +18,7 @@ from typing import Dict, Union, cast from flwr.common import typing -from flwr.proto import transport_pb2 as pb2 +from flwr.proto import transport_pb2 as pb2 # pylint: disable=E0611 from .serde import ( named_values_from_proto, @@ -50,8 +50,8 @@ def test_serialisation_deserialisation() -> None: def test_status_to_proto() -> None: """Test status message (de-)serialization.""" # Prepare - code_msg = pb2.Code.OK - status_msg = pb2.Status(code=code_msg, message="Success") + code_msg = pb2.Code.OK # pylint: disable=E1101 + status_msg = pb2.Status(code=code_msg, message="Success") # pylint: disable=E1101 code = typing.Code.OK status = typing.Status(code=code, message="Success") @@ -66,8 +66,8 @@ def test_status_to_proto() -> None: def test_status_from_proto() -> None: """Test status message (de-)serialization.""" # Prepare - code_msg = pb2.Code.OK - status_msg = pb2.Status(code=code_msg, message="Success") + code_msg = pb2.Code.OK # pylint: disable=E1101 + status_msg = pb2.Status(code=code_msg, message="Success") # pylint: disable=E1101 code = typing.Code.OK status = typing.Status(code=code, message="Success") diff --git a/src/py/flwr/driver/app.py b/src/py/flwr/driver/app.py index 987b4a31981b..4fa1ad8b5c02 100644 --- a/src/py/flwr/driver/app.py +++ b/src/py/flwr/driver/app.py @@ -25,7 +25,7 @@ from flwr.common import EventType, event from flwr.common.address import parse_address from flwr.common.logger import log -from flwr.proto import driver_pb2 +from flwr.proto import driver_pb2 # pylint: disable=E0611 from flwr.server.app import ServerConfig, init_defaults, run_fl from flwr.server.client_manager import ClientManager from flwr.server.history import History @@ -171,7 +171,9 @@ def update_client_manager( `client_manager.unregister()`. """ # Request for run_id - run_id = driver.create_run(driver_pb2.CreateRunRequest()).run_id + run_id = driver.create_run( + driver_pb2.CreateRunRequest() # pylint: disable=E1101 + ).run_id # Loop until the driver is disconnected registered_nodes: Dict[int, DriverClientProxy] = {} @@ -181,7 +183,7 @@ def update_client_manager( if driver.stub is None: break get_nodes_res = driver.get_nodes( - req=driver_pb2.GetNodesRequest(run_id=run_id) + req=driver_pb2.GetNodesRequest(run_id=run_id) # pylint: disable=E1101 ) all_node_ids = {node.node_id for node in get_nodes_res.nodes} dead_nodes = set(registered_nodes).difference(all_node_ids) diff --git a/src/py/flwr/driver/app_test.py b/src/py/flwr/driver/app_test.py index 82747e5afb2c..bfa0098f68e2 100644 --- a/src/py/flwr/driver/app_test.py +++ b/src/py/flwr/driver/app_test.py @@ -21,8 +21,11 @@ from unittest.mock import MagicMock from flwr.driver.app import update_client_manager -from flwr.proto.driver_pb2 import CreateRunResponse, GetNodesResponse -from flwr.proto.node_pb2 import Node +from flwr.proto.driver_pb2 import ( # pylint: disable=E0611 + CreateRunResponse, + GetNodesResponse, +) +from flwr.proto.node_pb2 import Node # pylint: disable=E0611 from flwr.server.client_manager import SimpleClientManager diff --git a/src/py/flwr/driver/driver.py b/src/py/flwr/driver/driver.py index 9f96cc46ce1e..512a2001165e 100644 --- a/src/py/flwr/driver/driver.py +++ b/src/py/flwr/driver/driver.py @@ -18,14 +18,14 @@ from typing import Iterable, List, Optional, Tuple from flwr.driver.grpc_driver import DEFAULT_SERVER_ADDRESS_DRIVER, GrpcDriver -from flwr.proto.driver_pb2 import ( +from flwr.proto.driver_pb2 import ( # pylint: disable=E0611 CreateRunRequest, GetNodesRequest, PullTaskResRequest, PushTaskInsRequest, ) -from flwr.proto.node_pb2 import Node -from flwr.proto.task_pb2 import TaskIns, TaskRes +from flwr.proto.node_pb2 import Node # pylint: disable=E0611 +from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611 class Driver: diff --git a/src/py/flwr/driver/driver_client_proxy.py b/src/py/flwr/driver/driver_client_proxy.py index 6c15acb9ebde..8b2e51c17ea0 100644 --- a/src/py/flwr/driver/driver_client_proxy.py +++ b/src/py/flwr/driver/driver_client_proxy.py @@ -20,7 +20,12 @@ from flwr import common from flwr.common import serde -from flwr.proto import driver_pb2, node_pb2, task_pb2, transport_pb2 +from flwr.proto import ( # pylint: disable=E0611 + driver_pb2, + node_pb2, + task_pb2, + transport_pb2, +) from flwr.server.client_proxy import ClientProxy from .grpc_driver import GrpcDriver @@ -42,7 +47,7 @@ def get_properties( self, ins: common.GetPropertiesIns, timeout: Optional[float] ) -> common.GetPropertiesRes: """Return client's properties.""" - server_message_proto: transport_pb2.ServerMessage = ( + server_message_proto: transport_pb2.ServerMessage = ( # pylint: disable=E1101 serde.server_message_to_proto( server_message=common.ServerMessage(get_properties_ins=ins) ) @@ -56,7 +61,7 @@ def get_parameters( self, ins: common.GetParametersIns, timeout: Optional[float] ) -> common.GetParametersRes: """Return the current local model parameters.""" - server_message_proto: transport_pb2.ServerMessage = ( + server_message_proto: transport_pb2.ServerMessage = ( # pylint: disable=E1101 serde.server_message_to_proto( server_message=common.ServerMessage(get_parameters_ins=ins) ) @@ -68,7 +73,7 @@ def get_parameters( def fit(self, ins: common.FitIns, timeout: Optional[float]) -> common.FitRes: """Train model parameters on the locally held dataset.""" - server_message_proto: transport_pb2.ServerMessage = ( + server_message_proto: transport_pb2.ServerMessage = ( # pylint: disable=E1101 serde.server_message_to_proto( server_message=common.ServerMessage(fit_ins=ins) ) @@ -82,7 +87,7 @@ def evaluate( self, ins: common.EvaluateIns, timeout: Optional[float] ) -> common.EvaluateRes: """Evaluate model parameters on the locally held dataset.""" - server_message_proto: transport_pb2.ServerMessage = ( + server_message_proto: transport_pb2.ServerMessage = ( # pylint: disable=E1101 serde.server_message_to_proto( server_message=common.ServerMessage(evaluate_ins=ins) ) @@ -99,25 +104,29 @@ def reconnect( return common.DisconnectRes(reason="") # Nothing to do here (yet) def _send_receive_msg( - self, server_message: transport_pb2.ServerMessage, timeout: Optional[float] - ) -> transport_pb2.ClientMessage: - task_ins = task_pb2.TaskIns( + self, + server_message: transport_pb2.ServerMessage, # pylint: disable=E1101 + timeout: Optional[float], + ) -> transport_pb2.ClientMessage: # pylint: disable=E1101 + task_ins = task_pb2.TaskIns( # pylint: disable=E1101 task_id="", group_id="", run_id=self.run_id, - task=task_pb2.Task( - producer=node_pb2.Node( + task=task_pb2.Task( # pylint: disable=E1101 + producer=node_pb2.Node( # pylint: disable=E1101 node_id=0, anonymous=True, ), - consumer=node_pb2.Node( + consumer=node_pb2.Node( # pylint: disable=E1101 node_id=self.node_id, anonymous=self.anonymous, ), legacy_server_message=server_message, ), ) - push_task_ins_req = driver_pb2.PushTaskInsRequest(task_ins_list=[task_ins]) + push_task_ins_req = driver_pb2.PushTaskInsRequest( # pylint: disable=E1101 + task_ins_list=[task_ins] + ) # Send TaskIns to Driver API push_task_ins_res = self.driver.push_task_ins(req=push_task_ins_req) @@ -133,15 +142,15 @@ def _send_receive_msg( start_time = time.time() while True: - pull_task_res_req = driver_pb2.PullTaskResRequest( - node=node_pb2.Node(node_id=0, anonymous=True), + pull_task_res_req = driver_pb2.PullTaskResRequest( # pylint: disable=E1101 + node=node_pb2.Node(node_id=0, anonymous=True), # pylint: disable=E1101 task_ids=[task_id], ) # Ask Driver API for TaskRes pull_task_res_res = self.driver.pull_task_res(req=pull_task_res_req) - task_res_list: List[task_pb2.TaskRes] = list( + task_res_list: List[task_pb2.TaskRes] = list( # pylint: disable=E1101 pull_task_res_res.task_res_list ) if len(task_res_list) == 1: diff --git a/src/py/flwr/driver/driver_client_proxy_test.py b/src/py/flwr/driver/driver_client_proxy_test.py index e7fb088dbf57..d3cab152e4db 100644 --- a/src/py/flwr/driver/driver_client_proxy_test.py +++ b/src/py/flwr/driver/driver_client_proxy_test.py @@ -23,8 +23,12 @@ import flwr from flwr.common.typing import Config, GetParametersIns from flwr.driver.driver_client_proxy import DriverClientProxy -from flwr.proto import driver_pb2, node_pb2, task_pb2 -from flwr.proto.transport_pb2 import ClientMessage, Parameters, Scalar +from flwr.proto import driver_pb2, node_pb2, task_pb2 # pylint: disable=E0611 +from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 + ClientMessage, + Parameters, + Scalar, +) MESSAGE_PARAMETERS = Parameters(tensors=[b"abc"], tensor_type="np") @@ -37,31 +41,39 @@ class DriverClientProxyTestCase(unittest.TestCase): def setUp(self) -> None: """Set up mocks for tests.""" self.driver = MagicMock() - self.driver.get_nodes.return_value = driver_pb2.GetNodesResponse( - nodes=[node_pb2.Node(node_id=1, anonymous=False)] + self.driver.get_nodes.return_value = ( + driver_pb2.GetNodesResponse( # pylint: disable=E1101 + nodes=[ + node_pb2.Node(node_id=1, anonymous=False) # pylint: disable=E1101 + ] + ) ) def test_get_properties(self) -> None: """Test positive case.""" # Prepare - self.driver.push_task_ins.return_value = driver_pb2.PushTaskInsResponse( - task_ids=["19341fd7-62e1-4eb4-beb4-9876d3acda32"] + self.driver.push_task_ins.return_value = ( + driver_pb2.PushTaskInsResponse( # pylint: disable=E1101 + task_ids=["19341fd7-62e1-4eb4-beb4-9876d3acda32"] + ) ) - self.driver.pull_task_res.return_value = driver_pb2.PullTaskResResponse( - task_res_list=[ - task_pb2.TaskRes( - task_id="554bd3c8-8474-4b93-a7db-c7bec1bf0012", - group_id="", - run_id=0, - task=task_pb2.Task( - legacy_client_message=ClientMessage( - get_properties_res=ClientMessage.GetPropertiesRes( - properties=CLIENT_PROPERTIES + self.driver.pull_task_res.return_value = ( + driver_pb2.PullTaskResResponse( # pylint: disable=E1101 + task_res_list=[ + task_pb2.TaskRes( # pylint: disable=E1101 + task_id="554bd3c8-8474-4b93-a7db-c7bec1bf0012", + group_id="", + run_id=0, + task=task_pb2.Task( # pylint: disable=E1101 + legacy_client_message=ClientMessage( + get_properties_res=ClientMessage.GetPropertiesRes( + properties=CLIENT_PROPERTIES + ) ) - ) - ), - ) - ] + ), + ) + ] + ) ) client = DriverClientProxy( node_id=1, driver=self.driver, anonymous=True, run_id=0 @@ -80,24 +92,28 @@ def test_get_properties(self) -> None: def test_get_parameters(self) -> None: """Test positive case.""" # Prepare - self.driver.push_task_ins.return_value = driver_pb2.PushTaskInsResponse( - task_ids=["19341fd7-62e1-4eb4-beb4-9876d3acda32"] + self.driver.push_task_ins.return_value = ( + driver_pb2.PushTaskInsResponse( # pylint: disable=E1101 + task_ids=["19341fd7-62e1-4eb4-beb4-9876d3acda32"] + ) ) - self.driver.pull_task_res.return_value = driver_pb2.PullTaskResResponse( - task_res_list=[ - task_pb2.TaskRes( - task_id="554bd3c8-8474-4b93-a7db-c7bec1bf0012", - group_id="", - run_id=0, - task=task_pb2.Task( - legacy_client_message=ClientMessage( - get_parameters_res=ClientMessage.GetParametersRes( - parameters=MESSAGE_PARAMETERS, + self.driver.pull_task_res.return_value = ( + driver_pb2.PullTaskResResponse( # pylint: disable=E1101 + task_res_list=[ + task_pb2.TaskRes( # pylint: disable=E1101 + task_id="554bd3c8-8474-4b93-a7db-c7bec1bf0012", + group_id="", + run_id=0, + task=task_pb2.Task( # pylint: disable=E1101 + legacy_client_message=ClientMessage( + get_parameters_res=ClientMessage.GetParametersRes( + parameters=MESSAGE_PARAMETERS, + ) ) - ) - ), - ) - ] + ), + ) + ] + ) ) client = DriverClientProxy( node_id=1, driver=self.driver, anonymous=True, run_id=0 @@ -115,25 +131,29 @@ def test_get_parameters(self) -> None: def test_fit(self) -> None: """Test positive case.""" # Prepare - self.driver.push_task_ins.return_value = driver_pb2.PushTaskInsResponse( - task_ids=["19341fd7-62e1-4eb4-beb4-9876d3acda32"] + self.driver.push_task_ins.return_value = ( + driver_pb2.PushTaskInsResponse( # pylint: disable=E1101 + task_ids=["19341fd7-62e1-4eb4-beb4-9876d3acda32"] + ) ) - self.driver.pull_task_res.return_value = driver_pb2.PullTaskResResponse( - task_res_list=[ - task_pb2.TaskRes( - task_id="554bd3c8-8474-4b93-a7db-c7bec1bf0012", - group_id="", - run_id=0, - task=task_pb2.Task( - legacy_client_message=ClientMessage( - fit_res=ClientMessage.FitRes( - parameters=MESSAGE_PARAMETERS, - num_examples=10, + self.driver.pull_task_res.return_value = ( + driver_pb2.PullTaskResResponse( # pylint: disable=E1101 + task_res_list=[ + task_pb2.TaskRes( # pylint: disable=E1101 + task_id="554bd3c8-8474-4b93-a7db-c7bec1bf0012", + group_id="", + run_id=0, + task=task_pb2.Task( # pylint: disable=E1101 + legacy_client_message=ClientMessage( + fit_res=ClientMessage.FitRes( + parameters=MESSAGE_PARAMETERS, + num_examples=10, + ) ) - ) - ), - ) - ] + ), + ) + ] + ) ) client = DriverClientProxy( node_id=1, driver=self.driver, anonymous=True, run_id=0 @@ -152,24 +172,28 @@ def test_fit(self) -> None: def test_evaluate(self) -> None: """Test positive case.""" # Prepare - self.driver.push_task_ins.return_value = driver_pb2.PushTaskInsResponse( - task_ids=["19341fd7-62e1-4eb4-beb4-9876d3acda32"] + self.driver.push_task_ins.return_value = ( + driver_pb2.PushTaskInsResponse( # pylint: disable=E1101 + task_ids=["19341fd7-62e1-4eb4-beb4-9876d3acda32"] + ) ) - self.driver.pull_task_res.return_value = driver_pb2.PullTaskResResponse( - task_res_list=[ - task_pb2.TaskRes( - task_id="554bd3c8-8474-4b93-a7db-c7bec1bf0012", - group_id="", - run_id=0, - task=task_pb2.Task( - legacy_client_message=ClientMessage( - evaluate_res=ClientMessage.EvaluateRes( - loss=0.0, num_examples=0 + self.driver.pull_task_res.return_value = ( + driver_pb2.PullTaskResResponse( # pylint: disable=E1101 + task_res_list=[ + task_pb2.TaskRes( # pylint: disable=E1101 + task_id="554bd3c8-8474-4b93-a7db-c7bec1bf0012", + group_id="", + run_id=0, + task=task_pb2.Task( # pylint: disable=E1101 + legacy_client_message=ClientMessage( + evaluate_res=ClientMessage.EvaluateRes( + loss=0.0, num_examples=0 + ) ) - ) - ), - ) - ] + ), + ) + ] + ) ) client = DriverClientProxy( node_id=1, driver=self.driver, anonymous=True, run_id=0 diff --git a/src/py/flwr/driver/driver_test.py b/src/py/flwr/driver/driver_test.py index 8f75bbf78362..1854a92b5ebe 100644 --- a/src/py/flwr/driver/driver_test.py +++ b/src/py/flwr/driver/driver_test.py @@ -19,12 +19,12 @@ from unittest.mock import Mock, patch from flwr.driver.driver import Driver -from flwr.proto.driver_pb2 import ( +from flwr.proto.driver_pb2 import ( # pylint: disable=E0611 GetNodesRequest, PullTaskResRequest, PushTaskInsRequest, ) -from flwr.proto.task_pb2 import Task, TaskIns, TaskRes +from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611 class TestDriver(unittest.TestCase): diff --git a/src/py/flwr/driver/grpc_driver.py b/src/py/flwr/driver/grpc_driver.py index 627b95cdb1b4..23d449790092 100644 --- a/src/py/flwr/driver/grpc_driver.py +++ b/src/py/flwr/driver/grpc_driver.py @@ -23,7 +23,7 @@ from flwr.common import EventType, event from flwr.common.grpc import create_channel from flwr.common.logger import log -from flwr.proto.driver_pb2 import ( +from flwr.proto.driver_pb2 import ( # pylint: disable=E0611 CreateRunRequest, CreateRunResponse, GetNodesRequest, @@ -33,7 +33,7 @@ PushTaskInsRequest, PushTaskInsResponse, ) -from flwr.proto.driver_pb2_grpc import DriverStub +from flwr.proto.driver_pb2_grpc import DriverStub # pylint: disable=E0611 DEFAULT_SERVER_ADDRESS_DRIVER = "[::]:9091" diff --git a/src/py/flwr/proto/driver_pb2.py b/src/py/flwr/proto/driver_pb2.py index 615bf4672afa..fe9c33da0fa9 100644 --- a/src/py/flwr/proto/driver_pb2.py +++ b/src/py/flwr/proto/driver_pb2.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: flwr/proto/driver.proto +# Protobuf Python Version: 4.25.0 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() @@ -18,92 +18,27 @@ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17\x66lwr/proto/driver.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x15\x66lwr/proto/task.proto\"\x12\n\x10\x43reateRunRequest\"#\n\x11\x43reateRunResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\x12\"!\n\x0fGetNodesRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x12\"3\n\x10GetNodesResponse\x12\x1f\n\x05nodes\x18\x01 \x03(\x0b\x32\x10.flwr.proto.Node\"@\n\x12PushTaskInsRequest\x12*\n\rtask_ins_list\x18\x01 \x03(\x0b\x32\x13.flwr.proto.TaskIns\"\'\n\x13PushTaskInsResponse\x12\x10\n\x08task_ids\x18\x02 \x03(\t\"F\n\x12PullTaskResRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x10\n\x08task_ids\x18\x02 \x03(\t\"A\n\x13PullTaskResResponse\x12*\n\rtask_res_list\x18\x01 \x03(\x0b\x32\x13.flwr.proto.TaskRes2\xc1\x02\n\x06\x44river\x12J\n\tCreateRun\x12\x1c.flwr.proto.CreateRunRequest\x1a\x1d.flwr.proto.CreateRunResponse\"\x00\x12G\n\x08GetNodes\x12\x1b.flwr.proto.GetNodesRequest\x1a\x1c.flwr.proto.GetNodesResponse\"\x00\x12P\n\x0bPushTaskIns\x12\x1e.flwr.proto.PushTaskInsRequest\x1a\x1f.flwr.proto.PushTaskInsResponse\"\x00\x12P\n\x0bPullTaskRes\x12\x1e.flwr.proto.PullTaskResRequest\x1a\x1f.flwr.proto.PullTaskResResponse\"\x00\x62\x06proto3') - - -_CREATERUNREQUEST = DESCRIPTOR.message_types_by_name['CreateRunRequest'] -_CREATERUNRESPONSE = DESCRIPTOR.message_types_by_name['CreateRunResponse'] -_GETNODESREQUEST = DESCRIPTOR.message_types_by_name['GetNodesRequest'] -_GETNODESRESPONSE = DESCRIPTOR.message_types_by_name['GetNodesResponse'] -_PUSHTASKINSREQUEST = DESCRIPTOR.message_types_by_name['PushTaskInsRequest'] -_PUSHTASKINSRESPONSE = DESCRIPTOR.message_types_by_name['PushTaskInsResponse'] -_PULLTASKRESREQUEST = DESCRIPTOR.message_types_by_name['PullTaskResRequest'] -_PULLTASKRESRESPONSE = DESCRIPTOR.message_types_by_name['PullTaskResResponse'] -CreateRunRequest = _reflection.GeneratedProtocolMessageType('CreateRunRequest', (_message.Message,), { - 'DESCRIPTOR' : _CREATERUNREQUEST, - '__module__' : 'flwr.proto.driver_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.CreateRunRequest) - }) -_sym_db.RegisterMessage(CreateRunRequest) - -CreateRunResponse = _reflection.GeneratedProtocolMessageType('CreateRunResponse', (_message.Message,), { - 'DESCRIPTOR' : _CREATERUNRESPONSE, - '__module__' : 'flwr.proto.driver_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.CreateRunResponse) - }) -_sym_db.RegisterMessage(CreateRunResponse) - -GetNodesRequest = _reflection.GeneratedProtocolMessageType('GetNodesRequest', (_message.Message,), { - 'DESCRIPTOR' : _GETNODESREQUEST, - '__module__' : 'flwr.proto.driver_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.GetNodesRequest) - }) -_sym_db.RegisterMessage(GetNodesRequest) - -GetNodesResponse = _reflection.GeneratedProtocolMessageType('GetNodesResponse', (_message.Message,), { - 'DESCRIPTOR' : _GETNODESRESPONSE, - '__module__' : 'flwr.proto.driver_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.GetNodesResponse) - }) -_sym_db.RegisterMessage(GetNodesResponse) - -PushTaskInsRequest = _reflection.GeneratedProtocolMessageType('PushTaskInsRequest', (_message.Message,), { - 'DESCRIPTOR' : _PUSHTASKINSREQUEST, - '__module__' : 'flwr.proto.driver_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.PushTaskInsRequest) - }) -_sym_db.RegisterMessage(PushTaskInsRequest) - -PushTaskInsResponse = _reflection.GeneratedProtocolMessageType('PushTaskInsResponse', (_message.Message,), { - 'DESCRIPTOR' : _PUSHTASKINSRESPONSE, - '__module__' : 'flwr.proto.driver_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.PushTaskInsResponse) - }) -_sym_db.RegisterMessage(PushTaskInsResponse) - -PullTaskResRequest = _reflection.GeneratedProtocolMessageType('PullTaskResRequest', (_message.Message,), { - 'DESCRIPTOR' : _PULLTASKRESREQUEST, - '__module__' : 'flwr.proto.driver_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.PullTaskResRequest) - }) -_sym_db.RegisterMessage(PullTaskResRequest) - -PullTaskResResponse = _reflection.GeneratedProtocolMessageType('PullTaskResResponse', (_message.Message,), { - 'DESCRIPTOR' : _PULLTASKRESRESPONSE, - '__module__' : 'flwr.proto.driver_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.PullTaskResResponse) - }) -_sym_db.RegisterMessage(PullTaskResResponse) - -_DRIVER = DESCRIPTOR.services_by_name['Driver'] +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.driver_pb2', _globals) if _descriptor._USE_C_DESCRIPTORS == False: - DESCRIPTOR._options = None - _CREATERUNREQUEST._serialized_start=85 - _CREATERUNREQUEST._serialized_end=103 - _CREATERUNRESPONSE._serialized_start=105 - _CREATERUNRESPONSE._serialized_end=140 - _GETNODESREQUEST._serialized_start=142 - _GETNODESREQUEST._serialized_end=175 - _GETNODESRESPONSE._serialized_start=177 - _GETNODESRESPONSE._serialized_end=228 - _PUSHTASKINSREQUEST._serialized_start=230 - _PUSHTASKINSREQUEST._serialized_end=294 - _PUSHTASKINSRESPONSE._serialized_start=296 - _PUSHTASKINSRESPONSE._serialized_end=335 - _PULLTASKRESREQUEST._serialized_start=337 - _PULLTASKRESREQUEST._serialized_end=407 - _PULLTASKRESRESPONSE._serialized_start=409 - _PULLTASKRESRESPONSE._serialized_end=474 - _DRIVER._serialized_start=477 - _DRIVER._serialized_end=798 + _globals['_CREATERUNREQUEST']._serialized_start=85 + _globals['_CREATERUNREQUEST']._serialized_end=103 + _globals['_CREATERUNRESPONSE']._serialized_start=105 + _globals['_CREATERUNRESPONSE']._serialized_end=140 + _globals['_GETNODESREQUEST']._serialized_start=142 + _globals['_GETNODESREQUEST']._serialized_end=175 + _globals['_GETNODESRESPONSE']._serialized_start=177 + _globals['_GETNODESRESPONSE']._serialized_end=228 + _globals['_PUSHTASKINSREQUEST']._serialized_start=230 + _globals['_PUSHTASKINSREQUEST']._serialized_end=294 + _globals['_PUSHTASKINSRESPONSE']._serialized_start=296 + _globals['_PUSHTASKINSRESPONSE']._serialized_end=335 + _globals['_PULLTASKRESREQUEST']._serialized_start=337 + _globals['_PULLTASKRESREQUEST']._serialized_end=407 + _globals['_PULLTASKRESRESPONSE']._serialized_start=409 + _globals['_PULLTASKRESRESPONSE']._serialized_end=474 + _globals['_DRIVER']._serialized_start=477 + _globals['_DRIVER']._serialized_end=798 # @@protoc_insertion_point(module_scope) diff --git a/src/py/flwr/proto/fleet_pb2.py b/src/py/flwr/proto/fleet_pb2.py index e86a53e2139e..e8443c296f0c 100644 --- a/src/py/flwr/proto/fleet_pb2.py +++ b/src/py/flwr/proto/fleet_pb2.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: flwr/proto/fleet.proto +# Protobuf Python Version: 4.25.0 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() @@ -18,115 +18,33 @@ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x66lwr/proto/fleet.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x15\x66lwr/proto/task.proto\"\x13\n\x11\x43reateNodeRequest\"4\n\x12\x43reateNodeResponse\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"3\n\x11\x44\x65leteNodeRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"\x14\n\x12\x44\x65leteNodeResponse\"F\n\x12PullTaskInsRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x10\n\x08task_ids\x18\x02 \x03(\t\"k\n\x13PullTaskInsResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12*\n\rtask_ins_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.TaskIns\"@\n\x12PushTaskResRequest\x12*\n\rtask_res_list\x18\x01 \x03(\x0b\x32\x13.flwr.proto.TaskRes\"\xae\x01\n\x13PushTaskResResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12=\n\x07results\x18\x02 \x03(\x0b\x32,.flwr.proto.PushTaskResResponse.ResultsEntry\x1a.\n\x0cResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\x1e\n\tReconnect\x12\x11\n\treconnect\x18\x01 \x01(\x04\x32\xc9\x02\n\x05\x46leet\x12M\n\nCreateNode\x12\x1d.flwr.proto.CreateNodeRequest\x1a\x1e.flwr.proto.CreateNodeResponse\"\x00\x12M\n\nDeleteNode\x12\x1d.flwr.proto.DeleteNodeRequest\x1a\x1e.flwr.proto.DeleteNodeResponse\"\x00\x12P\n\x0bPullTaskIns\x12\x1e.flwr.proto.PullTaskInsRequest\x1a\x1f.flwr.proto.PullTaskInsResponse\"\x00\x12P\n\x0bPushTaskRes\x12\x1e.flwr.proto.PushTaskResRequest\x1a\x1f.flwr.proto.PushTaskResResponse\"\x00\x62\x06proto3') - - -_CREATENODEREQUEST = DESCRIPTOR.message_types_by_name['CreateNodeRequest'] -_CREATENODERESPONSE = DESCRIPTOR.message_types_by_name['CreateNodeResponse'] -_DELETENODEREQUEST = DESCRIPTOR.message_types_by_name['DeleteNodeRequest'] -_DELETENODERESPONSE = DESCRIPTOR.message_types_by_name['DeleteNodeResponse'] -_PULLTASKINSREQUEST = DESCRIPTOR.message_types_by_name['PullTaskInsRequest'] -_PULLTASKINSRESPONSE = DESCRIPTOR.message_types_by_name['PullTaskInsResponse'] -_PUSHTASKRESREQUEST = DESCRIPTOR.message_types_by_name['PushTaskResRequest'] -_PUSHTASKRESRESPONSE = DESCRIPTOR.message_types_by_name['PushTaskResResponse'] -_PUSHTASKRESRESPONSE_RESULTSENTRY = _PUSHTASKRESRESPONSE.nested_types_by_name['ResultsEntry'] -_RECONNECT = DESCRIPTOR.message_types_by_name['Reconnect'] -CreateNodeRequest = _reflection.GeneratedProtocolMessageType('CreateNodeRequest', (_message.Message,), { - 'DESCRIPTOR' : _CREATENODEREQUEST, - '__module__' : 'flwr.proto.fleet_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.CreateNodeRequest) - }) -_sym_db.RegisterMessage(CreateNodeRequest) - -CreateNodeResponse = _reflection.GeneratedProtocolMessageType('CreateNodeResponse', (_message.Message,), { - 'DESCRIPTOR' : _CREATENODERESPONSE, - '__module__' : 'flwr.proto.fleet_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.CreateNodeResponse) - }) -_sym_db.RegisterMessage(CreateNodeResponse) - -DeleteNodeRequest = _reflection.GeneratedProtocolMessageType('DeleteNodeRequest', (_message.Message,), { - 'DESCRIPTOR' : _DELETENODEREQUEST, - '__module__' : 'flwr.proto.fleet_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.DeleteNodeRequest) - }) -_sym_db.RegisterMessage(DeleteNodeRequest) - -DeleteNodeResponse = _reflection.GeneratedProtocolMessageType('DeleteNodeResponse', (_message.Message,), { - 'DESCRIPTOR' : _DELETENODERESPONSE, - '__module__' : 'flwr.proto.fleet_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.DeleteNodeResponse) - }) -_sym_db.RegisterMessage(DeleteNodeResponse) - -PullTaskInsRequest = _reflection.GeneratedProtocolMessageType('PullTaskInsRequest', (_message.Message,), { - 'DESCRIPTOR' : _PULLTASKINSREQUEST, - '__module__' : 'flwr.proto.fleet_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.PullTaskInsRequest) - }) -_sym_db.RegisterMessage(PullTaskInsRequest) - -PullTaskInsResponse = _reflection.GeneratedProtocolMessageType('PullTaskInsResponse', (_message.Message,), { - 'DESCRIPTOR' : _PULLTASKINSRESPONSE, - '__module__' : 'flwr.proto.fleet_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.PullTaskInsResponse) - }) -_sym_db.RegisterMessage(PullTaskInsResponse) - -PushTaskResRequest = _reflection.GeneratedProtocolMessageType('PushTaskResRequest', (_message.Message,), { - 'DESCRIPTOR' : _PUSHTASKRESREQUEST, - '__module__' : 'flwr.proto.fleet_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.PushTaskResRequest) - }) -_sym_db.RegisterMessage(PushTaskResRequest) - -PushTaskResResponse = _reflection.GeneratedProtocolMessageType('PushTaskResResponse', (_message.Message,), { - - 'ResultsEntry' : _reflection.GeneratedProtocolMessageType('ResultsEntry', (_message.Message,), { - 'DESCRIPTOR' : _PUSHTASKRESRESPONSE_RESULTSENTRY, - '__module__' : 'flwr.proto.fleet_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.PushTaskResResponse.ResultsEntry) - }) - , - 'DESCRIPTOR' : _PUSHTASKRESRESPONSE, - '__module__' : 'flwr.proto.fleet_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.PushTaskResResponse) - }) -_sym_db.RegisterMessage(PushTaskResResponse) -_sym_db.RegisterMessage(PushTaskResResponse.ResultsEntry) - -Reconnect = _reflection.GeneratedProtocolMessageType('Reconnect', (_message.Message,), { - 'DESCRIPTOR' : _RECONNECT, - '__module__' : 'flwr.proto.fleet_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.Reconnect) - }) -_sym_db.RegisterMessage(Reconnect) - -_FLEET = DESCRIPTOR.services_by_name['Fleet'] +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.fleet_pb2', _globals) if _descriptor._USE_C_DESCRIPTORS == False: - DESCRIPTOR._options = None - _PUSHTASKRESRESPONSE_RESULTSENTRY._options = None - _PUSHTASKRESRESPONSE_RESULTSENTRY._serialized_options = b'8\001' - _CREATENODEREQUEST._serialized_start=84 - _CREATENODEREQUEST._serialized_end=103 - _CREATENODERESPONSE._serialized_start=105 - _CREATENODERESPONSE._serialized_end=157 - _DELETENODEREQUEST._serialized_start=159 - _DELETENODEREQUEST._serialized_end=210 - _DELETENODERESPONSE._serialized_start=212 - _DELETENODERESPONSE._serialized_end=232 - _PULLTASKINSREQUEST._serialized_start=234 - _PULLTASKINSREQUEST._serialized_end=304 - _PULLTASKINSRESPONSE._serialized_start=306 - _PULLTASKINSRESPONSE._serialized_end=413 - _PUSHTASKRESREQUEST._serialized_start=415 - _PUSHTASKRESREQUEST._serialized_end=479 - _PUSHTASKRESRESPONSE._serialized_start=482 - _PUSHTASKRESRESPONSE._serialized_end=656 - _PUSHTASKRESRESPONSE_RESULTSENTRY._serialized_start=610 - _PUSHTASKRESRESPONSE_RESULTSENTRY._serialized_end=656 - _RECONNECT._serialized_start=658 - _RECONNECT._serialized_end=688 - _FLEET._serialized_start=691 - _FLEET._serialized_end=1020 + _globals['_PUSHTASKRESRESPONSE_RESULTSENTRY']._options = None + _globals['_PUSHTASKRESRESPONSE_RESULTSENTRY']._serialized_options = b'8\001' + _globals['_CREATENODEREQUEST']._serialized_start=84 + _globals['_CREATENODEREQUEST']._serialized_end=103 + _globals['_CREATENODERESPONSE']._serialized_start=105 + _globals['_CREATENODERESPONSE']._serialized_end=157 + _globals['_DELETENODEREQUEST']._serialized_start=159 + _globals['_DELETENODEREQUEST']._serialized_end=210 + _globals['_DELETENODERESPONSE']._serialized_start=212 + _globals['_DELETENODERESPONSE']._serialized_end=232 + _globals['_PULLTASKINSREQUEST']._serialized_start=234 + _globals['_PULLTASKINSREQUEST']._serialized_end=304 + _globals['_PULLTASKINSRESPONSE']._serialized_start=306 + _globals['_PULLTASKINSRESPONSE']._serialized_end=413 + _globals['_PUSHTASKRESREQUEST']._serialized_start=415 + _globals['_PUSHTASKRESREQUEST']._serialized_end=479 + _globals['_PUSHTASKRESRESPONSE']._serialized_start=482 + _globals['_PUSHTASKRESRESPONSE']._serialized_end=656 + _globals['_PUSHTASKRESRESPONSE_RESULTSENTRY']._serialized_start=610 + _globals['_PUSHTASKRESRESPONSE_RESULTSENTRY']._serialized_end=656 + _globals['_RECONNECT']._serialized_start=658 + _globals['_RECONNECT']._serialized_end=688 + _globals['_FLEET']._serialized_start=691 + _globals['_FLEET']._serialized_end=1020 # @@protoc_insertion_point(module_scope) diff --git a/src/py/flwr/proto/node_pb2.py b/src/py/flwr/proto/node_pb2.py index 9d91900d8f53..b300f2c562c2 100644 --- a/src/py/flwr/proto/node_pb2.py +++ b/src/py/flwr/proto/node_pb2.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: flwr/proto/node.proto +# Protobuf Python Version: 4.25.0 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() @@ -16,19 +16,11 @@ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/node.proto\x12\nflwr.proto\"*\n\x04Node\x12\x0f\n\x07node_id\x18\x01 \x01(\x12\x12\x11\n\tanonymous\x18\x02 \x01(\x08\x62\x06proto3') - - -_NODE = DESCRIPTOR.message_types_by_name['Node'] -Node = _reflection.GeneratedProtocolMessageType('Node', (_message.Message,), { - 'DESCRIPTOR' : _NODE, - '__module__' : 'flwr.proto.node_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.Node) - }) -_sym_db.RegisterMessage(Node) - +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.node_pb2', _globals) if _descriptor._USE_C_DESCRIPTORS == False: - DESCRIPTOR._options = None - _NODE._serialized_start=37 - _NODE._serialized_end=79 + _globals['_NODE']._serialized_start=37 + _globals['_NODE']._serialized_end=79 # @@protoc_insertion_point(module_scope) diff --git a/src/py/flwr/proto/task_pb2.py b/src/py/flwr/proto/task_pb2.py index ba0e2e3f5218..8c9d6d001c1e 100644 --- a/src/py/flwr/proto/task_pb2.py +++ b/src/py/flwr/proto/task_pb2.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: flwr/proto/task.proto +# Protobuf Python Version: 4.25.0 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() @@ -18,131 +18,37 @@ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/task.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x1a\x66lwr/proto/transport.proto\"\xbe\x02\n\x04Task\x12\"\n\x08producer\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\"\n\x08\x63onsumer\x18\x02 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x12\n\ncreated_at\x18\x03 \x01(\t\x12\x14\n\x0c\x64\x65livered_at\x18\x04 \x01(\t\x12\x0b\n\x03ttl\x18\x05 \x01(\t\x12\x10\n\x08\x61ncestry\x18\x06 \x03(\t\x12)\n\x02sa\x18\x07 \x01(\x0b\x32\x1d.flwr.proto.SecureAggregation\x12<\n\x15legacy_server_message\x18\x65 \x01(\x0b\x32\x19.flwr.proto.ServerMessageB\x02\x18\x01\x12<\n\x15legacy_client_message\x18\x66 \x01(\x0b\x32\x19.flwr.proto.ClientMessageB\x02\x18\x01\"\\\n\x07TaskIns\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x12\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Task\"\\\n\x07TaskRes\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x12\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Task\"\xf3\x03\n\x05Value\x12\x10\n\x06\x64ouble\x18\x01 \x01(\x01H\x00\x12\x10\n\x06sint64\x18\x02 \x01(\x12H\x00\x12\x0e\n\x04\x62ool\x18\x03 \x01(\x08H\x00\x12\x10\n\x06string\x18\x04 \x01(\tH\x00\x12\x0f\n\x05\x62ytes\x18\x05 \x01(\x0cH\x00\x12\x33\n\x0b\x64ouble_list\x18\x15 \x01(\x0b\x32\x1c.flwr.proto.Value.DoubleListH\x00\x12\x33\n\x0bsint64_list\x18\x16 \x01(\x0b\x32\x1c.flwr.proto.Value.Sint64ListH\x00\x12/\n\tbool_list\x18\x17 \x01(\x0b\x32\x1a.flwr.proto.Value.BoolListH\x00\x12\x33\n\x0bstring_list\x18\x18 \x01(\x0b\x32\x1c.flwr.proto.Value.StringListH\x00\x12\x31\n\nbytes_list\x18\x19 \x01(\x0b\x32\x1b.flwr.proto.Value.BytesListH\x00\x1a\x1a\n\nDoubleList\x12\x0c\n\x04vals\x18\x01 \x03(\x01\x1a\x1a\n\nSint64List\x12\x0c\n\x04vals\x18\x01 \x03(\x12\x1a\x18\n\x08\x42oolList\x12\x0c\n\x04vals\x18\x01 \x03(\x08\x1a\x1a\n\nStringList\x12\x0c\n\x04vals\x18\x01 \x03(\t\x1a\x19\n\tBytesList\x12\x0c\n\x04vals\x18\x01 \x03(\x0c\x42\x07\n\x05value\"\xa0\x01\n\x11SecureAggregation\x12\x44\n\x0cnamed_values\x18\x01 \x03(\x0b\x32..flwr.proto.SecureAggregation.NamedValuesEntry\x1a\x45\n\x10NamedValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12 \n\x05value\x18\x02 \x01(\x0b\x32\x11.flwr.proto.Value:\x02\x38\x01\x62\x06proto3') - - -_TASK = DESCRIPTOR.message_types_by_name['Task'] -_TASKINS = DESCRIPTOR.message_types_by_name['TaskIns'] -_TASKRES = DESCRIPTOR.message_types_by_name['TaskRes'] -_VALUE = DESCRIPTOR.message_types_by_name['Value'] -_VALUE_DOUBLELIST = _VALUE.nested_types_by_name['DoubleList'] -_VALUE_SINT64LIST = _VALUE.nested_types_by_name['Sint64List'] -_VALUE_BOOLLIST = _VALUE.nested_types_by_name['BoolList'] -_VALUE_STRINGLIST = _VALUE.nested_types_by_name['StringList'] -_VALUE_BYTESLIST = _VALUE.nested_types_by_name['BytesList'] -_SECUREAGGREGATION = DESCRIPTOR.message_types_by_name['SecureAggregation'] -_SECUREAGGREGATION_NAMEDVALUESENTRY = _SECUREAGGREGATION.nested_types_by_name['NamedValuesEntry'] -Task = _reflection.GeneratedProtocolMessageType('Task', (_message.Message,), { - 'DESCRIPTOR' : _TASK, - '__module__' : 'flwr.proto.task_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.Task) - }) -_sym_db.RegisterMessage(Task) - -TaskIns = _reflection.GeneratedProtocolMessageType('TaskIns', (_message.Message,), { - 'DESCRIPTOR' : _TASKINS, - '__module__' : 'flwr.proto.task_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.TaskIns) - }) -_sym_db.RegisterMessage(TaskIns) - -TaskRes = _reflection.GeneratedProtocolMessageType('TaskRes', (_message.Message,), { - 'DESCRIPTOR' : _TASKRES, - '__module__' : 'flwr.proto.task_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.TaskRes) - }) -_sym_db.RegisterMessage(TaskRes) - -Value = _reflection.GeneratedProtocolMessageType('Value', (_message.Message,), { - - 'DoubleList' : _reflection.GeneratedProtocolMessageType('DoubleList', (_message.Message,), { - 'DESCRIPTOR' : _VALUE_DOUBLELIST, - '__module__' : 'flwr.proto.task_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.Value.DoubleList) - }) - , - - 'Sint64List' : _reflection.GeneratedProtocolMessageType('Sint64List', (_message.Message,), { - 'DESCRIPTOR' : _VALUE_SINT64LIST, - '__module__' : 'flwr.proto.task_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.Value.Sint64List) - }) - , - - 'BoolList' : _reflection.GeneratedProtocolMessageType('BoolList', (_message.Message,), { - 'DESCRIPTOR' : _VALUE_BOOLLIST, - '__module__' : 'flwr.proto.task_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.Value.BoolList) - }) - , - - 'StringList' : _reflection.GeneratedProtocolMessageType('StringList', (_message.Message,), { - 'DESCRIPTOR' : _VALUE_STRINGLIST, - '__module__' : 'flwr.proto.task_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.Value.StringList) - }) - , - - 'BytesList' : _reflection.GeneratedProtocolMessageType('BytesList', (_message.Message,), { - 'DESCRIPTOR' : _VALUE_BYTESLIST, - '__module__' : 'flwr.proto.task_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.Value.BytesList) - }) - , - 'DESCRIPTOR' : _VALUE, - '__module__' : 'flwr.proto.task_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.Value) - }) -_sym_db.RegisterMessage(Value) -_sym_db.RegisterMessage(Value.DoubleList) -_sym_db.RegisterMessage(Value.Sint64List) -_sym_db.RegisterMessage(Value.BoolList) -_sym_db.RegisterMessage(Value.StringList) -_sym_db.RegisterMessage(Value.BytesList) - -SecureAggregation = _reflection.GeneratedProtocolMessageType('SecureAggregation', (_message.Message,), { - - 'NamedValuesEntry' : _reflection.GeneratedProtocolMessageType('NamedValuesEntry', (_message.Message,), { - 'DESCRIPTOR' : _SECUREAGGREGATION_NAMEDVALUESENTRY, - '__module__' : 'flwr.proto.task_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.SecureAggregation.NamedValuesEntry) - }) - , - 'DESCRIPTOR' : _SECUREAGGREGATION, - '__module__' : 'flwr.proto.task_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.SecureAggregation) - }) -_sym_db.RegisterMessage(SecureAggregation) -_sym_db.RegisterMessage(SecureAggregation.NamedValuesEntry) - +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.task_pb2', _globals) if _descriptor._USE_C_DESCRIPTORS == False: - DESCRIPTOR._options = None - _TASK.fields_by_name['legacy_server_message']._options = None - _TASK.fields_by_name['legacy_server_message']._serialized_options = b'\030\001' - _TASK.fields_by_name['legacy_client_message']._options = None - _TASK.fields_by_name['legacy_client_message']._serialized_options = b'\030\001' - _SECUREAGGREGATION_NAMEDVALUESENTRY._options = None - _SECUREAGGREGATION_NAMEDVALUESENTRY._serialized_options = b'8\001' - _TASK._serialized_start=89 - _TASK._serialized_end=407 - _TASKINS._serialized_start=409 - _TASKINS._serialized_end=501 - _TASKRES._serialized_start=503 - _TASKRES._serialized_end=595 - _VALUE._serialized_start=598 - _VALUE._serialized_end=1097 - _VALUE_DOUBLELIST._serialized_start=953 - _VALUE_DOUBLELIST._serialized_end=979 - _VALUE_SINT64LIST._serialized_start=981 - _VALUE_SINT64LIST._serialized_end=1007 - _VALUE_BOOLLIST._serialized_start=1009 - _VALUE_BOOLLIST._serialized_end=1033 - _VALUE_STRINGLIST._serialized_start=1035 - _VALUE_STRINGLIST._serialized_end=1061 - _VALUE_BYTESLIST._serialized_start=1063 - _VALUE_BYTESLIST._serialized_end=1088 - _SECUREAGGREGATION._serialized_start=1100 - _SECUREAGGREGATION._serialized_end=1260 - _SECUREAGGREGATION_NAMEDVALUESENTRY._serialized_start=1191 - _SECUREAGGREGATION_NAMEDVALUESENTRY._serialized_end=1260 + _globals['_TASK'].fields_by_name['legacy_server_message']._options = None + _globals['_TASK'].fields_by_name['legacy_server_message']._serialized_options = b'\030\001' + _globals['_TASK'].fields_by_name['legacy_client_message']._options = None + _globals['_TASK'].fields_by_name['legacy_client_message']._serialized_options = b'\030\001' + _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._options = None + _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_options = b'8\001' + _globals['_TASK']._serialized_start=89 + _globals['_TASK']._serialized_end=407 + _globals['_TASKINS']._serialized_start=409 + _globals['_TASKINS']._serialized_end=501 + _globals['_TASKRES']._serialized_start=503 + _globals['_TASKRES']._serialized_end=595 + _globals['_VALUE']._serialized_start=598 + _globals['_VALUE']._serialized_end=1097 + _globals['_VALUE_DOUBLELIST']._serialized_start=953 + _globals['_VALUE_DOUBLELIST']._serialized_end=979 + _globals['_VALUE_SINT64LIST']._serialized_start=981 + _globals['_VALUE_SINT64LIST']._serialized_end=1007 + _globals['_VALUE_BOOLLIST']._serialized_start=1009 + _globals['_VALUE_BOOLLIST']._serialized_end=1033 + _globals['_VALUE_STRINGLIST']._serialized_start=1035 + _globals['_VALUE_STRINGLIST']._serialized_end=1061 + _globals['_VALUE_BYTESLIST']._serialized_start=1063 + _globals['_VALUE_BYTESLIST']._serialized_end=1088 + _globals['_SECUREAGGREGATION']._serialized_start=1100 + _globals['_SECUREAGGREGATION']._serialized_end=1260 + _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_start=1191 + _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_end=1260 # @@protoc_insertion_point(module_scope) diff --git a/src/py/flwr/proto/transport_pb2.py b/src/py/flwr/proto/transport_pb2.py index 1e3785b0e312..d3aae72b63ab 100644 --- a/src/py/flwr/proto/transport_pb2.py +++ b/src/py/flwr/proto/transport_pb2.py @@ -1,13 +1,12 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: flwr/proto/transport.proto +# Protobuf Python Version: 4.25.0 """Generated protocol buffer code.""" -from google.protobuf.internal import enum_type_wrapper from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() @@ -17,281 +16,73 @@ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1a\x66lwr/proto/transport.proto\x12\nflwr.proto\"9\n\x06Status\x12\x1e\n\x04\x63ode\x18\x01 \x01(\x0e\x32\x10.flwr.proto.Code\x12\x0f\n\x07message\x18\x02 \x01(\t\"2\n\nParameters\x12\x0f\n\x07tensors\x18\x01 \x03(\x0c\x12\x13\n\x0btensor_type\x18\x02 \x01(\t\"\xba\x08\n\rServerMessage\x12?\n\rreconnect_ins\x18\x01 \x01(\x0b\x32&.flwr.proto.ServerMessage.ReconnectInsH\x00\x12H\n\x12get_properties_ins\x18\x02 \x01(\x0b\x32*.flwr.proto.ServerMessage.GetPropertiesInsH\x00\x12H\n\x12get_parameters_ins\x18\x03 \x01(\x0b\x32*.flwr.proto.ServerMessage.GetParametersInsH\x00\x12\x33\n\x07\x66it_ins\x18\x04 \x01(\x0b\x32 .flwr.proto.ServerMessage.FitInsH\x00\x12=\n\x0c\x65valuate_ins\x18\x05 \x01(\x0b\x32%.flwr.proto.ServerMessage.EvaluateInsH\x00\x1a\x1f\n\x0cReconnectIns\x12\x0f\n\x07seconds\x18\x01 \x01(\x03\x1a\x9d\x01\n\x10GetPropertiesIns\x12\x46\n\x06\x63onfig\x18\x01 \x03(\x0b\x32\x36.flwr.proto.ServerMessage.GetPropertiesIns.ConfigEntry\x1a\x41\n\x0b\x43onfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.flwr.proto.Scalar:\x02\x38\x01\x1a\x9d\x01\n\x10GetParametersIns\x12\x46\n\x06\x63onfig\x18\x01 \x03(\x0b\x32\x36.flwr.proto.ServerMessage.GetParametersIns.ConfigEntry\x1a\x41\n\x0b\x43onfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.flwr.proto.Scalar:\x02\x38\x01\x1a\xb5\x01\n\x06\x46itIns\x12*\n\nparameters\x18\x01 \x01(\x0b\x32\x16.flwr.proto.Parameters\x12<\n\x06\x63onfig\x18\x02 \x03(\x0b\x32,.flwr.proto.ServerMessage.FitIns.ConfigEntry\x1a\x41\n\x0b\x43onfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.flwr.proto.Scalar:\x02\x38\x01\x1a\xbf\x01\n\x0b\x45valuateIns\x12*\n\nparameters\x18\x01 \x01(\x0b\x32\x16.flwr.proto.Parameters\x12\x41\n\x06\x63onfig\x18\x02 \x03(\x0b\x32\x31.flwr.proto.ServerMessage.EvaluateIns.ConfigEntry\x1a\x41\n\x0b\x43onfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.flwr.proto.Scalar:\x02\x38\x01\x42\x05\n\x03msg\"\xa0\t\n\rClientMessage\x12\x41\n\x0e\x64isconnect_res\x18\x01 \x01(\x0b\x32\'.flwr.proto.ClientMessage.DisconnectResH\x00\x12H\n\x12get_properties_res\x18\x02 \x01(\x0b\x32*.flwr.proto.ClientMessage.GetPropertiesResH\x00\x12H\n\x12get_parameters_res\x18\x03 \x01(\x0b\x32*.flwr.proto.ClientMessage.GetParametersResH\x00\x12\x33\n\x07\x66it_res\x18\x04 \x01(\x0b\x32 .flwr.proto.ClientMessage.FitResH\x00\x12=\n\x0c\x65valuate_res\x18\x05 \x01(\x0b\x32%.flwr.proto.ClientMessage.EvaluateResH\x00\x1a\x33\n\rDisconnectRes\x12\"\n\x06reason\x18\x01 \x01(\x0e\x32\x12.flwr.proto.Reason\x1a\xcd\x01\n\x10GetPropertiesRes\x12\"\n\x06status\x18\x01 \x01(\x0b\x32\x12.flwr.proto.Status\x12N\n\nproperties\x18\x02 \x03(\x0b\x32:.flwr.proto.ClientMessage.GetPropertiesRes.PropertiesEntry\x1a\x45\n\x0fPropertiesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.flwr.proto.Scalar:\x02\x38\x01\x1a\x62\n\x10GetParametersRes\x12\"\n\x06status\x18\x01 \x01(\x0b\x32\x12.flwr.proto.Status\x12*\n\nparameters\x18\x02 \x01(\x0b\x32\x16.flwr.proto.Parameters\x1a\xf2\x01\n\x06\x46itRes\x12\"\n\x06status\x18\x01 \x01(\x0b\x32\x12.flwr.proto.Status\x12*\n\nparameters\x18\x02 \x01(\x0b\x32\x16.flwr.proto.Parameters\x12\x14\n\x0cnum_examples\x18\x03 \x01(\x03\x12>\n\x07metrics\x18\x04 \x03(\x0b\x32-.flwr.proto.ClientMessage.FitRes.MetricsEntry\x1a\x42\n\x0cMetricsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.flwr.proto.Scalar:\x02\x38\x01\x1a\xde\x01\n\x0b\x45valuateRes\x12\"\n\x06status\x18\x01 \x01(\x0b\x32\x12.flwr.proto.Status\x12\x0c\n\x04loss\x18\x02 \x01(\x02\x12\x14\n\x0cnum_examples\x18\x03 \x01(\x03\x12\x43\n\x07metrics\x18\x04 \x03(\x0b\x32\x32.flwr.proto.ClientMessage.EvaluateRes.MetricsEntry\x1a\x42\n\x0cMetricsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.flwr.proto.Scalar:\x02\x38\x01\x42\x05\n\x03msg\"i\n\x06Scalar\x12\x10\n\x06\x64ouble\x18\x01 \x01(\x01H\x00\x12\x10\n\x06sint64\x18\x08 \x01(\x12H\x00\x12\x0e\n\x04\x62ool\x18\r \x01(\x08H\x00\x12\x10\n\x06string\x18\x0e \x01(\tH\x00\x12\x0f\n\x05\x62ytes\x18\x0f \x01(\x0cH\x00\x42\x08\n\x06scalar*\x8d\x01\n\x04\x43ode\x12\x06\n\x02OK\x10\x00\x12\"\n\x1eGET_PROPERTIES_NOT_IMPLEMENTED\x10\x01\x12\"\n\x1eGET_PARAMETERS_NOT_IMPLEMENTED\x10\x02\x12\x17\n\x13\x46IT_NOT_IMPLEMENTED\x10\x03\x12\x1c\n\x18\x45VALUATE_NOT_IMPLEMENTED\x10\x04*[\n\x06Reason\x12\x0b\n\x07UNKNOWN\x10\x00\x12\r\n\tRECONNECT\x10\x01\x12\x16\n\x12POWER_DISCONNECTED\x10\x02\x12\x14\n\x10WIFI_UNAVAILABLE\x10\x03\x12\x07\n\x03\x41\x43K\x10\x04\x32S\n\rFlowerService\x12\x42\n\x04Join\x12\x19.flwr.proto.ClientMessage\x1a\x19.flwr.proto.ServerMessage\"\x00(\x01\x30\x01\x62\x06proto3') -_CODE = DESCRIPTOR.enum_types_by_name['Code'] -Code = enum_type_wrapper.EnumTypeWrapper(_CODE) -_REASON = DESCRIPTOR.enum_types_by_name['Reason'] -Reason = enum_type_wrapper.EnumTypeWrapper(_REASON) -OK = 0 -GET_PROPERTIES_NOT_IMPLEMENTED = 1 -GET_PARAMETERS_NOT_IMPLEMENTED = 2 -FIT_NOT_IMPLEMENTED = 3 -EVALUATE_NOT_IMPLEMENTED = 4 -UNKNOWN = 0 -RECONNECT = 1 -POWER_DISCONNECTED = 2 -WIFI_UNAVAILABLE = 3 -ACK = 4 - - -_STATUS = DESCRIPTOR.message_types_by_name['Status'] -_PARAMETERS = DESCRIPTOR.message_types_by_name['Parameters'] -_SERVERMESSAGE = DESCRIPTOR.message_types_by_name['ServerMessage'] -_SERVERMESSAGE_RECONNECTINS = _SERVERMESSAGE.nested_types_by_name['ReconnectIns'] -_SERVERMESSAGE_GETPROPERTIESINS = _SERVERMESSAGE.nested_types_by_name['GetPropertiesIns'] -_SERVERMESSAGE_GETPROPERTIESINS_CONFIGENTRY = _SERVERMESSAGE_GETPROPERTIESINS.nested_types_by_name['ConfigEntry'] -_SERVERMESSAGE_GETPARAMETERSINS = _SERVERMESSAGE.nested_types_by_name['GetParametersIns'] -_SERVERMESSAGE_GETPARAMETERSINS_CONFIGENTRY = _SERVERMESSAGE_GETPARAMETERSINS.nested_types_by_name['ConfigEntry'] -_SERVERMESSAGE_FITINS = _SERVERMESSAGE.nested_types_by_name['FitIns'] -_SERVERMESSAGE_FITINS_CONFIGENTRY = _SERVERMESSAGE_FITINS.nested_types_by_name['ConfigEntry'] -_SERVERMESSAGE_EVALUATEINS = _SERVERMESSAGE.nested_types_by_name['EvaluateIns'] -_SERVERMESSAGE_EVALUATEINS_CONFIGENTRY = _SERVERMESSAGE_EVALUATEINS.nested_types_by_name['ConfigEntry'] -_CLIENTMESSAGE = DESCRIPTOR.message_types_by_name['ClientMessage'] -_CLIENTMESSAGE_DISCONNECTRES = _CLIENTMESSAGE.nested_types_by_name['DisconnectRes'] -_CLIENTMESSAGE_GETPROPERTIESRES = _CLIENTMESSAGE.nested_types_by_name['GetPropertiesRes'] -_CLIENTMESSAGE_GETPROPERTIESRES_PROPERTIESENTRY = _CLIENTMESSAGE_GETPROPERTIESRES.nested_types_by_name['PropertiesEntry'] -_CLIENTMESSAGE_GETPARAMETERSRES = _CLIENTMESSAGE.nested_types_by_name['GetParametersRes'] -_CLIENTMESSAGE_FITRES = _CLIENTMESSAGE.nested_types_by_name['FitRes'] -_CLIENTMESSAGE_FITRES_METRICSENTRY = _CLIENTMESSAGE_FITRES.nested_types_by_name['MetricsEntry'] -_CLIENTMESSAGE_EVALUATERES = _CLIENTMESSAGE.nested_types_by_name['EvaluateRes'] -_CLIENTMESSAGE_EVALUATERES_METRICSENTRY = _CLIENTMESSAGE_EVALUATERES.nested_types_by_name['MetricsEntry'] -_SCALAR = DESCRIPTOR.message_types_by_name['Scalar'] -Status = _reflection.GeneratedProtocolMessageType('Status', (_message.Message,), { - 'DESCRIPTOR' : _STATUS, - '__module__' : 'flwr.proto.transport_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.Status) - }) -_sym_db.RegisterMessage(Status) - -Parameters = _reflection.GeneratedProtocolMessageType('Parameters', (_message.Message,), { - 'DESCRIPTOR' : _PARAMETERS, - '__module__' : 'flwr.proto.transport_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.Parameters) - }) -_sym_db.RegisterMessage(Parameters) - -ServerMessage = _reflection.GeneratedProtocolMessageType('ServerMessage', (_message.Message,), { - - 'ReconnectIns' : _reflection.GeneratedProtocolMessageType('ReconnectIns', (_message.Message,), { - 'DESCRIPTOR' : _SERVERMESSAGE_RECONNECTINS, - '__module__' : 'flwr.proto.transport_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.ServerMessage.ReconnectIns) - }) - , - - 'GetPropertiesIns' : _reflection.GeneratedProtocolMessageType('GetPropertiesIns', (_message.Message,), { - - 'ConfigEntry' : _reflection.GeneratedProtocolMessageType('ConfigEntry', (_message.Message,), { - 'DESCRIPTOR' : _SERVERMESSAGE_GETPROPERTIESINS_CONFIGENTRY, - '__module__' : 'flwr.proto.transport_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.ServerMessage.GetPropertiesIns.ConfigEntry) - }) - , - 'DESCRIPTOR' : _SERVERMESSAGE_GETPROPERTIESINS, - '__module__' : 'flwr.proto.transport_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.ServerMessage.GetPropertiesIns) - }) - , - - 'GetParametersIns' : _reflection.GeneratedProtocolMessageType('GetParametersIns', (_message.Message,), { - - 'ConfigEntry' : _reflection.GeneratedProtocolMessageType('ConfigEntry', (_message.Message,), { - 'DESCRIPTOR' : _SERVERMESSAGE_GETPARAMETERSINS_CONFIGENTRY, - '__module__' : 'flwr.proto.transport_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.ServerMessage.GetParametersIns.ConfigEntry) - }) - , - 'DESCRIPTOR' : _SERVERMESSAGE_GETPARAMETERSINS, - '__module__' : 'flwr.proto.transport_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.ServerMessage.GetParametersIns) - }) - , - - 'FitIns' : _reflection.GeneratedProtocolMessageType('FitIns', (_message.Message,), { - - 'ConfigEntry' : _reflection.GeneratedProtocolMessageType('ConfigEntry', (_message.Message,), { - 'DESCRIPTOR' : _SERVERMESSAGE_FITINS_CONFIGENTRY, - '__module__' : 'flwr.proto.transport_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.ServerMessage.FitIns.ConfigEntry) - }) - , - 'DESCRIPTOR' : _SERVERMESSAGE_FITINS, - '__module__' : 'flwr.proto.transport_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.ServerMessage.FitIns) - }) - , - - 'EvaluateIns' : _reflection.GeneratedProtocolMessageType('EvaluateIns', (_message.Message,), { - - 'ConfigEntry' : _reflection.GeneratedProtocolMessageType('ConfigEntry', (_message.Message,), { - 'DESCRIPTOR' : _SERVERMESSAGE_EVALUATEINS_CONFIGENTRY, - '__module__' : 'flwr.proto.transport_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.ServerMessage.EvaluateIns.ConfigEntry) - }) - , - 'DESCRIPTOR' : _SERVERMESSAGE_EVALUATEINS, - '__module__' : 'flwr.proto.transport_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.ServerMessage.EvaluateIns) - }) - , - 'DESCRIPTOR' : _SERVERMESSAGE, - '__module__' : 'flwr.proto.transport_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.ServerMessage) - }) -_sym_db.RegisterMessage(ServerMessage) -_sym_db.RegisterMessage(ServerMessage.ReconnectIns) -_sym_db.RegisterMessage(ServerMessage.GetPropertiesIns) -_sym_db.RegisterMessage(ServerMessage.GetPropertiesIns.ConfigEntry) -_sym_db.RegisterMessage(ServerMessage.GetParametersIns) -_sym_db.RegisterMessage(ServerMessage.GetParametersIns.ConfigEntry) -_sym_db.RegisterMessage(ServerMessage.FitIns) -_sym_db.RegisterMessage(ServerMessage.FitIns.ConfigEntry) -_sym_db.RegisterMessage(ServerMessage.EvaluateIns) -_sym_db.RegisterMessage(ServerMessage.EvaluateIns.ConfigEntry) - -ClientMessage = _reflection.GeneratedProtocolMessageType('ClientMessage', (_message.Message,), { - - 'DisconnectRes' : _reflection.GeneratedProtocolMessageType('DisconnectRes', (_message.Message,), { - 'DESCRIPTOR' : _CLIENTMESSAGE_DISCONNECTRES, - '__module__' : 'flwr.proto.transport_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.ClientMessage.DisconnectRes) - }) - , - - 'GetPropertiesRes' : _reflection.GeneratedProtocolMessageType('GetPropertiesRes', (_message.Message,), { - - 'PropertiesEntry' : _reflection.GeneratedProtocolMessageType('PropertiesEntry', (_message.Message,), { - 'DESCRIPTOR' : _CLIENTMESSAGE_GETPROPERTIESRES_PROPERTIESENTRY, - '__module__' : 'flwr.proto.transport_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.ClientMessage.GetPropertiesRes.PropertiesEntry) - }) - , - 'DESCRIPTOR' : _CLIENTMESSAGE_GETPROPERTIESRES, - '__module__' : 'flwr.proto.transport_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.ClientMessage.GetPropertiesRes) - }) - , - - 'GetParametersRes' : _reflection.GeneratedProtocolMessageType('GetParametersRes', (_message.Message,), { - 'DESCRIPTOR' : _CLIENTMESSAGE_GETPARAMETERSRES, - '__module__' : 'flwr.proto.transport_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.ClientMessage.GetParametersRes) - }) - , - - 'FitRes' : _reflection.GeneratedProtocolMessageType('FitRes', (_message.Message,), { - - 'MetricsEntry' : _reflection.GeneratedProtocolMessageType('MetricsEntry', (_message.Message,), { - 'DESCRIPTOR' : _CLIENTMESSAGE_FITRES_METRICSENTRY, - '__module__' : 'flwr.proto.transport_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.ClientMessage.FitRes.MetricsEntry) - }) - , - 'DESCRIPTOR' : _CLIENTMESSAGE_FITRES, - '__module__' : 'flwr.proto.transport_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.ClientMessage.FitRes) - }) - , - - 'EvaluateRes' : _reflection.GeneratedProtocolMessageType('EvaluateRes', (_message.Message,), { - - 'MetricsEntry' : _reflection.GeneratedProtocolMessageType('MetricsEntry', (_message.Message,), { - 'DESCRIPTOR' : _CLIENTMESSAGE_EVALUATERES_METRICSENTRY, - '__module__' : 'flwr.proto.transport_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.ClientMessage.EvaluateRes.MetricsEntry) - }) - , - 'DESCRIPTOR' : _CLIENTMESSAGE_EVALUATERES, - '__module__' : 'flwr.proto.transport_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.ClientMessage.EvaluateRes) - }) - , - 'DESCRIPTOR' : _CLIENTMESSAGE, - '__module__' : 'flwr.proto.transport_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.ClientMessage) - }) -_sym_db.RegisterMessage(ClientMessage) -_sym_db.RegisterMessage(ClientMessage.DisconnectRes) -_sym_db.RegisterMessage(ClientMessage.GetPropertiesRes) -_sym_db.RegisterMessage(ClientMessage.GetPropertiesRes.PropertiesEntry) -_sym_db.RegisterMessage(ClientMessage.GetParametersRes) -_sym_db.RegisterMessage(ClientMessage.FitRes) -_sym_db.RegisterMessage(ClientMessage.FitRes.MetricsEntry) -_sym_db.RegisterMessage(ClientMessage.EvaluateRes) -_sym_db.RegisterMessage(ClientMessage.EvaluateRes.MetricsEntry) - -Scalar = _reflection.GeneratedProtocolMessageType('Scalar', (_message.Message,), { - 'DESCRIPTOR' : _SCALAR, - '__module__' : 'flwr.proto.transport_pb2' - # @@protoc_insertion_point(class_scope:flwr.proto.Scalar) - }) -_sym_db.RegisterMessage(Scalar) - -_FLOWERSERVICE = DESCRIPTOR.services_by_name['FlowerService'] +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.transport_pb2', _globals) if _descriptor._USE_C_DESCRIPTORS == False: - DESCRIPTOR._options = None - _SERVERMESSAGE_GETPROPERTIESINS_CONFIGENTRY._options = None - _SERVERMESSAGE_GETPROPERTIESINS_CONFIGENTRY._serialized_options = b'8\001' - _SERVERMESSAGE_GETPARAMETERSINS_CONFIGENTRY._options = None - _SERVERMESSAGE_GETPARAMETERSINS_CONFIGENTRY._serialized_options = b'8\001' - _SERVERMESSAGE_FITINS_CONFIGENTRY._options = None - _SERVERMESSAGE_FITINS_CONFIGENTRY._serialized_options = b'8\001' - _SERVERMESSAGE_EVALUATEINS_CONFIGENTRY._options = None - _SERVERMESSAGE_EVALUATEINS_CONFIGENTRY._serialized_options = b'8\001' - _CLIENTMESSAGE_GETPROPERTIESRES_PROPERTIESENTRY._options = None - _CLIENTMESSAGE_GETPROPERTIESRES_PROPERTIESENTRY._serialized_options = b'8\001' - _CLIENTMESSAGE_FITRES_METRICSENTRY._options = None - _CLIENTMESSAGE_FITRES_METRICSENTRY._serialized_options = b'8\001' - _CLIENTMESSAGE_EVALUATERES_METRICSENTRY._options = None - _CLIENTMESSAGE_EVALUATERES_METRICSENTRY._serialized_options = b'8\001' - _CODE._serialized_start=2533 - _CODE._serialized_end=2674 - _REASON._serialized_start=2676 - _REASON._serialized_end=2767 - _STATUS._serialized_start=42 - _STATUS._serialized_end=99 - _PARAMETERS._serialized_start=101 - _PARAMETERS._serialized_end=151 - _SERVERMESSAGE._serialized_start=154 - _SERVERMESSAGE._serialized_end=1236 - _SERVERMESSAGE_RECONNECTINS._serialized_start=500 - _SERVERMESSAGE_RECONNECTINS._serialized_end=531 - _SERVERMESSAGE_GETPROPERTIESINS._serialized_start=534 - _SERVERMESSAGE_GETPROPERTIESINS._serialized_end=691 - _SERVERMESSAGE_GETPROPERTIESINS_CONFIGENTRY._serialized_start=626 - _SERVERMESSAGE_GETPROPERTIESINS_CONFIGENTRY._serialized_end=691 - _SERVERMESSAGE_GETPARAMETERSINS._serialized_start=694 - _SERVERMESSAGE_GETPARAMETERSINS._serialized_end=851 - _SERVERMESSAGE_GETPARAMETERSINS_CONFIGENTRY._serialized_start=626 - _SERVERMESSAGE_GETPARAMETERSINS_CONFIGENTRY._serialized_end=691 - _SERVERMESSAGE_FITINS._serialized_start=854 - _SERVERMESSAGE_FITINS._serialized_end=1035 - _SERVERMESSAGE_FITINS_CONFIGENTRY._serialized_start=626 - _SERVERMESSAGE_FITINS_CONFIGENTRY._serialized_end=691 - _SERVERMESSAGE_EVALUATEINS._serialized_start=1038 - _SERVERMESSAGE_EVALUATEINS._serialized_end=1229 - _SERVERMESSAGE_EVALUATEINS_CONFIGENTRY._serialized_start=626 - _SERVERMESSAGE_EVALUATEINS_CONFIGENTRY._serialized_end=691 - _CLIENTMESSAGE._serialized_start=1239 - _CLIENTMESSAGE._serialized_end=2423 - _CLIENTMESSAGE_DISCONNECTRES._serialized_start=1587 - _CLIENTMESSAGE_DISCONNECTRES._serialized_end=1638 - _CLIENTMESSAGE_GETPROPERTIESRES._serialized_start=1641 - _CLIENTMESSAGE_GETPROPERTIESRES._serialized_end=1846 - _CLIENTMESSAGE_GETPROPERTIESRES_PROPERTIESENTRY._serialized_start=1777 - _CLIENTMESSAGE_GETPROPERTIESRES_PROPERTIESENTRY._serialized_end=1846 - _CLIENTMESSAGE_GETPARAMETERSRES._serialized_start=1848 - _CLIENTMESSAGE_GETPARAMETERSRES._serialized_end=1946 - _CLIENTMESSAGE_FITRES._serialized_start=1949 - _CLIENTMESSAGE_FITRES._serialized_end=2191 - _CLIENTMESSAGE_FITRES_METRICSENTRY._serialized_start=2125 - _CLIENTMESSAGE_FITRES_METRICSENTRY._serialized_end=2191 - _CLIENTMESSAGE_EVALUATERES._serialized_start=2194 - _CLIENTMESSAGE_EVALUATERES._serialized_end=2416 - _CLIENTMESSAGE_EVALUATERES_METRICSENTRY._serialized_start=2125 - _CLIENTMESSAGE_EVALUATERES_METRICSENTRY._serialized_end=2191 - _SCALAR._serialized_start=2425 - _SCALAR._serialized_end=2530 - _FLOWERSERVICE._serialized_start=2769 - _FLOWERSERVICE._serialized_end=2852 + _globals['_SERVERMESSAGE_GETPROPERTIESINS_CONFIGENTRY']._options = None + _globals['_SERVERMESSAGE_GETPROPERTIESINS_CONFIGENTRY']._serialized_options = b'8\001' + _globals['_SERVERMESSAGE_GETPARAMETERSINS_CONFIGENTRY']._options = None + _globals['_SERVERMESSAGE_GETPARAMETERSINS_CONFIGENTRY']._serialized_options = b'8\001' + _globals['_SERVERMESSAGE_FITINS_CONFIGENTRY']._options = None + _globals['_SERVERMESSAGE_FITINS_CONFIGENTRY']._serialized_options = b'8\001' + _globals['_SERVERMESSAGE_EVALUATEINS_CONFIGENTRY']._options = None + _globals['_SERVERMESSAGE_EVALUATEINS_CONFIGENTRY']._serialized_options = b'8\001' + _globals['_CLIENTMESSAGE_GETPROPERTIESRES_PROPERTIESENTRY']._options = None + _globals['_CLIENTMESSAGE_GETPROPERTIESRES_PROPERTIESENTRY']._serialized_options = b'8\001' + _globals['_CLIENTMESSAGE_FITRES_METRICSENTRY']._options = None + _globals['_CLIENTMESSAGE_FITRES_METRICSENTRY']._serialized_options = b'8\001' + _globals['_CLIENTMESSAGE_EVALUATERES_METRICSENTRY']._options = None + _globals['_CLIENTMESSAGE_EVALUATERES_METRICSENTRY']._serialized_options = b'8\001' + _globals['_CODE']._serialized_start=2533 + _globals['_CODE']._serialized_end=2674 + _globals['_REASON']._serialized_start=2676 + _globals['_REASON']._serialized_end=2767 + _globals['_STATUS']._serialized_start=42 + _globals['_STATUS']._serialized_end=99 + _globals['_PARAMETERS']._serialized_start=101 + _globals['_PARAMETERS']._serialized_end=151 + _globals['_SERVERMESSAGE']._serialized_start=154 + _globals['_SERVERMESSAGE']._serialized_end=1236 + _globals['_SERVERMESSAGE_RECONNECTINS']._serialized_start=500 + _globals['_SERVERMESSAGE_RECONNECTINS']._serialized_end=531 + _globals['_SERVERMESSAGE_GETPROPERTIESINS']._serialized_start=534 + _globals['_SERVERMESSAGE_GETPROPERTIESINS']._serialized_end=691 + _globals['_SERVERMESSAGE_GETPROPERTIESINS_CONFIGENTRY']._serialized_start=626 + _globals['_SERVERMESSAGE_GETPROPERTIESINS_CONFIGENTRY']._serialized_end=691 + _globals['_SERVERMESSAGE_GETPARAMETERSINS']._serialized_start=694 + _globals['_SERVERMESSAGE_GETPARAMETERSINS']._serialized_end=851 + _globals['_SERVERMESSAGE_GETPARAMETERSINS_CONFIGENTRY']._serialized_start=626 + _globals['_SERVERMESSAGE_GETPARAMETERSINS_CONFIGENTRY']._serialized_end=691 + _globals['_SERVERMESSAGE_FITINS']._serialized_start=854 + _globals['_SERVERMESSAGE_FITINS']._serialized_end=1035 + _globals['_SERVERMESSAGE_FITINS_CONFIGENTRY']._serialized_start=626 + _globals['_SERVERMESSAGE_FITINS_CONFIGENTRY']._serialized_end=691 + _globals['_SERVERMESSAGE_EVALUATEINS']._serialized_start=1038 + _globals['_SERVERMESSAGE_EVALUATEINS']._serialized_end=1229 + _globals['_SERVERMESSAGE_EVALUATEINS_CONFIGENTRY']._serialized_start=626 + _globals['_SERVERMESSAGE_EVALUATEINS_CONFIGENTRY']._serialized_end=691 + _globals['_CLIENTMESSAGE']._serialized_start=1239 + _globals['_CLIENTMESSAGE']._serialized_end=2423 + _globals['_CLIENTMESSAGE_DISCONNECTRES']._serialized_start=1587 + _globals['_CLIENTMESSAGE_DISCONNECTRES']._serialized_end=1638 + _globals['_CLIENTMESSAGE_GETPROPERTIESRES']._serialized_start=1641 + _globals['_CLIENTMESSAGE_GETPROPERTIESRES']._serialized_end=1846 + _globals['_CLIENTMESSAGE_GETPROPERTIESRES_PROPERTIESENTRY']._serialized_start=1777 + _globals['_CLIENTMESSAGE_GETPROPERTIESRES_PROPERTIESENTRY']._serialized_end=1846 + _globals['_CLIENTMESSAGE_GETPARAMETERSRES']._serialized_start=1848 + _globals['_CLIENTMESSAGE_GETPARAMETERSRES']._serialized_end=1946 + _globals['_CLIENTMESSAGE_FITRES']._serialized_start=1949 + _globals['_CLIENTMESSAGE_FITRES']._serialized_end=2191 + _globals['_CLIENTMESSAGE_FITRES_METRICSENTRY']._serialized_start=2125 + _globals['_CLIENTMESSAGE_FITRES_METRICSENTRY']._serialized_end=2191 + _globals['_CLIENTMESSAGE_EVALUATERES']._serialized_start=2194 + _globals['_CLIENTMESSAGE_EVALUATERES']._serialized_end=2416 + _globals['_CLIENTMESSAGE_EVALUATERES_METRICSENTRY']._serialized_start=2125 + _globals['_CLIENTMESSAGE_EVALUATERES_METRICSENTRY']._serialized_end=2191 + _globals['_SCALAR']._serialized_start=2425 + _globals['_SCALAR']._serialized_end=2530 + _globals['_FLOWERSERVICE']._serialized_start=2769 + _globals['_FLOWERSERVICE']._serialized_end=2852 # @@protoc_insertion_point(module_scope) diff --git a/src/py/flwr/server/app.py b/src/py/flwr/server/app.py index 63c24c37a685..636207e7a859 100644 --- a/src/py/flwr/server/app.py +++ b/src/py/flwr/server/app.py @@ -38,9 +38,15 @@ TRANSPORT_TYPE_REST, ) from flwr.common.logger import log -from flwr.proto.driver_pb2_grpc import add_DriverServicer_to_server -from flwr.proto.fleet_pb2_grpc import add_FleetServicer_to_server -from flwr.proto.transport_pb2_grpc import add_FlowerServiceServicer_to_server +from flwr.proto.driver_pb2_grpc import ( # pylint: disable=E0611 + add_DriverServicer_to_server, +) +from flwr.proto.fleet_pb2_grpc import ( # pylint: disable=E0611 + add_FleetServicer_to_server, +) +from flwr.proto.transport_pb2_grpc import ( # pylint: disable=E0611 + add_FlowerServiceServicer_to_server, +) from flwr.server.client_manager import ClientManager, SimpleClientManager from flwr.server.driver.driver_servicer import DriverServicer from flwr.server.fleet.grpc_bidi.driver_client_manager import DriverClientManager diff --git a/src/py/flwr/server/driver/driver_servicer.py b/src/py/flwr/server/driver/driver_servicer.py index 546ebd884ca9..275cc8ac6a03 100644 --- a/src/py/flwr/server/driver/driver_servicer.py +++ b/src/py/flwr/server/driver/driver_servicer.py @@ -22,8 +22,8 @@ import grpc from flwr.common.logger import log -from flwr.proto import driver_pb2_grpc -from flwr.proto.driver_pb2 import ( +from flwr.proto import driver_pb2_grpc # pylint: disable=E0611 +from flwr.proto.driver_pb2 import ( # pylint: disable=E0611 CreateRunRequest, CreateRunResponse, GetNodesRequest, @@ -33,8 +33,8 @@ PushTaskInsRequest, PushTaskInsResponse, ) -from flwr.proto.node_pb2 import Node -from flwr.proto.task_pb2 import TaskRes +from flwr.proto.node_pb2 import Node # pylint: disable=E0611 +from flwr.proto.task_pb2 import TaskRes # pylint: disable=E0611 from flwr.server.state import State, StateFactory from flwr.server.utils.validator import validate_task_ins_or_res diff --git a/src/py/flwr/server/fleet/grpc_bidi/flower_service_servicer.py b/src/py/flwr/server/fleet/grpc_bidi/flower_service_servicer.py index 1f7a8e9259fc..6eccb056390a 100644 --- a/src/py/flwr/server/fleet/grpc_bidi/flower_service_servicer.py +++ b/src/py/flwr/server/fleet/grpc_bidi/flower_service_servicer.py @@ -24,8 +24,11 @@ import grpc from iterators import TimeoutIterator -from flwr.proto import transport_pb2_grpc -from flwr.proto.transport_pb2 import ClientMessage, ServerMessage +from flwr.proto import transport_pb2_grpc # pylint: disable=E0611 +from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 + ClientMessage, + ServerMessage, +) from flwr.server.client_manager import ClientManager from flwr.server.fleet.grpc_bidi.grpc_bridge import GrpcBridge, InsWrapper, ResWrapper from flwr.server.fleet.grpc_bidi.grpc_client_proxy import GrpcClientProxy diff --git a/src/py/flwr/server/fleet/grpc_bidi/flower_service_servicer_test.py b/src/py/flwr/server/fleet/grpc_bidi/flower_service_servicer_test.py index 64140ed274c9..b5c3f504af03 100644 --- a/src/py/flwr/server/fleet/grpc_bidi/flower_service_servicer_test.py +++ b/src/py/flwr/server/fleet/grpc_bidi/flower_service_servicer_test.py @@ -18,7 +18,10 @@ import unittest from unittest.mock import MagicMock, call -from flwr.proto.transport_pb2 import ClientMessage, ServerMessage +from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 + ClientMessage, + ServerMessage, +) from flwr.server.fleet.grpc_bidi.flower_service_servicer import ( FlowerServiceServicer, register_client_proxy, diff --git a/src/py/flwr/server/fleet/grpc_bidi/grpc_bridge.py b/src/py/flwr/server/fleet/grpc_bidi/grpc_bridge.py index 4e68499f018d..d5b4a915c609 100644 --- a/src/py/flwr/server/fleet/grpc_bidi/grpc_bridge.py +++ b/src/py/flwr/server/fleet/grpc_bidi/grpc_bridge.py @@ -20,7 +20,10 @@ from threading import Condition from typing import Iterator, Optional -from flwr.proto.transport_pb2 import ClientMessage, ServerMessage +from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 + ClientMessage, + ServerMessage, +) @dataclass diff --git a/src/py/flwr/server/fleet/grpc_bidi/grpc_bridge_test.py b/src/py/flwr/server/fleet/grpc_bidi/grpc_bridge_test.py index bcfbe6e6fac8..6527c45d7d6c 100644 --- a/src/py/flwr/server/fleet/grpc_bidi/grpc_bridge_test.py +++ b/src/py/flwr/server/fleet/grpc_bidi/grpc_bridge_test.py @@ -19,7 +19,10 @@ from threading import Thread from typing import List, Union -from flwr.proto.transport_pb2 import ClientMessage, ServerMessage +from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 + ClientMessage, + ServerMessage, +) from flwr.server.fleet.grpc_bidi.grpc_bridge import ( GrpcBridge, GrpcBridgeClosed, diff --git a/src/py/flwr/server/fleet/grpc_bidi/grpc_client_proxy.py b/src/py/flwr/server/fleet/grpc_bidi/grpc_client_proxy.py index b9bc7330db31..46185896561e 100644 --- a/src/py/flwr/server/fleet/grpc_bidi/grpc_client_proxy.py +++ b/src/py/flwr/server/fleet/grpc_bidi/grpc_client_proxy.py @@ -19,7 +19,10 @@ from flwr import common from flwr.common import serde -from flwr.proto.transport_pb2 import ClientMessage, ServerMessage +from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 + ClientMessage, + ServerMessage, +) from flwr.server.client_proxy import ClientProxy from flwr.server.fleet.grpc_bidi.grpc_bridge import GrpcBridge, InsWrapper, ResWrapper diff --git a/src/py/flwr/server/fleet/grpc_bidi/grpc_client_proxy_test.py b/src/py/flwr/server/fleet/grpc_bidi/grpc_client_proxy_test.py index 329f29b3f616..1a417ae433d5 100644 --- a/src/py/flwr/server/fleet/grpc_bidi/grpc_client_proxy_test.py +++ b/src/py/flwr/server/fleet/grpc_bidi/grpc_client_proxy_test.py @@ -22,7 +22,11 @@ import flwr from flwr.common.typing import Config, GetParametersIns -from flwr.proto.transport_pb2 import ClientMessage, Parameters, Scalar +from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 + ClientMessage, + Parameters, + Scalar, +) from flwr.server.fleet.grpc_bidi.grpc_bridge import ResWrapper from flwr.server.fleet.grpc_bidi.grpc_client_proxy import GrpcClientProxy diff --git a/src/py/flwr/server/fleet/grpc_bidi/grpc_server.py b/src/py/flwr/server/fleet/grpc_bidi/grpc_server.py index fc81e8eb8f4c..e05df88dcd12 100644 --- a/src/py/flwr/server/fleet/grpc_bidi/grpc_server.py +++ b/src/py/flwr/server/fleet/grpc_bidi/grpc_server.py @@ -24,7 +24,9 @@ from flwr.common import GRPC_MAX_MESSAGE_LENGTH from flwr.common.logger import log -from flwr.proto.transport_pb2_grpc import add_FlowerServiceServicer_to_server +from flwr.proto.transport_pb2_grpc import ( # pylint: disable=E0611 + add_FlowerServiceServicer_to_server, +) from flwr.server.client_manager import ClientManager from flwr.server.driver.driver_servicer import DriverServicer from flwr.server.fleet.grpc_bidi.flower_service_servicer import FlowerServiceServicer diff --git a/src/py/flwr/server/fleet/grpc_bidi/ins_scheduler.py b/src/py/flwr/server/fleet/grpc_bidi/ins_scheduler.py index 0fa6f82a89b5..5843934b64a4 100644 --- a/src/py/flwr/server/fleet/grpc_bidi/ins_scheduler.py +++ b/src/py/flwr/server/fleet/grpc_bidi/ins_scheduler.py @@ -23,9 +23,12 @@ from flwr.client.message_handler.task_handler import configure_task_res from flwr.common import EvaluateRes, FitRes, GetParametersRes, GetPropertiesRes, serde from flwr.common.logger import log -from flwr.proto.node_pb2 import Node -from flwr.proto.task_pb2 import Task, TaskIns, TaskRes -from flwr.proto.transport_pb2 import ClientMessage, ServerMessage +from flwr.proto.node_pb2 import Node # pylint: disable=E0611 +from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611 +from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 + ClientMessage, + ServerMessage, +) from flwr.server.client_proxy import ClientProxy from flwr.server.state import State, StateFactory diff --git a/src/py/flwr/server/fleet/grpc_rere/fleet_servicer.py b/src/py/flwr/server/fleet/grpc_rere/fleet_servicer.py index 022470cffe8a..b12f365e898c 100644 --- a/src/py/flwr/server/fleet/grpc_rere/fleet_servicer.py +++ b/src/py/flwr/server/fleet/grpc_rere/fleet_servicer.py @@ -20,8 +20,8 @@ import grpc from flwr.common.logger import log -from flwr.proto import fleet_pb2_grpc -from flwr.proto.fleet_pb2 import ( +from flwr.proto import fleet_pb2_grpc # pylint: disable=E0611 +from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611 CreateNodeRequest, CreateNodeResponse, DeleteNodeRequest, diff --git a/src/py/flwr/server/fleet/message_handler/message_handler.py b/src/py/flwr/server/fleet/message_handler/message_handler.py index 71876386f059..8d451c896ed9 100644 --- a/src/py/flwr/server/fleet/message_handler/message_handler.py +++ b/src/py/flwr/server/fleet/message_handler/message_handler.py @@ -18,7 +18,7 @@ from typing import List, Optional from uuid import UUID -from flwr.proto.fleet_pb2 import ( +from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611 CreateNodeRequest, CreateNodeResponse, DeleteNodeRequest, @@ -29,8 +29,8 @@ PushTaskResResponse, Reconnect, ) -from flwr.proto.node_pb2 import Node -from flwr.proto.task_pb2 import TaskIns, TaskRes +from flwr.proto.node_pb2 import Node # pylint: disable=E0611 +from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611 from flwr.server.state import State diff --git a/src/py/flwr/server/fleet/message_handler/message_handler_test.py b/src/py/flwr/server/fleet/message_handler/message_handler_test.py index bb2205e26b18..c135f6fb7b61 100644 --- a/src/py/flwr/server/fleet/message_handler/message_handler_test.py +++ b/src/py/flwr/server/fleet/message_handler/message_handler_test.py @@ -17,14 +17,14 @@ from unittest.mock import MagicMock -from flwr.proto.fleet_pb2 import ( +from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611 CreateNodeRequest, DeleteNodeRequest, PullTaskInsRequest, PushTaskResRequest, ) -from flwr.proto.node_pb2 import Node -from flwr.proto.task_pb2 import Task, TaskRes +from flwr.proto.node_pb2 import Node # pylint: disable=E0611 +from flwr.proto.task_pb2 import Task, TaskRes # pylint: disable=E0611 from .message_handler import create_node, delete_node, pull_task_ins, push_task_res diff --git a/src/py/flwr/server/fleet/rest_rere/rest_api.py b/src/py/flwr/server/fleet/rest_rere/rest_api.py index cd1e47f24f00..b815558cb099 100644 --- a/src/py/flwr/server/fleet/rest_rere/rest_api.py +++ b/src/py/flwr/server/fleet/rest_rere/rest_api.py @@ -18,7 +18,7 @@ import sys from flwr.common.constant import MISSING_EXTRA_REST -from flwr.proto.fleet_pb2 import ( +from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611 CreateNodeRequest, DeleteNodeRequest, PullTaskInsRequest, diff --git a/src/py/flwr/server/state/in_memory_state.py b/src/py/flwr/server/state/in_memory_state.py index f8352fcfb091..f21845fcb909 100644 --- a/src/py/flwr/server/state/in_memory_state.py +++ b/src/py/flwr/server/state/in_memory_state.py @@ -22,7 +22,7 @@ from uuid import UUID, uuid4 from flwr.common import log, now -from flwr.proto.task_pb2 import TaskIns, TaskRes +from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611 from flwr.server.state.state import State from flwr.server.utils import validate_task_ins_or_res diff --git a/src/py/flwr/server/state/sqlite_state.py b/src/py/flwr/server/state/sqlite_state.py index 26f326819971..538ecb84491f 100644 --- a/src/py/flwr/server/state/sqlite_state.py +++ b/src/py/flwr/server/state/sqlite_state.py @@ -24,9 +24,12 @@ from uuid import UUID, uuid4 from flwr.common import log, now -from flwr.proto.node_pb2 import Node -from flwr.proto.task_pb2 import Task, TaskIns, TaskRes -from flwr.proto.transport_pb2 import ClientMessage, ServerMessage +from flwr.proto.node_pb2 import Node # pylint: disable=E0611 +from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611 +from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 + ClientMessage, + ServerMessage, +) from flwr.server.utils.validator import validate_task_ins_or_res from .state import State diff --git a/src/py/flwr/server/state/state.py b/src/py/flwr/server/state/state.py index 7ab3b6bc0848..9337ae6d8624 100644 --- a/src/py/flwr/server/state/state.py +++ b/src/py/flwr/server/state/state.py @@ -19,7 +19,7 @@ from typing import List, Optional, Set from uuid import UUID -from flwr.proto.task_pb2 import TaskIns, TaskRes +from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611 class State(abc.ABC): diff --git a/src/py/flwr/server/state/state_test.py b/src/py/flwr/server/state/state_test.py index 204b4ba97b5f..7f9094625765 100644 --- a/src/py/flwr/server/state/state_test.py +++ b/src/py/flwr/server/state/state_test.py @@ -22,9 +22,12 @@ from typing import List from uuid import uuid4 -from flwr.proto.node_pb2 import Node -from flwr.proto.task_pb2 import Task, TaskIns, TaskRes -from flwr.proto.transport_pb2 import ClientMessage, ServerMessage +from flwr.proto.node_pb2 import Node # pylint: disable=E0611 +from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611 +from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 + ClientMessage, + ServerMessage, +) from flwr.server.state import InMemoryState, SqliteState, State diff --git a/src/py/flwr/server/utils/validator.py b/src/py/flwr/server/utils/validator.py index fd89a01e4a4e..01dbcf982cce 100644 --- a/src/py/flwr/server/utils/validator.py +++ b/src/py/flwr/server/utils/validator.py @@ -17,7 +17,7 @@ from typing import List, Union -from flwr.proto.task_pb2 import TaskIns, TaskRes +from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611 # pylint: disable-next=too-many-branches,too-many-statements diff --git a/src/py/flwr/server/utils/validator_test.py b/src/py/flwr/server/utils/validator_test.py index 6627cc9a7887..a93e4fb4d457 100644 --- a/src/py/flwr/server/utils/validator_test.py +++ b/src/py/flwr/server/utils/validator_test.py @@ -18,9 +18,17 @@ import unittest from typing import List, Tuple -from flwr.proto.node_pb2 import Node -from flwr.proto.task_pb2 import SecureAggregation, Task, TaskIns, TaskRes -from flwr.proto.transport_pb2 import ClientMessage, ServerMessage +from flwr.proto.node_pb2 import Node # pylint: disable=E0611 +from flwr.proto.task_pb2 import ( # pylint: disable=E0611 + SecureAggregation, + Task, + TaskIns, + TaskRes, +) +from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 + ClientMessage, + ServerMessage, +) from .validator import validate_task_ins_or_res From 5ce2d8f60ca5975cf5b357f4e4737397836d7351 Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Thu, 18 Jan 2024 15:36:08 +0100 Subject: [PATCH 007/113] Add Python 3.11 to framework tests (#2394) Co-authored-by: Charles Beauville --- .github/workflows/framework.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/framework.yml b/.github/workflows/framework.yml index 0899940636d2..784f04750c5e 100644 --- a/.github/workflows/framework.yml +++ b/.github/workflows/framework.yml @@ -25,7 +25,7 @@ jobs: # In case of a mismatch, the job has to download Python to install it. # Note: Due to a bug in actions/setup-python we have to put 3.10 in # qoutes as it will otherwise will assume 3.1 - python: [3.8, 3.9, '3.10'] + python: [3.8, 3.9, '3.10', '3.11'] name: Python ${{ matrix.python }} From 9899dc9598a6bd4cc78248d70e0feca2aed2104c Mon Sep 17 00:00:00 2001 From: Adam Narozniak <51029327+adam-narozniak@users.noreply.github.com> Date: Thu, 18 Jan 2024 16:10:21 +0100 Subject: [PATCH 008/113] Make tensorflow e2e consistent with flwr (#2813) Co-authored-by: Javier --- datasets/e2e/tensorflow/pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/datasets/e2e/tensorflow/pyproject.toml b/datasets/e2e/tensorflow/pyproject.toml index 4d7b5f60e856..64c67c7695a5 100644 --- a/datasets/e2e/tensorflow/pyproject.toml +++ b/datasets/e2e/tensorflow/pyproject.toml @@ -12,4 +12,5 @@ authors = ["The Flower Authors "] python = ">=3.8,<3.11" flwr-datasets = { path = "./../../", extras = ["vision"] } tensorflow-cpu = "^2.9.1, !=2.11.1" +tensorflow-io-gcs-filesystem = "<0.35.0" parameterized = "==0.9.0" From 46bb216b7a5648fba1e5dde91a1a8df765751769 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Jan 2024 18:15:47 +0000 Subject: [PATCH 009/113] Update pytest requirement from ==7.4.3 to ==7.4.4 (#2811) --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 73a238615d60..d3c21bf6bf99 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -90,7 +90,7 @@ docformatter = "==1.7.5" mypy = "==1.6.1" pylint = "==3.0.3" flake8 = "==5.0.4" -pytest = "==7.4.3" +pytest = "==7.4.4" pytest-cov = "==4.1.0" pytest-watch = "==4.2.0" grpcio-tools = "==1.60.0" From ef01d29ab565ba5d111117515b0dd2802d5264ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Jan 2024 18:26:34 +0000 Subject: [PATCH 010/113] Update licensecheck requirement from ==2023.5.1 to ==2024 (#2810) --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index d3c21bf6bf99..4d15571b2491 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -121,7 +121,7 @@ pyroma = "==4.2" check-wheel-contents = "==0.4.0" GitPython = "==3.1.32" PyGithub = "==2.1.1" -licensecheck = "==2023.5.1" +licensecheck = "==2024" [tool.isort] line_length = 88 From 406f441c60f3a9bbcba3bdc8253415df44ceef3b Mon Sep 17 00:00:00 2001 From: Yan Gao Date: Thu, 18 Jan 2024 21:42:36 +0000 Subject: [PATCH 011/113] Retire the example of quickstart-xgboost-horizontal (#2801) Co-authored-by: yan-gao-GY Co-authored-by: Daniel J. Beutel --- .../hfedxgboost/hfedxgboost/conf/base.yaml | 2 +- baselines/hfedxgboost/hfedxgboost/strategy.py | 74 + .../quickstart-xgboost-horizontal/.gitignore | 2 - .../quickstart-xgboost-horizontal/README.md | 19 - .../code_horizontal.ipynb | 1560 ----------------- src/py/flwr/common/logger.py | 14 + src/py/flwr/server/strategy/fedxgb_nn_avg.py | 11 +- 7 files changed, 98 insertions(+), 1584 deletions(-) delete mode 100644 examples/quickstart-xgboost-horizontal/.gitignore delete mode 100644 examples/quickstart-xgboost-horizontal/README.md delete mode 100644 examples/quickstart-xgboost-horizontal/code_horizontal.ipynb diff --git a/baselines/hfedxgboost/hfedxgboost/conf/base.yaml b/baselines/hfedxgboost/hfedxgboost/conf/base.yaml index 310b123a9054..284aab88e316 100644 --- a/baselines/hfedxgboost/hfedxgboost/conf/base.yaml +++ b/baselines/hfedxgboost/hfedxgboost/conf/base.yaml @@ -37,7 +37,7 @@ client_resources: num_gpus: 0.0 strategy: - _target_: flwr.server.strategy.FedXgbNnAvg + _target_: hfedxgboost.strategy.FedXgbNnAvg _recursive_: true #everything to be instantiated fraction_fit: 1.0 fraction_evaluate: 0.0 # no clients will be sampled for federated evaluation (we will still perform global evaluation) diff --git a/baselines/hfedxgboost/hfedxgboost/strategy.py b/baselines/hfedxgboost/hfedxgboost/strategy.py index 17436c401c30..eb067a89e5f0 100644 --- a/baselines/hfedxgboost/hfedxgboost/strategy.py +++ b/baselines/hfedxgboost/hfedxgboost/strategy.py @@ -3,3 +3,77 @@ Needed only when the strategy is not yet implemented in Flower or because you want to extend or modify the functionality of an existing strategy. """ +from logging import WARNING +from typing import Any, Dict, List, Optional, Tuple, Union + +from flwr.common import FitRes, Scalar, ndarrays_to_parameters, parameters_to_ndarrays +from flwr.common.logger import log +from flwr.server.client_proxy import ClientProxy + +from flwr.server.strategy.aggregate import aggregate +from flwr.server.strategy import FedAvg + + +class FedXgbNnAvg(FedAvg): + """Configurable FedXgbNnAvg strategy implementation.""" + + def __init__(self, *args: Any, **kwargs: Any) -> None: + """Federated XGBoost [Ma et al., 2023] strategy. + + Implementation based on https://arxiv.org/abs/2304.07537. + """ + super().__init__(*args, **kwargs) + + def __repr__(self) -> str: + """Compute a string representation of the strategy.""" + rep = f"FedXgbNnAvg(accept_failures={self.accept_failures})" + return rep + + def evaluate( + self, server_round: int, parameters: Any + ) -> Optional[Tuple[float, Dict[str, Scalar]]]: + """Evaluate model parameters using an evaluation function.""" + if self.evaluate_fn is None: + # No evaluation function provided + return None + eval_res = self.evaluate_fn(server_round, parameters, {}) + if eval_res is None: + return None + loss, metrics = eval_res + return loss, metrics + + def aggregate_fit( + self, + server_round: int, + results: List[Tuple[ClientProxy, FitRes]], + failures: List[Union[Tuple[ClientProxy, FitRes], BaseException]], + ) -> Tuple[Optional[Any], Dict[str, Scalar]]: + """Aggregate fit results using weighted average.""" + if not results: + return None, {} + # Do not aggregate if there are failures and failures are not accepted + if not self.accept_failures and failures: + return None, {} + + # Convert results + weights_results = [ + ( + parameters_to_ndarrays(fit_res.parameters[0].parameters), # type: ignore # noqa: E501 # pylint: disable=line-too-long + fit_res.num_examples, + ) + for _, fit_res in results + ] + parameters_aggregated = ndarrays_to_parameters(aggregate(weights_results)) + + # Aggregate XGBoost trees from all clients + trees_aggregated = [fit_res.parameters[1] for _, fit_res in results] # type: ignore # noqa: E501 # pylint: disable=line-too-long + + # Aggregate custom metrics if aggregation fn was provided + metrics_aggregated = {} + if self.fit_metrics_aggregation_fn: + fit_metrics = [(res.num_examples, res.metrics) for _, res in results] + metrics_aggregated = self.fit_metrics_aggregation_fn(fit_metrics) + elif server_round == 1: # Only log this warning once + log(WARNING, "No fit_metrics_aggregation_fn provided") + + return [parameters_aggregated, trees_aggregated], metrics_aggregated diff --git a/examples/quickstart-xgboost-horizontal/.gitignore b/examples/quickstart-xgboost-horizontal/.gitignore deleted file mode 100644 index 4a6ddf5b9142..000000000000 --- a/examples/quickstart-xgboost-horizontal/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -dataset - diff --git a/examples/quickstart-xgboost-horizontal/README.md b/examples/quickstart-xgboost-horizontal/README.md deleted file mode 100644 index 346a33da7412..000000000000 --- a/examples/quickstart-xgboost-horizontal/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Federated XGBoost in Horizontal Setting (PyTorch) - -[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/adap/flower/blob/main/examples/quickstart-xgboost-horizontal/code_horizontal.ipynb) (or open the [Jupyter Notebook](https://github.com/adap/flower/blob/main/examples/quickstart-xgboost-horizontal/code_horizontal.ipynb)) - -This example demonstrates a federated XGBoost using Flower with PyTorch. This is a novel method to conduct federated XGBoost in the horizontal setting. It differs from the previous methods in the following ways: - -- We aggregate and conduct federated learning on client tree’s prediction outcomes by sending clients' built XGBoost trees to the server and then sharing to the clients. -- The exchange of privacy-sensitive information (gradients) is not needed. -- The model is a CNN with 1D convolution kernel size = the number of XGBoost trees in the client tree ensembles. -- Using 1D convolution, we make the tree learning rate (a hyperparameter of XGBoost) learnable. - -## Project Setup - -This implementation can be easily run in Google Colab with the button at the top of the README or as a standalone Jupyter notebook, -it will automatically download and extract the example data inside a `dataset` folder and `binary_classification` and `regression` sub-folders. - -## Datasets - -This implementation supports both binary classification and regression datasets in SVM light format, loaded from ([LIBSVM Data](https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/)). Simply download the dataset files from the website and put them in the folder location indicated above. diff --git a/examples/quickstart-xgboost-horizontal/code_horizontal.ipynb b/examples/quickstart-xgboost-horizontal/code_horizontal.ipynb deleted file mode 100644 index 4d76e0c26023..000000000000 --- a/examples/quickstart-xgboost-horizontal/code_horizontal.ipynb +++ /dev/null @@ -1,1560 +0,0 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Initialization" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "executionInfo": { - "elapsed": 15871, - "status": "ok", - "timestamp": 1670356049976, - "user": { - "displayName": "Chenyang Ma", - "userId": "17975430055716133031" - }, - "user_tz": 0 - }, - "outputId": "2c588ea0-a383-4461-e633-794e73d0f57a" - }, - "outputs": [], - "source": [ - "import os\n", - "import urllib.request\n", - "import bz2\n", - "import shutil\n", - "\n", - "CLASSIFICATION_PATH = os.path.join(\"dataset\", \"binary_classification\")\n", - "REGRESSION_PATH = os.path.join(\"dataset\", \"regression\")\n", - "\n", - "if not os.path.exists(CLASSIFICATION_PATH):\n", - " os.makedirs(CLASSIFICATION_PATH)\n", - " urllib.request.urlretrieve(\n", - " \"https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/binary/cod-rna\",\n", - " f\"{os.path.join(CLASSIFICATION_PATH, 'cod-rna')}\",\n", - " )\n", - " urllib.request.urlretrieve(\n", - " \"https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/binary/cod-rna.t\",\n", - " f\"{os.path.join(CLASSIFICATION_PATH, 'cod-rna.t')}\",\n", - " )\n", - " urllib.request.urlretrieve(\n", - " \"https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/binary/cod-rna.r\",\n", - " f\"{os.path.join(CLASSIFICATION_PATH, 'cod-rna.r')}\",\n", - " )\n", - " urllib.request.urlretrieve(\n", - " \"https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/binary/ijcnn1.t.bz2\",\n", - " f\"{os.path.join(CLASSIFICATION_PATH, 'ijcnn1.t.bz2')}\",\n", - " )\n", - " urllib.request.urlretrieve(\n", - " \"https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/binary/ijcnn1.tr.bz2\",\n", - " f\"{os.path.join(CLASSIFICATION_PATH, 'ijcnn1.tr.bz2')}\",\n", - " )\n", - " for filepath in os.listdir(CLASSIFICATION_PATH):\n", - " if filepath[-3:] == \"bz2\":\n", - " abs_filepath = os.path.join(CLASSIFICATION_PATH, filepath)\n", - " with bz2.BZ2File(abs_filepath) as fr, open(abs_filepath[:-4], \"wb\") as fw:\n", - " shutil.copyfileobj(fr, fw)\n", - "\n", - "if not os.path.exists(REGRESSION_PATH):\n", - " os.makedirs(REGRESSION_PATH)\n", - " urllib.request.urlretrieve(\n", - " \"https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/regression/eunite2001\",\n", - " f\"{os.path.join(REGRESSION_PATH, 'eunite2001')}\",\n", - " )\n", - " urllib.request.urlretrieve(\n", - " \"https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/regression/eunite2001.t\",\n", - " f\"{os.path.join(REGRESSION_PATH, 'eunite2001.t')}\",\n", - " )\n", - " urllib.request.urlretrieve(\n", - " \"https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/regression/YearPredictionMSD.bz2\",\n", - " f\"{os.path.join(REGRESSION_PATH, 'YearPredictionMSD.bz2')}\",\n", - " )\n", - " urllib.request.urlretrieve(\n", - " \"https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/regression/YearPredictionMSD.t.bz2\",\n", - " f\"{os.path.join(REGRESSION_PATH, 'YearPredictionMSD.t.bz2')}\",\n", - " )\n", - " for filepath in os.listdir(REGRESSION_PATH):\n", - " if filepath[-3:] == \"bz2\":\n", - " abs_filepath = os.path.join(REGRESSION_PATH, filepath)\n", - " with bz2.BZ2File(abs_filepath) as fr, open(abs_filepath[:-4], \"wb\") as fw:\n", - " shutil.copyfileobj(fr, fw)\n", - "\n", - "\n", - "!nvidia-smi\n", - "!pip install matplotlib scikit-learn tqdm torch torchmetrics torchsummary xgboost\n", - "!pip install -U \"flwr-nightly[simulation]\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Import relevant modules" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "executionInfo": { - "elapsed": 7, - "status": "ok", - "timestamp": 1670356049977, - "user": { - "displayName": "Chenyang Ma", - "userId": "17975430055716133031" - }, - "user_tz": 0 - }, - "outputId": "5289e33e-e18e-491b-d536-6b1052598994" - }, - "outputs": [], - "source": [ - "import xgboost as xgb\n", - "from xgboost import XGBClassifier, XGBRegressor\n", - "from sklearn.metrics import mean_squared_error, accuracy_score\n", - "from sklearn.datasets import load_svmlight_file\n", - "\n", - "import numpy as np\n", - "import torch, torch.nn as nn\n", - "import torch.nn.functional as F\n", - "import torchvision\n", - "from torchmetrics import Accuracy, MeanSquaredError\n", - "from tqdm import trange, tqdm\n", - "from torchsummary import summary\n", - "from torch.utils.data import DataLoader, Dataset, random_split\n", - "\n", - "print(\"Imported modules.\")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Import Flower relevant modules for Federated XGBoost" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import flwr as fl\n", - "from flwr.common.typing import Parameters\n", - "from collections import OrderedDict\n", - "from typing import Any, Dict, List, Optional, Tuple, Union\n", - "from flwr.common import NDArray, NDArrays\n", - "\n", - "print(\"Imported modules.\")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Define utility function for xgboost trees" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from matplotlib import pyplot as plt # pylint: disable=E0401\n", - "\n", - "\n", - "def plot_xgbtree(tree: Union[XGBClassifier, XGBRegressor], n_tree: int) -> None:\n", - " \"\"\"Visualize the built xgboost tree.\"\"\"\n", - " xgb.plot_tree(tree, num_trees=n_tree)\n", - " plt.rcParams[\"figure.figsize\"] = [50, 10]\n", - " plt.show()\n", - "\n", - "\n", - "def construct_tree(\n", - " dataset: Dataset, label: NDArray, n_estimators: int, tree_type: str\n", - ") -> Union[XGBClassifier, XGBRegressor]:\n", - " \"\"\"Construct a xgboost tree form tabular dataset.\"\"\"\n", - " if tree_type == \"BINARY\":\n", - " tree = xgb.XGBClassifier(\n", - " objective=\"binary:logistic\",\n", - " learning_rate=0.1,\n", - " max_depth=8,\n", - " n_estimators=n_estimators,\n", - " subsample=0.8,\n", - " colsample_bylevel=1,\n", - " colsample_bynode=1,\n", - " colsample_bytree=1,\n", - " alpha=5,\n", - " gamma=5,\n", - " num_parallel_tree=1,\n", - " min_child_weight=1,\n", - " )\n", - "\n", - " elif tree_type == \"REG\":\n", - " tree = xgb.XGBRegressor(\n", - " objective=\"reg:squarederror\",\n", - " learning_rate=0.1,\n", - " max_depth=8,\n", - " n_estimators=n_estimators,\n", - " subsample=0.8,\n", - " colsample_bylevel=1,\n", - " colsample_bynode=1,\n", - " colsample_bytree=1,\n", - " alpha=5,\n", - " gamma=5,\n", - " num_parallel_tree=1,\n", - " min_child_weight=1,\n", - " )\n", - "\n", - " tree.fit(dataset, label)\n", - " return tree\n", - "\n", - "\n", - "def construct_tree_from_loader(\n", - " dataset_loader: DataLoader, n_estimators: int, tree_type: str\n", - ") -> Union[XGBClassifier, XGBRegressor]:\n", - " \"\"\"Construct a xgboost tree form tabular dataset loader.\"\"\"\n", - " for dataset in dataset_loader:\n", - " data, label = dataset[0], dataset[1]\n", - " return construct_tree(data, label, n_estimators, tree_type)\n", - "\n", - "\n", - "def single_tree_prediction(\n", - " tree: Union[XGBClassifier, XGBRegressor], n_tree: int, dataset: NDArray\n", - ") -> Optional[NDArray]:\n", - " \"\"\"Extract the prediction result of a single tree in the xgboost tree\n", - " ensemble.\"\"\"\n", - " # How to access a single tree\n", - " # https://github.com/bmreiniger/datascience.stackexchange/blob/master/57905.ipynb\n", - " num_t = len(tree.get_booster().get_dump())\n", - " if n_tree > num_t:\n", - " print(\n", - " \"The tree index to be extracted is larger than the total number of trees.\"\n", - " )\n", - " return None\n", - "\n", - " return tree.predict( # type: ignore\n", - " dataset, iteration_range=(n_tree, n_tree + 1), output_margin=True\n", - " )\n", - "\n", - "\n", - "def tree_encoding( # pylint: disable=R0914\n", - " trainloader: DataLoader,\n", - " client_trees: Union[\n", - " Tuple[XGBClassifier, int],\n", - " Tuple[XGBRegressor, int],\n", - " List[Union[Tuple[XGBClassifier, int], Tuple[XGBRegressor, int]]],\n", - " ],\n", - " client_tree_num: int,\n", - " client_num: int,\n", - ") -> Optional[Tuple[NDArray, NDArray]]:\n", - " \"\"\"Transform the tabular dataset into prediction results using the\n", - " aggregated xgboost tree ensembles from all clients.\"\"\"\n", - " if trainloader is None:\n", - " return None\n", - "\n", - " for local_dataset in trainloader:\n", - " x_train, y_train = local_dataset[0], local_dataset[1]\n", - "\n", - " x_train_enc = np.zeros((x_train.shape[0], client_num * client_tree_num))\n", - " x_train_enc = np.array(x_train_enc, copy=True)\n", - "\n", - " temp_trees: Any = None\n", - " if isinstance(client_trees, list) is False:\n", - " temp_trees = [client_trees[0]] * client_num\n", - " elif isinstance(client_trees, list) and len(client_trees) != client_num:\n", - " temp_trees = [client_trees[0][0]] * client_num\n", - " else:\n", - " cids = []\n", - " temp_trees = []\n", - " for i, _ in enumerate(client_trees):\n", - " temp_trees.append(client_trees[i][0]) # type: ignore\n", - " cids.append(client_trees[i][1]) # type: ignore\n", - " sorted_index = np.argsort(np.asarray(cids))\n", - " temp_trees = np.asarray(temp_trees)[sorted_index]\n", - "\n", - " for i, _ in enumerate(temp_trees):\n", - " for j in range(client_tree_num):\n", - " x_train_enc[:, i * client_tree_num + j] = single_tree_prediction(\n", - " temp_trees[i], j, x_train\n", - " )\n", - "\n", - " x_train_enc32: Any = np.float32(x_train_enc)\n", - " y_train32: Any = np.float32(y_train)\n", - "\n", - " x_train_enc32, y_train32 = torch.from_numpy(\n", - " np.expand_dims(x_train_enc32, axis=1) # type: ignore\n", - " ), torch.from_numpy(\n", - " np.expand_dims(y_train32, axis=-1) # type: ignore\n", - " )\n", - " return x_train_enc32, y_train32" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Manually download and load the tabular dataset from LIBSVM data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "executionInfo": { - "elapsed": 26613, - "status": "ok", - "timestamp": 1670356076585, - "user": { - "displayName": "Chenyang Ma", - "userId": "17975430055716133031" - }, - "user_tz": 0 - }, - "outputId": "22843504-faf0-44cf-aedd-1df8d0ec87a6" - }, - "outputs": [], - "source": [ - "# Datasets can be downloaded from LIBSVM Data: https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/\n", - "binary_train = [\"cod-rna.t\", \"cod-rna\", \"ijcnn1.t\"]\n", - "binary_test = [\"cod-rna.r\", \"cod-rna.t\", \"ijcnn1.tr\"]\n", - "reg_train = [\"eunite2001\", \"YearPredictionMSD\"]\n", - "reg_test = [\"eunite2001.t\", \"YearPredictionMSD.t\"]\n", - "\n", - "# Define the type of training task. Binary classification: BINARY; Regression: REG\n", - "task_types = [\"BINARY\", \"REG\"]\n", - "task_type = task_types[0]\n", - "\n", - "# Select the downloaded training and test dataset\n", - "if task_type == \"BINARY\":\n", - " dataset_path = \"dataset/binary_classification/\"\n", - " train = binary_train[0]\n", - " test = binary_test[0]\n", - "elif task_type == \"REG\":\n", - " dataset_path = \"dataset/regression/\"\n", - " train = reg_train[0]\n", - " test = reg_test[0]\n", - "\n", - "data_train = load_svmlight_file(dataset_path + train, zero_based=False)\n", - "data_test = load_svmlight_file(dataset_path + test, zero_based=False)\n", - "\n", - "print(\"Task type selected is: \" + task_type)\n", - "print(\"Training dataset is: \" + train)\n", - "print(\"Test dataset is: \" + test)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Preprocess the tabular dataset" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "class TreeDataset(Dataset):\n", - " def __init__(self, data: NDArray, labels: NDArray) -> None:\n", - " self.labels = labels\n", - " self.data = data\n", - "\n", - " def __len__(self) -> int:\n", - " return len(self.labels)\n", - "\n", - " def __getitem__(self, idx: int) -> Dict[int, NDArray]:\n", - " label = self.labels[idx]\n", - " data = self.data[idx, :]\n", - " sample = {0: data, 1: label}\n", - " return sample\n", - "\n", - "\n", - "X_train = data_train[0].toarray()\n", - "y_train = data_train[1]\n", - "X_test = data_test[0].toarray()\n", - "y_test = data_test[1]\n", - "X_train.flags.writeable = True\n", - "y_train.flags.writeable = True\n", - "X_test.flags.writeable = True\n", - "y_test.flags.writeable = True\n", - "\n", - "# If the feature dimensions of the trainset and testset do not agree,\n", - "# specify n_features in the load_svmlight_file function in the above cell.\n", - "# https://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_svmlight_file.html\n", - "print(\"Feature dimension of the dataset:\", X_train.shape[1])\n", - "print(\"Size of the trainset:\", X_train.shape[0])\n", - "print(\"Size of the testset:\", X_test.shape[0])\n", - "assert X_train.shape[1] == X_test.shape[1]\n", - "\n", - "if task_type == \"BINARY\":\n", - " y_train[y_train == -1] = 0\n", - " y_test[y_test == -1] = 0\n", - "\n", - "trainset = TreeDataset(np.array(X_train, copy=True), np.array(y_train, copy=True))\n", - "testset = TreeDataset(np.array(X_test, copy=True), np.array(y_test, copy=True))" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Conduct tabular dataset partition for Federated Learning" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def get_dataloader(\n", - " dataset: Dataset, partition: str, batch_size: Union[int, str]\n", - ") -> DataLoader:\n", - " if batch_size == \"whole\":\n", - " batch_size = len(dataset)\n", - " return DataLoader(\n", - " dataset, batch_size=batch_size, pin_memory=True, shuffle=(partition == \"train\")\n", - " )\n", - "\n", - "\n", - "# https://github.com/adap/flower\n", - "def do_fl_partitioning(\n", - " trainset: Dataset,\n", - " testset: Dataset,\n", - " pool_size: int,\n", - " batch_size: Union[int, str],\n", - " val_ratio: float = 0.0,\n", - ") -> Tuple[DataLoader, DataLoader, DataLoader]:\n", - " # Split training set into `num_clients` partitions to simulate different local datasets\n", - " partition_size = len(trainset) // pool_size\n", - " lengths = [partition_size] * pool_size\n", - " if sum(lengths) != len(trainset):\n", - " lengths[-1] = len(trainset) - sum(lengths[0:-1])\n", - " datasets = random_split(trainset, lengths, torch.Generator().manual_seed(0))\n", - "\n", - " # Split each partition into train/val and create DataLoader\n", - " trainloaders = []\n", - " valloaders = []\n", - " for ds in datasets:\n", - " len_val = int(len(ds) * val_ratio)\n", - " len_train = len(ds) - len_val\n", - " lengths = [len_train, len_val]\n", - " ds_train, ds_val = random_split(ds, lengths, torch.Generator().manual_seed(0))\n", - " trainloaders.append(get_dataloader(ds_train, \"train\", batch_size))\n", - " if len_val != 0:\n", - " valloaders.append(get_dataloader(ds_val, \"val\", batch_size))\n", - " else:\n", - " valloaders = None\n", - " testloader = get_dataloader(testset, \"test\", batch_size)\n", - " return trainloaders, valloaders, testloader" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Define global variables for Federated XGBoost Learning" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# The number of clients participated in the federated learning\n", - "client_num = 5\n", - "\n", - "# The number of XGBoost trees in the tree ensemble that will be built for each client\n", - "client_tree_num = 500 // client_num" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Build global XGBoost tree for comparison" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "executionInfo": { - "elapsed": 1080216, - "status": "ok", - "timestamp": 1670357156788, - "user": { - "displayName": "Chenyang Ma", - "userId": "17975430055716133031" - }, - "user_tz": 0 - }, - "outputId": "d56f2821-5cd5-49ff-c5dc-f8d088eed799" - }, - "outputs": [], - "source": [ - "global_tree = construct_tree(X_train, y_train, client_tree_num, task_type)\n", - "preds_train = global_tree.predict(X_train)\n", - "preds_test = global_tree.predict(X_test)\n", - "\n", - "if task_type == \"BINARY\":\n", - " result_train = accuracy_score(y_train, preds_train)\n", - " result_test = accuracy_score(y_test, preds_test)\n", - " print(\"Global XGBoost Training Accuracy: %f\" % (result_train))\n", - " print(\"Global XGBoost Testing Accuracy: %f\" % (result_test))\n", - "elif task_type == \"REG\":\n", - " result_train = mean_squared_error(y_train, preds_train)\n", - " result_test = mean_squared_error(y_test, preds_test)\n", - " print(\"Global XGBoost Training MSE: %f\" % (result_train))\n", - " print(\"Global XGBoost Testing MSE: %f\" % (result_test))\n", - "\n", - "print(global_tree)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Simulate local XGBoost trees on clients for comparison" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "executionInfo": { - "elapsed": 242310, - "status": "ok", - "timestamp": 1670357399084, - "user": { - "displayName": "Chenyang Ma", - "userId": "17975430055716133031" - }, - "user_tz": 0 - }, - "outputId": "0739df9f-84de-4749-8de1-7bd7c6a32ccc" - }, - "outputs": [], - "source": [ - "client_trees_comparison = []\n", - "trainloaders, _, testloader = do_fl_partitioning(\n", - " trainset, testset, pool_size=client_num, batch_size=\"whole\", val_ratio=0.0\n", - ")\n", - "\n", - "for i, trainloader in enumerate(trainloaders):\n", - " for local_dataset in trainloader:\n", - " local_X_train, local_y_train = local_dataset[0], local_dataset[1]\n", - " tree = construct_tree(local_X_train, local_y_train, client_tree_num, task_type)\n", - " client_trees_comparison.append(tree)\n", - "\n", - " preds_train = client_trees_comparison[-1].predict(local_X_train)\n", - " preds_test = client_trees_comparison[-1].predict(X_test)\n", - "\n", - " if task_type == \"BINARY\":\n", - " result_train = accuracy_score(local_y_train, preds_train)\n", - " result_test = accuracy_score(y_test, preds_test)\n", - " print(\"Local Client %d XGBoost Training Accuracy: %f\" % (i, result_train))\n", - " print(\"Local Client %d XGBoost Testing Accuracy: %f\" % (i, result_test))\n", - " elif task_type == \"REG\":\n", - " result_train = mean_squared_error(local_y_train, preds_train)\n", - " result_test = mean_squared_error(y_test, preds_test)\n", - " print(\"Local Client %d XGBoost Training MSE: %f\" % (i, result_train))\n", - " print(\"Local Client %d XGBoost Testing MSE: %f\" % (i, result_test))" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Centralized Federated XGBoost\n", - "#### Create 1D convolutional neural network on trees prediction results. \n", - "#### 1D kernel size == client_tree_num\n", - "#### Make the learning rate of the tree ensembles learnable." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "executionInfo": { - "elapsed": 38, - "status": "ok", - "timestamp": 1670363021675, - "user": { - "displayName": "Chenyang Ma", - "userId": "17975430055716133031" - }, - "user_tz": 0 - } - }, - "outputs": [], - "source": [ - "class CNN(nn.Module):\n", - " def __init__(self, n_channel: int = 64) -> None:\n", - " super(CNN, self).__init__()\n", - " n_out = 1\n", - " self.task_type = task_type\n", - " self.conv1d = nn.Conv1d(\n", - " 1, n_channel, kernel_size=client_tree_num, stride=client_tree_num, padding=0\n", - " )\n", - " self.layer_direct = nn.Linear(n_channel * client_num, n_out)\n", - " self.ReLU = nn.ReLU()\n", - " self.Sigmoid = nn.Sigmoid()\n", - " self.Identity = nn.Identity()\n", - "\n", - " # Add weight initialization\n", - " for layer in self.modules():\n", - " if isinstance(layer, nn.Linear):\n", - " nn.init.kaiming_uniform_(\n", - " layer.weight, mode=\"fan_in\", nonlinearity=\"relu\"\n", - " )\n", - "\n", - " def forward(self, x: torch.Tensor) -> torch.Tensor:\n", - " x = self.ReLU(self.conv1d(x))\n", - " x = x.flatten(start_dim=1)\n", - " x = self.ReLU(x)\n", - " if self.task_type == \"BINARY\":\n", - " x = self.Sigmoid(self.layer_direct(x))\n", - " elif self.task_type == \"REG\":\n", - " x = self.Identity(self.layer_direct(x))\n", - " return x\n", - "\n", - " def get_weights(self) -> fl.common.NDArrays:\n", - " \"\"\"Get model weights as a list of NumPy ndarrays.\"\"\"\n", - " return [\n", - " np.array(val.cpu().numpy(), copy=True)\n", - " for _, val in self.state_dict().items()\n", - " ]\n", - "\n", - " def set_weights(self, weights: fl.common.NDArrays) -> None:\n", - " \"\"\"Set model weights from a list of NumPy ndarrays.\"\"\"\n", - " layer_dict = {}\n", - " for k, v in zip(self.state_dict().keys(), weights):\n", - " if v.ndim != 0:\n", - " layer_dict[k] = torch.Tensor(np.array(v, copy=True))\n", - " state_dict = OrderedDict(layer_dict)\n", - " self.load_state_dict(state_dict, strict=True)\n", - "\n", - "\n", - "def train(\n", - " task_type: str,\n", - " net: CNN,\n", - " trainloader: DataLoader,\n", - " device: torch.device,\n", - " num_iterations: int,\n", - " log_progress: bool = True,\n", - ") -> Tuple[float, float, int]:\n", - " # Define loss and optimizer\n", - " if task_type == \"BINARY\":\n", - " criterion = nn.BCELoss()\n", - " elif task_type == \"REG\":\n", - " criterion = nn.MSELoss()\n", - " # optimizer = torch.optim.SGD(net.parameters(), lr=0.001, momentum=0.9, weight_decay=1e-6)\n", - " optimizer = torch.optim.Adam(net.parameters(), lr=0.0001, betas=(0.9, 0.999))\n", - "\n", - " def cycle(iterable):\n", - " \"\"\"Repeats the contents of the train loader, in case it gets exhausted in 'num_iterations'.\"\"\"\n", - " while True:\n", - " for x in iterable:\n", - " yield x\n", - "\n", - " # Train the network\n", - " net.train()\n", - " total_loss, total_result, n_samples = 0.0, 0.0, 0\n", - " pbar = (\n", - " tqdm(iter(cycle(trainloader)), total=num_iterations, desc=f\"TRAIN\")\n", - " if log_progress\n", - " else iter(cycle(trainloader))\n", - " )\n", - "\n", - " # Unusually, this training is formulated in terms of number of updates/iterations/batches processed\n", - " # by the network. This will be helpful later on, when partitioning the data across clients: resulting\n", - " # in differences between dataset sizes and hence inconsistent numbers of updates per 'epoch'.\n", - " for i, data in zip(range(num_iterations), pbar):\n", - " tree_outputs, labels = data[0].to(device), data[1].to(device)\n", - " optimizer.zero_grad()\n", - "\n", - " outputs = net(tree_outputs)\n", - " loss = criterion(outputs, labels)\n", - " loss.backward()\n", - " optimizer.step()\n", - "\n", - " # Collected training loss and accuracy statistics\n", - " total_loss += loss.item()\n", - " n_samples += labels.size(0)\n", - "\n", - " if task_type == \"BINARY\":\n", - " acc = Accuracy(task=\"binary\")(outputs, labels.type(torch.int))\n", - " total_result += acc * labels.size(0)\n", - " elif task_type == \"REG\":\n", - " mse = MeanSquaredError()(outputs, labels.type(torch.int))\n", - " total_result += mse * labels.size(0)\n", - "\n", - " if log_progress:\n", - " if task_type == \"BINARY\":\n", - " pbar.set_postfix(\n", - " {\n", - " \"train_loss\": total_loss / n_samples,\n", - " \"train_acc\": total_result / n_samples,\n", - " }\n", - " )\n", - " elif task_type == \"REG\":\n", - " pbar.set_postfix(\n", - " {\n", - " \"train_loss\": total_loss / n_samples,\n", - " \"train_mse\": total_result / n_samples,\n", - " }\n", - " )\n", - " if log_progress:\n", - " print(\"\\n\")\n", - "\n", - " return total_loss / n_samples, total_result / n_samples, n_samples\n", - "\n", - "\n", - "def test(\n", - " task_type: str,\n", - " net: CNN,\n", - " testloader: DataLoader,\n", - " device: torch.device,\n", - " log_progress: bool = True,\n", - ") -> Tuple[float, float, int]:\n", - " \"\"\"Evaluates the network on test data.\"\"\"\n", - " if task_type == \"BINARY\":\n", - " criterion = nn.BCELoss()\n", - " elif task_type == \"REG\":\n", - " criterion = nn.MSELoss()\n", - "\n", - " total_loss, total_result, n_samples = 0.0, 0.0, 0\n", - " net.eval()\n", - " with torch.no_grad():\n", - " pbar = tqdm(testloader, desc=\"TEST\") if log_progress else testloader\n", - " for data in pbar:\n", - " tree_outputs, labels = data[0].to(device), data[1].to(device)\n", - " outputs = net(tree_outputs)\n", - "\n", - " # Collected testing loss and accuracy statistics\n", - " total_loss += criterion(outputs, labels).item()\n", - " n_samples += labels.size(0)\n", - "\n", - " if task_type == \"BINARY\":\n", - " acc = Accuracy(task=\"binary\")(\n", - " outputs.cpu(), labels.type(torch.int).cpu()\n", - " )\n", - " total_result += acc * labels.size(0)\n", - " elif task_type == \"REG\":\n", - " mse = MeanSquaredError()(outputs.cpu(), labels.type(torch.int).cpu())\n", - " total_result += mse * labels.size(0)\n", - "\n", - " if log_progress:\n", - " print(\"\\n\")\n", - "\n", - " return total_loss / n_samples, total_result / n_samples, n_samples" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Create Flower custom client\n", - "## Import Flower custom client relevant modules" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Flower client\n", - "from flwr.common import (\n", - " EvaluateIns,\n", - " EvaluateRes,\n", - " FitIns,\n", - " FitRes,\n", - " GetPropertiesIns,\n", - " GetPropertiesRes,\n", - " GetParametersIns,\n", - " GetParametersRes,\n", - " Status,\n", - " Code,\n", - " parameters_to_ndarrays,\n", - " ndarrays_to_parameters,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "executionInfo": { - "elapsed": 36, - "status": "ok", - "timestamp": 1670363021676, - "user": { - "displayName": "Chenyang Ma", - "userId": "17975430055716133031" - }, - "user_tz": 0 - } - }, - "outputs": [], - "source": [ - "def tree_encoding_loader(\n", - " dataloader: DataLoader,\n", - " batch_size: int,\n", - " client_trees: Union[\n", - " Tuple[XGBClassifier, int],\n", - " Tuple[XGBRegressor, int],\n", - " List[Union[Tuple[XGBClassifier, int], Tuple[XGBRegressor, int]]],\n", - " ],\n", - " client_tree_num: int,\n", - " client_num: int,\n", - ") -> DataLoader:\n", - " encoding = tree_encoding(dataloader, client_trees, client_tree_num, client_num)\n", - " if encoding is None:\n", - " return None\n", - " data, labels = encoding\n", - " tree_dataset = TreeDataset(data, labels)\n", - " return get_dataloader(tree_dataset, \"tree\", batch_size)\n", - "\n", - "\n", - "class FL_Client(fl.client.Client):\n", - " def __init__(\n", - " self,\n", - " task_type: str,\n", - " trainloader: DataLoader,\n", - " valloader: DataLoader,\n", - " client_tree_num: int,\n", - " client_num: int,\n", - " cid: str,\n", - " log_progress: bool = False,\n", - " ):\n", - " \"\"\"\n", - " Creates a client for training `network.Net` on tabular dataset.\n", - " \"\"\"\n", - " self.task_type = task_type\n", - " self.cid = cid\n", - " self.tree = construct_tree_from_loader(trainloader, client_tree_num, task_type)\n", - " self.trainloader_original = trainloader\n", - " self.valloader_original = valloader\n", - " self.trainloader = None\n", - " self.valloader = None\n", - " self.client_tree_num = client_tree_num\n", - " self.client_num = client_num\n", - " self.properties = {\"tensor_type\": \"numpy.ndarray\"}\n", - " self.log_progress = log_progress\n", - "\n", - " # instantiate model\n", - " self.net = CNN()\n", - "\n", - " # determine device\n", - " self.device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n", - "\n", - " def get_properties(self, ins: GetPropertiesIns) -> GetPropertiesRes:\n", - " return GetPropertiesRes(properties=self.properties)\n", - "\n", - " def get_parameters(\n", - " self, ins: GetParametersIns\n", - " ) -> Tuple[\n", - " GetParametersRes, Union[Tuple[XGBClassifier, int], Tuple[XGBRegressor, int]]\n", - " ]:\n", - " return [\n", - " GetParametersRes(\n", - " status=Status(Code.OK, \"\"),\n", - " parameters=ndarrays_to_parameters(self.net.get_weights()),\n", - " ),\n", - " (self.tree, int(self.cid)),\n", - " ]\n", - "\n", - " def set_parameters(\n", - " self,\n", - " parameters: Tuple[\n", - " Parameters,\n", - " Union[\n", - " Tuple[XGBClassifier, int],\n", - " Tuple[XGBRegressor, int],\n", - " List[Union[Tuple[XGBClassifier, int], Tuple[XGBRegressor, int]]],\n", - " ],\n", - " ],\n", - " ) -> Union[\n", - " Tuple[XGBClassifier, int],\n", - " Tuple[XGBRegressor, int],\n", - " List[Union[Tuple[XGBClassifier, int], Tuple[XGBRegressor, int]]],\n", - " ]:\n", - " self.net.set_weights(parameters_to_ndarrays(parameters[0]))\n", - " return parameters[1]\n", - "\n", - " def fit(self, fit_params: FitIns) -> FitRes:\n", - " # Process incoming request to train\n", - " num_iterations = fit_params.config[\"num_iterations\"]\n", - " batch_size = fit_params.config[\"batch_size\"]\n", - " aggregated_trees = self.set_parameters(fit_params.parameters)\n", - "\n", - " if type(aggregated_trees) is list:\n", - " print(\"Client \" + self.cid + \": recieved\", len(aggregated_trees), \"trees\")\n", - " else:\n", - " print(\"Client \" + self.cid + \": only had its own tree\")\n", - " self.trainloader = tree_encoding_loader(\n", - " self.trainloader_original,\n", - " batch_size,\n", - " aggregated_trees,\n", - " self.client_tree_num,\n", - " self.client_num,\n", - " )\n", - " self.valloader = tree_encoding_loader(\n", - " self.valloader_original,\n", - " batch_size,\n", - " aggregated_trees,\n", - " self.client_tree_num,\n", - " self.client_num,\n", - " )\n", - "\n", - " # num_iterations = None special behaviour: train(...) runs for a single epoch, however many updates it may be\n", - " num_iterations = num_iterations or len(self.trainloader)\n", - "\n", - " # Train the model\n", - " print(f\"Client {self.cid}: training for {num_iterations} iterations/updates\")\n", - " self.net.to(self.device)\n", - " train_loss, train_result, num_examples = train(\n", - " self.task_type,\n", - " self.net,\n", - " self.trainloader,\n", - " device=self.device,\n", - " num_iterations=num_iterations,\n", - " log_progress=self.log_progress,\n", - " )\n", - " print(\n", - " f\"Client {self.cid}: training round complete, {num_examples} examples processed\"\n", - " )\n", - "\n", - " # Return training information: model, number of examples processed and metrics\n", - " if self.task_type == \"BINARY\":\n", - " return FitRes(\n", - " status=Status(Code.OK, \"\"),\n", - " parameters=self.get_parameters(fit_params.config),\n", - " num_examples=num_examples,\n", - " metrics={\"loss\": train_loss, \"accuracy\": train_result},\n", - " )\n", - " elif self.task_type == \"REG\":\n", - " return FitRes(\n", - " status=Status(Code.OK, \"\"),\n", - " parameters=self.get_parameters(fit_params.config),\n", - " num_examples=num_examples,\n", - " metrics={\"loss\": train_loss, \"mse\": train_result},\n", - " )\n", - "\n", - " def evaluate(self, eval_params: EvaluateIns) -> EvaluateRes:\n", - " # Process incoming request to evaluate\n", - " self.set_parameters(eval_params.parameters)\n", - "\n", - " # Evaluate the model\n", - " self.net.to(self.device)\n", - " loss, result, num_examples = test(\n", - " self.task_type,\n", - " self.net,\n", - " self.valloader,\n", - " device=self.device,\n", - " log_progress=self.log_progress,\n", - " )\n", - "\n", - " # Return evaluation information\n", - " if self.task_type == \"BINARY\":\n", - " print(\n", - " f\"Client {self.cid}: evaluation on {num_examples} examples: loss={loss:.4f}, accuracy={result:.4f}\"\n", - " )\n", - " return EvaluateRes(\n", - " status=Status(Code.OK, \"\"),\n", - " loss=loss,\n", - " num_examples=num_examples,\n", - " metrics={\"accuracy\": result},\n", - " )\n", - " elif self.task_type == \"REG\":\n", - " print(\n", - " f\"Client {self.cid}: evaluation on {num_examples} examples: loss={loss:.4f}, mse={result:.4f}\"\n", - " )\n", - " return EvaluateRes(\n", - " status=Status(Code.OK, \"\"),\n", - " loss=loss,\n", - " num_examples=num_examples,\n", - " metrics={\"mse\": result},\n", - " )" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Create Flower custom server\n", - "## Import Flower custom server relevant modules" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Flower server\n", - "import functools\n", - "from flwr.server.strategy import FedXgbNnAvg\n", - "from flwr.server.app import ServerConfig\n", - "\n", - "import timeit\n", - "from logging import DEBUG, INFO\n", - "from typing import Dict, List, Optional, Tuple, Union\n", - "\n", - "from flwr.common import DisconnectRes, Parameters, ReconnectIns, Scalar\n", - "from flwr.common.logger import log\n", - "from flwr.common.typing import GetParametersIns\n", - "from flwr.server.client_manager import ClientManager, SimpleClientManager\n", - "from flwr.server.client_proxy import ClientProxy\n", - "from flwr.server.history import History\n", - "from flwr.server.strategy import Strategy\n", - "from flwr.server.server import (\n", - " reconnect_clients,\n", - " reconnect_client,\n", - " fit_clients,\n", - " fit_client,\n", - " _handle_finished_future_after_fit,\n", - " evaluate_clients,\n", - " evaluate_client,\n", - " _handle_finished_future_after_evaluate,\n", - ")\n", - "\n", - "FitResultsAndFailures = Tuple[\n", - " List[Tuple[ClientProxy, FitRes]],\n", - " List[Union[Tuple[ClientProxy, FitRes], BaseException]],\n", - "]\n", - "EvaluateResultsAndFailures = Tuple[\n", - " List[Tuple[ClientProxy, EvaluateRes]],\n", - " List[Union[Tuple[ClientProxy, EvaluateRes], BaseException]],\n", - "]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "class FL_Server(fl.server.Server):\n", - " \"\"\"Flower server.\"\"\"\n", - "\n", - " def __init__(\n", - " self, *, client_manager: ClientManager, strategy: Optional[Strategy] = None\n", - " ) -> None:\n", - " self._client_manager: ClientManager = client_manager\n", - " self.parameters: Parameters = Parameters(\n", - " tensors=[], tensor_type=\"numpy.ndarray\"\n", - " )\n", - " self.strategy: Strategy = strategy\n", - " self.max_workers: Optional[int] = None\n", - "\n", - " # pylint: disable=too-many-locals\n", - " def fit(self, num_rounds: int, timeout: Optional[float]) -> History:\n", - " \"\"\"Run federated averaging for a number of rounds.\"\"\"\n", - " history = History()\n", - "\n", - " # Initialize parameters\n", - " log(INFO, \"Initializing global parameters\")\n", - " self.parameters = self._get_initial_parameters(timeout=timeout)\n", - "\n", - " log(INFO, \"Evaluating initial parameters\")\n", - " res = self.strategy.evaluate(0, parameters=self.parameters)\n", - " if res is not None:\n", - " log(\n", - " INFO,\n", - " \"initial parameters (loss, other metrics): %s, %s\",\n", - " res[0],\n", - " res[1],\n", - " )\n", - " history.add_loss_centralized(server_round=0, loss=res[0])\n", - " history.add_metrics_centralized(server_round=0, metrics=res[1])\n", - "\n", - " # Run federated learning for num_rounds\n", - " log(INFO, \"FL starting\")\n", - " start_time = timeit.default_timer()\n", - "\n", - " for current_round in range(1, num_rounds + 1):\n", - " # Train model and replace previous global model\n", - " res_fit = self.fit_round(server_round=current_round, timeout=timeout)\n", - " if res_fit:\n", - " parameters_prime, _, _ = res_fit # fit_metrics_aggregated\n", - " if parameters_prime:\n", - " self.parameters = parameters_prime\n", - "\n", - " # Evaluate model using strategy implementation\n", - " res_cen = self.strategy.evaluate(current_round, parameters=self.parameters)\n", - " if res_cen is not None:\n", - " loss_cen, metrics_cen = res_cen\n", - " log(\n", - " INFO,\n", - " \"fit progress: (%s, %s, %s, %s)\",\n", - " current_round,\n", - " loss_cen,\n", - " metrics_cen,\n", - " timeit.default_timer() - start_time,\n", - " )\n", - " history.add_loss_centralized(server_round=current_round, loss=loss_cen)\n", - " history.add_metrics_centralized(\n", - " server_round=current_round, metrics=metrics_cen\n", - " )\n", - "\n", - " # Evaluate model on a sample of available clients\n", - " res_fed = self.evaluate_round(server_round=current_round, timeout=timeout)\n", - " if res_fed:\n", - " loss_fed, evaluate_metrics_fed, _ = res_fed\n", - " if loss_fed:\n", - " history.add_loss_distributed(\n", - " server_round=current_round, loss=loss_fed\n", - " )\n", - " history.add_metrics_distributed(\n", - " server_round=current_round, metrics=evaluate_metrics_fed\n", - " )\n", - "\n", - " # Bookkeeping\n", - " end_time = timeit.default_timer()\n", - " elapsed = end_time - start_time\n", - " log(INFO, \"FL finished in %s\", elapsed)\n", - " return history\n", - "\n", - " def evaluate_round(\n", - " self,\n", - " server_round: int,\n", - " timeout: Optional[float],\n", - " ) -> Optional[\n", - " Tuple[Optional[float], Dict[str, Scalar], EvaluateResultsAndFailures]\n", - " ]:\n", - " \"\"\"Validate current global model on a number of clients.\"\"\"\n", - "\n", - " # Get clients and their respective instructions from strategy\n", - " client_instructions = self.strategy.configure_evaluate(\n", - " server_round=server_round,\n", - " parameters=self.parameters,\n", - " client_manager=self._client_manager,\n", - " )\n", - " if not client_instructions:\n", - " log(INFO, \"evaluate_round %s: no clients selected, cancel\", server_round)\n", - " return None\n", - " log(\n", - " DEBUG,\n", - " \"evaluate_round %s: strategy sampled %s clients (out of %s)\",\n", - " server_round,\n", - " len(client_instructions),\n", - " self._client_manager.num_available(),\n", - " )\n", - "\n", - " # Collect `evaluate` results from all clients participating in this round\n", - " results, failures = evaluate_clients(\n", - " client_instructions,\n", - " max_workers=self.max_workers,\n", - " timeout=timeout,\n", - " )\n", - " log(\n", - " DEBUG,\n", - " \"evaluate_round %s received %s results and %s failures\",\n", - " server_round,\n", - " len(results),\n", - " len(failures),\n", - " )\n", - "\n", - " # Aggregate the evaluation results\n", - " aggregated_result: Tuple[\n", - " Optional[float],\n", - " Dict[str, Scalar],\n", - " ] = self.strategy.aggregate_evaluate(server_round, results, failures)\n", - "\n", - " loss_aggregated, metrics_aggregated = aggregated_result\n", - " return loss_aggregated, metrics_aggregated, (results, failures)\n", - "\n", - " def fit_round(\n", - " self,\n", - " server_round: int,\n", - " timeout: Optional[float],\n", - " ) -> Optional[\n", - " Tuple[\n", - " Optional[\n", - " Tuple[\n", - " Parameters,\n", - " Union[\n", - " Tuple[XGBClassifier, int],\n", - " Tuple[XGBRegressor, int],\n", - " List[\n", - " Union[Tuple[XGBClassifier, int], Tuple[XGBRegressor, int]]\n", - " ],\n", - " ],\n", - " ]\n", - " ],\n", - " Dict[str, Scalar],\n", - " FitResultsAndFailures,\n", - " ]\n", - " ]:\n", - " \"\"\"Perform a single round of federated averaging.\"\"\"\n", - "\n", - " # Get clients and their respective instructions from strategy\n", - " client_instructions = self.strategy.configure_fit(\n", - " server_round=server_round,\n", - " parameters=self.parameters,\n", - " client_manager=self._client_manager,\n", - " )\n", - "\n", - " if not client_instructions:\n", - " log(INFO, \"fit_round %s: no clients selected, cancel\", server_round)\n", - " return None\n", - " log(\n", - " DEBUG,\n", - " \"fit_round %s: strategy sampled %s clients (out of %s)\",\n", - " server_round,\n", - " len(client_instructions),\n", - " self._client_manager.num_available(),\n", - " )\n", - "\n", - " # Collect `fit` results from all clients participating in this round\n", - " results, failures = fit_clients(\n", - " client_instructions=client_instructions,\n", - " max_workers=self.max_workers,\n", - " timeout=timeout,\n", - " )\n", - "\n", - " log(\n", - " DEBUG,\n", - " \"fit_round %s received %s results and %s failures\",\n", - " server_round,\n", - " len(results),\n", - " len(failures),\n", - " )\n", - "\n", - " # Aggregate training results\n", - " NN_aggregated: Parameters\n", - " trees_aggregated: Union[\n", - " Tuple[XGBClassifier, int],\n", - " Tuple[XGBRegressor, int],\n", - " List[Union[Tuple[XGBClassifier, int], Tuple[XGBRegressor, int]]],\n", - " ]\n", - " metrics_aggregated: Dict[str, Scalar]\n", - " aggregated, metrics_aggregated = self.strategy.aggregate_fit(\n", - " server_round, results, failures\n", - " )\n", - " NN_aggregated, trees_aggregated = aggregated[0], aggregated[1]\n", - "\n", - " if type(trees_aggregated) is list:\n", - " print(\"Server side aggregated\", len(trees_aggregated), \"trees.\")\n", - " else:\n", - " print(\"Server side did not aggregate trees.\")\n", - "\n", - " return (\n", - " [NN_aggregated, trees_aggregated],\n", - " metrics_aggregated,\n", - " (results, failures),\n", - " )\n", - "\n", - " def _get_initial_parameters(\n", - " self, timeout: Optional[float]\n", - " ) -> Tuple[Parameters, Union[Tuple[XGBClassifier, int], Tuple[XGBRegressor, int]]]:\n", - " \"\"\"Get initial parameters from one of the available clients.\"\"\"\n", - "\n", - " # Server-side parameter initialization\n", - " parameters: Optional[Parameters] = self.strategy.initialize_parameters(\n", - " client_manager=self._client_manager\n", - " )\n", - " if parameters is not None:\n", - " log(INFO, \"Using initial parameters provided by strategy\")\n", - " return parameters\n", - "\n", - " # Get initial parameters from one of the clients\n", - " log(INFO, \"Requesting initial parameters from one random client\")\n", - " random_client = self._client_manager.sample(1)[0]\n", - " ins = GetParametersIns(config={})\n", - " get_parameters_res_tree = random_client.get_parameters(ins=ins, timeout=timeout)\n", - " parameters = [get_parameters_res_tree[0].parameters, get_parameters_res_tree[1]]\n", - " log(INFO, \"Received initial parameters from one random client\")\n", - "\n", - " return parameters" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Create server-side evaluation and experiment" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "executionInfo": { - "elapsed": 35, - "status": "ok", - "timestamp": 1670363021676, - "user": { - "displayName": "Chenyang Ma", - "userId": "17975430055716133031" - }, - "user_tz": 0 - } - }, - "outputs": [], - "source": [ - "def print_model_layers(model: nn.Module) -> None:\n", - " print(model)\n", - " for param_tensor in model.state_dict():\n", - " print(param_tensor, \"\\t\", model.state_dict()[param_tensor].size())\n", - "\n", - "\n", - "def serverside_eval(\n", - " server_round: int,\n", - " parameters: Tuple[\n", - " Parameters,\n", - " Union[\n", - " Tuple[XGBClassifier, int],\n", - " Tuple[XGBRegressor, int],\n", - " List[Union[Tuple[XGBClassifier, int], Tuple[XGBRegressor, int]]],\n", - " ],\n", - " ],\n", - " config: Dict[str, Scalar],\n", - " task_type: str,\n", - " testloader: DataLoader,\n", - " batch_size: int,\n", - " client_tree_num: int,\n", - " client_num: int,\n", - ") -> Tuple[float, Dict[str, float]]:\n", - " \"\"\"An evaluation function for centralized/serverside evaluation over the entire test set.\"\"\"\n", - " # device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n", - " device = \"cpu\"\n", - " model = CNN()\n", - " # print_model_layers(model)\n", - "\n", - " model.set_weights(parameters_to_ndarrays(parameters[0]))\n", - " model.to(device)\n", - "\n", - " trees_aggregated = parameters[1]\n", - " testloader = tree_encoding_loader(\n", - " testloader, batch_size, trees_aggregated, client_tree_num, client_num\n", - " )\n", - " loss, result, _ = test(\n", - " task_type, model, testloader, device=device, log_progress=False\n", - " )\n", - "\n", - " if task_type == \"BINARY\":\n", - " print(\n", - " f\"Evaluation on the server: test_loss={loss:.4f}, test_accuracy={result:.4f}\"\n", - " )\n", - " return loss, {\"accuracy\": result}\n", - " elif task_type == \"REG\":\n", - " print(f\"Evaluation on the server: test_loss={loss:.4f}, test_mse={result:.4f}\")\n", - " return loss, {\"mse\": result}\n", - "\n", - "\n", - "def start_experiment(\n", - " task_type: str,\n", - " trainset: Dataset,\n", - " testset: Dataset,\n", - " num_rounds: int = 5,\n", - " client_tree_num: int = 50,\n", - " client_pool_size: int = 5,\n", - " num_iterations: int = 100,\n", - " fraction_fit: float = 1.0,\n", - " min_fit_clients: int = 2,\n", - " batch_size: int = 32,\n", - " val_ratio: float = 0.1,\n", - ") -> History:\n", - " client_resources = {\"num_cpus\": 0.5} # 2 clients per CPU\n", - "\n", - " # Partition the dataset into subsets reserved for each client.\n", - " # - 'val_ratio' controls the proportion of the (local) client reserved as a local test set\n", - " # (good for testing how the final model performs on the client's local unseen data)\n", - " trainloaders, valloaders, testloader = do_fl_partitioning(\n", - " trainset,\n", - " testset,\n", - " batch_size=\"whole\",\n", - " pool_size=client_pool_size,\n", - " val_ratio=val_ratio,\n", - " )\n", - " print(\n", - " f\"Data partitioned across {client_pool_size} clients\"\n", - " f\" and {val_ratio} of local dataset reserved for validation.\"\n", - " )\n", - "\n", - " # Configure the strategy\n", - " def fit_config(server_round: int) -> Dict[str, Scalar]:\n", - " print(f\"Configuring round {server_round}\")\n", - " return {\n", - " \"num_iterations\": num_iterations,\n", - " \"batch_size\": batch_size,\n", - " }\n", - "\n", - " # FedXgbNnAvg\n", - " strategy = FedXgbNnAvg(\n", - " fraction_fit=fraction_fit,\n", - " fraction_evaluate=fraction_fit if val_ratio > 0.0 else 0.0,\n", - " min_fit_clients=min_fit_clients,\n", - " min_evaluate_clients=min_fit_clients,\n", - " min_available_clients=client_pool_size, # all clients should be available\n", - " on_fit_config_fn=fit_config,\n", - " on_evaluate_config_fn=(lambda r: {\"batch_size\": batch_size}),\n", - " evaluate_fn=functools.partial(\n", - " serverside_eval,\n", - " task_type=task_type,\n", - " testloader=testloader,\n", - " batch_size=batch_size,\n", - " client_tree_num=client_tree_num,\n", - " client_num=client_num,\n", - " ),\n", - " accept_failures=False,\n", - " )\n", - "\n", - " print(\n", - " f\"FL experiment configured for {num_rounds} rounds with {client_pool_size} client in the pool.\"\n", - " )\n", - " print(\n", - " f\"FL round will proceed with {fraction_fit * 100}% of clients sampled, at least {min_fit_clients}.\"\n", - " )\n", - "\n", - " def client_fn(cid: str) -> fl.client.Client:\n", - " \"\"\"Creates a federated learning client\"\"\"\n", - " if val_ratio > 0.0 and val_ratio <= 1.0:\n", - " return FL_Client(\n", - " task_type,\n", - " trainloaders[int(cid)],\n", - " valloaders[int(cid)],\n", - " client_tree_num,\n", - " client_pool_size,\n", - " cid,\n", - " log_progress=False,\n", - " )\n", - " else:\n", - " return FL_Client(\n", - " task_type,\n", - " trainloaders[int(cid)],\n", - " None,\n", - " client_tree_num,\n", - " client_pool_size,\n", - " cid,\n", - " log_progress=False,\n", - " )\n", - "\n", - " # Start the simulation\n", - " history = fl.simulation.start_simulation(\n", - " client_fn=client_fn,\n", - " server=FL_Server(client_manager=SimpleClientManager(), strategy=strategy),\n", - " num_clients=client_pool_size,\n", - " client_resources=client_resources,\n", - " config=ServerConfig(num_rounds=num_rounds),\n", - " strategy=strategy,\n", - " )\n", - "\n", - " print(history)\n", - "\n", - " return history" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Start federated training and inference\n", - "#### High-level workflow: \n", - "#### At round 1, each client first builds their own local XGBoost tree, and sends to the server. The server aggregates all trees and sends to all clients. \n", - "#### After round 1, each client calculates every other client tree’s prediction results, and trains a convolutional neural network with 1D convolution kernel size == the number of XGBoost trees in the tree ensemble. \n", - "#### The sharing of privacy-sensitive information is not needed, and the learning rate (a hyperparameter for XGBoost) is learnable using 1D convolution." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 624 - }, - "executionInfo": { - "elapsed": 7610, - "status": "error", - "timestamp": 1670363029252, - "user": { - "displayName": "Chenyang Ma", - "userId": "17975430055716133031" - }, - "user_tz": 0 - }, - "outputId": "ee2b7146-07ec-4f97-ba44-5b12b35bbeaf" - }, - "outputs": [], - "source": [ - "start_experiment(\n", - " task_type=task_type,\n", - " trainset=trainset,\n", - " testset=testset,\n", - " num_rounds=20,\n", - " client_tree_num=client_tree_num,\n", - " client_pool_size=client_num,\n", - " num_iterations=100,\n", - " batch_size=64,\n", - " fraction_fit=1.0,\n", - " min_fit_clients=1,\n", - " val_ratio=0.0,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "colab": { - "provenance": [] - }, - "gpuClass": "premium", - "kernelspec": { - "display_name": "FedXGBoost", - "language": "python", - "name": "python3" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/src/py/flwr/common/logger.py b/src/py/flwr/common/logger.py index 29d1562a86d3..50c902da38b5 100644 --- a/src/py/flwr/common/logger.py +++ b/src/py/flwr/common/logger.py @@ -111,3 +111,17 @@ def warn_experimental_feature(name: str) -> None: """, name, ) + + +def warn_deprecated_feature(name: str) -> None: + """Warn the user when they use a deprecated feature.""" + log( + WARN, + """ + DEPRECATED FEATURE: %s + + This is a deprecated feature. It will be removed + entirely in future versions of Flower. + """, + name, + ) diff --git a/src/py/flwr/server/strategy/fedxgb_nn_avg.py b/src/py/flwr/server/strategy/fedxgb_nn_avg.py index f300633d0d9f..8dedc925f350 100644 --- a/src/py/flwr/server/strategy/fedxgb_nn_avg.py +++ b/src/py/flwr/server/strategy/fedxgb_nn_avg.py @@ -25,7 +25,7 @@ from typing import Any, Dict, List, Optional, Tuple, Union from flwr.common import FitRes, Scalar, ndarrays_to_parameters, parameters_to_ndarrays -from flwr.common.logger import log +from flwr.common.logger import log, warn_deprecated_feature from flwr.server.client_proxy import ClientProxy from .aggregate import aggregate @@ -33,7 +33,13 @@ class FedXgbNnAvg(FedAvg): - """Configurable FedXgbNnAvg strategy implementation.""" + """Configurable FedXgbNnAvg strategy implementation. + + Warning + ------- + This strategy is deprecated, but a copy of it is available in Flower Baselines: + https://github.com/adap/flower/tree/main/baselines/hfedxgboost. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: """Federated XGBoost [Ma et al., 2023] strategy. @@ -41,6 +47,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: Implementation based on https://arxiv.org/abs/2304.07537. """ super().__init__(*args, **kwargs) + warn_deprecated_feature("`FedXgbNnAvg` strategy") def __repr__(self) -> str: """Compute a string representation of the strategy.""" From 6a72406b3e91765f0f24c0eb0ef8a2e1c2818792 Mon Sep 17 00:00:00 2001 From: Adam Narozniak <51029327+adam-narozniak@users.noreply.github.com> Date: Thu, 18 Jan 2024 23:05:09 +0100 Subject: [PATCH 012/113] Update pandas quickstart to use FDS (#2816) Co-authored-by: jafermarq --- examples/quickstart-pandas/README.md | 7 ++-- examples/quickstart-pandas/client.py | 46 ++++++++++++++++----- examples/quickstart-pandas/pyproject.toml | 2 +- examples/quickstart-pandas/requirements.txt | 2 +- examples/quickstart-pandas/run.sh | 6 +-- examples/quickstart-pandas/server.py | 11 +---- 6 files changed, 43 insertions(+), 31 deletions(-) diff --git a/examples/quickstart-pandas/README.md b/examples/quickstart-pandas/README.md index 2defc468c2ef..a25e6ea6ee36 100644 --- a/examples/quickstart-pandas/README.md +++ b/examples/quickstart-pandas/README.md @@ -1,6 +1,7 @@ # Flower Example using Pandas -This introductory example to Flower uses Pandas, but deep knowledge of Pandas is not necessarily required to run the example. However, it will help you understand how to adapt Flower to your use case. +This introductory example to Flower uses Pandas, but deep knowledge of Pandas is not necessarily required to run the example. However, it will help you understand how to adapt Flower to your use case. This example uses [Flower Datasets](https://flower.dev/docs/datasets/) to +download, partition and preprocess the dataset. Running this example in itself is quite easy. ## Project Setup @@ -69,13 +70,13 @@ Now you are ready to start the Flower clients which will participate in the lear Start client 1 in the first terminal: ```shell -$ python3 client.py +$ python3 client.py --node-id 0 ``` Start client 2 in the second terminal: ```shell -$ python3 client.py +$ python3 client.py --node-id 1 ``` You will see that the server is printing aggregated statistics about the dataset distributed amongst clients. Have a look to the [Flower Quickstarter documentation](https://flower.dev/docs/quickstart-pandas.html) for a detailed explanation. diff --git a/examples/quickstart-pandas/client.py b/examples/quickstart-pandas/client.py index 3feab3f6a0f4..c2f2605594d5 100644 --- a/examples/quickstart-pandas/client.py +++ b/examples/quickstart-pandas/client.py @@ -1,4 +1,4 @@ -import warnings +import argparse from typing import Dict, List, Tuple import numpy as np @@ -6,10 +6,10 @@ import flwr as fl +from flwr_datasets import FederatedDataset -df = pd.read_csv("./data/client.csv") -column_names = ["sepal length (cm)", "sepal width (cm)"] +column_names = ["sepal_length", "sepal_width"] def compute_hist(df: pd.DataFrame, col_name: str) -> np.ndarray: @@ -19,23 +19,47 @@ def compute_hist(df: pd.DataFrame, col_name: str) -> np.ndarray: # Define Flower client class FlowerClient(fl.client.NumPyClient): + def __init__(self, X: pd.DataFrame): + self.X = X + def fit( self, parameters: List[np.ndarray], config: Dict[str, str] ) -> Tuple[List[np.ndarray], int, Dict]: hist_list = [] # Execute query locally - for c in column_names: - hist = compute_hist(df, c) + for c in self.X.columns: + hist = compute_hist(self.X, c) hist_list.append(hist) return ( hist_list, - len(df), + len(self.X), {}, ) -# Start Flower client -fl.client.start_numpy_client( - server_address="127.0.0.1:8080", - client=FlowerClient(), -) +if __name__ == "__main__": + N_CLIENTS = 2 + + parser = argparse.ArgumentParser(description="Flower") + parser.add_argument( + "--node-id", + type=int, + choices=range(0, N_CLIENTS), + required=True, + help="Specifies the node id of artificially partitioned datasets.", + ) + args = parser.parse_args() + partition_id = args.node_id + + # Load the partition data + fds = FederatedDataset(dataset="hitorilabs/iris", partitioners={"train": N_CLIENTS}) + + dataset = fds.load_partition(partition_id, "train").with_format("pandas")[:] + # Use just the specified columns + X = dataset[column_names] + + # Start Flower client + fl.client.start_numpy_client( + server_address="127.0.0.1:8080", + client=FlowerClient(X), + ) diff --git a/examples/quickstart-pandas/pyproject.toml b/examples/quickstart-pandas/pyproject.toml index de20eaf61d63..6229210d6488 100644 --- a/examples/quickstart-pandas/pyproject.toml +++ b/examples/quickstart-pandas/pyproject.toml @@ -12,6 +12,6 @@ maintainers = ["The Flower Authors "] [tool.poetry.dependencies] python = ">=3.8,<3.11" flwr = ">=1.0,<2.0" +flwr-datasets = { extras = ["vision"], version = ">=0.0.2,<1.0.0" } numpy = "1.23.2" pandas = "2.0.0" -scikit-learn = "1.3.1" diff --git a/examples/quickstart-pandas/requirements.txt b/examples/quickstart-pandas/requirements.txt index 14308a55faaf..d44a3c6adab9 100644 --- a/examples/quickstart-pandas/requirements.txt +++ b/examples/quickstart-pandas/requirements.txt @@ -1,4 +1,4 @@ flwr>=1.0, <2.0 +flwr-datasets[vision]>=0.0.2, <1.0.0 numpy==1.23.2 pandas==2.0.0 -scikit-learn==1.3.1 diff --git a/examples/quickstart-pandas/run.sh b/examples/quickstart-pandas/run.sh index 6b85ce30bf45..571fa8bfb3e4 100755 --- a/examples/quickstart-pandas/run.sh +++ b/examples/quickstart-pandas/run.sh @@ -2,13 +2,9 @@ echo "Starting server" python server.py & sleep 3 # Sleep for 3s to give the server enough time to start -# Download data -mkdir -p ./data -python -c "from sklearn.datasets import load_iris; load_iris(as_frame=True)['data'].to_csv('./data/client.csv')" - for i in `seq 0 1`; do echo "Starting client $i" - python client.py & + python client.py --node-id ${i} & done # This will allow you to use CTRL+C to stop all background processes diff --git a/examples/quickstart-pandas/server.py b/examples/quickstart-pandas/server.py index c82304374836..af4c2a796788 100644 --- a/examples/quickstart-pandas/server.py +++ b/examples/quickstart-pandas/server.py @@ -1,5 +1,4 @@ -import pickle -from typing import Callable, Dict, List, Optional, Tuple, Union +from typing import Dict, List, Optional, Tuple, Union import numpy as np @@ -9,9 +8,6 @@ EvaluateRes, FitIns, FitRes, - Metrics, - MetricsAggregationFn, - NDArrays, Parameters, Scalar, ndarrays_to_parameters, @@ -23,11 +19,6 @@ class FedAnalytics(Strategy): - def __init__( - self, compute_fns: List[Callable] = None, col_names: List[str] = None - ) -> None: - super().__init__() - def initialize_parameters( self, client_manager: Optional[ClientManager] = None ) -> Optional[Parameters]: From 682bbd553920d26f699a8c2f75a1f6d5e02b33ff Mon Sep 17 00:00:00 2001 From: Javier Date: Fri, 19 Jan 2024 10:05:52 +0000 Subject: [PATCH 013/113] Add `task_type` to `Task` proto (#2819) --- src/proto/flwr/proto/task.proto | 3 ++- src/py/flwr/proto/task_pb2.py | 44 ++++++++++++++++----------------- src/py/flwr/proto/task_pb2.pyi | 5 +++- 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/src/proto/flwr/proto/task.proto b/src/proto/flwr/proto/task.proto index ad71d7ea3811..9faabe1eebd1 100644 --- a/src/proto/flwr/proto/task.proto +++ b/src/proto/flwr/proto/task.proto @@ -27,7 +27,8 @@ message Task { string delivered_at = 4; string ttl = 5; repeated string ancestry = 6; - SecureAggregation sa = 7; + string task_type = 7; + SecureAggregation sa = 8; ServerMessage legacy_server_message = 101 [ deprecated = true ]; ClientMessage legacy_client_message = 102 [ deprecated = true ]; diff --git a/src/py/flwr/proto/task_pb2.py b/src/py/flwr/proto/task_pb2.py index 8c9d6d001c1e..83ae15c0aba2 100644 --- a/src/py/flwr/proto/task_pb2.py +++ b/src/py/flwr/proto/task_pb2.py @@ -16,7 +16,7 @@ from flwr.proto import transport_pb2 as flwr_dot_proto_dot_transport__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/task.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x1a\x66lwr/proto/transport.proto\"\xbe\x02\n\x04Task\x12\"\n\x08producer\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\"\n\x08\x63onsumer\x18\x02 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x12\n\ncreated_at\x18\x03 \x01(\t\x12\x14\n\x0c\x64\x65livered_at\x18\x04 \x01(\t\x12\x0b\n\x03ttl\x18\x05 \x01(\t\x12\x10\n\x08\x61ncestry\x18\x06 \x03(\t\x12)\n\x02sa\x18\x07 \x01(\x0b\x32\x1d.flwr.proto.SecureAggregation\x12<\n\x15legacy_server_message\x18\x65 \x01(\x0b\x32\x19.flwr.proto.ServerMessageB\x02\x18\x01\x12<\n\x15legacy_client_message\x18\x66 \x01(\x0b\x32\x19.flwr.proto.ClientMessageB\x02\x18\x01\"\\\n\x07TaskIns\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x12\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Task\"\\\n\x07TaskRes\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x12\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Task\"\xf3\x03\n\x05Value\x12\x10\n\x06\x64ouble\x18\x01 \x01(\x01H\x00\x12\x10\n\x06sint64\x18\x02 \x01(\x12H\x00\x12\x0e\n\x04\x62ool\x18\x03 \x01(\x08H\x00\x12\x10\n\x06string\x18\x04 \x01(\tH\x00\x12\x0f\n\x05\x62ytes\x18\x05 \x01(\x0cH\x00\x12\x33\n\x0b\x64ouble_list\x18\x15 \x01(\x0b\x32\x1c.flwr.proto.Value.DoubleListH\x00\x12\x33\n\x0bsint64_list\x18\x16 \x01(\x0b\x32\x1c.flwr.proto.Value.Sint64ListH\x00\x12/\n\tbool_list\x18\x17 \x01(\x0b\x32\x1a.flwr.proto.Value.BoolListH\x00\x12\x33\n\x0bstring_list\x18\x18 \x01(\x0b\x32\x1c.flwr.proto.Value.StringListH\x00\x12\x31\n\nbytes_list\x18\x19 \x01(\x0b\x32\x1b.flwr.proto.Value.BytesListH\x00\x1a\x1a\n\nDoubleList\x12\x0c\n\x04vals\x18\x01 \x03(\x01\x1a\x1a\n\nSint64List\x12\x0c\n\x04vals\x18\x01 \x03(\x12\x1a\x18\n\x08\x42oolList\x12\x0c\n\x04vals\x18\x01 \x03(\x08\x1a\x1a\n\nStringList\x12\x0c\n\x04vals\x18\x01 \x03(\t\x1a\x19\n\tBytesList\x12\x0c\n\x04vals\x18\x01 \x03(\x0c\x42\x07\n\x05value\"\xa0\x01\n\x11SecureAggregation\x12\x44\n\x0cnamed_values\x18\x01 \x03(\x0b\x32..flwr.proto.SecureAggregation.NamedValuesEntry\x1a\x45\n\x10NamedValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12 \n\x05value\x18\x02 \x01(\x0b\x32\x11.flwr.proto.Value:\x02\x38\x01\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/task.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x1a\x66lwr/proto/transport.proto\"\xd1\x02\n\x04Task\x12\"\n\x08producer\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\"\n\x08\x63onsumer\x18\x02 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x12\n\ncreated_at\x18\x03 \x01(\t\x12\x14\n\x0c\x64\x65livered_at\x18\x04 \x01(\t\x12\x0b\n\x03ttl\x18\x05 \x01(\t\x12\x10\n\x08\x61ncestry\x18\x06 \x03(\t\x12\x11\n\ttask_type\x18\x07 \x01(\t\x12)\n\x02sa\x18\x08 \x01(\x0b\x32\x1d.flwr.proto.SecureAggregation\x12<\n\x15legacy_server_message\x18\x65 \x01(\x0b\x32\x19.flwr.proto.ServerMessageB\x02\x18\x01\x12<\n\x15legacy_client_message\x18\x66 \x01(\x0b\x32\x19.flwr.proto.ClientMessageB\x02\x18\x01\"\\\n\x07TaskIns\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x12\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Task\"\\\n\x07TaskRes\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x12\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Task\"\xf3\x03\n\x05Value\x12\x10\n\x06\x64ouble\x18\x01 \x01(\x01H\x00\x12\x10\n\x06sint64\x18\x02 \x01(\x12H\x00\x12\x0e\n\x04\x62ool\x18\x03 \x01(\x08H\x00\x12\x10\n\x06string\x18\x04 \x01(\tH\x00\x12\x0f\n\x05\x62ytes\x18\x05 \x01(\x0cH\x00\x12\x33\n\x0b\x64ouble_list\x18\x15 \x01(\x0b\x32\x1c.flwr.proto.Value.DoubleListH\x00\x12\x33\n\x0bsint64_list\x18\x16 \x01(\x0b\x32\x1c.flwr.proto.Value.Sint64ListH\x00\x12/\n\tbool_list\x18\x17 \x01(\x0b\x32\x1a.flwr.proto.Value.BoolListH\x00\x12\x33\n\x0bstring_list\x18\x18 \x01(\x0b\x32\x1c.flwr.proto.Value.StringListH\x00\x12\x31\n\nbytes_list\x18\x19 \x01(\x0b\x32\x1b.flwr.proto.Value.BytesListH\x00\x1a\x1a\n\nDoubleList\x12\x0c\n\x04vals\x18\x01 \x03(\x01\x1a\x1a\n\nSint64List\x12\x0c\n\x04vals\x18\x01 \x03(\x12\x1a\x18\n\x08\x42oolList\x12\x0c\n\x04vals\x18\x01 \x03(\x08\x1a\x1a\n\nStringList\x12\x0c\n\x04vals\x18\x01 \x03(\t\x1a\x19\n\tBytesList\x12\x0c\n\x04vals\x18\x01 \x03(\x0c\x42\x07\n\x05value\"\xa0\x01\n\x11SecureAggregation\x12\x44\n\x0cnamed_values\x18\x01 \x03(\x0b\x32..flwr.proto.SecureAggregation.NamedValuesEntry\x1a\x45\n\x10NamedValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12 \n\x05value\x18\x02 \x01(\x0b\x32\x11.flwr.proto.Value:\x02\x38\x01\x62\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -30,25 +30,25 @@ _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._options = None _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_options = b'8\001' _globals['_TASK']._serialized_start=89 - _globals['_TASK']._serialized_end=407 - _globals['_TASKINS']._serialized_start=409 - _globals['_TASKINS']._serialized_end=501 - _globals['_TASKRES']._serialized_start=503 - _globals['_TASKRES']._serialized_end=595 - _globals['_VALUE']._serialized_start=598 - _globals['_VALUE']._serialized_end=1097 - _globals['_VALUE_DOUBLELIST']._serialized_start=953 - _globals['_VALUE_DOUBLELIST']._serialized_end=979 - _globals['_VALUE_SINT64LIST']._serialized_start=981 - _globals['_VALUE_SINT64LIST']._serialized_end=1007 - _globals['_VALUE_BOOLLIST']._serialized_start=1009 - _globals['_VALUE_BOOLLIST']._serialized_end=1033 - _globals['_VALUE_STRINGLIST']._serialized_start=1035 - _globals['_VALUE_STRINGLIST']._serialized_end=1061 - _globals['_VALUE_BYTESLIST']._serialized_start=1063 - _globals['_VALUE_BYTESLIST']._serialized_end=1088 - _globals['_SECUREAGGREGATION']._serialized_start=1100 - _globals['_SECUREAGGREGATION']._serialized_end=1260 - _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_start=1191 - _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_end=1260 + _globals['_TASK']._serialized_end=426 + _globals['_TASKINS']._serialized_start=428 + _globals['_TASKINS']._serialized_end=520 + _globals['_TASKRES']._serialized_start=522 + _globals['_TASKRES']._serialized_end=614 + _globals['_VALUE']._serialized_start=617 + _globals['_VALUE']._serialized_end=1116 + _globals['_VALUE_DOUBLELIST']._serialized_start=972 + _globals['_VALUE_DOUBLELIST']._serialized_end=998 + _globals['_VALUE_SINT64LIST']._serialized_start=1000 + _globals['_VALUE_SINT64LIST']._serialized_end=1026 + _globals['_VALUE_BOOLLIST']._serialized_start=1028 + _globals['_VALUE_BOOLLIST']._serialized_end=1052 + _globals['_VALUE_STRINGLIST']._serialized_start=1054 + _globals['_VALUE_STRINGLIST']._serialized_end=1080 + _globals['_VALUE_BYTESLIST']._serialized_start=1082 + _globals['_VALUE_BYTESLIST']._serialized_end=1107 + _globals['_SECUREAGGREGATION']._serialized_start=1119 + _globals['_SECUREAGGREGATION']._serialized_end=1279 + _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_start=1210 + _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_end=1279 # @@protoc_insertion_point(module_scope) diff --git a/src/py/flwr/proto/task_pb2.pyi b/src/py/flwr/proto/task_pb2.pyi index f40a66ef98d1..1039fd3d56ae 100644 --- a/src/py/flwr/proto/task_pb2.pyi +++ b/src/py/flwr/proto/task_pb2.pyi @@ -21,6 +21,7 @@ class Task(google.protobuf.message.Message): DELIVERED_AT_FIELD_NUMBER: builtins.int TTL_FIELD_NUMBER: builtins.int ANCESTRY_FIELD_NUMBER: builtins.int + TASK_TYPE_FIELD_NUMBER: builtins.int SA_FIELD_NUMBER: builtins.int LEGACY_SERVER_MESSAGE_FIELD_NUMBER: builtins.int LEGACY_CLIENT_MESSAGE_FIELD_NUMBER: builtins.int @@ -33,6 +34,7 @@ class Task(google.protobuf.message.Message): ttl: typing.Text @property def ancestry(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[typing.Text]: ... + task_type: typing.Text @property def sa(self) -> global___SecureAggregation: ... @property @@ -47,12 +49,13 @@ class Task(google.protobuf.message.Message): delivered_at: typing.Text = ..., ttl: typing.Text = ..., ancestry: typing.Optional[typing.Iterable[typing.Text]] = ..., + task_type: typing.Text = ..., sa: typing.Optional[global___SecureAggregation] = ..., legacy_server_message: typing.Optional[flwr.proto.transport_pb2.ServerMessage] = ..., legacy_client_message: typing.Optional[flwr.proto.transport_pb2.ClientMessage] = ..., ) -> None: ... def HasField(self, field_name: typing_extensions.Literal["consumer",b"consumer","legacy_client_message",b"legacy_client_message","legacy_server_message",b"legacy_server_message","producer",b"producer","sa",b"sa"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["ancestry",b"ancestry","consumer",b"consumer","created_at",b"created_at","delivered_at",b"delivered_at","legacy_client_message",b"legacy_client_message","legacy_server_message",b"legacy_server_message","producer",b"producer","sa",b"sa","ttl",b"ttl"]) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["ancestry",b"ancestry","consumer",b"consumer","created_at",b"created_at","delivered_at",b"delivered_at","legacy_client_message",b"legacy_client_message","legacy_server_message",b"legacy_server_message","producer",b"producer","sa",b"sa","task_type",b"task_type","ttl",b"ttl"]) -> None: ... global___Task = Task class TaskIns(google.protobuf.message.Message): From 02740bd31c251ca5565c315448c62f51394f7f38 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 12:44:30 +0000 Subject: [PATCH 014/113] Update mypy requirement from ==1.6.1 to ==1.8.0 (#2812) Updates the requirements on [mypy](https://github.com/python/mypy) to permit the latest version. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.6.1...v1.8.0) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Taner Topal Co-authored-by: Daniel J. Beutel --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 4d15571b2491..1ccdc72666f6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -87,7 +87,7 @@ clang-format = "==17.0.4" isort = "==5.13.2" black = { version = "==23.10.1", extras = ["jupyter"] } docformatter = "==1.7.5" -mypy = "==1.6.1" +mypy = "==1.8.0" pylint = "==3.0.3" flake8 = "==5.0.4" pytest = "==7.4.4" From 7e089c197c4366bfe2ead2fb8b6e4413670a4bab Mon Sep 17 00:00:00 2001 From: Adam Narozniak <51029327+adam-narozniak@users.noreply.github.com> Date: Fri, 19 Jan 2024 13:57:28 +0100 Subject: [PATCH 015/113] FDS: Add typing module with array types definitions (#2796) --- datasets/flwr_datasets/common/typing.py | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 datasets/flwr_datasets/common/typing.py diff --git a/datasets/flwr_datasets/common/typing.py b/datasets/flwr_datasets/common/typing.py new file mode 100644 index 000000000000..ffaefaeec313 --- /dev/null +++ b/datasets/flwr_datasets/common/typing.py @@ -0,0 +1,26 @@ +# Copyright 2023 Flower Labs GmbH. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Flower Datasets type definitions.""" + + +from typing import Any, List + +import numpy as np +import numpy.typing as npt + +NDArray = npt.NDArray[Any] +NDArrayInt = npt.NDArray[np.int_] +NDArrayFloat = npt.NDArray[np.float_] +NDArrays = List[NDArray] From a5eee500f300407f5a45783ba1f4402fb78889b9 Mon Sep 17 00:00:00 2001 From: Pritam Neog Date: Fri, 19 Jan 2024 18:39:17 +0530 Subject: [PATCH 016/113] Improve checkpoint loading instructions (#2826) --- doc/source/how-to-save-and-load-model-checkpoints.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/source/how-to-save-and-load-model-checkpoints.rst b/doc/source/how-to-save-and-load-model-checkpoints.rst index 404df485fbae..0d711e375cd8 100644 --- a/doc/source/how-to-save-and-load-model-checkpoints.rst +++ b/doc/source/how-to-save-and-load-model-checkpoints.rst @@ -91,3 +91,7 @@ To load your progress, you simply append the following lines to your code. Note print("Loading pre-trained model from: ", latest_round_file) state_dict = torch.load(latest_round_file) net.load_state_dict(state_dict) + state_dict_ndarrays = [v.cpu().numpy() for v in net.state_dict().values()] + parameters = fl.common.ndarrays_to_parameters(state_dict_ndarrays) + +Return/use this object of type ``Parameters`` wherever necessary, such as in the ``initial_parameters`` when defining a ``Strategy``. \ No newline at end of file From fd581f20234399de4ad18844d2b891ca282039ca Mon Sep 17 00:00:00 2001 From: Charles Beauville Date: Fri, 19 Jan 2024 14:20:39 +0100 Subject: [PATCH 017/113] Make quote in contributor docs easier to read (#2827) --- .../contributor-tutorial-contribute-on-github.rst | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/source/contributor-tutorial-contribute-on-github.rst b/doc/source/contributor-tutorial-contribute-on-github.rst index aca7b0e68968..351d2408d9f3 100644 --- a/doc/source/contributor-tutorial-contribute-on-github.rst +++ b/doc/source/contributor-tutorial-contribute-on-github.rst @@ -357,23 +357,31 @@ Changelog entry When opening a new PR, inside its description, there should be a ``Changelog entry`` header. -As per the comment above this section:: +Above this header you should see the following comment that explains how to write your changelog entry: Inside the following 'Changelog entry' section, you should put the description of your changes that will be added to the changelog alongside your PR title. If the section is completely empty (without any token), the changelog will just contain the title of the PR for the changelog entry, without any description. + If the 'Changelog entry' section is removed entirely, it will categorize the PR as "General improvement" and add it to the changelog accordingly. + If the section contains some text other than tokens, it will use it to add a description to the change. + If the section contains one of the following tokens it will ignore any other text and put the PR under the corresponding section of the changelog: is for classifying a PR as a general improvement. + is to not add the PR to the changelog + is to add a general baselines change to the PR + is to add a general examples change to the PR + is to add a general sdk change to the PR + is to add a general simulations change to the PR Note that only one token should be used. From 818f6b7eb140dabadf163799473cb331703cacc2 Mon Sep 17 00:00:00 2001 From: Javier Date: Fri, 19 Jan 2024 16:31:49 +0000 Subject: [PATCH 018/113] Recordset basic enhancements (#2830) --- src/py/flwr/common/configsrecord.py | 19 ++++++++++++++----- src/py/flwr/common/metricsrecord.py | 19 ++++++++++++++----- src/py/flwr/common/parametersrecord.py | 17 ++++++++++++----- src/py/flwr/common/recordset_test.py | 4 ++-- 4 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/py/flwr/common/configsrecord.py b/src/py/flwr/common/configsrecord.py index 494cb88586ac..332269503ac0 100644 --- a/src/py/flwr/common/configsrecord.py +++ b/src/py/flwr/common/configsrecord.py @@ -25,7 +25,6 @@ class ConfigsRecord: """Configs record.""" - keep_input: bool data: Dict[str, ConfigsRecordValues] = field(default_factory=dict) def __init__( @@ -47,12 +46,13 @@ def __init__( to True, the data is duplicated in memory. If memory is a concern, set it to False. """ - self.keep_input = keep_input self.data = {} if configs_dict: - self.set_configs(configs_dict) + self.set_configs(configs_dict, keep_input=keep_input) - def set_configs(self, configs_dict: Dict[str, ConfigsRecordValues]) -> None: + def set_configs( + self, configs_dict: Dict[str, ConfigsRecordValues], keep_input: bool = True + ) -> None: """Add configs to the record. Parameters @@ -61,6 +61,11 @@ def set_configs(self, configs_dict: Dict[str, ConfigsRecordValues]) -> None: A dictionary that stores basic types (i.e. `str`,`int`, `float`, `bytes` as defined in `ConfigsRecordValues`) and list of such types (see `ConfigsScalarList`). + keep_input : bool (default: True) + A boolean indicating whether config passed should be deleted from the input + dictionary immediately after adding them to the record. When set + to True, the data is duplicated in memory. If memory is a concern, set + it to False. """ if any(not isinstance(k, str) for k in configs_dict.keys()): raise TypeError(f"Not all keys are of valid type. Expected {str}") @@ -88,7 +93,7 @@ def is_valid(value: ConfigsScalar) -> None: is_valid(value) # Add configs to record - if self.keep_input: + if keep_input: # Copy self.data = configs_dict.copy() else: @@ -96,3 +101,7 @@ def is_valid(value: ConfigsScalar) -> None: for key in list(configs_dict.keys()): self.data[key] = configs_dict[key] del configs_dict[key] + + def __getitem__(self, key: str) -> ConfigsRecordValues: + """Retrieve an element stored in record.""" + return self.data[key] diff --git a/src/py/flwr/common/metricsrecord.py b/src/py/flwr/common/metricsrecord.py index 68eca732efa2..d66a4454635a 100644 --- a/src/py/flwr/common/metricsrecord.py +++ b/src/py/flwr/common/metricsrecord.py @@ -25,7 +25,6 @@ class MetricsRecord: """Metrics record.""" - keep_input: bool data: Dict[str, MetricsRecordValues] = field(default_factory=dict) def __init__( @@ -46,12 +45,13 @@ def __init__( to True, the data is duplicated in memory. If memory is a concern, set it to False. """ - self.keep_input = keep_input self.data = {} if metrics_dict: - self.set_metrics(metrics_dict) + self.set_metrics(metrics_dict, keep_input=keep_input) - def set_metrics(self, metrics_dict: Dict[str, MetricsRecordValues]) -> None: + def set_metrics( + self, metrics_dict: Dict[str, MetricsRecordValues], keep_input: bool = True + ) -> None: """Add metrics to the record. Parameters @@ -59,6 +59,11 @@ def set_metrics(self, metrics_dict: Dict[str, MetricsRecordValues]) -> None: metrics_dict : Dict[str, MetricsRecordValues] A dictionary that stores basic types (i.e. `int`, `float` as defined in `MetricsScalar`) and list of such types (see `MetricsScalarList`). + keep_input : bool (default: True) + A boolean indicating whether metrics should be deleted from the input + dictionary immediately after adding them to the record. When set + to True, the data is duplicated in memory. If memory is a concern, set + it to False. """ if any(not isinstance(k, str) for k in metrics_dict.keys()): raise TypeError(f"Not all keys are of valid type. Expected {str}.") @@ -86,7 +91,7 @@ def is_valid(value: MetricsScalar) -> None: is_valid(value) # Add metrics to record - if self.keep_input: + if keep_input: # Copy self.data = metrics_dict.copy() else: @@ -94,3 +99,7 @@ def is_valid(value: MetricsScalar) -> None: for key in list(metrics_dict.keys()): self.data[key] = metrics_dict[key] del metrics_dict[key] + + def __getitem__(self, key: str) -> MetricsRecordValues: + """Retrieve an element stored in record.""" + return self.data[key] diff --git a/src/py/flwr/common/parametersrecord.py b/src/py/flwr/common/parametersrecord.py index 3d40c0488baa..ef02a0789ddf 100644 --- a/src/py/flwr/common/parametersrecord.py +++ b/src/py/flwr/common/parametersrecord.py @@ -59,7 +59,6 @@ class ParametersRecord: PyTorch's state_dict, but holding serialised tensors instead. """ - keep_input: bool data: OrderedDict[str, Array] = field(default_factory=OrderedDict[str, Array]) def __init__( @@ -82,25 +81,29 @@ def __init__( parameters after adding it to the record, set this flag to True. When set to True, the data is duplicated in memory. """ - self.keep_input = keep_input self.data = OrderedDict() if array_dict: - self.set_parameters(array_dict) + self.set_parameters(array_dict, keep_input=keep_input) - def set_parameters(self, array_dict: OrderedDict[str, Array]) -> None: + def set_parameters( + self, array_dict: OrderedDict[str, Array], keep_input: bool = False + ) -> None: """Add parameters to record. Parameters ---------- array_dict : OrderedDict[str, Array] A dictionary that stores serialized array-like or tensor-like objects. + keep_input : bool (default: False) + A boolean indicating whether parameters should be deleted from the input + dictionary immediately after adding them to the record. """ if any(not isinstance(k, str) for k in array_dict.keys()): raise TypeError(f"Not all keys are of valid type. Expected {str}") if any(not isinstance(v, Array) for v in array_dict.values()): raise TypeError(f"Not all values are of valid type. Expected {Array}") - if self.keep_input: + if keep_input: # Copy self.data = OrderedDict(array_dict) else: @@ -108,3 +111,7 @@ def set_parameters(self, array_dict: OrderedDict[str, Array]) -> None: for key in list(array_dict.keys()): self.data[key] = array_dict[key] del array_dict[key] + + def __getitem__(self, key: str) -> Array: + """Retrieve an element stored in record.""" + return self.data[key] diff --git a/src/py/flwr/common/recordset_test.py b/src/py/flwr/common/recordset_test.py index 3f0917d75cf5..b2f53ce43303 100644 --- a/src/py/flwr/common/recordset_test.py +++ b/src/py/flwr/common/recordset_test.py @@ -111,7 +111,7 @@ def test_set_parameters_while_keeping_intputs() -> None: array_dict = OrderedDict( {str(i): ndarray_to_array(ndarray) for i, ndarray in enumerate(get_ndarrays())} ) - p_record.set_parameters(array_dict) + p_record.set_parameters(array_dict, keep_input=True) # Creating a second parametersrecord passing the same `array_dict` (not erased) p_record_2 = ParametersRecord(array_dict) @@ -253,7 +253,7 @@ def test_set_metrics_to_metricsrecord_with_and_without_keeping_input( my_metrics_copy = my_metrics.copy() # Add metric - m_record.set_metrics(my_metrics) + m_record.set_metrics(my_metrics, keep_input=keep_input) # Check metrics are actually added # Check that input dict has been emptied when enabled such behaviour From 8f68938ad1fd961761816021a78f232144305863 Mon Sep 17 00:00:00 2001 From: Javier Date: Fri, 19 Jan 2024 17:48:07 +0000 Subject: [PATCH 019/113] Add `FlowerContext` and `Metadata` (#2820) Co-authored-by: Daniel J. Beutel --- src/py/flwr/common/flowercontext.py | 77 +++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 src/py/flwr/common/flowercontext.py diff --git a/src/py/flwr/common/flowercontext.py b/src/py/flwr/common/flowercontext.py new file mode 100644 index 000000000000..6e26d93bfe9a --- /dev/null +++ b/src/py/flwr/common/flowercontext.py @@ -0,0 +1,77 @@ +# Copyright 2024 Flower Labs GmbH. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""FlowerContext and Metadata.""" + + +from dataclasses import dataclass + +from .recordset import RecordSet + + +@dataclass +class Metadata: + """A dataclass holding metadata associated with the current task. + + Parameters + ---------- + run_id : int + An identifier for the current run. + task_id : str + An identifier for the current task. + group_id : str + An identifier for grouping tasks. In some settings + this is used as the FL round. + ttl : str + Time-to-live for this task. + task_type : str + A string that encodes the action to be executed on + the receiving end. + """ + + run_id: int + task_id: str + group_id: str + ttl: str + task_type: str + + +@dataclass +class FlowerContext: + """State of your application from the viewpoint of the entity using it. + + Parameters + ---------- + in_message : RecordSet + Holds records sent by another entity (e.g. sent by the server-side + logic to a client, or vice-versa) + out_message : RecordSet + Holds records added by the current entity. This `RecordSet` will + be sent out (e.g. back to the server-side for aggregation of + parameter, or to the client to perform a certain task) + local : RecordSet + Holds record added by the current entity and that will stay local. + This means that the data it holds will never leave the system it's running from. + This can be used as an intermediate storage or scratchpad when + executing middleware layers. It can also be used as a memory to access + at different points during the lifecycle of this entity (e.g. across + multiple rounds) + metadata : Metadata + A dataclass including information about the task to be executed. + """ + + in_message: RecordSet + out_message: RecordSet + local: RecordSet + metadata: Metadata From 3f9404f47e81a18b8b1ace5121353a12632d3018 Mon Sep 17 00:00:00 2001 From: Javier Date: Fri, 19 Jan 2024 19:59:15 +0000 Subject: [PATCH 020/113] Update supported types in ConfigsRecord and MetricsRecord (#2832) --- src/py/flwr/common/metricsrecord.py | 4 +++- src/py/flwr/common/recordset_test.py | 5 ++++- src/py/flwr/common/typing.py | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/py/flwr/common/metricsrecord.py b/src/py/flwr/common/metricsrecord.py index d66a4454635a..ecb8eff830ab 100644 --- a/src/py/flwr/common/metricsrecord.py +++ b/src/py/flwr/common/metricsrecord.py @@ -70,7 +70,9 @@ def set_metrics( def is_valid(value: MetricsScalar) -> None: """Check if value is of expected type.""" - if not isinstance(value, get_args(MetricsScalar)): + if not isinstance(value, get_args(MetricsScalar)) or isinstance( + value, bool + ): raise TypeError( "Not all values are of valid type." f" Expected {MetricsRecordValues} but you passed {type(value)}." diff --git a/src/py/flwr/common/recordset_test.py b/src/py/flwr/common/recordset_test.py index b2f53ce43303..0e4c351647da 100644 --- a/src/py/flwr/common/recordset_test.py +++ b/src/py/flwr/common/recordset_test.py @@ -189,6 +189,7 @@ def test_set_metrics_to_metricsrecord_with_correct_types( "key_type, value_fn", [ (str, lambda x: str(x.flatten()[0])), # str: str (supported: unsupported) + (str, lambda x: bool(x.flatten()[0])), # str: bool (supported: unsupported) ( str, lambda x: x.flatten().astype("str").tolist(), @@ -213,7 +214,7 @@ def test_set_metrics_to_metricsrecord_with_correct_types( ], ) def test_set_metrics_to_metricsrecord_with_incorrect_types( - key_type: Type[Union[str, int, float]], + key_type: Type[Union[str, int, float, bool]], value_fn: Callable[[NDArray], Union[NDArray, Dict[str, NDArray], List[float]]], ) -> None: """Test adding metrics of various unsupported types to a MetricsRecord.""" @@ -270,10 +271,12 @@ def test_set_metrics_to_metricsrecord_with_and_without_keeping_input( (str, lambda x: str(x.flatten()[0])), # str: str (str, lambda x: int(x.flatten()[0])), # str: int (str, lambda x: float(x.flatten()[0])), # str: float + (str, lambda x: bool(x.flatten()[0])), # str: bool (str, lambda x: x.flatten().tobytes()), # str: bytes (str, lambda x: x.flatten().astype("str").tolist()), # str: List[str] (str, lambda x: x.flatten().astype("int").tolist()), # str: List[int] (str, lambda x: x.flatten().astype("float").tolist()), # str: List[float] + (str, lambda x: x.flatten().astype("bool").tolist()), # str: List[bool] (str, lambda x: [x.flatten().tobytes()]), # str: List[bytes] ], ) diff --git a/src/py/flwr/common/typing.py b/src/py/flwr/common/typing.py index b247a9d2d9b5..d6b2ec9b158c 100644 --- a/src/py/flwr/common/typing.py +++ b/src/py/flwr/common/typing.py @@ -50,8 +50,8 @@ MetricsScalarList = Union[List[int], List[float]] MetricsRecordValues = Union[MetricsScalar, MetricsScalarList] # Value types for common.ConfigsRecord -ConfigsScalar = Union[MetricsScalar, str, bytes] -ConfigsScalarList = Union[MetricsScalarList, List[str], List[bytes]] +ConfigsScalar = Union[MetricsScalar, str, bytes, bool] +ConfigsScalarList = Union[MetricsScalarList, List[str], List[bytes], List[bool]] ConfigsRecordValues = Union[ConfigsScalar, ConfigsScalarList] Metrics = Dict[str, Scalar] From 033e4c2fcac846fb9a066d49c4b4bc9cd25b5f34 Mon Sep 17 00:00:00 2001 From: Adam Narozniak <51029327+adam-narozniak@users.noreply.github.com> Date: Mon, 22 Jan 2024 11:19:32 +0100 Subject: [PATCH 021/113] Migrate quickstart HuggingFace to flwr-datasets (#2829) Co-authored-by: jafermarq --- examples/quickstart-huggingface/README.md | 6 +- examples/quickstart-huggingface/client.py | 60 +++++++++---------- .../quickstart-huggingface/pyproject.toml | 1 + .../quickstart-huggingface/requirements.txt | 1 + examples/quickstart-huggingface/run.sh | 2 +- 5 files changed, 36 insertions(+), 34 deletions(-) diff --git a/examples/quickstart-huggingface/README.md b/examples/quickstart-huggingface/README.md index c1e3cc4edc06..fd868aa1fcce 100644 --- a/examples/quickstart-huggingface/README.md +++ b/examples/quickstart-huggingface/README.md @@ -1,6 +1,6 @@ # Federated HuggingFace Transformers using Flower and PyTorch -This introductory example to using [HuggingFace](https://huggingface.co) Transformers with Flower with PyTorch. This example has been extended from the [quickstart-pytorch](https://flower.dev/docs/examples/quickstart-pytorch.html) example. The training script closely follows the [HuggingFace course](https://huggingface.co/course/chapter3?fw=pt), so you are encouraged to check that out for detailed explaination for the transformer pipeline. +This introductory example to using [HuggingFace](https://huggingface.co) Transformers with Flower with PyTorch. This example has been extended from the [quickstart-pytorch](https://flower.dev/docs/examples/quickstart-pytorch.html) example. The training script closely follows the [HuggingFace course](https://huggingface.co/course/chapter3?fw=pt), so you are encouraged to check that out for a detailed explanation of the transformer pipeline. Like `quickstart-pytorch`, running this example in itself is also meant to be quite easy. @@ -62,13 +62,13 @@ Now you are ready to start the Flower clients which will participate in the lear Start client 1 in the first terminal: ```shell -python3 client.py +python3 client.py --node-id 0 ``` Start client 2 in the second terminal: ```shell -python3 client.py +python3 client.py --node-id 1 ``` You will see that PyTorch is starting a federated training. diff --git a/examples/quickstart-huggingface/client.py b/examples/quickstart-huggingface/client.py index 8717d710ad9c..5fa10b9ca0f2 100644 --- a/examples/quickstart-huggingface/client.py +++ b/examples/quickstart-huggingface/client.py @@ -1,58 +1,48 @@ -from collections import OrderedDict +import argparse import warnings +from collections import OrderedDict import flwr as fl import torch -import numpy as np - -import random -from torch.utils.data import DataLoader - -from datasets import load_dataset from evaluate import load as load_metric - -from transformers import AutoTokenizer, DataCollatorWithPadding +from torch.optim import AdamW +from torch.utils.data import DataLoader from transformers import AutoModelForSequenceClassification -from transformers import AdamW +from transformers import AutoTokenizer, DataCollatorWithPadding + +from flwr_datasets import FederatedDataset warnings.filterwarnings("ignore", category=UserWarning) DEVICE = torch.device("cpu") CHECKPOINT = "distilbert-base-uncased" # transformer model checkpoint -def load_data(): +def load_data(node_id): """Load IMDB data (training and eval)""" - raw_datasets = load_dataset("imdb") - raw_datasets = raw_datasets.shuffle(seed=42) - - # remove unnecessary data split - del raw_datasets["unsupervised"] + fds = FederatedDataset(dataset="imdb", partitioners={"train": 1_000}) + partition = fds.load_partition(node_id) + # Divide data: 80% train, 20% test + partition_train_test = partition.train_test_split(test_size=0.2) tokenizer = AutoTokenizer.from_pretrained(CHECKPOINT) def tokenize_function(examples): return tokenizer(examples["text"], truncation=True) - # random 100 samples - population = random.sample(range(len(raw_datasets["train"])), 100) - - tokenized_datasets = raw_datasets.map(tokenize_function, batched=True) - tokenized_datasets["train"] = tokenized_datasets["train"].select(population) - tokenized_datasets["test"] = tokenized_datasets["test"].select(population) - - tokenized_datasets = tokenized_datasets.remove_columns("text") - tokenized_datasets = tokenized_datasets.rename_column("label", "labels") + partition_train_test = partition_train_test.map(tokenize_function, batched=True) + partition_train_test = partition_train_test.remove_columns("text") + partition_train_test = partition_train_test.rename_column("label", "labels") data_collator = DataCollatorWithPadding(tokenizer=tokenizer) trainloader = DataLoader( - tokenized_datasets["train"], + partition_train_test["train"], shuffle=True, batch_size=32, collate_fn=data_collator, ) testloader = DataLoader( - tokenized_datasets["test"], batch_size=32, collate_fn=data_collator + partition_train_test["test"], batch_size=32, collate_fn=data_collator ) return trainloader, testloader @@ -88,12 +78,12 @@ def test(net, testloader): return loss, accuracy -def main(): +def main(node_id): net = AutoModelForSequenceClassification.from_pretrained( CHECKPOINT, num_labels=2 ).to(DEVICE) - trainloader, testloader = load_data() + trainloader, testloader = load_data(node_id) # Flower client class IMDBClient(fl.client.NumPyClient): @@ -122,4 +112,14 @@ def evaluate(self, parameters, config): if __name__ == "__main__": - main() + parser = argparse.ArgumentParser(description="Flower") + parser.add_argument( + "--node-id", + choices=list(range(1_000)), + required=True, + type=int, + help="Partition of the dataset divided into 1,000 iid partitions created " + "artificially.", + ) + node_id = parser.parse_args().node_id + main(node_id) diff --git a/examples/quickstart-huggingface/pyproject.toml b/examples/quickstart-huggingface/pyproject.toml index eb9687c5152c..50ba0b37f8d2 100644 --- a/examples/quickstart-huggingface/pyproject.toml +++ b/examples/quickstart-huggingface/pyproject.toml @@ -14,6 +14,7 @@ authors = [ [tool.poetry.dependencies] python = ">=3.8,<3.11" flwr = ">=1.0,<2.0" +flwr-datasets = ">=0.0.2,<1.0.0" torch = ">=1.13.1,<2.0" transformers = ">=4.30.0,<5.0" evaluate = ">=0.4.0,<1.0" diff --git a/examples/quickstart-huggingface/requirements.txt b/examples/quickstart-huggingface/requirements.txt index aeb2d13fc4a4..3cd5735625ba 100644 --- a/examples/quickstart-huggingface/requirements.txt +++ b/examples/quickstart-huggingface/requirements.txt @@ -1,4 +1,5 @@ flwr>=1.0, <2.0 +flwr-datasets>=0.0.2, <1.0.0 torch>=1.13.1, <2.0 transformers>=4.30.0, <5.0 evaluate>=0.4.0, <1.0 diff --git a/examples/quickstart-huggingface/run.sh b/examples/quickstart-huggingface/run.sh index c64f362086aa..e722a24a21a9 100755 --- a/examples/quickstart-huggingface/run.sh +++ b/examples/quickstart-huggingface/run.sh @@ -6,7 +6,7 @@ sleep 3 # Sleep for 3s to give the server enough time to start for i in `seq 0 1`; do echo "Starting client $i" - python client.py & + python client.py --node-id ${i}& done # This will allow you to use CTRL+C to stop all background processes From 255925938bd7c559af3f7f1ad7b363d34aab28d3 Mon Sep 17 00:00:00 2001 From: Javier Date: Mon, 22 Jan 2024 17:02:31 +0000 Subject: [PATCH 022/113] Improve records type checking (#2838) --- src/py/flwr/common/configsrecord.py | 13 +++++++++++-- src/py/flwr/common/metricsrecord.py | 13 +++++++++++-- src/py/flwr/common/recordset_test.py | 10 ++++++++++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/py/flwr/common/configsrecord.py b/src/py/flwr/common/configsrecord.py index 332269503ac0..b0480841e06c 100644 --- a/src/py/flwr/common/configsrecord.py +++ b/src/py/flwr/common/configsrecord.py @@ -87,8 +87,17 @@ def is_valid(value: ConfigsScalar) -> None: # 1s to check 10M element list on a M2 Pro # In such settings, you'd be better of treating such config as # an array and pass it to a ParametersRecord. - for list_value in value: - is_valid(list_value) + # Empty lists are valid + if len(value) > 0: + is_valid(value[0]) + # all elements in the list must be of the same valid type + # this is needed for protobuf + value_type = type(value[0]) + if not all(isinstance(v, value_type) for v in value): + raise TypeError( + "All values in a list must be of the same valid type. " + f"One of {ConfigsScalar}." + ) else: is_valid(value) diff --git a/src/py/flwr/common/metricsrecord.py b/src/py/flwr/common/metricsrecord.py index ecb8eff830ab..e70b0cb31d55 100644 --- a/src/py/flwr/common/metricsrecord.py +++ b/src/py/flwr/common/metricsrecord.py @@ -87,8 +87,17 @@ def is_valid(value: MetricsScalar) -> None: # 1s to check 10M element list on a M2 Pro # In such settings, you'd be better of treating such metric as # an array and pass it to a ParametersRecord. - for list_value in value: - is_valid(list_value) + # Empty lists are valid + if len(value) > 0: + is_valid(value[0]) + # all elements in the list must be of the same valid type + # this is needed for protobuf + value_type = type(value[0]) + if not all(isinstance(v, value_type) for v in value): + raise TypeError( + "All values in a list must be of the same valid type. " + f"One of {MetricsScalar}." + ) else: is_valid(value) diff --git a/src/py/flwr/common/recordset_test.py b/src/py/flwr/common/recordset_test.py index 0e4c351647da..83e1e4595f1d 100644 --- a/src/py/flwr/common/recordset_test.py +++ b/src/py/flwr/common/recordset_test.py @@ -162,6 +162,7 @@ def test_set_parameters_with_incorrect_types( (str, lambda x: float(x.flatten()[0])), # str: float (str, lambda x: x.flatten().astype("int").tolist()), # str: List[int] (str, lambda x: x.flatten().astype("float").tolist()), # str: List[float] + (str, lambda x: []), # str: empty list ], ) def test_set_metrics_to_metricsrecord_with_correct_types( @@ -203,6 +204,10 @@ def test_set_metrics_to_metricsrecord_with_correct_types( str, lambda x: [{str(v): v for v in x.flatten()}], ), # str: List[dict[str: float]] (supported: unsupported) + ( + str, + lambda x: [1, 2.0, 3.0, 4], + ), # str: List[mixing valid types] (supported: unsupported) ( int, lambda x: x.flatten().tolist(), @@ -278,6 +283,7 @@ def test_set_metrics_to_metricsrecord_with_and_without_keeping_input( (str, lambda x: x.flatten().astype("float").tolist()), # str: List[float] (str, lambda x: x.flatten().astype("bool").tolist()), # str: List[bool] (str, lambda x: [x.flatten().tobytes()]), # str: List[bytes] + (str, lambda x: []), # str: empyt list ], ) def test_set_configs_to_configsrecord_with_correct_types( @@ -310,6 +316,10 @@ def test_set_configs_to_configsrecord_with_correct_types( str, lambda x: [{str(v): v for v in x.flatten()}], ), # str: List[dict[str: float]] (supported: unsupported) + ( + str, + lambda x: [1, 2.0, 3.0, 4], + ), # str: List[mixing valid types] (supported: unsupported) ( int, lambda x: x.flatten().tolist(), From d7be8fb64507a83968479782976b9458435f909a Mon Sep 17 00:00:00 2001 From: Heng Pan <134433891+panh99@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:50:14 +0000 Subject: [PATCH 023/113] Add `*Record` ProtoBuf messages and corresponding serde functions. (#2831) --- src/proto/flwr/proto/recordset.proto | 70 +++++++ src/proto/flwr/proto/task.proto | 7 +- src/py/flwr/common/serde.py | 180 +++++++++++++++-- src/py/flwr/common/serde_test.py | 95 ++++++++- src/py/flwr/proto/recordset_pb2.py | 54 +++++ src/py/flwr/proto/recordset_pb2.pyi | 240 +++++++++++++++++++++++ src/py/flwr/proto/recordset_pb2_grpc.py | 4 + src/py/flwr/proto/recordset_pb2_grpc.pyi | 4 + src/py/flwr/proto/task_pb2.py | 37 ++-- src/py/flwr/proto/task_pb2.pyi | 76 ++----- src/py/flwr_tool/init_py_check.py | 2 +- src/py/flwr_tool/protoc.py | 2 +- src/py/flwr_tool/protoc_test.py | 2 +- 13 files changed, 654 insertions(+), 119 deletions(-) create mode 100644 src/proto/flwr/proto/recordset.proto create mode 100644 src/py/flwr/proto/recordset_pb2.py create mode 100644 src/py/flwr/proto/recordset_pb2.pyi create mode 100644 src/py/flwr/proto/recordset_pb2_grpc.py create mode 100644 src/py/flwr/proto/recordset_pb2_grpc.pyi diff --git a/src/proto/flwr/proto/recordset.proto b/src/proto/flwr/proto/recordset.proto new file mode 100644 index 000000000000..8e2e5d60b6db --- /dev/null +++ b/src/proto/flwr/proto/recordset.proto @@ -0,0 +1,70 @@ +// Copyright 2024 Flower Labs GmbH. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================== + +syntax = "proto3"; + +package flwr.proto; + +message DoubleList { repeated double vals = 1; } +message Sint64List { repeated sint64 vals = 1; } +message BoolList { repeated bool vals = 1; } +message StringList { repeated string vals = 1; } +message BytesList { repeated bytes vals = 1; } + +message Array { + string dtype = 1; + repeated int32 shape = 2; + string stype = 3; + bytes data = 4; +} + +message MetricsRecordValue { + oneof value { + // Single element + double double = 1; + sint64 sint64 = 2; + + // List types + DoubleList double_list = 21; + Sint64List sint64_list = 22; + } +} + +message ConfigsRecordValue { + oneof value { + // Single element + double double = 1; + sint64 sint64 = 2; + bool bool = 3; + string string = 4; + bytes bytes = 5; + + // List types + DoubleList double_list = 21; + Sint64List sint64_list = 22; + BoolList bool_list = 23; + StringList string_list = 24; + BytesList bytes_list = 25; + } +} + +message ParametersRecord { + repeated string data_keys = 1; + repeated Array data_values = 2; +} + +message MetricsRecord { map data = 1; } + +message ConfigsRecord { map data = 1; } diff --git a/src/proto/flwr/proto/task.proto b/src/proto/flwr/proto/task.proto index 9faabe1eebd1..20dd5a3aa6c8 100644 --- a/src/proto/flwr/proto/task.proto +++ b/src/proto/flwr/proto/task.proto @@ -18,6 +18,7 @@ syntax = "proto3"; package flwr.proto; import "flwr/proto/node.proto"; +import "flwr/proto/recordset.proto"; import "flwr/proto/transport.proto"; message Task { @@ -49,12 +50,6 @@ message TaskRes { } message Value { - message DoubleList { repeated double vals = 1; } - message Sint64List { repeated sint64 vals = 1; } - message BoolList { repeated bool vals = 1; } - message StringList { repeated string vals = 1; } - message BytesList { repeated bytes vals = 1; } - oneof value { // Single element double double = 1; diff --git a/src/py/flwr/common/serde.py b/src/py/flwr/common/serde.py index a059d95af833..2094c76a9856 100644 --- a/src/py/flwr/common/serde.py +++ b/src/py/flwr/common/serde.py @@ -15,10 +15,22 @@ """ProtoBuf serialization and deserialization.""" -from typing import Any, Dict, List, MutableMapping, cast - -from flwr.proto.task_pb2 import Value # pylint: disable=E0611 -from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 +from typing import Any, Dict, List, MutableMapping, OrderedDict, Type, TypeVar, cast + +from google.protobuf.message import Message + +# pylint: disable=E0611 +from flwr.proto.recordset_pb2 import Array as ProtoArray +from flwr.proto.recordset_pb2 import BoolList, BytesList +from flwr.proto.recordset_pb2 import ConfigsRecord as ProtoConfigsRecord +from flwr.proto.recordset_pb2 import ConfigsRecordValue as ProtoConfigsRecordValue +from flwr.proto.recordset_pb2 import DoubleList +from flwr.proto.recordset_pb2 import MetricsRecord as ProtoMetricsRecord +from flwr.proto.recordset_pb2 import MetricsRecordValue as ProtoMetricsRecordValue +from flwr.proto.recordset_pb2 import ParametersRecord as ProtoParametersRecord +from flwr.proto.recordset_pb2 import Sint64List, StringList +from flwr.proto.task_pb2 import Value +from flwr.proto.transport_pb2 import ( ClientMessage, Code, Parameters, @@ -28,7 +40,11 @@ Status, ) +# pylint: enable=E0611 from . import typing +from .configsrecord import ConfigsRecord +from .metricsrecord import MetricsRecord +from .parametersrecord import Array, ParametersRecord # === ServerMessage message === @@ -493,7 +509,7 @@ def scalar_from_proto(scalar_msg: Scalar) -> typing.Scalar: # === Value messages === -_python_type_to_field_name = { +_type_to_field = { float: "double", int: "sint64", bool: "bool", @@ -502,22 +518,20 @@ def scalar_from_proto(scalar_msg: Scalar) -> typing.Scalar: } -_python_list_type_to_message_and_field_name = { - float: (Value.DoubleList, "double_list"), - int: (Value.Sint64List, "sint64_list"), - bool: (Value.BoolList, "bool_list"), - str: (Value.StringList, "string_list"), - bytes: (Value.BytesList, "bytes_list"), +_list_type_to_class_and_field = { + float: (DoubleList, "double_list"), + int: (Sint64List, "sint64_list"), + bool: (BoolList, "bool_list"), + str: (StringList, "string_list"), + bytes: (BytesList, "bytes_list"), } def _check_value(value: typing.Value) -> None: - if isinstance(value, tuple(_python_type_to_field_name.keys())): + if isinstance(value, tuple(_type_to_field.keys())): return if isinstance(value, list): - if len(value) > 0 and isinstance( - value[0], tuple(_python_type_to_field_name.keys()) - ): + if len(value) > 0 and isinstance(value[0], tuple(_type_to_field.keys())): data_type = type(value[0]) for element in value: if isinstance(element, data_type): @@ -539,12 +553,12 @@ def value_to_proto(value: typing.Value) -> Value: arg = {} if isinstance(value, list): - msg_class, field_name = _python_list_type_to_message_and_field_name[ + msg_class, field_name = _list_type_to_class_and_field[ type(value[0]) if len(value) > 0 else int ] arg[field_name] = msg_class(vals=value) else: - arg[_python_type_to_field_name[type(value)]] = value + arg[_type_to_field[type(value)]] = value return Value(**arg) @@ -573,3 +587,135 @@ def named_values_from_proto( ) -> Dict[str, typing.Value]: """Deserialize named values from ProtoBuf.""" return {name: value_from_proto(value) for name, value in named_values_proto.items()} + + +# === Record messages === + + +T = TypeVar("T") + + +def _record_value_to_proto( + value: Any, allowed_types: List[type], proto_class: Type[T] +) -> T: + """Serialize `*RecordValue` to ProtoBuf.""" + arg = {} + for t in allowed_types: + # Single element + # Note: `isinstance(False, int) == True`. + if type(value) == t: # pylint: disable=C0123 + arg[_type_to_field[t]] = value + return proto_class(**arg) + # List + if isinstance(value, list) and all(isinstance(item, t) for item in value): + list_class, field_name = _list_type_to_class_and_field[t] + arg[field_name] = list_class(vals=value) + return proto_class(**arg) + # Invalid types + raise TypeError( + f"The type of the following value is not allowed " + f"in '{proto_class.__name__}':\n{value}" + ) + + +def _record_value_from_proto(value_proto: Message) -> Any: + """Deserialize `*RecordValue` from ProtoBuf.""" + value_field = cast(str, value_proto.WhichOneof("value")) + if value_field.endswith("list"): + value = list(getattr(value_proto, value_field).vals) + else: + value = getattr(value_proto, value_field) + return value + + +def _record_value_dict_to_proto( + value_dict: Dict[str, Any], allowed_types: List[type], value_proto_class: Type[T] +) -> Dict[str, T]: + """Serialize the record value dict to ProtoBuf.""" + + def proto(_v: Any) -> T: + return _record_value_to_proto(_v, allowed_types, value_proto_class) + + return {k: proto(v) for k, v in value_dict.items()} + + +def _record_value_dict_from_proto( + value_dict_proto: MutableMapping[str, Any] +) -> Dict[str, Any]: + """Deserialize the record value dict from ProtoBuf.""" + return {k: _record_value_from_proto(v) for k, v in value_dict_proto.items()} + + +def array_to_proto(array: Array) -> ProtoArray: + """Serialize Array to ProtoBuf.""" + return ProtoArray(**vars(array)) + + +def array_from_proto(array_proto: ProtoArray) -> Array: + """Deserialize Array from ProtoBuf.""" + return Array( + dtype=array_proto.dtype, + shape=list(array_proto.shape), + stype=array_proto.stype, + data=array_proto.data, + ) + + +def parameters_record_to_proto(record: ParametersRecord) -> ProtoParametersRecord: + """Serialize ParametersRecord to ProtoBuf.""" + return ProtoParametersRecord( + data_keys=record.data.keys(), + data_values=map(array_to_proto, record.data.values()), + ) + + +def parameters_record_from_proto( + record_proto: ProtoParametersRecord, +) -> ParametersRecord: + """Deserialize ParametersRecord from ProtoBuf.""" + return ParametersRecord( + array_dict=OrderedDict( + zip(record_proto.data_keys, map(array_from_proto, record_proto.data_values)) + ), + keep_input=False, + ) + + +def metrics_record_to_proto(record: MetricsRecord) -> ProtoMetricsRecord: + """Serialize MetricsRecord to ProtoBuf.""" + return ProtoMetricsRecord( + data=_record_value_dict_to_proto( + record.data, [float, int], ProtoMetricsRecordValue + ) + ) + + +def metrics_record_from_proto(record_proto: ProtoMetricsRecord) -> MetricsRecord: + """Deserialize MetricsRecord from ProtoBuf.""" + return MetricsRecord( + metrics_dict=cast( + Dict[str, typing.MetricsRecordValues], + _record_value_dict_from_proto(record_proto.data), + ), + keep_input=False, + ) + + +def configs_record_to_proto(record: ConfigsRecord) -> ProtoConfigsRecord: + """Serialize ConfigsRecord to ProtoBuf.""" + return ProtoConfigsRecord( + data=_record_value_dict_to_proto( + record.data, [int, float, bool, str, bytes], ProtoConfigsRecordValue + ) + ) + + +def configs_record_from_proto(record_proto: ProtoConfigsRecord) -> ConfigsRecord: + """Deserialize ConfigsRecord from ProtoBuf.""" + return ConfigsRecord( + configs_dict=cast( + Dict[str, typing.ConfigsRecordValues], + _record_value_dict_from_proto(record_proto.data), + ), + keep_input=False, + ) diff --git a/src/py/flwr/common/serde_test.py b/src/py/flwr/common/serde_test.py index 2c61c28eb0ee..c584597d89f6 100644 --- a/src/py/flwr/common/serde_test.py +++ b/src/py/flwr/common/serde_test.py @@ -15,14 +15,31 @@ """(De-)serialization tests.""" -from typing import Dict, Union, cast - -from flwr.common import typing -from flwr.proto import transport_pb2 as pb2 # pylint: disable=E0611 - +from typing import Dict, OrderedDict, Union, cast + +# pylint: disable=E0611 +from flwr.proto import transport_pb2 as pb2 +from flwr.proto.recordset_pb2 import Array as ProtoArray +from flwr.proto.recordset_pb2 import ConfigsRecord as ProtoConfigsRecord +from flwr.proto.recordset_pb2 import MetricsRecord as ProtoMetricsRecord +from flwr.proto.recordset_pb2 import ParametersRecord as ProtoParametersRecord + +# pylint: enable=E0611 +from . import typing +from .configsrecord import ConfigsRecord +from .metricsrecord import MetricsRecord +from .parametersrecord import Array, ParametersRecord from .serde import ( + array_from_proto, + array_to_proto, + configs_record_from_proto, + configs_record_to_proto, + metrics_record_from_proto, + metrics_record_to_proto, named_values_from_proto, named_values_to_proto, + parameters_record_from_proto, + parameters_record_to_proto, scalar_from_proto, scalar_to_proto, status_from_proto, @@ -157,3 +174,71 @@ def test_named_values_serialization_deserialization() -> None: assert elm1 == elm2 else: assert expected == actual + + +def test_array_serialization_deserialization() -> None: + """Test serialization and deserialization of Array.""" + # Prepare + original = Array(dtype="float", shape=[2, 2], stype="dense", data=b"1234") + + # Execute + proto = array_to_proto(original) + deserialized = array_from_proto(proto) + + # Assert + assert isinstance(proto, ProtoArray) + assert original == deserialized + + +def test_parameters_record_serialization_deserialization() -> None: + """Test serialization and deserialization of ParametersRecord.""" + # Prepare + original = ParametersRecord( + array_dict=OrderedDict( + [ + ("k1", Array(dtype="float", shape=[2, 2], stype="dense", data=b"1234")), + ("k2", Array(dtype="int", shape=[3], stype="sparse", data=b"567")), + ] + ), + keep_input=False, + ) + + # Execute + proto = parameters_record_to_proto(original) + deserialized = parameters_record_from_proto(proto) + + # Assert + assert isinstance(proto, ProtoParametersRecord) + assert original.data == deserialized.data + + +def test_metrics_record_serialization_deserialization() -> None: + """Test serialization and deserialization of MetricsRecord.""" + # Prepare + original = MetricsRecord( + metrics_dict={"accuracy": 0.95, "loss": 0.1}, keep_input=False + ) + + # Execute + proto = metrics_record_to_proto(original) + deserialized = metrics_record_from_proto(proto) + + # Assert + assert isinstance(proto, ProtoMetricsRecord) + assert original.data == deserialized.data + + +def test_configs_record_serialization_deserialization() -> None: + """Test serialization and deserialization of ConfigsRecord.""" + # Prepare + original = ConfigsRecord( + configs_dict={"learning_rate": 0.01, "batch_size": 32}, keep_input=False + ) + + # Execute + proto = configs_record_to_proto(original) + deserialized = configs_record_from_proto(proto) + + # Assert + assert isinstance(proto, ProtoConfigsRecord) + assert original.data == deserialized.data diff --git a/src/py/flwr/proto/recordset_pb2.py b/src/py/flwr/proto/recordset_pb2.py new file mode 100644 index 000000000000..4134511f1f53 --- /dev/null +++ b/src/py/flwr/proto/recordset_pb2.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: flwr/proto/recordset.proto +# Protobuf Python Version: 4.25.0 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1a\x66lwr/proto/recordset.proto\x12\nflwr.proto\"\x1a\n\nDoubleList\x12\x0c\n\x04vals\x18\x01 \x03(\x01\"\x1a\n\nSint64List\x12\x0c\n\x04vals\x18\x01 \x03(\x12\"\x18\n\x08\x42oolList\x12\x0c\n\x04vals\x18\x01 \x03(\x08\"\x1a\n\nStringList\x12\x0c\n\x04vals\x18\x01 \x03(\t\"\x19\n\tBytesList\x12\x0c\n\x04vals\x18\x01 \x03(\x0c\"B\n\x05\x41rray\x12\r\n\x05\x64type\x18\x01 \x01(\t\x12\r\n\x05shape\x18\x02 \x03(\x05\x12\r\n\x05stype\x18\x03 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c\"\x9f\x01\n\x12MetricsRecordValue\x12\x10\n\x06\x64ouble\x18\x01 \x01(\x01H\x00\x12\x10\n\x06sint64\x18\x02 \x01(\x12H\x00\x12-\n\x0b\x64ouble_list\x18\x15 \x01(\x0b\x32\x16.flwr.proto.DoubleListH\x00\x12-\n\x0bsint64_list\x18\x16 \x01(\x0b\x32\x16.flwr.proto.Sint64ListH\x00\x42\x07\n\x05value\"\xd9\x02\n\x12\x43onfigsRecordValue\x12\x10\n\x06\x64ouble\x18\x01 \x01(\x01H\x00\x12\x10\n\x06sint64\x18\x02 \x01(\x12H\x00\x12\x0e\n\x04\x62ool\x18\x03 \x01(\x08H\x00\x12\x10\n\x06string\x18\x04 \x01(\tH\x00\x12\x0f\n\x05\x62ytes\x18\x05 \x01(\x0cH\x00\x12-\n\x0b\x64ouble_list\x18\x15 \x01(\x0b\x32\x16.flwr.proto.DoubleListH\x00\x12-\n\x0bsint64_list\x18\x16 \x01(\x0b\x32\x16.flwr.proto.Sint64ListH\x00\x12)\n\tbool_list\x18\x17 \x01(\x0b\x32\x14.flwr.proto.BoolListH\x00\x12-\n\x0bstring_list\x18\x18 \x01(\x0b\x32\x16.flwr.proto.StringListH\x00\x12+\n\nbytes_list\x18\x19 \x01(\x0b\x32\x15.flwr.proto.BytesListH\x00\x42\x07\n\x05value\"M\n\x10ParametersRecord\x12\x11\n\tdata_keys\x18\x01 \x03(\t\x12&\n\x0b\x64\x61ta_values\x18\x02 \x03(\x0b\x32\x11.flwr.proto.Array\"\x8f\x01\n\rMetricsRecord\x12\x31\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32#.flwr.proto.MetricsRecord.DataEntry\x1aK\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.flwr.proto.MetricsRecordValue:\x02\x38\x01\"\x8f\x01\n\rConfigsRecord\x12\x31\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32#.flwr.proto.ConfigsRecord.DataEntry\x1aK\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.flwr.proto.ConfigsRecordValue:\x02\x38\x01\x62\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.recordset_pb2', _globals) +if _descriptor._USE_C_DESCRIPTORS == False: + DESCRIPTOR._options = None + _globals['_METRICSRECORD_DATAENTRY']._options = None + _globals['_METRICSRECORD_DATAENTRY']._serialized_options = b'8\001' + _globals['_CONFIGSRECORD_DATAENTRY']._options = None + _globals['_CONFIGSRECORD_DATAENTRY']._serialized_options = b'8\001' + _globals['_DOUBLELIST']._serialized_start=42 + _globals['_DOUBLELIST']._serialized_end=68 + _globals['_SINT64LIST']._serialized_start=70 + _globals['_SINT64LIST']._serialized_end=96 + _globals['_BOOLLIST']._serialized_start=98 + _globals['_BOOLLIST']._serialized_end=122 + _globals['_STRINGLIST']._serialized_start=124 + _globals['_STRINGLIST']._serialized_end=150 + _globals['_BYTESLIST']._serialized_start=152 + _globals['_BYTESLIST']._serialized_end=177 + _globals['_ARRAY']._serialized_start=179 + _globals['_ARRAY']._serialized_end=245 + _globals['_METRICSRECORDVALUE']._serialized_start=248 + _globals['_METRICSRECORDVALUE']._serialized_end=407 + _globals['_CONFIGSRECORDVALUE']._serialized_start=410 + _globals['_CONFIGSRECORDVALUE']._serialized_end=755 + _globals['_PARAMETERSRECORD']._serialized_start=757 + _globals['_PARAMETERSRECORD']._serialized_end=834 + _globals['_METRICSRECORD']._serialized_start=837 + _globals['_METRICSRECORD']._serialized_end=980 + _globals['_METRICSRECORD_DATAENTRY']._serialized_start=905 + _globals['_METRICSRECORD_DATAENTRY']._serialized_end=980 + _globals['_CONFIGSRECORD']._serialized_start=983 + _globals['_CONFIGSRECORD']._serialized_end=1126 + _globals['_CONFIGSRECORD_DATAENTRY']._serialized_start=1051 + _globals['_CONFIGSRECORD_DATAENTRY']._serialized_end=1126 +# @@protoc_insertion_point(module_scope) diff --git a/src/py/flwr/proto/recordset_pb2.pyi b/src/py/flwr/proto/recordset_pb2.pyi new file mode 100644 index 000000000000..1e9556de9ce6 --- /dev/null +++ b/src/py/flwr/proto/recordset_pb2.pyi @@ -0,0 +1,240 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" +import builtins +import google.protobuf.descriptor +import google.protobuf.internal.containers +import google.protobuf.message +import typing +import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +class DoubleList(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + VALS_FIELD_NUMBER: builtins.int + @property + def vals(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.float]: ... + def __init__(self, + *, + vals: typing.Optional[typing.Iterable[builtins.float]] = ..., + ) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["vals",b"vals"]) -> None: ... +global___DoubleList = DoubleList + +class Sint64List(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + VALS_FIELD_NUMBER: builtins.int + @property + def vals(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]: ... + def __init__(self, + *, + vals: typing.Optional[typing.Iterable[builtins.int]] = ..., + ) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["vals",b"vals"]) -> None: ... +global___Sint64List = Sint64List + +class BoolList(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + VALS_FIELD_NUMBER: builtins.int + @property + def vals(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.bool]: ... + def __init__(self, + *, + vals: typing.Optional[typing.Iterable[builtins.bool]] = ..., + ) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["vals",b"vals"]) -> None: ... +global___BoolList = BoolList + +class StringList(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + VALS_FIELD_NUMBER: builtins.int + @property + def vals(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[typing.Text]: ... + def __init__(self, + *, + vals: typing.Optional[typing.Iterable[typing.Text]] = ..., + ) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["vals",b"vals"]) -> None: ... +global___StringList = StringList + +class BytesList(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + VALS_FIELD_NUMBER: builtins.int + @property + def vals(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.bytes]: ... + def __init__(self, + *, + vals: typing.Optional[typing.Iterable[builtins.bytes]] = ..., + ) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["vals",b"vals"]) -> None: ... +global___BytesList = BytesList + +class Array(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + DTYPE_FIELD_NUMBER: builtins.int + SHAPE_FIELD_NUMBER: builtins.int + STYPE_FIELD_NUMBER: builtins.int + DATA_FIELD_NUMBER: builtins.int + dtype: typing.Text + @property + def shape(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]: ... + stype: typing.Text + data: builtins.bytes + def __init__(self, + *, + dtype: typing.Text = ..., + shape: typing.Optional[typing.Iterable[builtins.int]] = ..., + stype: typing.Text = ..., + data: builtins.bytes = ..., + ) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["data",b"data","dtype",b"dtype","shape",b"shape","stype",b"stype"]) -> None: ... +global___Array = Array + +class MetricsRecordValue(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + DOUBLE_FIELD_NUMBER: builtins.int + SINT64_FIELD_NUMBER: builtins.int + DOUBLE_LIST_FIELD_NUMBER: builtins.int + SINT64_LIST_FIELD_NUMBER: builtins.int + double: builtins.float + """Single element""" + + sint64: builtins.int + @property + def double_list(self) -> global___DoubleList: + """List types""" + pass + @property + def sint64_list(self) -> global___Sint64List: ... + def __init__(self, + *, + double: builtins.float = ..., + sint64: builtins.int = ..., + double_list: typing.Optional[global___DoubleList] = ..., + sint64_list: typing.Optional[global___Sint64List] = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["double",b"double","double_list",b"double_list","sint64",b"sint64","sint64_list",b"sint64_list","value",b"value"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["double",b"double","double_list",b"double_list","sint64",b"sint64","sint64_list",b"sint64_list","value",b"value"]) -> None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["value",b"value"]) -> typing.Optional[typing_extensions.Literal["double","sint64","double_list","sint64_list"]]: ... +global___MetricsRecordValue = MetricsRecordValue + +class ConfigsRecordValue(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + DOUBLE_FIELD_NUMBER: builtins.int + SINT64_FIELD_NUMBER: builtins.int + BOOL_FIELD_NUMBER: builtins.int + STRING_FIELD_NUMBER: builtins.int + BYTES_FIELD_NUMBER: builtins.int + DOUBLE_LIST_FIELD_NUMBER: builtins.int + SINT64_LIST_FIELD_NUMBER: builtins.int + BOOL_LIST_FIELD_NUMBER: builtins.int + STRING_LIST_FIELD_NUMBER: builtins.int + BYTES_LIST_FIELD_NUMBER: builtins.int + double: builtins.float + """Single element""" + + sint64: builtins.int + bool: builtins.bool + string: typing.Text + bytes: builtins.bytes + @property + def double_list(self) -> global___DoubleList: + """List types""" + pass + @property + def sint64_list(self) -> global___Sint64List: ... + @property + def bool_list(self) -> global___BoolList: ... + @property + def string_list(self) -> global___StringList: ... + @property + def bytes_list(self) -> global___BytesList: ... + def __init__(self, + *, + double: builtins.float = ..., + sint64: builtins.int = ..., + bool: builtins.bool = ..., + string: typing.Text = ..., + bytes: builtins.bytes = ..., + double_list: typing.Optional[global___DoubleList] = ..., + sint64_list: typing.Optional[global___Sint64List] = ..., + bool_list: typing.Optional[global___BoolList] = ..., + string_list: typing.Optional[global___StringList] = ..., + bytes_list: typing.Optional[global___BytesList] = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["bool",b"bool","bool_list",b"bool_list","bytes",b"bytes","bytes_list",b"bytes_list","double",b"double","double_list",b"double_list","sint64",b"sint64","sint64_list",b"sint64_list","string",b"string","string_list",b"string_list","value",b"value"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["bool",b"bool","bool_list",b"bool_list","bytes",b"bytes","bytes_list",b"bytes_list","double",b"double","double_list",b"double_list","sint64",b"sint64","sint64_list",b"sint64_list","string",b"string","string_list",b"string_list","value",b"value"]) -> None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["value",b"value"]) -> typing.Optional[typing_extensions.Literal["double","sint64","bool","string","bytes","double_list","sint64_list","bool_list","string_list","bytes_list"]]: ... +global___ConfigsRecordValue = ConfigsRecordValue + +class ParametersRecord(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + DATA_KEYS_FIELD_NUMBER: builtins.int + DATA_VALUES_FIELD_NUMBER: builtins.int + @property + def data_keys(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[typing.Text]: ... + @property + def data_values(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___Array]: ... + def __init__(self, + *, + data_keys: typing.Optional[typing.Iterable[typing.Text]] = ..., + data_values: typing.Optional[typing.Iterable[global___Array]] = ..., + ) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["data_keys",b"data_keys","data_values",b"data_values"]) -> None: ... +global___ParametersRecord = ParametersRecord + +class MetricsRecord(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + class DataEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: typing.Text + @property + def value(self) -> global___MetricsRecordValue: ... + def __init__(self, + *, + key: typing.Text = ..., + value: typing.Optional[global___MetricsRecordValue] = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["value",b"value"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["key",b"key","value",b"value"]) -> None: ... + + DATA_FIELD_NUMBER: builtins.int + @property + def data(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, global___MetricsRecordValue]: ... + def __init__(self, + *, + data: typing.Optional[typing.Mapping[typing.Text, global___MetricsRecordValue]] = ..., + ) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["data",b"data"]) -> None: ... +global___MetricsRecord = MetricsRecord + +class ConfigsRecord(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + class DataEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: typing.Text + @property + def value(self) -> global___ConfigsRecordValue: ... + def __init__(self, + *, + key: typing.Text = ..., + value: typing.Optional[global___ConfigsRecordValue] = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["value",b"value"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["key",b"key","value",b"value"]) -> None: ... + + DATA_FIELD_NUMBER: builtins.int + @property + def data(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, global___ConfigsRecordValue]: ... + def __init__(self, + *, + data: typing.Optional[typing.Mapping[typing.Text, global___ConfigsRecordValue]] = ..., + ) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["data",b"data"]) -> None: ... +global___ConfigsRecord = ConfigsRecord diff --git a/src/py/flwr/proto/recordset_pb2_grpc.py b/src/py/flwr/proto/recordset_pb2_grpc.py new file mode 100644 index 000000000000..2daafffebfc8 --- /dev/null +++ b/src/py/flwr/proto/recordset_pb2_grpc.py @@ -0,0 +1,4 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + diff --git a/src/py/flwr/proto/recordset_pb2_grpc.pyi b/src/py/flwr/proto/recordset_pb2_grpc.pyi new file mode 100644 index 000000000000..f3a5a087ef5d --- /dev/null +++ b/src/py/flwr/proto/recordset_pb2_grpc.pyi @@ -0,0 +1,4 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" diff --git a/src/py/flwr/proto/task_pb2.py b/src/py/flwr/proto/task_pb2.py index 83ae15c0aba2..963b07db94f8 100644 --- a/src/py/flwr/proto/task_pb2.py +++ b/src/py/flwr/proto/task_pb2.py @@ -13,10 +13,11 @@ from flwr.proto import node_pb2 as flwr_dot_proto_dot_node__pb2 +from flwr.proto import recordset_pb2 as flwr_dot_proto_dot_recordset__pb2 from flwr.proto import transport_pb2 as flwr_dot_proto_dot_transport__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/task.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x1a\x66lwr/proto/transport.proto\"\xd1\x02\n\x04Task\x12\"\n\x08producer\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\"\n\x08\x63onsumer\x18\x02 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x12\n\ncreated_at\x18\x03 \x01(\t\x12\x14\n\x0c\x64\x65livered_at\x18\x04 \x01(\t\x12\x0b\n\x03ttl\x18\x05 \x01(\t\x12\x10\n\x08\x61ncestry\x18\x06 \x03(\t\x12\x11\n\ttask_type\x18\x07 \x01(\t\x12)\n\x02sa\x18\x08 \x01(\x0b\x32\x1d.flwr.proto.SecureAggregation\x12<\n\x15legacy_server_message\x18\x65 \x01(\x0b\x32\x19.flwr.proto.ServerMessageB\x02\x18\x01\x12<\n\x15legacy_client_message\x18\x66 \x01(\x0b\x32\x19.flwr.proto.ClientMessageB\x02\x18\x01\"\\\n\x07TaskIns\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x12\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Task\"\\\n\x07TaskRes\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x12\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Task\"\xf3\x03\n\x05Value\x12\x10\n\x06\x64ouble\x18\x01 \x01(\x01H\x00\x12\x10\n\x06sint64\x18\x02 \x01(\x12H\x00\x12\x0e\n\x04\x62ool\x18\x03 \x01(\x08H\x00\x12\x10\n\x06string\x18\x04 \x01(\tH\x00\x12\x0f\n\x05\x62ytes\x18\x05 \x01(\x0cH\x00\x12\x33\n\x0b\x64ouble_list\x18\x15 \x01(\x0b\x32\x1c.flwr.proto.Value.DoubleListH\x00\x12\x33\n\x0bsint64_list\x18\x16 \x01(\x0b\x32\x1c.flwr.proto.Value.Sint64ListH\x00\x12/\n\tbool_list\x18\x17 \x01(\x0b\x32\x1a.flwr.proto.Value.BoolListH\x00\x12\x33\n\x0bstring_list\x18\x18 \x01(\x0b\x32\x1c.flwr.proto.Value.StringListH\x00\x12\x31\n\nbytes_list\x18\x19 \x01(\x0b\x32\x1b.flwr.proto.Value.BytesListH\x00\x1a\x1a\n\nDoubleList\x12\x0c\n\x04vals\x18\x01 \x03(\x01\x1a\x1a\n\nSint64List\x12\x0c\n\x04vals\x18\x01 \x03(\x12\x1a\x18\n\x08\x42oolList\x12\x0c\n\x04vals\x18\x01 \x03(\x08\x1a\x1a\n\nStringList\x12\x0c\n\x04vals\x18\x01 \x03(\t\x1a\x19\n\tBytesList\x12\x0c\n\x04vals\x18\x01 \x03(\x0c\x42\x07\n\x05value\"\xa0\x01\n\x11SecureAggregation\x12\x44\n\x0cnamed_values\x18\x01 \x03(\x0b\x32..flwr.proto.SecureAggregation.NamedValuesEntry\x1a\x45\n\x10NamedValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12 \n\x05value\x18\x02 \x01(\x0b\x32\x11.flwr.proto.Value:\x02\x38\x01\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/task.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x1a\x66lwr/proto/recordset.proto\x1a\x1a\x66lwr/proto/transport.proto\"\xd1\x02\n\x04Task\x12\"\n\x08producer\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\"\n\x08\x63onsumer\x18\x02 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x12\n\ncreated_at\x18\x03 \x01(\t\x12\x14\n\x0c\x64\x65livered_at\x18\x04 \x01(\t\x12\x0b\n\x03ttl\x18\x05 \x01(\t\x12\x10\n\x08\x61ncestry\x18\x06 \x03(\t\x12\x11\n\ttask_type\x18\x07 \x01(\t\x12)\n\x02sa\x18\x08 \x01(\x0b\x32\x1d.flwr.proto.SecureAggregation\x12<\n\x15legacy_server_message\x18\x65 \x01(\x0b\x32\x19.flwr.proto.ServerMessageB\x02\x18\x01\x12<\n\x15legacy_client_message\x18\x66 \x01(\x0b\x32\x19.flwr.proto.ClientMessageB\x02\x18\x01\"\\\n\x07TaskIns\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x12\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Task\"\\\n\x07TaskRes\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x12\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Task\"\xcc\x02\n\x05Value\x12\x10\n\x06\x64ouble\x18\x01 \x01(\x01H\x00\x12\x10\n\x06sint64\x18\x02 \x01(\x12H\x00\x12\x0e\n\x04\x62ool\x18\x03 \x01(\x08H\x00\x12\x10\n\x06string\x18\x04 \x01(\tH\x00\x12\x0f\n\x05\x62ytes\x18\x05 \x01(\x0cH\x00\x12-\n\x0b\x64ouble_list\x18\x15 \x01(\x0b\x32\x16.flwr.proto.DoubleListH\x00\x12-\n\x0bsint64_list\x18\x16 \x01(\x0b\x32\x16.flwr.proto.Sint64ListH\x00\x12)\n\tbool_list\x18\x17 \x01(\x0b\x32\x14.flwr.proto.BoolListH\x00\x12-\n\x0bstring_list\x18\x18 \x01(\x0b\x32\x16.flwr.proto.StringListH\x00\x12+\n\nbytes_list\x18\x19 \x01(\x0b\x32\x15.flwr.proto.BytesListH\x00\x42\x07\n\x05value\"\xa0\x01\n\x11SecureAggregation\x12\x44\n\x0cnamed_values\x18\x01 \x03(\x0b\x32..flwr.proto.SecureAggregation.NamedValuesEntry\x1a\x45\n\x10NamedValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12 \n\x05value\x18\x02 \x01(\x0b\x32\x11.flwr.proto.Value:\x02\x38\x01\x62\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -29,26 +30,16 @@ _globals['_TASK'].fields_by_name['legacy_client_message']._serialized_options = b'\030\001' _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._options = None _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_options = b'8\001' - _globals['_TASK']._serialized_start=89 - _globals['_TASK']._serialized_end=426 - _globals['_TASKINS']._serialized_start=428 - _globals['_TASKINS']._serialized_end=520 - _globals['_TASKRES']._serialized_start=522 - _globals['_TASKRES']._serialized_end=614 - _globals['_VALUE']._serialized_start=617 - _globals['_VALUE']._serialized_end=1116 - _globals['_VALUE_DOUBLELIST']._serialized_start=972 - _globals['_VALUE_DOUBLELIST']._serialized_end=998 - _globals['_VALUE_SINT64LIST']._serialized_start=1000 - _globals['_VALUE_SINT64LIST']._serialized_end=1026 - _globals['_VALUE_BOOLLIST']._serialized_start=1028 - _globals['_VALUE_BOOLLIST']._serialized_end=1052 - _globals['_VALUE_STRINGLIST']._serialized_start=1054 - _globals['_VALUE_STRINGLIST']._serialized_end=1080 - _globals['_VALUE_BYTESLIST']._serialized_start=1082 - _globals['_VALUE_BYTESLIST']._serialized_end=1107 - _globals['_SECUREAGGREGATION']._serialized_start=1119 - _globals['_SECUREAGGREGATION']._serialized_end=1279 - _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_start=1210 - _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_end=1279 + _globals['_TASK']._serialized_start=117 + _globals['_TASK']._serialized_end=454 + _globals['_TASKINS']._serialized_start=456 + _globals['_TASKINS']._serialized_end=548 + _globals['_TASKRES']._serialized_start=550 + _globals['_TASKRES']._serialized_end=642 + _globals['_VALUE']._serialized_start=645 + _globals['_VALUE']._serialized_end=977 + _globals['_SECUREAGGREGATION']._serialized_start=980 + _globals['_SECUREAGGREGATION']._serialized_end=1140 + _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_start=1071 + _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_end=1140 # @@protoc_insertion_point(module_scope) diff --git a/src/py/flwr/proto/task_pb2.pyi b/src/py/flwr/proto/task_pb2.pyi index 1039fd3d56ae..ebe69d05c974 100644 --- a/src/py/flwr/proto/task_pb2.pyi +++ b/src/py/flwr/proto/task_pb2.pyi @@ -4,6 +4,7 @@ isort:skip_file """ import builtins import flwr.proto.node_pb2 +import flwr.proto.recordset_pb2 import flwr.proto.transport_pb2 import google.protobuf.descriptor import google.protobuf.internal.containers @@ -104,61 +105,6 @@ global___TaskRes = TaskRes class Value(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor - class DoubleList(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor - VALS_FIELD_NUMBER: builtins.int - @property - def vals(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.float]: ... - def __init__(self, - *, - vals: typing.Optional[typing.Iterable[builtins.float]] = ..., - ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["vals",b"vals"]) -> None: ... - - class Sint64List(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor - VALS_FIELD_NUMBER: builtins.int - @property - def vals(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]: ... - def __init__(self, - *, - vals: typing.Optional[typing.Iterable[builtins.int]] = ..., - ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["vals",b"vals"]) -> None: ... - - class BoolList(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor - VALS_FIELD_NUMBER: builtins.int - @property - def vals(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.bool]: ... - def __init__(self, - *, - vals: typing.Optional[typing.Iterable[builtins.bool]] = ..., - ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["vals",b"vals"]) -> None: ... - - class StringList(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor - VALS_FIELD_NUMBER: builtins.int - @property - def vals(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[typing.Text]: ... - def __init__(self, - *, - vals: typing.Optional[typing.Iterable[typing.Text]] = ..., - ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["vals",b"vals"]) -> None: ... - - class BytesList(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor - VALS_FIELD_NUMBER: builtins.int - @property - def vals(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.bytes]: ... - def __init__(self, - *, - vals: typing.Optional[typing.Iterable[builtins.bytes]] = ..., - ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["vals",b"vals"]) -> None: ... - DOUBLE_FIELD_NUMBER: builtins.int SINT64_FIELD_NUMBER: builtins.int BOOL_FIELD_NUMBER: builtins.int @@ -177,17 +123,17 @@ class Value(google.protobuf.message.Message): string: typing.Text bytes: builtins.bytes @property - def double_list(self) -> global___Value.DoubleList: + def double_list(self) -> flwr.proto.recordset_pb2.DoubleList: """List types""" pass @property - def sint64_list(self) -> global___Value.Sint64List: ... + def sint64_list(self) -> flwr.proto.recordset_pb2.Sint64List: ... @property - def bool_list(self) -> global___Value.BoolList: ... + def bool_list(self) -> flwr.proto.recordset_pb2.BoolList: ... @property - def string_list(self) -> global___Value.StringList: ... + def string_list(self) -> flwr.proto.recordset_pb2.StringList: ... @property - def bytes_list(self) -> global___Value.BytesList: ... + def bytes_list(self) -> flwr.proto.recordset_pb2.BytesList: ... def __init__(self, *, double: builtins.float = ..., @@ -195,11 +141,11 @@ class Value(google.protobuf.message.Message): bool: builtins.bool = ..., string: typing.Text = ..., bytes: builtins.bytes = ..., - double_list: typing.Optional[global___Value.DoubleList] = ..., - sint64_list: typing.Optional[global___Value.Sint64List] = ..., - bool_list: typing.Optional[global___Value.BoolList] = ..., - string_list: typing.Optional[global___Value.StringList] = ..., - bytes_list: typing.Optional[global___Value.BytesList] = ..., + double_list: typing.Optional[flwr.proto.recordset_pb2.DoubleList] = ..., + sint64_list: typing.Optional[flwr.proto.recordset_pb2.Sint64List] = ..., + bool_list: typing.Optional[flwr.proto.recordset_pb2.BoolList] = ..., + string_list: typing.Optional[flwr.proto.recordset_pb2.StringList] = ..., + bytes_list: typing.Optional[flwr.proto.recordset_pb2.BytesList] = ..., ) -> None: ... def HasField(self, field_name: typing_extensions.Literal["bool",b"bool","bool_list",b"bool_list","bytes",b"bytes","bytes_list",b"bytes_list","double",b"double","double_list",b"double_list","sint64",b"sint64","sint64_list",b"sint64_list","string",b"string","string_list",b"string_list","value",b"value"]) -> builtins.bool: ... def ClearField(self, field_name: typing_extensions.Literal["bool",b"bool","bool_list",b"bool_list","bytes",b"bytes","bytes_list",b"bytes_list","double",b"double","double_list",b"double_list","sint64",b"sint64","sint64_list",b"sint64_list","string",b"string","string_list",b"string_list","value",b"value"]) -> None: ... diff --git a/src/py/flwr_tool/init_py_check.py b/src/py/flwr_tool/init_py_check.py index 8cdc2e0ab5be..67425139f991 100755 --- a/src/py/flwr_tool/init_py_check.py +++ b/src/py/flwr_tool/init_py_check.py @@ -36,7 +36,7 @@ def check_missing_init_files(absolute_path: str) -> None: if __name__ == "__main__": if len(sys.argv) == 0: - raise Exception( + raise Exception( # pylint: disable=W0719 "Please provide at least one directory path relative to your current working directory." ) for i, _ in enumerate(sys.argv): diff --git a/src/py/flwr_tool/protoc.py b/src/py/flwr_tool/protoc.py index 5d3ce942c1e0..b0b078c2eae4 100644 --- a/src/py/flwr_tool/protoc.py +++ b/src/py/flwr_tool/protoc.py @@ -51,7 +51,7 @@ def compile_all() -> None: exit_code = protoc.main(command) if exit_code != 0: - raise Exception(f"Error: {command} failed") + raise Exception(f"Error: {command} failed") # pylint: disable=W0719 if __name__ == "__main__": diff --git a/src/py/flwr_tool/protoc_test.py b/src/py/flwr_tool/protoc_test.py index 57ca3ff423c2..607d808c8497 100644 --- a/src/py/flwr_tool/protoc_test.py +++ b/src/py/flwr_tool/protoc_test.py @@ -28,4 +28,4 @@ def test_directories() -> None: def test_proto_file_count() -> None: """Test if the correct number of proto files were captured by the glob.""" - assert len(PROTO_FILES) == 5 + assert len(PROTO_FILES) == 6 From dfa30a30681042e1ad03264fa4aa5c9a1af1960a Mon Sep 17 00:00:00 2001 From: Gustavo Bertoli Date: Tue, 23 Jan 2024 15:25:47 +0100 Subject: [PATCH 024/113] Example for Custom Metrics calculation during Federated Learning (#1958) Co-authored-by: Yan Gao --- examples/custom-metrics/README.md | 106 +++++++++++++++++++++++ examples/custom-metrics/client.py | 71 +++++++++++++++ examples/custom-metrics/pyproject.toml | 19 ++++ examples/custom-metrics/requirements.txt | 4 + examples/custom-metrics/run.sh | 15 ++++ examples/custom-metrics/server.py | 58 +++++++++++++ 6 files changed, 273 insertions(+) create mode 100644 examples/custom-metrics/README.md create mode 100644 examples/custom-metrics/client.py create mode 100644 examples/custom-metrics/pyproject.toml create mode 100644 examples/custom-metrics/requirements.txt create mode 100755 examples/custom-metrics/run.sh create mode 100644 examples/custom-metrics/server.py diff --git a/examples/custom-metrics/README.md b/examples/custom-metrics/README.md new file mode 100644 index 000000000000..debcd7919839 --- /dev/null +++ b/examples/custom-metrics/README.md @@ -0,0 +1,106 @@ +# Flower Example using Custom Metrics + +This simple example demonstrates how to calculate custom metrics over multiple clients beyond the traditional ones available in the ML frameworks. In this case, it demonstrates the use of ready-available `scikit-learn` metrics: accuracy, recall, precision, and f1-score. + +Once both the test values (`y_test`) and the predictions (`y_pred`) are available on the client side (`client.py`), other metrics or custom ones are possible to be calculated. + +The main takeaways of this implementation are: + +- the use of the `output_dict` on the client side - inside `evaluate` method on `client.py` +- the use of the `evaluate_metrics_aggregation_fn` - to aggregate the metrics on the server side, part of the `strategy` on `server.py` + +This example is based on the `quickstart-tensorflow` with CIFAR-10, source [here](https://flower.dev/docs/quickstart-tensorflow.html), with the addition of [Flower Datasets](https://flower.dev/docs/datasets/index.html) to retrieve the CIFAR-10. + +Using the CIFAR-10 dataset for classification, this is a multi-class classification problem, thus some changes on how to calculate the metrics using `average='micro'` and `np.argmax` is required. For binary classification, this is not required. Also, for unsupervised learning tasks, such as using a deep autoencoder, a custom metric based on reconstruction error could be implemented on client side. + +## Project Setup + +Start by cloning the example project. We prepared a single-line command that you can copy into your shell which will checkout the example for you: + +```shell +git clone --depth=1 https://github.com/adap/flower.git && mv flower/examples/custom-metrics . && rm -rf flower && cd custom-metrics +``` + +This will create a new directory called `custom-metrics` containing the following files: + +```shell +-- pyproject.toml +-- requirements.txt +-- client.py +-- server.py +-- run.sh +-- README.md +``` + +### Installing Dependencies + +Project dependencies (such as `scikit-learn`, `tensorflow` and `flwr`) are defined in `pyproject.toml` and `requirements.txt`. We recommend [Poetry](https://python-poetry.org/docs/) to install those dependencies and manage your virtual environment ([Poetry installation](https://python-poetry.org/docs/#installation)) or [pip](https://pip.pypa.io/en/latest/development/), but feel free to use a different way of installing dependencies and managing virtual environments if you have other preferences. + +#### Poetry + +```shell +poetry install +poetry shell +``` + +Poetry will install all your dependencies in a newly created virtual environment. To verify that everything works correctly you can run the following command: + +```shell +poetry run python3 -c "import flwr" +``` + +If you don't see any errors you're good to go! + +#### pip + +Write the command below in your terminal to install the dependencies according to the configuration file requirements.txt. + +```shell +python -m venv venv +source venv/bin/activate +pip install -r requirements.txt +``` + +## Run Federated Learning with Custom Metrics + +Afterwards you are ready to start the Flower server as well as the clients. You can simply start the server in a terminal as follows: + +```shell +python server.py +``` + +Now you are ready to start the Flower clients which will participate in the learning. To do so simply open two more terminals and run the following command in each: + +```shell +python client.py +``` + +Alternatively you can run all of it in one shell as follows: + +```shell +python server.py & +# Wait for a few seconds to give the server enough time to start, then: +python client.py & +python client.py +``` + +or + +```shell +chmod +x run.sh +./run.sh +``` + +You will see that Keras is starting a federated training. Have a look to the [Flower Quickstarter documentation](https://flower.dev/docs/quickstart-tensorflow.html) for a detailed explanation. You can add `steps_per_epoch=3` to `model.fit()` if you just want to evaluate that everything works without having to wait for the client-side training to finish (this will save you a lot of time during development). + +Running `run.sh` will result in the following output (after 3 rounds): + +```shell +INFO flwr 2024-01-17 17:45:23,794 | app.py:228 | app_fit: metrics_distributed { + 'accuracy': [(1, 0.10000000149011612), (2, 0.10000000149011612), (3, 0.3393000066280365)], + 'acc': [(1, 0.1), (2, 0.1), (3, 0.3393)], + 'rec': [(1, 0.1), (2, 0.1), (3, 0.3393)], + 'prec': [(1, 0.1), (2, 0.1), (3, 0.3393)], + 'f1': [(1, 0.10000000000000002), (2, 0.10000000000000002), (3, 0.3393)] +} +``` diff --git a/examples/custom-metrics/client.py b/examples/custom-metrics/client.py new file mode 100644 index 000000000000..b2206118ed44 --- /dev/null +++ b/examples/custom-metrics/client.py @@ -0,0 +1,71 @@ +import os + +import flwr as fl +import numpy as np +import tensorflow as tf +from sklearn.metrics import accuracy_score, recall_score, precision_score, f1_score +from flwr_datasets import FederatedDataset + + +# Make TensorFlow log less verbose +os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3" + + +# Load model (MobileNetV2) +model = tf.keras.applications.MobileNetV2((32, 32, 3), classes=10, weights=None) +model.compile("adam", "sparse_categorical_crossentropy", metrics=["accuracy"]) + +# Load data with Flower Datasets (CIFAR-10) +fds = FederatedDataset(dataset="cifar10", partitioners={"train": 10}) +train = fds.load_full("train") +test = fds.load_full("test") + +# Using Numpy format +train_np = train.with_format("numpy") +test_np = test.with_format("numpy") +x_train, y_train = train_np["img"], train_np["label"] +x_test, y_test = test_np["img"], test_np["label"] + + +# Method for extra learning metrics calculation +def eval_learning(y_test, y_pred): + acc = accuracy_score(y_test, y_pred) + rec = recall_score( + y_test, y_pred, average="micro" + ) # average argument required for multi-class + prec = precision_score(y_test, y_pred, average="micro") + f1 = f1_score(y_test, y_pred, average="micro") + return acc, rec, prec, f1 + + +# Define Flower client +class FlowerClient(fl.client.NumPyClient): + def get_parameters(self, config): + return model.get_weights() + + def fit(self, parameters, config): + model.set_weights(parameters) + model.fit(x_train, y_train, epochs=1, batch_size=32) + return model.get_weights(), len(x_train), {} + + def evaluate(self, parameters, config): + model.set_weights(parameters) + loss, accuracy = model.evaluate(x_test, y_test) + y_pred = model.predict(x_test) + y_pred = np.argmax(y_pred, axis=1).reshape( + -1, 1 + ) # MobileNetV2 outputs 10 possible classes, argmax returns just the most probable + + acc, rec, prec, f1 = eval_learning(y_test, y_pred) + output_dict = { + "accuracy": accuracy, # accuracy from tensorflow model.evaluate + "acc": acc, + "rec": rec, + "prec": prec, + "f1": f1, + } + return loss, len(x_test), output_dict + + +# Start Flower client +fl.client.start_numpy_client(server_address="127.0.0.1:8080", client=FlowerClient()) diff --git a/examples/custom-metrics/pyproject.toml b/examples/custom-metrics/pyproject.toml new file mode 100644 index 000000000000..8a2da6562018 --- /dev/null +++ b/examples/custom-metrics/pyproject.toml @@ -0,0 +1,19 @@ +[build-system] +requires = ["poetry-core>=1.4.0"] +build-backend = "poetry.core.masonry.api" + +[tool.poetry] +name = "custom-metrics" +version = "0.1.0" +description = "Federated Learning with Flower and Custom Metrics" +authors = [ + "The Flower Authors ", + "Gustavo Bertoli " +] + +[tool.poetry.dependencies] +python = ">=3.8,<3.11" +flwr = ">=1.0,<2.0" +flwr-datasets = { version = "*", extras = ["vision"] } +scikit-learn = "^1.2.2" +tensorflow = "==2.12.0" \ No newline at end of file diff --git a/examples/custom-metrics/requirements.txt b/examples/custom-metrics/requirements.txt new file mode 100644 index 000000000000..69d867c5f287 --- /dev/null +++ b/examples/custom-metrics/requirements.txt @@ -0,0 +1,4 @@ +flwr>=1.0,<2.0 +flwr-datasets[vision] +scikit-learn>=1.2.2 +tensorflow==2.12.0 diff --git a/examples/custom-metrics/run.sh b/examples/custom-metrics/run.sh new file mode 100755 index 000000000000..c64f362086aa --- /dev/null +++ b/examples/custom-metrics/run.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +echo "Starting server" +python server.py & +sleep 3 # Sleep for 3s to give the server enough time to start + +for i in `seq 0 1`; do + echo "Starting client $i" + python client.py & +done + +# This will allow you to use CTRL+C to stop all background processes +trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM +# Wait for all background processes to complete +wait diff --git a/examples/custom-metrics/server.py b/examples/custom-metrics/server.py new file mode 100644 index 000000000000..f8420bf51f16 --- /dev/null +++ b/examples/custom-metrics/server.py @@ -0,0 +1,58 @@ +import flwr as fl +import numpy as np + + +# Define metrics aggregation function +def average_metrics(metrics): + """Aggregate metrics from multiple clients by calculating mean averages. + + Parameters: + - metrics (list): A list containing tuples, where each tuple represents metrics for a client. + Each tuple is structured as (num_examples, metric), where: + - num_examples (int): The number of examples used to compute the metrics. + - metric (dict): A dictionary containing custom metrics provided as `output_dict` + in the `evaluate` method from `client.py`. + + Returns: + A dictionary with the aggregated metrics, calculating mean averages. The keys of the + dictionary represent different metrics, including: + - 'accuracy': Mean accuracy calculated by TensorFlow. + - 'acc': Mean accuracy from scikit-learn. + - 'rec': Mean recall from scikit-learn. + - 'prec': Mean precision from scikit-learn. + - 'f1': Mean F1 score from scikit-learn. + + Note: If a weighted average is required, the `num_examples` parameter can be leveraged. + + Example: + Example `metrics` list for two clients after the last round: + [(10000, {'prec': 0.108, 'acc': 0.108, 'f1': 0.108, 'accuracy': 0.1080000028014183, 'rec': 0.108}), + (10000, {'f1': 0.108, 'rec': 0.108, 'accuracy': 0.1080000028014183, 'prec': 0.108, 'acc': 0.108})] + """ + + # Here num_examples are not taken into account by using _ + accuracies_tf = np.mean([metric["accuracy"] for _, metric in metrics]) + accuracies = np.mean([metric["acc"] for _, metric in metrics]) + recalls = np.mean([metric["rec"] for _, metric in metrics]) + precisions = np.mean([metric["prec"] for _, metric in metrics]) + f1s = np.mean([metric["f1"] for _, metric in metrics]) + + return { + "accuracy": accuracies_tf, + "acc": accuracies, + "rec": recalls, + "prec": precisions, + "f1": f1s, + } + + +# Define strategy and the custom aggregation function for the evaluation metrics +strategy = fl.server.strategy.FedAvg(evaluate_metrics_aggregation_fn=average_metrics) + + +# Start Flower server +fl.server.start_server( + server_address="0.0.0.0:8080", + config=fl.server.ServerConfig(num_rounds=3), + strategy=strategy, +) From a04265abb829bf955495d061ed092d923726dff9 Mon Sep 17 00:00:00 2001 From: Yan Gao Date: Tue, 23 Jan 2024 14:42:26 +0000 Subject: [PATCH 025/113] Update xgb doc for new features (#2821) Co-authored-by: yan-gao-GY --- doc/source/tutorial-quickstart-xgboost.rst | 616 ++++++++++++++++++--- 1 file changed, 542 insertions(+), 74 deletions(-) diff --git a/doc/source/tutorial-quickstart-xgboost.rst b/doc/source/tutorial-quickstart-xgboost.rst index 7eb58da7f2f6..3a7b356c4d2a 100644 --- a/doc/source/tutorial-quickstart-xgboost.rst +++ b/doc/source/tutorial-quickstart-xgboost.rst @@ -595,9 +595,164 @@ Comprehensive Federated XGBoost Now that you have known how federated XGBoost work with Flower, it's time to run some more comprehensive experiments by customising the experimental settings. In the xgboost-comprehensive example (`full code `_), -we provide more options to define various experimental setups, including data partitioning and centralised/distributed evaluation. +we provide more options to define various experimental setups, including aggregation strategies, data partitioning and centralised/distributed evaluation. +We also support `Flower simulation `_ making it easy to simulate large client cohorts in a resource-aware manner. Let's take a look! +Cyclic training +~~~~~~~~~~~~~~~~~~ + +In addition to bagging aggregation, we offer a cyclic training scheme, which performs FL in a client-by-client fashion. +Instead of aggregating multiple clients, there is only one single client participating in the training per round in the cyclic training scenario. +The trained local XGBoost trees will be passed to the next client as an initialised model for next round's boosting. + +To do this, we first customise a :code:`ClientManager` in :code:`server_utils.py`: + +.. code-block:: python + + class CyclicClientManager(SimpleClientManager): + """Provides a cyclic client selection rule.""" + + def sample( + self, + num_clients: int, + min_num_clients: Optional[int] = None, + criterion: Optional[Criterion] = None, + ) -> List[ClientProxy]: + """Sample a number of Flower ClientProxy instances.""" + + # Block until at least num_clients are connected. + if min_num_clients is None: + min_num_clients = num_clients + self.wait_for(min_num_clients) + + # Sample clients which meet the criterion + available_cids = list(self.clients) + if criterion is not None: + available_cids = [ + cid for cid in available_cids if criterion.select(self.clients[cid]) + ] + + if num_clients > len(available_cids): + log( + INFO, + "Sampling failed: number of available clients" + " (%s) is less than number of requested clients (%s).", + len(available_cids), + num_clients, + ) + return [] + + # Return all available clients + return [self.clients[cid] for cid in available_cids] + +The customised :code:`ClientManager` samples all available clients in each FL round based on the order of connection to the server. +Then, we define a new strategy :code:`FedXgbCyclic` in :code:`flwr.server.strategy.fedxgb_cyclic.py`, +in order to sequentially select only one client in given round and pass the received model to next client. + +.. code-block:: python + + class FedXgbCyclic(FedAvg): + """Configurable FedXgbCyclic strategy implementation.""" + + # pylint: disable=too-many-arguments,too-many-instance-attributes, line-too-long + def __init__( + self, + **kwargs: Any, + ): + self.global_model: Optional[bytes] = None + super().__init__(**kwargs) + + def aggregate_fit( + self, + server_round: int, + results: List[Tuple[ClientProxy, FitRes]], + failures: List[Union[Tuple[ClientProxy, FitRes], BaseException]], + ) -> Tuple[Optional[Parameters], Dict[str, Scalar]]: + """Aggregate fit results using bagging.""" + if not results: + return None, {} + # Do not aggregate if there are failures and failures are not accepted + if not self.accept_failures and failures: + return None, {} + + # Fetch the client model from last round as global model + for _, fit_res in results: + update = fit_res.parameters.tensors + for bst in update: + self.global_model = bst + + return ( + Parameters(tensor_type="", tensors=[cast(bytes, self.global_model)]), + {}, + ) + +Unlike the original :code:`FedAvg`, we don't perform aggregation here. +Instead, we just make a copy of the received client model as global model by overriding :code:`aggregate_fit`. + +Also, the customised :code:`configure_fit` and :code:`configure_evaluate` methods ensure the clients to be sequentially selected given FL round: + +.. code-block:: python + + def configure_fit( + self, server_round: int, parameters: Parameters, client_manager: ClientManager + ) -> List[Tuple[ClientProxy, FitIns]]: + """Configure the next round of training.""" + config = {} + if self.on_fit_config_fn is not None: + # Custom fit config function provided + config = self.on_fit_config_fn(server_round) + fit_ins = FitIns(parameters, config) + + # Sample clients + sample_size, min_num_clients = self.num_fit_clients( + client_manager.num_available() + ) + clients = client_manager.sample( + num_clients=sample_size, + min_num_clients=min_num_clients, + ) + + # Sample the clients sequentially given server_round + sampled_idx = (server_round - 1) % len(clients) + sampled_clients = [clients[sampled_idx]] + + # Return client/config pairs + return [(client, fit_ins) for client in sampled_clients] + + def configure_evaluate( + self, server_round: int, parameters: Parameters, client_manager: ClientManager + ) -> List[Tuple[ClientProxy, EvaluateIns]]: + """Configure the next round of evaluation.""" + # Do not configure federated evaluation if fraction eval is 0. + if self.fraction_evaluate == 0.0: + return [] + + # Parameters and config + config = {} + if self.on_evaluate_config_fn is not None: + # Custom evaluation config function provided + config = self.on_evaluate_config_fn(server_round) + evaluate_ins = EvaluateIns(parameters, config) + + # Sample clients + sample_size, min_num_clients = self.num_evaluation_clients( + client_manager.num_available() + ) + clients = client_manager.sample( + num_clients=sample_size, + min_num_clients=min_num_clients, + ) + + # Sample the clients sequentially given server_round + sampled_idx = (server_round - 1) % len(clients) + sampled_clients = [clients[sampled_idx]] + + # Return client/config pairs + return [(client, evaluate_ins) for client in sampled_clients] + + + Customised data partitioning ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -634,7 +789,7 @@ Currently, we provide four supported partitioner type to simulate the uniformity Customised centralised/distributed evaluation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -To facilitate centralised evaluation, we define a function in :code:`server.py`: +To facilitate centralised evaluation, we define a function in :code:`server_utils.py`: .. code-block:: python @@ -670,51 +825,265 @@ This function returns a evaluation function which instantiates a :code:`Booster` The evaluation is conducted by calling :code:`eval_set()` method, and the tested AUC value is reported. As for distributed evaluation on the clients, it's same as the quick-start example by -overriding the :code:`evaluate()` method insides the :code:`XgbClient` class in :code:`client.py`. +overriding the :code:`evaluate()` method insides the :code:`XgbClient` class in :code:`client_utils.py`. -Arguments parser -~~~~~~~~~~~~~~~~~~~~~~ +Flower simulation +~~~~~~~~~~~~~~~~~~~~ +We also provide an example code (:code:`sim.py`) to use the simulation capabilities of Flower to simulate federated XGBoost training on either a single machine or a cluster of machines. -In :code:`utils.py`, we define the arguments parsers for clients and server, allowing users to specify different experimental settings. -Let's first see the sever side: +.. code-block:: python + + from logging import INFO + import xgboost as xgb + from tqdm import tqdm + + import flwr as fl + from flwr_datasets import FederatedDataset + from flwr.common.logger import log + from flwr.server.strategy import FedXgbBagging, FedXgbCyclic + + from dataset import ( + instantiate_partitioner, + train_test_split, + transform_dataset_to_dmatrix, + separate_xy, + resplit, + ) + from utils import ( + sim_args_parser, + NUM_LOCAL_ROUND, + BST_PARAMS, + ) + from server_utils import ( + eval_config, + fit_config, + evaluate_metrics_aggregation, + get_evaluate_fn, + CyclicClientManager, + ) + from client_utils import XgbClient + +After importing all required packages, we define a :code:`main()` function to perform the simulation process: .. code-block:: python - import argparse + def main(): + # Parse arguments for experimental settings + args = sim_args_parser() + # Load (HIGGS) dataset and conduct partitioning + partitioner = instantiate_partitioner( + partitioner_type=args.partitioner_type, num_partitions=args.pool_size + ) + fds = FederatedDataset( + dataset="jxie/higgs", + partitioners={"train": partitioner}, + resplitter=resplit, + ) - def server_args_parser(): - """Parse arguments to define experimental settings on server side.""" - parser = argparse.ArgumentParser() + # Load centralised test set + if args.centralised_eval or args.centralised_eval_client: + log(INFO, "Loading centralised test set...") + test_data = fds.load_full("test") + test_data.set_format("numpy") + num_test = test_data.shape[0] + test_dmatrix = transform_dataset_to_dmatrix(test_data) + + # Load partitions and reformat data to DMatrix for xgboost + log(INFO, "Loading client local partitions...") + train_data_list = [] + valid_data_list = [] + + # Load and process all client partitions. This upfront cost is amortized soon + # after the simulation begins since clients wont need to preprocess their partition. + for node_id in tqdm(range(args.pool_size), desc="Extracting client partition"): + # Extract partition for client with node_id + partition = fds.load_partition(node_id=node_id, split="train") + partition.set_format("numpy") + + if args.centralised_eval_client: + # Use centralised test set for evaluation + train_data = partition + num_train = train_data.shape[0] + x_test, y_test = separate_xy(test_data) + valid_data_list.append(((x_test, y_test), num_test)) + else: + # Train/test splitting + train_data, valid_data, num_train, num_val = train_test_split( + partition, test_fraction=args.test_fraction, seed=args.seed + ) + x_valid, y_valid = separate_xy(valid_data) + valid_data_list.append(((x_valid, y_valid), num_val)) - parser.add_argument( - "--pool-size", default=2, type=int, help="Number of total clients." - ) - parser.add_argument( - "--num-rounds", default=5, type=int, help="Number of FL rounds." - ) - parser.add_argument( - "--num-clients-per-round", - default=2, - type=int, - help="Number of clients participate in training each round.", - ) - parser.add_argument( - "--num-evaluate-clients", - default=2, - type=int, - help="Number of clients selected for evaluation.", + x_train, y_train = separate_xy(train_data) + train_data_list.append(((x_train, y_train), num_train)) + +We first load the dataset and perform data partitioning, and the pre-processed data is stored in a :code:`list`. +After the simulation begins, the clients won't need to pre-process their partitions again. + +Then, we define the strategies and other hyper-parameters: + +.. code-block:: python + + # Define strategy + if args.train_method == "bagging": + # Bagging training + strategy = FedXgbBagging( + evaluate_function=get_evaluate_fn(test_dmatrix) + if args.centralised_eval + else None, + fraction_fit=(float(args.num_clients_per_round) / args.pool_size), + min_fit_clients=args.num_clients_per_round, + min_available_clients=args.pool_size, + min_evaluate_clients=args.num_evaluate_clients + if not args.centralised_eval + else 0, + fraction_evaluate=1.0 if not args.centralised_eval else 0.0, + on_evaluate_config_fn=eval_config, + on_fit_config_fn=fit_config, + evaluate_metrics_aggregation_fn=evaluate_metrics_aggregation + if not args.centralised_eval + else None, ) - parser.add_argument( - "--centralised-eval", - action="store_true", - help="Conduct centralised evaluation (True), or client evaluation on hold-out data (False).", + else: + # Cyclic training + strategy = FedXgbCyclic( + fraction_fit=1.0, + min_available_clients=args.pool_size, + fraction_evaluate=1.0, + evaluate_metrics_aggregation_fn=evaluate_metrics_aggregation, + on_evaluate_config_fn=eval_config, + on_fit_config_fn=fit_config, ) - args = parser.parse_args() - return args + # Resources to be assigned to each virtual client + # In this example we use CPU by default + client_resources = { + "num_cpus": args.num_cpus_per_client, + "num_gpus": 0.0, + } + + # Hyper-parameters for xgboost training + num_local_round = NUM_LOCAL_ROUND + params = BST_PARAMS + + # Setup learning rate + if args.train_method == "bagging" and args.scaled_lr: + new_lr = params["eta"] / args.pool_size + params.update({"eta": new_lr}) + +After that, we start the simulation by calling :code:`fl.simulation.start_simulation`: + +.. code-block:: python -This allows user to specify the number of total clients / FL rounds / participating clients / clients for evaluation, + # Start simulation + fl.simulation.start_simulation( + client_fn=get_client_fn( + train_data_list, + valid_data_list, + args.train_method, + params, + num_local_round, + ), + num_clients=args.pool_size, + client_resources=client_resources, + config=fl.server.ServerConfig(num_rounds=args.num_rounds), + strategy=strategy, + client_manager=CyclicClientManager() if args.train_method == "cyclic" else None, + ) + +One of key parameters for :code:`start_simulation` is :code:`client_fn` which returns a function to construct a client. +We define it as follows: + +.. code-block:: python + + def get_client_fn( + train_data_list, valid_data_list, train_method, params, num_local_round + ): + """Return a function to construct a client. + + The VirtualClientEngine will execute this function whenever a client is sampled by + the strategy to participate. + """ + + def client_fn(cid: str) -> fl.client.Client: + """Construct a FlowerClient with its own dataset partition.""" + x_train, y_train = train_data_list[int(cid)][0] + x_valid, y_valid = valid_data_list[int(cid)][0] + + # Reformat data to DMatrix + train_dmatrix = xgb.DMatrix(x_train, label=y_train) + valid_dmatrix = xgb.DMatrix(x_valid, label=y_valid) + + # Fetch the number of examples + num_train = train_data_list[int(cid)][1] + num_val = valid_data_list[int(cid)][1] + + # Create and return client + return XgbClient( + train_dmatrix, + valid_dmatrix, + num_train, + num_val, + num_local_round, + params, + train_method, + ) + + return client_fn + + + +Arguments parser +~~~~~~~~~~~~~~~~~~~~~~ + +In :code:`utils.py`, we define the arguments parsers for clients, server and simulation, allowing users to specify different experimental settings. +Let's first see the sever side: + +.. code-block:: python + + import argparse + + + def server_args_parser(): + """Parse arguments to define experimental settings on server side.""" + parser = argparse.ArgumentParser() + + parser.add_argument( + "--train-method", + default="bagging", + type=str, + choices=["bagging", "cyclic"], + help="Training methods selected from bagging aggregation or cyclic training.", + ) + parser.add_argument( + "--pool-size", default=2, type=int, help="Number of total clients." + ) + parser.add_argument( + "--num-rounds", default=5, type=int, help="Number of FL rounds." + ) + parser.add_argument( + "--num-clients-per-round", + default=2, + type=int, + help="Number of clients participate in training each round.", + ) + parser.add_argument( + "--num-evaluate-clients", + default=2, + type=int, + help="Number of clients selected for evaluation.", + ) + parser.add_argument( + "--centralised-eval", + action="store_true", + help="Conduct centralised evaluation (True), or client evaluation on hold-out data (False).", + ) + + args = parser.parse_args() + return args + +This allows user to specify training strategies / the number of total clients / FL rounds / participating clients / clients for evaluation, and evaluation fashion. Note that with :code:`--centralised-eval`, the sever will do centralised evaluation and all functionalities for client evaluation will be disabled. @@ -723,60 +1092,159 @@ Then, the argument parser on client side: .. code-block:: python def client_args_parser(): - """Parse arguments to define experimental settings on client side.""" - parser = argparse.ArgumentParser() + """Parse arguments to define experimental settings on client side.""" + parser = argparse.ArgumentParser() + + parser.add_argument( + "--train-method", + default="bagging", + type=str, + choices=["bagging", "cyclic"], + help="Training methods selected from bagging aggregation or cyclic training.", + ) + parser.add_argument( + "--num-partitions", default=10, type=int, help="Number of partitions." + ) + parser.add_argument( + "--partitioner-type", + default="uniform", + type=str, + choices=["uniform", "linear", "square", "exponential"], + help="Partitioner types.", + ) + parser.add_argument( + "--node-id", + default=0, + type=int, + help="Node ID used for the current client.", + ) + parser.add_argument( + "--seed", default=42, type=int, help="Seed used for train/test splitting." + ) + parser.add_argument( + "--test-fraction", + default=0.2, + type=float, + help="Test fraction for train/test splitting.", + ) + parser.add_argument( + "--centralised-eval", + action="store_true", + help="Conduct evaluation on centralised test set (True), or on hold-out data (False).", + ) + parser.add_argument( + "--scaled-lr", + action="store_true", + help="Perform scaled learning rate based on the number of clients (True).", + ) + + args = parser.parse_args() + return args - parser.add_argument( - "--num-partitions", default=10, type=int, help="Number of partitions." - ) - parser.add_argument( - "--partitioner-type", - default="uniform", - type=str, - choices=["uniform", "linear", "square", "exponential"], - help="Partitioner types.", - ) - parser.add_argument( - "--node-id", - default=0, - type=int, - help="Node ID used for the current client.", - ) - parser.add_argument( - "--seed", default=42, type=int, help="Seed used for train/test splitting." - ) - parser.add_argument( - "--test-fraction", - default=0.2, - type=float, - help="Test fraction for train/test splitting.", - ) - parser.add_argument( - "--centralised-eval", - action="store_true", - help="Conduct centralised evaluation (True), or client evaluation on hold-out data (False).", - ) +This defines various options for client data partitioning. +Besides, clients also have an option to conduct evaluation on centralised test set by setting :code:`--centralised-eval`, +as well as an option to perform scaled learning rate based on the number of clients by setting :code:`--scaled-lr`. - args = parser.parse_args() - return args +We also have an argument parser for simulation: -This defines various options for client data partitioning. -Besides, clients also have a option to conduct evaluation on centralised test set by setting :code:`--centralised-eval`. +.. code-block:: python + + def sim_args_parser(): + """Parse arguments to define experimental settings on server side.""" + parser = argparse.ArgumentParser() + + parser.add_argument( + "--train-method", + default="bagging", + type=str, + choices=["bagging", "cyclic"], + help="Training methods selected from bagging aggregation or cyclic training.", + ) + + # Server side + parser.add_argument( + "--pool-size", default=5, type=int, help="Number of total clients." + ) + parser.add_argument( + "--num-rounds", default=30, type=int, help="Number of FL rounds." + ) + parser.add_argument( + "--num-clients-per-round", + default=5, + type=int, + help="Number of clients participate in training each round.", + ) + parser.add_argument( + "--num-evaluate-clients", + default=5, + type=int, + help="Number of clients selected for evaluation.", + ) + parser.add_argument( + "--centralised-eval", + action="store_true", + help="Conduct centralised evaluation (True), or client evaluation on hold-out data (False).", + ) + parser.add_argument( + "--num-cpus-per-client", + default=2, + type=int, + help="Number of CPUs used for per client.", + ) + + # Client side + parser.add_argument( + "--partitioner-type", + default="uniform", + type=str, + choices=["uniform", "linear", "square", "exponential"], + help="Partitioner types.", + ) + parser.add_argument( + "--seed", default=42, type=int, help="Seed used for train/test splitting." + ) + parser.add_argument( + "--test-fraction", + default=0.2, + type=float, + help="Test fraction for train/test splitting.", + ) + parser.add_argument( + "--centralised-eval-client", + action="store_true", + help="Conduct evaluation on centralised test set (True), or on hold-out data (False).", + ) + parser.add_argument( + "--scaled-lr", + action="store_true", + help="Perform scaled learning rate based on the number of clients (True).", + ) + + args = parser.parse_args() + return args + +This integrates all arguments for both client and server sides. Example commands ~~~~~~~~~~~~~~~~~~~~~ -To run a centralised evaluated experiment on 5 clients with exponential distribution for 50 rounds, +To run a centralised evaluated experiment with bagging strategy on 5 clients with exponential distribution for 50 rounds, we first start the server as below: .. code-block:: shell - $ python3 server.py --pool-size=5 --num-rounds=50 --num-clients-per-round=5 --centralised-eval + $ python3 server.py --train-method=bagging --pool-size=5 --num-rounds=50 --num-clients-per-round=5 --centralised-eval Then, on each client terminal, we start the clients: .. code-block:: shell - $ python3 clients.py --num-partitions=5 --partitioner-type=exponential --node-id=NODE_ID + $ python3 clients.py --train-method=bagging --num-partitions=5 --partitioner-type=exponential --node-id=NODE_ID + +To run the same experiment with Flower simulation: + +.. code-block:: shell + + $ python3 sim.py --train-method=bagging --pool-size=5 --num-rounds=50 --num-clients-per-round=5 --partitioner-type=exponential --centralised-eval The full `code `_ for this comprehensive example can be found in :code:`examples/xgboost-comprehensive`. From 0e0af842ff9fead510dfc122a93f1440eeb3a75a Mon Sep 17 00:00:00 2001 From: Heng Pan <134433891+panh99@users.noreply.github.com> Date: Tue, 23 Jan 2024 17:41:24 +0000 Subject: [PATCH 026/113] Add `RecordSet` to `Task` proto (#2841) --- src/proto/flwr/proto/recordset.proto | 6 +++ src/proto/flwr/proto/task.proto | 3 +- src/py/flwr/common/serde.py | 32 ++++++++++++++ src/py/flwr/common/serde_test.py | 65 ++++++++++++++++++++++++++++ src/py/flwr/proto/recordset_pb2.py | 16 ++++++- src/py/flwr/proto/recordset_pb2.pyi | 65 ++++++++++++++++++++++++++++ src/py/flwr/proto/task_pb2.py | 26 ++++++----- src/py/flwr/proto/task_pb2.pyi | 14 +++--- 8 files changed, 208 insertions(+), 19 deletions(-) diff --git a/src/proto/flwr/proto/recordset.proto b/src/proto/flwr/proto/recordset.proto index 8e2e5d60b6db..d51d0f9ce416 100644 --- a/src/proto/flwr/proto/recordset.proto +++ b/src/proto/flwr/proto/recordset.proto @@ -68,3 +68,9 @@ message ParametersRecord { message MetricsRecord { map data = 1; } message ConfigsRecord { map data = 1; } + +message RecordSet { + map parameters = 1; + map metrics = 2; + map configs = 3; +} diff --git a/src/proto/flwr/proto/task.proto b/src/proto/flwr/proto/task.proto index 20dd5a3aa6c8..2cde16143d8d 100644 --- a/src/proto/flwr/proto/task.proto +++ b/src/proto/flwr/proto/task.proto @@ -29,10 +29,11 @@ message Task { string ttl = 5; repeated string ancestry = 6; string task_type = 7; - SecureAggregation sa = 8; + RecordSet recordset = 8; ServerMessage legacy_server_message = 101 [ deprecated = true ]; ClientMessage legacy_client_message = 102 [ deprecated = true ]; + SecureAggregation sa = 103 [ deprecated = true ]; } message TaskIns { diff --git a/src/py/flwr/common/serde.py b/src/py/flwr/common/serde.py index 2094c76a9856..2600d46edddc 100644 --- a/src/py/flwr/common/serde.py +++ b/src/py/flwr/common/serde.py @@ -28,6 +28,7 @@ from flwr.proto.recordset_pb2 import MetricsRecord as ProtoMetricsRecord from flwr.proto.recordset_pb2 import MetricsRecordValue as ProtoMetricsRecordValue from flwr.proto.recordset_pb2 import ParametersRecord as ProtoParametersRecord +from flwr.proto.recordset_pb2 import RecordSet as ProtoRecordSet from flwr.proto.recordset_pb2 import Sint64List, StringList from flwr.proto.task_pb2 import Value from flwr.proto.transport_pb2 import ( @@ -45,6 +46,7 @@ from .configsrecord import ConfigsRecord from .metricsrecord import MetricsRecord from .parametersrecord import Array, ParametersRecord +from .recordset import RecordSet # === ServerMessage message === @@ -719,3 +721,33 @@ def configs_record_from_proto(record_proto: ProtoConfigsRecord) -> ConfigsRecord ), keep_input=False, ) + + +# === RecordSet message === + + +def recordset_to_proto(recordset: RecordSet) -> ProtoRecordSet: + """Serialize RecordSet to ProtoBuf.""" + return ProtoRecordSet( + parameters={ + k: parameters_record_to_proto(v) for k, v in recordset.parameters.items() + }, + metrics={k: metrics_record_to_proto(v) for k, v in recordset.metrics.items()}, + configs={k: configs_record_to_proto(v) for k, v in recordset.configs.items()}, + ) + + +def recordset_from_proto(recordset_proto: ProtoRecordSet) -> RecordSet: + """Deserialize RecordSet from ProtoBuf.""" + return RecordSet( + parameters={ + k: parameters_record_from_proto(v) + for k, v in recordset_proto.parameters.items() + }, + metrics={ + k: metrics_record_from_proto(v) for k, v in recordset_proto.metrics.items() + }, + configs={ + k: configs_record_from_proto(v) for k, v in recordset_proto.configs.items() + }, + ) diff --git a/src/py/flwr/common/serde_test.py b/src/py/flwr/common/serde_test.py index c584597d89f6..53f40eee5e53 100644 --- a/src/py/flwr/common/serde_test.py +++ b/src/py/flwr/common/serde_test.py @@ -23,12 +23,14 @@ from flwr.proto.recordset_pb2 import ConfigsRecord as ProtoConfigsRecord from flwr.proto.recordset_pb2 import MetricsRecord as ProtoMetricsRecord from flwr.proto.recordset_pb2 import ParametersRecord as ProtoParametersRecord +from flwr.proto.recordset_pb2 import RecordSet as ProtoRecordSet # pylint: enable=E0611 from . import typing from .configsrecord import ConfigsRecord from .metricsrecord import MetricsRecord from .parametersrecord import Array, ParametersRecord +from .recordset import RecordSet from .serde import ( array_from_proto, array_to_proto, @@ -40,6 +42,8 @@ named_values_to_proto, parameters_record_from_proto, parameters_record_to_proto, + recordset_from_proto, + recordset_to_proto, scalar_from_proto, scalar_to_proto, status_from_proto, @@ -242,3 +246,64 @@ def test_configs_record_serialization_deserialization() -> None: # Assert assert isinstance(proto, ProtoConfigsRecord) assert original.data == deserialized.data + + +def test_recordset_serialization_deserialization() -> None: + """Test serialization and deserialization of RecordSet.""" + # Prepare + encoder_params_record = ParametersRecord( + array_dict=OrderedDict( + [ + ( + "k1", + Array(dtype="float", shape=[2, 2], stype="dense", data=b"1234"), + ), + ("k2", Array(dtype="int", shape=[3], stype="sparse", data=b"567")), + ] + ), + keep_input=False, + ) + decoder_params_record = ParametersRecord( + array_dict=OrderedDict( + [ + ( + "k1", + Array( + dtype="float", shape=[32, 32, 4], stype="dense", data=b"0987" + ), + ), + ] + ), + keep_input=False, + ) + + original = RecordSet( + parameters={ + "encoder_parameters": encoder_params_record, + "decoder_parameters": decoder_params_record, + }, + metrics={ + "acc_metrics": MetricsRecord( + metrics_dict={"accuracy": 0.95, "loss": 0.1}, keep_input=False + ) + }, + configs={ + "my_configs": ConfigsRecord( + configs_dict={ + "learning_rate": 0.01, + "batch_size": 32, + "public_key": b"21f8sioj@!#", + "log": "Hello, world!", + }, + keep_input=False, + ) + }, + ) + + # Execute + proto = recordset_to_proto(original) + deserialized = recordset_from_proto(proto) + + # Assert + assert isinstance(proto, ProtoRecordSet) + assert original == deserialized diff --git a/src/py/flwr/proto/recordset_pb2.py b/src/py/flwr/proto/recordset_pb2.py index 4134511f1f53..f7f74d72182b 100644 --- a/src/py/flwr/proto/recordset_pb2.py +++ b/src/py/flwr/proto/recordset_pb2.py @@ -14,7 +14,7 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1a\x66lwr/proto/recordset.proto\x12\nflwr.proto\"\x1a\n\nDoubleList\x12\x0c\n\x04vals\x18\x01 \x03(\x01\"\x1a\n\nSint64List\x12\x0c\n\x04vals\x18\x01 \x03(\x12\"\x18\n\x08\x42oolList\x12\x0c\n\x04vals\x18\x01 \x03(\x08\"\x1a\n\nStringList\x12\x0c\n\x04vals\x18\x01 \x03(\t\"\x19\n\tBytesList\x12\x0c\n\x04vals\x18\x01 \x03(\x0c\"B\n\x05\x41rray\x12\r\n\x05\x64type\x18\x01 \x01(\t\x12\r\n\x05shape\x18\x02 \x03(\x05\x12\r\n\x05stype\x18\x03 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c\"\x9f\x01\n\x12MetricsRecordValue\x12\x10\n\x06\x64ouble\x18\x01 \x01(\x01H\x00\x12\x10\n\x06sint64\x18\x02 \x01(\x12H\x00\x12-\n\x0b\x64ouble_list\x18\x15 \x01(\x0b\x32\x16.flwr.proto.DoubleListH\x00\x12-\n\x0bsint64_list\x18\x16 \x01(\x0b\x32\x16.flwr.proto.Sint64ListH\x00\x42\x07\n\x05value\"\xd9\x02\n\x12\x43onfigsRecordValue\x12\x10\n\x06\x64ouble\x18\x01 \x01(\x01H\x00\x12\x10\n\x06sint64\x18\x02 \x01(\x12H\x00\x12\x0e\n\x04\x62ool\x18\x03 \x01(\x08H\x00\x12\x10\n\x06string\x18\x04 \x01(\tH\x00\x12\x0f\n\x05\x62ytes\x18\x05 \x01(\x0cH\x00\x12-\n\x0b\x64ouble_list\x18\x15 \x01(\x0b\x32\x16.flwr.proto.DoubleListH\x00\x12-\n\x0bsint64_list\x18\x16 \x01(\x0b\x32\x16.flwr.proto.Sint64ListH\x00\x12)\n\tbool_list\x18\x17 \x01(\x0b\x32\x14.flwr.proto.BoolListH\x00\x12-\n\x0bstring_list\x18\x18 \x01(\x0b\x32\x16.flwr.proto.StringListH\x00\x12+\n\nbytes_list\x18\x19 \x01(\x0b\x32\x15.flwr.proto.BytesListH\x00\x42\x07\n\x05value\"M\n\x10ParametersRecord\x12\x11\n\tdata_keys\x18\x01 \x03(\t\x12&\n\x0b\x64\x61ta_values\x18\x02 \x03(\x0b\x32\x11.flwr.proto.Array\"\x8f\x01\n\rMetricsRecord\x12\x31\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32#.flwr.proto.MetricsRecord.DataEntry\x1aK\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.flwr.proto.MetricsRecordValue:\x02\x38\x01\"\x8f\x01\n\rConfigsRecord\x12\x31\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32#.flwr.proto.ConfigsRecord.DataEntry\x1aK\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.flwr.proto.ConfigsRecordValue:\x02\x38\x01\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1a\x66lwr/proto/recordset.proto\x12\nflwr.proto\"\x1a\n\nDoubleList\x12\x0c\n\x04vals\x18\x01 \x03(\x01\"\x1a\n\nSint64List\x12\x0c\n\x04vals\x18\x01 \x03(\x12\"\x18\n\x08\x42oolList\x12\x0c\n\x04vals\x18\x01 \x03(\x08\"\x1a\n\nStringList\x12\x0c\n\x04vals\x18\x01 \x03(\t\"\x19\n\tBytesList\x12\x0c\n\x04vals\x18\x01 \x03(\x0c\"B\n\x05\x41rray\x12\r\n\x05\x64type\x18\x01 \x01(\t\x12\r\n\x05shape\x18\x02 \x03(\x05\x12\r\n\x05stype\x18\x03 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c\"\x9f\x01\n\x12MetricsRecordValue\x12\x10\n\x06\x64ouble\x18\x01 \x01(\x01H\x00\x12\x10\n\x06sint64\x18\x02 \x01(\x12H\x00\x12-\n\x0b\x64ouble_list\x18\x15 \x01(\x0b\x32\x16.flwr.proto.DoubleListH\x00\x12-\n\x0bsint64_list\x18\x16 \x01(\x0b\x32\x16.flwr.proto.Sint64ListH\x00\x42\x07\n\x05value\"\xd9\x02\n\x12\x43onfigsRecordValue\x12\x10\n\x06\x64ouble\x18\x01 \x01(\x01H\x00\x12\x10\n\x06sint64\x18\x02 \x01(\x12H\x00\x12\x0e\n\x04\x62ool\x18\x03 \x01(\x08H\x00\x12\x10\n\x06string\x18\x04 \x01(\tH\x00\x12\x0f\n\x05\x62ytes\x18\x05 \x01(\x0cH\x00\x12-\n\x0b\x64ouble_list\x18\x15 \x01(\x0b\x32\x16.flwr.proto.DoubleListH\x00\x12-\n\x0bsint64_list\x18\x16 \x01(\x0b\x32\x16.flwr.proto.Sint64ListH\x00\x12)\n\tbool_list\x18\x17 \x01(\x0b\x32\x14.flwr.proto.BoolListH\x00\x12-\n\x0bstring_list\x18\x18 \x01(\x0b\x32\x16.flwr.proto.StringListH\x00\x12+\n\nbytes_list\x18\x19 \x01(\x0b\x32\x15.flwr.proto.BytesListH\x00\x42\x07\n\x05value\"M\n\x10ParametersRecord\x12\x11\n\tdata_keys\x18\x01 \x03(\t\x12&\n\x0b\x64\x61ta_values\x18\x02 \x03(\x0b\x32\x11.flwr.proto.Array\"\x8f\x01\n\rMetricsRecord\x12\x31\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32#.flwr.proto.MetricsRecord.DataEntry\x1aK\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.flwr.proto.MetricsRecordValue:\x02\x38\x01\"\x8f\x01\n\rConfigsRecord\x12\x31\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32#.flwr.proto.ConfigsRecord.DataEntry\x1aK\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.flwr.proto.ConfigsRecordValue:\x02\x38\x01\"\x97\x03\n\tRecordSet\x12\x39\n\nparameters\x18\x01 \x03(\x0b\x32%.flwr.proto.RecordSet.ParametersEntry\x12\x33\n\x07metrics\x18\x02 \x03(\x0b\x32\".flwr.proto.RecordSet.MetricsEntry\x12\x33\n\x07\x63onfigs\x18\x03 \x03(\x0b\x32\".flwr.proto.RecordSet.ConfigsEntry\x1aO\n\x0fParametersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12+\n\x05value\x18\x02 \x01(\x0b\x32\x1c.flwr.proto.ParametersRecord:\x02\x38\x01\x1aI\n\x0cMetricsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12(\n\x05value\x18\x02 \x01(\x0b\x32\x19.flwr.proto.MetricsRecord:\x02\x38\x01\x1aI\n\x0c\x43onfigsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12(\n\x05value\x18\x02 \x01(\x0b\x32\x19.flwr.proto.ConfigsRecord:\x02\x38\x01\x62\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -25,6 +25,12 @@ _globals['_METRICSRECORD_DATAENTRY']._serialized_options = b'8\001' _globals['_CONFIGSRECORD_DATAENTRY']._options = None _globals['_CONFIGSRECORD_DATAENTRY']._serialized_options = b'8\001' + _globals['_RECORDSET_PARAMETERSENTRY']._options = None + _globals['_RECORDSET_PARAMETERSENTRY']._serialized_options = b'8\001' + _globals['_RECORDSET_METRICSENTRY']._options = None + _globals['_RECORDSET_METRICSENTRY']._serialized_options = b'8\001' + _globals['_RECORDSET_CONFIGSENTRY']._options = None + _globals['_RECORDSET_CONFIGSENTRY']._serialized_options = b'8\001' _globals['_DOUBLELIST']._serialized_start=42 _globals['_DOUBLELIST']._serialized_end=68 _globals['_SINT64LIST']._serialized_start=70 @@ -51,4 +57,12 @@ _globals['_CONFIGSRECORD']._serialized_end=1126 _globals['_CONFIGSRECORD_DATAENTRY']._serialized_start=1051 _globals['_CONFIGSRECORD_DATAENTRY']._serialized_end=1126 + _globals['_RECORDSET']._serialized_start=1129 + _globals['_RECORDSET']._serialized_end=1536 + _globals['_RECORDSET_PARAMETERSENTRY']._serialized_start=1307 + _globals['_RECORDSET_PARAMETERSENTRY']._serialized_end=1386 + _globals['_RECORDSET_METRICSENTRY']._serialized_start=1388 + _globals['_RECORDSET_METRICSENTRY']._serialized_end=1461 + _globals['_RECORDSET_CONFIGSENTRY']._serialized_start=1463 + _globals['_RECORDSET_CONFIGSENTRY']._serialized_end=1536 # @@protoc_insertion_point(module_scope) diff --git a/src/py/flwr/proto/recordset_pb2.pyi b/src/py/flwr/proto/recordset_pb2.pyi index 1e9556de9ce6..86244697129c 100644 --- a/src/py/flwr/proto/recordset_pb2.pyi +++ b/src/py/flwr/proto/recordset_pb2.pyi @@ -238,3 +238,68 @@ class ConfigsRecord(google.protobuf.message.Message): ) -> None: ... def ClearField(self, field_name: typing_extensions.Literal["data",b"data"]) -> None: ... global___ConfigsRecord = ConfigsRecord + +class RecordSet(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + class ParametersEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: typing.Text + @property + def value(self) -> global___ParametersRecord: ... + def __init__(self, + *, + key: typing.Text = ..., + value: typing.Optional[global___ParametersRecord] = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["value",b"value"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["key",b"key","value",b"value"]) -> None: ... + + class MetricsEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: typing.Text + @property + def value(self) -> global___MetricsRecord: ... + def __init__(self, + *, + key: typing.Text = ..., + value: typing.Optional[global___MetricsRecord] = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["value",b"value"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["key",b"key","value",b"value"]) -> None: ... + + class ConfigsEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: typing.Text + @property + def value(self) -> global___ConfigsRecord: ... + def __init__(self, + *, + key: typing.Text = ..., + value: typing.Optional[global___ConfigsRecord] = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["value",b"value"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["key",b"key","value",b"value"]) -> None: ... + + PARAMETERS_FIELD_NUMBER: builtins.int + METRICS_FIELD_NUMBER: builtins.int + CONFIGS_FIELD_NUMBER: builtins.int + @property + def parameters(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, global___ParametersRecord]: ... + @property + def metrics(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, global___MetricsRecord]: ... + @property + def configs(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, global___ConfigsRecord]: ... + def __init__(self, + *, + parameters: typing.Optional[typing.Mapping[typing.Text, global___ParametersRecord]] = ..., + metrics: typing.Optional[typing.Mapping[typing.Text, global___MetricsRecord]] = ..., + configs: typing.Optional[typing.Mapping[typing.Text, global___ConfigsRecord]] = ..., + ) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["configs",b"configs","metrics",b"metrics","parameters",b"parameters"]) -> None: ... +global___RecordSet = RecordSet diff --git a/src/py/flwr/proto/task_pb2.py b/src/py/flwr/proto/task_pb2.py index 963b07db94f8..f9b2180b15dd 100644 --- a/src/py/flwr/proto/task_pb2.py +++ b/src/py/flwr/proto/task_pb2.py @@ -17,7 +17,7 @@ from flwr.proto import transport_pb2 as flwr_dot_proto_dot_transport__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/task.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x1a\x66lwr/proto/recordset.proto\x1a\x1a\x66lwr/proto/transport.proto\"\xd1\x02\n\x04Task\x12\"\n\x08producer\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\"\n\x08\x63onsumer\x18\x02 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x12\n\ncreated_at\x18\x03 \x01(\t\x12\x14\n\x0c\x64\x65livered_at\x18\x04 \x01(\t\x12\x0b\n\x03ttl\x18\x05 \x01(\t\x12\x10\n\x08\x61ncestry\x18\x06 \x03(\t\x12\x11\n\ttask_type\x18\x07 \x01(\t\x12)\n\x02sa\x18\x08 \x01(\x0b\x32\x1d.flwr.proto.SecureAggregation\x12<\n\x15legacy_server_message\x18\x65 \x01(\x0b\x32\x19.flwr.proto.ServerMessageB\x02\x18\x01\x12<\n\x15legacy_client_message\x18\x66 \x01(\x0b\x32\x19.flwr.proto.ClientMessageB\x02\x18\x01\"\\\n\x07TaskIns\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x12\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Task\"\\\n\x07TaskRes\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x12\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Task\"\xcc\x02\n\x05Value\x12\x10\n\x06\x64ouble\x18\x01 \x01(\x01H\x00\x12\x10\n\x06sint64\x18\x02 \x01(\x12H\x00\x12\x0e\n\x04\x62ool\x18\x03 \x01(\x08H\x00\x12\x10\n\x06string\x18\x04 \x01(\tH\x00\x12\x0f\n\x05\x62ytes\x18\x05 \x01(\x0cH\x00\x12-\n\x0b\x64ouble_list\x18\x15 \x01(\x0b\x32\x16.flwr.proto.DoubleListH\x00\x12-\n\x0bsint64_list\x18\x16 \x01(\x0b\x32\x16.flwr.proto.Sint64ListH\x00\x12)\n\tbool_list\x18\x17 \x01(\x0b\x32\x14.flwr.proto.BoolListH\x00\x12-\n\x0bstring_list\x18\x18 \x01(\x0b\x32\x16.flwr.proto.StringListH\x00\x12+\n\nbytes_list\x18\x19 \x01(\x0b\x32\x15.flwr.proto.BytesListH\x00\x42\x07\n\x05value\"\xa0\x01\n\x11SecureAggregation\x12\x44\n\x0cnamed_values\x18\x01 \x03(\x0b\x32..flwr.proto.SecureAggregation.NamedValuesEntry\x1a\x45\n\x10NamedValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12 \n\x05value\x18\x02 \x01(\x0b\x32\x11.flwr.proto.Value:\x02\x38\x01\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/task.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x1a\x66lwr/proto/recordset.proto\x1a\x1a\x66lwr/proto/transport.proto\"\xff\x02\n\x04Task\x12\"\n\x08producer\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\"\n\x08\x63onsumer\x18\x02 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x12\n\ncreated_at\x18\x03 \x01(\t\x12\x14\n\x0c\x64\x65livered_at\x18\x04 \x01(\t\x12\x0b\n\x03ttl\x18\x05 \x01(\t\x12\x10\n\x08\x61ncestry\x18\x06 \x03(\t\x12\x11\n\ttask_type\x18\x07 \x01(\t\x12(\n\trecordset\x18\x08 \x01(\x0b\x32\x15.flwr.proto.RecordSet\x12<\n\x15legacy_server_message\x18\x65 \x01(\x0b\x32\x19.flwr.proto.ServerMessageB\x02\x18\x01\x12<\n\x15legacy_client_message\x18\x66 \x01(\x0b\x32\x19.flwr.proto.ClientMessageB\x02\x18\x01\x12-\n\x02sa\x18g \x01(\x0b\x32\x1d.flwr.proto.SecureAggregationB\x02\x18\x01\"\\\n\x07TaskIns\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x12\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Task\"\\\n\x07TaskRes\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x12\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Task\"\xcc\x02\n\x05Value\x12\x10\n\x06\x64ouble\x18\x01 \x01(\x01H\x00\x12\x10\n\x06sint64\x18\x02 \x01(\x12H\x00\x12\x0e\n\x04\x62ool\x18\x03 \x01(\x08H\x00\x12\x10\n\x06string\x18\x04 \x01(\tH\x00\x12\x0f\n\x05\x62ytes\x18\x05 \x01(\x0cH\x00\x12-\n\x0b\x64ouble_list\x18\x15 \x01(\x0b\x32\x16.flwr.proto.DoubleListH\x00\x12-\n\x0bsint64_list\x18\x16 \x01(\x0b\x32\x16.flwr.proto.Sint64ListH\x00\x12)\n\tbool_list\x18\x17 \x01(\x0b\x32\x14.flwr.proto.BoolListH\x00\x12-\n\x0bstring_list\x18\x18 \x01(\x0b\x32\x16.flwr.proto.StringListH\x00\x12+\n\nbytes_list\x18\x19 \x01(\x0b\x32\x15.flwr.proto.BytesListH\x00\x42\x07\n\x05value\"\xa0\x01\n\x11SecureAggregation\x12\x44\n\x0cnamed_values\x18\x01 \x03(\x0b\x32..flwr.proto.SecureAggregation.NamedValuesEntry\x1a\x45\n\x10NamedValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12 \n\x05value\x18\x02 \x01(\x0b\x32\x11.flwr.proto.Value:\x02\x38\x01\x62\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -28,18 +28,20 @@ _globals['_TASK'].fields_by_name['legacy_server_message']._serialized_options = b'\030\001' _globals['_TASK'].fields_by_name['legacy_client_message']._options = None _globals['_TASK'].fields_by_name['legacy_client_message']._serialized_options = b'\030\001' + _globals['_TASK'].fields_by_name['sa']._options = None + _globals['_TASK'].fields_by_name['sa']._serialized_options = b'\030\001' _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._options = None _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_options = b'8\001' _globals['_TASK']._serialized_start=117 - _globals['_TASK']._serialized_end=454 - _globals['_TASKINS']._serialized_start=456 - _globals['_TASKINS']._serialized_end=548 - _globals['_TASKRES']._serialized_start=550 - _globals['_TASKRES']._serialized_end=642 - _globals['_VALUE']._serialized_start=645 - _globals['_VALUE']._serialized_end=977 - _globals['_SECUREAGGREGATION']._serialized_start=980 - _globals['_SECUREAGGREGATION']._serialized_end=1140 - _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_start=1071 - _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_end=1140 + _globals['_TASK']._serialized_end=500 + _globals['_TASKINS']._serialized_start=502 + _globals['_TASKINS']._serialized_end=594 + _globals['_TASKRES']._serialized_start=596 + _globals['_TASKRES']._serialized_end=688 + _globals['_VALUE']._serialized_start=691 + _globals['_VALUE']._serialized_end=1023 + _globals['_SECUREAGGREGATION']._serialized_start=1026 + _globals['_SECUREAGGREGATION']._serialized_end=1186 + _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_start=1117 + _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_end=1186 # @@protoc_insertion_point(module_scope) diff --git a/src/py/flwr/proto/task_pb2.pyi b/src/py/flwr/proto/task_pb2.pyi index ebe69d05c974..39119797c9e4 100644 --- a/src/py/flwr/proto/task_pb2.pyi +++ b/src/py/flwr/proto/task_pb2.pyi @@ -23,9 +23,10 @@ class Task(google.protobuf.message.Message): TTL_FIELD_NUMBER: builtins.int ANCESTRY_FIELD_NUMBER: builtins.int TASK_TYPE_FIELD_NUMBER: builtins.int - SA_FIELD_NUMBER: builtins.int + RECORDSET_FIELD_NUMBER: builtins.int LEGACY_SERVER_MESSAGE_FIELD_NUMBER: builtins.int LEGACY_CLIENT_MESSAGE_FIELD_NUMBER: builtins.int + SA_FIELD_NUMBER: builtins.int @property def producer(self) -> flwr.proto.node_pb2.Node: ... @property @@ -37,11 +38,13 @@ class Task(google.protobuf.message.Message): def ancestry(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[typing.Text]: ... task_type: typing.Text @property - def sa(self) -> global___SecureAggregation: ... + def recordset(self) -> flwr.proto.recordset_pb2.RecordSet: ... @property def legacy_server_message(self) -> flwr.proto.transport_pb2.ServerMessage: ... @property def legacy_client_message(self) -> flwr.proto.transport_pb2.ClientMessage: ... + @property + def sa(self) -> global___SecureAggregation: ... def __init__(self, *, producer: typing.Optional[flwr.proto.node_pb2.Node] = ..., @@ -51,12 +54,13 @@ class Task(google.protobuf.message.Message): ttl: typing.Text = ..., ancestry: typing.Optional[typing.Iterable[typing.Text]] = ..., task_type: typing.Text = ..., - sa: typing.Optional[global___SecureAggregation] = ..., + recordset: typing.Optional[flwr.proto.recordset_pb2.RecordSet] = ..., legacy_server_message: typing.Optional[flwr.proto.transport_pb2.ServerMessage] = ..., legacy_client_message: typing.Optional[flwr.proto.transport_pb2.ClientMessage] = ..., + sa: typing.Optional[global___SecureAggregation] = ..., ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["consumer",b"consumer","legacy_client_message",b"legacy_client_message","legacy_server_message",b"legacy_server_message","producer",b"producer","sa",b"sa"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["ancestry",b"ancestry","consumer",b"consumer","created_at",b"created_at","delivered_at",b"delivered_at","legacy_client_message",b"legacy_client_message","legacy_server_message",b"legacy_server_message","producer",b"producer","sa",b"sa","task_type",b"task_type","ttl",b"ttl"]) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["consumer",b"consumer","legacy_client_message",b"legacy_client_message","legacy_server_message",b"legacy_server_message","producer",b"producer","recordset",b"recordset","sa",b"sa"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["ancestry",b"ancestry","consumer",b"consumer","created_at",b"created_at","delivered_at",b"delivered_at","legacy_client_message",b"legacy_client_message","legacy_server_message",b"legacy_server_message","producer",b"producer","recordset",b"recordset","sa",b"sa","task_type",b"task_type","ttl",b"ttl"]) -> None: ... global___Task = Task class TaskIns(google.protobuf.message.Message): From 214d1c873487b3ad9d466eaa878dcfeda4d27d82 Mon Sep 17 00:00:00 2001 From: Javier Date: Tue, 23 Jan 2024 17:53:05 +0000 Subject: [PATCH 027/113] Convert `RecordSet` to/from legacy `*Ins/*Res` (#2828) --- src/py/flwr/common/recordset_compat.py | 401 ++++++++++++++++++++ src/py/flwr/common/recordset_compat_test.py | 234 ++++++++++++ src/py/flwr/common/recordset_test.py | 3 +- src/py/flwr/common/recordset_utils.py | 87 ----- 4 files changed, 636 insertions(+), 89 deletions(-) create mode 100644 src/py/flwr/common/recordset_compat.py create mode 100644 src/py/flwr/common/recordset_compat_test.py delete mode 100644 src/py/flwr/common/recordset_utils.py diff --git a/src/py/flwr/common/recordset_compat.py b/src/py/flwr/common/recordset_compat.py new file mode 100644 index 000000000000..c45f7fcd9fb8 --- /dev/null +++ b/src/py/flwr/common/recordset_compat.py @@ -0,0 +1,401 @@ +# Copyright 2024 Flower Labs GmbH. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""RecordSet utilities.""" + + +from typing import Dict, Mapping, OrderedDict, Tuple, Union, cast, get_args + +from .configsrecord import ConfigsRecord +from .metricsrecord import MetricsRecord +from .parametersrecord import Array, ParametersRecord +from .recordset import RecordSet +from .typing import ( + Code, + ConfigsRecordValues, + EvaluateIns, + EvaluateRes, + FitIns, + FitRes, + GetParametersIns, + GetParametersRes, + GetPropertiesIns, + GetPropertiesRes, + MetricsRecordValues, + Parameters, + Scalar, + Status, +) + + +def parametersrecord_to_parameters( + record: ParametersRecord, keep_input: bool = False +) -> Parameters: + """Convert ParameterRecord to legacy Parameters. + + Warning: Because `Arrays` in `ParametersRecord` encode more information of the + array-like or tensor-like data (e.g their datatype, shape) than `Parameters` it + might not be possible to reconstruct such data structures from `Parameters` objects + alone. Additional information or metadta must be provided from elsewhere. + + Parameters + ---------- + record : ParametersRecord + The record to be conveted into Parameters. + keep_input : bool (default: False) + A boolean indicating whether entries in the record should be deleted from the + input dictionary immediately after adding them to the record. + """ + parameters = Parameters(tensors=[], tensor_type="") + + for key in list(record.data.keys()): + parameters.tensors.append(record[key].data) + + if not parameters.tensor_type: + # Setting from first array in record. Recall the warning in the docstrings + # of this function. + parameters.tensor_type = record[key].stype + + if not keep_input: + del record.data[key] + + return parameters + + +def parameters_to_parametersrecord( + parameters: Parameters, keep_input: bool = False +) -> ParametersRecord: + """Convert legacy Parameters into a single ParametersRecord. + + Because there is no concept of names in the legacy Parameters, arbitrary keys will + be used when constructing the ParametersRecord. Similarly, the shape and data type + won't be recorded in the Array objects. + + Parameters + ---------- + parameters : Parameters + Parameters object to be represented as a ParametersRecord. + keep_input : bool (default: False) + A boolean indicating whether parameters should be deleted from the input + Parameters object (i.e. a list of serialized NumPy arrays) immediately after + adding them to the record. + """ + tensor_type = parameters.tensor_type + + p_record = ParametersRecord() + + num_arrays = len(parameters.tensors) + for idx in range(num_arrays): + if keep_input: + tensor = parameters.tensors[idx] + else: + tensor = parameters.tensors.pop(0) + p_record.set_parameters( + OrderedDict( + {str(idx): Array(data=tensor, dtype="", stype=tensor_type, shape=[])} + ) + ) + + return p_record + + +def _check_mapping_from_recordscalartype_to_scalar( + record_data: Mapping[str, Union[ConfigsRecordValues, MetricsRecordValues]] +) -> Dict[str, Scalar]: + """Check mapping `common.*RecordValues` into `common.Scalar` is possible.""" + for value in record_data.values(): + if not isinstance(value, get_args(Scalar)): + raise TypeError( + "There is not a 1:1 mapping between `common.Scalar` types and those " + "supported in `common.ConfigsRecordValues` or " + "`common.ConfigsRecordValues`. Consider casting your values to a type " + "supported by the `common.RecordSet` infrastructure. " + f"You used type: {type(value)}" + ) + return cast(Dict[str, Scalar], record_data) + + +def _recordset_to_fit_or_evaluate_ins_components( + recordset: RecordSet, + ins_str: str, + keep_input: bool, +) -> Tuple[Parameters, Dict[str, Scalar]]: + """Derive Fit/Evaluate Ins from a RecordSet.""" + # get Array and construct Parameters + parameters_record = recordset.get_parameters(f"{ins_str}.parameters") + + parameters = parametersrecord_to_parameters( + parameters_record, keep_input=keep_input + ) + + # get config dict + config_record = recordset.get_configs(f"{ins_str}.config") + + config_dict = _check_mapping_from_recordscalartype_to_scalar(config_record.data) + + return parameters, config_dict + + +def _fit_or_evaluate_ins_to_recordset( + ins: Union[FitIns, EvaluateIns], keep_input: bool +) -> RecordSet: + recordset = RecordSet() + + ins_str = "fitins" if isinstance(ins, FitIns) else "evaluateins" + recordset.set_parameters( + name=f"{ins_str}.parameters", + record=parameters_to_parametersrecord(ins.parameters, keep_input=keep_input), + ) + + recordset.set_configs( + name=f"{ins_str}.config", record=ConfigsRecord(ins.config) # type: ignore + ) + + return recordset + + +def _embed_status_into_recordset( + res_str: str, status: Status, recordset: RecordSet +) -> RecordSet: + status_dict: Dict[str, ConfigsRecordValues] = { + "code": int(status.code.value), + "message": status.message, + } + # we add it to a `ConfigsRecord`` because the `status.message`` is a string + # and `str` values aren't supported in `MetricsRecords` + recordset.set_configs(f"{res_str}.status", record=ConfigsRecord(status_dict)) + return recordset + + +def _extract_status_from_recordset(res_str: str, recordset: RecordSet) -> Status: + status = recordset.get_configs(f"{res_str}.status") + code = cast(int, status["code"]) + return Status(code=Code(code), message=str(status["message"])) + + +def recordset_to_fitins(recordset: RecordSet, keep_input: bool) -> FitIns: + """Derive FitIns from a RecordSet object.""" + parameters, config = _recordset_to_fit_or_evaluate_ins_components( + recordset, + ins_str="fitins", + keep_input=keep_input, + ) + + return FitIns(parameters=parameters, config=config) + + +def fitins_to_recordset(fitins: FitIns, keep_input: bool) -> RecordSet: + """Construct a RecordSet from a FitIns object.""" + return _fit_or_evaluate_ins_to_recordset(fitins, keep_input) + + +def recordset_to_fitres(recordset: RecordSet, keep_input: bool) -> FitRes: + """Derive FitRes from a RecordSet object.""" + ins_str = "fitres" + parameters = parametersrecord_to_parameters( + recordset.get_parameters(f"{ins_str}.parameters"), keep_input=keep_input + ) + + num_examples = cast( + int, recordset.get_metrics(f"{ins_str}.num_examples")["num_examples"] + ) + configs_record = recordset.get_configs(f"{ins_str}.metrics") + + metrics = _check_mapping_from_recordscalartype_to_scalar(configs_record.data) + status = _extract_status_from_recordset(ins_str, recordset) + + return FitRes( + status=status, parameters=parameters, num_examples=num_examples, metrics=metrics + ) + + +def fitres_to_recordset(fitres: FitRes, keep_input: bool) -> RecordSet: + """Construct a RecordSet from a FitRes object.""" + recordset = RecordSet() + + res_str = "fitres" + + recordset.set_configs( + name=f"{res_str}.metrics", record=ConfigsRecord(fitres.metrics) # type: ignore + ) + recordset.set_metrics( + name=f"{res_str}.num_examples", + record=MetricsRecord({"num_examples": fitres.num_examples}), + ) + recordset.set_parameters( + name=f"{res_str}.parameters", + record=parameters_to_parametersrecord(fitres.parameters, keep_input), + ) + + # status + recordset = _embed_status_into_recordset(res_str, fitres.status, recordset) + + return recordset + + +def recordset_to_evaluateins(recordset: RecordSet, keep_input: bool) -> EvaluateIns: + """Derive EvaluateIns from a RecordSet object.""" + parameters, config = _recordset_to_fit_or_evaluate_ins_components( + recordset, + ins_str="evaluateins", + keep_input=keep_input, + ) + + return EvaluateIns(parameters=parameters, config=config) + + +def evaluateins_to_recordset(evaluateins: EvaluateIns, keep_input: bool) -> RecordSet: + """Construct a RecordSet from a EvaluateIns object.""" + return _fit_or_evaluate_ins_to_recordset(evaluateins, keep_input) + + +def recordset_to_evaluateres(recordset: RecordSet) -> EvaluateRes: + """Derive EvaluateRes from a RecordSet object.""" + ins_str = "evaluateres" + + loss = cast(int, recordset.get_metrics(f"{ins_str}.loss")["loss"]) + + num_examples = cast( + int, recordset.get_metrics(f"{ins_str}.num_examples")["num_examples"] + ) + configs_record = recordset.get_configs(f"{ins_str}.metrics") + + metrics = _check_mapping_from_recordscalartype_to_scalar(configs_record.data) + status = _extract_status_from_recordset(ins_str, recordset) + + return EvaluateRes( + status=status, loss=loss, num_examples=num_examples, metrics=metrics + ) + + +def evaluateres_to_recordset(evaluateres: EvaluateRes) -> RecordSet: + """Construct a RecordSet from a EvaluateRes object.""" + recordset = RecordSet() + + res_str = "evaluateres" + # loss + recordset.set_metrics( + name=f"{res_str}.loss", + record=MetricsRecord({"loss": evaluateres.loss}), + ) + + # num_examples + recordset.set_metrics( + name=f"{res_str}.num_examples", + record=MetricsRecord({"num_examples": evaluateres.num_examples}), + ) + + # metrics + recordset.set_configs( + name=f"{res_str}.metrics", + record=ConfigsRecord(evaluateres.metrics), # type: ignore + ) + + # status + recordset = _embed_status_into_recordset( + f"{res_str}", evaluateres.status, recordset + ) + + return recordset + + +def recordset_to_getparametersins(recordset: RecordSet) -> GetParametersIns: + """Derive GetParametersIns from a RecordSet object.""" + config_record = recordset.get_configs("getparametersins.config") + + config_dict = _check_mapping_from_recordscalartype_to_scalar(config_record.data) + + return GetParametersIns(config=config_dict) + + +def getparametersins_to_recordset(getparameters_ins: GetParametersIns) -> RecordSet: + """Construct a RecordSet from a GetParametersIns object.""" + recordset = RecordSet() + + recordset.set_configs( + name="getparametersins.config", + record=ConfigsRecord(getparameters_ins.config), # type: ignore + ) + return recordset + + +def getparametersres_to_recordset(getparametersres: GetParametersRes) -> RecordSet: + """Construct a RecordSet from a GetParametersRes object.""" + recordset = RecordSet() + res_str = "getparametersres" + parameters_record = parameters_to_parametersrecord(getparametersres.parameters) + recordset.set_parameters(f"{res_str}.parameters", parameters_record) + + # status + recordset = _embed_status_into_recordset( + res_str, getparametersres.status, recordset + ) + + return recordset + + +def recordset_to_getparametersres(recordset: RecordSet) -> GetParametersRes: + """Derive GetParametersRes from a RecordSet object.""" + res_str = "getparametersres" + parameters = parametersrecord_to_parameters( + recordset.get_parameters(f"{res_str}.parameters") + ) + + status = _extract_status_from_recordset(res_str, recordset) + return GetParametersRes(status=status, parameters=parameters) + + +def recordset_to_getpropertiesins(recordset: RecordSet) -> GetPropertiesIns: + """Derive GetPropertiesIns from a RecordSet object.""" + config_record = recordset.get_configs("getpropertiesins.config") + config_dict = _check_mapping_from_recordscalartype_to_scalar(config_record.data) + + return GetPropertiesIns(config=config_dict) + + +def getpropertiesins_to_recordset(getpropertiesins: GetPropertiesIns) -> RecordSet: + """Construct a RecordSet from a GetPropertiesRes object.""" + recordset = RecordSet() + recordset.set_configs( + name="getpropertiesins.config", + record=ConfigsRecord(getpropertiesins.config), # type: ignore + ) + return recordset + + +def recordset_to_getpropertiesres(recordset: RecordSet) -> GetPropertiesRes: + """Derive GetPropertiesRes from a RecordSet object.""" + res_str = "getpropertiesres" + config_record = recordset.get_configs(f"{res_str}.properties") + properties = _check_mapping_from_recordscalartype_to_scalar(config_record.data) + + status = _extract_status_from_recordset(res_str, recordset=recordset) + + return GetPropertiesRes(status=status, properties=properties) + + +def getpropertiesres_to_recordset(getpropertiesres: GetPropertiesRes) -> RecordSet: + """Construct a RecordSet from a GetPropertiesRes object.""" + recordset = RecordSet() + res_str = "getpropertiesres" + recordset.set_configs( + name=f"{res_str}.properties", + record=ConfigsRecord(getpropertiesres.properties), # type: ignore + ) + # status + recordset = _embed_status_into_recordset( + res_str, getpropertiesres.status, recordset + ) + + return recordset diff --git a/src/py/flwr/common/recordset_compat_test.py b/src/py/flwr/common/recordset_compat_test.py new file mode 100644 index 000000000000..ad91cd3a42fc --- /dev/null +++ b/src/py/flwr/common/recordset_compat_test.py @@ -0,0 +1,234 @@ +# Copyright 2024 Flower Labs GmbH. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""RecordSet from legacy messages tests.""" + +from copy import deepcopy +from typing import Dict + +import numpy as np + +from .parameter import ndarrays_to_parameters +from .recordset_compat import ( + evaluateins_to_recordset, + evaluateres_to_recordset, + fitins_to_recordset, + fitres_to_recordset, + getparametersins_to_recordset, + getparametersres_to_recordset, + getpropertiesins_to_recordset, + getpropertiesres_to_recordset, + recordset_to_evaluateins, + recordset_to_evaluateres, + recordset_to_fitins, + recordset_to_fitres, + recordset_to_getparametersins, + recordset_to_getparametersres, + recordset_to_getpropertiesins, + recordset_to_getpropertiesres, +) +from .typing import ( + Code, + EvaluateIns, + EvaluateRes, + FitIns, + FitRes, + GetParametersIns, + GetParametersRes, + GetPropertiesIns, + GetPropertiesRes, + NDArrays, + Scalar, + Status, +) + + +def get_ndarrays() -> NDArrays: + """Return list of NumPy arrays.""" + arr1 = np.array([[1.0, 2.0], [3.0, 4], [5.0, 6.0]]) + arr2 = np.eye(2, 7, 3) + + return [arr1, arr2] + + +################################################## +# Testing conversion: *Ins --> RecordSet --> *Ins +# Testing conversion: *Res <-- RecordSet <-- *Res +################################################## + + +def _get_valid_fitins() -> FitIns: + arrays = get_ndarrays() + return FitIns(parameters=ndarrays_to_parameters(arrays), config={"a": 1.0, "b": 0}) + + +def _get_valid_fitres() -> FitRes: + """Returnn Valid parameters but potentially invalid config.""" + arrays = get_ndarrays() + metrics: Dict[str, Scalar] = {"a": 1.0, "b": 0} + return FitRes( + parameters=ndarrays_to_parameters(arrays), + num_examples=1, + status=Status(code=Code(0), message=""), + metrics=metrics, + ) + + +def _get_valid_evaluateins() -> EvaluateIns: + fit_ins = _get_valid_fitins() + return EvaluateIns(parameters=fit_ins.parameters, config=fit_ins.config) + + +def _get_valid_evaluateres() -> EvaluateRes: + """Return potentially invalid config.""" + metrics: Dict[str, Scalar] = {"a": 1.0, "b": 0} + return EvaluateRes( + num_examples=1, + loss=0.1, + status=Status(code=Code(0), message=""), + metrics=metrics, + ) + + +def _get_valid_getparametersins() -> GetParametersIns: + config_dict: Dict[str, Scalar] = { + "a": 1.0, + "b": 3, + "c": True, + } # valid since both Ins/Res communicate over ConfigsRecord + + return GetParametersIns(config_dict) + + +def _get_valid_getparametersres() -> GetParametersRes: + arrays = get_ndarrays() + return GetParametersRes( + status=Status(code=Code(0), message=""), + parameters=ndarrays_to_parameters(arrays), + ) + + +def _get_valid_getpropertiesins() -> GetPropertiesIns: + getparamsins = _get_valid_getparametersins() + return GetPropertiesIns(config=getparamsins.config) + + +def _get_valid_getpropertiesres() -> GetPropertiesRes: + config_dict: Dict[str, Scalar] = { + "a": 1.0, + "b": 3, + "c": True, + } # valid since both Ins/Res communicate over ConfigsRecord + + return GetPropertiesRes( + status=Status(code=Code(0), message=""), properties=config_dict + ) + + +def test_fitins_to_recordset_and_back() -> None: + """Test conversion FitIns --> RecordSet --> FitIns.""" + fitins = _get_valid_fitins() + + fitins_copy = deepcopy(fitins) + + recordset = fitins_to_recordset(fitins, keep_input=False) + + fitins_ = recordset_to_fitins(recordset, keep_input=False) + + assert fitins_copy == fitins_ + + +def test_fitres_to_recordset_and_back() -> None: + """Test conversion FitRes --> RecordSet --> FitRes.""" + fitres = _get_valid_fitres() + + fitres_copy = deepcopy(fitres) + + recordset = fitres_to_recordset(fitres, keep_input=False) + fitres_ = recordset_to_fitres(recordset, keep_input=False) + + assert fitres_copy == fitres_ + + +def test_evaluateins_to_recordset_and_back() -> None: + """Test conversion EvaluateIns --> RecordSet --> EvaluateIns.""" + evaluateins = _get_valid_evaluateins() + + evaluateins_copy = deepcopy(evaluateins) + + recordset = evaluateins_to_recordset(evaluateins, keep_input=False) + + evaluateins_ = recordset_to_evaluateins(recordset, keep_input=False) + + assert evaluateins_copy == evaluateins_ + + +def test_evaluateres_to_recordset_and_back() -> None: + """Test conversion EvaluateRes --> RecordSet --> EvaluateRes.""" + evaluateres = _get_valid_evaluateres() + + evaluateres_copy = deepcopy(evaluateres) + + recordset = evaluateres_to_recordset(evaluateres) + evaluateres_ = recordset_to_evaluateres(recordset) + + assert evaluateres_copy == evaluateres_ + + +def test_get_properties_ins_to_recordset_and_back() -> None: + """Test conversion GetPropertiesIns --> RecordSet --> GetPropertiesIns.""" + getproperties_ins = _get_valid_getpropertiesins() + + getproperties_ins_copy = deepcopy(getproperties_ins) + + recordset = getpropertiesins_to_recordset(getproperties_ins) + getproperties_ins_ = recordset_to_getpropertiesins(recordset) + + assert getproperties_ins_copy == getproperties_ins_ + + +def test_get_properties_res_to_recordset_and_back() -> None: + """Test conversion GetPropertiesRes --> RecordSet --> GetPropertiesRes.""" + getproperties_res = _get_valid_getpropertiesres() + + getproperties_res_copy = deepcopy(getproperties_res) + + recordset = getpropertiesres_to_recordset(getproperties_res) + getproperties_res_ = recordset_to_getpropertiesres(recordset) + + assert getproperties_res_copy == getproperties_res_ + + +def test_get_parameters_ins_to_recordset_and_back() -> None: + """Test conversion GetParametersIns --> RecordSet --> GetParametersIns.""" + getparameters_ins = _get_valid_getparametersins() + + getparameters_ins_copy = deepcopy(getparameters_ins) + + recordset = getparametersins_to_recordset(getparameters_ins) + getparameters_ins_ = recordset_to_getparametersins(recordset) + + assert getparameters_ins_copy == getparameters_ins_ + + +def test_get_parameters_res_to_recordset_and_back() -> None: + """Test conversion GetParametersRes --> RecordSet --> GetParametersRes.""" + getparameteres_res = _get_valid_getparametersres() + + getparameters_res_copy = deepcopy(getparameteres_res) + + recordset = getparametersres_to_recordset(getparameteres_res) + getparameteres_res_ = recordset_to_getparametersres(recordset) + + assert getparameters_res_copy == getparameteres_res_ diff --git a/src/py/flwr/common/recordset_test.py b/src/py/flwr/common/recordset_test.py index 83e1e4595f1d..e1825eaeef14 100644 --- a/src/py/flwr/common/recordset_test.py +++ b/src/py/flwr/common/recordset_test.py @@ -14,7 +14,6 @@ # ============================================================================== """RecordSet tests.""" - from typing import Callable, Dict, List, OrderedDict, Type, Union import numpy as np @@ -24,7 +23,7 @@ from .metricsrecord import MetricsRecord from .parameter import ndarrays_to_parameters, parameters_to_ndarrays from .parametersrecord import Array, ParametersRecord -from .recordset_utils import ( +from .recordset_compat import ( parameters_to_parametersrecord, parametersrecord_to_parameters, ) diff --git a/src/py/flwr/common/recordset_utils.py b/src/py/flwr/common/recordset_utils.py deleted file mode 100644 index c1e724fa2758..000000000000 --- a/src/py/flwr/common/recordset_utils.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright 2024 Flower Labs GmbH. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""RecordSet utilities.""" - - -from typing import OrderedDict - -from .parametersrecord import Array, ParametersRecord -from .typing import Parameters - - -def parametersrecord_to_parameters( - record: ParametersRecord, keep_input: bool = False -) -> Parameters: - """Convert ParameterRecord to legacy Parameters. - - Warning: Because `Arrays` in `ParametersRecord` encode more information of the - array-like or tensor-like data (e.g their datatype, shape) than `Parameters` it - might not be possible to reconstruct such data structures from `Parameters` objects - alone. Additional information or metadta must be provided from elsewhere. - - Parameters - ---------- - record : ParametersRecord - The record to be conveted into Parameters. - keep_input : bool (default: False) - A boolean indicating whether entries in the record should be deleted from the - input dictionary immediately after adding them to the record. - """ - parameters = Parameters(tensors=[], tensor_type="") - - for key in list(record.data.keys()): - parameters.tensors.append(record.data[key].data) - - if not keep_input: - del record.data[key] - - return parameters - - -def parameters_to_parametersrecord( - parameters: Parameters, keep_input: bool = False -) -> ParametersRecord: - """Convert legacy Parameters into a single ParametersRecord. - - Because there is no concept of names in the legacy Parameters, arbitrary keys will - be used when constructing the ParametersRecord. Similarly, the shape and data type - won't be recorded in the Array objects. - - Parameters - ---------- - parameters : Parameters - Parameters object to be represented as a ParametersRecord. - keep_input : bool (default: False) - A boolean indicating whether parameters should be deleted from the input - Parameters object (i.e. a list of serialized NumPy arrays) immediately after - adding them to the record. - """ - tensor_type = parameters.tensor_type - - p_record = ParametersRecord() - - num_arrays = len(parameters.tensors) - for idx in range(num_arrays): - if keep_input: - tensor = parameters.tensors[idx] - else: - tensor = parameters.tensors.pop(0) - p_record.set_parameters( - OrderedDict( - {str(idx): Array(data=tensor, dtype="", stype=tensor_type, shape=[])} - ) - ) - - return p_record From a96bc7f42d7824c2b88d8406b0e810eb73296130 Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Wed, 24 Jan 2024 12:07:30 +0100 Subject: [PATCH 028/113] Format advanced code examples (#2847) --- examples/advanced-pytorch/client.py | 2 +- examples/advanced-pytorch/server.py | 2 +- examples/advanced-pytorch/utils.py | 24 ++++++++++++++---------- examples/advanced-tensorflow/client.py | 2 +- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/examples/advanced-pytorch/client.py b/examples/advanced-pytorch/client.py index b22cbcd70465..9958d21136f3 100644 --- a/examples/advanced-pytorch/client.py +++ b/examples/advanced-pytorch/client.py @@ -110,7 +110,7 @@ def main() -> None: ) parser.add_argument( "--toy", - action='store_true', + action="store_true", help="Set to true to quicky run the client using only 10 datasamples. \ Useful for testing purposes. Default: False", ) diff --git a/examples/advanced-pytorch/server.py b/examples/advanced-pytorch/server.py index fda49b71a311..e596e0034164 100644 --- a/examples/advanced-pytorch/server.py +++ b/examples/advanced-pytorch/server.py @@ -76,7 +76,7 @@ def main(): parser = argparse.ArgumentParser(description="Flower") parser.add_argument( "--toy", - action='store_true', + action="store_true", help="Set to true to use only 10 datasamples for validation. \ Useful for testing purposes. Default: False", ) diff --git a/examples/advanced-pytorch/utils.py b/examples/advanced-pytorch/utils.py index 6512010b1f23..872928f0faa1 100644 --- a/examples/advanced-pytorch/utils.py +++ b/examples/advanced-pytorch/utils.py @@ -28,18 +28,21 @@ def load_centralized_data(): def apply_transforms(batch): """Apply transforms to the partition from FederatedDataset.""" - pytorch_transforms = Compose([ - Resize(256), - CenterCrop(224), - ToTensor(), - Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), - ]) + pytorch_transforms = Compose( + [ + Resize(256), + CenterCrop(224), + ToTensor(), + Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), + ] + ) batch["img"] = [pytorch_transforms(img) for img in batch["img"]] return batch -def train(net, trainloader, valloader, epochs, - device: torch.device = torch.device("cpu")): +def train( + net, trainloader, valloader, epochs, device: torch.device = torch.device("cpu") +): """Train the network on the training set.""" print("Starting training...") net.to(device) # move model to GPU if available @@ -71,8 +74,9 @@ def train(net, trainloader, valloader, epochs, return results -def test(net, testloader, steps: int = None, - device: torch.device = torch.device("cpu")): +def test( + net, testloader, steps: int = None, device: torch.device = torch.device("cpu") +): """Validate the network on the entire test set.""" print("Starting evalutation...") net.to(device) # move model to GPU if available diff --git a/examples/advanced-tensorflow/client.py b/examples/advanced-tensorflow/client.py index 033f20b1b027..f42c93784fc6 100644 --- a/examples/advanced-tensorflow/client.py +++ b/examples/advanced-tensorflow/client.py @@ -86,7 +86,7 @@ def main() -> None: ) parser.add_argument( "--toy", - action='store_true', + action="store_true", help="Set to true to quicky run the client using only 10 datasamples. " "Useful for testing purposes. Default: False", ) From 472f42a5d7d1b229d73b2d71f833aed10b0afdf5 Mon Sep 17 00:00:00 2001 From: Heng Pan <134433891+panh99@users.noreply.github.com> Date: Wed, 24 Jan 2024 13:27:53 +0000 Subject: [PATCH 029/113] Format main (#2848) Co-authored-by: Javier --- examples/quickstart-huggingface/client.py | 2 +- examples/vertical-fl/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/quickstart-huggingface/client.py b/examples/quickstart-huggingface/client.py index 5fa10b9ca0f2..85792df43e53 100644 --- a/examples/quickstart-huggingface/client.py +++ b/examples/quickstart-huggingface/client.py @@ -119,7 +119,7 @@ def evaluate(self, parameters, config): required=True, type=int, help="Partition of the dataset divided into 1,000 iid partitions created " - "artificially.", + "artificially.", ) node_id = parser.parse_args().node_id main(node_id) diff --git a/examples/vertical-fl/README.md b/examples/vertical-fl/README.md index d5ab0ab9c30d..78588180d3d6 100644 --- a/examples/vertical-fl/README.md +++ b/examples/vertical-fl/README.md @@ -295,7 +295,7 @@ class ServerModel(nn.Module): It comprises a single linear layer that accepts the concatenated outputs from all client models as its input. The number of inputs to this layer equals the -total number of outputs from the client models ( $3 \times 4 = 12$ ). After processing +total number of outputs from the client models (3 x 4 = 12). After processing these inputs, the linear layer's output is passed through a sigmoid activation function (`nn.Sigmoid()`), which maps the result to a `(0, 1)` range, providing a probability score indicative of the likelihood of survival. From 88f2e3e60b07f121e6cc86308782ae883667679b Mon Sep 17 00:00:00 2001 From: HelinLin <53761824+helin0815@users.noreply.github.com> Date: Wed, 24 Jan 2024 22:00:53 +0800 Subject: [PATCH 030/113] refactor: use alexnet to replace efficientnet (#2782) Co-authored-by: helin1 Co-authored-by: jafermarq --- examples/advanced-pytorch/README.md | 2 +- examples/advanced-pytorch/client.py | 36 ++++++++++++++-------- examples/advanced-pytorch/run.sh | 5 --- examples/advanced-pytorch/server.py | 17 +++++++++-- examples/advanced-pytorch/utils.py | 47 +++++++++-------------------- 5 files changed, 54 insertions(+), 53 deletions(-) diff --git a/examples/advanced-pytorch/README.md b/examples/advanced-pytorch/README.md index 2527e8e4a820..9101105b2618 100644 --- a/examples/advanced-pytorch/README.md +++ b/examples/advanced-pytorch/README.md @@ -68,4 +68,4 @@ but this can be changed by removing the `--toy` argument in the script. You can The `run.sh` script starts processes in the background so that you don't have to open eleven terminal windows. If you experiment with the code example and something goes wrong, simply using `CTRL + C` on Linux (or `CMD + C` on macOS) wouldn't normally kill all these processes, which is why the script ends with `trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT` and `wait`. This simply allows you to stop the experiment using `CTRL + C` (or `CMD + C`). If you change the script and anything goes wrong you can still use `killall python` (or `killall python3`) to kill all background processes (or a more specific command if you have other Python processes running that you don't want to kill). -You can also manually run `python3 server.py` and `python3 client.py --client-id ` for as many clients as you want but you have to make sure that each command is run in a different terminal window (or a different computer on the network). +You can also manually run `python3 server.py` and `python3 client.py --client-id ` for as many clients as you want but you have to make sure that each command is run in a different terminal window (or a different computer on the network). In addition, you can make your clients use either `EfficienNet` (default) or `AlexNet` (but all clients in the experiment should use the same). Switch between models using the `--model` flag when launching `client.py` and `server.py`. diff --git a/examples/advanced-pytorch/client.py b/examples/advanced-pytorch/client.py index 9958d21136f3..0eb457d68645 100644 --- a/examples/advanced-pytorch/client.py +++ b/examples/advanced-pytorch/client.py @@ -1,6 +1,5 @@ import utils from torch.utils.data import DataLoader -import torchvision.datasets import torch import flwr as fl import argparse @@ -17,26 +16,31 @@ def __init__( trainset: datasets.Dataset, testset: datasets.Dataset, device: torch.device, + model_str: str, validation_split: int = 0.1, ): self.device = device self.trainset = trainset self.testset = testset self.validation_split = validation_split + if model_str == "alexnet": + self.model = utils.load_alexnet(classes=10) + else: + self.model = utils.load_efficientnet(classes=10) def set_parameters(self, parameters): - """Loads a efficientnet model and replaces it parameters with the ones given.""" - model = utils.load_efficientnet(classes=10) - params_dict = zip(model.state_dict().keys(), parameters) + """Loads a alexnet or efficientnet model and replaces it parameters with the + ones given.""" + + params_dict = zip(self.model.state_dict().keys(), parameters) state_dict = OrderedDict({k: torch.tensor(v) for k, v in params_dict}) - model.load_state_dict(state_dict, strict=True) - return model + self.model.load_state_dict(state_dict, strict=True) def fit(self, parameters, config): """Train parameters on the locally held training set.""" # Update local model parameters - model = self.set_parameters(parameters) + self.set_parameters(parameters) # Get hyperparameters for this round batch_size: int = config["batch_size"] @@ -49,9 +53,9 @@ def fit(self, parameters, config): train_loader = DataLoader(trainset, batch_size=batch_size, shuffle=True) val_loader = DataLoader(valset, batch_size=batch_size) - results = utils.train(model, train_loader, val_loader, epochs, self.device) + results = utils.train(self.model, train_loader, val_loader, epochs, self.device) - parameters_prime = utils.get_model_params(model) + parameters_prime = utils.get_model_params(self.model) num_examples_train = len(trainset) return parameters_prime, num_examples_train, results @@ -59,7 +63,7 @@ def fit(self, parameters, config): def evaluate(self, parameters, config): """Evaluate parameters on the locally held test set.""" # Update local model parameters - model = self.set_parameters(parameters) + self.set_parameters(parameters) # Get config values steps: int = config["val_steps"] @@ -67,7 +71,7 @@ def evaluate(self, parameters, config): # Evaluate global model parameters on the local test data and return results testloader = DataLoader(self.testset, batch_size=16) - loss, accuracy = utils.test(model, testloader, steps, self.device) + loss, accuracy = utils.test(self.model, testloader, steps, self.device) return float(loss), len(self.testset), {"accuracy": float(accuracy)} @@ -121,6 +125,14 @@ def main() -> None: required=False, help="Set to true to use GPU. Default: False", ) + parser.add_argument( + "--model", + type=str, + default="efficientnet", + choices=["efficientnet", "alexnet"], + help="Use either Efficientnet or Alexnet models. \ + If you want to achieve differential privacy, please use the Alexnet model", + ) args = parser.parse_args() @@ -138,7 +150,7 @@ def main() -> None: trainset = trainset.select(range(10)) testset = testset.select(range(10)) # Start Flower client - client = CifarClient(trainset, testset, device) + client = CifarClient(trainset, testset, device, args.model) fl.client.start_numpy_client(server_address="127.0.0.1:8080", client=client) diff --git a/examples/advanced-pytorch/run.sh b/examples/advanced-pytorch/run.sh index 3367e1680535..c3d52491b987 100755 --- a/examples/advanced-pytorch/run.sh +++ b/examples/advanced-pytorch/run.sh @@ -2,11 +2,6 @@ set -e cd "$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"/ -# Download the EfficientNetB0 model -python -c "import torch; torch.hub.load( \ - 'NVIDIA/DeepLearningExamples:torchhub', \ - 'nvidia_efficientnet_b0', pretrained=True)" - python server.py --toy & sleep 10 # Sleep for 10s to give the server enough time to start and dowload the dataset diff --git a/examples/advanced-pytorch/server.py b/examples/advanced-pytorch/server.py index e596e0034164..489694ab1ea1 100644 --- a/examples/advanced-pytorch/server.py +++ b/examples/advanced-pytorch/server.py @@ -80,17 +80,28 @@ def main(): help="Set to true to use only 10 datasamples for validation. \ Useful for testing purposes. Default: False", ) + parser.add_argument( + "--model", + type=str, + default="efficientnet", + choices=["efficientnet", "alexnet"], + help="Use either Efficientnet or Alexnet models. \ + If you want to achieve differential privacy, please use the Alexnet model", + ) args = parser.parse_args() - model = utils.load_efficientnet(classes=10) + if args.model == "alexnet": + model = utils.load_alexnet(classes=10) + else: + model = utils.load_efficientnet(classes=10) model_parameters = [val.cpu().numpy() for _, val in model.state_dict().items()] # Create strategy strategy = fl.server.strategy.FedAvg( - fraction_fit=0.2, - fraction_evaluate=0.2, + fraction_fit=1.0, + fraction_evaluate=1.0, min_fit_clients=2, min_evaluate_clients=2, min_available_clients=10, diff --git a/examples/advanced-pytorch/utils.py b/examples/advanced-pytorch/utils.py index 872928f0faa1..186f079010dc 100644 --- a/examples/advanced-pytorch/utils.py +++ b/examples/advanced-pytorch/utils.py @@ -1,11 +1,11 @@ import torch from torchvision.transforms import Compose, ToTensor, Normalize, Resize, CenterCrop -from torch.utils.data import DataLoader - +from torchvision.models import efficientnet_b0, AlexNet import warnings from flwr_datasets import FederatedDataset + warnings.filterwarnings("ignore") @@ -48,7 +48,7 @@ def train( net.to(device) # move model to GPU if available criterion = torch.nn.CrossEntropyLoss().to(device) optimizer = torch.optim.SGD( - net.parameters(), lr=0.1, momentum=0.9, weight_decay=1e-4 + net.parameters(), lr=0.001, momentum=0.9, weight_decay=1e-4 ) net.train() for _ in range(epochs): @@ -98,38 +98,21 @@ def test( return loss, accuracy -def replace_classifying_layer(efficientnet_model, num_classes: int = 10): - """Replaces the final layer of the classifier.""" - num_features = efficientnet_model.classifier.fc.in_features - efficientnet_model.classifier.fc = torch.nn.Linear(num_features, num_classes) - - -def load_efficientnet(entrypoint: str = "nvidia_efficientnet_b0", classes: int = None): - """Loads pretrained efficientnet model from torch hub. Replaces final classifying - layer if classes is specified. - - Args: - entrypoint: EfficientNet model to download. - For supported entrypoints, please refer - https://pytorch.org/hub/nvidia_deeplearningexamples_efficientnet/ - classes: Number of classes in final classifying layer. Leave as None to get - the downloaded - model untouched. - Returns: - EfficientNet Model - - Note: One alternative implementation can be found at - https://github.com/lukemelas/EfficientNet-PyTorch - """ - efficientnet = torch.hub.load( - "NVIDIA/DeepLearningExamples:torchhub", entrypoint, pretrained=True - ) - - if classes is not None: - replace_classifying_layer(efficientnet, classes) +def load_efficientnet(classes: int = 10): + """Loads EfficienNetB0 from TorchVision.""" + efficientnet = efficientnet_b0(pretrained=True) + # Re-init output linear layer with the right number of classes + model_classes = efficientnet.classifier[1].in_features + if classes != model_classes: + efficientnet.classifier[1] = torch.nn.Linear(model_classes, classes) return efficientnet def get_model_params(model): """Returns a model's parameters.""" return [val.cpu().numpy() for _, val in model.state_dict().items()] + + +def load_alexnet(classes): + """Load AlexNet model from TorchVision.""" + return AlexNet(num_classes=classes) From 3b5df2a0a7ad3d03b6e78e107cd18510db9ed24d Mon Sep 17 00:00:00 2001 From: Javier Date: Thu, 25 Jan 2024 10:10:05 +0000 Subject: [PATCH 031/113] Split `FlowerContext` into `Message` and `Context` (#2851) --- src/py/flwr/common/context.py | 38 +++++++++++++++++++ .../common/{flowercontext.py => message.py} | 25 +++--------- 2 files changed, 44 insertions(+), 19 deletions(-) create mode 100644 src/py/flwr/common/context.py rename src/py/flwr/common/{flowercontext.py => message.py} (63%) diff --git a/src/py/flwr/common/context.py b/src/py/flwr/common/context.py new file mode 100644 index 000000000000..ad859d4c8407 --- /dev/null +++ b/src/py/flwr/common/context.py @@ -0,0 +1,38 @@ +# Copyright 2024 Flower Labs GmbH. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Context.""" + + +from dataclasses import dataclass + +from .recordset import RecordSet + + +@dataclass +class Context: + """State of your run. + + Parameters + ---------- + state : RecordSet + Holds records added by the entity in a given run and that will stay local. + This means that the data it holds will never leave the system it's running from. + This can be used as an intermediate storage or scratchpad when + executing middleware layers. It can also be used as a memory to access + at different points during the lifecycle of this entity (e.g. across + multiple rounds) + """ + + state: RecordSet diff --git a/src/py/flwr/common/flowercontext.py b/src/py/flwr/common/message.py similarity index 63% rename from src/py/flwr/common/flowercontext.py rename to src/py/flwr/common/message.py index 6e26d93bfe9a..f693d8e27bc3 100644 --- a/src/py/flwr/common/flowercontext.py +++ b/src/py/flwr/common/message.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""FlowerContext and Metadata.""" +"""Message.""" from dataclasses import dataclass @@ -48,30 +48,17 @@ class Metadata: @dataclass -class FlowerContext: +class Message: """State of your application from the viewpoint of the entity using it. Parameters ---------- - in_message : RecordSet - Holds records sent by another entity (e.g. sent by the server-side - logic to a client, or vice-versa) - out_message : RecordSet - Holds records added by the current entity. This `RecordSet` will - be sent out (e.g. back to the server-side for aggregation of - parameter, or to the client to perform a certain task) - local : RecordSet - Holds record added by the current entity and that will stay local. - This means that the data it holds will never leave the system it's running from. - This can be used as an intermediate storage or scratchpad when - executing middleware layers. It can also be used as a memory to access - at different points during the lifecycle of this entity (e.g. across - multiple rounds) metadata : Metadata A dataclass including information about the task to be executed. + message : RecordSet + Holds records either sent by another entity (e.g. sent by the server-side + logic to a client, or vice-versa) or that will be sent to it. """ - in_message: RecordSet - out_message: RecordSet - local: RecordSet metadata: Metadata + message: RecordSet From b02f263769655aec0e919f4683865a12bb1e7851 Mon Sep 17 00:00:00 2001 From: Javier Date: Thu, 25 Jan 2024 10:37:41 +0000 Subject: [PATCH 032/113] Make examples use `start_client()`. (#2718) --- examples/advanced-pytorch/client.py | 5 ++--- examples/advanced-tensorflow/client.py | 4 ++-- examples/custom-metrics/client.py | 2 +- examples/embedded-devices/client_pytorch.py | 4 ++-- examples/embedded-devices/client_tf.py | 4 ++-- examples/flower-in-30-minutes/tutorial.ipynb | 2 +- examples/mt-pytorch/client.py | 4 ++-- examples/opacus/dp_cifar_client.py | 4 ++-- examples/opacus/dp_cifar_simulation.py | 16 ++++++++-------- .../client.py | 2 +- .../client.py | 4 ++-- examples/quickstart-fastai/client.py | 4 ++-- examples/quickstart-huggingface/client.py | 2 +- examples/quickstart-jax/client.py | 2 +- examples/quickstart-mlcube/client.py | 4 ++-- examples/quickstart-pandas/client.py | 4 ++-- examples/quickstart-pytorch-lightning/client.py | 4 ++-- examples/quickstart-pytorch/client.py | 4 ++-- examples/quickstart-tabnet/client.py | 2 +- examples/quickstart-tensorflow/client.py | 2 +- examples/simulation-pytorch/sim.ipynb | 2 +- examples/simulation-pytorch/sim.py | 2 +- examples/simulation-tensorflow/sim.ipynb | 2 +- examples/simulation-tensorflow/sim.py | 2 +- examples/sklearn-logreg-mnist/client.py | 2 +- examples/whisper-federated-finetuning/client.py | 4 ++-- examples/xgboost-comprehensive/client.py | 2 +- examples/xgboost-quickstart/client.py | 2 +- 28 files changed, 48 insertions(+), 49 deletions(-) diff --git a/examples/advanced-pytorch/client.py b/examples/advanced-pytorch/client.py index 0eb457d68645..d4c8abe3d404 100644 --- a/examples/advanced-pytorch/client.py +++ b/examples/advanced-pytorch/client.py @@ -150,9 +150,8 @@ def main() -> None: trainset = trainset.select(range(10)) testset = testset.select(range(10)) # Start Flower client - client = CifarClient(trainset, testset, device, args.model) - - fl.client.start_numpy_client(server_address="127.0.0.1:8080", client=client) + client = CifarClient(trainset, testset, device, args.model).to_client() + fl.client.start_client(server_address="127.0.0.1:8080", client=client) if __name__ == "__main__": diff --git a/examples/advanced-tensorflow/client.py b/examples/advanced-tensorflow/client.py index f42c93784fc6..17d1d2306270 100644 --- a/examples/advanced-tensorflow/client.py +++ b/examples/advanced-tensorflow/client.py @@ -106,9 +106,9 @@ def main() -> None: x_test, y_test = x_test[:10], y_test[:10] # Start Flower client - client = CifarClient(model, x_train, y_train, x_test, y_test) + client = CifarClient(model, x_train, y_train, x_test, y_test).to_client() - fl.client.start_numpy_client( + fl.client.start_client( server_address="127.0.0.1:8080", client=client, root_certificates=Path(".cache/certificates/ca.crt").read_bytes(), diff --git a/examples/custom-metrics/client.py b/examples/custom-metrics/client.py index b2206118ed44..09e786a0cfac 100644 --- a/examples/custom-metrics/client.py +++ b/examples/custom-metrics/client.py @@ -68,4 +68,4 @@ def evaluate(self, parameters, config): # Start Flower client -fl.client.start_numpy_client(server_address="127.0.0.1:8080", client=FlowerClient()) +fl.client.start_client(server_address="127.0.0.1:8080", client=FlowerClient().to_client()) diff --git a/examples/embedded-devices/client_pytorch.py b/examples/embedded-devices/client_pytorch.py index 5d236c9e9389..8e72d668531a 100644 --- a/examples/embedded-devices/client_pytorch.py +++ b/examples/embedded-devices/client_pytorch.py @@ -204,11 +204,11 @@ def main(): trainsets, valsets, _ = prepare_dataset(use_mnist) # Start Flower client setting its associated data partition - fl.client.start_numpy_client( + fl.client.start_client( server_address=args.server_address, client=FlowerClient( trainset=trainsets[args.cid], valset=valsets[args.cid], use_mnist=use_mnist - ), + ).to_client(), ) diff --git a/examples/embedded-devices/client_tf.py b/examples/embedded-devices/client_tf.py index 3457af1c7a66..5ea34e44a98b 100644 --- a/examples/embedded-devices/client_tf.py +++ b/examples/embedded-devices/client_tf.py @@ -123,9 +123,9 @@ def main(): trainset, valset = partitions[args.cid] # Start Flower client setting its associated data partition - fl.client.start_numpy_client( + fl.client.start_client( server_address=args.server_address, - client=FlowerClient(trainset=trainset, valset=valset, use_mnist=use_mnist), + client=FlowerClient(trainset=trainset, valset=valset, use_mnist=use_mnist).to_client(), ) diff --git a/examples/flower-in-30-minutes/tutorial.ipynb b/examples/flower-in-30-minutes/tutorial.ipynb index 336ec4c19644..8f9eccf65b74 100644 --- a/examples/flower-in-30-minutes/tutorial.ipynb +++ b/examples/flower-in-30-minutes/tutorial.ipynb @@ -776,7 +776,7 @@ "\n", " return FlowerClient(\n", " trainloader=trainloaders[int(cid)], vallodaer=valloaders[int(cid)]\n", - " )\n", + " ).to_client()\n", "\n", " return client_fn\n", "\n", diff --git a/examples/mt-pytorch/client.py b/examples/mt-pytorch/client.py index 23cc736fd62b..295770a802bd 100644 --- a/examples/mt-pytorch/client.py +++ b/examples/mt-pytorch/client.py @@ -35,8 +35,8 @@ def evaluate(self, parameters, config): # Start Flower client -fl.client.start_numpy_client( +fl.client.start_client( server_address="0.0.0.0:9092", # "0.0.0.0:9093" for REST - client=FlowerClient(), + client=FlowerClient().to_client(), transport="grpc-rere", # "rest" for REST ) diff --git a/examples/opacus/dp_cifar_client.py b/examples/opacus/dp_cifar_client.py index bab1451ba707..cc30e7728222 100644 --- a/examples/opacus/dp_cifar_client.py +++ b/examples/opacus/dp_cifar_client.py @@ -28,7 +28,7 @@ def load_data(): model = Net() trainloader, testloader, sample_rate = load_data() -fl.client.start_numpy_client( +fl.client.start_client( server_address="127.0.0.1:8080", - client=DPCifarClient(model, trainloader, testloader), + client=DPCifarClient(model, trainloader, testloader).to_client(), ) diff --git a/examples/opacus/dp_cifar_simulation.py b/examples/opacus/dp_cifar_simulation.py index 14a9d037685b..d957caf8785c 100644 --- a/examples/opacus/dp_cifar_simulation.py +++ b/examples/opacus/dp_cifar_simulation.py @@ -1,14 +1,14 @@ import math from collections import OrderedDict -from typing import Callable, Optional, Tuple +from typing import Callable, Dict, Optional, Tuple import flwr as fl import numpy as np import torch import torchvision.transforms as transforms -from opacus.dp_model_inspector import DPModelInspector from torch.utils.data import DataLoader from torchvision.datasets import CIFAR10 +from flwr.common.typing import Scalar from dp_cifar_main import DEVICE, PARAMS, DPCifarClient, Net, test @@ -23,8 +23,6 @@ def client_fn(cid: str) -> fl.client.Client: # Load model. model = Net() # Check model is compatible with Opacus. - # inspector = DPModelInspector() - # print(f"Is the model valid? {inspector.validate(model)}") # Load data partition (divide CIFAR10 into NUM_CLIENTS distinct partitions, using 30% for validation). transform = transforms.Compose( @@ -45,12 +43,14 @@ def client_fn(cid: str) -> fl.client.Client: client_trainloader = DataLoader(client_trainset, PARAMS["batch_size"]) client_testloader = DataLoader(client_testset, PARAMS["batch_size"]) - return DPCifarClient(model, client_trainloader, client_testloader) + return DPCifarClient(model, client_trainloader, client_testloader).to_client() # Define an evaluation function for centralized evaluation (using whole CIFAR10 testset). def get_evaluate_fn() -> Callable[[fl.common.NDArrays], Optional[Tuple[float, float]]]: - def evaluate(weights: fl.common.NDArrays) -> Optional[Tuple[float, float]]: + def evaluate( + server_round: int, parameters: fl.common.NDArrays, config: Dict[str, Scalar] + ): transform = transforms.Compose( [ transforms.ToTensor(), @@ -63,7 +63,7 @@ def evaluate(weights: fl.common.NDArrays) -> Optional[Tuple[float, float]]: state_dict = OrderedDict( { k: torch.tensor(np.atleast_1d(v)) - for k, v in zip(model.state_dict().keys(), weights) + for k, v in zip(model.state_dict().keys(), parameters) } ) model.load_state_dict(state_dict, strict=True) @@ -82,7 +82,7 @@ def main() -> None: client_fn=client_fn, num_clients=NUM_CLIENTS, client_resources={"num_cpus": 1}, - num_rounds=3, + config=fl.server.ServerConfig(num_rounds=3), strategy=fl.server.strategy.FedAvg( fraction_fit=0.1, fraction_evaluate=0.1, evaluate_fn=get_evaluate_fn() ), diff --git a/examples/pytorch-federated-variational-autoencoder/client.py b/examples/pytorch-federated-variational-autoencoder/client.py index ceb55c79f564..65a86bcc2184 100644 --- a/examples/pytorch-federated-variational-autoencoder/client.py +++ b/examples/pytorch-federated-variational-autoencoder/client.py @@ -93,7 +93,7 @@ def evaluate(self, parameters, config): loss = test(net, testloader) return float(loss), len(testloader), {} - fl.client.start_numpy_client(server_address="127.0.0.1:8080", client=CifarClient()) + fl.client.start_client(server_address="127.0.0.1:8080", client=CifarClient().to_client()) if __name__ == "__main__": diff --git a/examples/pytorch-from-centralized-to-federated/client.py b/examples/pytorch-from-centralized-to-federated/client.py index 61c7e7f762b3..f89e03bc2053 100644 --- a/examples/pytorch-from-centralized-to-federated/client.py +++ b/examples/pytorch-from-centralized-to-federated/client.py @@ -93,8 +93,8 @@ def main() -> None: _ = model(next(iter(trainloader))["img"].to(DEVICE)) # Start client - client = CifarClient(model, trainloader, testloader) - fl.client.start_numpy_client(server_address="127.0.0.1:8080", client=client) + client = CifarClient(model, trainloader, testloader).to_client() + fl.client.start_client(server_address="127.0.0.1:8080", client=client) if __name__ == "__main__": diff --git a/examples/quickstart-fastai/client.py b/examples/quickstart-fastai/client.py index a88abbe525dc..6bb2a751d544 100644 --- a/examples/quickstart-fastai/client.py +++ b/examples/quickstart-fastai/client.py @@ -43,7 +43,7 @@ def evaluate(self, parameters, config): # Start Flower client -fl.client.start_numpy_client( +fl.client.start_client( server_address="127.0.0.1:8080", - client=FlowerClient(), + client=FlowerClient().to_client(), ) diff --git a/examples/quickstart-huggingface/client.py b/examples/quickstart-huggingface/client.py index 85792df43e53..0bfc81342972 100644 --- a/examples/quickstart-huggingface/client.py +++ b/examples/quickstart-huggingface/client.py @@ -108,7 +108,7 @@ def evaluate(self, parameters, config): return float(loss), len(testloader), {"accuracy": float(accuracy)} # Start client - fl.client.start_numpy_client(server_address="127.0.0.1:8080", client=IMDBClient()) + fl.client.start_client(server_address="127.0.0.1:8080", client=IMDBClient().to_client()) if __name__ == "__main__": diff --git a/examples/quickstart-jax/client.py b/examples/quickstart-jax/client.py index f9b056276deb..0cf74e2d2c05 100644 --- a/examples/quickstart-jax/client.py +++ b/examples/quickstart-jax/client.py @@ -52,4 +52,4 @@ def evaluate( # Start Flower client -fl.client.start_numpy_client(server_address="127.0.0.1:8080", client=FlowerClient()) +fl.client.start_client(server_address="127.0.0.1:8080", client=FlowerClient().to_client()) diff --git a/examples/quickstart-mlcube/client.py b/examples/quickstart-mlcube/client.py index 0a1962d8da8a..0470720bc296 100644 --- a/examples/quickstart-mlcube/client.py +++ b/examples/quickstart-mlcube/client.py @@ -43,8 +43,8 @@ def main(): os.path.dirname(os.path.abspath(__file__)), "workspaces", workspace_name ) - fl.client.start_numpy_client( - server_address="0.0.0.0:8080", client=MLCubeClient(workspace=workspace) + fl.client.start_client( + server_address="0.0.0.0:8080", client=MLCubeClient(workspace=workspace).to_client() ) diff --git a/examples/quickstart-pandas/client.py b/examples/quickstart-pandas/client.py index c2f2605594d5..8585922e4572 100644 --- a/examples/quickstart-pandas/client.py +++ b/examples/quickstart-pandas/client.py @@ -59,7 +59,7 @@ def fit( X = dataset[column_names] # Start Flower client - fl.client.start_numpy_client( + fl.client.start_client( server_address="127.0.0.1:8080", - client=FlowerClient(X), + client=FlowerClient(X).to_client(), ) diff --git a/examples/quickstart-pytorch-lightning/client.py b/examples/quickstart-pytorch-lightning/client.py index 1dabd5732b9b..fc5f1ee03cfe 100644 --- a/examples/quickstart-pytorch-lightning/client.py +++ b/examples/quickstart-pytorch-lightning/client.py @@ -72,8 +72,8 @@ def main() -> None: train_loader, val_loader, test_loader = mnist.load_data(node_id) # Flower client - client = FlowerClient(model, train_loader, val_loader, test_loader) - fl.client.start_numpy_client(server_address="127.0.0.1:8080", client=client) + client = FlowerClient(model, train_loader, val_loader, test_loader).to_client() + fl.client.start_client(server_address="127.0.0.1:8080", client=client) if __name__ == "__main__": diff --git a/examples/quickstart-pytorch/client.py b/examples/quickstart-pytorch/client.py index 1edb42d1ec81..b5ea4c94dd21 100644 --- a/examples/quickstart-pytorch/client.py +++ b/examples/quickstart-pytorch/client.py @@ -132,7 +132,7 @@ def evaluate(self, parameters, config): # Start Flower client -fl.client.start_numpy_client( +fl.client.start_client( server_address="127.0.0.1:8080", - client=FlowerClient(), + client=FlowerClient().to_client(), ) diff --git a/examples/quickstart-tabnet/client.py b/examples/quickstart-tabnet/client.py index da391a95710a..53913b2a2a09 100644 --- a/examples/quickstart-tabnet/client.py +++ b/examples/quickstart-tabnet/client.py @@ -79,4 +79,4 @@ def evaluate(self, parameters, config): # Start Flower client -fl.client.start_numpy_client(server_address="127.0.0.1:8080", client=TabNetClient()) +fl.client.start_client(server_address="127.0.0.1:8080", client=TabNetClient().to_client()) diff --git a/examples/quickstart-tensorflow/client.py b/examples/quickstart-tensorflow/client.py index d998adbdd899..43121f062c45 100644 --- a/examples/quickstart-tensorflow/client.py +++ b/examples/quickstart-tensorflow/client.py @@ -52,4 +52,4 @@ def evaluate(self, parameters, config): # Start Flower client -fl.client.start_numpy_client(server_address="127.0.0.1:8080", client=CifarClient()) +fl.client.start_client(server_address="127.0.0.1:8080", client=CifarClient().to_client()) diff --git a/examples/simulation-pytorch/sim.ipynb b/examples/simulation-pytorch/sim.ipynb index 508630cf9422..d1e7358566cc 100644 --- a/examples/simulation-pytorch/sim.ipynb +++ b/examples/simulation-pytorch/sim.ipynb @@ -509,7 +509,7 @@ " valloader = DataLoader(valset.with_transform(apply_transforms), batch_size=32)\n", "\n", " # Create and return client\n", - " return FlowerClient(trainloader, valloader)\n", + " return FlowerClient(trainloader, valloader).to_client()\n", "\n", " return client_fn\n", "\n", diff --git a/examples/simulation-pytorch/sim.py b/examples/simulation-pytorch/sim.py index 68d9426e83ab..0a6ed8ebb9b8 100644 --- a/examples/simulation-pytorch/sim.py +++ b/examples/simulation-pytorch/sim.py @@ -104,7 +104,7 @@ def client_fn(cid: str) -> fl.client.Client: valset = valset.with_transform(apply_transforms) # Create and return client - return FlowerClient(trainset, valset) + return FlowerClient(trainset, valset).to_client() return client_fn diff --git a/examples/simulation-tensorflow/sim.ipynb b/examples/simulation-tensorflow/sim.ipynb index 575b437018f3..5ef1992bcc7e 100644 --- a/examples/simulation-tensorflow/sim.ipynb +++ b/examples/simulation-tensorflow/sim.ipynb @@ -189,7 +189,7 @@ " )\n", "\n", " # Create and return client\n", - " return FlowerClient(trainset, valset)\n", + " return FlowerClient(trainset, valset).to_client()\n", "\n", " return client_fn\n", "\n", diff --git a/examples/simulation-tensorflow/sim.py b/examples/simulation-tensorflow/sim.py index 490e25fe8c8d..043c624a40a9 100644 --- a/examples/simulation-tensorflow/sim.py +++ b/examples/simulation-tensorflow/sim.py @@ -94,7 +94,7 @@ def client_fn(cid: str) -> fl.client.Client: ) # Create and return client - return FlowerClient(trainset, valset) + return FlowerClient(trainset, valset).to_client() return client_fn diff --git a/examples/sklearn-logreg-mnist/client.py b/examples/sklearn-logreg-mnist/client.py index a5fcaba87409..c5a312b41e61 100644 --- a/examples/sklearn-logreg-mnist/client.py +++ b/examples/sklearn-logreg-mnist/client.py @@ -62,4 +62,4 @@ def evaluate(self, parameters, config): # type: ignore return loss, len(X_test), {"accuracy": accuracy} # Start Flower client - fl.client.start_numpy_client(server_address="0.0.0.0:8080", client=MnistClient()) + fl.client.start_client(server_address="0.0.0.0:8080", client=MnistClient().to_client()) diff --git a/examples/whisper-federated-finetuning/client.py b/examples/whisper-federated-finetuning/client.py index 2bfeadfbdae6..07abc641f8fe 100644 --- a/examples/whisper-federated-finetuning/client.py +++ b/examples/whisper-federated-finetuning/client.py @@ -146,7 +146,7 @@ def client_fn(cid: str): return WhisperFlowerClient( full_train_dataset, num_classes, disable_tqdm, compile - ) + ).to_client() return client_fn @@ -174,7 +174,7 @@ def run_client(): client_data_path=CLIENT_DATA, ) - fl.client.start_numpy_client( + fl.client.start_client( server_address=f"{args.server_address}:8080", client=client_fn(args.cid) ) diff --git a/examples/xgboost-comprehensive/client.py b/examples/xgboost-comprehensive/client.py index ff7a4adf7977..0ffb48e1465e 100644 --- a/examples/xgboost-comprehensive/client.py +++ b/examples/xgboost-comprehensive/client.py @@ -171,4 +171,4 @@ def evaluate(self, ins: EvaluateIns) -> EvaluateRes: # Start Flower client -fl.client.start_client(server_address="127.0.0.1:8080", client=XgbClient()) +fl.client.start_client(server_address="127.0.0.1:8080", client=XgbClient().to_client()) diff --git a/examples/xgboost-quickstart/client.py b/examples/xgboost-quickstart/client.py index b5eab59ba14d..62e8a441bae1 100644 --- a/examples/xgboost-quickstart/client.py +++ b/examples/xgboost-quickstart/client.py @@ -173,4 +173,4 @@ def evaluate(self, ins: EvaluateIns) -> EvaluateRes: # Start Flower client -fl.client.start_client(server_address="127.0.0.1:8080", client=XgbClient()) +fl.client.start_client(server_address="127.0.0.1:8080", client=XgbClient().to_client()) From 944afcebf37f5983d35f26f83ee6266c88ccd6ac Mon Sep 17 00:00:00 2001 From: Nikos Vlachakis Date: Thu, 25 Jan 2024 18:05:27 +0200 Subject: [PATCH 033/113] Create new example flower-via-docker-compose (#2626) Co-authored-by: jafermarq --- README.md | 1 + examples/flower-via-docker-compose/.gitignore | 17 + examples/flower-via-docker-compose/Dockerfile | 19 + examples/flower-via-docker-compose/README.md | 254 ++++ examples/flower-via-docker-compose/client.py | 110 ++ .../config/grafana.ini | 12 + .../config/prometheus.yml | 19 + .../dashboards/dashboard_index.json | 1051 +++++++++++++++++ .../provisioning/dashboards/dashboards.yml | 12 + .../datasources/prometheus-datasource.yml | 9 + .../helpers/generate_docker_compose.py | 147 +++ .../helpers/load_data.py | 37 + .../flower-via-docker-compose/model/model.py | 18 + .../requirements.txt | 5 + examples/flower-via-docker-compose/server.py | 47 + .../strategy/strategy.py | 60 + 16 files changed, 1818 insertions(+) create mode 100644 examples/flower-via-docker-compose/.gitignore create mode 100644 examples/flower-via-docker-compose/Dockerfile create mode 100644 examples/flower-via-docker-compose/README.md create mode 100644 examples/flower-via-docker-compose/client.py create mode 100644 examples/flower-via-docker-compose/config/grafana.ini create mode 100644 examples/flower-via-docker-compose/config/prometheus.yml create mode 100644 examples/flower-via-docker-compose/config/provisioning/dashboards/dashboard_index.json create mode 100644 examples/flower-via-docker-compose/config/provisioning/dashboards/dashboards.yml create mode 100644 examples/flower-via-docker-compose/config/provisioning/datasources/prometheus-datasource.yml create mode 100644 examples/flower-via-docker-compose/helpers/generate_docker_compose.py create mode 100644 examples/flower-via-docker-compose/helpers/load_data.py create mode 100644 examples/flower-via-docker-compose/model/model.py create mode 100644 examples/flower-via-docker-compose/requirements.txt create mode 100644 examples/flower-via-docker-compose/server.py create mode 100644 examples/flower-via-docker-compose/strategy/strategy.py diff --git a/README.md b/README.md index 750b5cdb4b93..fe3295c4a22f 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,7 @@ Other [examples](https://github.com/adap/flower/tree/main/examples): - [Advanced Flower with TensorFlow/Keras](https://github.com/adap/flower/tree/main/examples/advanced-tensorflow) - [Advanced Flower with PyTorch](https://github.com/adap/flower/tree/main/examples/advanced-pytorch) - Single-Machine Simulation of Federated Learning Systems ([PyTorch](https://github.com/adap/flower/tree/main/examples/simulation_pytorch)) ([Tensorflow](https://github.com/adap/flower/tree/main/examples/simulation_tensorflow)) +- [Flower through Docker Compose and with Grafana dashboard](https://github.com/adap/flower/tree/main/examples/flower-via-docker-compose) ## Community diff --git a/examples/flower-via-docker-compose/.gitignore b/examples/flower-via-docker-compose/.gitignore new file mode 100644 index 000000000000..de5b2e7692bf --- /dev/null +++ b/examples/flower-via-docker-compose/.gitignore @@ -0,0 +1,17 @@ +# ignore __pycache__ directories +__pycache__/ + +# ignore .pyc files +*.pyc + +# ignore .vscode directory +.vscode/ + +# ignore .npz files +*.npz + +# ignore .csv files +*.csv + +# ignore docker-compose.yaml file +docker-compose.yml \ No newline at end of file diff --git a/examples/flower-via-docker-compose/Dockerfile b/examples/flower-via-docker-compose/Dockerfile new file mode 100644 index 000000000000..ee6fee3103a5 --- /dev/null +++ b/examples/flower-via-docker-compose/Dockerfile @@ -0,0 +1,19 @@ +# Use an official Python runtime as a parent image +FROM python:3.10-slim-buster + +# Set the working directory in the container to /app +WORKDIR /app + +# Copy the requirements file into the container +COPY ./requirements.txt /app/requirements.txt + +# Install gcc and other dependencies +RUN apt-get update && apt-get install -y \ + gcc \ + python3-dev && \ + rm -rf /var/lib/apt/lists/* + +# Install any needed packages specified in requirements.txt +RUN pip install -r requirements.txt + + diff --git a/examples/flower-via-docker-compose/README.md b/examples/flower-via-docker-compose/README.md new file mode 100644 index 000000000000..1d830e46cbdb --- /dev/null +++ b/examples/flower-via-docker-compose/README.md @@ -0,0 +1,254 @@ +# Leveraging Flower and Docker for Device Heterogeneity Management in Federated Learning + +

+ Flower Website + Docker Logo +

+ +## Introduction + +In this example, we tackle device heterogeneity in federated learning, arising from differences in memory and CPU capabilities across devices. This diversity affects training efficiency and inclusivity. Our strategy includes simulating this heterogeneity by setting CPU and memory limits in a Docker setup, using a custom Docker compose generator script. This approach creates a varied training environment and enables us to develop strategies to manage these disparities effectively. + +## Handling Device Heterogeneity + +1. **System Metrics Access**: + + - Effective management of device heterogeneity begins with monitoring system metrics of each container. We integrate the following services to achieve this: + - **Cadvisor**: Collects comprehensive metrics from each Docker container. + - **Prometheus**: Using `prometheus.yaml` for configuration, it scrapes data from Cadvisor at scheduled intervals, serving as a robust time-series database. Users can access the Prometheus UI at `http://localhost:9090` to create and run queries using PromQL, allowing for detailed insight into container performance. + +2. **Mitigating Heterogeneity**: + + - In this basic use case, we address device heterogeneity by establishing rules tailored to each container's system capabilities. This involves modifying training parameters, such as batch sizes and learning rates, based on each device's memory capacity and CPU availability. These settings are specified in the `client_configs` array in the `create_docker_compose` script. For example: + + ```python + client_configs = [ + {"mem_limit": "3g", "batch_size": 32, "cpus": 4, "learning_rate": 0.001}, + {"mem_limit": "6g", "batch_size": 256, "cpus": 1, "learning_rate": 0.05}, + {"mem_limit": "4g", "batch_size": 64, "cpus": 3, "learning_rate": 0.02}, + {"mem_limit": "5g", "batch_size": 128, "cpus": 2.5, "learning_rate": 0.09}, + ] + ``` + +## Prerequisites + +Docker must be installed and the Docker daemon running on your server. If you don't already have Docker installed, you can get [installation instructions for your specific Linux distribution or macOS from Docker](https://docs.docker.com/engine/install/). Besides Docker, the only extra requirement is having Python installed. You don't need to create a new environment for this example since all dependencies will be installed inside Docker containers automatically. + +## Running the Example + +Running this example is easy. For a more detailed step-by-step guide, including more useful material, refer to the detailed guide in the following section. + +```bash + +# Generate docker compose file +python helpers/generate_docker_compose.py # by default will configure to use 2 clients for 100 rounds + +# Build docker images +docker-compose build + +# Launch everything +docker-compose up +``` + +On your favourite browser, go to `http://localhost:3000` to see the Graphana dashboard showing system-level and application-level metrics. + +To stop all containers, open a new terminal and `cd` into this directory, then run `docker-compose down`. Alternatively, you can do `ctrl+c` on the same terminal and then run `docker-compose down` to ensure everything is terminated. + +## Running the Example (detailed) + +### Step 1: Configure Docker Compose + +Execute the following command to run the `helpers/generate_docker_compose.py` script. This script creates the docker-compose configuration needed to set up the environment. + +```bash +python helpers/generate_docker_compose.py +``` + +Within the script, specify the number of clients (`total_clients`) and resource limitations for each client in the `client_configs` array. You can adjust the number of rounds by passing `--num_rounds` to the above command. + +### Step 2: Build and Launch Containers + +1. **Execute Initialization Script**: + + - To build the Docker images and start the containers, use the following command: + + ```bash + # this is the only command you need to execute to run the entire example + docker-compose up + ``` + + - If you make any changes to the Dockerfile or other configuration files, you should rebuild the images to reflect these changes. This can be done by adding the `--build` flag to the command: + + ```bash + docker-compose up --build + ``` + + - The `--build` flag instructs Docker Compose to rebuild the images before starting the containers, ensuring that any code or configuration changes are included. + + - To stop all services, you have two options: + + - Run `docker-compose down` in another terminal if you are in the same directory. This command will stop and remove the containers, networks, and volumes created by `docker-compose up`. + - Press `Ctrl+C` once in the terminal where `docker-compose up` is running. This will stop the containers but won't remove them or the networks and volumes they use. + +2. **Services Startup**: + + - Several services will automatically launch as defined in your `docker-compose.yml` file: + + - **Monitoring Services**: Prometheus for metrics collection, Cadvisor for container monitoring, and Grafana for data visualization. + - **Flower Federated Learning Environment**: The Flower server and client containers are initialized and start running. + + - After launching the services, verify that all Docker containers are running correctly by executing the `docker ps` command. Here's an example output: + + ```bash + ➜ ~ docker ps + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES + 9f05820eba45 flower-via-docker-compose-client2 "python client.py --…" 50 seconds ago Up 48 seconds 0.0.0.0:6002->6002/tcp client2 + a0333715d504 flower-via-docker-compose-client1 "python client.py --…" 50 seconds ago Up 48 seconds 0.0.0.0:6001->6001/tcp client1 + 0da2bf735965 flower-via-docker-compose-server "python server.py --…" 50 seconds ago Up 48 seconds 0.0.0.0:6000->6000/tcp, 0.0.0.0:8000->8000/tcp, 0.0.0.0:8265->8265/tcp server + c57ef50657ae grafana/grafana:latest "/run.sh --config=/e…" 50 seconds ago Up 49 seconds 0.0.0.0:3000->3000/tcp grafana + 4f274c2083dc prom/prometheus:latest "/bin/prometheus --c…" 50 seconds ago Up 49 seconds 0.0.0.0:9090->9090/tcp prometheus + e9f4c9644a1c gcr.io/cadvisor/cadvisor:v0.47.0 "/usr/bin/cadvisor -…" 50 seconds ago Up 49 seconds 0.0.0.0:8080->8080/tcp cadvisor + ``` + + - To monitor the resource utilization of your containers in real-time and see the limits imposed in the Docker Compose file, you can use the `docker stats` command. This command provides a live stream of container CPU, memory, and network usage statistics. + + ```bash + ➜ ~ docker stats + CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS + 9f05820eba45 client2 104.44% 1.968GiB / 6GiB 32.80% 148MB / 3.22MB 0B / 284MB 82 + a0333715d504 client1 184.69% 1.498GiB / 3GiB 49.92% 149MB / 2.81MB 1.37MB / 284MB 82 + 0da2bf735965 server 0.12% 218.5MiB / 15.61GiB 1.37% 1.47MB / 2.89MB 2.56MB / 2.81MB 45 + c57ef50657ae grafana 0.24% 96.19MiB / 400MiB 24.05% 18.9kB / 3.79kB 77.8kB / 152kB 20 + 4f274c2083dc prometheus 1.14% 52.73MiB / 500MiB 10.55% 6.79MB / 211kB 1.02MB / 1.31MB 15 + e9f4c9644a1c cadvisor 7.31% 32.14MiB / 500MiB 6.43% 139kB / 6.66MB 500kB / 0B 18 + ``` + +3. **Automated Grafana Configuration**: + + - Grafana is configured to load pre-defined data sources and dashboards for immediate monitoring, facilitated by provisioning files. The provisioning files include `prometheus-datasource.yml` for data sources, located in the `./config/provisioning/datasources` directory, and `dashboard_index.json` for dashboards, in the `./config/provisioning/dashboards` directory. The `grafana.ini` file is also tailored to enhance user experience: + - **Admin Credentials**: We provide default admin credentials in the `grafana.ini` configuration, which simplifies access by eliminating the need for users to go through the initial login process. + - **Default Dashboard Path**: A default dashboard path is set in `grafana.ini` to ensure that the dashboard with all the necessary panels is rendered when Grafana is accessed. + + These files and settings are directly mounted into the Grafana container via Docker Compose volume mappings. This setup guarantees that upon startup, Grafana is pre-configured for monitoring, requiring no additional manual setup. + +4. **Begin Training Process**: + + - The federated learning training automatically begins once all client containers are successfully connected to the Flower server. This synchronizes the learning process across all participating clients. + +By following these steps, you will have a fully functional federated learning environment with device heterogeneity and monitoring capabilities. + +## Model Training and Dataset Integration + +### Data Pipeline with FLWR-Datasets + +We have integrated [`flwr-datasets`](https://flower.dev/docs/datasets/) into our data pipeline, which is managed within the `load_data.py` file in the `helpers/` directory. This script facilitates standardized access to datasets across the federated network and incorporates a `data_sampling_percentage` argument. This argument allows users to specify the percentage of the dataset to be used for training and evaluation, accommodating devices with lower memory capabilities to prevent Out-of-Memory (OOM) errors. + +### Model Selection and Dataset + +For the federated learning system, we have selected the MobileNet model due to its efficiency in image classification tasks. The model is trained and evaluated on the CIFAR-10 dataset. The combination of MobileNet and CIFAR-10 is ideal for demonstrating the capabilities of our federated learning solution in a heterogeneous device environment. + +- **MobileNet**: A streamlined architecture for mobile and embedded devices that balances performance and computational cost. +- **CIFAR-10 Dataset**: A standard benchmark dataset for image classification, containing various object classes that pose a comprehensive challenge for the learning model. + +By integrating these components, our framework is well-prepared to handle the intricacies of training over a distributed network with varying device capabilities and data availability. + +## Visualizing with Grafana + +### Access Grafana Dashboard + +Visit `http://localhost:3000` to enter Grafana. The automated setup ensures that you're greeted with a series of pre-configured dashboards, including the default screen with a comprehensive set of graphs. These dashboards are ready for immediate monitoring and can be customized to suit your specific requirements. + +### Dashboard Configuration + +The `dashboard_index.json` file, located in the `./config/provisioning/dashboards` directory, serves as the backbone of our Grafana dashboard's configuration. It defines the structure and settings of the dashboard panels, which are rendered when you access Grafana. This JSON file contains the specifications for various panels such as model accuracy, CPU usage, memory utilization, and network traffic. Each panel's configuration includes the data source, queries, visualization type, and other display settings like thresholds and colors. + +For instance, in our project setup, the `dashboard_index.json` configures a panel to display the model's accuracy over time using a time-series graph, and another panel to show the CPU usage across clients using a graph that plots data points as they are received. This file is fundamental for creating a customized and informative dashboard that provides a snapshot of the federated learning system's health and performance metrics. + +By modifying the `dashboard_index.json` file, users can tailor the Grafana dashboard to include additional metrics or change the appearance and behavior of existing panels to better fit their monitoring requirements. + +### Grafana Default Dashboard + +Below is the default Grafana dashboard that users will see upon accessing Grafana: + +grafana_home_screen + +This comprehensive dashboard provides insights into various system metrics across client-server containers. It includes visualizations such as: + +- **Application Metrics**: The "Model Accuracy" graph shows an upward trend as rounds of training progress, which is a positive indicator of the model learning and improving over time. Conversely, the "Model Loss" graph trends downward, suggesting that the model is becoming more precise and making fewer mistakes as it trains. + +- **CPU Usage**: The sharp spikes in the red graph, representing "client1", indicate peak CPU usage, which is considerably higher than that of "client2" (blue graph). This difference is due to "client1" being allocated more computing resources (up to 4 CPU cores) compared to "client2", which is limited to just 1 CPU core, hence the more subdued CPU usage pattern. + +- **Memory Utilization**: Both clients are allocated a similar amount of memory, reflected in the nearly same lines for memory usage. This uniform allocation allows for a straightforward comparison of how each client manages memory under similar conditions. + +- **Network Traffic**: Monitor incoming and outgoing network traffic to each client, which is crucial for understanding data exchange volumes during federated learning cycles. + +Together, these metrics paint a detailed picture of the federated learning operation, showcasing resource usage and model performance. Such insights are invaluable for system optimization, ensuring balanced load distribution and efficient model training. + +## Comprehensive Monitoring System Integration + +### Capturing Container Metrics with cAdvisor + +cAdvisor is seamlessly integrated into our monitoring setup to capture a variety of system and container metrics, such as CPU, memory, and network usage. These metrics are vital for analyzing the performance and resource consumption of the containers in the federated learning environment. + +### Custom Metrics: Setup and Monitoring via Prometheus + +In addition to the standard metrics captured by cAdvisor, we have implemented a process to track custom metrics like model's accuracy and loss within Grafana, using Prometheus as the backbone for metric collection. + +1. **Prometheus Client Installation**: + + - We began by installing the `prometheus_client` library in our Python environment, enabling us to define and expose custom metrics that Prometheus can scrape. + +2. **Defining Metrics in Server Script**: + + - Within our `server.py` script, we have established two key Prometheus Gauge metrics, specifically tailored for monitoring our federated learning model: `model_accuracy` and `model_loss`. These custom gauges are instrumental in capturing the most recent values of the model's accuracy and loss, which are essential metrics for evaluating the model's performance. The gauges are defined as follows: + + ```python + from prometheus_client import Gauge + + accuracy_gauge = Gauge('model_accuracy', 'Current accuracy of the global model') + loss_gauge = Gauge('model_loss', 'Current loss of the global model') + ``` + +3. **Exposing Metrics via HTTP Endpoint**: + + - We leveraged the `start_http_server` function from the `prometheus_client` library to launch an HTTP server on port 8000. This server provides the `/metrics` endpoint, where the custom metrics are accessible for Prometheus scraping. The function is called at the end of the `main` method in `server.py`: + + ```python + start_http_server(8000) + ``` + +4. **Updating Metrics Recording Strategy**: + + - The core of our metrics tracking lies in the `strategy.py` file, particularly within the `aggregate_evaluate` method. This method is crucial as it's where the federated learning model's accuracy and loss values are computed after each round of training with the aggregated data from all clients. + + ```python + self.accuracy_gauge.set(accuracy_aggregated) + self.loss_gauge.set(loss_aggregated) + ``` + +5. **Configuring Prometheus Scraping**: + + - In the `prometheus.yml` file, under `scrape_configs`, we configured a new job to scrape the custom metrics from the HTTP server. This setup includes the job's name, the scraping interval, and the target server's URL. + +### Visualizing the Monitoring Architecture + +The image below depicts the Prometheus scraping process as it is configured in our monitoring setup. Within this architecture: + +- The "Prometheus server" is the central component that retrieves and stores metrics. +- "cAdvisor" and the "HTTP server" we set up to expose our custom metrics are represented as "Prometheus targets" in the diagram. cAdvisor captures container metrics, while the HTTP server serves our custom `model_accuracy` and `model_loss` metrics at the `/metrics` endpoint. +- These targets are periodically scraped by the Prometheus server, aggregating data from both system-level and custom performance metrics. +- The aggregated data is then made available to the "Prometheus web UI" and "Grafana," as shown, enabling detailed visualization and analysis through the Grafana dashboard. + +prometheus-architecture + +By incorporating these steps, we have enriched our monitoring capabilities to not only include system-level metrics but also critical performance indicators of our federated learning model. This approach is pivotal for understanding and improving the learning process. Similarly, you can apply this methodology to track any other metric that you find interesting or relevant to your specific needs. This flexibility allows for a comprehensive and customized monitoring environment, tailored to the unique aspects and requirements of your federated learning system. + +## Additional Resources + +- **Grafana Tutorials**: Explore a variety of tutorials on Grafana at [Grafana Tutorials](https://grafana.com/tutorials/). +- **Prometheus Overview**: Learn more about Prometheus at their [official documentation](https://prometheus.io/docs/introduction/overview/). +- **cAdvisor Guide**: For information on monitoring Docker containers with cAdvisor, see this [Prometheus guide](https://prometheus.io/docs/guides/cadvisor/). + +## Conclusion + +This project serves as a foundational example of managing device heterogeneity within the federated learning context, employing the Flower framework alongside Docker, Prometheus, and Grafana. It's designed to be a starting point for users to explore and further adapt to the complexities of device heterogeneity in federated learning environments. diff --git a/examples/flower-via-docker-compose/client.py b/examples/flower-via-docker-compose/client.py new file mode 100644 index 000000000000..c894143532a1 --- /dev/null +++ b/examples/flower-via-docker-compose/client.py @@ -0,0 +1,110 @@ +import os +import argparse +import flwr as fl +import tensorflow as tf +import logging +from helpers.load_data import load_data +import os +from model.model import Model + +logging.basicConfig(level=logging.INFO) # Configure logging +logger = logging.getLogger(__name__) # Create logger for the module + +# Make TensorFlow log less verbose +os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3" + +# Parse command line arguments +parser = argparse.ArgumentParser(description="Flower client") + +parser.add_argument( + "--server_address", type=str, default="server:8080", help="Address of the server" +) +parser.add_argument( + "--batch_size", type=int, default=32, help="Batch size for training" +) +parser.add_argument( + "--learning_rate", type=float, default=0.1, help="Learning rate for the optimizer" +) +parser.add_argument("--client_id", type=int, default=1, help="Unique ID for the client") +parser.add_argument( + "--total_clients", type=int, default=2, help="Total number of clients" +) +parser.add_argument( + "--data_percentage", type=float, default=0.5, help="Portion of client data to use" +) + +args = parser.parse_args() + +# Create an instance of the model and pass the learning rate as an argument +model = Model(learning_rate=args.learning_rate) + +# Compile the model +model.compile() + + +class Client(fl.client.NumPyClient): + def __init__(self, args): + self.args = args + + logger.info("Preparing data...") + (x_train, y_train), (x_test, y_test) = load_data( + data_sampling_percentage=self.args.data_percentage, + client_id=self.args.client_id, + total_clients=self.args.total_clients, + ) + + self.x_train = x_train + self.y_train = y_train + self.x_test = x_test + self.y_test = y_test + + def get_parameters(self, config): + # Return the parameters of the model + return model.get_model().get_weights() + + def fit(self, parameters, config): + # Set the weights of the model + model.get_model().set_weights(parameters) + + # Train the model + history = model.get_model().fit( + self.x_train, self.y_train, batch_size=self.args.batch_size + ) + + # Calculate evaluation metric + results = { + "accuracy": float(history.history["accuracy"][-1]), + } + + # Get the parameters after training + parameters_prime = model.get_model().get_weights() + + # Directly return the parameters and the number of examples trained on + return parameters_prime, len(self.x_train), results + + def evaluate(self, parameters, config): + # Set the weights of the model + model.get_model().set_weights(parameters) + + # Evaluate the model and get the loss and accuracy + loss, accuracy = model.get_model().evaluate( + self.x_test, self.y_test, batch_size=self.args.batch_size + ) + + # Return the loss, the number of examples evaluated on and the accuracy + return float(loss), len(self.x_test), {"accuracy": float(accuracy)} + + +# Function to Start the Client +def start_fl_client(): + try: + client = Client(args).to_client() + fl.client.start_client(server_address=args.server_address, client=client) + except Exception as e: + logger.error("Error starting FL client: %s", e) + return {"status": "error", "message": str(e)} + + +if __name__ == "__main__": + # Call the function to start the client + start_fl_client() diff --git a/examples/flower-via-docker-compose/config/grafana.ini b/examples/flower-via-docker-compose/config/grafana.ini new file mode 100644 index 000000000000..775f39d7ec22 --- /dev/null +++ b/examples/flower-via-docker-compose/config/grafana.ini @@ -0,0 +1,12 @@ +[security] +allow_embedding = true +admin_user = admin +admin_password = admin + +[dashboards] +default_home_dashboard_path = /etc/grafana/provisioning/dashboards/dashboard_index.json + +[auth.anonymous] +enabled = true +org_name = Main Org. +org_role = Admin diff --git a/examples/flower-via-docker-compose/config/prometheus.yml b/examples/flower-via-docker-compose/config/prometheus.yml new file mode 100644 index 000000000000..46cf07b9dcee --- /dev/null +++ b/examples/flower-via-docker-compose/config/prometheus.yml @@ -0,0 +1,19 @@ + +global: + scrape_interval: 1s + evaluation_interval: 1s + +rule_files: +scrape_configs: + - job_name: 'cadvisor' + scrape_interval: 1s + metrics_path: '/metrics' + static_configs: + - targets: ['cadvisor:8080'] + labels: + group: 'cadvisor' + - job_name: 'server_metrics' + scrape_interval: 1s + metrics_path: '/metrics' + static_configs: + - targets: ['server:8000'] \ No newline at end of file diff --git a/examples/flower-via-docker-compose/config/provisioning/dashboards/dashboard_index.json b/examples/flower-via-docker-compose/config/provisioning/dashboards/dashboard_index.json new file mode 100644 index 000000000000..b52f19c57508 --- /dev/null +++ b/examples/flower-via-docker-compose/config/provisioning/dashboards/dashboard_index.json @@ -0,0 +1,1051 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Simple exporter for cadvisor only", + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 14282, + "graphTooltip": 0, + "id": 12, + "links": [], + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 22, + "title": "Application metrics", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "description": "Averaged federated accuracy across clients", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 23, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "model_accuracy", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Model Accuracy", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "description": "Averaged Federated Loss across clients", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 21, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "model_loss", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Model Loss", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 9 + }, + "id": 8, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "refId": "A" + } + ], + "title": "CPU", + "type": "row" + }, + { + "aliasColors": { + "client1": "red", + "client2": "blue", + "server": "yellow" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 10 + }, + "hiddenSeries": false, + "id": 15, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.2.2", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "editorMode": "code", + "expr": "sum(rate(container_cpu_usage_seconds_total{instance=~\"$host\",name=~\"$container\",name=~\".+\", name !~ \"(prometheus|cadvisor|grafana)\"}[10s])) by (name) *100", + "hide": false, + "interval": "", + "legendFormat": "{{name}}", + "range": true, + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "CPU Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:606", + "format": "percent", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:607", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 17 + }, + "id": 11, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "refId": "A" + } + ], + "title": "Memory", + "type": "row" + }, + { + "aliasColors": { + "client1": "red", + "client2": "blue", + "server": "yellow" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 18 + }, + "hiddenSeries": false, + "id": 9, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.2.2", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "editorMode": "code", + "expr": "sum(container_memory_rss{instance=~\"$host\",name=~\"$container\",name=~\".+\", name !~ \"(prometheus|cadvisor|grafana)\"}) by (name)", + "hide": false, + "interval": "", + "legendFormat": "{{name}}", + "range": true, + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Memory Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:606", + "format": "bytes", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:607", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": { + "client1": "red", + "client2": "blue", + "server": "yellow" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 18 + }, + "hiddenSeries": false, + "id": 14, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.2.2", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "editorMode": "code", + "expr": "sum(container_memory_cache{instance=~\"$host\",name=~\"$container\",name=~\".+\", name !~ \"(prometheus|cadvisor|grafana)\"}) by (name)", + "hide": false, + "interval": "", + "legendFormat": "{{name}}", + "range": true, + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Memory Cached", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:606", + "format": "bytes", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:607", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 26 + }, + "id": 2, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "refId": "A" + } + ], + "title": "Network", + "type": "row" + }, + { + "aliasColors": { + "client1": "red", + "client2": "blue", + "server": "yellow" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 27 + }, + "hiddenSeries": false, + "id": 4, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.2.2", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "editorMode": "code", + "expr": "sum(rate(container_network_receive_bytes_total{instance=~\"$host\",name=~\"$container\",name=~\".+\", name !~ \"(prometheus|cadvisor|grafana)\"}[10s])) by (name)", + "hide": false, + "interval": "", + "legendFormat": "{{name}}", + "range": true, + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Received Network Traffic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:674", + "format": "Bps", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:675", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": { + "client1": "red", + "client2": "blue", + "server": "yellow" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 27 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.2.2", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "editorMode": "code", + "expr": "sum(rate(container_network_transmit_bytes_total{instance=~\"$host\",name=~\"$container\",name=~\".+\", name !~ \"(prometheus|cadvisor|grafana)\"}[10s])) by (name)", + "interval": "", + "legendFormat": "{{name}}", + "range": true, + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Sent Network Traffic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:832", + "format": "Bps", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:833", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 35 + }, + "id": 19, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "refId": "A" + } + ], + "title": "Misc", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "fieldConfig": { + "defaults": { + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "filterable": false, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "id" + }, + "properties": [ + { + "id": "custom.width", + "value": 260 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Running" + }, + "properties": [ + { + "id": "unit", + "value": "d" + }, + { + "id": "decimals", + "value": 1 + }, + { + "id": "custom.cellOptions", + "value": { + "type": "color-text" + } + }, + { + "id": "color", + "value": { + "fixedColor": "dark-green", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 36 + }, + "id": 17, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "10.2.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "expr": "(time() - container_start_time_seconds{instance=~\"$host\",name=~\"$container\",name=~\".+\"})/86400", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "{{name}}", + "refId": "A" + } + ], + "title": "Containers Info", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "container_label_com_docker_compose_project", + "container_label_com_docker_compose_project_working_dir", + "image", + "instance", + "name", + "Value", + "container_label_com_docker_compose_service" + ] + } + } + }, + { + "id": "organize", + "options": { + "excludeByName": {}, + "indexByName": {}, + "renameByName": { + "Value": "Running", + "container_label_com_docker_compose_project": "Label", + "container_label_com_docker_compose_project_working_dir": "Working dir", + "container_label_com_docker_compose_service": "Service", + "image": "Registry Image", + "instance": "Instance", + "name": "Name" + } + } + } + ], + "type": "table" + } + ], + "refresh": "auto", + "schemaVersion": 38, + "tags": [], + "templating": { + "list": [ + { + "allValue": ".*", + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "definition": "label_values({__name__=~\"container.*\"},instance)", + "hide": 0, + "includeAll": true, + "label": "Host", + "multi": false, + "name": "host", + "options": [], + "query": { + "query": "label_values({__name__=~\"container.*\"},instance)", + "refId": "Prometheus-host-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 5, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "prometheus", + "uid": "db69454e-e558-479e-b4fc-80db52bf91da" + }, + "definition": "label_values({__name__=~\"container.*\", instance=~\"$host\"},name)", + "hide": 0, + "includeAll": true, + "label": "Container", + "multi": false, + "name": "container", + "options": [], + "query": { + "query": "label_values({__name__=~\"container.*\", instance=~\"$host\"},name)", + "refId": "Prometheus-container-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Cadvisor exporter Copy", + "uid": "fcf2a8da-792c-4b9f-a22f-876820b53c2f", + "version": 2, + "weekStart": "" +} \ No newline at end of file diff --git a/examples/flower-via-docker-compose/config/provisioning/dashboards/dashboards.yml b/examples/flower-via-docker-compose/config/provisioning/dashboards/dashboards.yml new file mode 100644 index 000000000000..e0d542f58f2b --- /dev/null +++ b/examples/flower-via-docker-compose/config/provisioning/dashboards/dashboards.yml @@ -0,0 +1,12 @@ +apiVersion: 1 + +providers: +- name: 'default' + orgId: 1 + folder: '' + type: file + disableDeletion: false + editable: true + updateIntervalSeconds: 5 # Optional: How often Grafana will scan for changed dashboards + options: + path: /etc/grafana/provisioning/dashboards diff --git a/examples/flower-via-docker-compose/config/provisioning/datasources/prometheus-datasource.yml b/examples/flower-via-docker-compose/config/provisioning/datasources/prometheus-datasource.yml new file mode 100644 index 000000000000..7c8ce00fdcdc --- /dev/null +++ b/examples/flower-via-docker-compose/config/provisioning/datasources/prometheus-datasource.yml @@ -0,0 +1,9 @@ +apiVersion: 1 + +datasources: +- name: Prometheus + type: prometheus + access: proxy + uid: db69454e-e558-479e-b4fc-80db52bf91da + url: http://host.docker.internal:9090 + isDefault: true diff --git a/examples/flower-via-docker-compose/helpers/generate_docker_compose.py b/examples/flower-via-docker-compose/helpers/generate_docker_compose.py new file mode 100644 index 000000000000..cde553a95e68 --- /dev/null +++ b/examples/flower-via-docker-compose/helpers/generate_docker_compose.py @@ -0,0 +1,147 @@ +import random +import argparse + +parser = argparse.ArgumentParser(description="Generated Docker Compose") +parser.add_argument( + "--total_clients", type=int, default=2, help="Total clients to spawn (default: 2)" +) +parser.add_argument( + "--num_rounds", type=int, default=100, help="Number of FL rounds (default: 100)" +) +parser.add_argument( + "--data_percentage", + type=float, + default=0.6, + help="Portion of client data to use (default: 0.6)", +) +parser.add_argument( + "--random", action="store_true", help="Randomize client configurations" +) + + +def create_docker_compose(args): + # cpus is used to set the number of CPUs available to the container as a fraction of the total number of CPUs on the host machine. + # mem_limit is used to set the memory limit for the container. + client_configs = [ + {"mem_limit": "3g", "batch_size": 32, "cpus": 4, "learning_rate": 0.001}, + {"mem_limit": "6g", "batch_size": 256, "cpus": 1, "learning_rate": 0.05}, + {"mem_limit": "4g", "batch_size": 64, "cpus": 3, "learning_rate": 0.02}, + {"mem_limit": "5g", "batch_size": 128, "cpus": 2.5, "learning_rate": 0.09}, + # Add or modify the configurations depending on your host machine + ] + + docker_compose_content = f""" +version: '3' +services: + prometheus: + image: prom/prometheus:latest + container_name: prometheus + ports: + - 9090:9090 + deploy: + restart_policy: + condition: on-failure + command: + - --config.file=/etc/prometheus/prometheus.yml + volumes: + - ./config/prometheus.yml:/etc/prometheus/prometheus.yml:ro + depends_on: + - cadvisor + + cadvisor: + image: gcr.io/cadvisor/cadvisor:v0.47.0 + container_name: cadvisor + privileged: true + deploy: + restart_policy: + condition: on-failure + ports: + - "8080:8080" + volumes: + - /:/rootfs:ro + - /var/run:/var/run:ro + - /sys:/sys:ro + - /var/lib/docker/:/var/lib/docker:ro + - /dev/disk/:/dev/disk:ro + - /var/run/docker.sock:/var/run/docker.sock + + grafana: + image: grafana/grafana:latest + container_name: grafana + ports: + - 3000:3000 + deploy: + restart_policy: + condition: on-failure + volumes: + - grafana-storage:/var/lib/grafana + - ./config/grafana.ini:/etc/grafana/grafana.ini + - ./config/provisioning/datasources:/etc/grafana/provisioning/datasources + - ./config/provisioning/dashboards:/etc/grafana/provisioning/dashboards + depends_on: + - prometheus + - cadvisor + command: + - --config=/etc/grafana/grafana.ini + + + server: + container_name: server + build: + context: . + dockerfile: Dockerfile + command: python server.py --number_of_rounds={args.num_rounds} + environment: + FLASK_RUN_PORT: 6000 + DOCKER_HOST_IP: host.docker.internal + volumes: + - .:/app + - /var/run/docker.sock:/var/run/docker.sock + ports: + - "6000:6000" + - "8265:8265" + - "8000:8000" + depends_on: + - prometheus + - grafana +""" + # Add client services + for i in range(1, args.total_clients + 1): + if args.random: + config = random.choice(client_configs) + else: + config = client_configs[(i - 1) % len(client_configs)] + docker_compose_content += f""" + client{i}: + container_name: client{i} + build: + context: . + dockerfile: Dockerfile + command: python client.py --server_address=server:8080 --data_percentage={args.data_percentage} --client_id={i} --total_clients={args.total_clients} --batch_size={config["batch_size"]} --learning_rate={config["learning_rate"]} + deploy: + resources: + limits: + cpus: "{(config['cpus'])}" + memory: "{config['mem_limit']}" + volumes: + - .:/app + - /var/run/docker.sock:/var/run/docker.sock + ports: + - "{6000 + i}:{6000 + i}" + depends_on: + - server + environment: + FLASK_RUN_PORT: {6000 + i} + container_name: client{i} + DOCKER_HOST_IP: host.docker.internal +""" + + docker_compose_content += "volumes:\n grafana-storage:\n" + + with open("docker-compose.yml", "w") as file: + file.write(docker_compose_content) + + +if __name__ == "__main__": + args = parser.parse_args() + create_docker_compose(args) diff --git a/examples/flower-via-docker-compose/helpers/load_data.py b/examples/flower-via-docker-compose/helpers/load_data.py new file mode 100644 index 000000000000..1f2784946868 --- /dev/null +++ b/examples/flower-via-docker-compose/helpers/load_data.py @@ -0,0 +1,37 @@ +import numpy as np +import tensorflow as tf +from flwr_datasets import FederatedDataset +import logging + +logging.basicConfig(level=logging.INFO) # Configure logging +logger = logging.getLogger(__name__) # Create logger for the module + + +def load_data(data_sampling_percentage=0.5, client_id=1, total_clients=2): + """Load federated dataset partition based on client ID. + + Args: + data_sampling_percentage (float): Percentage of the dataset to use for training. + client_id (int): Unique ID for the client. + total_clients (int): Total number of clients. + + Returns: + Tuple of arrays: `(x_train, y_train), (x_test, y_test)`. + """ + + # Download and partition dataset + fds = FederatedDataset(dataset="cifar10", partitioners={"train": total_clients}) + partition = fds.load_partition(client_id - 1, "train") + partition.set_format("numpy") + + # Divide data on each client: 80% train, 20% test + partition = partition.train_test_split(test_size=0.2) + x_train, y_train = partition["train"]["img"] / 255.0, partition["train"]["label"] + x_test, y_test = partition["test"]["img"] / 255.0, partition["test"]["label"] + + # Apply data sampling + num_samples = int(data_sampling_percentage * len(x_train)) + indices = np.random.choice(len(x_train), num_samples, replace=False) + x_train, y_train = x_train[indices], y_train[indices] + + return (x_train, y_train), (x_test, y_test) diff --git a/examples/flower-via-docker-compose/model/model.py b/examples/flower-via-docker-compose/model/model.py new file mode 100644 index 000000000000..ab26d089b858 --- /dev/null +++ b/examples/flower-via-docker-compose/model/model.py @@ -0,0 +1,18 @@ +import tensorflow as tf + + +# Class for the model. In this case, we are using the MobileNetV2 model from Keras +class Model: + def __init__(self, learning_rate): + self.learning_rate = learning_rate + self.loss_function = tf.keras.losses.SparseCategoricalCrossentropy() + self.model = tf.keras.applications.MobileNetV2( + (32, 32, 3), alpha=0.1, classes=10, weights=None + ) + self.optimizer = tf.keras.optimizers.Adam(learning_rate=self.learning_rate) + + def compile(self): + self.model.compile(self.optimizer, self.loss_function, metrics=["accuracy"]) + + def get_model(self): + return self.model diff --git a/examples/flower-via-docker-compose/requirements.txt b/examples/flower-via-docker-compose/requirements.txt new file mode 100644 index 000000000000..2a85546d0e18 --- /dev/null +++ b/examples/flower-via-docker-compose/requirements.txt @@ -0,0 +1,5 @@ +flwr==1.6.0 +tensorflow==2.13.1 +numpy==1.24.3 +prometheus_client == 0.19.0 +flwr_datasets[vision] == 0.0.2 \ No newline at end of file diff --git a/examples/flower-via-docker-compose/server.py b/examples/flower-via-docker-compose/server.py new file mode 100644 index 000000000000..99d1a7ef7399 --- /dev/null +++ b/examples/flower-via-docker-compose/server.py @@ -0,0 +1,47 @@ +import argparse +import flwr as fl +import logging +from strategy.strategy import FedCustom +from prometheus_client import start_http_server, Gauge + +# Initialize Logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +# Define a gauge to track the global model accuracy +accuracy_gauge = Gauge("model_accuracy", "Current accuracy of the global model") + +# Define a gauge to track the global model loss +loss_gauge = Gauge("model_loss", "Current loss of the global model") + +# Parse command line arguments +parser = argparse.ArgumentParser(description="Flower Server") +parser.add_argument( + "--number_of_rounds", + type=int, + default=100, + help="Number of FL rounds (default: 100)", +) +args = parser.parse_args() + + +# Function to Start Federated Learning Server +def start_fl_server(strategy, rounds): + try: + fl.server.start_server( + server_address="0.0.0.0:8080", + config=fl.server.ServerConfig(num_rounds=rounds), + strategy=strategy, + ) + except Exception as e: + logger.error(f"FL Server error: {e}", exc_info=True) + + +# Main Function +if __name__ == "__main__": + # Start Prometheus Metrics Server + start_http_server(8000) + + # Initialize Strategy Instance and Start FL Server + strategy_instance = FedCustom(accuracy_gauge=accuracy_gauge, loss_gauge=loss_gauge) + start_fl_server(strategy=strategy_instance, rounds=args.number_of_rounds) diff --git a/examples/flower-via-docker-compose/strategy/strategy.py b/examples/flower-via-docker-compose/strategy/strategy.py new file mode 100644 index 000000000000..9471a99f037f --- /dev/null +++ b/examples/flower-via-docker-compose/strategy/strategy.py @@ -0,0 +1,60 @@ +from typing import Dict, List, Optional, Tuple, Union +from flwr.common import Scalar, EvaluateRes +from flwr.server.client_proxy import ClientProxy +from flwr.server.strategy.aggregate import aggregate, weighted_loss_avg +import flwr as fl +import logging +from prometheus_client import Gauge + +logging.basicConfig(level=logging.INFO) # Configure logging +logger = logging.getLogger(__name__) # Create logger for the module + + +class FedCustom(fl.server.strategy.FedAvg): + def __init__( + self, accuracy_gauge: Gauge = None, loss_gauge: Gauge = None, *args, **kwargs + ): + super().__init__(*args, **kwargs) + + self.accuracy_gauge = accuracy_gauge + self.loss_gauge = loss_gauge + + def __repr__(self) -> str: + return "FedCustom" + + def aggregate_evaluate( + self, + server_round: int, + results: List[Tuple[ClientProxy, EvaluateRes]], + failures: List[Union[Tuple[ClientProxy, EvaluateRes], BaseException]], + ) -> Tuple[Optional[float], Dict[str, Scalar]]: + """Aggregate evaluation losses and accuracy using weighted average.""" + + if not results: + return None, {} + + # Calculate weighted average for loss using the provided function + loss_aggregated = weighted_loss_avg( + [ + (evaluate_res.num_examples, evaluate_res.loss) + for _, evaluate_res in results + ] + ) + + # Calculate weighted average for accuracy + accuracies = [ + evaluate_res.metrics["accuracy"] * evaluate_res.num_examples + for _, evaluate_res in results + ] + examples = [evaluate_res.num_examples for _, evaluate_res in results] + accuracy_aggregated = ( + sum(accuracies) / sum(examples) if sum(examples) != 0 else 0 + ) + + # Update the Prometheus gauges with the latest aggregated accuracy and loss values + self.accuracy_gauge.set(accuracy_aggregated) + self.loss_gauge.set(loss_aggregated) + + metrics_aggregated = {"loss": loss_aggregated, "accuracy": accuracy_aggregated} + + return loss_aggregated, metrics_aggregated From 3402dbbda9f9bd195e71dac9b6380fe4cde43305 Mon Sep 17 00:00:00 2001 From: Heng Pan <134433891+panh99@users.noreply.github.com> Date: Thu, 25 Jan 2024 16:30:21 +0000 Subject: [PATCH 034/113] Add conversion functions for `Message` (#2843) --- src/py/flwr/common/serde.py | 68 +++++++- src/py/flwr/common/serde_test.py | 260 +++++++++++++++++++++++-------- 2 files changed, 260 insertions(+), 68 deletions(-) diff --git a/src/py/flwr/common/serde.py b/src/py/flwr/common/serde.py index 2600d46edddc..97d3262dde94 100644 --- a/src/py/flwr/common/serde.py +++ b/src/py/flwr/common/serde.py @@ -17,7 +17,7 @@ from typing import Any, Dict, List, MutableMapping, OrderedDict, Type, TypeVar, cast -from google.protobuf.message import Message +from google.protobuf.message import Message as GrpcMessage # pylint: disable=E0611 from flwr.proto.recordset_pb2 import Array as ProtoArray @@ -30,7 +30,7 @@ from flwr.proto.recordset_pb2 import ParametersRecord as ProtoParametersRecord from flwr.proto.recordset_pb2 import RecordSet as ProtoRecordSet from flwr.proto.recordset_pb2 import Sint64List, StringList -from flwr.proto.task_pb2 import Value +from flwr.proto.task_pb2 import Task, TaskIns, TaskRes, Value from flwr.proto.transport_pb2 import ( ClientMessage, Code, @@ -44,6 +44,7 @@ # pylint: enable=E0611 from . import typing from .configsrecord import ConfigsRecord +from .message import Message, Metadata from .metricsrecord import MetricsRecord from .parametersrecord import Array, ParametersRecord from .recordset import RecordSet @@ -620,7 +621,7 @@ def _record_value_to_proto( ) -def _record_value_from_proto(value_proto: Message) -> Any: +def _record_value_from_proto(value_proto: GrpcMessage) -> Any: """Deserialize `*RecordValue` from ProtoBuf.""" value_field = cast(str, value_proto.WhichOneof("value")) if value_field.endswith("list"): @@ -751,3 +752,64 @@ def recordset_from_proto(recordset_proto: ProtoRecordSet) -> RecordSet: k: configs_record_from_proto(v) for k, v in recordset_proto.configs.items() }, ) + + +# === Message === + + +def message_to_taskins(message: Message) -> TaskIns: + """Create a TaskIns from the Message.""" + return TaskIns( + task=Task( + ttl=message.metadata.ttl, + task_type=message.metadata.task_type, + recordset=recordset_to_proto(message.message), + ), + ) + + +def message_from_taskins(taskins: TaskIns) -> Message: + """Create a Message from the TaskIns.""" + # Retrieve the Metadata + metadata = Metadata( + run_id=taskins.run_id, + task_id=taskins.task_id, + group_id=taskins.group_id, + ttl=taskins.task.ttl, + task_type=taskins.task.task_type, + ) + + # Return the Message + return Message( + metadata=metadata, + message=recordset_from_proto(taskins.task.recordset), + ) + + +def message_to_taskres(message: Message) -> TaskRes: + """Create a TaskRes from the Message.""" + return TaskRes( + task=Task( + ttl=message.metadata.ttl, + task_type=message.metadata.task_type, + recordset=recordset_to_proto(message.message), + ), + ) + + +def message_from_taskres(taskres: TaskRes) -> Message: + """Create a Message from the TaskIns.""" + # Retrieve the MetaData + metadata = Metadata( + run_id=taskres.run_id, + task_id=taskres.task_id, + group_id=taskres.group_id, + ttl=taskres.task.ttl, + task_type=taskres.task.task_type, + ) + + # Return the Message + return Message( + metadata=metadata, + message=recordset_from_proto(taskres.task.recordset), + ) diff --git a/src/py/flwr/common/serde_test.py b/src/py/flwr/common/serde_test.py index 53f40eee5e53..1f3d9239065b 100644 --- a/src/py/flwr/common/serde_test.py +++ b/src/py/flwr/common/serde_test.py @@ -15,7 +15,9 @@ """(De-)serialization tests.""" -from typing import Dict, OrderedDict, Union, cast +import random +import string +from typing import Any, Dict, Optional, OrderedDict, Type, TypeVar, Union, cast # pylint: disable=E0611 from flwr.proto import transport_pb2 as pb2 @@ -28,6 +30,7 @@ # pylint: enable=E0611 from . import typing from .configsrecord import ConfigsRecord +from .message import Message, Metadata from .metricsrecord import MetricsRecord from .parametersrecord import Array, ParametersRecord from .recordset import RecordSet @@ -36,6 +39,10 @@ array_to_proto, configs_record_from_proto, configs_record_to_proto, + message_from_taskins, + message_from_taskres, + message_to_taskins, + message_to_taskres, metrics_record_from_proto, metrics_record_to_proto, named_values_from_proto, @@ -180,10 +187,132 @@ def test_named_values_serialization_deserialization() -> None: assert expected == actual +T = TypeVar("T") + + +class RecordMaker: + """A record maker based on a seeded random number generator.""" + + def __init__(self, state: int = 42) -> None: + self.rng = random.Random(state) + + def randbytes(self, n: int) -> bytes: + """Create a bytes.""" + return self.rng.getrandbits(n * 8).to_bytes(n, "little") + + def get_str(self, length: Optional[int] = None) -> str: + """Create a string.""" + char_pool = ( + string.ascii_letters + string.digits + " !@#$%^&*()_-+=[]|;':,./<>?{}" + ) + if length is None: + length = self.rng.randint(1, 10) + return "".join(self.rng.choices(char_pool, k=length)) + + def get_value(self, dtype: Type[T]) -> T: + """Create a value of a given type.""" + ret: Any = None + if dtype == bool: + ret = self.rng.random() < 0.5 + elif dtype == str: + ret = self.get_str(self.rng.randint(10, 100)) + elif dtype == int: + ret = self.rng.randint(-1 << 30, 1 << 30) + elif dtype == float: + ret = (self.rng.random() - 0.5) * (2.0 ** self.rng.randint(0, 50)) + elif dtype == bytes: + ret = self.randbytes(self.rng.randint(10, 100)) + else: + raise NotImplementedError(f"Unsupported dtype: {dtype}") + return cast(T, ret) + + def array(self) -> Array: + """Create a Array.""" + dtypes = ("float", "int") + stypes = ("torch", "tf", "numpy") + max_shape_size = 100 + max_shape_dim = 10 + min_max_bytes_size = (10, 1000) + + dtype = self.rng.choice(dtypes) + shape = [ + self.rng.randint(1, max_shape_size) + for _ in range(self.rng.randint(1, max_shape_dim)) + ] + stype = self.rng.choice(stypes) + data = self.randbytes(self.rng.randint(*min_max_bytes_size)) + return Array(dtype=dtype, shape=shape, stype=stype, data=data) + + def parameters_record(self) -> ParametersRecord: + """Create a ParametersRecord.""" + num_arrays = self.rng.randint(1, 5) + arrays = OrderedDict( + [(self.get_str(), self.array()) for i in range(num_arrays)] + ) + return ParametersRecord(arrays, keep_input=False) + + def metrics_record(self) -> MetricsRecord: + """Create a MetricsRecord.""" + num_entries = self.rng.randint(1, 5) + types = (float, int) + return MetricsRecord( + metrics_dict={ + self.get_str(): self.get_value(self.rng.choice(types)) + for _ in range(num_entries) + }, + keep_input=False, + ) + + def configs_record(self) -> ConfigsRecord: + """Create a ConfigsRecord.""" + num_entries = self.rng.randint(1, 5) + types = (str, int, float, bytes, bool) + return ConfigsRecord( + configs_dict={ + self.get_str(): self.get_value(self.rng.choice(types)) + for _ in range(num_entries) + }, + keep_input=False, + ) + + def recordset( + self, + num_params_records: int, + num_metrics_records: int, + num_configs_records: int, + ) -> RecordSet: + """Create a RecordSet.""" + return RecordSet( + parameters={ + self.get_str(): self.parameters_record() + for _ in range(num_params_records) + }, + metrics={ + self.get_str(): self.metrics_record() + for _ in range(num_metrics_records) + }, + configs={ + self.get_str(): self.configs_record() + for _ in range(num_configs_records) + }, + ) + + def metadata(self) -> Metadata: + """Create a Metadata.""" + return Metadata( + run_id=self.rng.randint(0, 1 << 30), + task_id=self.get_str(64), + group_id=self.get_str(30), + ttl=self.get_str(10), + task_type=self.get_str(10), + ) + + def test_array_serialization_deserialization() -> None: """Test serialization and deserialization of Array.""" # Prepare - original = Array(dtype="float", shape=[2, 2], stype="dense", data=b"1234") + maker = RecordMaker() + original = maker.array() # Execute proto = array_to_proto(original) @@ -197,15 +326,8 @@ def test_array_serialization_deserialization() -> None: def test_parameters_record_serialization_deserialization() -> None: """Test serialization and deserialization of ParametersRecord.""" # Prepare - original = ParametersRecord( - array_dict=OrderedDict( - [ - ("k1", Array(dtype="float", shape=[2, 2], stype="dense", data=b"1234")), - ("k2", Array(dtype="int", shape=[3], stype="sparse", data=b"567")), - ] - ), - keep_input=False, - ) + maker = RecordMaker() + original = maker.parameters_record() # Execute proto = parameters_record_to_proto(original) @@ -219,9 +341,8 @@ def test_parameters_record_serialization_deserialization() -> None: def test_metrics_record_serialization_deserialization() -> None: """Test serialization and deserialization of MetricsRecord.""" # Prepare - original = MetricsRecord( - metrics_dict={"accuracy": 0.95, "loss": 0.1}, keep_input=False - ) + maker = RecordMaker() + original = maker.metrics_record() # Execute proto = metrics_record_to_proto(original) @@ -235,9 +356,8 @@ def test_metrics_record_serialization_deserialization() -> None: def test_configs_record_serialization_deserialization() -> None: """Test serialization and deserialization of ConfigsRecord.""" # Prepare - original = ConfigsRecord( - configs_dict={"learning_rate": 0.01, "batch_size": 32}, keep_input=False - ) + maker = RecordMaker() + original = maker.configs_record() # Execute proto = configs_record_to_proto(original) @@ -251,54 +371,8 @@ def test_configs_record_serialization_deserialization() -> None: def test_recordset_serialization_deserialization() -> None: """Test serialization and deserialization of RecordSet.""" # Prepare - encoder_params_record = ParametersRecord( - array_dict=OrderedDict( - [ - ( - "k1", - Array(dtype="float", shape=[2, 2], stype="dense", data=b"1234"), - ), - ("k2", Array(dtype="int", shape=[3], stype="sparse", data=b"567")), - ] - ), - keep_input=False, - ) - decoder_params_record = ParametersRecord( - array_dict=OrderedDict( - [ - ( - "k1", - Array( - dtype="float", shape=[32, 32, 4], stype="dense", data=b"0987" - ), - ), - ] - ), - keep_input=False, - ) - - original = RecordSet( - parameters={ - "encoder_parameters": encoder_params_record, - "decoder_parameters": decoder_params_record, - }, - metrics={ - "acc_metrics": MetricsRecord( - metrics_dict={"accuracy": 0.95, "loss": 0.1}, keep_input=False - ) - }, - configs={ - "my_configs": ConfigsRecord( - configs_dict={ - "learning_rate": 0.01, - "batch_size": 32, - "public_key": b"21f8sioj@!#", - "log": "Hello, world!", - }, - keep_input=False, - ) - }, - ) + maker = RecordMaker(state=0) + original = maker.recordset(2, 2, 1) # Execute proto = recordset_to_proto(original) @@ -307,3 +381,59 @@ def test_recordset_serialization_deserialization() -> None: # Assert assert isinstance(proto, ProtoRecordSet) assert original == deserialized + + +def test_message_to_and_from_taskins() -> None: + """Test Message to and from TaskIns.""" + # Prepare + maker = RecordMaker(state=1) + metadata = maker.metadata() + original = Message( + metadata=Metadata( + run_id=0, + task_id="", + group_id="", + ttl=metadata.ttl, + task_type=metadata.task_type, + ), + message=maker.recordset(1, 1, 1), + ) + + # Execute + taskins = message_to_taskins(original) + taskins.run_id = metadata.run_id + taskins.task_id = metadata.task_id + taskins.group_id = metadata.group_id + deserialized = message_from_taskins(taskins) + + # Assert + assert original.message == deserialized.message + assert metadata == deserialized.metadata + + +def test_message_to_and_from_taskres() -> None: + """Test Message to and from TaskRes.""" + # Prepare + maker = RecordMaker(state=2) + metadata = maker.metadata() + original = Message( + metadata=Metadata( + run_id=0, + task_id="", + group_id="", + ttl=metadata.ttl, + task_type=metadata.task_type, + ), + message=maker.recordset(1, 1, 1), + ) + + # Execute + taskres = message_to_taskres(original) + taskres.run_id = metadata.run_id + taskres.task_id = metadata.task_id + taskres.group_id = metadata.group_id + deserialized = message_from_taskres(taskres) + + # Assert + assert original.message == deserialized.message + assert metadata == deserialized.metadata From 539b5a1057cdd0e981c171bbad1d4da3b3527320 Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Thu, 25 Jan 2024 17:43:22 +0100 Subject: [PATCH 035/113] Fix ParametersRecord<>Parameters conversion (#2852) Co-authored-by: jafermarq --- src/py/flwr/common/recordset_compat.py | 23 +++++++++++++---------- src/py/flwr/common/recordset_test.py | 23 ++++++++++++++++++++--- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/py/flwr/common/recordset_compat.py b/src/py/flwr/common/recordset_compat.py index c45f7fcd9fb8..65a7181f219a 100644 --- a/src/py/flwr/common/recordset_compat.py +++ b/src/py/flwr/common/recordset_compat.py @@ -40,20 +40,22 @@ def parametersrecord_to_parameters( - record: ParametersRecord, keep_input: bool = False + record: ParametersRecord, keep_input: bool = True ) -> Parameters: """Convert ParameterRecord to legacy Parameters. - Warning: Because `Arrays` in `ParametersRecord` encode more information of the + Warnings + -------- + Because `Arrays` in `ParametersRecord` encode more information of the array-like or tensor-like data (e.g their datatype, shape) than `Parameters` it might not be possible to reconstruct such data structures from `Parameters` objects - alone. Additional information or metadta must be provided from elsewhere. + alone. Additional information or metadata must be provided from elsewhere. Parameters ---------- record : ParametersRecord The record to be conveted into Parameters. - keep_input : bool (default: False) + keep_input : bool (default: True) A boolean indicating whether entries in the record should be deleted from the input dictionary immediately after adding them to the record. """ @@ -74,7 +76,8 @@ def parametersrecord_to_parameters( def parameters_to_parametersrecord( - parameters: Parameters, keep_input: bool = False + parameters: Parameters, + keep_input: bool = True, ) -> ParametersRecord: """Convert legacy Parameters into a single ParametersRecord. @@ -86,7 +89,7 @@ def parameters_to_parametersrecord( ---------- parameters : Parameters Parameters object to be represented as a ParametersRecord. - keep_input : bool (default: False) + keep_input : bool (default=True) A boolean indicating whether parameters should be deleted from the input Parameters object (i.e. a list of serialized NumPy arrays) immediately after adding them to the record. @@ -96,17 +99,17 @@ def parameters_to_parametersrecord( p_record = ParametersRecord() num_arrays = len(parameters.tensors) + ordered_dict = OrderedDict() for idx in range(num_arrays): if keep_input: tensor = parameters.tensors[idx] else: tensor = parameters.tensors.pop(0) - p_record.set_parameters( - OrderedDict( - {str(idx): Array(data=tensor, dtype="", stype=tensor_type, shape=[])} - ) + ordered_dict[str(idx)] = Array( + data=tensor, dtype="", stype=tensor_type, shape=[] ) + p_record.set_parameters(ordered_dict, keep_input=keep_input) return p_record diff --git a/src/py/flwr/common/recordset_test.py b/src/py/flwr/common/recordset_test.py index e1825eaeef14..10fe85a56ecc 100644 --- a/src/py/flwr/common/recordset_test.py +++ b/src/py/flwr/common/recordset_test.py @@ -87,15 +87,32 @@ def test_parameters_to_array_and_back() -> None: assert np.array_equal(ndarray, ndarray_) -def test_parameters_to_parametersrecord_and_back() -> None: +@pytest.mark.parametrize( + "keep_input", + [False, True], +) +def test_parameters_to_parametersrecord_and_back(keep_input: bool) -> None: """Test conversion between legacy Parameters and ParametersRecords.""" ndarrays = get_ndarrays() parameters = ndarrays_to_parameters(ndarrays) - params_record = parameters_to_parametersrecord(parameters=parameters) + params_record = parameters_to_parametersrecord( + parameters=parameters, keep_input=keep_input + ) + + if keep_input: + # Verify inputed parameters are indeed as originally passed + assert parameters == ndarrays_to_parameters(ndarrays) + else: + # Verify tensors have been erased + assert len(parameters.tensors) == 0 + + parameters_ = parametersrecord_to_parameters(params_record, keep_input=keep_input) - parameters_ = parametersrecord_to_parameters(params_record) + if not keep_input: + # Verify Arrays in record have been erased + assert len(params_record.data) == 0 ndarrays_ = parameters_to_ndarrays(parameters=parameters_) From 4813f7853b1f4fbe775c302adb900e5e0b682275 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Jan 2024 17:58:52 +0100 Subject: [PATCH 036/113] Update types-requests requirement from ==2.31.0.10 to ==2.31.0.20240125 (#2850) Updates the requirements on [types-requests](https://github.com/python/typeshed) to permit the latest version. - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-requests dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Daniel J. Beutel --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 1ccdc72666f6..e47308b03f95 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -81,7 +81,7 @@ rest = ["requests", "starlette", "uvicorn"] [tool.poetry.group.dev.dependencies] types-dataclasses = "==0.6.6" types-protobuf = "==3.19.18" -types-requests = "==2.31.0.10" +types-requests = "==2.31.0.20240125" types-setuptools = "==69.0.0.20240115" clang-format = "==17.0.4" isort = "==5.13.2" From 52c3952ca72ece5a64aa740c50625c272ede9271 Mon Sep 17 00:00:00 2001 From: Javier Date: Thu, 25 Jan 2024 20:30:41 +0000 Subject: [PATCH 037/113] Remove default `keep_input` arguments (#2854) --- src/py/flwr/common/recordset_compat.py | 23 +++-- src/py/flwr/common/recordset_compat_test.py | 103 ++++++++++++++++---- src/py/flwr/common/recordset_test.py | 31 +++--- 3 files changed, 116 insertions(+), 41 deletions(-) diff --git a/src/py/flwr/common/recordset_compat.py b/src/py/flwr/common/recordset_compat.py index 65a7181f219a..e0e591048820 100644 --- a/src/py/flwr/common/recordset_compat.py +++ b/src/py/flwr/common/recordset_compat.py @@ -40,7 +40,7 @@ def parametersrecord_to_parameters( - record: ParametersRecord, keep_input: bool = True + record: ParametersRecord, keep_input: bool ) -> Parameters: """Convert ParameterRecord to legacy Parameters. @@ -55,7 +55,7 @@ def parametersrecord_to_parameters( ---------- record : ParametersRecord The record to be conveted into Parameters. - keep_input : bool (default: True) + keep_input : bool A boolean indicating whether entries in the record should be deleted from the input dictionary immediately after adding them to the record. """ @@ -76,8 +76,7 @@ def parametersrecord_to_parameters( def parameters_to_parametersrecord( - parameters: Parameters, - keep_input: bool = True, + parameters: Parameters, keep_input: bool ) -> ParametersRecord: """Convert legacy Parameters into a single ParametersRecord. @@ -89,7 +88,7 @@ def parameters_to_parametersrecord( ---------- parameters : Parameters Parameters object to be represented as a ParametersRecord. - keep_input : bool (default=True) + keep_input : bool A boolean indicating whether parameters should be deleted from the input Parameters object (i.e. a list of serialized NumPy arrays) immediately after adding them to the record. @@ -333,11 +332,15 @@ def getparametersins_to_recordset(getparameters_ins: GetParametersIns) -> Record return recordset -def getparametersres_to_recordset(getparametersres: GetParametersRes) -> RecordSet: +def getparametersres_to_recordset( + getparametersres: GetParametersRes, keep_input: bool +) -> RecordSet: """Construct a RecordSet from a GetParametersRes object.""" recordset = RecordSet() res_str = "getparametersres" - parameters_record = parameters_to_parametersrecord(getparametersres.parameters) + parameters_record = parameters_to_parametersrecord( + getparametersres.parameters, keep_input=keep_input + ) recordset.set_parameters(f"{res_str}.parameters", parameters_record) # status @@ -348,11 +351,13 @@ def getparametersres_to_recordset(getparametersres: GetParametersRes) -> RecordS return recordset -def recordset_to_getparametersres(recordset: RecordSet) -> GetParametersRes: +def recordset_to_getparametersres( + recordset: RecordSet, keep_input: bool +) -> GetParametersRes: """Derive GetParametersRes from a RecordSet object.""" res_str = "getparametersres" parameters = parametersrecord_to_parameters( - recordset.get_parameters(f"{res_str}.parameters") + recordset.get_parameters(f"{res_str}.parameters"), keep_input=keep_input ) status = _extract_status_from_recordset(res_str, recordset) diff --git a/src/py/flwr/common/recordset_compat_test.py b/src/py/flwr/common/recordset_compat_test.py index ad91cd3a42fc..288326dc9e83 100644 --- a/src/py/flwr/common/recordset_compat_test.py +++ b/src/py/flwr/common/recordset_compat_test.py @@ -15,9 +15,10 @@ """RecordSet from legacy messages tests.""" from copy import deepcopy -from typing import Dict +from typing import Callable, Dict import numpy as np +import pytest from .parameter import ndarrays_to_parameters from .recordset_compat import ( @@ -136,42 +137,88 @@ def _get_valid_getpropertiesres() -> GetPropertiesRes: ) -def test_fitins_to_recordset_and_back() -> None: +@pytest.mark.parametrize( + "keep_input, validate_freed_fn", + [ + ( + False, + lambda x, x_copy, y: len(x.parameters.tensors) == 0 and x_copy == y, + ), # check tensors were freed + ( + True, + lambda x, x_copy, y: x == y, + ), + ], +) +def test_fitins_to_recordset_and_back( + keep_input: bool, validate_freed_fn: Callable[[FitIns, FitIns, FitIns], bool] +) -> None: """Test conversion FitIns --> RecordSet --> FitIns.""" fitins = _get_valid_fitins() fitins_copy = deepcopy(fitins) - recordset = fitins_to_recordset(fitins, keep_input=False) + recordset = fitins_to_recordset(fitins, keep_input=keep_input) - fitins_ = recordset_to_fitins(recordset, keep_input=False) + fitins_ = recordset_to_fitins(recordset, keep_input=keep_input) - assert fitins_copy == fitins_ + assert validate_freed_fn(fitins, fitins_copy, fitins_) -def test_fitres_to_recordset_and_back() -> None: +@pytest.mark.parametrize( + "keep_input, validate_freed_fn", + [ + ( + False, + lambda x, x_copy, y: len(x.parameters.tensors) == 0 and x_copy == y, + ), # check tensors were freed + ( + True, + lambda x, x_copy, y: x == y, + ), + ], +) +def test_fitres_to_recordset_and_back( + keep_input: bool, validate_freed_fn: Callable[[FitRes, FitRes, FitRes], bool] +) -> None: """Test conversion FitRes --> RecordSet --> FitRes.""" fitres = _get_valid_fitres() fitres_copy = deepcopy(fitres) - recordset = fitres_to_recordset(fitres, keep_input=False) - fitres_ = recordset_to_fitres(recordset, keep_input=False) + recordset = fitres_to_recordset(fitres, keep_input=keep_input) + fitres_ = recordset_to_fitres(recordset, keep_input=keep_input) - assert fitres_copy == fitres_ + assert validate_freed_fn(fitres, fitres_copy, fitres_) -def test_evaluateins_to_recordset_and_back() -> None: +@pytest.mark.parametrize( + "keep_input, validate_freed_fn", + [ + ( + False, + lambda x, x_copy, y: len(x.parameters.tensors) == 0 and x_copy == y, + ), # check tensors were freed + ( + True, + lambda x, x_copy, y: x == y, + ), + ], +) +def test_evaluateins_to_recordset_and_back( + keep_input: bool, + validate_freed_fn: Callable[[EvaluateIns, EvaluateIns, EvaluateIns], bool], +) -> None: """Test conversion EvaluateIns --> RecordSet --> EvaluateIns.""" evaluateins = _get_valid_evaluateins() evaluateins_copy = deepcopy(evaluateins) - recordset = evaluateins_to_recordset(evaluateins, keep_input=False) + recordset = evaluateins_to_recordset(evaluateins, keep_input=keep_input) - evaluateins_ = recordset_to_evaluateins(recordset, keep_input=False) + evaluateins_ = recordset_to_evaluateins(recordset, keep_input=keep_input) - assert evaluateins_copy == evaluateins_ + assert validate_freed_fn(evaluateins, evaluateins_copy, evaluateins_) def test_evaluateres_to_recordset_and_back() -> None: @@ -222,13 +269,35 @@ def test_get_parameters_ins_to_recordset_and_back() -> None: assert getparameters_ins_copy == getparameters_ins_ -def test_get_parameters_res_to_recordset_and_back() -> None: +@pytest.mark.parametrize( + "keep_input, validate_freed_fn", + [ + ( + False, + lambda x, x_copy, y: len(x.parameters.tensors) == 0 and x_copy == y, + ), # check tensors were freed + ( + True, + lambda x, x_copy, y: x == y, + ), + ], +) +def test_get_parameters_res_to_recordset_and_back( + keep_input: bool, + validate_freed_fn: Callable[ + [GetParametersRes, GetParametersRes, GetParametersRes], bool + ], +) -> None: """Test conversion GetParametersRes --> RecordSet --> GetParametersRes.""" getparameteres_res = _get_valid_getparametersres() getparameters_res_copy = deepcopy(getparameteres_res) - recordset = getparametersres_to_recordset(getparameteres_res) - getparameteres_res_ = recordset_to_getparametersres(recordset) + recordset = getparametersres_to_recordset(getparameteres_res, keep_input=keep_input) + getparameteres_res_ = recordset_to_getparametersres( + recordset, keep_input=keep_input + ) - assert getparameters_res_copy == getparameteres_res_ + assert validate_freed_fn( + getparameteres_res, getparameters_res_copy, getparameteres_res_ + ) diff --git a/src/py/flwr/common/recordset_test.py b/src/py/flwr/common/recordset_test.py index 10fe85a56ecc..cb199813f450 100644 --- a/src/py/flwr/common/recordset_test.py +++ b/src/py/flwr/common/recordset_test.py @@ -14,6 +14,7 @@ # ============================================================================== """RecordSet tests.""" +from copy import deepcopy from typing import Callable, Dict, List, OrderedDict, Type, Union import numpy as np @@ -88,36 +89,36 @@ def test_parameters_to_array_and_back() -> None: @pytest.mark.parametrize( - "keep_input", - [False, True], + "keep_input, validate_freed_fn", + [ + (False, lambda x, x_copy, y: len(x.tensors) == 0), # check tensors were freed + (True, lambda x, x_copy, y: x.tensors == y.tensors), # check they are equal + ], ) -def test_parameters_to_parametersrecord_and_back(keep_input: bool) -> None: +def test_parameters_to_parametersrecord_and_back( + keep_input: bool, + validate_freed_fn: Callable[[Parameters, Parameters, Parameters], bool], +) -> None: """Test conversion between legacy Parameters and ParametersRecords.""" ndarrays = get_ndarrays() parameters = ndarrays_to_parameters(ndarrays) + parameters_copy = deepcopy(parameters) params_record = parameters_to_parametersrecord( parameters=parameters, keep_input=keep_input ) - if keep_input: - # Verify inputed parameters are indeed as originally passed - assert parameters == ndarrays_to_parameters(ndarrays) - else: - # Verify tensors have been erased - assert len(parameters.tensors) == 0 - parameters_ = parametersrecord_to_parameters(params_record, keep_input=keep_input) - if not keep_input: - # Verify Arrays in record have been erased - assert len(params_record.data) == 0 - ndarrays_ = parameters_to_ndarrays(parameters=parameters_) + # Validate returned NDArrays match those at the beginning for arr, arr_ in zip(ndarrays, ndarrays_): - assert np.array_equal(arr, arr_) + assert np.array_equal(arr, arr_), "no" + + # Validate initial Parameters object has been handled according to `keep_input` + assert validate_freed_fn(parameters, parameters_copy, parameters_) def test_set_parameters_while_keeping_intputs() -> None: From 9bfd38e55df0b763707ab2992ec38b568e21501d Mon Sep 17 00:00:00 2001 From: Javier Date: Fri, 26 Jan 2024 12:28:14 +0000 Subject: [PATCH 038/113] Replace `RunState` with `RecordSet` (#2855) --- e2e/bare/client.py | 14 +++++++---- e2e/pytorch/client.py | 14 ++++++----- src/py/flwr/client/client.py | 8 +++--- .../client/message_handler/message_handler.py | 14 +++++------ .../message_handler/message_handler_test.py | 6 ++--- src/py/flwr/client/middleware/utils_test.py | 10 ++++---- src/py/flwr/client/node_state.py | 10 ++++---- src/py/flwr/client/node_state_tests.py | 17 +++++++------ src/py/flwr/client/numpy_client.py | 12 ++++----- src/py/flwr/client/run_state.py | 25 ------------------- src/py/flwr/client/typing.py | 6 ++--- .../simulation/ray_transport/ray_actor.py | 16 ++++++------ .../ray_transport/ray_client_proxy_test.py | 14 ++++++++--- 13 files changed, 78 insertions(+), 88 deletions(-) delete mode 100644 src/py/flwr/client/run_state.py diff --git a/e2e/bare/client.py b/e2e/bare/client.py index 8e5c3adff5e6..db83919a0c11 100644 --- a/e2e/bare/client.py +++ b/e2e/bare/client.py @@ -3,6 +3,8 @@ import flwr as fl import numpy as np +from flwr.common.configsrecord import ConfigsRecord + SUBSET_SIZE = 1000 STATE_VAR = 'timestamp' @@ -18,13 +20,15 @@ def get_parameters(self, config): def _record_timestamp_to_state(self): """Record timestamp to client's state.""" t_stamp = datetime.now().timestamp() - if STATE_VAR in self.state.state: - self.state.state[STATE_VAR] += f",{t_stamp}" - else: - self.state.state[STATE_VAR] = str(t_stamp) + value = str(t_stamp) + if STATE_VAR in self.state.configs.keys(): + value = self.state.get_configs(STATE_VAR)[STATE_VAR] # type: ignore + value += f",{t_stamp}" + + self.state.set_configs(name=STATE_VAR, record=ConfigsRecord({STATE_VAR: value})) def _retrieve_timestamp_from_state(self): - return self.state.state[STATE_VAR] + return self.state.get_configs(STATE_VAR)[STATE_VAR] def fit(self, parameters, config): model_params = parameters diff --git a/e2e/pytorch/client.py b/e2e/pytorch/client.py index d180ad5d4eca..53de31b7351b 100644 --- a/e2e/pytorch/client.py +++ b/e2e/pytorch/client.py @@ -11,6 +11,7 @@ from tqdm import tqdm import flwr as fl +from flwr.common.configsrecord import ConfigsRecord # ############################################################################# # 1. Regular PyTorch pipeline: nn.Module, train, test, and DataLoader @@ -95,14 +96,15 @@ def get_parameters(self, config): def _record_timestamp_to_state(self): """Record timestamp to client's state.""" t_stamp = datetime.now().timestamp() - if STATE_VAR in self.state.state: - self.state.state[STATE_VAR] += f",{t_stamp}" - else: - self.state.state[STATE_VAR] = str(t_stamp) + value = str(t_stamp) + if STATE_VAR in self.state.configs.keys(): + value = self.state.get_configs(STATE_VAR)[STATE_VAR] # type: ignore + value += f",{t_stamp}" + + self.state.set_configs(name=STATE_VAR, record=ConfigsRecord({STATE_VAR: value})) def _retrieve_timestamp_from_state(self): - return self.state.state[STATE_VAR] - + return self.state.get_configs(STATE_VAR)[STATE_VAR] def fit(self, parameters, config): set_parameters(net, parameters) train(net, trainloader, epochs=1) diff --git a/src/py/flwr/client/client.py b/src/py/flwr/client/client.py index 54b53296fd2f..8be7ff82f544 100644 --- a/src/py/flwr/client/client.py +++ b/src/py/flwr/client/client.py @@ -19,7 +19,6 @@ from abc import ABC -from flwr.client.run_state import RunState from flwr.common import ( Code, EvaluateIns, @@ -33,12 +32,13 @@ Parameters, Status, ) +from flwr.common.recordset import RecordSet class Client(ABC): """Abstract base class for Flower clients.""" - state: RunState + state: RecordSet def get_properties(self, ins: GetPropertiesIns) -> GetPropertiesRes: """Return set of client's properties. @@ -141,11 +141,11 @@ def evaluate(self, ins: EvaluateIns) -> EvaluateRes: metrics={}, ) - def get_state(self) -> RunState: + def get_state(self) -> RecordSet: """Get the run state from this client.""" return self.state - def set_state(self, state: RunState) -> None: + def set_state(self, state: RecordSet) -> None: """Apply a run state to this client.""" self.state = state diff --git a/src/py/flwr/client/message_handler/message_handler.py b/src/py/flwr/client/message_handler/message_handler.py index 8cfe909c1738..2cb9df0f1cdd 100644 --- a/src/py/flwr/client/message_handler/message_handler.py +++ b/src/py/flwr/client/message_handler/message_handler.py @@ -28,10 +28,10 @@ get_server_message_from_task_ins, wrap_client_message_in_task_res, ) -from flwr.client.run_state import RunState from flwr.client.secure_aggregation import SecureAggregationHandler from flwr.client.typing import ClientFn from flwr.common import serde +from flwr.common.recordset import RecordSet from flwr.proto.task_pb2 import ( # pylint: disable=E0611 SecureAggregation, Task, @@ -88,15 +88,15 @@ def handle_control_message(task_ins: TaskIns) -> Tuple[Optional[TaskRes], int]: def handle( - client_fn: ClientFn, state: RunState, task_ins: TaskIns -) -> Tuple[TaskRes, RunState]: + client_fn: ClientFn, state: RecordSet, task_ins: TaskIns +) -> Tuple[TaskRes, RecordSet]: """Handle incoming TaskIns from the server. Parameters ---------- client_fn : ClientFn A callable that instantiates a Client. - state : RunState + state : RecordSet A dataclass storing the state for the run being executed by the client. task_ins: TaskIns The task instruction coming from the server, to be processed by the client. @@ -135,15 +135,15 @@ def handle( def handle_legacy_message( - client_fn: ClientFn, state: RunState, server_msg: ServerMessage -) -> Tuple[ClientMessage, RunState]: + client_fn: ClientFn, state: RecordSet, server_msg: ServerMessage +) -> Tuple[ClientMessage, RecordSet]: """Handle incoming messages from the server. Parameters ---------- client_fn : ClientFn A callable that instantiates a Client. - state : RunState + state : RecordSet A dataclass storing the state for the run being executed by the client. server_msg: ServerMessage The message coming from the server, to be processed by the client. diff --git a/src/py/flwr/client/message_handler/message_handler_test.py b/src/py/flwr/client/message_handler/message_handler_test.py index 194f75fe30ca..6f73169677c5 100644 --- a/src/py/flwr/client/message_handler/message_handler_test.py +++ b/src/py/flwr/client/message_handler/message_handler_test.py @@ -18,7 +18,6 @@ import uuid from flwr.client import Client -from flwr.client.run_state import RunState from flwr.client.typing import ClientFn from flwr.common import ( EvaluateIns, @@ -33,6 +32,7 @@ serde, typing, ) +from flwr.common.recordset import RecordSet from flwr.proto.node_pb2 import Node # pylint: disable=E0611 from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611 from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 @@ -141,7 +141,7 @@ def test_client_without_get_properties() -> None: ) task_res, _ = handle( client_fn=_get_client_fn(client), - state=RunState(state={}), + state=RecordSet(), task_ins=task_ins, ) @@ -209,7 +209,7 @@ def test_client_with_get_properties() -> None: ) task_res, _ = handle( client_fn=_get_client_fn(client), - state=RunState(state={}), + state=RecordSet(), task_ins=task_ins, ) diff --git a/src/py/flwr/client/middleware/utils_test.py b/src/py/flwr/client/middleware/utils_test.py index 006fe6db4799..37a24ea7442f 100644 --- a/src/py/flwr/client/middleware/utils_test.py +++ b/src/py/flwr/client/middleware/utils_test.py @@ -18,8 +18,8 @@ import unittest from typing import List -from flwr.client.run_state import RunState from flwr.client.typing import Bwd, FlowerCallable, Fwd, Layer +from flwr.common.recordset import RecordSet from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611 from .utils import make_ffn @@ -45,7 +45,7 @@ def make_mock_app(name: str, footprint: List[str]) -> FlowerCallable: def app(fwd: Fwd) -> Bwd: footprint.append(name) fwd.task_ins.task_id += f"{name}" - return Bwd(task_res=TaskRes(task_id=name), state=RunState({})) + return Bwd(task_res=TaskRes(task_id=name), state=RecordSet()) return app @@ -66,7 +66,7 @@ def test_multiple_middlewares(self) -> None: # Execute wrapped_app = make_ffn(mock_app, mock_middleware_layers) - task_res = wrapped_app(Fwd(task_ins=task_ins, state=RunState({}))).task_res + task_res = wrapped_app(Fwd(task_ins=task_ins, state=RecordSet())).task_res # Assert trace = mock_middleware_names + ["app"] @@ -86,11 +86,11 @@ def filter_layer(fwd: Fwd, _: FlowerCallable) -> Bwd: footprint.append("filter") fwd.task_ins.task_id += "filter" # Skip calling app - return Bwd(task_res=TaskRes(task_id="filter"), state=RunState({})) + return Bwd(task_res=TaskRes(task_id="filter"), state=RecordSet()) # Execute wrapped_app = make_ffn(mock_app, [filter_layer]) - task_res = wrapped_app(Fwd(task_ins=task_ins, state=RunState({}))).task_res + task_res = wrapped_app(Fwd(task_ins=task_ins, state=RecordSet())).task_res # Assert self.assertEqual(footprint, ["filter"]) diff --git a/src/py/flwr/client/node_state.py b/src/py/flwr/client/node_state.py index 0a29be511806..dd0f9913d73d 100644 --- a/src/py/flwr/client/node_state.py +++ b/src/py/flwr/client/node_state.py @@ -17,7 +17,7 @@ from typing import Any, Dict -from flwr.client.run_state import RunState +from flwr.common.recordset import RecordSet class NodeState: @@ -25,14 +25,14 @@ class NodeState: def __init__(self) -> None: self._meta: Dict[str, Any] = {} # holds metadata about the node - self.run_states: Dict[int, RunState] = {} + self.run_states: Dict[int, RecordSet] = {} def register_runstate(self, run_id: int) -> None: """Register new run state for this node.""" if run_id not in self.run_states: - self.run_states[run_id] = RunState({}) + self.run_states[run_id] = RecordSet() - def retrieve_runstate(self, run_id: int) -> RunState: + def retrieve_runstate(self, run_id: int) -> RecordSet: """Get run state given a run_id.""" if run_id in self.run_states: return self.run_states[run_id] @@ -43,6 +43,6 @@ def retrieve_runstate(self, run_id: int) -> RunState: " by a client." ) - def update_runstate(self, run_id: int, run_state: RunState) -> None: + def update_runstate(self, run_id: int, run_state: RecordSet) -> None: """Update run state.""" self.run_states[run_id] = run_state diff --git a/src/py/flwr/client/node_state_tests.py b/src/py/flwr/client/node_state_tests.py index 7bc0d77d16cf..d26dddc45fe2 100644 --- a/src/py/flwr/client/node_state_tests.py +++ b/src/py/flwr/client/node_state_tests.py @@ -16,15 +16,18 @@ from flwr.client.node_state import NodeState -from flwr.client.run_state import RunState +from flwr.common.configsrecord import ConfigsRecord +from flwr.common.recordset import RecordSet from flwr.proto.task_pb2 import TaskIns # pylint: disable=E0611 -def _run_dummy_task(state: RunState) -> RunState: - if "counter" in state.state: - state.state["counter"] += "1" - else: - state.state["counter"] = "1" +def _run_dummy_task(state: RecordSet) -> RecordSet: + counter_value: str = "1" + if "counter" in state.configs.keys(): + counter_value = state.get_configs("counter")["count"] # type: ignore + counter_value += "1" + + state.set_configs(name="counter", record=ConfigsRecord({"count": counter_value})) return state @@ -56,4 +59,4 @@ def test_multirun_in_node_state() -> None: # Verify values for run_id, state in node_state.run_states.items(): - assert state.state["counter"] == expected_values[run_id] + assert state.get_configs("counter")["count"] == expected_values[run_id] diff --git a/src/py/flwr/client/numpy_client.py b/src/py/flwr/client/numpy_client.py index d67fb90512d4..d0991fc27081 100644 --- a/src/py/flwr/client/numpy_client.py +++ b/src/py/flwr/client/numpy_client.py @@ -19,7 +19,6 @@ from typing import Callable, Dict, Tuple from flwr.client.client import Client -from flwr.client.run_state import RunState from flwr.common import ( Config, NDArrays, @@ -27,6 +26,7 @@ ndarrays_to_parameters, parameters_to_ndarrays, ) +from flwr.common.recordset import RecordSet from flwr.common.typing import ( Code, EvaluateIns, @@ -70,7 +70,7 @@ class NumPyClient(ABC): """Abstract base class for Flower clients using NumPy.""" - state: RunState + state: RecordSet def get_properties(self, config: Config) -> Dict[str, Scalar]: """Return a client's set of properties. @@ -174,11 +174,11 @@ def evaluate( _ = (self, parameters, config) return 0.0, 0, {} - def get_state(self) -> RunState: + def get_state(self) -> RecordSet: """Get the run state from this client.""" return self.state - def set_state(self, state: RunState) -> None: + def set_state(self, state: RecordSet) -> None: """Apply a run state to this client.""" self.state = state @@ -278,12 +278,12 @@ def _evaluate(self: Client, ins: EvaluateIns) -> EvaluateRes: ) -def _get_state(self: Client) -> RunState: +def _get_state(self: Client) -> RecordSet: """Return state of underlying NumPyClient.""" return self.numpy_client.get_state() # type: ignore -def _set_state(self: Client, state: RunState) -> None: +def _set_state(self: Client, state: RecordSet) -> None: """Apply state to underlying NumPyClient.""" self.numpy_client.set_state(state) # type: ignore diff --git a/src/py/flwr/client/run_state.py b/src/py/flwr/client/run_state.py deleted file mode 100644 index c2755eb995eb..000000000000 --- a/src/py/flwr/client/run_state.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2023 Flower Labs GmbH. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Run state.""" - -from dataclasses import dataclass -from typing import Dict - - -@dataclass -class RunState: - """State of a run executed by a client node.""" - - state: Dict[str, str] diff --git a/src/py/flwr/client/typing.py b/src/py/flwr/client/typing.py index 5291afb83d98..f2d159a2950c 100644 --- a/src/py/flwr/client/typing.py +++ b/src/py/flwr/client/typing.py @@ -17,7 +17,7 @@ from dataclasses import dataclass from typing import Callable -from flwr.client.run_state import RunState +from flwr.common.recordset import RecordSet from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611 from .client import Client as Client @@ -28,7 +28,7 @@ class Fwd: """.""" task_ins: TaskIns - state: RunState + state: RecordSet @dataclass @@ -36,7 +36,7 @@ class Bwd: """.""" task_res: TaskRes - state: RunState + state: RecordSet FlowerCallable = Callable[[Fwd], Bwd] diff --git a/src/py/flwr/simulation/ray_transport/ray_actor.py b/src/py/flwr/simulation/ray_transport/ray_actor.py index 38af3f08daa2..aac73dfa2a62 100644 --- a/src/py/flwr/simulation/ray_transport/ray_actor.py +++ b/src/py/flwr/simulation/ray_transport/ray_actor.py @@ -27,8 +27,8 @@ from flwr import common from flwr.client import Client, ClientFn -from flwr.client.run_state import RunState from flwr.common.logger import log +from flwr.common.recordset import RecordSet from flwr.simulation.ray_transport.utils import check_clientfn_returns_client # All possible returns by a client @@ -61,8 +61,8 @@ def run( client_fn: ClientFn, job_fn: JobFn, cid: str, - state: RunState, - ) -> Tuple[str, ClientRes, RunState]: + state: RecordSet, + ) -> Tuple[str, ClientRes, RecordSet]: """Run a client run.""" # Execute tasks and return result # return also cid which is needed to ensure results @@ -237,7 +237,7 @@ def add_actors_to_pool(self, num_actors: int) -> None: self._idle_actors.extend(new_actors) self.num_actors += num_actors - def submit(self, fn: Any, value: Tuple[ClientFn, JobFn, str, RunState]) -> None: + def submit(self, fn: Any, value: Tuple[ClientFn, JobFn, str, RecordSet]) -> None: """Take idle actor and assign it a client run. Submit a job to an actor by first removing it from the list of idle actors, then @@ -255,7 +255,7 @@ def submit(self, fn: Any, value: Tuple[ClientFn, JobFn, str, RunState]) -> None: self._cid_to_future[cid]["future"] = future_key def submit_client_job( - self, actor_fn: Any, job: Tuple[ClientFn, JobFn, str, RunState] + self, actor_fn: Any, job: Tuple[ClientFn, JobFn, str, RecordSet] ) -> None: """Submit a job while tracking client ids.""" _, _, cid, _ = job @@ -295,7 +295,7 @@ def _is_future_ready(self, cid: str) -> bool: return self._cid_to_future[cid]["ready"] # type: ignore - def _fetch_future_result(self, cid: str) -> Tuple[ClientRes, RunState]: + def _fetch_future_result(self, cid: str) -> Tuple[ClientRes, RecordSet]: """Fetch result and updated state for a VirtualClient from Object Store. The job submitted by the ClientProxy interfacing with client with cid=cid is @@ -305,7 +305,7 @@ def _fetch_future_result(self, cid: str) -> Tuple[ClientRes, RunState]: future: ObjectRef[Any] = self._cid_to_future[cid]["future"] # type: ignore res_cid, res, updated_state = ray.get( future - ) # type: (str, ClientRes, RunState) + ) # type: (str, ClientRes, RecordSet) except ray.exceptions.RayActorError as ex: log(ERROR, ex) if hasattr(ex, "actor_id"): @@ -409,7 +409,7 @@ def process_unordered_future(self, timeout: Optional[float] = None) -> None: def get_client_result( self, cid: str, timeout: Optional[float] - ) -> Tuple[ClientRes, RunState]: + ) -> Tuple[ClientRes, RecordSet]: """Get result from VirtualClient with specific cid.""" # Loop until all jobs submitted to the pool are completed. Break early # if the result for the ClientProxy calling this method is ready diff --git a/src/py/flwr/simulation/ray_transport/ray_client_proxy_test.py b/src/py/flwr/simulation/ray_transport/ray_client_proxy_test.py index 9df71635b949..99ed0f4010df 100644 --- a/src/py/flwr/simulation/ray_transport/ray_client_proxy_test.py +++ b/src/py/flwr/simulation/ray_transport/ray_client_proxy_test.py @@ -22,8 +22,9 @@ import ray from flwr.client import Client, NumPyClient -from flwr.client.run_state import RunState from flwr.common import Code, GetPropertiesRes, Status +from flwr.common.configsrecord import ConfigsRecord +from flwr.common.recordset import RecordSet from flwr.simulation.ray_transport.ray_actor import ( ClientRes, DefaultActor, @@ -54,7 +55,9 @@ def cid_times_pi(client: Client) -> ClientRes: # pylint: disable=unused-argumen result = int(cid) * pi # store something in state - client.numpy_client.state.state["result"] = str(result) # type: ignore + client.numpy_client.state.set_configs( # type: ignore + "result", record=ConfigsRecord({"result": str(result)}) + ) # now let's convert it to a GetPropertiesRes response return GetPropertiesRes( @@ -141,10 +144,13 @@ def test_cid_consistency_all_submit_first_run_consistency() -> None: res, updated_state = prox.actor_pool.get_client_result(prox.cid, timeout=None) prox.proxy_state.update_runstate(run_id, run_state=updated_state) res = cast(GetPropertiesRes, res) + assert int(prox.cid) * pi == res.properties["result"] assert ( str(int(prox.cid) * pi) - == prox.proxy_state.retrieve_runstate(run_id).state["result"] + == prox.proxy_state.retrieve_runstate(run_id).get_configs("result")[ + "result" + ] ) ray.shutdown() @@ -162,7 +168,7 @@ def test_cid_consistency_without_proxies() -> None: job = job_fn(cid) pool.submit_client_job( lambda a, c_fn, j_fn, cid_, state: a.run.remote(c_fn, j_fn, cid_, state), - (get_dummy_client, job, cid, RunState(state={})), + (get_dummy_client, job, cid, RecordSet()), ) # fetch results one at a time From 08667701195d52e7699d1f0c2dfa4149b228ad40 Mon Sep 17 00:00:00 2001 From: Javier Date: Fri, 26 Jan 2024 14:10:21 +0000 Subject: [PATCH 039/113] Replace client's state with `common.Context` (#2858) Co-authored-by: Daniel J. Beutel --- e2e/bare/client.py | 8 ++-- e2e/pytorch/client.py | 8 ++-- src/py/flwr/client/app.py | 10 ++--- src/py/flwr/client/client.py | 16 ++++---- src/py/flwr/client/flower.py | 6 +-- .../client/message_handler/message_handler.py | 30 +++++++-------- .../message_handler/message_handler_test.py | 5 ++- src/py/flwr/client/middleware/utils_test.py | 13 +++++-- src/py/flwr/client/node_state.py | 29 +++++++------- src/py/flwr/client/node_state_tests.py | 26 +++++++------ src/py/flwr/client/numpy_client.py | 32 ++++++++-------- src/py/flwr/client/typing.py | 6 +-- .../simulation/ray_transport/ray_actor.py | 38 +++++++++---------- .../ray_transport/ray_client_proxy.py | 8 ++-- .../ray_transport/ray_client_proxy_test.py | 17 +++++---- 15 files changed, 131 insertions(+), 121 deletions(-) diff --git a/e2e/bare/client.py b/e2e/bare/client.py index db83919a0c11..59ef2e4248ee 100644 --- a/e2e/bare/client.py +++ b/e2e/bare/client.py @@ -21,14 +21,14 @@ def _record_timestamp_to_state(self): """Record timestamp to client's state.""" t_stamp = datetime.now().timestamp() value = str(t_stamp) - if STATE_VAR in self.state.configs.keys(): - value = self.state.get_configs(STATE_VAR)[STATE_VAR] # type: ignore + if STATE_VAR in self.context.state.configs.keys(): + value = self.context.state.get_configs(STATE_VAR)[STATE_VAR] # type: ignore value += f",{t_stamp}" - self.state.set_configs(name=STATE_VAR, record=ConfigsRecord({STATE_VAR: value})) + self.context.state.set_configs(name=STATE_VAR, record=ConfigsRecord({STATE_VAR: value})) def _retrieve_timestamp_from_state(self): - return self.state.get_configs(STATE_VAR)[STATE_VAR] + return self.context.state.get_configs(STATE_VAR)[STATE_VAR] def fit(self, parameters, config): model_params = parameters diff --git a/e2e/pytorch/client.py b/e2e/pytorch/client.py index 53de31b7351b..ccd36f47d22a 100644 --- a/e2e/pytorch/client.py +++ b/e2e/pytorch/client.py @@ -97,14 +97,14 @@ def _record_timestamp_to_state(self): """Record timestamp to client's state.""" t_stamp = datetime.now().timestamp() value = str(t_stamp) - if STATE_VAR in self.state.configs.keys(): - value = self.state.get_configs(STATE_VAR)[STATE_VAR] # type: ignore + if STATE_VAR in self.context.state.configs.keys(): + value = self.context.state.get_configs(STATE_VAR)[STATE_VAR] # type: ignore value += f",{t_stamp}" - self.state.set_configs(name=STATE_VAR, record=ConfigsRecord({STATE_VAR: value})) + self.context.state.set_configs(name=STATE_VAR, record=ConfigsRecord({STATE_VAR: value})) def _retrieve_timestamp_from_state(self): - return self.state.get_configs(STATE_VAR)[STATE_VAR] + return self.context.state.get_configs(STATE_VAR)[STATE_VAR] def fit(self, parameters, config): set_parameters(net, parameters) train(net, trainloader, epochs=1) diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index ae5beeae07d6..e1c9ec0cf9ae 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -352,7 +352,7 @@ def _load_app() -> Flower: break # Register state - node_state.register_runstate(run_id=task_ins.run_id) + node_state.register_context(run_id=task_ins.run_id) # Load app app: Flower = load_flower_callable_fn() @@ -360,14 +360,14 @@ def _load_app() -> Flower: # Handle task message fwd_msg: Fwd = Fwd( task_ins=task_ins, - state=node_state.retrieve_runstate(run_id=task_ins.run_id), + context=node_state.retrieve_context(run_id=task_ins.run_id), ) bwd_msg: Bwd = app(fwd=fwd_msg) # Update node state - node_state.update_runstate( - run_id=bwd_msg.task_res.run_id, - run_state=bwd_msg.state, + node_state.update_context( + run_id=fwd_msg.task_ins.run_id, + context=bwd_msg.context, ) # Send diff --git a/src/py/flwr/client/client.py b/src/py/flwr/client/client.py index 8be7ff82f544..6d982ecc9a9e 100644 --- a/src/py/flwr/client/client.py +++ b/src/py/flwr/client/client.py @@ -32,13 +32,13 @@ Parameters, Status, ) -from flwr.common.recordset import RecordSet +from flwr.common.context import Context class Client(ABC): """Abstract base class for Flower clients.""" - state: RecordSet + context: Context def get_properties(self, ins: GetPropertiesIns) -> GetPropertiesRes: """Return set of client's properties. @@ -141,13 +141,13 @@ def evaluate(self, ins: EvaluateIns) -> EvaluateRes: metrics={}, ) - def get_state(self) -> RecordSet: - """Get the run state from this client.""" - return self.state + def get_context(self) -> Context: + """Get the run context from this client.""" + return self.context - def set_state(self, state: RecordSet) -> None: - """Apply a run state to this client.""" - self.state = state + def set_context(self, context: Context) -> None: + """Apply a run context to this client.""" + self.context = context def to_client(self) -> Client: """Return client (itself).""" diff --git a/src/py/flwr/client/flower.py b/src/py/flwr/client/flower.py index 535f096e5866..157642c0fea6 100644 --- a/src/py/flwr/client/flower.py +++ b/src/py/flwr/client/flower.py @@ -56,12 +56,12 @@ def __init__( ) -> None: # Create wrapper function for `handle` def ffn(fwd: Fwd) -> Bwd: # pylint: disable=invalid-name - task_res, state_updated = handle( + task_res, context_updated = handle( client_fn=client_fn, - state=fwd.state, + context=fwd.context, task_ins=fwd.task_ins, ) - return Bwd(task_res=task_res, state=state_updated) + return Bwd(task_res=task_res, context=context_updated) # Wrap middleware layers around the wrapped handle function self._call = make_ffn(ffn, layers if layers is not None else []) diff --git a/src/py/flwr/client/message_handler/message_handler.py b/src/py/flwr/client/message_handler/message_handler.py index 2cb9df0f1cdd..8c920dcc585e 100644 --- a/src/py/flwr/client/message_handler/message_handler.py +++ b/src/py/flwr/client/message_handler/message_handler.py @@ -31,7 +31,7 @@ from flwr.client.secure_aggregation import SecureAggregationHandler from flwr.client.typing import ClientFn from flwr.common import serde -from flwr.common.recordset import RecordSet +from flwr.common.context import Context from flwr.proto.task_pb2 import ( # pylint: disable=E0611 SecureAggregation, Task, @@ -88,16 +88,16 @@ def handle_control_message(task_ins: TaskIns) -> Tuple[Optional[TaskRes], int]: def handle( - client_fn: ClientFn, state: RecordSet, task_ins: TaskIns -) -> Tuple[TaskRes, RecordSet]: + client_fn: ClientFn, context: Context, task_ins: TaskIns +) -> Tuple[TaskRes, Context]: """Handle incoming TaskIns from the server. Parameters ---------- client_fn : ClientFn A callable that instantiates a Client. - state : RecordSet - A dataclass storing the state for the run being executed by the client. + context : Context + A dataclass storing the context for the run being executed by the client. task_ins: TaskIns The task instruction coming from the server, to be processed by the client. @@ -110,7 +110,7 @@ def handle( if server_msg is None: # Instantiate the client client = client_fn("-1") - client.set_state(state) + client.set_context(context) # Secure Aggregation if task_ins.task.HasField("sa") and isinstance( client, SecureAggregationHandler @@ -127,24 +127,24 @@ def handle( sa=SecureAggregation(named_values=serde.named_values_to_proto(res)), ), ) - return task_res, client.get_state() + return task_res, client.get_context() raise NotImplementedError() - client_msg, updated_state = handle_legacy_message(client_fn, state, server_msg) + client_msg, updated_context = handle_legacy_message(client_fn, context, server_msg) task_res = wrap_client_message_in_task_res(client_msg) - return task_res, updated_state + return task_res, updated_context def handle_legacy_message( - client_fn: ClientFn, state: RecordSet, server_msg: ServerMessage -) -> Tuple[ClientMessage, RecordSet]: + client_fn: ClientFn, context: Context, server_msg: ServerMessage +) -> Tuple[ClientMessage, Context]: """Handle incoming messages from the server. Parameters ---------- client_fn : ClientFn A callable that instantiates a Client. - state : RecordSet - A dataclass storing the state for the run being executed by the client. + context : Context + A dataclass storing the context for the run being executed by the client. server_msg: ServerMessage The message coming from the server, to be processed by the client. @@ -161,7 +161,7 @@ def handle_legacy_message( # Instantiate the client client = client_fn("-1") - client.set_state(state) + client.set_context(context) # Execute task message = None if field == "get_properties_ins": @@ -173,7 +173,7 @@ def handle_legacy_message( if field == "evaluate_ins": message = _evaluate(client, server_msg.evaluate_ins) if message: - return message, client.get_state() + return message, client.get_context() raise UnknownServerMessage() diff --git a/src/py/flwr/client/message_handler/message_handler_test.py b/src/py/flwr/client/message_handler/message_handler_test.py index 6f73169677c5..707570cd8e57 100644 --- a/src/py/flwr/client/message_handler/message_handler_test.py +++ b/src/py/flwr/client/message_handler/message_handler_test.py @@ -32,6 +32,7 @@ serde, typing, ) +from flwr.common.context import Context from flwr.common.recordset import RecordSet from flwr.proto.node_pb2 import Node # pylint: disable=E0611 from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611 @@ -141,7 +142,7 @@ def test_client_without_get_properties() -> None: ) task_res, _ = handle( client_fn=_get_client_fn(client), - state=RecordSet(), + context=Context(state=RecordSet()), task_ins=task_ins, ) @@ -209,7 +210,7 @@ def test_client_with_get_properties() -> None: ) task_res, _ = handle( client_fn=_get_client_fn(client), - state=RecordSet(), + context=Context(state=RecordSet()), task_ins=task_ins, ) diff --git a/src/py/flwr/client/middleware/utils_test.py b/src/py/flwr/client/middleware/utils_test.py index 37a24ea7442f..fe3f7832ceb2 100644 --- a/src/py/flwr/client/middleware/utils_test.py +++ b/src/py/flwr/client/middleware/utils_test.py @@ -19,6 +19,7 @@ from typing import List from flwr.client.typing import Bwd, FlowerCallable, Fwd, Layer +from flwr.common.context import Context from flwr.common.recordset import RecordSet from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611 @@ -45,7 +46,7 @@ def make_mock_app(name: str, footprint: List[str]) -> FlowerCallable: def app(fwd: Fwd) -> Bwd: footprint.append(name) fwd.task_ins.task_id += f"{name}" - return Bwd(task_res=TaskRes(task_id=name), state=RecordSet()) + return Bwd(task_res=TaskRes(task_id=name), context=Context(state=RecordSet())) return app @@ -66,7 +67,8 @@ def test_multiple_middlewares(self) -> None: # Execute wrapped_app = make_ffn(mock_app, mock_middleware_layers) - task_res = wrapped_app(Fwd(task_ins=task_ins, state=RecordSet())).task_res + dummy_context = Context(state=RecordSet()) + task_res = wrapped_app(Fwd(task_ins=task_ins, context=dummy_context)).task_res # Assert trace = mock_middleware_names + ["app"] @@ -86,11 +88,14 @@ def filter_layer(fwd: Fwd, _: FlowerCallable) -> Bwd: footprint.append("filter") fwd.task_ins.task_id += "filter" # Skip calling app - return Bwd(task_res=TaskRes(task_id="filter"), state=RecordSet()) + return Bwd( + task_res=TaskRes(task_id="filter"), context=Context(state=RecordSet()) + ) # Execute wrapped_app = make_ffn(mock_app, [filter_layer]) - task_res = wrapped_app(Fwd(task_ins=task_ins, state=RecordSet())).task_res + dummy_context = Context(state=RecordSet()) + task_res = wrapped_app(Fwd(task_ins=task_ins, context=dummy_context)).task_res # Assert self.assertEqual(footprint, ["filter"]) diff --git a/src/py/flwr/client/node_state.py b/src/py/flwr/client/node_state.py index dd0f9913d73d..465bbd356c1c 100644 --- a/src/py/flwr/client/node_state.py +++ b/src/py/flwr/client/node_state.py @@ -17,6 +17,7 @@ from typing import Any, Dict +from flwr.common.context import Context from flwr.common.recordset import RecordSet @@ -25,24 +26,24 @@ class NodeState: def __init__(self) -> None: self._meta: Dict[str, Any] = {} # holds metadata about the node - self.run_states: Dict[int, RecordSet] = {} + self.run_contexts: Dict[int, Context] = {} - def register_runstate(self, run_id: int) -> None: - """Register new run state for this node.""" - if run_id not in self.run_states: - self.run_states[run_id] = RecordSet() + def register_context(self, run_id: int) -> None: + """Register new run context for this node.""" + if run_id not in self.run_contexts: + self.run_contexts[run_id] = Context(state=RecordSet()) - def retrieve_runstate(self, run_id: int) -> RecordSet: - """Get run state given a run_id.""" - if run_id in self.run_states: - return self.run_states[run_id] + def retrieve_context(self, run_id: int) -> Context: + """Get run context given a run_id.""" + if run_id in self.run_contexts: + return self.run_contexts[run_id] raise RuntimeError( - f"RunState for run_id={run_id} doesn't exist." - " A run must be registered before it can be retrieved or updated " + f"Context for run_id={run_id} doesn't exist." + " A run context must be registered before it can be retrieved or updated " " by a client." ) - def update_runstate(self, run_id: int, run_state: RecordSet) -> None: - """Update run state.""" - self.run_states[run_id] = run_state + def update_context(self, run_id: int, context: Context) -> None: + """Update run context.""" + self.run_contexts[run_id] = context diff --git a/src/py/flwr/client/node_state_tests.py b/src/py/flwr/client/node_state_tests.py index d26dddc45fe2..11e5e74a31ec 100644 --- a/src/py/flwr/client/node_state_tests.py +++ b/src/py/flwr/client/node_state_tests.py @@ -17,19 +17,21 @@ from flwr.client.node_state import NodeState from flwr.common.configsrecord import ConfigsRecord -from flwr.common.recordset import RecordSet +from flwr.common.context import Context from flwr.proto.task_pb2 import TaskIns # pylint: disable=E0611 -def _run_dummy_task(state: RecordSet) -> RecordSet: +def _run_dummy_task(context: Context) -> Context: counter_value: str = "1" - if "counter" in state.configs.keys(): - counter_value = state.get_configs("counter")["count"] # type: ignore + if "counter" in context.state.configs.keys(): + counter_value = context.get_configs("counter")["count"] # type: ignore counter_value += "1" - state.set_configs(name="counter", record=ConfigsRecord({"count": counter_value})) + context.state.set_configs( + name="counter", record=ConfigsRecord({"count": counter_value}) + ) - return state + return context def test_multirun_in_node_state() -> None: @@ -46,17 +48,17 @@ def test_multirun_in_node_state() -> None: run_id = task.run_id # Register - node_state.register_runstate(run_id=run_id) + node_state.register_context(run_id=run_id) # Get run state - state = node_state.retrieve_runstate(run_id=run_id) + context = node_state.retrieve_context(run_id=run_id) # Run "task" - updated_state = _run_dummy_task(state) + updated_state = _run_dummy_task(context) # Update run state - node_state.update_runstate(run_id=run_id, run_state=updated_state) + node_state.update_context(run_id=run_id, context=updated_state) # Verify values - for run_id, state in node_state.run_states.items(): - assert state.get_configs("counter")["count"] == expected_values[run_id] + for run_id, context in node_state.run_contexts.items(): + assert context.state.get_configs("counter")["count"] == expected_values[run_id] diff --git a/src/py/flwr/client/numpy_client.py b/src/py/flwr/client/numpy_client.py index d0991fc27081..a77889912a09 100644 --- a/src/py/flwr/client/numpy_client.py +++ b/src/py/flwr/client/numpy_client.py @@ -26,7 +26,7 @@ ndarrays_to_parameters, parameters_to_ndarrays, ) -from flwr.common.recordset import RecordSet +from flwr.common.context import Context from flwr.common.typing import ( Code, EvaluateIns, @@ -70,7 +70,7 @@ class NumPyClient(ABC): """Abstract base class for Flower clients using NumPy.""" - state: RecordSet + context: Context def get_properties(self, config: Config) -> Dict[str, Scalar]: """Return a client's set of properties. @@ -174,13 +174,13 @@ def evaluate( _ = (self, parameters, config) return 0.0, 0, {} - def get_state(self) -> RecordSet: - """Get the run state from this client.""" - return self.state + def get_context(self) -> Context: + """Get the run context from this client.""" + return self.context - def set_state(self, state: RecordSet) -> None: - """Apply a run state to this client.""" - self.state = state + def set_context(self, context: Context) -> None: + """Apply a run context to this client.""" + self.context = context def to_client(self) -> Client: """Convert to object to Client type and return it.""" @@ -278,21 +278,21 @@ def _evaluate(self: Client, ins: EvaluateIns) -> EvaluateRes: ) -def _get_state(self: Client) -> RecordSet: - """Return state of underlying NumPyClient.""" - return self.numpy_client.get_state() # type: ignore +def _get_context(self: Client) -> Context: + """Return context of underlying NumPyClient.""" + return self.numpy_client.get_context() # type: ignore -def _set_state(self: Client, state: RecordSet) -> None: - """Apply state to underlying NumPyClient.""" - self.numpy_client.set_state(state) # type: ignore +def _set_context(self: Client, context: Context) -> None: + """Apply context to underlying NumPyClient.""" + self.numpy_client.set_context(context) # type: ignore def _wrap_numpy_client(client: NumPyClient) -> Client: member_dict: Dict[str, Callable] = { # type: ignore "__init__": _constructor, - "get_state": _get_state, - "set_state": _set_state, + "get_context": _get_context, + "set_context": _set_context, } # Add wrapper type methods (if overridden) diff --git a/src/py/flwr/client/typing.py b/src/py/flwr/client/typing.py index f2d159a2950c..8f7940405f42 100644 --- a/src/py/flwr/client/typing.py +++ b/src/py/flwr/client/typing.py @@ -17,7 +17,7 @@ from dataclasses import dataclass from typing import Callable -from flwr.common.recordset import RecordSet +from flwr.common.context import Context from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611 from .client import Client as Client @@ -28,7 +28,7 @@ class Fwd: """.""" task_ins: TaskIns - state: RecordSet + context: Context @dataclass @@ -36,7 +36,7 @@ class Bwd: """.""" task_res: TaskRes - state: RecordSet + context: Context FlowerCallable = Callable[[Fwd], Bwd] diff --git a/src/py/flwr/simulation/ray_transport/ray_actor.py b/src/py/flwr/simulation/ray_transport/ray_actor.py index aac73dfa2a62..853566a4cbeb 100644 --- a/src/py/flwr/simulation/ray_transport/ray_actor.py +++ b/src/py/flwr/simulation/ray_transport/ray_actor.py @@ -27,8 +27,8 @@ from flwr import common from flwr.client import Client, ClientFn +from flwr.common.context import Context from flwr.common.logger import log -from flwr.common.recordset import RecordSet from flwr.simulation.ray_transport.utils import check_clientfn_returns_client # All possible returns by a client @@ -61,8 +61,8 @@ def run( client_fn: ClientFn, job_fn: JobFn, cid: str, - state: RecordSet, - ) -> Tuple[str, ClientRes, RecordSet]: + context: Context, + ) -> Tuple[str, ClientRes, Context]: """Run a client run.""" # Execute tasks and return result # return also cid which is needed to ensure results @@ -70,12 +70,12 @@ def run( try: # Instantiate client (check 'Client' type is returned) client = check_clientfn_returns_client(client_fn(cid)) - # Inject state - client.set_state(state) + # Inject context + client.set_context(context) # Run client job job_results = job_fn(client) - # Retrieve state (potentially updated) - updated_state = client.get_state() + # Retrieve context (potentially updated) + updated_context = client.get_context() except Exception as ex: client_trace = traceback.format_exc() message = ( @@ -89,7 +89,7 @@ def run( ) raise ClientException(str(message)) from ex - return cid, job_results, updated_state + return cid, job_results, updated_context @ray.remote @@ -237,16 +237,16 @@ def add_actors_to_pool(self, num_actors: int) -> None: self._idle_actors.extend(new_actors) self.num_actors += num_actors - def submit(self, fn: Any, value: Tuple[ClientFn, JobFn, str, RecordSet]) -> None: + def submit(self, fn: Any, value: Tuple[ClientFn, JobFn, str, Context]) -> None: """Take idle actor and assign it a client run. Submit a job to an actor by first removing it from the list of idle actors, then check if this actor was flagged to be removed from the pool """ - client_fn, job_fn, cid, state = value + client_fn, job_fn, cid, context = value actor = self._idle_actors.pop() if self._check_and_remove_actor_from_pool(actor): - future = fn(actor, client_fn, job_fn, cid, state) + future = fn(actor, client_fn, job_fn, cid, context) future_key = tuple(future) if isinstance(future, List) else future self._future_to_actor[future_key] = (self._next_task_index, actor, cid) self._next_task_index += 1 @@ -255,7 +255,7 @@ def submit(self, fn: Any, value: Tuple[ClientFn, JobFn, str, RecordSet]) -> None self._cid_to_future[cid]["future"] = future_key def submit_client_job( - self, actor_fn: Any, job: Tuple[ClientFn, JobFn, str, RecordSet] + self, actor_fn: Any, job: Tuple[ClientFn, JobFn, str, Context] ) -> None: """Submit a job while tracking client ids.""" _, _, cid, _ = job @@ -295,17 +295,17 @@ def _is_future_ready(self, cid: str) -> bool: return self._cid_to_future[cid]["ready"] # type: ignore - def _fetch_future_result(self, cid: str) -> Tuple[ClientRes, RecordSet]: - """Fetch result and updated state for a VirtualClient from Object Store. + def _fetch_future_result(self, cid: str) -> Tuple[ClientRes, Context]: + """Fetch result and updated context for a VirtualClient from Object Store. The job submitted by the ClientProxy interfacing with client with cid=cid is ready. Here we fetch it from the object store and return. """ try: future: ObjectRef[Any] = self._cid_to_future[cid]["future"] # type: ignore - res_cid, res, updated_state = ray.get( + res_cid, res, updated_context = ray.get( future - ) # type: (str, ClientRes, RecordSet) + ) # type: (str, ClientRes, Context) except ray.exceptions.RayActorError as ex: log(ERROR, ex) if hasattr(ex, "actor_id"): @@ -322,7 +322,7 @@ def _fetch_future_result(self, cid: str) -> Tuple[ClientRes, RecordSet]: # Reset mapping self._reset_cid_to_future_dict(cid) - return res, updated_state + return res, updated_context def _flag_actor_for_removal(self, actor_id_hex: str) -> None: """Flag actor that should be removed from pool.""" @@ -409,7 +409,7 @@ def process_unordered_future(self, timeout: Optional[float] = None) -> None: def get_client_result( self, cid: str, timeout: Optional[float] - ) -> Tuple[ClientRes, RecordSet]: + ) -> Tuple[ClientRes, Context]: """Get result from VirtualClient with specific cid.""" # Loop until all jobs submitted to the pool are completed. Break early # if the result for the ClientProxy calling this method is ready @@ -421,5 +421,5 @@ def get_client_result( break # Fetch result belonging to the VirtualClient calling this method - # Return both result from tasks and (potentially) updated run state + # Return both result from tasks and (potentially) updated run context return self._fetch_future_result(cid) diff --git a/src/py/flwr/simulation/ray_transport/ray_client_proxy.py b/src/py/flwr/simulation/ray_transport/ray_client_proxy.py index 5c05850dfd2f..894012dc6d70 100644 --- a/src/py/flwr/simulation/ray_transport/ray_client_proxy.py +++ b/src/py/flwr/simulation/ray_transport/ray_client_proxy.py @@ -138,20 +138,20 @@ def _submit_job(self, job_fn: JobFn, timeout: Optional[float]) -> ClientRes: run_id = 0 # Register state - self.proxy_state.register_runstate(run_id=run_id) + self.proxy_state.register_context(run_id=run_id) # Retrieve state - state = self.proxy_state.retrieve_runstate(run_id=run_id) + state = self.proxy_state.retrieve_context(run_id=run_id) try: self.actor_pool.submit_client_job( lambda a, c_fn, j_fn, cid, state: a.run.remote(c_fn, j_fn, cid, state), (self.client_fn, job_fn, self.cid, state), ) - res, updated_state = self.actor_pool.get_client_result(self.cid, timeout) + res, updated_context = self.actor_pool.get_client_result(self.cid, timeout) # Update state - self.proxy_state.update_runstate(run_id=run_id, run_state=updated_state) + self.proxy_state.update_context(run_id=run_id, context=updated_context) except Exception as ex: if self.actor_pool.num_actors == 0: diff --git a/src/py/flwr/simulation/ray_transport/ray_client_proxy_test.py b/src/py/flwr/simulation/ray_transport/ray_client_proxy_test.py index 99ed0f4010df..b380d37d01c8 100644 --- a/src/py/flwr/simulation/ray_transport/ray_client_proxy_test.py +++ b/src/py/flwr/simulation/ray_transport/ray_client_proxy_test.py @@ -24,6 +24,7 @@ from flwr.client import Client, NumPyClient from flwr.common import Code, GetPropertiesRes, Status from flwr.common.configsrecord import ConfigsRecord +from flwr.common.context import Context from flwr.common.recordset import RecordSet from flwr.simulation.ray_transport.ray_actor import ( ClientRes, @@ -54,8 +55,8 @@ def job_fn(cid: str) -> JobFn: # pragma: no cover def cid_times_pi(client: Client) -> ClientRes: # pylint: disable=unused-argument result = int(cid) * pi - # store something in state - client.numpy_client.state.set_configs( # type: ignore + # store something in context + client.numpy_client.context.state.set_configs( # type: ignore "result", record=ConfigsRecord({"result": str(result)}) ) @@ -128,9 +129,9 @@ def test_cid_consistency_all_submit_first_run_consistency() -> None: shuffle(proxies) for prox in proxies: # Register state - prox.proxy_state.register_runstate(run_id=run_id) + prox.proxy_state.register_context(run_id=run_id) # Retrieve state - state = prox.proxy_state.retrieve_runstate(run_id=run_id) + state = prox.proxy_state.retrieve_context(run_id=run_id) job = job_fn(prox.cid) prox.actor_pool.submit_client_job( @@ -141,14 +142,14 @@ def test_cid_consistency_all_submit_first_run_consistency() -> None: # fetch results one at a time shuffle(proxies) for prox in proxies: - res, updated_state = prox.actor_pool.get_client_result(prox.cid, timeout=None) - prox.proxy_state.update_runstate(run_id, run_state=updated_state) + res, updated_context = prox.actor_pool.get_client_result(prox.cid, timeout=None) + prox.proxy_state.update_context(run_id, context=updated_context) res = cast(GetPropertiesRes, res) assert int(prox.cid) * pi == res.properties["result"] assert ( str(int(prox.cid) * pi) - == prox.proxy_state.retrieve_runstate(run_id).get_configs("result")[ + == prox.proxy_state.retrieve_context(run_id).state.get_configs("result")[ "result" ] ) @@ -168,7 +169,7 @@ def test_cid_consistency_without_proxies() -> None: job = job_fn(cid) pool.submit_client_job( lambda a, c_fn, j_fn, cid_, state: a.run.remote(c_fn, j_fn, cid_, state), - (get_dummy_client, job, cid, RecordSet()), + (get_dummy_client, job, cid, Context(state=RecordSet())), ) # fetch results one at a time From 3cd2f4883965b2179859be0bc21b972756e77e93 Mon Sep 17 00:00:00 2001 From: Heng Pan <134433891+panh99@users.noreply.github.com> Date: Fri, 26 Jan 2024 15:45:22 +0000 Subject: [PATCH 040/113] Fix a bug in serde._record_value_to_proto (#2859) --- src/py/flwr/common/serde.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/py/flwr/common/serde.py b/src/py/flwr/common/serde.py index 97d3262dde94..9e12a30d8089 100644 --- a/src/py/flwr/common/serde.py +++ b/src/py/flwr/common/serde.py @@ -601,12 +601,15 @@ def named_values_from_proto( def _record_value_to_proto( value: Any, allowed_types: List[type], proto_class: Type[T] ) -> T: - """Serialize `*RecordValue` to ProtoBuf.""" + """Serialize `*RecordValue` to ProtoBuf. + + Note: `bool` MUST be put in the front of allowd_types if it exists. + """ arg = {} for t in allowed_types: # Single element # Note: `isinstance(False, int) == True`. - if type(value) == t: # pylint: disable=C0123 + if isinstance(value, t): arg[_type_to_field[t]] = value return proto_class(**arg) # List @@ -634,7 +637,14 @@ def _record_value_from_proto(value_proto: GrpcMessage) -> Any: def _record_value_dict_to_proto( value_dict: Dict[str, Any], allowed_types: List[type], value_proto_class: Type[T] ) -> Dict[str, T]: - """Serialize the record value dict to ProtoBuf.""" + """Serialize the record value dict to ProtoBuf. + + Note: `bool` MUST be put in the front of allowd_types if it exists. + """ + # Move bool to the front + if bool in allowed_types and allowed_types[0] != bool: + allowed_types.remove(bool) + allowed_types.insert(0, bool) def proto(_v: Any) -> T: return _record_value_to_proto(_v, allowed_types, value_proto_class) @@ -708,7 +718,7 @@ def configs_record_to_proto(record: ConfigsRecord) -> ProtoConfigsRecord: """Serialize ConfigsRecord to ProtoBuf.""" return ProtoConfigsRecord( data=_record_value_dict_to_proto( - record.data, [int, float, bool, str, bytes], ProtoConfigsRecordValue + record.data, [bool, int, float, str, bytes], ProtoConfigsRecordValue ) ) From f3e496ca57a4eb8d84f44ff3d3e20b927cd4c85a Mon Sep 17 00:00:00 2001 From: Adam Narozniak <51029327+adam-narozniak@users.noreply.github.com> Date: Mon, 29 Jan 2024 10:13:37 +0100 Subject: [PATCH 041/113] Migrate embedded devices example to use flwr-datasets (#2825) --- examples/embedded-devices/Dockerfile | 1 + examples/embedded-devices/README.md | 3 +- examples/embedded-devices/client_pytorch.py | 92 +++++++------------ examples/embedded-devices/client_tf.py | 46 +++++----- .../embedded-devices/requirements_pytorch.txt | 1 + examples/embedded-devices/requirements_tf.txt | 1 + examples/embedded-devices/server.py | 7 +- 7 files changed, 63 insertions(+), 88 deletions(-) diff --git a/examples/embedded-devices/Dockerfile b/examples/embedded-devices/Dockerfile index ea63839bc9d6..a85c05c4bb7a 100644 --- a/examples/embedded-devices/Dockerfile +++ b/examples/embedded-devices/Dockerfile @@ -8,6 +8,7 @@ RUN pip3 install --upgrade pip # Install flower RUN pip3 install flwr>=1.0 +RUN pip3 install flwr-datsets>=0.2 RUN pip3 install tqdm==4.65.0 WORKDIR /client diff --git a/examples/embedded-devices/README.md b/examples/embedded-devices/README.md index 4c79eafbbf84..5afe3965bd5b 100644 --- a/examples/embedded-devices/README.md +++ b/examples/embedded-devices/README.md @@ -192,7 +192,8 @@ On the machine of your choice, launch the server: # Launch your server. # Will wait for at least 2 clients to be connected, then will train for 3 FL rounds # The command below will sample all clients connected (since sample_fraction=1.0) -python server.py --rounds 3 --min_num_clients 2 --sample_fraction 1.0 # append `--mnist` if you want to use that dataset/model setting +# The the server is dataset agnostic (use the same command for MNIST and CIFAR10) +python server.py --rounds 3 --min_num_clients 2 --sample_fraction 1.0 ``` > If you are on macOS with Apple Silicon (i.e. M1, M2 chips), you might encounter a `grpcio`-related issue when launching your server. If you are in a conda environment you can solve this easily by doing: `pip uninstall grpcio` and then `conda install grpcio`. diff --git a/examples/embedded-devices/client_pytorch.py b/examples/embedded-devices/client_pytorch.py index 8e72d668531a..134b573f7608 100644 --- a/examples/embedded-devices/client_pytorch.py +++ b/examples/embedded-devices/client_pytorch.py @@ -6,18 +6,19 @@ import torch import torch.nn as nn import torch.nn.functional as F -from torch.utils.data import DataLoader, random_split -from torchvision.datasets import CIFAR10, MNIST +from torch.utils.data import DataLoader from torchvision.transforms import Compose, Normalize, ToTensor from torchvision.models import mobilenet_v3_small from tqdm import tqdm +from flwr_datasets import FederatedDataset + parser = argparse.ArgumentParser(description="Flower Embedded devices") parser.add_argument( "--server_address", type=str, default="0.0.0.0:8080", - help=f"gRPC server address (deafault '0.0.0.0:8080')", + help=f"gRPC server address (default '0.0.0.0:8080')", ) parser.add_argument( "--cid", @@ -28,26 +29,13 @@ parser.add_argument( "--mnist", action="store_true", - help="If you use Raspberry Pi Zero clients (which just have 512MB or RAM) use MNIST", + help="If you use Raspberry Pi Zero clients (which just have 512MB or RAM) use " + "MNIST", ) - warnings.filterwarnings("ignore", category=UserWarning) NUM_CLIENTS = 50 -# a config for mobilenetv2 that works for -# small input sizes (i.e. 32x32 as in CIFAR) -mb2_cfg = [ - (1, 16, 1, 1), - (6, 24, 2, 1), - (6, 32, 3, 2), - (6, 64, 4, 2), - (6, 96, 3, 1), - (6, 160, 3, 2), - (6, 320, 1, 1), -] - - class Net(nn.Module): """Model (simple CNN adapted from 'PyTorch: A 60 Minute Blitz').""" @@ -73,7 +61,9 @@ def train(net, trainloader, optimizer, epochs, device): """Train the model on the training set.""" criterion = torch.nn.CrossEntropyLoss() for _ in range(epochs): - for images, labels in tqdm(trainloader): + for batch in tqdm(trainloader): + batch = list(batch.values()) + images, labels = batch[0], batch[1] optimizer.zero_grad() criterion(net(images.to(device)), labels.to(device)).backward() optimizer.step() @@ -84,7 +74,9 @@ def test(net, testloader, device): criterion = torch.nn.CrossEntropyLoss() correct, loss = 0, 0.0 with torch.no_grad(): - for images, labels in tqdm(testloader): + for batch in tqdm(testloader): + batch = list(batch.values()) + images, labels = batch[0], batch[1] outputs = net(images.to(device)) labels = labels.to(device) loss += criterion(outputs, labels).item() @@ -95,44 +87,32 @@ def test(net, testloader, device): def prepare_dataset(use_mnist: bool): """Get MNIST/CIFAR-10 and return client partitions and global testset.""" - dataset = MNIST if use_mnist else CIFAR10 if use_mnist: + fds = FederatedDataset(dataset="mnist", partitioners={"train": NUM_CLIENTS}) + img_key = "image" norm = Normalize((0.1307,), (0.3081,)) else: + fds = FederatedDataset(dataset="cifar10", partitioners={"train": NUM_CLIENTS}) + img_key = "img" norm = Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) - - trf = Compose([ToTensor(), norm]) - trainset = dataset("./data", train=True, download=True, transform=trf) - testset = dataset("./data", train=False, download=True, transform=trf) - - print("Partitioning dataset (IID)...") - - # Split trainset into `num_partitions` trainsets - num_images = len(trainset) // NUM_CLIENTS - partition_len = [num_images] * NUM_CLIENTS - - trainsets = random_split( - trainset, partition_len, torch.Generator().manual_seed(2023) - ) - - val_ratio = 0.1 - - # Create dataloaders with train+val support - train_partitions = [] - val_partitions = [] - for trainset_ in trainsets: - num_total = len(trainset_) - num_val = int(val_ratio * num_total) - num_train = num_total - num_val - - for_train, for_val = random_split( - trainset_, [num_train, num_val], torch.Generator().manual_seed(2023) - ) - - train_partitions.append(for_train) - val_partitions.append(for_val) - - return train_partitions, val_partitions, testset + pytorch_transforms = Compose([ToTensor(), norm]) + def apply_transforms(batch): + """Apply transforms to the partition from FederatedDataset.""" + batch[img_key] = [pytorch_transforms(img) for img in batch[img_key]] + return batch + + trainsets = [] + validsets = [] + for node_id in range(NUM_CLIENTS): + partition = fds.load_partition(node_id, "train") + # Divide data on each node: 90% train, 10% test + partition = partition.train_test_split(test_size=0.1) + partition = partition.with_transform(apply_transforms) + trainsets.append(partition["train"]) + validsets.append(partition["test"]) + testset = fds.load_full("test") + testset = testset.with_transform(apply_transforms) + return trainsets, validsets, testset # Flower client, adapted from Pytorch quickstart/simulation example @@ -148,8 +128,6 @@ def __init__(self, trainset, valset, use_mnist): self.model = Net() else: self.model = mobilenet_v3_small(num_classes=10) - # let's not reduce spatial resolution too early - self.model.features[0][0].stride = (1, 1) # Determine device self.device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") self.model.to(self.device) # send model to device @@ -200,7 +178,7 @@ def main(): assert args.cid < NUM_CLIENTS use_mnist = args.mnist - # Download CIFAR-10 dataset and partition it + # Download dataset and partition it trainsets, valsets, _ = prepare_dataset(use_mnist) # Start Flower client setting its associated data partition diff --git a/examples/embedded-devices/client_tf.py b/examples/embedded-devices/client_tf.py index 5ea34e44a98b..712068af5fc4 100644 --- a/examples/embedded-devices/client_tf.py +++ b/examples/embedded-devices/client_tf.py @@ -6,6 +6,8 @@ import tensorflow as tf from tensorflow import keras as keras +from flwr_datasets import FederatedDataset + parser = argparse.ArgumentParser(description="Flower Embedded devices") parser.add_argument( "--server_address", @@ -32,30 +34,26 @@ def prepare_dataset(use_mnist: bool): """Download and partitions the CIFAR-10/MNIST dataset.""" if use_mnist: - (x_train, y_train), testset = tf.keras.datasets.mnist.load_data() + fds = FederatedDataset(dataset="mnist", partitioners={"train": NUM_CLIENTS}) + img_key = "image" else: - (x_train, y_train), testset = tf.keras.datasets.cifar10.load_data() + fds = FederatedDataset(dataset="cifar10", partitioners={"train": NUM_CLIENTS}) + img_key = "img" partitions = [] - # We keep all partitions equal-sized in this example - partition_size = math.floor(len(x_train) / NUM_CLIENTS) - for cid in range(NUM_CLIENTS): - # Split dataset into non-overlapping NUM_CLIENT partitions - idx_from, idx_to = int(cid) * partition_size, (int(cid) + 1) * partition_size - - x_train_cid, y_train_cid = ( - x_train[idx_from:idx_to] / 255.0, - y_train[idx_from:idx_to], - ) - - # now partition into train/validation - # Use 10% of the client's training data for validation - split_idx = math.floor(len(x_train_cid) * 0.9) - - client_train = (x_train_cid[:split_idx], y_train_cid[:split_idx]) - client_val = (x_train_cid[split_idx:], y_train_cid[split_idx:]) - partitions.append((client_train, client_val)) - - return partitions, testset + for node_id in range(NUM_CLIENTS): + partition = fds.load_partition(node_id, "train") + partition.set_format("numpy") + # Divide data on each node: 90% train, 10% test + partition = partition.train_test_split(test_size=0.1) + x_train, y_train = partition["train"][img_key] / 255.0, partition["train"][ + "label"] + x_test, y_test = partition["test"][img_key] / 255.0, partition["test"]["label"] + partitions.append(((x_train, y_train), (x_test, y_test))) + data_centralized = fds.load_full("test") + data_centralized.set_format("numpy") + x_centralized = data_centralized[img_key] / 255.0 + y_centralized = data_centralized["label"] + return partitions, (x_centralized, y_centralized) class FlowerClient(fl.client.NumPyClient): @@ -68,7 +66,7 @@ def __init__(self, trainset, valset, use_mnist: bool): # Instantiate model if use_mnist: # small model for MNIST - self.model = model = keras.Sequential( + self.model = keras.Sequential( [ keras.Input(shape=(28, 28, 1)), keras.layers.Conv2D(32, kernel_size=(5, 5), activation="relu"), @@ -118,7 +116,7 @@ def main(): assert args.cid < NUM_CLIENTS use_mnist = args.mnist - # Download CIFAR-10 dataset and partition it + # Download dataset and partition it partitions, _ = prepare_dataset(use_mnist) trainset, valset = partitions[args.cid] diff --git a/examples/embedded-devices/requirements_pytorch.txt b/examples/embedded-devices/requirements_pytorch.txt index 797ca6db6244..f859c4efef17 100644 --- a/examples/embedded-devices/requirements_pytorch.txt +++ b/examples/embedded-devices/requirements_pytorch.txt @@ -1,4 +1,5 @@ flwr>=1.0, <2.0 +flwr-datasets[vision]>=0.0.2, <1.0.0 torch==1.13.1 torchvision==0.14.1 tqdm==4.65.0 diff --git a/examples/embedded-devices/requirements_tf.txt b/examples/embedded-devices/requirements_tf.txt index c7068d40b9c2..ff65b9c31648 100644 --- a/examples/embedded-devices/requirements_tf.txt +++ b/examples/embedded-devices/requirements_tf.txt @@ -1,2 +1,3 @@ flwr>=1.0, <2.0 +flwr-datasets[vision]>=0.0.2, <1.0.0 tensorflow >=2.9.1, != 2.11.1 diff --git a/examples/embedded-devices/server.py b/examples/embedded-devices/server.py index 2a15f792297e..2a6194aa5088 100644 --- a/examples/embedded-devices/server.py +++ b/examples/embedded-devices/server.py @@ -30,16 +30,11 @@ default=2, help="Minimum number of available clients required for sampling (default: 2)", ) -parser.add_argument( - "--mnist", - action="store_true", - help="If you use Raspberry Pi Zero clients (which just have 512MB or RAM) use MNIST", -) # Define metric aggregation function def weighted_average(metrics: List[Tuple[int, Metrics]]) -> Metrics: - """Thist function averages teh `accuracy` metric sent by the clients in a `evaluate` + """This function averages teh `accuracy` metric sent by the clients in a `evaluate` stage (i.e. clients received the global model and evaluate it on their local validation sets).""" # Multiply accuracy of each client by number of examples used From e4b53131fbdbf25a4fcbbc1bf8f8549969c1bcc4 Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Mon, 29 Jan 2024 10:59:58 +0100 Subject: [PATCH 042/113] Remove grpc-bidi support from flower-server (#2860) --- src/py/flwr/driver/app.py | 7 +- src/py/flwr/server/app.py | 78 -------- .../fleet/grpc_bidi/driver_client_manager.py | 140 -------------- .../server/fleet/grpc_bidi/ins_scheduler.py | 174 ------------------ 4 files changed, 3 insertions(+), 396 deletions(-) delete mode 100644 src/py/flwr/server/fleet/grpc_bidi/driver_client_manager.py delete mode 100644 src/py/flwr/server/fleet/grpc_bidi/ins_scheduler.py diff --git a/src/py/flwr/driver/app.py b/src/py/flwr/driver/app.py index 4fa1ad8b5c02..cbacd6b53ab8 100644 --- a/src/py/flwr/driver/app.py +++ b/src/py/flwr/driver/app.py @@ -72,11 +72,10 @@ def start_driver( # pylint: disable=too-many-arguments, too-many-locals An implementation of the abstract base class `flwr.server.strategy.Strategy`. If no strategy is provided, then `start_server` will use `flwr.server.strategy.FedAvg`. - client_manager : Optional[flwr.driver.DriverClientManager] (default: None) - An implementation of the class - `flwr.driver.driver_client_manager.DriverClientManager`. If no + client_manager : Optional[flwr.server.DriverClientManager] (default: None) + An implementation of the class `flwr.server.ClientManager`. If no implementation is provided, then `start_driver` will use - `flwr.driver.driver_client_manager.DriverClientManager`. + `flwr.server.SimpleClientManager`. root_certificates : Optional[Union[bytes, str]] (default: None) The PEM-encoded root certificates as a byte string or a path string. If provided, a secure connection using the certificates will be diff --git a/src/py/flwr/server/app.py b/src/py/flwr/server/app.py index 636207e7a859..e50e631b3ca3 100644 --- a/src/py/flwr/server/app.py +++ b/src/py/flwr/server/app.py @@ -33,7 +33,6 @@ from flwr.common.address import parse_address from flwr.common.constant import ( MISSING_EXTRA_REST, - TRANSPORT_TYPE_GRPC_BIDI, TRANSPORT_TYPE_GRPC_RERE, TRANSPORT_TYPE_REST, ) @@ -44,13 +43,8 @@ from flwr.proto.fleet_pb2_grpc import ( # pylint: disable=E0611 add_FleetServicer_to_server, ) -from flwr.proto.transport_pb2_grpc import ( # pylint: disable=E0611 - add_FlowerServiceServicer_to_server, -) from flwr.server.client_manager import ClientManager, SimpleClientManager from flwr.server.driver.driver_servicer import DriverServicer -from flwr.server.fleet.grpc_bidi.driver_client_manager import DriverClientManager -from flwr.server.fleet.grpc_bidi.flower_service_servicer import FlowerServiceServicer from flwr.server.fleet.grpc_bidi.grpc_server import ( generic_create_grpc_server, start_grpc_server, @@ -319,19 +313,6 @@ def run_fleet_api() -> None: ) fleet_thread.start() bckg_threads.append(fleet_thread) - elif args.fleet_api_type == TRANSPORT_TYPE_GRPC_BIDI: - address_arg = args.grpc_fleet_api_address - parsed_address = parse_address(address_arg) - if not parsed_address: - sys.exit(f"Fleet IP address ({address_arg}) cannot be parsed.") - host, port, is_v6 = parsed_address - address = f"[{host}]:{port}" if is_v6 else f"{host}:{port}" - fleet_server = _run_fleet_api_grpc_bidi( - address=address, - state_factory=state_factory, - certificates=certificates, - ) - grpc_servers.append(fleet_server) elif args.fleet_api_type == TRANSPORT_TYPE_GRPC_RERE: address_arg = args.grpc_rere_fleet_api_address parsed_address = parse_address(address_arg) @@ -418,19 +399,6 @@ def run_server() -> None: ) fleet_thread.start() bckg_threads.append(fleet_thread) - elif args.fleet_api_type == TRANSPORT_TYPE_GRPC_BIDI: - address_arg = args.grpc_bidi_fleet_api_address - parsed_address = parse_address(address_arg) - if not parsed_address: - sys.exit(f"Fleet IP address ({address_arg}) cannot be parsed.") - host, port, is_v6 = parsed_address - address = f"[{host}]:{port}" if is_v6 else f"{host}:{port}" - fleet_server = _run_fleet_api_grpc_bidi( - address=address, - state_factory=state_factory, - certificates=certificates, - ) - grpc_servers.append(fleet_server) elif args.fleet_api_type == TRANSPORT_TYPE_GRPC_RERE: address_arg = args.grpc_rere_fleet_api_address parsed_address = parse_address(address_arg) @@ -556,35 +524,6 @@ def _run_driver_api_grpc( return driver_grpc_server -def _run_fleet_api_grpc_bidi( - address: str, - state_factory: StateFactory, - certificates: Optional[Tuple[bytes, bytes, bytes]], -) -> grpc.Server: - """Run Fleet API (gRPC, bidirectional streaming).""" - # DriverClientManager - driver_client_manager = DriverClientManager( - state_factory=state_factory, - ) - - # Create (legacy) Fleet API gRPC server - fleet_servicer = FlowerServiceServicer( - client_manager=driver_client_manager, - ) - fleet_add_servicer_to_server_fn = add_FlowerServiceServicer_to_server - fleet_grpc_server = generic_create_grpc_server( - servicer_and_add_fn=(fleet_servicer, fleet_add_servicer_to_server_fn), - server_address=address, - max_message_length=GRPC_MAX_MESSAGE_LENGTH, - certificates=certificates, - ) - - log(INFO, "Flower ECE: Starting Fleet API (gRPC-bidi) on %s", address) - fleet_grpc_server.start() - - return fleet_grpc_server - - def _run_fleet_api_grpc_rere( address: str, state_factory: StateFactory, @@ -785,13 +724,6 @@ def _add_args_fleet_api(parser: argparse.ArgumentParser) -> None: const=TRANSPORT_TYPE_REST, help="Start a Fleet API server (REST, experimental)", ) - ex_group.add_argument( - "--grpc-bidi", - action="store_const", - dest="fleet_api_type", - const=TRANSPORT_TYPE_GRPC_BIDI, - help="Start a Fleet API server (gRPC-bidi)", - ) # Fleet API gRPC-rere options grpc_rere_group = parser.add_argument_group( @@ -828,13 +760,3 @@ def _add_args_fleet_api(parser: argparse.ArgumentParser) -> None: type=int, default=1, ) - - # Fleet API gRPC-bidi options - grpc_bidi_group = parser.add_argument_group( - "Fleet API (gRPC-bidi) server options", "" - ) - grpc_bidi_group.add_argument( - "--grpc-bidi-fleet-api-address", - help="Fleet API (gRPC-bidi) server address (IPv4, IPv6, or a domain name)", - default=ADDRESS_FLEET_API_GRPC_RERE, - ) diff --git a/src/py/flwr/server/fleet/grpc_bidi/driver_client_manager.py b/src/py/flwr/server/fleet/grpc_bidi/driver_client_manager.py deleted file mode 100644 index dc94bf3912d7..000000000000 --- a/src/py/flwr/server/fleet/grpc_bidi/driver_client_manager.py +++ /dev/null @@ -1,140 +0,0 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Flower DriverClientManager.""" - - -import threading -from typing import Dict, List, Optional, Set, Tuple - -from flwr.server.client_manager import ClientManager -from flwr.server.client_proxy import ClientProxy -from flwr.server.criterion import Criterion -from flwr.server.state import State, StateFactory - -from .ins_scheduler import InsScheduler - - -class DriverClientManager(ClientManager): - """Provides a pool of available clients.""" - - def __init__(self, state_factory: StateFactory) -> None: - self._cv = threading.Condition() - self.nodes: Dict[str, Tuple[int, InsScheduler]] = {} - self.state_factory = state_factory - - def __len__(self) -> int: - """Return the number of available clients. - - Returns - ------- - num_available : int - The number of currently available clients. - """ - return len(self.nodes) - - def num_available(self) -> int: - """Return the number of available clients. - - Returns - ------- - num_available : int - The number of currently available clients. - """ - return len(self) - - def register(self, client: ClientProxy) -> bool: - """Register Flower ClientProxy instance. - - Parameters - ---------- - client : flwr.server.client_proxy.ClientProxy - - Returns - ------- - success : bool - Indicating if registration was successful. False if ClientProxy is - already registered or can not be registered for any reason. - """ - if client.cid in self.nodes: - return False - - # Create node in State - state: State = self.state_factory.state() - client.node_id = state.create_node() - - # Create and start the instruction scheduler - ins_scheduler = InsScheduler( - client_proxy=client, - state_factory=self.state_factory, - ) - ins_scheduler.start() - - # Store cid, node_id, and InsScheduler - self.nodes[client.cid] = (client.node_id, ins_scheduler) - - with self._cv: - self._cv.notify_all() - - return True - - def unregister(self, client: ClientProxy) -> None: - """Unregister Flower ClientProxy instance. - - This method is idempotent. - - Parameters - ---------- - client : flwr.server.client_proxy.ClientProxy - """ - if client.cid in self.nodes: - node_id, ins_scheduler = self.nodes[client.cid] - del self.nodes[client.cid] - ins_scheduler.stop() - - # Delete node_id in State - state: State = self.state_factory.state() - state.delete_node(node_id=node_id) - - with self._cv: - self._cv.notify_all() - - def all_ids(self) -> Set[int]: - """Return all available node ids. - - Returns - ------- - ids : Set[int] - The IDs of all currently available nodes. - """ - return {node_id for _, (node_id, _) in self.nodes.items()} - - # --- Unimplemented methods ----------------------------------------------- - - def all(self) -> Dict[str, ClientProxy]: - """Not implemented.""" - raise NotImplementedError() - - def wait_for(self, num_clients: int, timeout: int = 86400) -> bool: - """Not implemented.""" - raise NotImplementedError() - - def sample( - self, - num_clients: int, - min_num_clients: Optional[int] = None, - criterion: Optional[Criterion] = None, - ) -> List[ClientProxy]: - """Not implemented.""" - raise NotImplementedError() diff --git a/src/py/flwr/server/fleet/grpc_bidi/ins_scheduler.py b/src/py/flwr/server/fleet/grpc_bidi/ins_scheduler.py deleted file mode 100644 index 5843934b64a4..000000000000 --- a/src/py/flwr/server/fleet/grpc_bidi/ins_scheduler.py +++ /dev/null @@ -1,174 +0,0 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Instruction scheduler for the legacy gRPC transport stack.""" - - -import threading -import time -from logging import DEBUG, ERROR -from typing import Dict, List, Optional - -from flwr.client.message_handler.task_handler import configure_task_res -from flwr.common import EvaluateRes, FitRes, GetParametersRes, GetPropertiesRes, serde -from flwr.common.logger import log -from flwr.proto.node_pb2 import Node # pylint: disable=E0611 -from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611 -from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 - ClientMessage, - ServerMessage, -) -from flwr.server.client_proxy import ClientProxy -from flwr.server.state import State, StateFactory - - -class InsScheduler: - """Schedule ClientProxy calls on a background thread.""" - - def __init__(self, client_proxy: ClientProxy, state_factory: StateFactory): - self.client_proxy = client_proxy - self.state_factory = state_factory - self.worker_thread: Optional[threading.Thread] = None - self.shared_memory_state = {"stop": False} - - def start(self) -> None: - """Start the worker thread.""" - self.worker_thread = threading.Thread( - target=_worker, - args=( - self.client_proxy, - self.shared_memory_state, - self.state_factory, - ), - ) - self.worker_thread.start() - - def stop(self) -> None: - """Stop the worker thread.""" - if self.worker_thread is None: - log(ERROR, "InsScheduler.stop called, but worker_thread is None") - return - self.shared_memory_state["stop"] = True - self.worker_thread.join() - self.worker_thread = None - self.shared_memory_state["stop"] = False - - -def _worker( - client_proxy: ClientProxy, - shared_memory_state: Dict[str, bool], - state_factory: StateFactory, -) -> None: - """Sequentially call ClientProxy methods to process outstanding tasks.""" - log(DEBUG, "Worker for node %i started", client_proxy.node_id) - - state: State = state_factory.state() - while not shared_memory_state["stop"]: - log(DEBUG, "Worker for node %i checking state", client_proxy.node_id) - - # Step 1: pull *Ins (next task) out of `state` - task_ins_list: List[TaskIns] = state.get_task_ins( - node_id=client_proxy.node_id, - limit=1, - ) - if not task_ins_list: - log(DEBUG, "Worker for node %i: no task found", client_proxy.node_id) - time.sleep(3) - continue - - task_ins = task_ins_list[0] - log( - DEBUG, - "Worker for node %i: FOUND task %s", - client_proxy.node_id, - task_ins.task_id, - ) - - # Step 2: call client_proxy.{fit,evaluate,...} - server_message = task_ins.task.legacy_server_message - client_message_proto = _call_client_proxy( - client_proxy=client_proxy, - server_message=server_message, - timeout=None, - ) - - # Step 3: wrap FitRes in a ClientMessage in a Task in a TaskRes - task_res = configure_task_res( - TaskRes(task=Task(legacy_client_message=client_message_proto)), - task_ins, - Node(node_id=client_proxy.node_id, anonymous=False), - ) - - # Step 4: write *Res (result) back to `state` - state.store_task_res(task_res=task_res) - - # Exit worker thread - log(DEBUG, "Worker for node %i stopped", client_proxy.node_id) - - -def _call_client_proxy( - client_proxy: ClientProxy, server_message: ServerMessage, timeout: Optional[float] -) -> ClientMessage: - """.""" - # pylint: disable=too-many-locals - - field = server_message.WhichOneof("msg") - - if field == "get_properties_ins": - get_properties_ins = serde.get_properties_ins_from_proto( - msg=server_message.get_properties_ins - ) - get_properties_res: GetPropertiesRes = client_proxy.get_properties( - ins=get_properties_ins, - timeout=timeout, - ) - get_properties_res_proto = serde.get_properties_res_to_proto( - res=get_properties_res - ) - return ClientMessage(get_properties_res=get_properties_res_proto) - - if field == "get_parameters_ins": - get_parameters_ins = serde.get_parameters_ins_from_proto( - msg=server_message.get_parameters_ins - ) - get_parameters_res: GetParametersRes = client_proxy.get_parameters( - ins=get_parameters_ins, - timeout=timeout, - ) - get_parameters_res_proto = serde.get_parameters_res_to_proto( - res=get_parameters_res - ) - return ClientMessage(get_parameters_res=get_parameters_res_proto) - - if field == "fit_ins": - fit_ins = serde.fit_ins_from_proto(msg=server_message.fit_ins) - fit_res: FitRes = client_proxy.fit( - ins=fit_ins, - timeout=timeout, - ) - fit_res_proto = serde.fit_res_to_proto(res=fit_res) - return ClientMessage(fit_res=fit_res_proto) - - if field == "evaluate_ins": - evaluate_ins = serde.evaluate_ins_from_proto(msg=server_message.evaluate_ins) - evaluate_res: EvaluateRes = client_proxy.evaluate( - ins=evaluate_ins, - timeout=timeout, - ) - evaluate_res_proto = serde.evaluate_res_to_proto(res=evaluate_res) - return ClientMessage(evaluate_res=evaluate_res_proto) - - raise ValueError( - "Unsupported instruction in ServerMessage, cannot deserialize from ProtoBuf" - ) From 89c735a9b086b1cb3f5ebca99eeedcb539e38dfb Mon Sep 17 00:00:00 2001 From: Javier Date: Mon, 29 Jan 2024 10:54:09 +0000 Subject: [PATCH 043/113] Replace `Fwd/Bwd` with `Message/Context` (#2842) Co-authored-by: jafermarq Co-authored-by: Heng Pan Co-authored-by: Daniel J. Beutel --- src/py/flwr/client/app.py | 26 +- src/py/flwr/client/flower.py | 25 +- src/py/flwr/client/grpc_client/connection.py | 94 +++++- .../client/grpc_client/connection_test.py | 45 ++- .../client/grpc_rere_client/connection.py | 4 +- .../client/message_handler/message_handler.py | 272 ++++++------------ .../message_handler/message_handler_test.py | 152 +++------- .../client/message_handler/task_handler.py | 51 +--- .../message_handler/task_handler_test.py | 116 +------- src/py/flwr/client/middleware/utils.py | 8 +- src/py/flwr/client/middleware/utils_test.py | 91 ++++-- src/py/flwr/client/rest_client/connection.py | 4 +- src/py/flwr/client/typing.py | 24 +- src/py/flwr/common/constant.py | 5 + src/py/flwr/driver/driver_client_proxy.py | 89 +++--- .../flwr/driver/driver_client_proxy_test.py | 98 +++++-- src/py/flwr/flower/__init__.py | 4 - src/py/flwr/server/state/state_test.py | 15 +- src/py/flwr/server/utils/validator.py | 38 +-- src/py/flwr/server/utils/validator_test.py | 84 +----- 20 files changed, 504 insertions(+), 741 deletions(-) diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index e1c9ec0cf9ae..c310221ba7af 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -24,7 +24,7 @@ from flwr.client.client import Client from flwr.client.flower import Flower -from flwr.client.typing import Bwd, ClientFn, Fwd +from flwr.client.typing import ClientFn from flwr.common import GRPC_MAX_MESSAGE_LENGTH, EventType, event from flwr.common.address import parse_address from flwr.common.constant import ( @@ -35,6 +35,7 @@ TRANSPORT_TYPES, ) from flwr.common.logger import log, warn_experimental_feature +from flwr.common.serde import message_from_taskins, message_to_taskres from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611 from .flower import load_flower_callable @@ -351,27 +352,32 @@ def _load_app() -> Flower: send(task_res) break - # Register state + # Register context for this run node_state.register_context(run_id=task_ins.run_id) + # Retrieve context for this run + context = node_state.retrieve_context(run_id=task_ins.run_id) + + # Get Message from TaskIns + message = message_from_taskins(task_ins) + # Load app app: Flower = load_flower_callable_fn() # Handle task message - fwd_msg: Fwd = Fwd( - task_ins=task_ins, - context=node_state.retrieve_context(run_id=task_ins.run_id), - ) - bwd_msg: Bwd = app(fwd=fwd_msg) + out_message = app(message=message, context=context) # Update node state node_state.update_context( - run_id=fwd_msg.task_ins.run_id, - context=bwd_msg.context, + run_id=message.metadata.run_id, + context=context, ) + # Construct TaskRes from out_message + task_res = message_to_taskres(out_message) + # Send - send(bwd_msg.task_res) + send(task_res) # Unregister node if delete_node is not None: diff --git a/src/py/flwr/client/flower.py b/src/py/flwr/client/flower.py index 157642c0fea6..91f64502acfa 100644 --- a/src/py/flwr/client/flower.py +++ b/src/py/flwr/client/flower.py @@ -18,9 +18,13 @@ import importlib from typing import List, Optional, cast -from flwr.client.message_handler.message_handler import handle +from flwr.client.message_handler.message_handler import ( + handle_legacy_message_from_tasktype, +) from flwr.client.middleware.utils import make_ffn -from flwr.client.typing import Bwd, ClientFn, Fwd, Layer +from flwr.client.typing import ClientFn, Layer +from flwr.common.context import Context +from flwr.common.message import Message class Flower: @@ -55,20 +59,21 @@ def __init__( layers: Optional[List[Layer]] = None, ) -> None: # Create wrapper function for `handle` - def ffn(fwd: Fwd) -> Bwd: # pylint: disable=invalid-name - task_res, context_updated = handle( - client_fn=client_fn, - context=fwd.context, - task_ins=fwd.task_ins, + def ffn( + message: Message, + context: Context, + ) -> Message: # pylint: disable=invalid-name + out_message = handle_legacy_message_from_tasktype( + client_fn=client_fn, message=message, context=context ) - return Bwd(task_res=task_res, context=context_updated) + return out_message # Wrap middleware layers around the wrapped handle function self._call = make_ffn(ffn, layers if layers is not None else []) - def __call__(self, fwd: Fwd) -> Bwd: + def __call__(self, message: Message, context: Context) -> Message: """.""" - return self._call(fwd) + return self._call(message, context) class LoadCallableError(Exception): diff --git a/src/py/flwr/client/grpc_client/connection.py b/src/py/flwr/client/grpc_client/connection.py index 5f11912c587c..4ca80642199d 100644 --- a/src/py/flwr/client/grpc_client/connection.py +++ b/src/py/flwr/client/grpc_client/connection.py @@ -20,15 +20,26 @@ from logging import DEBUG from pathlib import Path from queue import Queue -from typing import Callable, Iterator, Optional, Tuple, Union +from typing import Callable, Iterator, Optional, Tuple, Union, cast from flwr.common import GRPC_MAX_MESSAGE_LENGTH +from flwr.common import recordset_compat as compat +from flwr.common import serde +from flwr.common.configsrecord import ConfigsRecord +from flwr.common.constant import ( + TASK_TYPE_EVALUATE, + TASK_TYPE_FIT, + TASK_TYPE_GET_PARAMETERS, + TASK_TYPE_GET_PROPERTIES, +) from flwr.common.grpc import create_channel from flwr.common.logger import log +from flwr.common.recordset import RecordSet from flwr.proto.node_pb2 import Node # pylint: disable=E0611 from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611 from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 ClientMessage, + Reason, ServerMessage, ) from flwr.proto.transport_pb2_grpc import FlowerServiceStub # pylint: disable=E0611 @@ -46,7 +57,7 @@ def on_channel_state_change(channel_connectivity: str) -> None: @contextmanager -def grpc_connection( +def grpc_connection( # pylint: disable=R0915 server_address: str, insecure: bool, max_message_length: int = GRPC_MAX_MESSAGE_LENGTH, @@ -118,7 +129,48 @@ def grpc_connection( server_message_iterator: Iterator[ServerMessage] = stub.Join(iter(queue.get, None)) def receive() -> TaskIns: - server_message = next(server_message_iterator) + # Receive ServerMessage proto + proto = next(server_message_iterator) + + # ServerMessage proto --> *Ins --> RecordSet + field = proto.WhichOneof("msg") + task_type = "" + if field == "get_properties_ins": + recordset = compat.getpropertiesins_to_recordset( + serde.get_properties_ins_from_proto(proto.get_properties_ins) + ) + task_type = TASK_TYPE_GET_PROPERTIES + elif field == "get_parameters_ins": + recordset = compat.getparametersins_to_recordset( + serde.get_parameters_ins_from_proto(proto.get_parameters_ins) + ) + task_type = TASK_TYPE_GET_PARAMETERS + elif field == "fit_ins": + recordset = compat.fitins_to_recordset( + serde.fit_ins_from_proto(proto.fit_ins), False + ) + task_type = TASK_TYPE_FIT + elif field == "evaluate_ins": + recordset = compat.evaluateins_to_recordset( + serde.evaluate_ins_from_proto(proto.evaluate_ins), False + ) + task_type = TASK_TYPE_EVALUATE + elif field == "reconnect_ins": + recordset = RecordSet() + recordset.set_configs( + "config", ConfigsRecord({"seconds": proto.reconnect_ins.seconds}) + ) + task_type = "reconnect" + else: + raise ValueError( + "Unsupported instruction in ServerMessage, " + "cannot deserialize from ProtoBuf" + ) + + # RecordSet --> RecordSet proto + recordset_proto = serde.recordset_to_proto(recordset) + + # Construct TaskIns return TaskIns( task_id=str(uuid.uuid4()), group_id="", @@ -127,13 +179,43 @@ def receive() -> TaskIns: producer=Node(node_id=0, anonymous=True), consumer=Node(node_id=0, anonymous=True), ancestry=[], - legacy_server_message=server_message, + task_type=task_type, + recordset=recordset_proto, ), ) def send(task_res: TaskRes) -> None: - msg = task_res.task.legacy_client_message - return queue.put(msg, block=False) + # Retrieve RecordSet and task_type + recordset = serde.recordset_from_proto(task_res.task.recordset) + task_type = task_res.task.task_type + + # RecordSet --> *Res --> *Res proto -> ClientMessage proto + if task_type == TASK_TYPE_GET_PROPERTIES: + getpropres = compat.recordset_to_getpropertiesres(recordset) + msg_proto = ClientMessage( + get_properties_res=serde.get_properties_res_to_proto(getpropres) + ) + elif task_type == TASK_TYPE_GET_PARAMETERS: + getparamres = compat.recordset_to_getparametersres(recordset, False) + msg_proto = ClientMessage( + get_parameters_res=serde.get_parameters_res_to_proto(getparamres) + ) + elif task_type == TASK_TYPE_FIT: + fitres = compat.recordset_to_fitres(recordset, False) + msg_proto = ClientMessage(fit_res=serde.fit_res_to_proto(fitres)) + elif task_type == TASK_TYPE_EVALUATE: + evalres = compat.recordset_to_evaluateres(recordset) + msg_proto = ClientMessage(evaluate_res=serde.evaluate_res_to_proto(evalres)) + elif task_type == "reconnect": + reason = cast(Reason.ValueType, recordset.get_configs("config")["reason"]) + msg_proto = ClientMessage( + disconnect_res=ClientMessage.DisconnectRes(reason=reason) + ) + else: + raise ValueError(f"Invalid task type: {task_type}") + + # Send ClientMessage proto + return queue.put(msg_proto, block=False) try: # Yield methods diff --git a/src/py/flwr/client/grpc_client/connection_test.py b/src/py/flwr/client/grpc_client/connection_test.py index bcfa76bb36c0..f2b362750df4 100644 --- a/src/py/flwr/client/grpc_client/connection_test.py +++ b/src/py/flwr/client/grpc_client/connection_test.py @@ -23,6 +23,12 @@ import grpc +from flwr.common import recordset_compat as compat +from flwr.common import serde +from flwr.common.configsrecord import ConfigsRecord +from flwr.common.constant import TASK_TYPE_GET_PROPERTIES +from flwr.common.recordset import RecordSet +from flwr.common.typing import Code, GetPropertiesRes, Status from flwr.proto.task_pb2 import Task, TaskRes # pylint: disable=E0611 from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 ClientMessage, @@ -35,11 +41,21 @@ EXPECTED_NUM_SERVER_MESSAGE = 10 -SERVER_MESSAGE = ServerMessage() +SERVER_MESSAGE = ServerMessage(get_properties_ins=ServerMessage.GetPropertiesIns()) SERVER_MESSAGE_RECONNECT = ServerMessage(reconnect_ins=ServerMessage.ReconnectIns()) -CLIENT_MESSAGE = ClientMessage() -CLIENT_MESSAGE_DISCONNECT = ClientMessage(disconnect_res=ClientMessage.DisconnectRes()) +TASK_GET_PROPERTIES = Task( + task_type=TASK_TYPE_GET_PROPERTIES, + recordset=serde.recordset_to_proto( + compat.getpropertiesres_to_recordset(GetPropertiesRes(Status(Code.OK, ""), {})) + ), +) +TASK_DISCONNECT = Task( + task_type="reconnect", + recordset=serde.recordset_to_proto( + RecordSet(configs={"config": ConfigsRecord({"reason": 0})}) + ), +) def unused_tcp_port() -> int: @@ -104,31 +120,14 @@ def run_client() -> int: # Block until server responds with a message task_ins = receive() - if task_ins is None: - raise ValueError("Unexpected None value") - - # pylint: disable=no-member - if task_ins.HasField("task") and task_ins.task.HasField( - "legacy_server_message" - ): - server_message = task_ins.task.legacy_server_message - else: - server_message = None - # pylint: enable=no-member - - if server_message is None: - raise ValueError("Unexpected None value") - messages_received += 1 - if server_message.HasField("reconnect_ins"): - task_res = TaskRes( - task=Task(legacy_client_message=CLIENT_MESSAGE_DISCONNECT) - ) + if task_ins.task.task_type == "reconnect": # type: ignore + task_res = TaskRes(task=TASK_DISCONNECT) send(task_res) break # Process server_message and send client_message... - task_res = TaskRes(task=Task(legacy_client_message=CLIENT_MESSAGE)) + task_res = TaskRes(task=TASK_GET_PROPERTIES) send(task_res) return messages_received diff --git a/src/py/flwr/client/grpc_rere_client/connection.py b/src/py/flwr/client/grpc_rere_client/connection.py index cb1a7021dc9d..e5a4b6883378 100644 --- a/src/py/flwr/client/grpc_rere_client/connection.py +++ b/src/py/flwr/client/grpc_rere_client/connection.py @@ -148,9 +148,7 @@ def receive() -> Optional[TaskIns]: task_ins: Optional[TaskIns] = get_task_ins(response) # Discard the current TaskIns if not valid - if task_ins is not None and not validate_task_ins( - task_ins, discard_reconnect_ins=True - ): + if task_ins is not None and not validate_task_ins(task_ins): task_ins = None # Remember `task_ins` until `task_res` is available diff --git a/src/py/flwr/client/message_handler/message_handler.py b/src/py/flwr/client/message_handler/message_handler.py index 8c920dcc585e..ea87c35c83f7 100644 --- a/src/py/flwr/client/message_handler/message_handler.py +++ b/src/py/flwr/client/message_handler/message_handler.py @@ -15,29 +15,37 @@ """Client-side message handler.""" -from typing import Optional, Tuple +from typing import Optional, Tuple, cast from flwr.client.client import ( - Client, maybe_call_evaluate, maybe_call_fit, maybe_call_get_parameters, maybe_call_get_properties, ) -from flwr.client.message_handler.task_handler import ( - get_server_message_from_task_ins, - wrap_client_message_in_task_res, -) -from flwr.client.secure_aggregation import SecureAggregationHandler from flwr.client.typing import ClientFn from flwr.common import serde +from flwr.common.configsrecord import ConfigsRecord +from flwr.common.constant import ( + TASK_TYPE_EVALUATE, + TASK_TYPE_FIT, + TASK_TYPE_GET_PARAMETERS, + TASK_TYPE_GET_PROPERTIES, +) from flwr.common.context import Context -from flwr.proto.task_pb2 import ( # pylint: disable=E0611 - SecureAggregation, - Task, - TaskIns, - TaskRes, +from flwr.common.message import Message, Metadata +from flwr.common.recordset import RecordSet +from flwr.common.recordset_compat import ( + evaluateres_to_recordset, + fitres_to_recordset, + getparametersres_to_recordset, + getpropertiesres_to_recordset, + recordset_to_evaluateins, + recordset_to_fitins, + recordset_to_getparametersins, + recordset_to_getpropertiesins, ) +from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611 from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 ClientMessage, Reason, @@ -63,118 +71,92 @@ def handle_control_message(task_ins: TaskIns) -> Tuple[Optional[TaskRes], int]: Returns ------- + task_res : Optional[TaskRes] + TaskRes to be sent back to the server. If None, the client should + continue to process messages from the server. sleep_duration : int Number of seconds that the client should disconnect from the server. - keep_going : bool - Flag that indicates whether the client should continue to process the - next message from the server (True) or disconnect and optionally - reconnect later (False). """ - server_msg = get_server_message_from_task_ins(task_ins, exclude_reconnect_ins=False) - - # SecAgg message - if server_msg is None: - return None, 0 - - # ReconnectIns message - field = server_msg.WhichOneof("msg") - if field == "reconnect_ins": - disconnect_msg, sleep_duration = _reconnect(server_msg.reconnect_ins) - task_res = wrap_client_message_in_task_res(disconnect_msg) + if task_ins.task.task_type == "reconnect": + # Retrieve ReconnectIns from recordset + recordset = serde.recordset_from_proto(task_ins.task.recordset) + seconds = cast(int, recordset.get_configs("config")["seconds"]) + # Construct ReconnectIns and call _reconnect + disconnect_msg, sleep_duration = _reconnect( + ServerMessage.ReconnectIns(seconds=seconds) + ) + # Store DisconnectRes in recordset + reason = cast(int, disconnect_msg.disconnect_res.reason) + recordset = RecordSet() + recordset.set_configs("config", ConfigsRecord({"reason": reason})) + task_res = TaskRes( + task=Task( + task_type="reconnect", + recordset=serde.recordset_to_proto(recordset), + ) + ) + # Return TaskRes and sleep duration return task_res, sleep_duration # Any other message return None, 0 -def handle( - client_fn: ClientFn, context: Context, task_ins: TaskIns -) -> Tuple[TaskRes, Context]: - """Handle incoming TaskIns from the server. - - Parameters - ---------- - client_fn : ClientFn - A callable that instantiates a Client. - context : Context - A dataclass storing the context for the run being executed by the client. - task_ins: TaskIns - The task instruction coming from the server, to be processed by the client. - - Returns - ------- - task_res : TaskRes - The task response that should be returned to the server. - """ - server_msg = get_server_message_from_task_ins(task_ins, exclude_reconnect_ins=False) - if server_msg is None: - # Instantiate the client - client = client_fn("-1") - client.set_context(context) - # Secure Aggregation - if task_ins.task.HasField("sa") and isinstance( - client, SecureAggregationHandler - ): - # pylint: disable-next=invalid-name - named_values = serde.named_values_from_proto(task_ins.task.sa.named_values) - res = client.handle_secure_aggregation(named_values) - task_res = TaskRes( - task_id="", - group_id="", - run_id=0, - task=Task( - ancestry=[], - sa=SecureAggregation(named_values=serde.named_values_to_proto(res)), - ), - ) - return task_res, client.get_context() - raise NotImplementedError() - client_msg, updated_context = handle_legacy_message(client_fn, context, server_msg) - task_res = wrap_client_message_in_task_res(client_msg) - return task_res, updated_context - - -def handle_legacy_message( - client_fn: ClientFn, context: Context, server_msg: ServerMessage -) -> Tuple[ClientMessage, Context]: - """Handle incoming messages from the server. - - Parameters - ---------- - client_fn : ClientFn - A callable that instantiates a Client. - context : Context - A dataclass storing the context for the run being executed by the client. - server_msg: ServerMessage - The message coming from the server, to be processed by the client. - - Returns - ------- - client_msg : ClientMessage - The result message that should be returned to the server. - """ - field = server_msg.WhichOneof("msg") - - # Must be handled elsewhere - if field == "reconnect_ins": - raise UnexpectedServerMessage() - - # Instantiate the client +def handle_legacy_message_from_tasktype( + client_fn: ClientFn, message: Message, context: Context +) -> Message: + """Handle legacy message in the inner most middleware layer.""" client = client_fn("-1") + client.set_context(context) - # Execute task - message = None - if field == "get_properties_ins": - message = _get_properties(client, server_msg.get_properties_ins) - if field == "get_parameters_ins": - message = _get_parameters(client, server_msg.get_parameters_ins) - if field == "fit_ins": - message = _fit(client, server_msg.fit_ins) - if field == "evaluate_ins": - message = _evaluate(client, server_msg.evaluate_ins) - if message: - return message, client.get_context() - raise UnknownServerMessage() + + task_type = message.metadata.task_type + + # Handle GetPropertiesIns + if task_type == TASK_TYPE_GET_PROPERTIES: + get_properties_res = maybe_call_get_properties( + client=client, + get_properties_ins=recordset_to_getpropertiesins(message.message), + ) + out_recordset = getpropertiesres_to_recordset(get_properties_res) + # Handle GetParametersIns + elif task_type == TASK_TYPE_GET_PARAMETERS: + get_parameters_res = maybe_call_get_parameters( + client=client, + get_parameters_ins=recordset_to_getparametersins(message.message), + ) + out_recordset = getparametersres_to_recordset( + get_parameters_res, keep_input=True + ) + # Handle FitIns + elif task_type == TASK_TYPE_FIT: + fit_res = maybe_call_fit( + client=client, + fit_ins=recordset_to_fitins(message.message, keep_input=True), + ) + out_recordset = fitres_to_recordset(fit_res, keep_input=True) + # Handle EvaluateIns + elif task_type == TASK_TYPE_EVALUATE: + evaluate_res = maybe_call_evaluate( + client=client, + evaluate_ins=recordset_to_evaluateins(message.message, keep_input=True), + ) + out_recordset = evaluateres_to_recordset(evaluate_res) + else: + raise ValueError(f"Invalid task type: {task_type}") + + # Return Message + out_message = Message( + metadata=Metadata( + run_id=0, # Non-user defined + task_id="", # Non-user defined + group_id="", # Non-user defined + ttl="", + task_type=task_type, + ), + message=out_recordset, + ) + return out_message def _reconnect( @@ -189,67 +171,3 @@ def _reconnect( # Build DisconnectRes message disconnect_res = ClientMessage.DisconnectRes(reason=reason) return ClientMessage(disconnect_res=disconnect_res), sleep_duration - - -def _get_properties( - client: Client, get_properties_msg: ServerMessage.GetPropertiesIns -) -> ClientMessage: - # Deserialize `get_properties` instruction - get_properties_ins = serde.get_properties_ins_from_proto(get_properties_msg) - - # Request properties - get_properties_res = maybe_call_get_properties( - client=client, - get_properties_ins=get_properties_ins, - ) - - # Serialize response - get_properties_res_proto = serde.get_properties_res_to_proto(get_properties_res) - return ClientMessage(get_properties_res=get_properties_res_proto) - - -def _get_parameters( - client: Client, get_parameters_msg: ServerMessage.GetParametersIns -) -> ClientMessage: - # Deserialize `get_parameters` instruction - get_parameters_ins = serde.get_parameters_ins_from_proto(get_parameters_msg) - - # Request parameters - get_parameters_res = maybe_call_get_parameters( - client=client, - get_parameters_ins=get_parameters_ins, - ) - - # Serialize response - get_parameters_res_proto = serde.get_parameters_res_to_proto(get_parameters_res) - return ClientMessage(get_parameters_res=get_parameters_res_proto) - - -def _fit(client: Client, fit_msg: ServerMessage.FitIns) -> ClientMessage: - # Deserialize fit instruction - fit_ins = serde.fit_ins_from_proto(fit_msg) - - # Perform fit - fit_res = maybe_call_fit( - client=client, - fit_ins=fit_ins, - ) - - # Serialize fit result - fit_res_proto = serde.fit_res_to_proto(fit_res) - return ClientMessage(fit_res=fit_res_proto) - - -def _evaluate(client: Client, evaluate_msg: ServerMessage.EvaluateIns) -> ClientMessage: - # Deserialize evaluate instruction - evaluate_ins = serde.evaluate_ins_from_proto(evaluate_msg) - - # Perform evaluation - evaluate_res = maybe_call_evaluate( - client=client, - evaluate_ins=evaluate_ins, - ) - - # Serialize evaluate result - evaluate_res_proto = serde.evaluate_res_to_proto(evaluate_res) - return ClientMessage(evaluate_res=evaluate_res_proto) diff --git a/src/py/flwr/client/message_handler/message_handler_test.py b/src/py/flwr/client/message_handler/message_handler_test.py index 707570cd8e57..ad09ca95abc7 100644 --- a/src/py/flwr/client/message_handler/message_handler_test.py +++ b/src/py/flwr/client/message_handler/message_handler_test.py @@ -20,6 +20,7 @@ from flwr.client import Client from flwr.client.typing import ClientFn from flwr.common import ( + Code, EvaluateIns, EvaluateRes, FitIns, @@ -29,21 +30,16 @@ GetPropertiesIns, GetPropertiesRes, Parameters, - serde, - typing, + Status, ) +from flwr.common import recordset_compat as compat +from flwr.common import typing +from flwr.common.constant import TASK_TYPE_GET_PROPERTIES from flwr.common.context import Context +from flwr.common.message import Message, Metadata from flwr.common.recordset import RecordSet -from flwr.proto.node_pb2 import Node # pylint: disable=E0611 -from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611 -from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 - ClientMessage, - Code, - ServerMessage, - Status, -) -from .message_handler import handle, handle_control_message +from .message_handler import handle_legacy_message_from_tasktype class ClientWithoutProps(Client): @@ -122,137 +118,73 @@ def test_client_without_get_properties() -> None: """Test client implementing get_properties.""" # Prepare client = ClientWithoutProps() - ins = ServerMessage.GetPropertiesIns() - - task_ins: TaskIns = TaskIns( - task_id=str(uuid.uuid4()), - group_id="", - run_id=0, - task=Task( - producer=Node(node_id=0, anonymous=True), - consumer=Node(node_id=0, anonymous=True), - ancestry=[], - legacy_server_message=ServerMessage(get_properties_ins=ins), + recordset = compat.getpropertiesins_to_recordset(GetPropertiesIns({})) + message = Message( + metadata=Metadata( + run_id=0, + task_id=str(uuid.uuid4()), + group_id="", + ttl="", + task_type=TASK_TYPE_GET_PROPERTIES, ), + message=recordset, ) # Execute - disconnect_task_res, actual_sleep_duration = handle_control_message( - task_ins=task_ins - ) - task_res, _ = handle( + actual_msg = handle_legacy_message_from_tasktype( client_fn=_get_client_fn(client), + message=message, context=Context(state=RecordSet()), - task_ins=task_ins, - ) - - if not task_res.HasField("task"): - raise ValueError("Task value not found") - - # pylint: disable=no-member - if not task_res.task.HasField("legacy_client_message"): - raise ValueError("Unexpected None value") - # pylint: enable=no-member - - task_res.MergeFrom( - TaskRes( - task_id=str(uuid.uuid4()), - group_id="", - run_id=0, - ) - ) - # pylint: disable=no-member - task_res.task.MergeFrom( - Task( - producer=Node(node_id=0, anonymous=True), - consumer=Node(node_id=0, anonymous=True), - ancestry=[task_ins.task_id], - ) ) - actual_msg = task_res.task.legacy_client_message - # pylint: enable=no-member - # Assert - expected_get_properties_res = ClientMessage.GetPropertiesRes( + expected_get_properties_res = GetPropertiesRes( status=Status( code=Code.GET_PROPERTIES_NOT_IMPLEMENTED, message="Client does not implement `get_properties`", - ) + ), + properties={}, ) - expected_msg = ClientMessage(get_properties_res=expected_get_properties_res) + expected_rs = compat.getpropertiesres_to_recordset(expected_get_properties_res) + expected_msg = Message(message.metadata, expected_rs) - assert actual_msg == expected_msg - assert not disconnect_task_res - assert actual_sleep_duration == 0 + assert actual_msg.message == expected_msg.message + assert actual_msg.metadata.task_type == expected_msg.metadata.task_type def test_client_with_get_properties() -> None: """Test client not implementing get_properties.""" # Prepare client = ClientWithProps() - ins = ServerMessage.GetPropertiesIns() - task_ins = TaskIns( - task_id=str(uuid.uuid4()), - group_id="", - run_id=0, - task=Task( - producer=Node(node_id=0, anonymous=True), - consumer=Node(node_id=0, anonymous=True), - ancestry=[], - legacy_server_message=ServerMessage(get_properties_ins=ins), + recordset = compat.getpropertiesins_to_recordset(GetPropertiesIns({})) + message = Message( + metadata=Metadata( + run_id=0, + task_id=str(uuid.uuid4()), + group_id="", + ttl="", + task_type=TASK_TYPE_GET_PROPERTIES, ), + message=recordset, ) # Execute - disconnect_task_res, actual_sleep_duration = handle_control_message( - task_ins=task_ins - ) - task_res, _ = handle( + actual_msg = handle_legacy_message_from_tasktype( client_fn=_get_client_fn(client), + message=message, context=Context(state=RecordSet()), - task_ins=task_ins, ) - if not task_res.HasField("task"): - raise ValueError("Task value not found") - - # pylint: disable=no-member - if not task_res.task.HasField("legacy_client_message"): - raise ValueError("Unexpected None value") - # pylint: enable=no-member - - task_res.MergeFrom( - TaskRes( - task_id=str(uuid.uuid4()), - group_id="", - run_id=0, - ) - ) - # pylint: disable=no-member - task_res.task.MergeFrom( - Task( - producer=Node(node_id=0, anonymous=True), - consumer=Node(node_id=0, anonymous=True), - ancestry=[task_ins.task_id], - ) - ) - - actual_msg = task_res.task.legacy_client_message - # pylint: enable=no-member - # Assert - expected_get_properties_res = ClientMessage.GetPropertiesRes( + expected_get_properties_res = GetPropertiesRes( status=Status( code=Code.OK, message="Success", ), - properties=serde.properties_to_proto( - properties={"str_prop": "val", "int_prop": 1} - ), + properties={"str_prop": "val", "int_prop": 1}, ) - expected_msg = ClientMessage(get_properties_res=expected_get_properties_res) + expected_rs = compat.getpropertiesres_to_recordset(expected_get_properties_res) + expected_msg = Message(message.metadata, expected_rs) - assert actual_msg == expected_msg - assert not disconnect_task_res - assert actual_sleep_duration == 0 + assert actual_msg.message == expected_msg.message + assert actual_msg.metadata.task_type == expected_msg.metadata.task_type diff --git a/src/py/flwr/client/message_handler/task_handler.py b/src/py/flwr/client/message_handler/task_handler.py index 667cb9c98d46..daac1be77138 100644 --- a/src/py/flwr/client/message_handler/task_handler.py +++ b/src/py/flwr/client/message_handler/task_handler.py @@ -20,21 +20,15 @@ from flwr.proto.fleet_pb2 import PullTaskInsResponse # pylint: disable=E0611 from flwr.proto.node_pb2 import Node # pylint: disable=E0611 from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611 -from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 - ClientMessage, - ServerMessage, -) -def validate_task_ins(task_ins: TaskIns, discard_reconnect_ins: bool) -> bool: +def validate_task_ins(task_ins: TaskIns) -> bool: """Validate a TaskIns before it entering the message handling process. Parameters ---------- task_ins: TaskIns The task instruction coming from the server. - discard_reconnect_ins: bool - If True, ReconnectIns will not be considered as valid content. Returns ------- @@ -42,23 +36,8 @@ def validate_task_ins(task_ins: TaskIns, discard_reconnect_ins: bool) -> bool: True if the TaskIns is deemed valid and therefore suitable for undergoing the message handling process, False otherwise. """ - # Check if the task_ins contains legacy_server_message or sa. - # If legacy_server_message is set, check if ServerMessage is one of - # {GetPropertiesIns, GetParametersIns, FitIns, EvaluateIns, ReconnectIns*} - # Discard ReconnectIns if discard_reconnect_ins is true. - if ( - not task_ins.HasField("task") - or ( - not task_ins.task.HasField("legacy_server_message") - and not task_ins.task.HasField("sa") - ) - or ( - discard_reconnect_ins - and task_ins.task.legacy_server_message.WhichOneof("msg") == "reconnect_ins" - ) - ): + if not (task_ins.HasField("task") and task_ins.task.HasField("recordset")): return False - return True @@ -110,32 +89,6 @@ def get_task_ins( return task_ins -def get_server_message_from_task_ins( - task_ins: TaskIns, exclude_reconnect_ins: bool -) -> Optional[ServerMessage]: - """Get ServerMessage from TaskIns, if available.""" - # Return the message if it is in - # {GetPropertiesIns, GetParametersIns, FitIns, EvaluateIns} - # Return the message if it is ReconnectIns and exclude_reconnect_ins is False. - if not validate_task_ins( - task_ins, discard_reconnect_ins=exclude_reconnect_ins - ) or not task_ins.task.HasField("legacy_server_message"): - return None - - return task_ins.task.legacy_server_message - - -def wrap_client_message_in_task_res(client_message: ClientMessage) -> TaskRes: - """Wrap ClientMessage in TaskRes.""" - # Instantiate a TaskRes, only filling client_message field. - return TaskRes( - task_id="", - group_id="", - run_id=0, - task=Task(ancestry=[], legacy_client_message=client_message), - ) - - def configure_task_res( task_res: TaskRes, ref_task_ins: TaskIns, producer: Node ) -> TaskRes: diff --git a/src/py/flwr/client/message_handler/task_handler_test.py b/src/py/flwr/client/message_handler/task_handler_test.py index c1111d0935c0..9a668231d509 100644 --- a/src/py/flwr/client/message_handler/task_handler_test.py +++ b/src/py/flwr/client/message_handler/task_handler_test.py @@ -16,75 +16,35 @@ from flwr.client.message_handler.task_handler import ( - get_server_message_from_task_ins, get_task_ins, validate_task_ins, validate_task_res, - wrap_client_message_in_task_res, ) +from flwr.common import serde +from flwr.common.recordset import RecordSet from flwr.proto.fleet_pb2 import PullTaskInsResponse # pylint: disable=E0611 -from flwr.proto.task_pb2 import ( # pylint: disable=E0611 - SecureAggregation, - Task, - TaskIns, - TaskRes, -) -from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 - ClientMessage, - ServerMessage, -) +from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611 def test_validate_task_ins_no_task() -> None: """Test validate_task_ins.""" task_ins = TaskIns(task=None) - assert not validate_task_ins(task_ins, discard_reconnect_ins=True) - assert not validate_task_ins(task_ins, discard_reconnect_ins=False) + assert not validate_task_ins(task_ins) def test_validate_task_ins_no_content() -> None: """Test validate_task_ins.""" - task_ins = TaskIns(task=Task(legacy_server_message=None, sa=None)) - - assert not validate_task_ins(task_ins, discard_reconnect_ins=True) - assert not validate_task_ins(task_ins, discard_reconnect_ins=False) - - -def test_validate_task_ins_with_reconnect_ins() -> None: - """Test validate_task_ins.""" - task_ins = TaskIns( - task=Task( - legacy_server_message=ServerMessage( - reconnect_ins=ServerMessage.ReconnectIns(seconds=3) - ) - ) - ) - - assert not validate_task_ins(task_ins, discard_reconnect_ins=True) - assert validate_task_ins(task_ins, discard_reconnect_ins=False) - - -def test_validate_task_ins_valid_legacy_server_message() -> None: - """Test validate_task_ins.""" - task_ins = TaskIns( - task=Task( - legacy_server_message=ServerMessage( - get_properties_ins=ServerMessage.GetPropertiesIns() - ) - ) - ) + task_ins = TaskIns(task=Task(recordset=None)) - assert validate_task_ins(task_ins, discard_reconnect_ins=True) - assert validate_task_ins(task_ins, discard_reconnect_ins=False) + assert not validate_task_ins(task_ins) -def test_validate_task_ins_valid_sa() -> None: +def test_validate_task_ins_valid() -> None: """Test validate_task_ins.""" - task_ins = TaskIns(task=Task(sa=SecureAggregation())) + task_ins = TaskIns(task=Task(recordset=serde.recordset_to_proto(RecordSet()))) - assert validate_task_ins(task_ins, discard_reconnect_ins=True) - assert validate_task_ins(task_ins, discard_reconnect_ins=False) + assert validate_task_ins(task_ins) def test_validate_task_res() -> None: @@ -142,61 +102,3 @@ def test_get_task_ins_multiple_ins() -> None: ) actual_task_ins = get_task_ins(res) assert actual_task_ins == expected_task_ins - - -def test_get_server_message_from_task_ins_invalid() -> None: - """Test get_server_message_from_task_ins.""" - task_ins = TaskIns(task=Task(legacy_server_message=None)) - msg_t = get_server_message_from_task_ins(task_ins, exclude_reconnect_ins=True) - msg_f = get_server_message_from_task_ins(task_ins, exclude_reconnect_ins=False) - - assert msg_t is None - assert msg_f is None - - -def test_get_server_message_from_task_ins_reconnect_ins() -> None: - """Test get_server_message_from_task_ins.""" - expected_server_message = ServerMessage( - reconnect_ins=ServerMessage.ReconnectIns(seconds=3) - ) - task_ins = TaskIns(task=Task(legacy_server_message=expected_server_message)) - msg_t = get_server_message_from_task_ins(task_ins, exclude_reconnect_ins=True) - msg_f = get_server_message_from_task_ins(task_ins, exclude_reconnect_ins=False) - - assert msg_t is None - assert msg_f == expected_server_message - - -def test_get_server_message_from_task_ins_sa() -> None: - """Test get_server_message_from_task_ins.""" - task_ins = TaskIns(task=Task(sa=SecureAggregation())) - msg_t = get_server_message_from_task_ins(task_ins, exclude_reconnect_ins=True) - msg_f = get_server_message_from_task_ins(task_ins, exclude_reconnect_ins=False) - - assert msg_t is None - assert msg_f is None - - -def test_get_server_message_from_task_ins_valid_legacy_server_message() -> None: - """Test get_server_message_from_task_ins.""" - expected_server_message = ServerMessage( - get_properties_ins=ServerMessage.GetPropertiesIns() - ) - task_ins = TaskIns(task=Task(legacy_server_message=expected_server_message)) - msg_t = get_server_message_from_task_ins(task_ins, exclude_reconnect_ins=True) - msg_f = get_server_message_from_task_ins(task_ins, exclude_reconnect_ins=False) - - assert msg_t == expected_server_message - assert msg_f == expected_server_message - - -def test_wrap_client_message_in_task_res() -> None: - """Test wrap_client_message_in_task_res.""" - expected_client_message = ClientMessage( - get_properties_res=ClientMessage.GetPropertiesRes() - ) - task_res = wrap_client_message_in_task_res(expected_client_message) - - assert validate_task_res(task_res) - # pylint: disable-next=no-member - assert task_res.task.legacy_client_message == expected_client_message diff --git a/src/py/flwr/client/middleware/utils.py b/src/py/flwr/client/middleware/utils.py index d93132403c1e..6d24da558576 100644 --- a/src/py/flwr/client/middleware/utils.py +++ b/src/py/flwr/client/middleware/utils.py @@ -17,15 +17,17 @@ from typing import List -from flwr.client.typing import Bwd, FlowerCallable, Fwd, Layer +from flwr.client.typing import FlowerCallable, Layer +from flwr.common.context import Context +from flwr.common.message import Message def make_ffn(ffn: FlowerCallable, layers: List[Layer]) -> FlowerCallable: """.""" def wrap_ffn(_ffn: FlowerCallable, _layer: Layer) -> FlowerCallable: - def new_ffn(fwd: Fwd) -> Bwd: - return _layer(fwd, _ffn) + def new_ffn(message: Message, context: Context) -> Message: + return _layer(message, context, _ffn) return new_ffn diff --git a/src/py/flwr/client/middleware/utils_test.py b/src/py/flwr/client/middleware/utils_test.py index fe3f7832ceb2..a4e1f6e87599 100644 --- a/src/py/flwr/client/middleware/utils_test.py +++ b/src/py/flwr/client/middleware/utils_test.py @@ -18,24 +18,41 @@ import unittest from typing import List -from flwr.client.typing import Bwd, FlowerCallable, Fwd, Layer +from flwr.client.typing import FlowerCallable, Layer +from flwr.common.configsrecord import ConfigsRecord from flwr.common.context import Context +from flwr.common.message import Message, Metadata +from flwr.common.metricsrecord import MetricsRecord from flwr.common.recordset import RecordSet -from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611 from .utils import make_ffn +METRIC = "context" +COUNTER = "counter" + + +def _increment_context_counter(context: Context) -> None: + # Read from context + current_counter: int = context.state.get_metrics(METRIC)[COUNTER] # type: ignore + # update and override context + current_counter += 1 + context.state.set_metrics(METRIC, record=MetricsRecord({COUNTER: current_counter})) + def make_mock_middleware(name: str, footprint: List[str]) -> Layer: """Make a mock middleware layer.""" - def middleware(fwd: Fwd, app: FlowerCallable) -> Bwd: + def middleware(message: Message, context: Context, app: FlowerCallable) -> Message: footprint.append(name) - fwd.task_ins.task_id += f"{name}" - bwd = app(fwd) + # add empty ConfigRecord to in_message for this middleware layer + message.message.set_configs(name=name, record=ConfigsRecord()) + _increment_context_counter(context) + out_message: Message = app(message, context) footprint.append(name) - bwd.task_res.task_id += f"{name}" - return bwd + _increment_context_counter(context) + # add empty ConfigRegcord to out_message for this middleware layer + out_message.message.set_configs(name=name, record=ConfigsRecord()) + return out_message return middleware @@ -43,14 +60,24 @@ def middleware(fwd: Fwd, app: FlowerCallable) -> Bwd: def make_mock_app(name: str, footprint: List[str]) -> FlowerCallable: """Make a mock app.""" - def app(fwd: Fwd) -> Bwd: + def app(message: Message, context: Context) -> Message: footprint.append(name) - fwd.task_ins.task_id += f"{name}" - return Bwd(task_res=TaskRes(task_id=name), context=Context(state=RecordSet())) + message.message.set_configs(name=name, record=ConfigsRecord()) + out_message = Message(metadata=message.metadata, message=RecordSet()) + out_message.message.set_configs(name=name, record=ConfigsRecord()) + print(context) + return out_message return app +def _get_dummy_flower_message() -> Message: + return Message( + message=RecordSet(), + metadata=Metadata(run_id=0, task_id="", group_id="", ttl="", task_type="mock"), + ) + + class TestMakeApp(unittest.TestCase): """Tests for the `make_app` function.""" @@ -63,42 +90,54 @@ def test_multiple_middlewares(self) -> None: mock_middleware_layers = [ make_mock_middleware(name, footprint) for name in mock_middleware_names ] - task_ins = TaskIns() + + state = RecordSet() + state.set_metrics(METRIC, record=MetricsRecord({COUNTER: 0.0})) + context = Context(state=state) + message = _get_dummy_flower_message() # Execute wrapped_app = make_ffn(mock_app, mock_middleware_layers) - dummy_context = Context(state=RecordSet()) - task_res = wrapped_app(Fwd(task_ins=task_ins, context=dummy_context)).task_res + out_message = wrapped_app(message, context) # Assert trace = mock_middleware_names + ["app"] self.assertEqual(footprint, trace + list(reversed(mock_middleware_names))) # pylint: disable-next=no-member - self.assertEqual(task_ins.task_id, "".join(trace)) - self.assertEqual(task_res.task_id, "".join(reversed(trace))) + self.assertEqual("".join(message.message.configs.keys()), "".join(trace)) + self.assertEqual( + "".join(out_message.message.configs.keys()), "".join(reversed(trace)) + ) + self.assertEqual( + state.get_metrics(METRIC)[COUNTER], 2 * len(mock_middleware_layers) + ) def test_filter(self) -> None: """Test if a middleware can filter incoming TaskIns.""" # Prepare footprint: List[str] = [] mock_app = make_mock_app("app", footprint) - task_ins = TaskIns() - - def filter_layer(fwd: Fwd, _: FlowerCallable) -> Bwd: + context = Context(state=RecordSet()) + message = _get_dummy_flower_message() + + def filter_layer( + message: Message, + _1: Context, + _2: FlowerCallable, + ) -> Message: footprint.append("filter") - fwd.task_ins.task_id += "filter" + message.message.set_configs(name="filter", record=ConfigsRecord()) + out_message = Message(metadata=message.metadata, message=RecordSet()) + out_message.message.set_configs(name="filter", record=ConfigsRecord()) # Skip calling app - return Bwd( - task_res=TaskRes(task_id="filter"), context=Context(state=RecordSet()) - ) + return out_message # Execute wrapped_app = make_ffn(mock_app, [filter_layer]) - dummy_context = Context(state=RecordSet()) - task_res = wrapped_app(Fwd(task_ins=task_ins, context=dummy_context)).task_res + out_message = wrapped_app(message, context) # Assert self.assertEqual(footprint, ["filter"]) # pylint: disable-next=no-member - self.assertEqual(task_ins.task_id, "filter") - self.assertEqual(task_res.task_id, "filter") + self.assertEqual(list(message.message.configs.keys())[0], "filter") + self.assertEqual(list(out_message.message.configs.keys())[0], "filter") diff --git a/src/py/flwr/client/rest_client/connection.py b/src/py/flwr/client/rest_client/connection.py index bb55f130f1a8..1ab15f57e521 100644 --- a/src/py/flwr/client/rest_client/connection.py +++ b/src/py/flwr/client/rest_client/connection.py @@ -256,9 +256,7 @@ def receive() -> Optional[TaskIns]: task_ins: Optional[TaskIns] = get_task_ins(pull_task_ins_response_proto) # Discard the current TaskIns if not valid - if task_ins is not None and not validate_task_ins( - task_ins, discard_reconnect_ins=True - ): + if task_ins is not None and not validate_task_ins(task_ins): task_ins = None # Remember `task_ins` until `task_res` is available diff --git a/src/py/flwr/client/typing.py b/src/py/flwr/client/typing.py index 8f7940405f42..18ddcb62f23f 100644 --- a/src/py/flwr/client/typing.py +++ b/src/py/flwr/client/typing.py @@ -14,31 +14,13 @@ # ============================================================================== """Custom types for Flower clients.""" -from dataclasses import dataclass from typing import Callable from flwr.common.context import Context -from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611 +from flwr.common.message import Message from .client import Client as Client - -@dataclass -class Fwd: - """.""" - - task_ins: TaskIns - context: Context - - -@dataclass -class Bwd: - """.""" - - task_res: TaskRes - context: Context - - -FlowerCallable = Callable[[Fwd], Bwd] +FlowerCallable = Callable[[Message, Context], Message] ClientFn = Callable[[str], Client] -Layer = Callable[[Fwd, FlowerCallable], Bwd] +Layer = Callable[[Message, Context, FlowerCallable], Message] diff --git a/src/py/flwr/common/constant.py b/src/py/flwr/common/constant.py index 49802f2815be..8d1d865f084b 100644 --- a/src/py/flwr/common/constant.py +++ b/src/py/flwr/common/constant.py @@ -31,3 +31,8 @@ TRANSPORT_TYPE_GRPC_RERE, TRANSPORT_TYPE_REST, ] + +TASK_TYPE_GET_PROPERTIES = "get_properties" +TASK_TYPE_GET_PARAMETERS = "get_parameters" +TASK_TYPE_FIT = "fit" +TASK_TYPE_EVALUATE = "evaluate" diff --git a/src/py/flwr/driver/driver_client_proxy.py b/src/py/flwr/driver/driver_client_proxy.py index 8b2e51c17ea0..e0ff26c035f7 100644 --- a/src/py/flwr/driver/driver_client_proxy.py +++ b/src/py/flwr/driver/driver_client_proxy.py @@ -16,16 +16,19 @@ import time -from typing import List, Optional, cast +from typing import List, Optional from flwr import common +from flwr.common import recordset_compat as compat from flwr.common import serde -from flwr.proto import ( # pylint: disable=E0611 - driver_pb2, - node_pb2, - task_pb2, - transport_pb2, +from flwr.common.constant import ( + TASK_TYPE_EVALUATE, + TASK_TYPE_FIT, + TASK_TYPE_GET_PARAMETERS, + TASK_TYPE_GET_PROPERTIES, ) +from flwr.common.recordset import RecordSet +from flwr.proto import driver_pb2, node_pb2, task_pb2 # pylint: disable=E0611 from flwr.server.client_proxy import ClientProxy from .grpc_driver import GrpcDriver @@ -47,55 +50,51 @@ def get_properties( self, ins: common.GetPropertiesIns, timeout: Optional[float] ) -> common.GetPropertiesRes: """Return client's properties.""" - server_message_proto: transport_pb2.ServerMessage = ( # pylint: disable=E1101 - serde.server_message_to_proto( - server_message=common.ServerMessage(get_properties_ins=ins) - ) - ) - return cast( - common.GetPropertiesRes, - self._send_receive_msg(server_message_proto, timeout).get_properties_res, + # Ins to RecordSet + out_recordset = compat.getpropertiesins_to_recordset(ins) + # Fetch response + in_recordset = self._send_receive_recordset( + out_recordset, TASK_TYPE_GET_PROPERTIES, timeout ) + # RecordSet to Res + return compat.recordset_to_getpropertiesres(in_recordset) def get_parameters( self, ins: common.GetParametersIns, timeout: Optional[float] ) -> common.GetParametersRes: """Return the current local model parameters.""" - server_message_proto: transport_pb2.ServerMessage = ( # pylint: disable=E1101 - serde.server_message_to_proto( - server_message=common.ServerMessage(get_parameters_ins=ins) - ) - ) - return cast( - common.GetParametersRes, - self._send_receive_msg(server_message_proto, timeout).get_parameters_res, + # Ins to RecordSet + out_recordset = compat.getparametersins_to_recordset(ins) + # Fetch response + in_recordset = self._send_receive_recordset( + out_recordset, TASK_TYPE_GET_PARAMETERS, timeout ) + # RecordSet to Res + return compat.recordset_to_getparametersres(in_recordset, False) def fit(self, ins: common.FitIns, timeout: Optional[float]) -> common.FitRes: """Train model parameters on the locally held dataset.""" - server_message_proto: transport_pb2.ServerMessage = ( # pylint: disable=E1101 - serde.server_message_to_proto( - server_message=common.ServerMessage(fit_ins=ins) - ) - ) - return cast( - common.FitRes, - self._send_receive_msg(server_message_proto, timeout).fit_res, + # Ins to RecordSet + out_recordset = compat.fitins_to_recordset(ins, keep_input=True) + # Fetch response + in_recordset = self._send_receive_recordset( + out_recordset, TASK_TYPE_FIT, timeout ) + # RecordSet to Res + return compat.recordset_to_fitres(in_recordset, keep_input=False) def evaluate( self, ins: common.EvaluateIns, timeout: Optional[float] ) -> common.EvaluateRes: """Evaluate model parameters on the locally held dataset.""" - server_message_proto: transport_pb2.ServerMessage = ( # pylint: disable=E1101 - serde.server_message_to_proto( - server_message=common.ServerMessage(evaluate_ins=ins) - ) - ) - return cast( - common.EvaluateRes, - self._send_receive_msg(server_message_proto, timeout).evaluate_res, + # Ins to RecordSet + out_recordset = compat.evaluateins_to_recordset(ins, keep_input=True) + # Fetch response + in_recordset = self._send_receive_recordset( + out_recordset, TASK_TYPE_EVALUATE, timeout ) + # RecordSet to Res + return compat.recordset_to_evaluateres(in_recordset) def reconnect( self, ins: common.ReconnectIns, timeout: Optional[float] @@ -103,11 +102,12 @@ def reconnect( """Disconnect and (optionally) reconnect later.""" return common.DisconnectRes(reason="") # Nothing to do here (yet) - def _send_receive_msg( + def _send_receive_recordset( self, - server_message: transport_pb2.ServerMessage, # pylint: disable=E1101 + recordset: RecordSet, + task_type: str, timeout: Optional[float], - ) -> transport_pb2.ClientMessage: # pylint: disable=E1101 + ) -> RecordSet: task_ins = task_pb2.TaskIns( # pylint: disable=E1101 task_id="", group_id="", @@ -121,7 +121,8 @@ def _send_receive_msg( node_id=self.node_id, anonymous=self.anonymous, ), - legacy_server_message=server_message, + task_type=task_type, + recordset=serde.recordset_to_proto(recordset), ), ) push_task_ins_req = driver_pb2.PushTaskInsRequest( # pylint: disable=E1101 @@ -155,9 +156,7 @@ def _send_receive_msg( ) if len(task_res_list) == 1: task_res = task_res_list[0] - return serde.client_message_from_proto( # type: ignore - task_res.task.legacy_client_message - ) + return serde.recordset_from_proto(task_res.task.recordset) if timeout is not None and time.time() > start_time + timeout: raise RuntimeError("Timeout reached") diff --git a/src/py/flwr/driver/driver_client_proxy_test.py b/src/py/flwr/driver/driver_client_proxy_test.py index d3cab152e4db..4e9a02a6cbf9 100644 --- a/src/py/flwr/driver/driver_client_proxy_test.py +++ b/src/py/flwr/driver/driver_client_proxy_test.py @@ -16,23 +16,63 @@ import unittest +from typing import Union, cast from unittest.mock import MagicMock import numpy as np import flwr -from flwr.common.typing import Config, GetParametersIns -from flwr.driver.driver_client_proxy import DriverClientProxy -from flwr.proto import driver_pb2, node_pb2, task_pb2 # pylint: disable=E0611 -from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 - ClientMessage, +from flwr.common import recordset_compat as compat +from flwr.common import serde +from flwr.common.constant import ( + TASK_TYPE_EVALUATE, + TASK_TYPE_FIT, + TASK_TYPE_GET_PARAMETERS, + TASK_TYPE_GET_PROPERTIES, +) +from flwr.common.typing import ( + Code, + Config, + EvaluateIns, + EvaluateRes, + FitRes, + GetParametersIns, + GetParametersRes, + GetPropertiesRes, Parameters, - Scalar, + Properties, + Status, ) +from flwr.driver.driver_client_proxy import DriverClientProxy +from flwr.proto import driver_pb2, node_pb2, task_pb2 # pylint: disable=E0611 MESSAGE_PARAMETERS = Parameters(tensors=[b"abc"], tensor_type="np") -CLIENT_PROPERTIES = {"tensor_type": Scalar(string="numpy.ndarray")} +CLIENT_PROPERTIES = cast(Properties, {"tensor_type": "numpy.ndarray"}) +CLIENT_STATUS = Status(code=Code.OK, message="OK") + + +def _make_task( + res: Union[GetParametersRes, GetPropertiesRes, FitRes, EvaluateRes] +) -> task_pb2.Task: # pylint: disable=E1101 + if isinstance(res, GetParametersRes): + task_type = TASK_TYPE_GET_PARAMETERS + recordset = compat.getparametersres_to_recordset(res, True) + elif isinstance(res, GetPropertiesRes): + task_type = TASK_TYPE_GET_PROPERTIES + recordset = compat.getpropertiesres_to_recordset(res) + elif isinstance(res, FitRes): + task_type = TASK_TYPE_FIT + recordset = compat.fitres_to_recordset(res, True) + elif isinstance(res, EvaluateRes): + task_type = TASK_TYPE_EVALUATE + recordset = compat.evaluateres_to_recordset(res) + else: + raise ValueError(f"Unsupported type: {type(res)}") + return task_pb2.Task( # pylint: disable=E1101 + task_type=task_type, + recordset=serde.recordset_to_proto(recordset), + ) class DriverClientProxyTestCase(unittest.TestCase): @@ -64,11 +104,9 @@ def test_get_properties(self) -> None: task_id="554bd3c8-8474-4b93-a7db-c7bec1bf0012", group_id="", run_id=0, - task=task_pb2.Task( # pylint: disable=E1101 - legacy_client_message=ClientMessage( - get_properties_res=ClientMessage.GetPropertiesRes( - properties=CLIENT_PROPERTIES - ) + task=_make_task( + GetPropertiesRes( + status=CLIENT_STATUS, properties=CLIENT_PROPERTIES ) ), ) @@ -104,11 +142,10 @@ def test_get_parameters(self) -> None: task_id="554bd3c8-8474-4b93-a7db-c7bec1bf0012", group_id="", run_id=0, - task=task_pb2.Task( # pylint: disable=E1101 - legacy_client_message=ClientMessage( - get_parameters_res=ClientMessage.GetParametersRes( - parameters=MESSAGE_PARAMETERS, - ) + task=_make_task( + GetParametersRes( + status=CLIENT_STATUS, + parameters=MESSAGE_PARAMETERS, ) ), ) @@ -143,12 +180,12 @@ def test_fit(self) -> None: task_id="554bd3c8-8474-4b93-a7db-c7bec1bf0012", group_id="", run_id=0, - task=task_pb2.Task( # pylint: disable=E1101 - legacy_client_message=ClientMessage( - fit_res=ClientMessage.FitRes( - parameters=MESSAGE_PARAMETERS, - num_examples=10, - ) + task=_make_task( + FitRes( + status=CLIENT_STATUS, + parameters=MESSAGE_PARAMETERS, + num_examples=10, + metrics={}, ) ), ) @@ -184,11 +221,12 @@ def test_evaluate(self) -> None: task_id="554bd3c8-8474-4b93-a7db-c7bec1bf0012", group_id="", run_id=0, - task=task_pb2.Task( # pylint: disable=E1101 - legacy_client_message=ClientMessage( - evaluate_res=ClientMessage.EvaluateRes( - loss=0.0, num_examples=0 - ) + task=_make_task( + EvaluateRes( + status=CLIENT_STATUS, + loss=0.0, + num_examples=0, + metrics={}, ) ), ) @@ -198,8 +236,8 @@ def test_evaluate(self) -> None: client = DriverClientProxy( node_id=1, driver=self.driver, anonymous=True, run_id=0 ) - parameters = flwr.common.Parameters(tensors=[], tensor_type="np") - evaluate_ins: flwr.common.EvaluateIns = flwr.common.EvaluateIns(parameters, {}) + parameters = Parameters(tensors=[], tensor_type="np") + evaluate_ins = EvaluateIns(parameters, {}) # Execute evaluate_res = client.evaluate(evaluate_ins, timeout=None) diff --git a/src/py/flwr/flower/__init__.py b/src/py/flwr/flower/__init__.py index 892a7ce5afdc..8b566981c77a 100644 --- a/src/py/flwr/flower/__init__.py +++ b/src/py/flwr/flower/__init__.py @@ -16,11 +16,7 @@ from flwr.client.flower import Flower as Flower -from flwr.client.typing import Bwd as Bwd -from flwr.client.typing import Fwd as Fwd __all__ = [ "Flower", - "Fwd", - "Bwd", ] diff --git a/src/py/flwr/server/state/state_test.py b/src/py/flwr/server/state/state_test.py index 7f9094625765..95d764792ff3 100644 --- a/src/py/flwr/server/state/state_test.py +++ b/src/py/flwr/server/state/state_test.py @@ -23,11 +23,8 @@ from uuid import uuid4 from flwr.proto.node_pb2 import Node # pylint: disable=E0611 +from flwr.proto.recordset_pb2 import RecordSet # pylint: disable=E0611 from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611 -from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 - ClientMessage, - ServerMessage, -) from flwr.server.state import InMemoryState, SqliteState, State @@ -421,9 +418,8 @@ def create_task_ins( delivered_at=delivered_at, producer=Node(node_id=0, anonymous=True), consumer=consumer, - legacy_server_message=ServerMessage( - reconnect_ins=ServerMessage.ReconnectIns() - ), + task_type="mock", + recordset=RecordSet(parameters={}, metrics={}, configs={}), ), ) return task @@ -444,9 +440,8 @@ def create_task_res( producer=Node(node_id=producer_node_id, anonymous=anonymous), consumer=Node(node_id=0, anonymous=True), ancestry=ancestry, - legacy_client_message=ClientMessage( - disconnect_res=ClientMessage.DisconnectRes() - ), + task_type="mock", + recordset=RecordSet(parameters={}, metrics={}, configs={}), ), ) return task_res diff --git a/src/py/flwr/server/utils/validator.py b/src/py/flwr/server/utils/validator.py index 01dbcf982cce..f9b271beafdc 100644 --- a/src/py/flwr/server/utils/validator.py +++ b/src/py/flwr/server/utils/validator.py @@ -64,21 +64,10 @@ def validate_task_ins_or_res(tasks_ins_res: Union[TaskIns, TaskRes]) -> List[str validation_errors.append("non-anonymous consumer MUST provide a `node_id`") # Content check - has_fields = { - "sa": tasks_ins_res.task.HasField("sa"), - "legacy_server_message": tasks_ins_res.task.HasField( - "legacy_server_message" - ), - } - if not (has_fields["sa"] or has_fields["legacy_server_message"]): - err_msg = ", ".join([f"`{field}`" for field in has_fields]) - validation_errors.append( - f"`task` in `TaskIns` must set at least one of fields {{{err_msg}}}" - ) - if has_fields[ - "legacy_server_message" - ] and not tasks_ins_res.task.legacy_server_message.HasField("msg"): - validation_errors.append("`legacy_server_message` does not set field `msg`") + if tasks_ins_res.task.task_type == "": + validation_errors.append("`task_type` MUST be set") + if not tasks_ins_res.task.HasField("recordset"): + validation_errors.append("`recordset` MUST be set") # Ancestors if len(tasks_ins_res.task.ancestry) != 0: @@ -115,21 +104,10 @@ def validate_task_ins_or_res(tasks_ins_res: Union[TaskIns, TaskRes]) -> List[str validation_errors.append("non-anonymous consumer MUST provide a `node_id`") # Content check - has_fields = { - "sa": tasks_ins_res.task.HasField("sa"), - "legacy_client_message": tasks_ins_res.task.HasField( - "legacy_client_message" - ), - } - if not (has_fields["sa"] or has_fields["legacy_client_message"]): - err_msg = ", ".join([f"`{field}`" for field in has_fields]) - validation_errors.append( - f"`task` in `TaskRes` must set at least one of fields {{{err_msg}}}" - ) - if has_fields[ - "legacy_client_message" - ] and not tasks_ins_res.task.legacy_client_message.HasField("msg"): - validation_errors.append("`legacy_client_message` does not set field `msg`") + if tasks_ins_res.task.task_type == "": + validation_errors.append("`task_type` MUST be set") + if not tasks_ins_res.task.HasField("recordset"): + validation_errors.append("`recordset` MUST be set") # Ancestors if len(tasks_ins_res.task.ancestry) == 0: diff --git a/src/py/flwr/server/utils/validator_test.py b/src/py/flwr/server/utils/validator_test.py index a93e4fb4d457..8e0849508020 100644 --- a/src/py/flwr/server/utils/validator_test.py +++ b/src/py/flwr/server/utils/validator_test.py @@ -19,16 +19,8 @@ from typing import List, Tuple from flwr.proto.node_pb2 import Node # pylint: disable=E0611 -from flwr.proto.task_pb2 import ( # pylint: disable=E0611 - SecureAggregation, - Task, - TaskIns, - TaskRes, -) -from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 - ClientMessage, - ServerMessage, -) +from flwr.proto.recordset_pb2 import RecordSet # pylint: disable=E0611 +from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611 from .validator import validate_task_ins_or_res @@ -45,16 +37,12 @@ def test_task_ins(self) -> None: # Execute & Assert for consumer_node_id, anonymous in valid_ins: - msg = create_task_ins( - consumer_node_id, anonymous, has_legacy_server_message=True - ) + msg = create_task_ins(consumer_node_id, anonymous) val_errors = validate_task_ins_or_res(msg) self.assertFalse(val_errors) for consumer_node_id, anonymous in invalid_ins: - msg = create_task_ins( - consumer_node_id, anonymous, has_legacy_server_message=True - ) + msg = create_task_ins(consumer_node_id, anonymous) val_errors = validate_task_ins_or_res(msg) self.assertTrue(val_errors) @@ -78,61 +66,19 @@ def test_is_valid_task_res(self) -> None: # Execute & Assert for producer_node_id, anonymous, ancestry in valid_res: - msg = create_task_res( - producer_node_id, anonymous, ancestry, has_legacy_client_message=True - ) + msg = create_task_res(producer_node_id, anonymous, ancestry) val_errors = validate_task_ins_or_res(msg) self.assertFalse(val_errors) for producer_node_id, anonymous, ancestry in invalid_res: - msg = create_task_res( - producer_node_id, anonymous, ancestry, has_legacy_client_message=True - ) + msg = create_task_res(producer_node_id, anonymous, ancestry) val_errors = validate_task_ins_or_res(msg) self.assertTrue(val_errors, (producer_node_id, anonymous, ancestry)) - def test_task_ins_secure_aggregation(self) -> None: - """Test is_valid task_ins for Secure Aggregation.""" - # Prepare - # (has_legacy_server_message, has_sa) - valid_ins = [(True, True), (False, True)] - invalid_ins = [(False, False)] - - # Execute & Assert - for has_legacy_server_message, has_sa in valid_ins: - msg = create_task_ins(1, False, has_legacy_server_message, has_sa) - val_errors = validate_task_ins_or_res(msg) - self.assertFalse(val_errors) - - for has_legacy_server_message, has_sa in invalid_ins: - msg = create_task_ins(1, False, has_legacy_server_message, has_sa) - val_errors = validate_task_ins_or_res(msg) - self.assertTrue(val_errors) - - def test_task_res_secure_aggregation(self) -> None: - """Test is_valid task_res for Secure Aggregation.""" - # Prepare - # (has_legacy_server_message, has_sa) - valid_res = [(True, True), (False, True)] - invalid_res = [(False, False)] - - # Execute & Assert - for has_legacy_client_message, has_sa in valid_res: - msg = create_task_res(0, True, ["1"], has_legacy_client_message, has_sa) - val_errors = validate_task_ins_or_res(msg) - self.assertFalse(val_errors) - - for has_legacy_client_message, has_sa in invalid_res: - msg = create_task_res(0, True, ["1"], has_legacy_client_message, has_sa) - val_errors = validate_task_ins_or_res(msg) - self.assertTrue(val_errors) - def create_task_ins( consumer_node_id: int, anonymous: bool, - has_legacy_server_message: bool = False, - has_sa: bool = False, delivered_at: str = "", ) -> TaskIns: """Create a TaskIns for testing.""" @@ -148,12 +94,8 @@ def create_task_ins( delivered_at=delivered_at, producer=Node(node_id=0, anonymous=True), consumer=consumer, - legacy_server_message=ServerMessage( - reconnect_ins=ServerMessage.ReconnectIns() - ) - if has_legacy_server_message - else None, - sa=SecureAggregation(named_values={}) if has_sa else None, + task_type="mock", + recordset=RecordSet(parameters={}, metrics={}, configs={}), ), ) return task @@ -163,8 +105,6 @@ def create_task_res( producer_node_id: int, anonymous: bool, ancestry: List[str], - has_legacy_client_message: bool = False, - has_sa: bool = False, ) -> TaskRes: """Create a TaskRes for testing.""" task_res = TaskRes( @@ -175,12 +115,8 @@ def create_task_res( producer=Node(node_id=producer_node_id, anonymous=anonymous), consumer=Node(node_id=0, anonymous=True), ancestry=ancestry, - legacy_client_message=ClientMessage( - disconnect_res=ClientMessage.DisconnectRes() - ) - if has_legacy_client_message - else None, - sa=SecureAggregation(named_values={}) if has_sa else None, + task_type="mock", + recordset=RecordSet(parameters={}, metrics={}, configs={}), ), ) return task_res From df3d5f5ac235c7dbb799dbcbb435e62fbb5caaad Mon Sep 17 00:00:00 2001 From: Robert Kuska Date: Mon, 29 Jan 2024 13:56:04 +0100 Subject: [PATCH 044/113] Update tutorial link in README (#2864) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fe3295c4a22f..79e931dade9d 100644 --- a/README.md +++ b/README.md @@ -56,11 +56,11 @@ Flower's goal is to make federated learning accessible to everyone. This series 2. **Using Strategies in Federated Learning** - [![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/adap/flower/blob/main/doc/source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb) (or open the [Jupyter Notebook](https://github.com/adap/flower/blob/main/doc/source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb)) + [![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/adap/flower/blob/main/doc/source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb) (or open the [Jupyter Notebook](https://github.com/adap/flower/blob/main/doc/source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb)) 3. **Building Strategies for Federated Learning** - [![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/adap/flower/blob/main/doc/source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb) (or open the [Jupyter Notebook](https://github.com/adap/flower/blob/main/doc/source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb)) + [![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/adap/flower/blob/main/doc/source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb) (or open the [Jupyter Notebook](https://github.com/adap/flower/blob/main/doc/source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb)) 4. **Custom Clients for Federated Learning** From f649b66c99907a0d6ff02a607ae96bcf2f8702a3 Mon Sep 17 00:00:00 2001 From: Heng Pan <134433891+panh99@users.noreply.github.com> Date: Mon, 29 Jan 2024 13:12:36 +0000 Subject: [PATCH 045/113] Remove `legacy_*_message` fields from `Task` message (#2865) --- src/proto/flwr/proto/task.proto | 2 - src/py/flwr/proto/task_pb2.py | 28 ++++++------ src/py/flwr/proto/task_pb2.pyi | 13 +----- src/py/flwr/server/state/sqlite_state.py | 43 ++++++++----------- src/py/flwr/server/state/sqlite_state_test.py | 4 +- 5 files changed, 35 insertions(+), 55 deletions(-) diff --git a/src/proto/flwr/proto/task.proto b/src/proto/flwr/proto/task.proto index 2cde16143d8d..8eff70a9ede6 100644 --- a/src/proto/flwr/proto/task.proto +++ b/src/proto/flwr/proto/task.proto @@ -31,8 +31,6 @@ message Task { string task_type = 7; RecordSet recordset = 8; - ServerMessage legacy_server_message = 101 [ deprecated = true ]; - ClientMessage legacy_client_message = 102 [ deprecated = true ]; SecureAggregation sa = 103 [ deprecated = true ]; } diff --git a/src/py/flwr/proto/task_pb2.py b/src/py/flwr/proto/task_pb2.py index f9b2180b15dd..de2480fa2b0c 100644 --- a/src/py/flwr/proto/task_pb2.py +++ b/src/py/flwr/proto/task_pb2.py @@ -17,31 +17,27 @@ from flwr.proto import transport_pb2 as flwr_dot_proto_dot_transport__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/task.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x1a\x66lwr/proto/recordset.proto\x1a\x1a\x66lwr/proto/transport.proto\"\xff\x02\n\x04Task\x12\"\n\x08producer\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\"\n\x08\x63onsumer\x18\x02 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x12\n\ncreated_at\x18\x03 \x01(\t\x12\x14\n\x0c\x64\x65livered_at\x18\x04 \x01(\t\x12\x0b\n\x03ttl\x18\x05 \x01(\t\x12\x10\n\x08\x61ncestry\x18\x06 \x03(\t\x12\x11\n\ttask_type\x18\x07 \x01(\t\x12(\n\trecordset\x18\x08 \x01(\x0b\x32\x15.flwr.proto.RecordSet\x12<\n\x15legacy_server_message\x18\x65 \x01(\x0b\x32\x19.flwr.proto.ServerMessageB\x02\x18\x01\x12<\n\x15legacy_client_message\x18\x66 \x01(\x0b\x32\x19.flwr.proto.ClientMessageB\x02\x18\x01\x12-\n\x02sa\x18g \x01(\x0b\x32\x1d.flwr.proto.SecureAggregationB\x02\x18\x01\"\\\n\x07TaskIns\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x12\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Task\"\\\n\x07TaskRes\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x12\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Task\"\xcc\x02\n\x05Value\x12\x10\n\x06\x64ouble\x18\x01 \x01(\x01H\x00\x12\x10\n\x06sint64\x18\x02 \x01(\x12H\x00\x12\x0e\n\x04\x62ool\x18\x03 \x01(\x08H\x00\x12\x10\n\x06string\x18\x04 \x01(\tH\x00\x12\x0f\n\x05\x62ytes\x18\x05 \x01(\x0cH\x00\x12-\n\x0b\x64ouble_list\x18\x15 \x01(\x0b\x32\x16.flwr.proto.DoubleListH\x00\x12-\n\x0bsint64_list\x18\x16 \x01(\x0b\x32\x16.flwr.proto.Sint64ListH\x00\x12)\n\tbool_list\x18\x17 \x01(\x0b\x32\x14.flwr.proto.BoolListH\x00\x12-\n\x0bstring_list\x18\x18 \x01(\x0b\x32\x16.flwr.proto.StringListH\x00\x12+\n\nbytes_list\x18\x19 \x01(\x0b\x32\x15.flwr.proto.BytesListH\x00\x42\x07\n\x05value\"\xa0\x01\n\x11SecureAggregation\x12\x44\n\x0cnamed_values\x18\x01 \x03(\x0b\x32..flwr.proto.SecureAggregation.NamedValuesEntry\x1a\x45\n\x10NamedValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12 \n\x05value\x18\x02 \x01(\x0b\x32\x11.flwr.proto.Value:\x02\x38\x01\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/task.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x1a\x66lwr/proto/recordset.proto\x1a\x1a\x66lwr/proto/transport.proto\"\x83\x02\n\x04Task\x12\"\n\x08producer\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\"\n\x08\x63onsumer\x18\x02 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x12\n\ncreated_at\x18\x03 \x01(\t\x12\x14\n\x0c\x64\x65livered_at\x18\x04 \x01(\t\x12\x0b\n\x03ttl\x18\x05 \x01(\t\x12\x10\n\x08\x61ncestry\x18\x06 \x03(\t\x12\x11\n\ttask_type\x18\x07 \x01(\t\x12(\n\trecordset\x18\x08 \x01(\x0b\x32\x15.flwr.proto.RecordSet\x12-\n\x02sa\x18g \x01(\x0b\x32\x1d.flwr.proto.SecureAggregationB\x02\x18\x01\"\\\n\x07TaskIns\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x12\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Task\"\\\n\x07TaskRes\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x12\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Task\"\xcc\x02\n\x05Value\x12\x10\n\x06\x64ouble\x18\x01 \x01(\x01H\x00\x12\x10\n\x06sint64\x18\x02 \x01(\x12H\x00\x12\x0e\n\x04\x62ool\x18\x03 \x01(\x08H\x00\x12\x10\n\x06string\x18\x04 \x01(\tH\x00\x12\x0f\n\x05\x62ytes\x18\x05 \x01(\x0cH\x00\x12-\n\x0b\x64ouble_list\x18\x15 \x01(\x0b\x32\x16.flwr.proto.DoubleListH\x00\x12-\n\x0bsint64_list\x18\x16 \x01(\x0b\x32\x16.flwr.proto.Sint64ListH\x00\x12)\n\tbool_list\x18\x17 \x01(\x0b\x32\x14.flwr.proto.BoolListH\x00\x12-\n\x0bstring_list\x18\x18 \x01(\x0b\x32\x16.flwr.proto.StringListH\x00\x12+\n\nbytes_list\x18\x19 \x01(\x0b\x32\x15.flwr.proto.BytesListH\x00\x42\x07\n\x05value\"\xa0\x01\n\x11SecureAggregation\x12\x44\n\x0cnamed_values\x18\x01 \x03(\x0b\x32..flwr.proto.SecureAggregation.NamedValuesEntry\x1a\x45\n\x10NamedValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12 \n\x05value\x18\x02 \x01(\x0b\x32\x11.flwr.proto.Value:\x02\x38\x01\x62\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.task_pb2', _globals) if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None - _globals['_TASK'].fields_by_name['legacy_server_message']._options = None - _globals['_TASK'].fields_by_name['legacy_server_message']._serialized_options = b'\030\001' - _globals['_TASK'].fields_by_name['legacy_client_message']._options = None - _globals['_TASK'].fields_by_name['legacy_client_message']._serialized_options = b'\030\001' _globals['_TASK'].fields_by_name['sa']._options = None _globals['_TASK'].fields_by_name['sa']._serialized_options = b'\030\001' _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._options = None _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_options = b'8\001' _globals['_TASK']._serialized_start=117 - _globals['_TASK']._serialized_end=500 - _globals['_TASKINS']._serialized_start=502 - _globals['_TASKINS']._serialized_end=594 - _globals['_TASKRES']._serialized_start=596 - _globals['_TASKRES']._serialized_end=688 - _globals['_VALUE']._serialized_start=691 - _globals['_VALUE']._serialized_end=1023 - _globals['_SECUREAGGREGATION']._serialized_start=1026 - _globals['_SECUREAGGREGATION']._serialized_end=1186 - _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_start=1117 - _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_end=1186 + _globals['_TASK']._serialized_end=376 + _globals['_TASKINS']._serialized_start=378 + _globals['_TASKINS']._serialized_end=470 + _globals['_TASKRES']._serialized_start=472 + _globals['_TASKRES']._serialized_end=564 + _globals['_VALUE']._serialized_start=567 + _globals['_VALUE']._serialized_end=899 + _globals['_SECUREAGGREGATION']._serialized_start=902 + _globals['_SECUREAGGREGATION']._serialized_end=1062 + _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_start=993 + _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_end=1062 # @@protoc_insertion_point(module_scope) diff --git a/src/py/flwr/proto/task_pb2.pyi b/src/py/flwr/proto/task_pb2.pyi index 39119797c9e4..51fe9c196836 100644 --- a/src/py/flwr/proto/task_pb2.pyi +++ b/src/py/flwr/proto/task_pb2.pyi @@ -5,7 +5,6 @@ isort:skip_file import builtins import flwr.proto.node_pb2 import flwr.proto.recordset_pb2 -import flwr.proto.transport_pb2 import google.protobuf.descriptor import google.protobuf.internal.containers import google.protobuf.message @@ -24,8 +23,6 @@ class Task(google.protobuf.message.Message): ANCESTRY_FIELD_NUMBER: builtins.int TASK_TYPE_FIELD_NUMBER: builtins.int RECORDSET_FIELD_NUMBER: builtins.int - LEGACY_SERVER_MESSAGE_FIELD_NUMBER: builtins.int - LEGACY_CLIENT_MESSAGE_FIELD_NUMBER: builtins.int SA_FIELD_NUMBER: builtins.int @property def producer(self) -> flwr.proto.node_pb2.Node: ... @@ -40,10 +37,6 @@ class Task(google.protobuf.message.Message): @property def recordset(self) -> flwr.proto.recordset_pb2.RecordSet: ... @property - def legacy_server_message(self) -> flwr.proto.transport_pb2.ServerMessage: ... - @property - def legacy_client_message(self) -> flwr.proto.transport_pb2.ClientMessage: ... - @property def sa(self) -> global___SecureAggregation: ... def __init__(self, *, @@ -55,12 +48,10 @@ class Task(google.protobuf.message.Message): ancestry: typing.Optional[typing.Iterable[typing.Text]] = ..., task_type: typing.Text = ..., recordset: typing.Optional[flwr.proto.recordset_pb2.RecordSet] = ..., - legacy_server_message: typing.Optional[flwr.proto.transport_pb2.ServerMessage] = ..., - legacy_client_message: typing.Optional[flwr.proto.transport_pb2.ClientMessage] = ..., sa: typing.Optional[global___SecureAggregation] = ..., ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["consumer",b"consumer","legacy_client_message",b"legacy_client_message","legacy_server_message",b"legacy_server_message","producer",b"producer","recordset",b"recordset","sa",b"sa"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["ancestry",b"ancestry","consumer",b"consumer","created_at",b"created_at","delivered_at",b"delivered_at","legacy_client_message",b"legacy_client_message","legacy_server_message",b"legacy_server_message","producer",b"producer","recordset",b"recordset","sa",b"sa","task_type",b"task_type","ttl",b"ttl"]) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["consumer",b"consumer","producer",b"producer","recordset",b"recordset","sa",b"sa"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["ancestry",b"ancestry","consumer",b"consumer","created_at",b"created_at","delivered_at",b"delivered_at","producer",b"producer","recordset",b"recordset","sa",b"sa","task_type",b"task_type","ttl",b"ttl"]) -> None: ... global___Task = Task class TaskIns(google.protobuf.message.Message): diff --git a/src/py/flwr/server/state/sqlite_state.py b/src/py/flwr/server/state/sqlite_state.py index 538ecb84491f..224c16cdf013 100644 --- a/src/py/flwr/server/state/sqlite_state.py +++ b/src/py/flwr/server/state/sqlite_state.py @@ -25,11 +25,8 @@ from flwr.common import log, now from flwr.proto.node_pb2 import Node # pylint: disable=E0611 +from flwr.proto.recordset_pb2 import RecordSet # pylint: disable=E0611 from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611 -from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 - ClientMessage, - ServerMessage, -) from flwr.server.utils.validator import validate_task_ins_or_res from .state import State @@ -50,7 +47,7 @@ CREATE TABLE IF NOT EXISTS task_ins( task_id TEXT UNIQUE, group_id TEXT, - run_id INTEGER, + run_id INTEGER, producer_anonymous BOOLEAN, producer_node_id INTEGER, consumer_anonymous BOOLEAN, @@ -59,8 +56,8 @@ delivered_at TEXT, ttl TEXT, ancestry TEXT, - legacy_server_message BLOB, - legacy_client_message BLOB, + task_type TEXT, + recordset BLOB, FOREIGN KEY(run_id) REFERENCES run(run_id) ); """ @@ -70,7 +67,7 @@ CREATE TABLE IF NOT EXISTS task_res( task_id TEXT UNIQUE, group_id TEXT, - run_id INTEGER, + run_id INTEGER, producer_anonymous BOOLEAN, producer_node_id INTEGER, consumer_anonymous BOOLEAN, @@ -79,8 +76,8 @@ delivered_at TEXT, ttl TEXT, ancestry TEXT, - legacy_server_message BLOB, - legacy_client_message BLOB, + task_type TEXT, + recordset BLOB, FOREIGN KEY(run_id) REFERENCES run(run_id) ); """ @@ -549,10 +546,8 @@ def task_ins_to_dict(task_msg: TaskIns) -> Dict[str, Any]: "delivered_at": task_msg.task.delivered_at, "ttl": task_msg.task.ttl, "ancestry": ",".join(task_msg.task.ancestry), - "legacy_server_message": ( - task_msg.task.legacy_server_message.SerializeToString() - ), - "legacy_client_message": None, + "task_type": task_msg.task.task_type, + "recordset": task_msg.task.recordset.SerializeToString(), } return result @@ -571,18 +566,16 @@ def task_res_to_dict(task_msg: TaskRes) -> Dict[str, Any]: "delivered_at": task_msg.task.delivered_at, "ttl": task_msg.task.ttl, "ancestry": ",".join(task_msg.task.ancestry), - "legacy_server_message": None, - "legacy_client_message": ( - task_msg.task.legacy_client_message.SerializeToString() - ), + "task_type": task_msg.task.task_type, + "recordset": task_msg.task.recordset.SerializeToString(), } return result def dict_to_task_ins(task_dict: Dict[str, Any]) -> TaskIns: """Turn task_dict into protobuf message.""" - server_message = ServerMessage() - server_message.ParseFromString(task_dict["legacy_server_message"]) + recordset = RecordSet() + recordset.ParseFromString(task_dict["recordset"]) result = TaskIns( task_id=task_dict["task_id"], @@ -601,7 +594,8 @@ def dict_to_task_ins(task_dict: Dict[str, Any]) -> TaskIns: delivered_at=task_dict["delivered_at"], ttl=task_dict["ttl"], ancestry=task_dict["ancestry"].split(","), - legacy_server_message=server_message, + task_type=task_dict["task_type"], + recordset=recordset, ), ) return result @@ -609,8 +603,8 @@ def dict_to_task_ins(task_dict: Dict[str, Any]) -> TaskIns: def dict_to_task_res(task_dict: Dict[str, Any]) -> TaskRes: """Turn task_dict into protobuf message.""" - client_message = ClientMessage() - client_message.ParseFromString(task_dict["legacy_client_message"]) + recordset = RecordSet() + recordset.ParseFromString(task_dict["recordset"]) result = TaskRes( task_id=task_dict["task_id"], @@ -629,7 +623,8 @@ def dict_to_task_res(task_dict: Dict[str, Any]) -> TaskRes: delivered_at=task_dict["delivered_at"], ttl=task_dict["ttl"], ancestry=task_dict["ancestry"].split(","), - legacy_client_message=client_message, + task_type=task_dict["task_type"], + recordset=recordset, ), ) return result diff --git a/src/py/flwr/server/state/sqlite_state_test.py b/src/py/flwr/server/state/sqlite_state_test.py index a3f899386011..f9d88ee07853 100644 --- a/src/py/flwr/server/state/sqlite_state_test.py +++ b/src/py/flwr/server/state/sqlite_state_test.py @@ -40,8 +40,8 @@ def test_ins_res_to_dict(self) -> None: "delivered_at", "ttl", "ancestry", - "legacy_server_message", - "legacy_client_message", + "task_type", + "recordset", ] # Execute From ec88d45a35d6c912a0c161585e00a9bf54c99fe9 Mon Sep 17 00:00:00 2001 From: Heng Pan <134433891+panh99@users.noreply.github.com> Date: Mon, 29 Jan 2024 14:25:53 +0000 Subject: [PATCH 046/113] Remove `sa` field and unused serde functions (#2866) --- src/proto/flwr/proto/task.proto | 22 --- src/py/flwr/common/serde.py | 226 +------------------------------ src/py/flwr/common/serde_test.py | 86 +----------- src/py/flwr/proto/task_pb2.py | 22 +-- src/py/flwr/proto/task_pb2.pyi | 84 +----------- 5 files changed, 11 insertions(+), 429 deletions(-) diff --git a/src/proto/flwr/proto/task.proto b/src/proto/flwr/proto/task.proto index 8eff70a9ede6..7ae0c31fded5 100644 --- a/src/proto/flwr/proto/task.proto +++ b/src/proto/flwr/proto/task.proto @@ -30,8 +30,6 @@ message Task { repeated string ancestry = 6; string task_type = 7; RecordSet recordset = 8; - - SecureAggregation sa = 103 [ deprecated = true ]; } message TaskIns { @@ -47,23 +45,3 @@ message TaskRes { sint64 run_id = 3; Task task = 4; } - -message Value { - oneof value { - // Single element - double double = 1; - sint64 sint64 = 2; - bool bool = 3; - string string = 4; - bytes bytes = 5; - - // List types - DoubleList double_list = 21; - Sint64List sint64_list = 22; - BoolList bool_list = 23; - StringList string_list = 24; - BytesList bytes_list = 25; - } -} - -message SecureAggregation { map named_values = 1; } diff --git a/src/py/flwr/common/serde.py b/src/py/flwr/common/serde.py index 9e12a30d8089..92c4e2cdad00 100644 --- a/src/py/flwr/common/serde.py +++ b/src/py/flwr/common/serde.py @@ -30,7 +30,7 @@ from flwr.proto.recordset_pb2 import ParametersRecord as ProtoParametersRecord from flwr.proto.recordset_pb2 import RecordSet as ProtoRecordSet from flwr.proto.recordset_pb2 import Sint64List, StringList -from flwr.proto.task_pb2 import Task, TaskIns, TaskRes, Value +from flwr.proto.task_pb2 import Task, TaskIns, TaskRes from flwr.proto.transport_pb2 import ( ClientMessage, Code, @@ -49,142 +49,6 @@ from .parametersrecord import Array, ParametersRecord from .recordset import RecordSet -# === ServerMessage message === - - -def server_message_to_proto(server_message: typing.ServerMessage) -> ServerMessage: - """Serialize `ServerMessage` to ProtoBuf.""" - if server_message.get_properties_ins is not None: - return ServerMessage( - get_properties_ins=get_properties_ins_to_proto( - server_message.get_properties_ins, - ) - ) - if server_message.get_parameters_ins is not None: - return ServerMessage( - get_parameters_ins=get_parameters_ins_to_proto( - server_message.get_parameters_ins, - ) - ) - if server_message.fit_ins is not None: - return ServerMessage( - fit_ins=fit_ins_to_proto( - server_message.fit_ins, - ) - ) - if server_message.evaluate_ins is not None: - return ServerMessage( - evaluate_ins=evaluate_ins_to_proto( - server_message.evaluate_ins, - ) - ) - raise ValueError( - "No instruction set in ServerMessage, cannot serialize to ProtoBuf" - ) - - -def server_message_from_proto( - server_message_proto: ServerMessage, -) -> typing.ServerMessage: - """Deserialize `ServerMessage` from ProtoBuf.""" - field = server_message_proto.WhichOneof("msg") - if field == "get_properties_ins": - return typing.ServerMessage( - get_properties_ins=get_properties_ins_from_proto( - server_message_proto.get_properties_ins, - ) - ) - if field == "get_parameters_ins": - return typing.ServerMessage( - get_parameters_ins=get_parameters_ins_from_proto( - server_message_proto.get_parameters_ins, - ) - ) - if field == "fit_ins": - return typing.ServerMessage( - fit_ins=fit_ins_from_proto( - server_message_proto.fit_ins, - ) - ) - if field == "evaluate_ins": - return typing.ServerMessage( - evaluate_ins=evaluate_ins_from_proto( - server_message_proto.evaluate_ins, - ) - ) - raise ValueError( - "Unsupported instruction in ServerMessage, cannot deserialize from ProtoBuf" - ) - - -# === ClientMessage message === - - -def client_message_to_proto(client_message: typing.ClientMessage) -> ClientMessage: - """Serialize `ClientMessage` to ProtoBuf.""" - if client_message.get_properties_res is not None: - return ClientMessage( - get_properties_res=get_properties_res_to_proto( - client_message.get_properties_res, - ) - ) - if client_message.get_parameters_res is not None: - return ClientMessage( - get_parameters_res=get_parameters_res_to_proto( - client_message.get_parameters_res, - ) - ) - if client_message.fit_res is not None: - return ClientMessage( - fit_res=fit_res_to_proto( - client_message.fit_res, - ) - ) - if client_message.evaluate_res is not None: - return ClientMessage( - evaluate_res=evaluate_res_to_proto( - client_message.evaluate_res, - ) - ) - raise ValueError( - "No instruction set in ClientMessage, cannot serialize to ProtoBuf" - ) - - -def client_message_from_proto( - client_message_proto: ClientMessage, -) -> typing.ClientMessage: - """Deserialize `ClientMessage` from ProtoBuf.""" - field = client_message_proto.WhichOneof("msg") - if field == "get_properties_res": - return typing.ClientMessage( - get_properties_res=get_properties_res_from_proto( - client_message_proto.get_properties_res, - ) - ) - if field == "get_parameters_res": - return typing.ClientMessage( - get_parameters_res=get_parameters_res_from_proto( - client_message_proto.get_parameters_res, - ) - ) - if field == "fit_res": - return typing.ClientMessage( - fit_res=fit_res_from_proto( - client_message_proto.fit_res, - ) - ) - if field == "evaluate_res": - return typing.ClientMessage( - evaluate_res=evaluate_res_from_proto( - client_message_proto.evaluate_res, - ) - ) - raise ValueError( - "Unsupported instruction in ClientMessage, cannot deserialize from ProtoBuf" - ) - - # === Parameters message === @@ -209,26 +73,9 @@ def reconnect_ins_to_proto(ins: typing.ReconnectIns) -> ServerMessage.ReconnectI return ServerMessage.ReconnectIns() -def reconnect_ins_from_proto(msg: ServerMessage.ReconnectIns) -> typing.ReconnectIns: - """Deserialize `ReconnectIns` from ProtoBuf.""" - return typing.ReconnectIns(seconds=msg.seconds) - - # === DisconnectRes message === -def disconnect_res_to_proto(res: typing.DisconnectRes) -> ClientMessage.DisconnectRes: - """Serialize `DisconnectRes` to ProtoBuf.""" - reason_proto = Reason.UNKNOWN - if res.reason == "RECONNECT": - reason_proto = Reason.RECONNECT - elif res.reason == "POWER_DISCONNECTED": - reason_proto = Reason.POWER_DISCONNECTED - elif res.reason == "WIFI_UNAVAILABLE": - reason_proto = Reason.WIFI_UNAVAILABLE - return ClientMessage.DisconnectRes(reason=reason_proto) - - def disconnect_res_from_proto(msg: ClientMessage.DisconnectRes) -> typing.DisconnectRes: """Deserialize `DisconnectRes` from ProtoBuf.""" if msg.reason == Reason.RECONNECT: @@ -509,7 +356,7 @@ def scalar_from_proto(scalar_msg: Scalar) -> typing.Scalar: return cast(typing.Scalar, scalar) -# === Value messages === +# === Record messages === _type_to_field = { @@ -519,8 +366,6 @@ def scalar_from_proto(scalar_msg: Scalar) -> typing.Scalar: str: "string", bytes: "bytes", } - - _list_type_to_class_and_field = { float: (DoubleList, "double_list"), int: (Sint64List, "sint64_list"), @@ -528,73 +373,6 @@ def scalar_from_proto(scalar_msg: Scalar) -> typing.Scalar: str: (StringList, "string_list"), bytes: (BytesList, "bytes_list"), } - - -def _check_value(value: typing.Value) -> None: - if isinstance(value, tuple(_type_to_field.keys())): - return - if isinstance(value, list): - if len(value) > 0 and isinstance(value[0], tuple(_type_to_field.keys())): - data_type = type(value[0]) - for element in value: - if isinstance(element, data_type): - continue - raise TypeError( - f"Inconsistent type: the types of elements in the list must " - f"be the same (expected {data_type}, but got {type(element)})." - ) - else: - raise TypeError( - f"Accepted types: {bool, bytes, float, int, str} or " - f"list of these types." - ) - - -def value_to_proto(value: typing.Value) -> Value: - """Serialize `Value` to ProtoBuf.""" - _check_value(value) - - arg = {} - if isinstance(value, list): - msg_class, field_name = _list_type_to_class_and_field[ - type(value[0]) if len(value) > 0 else int - ] - arg[field_name] = msg_class(vals=value) - else: - arg[_type_to_field[type(value)]] = value - return Value(**arg) - - -def value_from_proto(value_msg: Value) -> typing.Value: - """Deserialize `Value` from ProtoBuf.""" - value_field = cast(str, value_msg.WhichOneof("value")) - if value_field.endswith("list"): - value = list(getattr(value_msg, value_field).vals) - else: - value = getattr(value_msg, value_field) - return cast(typing.Value, value) - - -# === Named Values === - - -def named_values_to_proto( - named_values: Dict[str, typing.Value], -) -> Dict[str, Value]: - """Serialize named values to ProtoBuf.""" - return {name: value_to_proto(value) for name, value in named_values.items()} - - -def named_values_from_proto( - named_values_proto: MutableMapping[str, Value] -) -> Dict[str, typing.Value]: - """Deserialize named values from ProtoBuf.""" - return {name: value_from_proto(value) for name, value in named_values_proto.items()} - - -# === Record messages === - - T = TypeVar("T") diff --git a/src/py/flwr/common/serde_test.py b/src/py/flwr/common/serde_test.py index 1f3d9239065b..2a229a87e399 100644 --- a/src/py/flwr/common/serde_test.py +++ b/src/py/flwr/common/serde_test.py @@ -17,7 +17,7 @@ import random import string -from typing import Any, Dict, Optional, OrderedDict, Type, TypeVar, Union, cast +from typing import Any, Optional, OrderedDict, Type, TypeVar, Union, cast # pylint: disable=E0611 from flwr.proto import transport_pb2 as pb2 @@ -45,8 +45,6 @@ message_to_taskres, metrics_record_from_proto, metrics_record_to_proto, - named_values_from_proto, - named_values_to_proto, parameters_record_from_proto, parameters_record_to_proto, recordset_from_proto, @@ -55,8 +53,6 @@ scalar_to_proto, status_from_proto, status_to_proto, - value_from_proto, - value_to_proto, ) @@ -107,86 +103,6 @@ def test_status_from_proto() -> None: assert actual_status == status -def test_value_serialization_deserialization() -> None: - """Test if values are identical after (de-)serialization.""" - # Prepare - values = [ - # boolean scalar and list - True, - [True, False, False, True], - # bytes scalar and list - b"test \x01\x02\x03 !@#$%^&*()", - [b"\x0a\x0b", b"\x0c\x0d\x0e", b"\x0f"], - # float scalar and list - 3.14, - [2.714, -0.012], - # integer scalar and list - 23, - [123456], - # string scalar and list - "abcdefghijklmnopqrstuvwxy", - ["456hgdhfd", "1234567890123456789012345678901", "I'm a string."], - # empty list - [], - ] - - for value in values: - # Execute - serialized = value_to_proto(cast(typing.Value, value)) - deserialized = value_from_proto(serialized) - - # Assert - if isinstance(value, list): - assert isinstance(deserialized, list) - assert len(value) == len(deserialized) - for elm1, elm2 in zip(value, deserialized): - assert elm1 == elm2 - else: - assert value == deserialized - - -def test_named_values_serialization_deserialization() -> None: - """Test if named values is identical after (de-)serialization.""" - # Prepare - values = [ - # boolean scalar and list - True, - [True, False, False, True], - # bytes scalar and list - b"test \x01\x02\x03 !@#$%^&*()", - [b"\x0a\x0b", b"\x0c\x0d\x0e", b"\x0f"], - # float scalar and list - 3.14, - [2.714, -0.012], - # integer scalar and list - 23, - [123456], - # string scalar and list - "abcdefghijklmnopqrstuvwxy", - ["456hgdhfd", "1234567890123456789012345678901", "I'm a string."], - # empty list - [], - ] - named_values = {f"value {i}": value for i, value in enumerate(values)} - - # Execute - serialized = named_values_to_proto(cast(Dict[str, typing.Value], named_values)) - deserialized = named_values_from_proto(serialized) - - # Assert - assert len(named_values) == len(deserialized) - for name in named_values: - expected = named_values[name] - actual = deserialized[name] - if isinstance(expected, list): - assert isinstance(actual, list) - assert len(expected) == len(actual) - for elm1, elm2 in zip(expected, actual): - assert elm1 == elm2 - else: - assert expected == actual - - T = TypeVar("T") diff --git a/src/py/flwr/proto/task_pb2.py b/src/py/flwr/proto/task_pb2.py index de2480fa2b0c..9294b27eec0e 100644 --- a/src/py/flwr/proto/task_pb2.py +++ b/src/py/flwr/proto/task_pb2.py @@ -17,27 +17,17 @@ from flwr.proto import transport_pb2 as flwr_dot_proto_dot_transport__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/task.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x1a\x66lwr/proto/recordset.proto\x1a\x1a\x66lwr/proto/transport.proto\"\x83\x02\n\x04Task\x12\"\n\x08producer\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\"\n\x08\x63onsumer\x18\x02 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x12\n\ncreated_at\x18\x03 \x01(\t\x12\x14\n\x0c\x64\x65livered_at\x18\x04 \x01(\t\x12\x0b\n\x03ttl\x18\x05 \x01(\t\x12\x10\n\x08\x61ncestry\x18\x06 \x03(\t\x12\x11\n\ttask_type\x18\x07 \x01(\t\x12(\n\trecordset\x18\x08 \x01(\x0b\x32\x15.flwr.proto.RecordSet\x12-\n\x02sa\x18g \x01(\x0b\x32\x1d.flwr.proto.SecureAggregationB\x02\x18\x01\"\\\n\x07TaskIns\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x12\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Task\"\\\n\x07TaskRes\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x12\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Task\"\xcc\x02\n\x05Value\x12\x10\n\x06\x64ouble\x18\x01 \x01(\x01H\x00\x12\x10\n\x06sint64\x18\x02 \x01(\x12H\x00\x12\x0e\n\x04\x62ool\x18\x03 \x01(\x08H\x00\x12\x10\n\x06string\x18\x04 \x01(\tH\x00\x12\x0f\n\x05\x62ytes\x18\x05 \x01(\x0cH\x00\x12-\n\x0b\x64ouble_list\x18\x15 \x01(\x0b\x32\x16.flwr.proto.DoubleListH\x00\x12-\n\x0bsint64_list\x18\x16 \x01(\x0b\x32\x16.flwr.proto.Sint64ListH\x00\x12)\n\tbool_list\x18\x17 \x01(\x0b\x32\x14.flwr.proto.BoolListH\x00\x12-\n\x0bstring_list\x18\x18 \x01(\x0b\x32\x16.flwr.proto.StringListH\x00\x12+\n\nbytes_list\x18\x19 \x01(\x0b\x32\x15.flwr.proto.BytesListH\x00\x42\x07\n\x05value\"\xa0\x01\n\x11SecureAggregation\x12\x44\n\x0cnamed_values\x18\x01 \x03(\x0b\x32..flwr.proto.SecureAggregation.NamedValuesEntry\x1a\x45\n\x10NamedValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12 \n\x05value\x18\x02 \x01(\x0b\x32\x11.flwr.proto.Value:\x02\x38\x01\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/task.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x1a\x66lwr/proto/recordset.proto\x1a\x1a\x66lwr/proto/transport.proto\"\xd4\x01\n\x04Task\x12\"\n\x08producer\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\"\n\x08\x63onsumer\x18\x02 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x12\n\ncreated_at\x18\x03 \x01(\t\x12\x14\n\x0c\x64\x65livered_at\x18\x04 \x01(\t\x12\x0b\n\x03ttl\x18\x05 \x01(\t\x12\x10\n\x08\x61ncestry\x18\x06 \x03(\t\x12\x11\n\ttask_type\x18\x07 \x01(\t\x12(\n\trecordset\x18\x08 \x01(\x0b\x32\x15.flwr.proto.RecordSet\"\\\n\x07TaskIns\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x12\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Task\"\\\n\x07TaskRes\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x12\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Taskb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.task_pb2', _globals) if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None - _globals['_TASK'].fields_by_name['sa']._options = None - _globals['_TASK'].fields_by_name['sa']._serialized_options = b'\030\001' - _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._options = None - _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_options = b'8\001' _globals['_TASK']._serialized_start=117 - _globals['_TASK']._serialized_end=376 - _globals['_TASKINS']._serialized_start=378 - _globals['_TASKINS']._serialized_end=470 - _globals['_TASKRES']._serialized_start=472 - _globals['_TASKRES']._serialized_end=564 - _globals['_VALUE']._serialized_start=567 - _globals['_VALUE']._serialized_end=899 - _globals['_SECUREAGGREGATION']._serialized_start=902 - _globals['_SECUREAGGREGATION']._serialized_end=1062 - _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_start=993 - _globals['_SECUREAGGREGATION_NAMEDVALUESENTRY']._serialized_end=1062 + _globals['_TASK']._serialized_end=329 + _globals['_TASKINS']._serialized_start=331 + _globals['_TASKINS']._serialized_end=423 + _globals['_TASKRES']._serialized_start=425 + _globals['_TASKRES']._serialized_end=517 # @@protoc_insertion_point(module_scope) diff --git a/src/py/flwr/proto/task_pb2.pyi b/src/py/flwr/proto/task_pb2.pyi index 51fe9c196836..4c8412fd691a 100644 --- a/src/py/flwr/proto/task_pb2.pyi +++ b/src/py/flwr/proto/task_pb2.pyi @@ -23,7 +23,6 @@ class Task(google.protobuf.message.Message): ANCESTRY_FIELD_NUMBER: builtins.int TASK_TYPE_FIELD_NUMBER: builtins.int RECORDSET_FIELD_NUMBER: builtins.int - SA_FIELD_NUMBER: builtins.int @property def producer(self) -> flwr.proto.node_pb2.Node: ... @property @@ -36,8 +35,6 @@ class Task(google.protobuf.message.Message): task_type: typing.Text @property def recordset(self) -> flwr.proto.recordset_pb2.RecordSet: ... - @property - def sa(self) -> global___SecureAggregation: ... def __init__(self, *, producer: typing.Optional[flwr.proto.node_pb2.Node] = ..., @@ -48,10 +45,9 @@ class Task(google.protobuf.message.Message): ancestry: typing.Optional[typing.Iterable[typing.Text]] = ..., task_type: typing.Text = ..., recordset: typing.Optional[flwr.proto.recordset_pb2.RecordSet] = ..., - sa: typing.Optional[global___SecureAggregation] = ..., ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["consumer",b"consumer","producer",b"producer","recordset",b"recordset","sa",b"sa"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["ancestry",b"ancestry","consumer",b"consumer","created_at",b"created_at","delivered_at",b"delivered_at","producer",b"producer","recordset",b"recordset","sa",b"sa","task_type",b"task_type","ttl",b"ttl"]) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["consumer",b"consumer","producer",b"producer","recordset",b"recordset"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["ancestry",b"ancestry","consumer",b"consumer","created_at",b"created_at","delivered_at",b"delivered_at","producer",b"producer","recordset",b"recordset","task_type",b"task_type","ttl",b"ttl"]) -> None: ... global___Task = Task class TaskIns(google.protobuf.message.Message): @@ -97,79 +93,3 @@ class TaskRes(google.protobuf.message.Message): def HasField(self, field_name: typing_extensions.Literal["task",b"task"]) -> builtins.bool: ... def ClearField(self, field_name: typing_extensions.Literal["group_id",b"group_id","run_id",b"run_id","task",b"task","task_id",b"task_id"]) -> None: ... global___TaskRes = TaskRes - -class Value(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor - DOUBLE_FIELD_NUMBER: builtins.int - SINT64_FIELD_NUMBER: builtins.int - BOOL_FIELD_NUMBER: builtins.int - STRING_FIELD_NUMBER: builtins.int - BYTES_FIELD_NUMBER: builtins.int - DOUBLE_LIST_FIELD_NUMBER: builtins.int - SINT64_LIST_FIELD_NUMBER: builtins.int - BOOL_LIST_FIELD_NUMBER: builtins.int - STRING_LIST_FIELD_NUMBER: builtins.int - BYTES_LIST_FIELD_NUMBER: builtins.int - double: builtins.float - """Single element""" - - sint64: builtins.int - bool: builtins.bool - string: typing.Text - bytes: builtins.bytes - @property - def double_list(self) -> flwr.proto.recordset_pb2.DoubleList: - """List types""" - pass - @property - def sint64_list(self) -> flwr.proto.recordset_pb2.Sint64List: ... - @property - def bool_list(self) -> flwr.proto.recordset_pb2.BoolList: ... - @property - def string_list(self) -> flwr.proto.recordset_pb2.StringList: ... - @property - def bytes_list(self) -> flwr.proto.recordset_pb2.BytesList: ... - def __init__(self, - *, - double: builtins.float = ..., - sint64: builtins.int = ..., - bool: builtins.bool = ..., - string: typing.Text = ..., - bytes: builtins.bytes = ..., - double_list: typing.Optional[flwr.proto.recordset_pb2.DoubleList] = ..., - sint64_list: typing.Optional[flwr.proto.recordset_pb2.Sint64List] = ..., - bool_list: typing.Optional[flwr.proto.recordset_pb2.BoolList] = ..., - string_list: typing.Optional[flwr.proto.recordset_pb2.StringList] = ..., - bytes_list: typing.Optional[flwr.proto.recordset_pb2.BytesList] = ..., - ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["bool",b"bool","bool_list",b"bool_list","bytes",b"bytes","bytes_list",b"bytes_list","double",b"double","double_list",b"double_list","sint64",b"sint64","sint64_list",b"sint64_list","string",b"string","string_list",b"string_list","value",b"value"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["bool",b"bool","bool_list",b"bool_list","bytes",b"bytes","bytes_list",b"bytes_list","double",b"double","double_list",b"double_list","sint64",b"sint64","sint64_list",b"sint64_list","string",b"string","string_list",b"string_list","value",b"value"]) -> None: ... - def WhichOneof(self, oneof_group: typing_extensions.Literal["value",b"value"]) -> typing.Optional[typing_extensions.Literal["double","sint64","bool","string","bytes","double_list","sint64_list","bool_list","string_list","bytes_list"]]: ... -global___Value = Value - -class SecureAggregation(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor - class NamedValuesEntry(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor - KEY_FIELD_NUMBER: builtins.int - VALUE_FIELD_NUMBER: builtins.int - key: typing.Text - @property - def value(self) -> global___Value: ... - def __init__(self, - *, - key: typing.Text = ..., - value: typing.Optional[global___Value] = ..., - ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["value",b"value"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["key",b"key","value",b"value"]) -> None: ... - - NAMED_VALUES_FIELD_NUMBER: builtins.int - @property - def named_values(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, global___Value]: ... - def __init__(self, - *, - named_values: typing.Optional[typing.Mapping[typing.Text, global___Value]] = ..., - ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["named_values",b"named_values"]) -> None: ... -global___SecureAggregation = SecureAggregation From 8363759c7a7e1d3e4894b42ccf022294c78672be Mon Sep 17 00:00:00 2001 From: Javier Date: Mon, 29 Jan 2024 17:23:24 +0000 Subject: [PATCH 047/113] Discard input for parameter results in `message_handler` (#2867) --- src/py/flwr/client/message_handler/message_handler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/py/flwr/client/message_handler/message_handler.py b/src/py/flwr/client/message_handler/message_handler.py index ea87c35c83f7..92815f8a17b1 100644 --- a/src/py/flwr/client/message_handler/message_handler.py +++ b/src/py/flwr/client/message_handler/message_handler.py @@ -126,7 +126,7 @@ def handle_legacy_message_from_tasktype( get_parameters_ins=recordset_to_getparametersins(message.message), ) out_recordset = getparametersres_to_recordset( - get_parameters_res, keep_input=True + get_parameters_res, keep_input=False ) # Handle FitIns elif task_type == TASK_TYPE_FIT: @@ -134,7 +134,7 @@ def handle_legacy_message_from_tasktype( client=client, fit_ins=recordset_to_fitins(message.message, keep_input=True), ) - out_recordset = fitres_to_recordset(fit_res, keep_input=True) + out_recordset = fitres_to_recordset(fit_res, keep_input=False) # Handle EvaluateIns elif task_type == TASK_TYPE_EVALUATE: evaluate_res = maybe_call_evaluate( From 6c6de09138f81af8de0c7b6d26620fb4c0808d5f Mon Sep 17 00:00:00 2001 From: Heng Pan <134433891+panh99@users.noreply.github.com> Date: Mon, 29 Jan 2024 18:06:19 +0000 Subject: [PATCH 048/113] Update send/receive to use Message instead of TaskIns/TaskRes (#2868) --- src/py/flwr/client/app.py | 29 ++++++-------- src/py/flwr/client/grpc_client/connection.py | 36 +++++++---------- .../client/grpc_client/connection_test.py | 39 +++++++++++-------- .../client/grpc_rere_client/connection.py | 19 +++++---- .../client/message_handler/message_handler.py | 30 +++++++------- src/py/flwr/client/rest_client/connection.py | 21 ++++++---- 6 files changed, 91 insertions(+), 83 deletions(-) diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index c310221ba7af..dcea3b91da83 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -35,8 +35,7 @@ TRANSPORT_TYPES, ) from flwr.common.logger import log, warn_experimental_feature -from flwr.common.serde import message_from_taskins, message_to_taskres -from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611 +from flwr.common.message import Message from .flower import load_flower_callable from .grpc_client.connection import grpc_connection @@ -341,25 +340,22 @@ def _load_app() -> Flower: while True: # Receive - task_ins = receive() - if task_ins is None: + message = receive() + if message is None: time.sleep(3) # Wait for 3s before asking again continue # Handle control message - task_res, sleep_duration = handle_control_message(task_ins=task_ins) - if task_res: - send(task_res) + out_message, sleep_duration = handle_control_message(message) + if out_message: + send(out_message) break # Register context for this run - node_state.register_context(run_id=task_ins.run_id) + node_state.register_context(run_id=message.metadata.run_id) # Retrieve context for this run - context = node_state.retrieve_context(run_id=task_ins.run_id) - - # Get Message from TaskIns - message = message_from_taskins(task_ins) + context = node_state.retrieve_context(run_id=message.metadata.run_id) # Load app app: Flower = load_flower_callable_fn() @@ -373,11 +369,8 @@ def _load_app() -> Flower: context=context, ) - # Construct TaskRes from out_message - task_res = message_to_taskres(out_message) - # Send - send(task_res) + send(out_message) # Unregister node if delete_node is not None: @@ -496,8 +489,8 @@ def _init_connection( [str, bool, int, Union[bytes, str, None]], ContextManager[ Tuple[ - Callable[[], Optional[TaskIns]], - Callable[[TaskRes], None], + Callable[[], Optional[Message]], + Callable[[Message], None], Optional[Callable[[], None]], Optional[Callable[[], None]], ] diff --git a/src/py/flwr/client/grpc_client/connection.py b/src/py/flwr/client/grpc_client/connection.py index 4ca80642199d..bd1ea5fab307 100644 --- a/src/py/flwr/client/grpc_client/connection.py +++ b/src/py/flwr/client/grpc_client/connection.py @@ -34,9 +34,8 @@ ) from flwr.common.grpc import create_channel from flwr.common.logger import log +from flwr.common.message import Message, Metadata from flwr.common.recordset import RecordSet -from flwr.proto.node_pb2 import Node # pylint: disable=E0611 -from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611 from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 ClientMessage, Reason, @@ -64,8 +63,8 @@ def grpc_connection( # pylint: disable=R0915 root_certificates: Optional[Union[bytes, str]] = None, ) -> Iterator[ Tuple[ - Callable[[], Optional[TaskIns]], - Callable[[TaskRes], None], + Callable[[], Optional[Message]], + Callable[[Message], None], Optional[Callable[[], None]], Optional[Callable[[], None]], ] @@ -128,7 +127,7 @@ def grpc_connection( # pylint: disable=R0915 server_message_iterator: Iterator[ServerMessage] = stub.Join(iter(queue.get, None)) - def receive() -> TaskIns: + def receive() -> Message: # Receive ServerMessage proto proto = next(server_message_iterator) @@ -167,27 +166,22 @@ def receive() -> TaskIns: "cannot deserialize from ProtoBuf" ) - # RecordSet --> RecordSet proto - recordset_proto = serde.recordset_to_proto(recordset) - - # Construct TaskIns - return TaskIns( - task_id=str(uuid.uuid4()), - group_id="", - run_id=0, - task=Task( - producer=Node(node_id=0, anonymous=True), - consumer=Node(node_id=0, anonymous=True), - ancestry=[], + # Construct Message + return Message( + metadata=Metadata( + run_id=0, + task_id=str(uuid.uuid4()), + group_id="", + ttl="", task_type=task_type, - recordset=recordset_proto, ), + message=recordset, ) - def send(task_res: TaskRes) -> None: + def send(message: Message) -> None: # Retrieve RecordSet and task_type - recordset = serde.recordset_from_proto(task_res.task.recordset) - task_type = task_res.task.task_type + recordset = message.message + task_type = message.metadata.task_type # RecordSet --> *Res --> *Res proto -> ClientMessage proto if task_type == TASK_TYPE_GET_PROPERTIES: diff --git a/src/py/flwr/client/grpc_client/connection_test.py b/src/py/flwr/client/grpc_client/connection_test.py index f2b362750df4..8631c4a9b12b 100644 --- a/src/py/flwr/client/grpc_client/connection_test.py +++ b/src/py/flwr/client/grpc_client/connection_test.py @@ -24,12 +24,11 @@ import grpc from flwr.common import recordset_compat as compat -from flwr.common import serde from flwr.common.configsrecord import ConfigsRecord from flwr.common.constant import TASK_TYPE_GET_PROPERTIES +from flwr.common.message import Message, Metadata from flwr.common.recordset import RecordSet from flwr.common.typing import Code, GetPropertiesRes, Status -from flwr.proto.task_pb2 import Task, TaskRes # pylint: disable=E0611 from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 ClientMessage, ServerMessage, @@ -44,17 +43,27 @@ SERVER_MESSAGE = ServerMessage(get_properties_ins=ServerMessage.GetPropertiesIns()) SERVER_MESSAGE_RECONNECT = ServerMessage(reconnect_ins=ServerMessage.ReconnectIns()) -TASK_GET_PROPERTIES = Task( - task_type=TASK_TYPE_GET_PROPERTIES, - recordset=serde.recordset_to_proto( - compat.getpropertiesres_to_recordset(GetPropertiesRes(Status(Code.OK, ""), {})) +MESSAGE_GET_PROPERTIES = Message( + metadata=Metadata( + run_id=0, + task_id="", + group_id="", + ttl="", + task_type=TASK_TYPE_GET_PROPERTIES, + ), + message=compat.getpropertiesres_to_recordset( + GetPropertiesRes(Status(Code.OK, ""), {}) ), ) -TASK_DISCONNECT = Task( - task_type="reconnect", - recordset=serde.recordset_to_proto( - RecordSet(configs={"config": ConfigsRecord({"reason": 0})}) +MESSAGE_DISCONNECT = Message( + metadata=Metadata( + run_id=0, + task_id="", + group_id="", + ttl="", + task_type="reconnect", ), + message=RecordSet(configs={"config": ConfigsRecord({"reason": 0})}), ) @@ -118,17 +127,15 @@ def run_client() -> int: # Setup processing loop while True: # Block until server responds with a message - task_ins = receive() + message = receive() messages_received += 1 - if task_ins.task.task_type == "reconnect": # type: ignore - task_res = TaskRes(task=TASK_DISCONNECT) - send(task_res) + if message.metadata.task_type == "reconnect": # type: ignore + send(MESSAGE_DISCONNECT) break # Process server_message and send client_message... - task_res = TaskRes(task=TASK_GET_PROPERTIES) - send(task_res) + send(MESSAGE_GET_PROPERTIES) return messages_received diff --git a/src/py/flwr/client/grpc_rere_client/connection.py b/src/py/flwr/client/grpc_rere_client/connection.py index e5a4b6883378..07635d002721 100644 --- a/src/py/flwr/client/grpc_rere_client/connection.py +++ b/src/py/flwr/client/grpc_rere_client/connection.py @@ -29,6 +29,8 @@ from flwr.common import GRPC_MAX_MESSAGE_LENGTH from flwr.common.grpc import create_channel from flwr.common.logger import log, warn_experimental_feature +from flwr.common.message import Message +from flwr.common.serde import message_from_taskins, message_to_taskres from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611 CreateNodeRequest, DeleteNodeRequest, @@ -37,7 +39,7 @@ ) from flwr.proto.fleet_pb2_grpc import FleetStub # pylint: disable=E0611 from flwr.proto.node_pb2 import Node # pylint: disable=E0611 -from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611 +from flwr.proto.task_pb2 import TaskIns # pylint: disable=E0611 KEY_NODE = "node" KEY_TASK_INS = "current_task_ins" @@ -56,8 +58,8 @@ def grpc_request_response( root_certificates: Optional[Union[bytes, str]] = None, ) -> Iterator[ Tuple[ - Callable[[], Optional[TaskIns]], - Callable[[TaskRes], None], + Callable[[], Optional[Message]], + Callable[[Message], None], Optional[Callable[[], None]], Optional[Callable[[], None]], ] @@ -132,7 +134,7 @@ def delete_node() -> None: del node_store[KEY_NODE] - def receive() -> Optional[TaskIns]: + def receive() -> Optional[Message]: """Receive next task from server.""" # Get Node if node_store[KEY_NODE] is None: @@ -154,10 +156,10 @@ def receive() -> Optional[TaskIns]: # Remember `task_ins` until `task_res` is available state[KEY_TASK_INS] = task_ins - # Return the TaskIns if available - return task_ins + # Return the message if available + return message_from_taskins(task_ins) if task_ins is not None else None - def send(task_res: TaskRes) -> None: + def send(message: Message) -> None: """Send task result back to server.""" # Get Node if node_store[KEY_NODE] is None: @@ -171,6 +173,9 @@ def send(task_res: TaskRes) -> None: return task_ins: TaskIns = cast(TaskIns, state[KEY_TASK_INS]) + # Construct TaskRes + task_res = message_to_taskres(message) + # Check if fields to be set are not initialized if not validate_task_res(task_res): state[KEY_TASK_INS] = None diff --git a/src/py/flwr/client/message_handler/message_handler.py b/src/py/flwr/client/message_handler/message_handler.py index 92815f8a17b1..e61e151da5e9 100644 --- a/src/py/flwr/client/message_handler/message_handler.py +++ b/src/py/flwr/client/message_handler/message_handler.py @@ -24,7 +24,6 @@ maybe_call_get_properties, ) from flwr.client.typing import ClientFn -from flwr.common import serde from flwr.common.configsrecord import ConfigsRecord from flwr.common.constant import ( TASK_TYPE_EVALUATE, @@ -45,7 +44,6 @@ recordset_to_getparametersins, recordset_to_getpropertiesins, ) -from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611 from flwr.proto.transport_pb2 import ( # pylint: disable=E0611 ClientMessage, Reason, @@ -61,25 +59,25 @@ class UnknownServerMessage(Exception): """Exception indicating that the received message is unknown.""" -def handle_control_message(task_ins: TaskIns) -> Tuple[Optional[TaskRes], int]: +def handle_control_message(message: Message) -> Tuple[Optional[Message], int]: """Handle control part of the incoming message. Parameters ---------- - task_ins : TaskIns - The task instruction coming from the server, to be processed by the client. + message : Message + The Message coming from the server, to be processed by the client. Returns ------- - task_res : Optional[TaskRes] - TaskRes to be sent back to the server. If None, the client should + message : Optional[Message] + Message to be sent back to the server. If None, the client should continue to process messages from the server. sleep_duration : int Number of seconds that the client should disconnect from the server. """ - if task_ins.task.task_type == "reconnect": + if message.metadata.task_type == "reconnect": # Retrieve ReconnectIns from recordset - recordset = serde.recordset_from_proto(task_ins.task.recordset) + recordset = message.message seconds = cast(int, recordset.get_configs("config")["seconds"]) # Construct ReconnectIns and call _reconnect disconnect_msg, sleep_duration = _reconnect( @@ -89,14 +87,18 @@ def handle_control_message(task_ins: TaskIns) -> Tuple[Optional[TaskRes], int]: reason = cast(int, disconnect_msg.disconnect_res.reason) recordset = RecordSet() recordset.set_configs("config", ConfigsRecord({"reason": reason})) - task_res = TaskRes( - task=Task( + out_message = Message( + metadata=Metadata( + run_id=0, + task_id="", + group_id="", + ttl="", task_type="reconnect", - recordset=serde.recordset_to_proto(recordset), - ) + ), + message=recordset, ) # Return TaskRes and sleep duration - return task_res, sleep_duration + return out_message, sleep_duration # Any other message return None, 0 diff --git a/src/py/flwr/client/rest_client/connection.py b/src/py/flwr/client/rest_client/connection.py index 1ab15f57e521..a5c8ea0957d2 100644 --- a/src/py/flwr/client/rest_client/connection.py +++ b/src/py/flwr/client/rest_client/connection.py @@ -29,6 +29,8 @@ from flwr.common import GRPC_MAX_MESSAGE_LENGTH from flwr.common.constant import MISSING_EXTRA_REST from flwr.common.logger import log +from flwr.common.message import Message +from flwr.common.serde import message_from_taskins, message_to_taskres from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611 CreateNodeRequest, CreateNodeResponse, @@ -39,7 +41,7 @@ PushTaskResResponse, ) from flwr.proto.node_pb2 import Node # pylint: disable=E0611 -from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611 +from flwr.proto.task_pb2 import TaskIns # pylint: disable=E0611 try: import requests @@ -68,8 +70,8 @@ def http_request_response( ] = None, # pylint: disable=unused-argument ) -> Iterator[ Tuple[ - Callable[[], Optional[TaskIns]], - Callable[[TaskRes], None], + Callable[[], Optional[Message]], + Callable[[Message], None], Optional[Callable[[], None]], Optional[Callable[[], None]], ] @@ -206,7 +208,7 @@ def delete_node() -> None: PATH_PULL_TASK_INS, ) - def receive() -> Optional[TaskIns]: + def receive() -> Optional[Message]: """Receive next task from server.""" # Get Node if node_store[KEY_NODE] is None: @@ -262,12 +264,14 @@ def receive() -> Optional[TaskIns]: # Remember `task_ins` until `task_res` is available state[KEY_TASK_INS] = task_ins - # Return the TaskIns if available + # Return the Message if available + message = None if task_ins is not None: + message = message_from_taskins(task_ins) log(INFO, "[Node] POST /%s: success", PATH_PULL_TASK_INS) - return task_ins + return message - def send(task_res: TaskRes) -> None: + def send(message: Message) -> None: """Send task result back to server.""" # Get Node if node_store[KEY_NODE] is None: @@ -281,6 +285,9 @@ def send(task_res: TaskRes) -> None: task_ins: TaskIns = cast(TaskIns, state[KEY_TASK_INS]) + # Construct TaskRes + task_res = message_to_taskres(message) + # Check if fields to be set are not initialized if not validate_task_res(task_res): state[KEY_TASK_INS] = None From cefb53bd85cb250d7e4a9a2b93ed44a28c107c90 Mon Sep 17 00:00:00 2001 From: Javier Date: Tue, 30 Jan 2024 09:45:31 +0000 Subject: [PATCH 049/113] Remove MXNet e2e test (#2870) --- .github/workflows/e2e.yml | 5 -- e2e/mxnet/.gitignore | 1 - e2e/mxnet/README.md | 5 -- e2e/mxnet/client.py | 141 -------------------------------------- e2e/mxnet/driver.py | 7 -- e2e/mxnet/pyproject.toml | 15 ---- e2e/mxnet/simulation.py | 11 --- 7 files changed, 185 deletions(-) delete mode 100644 e2e/mxnet/.gitignore delete mode 100644 e2e/mxnet/README.md delete mode 100644 e2e/mxnet/client.py delete mode 100644 e2e/mxnet/driver.py delete mode 100644 e2e/mxnet/pyproject.toml delete mode 100644 e2e/mxnet/simulation.py diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index bf3843c25bd4..3352714b854e 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -89,11 +89,6 @@ jobs: from torchvision.datasets import MNIST MNIST('./data', download=True) - - directory: mxnet - dataset: | - import mxnet as mx - mx.test_utils.get_mnist() - - directory: scikit-learn dataset: | import openml diff --git a/e2e/mxnet/.gitignore b/e2e/mxnet/.gitignore deleted file mode 100644 index 10d00b5797e2..000000000000 --- a/e2e/mxnet/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.gz diff --git a/e2e/mxnet/README.md b/e2e/mxnet/README.md deleted file mode 100644 index 3fa76bac5ce0..000000000000 --- a/e2e/mxnet/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Flower with MXNet testing - -This directory is used for testing Flower with MXNet by using a simple NN with MNIST data. - -It uses the `FedAvg` strategy. \ No newline at end of file diff --git a/e2e/mxnet/client.py b/e2e/mxnet/client.py deleted file mode 100644 index 2f0b714e708c..000000000000 --- a/e2e/mxnet/client.py +++ /dev/null @@ -1,141 +0,0 @@ -"""Flower client example using MXNet for MNIST classification. - -The code is generally adapted from: - -https://mxnet.apache.org/api/python/docs/tutorials/packages/gluon/image/mnist.html -""" - - -import flwr as fl -import numpy as np -import mxnet as mx -from mxnet import nd -from mxnet import gluon -from mxnet.gluon import nn -from mxnet import autograd as ag -import mxnet.ndarray as F - -SUBSET_SIZE = 50 - -# Fixing the random seed -mx.random.seed(42) - -# Setup context to GPU or CPU -DEVICE = [mx.gpu() if mx.test_utils.list_gpus() else mx.cpu()] - -def model(): - net = nn.Sequential() - net.add(nn.Dense(256, activation="relu")) - net.add(nn.Dense(64, activation="relu")) - net.add(nn.Dense(10)) - net.collect_params().initialize() - return net - -def load_data(): - print("Download Dataset") - mnist = mx.test_utils.get_mnist() - batch_size = 100 - train_data = mx.io.NDArrayIter( - mnist["train_data"][:SUBSET_SIZE], mnist["train_label"][:SUBSET_SIZE], batch_size, shuffle=True - ) - val_data = mx.io.NDArrayIter(mnist["test_data"][:10], mnist["test_label"][:10], batch_size) - return train_data, val_data - - -def train(net, train_data, epoch): - trainer = gluon.Trainer(net.collect_params(), "sgd", {"learning_rate": 0.01}) - accuracy_metric = mx.metric.Accuracy() - loss_metric = mx.metric.CrossEntropy() - metrics = mx.metric.CompositeEvalMetric() - for child_metric in [accuracy_metric, loss_metric]: - metrics.add(child_metric) - softmax_cross_entropy_loss = gluon.loss.SoftmaxCrossEntropyLoss() - for i in range(epoch): - train_data.reset() - num_examples = 0 - for batch in train_data: - data = gluon.utils.split_and_load( - batch.data[0], ctx_list=DEVICE, batch_axis=0 - ) - label = gluon.utils.split_and_load( - batch.label[0], ctx_list=DEVICE, batch_axis=0 - ) - outputs = [] - with ag.record(): - for x, y in zip(data, label): - z = net(x) - loss = softmax_cross_entropy_loss(z, y) - loss.backward() - outputs.append(z.softmax()) - num_examples += len(x) - metrics.update(label, outputs) - trainer.step(batch.data[0].shape[0]) - trainings_metric = metrics.get_name_value() - print("Accuracy & loss at epoch %d: %s" % (i, trainings_metric)) - return trainings_metric, num_examples - - -def test(net, val_data): - accuracy_metric = mx.metric.Accuracy() - loss_metric = mx.metric.CrossEntropy() - metrics = mx.metric.CompositeEvalMetric() - for child_metric in [accuracy_metric, loss_metric]: - metrics.add(child_metric) - val_data.reset() - num_examples = 0 - for batch in val_data: - data = gluon.utils.split_and_load(batch.data[0], ctx_list=DEVICE, batch_axis=0) - label = gluon.utils.split_and_load( - batch.label[0], ctx_list=DEVICE, batch_axis=0 - ) - outputs = [] - for x in data: - outputs.append(net(x).softmax()) - num_examples += len(x) - metrics.update(label, outputs) - metrics.update(label, outputs) - return metrics.get_name_value(), num_examples - -train_data, val_data = load_data() - -model = model() -init = nd.random.uniform(shape=(2, 784)) -model(init) - -# Flower Client -class FlowerClient(fl.client.NumPyClient): - def get_parameters(self, config): - param = [] - for val in model.collect_params(".*weight").values(): - p = val.data() - param.append(p.asnumpy()) - return param - - def set_parameters(self, parameters): - params = zip(model.collect_params(".*weight").keys(), parameters) - for key, value in params: - model.collect_params().setattr(key, value) - - def fit(self, parameters, config): - self.set_parameters(parameters) - [accuracy, loss], num_examples = train(model, train_data, epoch=2) - results = {"accuracy": float(accuracy[1]), "loss": float(loss[1])} - return self.get_parameters(config={}), num_examples, results - - def evaluate(self, parameters, config): - self.set_parameters(parameters) - [accuracy, loss], num_examples = test(model, val_data) - print("Evaluation accuracy & loss", accuracy, loss) - return float(loss[1]), num_examples, {"accuracy": float(accuracy[1])} - - -def client_fn(cid): - return FlowerClient().to_client() - -flower = fl.flower.Flower( - client_fn=client_fn, -) - -if __name__ == "__main__": - # Start Flower client - fl.client.start_numpy_client(server_address="127.0.0.1:8080", client=FlowerClient()) diff --git a/e2e/mxnet/driver.py b/e2e/mxnet/driver.py deleted file mode 100644 index 2b1b35d9e89c..000000000000 --- a/e2e/mxnet/driver.py +++ /dev/null @@ -1,7 +0,0 @@ -import flwr as fl - -hist = fl.driver.start_driver( - server_address="0.0.0.0:9091", - config=fl.server.ServerConfig(num_rounds=3), -) -assert (hist.losses_distributed[0][1] / hist.losses_distributed[-1][1]) >= 1 diff --git a/e2e/mxnet/pyproject.toml b/e2e/mxnet/pyproject.toml deleted file mode 100644 index 71bd0e6374bd..000000000000 --- a/e2e/mxnet/pyproject.toml +++ /dev/null @@ -1,15 +0,0 @@ -[build-system] -requires = ["poetry-core>=1.4.0"] -build-backend = "poetry.core.masonry.api" - -[tool.poetry] -name = "mxnet_example" -version = "0.1.0" -description = "MXNet example with MNIST and CNN" -authors = ["The Flower Authors "] - -[tool.poetry.dependencies] -python = "^3.8" -flwr = { path = "../../", develop = true, extras = ["simulation"] } -mxnet = "^1.7.0" -numpy = "1.23.1" diff --git a/e2e/mxnet/simulation.py b/e2e/mxnet/simulation.py deleted file mode 100644 index 5f0e5334bd08..000000000000 --- a/e2e/mxnet/simulation.py +++ /dev/null @@ -1,11 +0,0 @@ -import flwr as fl - -from client import client_fn - -hist = fl.simulation.start_simulation( - client_fn=client_fn, - num_clients=2, - config=fl.server.ServerConfig(num_rounds=3), -) - -assert hist.losses_distributed[-1][1] == 0 or (hist.losses_distributed[0][1] / hist.losses_distributed[-1][1]) >= 0.98 From 81cc08ed68d8fa24920faea254ccf529e13af888 Mon Sep 17 00:00:00 2001 From: Javier Date: Tue, 30 Jan 2024 10:30:10 +0000 Subject: [PATCH 050/113] Stop using `start_numpy_client` in e2e tests (#2869) Co-authored-by: Daniel J. Beutel --- ...mple-jax-from-centralized-to-federated.rst | 2 +- ...-pytorch-from-centralized-to-federated.rst | 4 +-- doc/source/how-to-enable-ssl-connections.rst | 4 +-- doc/source/how-to-run-simulations.rst | 2 +- doc/source/ref-changelog.md | 4 +++ .../tutorial-quickstart-huggingface.rst | 4 +-- doc/source/tutorial-quickstart-jax.rst | 2 +- doc/source/tutorial-quickstart-pytorch.rst | 4 +-- .../tutorial-quickstart-scikitlearn.rst | 4 +-- doc/source/tutorial-quickstart-tensorflow.rst | 4 +-- e2e/bare-https/client.py | 4 +-- e2e/bare/client.py | 2 +- e2e/fastai/client.py | 4 +-- e2e/jax/client.py | 2 +- e2e/opacus/client.py | 4 +-- e2e/pandas/client.py | 4 +-- e2e/pytorch-lightning/client.py | 4 +-- e2e/pytorch/client.py | 4 +-- e2e/scikit-learn/client.py | 2 +- e2e/strategies/client.py | 2 +- e2e/tabnet/client.py | 2 +- e2e/tensorflow/client.py | 2 +- src/py/flwr/client/app.py | 35 +++++++++++-------- src/py/flwr/simulation/ray_transport/utils.py | 21 +++++------ 24 files changed, 69 insertions(+), 57 deletions(-) diff --git a/doc/source/example-jax-from-centralized-to-federated.rst b/doc/source/example-jax-from-centralized-to-federated.rst index 2b1823e9d408..6b06a288a67a 100644 --- a/doc/source/example-jax-from-centralized-to-federated.rst +++ b/doc/source/example-jax-from-centralized-to-federated.rst @@ -259,7 +259,7 @@ Having defined the federation process, we can run it. # Start Flower client client = FlowerClient(params, grad_fn, train_x, train_y, test_x, test_y) - fl.client.start_numpy_client(server_address="0.0.0.0:8080", client) + fl.client.start_client(server_address="0.0.0.0:8080", client.to_client()) if __name__ == "__main__": main() diff --git a/doc/source/example-pytorch-from-centralized-to-federated.rst b/doc/source/example-pytorch-from-centralized-to-federated.rst index d649658667da..58101135b8c0 100644 --- a/doc/source/example-pytorch-from-centralized-to-federated.rst +++ b/doc/source/example-pytorch-from-centralized-to-federated.rst @@ -278,7 +278,7 @@ We included type annotations to give you a better understanding of the data type return float(loss), self.num_examples["testset"], {"accuracy": float(accuracy)} All that's left to do it to define a function that loads both model and data, creates a :code:`CifarClient`, and starts this client. -You load your data and model by using :code:`cifar.py`. Start :code:`CifarClient` with the function :code:`fl.client.start_numpy_client()` by pointing it at the same IP adress we used in :code:`server.py`: +You load your data and model by using :code:`cifar.py`. Start :code:`CifarClient` with the function :code:`fl.client.start_client()` by pointing it at the same IP adress we used in :code:`server.py`: .. code-block:: python @@ -292,7 +292,7 @@ You load your data and model by using :code:`cifar.py`. Start :code:`CifarClient # Start client client = CifarClient(model, trainloader, testloader, num_examples) - fl.client.start_numpy_client(server_address="0.0.0.0:8080", client) + fl.client.start_client(server_address="0.0.0.0:8080", client.to_client()) if __name__ == "__main__": diff --git a/doc/source/how-to-enable-ssl-connections.rst b/doc/source/how-to-enable-ssl-connections.rst index fa59d4423c5a..051dd5711497 100644 --- a/doc/source/how-to-enable-ssl-connections.rst +++ b/doc/source/how-to-enable-ssl-connections.rst @@ -75,9 +75,9 @@ We are now going to show how to write a client which uses the previously generat client = MyFlowerClient() # Start client - fl.client.start_numpy_client( + fl.client.start_client( "localhost:8080", - client=client, + client=client.to_client(), root_certificates=Path(".cache/certificates/ca.crt").read_bytes(), ) diff --git a/doc/source/how-to-run-simulations.rst b/doc/source/how-to-run-simulations.rst index 707e3d3ffe84..6e0520a79bf5 100644 --- a/doc/source/how-to-run-simulations.rst +++ b/doc/source/how-to-run-simulations.rst @@ -7,7 +7,7 @@ Run simulations Simulating Federated Learning workloads is useful for a multitude of use-cases: you might want to run your workload on a large cohort of clients but without having to source, configure and mange a large number of physical devices; you might want to run your FL workloads as fast as possible on the compute systems you have access to without having to go through a complex setup process; you might want to validate your algorithm on different scenarios at varying levels of data and system heterogeneity, client availability, privacy budgets, etc. These are among some of the use-cases where simulating FL workloads makes sense. Flower can accommodate these scenarios by means of its `VirtualClientEngine `_ or VCE. -The :code:`VirtualClientEngine` schedules, launches and manages `virtual` clients. These clients are identical to `non-virtual` clients (i.e. the ones you launch via the command `flwr.client.start_numpy_client `_) in the sense that they can be configure by creating a class inheriting, for example, from `flwr.client.NumPyClient `_ and therefore behave in an identical way. In addition to that, clients managed by the :code:`VirtualClientEngine` are: +The :code:`VirtualClientEngine` schedules, launches and manages `virtual` clients. These clients are identical to `non-virtual` clients (i.e. the ones you launch via the command `flwr.client.start_client `_) in the sense that they can be configure by creating a class inheriting, for example, from `flwr.client.NumPyClient `_ and therefore behave in an identical way. In addition to that, clients managed by the :code:`VirtualClientEngine` are: * resource-aware: this means that each client gets assigned a portion of the compute and memory on your system. You as a user can control this at the beginning of the simulation and allows you to control the degree of parallelism of your Flower FL simulation. The fewer the resources per client, the more clients can run concurrently on the same hardware. * self-managed: this means that you as a user do not need to launch clients manually, instead this gets delegated to :code:`VirtualClientEngine`'s internals. diff --git a/doc/source/ref-changelog.md b/doc/source/ref-changelog.md index 5f323bc80baa..f1af015ac24c 100644 --- a/doc/source/ref-changelog.md +++ b/doc/source/ref-changelog.md @@ -8,6 +8,10 @@ - **Retiring MXNet examples** The development of the MXNet fremework has ended and the project is now [archived on GitHub](https://github.com/apache/mxnet). Existing MXNet examples won't receive updates [#2724](https://github.com/adap/flower/pull/2724) +- **Deprecated `start_numpy_client`**. ([#2563](https://github.com/adap/flower/pull/2563)) + + Until now, clients of type `NumPyClient` needed to be started via `start_numpy_client`. In our efforts to consolidate the core framework, we have introduced changes, and now all client types should start via `start_client`. To continue using `NumPyClient` clients, you simply need to first call the `.to_client()` method and then pass returned `Client` object to `start_client`. The examples and the documentation have been updated accordingly. + - **Update Flower Baselines** - HFedXGBoost [#2226](https://github.com/adap/flower/pull/2226) diff --git a/doc/source/tutorial-quickstart-huggingface.rst b/doc/source/tutorial-quickstart-huggingface.rst index 7718e6558456..1e06120b452f 100644 --- a/doc/source/tutorial-quickstart-huggingface.rst +++ b/doc/source/tutorial-quickstart-huggingface.rst @@ -212,9 +212,9 @@ We can now start client instances using: .. code-block:: python - fl.client.start_numpy_client( + fl.client.start_client( server_address="127.0.0.1:8080", - client=IMDBClient() + client=IMDBClient().to_client() ) diff --git a/doc/source/tutorial-quickstart-jax.rst b/doc/source/tutorial-quickstart-jax.rst index 945f231e112e..d2b9243e2bb3 100644 --- a/doc/source/tutorial-quickstart-jax.rst +++ b/doc/source/tutorial-quickstart-jax.rst @@ -265,7 +265,7 @@ Having defined the federation process, we can run it. # Start Flower client client = FlowerClient(params, grad_fn, train_x, train_y, test_x, test_y) - fl.client.start_numpy_client(server_address="0.0.0.0:8080", client) + fl.client.start_client(server_address="0.0.0.0:8080", client=client.to_client()) if __name__ == "__main__": main() diff --git a/doc/source/tutorial-quickstart-pytorch.rst b/doc/source/tutorial-quickstart-pytorch.rst index fb77d107b63f..f15a4a93114e 100644 --- a/doc/source/tutorial-quickstart-pytorch.rst +++ b/doc/source/tutorial-quickstart-pytorch.rst @@ -191,10 +191,10 @@ to actually run this client: .. code-block:: python - fl.client.start_numpy_client(server_address="[::]:8080", client=CifarClient()) + fl.client.start_client(server_address="[::]:8080", client=CifarClient().to_client()) That's it for the client. We only have to implement :code:`Client` or -:code:`NumPyClient` and call :code:`fl.client.start_client()` or :code:`fl.client.start_numpy_client()`. The string :code:`"[::]:8080"` tells the client which server to connect to. In our case we can run the server and the client on the same machine, therefore we use +:code:`NumPyClient` and call :code:`fl.client.start_client()`. If you implement a client of type :code:`NumPyClient` you'll need to first call its :code:`to_client()` method. The string :code:`"[::]:8080"` tells the client which server to connect to. In our case we can run the server and the client on the same machine, therefore we use :code:`"[::]:8080"`. If we run a truly federated workload with the server and clients running on different machines, all that needs to change is the :code:`server_address` we point the client at. diff --git a/doc/source/tutorial-quickstart-scikitlearn.rst b/doc/source/tutorial-quickstart-scikitlearn.rst index b33068e975fa..4921f63bab2c 100644 --- a/doc/source/tutorial-quickstart-scikitlearn.rst +++ b/doc/source/tutorial-quickstart-scikitlearn.rst @@ -145,10 +145,10 @@ to actually run this client: .. code-block:: python - fl.client.start_numpy_client("0.0.0.0:8080", client=MnistClient()) + fl.client.start_client("0.0.0.0:8080", client=MnistClient().to_client()) That's it for the client. We only have to implement :code:`Client` or -:code:`NumPyClient` and call :code:`fl.client.start_client()` or :code:`fl.client.start_numpy_client()`. The string :code:`"0.0.0.0:8080"` tells the client which server to connect to. In our case we can run the server and the client on the same machine, therefore we use +:code:`NumPyClient` and call :code:`fl.client.start_client()`. If you implement a client of type :code:`NumPyClient` you'll need to first call its :code:`to_client()` method. The string :code:`"0.0.0.0:8080"` tells the client which server to connect to. In our case we can run the server and the client on the same machine, therefore we use :code:`"0.0.0.0:8080"`. If we run a truly federated workload with the server and clients running on different machines, all that needs to change is the :code:`server_address` we pass to the client. diff --git a/doc/source/tutorial-quickstart-tensorflow.rst b/doc/source/tutorial-quickstart-tensorflow.rst index 64b2255a9ac6..bd63eb461d21 100644 --- a/doc/source/tutorial-quickstart-tensorflow.rst +++ b/doc/source/tutorial-quickstart-tensorflow.rst @@ -84,11 +84,11 @@ to actually run this client: .. code-block:: python - fl.client.start_numpy_client(server_address="[::]:8080", client=CifarClient()) + fl.client.start_client(server_address="[::]:8080", client=CifarClient().to_client()) That's it for the client. We only have to implement :code:`Client` or -:code:`NumPyClient` and call :code:`fl.client.start_client()` or :code:`fl.client.start_numpy_client()`. The string :code:`"[::]:8080"` tells the client which server to connect to. In our case we can run the server and the client on the same machine, therefore we use +:code:`NumPyClient` and call :code:`fl.client.start_client()`. If you implement a client of type :code:`NumPyClient` you'll need to first call its :code:`to_client()` method. The string :code:`"[::]:8080"` tells the client which server to connect to. In our case we can run the server and the client on the same machine, therefore we use :code:`"[::]:8080"`. If we run a truly federated workload with the server and clients running on different machines, all that needs to change is the :code:`server_address` we point the client at. diff --git a/e2e/bare-https/client.py b/e2e/bare-https/client.py index 20a5b4875ddf..04563acdd73f 100644 --- a/e2e/bare-https/client.py +++ b/e2e/bare-https/client.py @@ -31,9 +31,9 @@ def client_fn(cid): if __name__ == "__main__": # Start Flower client - fl.client.start_numpy_client( + fl.client.start_client( server_address="127.0.0.1:8080", - client=FlowerClient(), + client=FlowerClient().to_client(), root_certificates=Path("certificates/ca.crt").read_bytes(), insecure=False, ) diff --git a/e2e/bare/client.py b/e2e/bare/client.py index 59ef2e4248ee..1068bd7da6d1 100644 --- a/e2e/bare/client.py +++ b/e2e/bare/client.py @@ -52,4 +52,4 @@ def client_fn(cid): if __name__ == "__main__": # Start Flower client - fl.client.start_numpy_client(server_address="127.0.0.1:8080", client=FlowerClient()) + fl.client.start_client(server_address="127.0.0.1:8080", client=FlowerClient().to_client()) diff --git a/e2e/fastai/client.py b/e2e/fastai/client.py index 4425fed25277..69b20f7e26c3 100644 --- a/e2e/fastai/client.py +++ b/e2e/fastai/client.py @@ -60,7 +60,7 @@ def client_fn(cid): if __name__ == "__main__": # Start Flower client - fl.client.start_numpy_client( + fl.client.start_client( server_address="127.0.0.1:8080", - client=FlowerClient(), + client=FlowerClient().to_client(), ) diff --git a/e2e/jax/client.py b/e2e/jax/client.py index 495d6a671981..1536487dd466 100644 --- a/e2e/jax/client.py +++ b/e2e/jax/client.py @@ -59,4 +59,4 @@ def client_fn(cid): if __name__ == "__main__": # Start Flower client - fl.client.start_numpy_client(server_address="127.0.0.1:8080", client=FlowerClient()) + fl.client.start_client(server_address="127.0.0.1:8080", client=FlowerClient().to_client()) diff --git a/e2e/opacus/client.py b/e2e/opacus/client.py index 2e5c363381fa..205bc39adbac 100644 --- a/e2e/opacus/client.py +++ b/e2e/opacus/client.py @@ -142,7 +142,7 @@ def client_fn(cid): ) if __name__ == "__main__": - fl.client.start_numpy_client( + fl.client.start_client( server_address="127.0.0.1:8080", - client=FlowerClient(model) + client=FlowerClient(model).to_client() ) diff --git a/e2e/pandas/client.py b/e2e/pandas/client.py index 5b8670091cb3..efc2eb763f53 100644 --- a/e2e/pandas/client.py +++ b/e2e/pandas/client.py @@ -42,7 +42,7 @@ def client_fn(cid): if __name__ == "__main__": # Start Flower client - fl.client.start_numpy_client( + fl.client.start_client( server_address="127.0.0.1:8080", - client=FlowerClient(), + client=FlowerClient().to_client(), ) diff --git a/e2e/pytorch-lightning/client.py b/e2e/pytorch-lightning/client.py index 71b178eca8c3..632683e8ec01 100644 --- a/e2e/pytorch-lightning/client.py +++ b/e2e/pytorch-lightning/client.py @@ -65,8 +65,8 @@ def main() -> None: train_loader, val_loader, test_loader = mnist.load_data() # Flower client - client = FlowerClient(model, train_loader, val_loader, test_loader) - fl.client.start_numpy_client(server_address="127.0.0.1:8080", client=client) + client = FlowerClient(model, train_loader, val_loader, test_loader).to_client() + fl.client.start_client(server_address="127.0.0.1:8080", client=client) if __name__ == "__main__": diff --git a/e2e/pytorch/client.py b/e2e/pytorch/client.py index ccd36f47d22a..cce4701ff6e6 100644 --- a/e2e/pytorch/client.py +++ b/e2e/pytorch/client.py @@ -133,7 +133,7 @@ def client_fn(cid): if __name__ == "__main__": # Start Flower client - fl.client.start_numpy_client( + fl.client.start_client( server_address="127.0.0.1:8080", - client=FlowerClient(), + client=FlowerClient().to_client(), ) diff --git a/e2e/scikit-learn/client.py b/e2e/scikit-learn/client.py index fdca96c1697a..e137a28c356b 100644 --- a/e2e/scikit-learn/client.py +++ b/e2e/scikit-learn/client.py @@ -52,4 +52,4 @@ def client_fn(cid): if __name__ == "__main__": # Start Flower client - fl.client.start_numpy_client(server_address="0.0.0.0:8080", client=FlowerClient()) + fl.client.start_client(server_address="0.0.0.0:8080", client=FlowerClient().to_client()) diff --git a/e2e/strategies/client.py b/e2e/strategies/client.py index eb4598cb5439..5a341d041f12 100644 --- a/e2e/strategies/client.py +++ b/e2e/strategies/client.py @@ -54,4 +54,4 @@ def client_fn(cid): if __name__ == "__main__": # Start Flower client - fl.client.start_numpy_client(server_address="127.0.0.1:8080", client=FlowerClient()) + fl.client.start_client(server_address="127.0.0.1:8080", client=FlowerClient().to_client()) diff --git a/e2e/tabnet/client.py b/e2e/tabnet/client.py index 3c10df0c79f1..5e3a5e52680b 100644 --- a/e2e/tabnet/client.py +++ b/e2e/tabnet/client.py @@ -87,4 +87,4 @@ def client_fn(cid): if __name__ == "__main__": # Start Flower client - fl.client.start_numpy_client(server_address="127.0.0.1:8080", client=FlowerClient()) + fl.client.start_client(server_address="127.0.0.1:8080", client=FlowerClient().to_client()) diff --git a/e2e/tensorflow/client.py b/e2e/tensorflow/client.py index 4ad2d5ebda57..fc5eb5ab39b3 100644 --- a/e2e/tensorflow/client.py +++ b/e2e/tensorflow/client.py @@ -40,4 +40,4 @@ def client_fn(cid): if __name__ == "__main__": # Start Flower client - fl.client.start_numpy_client(server_address="127.0.0.1:8080", client=FlowerClient()) + fl.client.start_client(server_address="127.0.0.1:8080", client=FlowerClient().to_client()) diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index dcea3b91da83..2f02e753d63a 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -34,7 +34,7 @@ TRANSPORT_TYPE_REST, TRANSPORT_TYPES, ) -from flwr.common.logger import log, warn_experimental_feature +from flwr.common.logger import log, warn_deprecated_feature, warn_experimental_feature from flwr.common.message import Message from .flower import load_flower_callable @@ -399,6 +399,12 @@ def start_numpy_client( ) -> None: """Start a Flower NumPyClient which connects to a gRPC server. + Warning + ------- + This function is deprecated since 1.7.0. Use :code:`flwr.client.start_client` + instead and first convert your :code:`NumPyClient` to type + :code:`flwr.client.Client` by executing its :code:`to_client()` method. + Parameters ---------- server_address : str @@ -454,21 +460,22 @@ def start_numpy_client( >>> root_certificates=Path("/crts/root.pem").read_bytes(), >>> ) """ - # warnings.warn( - # "flwr.client.start_numpy_client() is deprecated and will " - # "be removed in a future version of Flower. Instead, pass " - # "your client to `flwr.client.start_client()` by calling " - # "first the `.to_client()` method as shown below: \n" - # "\tflwr.client.start_client(\n" - # "\t\tserver_address=':',\n" - # "\t\tclient=FlowerClient().to_client()\n" - # "\t)", - # DeprecationWarning, - # stacklevel=2, - # ) + mssg = ( + "flwr.client.start_numpy_client() is deprecated. \n\tInstead, use " + "`flwr.client.start_client()` by ensuring you first call " + "the `.to_client()` method as shown below: \n" + "\tflwr.client.start_client(\n" + "\t\tserver_address=':',\n" + "\t\tclient=FlowerClient().to_client()," + " # <-- where FlowerClient is of type flwr.client.NumPyClient object\n" + "\t)\n" + "\tUsing `start_numpy_client()` is deprecated." + ) + + warn_deprecated_feature(name=mssg) # Calling this function is deprecated. A warning is thrown. - # We first need to convert either the supplied client to `Client.` + # We first need to convert the supplied client to `Client.` wrp_client = client.to_client() diff --git a/src/py/flwr/simulation/ray_transport/utils.py b/src/py/flwr/simulation/ray_transport/utils.py index 41aa8049eaf0..dd9fb6b2aa85 100644 --- a/src/py/flwr/simulation/ray_transport/utils.py +++ b/src/py/flwr/simulation/ray_transport/utils.py @@ -15,6 +15,7 @@ """Utilities for Actors in the Virtual Client Engine.""" import traceback +import warnings from logging import ERROR from flwr.client import Client @@ -26,7 +27,7 @@ TF = None # Display Deprecation warning once -# warnings.filterwarnings("once", category=DeprecationWarning) +warnings.filterwarnings("once", category=DeprecationWarning) def enable_tf_gpu_growth() -> None: @@ -69,15 +70,15 @@ def check_clientfn_returns_client(client: Client) -> Client: the client internally to `Client` by calling `.to_client()`. """ if not isinstance(client, Client): - # mssg = ( - # " Ensure your client is of type `Client`. Please convert it" - # " using the `.to_client()` method before returning it" - # " in the `client_fn` you pass to `start_simulation`." - # " We have applied this conversion on your behalf." - # " Not returning a `Client` might trigger an error in future" - # " versions of Flower." - # ) + mssg = ( + " Ensure your client is of type `flwr.client.Client`. Please convert it" + " using the `.to_client()` method before returning it" + " in the `client_fn` you pass to `start_simulation`." + " We have applied this conversion on your behalf." + " Not returning a `Client` might trigger an error in future" + " versions of Flower." + ) - # warnings.warn(mssg, DeprecationWarning, stacklevel=2) + warnings.warn(mssg, DeprecationWarning, stacklevel=2) client = client.to_client() return client From b9b0a90a6eb7aa129116c2f62753fd07f3713aa2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jan 2024 11:04:51 +0000 Subject: [PATCH 051/113] Update types-setuptools requirement (#2857) Updates the requirements on [types-setuptools](https://github.com/python/typeshed) to permit the latest version. - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-setuptools dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Daniel J. Beutel --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index e47308b03f95..4beb3f0c6446 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -82,7 +82,7 @@ rest = ["requests", "starlette", "uvicorn"] types-dataclasses = "==0.6.6" types-protobuf = "==3.19.18" types-requests = "==2.31.0.20240125" -types-setuptools = "==69.0.0.20240115" +types-setuptools = "==69.0.0.20240125" clang-format = "==17.0.4" isort = "==5.13.2" black = { version = "==23.10.1", extras = ["jupyter"] } From 354cfa107e7ebbdc9855c6e76487bf62057c9b48 Mon Sep 17 00:00:00 2001 From: Javier Date: Tue, 30 Jan 2024 17:00:57 +0000 Subject: [PATCH 052/113] Update simulation step-by-step example (#2726) --- .../Part-I/client.py | 2 +- .../Part-II/client.py | 2 +- .../README.md | 13 ++++++------- .../requirements.txt | 2 ++ 4 files changed, 10 insertions(+), 9 deletions(-) create mode 100644 examples/flower-simulation-step-by-step-pytorch/requirements.txt diff --git a/examples/flower-simulation-step-by-step-pytorch/Part-I/client.py b/examples/flower-simulation-step-by-step-pytorch/Part-I/client.py index b10c32d36c42..eac831ad1932 100644 --- a/examples/flower-simulation-step-by-step-pytorch/Part-I/client.py +++ b/examples/flower-simulation-step-by-step-pytorch/Part-I/client.py @@ -98,7 +98,7 @@ def client_fn(cid: str): trainloader=trainloaders[int(cid)], vallodaer=valloaders[int(cid)], num_classes=num_classes, - ) + ).to_client() # return the function to spawn client return client_fn diff --git a/examples/flower-simulation-step-by-step-pytorch/Part-II/client.py b/examples/flower-simulation-step-by-step-pytorch/Part-II/client.py index d269d4892a0e..7da9547d7362 100644 --- a/examples/flower-simulation-step-by-step-pytorch/Part-II/client.py +++ b/examples/flower-simulation-step-by-step-pytorch/Part-II/client.py @@ -75,6 +75,6 @@ def client_fn(cid: str): trainloader=trainloaders[int(cid)], vallodaer=valloaders[int(cid)], model_cfg=model_cfg, - ) + ).to_client() return client_fn diff --git a/examples/flower-simulation-step-by-step-pytorch/README.md b/examples/flower-simulation-step-by-step-pytorch/README.md index 55b8d837b090..beb8dd7f6f95 100644 --- a/examples/flower-simulation-step-by-step-pytorch/README.md +++ b/examples/flower-simulation-step-by-step-pytorch/README.md @@ -1,5 +1,7 @@ # Flower Simulation Step-by-Step +> Since this tutorial (and its video series) was put together, Flower has been updated a few times. As a result, some of the steps to construct the environment (see below) have been updated. Some parts of the code have also been updated. Overall, the content of this tutorial and how things work remains the same as in the video tutorials. + This directory contains the code developed in the `Flower Simulation` tutorial series on Youtube. You can find all the videos [here](https://www.youtube.com/playlist?list=PLNG4feLHqCWlnj8a_E1A_n5zr2-8pafTB) or clicking on the video preview below. - In `Part-I` (7 videos) we developed from scratch a complete Federated Learning pipeline for simulation using PyTorch. @@ -19,20 +21,17 @@ As presented in the video, we first need to create a Python environment. You are # I'm assuming you are running this on an Ubuntu 22.04 machine (GPU is not required) # create the environment -conda create -n flower_tutorial python=3.8 -y +conda create -n flower_tutorial python=3.9 -y # activate your environment (depending on how you installed conda you might need to use `conda activate ...` instead) source activate flower_tutorial # install PyToch (other versions would likely work) conda install pytorch==1.13.1 torchvision==0.14.1 torchaudio==0.13.1 pytorch-cuda=11.6 -c pytorch -c nvidia -y -# conda install pytorch==1.13.1 torchvision==0.14.1 torchaudio==0.13.1 -c pytorch # If you don't have a GPU +# conda install pytorch==1.13.1 torchvision==0.14.1 torchaudio==0.13.1 -c pytorch -y # If you don't have a GPU -# install flower (for FL) and hydra (for configs) -pip install flwr==1.4.0 hydra-core==1.3.2 -# install ray -# you might see some warning messages after installing it (you can ignore them) -pip install ray==1.11.1 +# Install Flower and other dependencies +pip install -r requirements.txt ``` If you are running this on macOS with Apple Silicon (i.e. M1, M2), you'll need a different `grpcio` package if you see an error when running the code. To fix this do: diff --git a/examples/flower-simulation-step-by-step-pytorch/requirements.txt b/examples/flower-simulation-step-by-step-pytorch/requirements.txt new file mode 100644 index 000000000000..a322192ca711 --- /dev/null +++ b/examples/flower-simulation-step-by-step-pytorch/requirements.txt @@ -0,0 +1,2 @@ +flwr[simulation]>=1.0, <2.0 +hydra-core==1.3.2 \ No newline at end of file From 12b06430834ff70f5eea9a3b83275baf578a09b6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 31 Jan 2024 09:09:38 +0100 Subject: [PATCH 053/113] Update jupyterlab requirement from ==4.0.9 to ==4.0.12 (#2872) Updates the requirements on [jupyterlab](https://github.com/jupyterlab/jupyterlab) to permit the latest version. - [Release notes](https://github.com/jupyterlab/jupyterlab/releases) - [Changelog](https://github.com/jupyterlab/jupyterlab/blob/@jupyterlab/lsp@4.0.12/CHANGELOG.md) - [Commits](https://github.com/jupyterlab/jupyterlab/compare/@jupyterlab/lsp@4.0.9...@jupyterlab/lsp@4.0.12) --- updated-dependencies: - dependency-name: jupyterlab dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 4beb3f0c6446..b944b3e98bfb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -95,7 +95,7 @@ pytest-cov = "==4.1.0" pytest-watch = "==4.2.0" grpcio-tools = "==1.60.0" mypy-protobuf = "==3.2.0" -jupyterlab = "==4.0.9" +jupyterlab = "==4.0.12" rope = "==1.11.0" semver = "==3.0.2" sphinx = "==6.2.1" From 44101febc6caaa2503f891c24438b2d7d938f962 Mon Sep 17 00:00:00 2001 From: Charles Beauville Date: Wed, 31 Jan 2024 11:56:05 +0100 Subject: [PATCH 054/113] Fix error when using SQLite with gRPC-rere (#2874) --- src/py/flwr/server/app.py | 2 +- .../flwr/server/fleet/grpc_rere/fleet_servicer.py | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/py/flwr/server/app.py b/src/py/flwr/server/app.py index e50e631b3ca3..079d6923b23c 100644 --- a/src/py/flwr/server/app.py +++ b/src/py/flwr/server/app.py @@ -532,7 +532,7 @@ def _run_fleet_api_grpc_rere( """Run Fleet API (gRPC, request-response).""" # Create Fleet API gRPC server fleet_servicer = FleetServicer( - state=state_factory.state(), + state_factory=state_factory, ) fleet_add_servicer_to_server_fn = add_FleetServicer_to_server fleet_grpc_server = generic_create_grpc_server( diff --git a/src/py/flwr/server/fleet/grpc_rere/fleet_servicer.py b/src/py/flwr/server/fleet/grpc_rere/fleet_servicer.py index b12f365e898c..25707b6247fa 100644 --- a/src/py/flwr/server/fleet/grpc_rere/fleet_servicer.py +++ b/src/py/flwr/server/fleet/grpc_rere/fleet_servicer.py @@ -32,14 +32,14 @@ PushTaskResResponse, ) from flwr.server.fleet.message_handler import message_handler -from flwr.server.state import State +from flwr.server.state import StateFactory class FleetServicer(fleet_pb2_grpc.FleetServicer): """Fleet API servicer.""" - def __init__(self, state: State) -> None: - self.state = state + def __init__(self, state_factory: StateFactory) -> None: + self.state_factory = state_factory def CreateNode( self, request: CreateNodeRequest, context: grpc.ServicerContext @@ -48,7 +48,7 @@ def CreateNode( log(INFO, "FleetServicer.CreateNode") return message_handler.create_node( request=request, - state=self.state, + state=self.state_factory.state(), ) def DeleteNode( @@ -58,7 +58,7 @@ def DeleteNode( log(INFO, "FleetServicer.DeleteNode") return message_handler.delete_node( request=request, - state=self.state, + state=self.state_factory.state(), ) def PullTaskIns( @@ -68,7 +68,7 @@ def PullTaskIns( log(INFO, "FleetServicer.PullTaskIns") return message_handler.pull_task_ins( request=request, - state=self.state, + state=self.state_factory.state(), ) def PushTaskRes( @@ -78,5 +78,5 @@ def PushTaskRes( log(INFO, "FleetServicer.PushTaskRes") return message_handler.push_task_res( request=request, - state=self.state, + state=self.state_factory.state(), ) From 2c4f055c615041999b6a73a7f4b5ea0dafc8e6f3 Mon Sep 17 00:00:00 2001 From: Charles Beauville Date: Wed, 31 Jan 2024 15:14:00 +0100 Subject: [PATCH 055/113] Add SQlite test to E2E (#2873) --- .github/workflows/e2e.yml | 3 +++ e2e/test_driver.sh | 11 ++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 3352714b854e..e7b596fb92f6 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -133,6 +133,9 @@ jobs: run: python simulation.py - name: Run driver test run: ./../test_driver.sh "${{ matrix.directory }}" + - name: Test server with sqlite state + if: ${{ matrix.directory == 'bare' }} + run: ./../test_driver.sh bare sqlite strategies: runs-on: ubuntu-22.04 diff --git a/e2e/test_driver.sh b/e2e/test_driver.sh index 32314bd22533..2e5936198634 100755 --- a/e2e/test_driver.sh +++ b/e2e/test_driver.sh @@ -13,7 +13,16 @@ case "$1" in ;; esac -timeout 2m flower-server $server_arg & +case "$2" in + sqlite) + db_args="--database $(date +%s).db" + ;; + *) + db_args="--database :flwr-in-memory-state:" + ;; +esac + +timeout 2m flower-server $server_arg $db_args & sleep 3 timeout 2m flower-client client:flower $client_arg --server 127.0.0.1:9092 & From e49a0c998915c40b18cd270b5f31212424516edb Mon Sep 17 00:00:00 2001 From: Charles Beauville Date: Wed, 31 Jan 2024 16:33:34 +0100 Subject: [PATCH 056/113] Add REST transport to client callable (#2879) --- .github/workflows/e2e.yml | 5 ++++- e2e/bare/pyproject.toml | 2 +- e2e/test_driver.sh | 19 ++++++++++++++----- src/py/flwr/client/app.py | 7 ++++++- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index e7b596fb92f6..065e79fff9ab 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -133,7 +133,10 @@ jobs: run: python simulation.py - name: Run driver test run: ./../test_driver.sh "${{ matrix.directory }}" - - name: Test server with sqlite state + - name: Run driver test with REST + if: ${{ matrix.directory == 'bare' }} + run: ./../test_driver.sh bare rest + - name: Run driver test with SQLite database if: ${{ matrix.directory == 'bare' }} run: ./../test_driver.sh bare sqlite diff --git a/e2e/bare/pyproject.toml b/e2e/bare/pyproject.toml index b9a4028806c3..cde8728f5c34 100644 --- a/e2e/bare/pyproject.toml +++ b/e2e/bare/pyproject.toml @@ -10,4 +10,4 @@ authors = ["The Flower Authors "] [tool.poetry.dependencies] python = "^3.8" -flwr = { path = "../../", develop = true, extras = ["simulation"] } +flwr = { path = "../../", develop = true, extras = ["simulation", "rest"] } diff --git a/e2e/test_driver.sh b/e2e/test_driver.sh index 2e5936198634..bcf796bd78bb 100755 --- a/e2e/test_driver.sh +++ b/e2e/test_driver.sh @@ -14,21 +14,30 @@ case "$1" in esac case "$2" in + rest) + rest_arg="--rest" + server_address="http://localhost:9093" + db_arg="--database :flwr-in-memory-state:" + ;; sqlite) - db_args="--database $(date +%s).db" + rest_arg="" + server_address="127.0.0.1:9092" + db_arg="--database $(date +%s).db" ;; *) - db_args="--database :flwr-in-memory-state:" + rest_arg="" + server_address="127.0.0.1:9092" + db_arg="--database :flwr-in-memory-state:" ;; esac -timeout 2m flower-server $server_arg $db_args & +timeout 2m flower-server $server_arg $db_arg $rest_arg & sleep 3 -timeout 2m flower-client client:flower $client_arg --server 127.0.0.1:9092 & +timeout 2m flower-client client:flower $client_arg $rest_arg --server $server_address & sleep 3 -timeout 2m flower-client client:flower $client_arg --server 127.0.0.1:9092 & +timeout 2m flower-client client:flower $client_arg $rest_arg --server $server_address & sleep 3 timeout 2m python driver.py & diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index 2f02e753d63a..4dc233a5c076 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -88,7 +88,7 @@ def _load() -> Flower: _start_client_internal( server_address=args.server, load_flower_callable_fn=_load, - transport="grpc-rere", # Only + transport="rest" if args.rest else "grpc-rere", root_certificates=root_certificates, insecure=args.insecure, ) @@ -111,6 +111,11 @@ def _parse_args_client() -> argparse.ArgumentParser: help="Run the client without HTTPS. By default, the client runs with " "HTTPS enabled. Use this flag only if you understand the risks.", ) + parser.add_argument( + "--rest", + action="store_true", + help="Use REST as a transport layer for the client.", + ) parser.add_argument( "--root-certificates", metavar="ROOT_CERT", From a3d34aabc60adf6d7491a07f44c394c0b984ba6a Mon Sep 17 00:00:00 2001 From: Charles Beauville Date: Thu, 1 Feb 2024 10:28:28 +0100 Subject: [PATCH 057/113] Improve logging for Client callable (#2883) --- src/py/flwr/client/app.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index 4dc233a5c076..ba20c2fdb7b5 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -18,7 +18,7 @@ import argparse import sys import time -from logging import INFO, WARN +from logging import DEBUG, INFO, WARN from pathlib import Path from typing import Callable, ContextManager, Optional, Tuple, Union @@ -62,7 +62,12 @@ def run_client() -> None: "the '--root-certificates' option when running in insecure mode, " "or omit '--insecure' to use HTTPS." ) - log(WARN, "Option `--insecure` was set. Starting insecure HTTP client.") + log( + WARN, + "Option `--insecure` was set. " + "Starting insecure HTTP client connected to %s.", + args.server, + ) root_certificates = None else: # Load the certificates if provided, or load the system certificates @@ -71,11 +76,19 @@ def run_client() -> None: root_certificates = None else: root_certificates = Path(cert_path).read_bytes() + log( + DEBUG, + "Starting secure HTTPS client connected to %s " + "with the following certificates: %s.", + args.server, + cert_path, + ) - print(args.root_certificates) - print(args.server) - print(args.dir) - print(args.callable) + log( + DEBUG, + "The Flower client uses `%s` to execute tasks", + args.callable, + ) callable_dir = args.dir if callable_dir is not None: From 1913d76c8234b02aece3de4140f40fe5f3ed1efb Mon Sep 17 00:00:00 2001 From: Javier Date: Thu, 1 Feb 2024 09:45:07 +0000 Subject: [PATCH 058/113] Deprecate `NumPyClient` (#2563) --- doc/locales/fr/LC_MESSAGES/framework-docs.po | 24 ++++++++----------- .../pt_BR/LC_MESSAGES/framework-docs.po | 12 ++++------ .../zh_Hans/LC_MESSAGES/framework-docs.po | 12 ++++------ 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/doc/locales/fr/LC_MESSAGES/framework-docs.po b/doc/locales/fr/LC_MESSAGES/framework-docs.po index eb1ae9a9d28b..07ed245bf36f 100644 --- a/doc/locales/fr/LC_MESSAGES/framework-docs.po +++ b/doc/locales/fr/LC_MESSAGES/framework-docs.po @@ -3239,14 +3239,14 @@ msgid "" "All that's left to do it to define a function that loads both model and " "data, creates a :code:`CifarClient`, and starts this client. You load " "your data and model by using :code:`cifar.py`. Start :code:`CifarClient` " -"with the function :code:`fl.client.start_numpy_client()` by pointing it " +"with the function :code:`fl.client.start_client()` by pointing it " "at the same IP adress we used in :code:`server.py`:" msgstr "" "Il ne reste plus qu'à définir une fonction qui charge le modèle et les " "données, crée un :code:`CifarClient` et démarre ce client. Tu charges tes" " données et ton modèle en utilisant :code:`cifar.py`. Démarre " ":code:`CifarClient` avec la fonction " -":code:`fl.client.start_numpy_client()` en la faisant pointer sur la même " +":code:`fl.client.start_client()` en la faisant pointer sur la même " "adresse IP que celle que nous avons utilisée dans :code:`server.py` :" #: ../../source/example-pytorch-from-centralized-to-federated.rst:307 @@ -6137,8 +6137,8 @@ msgstr "" msgid "" "The :code:`VirtualClientEngine` schedules, launches and manages `virtual`" " clients. These clients are identical to `non-virtual` clients (i.e. the " -"ones you launch via the command `flwr.client.start_numpy_client `_) in the sense that they can be configure " +"ones you launch via the command `flwr.client.start_client `_) in the sense that they can be configure " "by creating a class inheriting, for example, from " "`flwr.client.NumPyClient `_ " "and therefore behave in an identical way. In addition to that, clients " @@ -14091,8 +14091,7 @@ msgstr "" #: ../../source/tutorial-quickstart-scikitlearn.rst:147 msgid "" "That's it for the client. We only have to implement :code:`Client` or " -":code:`NumPyClient` and call :code:`fl.client.start_client()` or " -":code:`fl.client.start_numpy_client()`. The string " +":code:`NumPyClient` and call :code:`fl.client.start_client()`. The string " ":code:`\"0.0.0.0:8080\"` tells the client which server to connect to. In " "our case we can run the server and the client on the same machine, " "therefore we use :code:`\"0.0.0.0:8080\"`. If we run a truly federated " @@ -14100,8 +14099,7 @@ msgid "" "that needs to change is the :code:`server_address` we pass to the client." msgstr "" "C'est tout pour le client. Il nous suffit d'implémenter :code:`Client` ou" -" :code:`NumPyClient` et d'appeler :code:`fl.client.start_client()` ou " -":code:`fl.client.start_numpy_client()`. La chaîne :code:`\"0.0.0:8080\"` " +" :code:`NumPyClient` et d'appeler :code:`fl.client.start_client()`. La chaîne :code:`\"0.0.0:8080\"` " "indique au client à quel serveur se connecter. Dans notre cas, nous " "pouvons exécuter le serveur et le client sur la même machine, c'est " "pourquoi nous utilisons :code:`\"0.0.0:8080\"`. Si nous exécutons une " @@ -14325,8 +14323,7 @@ msgstr "" #: ../../source/tutorial-quickstart-tensorflow.rst:87 msgid "" "That's it for the client. We only have to implement :code:`Client` or " -":code:`NumPyClient` and call :code:`fl.client.start_client()` or " -":code:`fl.client.start_numpy_client()`. The string :code:`\"[::]:8080\"` " +":code:`NumPyClient` and call :code:`fl.client.start_client()`. The string :code:`\"[::]:8080\"` " "tells the client which server to connect to. In our case we can run the " "server and the client on the same machine, therefore we use " ":code:`\"[::]:8080\"`. If we run a truly federated workload with the " @@ -14334,8 +14331,7 @@ msgid "" "change is the :code:`server_address` we point the client at." msgstr "" "C'est tout pour le client. Il nous suffit d'implémenter :code:`Client` ou" -" :code:`NumPyClient` et d'appeler :code:`fl.client.start_client()` ou " -":code:`fl.client.start_numpy_client()`. La chaîne :code:`\"[: :]:8080\"` " +" :code:`NumPyClient` et d'appeler :code:`fl.client.start_client()`. La chaîne :code:`\"[: :]:8080\"` " "indique au client à quel serveur se connecter. Dans notre cas, nous " "pouvons exécuter le serveur et le client sur la même machine, c'est " "pourquoi nous utilisons :code:`\"[: :]:8080\"`. Si nous exécutons une " @@ -17225,8 +17221,8 @@ msgstr "" #~ " and manages `virtual` clients. These " #~ "clients are identical to `non-virtual`" #~ " clients (i.e. the ones you launch" -#~ " via the command `flwr.client.start_numpy_client" -#~ " `_)" +#~ " via the command `flwr.client.start_client" +#~ " `_)" #~ " in the sense that they can be" #~ " configure by creating a class " #~ "inheriting, for example, from " diff --git a/doc/locales/pt_BR/LC_MESSAGES/framework-docs.po b/doc/locales/pt_BR/LC_MESSAGES/framework-docs.po index 4bb195306670..c61dcd5d6c0d 100644 --- a/doc/locales/pt_BR/LC_MESSAGES/framework-docs.po +++ b/doc/locales/pt_BR/LC_MESSAGES/framework-docs.po @@ -2544,7 +2544,7 @@ msgid "" "All that's left to do it to define a function that loads both model and " "data, creates a :code:`CifarClient`, and starts this client. You load " "your data and model by using :code:`cifar.py`. Start :code:`CifarClient` " -"with the function :code:`fl.client.start_numpy_client()` by pointing it " +"with the function :code:`fl.client.start_client()` by pointing it " "at the same IP adress we used in :code:`server.py`:" msgstr "" @@ -4664,8 +4664,8 @@ msgstr "" msgid "" "The :code:`VirtualClientEngine` schedules, launches and manages `virtual`" " clients. These clients are identical to `non-virtual` clients (i.e. the " -"ones you launch via the command `flwr.client.start_numpy_client `_) in the sense that they can be configure " +"ones you launch via the command `flwr.client.start_client `_) in the sense that they can be configure " "by creating a class inheriting, for example, from " "`flwr.client.NumPyClient `_ " "and therefore behave in an identical way. In addition to that, clients " @@ -9719,8 +9719,7 @@ msgstr "" #: ../../source/tutorial-quickstart-scikitlearn.rst:150 msgid "" "That's it for the client. We only have to implement :code:`Client` or " -":code:`NumPyClient` and call :code:`fl.client.start_client()` or " -":code:`fl.client.start_numpy_client()`. The string " +":code:`NumPyClient` and call :code:`fl.client.start_client()`. The string " ":code:`\"0.0.0.0:8080\"` tells the client which server to connect to. In " "our case we can run the server and the client on the same machine, " "therefore we use :code:`\"0.0.0.0:8080\"`. If we run a truly federated " @@ -9896,8 +9895,7 @@ msgstr "" #: ../../source/tutorial-quickstart-tensorflow.rst:90 msgid "" "That's it for the client. We only have to implement :code:`Client` or " -":code:`NumPyClient` and call :code:`fl.client.start_client()` or " -":code:`fl.client.start_numpy_client()`. The string :code:`\"[::]:8080\"` " +":code:`NumPyClient` and call :code:`fl.client.start_client()`. The string :code:`\"[::]:8080\"` " "tells the client which server to connect to. In our case we can run the " "server and the client on the same machine, therefore we use " ":code:`\"[::]:8080\"`. If we run a truly federated workload with the " diff --git a/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po b/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po index 87af28422d56..8a80efee2829 100644 --- a/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po +++ b/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po @@ -2545,7 +2545,7 @@ msgid "" "All that's left to do it to define a function that loads both model and " "data, creates a :code:`CifarClient`, and starts this client. You load " "your data and model by using :code:`cifar.py`. Start :code:`CifarClient` " -"with the function :code:`fl.client.start_numpy_client()` by pointing it " +"with the function :code:`fl.client.start_client()` by pointing it " "at the same IP adress we used in :code:`server.py`:" msgstr "" @@ -4667,8 +4667,8 @@ msgstr "" msgid "" "The :code:`VirtualClientEngine` schedules, launches and manages `virtual`" " clients. These clients are identical to `non-virtual` clients (i.e. the " -"ones you launch via the command `flwr.client.start_numpy_client `_) in the sense that they can be configure " +"ones you launch via the command `flwr.client.start_client `_) in the sense that they can be configure " "by creating a class inheriting, for example, from " "`flwr.client.NumPyClient `_ " "and therefore behave in an identical way. In addition to that, clients " @@ -11011,8 +11011,7 @@ msgstr "" #: ../../source/tutorial-quickstart-scikitlearn.rst:150 msgid "" "That's it for the client. We only have to implement :code:`Client` or " -":code:`NumPyClient` and call :code:`fl.client.start_client()` or " -":code:`fl.client.start_numpy_client()`. The string " +":code:`NumPyClient` and call :code:`fl.client.start_client()`. The string " ":code:`\"0.0.0.0:8080\"` tells the client which server to connect to. In " "our case we can run the server and the client on the same machine, " "therefore we use :code:`\"0.0.0.0:8080\"`. If we run a truly federated " @@ -11192,8 +11191,7 @@ msgstr "" #: ../../source/tutorial-quickstart-tensorflow.rst:90 msgid "" "That's it for the client. We only have to implement :code:`Client` or " -":code:`NumPyClient` and call :code:`fl.client.start_client()` or " -":code:`fl.client.start_numpy_client()`. The string :code:`\"[::]:8080\"` " +":code:`NumPyClient` and call :code:`fl.client.start_client()`. The string :code:`\"[::]:8080\"` " "tells the client which server to connect to. In our case we can run the " "server and the client on the same machine, therefore we use " ":code:`\"[::]:8080\"`. If we run a truly federated workload with the " From ac77ead5b2f2c7ad2d47259fb0fee249455c52bb Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Thu, 1 Feb 2024 10:56:23 +0100 Subject: [PATCH 059/113] Format code examples (#2877) Co-authored-by: Taner Topal --- examples/custom-metrics/client.py | 4 +++- examples/embedded-devices/client_pytorch.py | 6 ++++-- examples/embedded-devices/client_tf.py | 10 +++++++--- .../client.py | 4 +++- examples/quickstart-huggingface/client.py | 4 +++- examples/quickstart-jax/client.py | 4 +++- examples/quickstart-mlcube/client.py | 3 ++- examples/quickstart-tabnet/client.py | 4 +++- examples/quickstart-tensorflow/client.py | 4 +++- examples/sklearn-logreg-mnist/client.py | 4 +++- 10 files changed, 34 insertions(+), 13 deletions(-) diff --git a/examples/custom-metrics/client.py b/examples/custom-metrics/client.py index 09e786a0cfac..d0230e455477 100644 --- a/examples/custom-metrics/client.py +++ b/examples/custom-metrics/client.py @@ -68,4 +68,6 @@ def evaluate(self, parameters, config): # Start Flower client -fl.client.start_client(server_address="127.0.0.1:8080", client=FlowerClient().to_client()) +fl.client.start_client( + server_address="127.0.0.1:8080", client=FlowerClient().to_client() +) diff --git a/examples/embedded-devices/client_pytorch.py b/examples/embedded-devices/client_pytorch.py index 134b573f7608..f326db7c678c 100644 --- a/examples/embedded-devices/client_pytorch.py +++ b/examples/embedded-devices/client_pytorch.py @@ -30,12 +30,13 @@ "--mnist", action="store_true", help="If you use Raspberry Pi Zero clients (which just have 512MB or RAM) use " - "MNIST", + "MNIST", ) warnings.filterwarnings("ignore", category=UserWarning) NUM_CLIENTS = 50 + class Net(nn.Module): """Model (simple CNN adapted from 'PyTorch: A 60 Minute Blitz').""" @@ -96,6 +97,7 @@ def prepare_dataset(use_mnist: bool): img_key = "img" norm = Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) pytorch_transforms = Compose([ToTensor(), norm]) + def apply_transforms(batch): """Apply transforms to the partition from FederatedDataset.""" batch[img_key] = [pytorch_transforms(img) for img in batch[img_key]] @@ -112,7 +114,7 @@ def apply_transforms(batch): validsets.append(partition["test"]) testset = fds.load_full("test") testset = testset.with_transform(apply_transforms) - return trainsets, validsets, testset + return trainsets, validsets, testset # Flower client, adapted from Pytorch quickstart/simulation example diff --git a/examples/embedded-devices/client_tf.py b/examples/embedded-devices/client_tf.py index 712068af5fc4..ae793ecd81e0 100644 --- a/examples/embedded-devices/client_tf.py +++ b/examples/embedded-devices/client_tf.py @@ -45,8 +45,10 @@ def prepare_dataset(use_mnist: bool): partition.set_format("numpy") # Divide data on each node: 90% train, 10% test partition = partition.train_test_split(test_size=0.1) - x_train, y_train = partition["train"][img_key] / 255.0, partition["train"][ - "label"] + x_train, y_train = ( + partition["train"][img_key] / 255.0, + partition["train"]["label"], + ) x_test, y_test = partition["test"][img_key] / 255.0, partition["test"]["label"] partitions.append(((x_train, y_train), (x_test, y_test))) data_centralized = fds.load_full("test") @@ -123,7 +125,9 @@ def main(): # Start Flower client setting its associated data partition fl.client.start_client( server_address=args.server_address, - client=FlowerClient(trainset=trainset, valset=valset, use_mnist=use_mnist).to_client(), + client=FlowerClient( + trainset=trainset, valset=valset, use_mnist=use_mnist + ).to_client(), ) diff --git a/examples/pytorch-federated-variational-autoencoder/client.py b/examples/pytorch-federated-variational-autoencoder/client.py index 65a86bcc2184..fc71f7e70c0b 100644 --- a/examples/pytorch-federated-variational-autoencoder/client.py +++ b/examples/pytorch-federated-variational-autoencoder/client.py @@ -93,7 +93,9 @@ def evaluate(self, parameters, config): loss = test(net, testloader) return float(loss), len(testloader), {} - fl.client.start_client(server_address="127.0.0.1:8080", client=CifarClient().to_client()) + fl.client.start_client( + server_address="127.0.0.1:8080", client=CifarClient().to_client() + ) if __name__ == "__main__": diff --git a/examples/quickstart-huggingface/client.py b/examples/quickstart-huggingface/client.py index 0bfc81342972..5dc461d30536 100644 --- a/examples/quickstart-huggingface/client.py +++ b/examples/quickstart-huggingface/client.py @@ -108,7 +108,9 @@ def evaluate(self, parameters, config): return float(loss), len(testloader), {"accuracy": float(accuracy)} # Start client - fl.client.start_client(server_address="127.0.0.1:8080", client=IMDBClient().to_client()) + fl.client.start_client( + server_address="127.0.0.1:8080", client=IMDBClient().to_client() + ) if __name__ == "__main__": diff --git a/examples/quickstart-jax/client.py b/examples/quickstart-jax/client.py index 0cf74e2d2c05..afd6f197bcde 100644 --- a/examples/quickstart-jax/client.py +++ b/examples/quickstart-jax/client.py @@ -52,4 +52,6 @@ def evaluate( # Start Flower client -fl.client.start_client(server_address="127.0.0.1:8080", client=FlowerClient().to_client()) +fl.client.start_client( + server_address="127.0.0.1:8080", client=FlowerClient().to_client() +) diff --git a/examples/quickstart-mlcube/client.py b/examples/quickstart-mlcube/client.py index 0470720bc296..46ddd45f52ce 100644 --- a/examples/quickstart-mlcube/client.py +++ b/examples/quickstart-mlcube/client.py @@ -44,7 +44,8 @@ def main(): ) fl.client.start_client( - server_address="0.0.0.0:8080", client=MLCubeClient(workspace=workspace).to_client() + server_address="0.0.0.0:8080", + client=MLCubeClient(workspace=workspace).to_client(), ) diff --git a/examples/quickstart-tabnet/client.py b/examples/quickstart-tabnet/client.py index 53913b2a2a09..2289b1b55b3d 100644 --- a/examples/quickstart-tabnet/client.py +++ b/examples/quickstart-tabnet/client.py @@ -79,4 +79,6 @@ def evaluate(self, parameters, config): # Start Flower client -fl.client.start_client(server_address="127.0.0.1:8080", client=TabNetClient().to_client()) +fl.client.start_client( + server_address="127.0.0.1:8080", client=TabNetClient().to_client() +) diff --git a/examples/quickstart-tensorflow/client.py b/examples/quickstart-tensorflow/client.py index 43121f062c45..37abbbcc46ec 100644 --- a/examples/quickstart-tensorflow/client.py +++ b/examples/quickstart-tensorflow/client.py @@ -52,4 +52,6 @@ def evaluate(self, parameters, config): # Start Flower client -fl.client.start_client(server_address="127.0.0.1:8080", client=CifarClient().to_client()) +fl.client.start_client( + server_address="127.0.0.1:8080", client=CifarClient().to_client() +) diff --git a/examples/sklearn-logreg-mnist/client.py b/examples/sklearn-logreg-mnist/client.py index c5a312b41e61..3d41cb6fbb21 100644 --- a/examples/sklearn-logreg-mnist/client.py +++ b/examples/sklearn-logreg-mnist/client.py @@ -62,4 +62,6 @@ def evaluate(self, parameters, config): # type: ignore return loss, len(X_test), {"accuracy": accuracy} # Start Flower client - fl.client.start_client(server_address="0.0.0.0:8080", client=MnistClient().to_client()) + fl.client.start_client( + server_address="0.0.0.0:8080", client=MnistClient().to_client() + ) From 387853c577b636fa8129fd144e3a7fb0979de2a2 Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Thu, 1 Feb 2024 11:08:03 +0100 Subject: [PATCH 060/113] Add example formatting to test.sh (#2875) Co-authored-by: Taner Topal --- dev/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/test.sh b/dev/test.sh index d3130bf3f6c2..1ed1b96edea1 100755 --- a/dev/test.sh +++ b/dev/test.sh @@ -15,7 +15,7 @@ python -m isort --check-only --skip src/py/flwr/proto src/py/flwr echo "- isort: done" echo "- black: start" -python -m black --exclude "src\/py\/flwr\/proto" --check src/py/flwr +python -m black --exclude "src\/py\/flwr\/proto" --check src/py/flwr examples echo "- black: done" echo "- init_py_check: start" From a2a6f5886ea39e0f0f1be05e156609433f7af07e Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Thu, 1 Feb 2024 11:19:31 +0100 Subject: [PATCH 061/113] Update CODEOWNERS (#2876) --- .github/CODEOWNERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 71a8aea59859..8dac63a20598 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -3,6 +3,9 @@ # Default code owners * @danieljanes @tanertopal +# README.md +README.md @jafermarq @tanertopal @danieljanes + # Flower Baselines /baselines @jafermarq @tanertopal @danieljanes From e28c17a03031750b2237bc85e54c37d27546eefe Mon Sep 17 00:00:00 2001 From: Yan Gao Date: Thu, 1 Feb 2024 10:36:46 +0000 Subject: [PATCH 062/113] Add __repr__ for fedxgb_bagging and fedxgb_cyclic strategies (#2885) --- src/py/flwr/server/strategy/fedxgb_bagging.py | 5 +++++ src/py/flwr/server/strategy/fedxgb_cyclic.py | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/py/flwr/server/strategy/fedxgb_bagging.py b/src/py/flwr/server/strategy/fedxgb_bagging.py index cafb466c2e8b..a8e8adddafbb 100644 --- a/src/py/flwr/server/strategy/fedxgb_bagging.py +++ b/src/py/flwr/server/strategy/fedxgb_bagging.py @@ -44,6 +44,11 @@ def __init__( self.global_model: Optional[bytes] = None super().__init__(**kwargs) + def __repr__(self) -> str: + """Compute a string representation of the strategy.""" + rep = f"FedXgbBagging(accept_failures={self.accept_failures})" + return rep + def aggregate_fit( self, server_round: int, diff --git a/src/py/flwr/server/strategy/fedxgb_cyclic.py b/src/py/flwr/server/strategy/fedxgb_cyclic.py index e2707b02d19d..2605daab29f4 100644 --- a/src/py/flwr/server/strategy/fedxgb_cyclic.py +++ b/src/py/flwr/server/strategy/fedxgb_cyclic.py @@ -37,6 +37,11 @@ def __init__( self.global_model: Optional[bytes] = None super().__init__(**kwargs) + def __repr__(self) -> str: + """Compute a string representation of the strategy.""" + rep = f"FedXgbCyclic(accept_failures={self.accept_failures})" + return rep + def aggregate_fit( self, server_round: int, From ef9c4122c7f712812ff70b38f1dbf6ef5c1e6689 Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Thu, 1 Feb 2024 11:48:13 +0100 Subject: [PATCH 063/113] Update setup-python action as v4 is using a depricated node version (#2886) --- .github/actions/bootstrap/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/bootstrap/action.yml b/.github/actions/bootstrap/action.yml index bab5113bc567..5b0c10f53f5e 100644 --- a/.github/actions/bootstrap/action.yml +++ b/.github/actions/bootstrap/action.yml @@ -30,7 +30,7 @@ runs: using: "composite" steps: - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ inputs.python-version }} - name: Install build tools From 55e9004b767fede5a35929b846ee237804a37efd Mon Sep 17 00:00:00 2001 From: Heng Pan <134433891+panh99@users.noreply.github.com> Date: Thu, 1 Feb 2024 11:04:50 +0000 Subject: [PATCH 064/113] Add SecAggPlus layer (#2871) --- examples/secaggplus-mt/client.py | 33 ++- examples/secaggplus-mt/driver.py | 5 +- examples/secaggplus-mt/run.sh | 17 +- examples/secaggplus-mt/workflows.py | 41 ++- src/py/flwr/client/middleware/__init__.py | 2 + .../secure_aggregation/__init__.py | 10 +- .../secaggplus_middleware.py} | 252 ++++++++++-------- .../secaggplus_middleware_test.py} | 206 ++++++++------ .../flwr/client/secure_aggregation/handler.py | 43 --- .../secaggplus_constants.py | 2 + 10 files changed, 337 insertions(+), 274 deletions(-) rename src/py/flwr/client/{ => middleware}/secure_aggregation/__init__.py (76%) rename src/py/flwr/client/{secure_aggregation/secaggplus_handler.py => middleware/secure_aggregation/secaggplus_middleware.py} (70%) rename src/py/flwr/client/{secure_aggregation/secaggplus_handler_test.py => middleware/secure_aggregation/secaggplus_middleware_test.py} (57%) delete mode 100644 src/py/flwr/client/secure_aggregation/handler.py diff --git a/examples/secaggplus-mt/client.py b/examples/secaggplus-mt/client.py index f0f1348ee378..a0ed9e7181c7 100644 --- a/examples/secaggplus-mt/client.py +++ b/examples/secaggplus-mt/client.py @@ -5,11 +5,11 @@ import flwr as fl from flwr.common import Status, FitIns, FitRes, Code from flwr.common.parameter import ndarrays_to_parameters -from flwr.client.secure_aggregation import SecAggPlusHandler +from flwr.client.middleware import secaggplus_middleware # Define Flower client with the SecAgg+ protocol -class FlowerClient(fl.client.Client, SecAggPlusHandler): +class FlowerClient(fl.client.Client): def fit(self, fit_ins: FitIns) -> FitRes: ret_vec = [np.ones(3)] ret = FitRes( @@ -19,17 +19,30 @@ def fit(self, fit_ins: FitIns) -> FitRes: metrics={}, ) # Force a significant delay for testing purposes - if self._shared_state.sid == 0: - print(f"Client {self._shared_state.sid} dropped for testing purposes.") + if fit_ins.config["drop"]: + print(f"Client dropped for testing purposes.") time.sleep(4) return ret - print(f"Client {self._shared_state.sid} uploading {ret_vec[0]}...") + print(f"Client uploading {ret_vec[0]}...") return ret -# Start Flower client -fl.client.start_client( - server_address="0.0.0.0:9092", - client=FlowerClient(), - transport="grpc-rere", +def client_fn(cid: str): + """.""" + return FlowerClient().to_client() + + +# To run this: `flower-client --callable client:flower` +flower = fl.flower.Flower( + client_fn=client_fn, + layers=[secaggplus_middleware], ) + + +if __name__ == "__main__": + # Start Flower client + fl.client.start_client( + server_address="0.0.0.0:9092", + client=FlowerClient(), + transport="grpc-rere", + ) diff --git a/examples/secaggplus-mt/driver.py b/examples/secaggplus-mt/driver.py index f5871f1b44e4..d0d9a75f1b76 100644 --- a/examples/secaggplus-mt/driver.py +++ b/examples/secaggplus-mt/driver.py @@ -24,7 +24,6 @@ def merge(_task: task_pb2.Task, _merge_task: task_pb2.Task) -> task_pb2.Task: task_id="", # Do not set, will be created and set by the DriverAPI group_id="", run_id=run_id, - run_id=run_id, task=merge( task, task_pb2.Task( @@ -193,9 +192,7 @@ def weighted_average(metrics: List[Tuple[int, Metrics]]) -> Metrics: break # Collect correct results - node_messages = task_res_list_to_task_dict( - [res for res in all_task_res if res.task.HasField("sa")] - ) + node_messages = task_res_list_to_task_dict(all_task_res) workflow.close() # Slow down the start of the next round diff --git a/examples/secaggplus-mt/run.sh b/examples/secaggplus-mt/run.sh index 5cc769f6cbd8..852798c0ab21 100755 --- a/examples/secaggplus-mt/run.sh +++ b/examples/secaggplus-mt/run.sh @@ -1,13 +1,13 @@ #!/bin/bash # Kill any currently running client.py processes -pkill -f 'python client.py' +pkill -f 'flower-client' -# Kill any currently running flower-server processes with --grpc-rere option -pkill -f 'flower-server --grpc-rere' +# Kill any currently running flower-server processes +pkill -f 'flower-server' # Start the flower server echo "Starting flower server in background..." -flower-server --grpc-rere > /dev/null 2>&1 & +flower-server --insecure > /dev/null 2>&1 & sleep 2 # Number of client processes to start @@ -18,8 +18,7 @@ echo "Starting $N clients in background..." # Start N client processes for i in $(seq 1 $N) do - python client.py > /dev/null 2>&1 & - # python client.py & + flower-client --insecure client:flower > /dev/null 2>&1 & sleep 0.1 done @@ -29,7 +28,7 @@ python driver.py echo "Clearing background processes..." # Kill any currently running client.py processes -pkill -f 'python client.py' +pkill -f 'flower-client' -# Kill any currently running flower-server processes with --grpc-rere option -pkill -f 'flower-server --grpc-rere' +# Kill any currently running flower-server processes +pkill -f 'flower-server' \ No newline at end of file diff --git a/examples/secaggplus-mt/workflows.py b/examples/secaggplus-mt/workflows.py index 3117e308a498..b98de883b8f7 100644 --- a/examples/secaggplus-mt/workflows.py +++ b/examples/secaggplus-mt/workflows.py @@ -1,6 +1,6 @@ import random from logging import WARNING -from typing import Callable, Dict, Generator, List +from typing import Callable, Dict, Generator, List, Optional import numpy as np @@ -36,7 +36,6 @@ KEY_DESTINATION_LIST, KEY_MASKED_PARAMETERS, KEY_MOD_RANGE, - KEY_PARAMETERS, KEY_PUBLIC_KEY_1, KEY_PUBLIC_KEY_2, KEY_SAMPLE_NUMBER, @@ -52,11 +51,16 @@ STAGE_SETUP, STAGE_SHARE_KEYS, STAGE_UNMASK, + RECORD_KEY_CONFIGS, ) from flwr.common.secure_aggregation.secaggplus_utils import pseudo_rand_gen -from flwr.common.serde import named_values_from_proto, named_values_to_proto -from flwr.common.typing import Value -from flwr.proto.task_pb2 import SecureAggregation, Task +from flwr.common.typing import ConfigsRecordValues, FitIns, ServerMessage +from flwr.proto.task_pb2 import Task +from flwr.common import serde +from flwr.common.constant import TASK_TYPE_FIT +from flwr.common.recordset import RecordSet +from flwr.common import recordset_compat as compat +from flwr.common.configsrecord import ConfigsRecord LOG_EXPLAIN = True @@ -68,12 +72,23 @@ def get_workflow_factory() -> ( return _wrap_workflow_with_sec_agg -def _wrap_in_task(named_values: Dict[str, Value]) -> Task: - return Task(sa=SecureAggregation(named_values=named_values_to_proto(named_values))) +def _wrap_in_task( + named_values: Dict[str, ConfigsRecordValues], fit_ins: Optional[FitIns] = None +) -> Task: + if fit_ins is not None: + recordset = compat.fitins_to_recordset(fit_ins, keep_input=True) + else: + recordset = RecordSet() + recordset.set_configs(RECORD_KEY_CONFIGS, ConfigsRecord(named_values)) + return Task( + task_type=TASK_TYPE_FIT, + recordset=serde.recordset_to_proto(recordset), + ) -def _get_from_task(task: Task) -> Dict[str, Value]: - return named_values_from_proto(task.sa.named_values) +def _get_from_task(task: Task) -> Dict[str, ConfigsRecordValues]: + recordset = serde.recordset_from_proto(task.recordset) + return recordset.get_configs(RECORD_KEY_CONFIGS).data _secure_aggregation_configuration = { @@ -233,15 +248,16 @@ def workflow_with_sec_agg( if LOG_EXPLAIN: print(f"\nForwarding encrypted key shares and requesting masked input...") # Send encrypted secret key shares to clients (plus model parameters) - weights = parameters_to_ndarrays(parameters) yield { node_id: _wrap_in_task( named_values={ KEY_STAGE: STAGE_COLLECT_MASKED_INPUT, KEY_CIPHERTEXT_LIST: fwd_ciphertexts[nid2sid[node_id]], KEY_SOURCE_LIST: fwd_srcs[nid2sid[node_id]], - KEY_PARAMETERS: [ndarray_to_bytes(arr) for arr in weights], - } + }, + fit_ins=FitIns( + parameters=parameters, config={"drop": nid2sid[node_id] == 0} + ), ) for node_id in surviving_node_ids } @@ -249,6 +265,7 @@ def workflow_with_sec_agg( node_messages = yield surviving_node_ids = [node_id for node_id in node_messages] # Get shape of vector sent by first client + weights = parameters_to_ndarrays(parameters) masked_vector = [np.array([0], dtype=int)] + get_zero_parameters( [w.shape for w in weights] ) diff --git a/src/py/flwr/client/middleware/__init__.py b/src/py/flwr/client/middleware/__init__.py index 58b31296fbbe..2cab6e61899c 100644 --- a/src/py/flwr/client/middleware/__init__.py +++ b/src/py/flwr/client/middleware/__init__.py @@ -15,8 +15,10 @@ """Middleware layers.""" +from .secure_aggregation.secaggplus_middleware import secaggplus_middleware from .utils import make_ffn __all__ = [ "make_ffn", + "secaggplus_middleware", ] diff --git a/src/py/flwr/client/secure_aggregation/__init__.py b/src/py/flwr/client/middleware/secure_aggregation/__init__.py similarity index 76% rename from src/py/flwr/client/secure_aggregation/__init__.py rename to src/py/flwr/client/middleware/secure_aggregation/__init__.py index 37c816a390de..353828b02517 100644 --- a/src/py/flwr/client/secure_aggregation/__init__.py +++ b/src/py/flwr/client/middleware/secure_aggregation/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2023 Flower Labs GmbH. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -13,12 +13,8 @@ # limitations under the License. # ============================================================================== """Secure Aggregation handlers.""" - - -from .handler import SecureAggregationHandler -from .secaggplus_handler import SecAggPlusHandler +from .secaggplus_middleware import secaggplus_middleware __all__ = [ - "SecAggPlusHandler", - "SecureAggregationHandler", + "secaggplus_middleware", ] diff --git a/src/py/flwr/client/secure_aggregation/secaggplus_handler.py b/src/py/flwr/client/middleware/secure_aggregation/secaggplus_middleware.py similarity index 70% rename from src/py/flwr/client/secure_aggregation/secaggplus_handler.py rename to src/py/flwr/client/middleware/secure_aggregation/secaggplus_middleware.py index 4b74c1ace3de..885dc4d9cbf5 100644 --- a/src/py/flwr/client/secure_aggregation/secaggplus_handler.py +++ b/src/py/flwr/client/middleware/secure_aggregation/secaggplus_middleware.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2024 Flower Labs GmbH. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,18 +17,18 @@ import os from dataclasses import dataclass, field -from logging import ERROR, INFO, WARNING -from typing import Any, Dict, List, Optional, Tuple, Union, cast - -from flwr.client.client import Client -from flwr.client.numpy_client import NumPyClient -from flwr.common import ( - bytes_to_ndarray, - ndarray_to_bytes, - ndarrays_to_parameters, - parameters_to_ndarrays, -) +from logging import INFO, WARNING +from typing import Any, Callable, Dict, List, Tuple, cast + +from flwr.client.typing import FlowerCallable +from flwr.common import ndarray_to_bytes, parameters_to_ndarrays +from flwr.common import recordset_compat as compat +from flwr.common.configsrecord import ConfigsRecord +from flwr.common.constant import TASK_TYPE_FIT +from flwr.common.context import Context from flwr.common.logger import log +from flwr.common.message import Message, Metadata +from flwr.common.recordset import RecordSet from flwr.common.secure_aggregation.crypto.shamir import create_shares from flwr.common.secure_aggregation.crypto.symmetric_encryption import ( bytes_to_private_key, @@ -56,7 +56,6 @@ KEY_DESTINATION_LIST, KEY_MASKED_PARAMETERS, KEY_MOD_RANGE, - KEY_PARAMETERS, KEY_PUBLIC_KEY_1, KEY_PUBLIC_KEY_2, KEY_SAMPLE_NUMBER, @@ -68,6 +67,8 @@ KEY_STAGE, KEY_TARGET_RANGE, KEY_THRESHOLD, + RECORD_KEY_CONFIGS, + RECORD_KEY_STATE, STAGE_COLLECT_MASKED_INPUT, STAGE_SETUP, STAGE_SHARE_KEYS, @@ -79,9 +80,7 @@ share_keys_plaintext_concat, share_keys_plaintext_separate, ) -from flwr.common.typing import FitIns, Value - -from .handler import SecureAggregationHandler +from flwr.common.typing import ConfigsRecordValues, FitRes @dataclass @@ -89,6 +88,8 @@ class SecAggPlusState: """State of the SecAgg+ protocol.""" + current_stage: str = STAGE_UNMASK + sid: int = 0 sample_num: int = 0 share_num: int = 0 @@ -112,70 +113,115 @@ class SecAggPlusState: ss2_dict: Dict[int, bytes] = field(default_factory=dict) public_keys_dict: Dict[int, Tuple[bytes, bytes]] = field(default_factory=dict) - client: Optional[Union[Client, NumPyClient]] = None - - -class SecAggPlusHandler(SecureAggregationHandler): - """Message handler for the SecAgg+ protocol.""" - - _shared_state = SecAggPlusState() - _current_stage = STAGE_UNMASK - - def handle_secure_aggregation( - self, named_values: Dict[str, Value] - ) -> Dict[str, Value]: - """Handle incoming message and return results, following the SecAgg+ protocol. - - Parameters - ---------- - named_values : Dict[str, Value] - The named values retrieved from the SecureAggregation sub-message - of Task message in the server's TaskIns. + def __init__(self, **kwargs: ConfigsRecordValues) -> None: + for k, v in kwargs.items(): + if k.endswith(":V"): + continue + new_v: Any = v + if k.endswith(":K"): + k = k[:-2] + keys = cast(List[int], v) + values = cast(List[bytes], kwargs[f"{k}:V"]) + if len(values) > len(keys): + updated_values = [ + tuple(values[i : i + 2]) for i in range(0, len(values), 2) + ] + new_v = dict(zip(keys, updated_values)) + else: + new_v = dict(zip(keys, values)) + self.__setattr__(k, new_v) + + def to_dict(self) -> Dict[str, ConfigsRecordValues]: + """Convert the state to a dictionary.""" + ret = vars(self) + for k in list(ret.keys()): + if isinstance(ret[k], dict): + # Replace dict with two lists + v = cast(Dict[str, Any], ret.pop(k)) + ret[f"{k}:K"] = list(v.keys()) + if k == "public_keys_dict": + v_list: List[bytes] = [] + for b1_b2 in cast(List[Tuple[bytes, bytes]], v.values()): + v_list.extend(b1_b2) + ret[f"{k}:V"] = v_list + else: + ret[f"{k}:V"] = list(v.values()) + return ret + + +def _get_fit_fn( + msg: Message, ctxt: Context, call_next: FlowerCallable +) -> Callable[[], FitRes]: + """Get the fit function.""" + + def fit() -> FitRes: + out_msg = call_next(msg, ctxt) + return compat.recordset_to_fitres(out_msg.message, keep_input=False) + + return fit + + +def secaggplus_middleware( + msg: Message, + ctxt: Context, + call_next: FlowerCallable, +) -> Message: + """Handle incoming message and return results, following the SecAgg+ protocol.""" + # Ignore non-fit messages + if msg.metadata.task_type != TASK_TYPE_FIT: + return call_next(msg, ctxt) + + # Retrieve local state + if RECORD_KEY_STATE not in ctxt.state.configs: + ctxt.state.set_configs(RECORD_KEY_STATE, ConfigsRecord({})) + state_dict = ctxt.state.get_configs(RECORD_KEY_STATE).data + state = SecAggPlusState(**state_dict) + + # Retrieve incoming configs + configs = msg.message.get_configs(RECORD_KEY_CONFIGS).data - Returns - ------- - Dict[str, Value] - The final/intermediate results of the SecAgg+ protocol. - """ - # Check if self is a client - if not isinstance(self, (Client, NumPyClient)): - raise TypeError( - "The subclass of SecAggPlusHandler must be " - "the subclass of Client or NumPyClient." - ) - - # Check the validity of the next stage - check_stage(self._current_stage, named_values) - - # Update the current stage - self._current_stage = cast(str, named_values.pop(KEY_STAGE)) + # Check the validity of the next stage + check_stage(state.current_stage, configs) + + # Update the current stage + state.current_stage = cast(str, configs.pop(KEY_STAGE)) + + # Check the validity of the configs based on the current stage + check_configs(state.current_stage, configs) + + # Execute + if state.current_stage == STAGE_SETUP: + res = _setup(state, configs) + elif state.current_stage == STAGE_SHARE_KEYS: + res = _share_keys(state, configs) + elif state.current_stage == STAGE_COLLECT_MASKED_INPUT: + fit = _get_fit_fn(msg, ctxt, call_next) + res = _collect_masked_input(state, configs, fit) + elif state.current_stage == STAGE_UNMASK: + res = _unmask(state, configs) + else: + raise ValueError(f"Unknown secagg stage: {state.current_stage}") - # Check the validity of the `named_values` based on the current stage - check_named_values(self._current_stage, named_values) + # Save state + ctxt.state.set_configs(RECORD_KEY_STATE, ConfigsRecord(state.to_dict())) - # Execute - if self._current_stage == STAGE_SETUP: - self._shared_state = SecAggPlusState(client=self) - return _setup(self._shared_state, named_values) - if self._current_stage == STAGE_SHARE_KEYS: - return _share_keys(self._shared_state, named_values) - if self._current_stage == STAGE_COLLECT_MASKED_INPUT: - return _collect_masked_input(self._shared_state, named_values) - if self._current_stage == STAGE_UNMASK: - return _unmask(self._shared_state, named_values) - raise ValueError(f"Unknown secagg stage: {self._current_stage}") + # Return message + return Message( + metadata=Metadata(0, "", "", "", TASK_TYPE_FIT), + message=RecordSet(configs={RECORD_KEY_CONFIGS: ConfigsRecord(res, False)}), + ) -def check_stage(current_stage: str, named_values: Dict[str, Value]) -> None: +def check_stage(current_stage: str, configs: Dict[str, ConfigsRecordValues]) -> None: """Check the validity of the next stage.""" # Check the existence of KEY_STAGE - if KEY_STAGE not in named_values: + if KEY_STAGE not in configs: raise KeyError( f"The required key '{KEY_STAGE}' is missing from the input `named_values`." ) # Check the value type of the KEY_STAGE - next_stage = named_values[KEY_STAGE] + next_stage = configs[KEY_STAGE] if not isinstance(next_stage, str): raise TypeError( f"The value for the key '{KEY_STAGE}' must be of type {str}, " @@ -198,8 +244,8 @@ def check_stage(current_stage: str, named_values: Dict[str, Value]) -> None: # pylint: disable-next=too-many-branches -def check_named_values(stage: str, named_values: Dict[str, Value]) -> None: - """Check the validity of the input `named_values`.""" +def check_configs(stage: str, configs: Dict[str, ConfigsRecordValues]) -> None: + """Check the validity of the configs.""" # Check `named_values` for the setup stage if stage == STAGE_SETUP: key_type_pairs = [ @@ -212,7 +258,7 @@ def check_named_values(stage: str, named_values: Dict[str, Value]) -> None: (KEY_MOD_RANGE, int), ] for key, expected_type in key_type_pairs: - if key not in named_values: + if key not in configs: raise KeyError( f"Stage {STAGE_SETUP}: the required key '{key}' is " "missing from the input `named_values`." @@ -220,14 +266,14 @@ def check_named_values(stage: str, named_values: Dict[str, Value]) -> None: # Bool is a subclass of int in Python, # so `isinstance(v, int)` will return True even if v is a boolean. # pylint: disable-next=unidiomatic-typecheck - if type(named_values[key]) is not expected_type: + if type(configs[key]) is not expected_type: raise TypeError( f"Stage {STAGE_SETUP}: The value for the key '{key}' " f"must be of type {expected_type}, " - f"but got {type(named_values[key])} instead." + f"but got {type(configs[key])} instead." ) elif stage == STAGE_SHARE_KEYS: - for key, value in named_values.items(): + for key, value in configs.items(): if ( not isinstance(value, list) or len(value) != 2 @@ -242,18 +288,17 @@ def check_named_values(stage: str, named_values: Dict[str, Value]) -> None: key_type_pairs = [ (KEY_CIPHERTEXT_LIST, bytes), (KEY_SOURCE_LIST, int), - (KEY_PARAMETERS, bytes), ] for key, expected_type in key_type_pairs: - if key not in named_values: + if key not in configs: raise KeyError( f"Stage {STAGE_COLLECT_MASKED_INPUT}: " f"the required key '{key}' is " "missing from the input `named_values`." ) - if not isinstance(named_values[key], list) or any( + if not isinstance(configs[key], list) or any( elm - for elm in cast(List[Any], named_values[key]) + for elm in cast(List[Any], configs[key]) # pylint: disable-next=unidiomatic-typecheck if type(elm) is not expected_type ): @@ -268,15 +313,15 @@ def check_named_values(stage: str, named_values: Dict[str, Value]) -> None: (KEY_DEAD_SECURE_ID_LIST, int), ] for key, expected_type in key_type_pairs: - if key not in named_values: + if key not in configs: raise KeyError( f"Stage {STAGE_UNMASK}: " f"the required key '{key}' is " "missing from the input `named_values`." ) - if not isinstance(named_values[key], list) or any( + if not isinstance(configs[key], list) or any( elm - for elm in cast(List[Any], named_values[key]) + for elm in cast(List[Any], configs[key]) # pylint: disable-next=unidiomatic-typecheck if type(elm) is not expected_type ): @@ -289,9 +334,11 @@ def check_named_values(stage: str, named_values: Dict[str, Value]) -> None: raise ValueError(f"Unknown secagg stage: {stage}") -def _setup(state: SecAggPlusState, named_values: Dict[str, Value]) -> Dict[str, Value]: +def _setup( + state: SecAggPlusState, configs: Dict[str, ConfigsRecordValues] +) -> Dict[str, ConfigsRecordValues]: # Assigning parameter values to object fields - sec_agg_param_dict = named_values + sec_agg_param_dict = configs state.sample_num = cast(int, sec_agg_param_dict[KEY_SAMPLE_NUMBER]) state.sid = cast(int, sec_agg_param_dict[KEY_SECURE_ID]) log(INFO, "Client %d: starting stage 0...", state.sid) @@ -324,9 +371,9 @@ def _setup(state: SecAggPlusState, named_values: Dict[str, Value]) -> Dict[str, # pylint: disable-next=too-many-locals def _share_keys( - state: SecAggPlusState, named_values: Dict[str, Value] -) -> Dict[str, Value]: - named_bytes_tuples = cast(Dict[str, Tuple[bytes, bytes]], named_values) + state: SecAggPlusState, configs: Dict[str, ConfigsRecordValues] +) -> Dict[str, ConfigsRecordValues]: + named_bytes_tuples = cast(Dict[str, Tuple[bytes, bytes]], configs) key_dict = {int(sid): (pk1, pk2) for sid, (pk1, pk2) in named_bytes_tuples.items()} log(INFO, "Client %d: starting stage 1...", state.sid) state.public_keys_dict = key_dict @@ -386,12 +433,14 @@ def _share_keys( # pylint: disable-next=too-many-locals def _collect_masked_input( - state: SecAggPlusState, named_values: Dict[str, Value] -) -> Dict[str, Value]: + state: SecAggPlusState, + configs: Dict[str, ConfigsRecordValues], + fit: Callable[[], FitRes], +) -> Dict[str, ConfigsRecordValues]: log(INFO, "Client %d: starting stage 2...", state.sid) available_clients: List[int] = [] - ciphertexts = cast(List[bytes], named_values[KEY_CIPHERTEXT_LIST]) - srcs = cast(List[int], named_values[KEY_SOURCE_LIST]) + ciphertexts = cast(List[bytes], configs[KEY_CIPHERTEXT_LIST]) + srcs = cast(List[int], configs[KEY_SOURCE_LIST]) if len(ciphertexts) + 1 < state.threshold: raise ValueError("Not enough available neighbour clients.") @@ -417,18 +466,9 @@ def _collect_masked_input( state.sk1_share_dict[src] = sk1_share # Fit client - parameters_bytes = cast(List[bytes], named_values[KEY_PARAMETERS]) - parameters = [bytes_to_ndarray(w) for w in parameters_bytes] - if isinstance(state.client, Client): - fit_res = state.client.fit( - FitIns(parameters=ndarrays_to_parameters(parameters), config={}) - ) - parameters_factor = fit_res.num_examples - parameters = parameters_to_ndarrays(fit_res.parameters) - elif isinstance(state.client, NumPyClient): - parameters, parameters_factor, _ = state.client.fit(parameters, {}) - else: - log(ERROR, "Client %d: fit function is missing.", state.sid) + fit_res = fit() + parameters_factor = fit_res.num_examples + parameters = parameters_to_ndarrays(fit_res.parameters) # Quantize parameter update (vector) quantized_parameters = quantize( @@ -468,11 +508,13 @@ def _collect_masked_input( } -def _unmask(state: SecAggPlusState, named_values: Dict[str, Value]) -> Dict[str, Value]: +def _unmask( + state: SecAggPlusState, configs: Dict[str, ConfigsRecordValues] +) -> Dict[str, ConfigsRecordValues]: log(INFO, "Client %d: starting stage 3...", state.sid) - active_sids = cast(List[int], named_values[KEY_ACTIVE_SECURE_ID_LIST]) - dead_sids = cast(List[int], named_values[KEY_DEAD_SECURE_ID_LIST]) + active_sids = cast(List[int], configs[KEY_ACTIVE_SECURE_ID_LIST]) + dead_sids = cast(List[int], configs[KEY_DEAD_SECURE_ID_LIST]) # Send private mask seed share for every avaliable client (including itclient) # Send first private key share for building pairwise mask for every dropped client if len(active_sids) < state.threshold: diff --git a/src/py/flwr/client/secure_aggregation/secaggplus_handler_test.py b/src/py/flwr/client/middleware/secure_aggregation/secaggplus_middleware_test.py similarity index 57% rename from src/py/flwr/client/secure_aggregation/secaggplus_handler_test.py rename to src/py/flwr/client/middleware/secure_aggregation/secaggplus_middleware_test.py index 9693a46af989..8ec52d71cbdd 100644 --- a/src/py/flwr/client/secure_aggregation/secaggplus_handler_test.py +++ b/src/py/flwr/client/middleware/secure_aggregation/secaggplus_middleware_test.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2024 Flower Labs GmbH. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -16,16 +16,20 @@ import unittest from itertools import product -from typing import Any, Dict, List, cast - -from flwr.client import NumPyClient +from typing import Callable, Dict, List + +from flwr.client.middleware import make_ffn +from flwr.common.configsrecord import ConfigsRecord +from flwr.common.constant import TASK_TYPE_FIT +from flwr.common.context import Context +from flwr.common.message import Message, Metadata +from flwr.common.recordset import RecordSet from flwr.common.secure_aggregation.secaggplus_constants import ( KEY_ACTIVE_SECURE_ID_LIST, KEY_CIPHERTEXT_LIST, KEY_CLIPPING_RANGE, KEY_DEAD_SECURE_ID_LIST, KEY_MOD_RANGE, - KEY_PARAMETERS, KEY_SAMPLE_NUMBER, KEY_SECURE_ID, KEY_SHARE_NUMBER, @@ -33,34 +37,68 @@ KEY_STAGE, KEY_TARGET_RANGE, KEY_THRESHOLD, + RECORD_KEY_CONFIGS, + RECORD_KEY_STATE, STAGE_COLLECT_MASKED_INPUT, STAGE_SETUP, STAGE_SHARE_KEYS, STAGE_UNMASK, STAGES, ) -from flwr.common.typing import Value +from flwr.common.typing import ConfigsRecordValues -from .secaggplus_handler import SecAggPlusHandler, check_named_values +from .secaggplus_middleware import SecAggPlusState, check_configs, secaggplus_middleware -class EmptyFlowerNumPyClient(NumPyClient, SecAggPlusHandler): - """Empty NumPyClient.""" +def get_test_handler( + ctxt: Context, +) -> Callable[[Dict[str, ConfigsRecordValues]], Dict[str, ConfigsRecordValues]]: + """.""" + def empty_ffn(_: Message, _2: Context) -> Message: + return Message( + metadata=Metadata(0, "", "", "", TASK_TYPE_FIT), + message=RecordSet(), + ) + + app = make_ffn(empty_ffn, [secaggplus_middleware]) + + def func(configs: Dict[str, ConfigsRecordValues]) -> Dict[str, ConfigsRecordValues]: + in_msg = Message( + metadata=Metadata(0, "", "", "", TASK_TYPE_FIT), + message=RecordSet(configs={RECORD_KEY_CONFIGS: ConfigsRecord(configs)}), + ) + out_msg = app(in_msg, ctxt) + return out_msg.message.get_configs(RECORD_KEY_CONFIGS).data + + return func + + +def _make_ctxt() -> Context: + cfg = ConfigsRecord(SecAggPlusState().to_dict()) + return Context(RecordSet(configs={RECORD_KEY_STATE: cfg})) -class TestSecAggPlusHandler(unittest.TestCase): - """Test the SecAgg+ protocol handler.""" - def test_invalid_handler(self) -> None: - """Test invalid handler.""" - handler = SecAggPlusHandler() +def _make_set_state_fn( + ctxt: Context, +) -> Callable[[str], None]: + def set_stage(stage: str) -> None: + state_dict = ctxt.state.get_configs(RECORD_KEY_STATE).data + state = SecAggPlusState(**state_dict) + state.current_stage = stage + ctxt.state.set_configs(RECORD_KEY_STATE, ConfigsRecord(state.to_dict())) - with self.assertRaises(TypeError): - handler.handle_secure_aggregation({}) + return set_stage + + +class TestSecAggPlusHandler(unittest.TestCase): + """Test the SecAgg+ protocol handler.""" def test_stage_transition(self) -> None: """Test stage transition.""" - handler = EmptyFlowerNumPyClient() + ctxt = _make_ctxt() + handler = get_test_handler(ctxt) + set_stage = _make_set_state_fn(ctxt) assert STAGES == ( STAGE_SETUP, @@ -88,28 +126,24 @@ def test_stage_transition(self) -> None: # If the next stage is valid, the function should update the current stage # and then raise KeyError or other exceptions when trying to execute SA. for current_stage, next_stage in valid_transitions: - # pylint: disable-next=protected-access - handler._current_stage = current_stage + set_stage(current_stage) with self.assertRaises(KeyError): - handler.handle_secure_aggregation({KEY_STAGE: next_stage}) - # pylint: disable-next=protected-access - assert handler._current_stage == next_stage + handler({KEY_STAGE: next_stage}) # Test invalid transitions # If the next stage is invalid, the function should raise ValueError for current_stage, next_stage in invalid_transitions: - # pylint: disable-next=protected-access - handler._current_stage = current_stage + set_stage(current_stage) with self.assertRaises(ValueError): - handler.handle_secure_aggregation({KEY_STAGE: next_stage}) - # pylint: disable-next=protected-access - assert handler._current_stage == current_stage + handler({KEY_STAGE: next_stage}) def test_stage_setup_check(self) -> None: """Test content checking for the setup stage.""" - handler = EmptyFlowerNumPyClient() + ctxt = _make_ctxt() + handler = get_test_handler(ctxt) + set_stage = _make_set_state_fn(ctxt) valid_key_type_pairs = [ (KEY_SAMPLE_NUMBER, int), @@ -121,7 +155,7 @@ def test_stage_setup_check(self) -> None: (KEY_MOD_RANGE, int), ] - type_to_test_value: Dict[type, Value] = { + type_to_test_value: Dict[type, ConfigsRecordValues] = { int: 10, bool: True, float: 1.0, @@ -129,47 +163,49 @@ def test_stage_setup_check(self) -> None: bytes: b"test", } - valid_named_values: Dict[str, Value] = { + valid_configs: Dict[str, ConfigsRecordValues] = { key: type_to_test_value[value_type] for key, value_type in valid_key_type_pairs } # Test valid `named_values` try: - check_named_values(STAGE_SETUP, valid_named_values.copy()) + check_configs(STAGE_SETUP, valid_configs.copy()) # pylint: disable-next=broad-except except Exception as exc: self.fail(f"check_named_values() raised {type(exc)} unexpectedly!") # Set the stage - valid_named_values[KEY_STAGE] = STAGE_SETUP + valid_configs[KEY_STAGE] = STAGE_SETUP # Test invalid `named_values` for key, value_type in valid_key_type_pairs: - invalid_named_values = valid_named_values.copy() + invalid_configs = valid_configs.copy() # Test wrong value type for the key for other_type, other_value in type_to_test_value.items(): if other_type == value_type: continue - invalid_named_values[key] = other_value - # pylint: disable-next=protected-access - handler._current_stage = STAGE_UNMASK + invalid_configs[key] = other_value + + set_stage(STAGE_UNMASK) with self.assertRaises(TypeError): - handler.handle_secure_aggregation(invalid_named_values.copy()) + handler(invalid_configs.copy()) # Test missing key - invalid_named_values.pop(key) - # pylint: disable-next=protected-access - handler._current_stage = STAGE_UNMASK + invalid_configs.pop(key) + + set_stage(STAGE_UNMASK) with self.assertRaises(KeyError): - handler.handle_secure_aggregation(invalid_named_values.copy()) + handler(invalid_configs.copy()) def test_stage_share_keys_check(self) -> None: """Test content checking for the share keys stage.""" - handler = EmptyFlowerNumPyClient() + ctxt = _make_ctxt() + handler = get_test_handler(ctxt) + set_stage = _make_set_state_fn(ctxt) - valid_named_values: Dict[str, Value] = { + valid_configs: Dict[str, ConfigsRecordValues] = { "1": [b"public key 1", b"public key 2"], "2": [b"public key 1", b"public key 2"], "3": [b"public key 1", b"public key 2"], @@ -177,111 +213,113 @@ def test_stage_share_keys_check(self) -> None: # Test valid `named_values` try: - check_named_values(STAGE_SHARE_KEYS, valid_named_values.copy()) + check_configs(STAGE_SHARE_KEYS, valid_configs.copy()) # pylint: disable-next=broad-except except Exception as exc: self.fail(f"check_named_values() raised {type(exc)} unexpectedly!") # Set the stage - valid_named_values[KEY_STAGE] = STAGE_SHARE_KEYS + valid_configs[KEY_STAGE] = STAGE_SHARE_KEYS # Test invalid `named_values` - invalid_values: List[Value] = [ + invalid_values: List[ConfigsRecordValues] = [ b"public key 1", [b"public key 1"], [b"public key 1", b"public key 2", b"public key 3"], ] for value in invalid_values: - invalid_named_values = valid_named_values.copy() - invalid_named_values["1"] = value + invalid_configs = valid_configs.copy() + invalid_configs["1"] = value - # pylint: disable-next=protected-access - handler._current_stage = STAGE_SETUP + set_stage(STAGE_SETUP) with self.assertRaises(TypeError): - handler.handle_secure_aggregation(invalid_named_values.copy()) + handler(invalid_configs.copy()) def test_stage_collect_masked_input_check(self) -> None: """Test content checking for the collect masked input stage.""" - handler = EmptyFlowerNumPyClient() + ctxt = _make_ctxt() + handler = get_test_handler(ctxt) + set_stage = _make_set_state_fn(ctxt) - valid_named_values: Dict[str, Value] = { + valid_configs: Dict[str, ConfigsRecordValues] = { KEY_CIPHERTEXT_LIST: [b"ctxt!", b"ctxt@", b"ctxt#", b"ctxt?"], KEY_SOURCE_LIST: [32, 51324, 32324123, -3], - KEY_PARAMETERS: [b"params1", b"params2"], } # Test valid `named_values` try: - check_named_values(STAGE_COLLECT_MASKED_INPUT, valid_named_values.copy()) + check_configs(STAGE_COLLECT_MASKED_INPUT, valid_configs.copy()) # pylint: disable-next=broad-except except Exception as exc: self.fail(f"check_named_values() raised {type(exc)} unexpectedly!") # Set the stage - valid_named_values[KEY_STAGE] = STAGE_COLLECT_MASKED_INPUT + valid_configs[KEY_STAGE] = STAGE_COLLECT_MASKED_INPUT # Test invalid `named_values` # Test missing keys - for key in list(valid_named_values.keys()): + for key in list(valid_configs.keys()): if key == KEY_STAGE: continue - invalid_named_values = valid_named_values.copy() - invalid_named_values.pop(key) - # pylint: disable-next=protected-access - handler._current_stage = STAGE_SHARE_KEYS + invalid_configs = valid_configs.copy() + invalid_configs.pop(key) + + set_stage(STAGE_SHARE_KEYS) with self.assertRaises(KeyError): - handler.handle_secure_aggregation(invalid_named_values) + handler(invalid_configs) # Test wrong value type for the key - for key in valid_named_values: + for key in valid_configs: if key == KEY_STAGE: continue - invalid_named_values = valid_named_values.copy() - cast(List[Any], invalid_named_values[key]).append(3.1415926) - # pylint: disable-next=protected-access - handler._current_stage = STAGE_SHARE_KEYS + invalid_configs = valid_configs.copy() + invalid_configs[key] = [3.1415926] + + set_stage(STAGE_SHARE_KEYS) with self.assertRaises(TypeError): - handler.handle_secure_aggregation(invalid_named_values) + handler(invalid_configs) def test_stage_unmask_check(self) -> None: """Test content checking for the unmasking stage.""" - handler = EmptyFlowerNumPyClient() + ctxt = _make_ctxt() + handler = get_test_handler(ctxt) + set_stage = _make_set_state_fn(ctxt) - valid_named_values: Dict[str, Value] = { + valid_configs: Dict[str, ConfigsRecordValues] = { KEY_ACTIVE_SECURE_ID_LIST: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], KEY_DEAD_SECURE_ID_LIST: [32, 51324, 32324123, -3], } # Test valid `named_values` try: - check_named_values(STAGE_UNMASK, valid_named_values.copy()) + check_configs(STAGE_UNMASK, valid_configs.copy()) # pylint: disable-next=broad-except except Exception as exc: self.fail(f"check_named_values() raised {type(exc)} unexpectedly!") # Set the stage - valid_named_values[KEY_STAGE] = STAGE_UNMASK + valid_configs[KEY_STAGE] = STAGE_UNMASK # Test invalid `named_values` # Test missing keys - for key in list(valid_named_values.keys()): + for key in list(valid_configs.keys()): if key == KEY_STAGE: continue - invalid_named_values = valid_named_values.copy() - invalid_named_values.pop(key) - # pylint: disable-next=protected-access - handler._current_stage = STAGE_COLLECT_MASKED_INPUT + invalid_configs = valid_configs.copy() + invalid_configs.pop(key) + + set_stage(STAGE_COLLECT_MASKED_INPUT) with self.assertRaises(KeyError): - handler.handle_secure_aggregation(invalid_named_values) + handler(invalid_configs) # Test wrong value type for the key - for key in valid_named_values: + for key in valid_configs: if key == KEY_STAGE: continue - invalid_named_values = valid_named_values.copy() - cast(List[Any], invalid_named_values[key]).append(True) - # pylint: disable-next=protected-access - handler._current_stage = STAGE_COLLECT_MASKED_INPUT + invalid_configs = valid_configs.copy() + invalid_configs[key] = [True, False, True, False] + + set_stage(STAGE_COLLECT_MASKED_INPUT) with self.assertRaises(TypeError): - handler.handle_secure_aggregation(invalid_named_values) + handler(invalid_configs) diff --git a/src/py/flwr/client/secure_aggregation/handler.py b/src/py/flwr/client/secure_aggregation/handler.py deleted file mode 100644 index 487ed842c93f..000000000000 --- a/src/py/flwr/client/secure_aggregation/handler.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Message Handler for Secure Aggregation (abstract base class).""" - - -from abc import ABC, abstractmethod -from typing import Dict - -from flwr.common.typing import Value - - -class SecureAggregationHandler(ABC): - """Abstract base class for secure aggregation message handlers.""" - - @abstractmethod - def handle_secure_aggregation( - self, named_values: Dict[str, Value] - ) -> Dict[str, Value]: - """Handle incoming Secure Aggregation message and return results. - - Parameters - ---------- - named_values : Dict[str, Value] - The named values retrieved from the SecureAggregation sub-message - of Task message in the server's TaskIns. - - Returns - ------- - Dict[str, Value] - The final/intermediate results of the Secure Aggregation protocol. - """ diff --git a/src/py/flwr/common/secure_aggregation/secaggplus_constants.py b/src/py/flwr/common/secure_aggregation/secaggplus_constants.py index 8dd21a6016f1..9a2bf26e98e8 100644 --- a/src/py/flwr/common/secure_aggregation/secaggplus_constants.py +++ b/src/py/flwr/common/secure_aggregation/secaggplus_constants.py @@ -14,6 +14,8 @@ # ============================================================================== """Constants for the SecAgg/SecAgg+ protocol.""" +RECORD_KEY_STATE = "secaggplus_state" +RECORD_KEY_CONFIGS = "secaggplus_configs" # Names of stages STAGE_SETUP = "setup" From 0f3a7345930334f854ba4117daa9564cd931ac00 Mon Sep 17 00:00:00 2001 From: Yan Gao Date: Thu, 1 Feb 2024 12:00:32 +0000 Subject: [PATCH 065/113] XGBoost Flower simulation (#2668) Co-authored-by: yan-gao-GY Co-authored-by: Daniel J. Beutel Co-authored-by: jafermarq Co-authored-by: Taner Topal --- README.md | 2 + examples/xgboost-comprehensive/README.md | 101 ++++++++-- .../_static/xgboost_flower_auc.png | Bin 68480 -> 0 bytes .../_static/xgboost_flower_auc_bagging.png | Bin 0 -> 78478 bytes .../_static/xgboost_flower_auc_cyclic.png | Bin 0 -> 69981 bytes examples/xgboost-comprehensive/client.py | 144 +++----------- .../xgboost-comprehensive/client_utils.py | 126 ++++++++++++ examples/xgboost-comprehensive/dataset.py | 10 +- examples/xgboost-comprehensive/pyproject.toml | 2 +- .../xgboost-comprehensive/requirements.txt | 2 +- examples/xgboost-comprehensive/run_bagging.sh | 4 +- examples/xgboost-comprehensive/server.py | 110 ++-------- .../xgboost-comprehensive/server_utils.py | 101 ++++++++++ examples/xgboost-comprehensive/sim.py | 188 ++++++++++++++++++ examples/xgboost-comprehensive/utils.py | 84 +++++++- 15 files changed, 632 insertions(+), 242 deletions(-) delete mode 100644 examples/xgboost-comprehensive/_static/xgboost_flower_auc.png create mode 100644 examples/xgboost-comprehensive/_static/xgboost_flower_auc_bagging.png create mode 100644 examples/xgboost-comprehensive/_static/xgboost_flower_auc_cyclic.png create mode 100644 examples/xgboost-comprehensive/client_utils.py create mode 100644 examples/xgboost-comprehensive/server_utils.py create mode 100644 examples/xgboost-comprehensive/sim.py diff --git a/README.md b/README.md index 79e931dade9d..8e32fcde22a0 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,7 @@ Quickstart examples: - [Quickstart (Pandas)](https://github.com/adap/flower/tree/main/examples/quickstart-pandas) - [Quickstart (JAX)](https://github.com/adap/flower/tree/main/examples/quickstart-jax) - [Quickstart (scikit-learn)](https://github.com/adap/flower/tree/main/examples/sklearn-logreg-mnist) +- [Quickstart (XGBoost)](https://github.com/adap/flower/tree/main/examples/xgboost-quickstart) - [Quickstart (Android [TFLite])](https://github.com/adap/flower/tree/main/examples/android) - [Quickstart (iOS [CoreML])](https://github.com/adap/flower/tree/main/examples/ios) @@ -135,6 +136,7 @@ Other [examples](https://github.com/adap/flower/tree/main/examples): - [Advanced Flower with TensorFlow/Keras](https://github.com/adap/flower/tree/main/examples/advanced-tensorflow) - [Advanced Flower with PyTorch](https://github.com/adap/flower/tree/main/examples/advanced-pytorch) - Single-Machine Simulation of Federated Learning Systems ([PyTorch](https://github.com/adap/flower/tree/main/examples/simulation_pytorch)) ([Tensorflow](https://github.com/adap/flower/tree/main/examples/simulation_tensorflow)) +- [Comprehensive Flower+XGBoost](https://github.com/adap/flower/tree/main/examples/xgboost-comprehensive) - [Flower through Docker Compose and with Grafana dashboard](https://github.com/adap/flower/tree/main/examples/flower-via-docker-compose) ## Community diff --git a/examples/xgboost-comprehensive/README.md b/examples/xgboost-comprehensive/README.md index 11c4c3f9a08b..97ecc39b47f2 100644 --- a/examples/xgboost-comprehensive/README.md +++ b/examples/xgboost-comprehensive/README.md @@ -1,7 +1,7 @@ # Flower Example using XGBoost (Comprehensive) This example demonstrates a comprehensive federated learning setup using Flower with XGBoost. -We use [HIGGS](https://archive.ics.uci.edu/dataset/280/higgs) dataset to perform a binary classification task. +We use [HIGGS](https://archive.ics.uci.edu/dataset/280/higgs) dataset to perform a binary classification task. This examples uses [Flower Datasets](https://flower.dev/docs/datasets/) to retrieve, partition and preprocess the data for each Flower client. It differs from the [xgboost-quickstart](https://github.com/adap/flower/tree/main/examples/xgboost-quickstart) example in the following ways: - Arguments parsers of server and clients for hyperparameters selection. @@ -10,6 +10,32 @@ It differs from the [xgboost-quickstart](https://github.com/adap/flower/tree/mai - Customised partitioner type (uniform, linear, square, exponential). - Centralised/distributed evaluation. - Bagging/cyclic training methods. +- You can run it with Flower Simulation + +## Training Strategies + +This example provides two training strategies, **bagging aggregation** and **cyclic training**. + +### Bagging Aggregation + +Bagging (bootstrap) aggregation is an ensemble meta-algorithm in machine learning, +used for enhancing the stability and accuracy of machine learning algorithms. +Here, we leverage this algorithm for XGBoost trees. + +Specifically, each client is treated as a bootstrap by random subsampling (data partitioning in FL). +At each FL round, all clients boost a number of trees (in this example, 1 tree) based on the local bootstrap samples. +Then, the clients' trees are aggregated on the server, and concatenates them to the global model from previous round. +The aggregated tree ensemble is regarded as a new global model. + +This way, let's consider a scenario with M clients. +Given FL round R, the bagging models consist of (M * R) trees. + +### Cyclic Training + +Cyclic XGBoost training performs FL in a client-by-client fashion. +Instead of aggregating multiple clients, +there is only one single client participating in the training per round in the cyclic training scenario. +The trained local XGBoost trees will be passed to the next client as an initialised model for next round's boosting. ## Project Setup @@ -26,7 +52,10 @@ This will create a new directory called `xgboost-comprehensive` containing the f -- server.py <- Defines the server-side logic -- client.py <- Defines the client-side logic -- dataset.py <- Defines the functions of data loading and partitioning --- utils.py <- Defines the arguments parser for clients and server +-- utils.py <- Defines the arguments parser and hyper-parameters +-- client_utils.py <- Defines the client utility functions +-- server_utils.py <- Defines the server utility functions +-- sim.py <- Example of using Flower simulation -- run_bagging.sh <- Commands to run bagging experiments -- run_cyclic.sh <- Commands to run cyclic experiments -- pyproject.toml <- Example dependencies (if you use Poetry) @@ -47,7 +76,7 @@ poetry shell Poetry will install all your dependencies in a newly created virtual environment. To verify that everything works correctly you can run the following command: ```shell -poetry run python3 -c "import flwr" +poetry run python -c "import flwr" ``` If you don't see any errors you're good to go! @@ -62,44 +91,76 @@ pip install -r requirements.txt ## Run Federated Learning with XGBoost and Flower +You can run this example in two ways: either by manually launching the server, and then several clients that connect to it; or by launching a Flower simulation. Both run the same workload, yielding identical results. The former is ideal for deployments on different machines, while the latter makes it easy to simulate large client cohorts in a resource-aware manner. You can read more about how Flower Simulation works in the [Documentation](https://flower.dev/docs/framework/how-to-run-simulations.html). The commands shown below assume you have activated your environment (if you decide to use Poetry, you can activate it via `poetry shell`). + +### Independent Client/Server Setup + We have two scripts to run bagging and cyclic (client-by-client) experiments. The included `run_bagging.sh` or `run_cyclic.sh` will start the Flower server (using `server.py`), sleep for 15 seconds to ensure that the server is up, and then start 5 Flower clients (using `client.py`) with a small subset of the data from exponential partition distribution. + You can simply start everything in a terminal as follows: ```shell -poetry run ./run_bagging.sh +./run_bagging.sh ``` Or ```shell -poetry run ./run_cyclic.sh +./run_cyclic.sh +``` + +The script starts processes in the background so that you don't have to open six terminal windows. + +You can also run the example without the scripts. First, launch the server: + +```bash +python server.py --train-method=bagging/cyclic --pool-size=N --num-clients-per-round=N +``` + +Then run at least two clients (each on a new terminal or computer in your network) passing different `NODE_ID` and all using the same `N` (denoting the total number of clients or data partitions): + +```bash +python client.py --train-method=bagging/cyclic --node-id=NODE_ID --num-partitions=N +``` + +### Flower Simulation Setup + +We also provide an example code (`sim.py`) to use the simulation capabilities of Flower to simulate federated XGBoost training on either a single machine or a cluster of machines. With default arguments, each client will use 2 CPUs. + +To run bagging aggregation with 5 clients for 30 rounds evaluated on centralised test set: + +```shell +python sim.py --train-method=bagging --pool-size=5 --num-clients-per-round=5 --num-rounds=30 --centralised-eval ``` -The script starts processes in the background so that you don't have to open eleven terminal windows. -If you experiment with the code example and something goes wrong, simply using `CTRL + C` on Linux (or `CMD + C` on macOS) wouldn't normally kill all these processes, -which is why the script ends with `trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT` and `wait`. -This simply allows you to stop the experiment using `CTRL + C` (or `CMD + C`). -If you change the script and anything goes wrong you can still use `killall python` (or `killall python3`) -to kill all background processes (or a more specific command if you have other Python processes running that you don't want to kill). +To run cyclic training with 5 clients for 30 rounds evaluated on centralised test set: -You can also manually run `poetry run python3 server.py --train-method=bagging/cyclic --pool-size=N --num-clients-per-round=N` -and `poetry run python3 client.py --train-method=bagging/cyclic --node-id=NODE_ID --num-partitions=N` for as many clients as you want, -but you have to make sure that each command is run in a different terminal window (or a different computer on the network). +```shell +python sim.py --train-method=cyclic --pool-size=5 --num-rounds=30 --centralised-eval-client +``` In addition, we provide more options to customise the experimental settings, including data partitioning and centralised/distributed evaluation (see `utils.py`). -Look at the [code](https://github.com/adap/flower/tree/main/examples/xgboost-comprehensive) -and [tutorial](https://flower.dev/docs/framework/tutorial-quickstart-xgboost.html) for a detailed explanation. +Check the [tutorial](https://flower.dev/docs/framework/tutorial-quickstart-xgboost.html) for a detailed explanation. ### Expected Experimental Results #### Bagging aggregation experiment -![](_static/xgboost_flower_auc.png) +![](_static/xgboost_flower_auc_bagging.png) -The figure above shows the centralised tested AUC performance over FL rounds on 4 experimental settings. +The figure above shows the centralised tested AUC performance over FL rounds with bagging aggregation strategy on 4 experimental settings. One can see that all settings obtain stable performance boost over FL rounds (especially noticeable at the start of training). -As expected, uniform client distribution shows higher AUC values (beyond 83% at the end) than square/exponential setup. -Feel free to explore more interesting experiments by yourself! +As expected, uniform client distribution shows higher AUC values than square/exponential setup. + +#### Cyclic training experiment + +![](_static/xgboost_flower_auc_cyclic.png) + +This figure shows the cyclic training results on centralised test set. +The models with cyclic training requires more rounds to converge +because only a single client participate in the training per round. + +Feel free to explore more interesting experiments by yourself ! diff --git a/examples/xgboost-comprehensive/_static/xgboost_flower_auc.png b/examples/xgboost-comprehensive/_static/xgboost_flower_auc.png deleted file mode 100644 index e6a4bfb83250cb280b435b364adb4dd2fed0f414..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68480 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 X2M{uX{m*Uae?w>g|1`4vW9&Zw55TC& literal 0 HcmV?d00001 diff --git a/baselines/fedpara/_static/Cifar10_noniid.jpeg b/baselines/fedpara/_static/Cifar10_noniid.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..2f510f04731803fc64500f7ac6aab54666347f35 GIT binary patch literal 40363 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 literal 0 HcmV?d00001 diff --git a/baselines/fedpara/_static/non-iid_mnist_personalization.png b/baselines/fedpara/_static/non-iid_mnist_personalization.png new file mode 100644 index 0000000000000000000000000000000000000000..4b09de2c28366790aa575e78ba029fe5d5b9d178 GIT binary patch literal 17118 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 NDArrays: + """Return the parameters of the current net.""" + return [val.cpu().numpy() for _, val in self.net.state_dict().items()] + + def set_parameters(self, parameters: NDArrays) -> None: + """Apply parameters to model state dict.""" + params_dict = zip(self.net.state_dict().keys(), parameters) + state_dict = OrderedDict({k: torch.Tensor(v) for k, v in params_dict}) + self.net.load_state_dict(state_dict, strict=True) + + def fit( + self, parameters: NDArrays, config: Dict[str, Scalar] + ) -> Tuple[NDArrays, int, Dict]: + """Train the network on the training set.""" + self.set_parameters(parameters) + + train( + self.net, + self.train_loader, + self.device, + epochs=self.num_epochs, + hyperparams=config, + epoch=int(config["curr_round"]), + ) + + return ( + self.get_parameters({}), + len(self.train_loader), + {}, + ) + + +# pylint: disable=too-many-instance-attributes +class PFlowerClient(fl.client.NumPyClient): + """Personalized Flower Client.""" + + def __init__( # pylint: disable=too-many-arguments + self, + cid: int, + net: torch.nn.Module, + train_loader: DataLoader, + test_loader: DataLoader, + device: str, + num_epochs: int, + state_path: str, + algorithm: str, + ): + self.cid = cid + self.net = net + self.train_loader = train_loader + self.test_loader = test_loader + self.device = torch.device(device) + self.num_epochs = num_epochs + self.state_path = state_path + self.algorithm = algorithm + self.private_server_param: Dict[str, torch.Tensor] = {} + + def get_parameters(self, config: Dict[str, Scalar]) -> NDArrays: + """Return the parameters of the current net.""" + model_dict = self.net.state_dict().copy() + # overwrite the server private parameters + for k in self.private_server_param.keys(): + model_dict[k] = self.private_server_param[k] + return [val.cpu().numpy() for _, val in model_dict.items()] + + def set_parameters(self, parameters: NDArrays, evaluate: bool) -> None: + """Apply parameters to model state dict.""" + params_dict = zip(self.net.state_dict().keys(), parameters) + server_dict = OrderedDict({k: torch.Tensor(v) for k, v in params_dict}) + self.private_server_param = { + k: server_dict[k] + for k in get_keys_state_dict( + model=self.net, algorithm=self.algorithm, mode="local" + ) + } + + if evaluate: + client_dict = self.net.state_dict().copy() + else: + client_dict = copy.deepcopy(server_dict) + + if os.path.isfile(self.state_path): + with open(self.state_path, "rb") as f: + client_dict = torch.load(f) + + for k in get_keys_state_dict( + model=self.net, algorithm=self.algorithm, mode="global" + ): + client_dict[k] = server_dict[k] + + self.net.load_state_dict(client_dict, strict=False) + + def fit( + self, parameters: NDArrays, config: Dict[str, Scalar] + ) -> Tuple[NDArrays, int, Dict]: + """Train the network on the training set.""" + self.set_parameters(parameters, evaluate=False) + + train( + self.net, + self.train_loader, + self.device, + epochs=self.num_epochs, + hyperparams=config, + epoch=int(config["curr_round"]), + ) + if self.state_path is not None: + with open(self.state_path, "wb") as f: + torch.save(self.net.state_dict(), f) + + return ( + self.get_parameters({}), + len(self.train_loader), + {}, + ) + + def evaluate( + self, parameters: NDArrays, config: Dict[str, Scalar] + ) -> Tuple[float, int, Dict]: + """Evaluate the network on the test set.""" + self.set_parameters(parameters, evaluate=True) + self.net.to(self.device) + loss, accuracy = test(self.net, self.test_loader, device=self.device) + return loss, len(self.test_loader), {"accuracy": accuracy} + + +# pylint: disable=too-many-arguments +def gen_client_fn( + train_loaders: List[DataLoader], + model: DictConfig, + num_epochs: int, + args: Dict, + test_loader: Optional[List[DataLoader]] = None, + state_path: Optional[str] = None, +) -> Callable[[str], fl.client.NumPyClient]: + """Return a function which creates a new FlowerClient for a given cid.""" + + def client_fn(cid: str) -> fl.client.NumPyClient: + """Create a new FlowerClient for a given cid.""" + cid_ = int(cid) + device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") + if args["algorithm"].lower() == "pfedpara" or args["algorithm"] == "fedper": + cl_path = f"{state_path}/client_{cid_}.pth" + return PFlowerClient( + cid=cid_, + net=instantiate(model).to(device), + train_loader=train_loaders[cid_], + test_loader=copy.deepcopy(test_loader), + num_epochs=num_epochs, + state_path=cl_path, + algorithm=args["algorithm"].lower(), + device=device, + ) + return FlowerClient( + cid=cid_, + net=instantiate(model).to(device), + train_loader=train_loaders[cid_], + num_epochs=num_epochs, + device=device, + ) + + return client_fn diff --git a/baselines/fedpara/fedpara/conf/cifar10.yaml b/baselines/fedpara/fedpara/conf/cifar10.yaml new file mode 100644 index 000000000000..97ec2520c3c1 --- /dev/null +++ b/baselines/fedpara/fedpara/conf/cifar10.yaml @@ -0,0 +1,43 @@ +--- +seed: 121 + +num_clients: 100 +num_rounds: 200 +clients_per_round: 16 +num_epochs: 5 +batch_size: 64 +algorithm: FedPara + +server_device: cuda + +client_resources: + num_cpus: 2 + num_gpus: 0.125 + +dataset_config: + name: CIFAR10 + partition: non-iid + num_classes: 10 + alpha: 0.5 + +model: + _target_: fedpara.models.VGG + num_classes: ${dataset_config.num_classes} + param_type: lowrank # lowrank or standard + ratio: 0.1 # lowrank ratio + +hyperparams: + eta_l: 0.1 + learning_decay: 0.992 + + +strategy: + _target_: flwr.server.strategy.FedAvg + fraction_fit: 0.00001 + fraction_evaluate: 0.0 + min_evaluate_clients: 0 + min_fit_clients: ${clients_per_round} + min_available_clients: ${clients_per_round} + accept_failures: false + +exp_id: ${model.param_type}_${dataset_config.name}_${dataset_config.partition}_alpha${dataset_config.alpha} diff --git a/baselines/fedpara/fedpara/conf/cifar100.yaml b/baselines/fedpara/fedpara/conf/cifar100.yaml new file mode 100644 index 000000000000..d1023014605b --- /dev/null +++ b/baselines/fedpara/fedpara/conf/cifar100.yaml @@ -0,0 +1,42 @@ +--- +seed: 342130 + +num_clients: 50 +num_rounds: 400 +clients_per_round: 8 +num_epochs: 5 +batch_size: 64 +algorithm: FedPara + +server_device: cuda + +client_resources: + num_cpus: 2 + num_gpus: 0.125 + +dataset_config: + name: CIFAR100 + partition: non-iid + num_classes: 100 + alpha: 0.5 + +model: + _target_: fedpara.models.VGG + num_classes: ${dataset_config.num_classes} + param_type: lowrank # lowrank or standard + ratio: 0.4 # lowrank ratio + +hyperparams: + eta_l: 0.1 + learning_decay: 0.992 + +strategy: + _target_: flwr.server.strategy.FedAvg + fraction_fit: 0.00001 + fraction_evaluate: 0.0 + min_evaluate_clients: 0 + min_fit_clients: ${clients_per_round} + min_available_clients: ${clients_per_round} + accept_failures: false + +exp_id: ${model.param_type}_${dataset_config.name}_${dataset_config.partition}_alpha${dataset_config.alpha} \ No newline at end of file diff --git a/baselines/fedpara/fedpara/conf/mnist_fedavg.yaml b/baselines/fedpara/fedpara/conf/mnist_fedavg.yaml new file mode 100644 index 000000000000..d0cda9a62e76 --- /dev/null +++ b/baselines/fedpara/fedpara/conf/mnist_fedavg.yaml @@ -0,0 +1,38 @@ +--- +seed: 424 + +num_clients: 100 +num_rounds: 100 +clients_per_round: 10 +num_epochs: 1 +batch_size: 10 +server_device: cuda +algorithm: fedavg + +client_resources: + num_cpus: 2 + num_gpus: 0.1 + +dataset_config: + name: MNIST + num_classes: 10 + shard_size: 300 + +model: + _target_: fedpara.models.FC + num_classes: ${dataset_config.num_classes} + hidden_size: 200 + +hyperparams: + eta_l: 0.05 + learning_decay: 1 + +strategy: + _target_: flwr.server.strategy.FedAvg + fraction_fit: 0.00001 + fraction_evaluate: 0 + min_evaluate_clients: 0 + min_fit_clients: ${clients_per_round} + min_available_clients: ${clients_per_round} + +exp_id: ${algorithm}_${dataset_config.name} diff --git a/baselines/fedpara/fedpara/conf/mnist_fedper.yaml b/baselines/fedpara/fedpara/conf/mnist_fedper.yaml new file mode 100644 index 000000000000..dd9034284459 --- /dev/null +++ b/baselines/fedpara/fedpara/conf/mnist_fedper.yaml @@ -0,0 +1,45 @@ +--- +seed: 17 + +num_clients: 100 +num_rounds: 100 +clients_per_round: 10 +num_epochs: 1 +batch_size: 10 +state_path: ./client_states/ +server_device: cuda +client_device: cuda + +algorithm: fedper +# fedavg in future + +client_resources: + num_cpus: 2 + num_gpus: 0.1 + +dataset_config: + name: MNIST + num_classes: 10 + shard_size: 300 + + data_seed: ${seed} + +model: + _target_: fedpara.models.FC + num_classes: ${dataset_config.num_classes} + hidden_size: 200 + +hyperparams: + eta_l: 0.05 + learning_decay: 0 + +strategy: + _target_: flwr.server.strategy.FedAvg + fraction_fit: 0.00001 + fraction_evaluate: 0.00001 + min_evaluate_clients: ${clients_per_round} + min_fit_clients: ${clients_per_round} + min_available_clients: ${clients_per_round} + + +exp_id: ${algorithm}_${dataset_config.name} diff --git a/baselines/fedpara/fedpara/conf/mnist_pfedpara.yaml b/baselines/fedpara/fedpara/conf/mnist_pfedpara.yaml new file mode 100644 index 000000000000..5733397def0f --- /dev/null +++ b/baselines/fedpara/fedpara/conf/mnist_pfedpara.yaml @@ -0,0 +1,41 @@ +--- +seed: 17 + +num_clients: 100 +num_rounds: 100 +clients_per_round: 10 +num_epochs: 5 +batch_size: 10 +state_path: ./client_states/ +server_device: cuda +algorithm: pFedpara + +client_resources: + num_cpus: 2 + num_gpus: 0.1 + +dataset_config: + name: MNIST + num_classes: 10 + shard_size: 300 + +model: + _target_: fedpara.models.FC + num_classes: ${dataset_config.num_classes} + param_type: lowrank # lowrank or standard + ratio: 0.5 # lowrank ratio + hidden_size: 200 + +hyperparams: + eta_l: 0.01 + learning_decay: 0.999 + +strategy: + _target_: flwr.server.strategy.FedAvg + fraction_fit: 0.00001 + fraction_evaluate: 0.00001 + min_evaluate_clients: ${clients_per_round} + min_fit_clients: ${clients_per_round} + min_available_clients: ${clients_per_round} + +exp_id: ${algorithm}_${dataset_config.name}_${model.param_type}_${model.ratio} diff --git a/baselines/fedpara/fedpara/dataset.py b/baselines/fedpara/fedpara/dataset.py new file mode 100644 index 000000000000..c76a75d982f6 --- /dev/null +++ b/baselines/fedpara/fedpara/dataset.py @@ -0,0 +1,139 @@ +"""Dataset loading and processing utilities.""" + +import pickle +from typing import List, Tuple + +from torch.utils.data import DataLoader +from torchvision import datasets, transforms + +from fedpara.dataset_preparation import ( + DatasetSplit, + iid, + noniid, + noniid_partition_loader, +) + + +def load_datasets( + config, num_clients, batch_size +) -> Tuple[List[DataLoader], DataLoader]: + """Load the dataset and return the dataloaders for the clients and the server.""" + print("Loading data...") + match config["name"]: + case "CIFAR10": + Dataset = datasets.CIFAR10 + case "CIFAR100": + Dataset = datasets.CIFAR100 + case "MNIST": + Dataset = datasets.MNIST + case _: + raise NotImplementedError + data_directory = f"./data/{config['name'].lower()}/" + match config["name"]: + case "CIFAR10" | "CIFAR100": + ds_path = f"{data_directory}train_{num_clients}_{config.alpha:.2f}.pkl" + transform_train = transforms.Compose( + [ + transforms.RandomCrop(32, padding=4), + transforms.RandomHorizontalFlip(), + transforms.ToTensor(), + transforms.Normalize( + (0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010) + ), + ] + ) + transform_test = transforms.Compose( + [ + transforms.ToTensor(), + transforms.Normalize( + (0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010) + ), + ] + ) + try: + with open(ds_path, "rb") as file: + train_datasets = pickle.load(file).values() + dataset_train = Dataset( + data_directory, + train=True, + download=False, + transform=transform_train, + ) + dataset_test = Dataset( + data_directory, + train=False, + download=False, + transform=transform_test, + ) + except FileNotFoundError: + dataset_train = Dataset( + data_directory, train=True, download=True, transform=transform_train + ) + if config.partition == "iid": + train_datasets = iid(dataset_train, num_clients) + else: + train_datasets, _ = noniid(dataset_train, num_clients, config.alpha) + pickle.dump(train_datasets, open(ds_path, "wb")) + train_datasets = train_datasets.values() + dataset_test = Dataset( + data_directory, train=False, download=True, transform=transform_test + ) + + case "MNIST": + ds_path = f"{data_directory}train_{num_clients}.pkl" + transform_train = transforms.Compose( + [ + transforms.ToTensor(), + transforms.Normalize((0.1307,), (0.3081,)), + ] + ) + transform_test = transforms.Compose( + [transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))] + ) + try: + train_datasets = pickle.load(open(ds_path, "rb")) + dataset_train = Dataset( + data_directory, + train=True, + download=False, + transform=transform_train, + ) + dataset_test = Dataset( + data_directory, + train=False, + download=False, + transform=transform_test, + ) + + except FileNotFoundError: + dataset_train = Dataset( + data_directory, train=True, download=True, transform=transform_train + ) + train_datasets = noniid_partition_loader( + dataset_train, + m_per_shard=config.shard_size, + n_shards_per_client=len(dataset_train) // (config.shard_size * 100), + ) + pickle.dump(train_datasets, open(ds_path, "wb")) + dataset_test = Dataset( + data_directory, train=False, download=True, transform=transform_test + ) + train_loaders = [ + DataLoader(x, batch_size=batch_size, shuffle=True) + for x in train_datasets + ] + test_loader = DataLoader(dataset_test, batch_size=batch_size, num_workers=2) + return train_loaders, test_loader + + test_loader = DataLoader(dataset_test, batch_size=batch_size, num_workers=2) + train_loaders = [ + DataLoader( + DatasetSplit(dataset_train, ids), + batch_size=batch_size, + shuffle=True, + num_workers=2, + ) + for ids in train_datasets + ] + + return train_loaders, test_loader diff --git a/baselines/fedpara/fedpara/dataset_preparation.py b/baselines/fedpara/fedpara/dataset_preparation.py new file mode 100644 index 000000000000..2f3922e97cef --- /dev/null +++ b/baselines/fedpara/fedpara/dataset_preparation.py @@ -0,0 +1,160 @@ +"""Handle the dataset partitioning and (optionally) complex downloads. + +Please add here all the necessary logic to either download, uncompress, pre/post-process +your dataset (or all of the above). If the desired way of running your baseline is to +first download the dataset and partition it and then run the experiments, please +uncomment the lines below and tell us in the README.md (see the "Running the Experiment" +block) that this file should be executed first. +""" + +import random +from collections import defaultdict + +import numpy as np +import torch +from torch.utils.data import Dataset + + +class DatasetSplit(Dataset): + """An abstract Dataset class wrapped around Pytorch Dataset class.""" + + def __init__(self, dataset, idxs): + self.dataset = dataset + self.targets = dataset.targets + self.idxs = list(idxs) + + def __len__(self): + """Return number of images.""" + return len(self.idxs) + + def __getitem__(self, item): + """Return a transformed example of the dataset.""" + image, label = self.dataset[self.idxs[item]] + return image, label + + +def iid(dataset, num_users): + """Sample I.I.D. clients data from a dataset. + + Args: + dataset: dataset object + num_users: number of users + Returns: + dict of image index + """ + num_items = int(len(dataset) / num_users) + dict_users, all_idxs = {}, list(range(len(dataset))) + for i in range(num_users): + dict_users[i] = set(np.random.choice(all_idxs, num_items, replace=False)) + all_idxs = list(set(all_idxs) - dict_users[i]) + return dict_users + + +# pylint: disable=too-many-locals +def noniid(dataset, no_participants, alpha=0.5): + """Sample non-I.I.D client data from dataset. + + Args: + dataset: dataset object + no_participants: number of users + alpha: float parameter for dirichlet distribution + Returns: + dict of image index + Requires: + cifar_classes, a preprocessed class-indice dictionary. + Sample Method: take a uniformly sampled 10/100-dimension vector + as parameters for dirichlet distribution to sample number of + images in each class. + """ + np.random.seed(666) + random.seed(666) + cifar_classes = {} + for ind, x in enumerate(dataset): + _, label = x + if label in cifar_classes: + cifar_classes[label].append(ind) + else: + cifar_classes[label] = [ind] + + per_participant_list = defaultdict(list) + no_classes = len(cifar_classes.keys()) + class_size = len(cifar_classes[0]) + datasize = {} + for n in range(no_classes): + random.shuffle(cifar_classes[n]) + sampled_probabilities = class_size * np.random.dirichlet( + np.array(no_participants * [alpha]) + ) + for user in range(no_participants): + no_imgs = int(round(sampled_probabilities[user])) + datasize[user, n] = no_imgs + sampled_list = cifar_classes[n][: min(len(cifar_classes[n]), no_imgs)] + per_participant_list[user].extend(sampled_list) + cifar_classes[n] = cifar_classes[n][min(len(cifar_classes[n]), no_imgs) :] + train_img_size = np.zeros(no_participants) + for i in range(no_participants): + train_img_size[i] = sum([datasize[i, j] for j in range(no_classes)]) + clas_weight = np.zeros((no_participants, no_classes)) + for i in range(no_participants): + for j in range(no_classes): + clas_weight[i, j] = float(datasize[i, j]) / float((train_img_size[i])) + return per_participant_list, clas_weight + + +def data_to_tensor(data): + """Load dataset to memory, applies transform.""" + loader = torch.utils.data.DataLoader(data, batch_size=len(data)) + img, label = next(iter(loader)) + return img, label + + +def noniid_partition_loader(data, m_per_shard=300, n_shards_per_client=2): + """Partition in semi-pathological fashion. + + 1. sort examples by label, form shards of size 300 by grouping points + successively + 2. each client is 2 random shards + most clients will have 2 digits, at most 4. + """ + # load data into memory + img, label = data_to_tensor(data) + + # sort + idx = torch.argsort(label) + img = img[idx] + label = label[idx] + + # split into n_shards of size m_per_shard + m = len(data) + assert m % m_per_shard == 0 + n_shards = m // m_per_shard + shards_idx = [ + torch.arange(m_per_shard * i, m_per_shard * (i + 1)) for i in range(n_shards) + ] + random.shuffle(shards_idx) # shuffle shards + + # pick shards to create a dataset for each client + assert n_shards % n_shards_per_client == 0 + n_clients = n_shards // n_shards_per_client + client_data = [ + torch.utils.data.TensorDataset( + torch.cat( + [ + img[shards_idx[j]] + for j in range( + i * n_shards_per_client, (i + 1) * n_shards_per_client + ) + ] + ), + torch.cat( + [ + label[shards_idx[j]] + for j in range( + i * n_shards_per_client, (i + 1) * n_shards_per_client + ) + ] + ), + ) + for i in range(n_clients) + ] + return client_data diff --git a/baselines/fedpara/fedpara/main.py b/baselines/fedpara/fedpara/main.py new file mode 100644 index 000000000000..2397a20e17ef --- /dev/null +++ b/baselines/fedpara/fedpara/main.py @@ -0,0 +1,124 @@ +"""Main script for running FedPara.""" + +from typing import Dict + +import flwr as fl +import hydra +from flwr.common import Scalar +from hydra.core.hydra_config import HydraConfig +from hydra.utils import instantiate +from omegaconf import DictConfig, OmegaConf + +from fedpara import client, server, utils +from fedpara.dataset import load_datasets +from fedpara.server import weighted_average +from fedpara.utils import ( + get_parameters, + save_results_as_pickle, + seed_everything, + set_client_state_save_path, +) + + +@hydra.main(config_path="conf", config_name="cifar10", version_base=None) +def main(cfg: DictConfig) -> None: + """Run the baseline. + + Parameters + ---------- + cfg : DictConfig + An omegaconf object that stores the hydra config. + """ + # 1. Print parsed config + print(OmegaConf.to_yaml(cfg)) + seed_everything(cfg.seed) + OmegaConf.to_container(cfg, resolve=True) + if "state_path" in cfg: + state_path = set_client_state_save_path(cfg.state_path) + else: + state_path = None + + # 2. Prepare dataset + train_loaders, test_loader = load_datasets( + config=cfg.dataset_config, + num_clients=cfg.num_clients, + batch_size=cfg.batch_size, + ) + + # 3. Define clients + # In this scheme the responsability of choosing the client is on the client manager + + client_fn = client.gen_client_fn( + train_loaders=train_loaders, + test_loader=test_loader, + model=cfg.model, + num_epochs=cfg.num_epochs, + args={"algorithm": cfg.algorithm}, + state_path=state_path, + ) + + def get_on_fit_config(): + def fit_config_fn(server_round: int): + fit_config: Dict[str, Scalar] = OmegaConf.to_container( + cfg.hyperparams, resolve=True + ) # type: ignore + fit_config["curr_round"] = server_round + return fit_config + + return fit_config_fn + + net_glob = instantiate(cfg.model) + + # 4. Define strategy + if cfg.strategy.min_evaluate_clients: + strategy = instantiate( + cfg.strategy, + on_fit_config_fn=get_on_fit_config(), + initial_parameters=fl.common.ndarrays_to_parameters( + get_parameters(net_glob) + ), + evaluate_metrics_aggregation_fn=weighted_average, + ) + + else: + evaluate_fn = server.gen_evaluate_fn( + num_clients=cfg.num_clients, + test_loader=test_loader, + model=cfg.model, + device=cfg.server_device, + ) + strategy = instantiate( + cfg.strategy, + evaluate_fn=evaluate_fn, + on_fit_config_fn=get_on_fit_config(), + initial_parameters=fl.common.ndarrays_to_parameters( + get_parameters(net_glob) + ), + ) + + # 5. Start Simulation + history = fl.simulation.start_simulation( + client_fn=client_fn, + num_clients=cfg.num_clients, + config=fl.server.ServerConfig(num_rounds=cfg.num_rounds), + strategy=strategy, + client_resources=cfg.client_resources, + ) + save_path = HydraConfig.get().runtime.output_dir + + save_results_as_pickle(history, file_path=save_path) + + # 6. Save results + file_suffix = "_".join([(net_glob).__class__.__name__, f"{cfg.exp_id}"]) + + utils.plot_metric_from_history( + hist=history, + save_plot_path=save_path, + suffix=file_suffix, + cfg=cfg, + model_size=net_glob.model_size[1], + ) + + +if __name__ == "__main__": + main() diff --git a/baselines/fedpara/fedpara/models.py b/baselines/fedpara/fedpara/models.py new file mode 100644 index 000000000000..370720ff58ce --- /dev/null +++ b/baselines/fedpara/fedpara/models.py @@ -0,0 +1,478 @@ +"""Model definitions for FedPara.""" + +import math +from typing import Dict, Tuple + +import numpy as np +import torch +import torch.nn.functional as F +from flwr.common import Scalar +from torch import nn +from torch.nn import init +from torch.utils.data import DataLoader + + +class LowRankNN(nn.Module): + """Fedpara Low-rank weight systhesis for fully connected layer.""" + + def __init__(self, input_, output, rank) -> None: + super().__init__() + + self.X = nn.Parameter( + torch.empty(size=(input_, rank)), + requires_grad=True, + ) + self.Y = nn.Parameter(torch.empty(size=(output, rank)), requires_grad=True) + + init.kaiming_normal_(self.X, mode="fan_out", nonlinearity="relu") + init.kaiming_normal_(self.Y, mode="fan_out", nonlinearity="relu") + + def forward(self): + """Forward pass.""" + out = torch.einsum("yr,xr->yx", self.Y, self.X) + return out + + +class Linear(nn.Module): + """Low-rank fully connected layer module for personalized scheme.""" + + def __init__(self, input_, output, ratio, bias=True) -> None: + super().__init__() + rank = self._calc_from_ratio(ratio, input_, output) + self.w1 = LowRankNN(input_, output, rank) + self.w2 = LowRankNN(input_, output, rank) + # make the bias for each layer + if bias: + self.bias = nn.Parameter(torch.zeros(output)) + + @staticmethod + def _calc_from_ratio(ratio, input_, output): + # Return the low-rank of sub-matrices given the compression ratio + # minimum possible parameter + r1 = int(np.ceil(np.sqrt(output))) + r2 = int(np.ceil(np.sqrt(input_))) + r = np.min((r1, r2)) + # maximum possible rank + # To solve it we need to know the roots of quadratic equation: 2*r*(m+n)=m*n + r3 = math.floor((output * input_) / (2 * (output + input_))) + rank = math.ceil((1 - ratio) * r + ratio * r3) + return rank + + def forward(self, x): + """Forward pass.""" + # personalized + w = self.w1() * self.w2() + self.w1() + out = F.linear(x, w, self.bias) + return out + + +class FC(nn.Module): + """2NN Fully connected layer as in the paper: https://arxiv.org/abs/1602.05629.""" + + def __init__( # pylint: disable=too-many-arguments + self, + input_size=28**2, + hidden_size=200, + num_classes=10, + ratio=0.5, + param_type="standard", + ): + super().__init__() + self.input_size = input_size + if param_type == "standard": + self.fc1 = nn.Linear(input_size, hidden_size) + self.fc2 = nn.Linear(hidden_size, 256) + self.out = nn.Linear(256, num_classes) + + elif param_type == "lowrank": + self.fc1 = Linear(input_size, hidden_size, ratio) + self.fc2 = Linear(hidden_size, 256, ratio) + self.out = Linear(256, num_classes, ratio) + + else: + raise ValueError("param_type must be either standard or lowrank") + + @property + def model_size(self): + """Return the total number of trainable parameters (in million paramaters) and. + + the size of the model in MB. + """ + total_trainable_params = ( + sum(p.numel() for p in self.parameters() if p.requires_grad) / 1e6 + ) + param_size = 0 + for param in self.parameters(): + param_size += param.nelement() * param.element_size() + buffer_size = 0 + for buffer in self.buffers(): + buffer_size += buffer.nelement() * buffer.element_size() + size_all_mb = (param_size + buffer_size) / 1024**2 + return total_trainable_params, size_all_mb + + def forward(self, x): + """Forward pass.""" + x = x.view(-1, self.input_size) + x = F.relu(self.fc1(x)) + x = F.relu(self.fc2(x)) + x = self.out(x) + return x + + +class LowRank(nn.Module): + """Fedpara Low-rank weight systhesis for Convolution layer.""" + + def __init__( # pylint: disable=too-many-arguments + self, + in_channels: int, + out_channels: int, + low_rank: int, + kernel_size: int, + ): + super().__init__() + self.T = nn.Parameter( + torch.empty(size=(low_rank, low_rank, kernel_size, kernel_size)), + requires_grad=True, + ) + self.X = nn.Parameter( + torch.empty(size=(low_rank, out_channels)), requires_grad=True + ) + self.Y = nn.Parameter( + torch.empty(size=(low_rank, in_channels)), requires_grad=True + ) + init.kaiming_normal_(self.T, mode="fan_out", nonlinearity="relu") + init.kaiming_normal_(self.X, mode="fan_out", nonlinearity="relu") + init.kaiming_normal_(self.Y, mode="fan_out", nonlinearity="relu") + + def forward(self): + """Forward pass.""" + # torch.einsum simplify the tensor produce (matrix multiplication) + return torch.einsum("xyzw,xo,yi->oizw", self.T, self.X, self.Y) + + +# pylint: disable=too-many-instance-attributes +class Conv2d(nn.Module): + """Convolutional layer with low-rank weights.""" + + def __init__( # pylint: disable=too-many-arguments + self, + in_channels: int, + out_channels: int, + kernel_size: int = 3, + stride: int = 1, + padding: int = 0, + bias: bool = False, + ratio: float = 0.1, + add_nonlinear: bool = False, + ): + super().__init__() + self.in_channels = in_channels + self.out_channels = out_channels + self.kernel_size = kernel_size + self.stride = stride + self.padding = padding + self.bias = bias + self.ratio = ratio + self.low_rank = self._calc_from_ratio() + self.add_nonlinear = add_nonlinear + self.W1 = LowRank(in_channels, out_channels, self.low_rank, kernel_size) + self.W2 = LowRank(in_channels, out_channels, self.low_rank, kernel_size) + self.bias = nn.Parameter(torch.zeros(out_channels)) if bias else None + self.tanh = nn.Tanh() + + def _calc_from_ratio(self): + # Return the low-rank of sub-matrices given the compression ratio + + # minimum possible parameter + r1 = int(np.ceil(np.sqrt(self.out_channels))) + r2 = int(np.ceil(np.sqrt(self.in_channels))) + r = np.min((r1, r2)) + + # maximum possible rank, + # To solve it we need to know the roots of quadratic equation: ax^2+bx+c=0 + # a = kernel**2 + # b = out channel+ in channel + # c = - num_target_params/2 + # r3 is floored because we cannot take the ceil as it results a bigger number + # of parameters than the original problem + + num_target_params = ( + self.out_channels * self.in_channels * (self.kernel_size**2) + ) + a, b, c = ( + self.kernel_size**2, + self.out_channels + self.in_channels, + -num_target_params / 2, + ) + discriminant = b**2 - 4 * a * c + r3 = math.floor((-b + math.sqrt(discriminant)) / (2 * a)) + ratio = math.ceil((1 - self.ratio) * r + self.ratio * r3) + return ratio + + def forward(self, x): + """Forward pass.""" + # Hadamard product of two submatrices + if self.add_nonlinear: + W = self.tanh(self.W1()) * self.tanh(self.W2()) + else: + W = self.W1() * self.W2() + out = F.conv2d( + input=x, weight=W, bias=self.bias, stride=self.stride, padding=self.padding + ) + return out + + +# pylint: disable=too-many-instance-attributes +class VGG(nn.Module): + """VGG16GN model.""" + + def __init__( # pylint: disable=too-many-arguments + self, + num_classes, + num_groups=2, + ratio=0.1, + param_type="lowrank", + add_nonlinear=False, + ): + super().__init__() + self.param_type = param_type + self.num_groups = num_groups + self.num_classes = num_classes + self.ratio = ratio + self.add_nonlinear = add_nonlinear + self.features = self._make_layers( + [ + 64, + 64, + "M", + 128, + 128, + "M", + 256, + 256, + 256, + "M", + 512, + 512, + 512, + "M", + 512, + 512, + 512, + "M", + ] + ) + self.classifier = nn.Sequential( + nn.Dropout(), + nn.Linear(512, 512), + nn.ReLU(inplace=True), + nn.Dropout(), + nn.Linear(512, 512), + nn.ReLU(inplace=True), + nn.Linear(512, num_classes), + ) + self._init_weights() + + def _init_weights(self): + """Initialize the weights.""" + for name, module in self.features.named_children(): + module = getattr(self.features, name) + if isinstance(module, nn.Conv2d): + if self.param_type == "lowrank": + num_channels = module.in_channels + setattr( + self.features, + name, + Conv2d( + num_channels, + module.out_channels, + module.kernel_size[0], + module.stride[0], + module.padding[0], + module.bias is not None, + ratio=self.ratio, + add_nonlinear=self.add_nonlinear, + # send the activation function to the Conv2d class + ), + ) + elif self.param_type == "standard": + n = ( + module.kernel_size[0] + * module.kernel_size[1] + * module.out_channels + ) + module.weight.data.normal_(0, math.sqrt(2.0 / n)) + module.bias.data.zero_() + + def _make_layers(self, cfg, group_norm=True): + layers = [] + in_channels = 3 + for v in cfg: + if v == "M": + layers += [nn.MaxPool2d(kernel_size=2, stride=2)] + else: + conv2d = nn.Conv2d(in_channels, v, kernel_size=3, padding=1) + if group_norm: + layers += [ + conv2d, + nn.GroupNorm(self.num_groups, v), + nn.ReLU(inplace=True), + ] + else: + layers += [conv2d, nn.ReLU(inplace=True)] + in_channels = v + return nn.Sequential(*layers) + + @property + def model_size(self): + """Return the total number of trainable parameters (in million paramaters) and. + + the size of the model in MB. + """ + total_trainable_params = ( + sum(p.numel() for p in self.parameters() if p.requires_grad) / 1e6 + ) + param_size = 0 + for param in self.parameters(): + param_size += param.nelement() * param.element_size() + buffer_size = 0 + for buffer in self.buffers(): + buffer_size += buffer.nelement() * buffer.element_size() + size_all_mb = (param_size + buffer_size) / 1024**2 + return total_trainable_params, size_all_mb + + def forward(self, x): + """Forward pass.""" + x = self.features(x) + x = x.view(x.size(0), -1) + x = self.classifier(x) + return x + + +# Create an instance of the VGG16GN model with Group Normalization, +# custom Conv2d, and modified classifier +def test( + net: nn.Module, test_loader: DataLoader, device: torch.device +) -> Tuple[float, float]: + """Evaluate the network on the entire test set. + + Parameters + ---------- + net : nn.Module + The neural network to test. + test_loader : DataLoader + The DataLoader containing the data to test the network on. + device : torch.device + The device on which the model should be tested, either 'cpu' or 'cuda'. + + Returns + ------- + Tuple[float, float] + The loss and the accuracy of the input model on the given data. + """ + if len(test_loader.dataset) == 0: + raise ValueError("Testloader can't be 0, exiting...") + + criterion = torch.nn.CrossEntropyLoss() + correct, total, loss = 0, 0, 0.0 + net.eval() + with torch.no_grad(): + for images, labels in test_loader: + images, labels = images.to(device), labels.to(device) + outputs = net(images) + loss += criterion(outputs, labels).item() + _, predicted = torch.max(outputs.data, 1) + total += labels.size(0) + correct += (predicted == labels).sum().item() + loss /= len(test_loader.dataset) + accuracy = correct / total + return loss, accuracy + + +def train( # pylint: disable=too-many-arguments + net: nn.Module, + trainloader: DataLoader, + device: torch.device, + epochs: int, + hyperparams: Dict[str, Scalar], + epoch: int, +) -> None: + """Train the network on the training set. + + Parameters + ---------- + net : nn.Module + The neural network to train. + trainloader : DataLoader + The DataLoader containing the data to train the network on. + device : torch.device + The device on which the model should be trained, either 'cpu' or 'cuda'. + epochs : int + The number of epochs the model should be trained for. + hyperparams : Dict[str, Scalar] + The hyperparameters to use for training. + """ + lr = float(hyperparams["eta_l"]) * float(hyperparams["learning_decay"]) ** ( + epoch - 1 + ) + criterion = torch.nn.CrossEntropyLoss() + optimizer = torch.optim.SGD( + net.parameters(), + lr=lr, + momentum=0, + weight_decay=0, + ) + net.train() + for _ in range(epochs): + net = _train_one_epoch( + net=net, + trainloader=trainloader, + device=device, + criterion=criterion, + optimizer=optimizer, + ) + + +def _train_one_epoch( # pylint: disable=too-many-arguments + net: nn.Module, + trainloader: DataLoader, + device: torch.device, + criterion, + optimizer, +) -> nn.Module: + """Train for one epoch. + + Parameters + ---------- + net : nn.Module + The neural network to train. + trainloader : DataLoader + The DataLoader containing the data to train the network on. + device : torch.device + The device on which the model should be trained, either 'cpu' or 'cuda'. + criterion : + The loss function to use for training + optimizer : + The optimizer to use for training + hyperparams : Dict[str, Scalar] + The hyperparameters to use for training. + + Returns + ------- + nn.Module + The model that has been trained for one epoch. + """ + for images, labels in trainloader: + images, labels = images.to(device), labels.to(device) + net.zero_grad() + log_probs = net(images) + loss = criterion(log_probs, labels) + loss.backward() + optimizer.step() + return net + + +if __name__ == "__main__": + model = VGG(num_classes=10, num_groups=2, param_type="standard", ratio=0.4) + # Print the modified VGG16GN model architecture + print(model.model_size) diff --git a/baselines/fedpara/fedpara/server.py b/baselines/fedpara/fedpara/server.py new file mode 100644 index 000000000000..036efa090c52 --- /dev/null +++ b/baselines/fedpara/fedpara/server.py @@ -0,0 +1,77 @@ +"""Global evaluation function.""" + +from collections import OrderedDict +from typing import Callable, Dict, List, Optional, Tuple + +import torch +from flwr.common import Metrics, NDArrays, Scalar +from hydra.utils import instantiate +from omegaconf import DictConfig +from torch.utils.data import DataLoader + +from fedpara.models import test + + +def get_on_fit_config(hypearparams: Dict): + """Generate fit config function.""" + + def fit_config_fn(server_round: int): + hypearparams["curr_round"] = server_round + return hypearparams + + return fit_config_fn + + +def gen_evaluate_fn( + num_clients: int, + test_loader: DataLoader, + model: DictConfig, + device, +) -> Callable[ + [int, NDArrays, Dict[str, Scalar]], Optional[Tuple[float, Dict[str, Scalar]]] +]: + """Generate a centralized evaluation function. + + Parameters + ---------- + model: DictConfig + The model details to evaluate. + test_loader : DataLoader + The dataloader to test the model with. + device : torch.device + The device to test the model on. + + Returns + ------- + Callable[ [int, NDArrays, Dict[str, Scalar]], + Optional[Tuple[float, Dict[str, Scalar]]] ] + The centralized evaluation function. + """ + + # pylint: disable=unused-argument + def evaluate( + server_round, + parameters_ndarrays: NDArrays, + __, + ) -> Optional[Tuple[float, Dict[str, Scalar]]]: + """Use the entire CIFAR-10/100 test set for evaluation.""" + net = instantiate(model) + params_dict = zip(net.state_dict().keys(), parameters_ndarrays) + state_dict = OrderedDict({k: torch.Tensor(v) for k, v in params_dict}) + net.load_state_dict(state_dict, strict=True) + net.to(device) + + loss, accuracy = test(net, test_loader, device=device) + return loss, {"accuracy": accuracy} + + return evaluate + + +def weighted_average(metrics: List[Tuple[int, Metrics]]) -> Metrics: + """Do weighted average of metrics.""" + # Multiply accuracy of each client by number of examples used + accuracies = [float(num_examples * m["accuracy"]) for num_examples, m in metrics] + examples = [num_examples for num_examples, _ in metrics] + print(f"accuracies: {sum(accuracies) / sum(examples)}") + # Aggregate and return custom metric (weighted average) + return {"accuracy": sum(accuracies) / sum(examples)} diff --git a/baselines/fedpara/fedpara/strategy.py b/baselines/fedpara/fedpara/strategy.py new file mode 100644 index 000000000000..17436c401c30 --- /dev/null +++ b/baselines/fedpara/fedpara/strategy.py @@ -0,0 +1,5 @@ +"""Optionally define a custom strategy. + +Needed only when the strategy is not yet implemented in Flower or because you want to +extend or modify the functionality of an existing strategy. +""" diff --git a/baselines/fedpara/fedpara/utils.py b/baselines/fedpara/fedpara/utils.py new file mode 100644 index 000000000000..fcaf95f50c59 --- /dev/null +++ b/baselines/fedpara/fedpara/utils.py @@ -0,0 +1,161 @@ +"""Utility functions for FedPara.""" + +import os +import pickle +import random +import time +from pathlib import Path +from secrets import token_hex +from typing import List, Optional + +import matplotlib.pyplot as plt +import numpy as np +import torch +from flwr.common import NDArrays +from flwr.server import History +from omegaconf import DictConfig +from torch.nn import Module + + +def plot_metric_from_history( + hist: History, + save_plot_path: str, + model_size: float, + cfg: DictConfig, + suffix: str = "", +) -> None: + """Plot the metrics from the history of the server. + + Parameters + ---------- + hist : History + Object containing evaluation for all rounds. + save_plot_path : str + Folder to save the plot to. + model_size : float + Size of the model in MB. + cfg : Optional + Optional dictionary containing the configuration of the experiment. + suffix: Optional + Optional string to add at the end of the filename for the plot. + """ + metric_dict = ( + hist.metrics_centralized + if hist.metrics_centralized + else hist.metrics_distributed + ) + _, axs = plt.subplots() + rounds, values_accuracy = zip(*metric_dict["accuracy"]) + r_cc = (i * 2 * model_size * int(cfg.clients_per_round) / 1024 for i in rounds) + + # Set the title + # make the suffix space seperated not underscore seperated + title = " ".join(suffix.split("_")) + axs.set_title(title) + axs.grid(True) + axs.plot(np.asarray([*r_cc]), np.asarray(values_accuracy)) + axs.set_ylabel("Accuracy") + axs.set_xlabel("Communication Cost (GB)") + fig_name = suffix + ".png" + plt.savefig(Path(save_plot_path) / Path(fig_name)) + plt.close() + + +def seed_everything(seed): + """Seed everything for reproducibility.""" + np.random.seed(seed) + torch.manual_seed(seed) + random.seed(seed) + torch.backends.cudnn.deterministic = True + + +def get_parameters(net: Module) -> NDArrays: + """Get the parameters of the network.""" + return [val.cpu().numpy() for _, val in net.state_dict().items()] + + +def save_results_as_pickle( + history: History, + file_path: str, + default_filename: Optional[str] = "history.pkl", +) -> None: + """Save results from simulation to pickle. + + Parameters + ---------- + history: History + History returned by start_simulation. + file_path: Union[str, Path] + Path to file to create and store both history and extra_results. + If path is a directory, the default_filename will be used. + path doesn't exist, it will be created. If file exists, a + randomly generated suffix will be added to the file name. This + is done to avoid overwritting results. + extra_results : Optional[Dict] + A dictionary containing additional results you would like + to be saved to disk. Default: {} (an empty dictionary) + default_filename: Optional[str] + File used by default if file_path points to a directory instead + to a file. Default: "results.pkl" + """ + path = Path(file_path) + + # ensure path exists + path.mkdir(exist_ok=True, parents=True) + + def _add_random_suffix(path_: Path): + """Add a random suffix to the file name.""" + print(f"File `{path_}` exists! ") + suffix = token_hex(4) + print(f"New results to be saved with suffix: {suffix}") + return path_.parent / (path_.stem + "_" + suffix + ".pkl") + + def _complete_path_with_default_name(path_: Path): + """Append the default file name to the path.""" + print("Using default filename") + if default_filename is None: + return path_ + return path_ / default_filename + + if path.is_dir(): + path = _complete_path_with_default_name(path) + + if path.is_file(): + path = _add_random_suffix(path) + + print(f"Results will be saved into: {path}") + # data = {"history": history, **extra_results} + data = {"history": history} + # save results to pickle + with open(str(path), "wb") as handle: + pickle.dump(data, handle, protocol=pickle.HIGHEST_PROTOCOL) + + +def set_client_state_save_path(path: str) -> str: + """Set the client state save path.""" + client_state_save_path = time.strftime("%Y-%m-%d") + client_state_sub_path = time.strftime("%H-%M-%S") + client_state_save_path = f"{path}{client_state_save_path}/{client_state_sub_path}" + if not os.path.exists(client_state_save_path): + os.makedirs(client_state_save_path) + return client_state_save_path + + +def get_keys_state_dict(model, algorithm, mode: str = "local") -> List[str]: + """.""" + keys: List[str] = [] + match algorithm: + case "fedper": + if mode == "local": + keys = list(filter(lambda x: "fc1" not in x, model.state_dict().keys())) + elif mode == "global": + keys = list(filter(lambda x: "fc1" in x, model.state_dict().keys())) + case "pfedpara": + if mode == "local": + keys = list(filter(lambda x: "w2" in x, model.state_dict().keys())) + elif mode == "global": + keys = list(filter(lambda x: "w1" in x, model.state_dict().keys())) + case _: + raise NotImplementedError(f"algorithm {algorithm} not implemented") + + return keys diff --git a/baselines/fedpara/pyproject.toml b/baselines/fedpara/pyproject.toml new file mode 100644 index 000000000000..c5751c536043 --- /dev/null +++ b/baselines/fedpara/pyproject.toml @@ -0,0 +1,142 @@ +[build-system] +requires = ["poetry-core>=1.4.0"] +build-backend = "poetry.masonry.api" + +[tool.poetry] +name = "fedpara" # <----- Ensure it matches the name of your baseline directory containing all the source code +version = "1.0.0" +description = "Flower Baselines" +license = "Apache-2.0" +authors = ["Yahia Salaheldin Shaaban ", "Omar Mokhtar < >", "Roeia Amr < >"] +readme = "README.md" +homepage = "https://flower.dev" +repository = "https://github.com/adap/flower" +documentation = "https://flower.dev" +classifiers = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: Apache Software License", + "Operating System :: MacOS :: MacOS X", + "Operating System :: POSIX :: Linux", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: Implementation :: CPython", + "Topic :: Scientific/Engineering", + "Topic :: Scientific/Engineering :: Artificial Intelligence", + "Topic :: Scientific/Engineering :: Mathematics", + "Topic :: Software Development", + "Topic :: Software Development :: Libraries", + "Topic :: Software Development :: Libraries :: Python Modules", + "Typing :: Typed", +] + +[tool.poetry.dependencies] +python = ">=3.10, <3.12.0" # don't change this +flwr = { extras = ["simulation"], version = "1.5.0" } +hydra-core = "1.3.2" # don't change this +matplotlib = "^3.7.2" +tqdm = "^4.66.1" +torch = {url = "https://download.pytorch.org/whl/cu117/torch-2.0.1%2Bcu117-cp310-cp310-linux_x86_64.whl"} +torchvision = { url = "https://download.pytorch.org/whl/cu117/torchvision-0.15.2%2Bcu117-cp310-cp310-linux_x86_64.whl"} + +[tool.poetry.dev-dependencies] +isort = "==5.11.5" +black = "==23.1.0" +docformatter = "==1.5.1" +mypy = "==1.4.1" +pylint = "==2.8.2" +flake8 = "==3.9.2" +pytest = "==6.2.4" +pytest-watch = "==4.2.0" +ruff = "==0.0.272" +types-requests = "==2.27.7" +virtualenv = "20.21.0" + +[tool.isort] +line_length = 88 +indent = " " +multi_line_output = 3 +include_trailing_comma = true +force_grid_wrap = 0 +use_parentheses = true + +[tool.black] +line-length = 88 +target-version = ["py38", "py39", "py310", "py311"] + +[tool.pytest.ini_options] +minversion = "6.2" +addopts = "-qq" +testpaths = [ + "flwr_baselines", +] + +[tool.mypy] +ignore_missing_imports = true +strict = false +plugins = "numpy.typing.mypy_plugin" + +[tool.pylint."MESSAGES CONTROL"] +disable = "bad-continuation,duplicate-code,too-few-public-methods,useless-import-alias" +good-names = "i,j,k,_,x,y,X,Y,m,w1,w2,W1,W2,n,r1,r2,r3,W,w,v,lr,f,r,T,a,b,c" +signature-mutators="hydra.main.main" + +[tool.pylint.typecheck] +generated-members="numpy.*, torch.*, tensorflow.*" + +[[tool.mypy.overrides]] +module = [ + "importlib.metadata.*", + "importlib_metadata.*", +] +follow_imports = "skip" +follow_imports_for_stubs = true +disallow_untyped_calls = false + +[[tool.mypy.overrides]] +module = "torch.*" +follow_imports = "skip" +follow_imports_for_stubs = true + +[tool.docformatter] +wrap-summaries = 88 +wrap-descriptions = 88 + +[tool.ruff] +target-version = "py38" +line-length = 88 +select = ["D", "E", "F", "W", "B", "ISC", "C4"] +fixable = ["D", "E", "F", "W", "B", "ISC", "C4"] +ignore = ["B024", "B027"] +exclude = [ + ".bzr", + ".direnv", + ".eggs", + ".git", + ".hg", + ".mypy_cache", + ".nox", + ".pants.d", + ".pytype", + ".ruff_cache", + ".svn", + ".tox", + ".venv", + "__pypackages__", + "_build", + "buck-out", + "build", + "dist", + "node_modules", + "venv", + "proto", +] + +[tool.ruff.pydocstyle] +convention = "numpy" diff --git a/doc/source/ref-changelog.md b/doc/source/ref-changelog.md index f1af015ac24c..685553aee657 100644 --- a/doc/source/ref-changelog.md +++ b/doc/source/ref-changelog.md @@ -24,6 +24,8 @@ - FedAvgM [#2246](https://github.com/adap/flower/pull/2246) + - FedPara [#2722](https://github.com/adap/flower/pull/2722) + ## v1.6.0 (2023-11-28) ### Thanks to our contributors From d472514173ba47dd8931cc9b8cb66f1b8b3692a8 Mon Sep 17 00:00:00 2001 From: mohammadnaseri Date: Thu, 1 Feb 2024 13:36:14 +0000 Subject: [PATCH 070/113] Deprecate legacy DP wrappers (#2749) --- src/py/flwr/client/dpfedavg_numpy_client.py | 9 ++++++++- src/py/flwr/common/dp.py | 4 ++++ src/py/flwr/server/strategy/dpfedavg_adaptive.py | 9 ++++++++- src/py/flwr/server/strategy/dpfedavg_fixed.py | 10 ++++++++-- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/py/flwr/client/dpfedavg_numpy_client.py b/src/py/flwr/client/dpfedavg_numpy_client.py index c39b89b31da3..ab31a289d29b 100644 --- a/src/py/flwr/client/dpfedavg_numpy_client.py +++ b/src/py/flwr/client/dpfedavg_numpy_client.py @@ -22,13 +22,20 @@ from flwr.client.numpy_client import NumPyClient from flwr.common.dp import add_gaussian_noise, clip_by_l2 +from flwr.common.logger import warn_deprecated_feature from flwr.common.typing import Config, NDArrays, Scalar class DPFedAvgNumPyClient(NumPyClient): - """Wrapper for configuring a Flower client for DP.""" + """Wrapper for configuring a Flower client for DP. + + Warning + ------- + This class is deprecated and will be removed in a future release. + """ def __init__(self, client: NumPyClient) -> None: + warn_deprecated_feature("`DPFedAvgNumPyClient` wrapper") super().__init__() self.client = client diff --git a/src/py/flwr/common/dp.py b/src/py/flwr/common/dp.py index 5030ad34805b..83a72b8ce749 100644 --- a/src/py/flwr/common/dp.py +++ b/src/py/flwr/common/dp.py @@ -19,11 +19,13 @@ import numpy as np +from flwr.common.logger import warn_deprecated_feature from flwr.common.typing import NDArrays # Calculates the L2-norm of a potentially ragged array def _get_update_norm(update: NDArrays) -> float: + warn_deprecated_feature("`_get_update_norm` method") flattened_update = update[0] for i in range(1, len(update)): flattened_update = np.append(flattened_update, update[i]) @@ -32,6 +34,7 @@ def _get_update_norm(update: NDArrays) -> float: def add_gaussian_noise(update: NDArrays, std_dev: float) -> NDArrays: """Add iid Gaussian noise to each floating point value in the update.""" + warn_deprecated_feature("`add_gaussian_noise` method") update_noised = [ layer + np.random.normal(0, std_dev, layer.shape) for layer in update ] @@ -40,6 +43,7 @@ def add_gaussian_noise(update: NDArrays, std_dev: float) -> NDArrays: def clip_by_l2(update: NDArrays, threshold: float) -> Tuple[NDArrays, bool]: """Scales the update so thats its L2 norm is upper-bound to threshold.""" + warn_deprecated_feature("`clip_by_l2` method") update_norm = _get_update_norm(update) scaling_factor = min(1, threshold / update_norm) update_clipped: NDArrays = [layer * scaling_factor for layer in update] diff --git a/src/py/flwr/server/strategy/dpfedavg_adaptive.py b/src/py/flwr/server/strategy/dpfedavg_adaptive.py index 8b3278cc9ba0..a908679ed668 100644 --- a/src/py/flwr/server/strategy/dpfedavg_adaptive.py +++ b/src/py/flwr/server/strategy/dpfedavg_adaptive.py @@ -24,6 +24,7 @@ import numpy as np from flwr.common import FitIns, FitRes, Parameters, Scalar +from flwr.common.logger import warn_deprecated_feature from flwr.server.client_manager import ClientManager from flwr.server.client_proxy import ClientProxy from flwr.server.strategy.dpfedavg_fixed import DPFedAvgFixed @@ -31,7 +32,12 @@ class DPFedAvgAdaptive(DPFedAvgFixed): - """Wrapper for configuring a Strategy for DP with Adaptive Clipping.""" + """Wrapper for configuring a Strategy for DP with Adaptive Clipping. + + Warning + ------- + This class is deprecated and will be removed in a future release. + """ # pylint: disable=too-many-arguments,too-many-instance-attributes def __init__( @@ -45,6 +51,7 @@ def __init__( clip_norm_target_quantile: float = 0.5, clip_count_stddev: Optional[float] = None, ) -> None: + warn_deprecated_feature("`DPFedAvgAdaptive` wrapper") super().__init__( strategy=strategy, num_sampled_clients=num_sampled_clients, diff --git a/src/py/flwr/server/strategy/dpfedavg_fixed.py b/src/py/flwr/server/strategy/dpfedavg_fixed.py index f2f1c206f3de..b182ac26cef8 100644 --- a/src/py/flwr/server/strategy/dpfedavg_fixed.py +++ b/src/py/flwr/server/strategy/dpfedavg_fixed.py @@ -17,11 +17,11 @@ Paper: arxiv.org/pdf/1710.06963.pdf """ - from typing import Dict, List, Optional, Tuple, Union from flwr.common import EvaluateIns, EvaluateRes, FitIns, FitRes, Parameters, Scalar from flwr.common.dp import add_gaussian_noise +from flwr.common.logger import warn_deprecated_feature from flwr.common.parameter import ndarrays_to_parameters, parameters_to_ndarrays from flwr.server.client_manager import ClientManager from flwr.server.client_proxy import ClientProxy @@ -29,7 +29,12 @@ class DPFedAvgFixed(Strategy): - """Wrapper for configuring a Strategy for DP with Fixed Clipping.""" + """Wrapper for configuring a Strategy for DP with Fixed Clipping. + + Warning + ------- + This class is deprecated and will be removed in a future release. + """ # pylint: disable=too-many-arguments,too-many-instance-attributes def __init__( @@ -40,6 +45,7 @@ def __init__( noise_multiplier: float = 1, server_side_noising: bool = True, ) -> None: + warn_deprecated_feature("`DPFedAvgFixed` wrapper") super().__init__() self.strategy = strategy # Doing fixed-size subsampling as in https://arxiv.org/abs/1905.03871. From f778253424a7871f5e57721a29b5033d96e12f94 Mon Sep 17 00:00:00 2001 From: Charles Beauville Date: Thu, 1 Feb 2024 14:47:51 +0100 Subject: [PATCH 071/113] Add PR title in changelog by default (#2888) --- .github/PULL_REQUEST_TEMPLATE.md | 4 ++-- .../contributor-tutorial-contribute-on-github.rst | 15 ++++----------- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 479f88c1bbd5..b9d4a0a23e23 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -44,7 +44,7 @@ Example: The variable `rnd` was renamed to `server_round` to improve readability ### What's new? From 0c7fa3bd6e1a7f3b0e332df21dc16697c7f4d5cb Mon Sep 17 00:00:00 2001 From: Charles Beauville Date: Mon, 5 Feb 2024 14:45:06 +0100 Subject: [PATCH 078/113] Use `dist` directory when publishing via CI (#2903) --- .github/workflows/framework-release.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/framework-release.yml b/.github/workflows/framework-release.yml index 0f3cda8abae3..f052d3a4a928 100644 --- a/.github/workflows/framework-release.yml +++ b/.github/workflows/framework-release.yml @@ -34,7 +34,9 @@ jobs: wheel_url="https://artifact.flower.dev/py/release/v${TAG_NAME}/${wheel_name}" tar_url="https://artifact.flower.dev/py/release/v${TAG_NAME}/${tar_name}" - curl $wheel_url --output $wheel_name - curl $tar_url --output $tar_name + mkdir -p dist + + curl $wheel_url --output dist/$wheel_name + curl $tar_url --output dist/$tar_name python -m poetry publish -u __token__ -p ${{ secrets.PYPI_TOKEN }} From a8eebdeef149b95d276830f2407081baf66b3156 Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Mon, 5 Feb 2024 14:58:04 +0100 Subject: [PATCH 079/113] Update version to 1.8.0 (#2902) --- doc/locales/pt_BR/LC_MESSAGES/framework-docs.po | 4 ++-- doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po | 4 ++-- doc/source/conf.py | 2 +- ...ntributor-how-to-install-development-versions.rst | 8 ++++---- doc/source/ref-changelog.md | 12 +++++++++--- examples/doc/source/conf.py | 2 +- examples/flower-via-docker-compose/requirements.txt | 2 +- examples/xgboost-quickstart/pyproject.toml | 2 +- examples/xgboost-quickstart/requirements.txt | 2 +- pyproject.toml | 2 +- 10 files changed, 23 insertions(+), 17 deletions(-) diff --git a/doc/locales/pt_BR/LC_MESSAGES/framework-docs.po b/doc/locales/pt_BR/LC_MESSAGES/framework-docs.po index c61dcd5d6c0d..1dd6a27fe17e 100644 --- a/doc/locales/pt_BR/LC_MESSAGES/framework-docs.po +++ b/doc/locales/pt_BR/LC_MESSAGES/framework-docs.po @@ -518,13 +518,13 @@ msgid "" msgstr "" #: ../../source/contributor-how-to-install-development-versions.rst:62 -msgid "Upload the whl (e.g., ``flwr-1.6.0-py3-none-any.whl``)" +msgid "Upload the whl (e.g., ``flwr-1.7.0-py3-none-any.whl``)" msgstr "" #: ../../source/contributor-how-to-install-development-versions.rst:63 msgid "" "Change ``!pip install -q 'flwr[simulation]' torch torchvision " -"matplotlib`` to ``!pip install -q 'flwr-1.6.0-py3-none-" +"matplotlib`` to ``!pip install -q 'flwr-1.7.0-py3-none-" "any.whl[simulation]' torch torchvision matplotlib``" msgstr "" diff --git a/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po b/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po index 8a80efee2829..8e57cbfda0c0 100644 --- a/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po +++ b/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po @@ -519,13 +519,13 @@ msgid "" msgstr "" #: ../../source/contributor-how-to-install-development-versions.rst:62 -msgid "Upload the whl (e.g., ``flwr-1.6.0-py3-none-any.whl``)" +msgid "Upload the whl (e.g., ``flwr-1.7.0-py3-none-any.whl``)" msgstr "" #: ../../source/contributor-how-to-install-development-versions.rst:63 msgid "" "Change ``!pip install -q 'flwr[simulation]' torch torchvision " -"matplotlib`` to ``!pip install -q 'flwr-1.6.0-py3-none-" +"matplotlib`` to ``!pip install -q 'flwr-1.7.0-py3-none-" "any.whl[simulation]' torch torchvision matplotlib``" msgstr "" diff --git a/doc/source/conf.py b/doc/source/conf.py index 503f76cb9eca..dfb11ee37a46 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -86,7 +86,7 @@ author = "The Flower Authors" # The full version, including alpha/beta/rc tags -release = "1.7.0" +release = "1.8.0" # -- General configuration --------------------------------------------------- diff --git a/doc/source/contributor-how-to-install-development-versions.rst b/doc/source/contributor-how-to-install-development-versions.rst index 243f4ef97e8e..558ec7f8ec46 100644 --- a/doc/source/contributor-how-to-install-development-versions.rst +++ b/doc/source/contributor-how-to-install-development-versions.rst @@ -19,8 +19,8 @@ Install ``flwr`` from a local copy of the Flower source code via ``pyproject.tom Install ``flwr`` from a local wheel file via ``pyproject.toml``: -- ``flwr = { path = "../../dist/flwr-1.0.0-py3-none-any.whl" }`` (without extras) -- ``flwr = { path = "../../dist/flwr-1.0.0-py3-none-any.whl", extras = ["simulation"] }`` (with extras) +- ``flwr = { path = "../../dist/flwr-1.8.0-py3-none-any.whl" }`` (without extras) +- ``flwr = { path = "../../dist/flwr-1.8.0-py3-none-any.whl", extras = ["simulation"] }`` (with extras) Please refer to the Poetry documentation for further details: `Poetry Dependency Specification `_ @@ -59,5 +59,5 @@ Open a development version of the same notebook from branch `branch-name` by cha Install a `whl` on Google Colab: 1. In the vertical icon grid on the left hand side, select ``Files`` > ``Upload to session storage`` -2. Upload the whl (e.g., ``flwr-1.7.0-py3-none-any.whl``) -3. Change ``!pip install -q 'flwr[simulation]' torch torchvision matplotlib`` to ``!pip install -q 'flwr-1.7.0-py3-none-any.whl[simulation]' torch torchvision matplotlib`` +2. Upload the whl (e.g., ``flwr-1.8.0-py3-none-any.whl``) +3. Change ``!pip install -q 'flwr[simulation]' torch torchvision matplotlib`` to ``!pip install -q 'flwr-1.8.0-py3-none-any.whl[simulation]' torch torchvision matplotlib`` diff --git a/doc/source/ref-changelog.md b/doc/source/ref-changelog.md index c5636ce6ba49..78d1e0e491a4 100644 --- a/doc/source/ref-changelog.md +++ b/doc/source/ref-changelog.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### What's new? + +### Incompatible changes + ## v1.7.0 (2024-02-05) ### Thanks to our contributors @@ -48,7 +54,7 @@ We would like to give our special thanks to all the contributors who made the ne Several code examples were updated to use [Flower Datasets](https://flower.dev/docs/datasets/). -- **General updates to Flower Examples** ([#2381](https://github.com/adap/flower/pull/2381), [2805](https://github.com/adap/flower/pull/2805), [2782](https://github.com/adap/flower/pull/2782), [2806](https://github.com/adap/flower/pull/2806), [2829](https://github.com/adap/flower/pull/2829), [2825](https://github.com/adap/flower/pull/2825), [2816](https://github.com/adap/flower/pull/2816), [#2726](https://github.com/adap/flower/pull/2726), [#2659](https://github.com/adap/flower/pull/2659), [#2655](https://github.com/adap/flower/pull/2655)) +- **General updates to Flower Examples** ([#2381](https://github.com/adap/flower/pull/2381), [#2805](https://github.com/adap/flower/pull/2805), [#2782](https://github.com/adap/flower/pull/2782), [#2806](https://github.com/adap/flower/pull/2806), [#2829](https://github.com/adap/flower/pull/2829), [#2825](https://github.com/adap/flower/pull/2825), [#2816](https://github.com/adap/flower/pull/2816), [#2726](https://github.com/adap/flower/pull/2726), [#2659](https://github.com/adap/flower/pull/2659), [#2655](https://github.com/adap/flower/pull/2655)) Many Flower code examples received substantial updates. @@ -69,7 +75,7 @@ We would like to give our special thanks to all the contributors who made the ne - **Update dependencies** ([#2753](https://github.com/adap/flower/pull/2753), [#2651](https://github.com/adap/flower/pull/2651), [#2739](https://github.com/adap/flower/pull/2739), [#2837](https://github.com/adap/flower/pull/2837), [#2788](https://github.com/adap/flower/pull/2788), [#2811](https://github.com/adap/flower/pull/2811), [#2774](https://github.com/adap/flower/pull/2774), [#2790](https://github.com/adap/flower/pull/2790), [#2751](https://github.com/adap/flower/pull/2751), [#2850](https://github.com/adap/flower/pull/2850), [#2812](https://github.com/adap/flower/pull/2812), [#2872](https://github.com/adap/flower/pull/2872), [#2736](https://github.com/adap/flower/pull/2736), [#2756](https://github.com/adap/flower/pull/2756), [#2857](https://github.com/adap/flower/pull/2857), [#2757](https://github.com/adap/flower/pull/2757), [#2810](https://github.com/adap/flower/pull/2810), [#2740](https://github.com/adap/flower/pull/2740), [#2789](https://github.com/adap/flower/pull/2789)) -- **General improvements** ([#2803](https://github.com/adap/flower/pull/2803), [2847](https://github.com/adap/flower/pull/2847), [2877](https://github.com/adap/flower/pull/2877), [2690](https://github.com/adap/flower/pull/2690), [2889](https://github.com/adap/flower/pull/2889), [2874](https://github.com/adap/flower/pull/2874), [2819](https://github.com/adap/flower/pull/2819), [2689](https://github.com/adap/flower/pull/2689), [2457](https://github.com/adap/flower/pull/2457), [2870](https://github.com/adap/flower/pull/2870), [2669](https://github.com/adap/flower/pull/2669), [2876](https://github.com/adap/flower/pull/2876), [2885](https://github.com/adap/flower/pull/2885), [2858](https://github.com/adap/flower/pull/2858), [2867](https://github.com/adap/flower/pull/2867), [2351](https://github.com/adap/flower/pull/2351), [2886](https://github.com/adap/flower/pull/2886), [2860](https://github.com/adap/flower/pull/2860), [2828](https://github.com/adap/flower/pull/2828), [2869](https://github.com/adap/flower/pull/2869), [2875](https://github.com/adap/flower/pull/2875), [2733](https://github.com/adap/flower/pull/2733), [2488](https://github.com/adap/flower/pull/2488), [2646](https://github.com/adap/flower/pull/2646), [2879](https://github.com/adap/flower/pull/2879), [2821](https://github.com/adap/flower/pull/2821), [2855](https://github.com/adap/flower/pull/2855), [2800](https://github.com/adap/flower/pull/2800), [2807](https://github.com/adap/flower/pull/2807), [2801](https://github.com/adap/flower/pull/2801), [2804](https://github.com/adap/flower/pull/2804), [2851](https://github.com/adap/flower/pull/2851), [2787](https://github.com/adap/flower/pull/2787), [2852](https://github.com/adap/flower/pull/2852), [#2672](https://github.com/adap/flower/pull/2672), [#2759](https://github.com/adap/flower/pull/2759)) +- **General improvements** ([#2803](https://github.com/adap/flower/pull/2803), [#2847](https://github.com/adap/flower/pull/2847), [#2877](https://github.com/adap/flower/pull/2877), [#2690](https://github.com/adap/flower/pull/2690), [#2889](https://github.com/adap/flower/pull/2889), [#2874](https://github.com/adap/flower/pull/2874), [#2819](https://github.com/adap/flower/pull/2819), [#2689](https://github.com/adap/flower/pull/2689), [#2457](https://github.com/adap/flower/pull/2457), [#2870](https://github.com/adap/flower/pull/2870), [#2669](https://github.com/adap/flower/pull/2669), [#2876](https://github.com/adap/flower/pull/2876), [#2885](https://github.com/adap/flower/pull/2885), [#2858](https://github.com/adap/flower/pull/2858), [#2867](https://github.com/adap/flower/pull/2867), [#2351](https://github.com/adap/flower/pull/2351), [#2886](https://github.com/adap/flower/pull/2886), [#2860](https://github.com/adap/flower/pull/2860), [#2828](https://github.com/adap/flower/pull/2828), [#2869](https://github.com/adap/flower/pull/2869), [#2875](https://github.com/adap/flower/pull/2875), [#2733](https://github.com/adap/flower/pull/2733), [#2488](https://github.com/adap/flower/pull/2488), [#2646](https://github.com/adap/flower/pull/2646), [#2879](https://github.com/adap/flower/pull/2879), [#2821](https://github.com/adap/flower/pull/2821), [#2855](https://github.com/adap/flower/pull/2855), [#2800](https://github.com/adap/flower/pull/2800), [#2807](https://github.com/adap/flower/pull/2807), [#2801](https://github.com/adap/flower/pull/2801), [#2804](https://github.com/adap/flower/pull/2804), [#2851](https://github.com/adap/flower/pull/2851), [#2787](https://github.com/adap/flower/pull/2787), [#2852](https://github.com/adap/flower/pull/2852), [#2672](https://github.com/adap/flower/pull/2672), [#2759](https://github.com/adap/flower/pull/2759)) ### Incompatible changes @@ -179,7 +185,7 @@ We would like to give our special thanks to all the contributors who made the ne - **General updates to Flower SDKs** ([#2288](https://github.com/adap/flower/pull/2288), [#2429](https://github.com/adap/flower/pull/2429), [#2555](https://github.com/adap/flower/pull/2555), [#2543](https://github.com/adap/flower/pull/2543), [#2544](https://github.com/adap/flower/pull/2544), [#2597](https://github.com/adap/flower/pull/2597), [#2623](https://github.com/adap/flower/pull/2623)) -- **General improvements** ([#2309](https://github.com/adap/flower/pull/2309), [#2310](https://github.com/adap/flower/pull/2310), [2313](https://github.com/adap/flower/pull/2313), [#2316](https://github.com/adap/flower/pull/2316), [2317](https://github.com/adap/flower/pull/2317), [#2349](https://github.com/adap/flower/pull/2349), [#2360](https://github.com/adap/flower/pull/2360), [#2402](https://github.com/adap/flower/pull/2402), [#2446](https://github.com/adap/flower/pull/2446), [#2561](https://github.com/adap/flower/pull/2561), [#2273](https://github.com/adap/flower/pull/2273), [#2267](https://github.com/adap/flower/pull/2267), [#2274](https://github.com/adap/flower/pull/2274), [#2275](https://github.com/adap/flower/pull/2275), [#2432](https://github.com/adap/flower/pull/2432), [#2251](https://github.com/adap/flower/pull/2251), [#2321](https://github.com/adap/flower/pull/2321), [#1936](https://github.com/adap/flower/pull/1936), [#2408](https://github.com/adap/flower/pull/2408), [#2413](https://github.com/adap/flower/pull/2413), [#2401](https://github.com/adap/flower/pull/2401), [#2531](https://github.com/adap/flower/pull/2531), [#2534](https://github.com/adap/flower/pull/2534), [#2535](https://github.com/adap/flower/pull/2535), [#2521](https://github.com/adap/flower/pull/2521), [#2553](https://github.com/adap/flower/pull/2553), [#2596](https://github.com/adap/flower/pull/2596)) +- **General improvements** ([#2309](https://github.com/adap/flower/pull/2309), [#2310](https://github.com/adap/flower/pull/2310), [#2313](https://github.com/adap/flower/pull/2313), [#2316](https://github.com/adap/flower/pull/2316), [#2317](https://github.com/adap/flower/pull/2317), [#2349](https://github.com/adap/flower/pull/2349), [#2360](https://github.com/adap/flower/pull/2360), [#2402](https://github.com/adap/flower/pull/2402), [#2446](https://github.com/adap/flower/pull/2446), [#2561](https://github.com/adap/flower/pull/2561), [#2273](https://github.com/adap/flower/pull/2273), [#2267](https://github.com/adap/flower/pull/2267), [#2274](https://github.com/adap/flower/pull/2274), [#2275](https://github.com/adap/flower/pull/2275), [#2432](https://github.com/adap/flower/pull/2432), [#2251](https://github.com/adap/flower/pull/2251), [#2321](https://github.com/adap/flower/pull/2321), [#1936](https://github.com/adap/flower/pull/1936), [#2408](https://github.com/adap/flower/pull/2408), [#2413](https://github.com/adap/flower/pull/2413), [#2401](https://github.com/adap/flower/pull/2401), [#2531](https://github.com/adap/flower/pull/2531), [#2534](https://github.com/adap/flower/pull/2534), [#2535](https://github.com/adap/flower/pull/2535), [#2521](https://github.com/adap/flower/pull/2521), [#2553](https://github.com/adap/flower/pull/2553), [#2596](https://github.com/adap/flower/pull/2596)) Flower received many improvements under the hood, too many to list here. diff --git a/examples/doc/source/conf.py b/examples/doc/source/conf.py index 3d629c39c7ea..608aaeaeed6b 100644 --- a/examples/doc/source/conf.py +++ b/examples/doc/source/conf.py @@ -30,7 +30,7 @@ author = "The Flower Authors" # The full version, including alpha/beta/rc tags -release = "1.7.0" +release = "1.8.0" # -- General configuration --------------------------------------------------- diff --git a/examples/flower-via-docker-compose/requirements.txt b/examples/flower-via-docker-compose/requirements.txt index 2a85546d0e18..92e0fb13b290 100644 --- a/examples/flower-via-docker-compose/requirements.txt +++ b/examples/flower-via-docker-compose/requirements.txt @@ -2,4 +2,4 @@ flwr==1.6.0 tensorflow==2.13.1 numpy==1.24.3 prometheus_client == 0.19.0 -flwr_datasets[vision] == 0.0.2 \ No newline at end of file +flwr_datasets[vision] == 0.0.2 diff --git a/examples/xgboost-quickstart/pyproject.toml b/examples/xgboost-quickstart/pyproject.toml index 7b3cbd9659a2..af0164514cf1 100644 --- a/examples/xgboost-quickstart/pyproject.toml +++ b/examples/xgboost-quickstart/pyproject.toml @@ -10,6 +10,6 @@ authors = ["The Flower Authors "] [tool.poetry.dependencies] python = ">=3.8,<3.11" -flwr = ">=1.6.0,<2.0" +flwr = ">=1.7.0,<2.0" flwr-datasets = ">=0.0.1,<1.0.0" xgboost = ">=2.0.0,<3.0.0" diff --git a/examples/xgboost-quickstart/requirements.txt b/examples/xgboost-quickstart/requirements.txt index 4ccd5587bfc3..c6949e0651c5 100644 --- a/examples/xgboost-quickstart/requirements.txt +++ b/examples/xgboost-quickstart/requirements.txt @@ -1,3 +1,3 @@ -flwr>=1.6.0, <2.0 +flwr>=1.7.0, <2.0 flwr-datasets>=0.0.1, <1.0.0 xgboost>=2.0.0, <3.0.0 diff --git a/pyproject.toml b/pyproject.toml index f121ac30f44d..2c3a265c4516 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "flwr" -version = "1.7.0" +version = "1.8.0" description = "Flower: A Friendly Federated Learning Framework" license = "Apache-2.0" authors = ["The Flower Authors "] From 54da86351cc218ab57d96f60bc7fe22dafb0416b Mon Sep 17 00:00:00 2001 From: Robert Steiner Date: Tue, 6 Feb 2024 12:13:01 +0100 Subject: [PATCH 080/113] Update flwr in docker docs and examples (#2907) --- .github/workflows/docker-client.yml | 2 +- .github/workflows/docker-server.yml | 2 +- ...contributor-how-to-build-docker-images.rst | 8 +++---- doc/source/how-to-run-flower-using-docker.rst | 22 +++++++++---------- .../requirements.txt | 6 ++--- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/docker-client.yml b/.github/workflows/docker-client.yml index 47083b258982..3c2d83596733 100644 --- a/.github/workflows/docker-client.yml +++ b/.github/workflows/docker-client.yml @@ -4,7 +4,7 @@ on: workflow_dispatch: inputs: flwr-version: - description: "Version of Flower e.g. (1.6.0)." + description: "Version of Flower e.g. (1.7.0)." required: true type: string diff --git a/.github/workflows/docker-server.yml b/.github/workflows/docker-server.yml index f580a8e9a280..1e43715207d4 100644 --- a/.github/workflows/docker-server.yml +++ b/.github/workflows/docker-server.yml @@ -4,7 +4,7 @@ on: workflow_dispatch: inputs: flwr-version: - description: "Version of Flower e.g. (1.6.0)." + description: "Version of Flower e.g. (1.7.0)." required: true type: string base-image-tag: diff --git a/doc/source/contributor-how-to-build-docker-images.rst b/doc/source/contributor-how-to-build-docker-images.rst index d85e48155de0..2c6c7a7ab986 100644 --- a/doc/source/contributor-how-to-build-docker-images.rst +++ b/doc/source/contributor-how-to-build-docker-images.rst @@ -98,17 +98,17 @@ Building the server image * - ``FLWR_VERSION`` - Version of Flower to be installed. - Yes - - ``1.6.0`` + - ``1.7.0`` The following example creates a server image with the official Flower base image py3.11-ubuntu22.04 -and Flower 1.6.0: +and Flower 1.7.0: .. code-block:: bash $ cd src/docker/server/ $ docker build \ --build-arg BASE_IMAGE_TAG=py3.11-ubuntu22.04 \ - --build-arg FLWR_VERSION=1.6.0 \ + --build-arg FLWR_VERSION=1.7.0 \ -t flwr_server:0.1.0 . The name of image is ``flwr_server`` and the tag ``0.1.0``. Remember that the build arguments as well @@ -125,7 +125,7 @@ the tag of your image. $ docker build \ --build-arg BASE_REPOSITORY=flwr_base \ --build-arg BASE_IMAGE_TAG=0.1.0 \ - --build-arg FLWR_VERSION=1.6.0 \ + --build-arg FLWR_VERSION=1.7.0 \ -t flwr_server:0.1.0 . After creating the image, we can test whether the image is working: diff --git a/doc/source/how-to-run-flower-using-docker.rst b/doc/source/how-to-run-flower-using-docker.rst index 27ff61c280cb..8d47dcd3f2ab 100644 --- a/doc/source/how-to-run-flower-using-docker.rst +++ b/doc/source/how-to-run-flower-using-docker.rst @@ -31,12 +31,12 @@ If you're looking to try out Flower, you can use the following command: .. code-block:: bash - $ docker run --rm -p 9091:9091 -p 9092:9092 flwr/server:1.6.0-py3.11-ubuntu22.04 \ + $ docker run --rm -p 9091:9091 -p 9092:9092 flwr/server:1.7.0-py3.11-ubuntu22.04 \ --insecure -The command will pull the Docker image with the tag ``1.6.0-py3.11-ubuntu22.04`` from Docker Hub. +The command will pull the Docker image with the tag ``1.7.0-py3.11-ubuntu22.04`` from Docker Hub. The tag contains the information which Flower, Python and Ubuntu is used. In this case, it -uses Flower 1.6.0, Python 3.11 and Ubuntu 22.04. The ``--rm`` flag tells Docker to remove +uses Flower 1.7.0, Python 3.11 and Ubuntu 22.04. The ``--rm`` flag tells Docker to remove the container after it exits. .. note:: @@ -61,7 +61,7 @@ You can use ``--help`` to view all available flags that the server supports: .. code-block:: bash - $ docker run --rm flwr/server:1.6.0-py3.11-ubuntu22.04 --help + $ docker run --rm flwr/server:1.7.0-py3.11-ubuntu22.04 --help Mounting a volume to store the state on the host system ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -75,7 +75,7 @@ flag ``--database`` to specify the name of the database file. .. code-block:: bash $ docker run --rm \ - -p 9091:9091 -p 9092:9092 -v ~/:/app/ flwr/server:1.6.0-py3.11-ubuntu22.04 \ + -p 9091:9091 -p 9092:9092 -v ~/:/app/ flwr/server:1.7.0-py3.11-ubuntu22.04 \ --insecure \ --database state.db @@ -101,7 +101,7 @@ the server with the ``--certificates`` flag. .. code-block:: bash $ docker run --rm \ - -p 9091:9091 -p 9092:9092 -v ./certificates/:/app/ flwr/server:1.6.0-py3.11-ubuntu22.04 \ + -p 9091:9091 -p 9092:9092 -v ./certificates/:/app/ flwr/server:1.7.0-py3.11-ubuntu22.04 \ --certificates ca.crt server.pem server.key Using a different Flower or Python version @@ -118,19 +118,19 @@ updates of system dependencies that should not change the functionality of Flowe want to ensure that you always use the same image, you can specify the hash of the image instead of the tag. -The following command returns the current image hash referenced by the ``server:1.6.0-py3.11-ubuntu22.04`` tag: +The following command returns the current image hash referenced by the ``server:1.7.0-py3.11-ubuntu22.04`` tag: .. code-block:: bash - $ docker inspect --format='{{index .RepoDigests 0}}' flwr/server:1.6.0-py3.11-ubuntu22.04 - flwr/server@sha256:43fc389bcb016feab2b751b2ccafc9e9a906bb0885bd92b972329801086bc017 + $ docker inspect --format='{{index .RepoDigests 0}}' flwr/server:1.7.0-py3.11-ubuntu22.04 + flwr/server@sha256:c4be5012f9d73e3022e98735a889a463bb2f4f434448ebc19c61379920b1b327 Next, we can pin the hash when running a new server container: .. code-block:: bash $ docker run \ - --rm flwr/server@sha256:43fc389bcb016feab2b751b2ccafc9e9a906bb0885bd92b972329801086bc017 \ + --rm flwr/server@sha256:c4be5012f9d73e3022e98735a889a463bb2f4f434448ebc19c61379920b1b327 \ --insecure Setting environment variables @@ -141,4 +141,4 @@ To set a variable inside a Docker container, you can use the ``-e = .. code-block:: bash $ docker run -e FLWR_TELEMETRY_ENABLED=0 \ - --rm flwr/server:1.6.0-py3.11-ubuntu22.04 --insecure + --rm flwr/server:1.7.0-py3.11-ubuntu22.04 --insecure diff --git a/examples/flower-via-docker-compose/requirements.txt b/examples/flower-via-docker-compose/requirements.txt index 92e0fb13b290..b93e5b1d9f2b 100644 --- a/examples/flower-via-docker-compose/requirements.txt +++ b/examples/flower-via-docker-compose/requirements.txt @@ -1,5 +1,5 @@ -flwr==1.6.0 -tensorflow==2.13.1 -numpy==1.24.3 +flwr==1.7.0 +tensorflow==2.13.1 +numpy==1.24.3 prometheus_client == 0.19.0 flwr_datasets[vision] == 0.0.2 From 3f757c7de94766784f15f14cfb0f8cec8566aa8a Mon Sep 17 00:00:00 2001 From: Yan Gao Date: Wed, 7 Feb 2024 12:28:11 +0000 Subject: [PATCH 081/113] Update required flwr version from nightly to 1.7.0 (#2910) --- examples/xgboost-comprehensive/pyproject.toml | 2 +- examples/xgboost-comprehensive/requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/xgboost-comprehensive/pyproject.toml b/examples/xgboost-comprehensive/pyproject.toml index a4d2d0fd837b..e6495a98c969 100644 --- a/examples/xgboost-comprehensive/pyproject.toml +++ b/examples/xgboost-comprehensive/pyproject.toml @@ -10,6 +10,6 @@ authors = ["The Flower Authors "] [tool.poetry.dependencies] python = ">=3.8,<3.11" -flwr-nightly = { extras = ["simulation"], version = ">=1.0,<2.0" } +flwr-nightly = { extras = ["simulation"], version = ">=1.7.0,<2.0" } flwr-datasets = ">=0.0.2,<1.0.0" xgboost = ">=2.0.0,<3.0.0" diff --git a/examples/xgboost-comprehensive/requirements.txt b/examples/xgboost-comprehensive/requirements.txt index 360fbfb066c5..b5b1d83bcdd1 100644 --- a/examples/xgboost-comprehensive/requirements.txt +++ b/examples/xgboost-comprehensive/requirements.txt @@ -1,3 +1,3 @@ -flwr-nightly[simulation]>=1.0, <2.0 +flwr[simulation]>=1.7.0, <2.0 flwr-datasets>=0.0.2, <1.0.0 xgboost>=2.0.0, <3.0.0 From 57da58ae5f28d4468f0982ba3863629ab7718808 Mon Sep 17 00:00:00 2001 From: Yan Gao Date: Fri, 9 Feb 2024 12:34:20 +0000 Subject: [PATCH 082/113] Add Chinese language button on framework doc page (#2914) --- doc/source/_templates/sidebar/lang.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/source/_templates/sidebar/lang.html b/doc/source/_templates/sidebar/lang.html index b5143bd7212b..04b3af62c7ce 100644 --- a/doc/source/_templates/sidebar/lang.html +++ b/doc/source/_templates/sidebar/lang.html @@ -3,6 +3,7 @@ {% endif %} From e409f635e1ca6fd6ebfcfd0aad3007f0427e3f6f Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Fri, 9 Feb 2024 14:15:37 +0100 Subject: [PATCH 083/113] Rename middleware layers to mods (#2911) --- doc/source/conf.py | 1 + .../how-to-use-built-in-middleware-layers.rst | 87 ------------------ doc/source/how-to-use-built-in-mods.rst | 89 +++++++++++++++++++ doc/source/index.rst | 2 +- examples/secaggplus-mt/client.py | 4 +- src/py/flwr/client/flower.py | 10 +-- .../client/message_handler/message_handler.py | 2 +- .../client/{middleware => mod}/__init__.py | 6 +- .../secure_aggregation/__init__.py | 8 +- .../secure_aggregation/secaggplus_mod.py} | 2 +- .../secaggplus_mod_test.py} | 6 +- .../flwr/client/{middleware => mod}/utils.py | 14 +-- .../client/{middleware => mod}/utils_test.py | 40 ++++----- src/py/flwr/client/typing.py | 6 +- src/py/flwr/common/context.py | 2 +- 15 files changed, 141 insertions(+), 138 deletions(-) delete mode 100644 doc/source/how-to-use-built-in-middleware-layers.rst create mode 100644 doc/source/how-to-use-built-in-mods.rst rename src/py/flwr/client/{middleware => mod}/__init__.py (85%) rename src/py/flwr/client/{middleware => mod}/secure_aggregation/__init__.py (85%) rename src/py/flwr/client/{middleware/secure_aggregation/secaggplus_middleware.py => mod/secure_aggregation/secaggplus_mod.py} (99%) rename src/py/flwr/client/{middleware/secure_aggregation/secaggplus_middleware_test.py => mod/secure_aggregation/secaggplus_mod_test.py} (98%) rename src/py/flwr/client/{middleware => mod}/utils.py (71%) rename src/py/flwr/client/{middleware => mod}/utils_test.py (78%) diff --git a/doc/source/conf.py b/doc/source/conf.py index dfb11ee37a46..259d8a988841 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -173,6 +173,7 @@ def find_test_modules(package_path): "writing-documentation": "contributor-how-to-write-documentation.html", "apiref-binaries": "ref-api-cli.html", "fedbn-example-pytorch-from-centralized-to-federated": "example-fedbn-pytorch-from-centralized-to-federated.html", + "how-to-use-built-in-middleware-layers": "how-to-use-built-in-mods.html", # Restructuring: tutorials "tutorial/Flower-0-What-is-FL": "tutorial-series-what-is-federated-learning.html", "tutorial/Flower-1-Intro-to-FL-PyTorch": "tutorial-series-get-started-with-flower-pytorch.html", diff --git a/doc/source/how-to-use-built-in-middleware-layers.rst b/doc/source/how-to-use-built-in-middleware-layers.rst deleted file mode 100644 index 2e91623b26be..000000000000 --- a/doc/source/how-to-use-built-in-middleware-layers.rst +++ /dev/null @@ -1,87 +0,0 @@ -Use Built-in Middleware Layers -============================== - -**Note: This tutorial covers experimental features. The functionality and interfaces may change in future versions.** - -In this tutorial, we will learn how to utilize built-in middleware layers to augment the behavior of a ``FlowerCallable``. Middleware allows us to perform operations before and after a task is processed in the ``FlowerCallable``. - -What is middleware? -------------------- - -Middleware is a callable that wraps around a ``FlowerCallable``. It can manipulate or inspect incoming tasks (``TaskIns``) in the ``Fwd`` and the resulting tasks (``TaskRes``) in the ``Bwd``. The signature for a middleware layer (``Layer``) is as follows: - -.. code-block:: python - - FlowerCallable = Callable[[Fwd], Bwd] - Layer = Callable[[Fwd, FlowerCallable], Bwd] - -A typical middleware function might look something like this: - -.. code-block:: python - - def example_middleware(fwd: Fwd, ffn: FlowerCallable) -> Bwd: - # Do something with Fwd before passing to the inner ``FlowerCallable``. - bwd = ffn(fwd) - # Do something with Bwd before returning. - return bwd - -Using middleware layers ------------------------ - -To use middleware layers in your ``FlowerCallable``, you can follow these steps: - -1. Import the required middleware -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -First, import the built-in middleware layers you intend to use: - -.. code-block:: python - - import flwr as fl - from flwr.client.middleware import example_middleware1, example_middleware2 - -2. Define your client function -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Define your client function (``client_fn``) that will be wrapped by the middleware: - -.. code-block:: python - - def client_fn(cid): - # Your client code goes here. - return # your client - -3. Create the ``FlowerCallable`` with middleware -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Create your ``FlowerCallable`` and pass the middleware layers as a list to the ``layers`` argument. The order in which you provide the middleware layers matters: - -.. code-block:: python - - flower = fl.app.Flower( - client_fn=client_fn, - layers=[ - example_middleware1, # Middleware layer 1 - example_middleware2, # Middleware layer 2 - ] - ) - -Order of execution ------------------- - -When the ``FlowerCallable`` runs, the middleware layers are executed in the order they are provided in the list: - -1. ``example_middleware1`` (outermost layer) -2. ``example_middleware2`` (next layer) -3. Message handler (core function that handles ``TaskIns`` and returns ``TaskRes``) -4. ``example_middleware2`` (on the way back) -5. ``example_middleware1`` (outermost layer on the way back) - -Each middleware has a chance to inspect and modify the ``TaskIns`` in the ``Fwd`` before passing it to the next layer, and likewise with the ``TaskRes`` in the ``Bwd`` before returning it up the stack. - -Conclusion ----------- - -By following this guide, you have learned how to effectively use middleware layers to enhance your ``FlowerCallable``'s functionality. Remember that the order of middleware is crucial and affects how the input and output are processed. - -Enjoy building more robust and flexible ``FlowerCallable``s with middleware layers! diff --git a/doc/source/how-to-use-built-in-mods.rst b/doc/source/how-to-use-built-in-mods.rst new file mode 100644 index 000000000000..5d4ec782a138 --- /dev/null +++ b/doc/source/how-to-use-built-in-mods.rst @@ -0,0 +1,89 @@ +Use Built-in Mods +================= + +**Note: This tutorial covers experimental features. The functionality and interfaces may change in future versions.** + +In this tutorial, we will learn how to utilize built-in mods to augment the behavior of a ``FlowerCallable``. Mods (sometimes also called Modifiers) allow us to perform operations before and after a task is processed in the ``FlowerCallable``. + +What are Mods? +-------------- + +A Mod is a callable that wraps around a ``FlowerCallable``. It can manipulate or inspect the incoming ``Message`` and the resulting outgoing ``Message``. The signature for a ``Mod`` is as follows: + +.. code-block:: python + + FlowerCallable = Callable[[Fwd], Bwd] + Mod = Callable[[Fwd, FlowerCallable], Bwd] + +A typical mod function might look something like this: + +.. code-block:: python + + def example_mod(msg: Message, ctx: Context, nxt: FlowerCallable) -> Message: + # Do something with incoming Message (or Context) + # before passing to the inner ``FlowerCallable`` + msg = nxt(msg, ctx) + # Do something with outgoing Message (or Context) + # before returning + return msg + +Using Mods +---------- + +To use mods in your ``FlowerCallable``, you can follow these steps: + +1. Import the required mods +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +First, import the built-in mod you intend to use: + +.. code-block:: python + + import flwr as fl + from flwr.client.mod import example_mod_1, example_mod_2 + +2. Define your client function +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Define your client function (``client_fn``) that will be wrapped by the mod(s): + +.. code-block:: python + + def client_fn(cid): + # Your client code goes here. + return # your client + +3. Create the ``FlowerCallable`` with mods +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Create your ``FlowerCallable`` and pass the mods as a list to the ``mods`` argument. The order in which you provide the mods matters: + +.. code-block:: python + + flower = fl.app.Flower( + client_fn=client_fn, + mods=[ + example_mod_1, # Mod 1 + example_mod_2, # Mod 2 + ] + ) + +Order of execution +------------------ + +When the ``FlowerCallable`` runs, the mods are executed in the order they are provided in the list: + +1. ``example_mod_1`` (outermost mod) +2. ``example_mod_2`` (next mod) +3. Message handler (core function that handles the incoming ``Message`` and returns the outgoing ``Message``) +4. ``example_mod_2`` (on the way back) +5. ``example_mod_1`` (outermost mod on the way back) + +Each mod has a chance to inspect and modify the incoming ``Message`` before passing it to the next mod, and likewise with the outgoing ``Message`` before returning it up the stack. + +Conclusion +---------- + +By following this guide, you have learned how to effectively use mods to enhance your ``FlowerCallable``'s functionality. Remember that the order of mods is crucial and affects how the input and output are processed. + +Enjoy building more robust and flexible ``FlowerCallable``s with mods! diff --git a/doc/source/index.rst b/doc/source/index.rst index 5df591d6ce05..7e2b4052bee6 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -91,7 +91,7 @@ Problem-oriented how-to guides show step-by-step how to achieve a specific goal. how-to-configure-logging how-to-enable-ssl-connections how-to-upgrade-to-flower-1.0 - how-to-use-built-in-middleware-layers + how-to-use-built-in-mods how-to-run-flower-using-docker .. toctree:: diff --git a/examples/secaggplus-mt/client.py b/examples/secaggplus-mt/client.py index a0ed9e7181c7..92c5bf7317cc 100644 --- a/examples/secaggplus-mt/client.py +++ b/examples/secaggplus-mt/client.py @@ -5,7 +5,7 @@ import flwr as fl from flwr.common import Status, FitIns, FitRes, Code from flwr.common.parameter import ndarrays_to_parameters -from flwr.client.middleware import secaggplus_middleware +from flwr.client.mod import secaggplus_mod # Define Flower client with the SecAgg+ protocol @@ -35,7 +35,7 @@ def client_fn(cid: str): # To run this: `flower-client --callable client:flower` flower = fl.flower.Flower( client_fn=client_fn, - layers=[secaggplus_middleware], + mods=[secaggplus_mod], ) diff --git a/src/py/flwr/client/flower.py b/src/py/flwr/client/flower.py index 91f64502acfa..b096a1003b19 100644 --- a/src/py/flwr/client/flower.py +++ b/src/py/flwr/client/flower.py @@ -21,8 +21,8 @@ from flwr.client.message_handler.message_handler import ( handle_legacy_message_from_tasktype, ) -from flwr.client.middleware.utils import make_ffn -from flwr.client.typing import ClientFn, Layer +from flwr.client.mod.utils import make_ffn +from flwr.client.typing import ClientFn, Mod from flwr.common.context import Context from flwr.common.message import Message @@ -56,7 +56,7 @@ class Flower: def __init__( self, client_fn: ClientFn, # Only for backward compatibility - layers: Optional[List[Layer]] = None, + mods: Optional[List[Mod]] = None, ) -> None: # Create wrapper function for `handle` def ffn( @@ -68,8 +68,8 @@ def ffn( ) return out_message - # Wrap middleware layers around the wrapped handle function - self._call = make_ffn(ffn, layers if layers is not None else []) + # Wrap mods around the wrapped handle function + self._call = make_ffn(ffn, mods if mods is not None else []) def __call__(self, message: Message, context: Context) -> Message: """.""" diff --git a/src/py/flwr/client/message_handler/message_handler.py b/src/py/flwr/client/message_handler/message_handler.py index e61e151da5e9..451da089eaf0 100644 --- a/src/py/flwr/client/message_handler/message_handler.py +++ b/src/py/flwr/client/message_handler/message_handler.py @@ -107,7 +107,7 @@ def handle_control_message(message: Message) -> Tuple[Optional[Message], int]: def handle_legacy_message_from_tasktype( client_fn: ClientFn, message: Message, context: Context ) -> Message: - """Handle legacy message in the inner most middleware layer.""" + """Handle legacy message in the inner most mod.""" client = client_fn("-1") client.set_context(context) diff --git a/src/py/flwr/client/middleware/__init__.py b/src/py/flwr/client/mod/__init__.py similarity index 85% rename from src/py/flwr/client/middleware/__init__.py rename to src/py/flwr/client/mod/__init__.py index 2cab6e61899c..a181865614df 100644 --- a/src/py/flwr/client/middleware/__init__.py +++ b/src/py/flwr/client/mod/__init__.py @@ -12,13 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Middleware layers.""" +"""Mods.""" -from .secure_aggregation.secaggplus_middleware import secaggplus_middleware +from .secure_aggregation.secaggplus_mod import secaggplus_mod from .utils import make_ffn __all__ = [ "make_ffn", - "secaggplus_middleware", + "secaggplus_mod", ] diff --git a/src/py/flwr/client/middleware/secure_aggregation/__init__.py b/src/py/flwr/client/mod/secure_aggregation/__init__.py similarity index 85% rename from src/py/flwr/client/middleware/secure_aggregation/__init__.py rename to src/py/flwr/client/mod/secure_aggregation/__init__.py index 353828b02517..863c149f952e 100644 --- a/src/py/flwr/client/middleware/secure_aggregation/__init__.py +++ b/src/py/flwr/client/mod/secure_aggregation/__init__.py @@ -12,9 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Secure Aggregation handlers.""" -from .secaggplus_middleware import secaggplus_middleware +"""Secure Aggregation mods.""" + + +from .secaggplus_mod import secaggplus_mod __all__ = [ - "secaggplus_middleware", + "secaggplus_mod", ] diff --git a/src/py/flwr/client/middleware/secure_aggregation/secaggplus_middleware.py b/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py similarity index 99% rename from src/py/flwr/client/middleware/secure_aggregation/secaggplus_middleware.py rename to src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py index 885dc4d9cbf5..f48563e24f48 100644 --- a/src/py/flwr/client/middleware/secure_aggregation/secaggplus_middleware.py +++ b/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py @@ -161,7 +161,7 @@ def fit() -> FitRes: return fit -def secaggplus_middleware( +def secaggplus_mod( msg: Message, ctxt: Context, call_next: FlowerCallable, diff --git a/src/py/flwr/client/middleware/secure_aggregation/secaggplus_middleware_test.py b/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod_test.py similarity index 98% rename from src/py/flwr/client/middleware/secure_aggregation/secaggplus_middleware_test.py rename to src/py/flwr/client/mod/secure_aggregation/secaggplus_mod_test.py index 8ec52d71cbdd..80d607318651 100644 --- a/src/py/flwr/client/middleware/secure_aggregation/secaggplus_middleware_test.py +++ b/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod_test.py @@ -18,7 +18,7 @@ from itertools import product from typing import Callable, Dict, List -from flwr.client.middleware import make_ffn +from flwr.client.mod import make_ffn from flwr.common.configsrecord import ConfigsRecord from flwr.common.constant import TASK_TYPE_FIT from flwr.common.context import Context @@ -47,7 +47,7 @@ ) from flwr.common.typing import ConfigsRecordValues -from .secaggplus_middleware import SecAggPlusState, check_configs, secaggplus_middleware +from .secaggplus_mod import SecAggPlusState, check_configs, secaggplus_mod def get_test_handler( @@ -61,7 +61,7 @@ def empty_ffn(_: Message, _2: Context) -> Message: message=RecordSet(), ) - app = make_ffn(empty_ffn, [secaggplus_middleware]) + app = make_ffn(empty_ffn, [secaggplus_mod]) def func(configs: Dict[str, ConfigsRecordValues]) -> Dict[str, ConfigsRecordValues]: in_msg = Message( diff --git a/src/py/flwr/client/middleware/utils.py b/src/py/flwr/client/mod/utils.py similarity index 71% rename from src/py/flwr/client/middleware/utils.py rename to src/py/flwr/client/mod/utils.py index 6d24da558576..36e29d41e6ac 100644 --- a/src/py/flwr/client/middleware/utils.py +++ b/src/py/flwr/client/mod/utils.py @@ -12,26 +12,26 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Utility functions for middleware layers.""" +"""Utility functions for mods.""" from typing import List -from flwr.client.typing import FlowerCallable, Layer +from flwr.client.typing import FlowerCallable, Mod from flwr.common.context import Context from flwr.common.message import Message -def make_ffn(ffn: FlowerCallable, layers: List[Layer]) -> FlowerCallable: +def make_ffn(ffn: FlowerCallable, mods: List[Mod]) -> FlowerCallable: """.""" - def wrap_ffn(_ffn: FlowerCallable, _layer: Layer) -> FlowerCallable: + def wrap_ffn(_ffn: FlowerCallable, _mod: Mod) -> FlowerCallable: def new_ffn(message: Message, context: Context) -> Message: - return _layer(message, context, _ffn) + return _mod(message, context, _ffn) return new_ffn - for layer in reversed(layers): - ffn = wrap_ffn(ffn, layer) + for mod in reversed(mods): + ffn = wrap_ffn(ffn, mod) return ffn diff --git a/src/py/flwr/client/middleware/utils_test.py b/src/py/flwr/client/mod/utils_test.py similarity index 78% rename from src/py/flwr/client/middleware/utils_test.py rename to src/py/flwr/client/mod/utils_test.py index a4e1f6e87599..cbbf3af6d2b3 100644 --- a/src/py/flwr/client/middleware/utils_test.py +++ b/src/py/flwr/client/mod/utils_test.py @@ -18,7 +18,7 @@ import unittest from typing import List -from flwr.client.typing import FlowerCallable, Layer +from flwr.client.typing import FlowerCallable, Mod from flwr.common.configsrecord import ConfigsRecord from flwr.common.context import Context from flwr.common.message import Message, Metadata @@ -39,22 +39,22 @@ def _increment_context_counter(context: Context) -> None: context.state.set_metrics(METRIC, record=MetricsRecord({COUNTER: current_counter})) -def make_mock_middleware(name: str, footprint: List[str]) -> Layer: - """Make a mock middleware layer.""" +def make_mock_mod(name: str, footprint: List[str]) -> Mod: + """Make a mock mod.""" - def middleware(message: Message, context: Context, app: FlowerCallable) -> Message: + def mod(message: Message, context: Context, app: FlowerCallable) -> Message: footprint.append(name) - # add empty ConfigRecord to in_message for this middleware layer + # add empty ConfigRecord to in_message for this mod message.message.set_configs(name=name, record=ConfigsRecord()) _increment_context_counter(context) out_message: Message = app(message, context) footprint.append(name) _increment_context_counter(context) - # add empty ConfigRegcord to out_message for this middleware layer + # add empty ConfigRegcord to out_message for this mod out_message.message.set_configs(name=name, record=ConfigsRecord()) return out_message - return middleware + return mod def make_mock_app(name: str, footprint: List[str]) -> FlowerCallable: @@ -81,15 +81,13 @@ def _get_dummy_flower_message() -> Message: class TestMakeApp(unittest.TestCase): """Tests for the `make_app` function.""" - def test_multiple_middlewares(self) -> None: - """Test if multiple middlewares are called in the correct order.""" + def test_multiple_mods(self) -> None: + """Test if multiple mods are called in the correct order.""" # Prepare footprint: List[str] = [] mock_app = make_mock_app("app", footprint) - mock_middleware_names = [f"middleware{i}" for i in range(1, 15)] - mock_middleware_layers = [ - make_mock_middleware(name, footprint) for name in mock_middleware_names - ] + mock_mod_names = [f"mod{i}" for i in range(1, 15)] + mock_mods = [make_mock_mod(name, footprint) for name in mock_mod_names] state = RecordSet() state.set_metrics(METRIC, record=MetricsRecord({COUNTER: 0.0})) @@ -97,30 +95,28 @@ def test_multiple_middlewares(self) -> None: message = _get_dummy_flower_message() # Execute - wrapped_app = make_ffn(mock_app, mock_middleware_layers) + wrapped_app = make_ffn(mock_app, mock_mods) out_message = wrapped_app(message, context) # Assert - trace = mock_middleware_names + ["app"] - self.assertEqual(footprint, trace + list(reversed(mock_middleware_names))) + trace = mock_mod_names + ["app"] + self.assertEqual(footprint, trace + list(reversed(mock_mod_names))) # pylint: disable-next=no-member self.assertEqual("".join(message.message.configs.keys()), "".join(trace)) self.assertEqual( "".join(out_message.message.configs.keys()), "".join(reversed(trace)) ) - self.assertEqual( - state.get_metrics(METRIC)[COUNTER], 2 * len(mock_middleware_layers) - ) + self.assertEqual(state.get_metrics(METRIC)[COUNTER], 2 * len(mock_mods)) def test_filter(self) -> None: - """Test if a middleware can filter incoming TaskIns.""" + """Test if a mod can filter incoming TaskIns.""" # Prepare footprint: List[str] = [] mock_app = make_mock_app("app", footprint) context = Context(state=RecordSet()) message = _get_dummy_flower_message() - def filter_layer( + def filter_mod( message: Message, _1: Context, _2: FlowerCallable, @@ -133,7 +129,7 @@ def filter_layer( return out_message # Execute - wrapped_app = make_ffn(mock_app, [filter_layer]) + wrapped_app = make_ffn(mock_app, [filter_mod]) out_message = wrapped_app(message, context) # Assert diff --git a/src/py/flwr/client/typing.py b/src/py/flwr/client/typing.py index 18ddcb62f23f..d875bab87538 100644 --- a/src/py/flwr/client/typing.py +++ b/src/py/flwr/client/typing.py @@ -21,6 +21,8 @@ from .client import Client as Client -FlowerCallable = Callable[[Message, Context], Message] +# Compatibility ClientFn = Callable[[str], Client] -Layer = Callable[[Message, Context, FlowerCallable], Message] + +FlowerCallable = Callable[[Message, Context], Message] +Mod = Callable[[Message, Context, FlowerCallable], Message] diff --git a/src/py/flwr/common/context.py b/src/py/flwr/common/context.py index ad859d4c8407..30c1131a206f 100644 --- a/src/py/flwr/common/context.py +++ b/src/py/flwr/common/context.py @@ -30,7 +30,7 @@ class Context: Holds records added by the entity in a given run and that will stay local. This means that the data it holds will never leave the system it's running from. This can be used as an intermediate storage or scratchpad when - executing middleware layers. It can also be used as a memory to access + executing mods. It can also be used as a memory to access at different points during the lifecycle of this entity (e.g. across multiple rounds) """ From 946379a9da73550dfe1a67aca9a5692611ca953f Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Fri, 9 Feb 2024 20:31:24 +0100 Subject: [PATCH 084/113] Rename Flower callable to ClientApp (#2915) --- doc/source/how-to-use-built-in-mods.rst | 26 +++++----- e2e/bare-https/client.py | 2 +- e2e/bare/client.py | 2 +- e2e/fastai/client.py | 2 +- e2e/jax/client.py | 2 +- e2e/opacus/client.py | 2 +- e2e/pandas/client.py | 3 +- e2e/pytorch-lightning/client.py | 2 +- e2e/pytorch/client.py | 2 +- e2e/scikit-learn/client.py | 2 +- e2e/strategies/client.py | 2 +- e2e/tabnet/client.py | 2 +- e2e/tensorflow/client.py | 2 +- e2e/test_driver.sh | 4 +- examples/mt-pytorch-callable/README.md | 4 +- examples/mt-pytorch-callable/client.py | 4 +- examples/secaggplus-mt/client.py | 4 +- examples/secaggplus-mt/run.sh | 4 +- src/py/flwr/__init__.py | 3 +- src/py/flwr/client/__init__.py | 2 + src/py/flwr/client/app.py | 52 +++++++++---------- .../flwr/client/{flower.py => clientapp.py} | 46 ++++++++-------- .../mod/secure_aggregation/secaggplus_mod.py | 6 +-- src/py/flwr/client/mod/utils.py | 6 +-- src/py/flwr/client/mod/utils_test.py | 8 +-- src/py/flwr/client/typing.py | 5 +- src/py/flwr/flower/__init__.py | 22 -------- 27 files changed, 100 insertions(+), 121 deletions(-) rename src/py/flwr/client/{flower.py => clientapp.py} (73%) delete mode 100644 src/py/flwr/flower/__init__.py diff --git a/doc/source/how-to-use-built-in-mods.rst b/doc/source/how-to-use-built-in-mods.rst index 5d4ec782a138..af7102de9d0b 100644 --- a/doc/source/how-to-use-built-in-mods.rst +++ b/doc/source/how-to-use-built-in-mods.rst @@ -3,25 +3,25 @@ Use Built-in Mods **Note: This tutorial covers experimental features. The functionality and interfaces may change in future versions.** -In this tutorial, we will learn how to utilize built-in mods to augment the behavior of a ``FlowerCallable``. Mods (sometimes also called Modifiers) allow us to perform operations before and after a task is processed in the ``FlowerCallable``. +In this tutorial, we will learn how to utilize built-in mods to augment the behavior of a ``ClientApp``. Mods (sometimes also called Modifiers) allow us to perform operations before and after a task is processed in the ``ClientApp``. What are Mods? -------------- -A Mod is a callable that wraps around a ``FlowerCallable``. It can manipulate or inspect the incoming ``Message`` and the resulting outgoing ``Message``. The signature for a ``Mod`` is as follows: +A Mod is a callable that wraps around a ``ClientApp``. It can manipulate or inspect the incoming ``Message`` and the resulting outgoing ``Message``. The signature for a ``Mod`` is as follows: .. code-block:: python - FlowerCallable = Callable[[Fwd], Bwd] - Mod = Callable[[Fwd, FlowerCallable], Bwd] + ClientApp = Callable[[Message, Context], Message] + Mod = Callable[[Message, Context, ClientApp], Message] A typical mod function might look something like this: .. code-block:: python - def example_mod(msg: Message, ctx: Context, nxt: FlowerCallable) -> Message: + def example_mod(msg: Message, ctx: Context, nxt: ClientApp) -> Message: # Do something with incoming Message (or Context) - # before passing to the inner ``FlowerCallable`` + # before passing to the inner ``ClientApp`` msg = nxt(msg, ctx) # Do something with outgoing Message (or Context) # before returning @@ -30,7 +30,7 @@ A typical mod function might look something like this: Using Mods ---------- -To use mods in your ``FlowerCallable``, you can follow these steps: +To use mods in your ``ClientApp``, you can follow these steps: 1. Import the required mods ~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -53,14 +53,14 @@ Define your client function (``client_fn``) that will be wrapped by the mod(s): # Your client code goes here. return # your client -3. Create the ``FlowerCallable`` with mods +3. Create the ``ClientApp`` with mods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Create your ``FlowerCallable`` and pass the mods as a list to the ``mods`` argument. The order in which you provide the mods matters: +Create your ``ClientApp`` and pass the mods as a list to the ``mods`` argument. The order in which you provide the mods matters: .. code-block:: python - flower = fl.app.Flower( + app = fl.client.ClientApp( client_fn=client_fn, mods=[ example_mod_1, # Mod 1 @@ -71,7 +71,7 @@ Create your ``FlowerCallable`` and pass the mods as a list to the ``mods`` argum Order of execution ------------------ -When the ``FlowerCallable`` runs, the mods are executed in the order they are provided in the list: +When the ``ClientApp`` runs, the mods are executed in the order they are provided in the list: 1. ``example_mod_1`` (outermost mod) 2. ``example_mod_2`` (next mod) @@ -84,6 +84,6 @@ Each mod has a chance to inspect and modify the incoming ``Message`` before pass Conclusion ---------- -By following this guide, you have learned how to effectively use mods to enhance your ``FlowerCallable``'s functionality. Remember that the order of mods is crucial and affects how the input and output are processed. +By following this guide, you have learned how to effectively use mods to enhance your ``ClientApp``'s functionality. Remember that the order of mods is crucial and affects how the input and output are processed. -Enjoy building more robust and flexible ``FlowerCallable``s with mods! +Enjoy building more robust and flexible ``ClientApp``s with mods! diff --git a/e2e/bare-https/client.py b/e2e/bare-https/client.py index 04563acdd73f..b4570b36512d 100644 --- a/e2e/bare-https/client.py +++ b/e2e/bare-https/client.py @@ -25,7 +25,7 @@ def evaluate(self, parameters, config): def client_fn(cid): return FlowerClient().to_client() -flower = fl.flower.Flower( +app = fl.client.ClientApp( client_fn=client_fn, ) diff --git a/e2e/bare/client.py b/e2e/bare/client.py index 1068bd7da6d1..a9425b39778a 100644 --- a/e2e/bare/client.py +++ b/e2e/bare/client.py @@ -46,7 +46,7 @@ def evaluate(self, parameters, config): def client_fn(cid): return FlowerClient().to_client() -flower = fl.flower.Flower( +app = fl.client.ClientApp( client_fn=client_fn, ) diff --git a/e2e/fastai/client.py b/e2e/fastai/client.py index 69b20f7e26c3..c4bfb89c2dde 100644 --- a/e2e/fastai/client.py +++ b/e2e/fastai/client.py @@ -53,7 +53,7 @@ def client_fn(cid): return FlowerClient().to_client() -flower = fl.flower.Flower( +app = fl.client.ClientApp( client_fn=client_fn, ) diff --git a/e2e/jax/client.py b/e2e/jax/client.py index 1536487dd466..a4e4d1f55117 100644 --- a/e2e/jax/client.py +++ b/e2e/jax/client.py @@ -53,7 +53,7 @@ def evaluate( def client_fn(cid): return FlowerClient().to_client() -flower = fl.flower.Flower( +app = fl.client.ClientApp( client_fn=client_fn, ) diff --git a/e2e/opacus/client.py b/e2e/opacus/client.py index 205bc39adbac..00437a31233c 100644 --- a/e2e/opacus/client.py +++ b/e2e/opacus/client.py @@ -137,7 +137,7 @@ def client_fn(cid): model = Net() return FlowerClient(model).to_client() -flower = fl.flower.Flower( +app = fl.client.ClientApp( client_fn=client_fn, ) diff --git a/e2e/pandas/client.py b/e2e/pandas/client.py index efc2eb763f53..0ecd75df3ae8 100644 --- a/e2e/pandas/client.py +++ b/e2e/pandas/client.py @@ -1,4 +1,3 @@ -import warnings from typing import Dict, List, Tuple import numpy as np @@ -36,7 +35,7 @@ def fit( def client_fn(cid): return FlowerClient().to_client() -flower = fl.flower.Flower( +app = fl.client.ClientApp( client_fn=client_fn, ) diff --git a/e2e/pytorch-lightning/client.py b/e2e/pytorch-lightning/client.py index 632683e8ec01..fde550e31c08 100644 --- a/e2e/pytorch-lightning/client.py +++ b/e2e/pytorch-lightning/client.py @@ -55,7 +55,7 @@ def client_fn(cid): # Flower client return FlowerClient(model, train_loader, val_loader, test_loader).to_client() -flower = fl.flower.Flower( +app = fl.client.ClientApp( client_fn=client_fn, ) diff --git a/e2e/pytorch/client.py b/e2e/pytorch/client.py index cce4701ff6e6..0f1b8e159f7d 100644 --- a/e2e/pytorch/client.py +++ b/e2e/pytorch/client.py @@ -126,7 +126,7 @@ def set_parameters(model, parameters): def client_fn(cid): return FlowerClient().to_client() -flower = fl.flower.Flower( +app = fl.client.ClientApp( client_fn=client_fn, ) diff --git a/e2e/scikit-learn/client.py b/e2e/scikit-learn/client.py index e137a28c356b..e073d3cb2748 100644 --- a/e2e/scikit-learn/client.py +++ b/e2e/scikit-learn/client.py @@ -46,7 +46,7 @@ def evaluate(self, parameters, config): # type: ignore def client_fn(cid): return FlowerClient().to_client() -flower = fl.flower.Flower( +app = fl.client.ClientApp( client_fn=client_fn, ) diff --git a/e2e/strategies/client.py b/e2e/strategies/client.py index 5a341d041f12..3b49f770dc6b 100644 --- a/e2e/strategies/client.py +++ b/e2e/strategies/client.py @@ -47,7 +47,7 @@ def client_fn(cid): return FlowerClient().to_client() -flower = fl.flower.Flower( +app = fl.client.ClientApp( client_fn=client_fn, ) diff --git a/e2e/tabnet/client.py b/e2e/tabnet/client.py index 5e3a5e52680b..0290ba4629de 100644 --- a/e2e/tabnet/client.py +++ b/e2e/tabnet/client.py @@ -81,7 +81,7 @@ def evaluate(self, parameters, config): def client_fn(cid): return FlowerClient().to_client() -flower = fl.flower.Flower( +app = fl.client.ClientApp( client_fn=client_fn, ) diff --git a/e2e/tensorflow/client.py b/e2e/tensorflow/client.py index fc5eb5ab39b3..10ee91136241 100644 --- a/e2e/tensorflow/client.py +++ b/e2e/tensorflow/client.py @@ -34,7 +34,7 @@ def evaluate(self, parameters, config): def client_fn(cid): return FlowerClient().to_client() -flower = fl.flower.Flower( +app = fl.client.ClientApp( client_fn=client_fn, ) diff --git a/e2e/test_driver.sh b/e2e/test_driver.sh index bcf796bd78bb..989f89039019 100755 --- a/e2e/test_driver.sh +++ b/e2e/test_driver.sh @@ -34,10 +34,10 @@ esac timeout 2m flower-server $server_arg $db_arg $rest_arg & sleep 3 -timeout 2m flower-client client:flower $client_arg $rest_arg --server $server_address & +timeout 2m flower-client client:app $client_arg $rest_arg --server $server_address & sleep 3 -timeout 2m flower-client client:flower $client_arg $rest_arg --server $server_address & +timeout 2m flower-client client:app $client_arg $rest_arg --server $server_address & sleep 3 timeout 2m python driver.py & diff --git a/examples/mt-pytorch-callable/README.md b/examples/mt-pytorch-callable/README.md index 120e28098344..5bfa94d026e5 100644 --- a/examples/mt-pytorch-callable/README.md +++ b/examples/mt-pytorch-callable/README.md @@ -33,13 +33,13 @@ flower-server --insecure In a new terminal window, start the first long-running Flower client: ```bash -flower-client --insecure client:flower +flower-client client:app --insecure ``` In yet another new terminal window, start the second long-running Flower client: ```bash -flower-client --insecure client:flower +flower-client client:app --insecure ``` ## Start the Driver script diff --git a/examples/mt-pytorch-callable/client.py b/examples/mt-pytorch-callable/client.py index 4195a714ca89..ca88fc3c9824 100644 --- a/examples/mt-pytorch-callable/client.py +++ b/examples/mt-pytorch-callable/client.py @@ -108,8 +108,8 @@ def client_fn(cid: str): return FlowerClient().to_client() -# To run this: `flower-client client:flower` -flower = fl.flower.Flower( +# To run this: `flower-client client:app` +app = fl.client.ClientApp( client_fn=client_fn, ) diff --git a/examples/secaggplus-mt/client.py b/examples/secaggplus-mt/client.py index 92c5bf7317cc..dc9deef7d605 100644 --- a/examples/secaggplus-mt/client.py +++ b/examples/secaggplus-mt/client.py @@ -32,8 +32,8 @@ def client_fn(cid: str): return FlowerClient().to_client() -# To run this: `flower-client --callable client:flower` -flower = fl.flower.Flower( +# To run this: `flower-client client:app` +app = fl.client.ClientApp( client_fn=client_fn, mods=[secaggplus_mod], ) diff --git a/examples/secaggplus-mt/run.sh b/examples/secaggplus-mt/run.sh index 852798c0ab21..e2c16bbe3541 100755 --- a/examples/secaggplus-mt/run.sh +++ b/examples/secaggplus-mt/run.sh @@ -18,7 +18,7 @@ echo "Starting $N clients in background..." # Start N client processes for i in $(seq 1 $N) do - flower-client --insecure client:flower > /dev/null 2>&1 & + flower-client --insecure client:app > /dev/null 2>&1 & sleep 0.1 done @@ -31,4 +31,4 @@ echo "Clearing background processes..." pkill -f 'flower-client' # Kill any currently running flower-server processes -pkill -f 'flower-server' \ No newline at end of file +pkill -f 'flower-server' diff --git a/src/py/flwr/__init__.py b/src/py/flwr/__init__.py index e05799280339..d3cbf00747a4 100644 --- a/src/py/flwr/__init__.py +++ b/src/py/flwr/__init__.py @@ -17,13 +17,12 @@ from flwr.common.version import package_version as _package_version -from . import client, common, driver, flower, server, simulation +from . import client, common, driver, server, simulation __all__ = [ "client", "common", "driver", - "flower", "server", "simulation", ] diff --git a/src/py/flwr/client/__init__.py b/src/py/flwr/client/__init__.py index 13540a76cc25..a3bd3bf33e78 100644 --- a/src/py/flwr/client/__init__.py +++ b/src/py/flwr/client/__init__.py @@ -19,11 +19,13 @@ from .app import start_client as start_client from .app import start_numpy_client as start_numpy_client from .client import Client as Client +from .clientapp import ClientApp as ClientApp from .numpy_client import NumPyClient as NumPyClient from .typing import ClientFn as ClientFn __all__ = [ "Client", + "ClientApp", "ClientFn", "NumPyClient", "run_client", diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index ba20c2fdb7b5..56520f76db6c 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -23,7 +23,7 @@ from typing import Callable, ContextManager, Optional, Tuple, Union from flwr.client.client import Client -from flwr.client.flower import Flower +from flwr.client.clientapp import ClientApp from flwr.client.typing import ClientFn from flwr.common import GRPC_MAX_MESSAGE_LENGTH, EventType, event from flwr.common.address import parse_address @@ -37,7 +37,7 @@ from flwr.common.logger import log, warn_deprecated_feature, warn_experimental_feature from flwr.common.message import Message -from .flower import load_flower_callable +from .clientapp import load_client_app from .grpc_client.connection import grpc_connection from .grpc_rere_client.connection import grpc_request_response from .message_handler.message_handler import handle_control_message @@ -86,21 +86,21 @@ def run_client() -> None: log( DEBUG, - "The Flower client uses `%s` to execute tasks", - args.callable, + "Flower will load ClientApp `%s` to execute tasks", + getattr(args, "client-app"), ) - callable_dir = args.dir - if callable_dir is not None: - sys.path.insert(0, callable_dir) + client_app_dir = args.dir + if client_app_dir is not None: + sys.path.insert(0, client_app_dir) - def _load() -> Flower: - flower: Flower = load_flower_callable(args.callable) - return flower + def _load() -> ClientApp: + client_app: ClientApp = load_client_app(getattr(args, "client-app")) + return client_app _start_client_internal( server_address=args.server, - load_flower_callable_fn=_load, + load_client_app_fn=_load, transport="rest" if args.rest else "grpc-rere", root_certificates=root_certificates, insecure=args.insecure, @@ -115,8 +115,8 @@ def _parse_args_client() -> argparse.ArgumentParser: ) parser.add_argument( - "callable", - help="For example: `client:flower` or `project.package.module:wrapper.flower`", + "client-app", + help="For example: `client:app` or `project.package.module:wrapper.app`", ) parser.add_argument( "--insecure", @@ -247,7 +247,7 @@ class `flwr.client.Client` (default: None) event(EventType.START_CLIENT_ENTER) _start_client_internal( server_address=server_address, - load_flower_callable_fn=None, + load_client_app_fn=None, client_fn=client_fn, client=client, grpc_max_message_length=grpc_max_message_length, @@ -265,7 +265,7 @@ class `flwr.client.Client` (default: None) def _start_client_internal( *, server_address: str, - load_flower_callable_fn: Optional[Callable[[], Flower]] = None, + load_client_app_fn: Optional[Callable[[], ClientApp]] = None, client_fn: Optional[ClientFn] = None, client: Optional[Client] = None, grpc_max_message_length: int = GRPC_MAX_MESSAGE_LENGTH, @@ -281,8 +281,8 @@ def _start_client_internal( The IPv4 or IPv6 address of the server. If the Flower server runs on the same machine on port 8080, then `server_address` would be `"[::]:8080"`. - load_flower_callable_fn : Optional[Callable[[], Flower]] (default: None) - A function that can be used to load a `Flower` callable instance. + load_client_app_fn : Optional[Callable[[], ClientApp]] (default: None) + A function that can be used to load a `ClientApp` instance. client_fn : Optional[ClientFn] A callable that instantiates a Client. (default: None) client : Optional[flwr.client.Client] @@ -311,7 +311,7 @@ class `flwr.client.Client` (default: None) if insecure is None: insecure = root_certificates is None - if load_flower_callable_fn is None: + if load_client_app_fn is None: _check_actionable_client(client, client_fn) if client_fn is None: @@ -327,14 +327,14 @@ def single_client_factory( client_fn = single_client_factory - def _load_app() -> Flower: - return Flower(client_fn=client_fn) + def _load_client_app() -> ClientApp: + return ClientApp(client_fn=client_fn) - load_flower_callable_fn = _load_app + load_client_app_fn = _load_client_app else: - warn_experimental_feature("`load_flower_callable_fn`") + warn_experimental_feature("`load_client_app_fn`") - # At this point, only `load_flower_callable_fn` should be used + # At this point, only `load_client_app_fn` should be used # Both `client` and `client_fn` must not be used directly # Initialize connection context manager @@ -375,11 +375,11 @@ def _load_app() -> Flower: # Retrieve context for this run context = node_state.retrieve_context(run_id=message.metadata.run_id) - # Load app - app: Flower = load_flower_callable_fn() + # Load ClientApp instance + client_app: ClientApp = load_client_app_fn() # Handle task message - out_message = app(message=message, context=context) + out_message = client_app(message=message, context=context) # Update node state node_state.update_context( diff --git a/src/py/flwr/client/flower.py b/src/py/flwr/client/clientapp.py similarity index 73% rename from src/py/flwr/client/flower.py rename to src/py/flwr/client/clientapp.py index b096a1003b19..fbd443cc7500 100644 --- a/src/py/flwr/client/flower.py +++ b/src/py/flwr/client/clientapp.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Flower callable.""" +"""Flower ClientApp.""" import importlib @@ -27,13 +27,13 @@ from flwr.common.message import Message -class Flower: - """Flower callable. +class ClientApp: + """Flower ClientApp. Examples -------- - Assuming a typical client implementation in `FlowerClient`, you can wrap it in a - Flower callable as follows: + Assuming a typical `Client` implementation named `FlowerClient`, you can wrap it in + a `ClientApp` as follows: >>> class FlowerClient(NumPyClient): >>> # ... @@ -41,16 +41,16 @@ class Flower: >>> def client_fn(cid): >>> return FlowerClient().to_client() >>> - >>> flower = Flower(client_fn) + >>> app = ClientApp(client_fn) If the above code is in a Python module called `client`, it can be started as follows: - >>> flower-client --callable client:flower + >>> flower-client client:app --insecure - In this `client:flower` example, `client` refers to the Python module in which the - previous code lives in. `flower` refers to the global attribute `flower` that points - to an object of type `Flower` (a Flower callable). + In this `client:app` example, `client` refers to the Python module `client.py` in + which the previous code lives in and `app` refers to the global attribute `app` that + points to an object of type `ClientApp`. """ def __init__( @@ -76,25 +76,25 @@ def __call__(self, message: Message, context: Context) -> Message: return self._call(message, context) -class LoadCallableError(Exception): +class LoadClientAppError(Exception): """.""" -def load_flower_callable(module_attribute_str: str) -> Flower: - """Load the `Flower` object specified in a module attribute string. +def load_client_app(module_attribute_str: str) -> ClientApp: + """Load the `ClientApp` object specified in a module attribute string. The module/attribute string should have the form :. Valid - examples include `client:flower` and `project.package.module:wrapper.flower`. It + examples include `client:app` and `project.package.module:wrapper.app`. It must refer to a module on the PYTHONPATH, the module needs to have the specified - attribute, and the attribute must be of type `Flower`. + attribute, and the attribute must be of type `ClientApp`. """ module_str, _, attributes_str = module_attribute_str.partition(":") if not module_str: - raise LoadCallableError( + raise LoadClientAppError( f"Missing module in {module_attribute_str}", ) from None if not attributes_str: - raise LoadCallableError( + raise LoadClientAppError( f"Missing attribute in {module_attribute_str}", ) from None @@ -102,7 +102,7 @@ def load_flower_callable(module_attribute_str: str) -> Flower: try: module = importlib.import_module(module_str) except ModuleNotFoundError: - raise LoadCallableError( + raise LoadClientAppError( f"Unable to load module {module_str}", ) from None @@ -112,14 +112,14 @@ def load_flower_callable(module_attribute_str: str) -> Flower: for attribute_str in attributes_str.split("."): attribute = getattr(attribute, attribute_str) except AttributeError: - raise LoadCallableError( + raise LoadClientAppError( f"Unable to load attribute {attributes_str} from module {module_str}", ) from None # Check type - if not isinstance(attribute, Flower): - raise LoadCallableError( - f"Attribute {attributes_str} is not of type {Flower}", + if not isinstance(attribute, ClientApp): + raise LoadClientAppError( + f"Attribute {attributes_str} is not of type {ClientApp}", ) from None - return cast(Flower, attribute) + return cast(ClientApp, attribute) diff --git a/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py b/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py index f48563e24f48..850e02a2b5f9 100644 --- a/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py +++ b/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py @@ -20,7 +20,7 @@ from logging import INFO, WARNING from typing import Any, Callable, Dict, List, Tuple, cast -from flwr.client.typing import FlowerCallable +from flwr.client.typing import ClientAppCallable from flwr.common import ndarray_to_bytes, parameters_to_ndarrays from flwr.common import recordset_compat as compat from flwr.common.configsrecord import ConfigsRecord @@ -150,7 +150,7 @@ def to_dict(self) -> Dict[str, ConfigsRecordValues]: def _get_fit_fn( - msg: Message, ctxt: Context, call_next: FlowerCallable + msg: Message, ctxt: Context, call_next: ClientAppCallable ) -> Callable[[], FitRes]: """Get the fit function.""" @@ -164,7 +164,7 @@ def fit() -> FitRes: def secaggplus_mod( msg: Message, ctxt: Context, - call_next: FlowerCallable, + call_next: ClientAppCallable, ) -> Message: """Handle incoming message and return results, following the SecAgg+ protocol.""" # Ignore non-fit messages diff --git a/src/py/flwr/client/mod/utils.py b/src/py/flwr/client/mod/utils.py index 36e29d41e6ac..3db5da563c23 100644 --- a/src/py/flwr/client/mod/utils.py +++ b/src/py/flwr/client/mod/utils.py @@ -17,15 +17,15 @@ from typing import List -from flwr.client.typing import FlowerCallable, Mod +from flwr.client.typing import ClientAppCallable, Mod from flwr.common.context import Context from flwr.common.message import Message -def make_ffn(ffn: FlowerCallable, mods: List[Mod]) -> FlowerCallable: +def make_ffn(ffn: ClientAppCallable, mods: List[Mod]) -> ClientAppCallable: """.""" - def wrap_ffn(_ffn: FlowerCallable, _mod: Mod) -> FlowerCallable: + def wrap_ffn(_ffn: ClientAppCallable, _mod: Mod) -> ClientAppCallable: def new_ffn(message: Message, context: Context) -> Message: return _mod(message, context, _ffn) diff --git a/src/py/flwr/client/mod/utils_test.py b/src/py/flwr/client/mod/utils_test.py index cbbf3af6d2b3..782ca8b0f97e 100644 --- a/src/py/flwr/client/mod/utils_test.py +++ b/src/py/flwr/client/mod/utils_test.py @@ -18,7 +18,7 @@ import unittest from typing import List -from flwr.client.typing import FlowerCallable, Mod +from flwr.client.typing import ClientAppCallable, Mod from flwr.common.configsrecord import ConfigsRecord from flwr.common.context import Context from flwr.common.message import Message, Metadata @@ -42,7 +42,7 @@ def _increment_context_counter(context: Context) -> None: def make_mock_mod(name: str, footprint: List[str]) -> Mod: """Make a mock mod.""" - def mod(message: Message, context: Context, app: FlowerCallable) -> Message: + def mod(message: Message, context: Context, app: ClientAppCallable) -> Message: footprint.append(name) # add empty ConfigRecord to in_message for this mod message.message.set_configs(name=name, record=ConfigsRecord()) @@ -57,7 +57,7 @@ def mod(message: Message, context: Context, app: FlowerCallable) -> Message: return mod -def make_mock_app(name: str, footprint: List[str]) -> FlowerCallable: +def make_mock_app(name: str, footprint: List[str]) -> ClientAppCallable: """Make a mock app.""" def app(message: Message, context: Context) -> Message: @@ -119,7 +119,7 @@ def test_filter(self) -> None: def filter_mod( message: Message, _1: Context, - _2: FlowerCallable, + _2: ClientAppCallable, ) -> Message: footprint.append("filter") message.message.set_configs(name="filter", record=ConfigsRecord()) diff --git a/src/py/flwr/client/typing.py b/src/py/flwr/client/typing.py index d875bab87538..7aef2b30e0fc 100644 --- a/src/py/flwr/client/typing.py +++ b/src/py/flwr/client/typing.py @@ -14,6 +14,7 @@ # ============================================================================== """Custom types for Flower clients.""" + from typing import Callable from flwr.common.context import Context @@ -24,5 +25,5 @@ # Compatibility ClientFn = Callable[[str], Client] -FlowerCallable = Callable[[Message, Context], Message] -Mod = Callable[[Message, Context, FlowerCallable], Message] +ClientAppCallable = Callable[[Message, Context], Message] +Mod = Callable[[Message, Context, ClientAppCallable], Message] diff --git a/src/py/flwr/flower/__init__.py b/src/py/flwr/flower/__init__.py deleted file mode 100644 index 8b566981c77a..000000000000 --- a/src/py/flwr/flower/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2020 Adap GmbH. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Flower callable package.""" - - -from flwr.client.flower import Flower as Flower - -__all__ = [ - "Flower", -] From 3298d0802976936d4a5919358276eda2dc73fdef Mon Sep 17 00:00:00 2001 From: "Weblate (bot)" Date: Sat, 10 Feb 2024 12:49:04 +0100 Subject: [PATCH 085/113] Translations update from Hosted Weblate (#2654) --- .../zh_Hans/LC_MESSAGES/framework-docs.po | 12530 ++++++++++------ 1 file changed, 7611 insertions(+), 4919 deletions(-) diff --git a/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po b/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po index 8e57cbfda0c0..47a12f4437a4 100644 --- a/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po +++ b/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: Flower main\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-11-23 18:31+0100\n" -"PO-Revision-Date: 2023-11-25 19:00+0000\n" +"PO-Revision-Date: 2024-02-09 14:19+0000\n" "Last-Translator: Yan Gao \n" "Language-Team: Chinese (Simplified) \n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 5.2.1-rc\n" +"X-Generator: Weblate 5.4-dev\n" "Generated-By: Babel 2.13.1\n" #: ../../source/contributor-explanation-architecture.rst:2 @@ -30,8 +30,8 @@ msgstr "边缘客户端引擎" #: ../../source/contributor-explanation-architecture.rst:7 msgid "" -"`Flower `_ core framework architecture with Edge " -"Client Engine" +"`Flower `_ core framework architecture with Edge Client " +"Engine" msgstr "具有边缘客户端引擎的`Flower `核心架构" #: ../../source/contributor-explanation-architecture.rst:13 @@ -50,9 +50,10 @@ msgstr "可同步进行的虚拟客户端引擎和边缘客户端引擎" #: ../../source/contributor-explanation-architecture.rst:23 msgid "" -"`Flower `_ core framework architecture with both " -"Virtual Client Engine and Edge Client Engine" -msgstr "具有虚拟客户端引擎和边缘客户端引擎的`Flower `核心架构" +"`Flower `_ core framework architecture with both Virtual " +"Client Engine and Edge Client Engine" +msgstr "" +"具有虚拟客户端引擎和边缘客户端引擎的`Flower `核心架构" #: ../../source/contributor-how-create-new-messages.rst:2 msgid "Creating New Messages" @@ -60,68 +61,74 @@ msgstr "创建新信息" #: ../../source/contributor-how-create-new-messages.rst:4 msgid "" -"This is a simple guide for creating a new type of message between the " -"server and clients in Flower." -msgstr "" +"This is a simple guide for creating a new type of message between the server " +"and clients in Flower." +msgstr "这是一个如何用Flower在服务器和客户端之间创建新类型的信息的简要指导。" #: ../../source/contributor-how-create-new-messages.rst:6 msgid "" -"Let's suppose we have the following example functions in " -":code:`server.py` and :code:`numpy_client.py`..." +"Let's suppose we have the following example functions in :code:`server.py` " +"and :code:`numpy_client.py`..." msgstr "" +"假设我们在脚本code:`server.py`和code:`numpy_client.py`中有以下的示例函数..." #: ../../source/contributor-how-create-new-messages.rst:8 msgid "Server's side:" -msgstr "" +msgstr "在服务器端:" #: ../../source/contributor-how-create-new-messages.rst:17 msgid "Client's side:" -msgstr "" +msgstr "在客户端:" #: ../../source/contributor-how-create-new-messages.rst:26 msgid "" -"Let's now see what we need to implement in order to get this simple " -"function between the server and client to work!" +"Let's now see what we need to implement in order to get this simple function " +"between the server and client to work!" msgstr "" +"现在让我们来看看,为了让服务器和客户端之间的这个简单的函数正常工作,我们需要" +"实现哪些功能!" #: ../../source/contributor-how-create-new-messages.rst:30 msgid "Message Types for Protocol Buffers" -msgstr "" +msgstr "协议缓冲区的信息类型" #: ../../source/contributor-how-create-new-messages.rst:32 msgid "" -"The first thing we need to do is to define a message type for the RPC " -"system in :code:`transport.proto`. Note that we have to do it for both " -"the request and response messages. For more details on the syntax of " -"proto3, please see the `official documentation " -"`_." +"The first thing we need to do is to define a message type for the RPC system " +"in :code:`transport.proto`. Note that we have to do it for both the request " +"and response messages. For more details on the syntax of proto3, please see " +"the `official documentation `_." msgstr "" +"我们需要做的第一件事是在脚本code:`transport.proto`中定义 RPC 系统的消息类型。" +"请注意,我们必须对请求信息和响应信息都这样做。有关 proto3 语法的更多详情,请" +"参阅官方文档 `_。" #: ../../source/contributor-how-create-new-messages.rst:35 msgid "Within the :code:`ServerMessage` block:" -msgstr "" +msgstr "在 :code:`ServerMessage` 代码块中:" #: ../../source/contributor-how-create-new-messages.rst:52 msgid "Within the ClientMessage block:" -msgstr "" +msgstr "在 ClientMessage 代码块中:" #: ../../source/contributor-how-create-new-messages.rst:70 msgid "" -"Make sure to also add a field of the newly created message type in " -":code:`oneof msg`." -msgstr "" +"Make sure to also add a field of the newly created message type in :code:" +"`oneof msg`." +msgstr "确保在 :code:`oneof msg` 中也添加一个新创建的消息类型字段。" #: ../../source/contributor-how-create-new-messages.rst:72 msgid "Once that is done, we will compile the file with:" -msgstr "" +msgstr "完成后,我们将使用:" #: ../../source/contributor-how-create-new-messages.rst:78 msgid "If it compiles succesfully, you should see the following message:" -msgstr "" +msgstr "如果编译成功,你应该会看到以下信息:" #: ../../source/contributor-how-create-new-messages.rst:87 msgid "Serialization and Deserialization Functions" -msgstr "" +msgstr "序列化和反序列化函数" #: ../../source/contributor-how-create-new-messages.rst:89 msgid "" @@ -129,295 +136,364 @@ msgid "" "datatypes to or from our defined RPC message types. You should add these " "functions in :code:`serde.py`." msgstr "" +"下一步是添加函数,以便将 Python 数据类型序列化和反序列化为我们定义的 RPC 消息" +"类型或从我们定义的 RPC 消息类型反序列化和反序列化 Python 数据类型。您应该在 :" +"code:`serde.py` 中添加这些函数。" #: ../../source/contributor-how-create-new-messages.rst:91 msgid "The four functions:" -msgstr "" +msgstr "四种函数:" #: ../../source/contributor-how-create-new-messages.rst:112 msgid "Sending the Message from the Server" -msgstr "" +msgstr "从服务器发送信息" #: ../../source/contributor-how-create-new-messages.rst:114 msgid "" -"Now write the request function in your Client Proxy class (e.g., " -":code:`grpc_client_proxy.py`) using the serde functions you just created:" +"Now write the request function in your Client Proxy class (e.g., :code:" +"`grpc_client_proxy.py`) using the serde functions you just created:" msgstr "" +"现在,在客户端代理类(例如 :code:`grpc_client_proxy.py`)中使用刚才创建的 " +"serde 函数编写请求函数:" #: ../../source/contributor-how-create-new-messages.rst:128 msgid "Receiving the Message by the Client" -msgstr "" +msgstr "由客户端接收信息" #: ../../source/contributor-how-create-new-messages.rst:130 msgid "" -"Last step! Modify the code in :code:`message_handler.py` to check the " -"field of your message and call the :code:`example_response` function. " -"Remember to use the serde functions!" +"Last step! Modify the code in :code:`message_handler.py` to check the field " +"of your message and call the :code:`example_response` function. Remember to " +"use the serde functions!" msgstr "" +"最后一步 修改 :code:`message_handler.py` 中的代码,检查信息的字段并调用 :" +"code:`example_response` 函数。记住使用 serde 函数!" #: ../../source/contributor-how-create-new-messages.rst:132 msgid "Within the handle function:" -msgstr "" +msgstr "在句柄函数内:" #: ../../source/contributor-how-create-new-messages.rst:139 msgid "And add a new function:" -msgstr "" +msgstr "并增加一个新函数:" #: ../../source/contributor-how-create-new-messages.rst:149 msgid "Hopefully, when you run your program you will get the intended result!" -msgstr "" +msgstr "希望您在运行程序时能得到预期的结果!" #: ../../source/contributor-how-to-contribute-translations.rst:2 msgid "Contribute translations" -msgstr "" +msgstr "贡献译文" #: ../../source/contributor-how-to-contribute-translations.rst:4 msgid "" -"Since `Flower 1.5 `_ we have introduced translations to " -"our doc pages, but, as you might have noticed, the translations are often" -" imperfect. If you speak languages other than English, you might be able " -"to help us in our effort to make Federated Learning accessible to as many" -" people as possible by contributing to those translations! This might " -"also be a great opportunity for those wanting to become open source " -"contributors with little prerequistes." -msgstr "" +"Since `Flower 1.5 `_ we have introduced translations to our doc pages, " +"but, as you might have noticed, the translations are often imperfect. If you " +"speak languages other than English, you might be able to help us in our " +"effort to make Federated Learning accessible to as many people as possible " +"by contributing to those translations! This might also be a great " +"opportunity for those wanting to become open source contributors with little " +"prerequistes." +msgstr "" +"从 `Flower 1.5 `_ 开始,我们在文档页面中引入了翻译,但正如你可能已经" +"注意到的,这些翻译往往并不完美。如果您会说英语以外的语言,也许您可以帮助我们" +"翻译这些文档,让更多的人了解 Federated Learning!对于那些想成为开源贡献者的人" +"来说,这也是一个很好的机会。" #: ../../source/contributor-how-to-contribute-translations.rst:13 msgid "" -"Our translation project is publicly available over on `Weblate " -"`_, this " -"where most of the work will happen." +"Our translation project is publicly available over on `Weblate `_, this where most of " +"the work will happen." msgstr "" +"我们的翻译项目已在 \"Weblate `_\"上公开,大部分工作都将在这里进行。" #: ../../source/contributor-how-to-contribute-translations.rst:18 msgid "Contribute to existing languages" -msgstr "" +msgstr "为现有语言作出贡献" #: ../../source/contributor-how-to-contribute-translations.rst:23 msgid "" -"The first thing you will need to do in order to contribute is to create a" -" free Weblate account on this `page " -"`_. More information about" -" profile settings can be found `here " +"The first thing you will need to do in order to contribute is to create a " +"free Weblate account on this `page `_. More information about profile settings can be found `here " "`_." msgstr "" +"您需要做的第一件事就是在本`网页`_上创建一个免费的Weblate帐户。有关个人资料设置的更多信息,请参阅`这里 " +"`_。" #: ../../source/contributor-how-to-contribute-translations.rst:29 msgid "" -"Once you are signed in to Weblate, you can navigate to the `Flower " -"Framework project `_. Here, you should see the different existing languages" -" that can be found on the website." +"Once you are signed in to Weblate, you can navigate to the `Flower Framework " +"project `_. " +"Here, you should see the different existing languages that can be found on " +"the website." msgstr "" +"登录到Weblate后,您可以导航到 \"Flower Framework \"项目`_。在这里,您可以看到网站上现有" +"的各种语言。" #: ../../source/contributor-how-to-contribute-translations.rst:34 msgid "" -"Once you have selected the language you want to contribute to, you should" -" see a similar interface to this:" -msgstr "" +"Once you have selected the language you want to contribute to, you should " +"see a similar interface to this:" +msgstr "选择您要贡献的语言后,您应该会看到与此类似的界面:" #: ../../source/contributor-how-to-contribute-translations.rst:39 msgid "" "The most straight forward option here is to click on the ``Translate`` " -"button on the top right (in the ``Translation status`` section). This " -"will automatically bring you to the translation interface for " -"untranslated strings." +"button on the top right (in the ``Translation status`` section). This will " +"automatically bring you to the translation interface for untranslated " +"strings." msgstr "" +"最简单的方法是点击右上角(\"翻译状态 \"部分)的 \"翻译 \"按钮。这将自动带您进" +"入未翻译字符串的翻译界面。" #: ../../source/contributor-how-to-contribute-translations.rst:43 msgid "This is what the interface looks like:" -msgstr "" +msgstr "这就是界面的样子:" #: ../../source/contributor-how-to-contribute-translations.rst:47 msgid "" -"You input your translation in the textbox at the top and then, once you " -"are happy with it, you either press ``Save and continue`` (to save the " -"translation and go to the next untranslated string), ``Save and stay`` " -"(to save the translation and stay on the same page), ``Suggest`` (to add " -"your translation to suggestions for other users to view), or ``Skip`` (to" -" go to the next untranslated string without saving anything)." +"You input your translation in the textbox at the top and then, once you are " +"happy with it, you either press ``Save and continue`` (to save the " +"translation and go to the next untranslated string), ``Save and stay`` (to " +"save the translation and stay on the same page), ``Suggest`` (to add your " +"translation to suggestions for other users to view), or ``Skip`` (to go to " +"the next untranslated string without saving anything)." msgstr "" +"您可以在顶部的文本框中输入翻译内容,满意后按 \"保存并继续\"(保存翻译内容并转" +"到下一个未翻译的字符串)、\"保存并停留\"(保存翻译内容并停留在同一页" +"面)、\"建议\"(将您的翻译添加到建议中供其他用户查看)或 \"跳过\"(转到下一个" +"未翻译的字符串而不保存任何内容)。" #: ../../source/contributor-how-to-contribute-translations.rst:54 msgid "" "In order to help with the translations, you can see on the bottom the " "``Nearby strings``, the ``Comments`` (from other contributors), the " "``Automatic suggestions`` (from machine translation engines), the " -"translations in ``Other languages``, and the ``History`` of translations " -"for this string." +"translations in ``Other languages``, and the ``History`` of translations for " +"this string." msgstr "" +"为了帮助翻译,您可以在底部看到 \"邻近字符串\"、\"评论\"(来自其他贡献" +"者)、\"自动建议\"(来自机器翻译引擎)、\"其他语言 \"中的翻译以及该字符串的 " +"\"历史翻译\"。" #: ../../source/contributor-how-to-contribute-translations.rst:59 msgid "" -"On the right, under the ``String information`` section, you can also " -"click the link under ``Source string location`` in order to view the " -"source of the doc file containing the string." +"On the right, under the ``String information`` section, you can also click " +"the link under ``Source string location`` in order to view the source of the " +"doc file containing the string." msgstr "" +"在右侧的 \"字符串信息 \"部分,您还可以单击 \"源字符串位置 \"下的链接,以查看" +"包含字符串的 doc 文件的源文件。" #: ../../source/contributor-how-to-contribute-translations.rst:63 msgid "" -"For more information about translating using Weblate, you can check out " -"this `in-depth guide " -"`_." +"For more information about translating using Weblate, you can check out this " +"`in-depth guide `_." msgstr "" +"有关使用 Weblate 进行翻译的更多信息,您可以查看本 \"深入指南 `_\"。" #: ../../source/contributor-how-to-contribute-translations.rst:67 msgid "Add new languages" -msgstr "" +msgstr "添加新语言" #: ../../source/contributor-how-to-contribute-translations.rst:69 msgid "" -"If you want to add a new language, you will first have to contact us, " -"either on `Slack `_, or by opening an " -"issue on our `GitHub repo `_." +"If you want to add a new language, you will first have to contact us, either " +"on `Slack `_, or by opening an issue on our " +"`GitHub repo `_." msgstr "" +"如果您想添加新语言,请先联系我们,可以在 `Slack `_ 上联系,也可以在我们的 `GitHub repo `_ 上提交问题。" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:2 msgid "Develop in VSCode Dev Containers" -msgstr "" +msgstr "使用 VSCode Dev Containers 进行开发" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:4 msgid "" -"When working on the Flower framework we want to ensure that all " -"contributors use the same developer environment to format code or run " -"tests. For this purpose we are using the VSCode Remote Containers " -"extension. What is it? Read the following quote:" +"When working on the Flower framework we want to ensure that all contributors " +"use the same developer environment to format code or run tests. For this " +"purpose we are using the VSCode Remote Containers extension. What is it? " +"Read the following quote:" msgstr "" +"在开发 Flower 框架时,我们希望确保所有贡献者使用相同的开发环境来格式化代码或" +"运行测试。为此,我们使用了 VSCode 远程容器扩展。这是什么?请阅读下面这段话:" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:7 msgid "" -"The Visual Studio Code Remote - Containers extension lets you use a " -"Docker container as a fully-featured development environment. It allows " -"you to open any folder inside (or mounted into) a container and take " -"advantage of Visual Studio Code's full feature set. A " -":code:`devcontainer.json` file in your project tells VS Code how to " -"access (or create) a development container with a well-defined tool and " -"runtime stack. This container can be used to run an application or to " -"separate tools, libraries, or runtimes needed for working with a " -"codebase." -msgstr "" +"The Visual Studio Code Remote - Containers extension lets you use a Docker " +"container as a fully-featured development environment. It allows you to open " +"any folder inside (or mounted into) a container and take advantage of Visual " +"Studio Code's full feature set. A :code:`devcontainer.json` file in your " +"project tells VS Code how to access (or create) a development container with " +"a well-defined tool and runtime stack. This container can be used to run an " +"application or to separate tools, libraries, or runtimes needed for working " +"with a codebase." +msgstr "" +"Visual Studio Code Remote - Containers扩展可让你将Docker容器用作功能齐全的开" +"发环境。它允许你打开容器内(或挂载到容器内)的任何文件夹,并利用 Visual " +"Studio Code 的全部功能集。项目中的 :code:`devcontainer.json` 文件会告诉 VS " +"Code 如何访问(或创建)一个带有定义明确的工具和运行时栈的开发容器。该容器可用" +"于运行应用程序,也可用于分离处理代码库所需的工具、库或运行时。" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:9 msgid "" -"Workspace files are mounted from the local file system or copied or " -"cloned into the container. Extensions are installed and run inside the " -"container, where they have full access to the tools, platform, and file " -"system. This means that you can seamlessly switch your entire development" -" environment just by connecting to a different container." +"Workspace files are mounted from the local file system or copied or cloned " +"into the container. Extensions are installed and run inside the container, " +"where they have full access to the tools, platform, and file system. This " +"means that you can seamlessly switch your entire development environment " +"just by connecting to a different container." msgstr "" +"工作区文件从本地文件系统加载,或复制或克隆到容器中。扩展在容器内安装和运行," +"在容器内它们可以完全访问工具、平台和文件系统。这意味着,只需连接到不同的容" +"器,就能无缝切换整个开发环境。" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:11 msgid "" -"Source: `Official VSCode documentation " -"`_" +"Source: `Official VSCode documentation `_" msgstr "" +"来源:`VSCode 官方文档 `_" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:15 msgid "Getting started" -msgstr "" +msgstr "开始" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:17 msgid "" -"Configuring and setting up the :code:`Dockerfile` as well the " -"configuration for the devcontainer can be a bit more involved. The good " -"thing is you want have to do it. Usually it should be enough to install " -"Docker on your system and ensure its available on your command line. " -"Additionally, install the `VSCode Containers Extension `_." +"Configuring and setting up the :code:`Dockerfile` as well the configuration " +"for the devcontainer can be a bit more involved. The good thing is you want " +"have to do it. Usually it should be enough to install Docker on your system " +"and ensure its available on your command line. Additionally, install the " +"`VSCode Containers Extension `_." msgstr "" +"配置和设置 :code:`Dockerfile` 以及 devcontainer 的配置可能比较复杂。好在你想" +"做就得做。通常只需在系统中安装 Docker 并确保其在命令行中可用即可。此外,请安" +"装 `VSCode Containers Extension `_。" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:19 msgid "" -"Now you should be good to go. When starting VSCode, it will ask you to " -"run in the container environment and - if you confirm - automatically " -"build the container and use it. To manually instruct VSCode to use the " -"devcontainer, you can, after installing the extension, click the green " -"area in the bottom left corner of your VSCode window and select the " -"option *(Re)Open Folder in Container*." +"Now you should be good to go. When starting VSCode, it will ask you to run " +"in the container environment and - if you confirm - automatically build the " +"container and use it. To manually instruct VSCode to use the devcontainer, " +"you can, after installing the extension, click the green area in the bottom " +"left corner of your VSCode window and select the option *(Re)Open Folder in " +"Container*." msgstr "" +"现在你应该可以开始了。启动 VSCode 时,它会要求你在容器环境中运行,如果你确" +"认,它会自动构建容器并使用它。要手动指示 VSCode 使用 devcontainer,可以在安装" +"扩展后,点击 VSCode 窗口左下角的绿色区域,然后选择 \"*(重新)在容器中打开文" +"件夹*\"选项。" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:21 msgid "" -"In some cases your setup might be more involved. For those cases consult " -"the following sources:" -msgstr "" +"In some cases your setup might be more involved. For those cases consult the " +"following sources:" +msgstr "在某些情况下,您的设置可能更复杂。有关这些情况,请参考以下资料:" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:23 msgid "" -"`Developing inside a Container " -"`_" +"`Developing inside a Container `_" msgstr "" +"在容器内开发 `_" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:24 msgid "" -"`Remote development in Containers " -"`_" +"`Remote development in Containers `_" msgstr "" +"容器中的远程开发 `_" #: ../../source/contributor-how-to-install-development-versions.rst:2 msgid "Install development versions" -msgstr "" +msgstr "安装开发版本" #: ../../source/contributor-how-to-install-development-versions.rst:5 msgid "Install development versions of Flower" -msgstr "" +msgstr "安装 Flower 的开发版本" #: ../../source/contributor-how-to-install-development-versions.rst:8 msgid "Using Poetry (recommended)" -msgstr "" +msgstr "使用诗歌(推荐)" #: ../../source/contributor-how-to-install-development-versions.rst:10 msgid "" -"Install a ``flwr`` pre-release from PyPI: update the ``flwr`` dependency " -"in ``pyproject.toml`` and then reinstall (don't forget to delete " -"``poetry.lock`` (``rm poetry.lock``) before running ``poetry install``)." +"Install a ``flwr`` pre-release from PyPI: update the ``flwr`` dependency in " +"``pyproject.toml`` and then reinstall (don't forget to delete ``poetry." +"lock`` (``rm poetry.lock``) before running ``poetry install``)." msgstr "" +"安装来自 PyPI 的 ``flwr`` 预发布版本:更新 ``pyproject.toml`` 中的 ``flwr`` " +"依赖关系,然后重新安装(运行 ``poetry install` 前,别忘了删除 ``poetry.lock` " +"(``rm poetry.lock`))。" #: ../../source/contributor-how-to-install-development-versions.rst:12 msgid "" "``flwr = { version = \"1.0.0a0\", allow-prereleases = true }`` (without " "extras)" msgstr "" +"``flwr = { version = \"1.0.0a0\", allow-prereleases = true }`` (不含额外内" +"容)" #: ../../source/contributor-how-to-install-development-versions.rst:13 msgid "" "``flwr = { version = \"1.0.0a0\", allow-prereleases = true, extras = " "[\"simulation\"] }`` (with extras)" msgstr "" +"``flwr = { version = \"1.0.0a0\", allow-prereleases = true, extras = " +"[\"simulation\"] }`` (包含额外内容)" #: ../../source/contributor-how-to-install-development-versions.rst:15 msgid "" -"Install ``flwr`` from a local copy of the Flower source code via " -"``pyproject.toml``:" -msgstr "" +"Install ``flwr`` from a local copy of the Flower source code via ``pyproject." +"toml``:" +msgstr "通过 ``pyproject.toml`` 从 Flower 源代码的本地副本安装 ``flwr``:" #: ../../source/contributor-how-to-install-development-versions.rst:17 msgid "``flwr = { path = \"../../\", develop = true }`` (without extras)" -msgstr "" +msgstr "``flwr = { path = \"../../\", develop = true }`` (不含额外内容)" #: ../../source/contributor-how-to-install-development-versions.rst:18 msgid "" -"``flwr = { path = \"../../\", develop = true, extras = [\"simulation\"] " -"}`` (with extras)" +"``flwr = { path = \"../../\", develop = true, extras = [\"simulation\"] }`` " +"(with extras)" msgstr "" +"``flwr = { path = \"../../\", develop = true, extras = [\"simulation\"] }`` " +"(包含额外内容)" #: ../../source/contributor-how-to-install-development-versions.rst:20 msgid "Install ``flwr`` from a local wheel file via ``pyproject.toml``:" -msgstr "" +msgstr "通过 ``pyproject.toml`` 从本地轮子文件安装 ``flwr``:" #: ../../source/contributor-how-to-install-development-versions.rst:22 msgid "" -"``flwr = { path = \"../../dist/flwr-1.0.0-py3-none-any.whl\" }`` (without" -" extras)" +"``flwr = { path = \"../../dist/flwr-1.0.0-py3-none-any.whl\" }`` (without " +"extras)" msgstr "" +"``flwr = { path = \"../../dist/flwr-1.0.0-py3-none-any.whl\" }``(无额外内" +"容)" #: ../../source/contributor-how-to-install-development-versions.rst:23 msgid "" "``flwr = { path = \"../../dist/flwr-1.0.0-py3-none-any.whl\", extras = " "[\"simulation\"] }`` (with extras)" msgstr "" +"``flwr = { path = \"../../dist/flwr-1.0.0-py3-none-any.whl\", extras = " +"[\"simulation\"] }`` (包含额外内容)" #: ../../source/contributor-how-to-install-development-versions.rst:25 msgid "" @@ -425,98 +501,114 @@ msgid "" "Dependency Specification `_" msgstr "" +"有关详细信息,请参阅 Poetry 文档: 诗歌依赖性规范 `_" #: ../../source/contributor-how-to-install-development-versions.rst:28 msgid "Using pip (recommended on Colab)" -msgstr "" +msgstr "使用 pip(建议在 Colab 上使用)" #: ../../source/contributor-how-to-install-development-versions.rst:30 msgid "Install a ``flwr`` pre-release from PyPI:" -msgstr "" +msgstr "从 PyPI 安装 ``flwr`` 预发行版:" #: ../../source/contributor-how-to-install-development-versions.rst:32 msgid "``pip install -U --pre flwr`` (without extras)" -msgstr "" +msgstr "`pip install -U -pre flwr``(不含额外功能)" #: ../../source/contributor-how-to-install-development-versions.rst:33 msgid "``pip install -U --pre flwr[simulation]`` (with extras)" -msgstr "" +msgstr "`pip install -U -pre flwr[simulation]``(包含额外功能)" #: ../../source/contributor-how-to-install-development-versions.rst:35 msgid "" "Python packages can be installed from git repositories. Use one of the " "following commands to install the Flower directly from GitHub." msgstr "" +"Python 软件包可以从 git 仓库安装。使用以下命令之一直接从 GitHub 安装 Flower。" #: ../../source/contributor-how-to-install-development-versions.rst:37 msgid "Install ``flwr`` from the default GitHub branch (``main``):" -msgstr "" +msgstr "从 GitHub 的默认分支 (``main`) 安装 ``flwr``:" #: ../../source/contributor-how-to-install-development-versions.rst:39 msgid "" -"``pip install flwr@git+https://github.com/adap/flower.git`` (without " -"extras)" +"``pip install flwr@git+https://github.com/adap/flower.git`` (without extras)" msgstr "" +"`pip install flwr@git+https://github.com/adap/flower.git`` (不含额外功能)" #: ../../source/contributor-how-to-install-development-versions.rst:40 msgid "" "``pip install flwr[simulation]@git+https://github.com/adap/flower.git`` " "(with extras)" msgstr "" +"`pip install flwr[simulation]@git+https://github.com/adap/flower.git``(带附" +"加功能)" #: ../../source/contributor-how-to-install-development-versions.rst:42 msgid "Install ``flwr`` from a specific GitHub branch (``branch-name``):" -msgstr "" +msgstr "从特定的 GitHub 分支 (`分支名`) 安装 ``flwr``:" #: ../../source/contributor-how-to-install-development-versions.rst:44 msgid "" "``pip install flwr@git+https://github.com/adap/flower.git@branch-name`` " "(without extras)" msgstr "" +"`pip install flwr@git+https://github.com/adap/flower.git@branch-name`` (不含" +"附加功能)" #: ../../source/contributor-how-to-install-development-versions.rst:45 msgid "" -"``pip install flwr[simulation]@git+https://github.com/adap/flower.git" -"@branch-name`` (with extras)" +"``pip install flwr[simulation]@git+https://github.com/adap/flower.git@branch-" +"name`` (with extras)" msgstr "" +"`pip安装flwr[模拟]@git+https://github.com/adap/flower.git@分支名``(带附加功" +"能)" #: ../../source/contributor-how-to-install-development-versions.rst:49 msgid "Open Jupyter Notebooks on Google Colab" -msgstr "" +msgstr "在谷歌 Colab 上打开 Jupyter 笔记本" #: ../../source/contributor-how-to-install-development-versions.rst:51 msgid "" -"Open the notebook ``doc/source/tutorial-get-started-with-flower-" -"pytorch.ipynb``:" +"Open the notebook ``doc/source/tutorial-get-started-with-flower-pytorch." +"ipynb``:" msgstr "" +"打开笔记本 ``doc/source/tutorial-get-started-with-flower-pytorch.ipynb``:" #: ../../source/contributor-how-to-install-development-versions.rst:53 msgid "" -"https://colab.research.google.com/github/adap/flower/blob/main/doc/source" -"/tutorial-get-started-with-flower-pytorch.ipynb" +"https://colab.research.google.com/github/adap/flower/blob/main/doc/source/" +"tutorial-get-started-with-flower-pytorch.ipynb" msgstr "" +"https://colab.research.google.com/github/adap/flower/blob/main/doc/source/" +"tutorial-get-started-with-flower-pytorch.ipynb" #: ../../source/contributor-how-to-install-development-versions.rst:55 msgid "" -"Open a development version of the same notebook from branch `branch-name`" -" by changing ``main`` to ``branch-name`` (right after ``blob``):" +"Open a development version of the same notebook from branch `branch-name` by " +"changing ``main`` to ``branch-name`` (right after ``blob``):" msgstr "" +"将 ``main`` 改为 ``branch-name``(紧跟在 ``blob``之后),从分支 `branch-" +"name` 打开同一笔记本的开发版本:" #: ../../source/contributor-how-to-install-development-versions.rst:57 msgid "" -"https://colab.research.google.com/github/adap/flower/blob/branch-" -"name/doc/source/tutorial-get-started-with-flower-pytorch.ipynb" +"https://colab.research.google.com/github/adap/flower/blob/branch-name/doc/" +"source/tutorial-get-started-with-flower-pytorch.ipynb" msgstr "" +"https://colab.research.google.com/github/adap/flower/blob/branch-name/doc/" +"source/tutorial-get-started-with-flower-pytorch.ipynb" #: ../../source/contributor-how-to-install-development-versions.rst:59 msgid "Install a `whl` on Google Colab:" -msgstr "" +msgstr "在 Google Colab 上安装 `whl`:" #: ../../source/contributor-how-to-install-development-versions.rst:61 msgid "" -"In the vertical icon grid on the left hand side, select ``Files`` > " -"``Upload to session storage``" -msgstr "" +"In the vertical icon grid on the left hand side, select ``Files`` > ``Upload " +"to session storage``" +msgstr "在左侧的垂直图标网格中,选择 \"文件\">\"上传到会话存储\"" #: ../../source/contributor-how-to-install-development-versions.rst:62 msgid "Upload the whl (e.g., ``flwr-1.7.0-py3-none-any.whl``)" @@ -524,57 +616,66 @@ msgstr "" #: ../../source/contributor-how-to-install-development-versions.rst:63 msgid "" -"Change ``!pip install -q 'flwr[simulation]' torch torchvision " -"matplotlib`` to ``!pip install -q 'flwr-1.7.0-py3-none-" -"any.whl[simulation]' torch torchvision matplotlib``" +"Change ``!pip install -q 'flwr[simulation]' torch torchvision matplotlib`` " +"to ``!pip install -q 'flwr-1.7.0-py3-none-any.whl[simulation]' torch " +"torchvision matplotlib``" msgstr "" #: ../../source/contributor-how-to-release-flower.rst:2 msgid "Release Flower" -msgstr "" +msgstr "发布 Flower" #: ../../source/contributor-how-to-release-flower.rst:4 msgid "" "This document describes the current release process. It may or may not " "change in the future." -msgstr "" +msgstr "本文件描述了当前的发布流程。今后可能会有变化,也可能不会有变化。" #: ../../source/contributor-how-to-release-flower.rst:7 msgid "Before the release" -msgstr "" +msgstr "发布前" #: ../../source/contributor-how-to-release-flower.rst:9 msgid "" "Update the changelog (``changelog.md``) with all relevant changes that " -"happened after the last release. If the last release was tagged " -"``v1.2.0``, you can use the following URL to see all commits that got " -"merged into ``main`` since then:" +"happened after the last release. If the last release was tagged ``v1.2.0``, " +"you can use the following URL to see all commits that got merged into " +"``main`` since then:" msgstr "" +"更新更新日志 (``changelog.md``),加入上次发布后发生的所有相关变更。如果上次发" +"布的版本被标记为 ``v1.2.0``,则可以使用以下 URL 查看此后合并到 ``main`` 的所" +"有提交:" #: ../../source/contributor-how-to-release-flower.rst:11 msgid "" -"`GitHub: Compare v1.2.0...main " -"`_" +"`GitHub: Compare v1.2.0...main `_" msgstr "" +"`GitHub: Compare v1.2.0...main `_" #: ../../source/contributor-how-to-release-flower.rst:13 msgid "" -"Thank the authors who contributed since the last release. This can be " -"done by running the ``./dev/add-shortlog.sh`` convenience script (it can " -"be ran multiple times and will update the names in the list if new " -"contributors were added in the meantime)." +"Thank the authors who contributed since the last release. This can be done " +"by running the ``./dev/add-shortlog.sh`` convenience script (it can be ran " +"multiple times and will update the names in the list if new contributors " +"were added in the meantime)." msgstr "" +"感谢自上次发布以来做出贡献的作者。可以通过运行 ``./dev/add-shortlog.sh`` 方便" +"脚本来完成(可以多次运行,如果在此期间有新的贡献者加入,则会更新列表中的名" +"字)。" #: ../../source/contributor-how-to-release-flower.rst:16 msgid "During the release" -msgstr "" +msgstr "在发布期间" #: ../../source/contributor-how-to-release-flower.rst:18 msgid "" -"The version number of a release is stated in ``pyproject.toml``. To " -"release a new version of Flower, the following things need to happen (in " -"that order):" +"The version number of a release is stated in ``pyproject.toml``. To release " +"a new version of Flower, the following things need to happen (in that order):" msgstr "" +"版本号在 ``pyproject.toml`` 中说明。要发布 Flower 的新版本,需要完成以下工作" +"(按顺序排列):" #: ../../source/contributor-how-to-release-flower.rst:20 msgid "" @@ -582,914 +683,1034 @@ msgid "" "version number and date for the release you are building. Create a pull " "request with the change." msgstr "" +"更新 ``changelog.md`` 部分的标题 ``Unreleased`` 以包含你正在构建的版本的版本" +"号和日期。创建一个包含更改的拉取请求。" #: ../../source/contributor-how-to-release-flower.rst:21 msgid "" -"Tag the release commit with the version number as soon as the PR is " -"merged: ``git tag v0.12.3``, then ``git push --tags``. This will create a" -" draft release on GitHub containing the correct artifacts and the " -"relevant part of the changelog." +"Tag the release commit with the version number as soon as the PR is merged: " +"``git tag v0.12.3``, then ``git push --tags``. This will create a draft " +"release on GitHub containing the correct artifacts and the relevant part of " +"the changelog." msgstr "" +"在 PR 合并后立即用版本号标记发布提交:``git tag v0.12.3``,然后``git push --" +"tags``。这将在 GitHub 上创建一个包含正确工件和更新日志相关部分的发布草案。" #: ../../source/contributor-how-to-release-flower.rst:22 -msgid "Check the draft release on GitHub, and if everything is good, publish it." -msgstr "" +msgid "" +"Check the draft release on GitHub, and if everything is good, publish it." +msgstr "检查 GitHub 上的发布稿,如果一切正常,就发布它。" #: ../../source/contributor-how-to-release-flower.rst:25 msgid "After the release" -msgstr "" +msgstr "发布后" #: ../../source/contributor-how-to-release-flower.rst:27 msgid "Create a pull request which contains the following changes:" -msgstr "" +msgstr "创建包含以下更改的拉取请求:" #: ../../source/contributor-how-to-release-flower.rst:29 msgid "Increase the minor version in ``pyproject.toml`` by one." -msgstr "" +msgstr "将 ``pyproject.toml`` 中的次要版本增加一个。" #: ../../source/contributor-how-to-release-flower.rst:30 msgid "Update all files which contain the current version number if necessary." -msgstr "" +msgstr "如有必要,更新包含当前版本号的所有文件。" #: ../../source/contributor-how-to-release-flower.rst:31 msgid "Add a new ``Unreleased`` section in ``changelog.md``." -msgstr "" +msgstr "在 ``changelog.md`` 中添加新的 ``Unreleased`` 部分。" #: ../../source/contributor-how-to-release-flower.rst:33 msgid "" -"Merge the pull request on the same day (i.e., before a new nighly release" -" gets published to PyPI)." -msgstr "" +"Merge the pull request on the same day (i.e., before a new nighly release " +"gets published to PyPI)." +msgstr "在同一天合并拉取请求(即在新版本发布到 PyPI 之前)。" #: ../../source/contributor-how-to-release-flower.rst:36 msgid "Publishing a pre-release" -msgstr "" +msgstr "发布预发布版本" #: ../../source/contributor-how-to-release-flower.rst:39 msgid "Pre-release naming" -msgstr "" +msgstr "释放前命名" #: ../../source/contributor-how-to-release-flower.rst:41 msgid "" "PyPI supports pre-releases (alpha, beta, release candiate). Pre-releases " "MUST use one of the following naming patterns:" msgstr "" +"PyPI 支持预发布版本(alpha、beta、release candiate)。预发布版本必须使用以下" +"命名模式之一:" #: ../../source/contributor-how-to-release-flower.rst:43 msgid "Alpha: ``MAJOR.MINOR.PATCHaN``" -msgstr "" +msgstr "阿尔法 ``MAJOR.MINOR.PATCHaN``" #: ../../source/contributor-how-to-release-flower.rst:44 msgid "Beta: ``MAJOR.MINOR.PATCHbN``" -msgstr "" +msgstr "贝塔: ``MAJOR.MINOR.PATCHbN``" #: ../../source/contributor-how-to-release-flower.rst:45 msgid "Release candiate (RC): ``MAJOR.MINOR.PATCHrcN``" -msgstr "" +msgstr "版本代号 (RC): ``MAJOR.MINOR.PATCHrcN``" #: ../../source/contributor-how-to-release-flower.rst:47 msgid "Examples include:" -msgstr "" +msgstr "例子包括:" #: ../../source/contributor-how-to-release-flower.rst:49 msgid "``1.0.0a0``" -msgstr "" +msgstr "``1.0.0a0``" #: ../../source/contributor-how-to-release-flower.rst:50 msgid "``1.0.0b0``" -msgstr "" +msgstr "``1.0.0b0``" #: ../../source/contributor-how-to-release-flower.rst:51 msgid "``1.0.0rc0``" -msgstr "" +msgstr "``1.0.0rc0``" #: ../../source/contributor-how-to-release-flower.rst:52 msgid "``1.0.0rc1``" -msgstr "" +msgstr "``1.0.0rc1``" #: ../../source/contributor-how-to-release-flower.rst:54 msgid "" "This is in line with PEP-440 and the recommendations from the Python " "Packaging Authority (PyPA):" -msgstr "" +msgstr "这符合 PEP-440 和 Python 包装管理局 (PyPA) 的建议:" #: ../../source/contributor-how-to-release-flower.rst:57 msgid "`PEP-440 `_" -msgstr "" +msgstr "`PEP-440 `_" #: ../../source/contributor-how-to-release-flower.rst:58 msgid "" -"`PyPA Choosing a versioning scheme " -"`_" +"`PyPA Choosing a versioning scheme `_" msgstr "" +"`PyPA 选择版本控制方案 `_" #: ../../source/contributor-how-to-release-flower.rst:60 msgid "" -"Note that the approach defined by PyPA is not compatible with SemVer " -"2.0.0 spec, for details consult the `Semantic Versioning Specification " -"`_ (specifically item " -"11 on precedence)." +"Note that the approach defined by PyPA is not compatible with SemVer 2.0.0 " +"spec, for details consult the `Semantic Versioning Specification `_ (specifically item 11 on " +"precedence)." msgstr "" +"请注意,PyPA 所定义的方法与 SemVer 2.0.0 规范不兼容,详情请查阅《语义版本规" +"范》`_(特别是关于优先级的" +"第 11 项)。" #: ../../source/contributor-how-to-release-flower.rst:63 msgid "Pre-release classification" -msgstr "" +msgstr "发布前分类" #: ../../source/contributor-how-to-release-flower.rst:65 -msgid "Should the next pre-release be called alpha, beta, or release candidate?" -msgstr "" +msgid "" +"Should the next pre-release be called alpha, beta, or release candidate?" +msgstr "下一个预发布版应该叫阿尔法版、贝塔版还是候选发布版?" #: ../../source/contributor-how-to-release-flower.rst:67 msgid "" -"RC: feature complete, no known issues (apart from issues that are " -"classified as \"won't fix\" for the next stable release) - if no issues " -"surface this will become the next stable release" +"RC: feature complete, no known issues (apart from issues that are classified " +"as \"won't fix\" for the next stable release) - if no issues surface this " +"will become the next stable release" msgstr "" +"RC:功能完整,无已知问题(除了下一个稳定版中被列为 \"不会修复 \"的问题)--如" +"果没有问题出现,这将成为下一个稳定版" #: ../../source/contributor-how-to-release-flower.rst:68 msgid "Beta: feature complete, allowed to have known issues" -msgstr "" +msgstr "贝塔版:功能完整,允许存在已知问题" #: ../../source/contributor-how-to-release-flower.rst:69 msgid "Alpha: not feature complete, allowed to have known issues" -msgstr "" +msgstr "阿尔法版:功能不完整,允许存在已知问题" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:2 msgid "Set up a virtual env" -msgstr "" +msgstr "建立虚拟环境" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:4 msgid "" "It is recommended to run your Python setup within a virtual environment. " "This guide shows three different examples how to create a virtual " -"environment with pyenv virtualenv, poetry, or Anaconda. You can follow " -"the instructions or choose your preferred setup." +"environment with pyenv virtualenv, poetry, or Anaconda. You can follow the " +"instructions or choose your preferred setup." msgstr "" +"建议在虚拟环境中运行 Python 设置。本指南展示了如何使用 pyenv virtualenv、" +"poes 或 Anaconda 创建虚拟环境的三个不同示例。您可以按照说明或选择您喜欢的设" +"置。" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:9 msgid "Python Version" -msgstr "" +msgstr "Python 版本" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:11 #: ../../source/how-to-install-flower.rst:8 msgid "" -"Flower requires at least `Python 3.8 `_, " -"but `Python 3.10 `_ or above is " -"recommended." +"Flower requires at least `Python 3.8 `_, but " +"`Python 3.10 `_ or above is recommended." msgstr "" +"Flower 至少需要 `Python 3.8 `_,但建议使用 " +"`Python 3.10 `_或更高版本。" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:14 msgid "Virutualenv with Pyenv/Virtualenv" -msgstr "" +msgstr "Virutualenv 和 Pyenv/Virtualenv" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:16 msgid "" -"One of the recommended virtual environment is `pyenv " -"`_/`virtualenv `_. Please see `Flower examples " -"`_ for details." +"One of the recommended virtual environment is `pyenv `_/`virtualenv `_. " +"Please see `Flower examples `_ for details." msgstr "" +"其中一个推荐的虚拟环境是 `pyenv `_/" +"`virtualenv `_。详情请参见 " +"`Flower 示例 `_。" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:18 msgid "" "Once Pyenv is set up, you can use it to install `Python Version 3.10 " "`_ or above:" msgstr "" +"一旦设置好 Pyenv,就可以用它来安装 `Python 3.10 `_ 或更高版本:" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:24 msgid "Create the virtualenv with:" -msgstr "" +msgstr "创建虚拟环境:" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:31 msgid "Activate the virtualenv by running the following command:" -msgstr "" +msgstr "运行以下命令激活 virtualenv:" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:39 msgid "Virtualenv with Poetry" -msgstr "" +msgstr "有诗意的 Virtualenv" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:41 msgid "" -"The Flower examples are based on `Poetry `_ to manage dependencies. After installing Poetry you " -"simply create a virtual environment with:" +"The Flower examples are based on `Poetry `_ " +"to manage dependencies. After installing Poetry you simply create a virtual " +"environment with:" msgstr "" +"Flower 示例基于 `Poetry `_ 来管理依赖关系。" +"安装 Poetry 后,只需创建一个虚拟环境即可:" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:47 msgid "" -"If you open a new terminal you can activate the previously created " -"virtual environment with the following command:" -msgstr "" +"If you open a new terminal you can activate the previously created virtual " +"environment with the following command:" +msgstr "如果打开一个新终端,可以使用以下命令激活之前创建的虚拟环境:" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:55 msgid "Virtualenv with Anaconda" -msgstr "" +msgstr "使用 Anaconda 的 Virtualenv" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:57 msgid "" -"If you prefer to use Anaconda for your virtual environment then install " -"and setup the `conda `_ package. After setting it up you can " -"create a virtual environment with:" +"If you prefer to use Anaconda for your virtual environment then install and " +"setup the `conda `_ package. After setting it up you can create a virtual " +"environment with:" msgstr "" +"如果你更喜欢在虚拟环境中使用 Anaconda,那么请安装并设置 `conda `_ 软件包。设" +"置完成后,您就可以使用以下工具创建虚拟环境:" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:63 msgid "and activate the virtual environment with:" -msgstr "" +msgstr "并激活虚拟环境:" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:71 msgid "And then?" -msgstr "" +msgstr "然后呢?" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:73 msgid "" -"As soon as you created your virtual environment you clone one of the " -"`Flower examples `_." +"As soon as you created your virtual environment you clone one of the `Flower " +"examples `_." msgstr "" +"创建虚拟环境后,您可以克隆一个 `Flower 示例 `_。" #: ../../source/contributor-how-to-write-documentation.rst:2 msgid "Write documentation" -msgstr "" +msgstr "编写文件" #: ../../source/contributor-how-to-write-documentation.rst:6 msgid "Project layout" -msgstr "" +msgstr "项目布局" #: ../../source/contributor-how-to-write-documentation.rst:8 msgid "" -"The Flower documentation lives in the ``doc`` directory. The Sphinx-based" -" documentation system supports both reStructuredText (``.rst`` files) and" -" Markdown (``.md`` files)." +"The Flower documentation lives in the ``doc`` directory. The Sphinx-based " +"documentation system supports both reStructuredText (``.rst`` files) and " +"Markdown (``.md`` files)." msgstr "" +"Flower 文档位于 ``doc`` 目录中。基于 Sphinx 的文档系统支持 reStructuredText" +"(``.rst`` 文件)和 Markdown(``.md`` 文件)。" #: ../../source/contributor-how-to-write-documentation.rst:10 #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:119 msgid "" -"Note that, in order to build the documentation locally (with ``poetry run" -" make html``, like described below), `Pandoc " -"_` needs to be installed on the " -"system." +"Note that, in order to build the documentation locally (with ``poetry run " +"make html``, like described below), `Pandoc _` needs to be installed on the system." msgstr "" +"请注意,要在本地构建文档(使用 ``poetry run make html``,如下所述),系统上必" +"须安装 ``Pandoc _`。" #: ../../source/contributor-how-to-write-documentation.rst:14 msgid "Edit an existing page" -msgstr "" +msgstr "编辑现有页面" #: ../../source/contributor-how-to-write-documentation.rst:16 msgid "Edit an existing ``.rst`` (or ``.md``) file under ``doc/source/``" -msgstr "" +msgstr "编辑 ``doc/source/`` 下现有的 ``.rst`` (或 ``.md``) 文件" #: ../../source/contributor-how-to-write-documentation.rst:17 #: ../../source/contributor-how-to-write-documentation.rst:27 msgid "Compile the docs: ``cd doc``, then ``poetry run make html``" -msgstr "" +msgstr "编译文档: cd doc``,然后 ``poetry run make html``" #: ../../source/contributor-how-to-write-documentation.rst:18 #: ../../source/contributor-how-to-write-documentation.rst:28 msgid "Open ``doc/build/html/index.html`` in the browser to check the result" -msgstr "" +msgstr "在浏览器中打开 ``doc/build/html/index.html`` 查看结果" #: ../../source/contributor-how-to-write-documentation.rst:22 msgid "Create a new page" -msgstr "" +msgstr "创建新页面" #: ../../source/contributor-how-to-write-documentation.rst:24 msgid "Add new ``.rst`` file under ``doc/source/``" -msgstr "" +msgstr "在 ``doc/source/`` 下添加新的 ``.rst`` 文件" #: ../../source/contributor-how-to-write-documentation.rst:25 msgid "Add content to the new ``.rst`` file" -msgstr "" +msgstr "为新的 ``.rst`` 文件添加内容" #: ../../source/contributor-how-to-write-documentation.rst:26 msgid "Link to the new rst from ``index.rst``" -msgstr "" +msgstr "从 ``index.rst`` 链接到新的 rst" #: ../../source/contributor-ref-good-first-contributions.rst:2 msgid "Good first contributions" -msgstr "" +msgstr "良好的首批捐款" #: ../../source/contributor-ref-good-first-contributions.rst:4 msgid "" -"We welcome contributions to Flower! However, it is not always easy to " -"know where to start. We therefore put together a few recommendations on " -"where to start to increase your chances of getting your PR accepted into " -"the Flower codebase." +"We welcome contributions to Flower! However, it is not always easy to know " +"where to start. We therefore put together a few recommendations on where to " +"start to increase your chances of getting your PR accepted into the Flower " +"codebase." msgstr "" +"我们欢迎为《鲜花》投稿!然而,要知道从哪里开始并非易事。因此,我们提出了一些" +"建议,告诉您从哪里开始,以增加您的 PR 被 Flower 代码库接受的机会。" #: ../../source/contributor-ref-good-first-contributions.rst:11 msgid "Where to start" -msgstr "" +msgstr "从哪里开始" #: ../../source/contributor-ref-good-first-contributions.rst:13 msgid "" -"Until the Flower core library matures it will be easier to get PR's " -"accepted if they only touch non-core areas of the codebase. Good " -"candidates to get started are:" +"Until the Flower core library matures it will be easier to get PR's accepted " +"if they only touch non-core areas of the codebase. Good candidates to get " +"started are:" msgstr "" +"在 Flower 核心库成熟之前,如果 PR 只涉及代码库中的非核心区域,则会更容易被接" +"受。可以从以下方面入手:" #: ../../source/contributor-ref-good-first-contributions.rst:17 msgid "Documentation: What's missing? What could be expressed more clearly?" -msgstr "" +msgstr "文件: 缺少什么?哪些内容可以表达得更清楚?" #: ../../source/contributor-ref-good-first-contributions.rst:18 msgid "Baselines: See below." -msgstr "" +msgstr "基线: 见下文。" #: ../../source/contributor-ref-good-first-contributions.rst:19 msgid "Examples: See below." -msgstr "" +msgstr "举例说明: 见下文。" #: ../../source/contributor-ref-good-first-contributions.rst:23 msgid "Request for Flower Baselines" -msgstr "" +msgstr "Flower 基线申请" #: ../../source/contributor-ref-good-first-contributions.rst:25 msgid "" -"If you are not familiar with Flower Baselines, you should probably check-" -"out our `contributing guide for baselines `_." +"If you are not familiar with Flower Baselines, you should probably check-out " +"our `contributing guide for baselines `_." msgstr "" +"如果您对 Flower Baselines 还不熟悉,也许应该看看我们的 \"基线贡献指南 " +"`_\"。" #: ../../source/contributor-ref-good-first-contributions.rst:27 msgid "" -"You should then check out the open `issues " -"`_" -" for baseline requests. If you find a baseline that you'd like to work on" -" and that has no assignes, feel free to assign it to yourself and start " -"working on it!" +"You should then check out the open `issues `_ for baseline " +"requests. If you find a baseline that you'd like to work on and that has no " +"assignes, feel free to assign it to yourself and start working on it!" msgstr "" +"然后,您应该查看开放的 `issues `_ 基线请求。如果您发现了自" +"己想做的基线,而它还没有被分配,请随时把它分配给自己,然后开始工作!" #: ../../source/contributor-ref-good-first-contributions.rst:31 msgid "" -"Otherwise, if you don't find a baseline you'd like to work on, be sure to" -" open a new issue with the baseline request template!" +"Otherwise, if you don't find a baseline you'd like to work on, be sure to " +"open a new issue with the baseline request template!" msgstr "" +"否则,如果您没有找到想要处理的基线,请务必使用基线请求模板打开一个新问题!" #: ../../source/contributor-ref-good-first-contributions.rst:34 msgid "Request for examples" -msgstr "" +msgstr "要求提供范例" #: ../../source/contributor-ref-good-first-contributions.rst:36 msgid "" "We wish we had more time to write usage examples because we believe they " -"help users to get started with building what they want to build. Here are" -" a few ideas where we'd be happy to accept a PR:" +"help users to get started with building what they want to build. Here are a " +"few ideas where we'd be happy to accept a PR:" msgstr "" +"我们希望有更多的时间来撰写使用示例,因为我们相信这些示例可以帮助用户开始构建" +"他们想要构建的东西。以下是我们乐意接受 PR 的几个想法:" #: ../../source/contributor-ref-good-first-contributions.rst:40 msgid "Llama 2 fine-tuning, with Hugging Face Transformers and PyTorch" -msgstr "" +msgstr "微调 \"拉玛 2\",使用 \"抱脸变形金刚 \"和 PyTorch" #: ../../source/contributor-ref-good-first-contributions.rst:41 msgid "XGBoost" -msgstr "" +msgstr "XGBoost" #: ../../source/contributor-ref-good-first-contributions.rst:42 msgid "Android ONNX on-device training" -msgstr "" +msgstr "安卓 ONNX 设备上培训" #: ../../source/contributor-ref-secure-aggregation-protocols.rst:2 msgid "Secure Aggregation Protocols" -msgstr "" +msgstr "安全聚合协议" #: ../../source/contributor-ref-secure-aggregation-protocols.rst:4 msgid "" -"Include SecAgg, SecAgg+, and LightSecAgg protocol. The LightSecAgg " -"protocol has not been implemented yet, so its diagram and abstraction may" -" not be accurate in practice. The SecAgg protocol can be considered as a " -"special case of the SecAgg+ protocol." +"Include SecAgg, SecAgg+, and LightSecAgg protocol. The LightSecAgg protocol " +"has not been implemented yet, so its diagram and abstraction may not be " +"accurate in practice. The SecAgg protocol can be considered as a special " +"case of the SecAgg+ protocol." msgstr "" +"包括 SecAgg、SecAgg+ 和 LightSecAgg 协议。LightSecAgg 协议尚未实施,因此其图" +"表和抽象在实践中可能并不准确。SecAgg 协议可视为 SecAgg+ 协议的特例。" #: ../../source/contributor-ref-secure-aggregation-protocols.rst:8 msgid "The :code:`SecAgg+` abstraction" -msgstr "" +msgstr "代码:`SecAgg+` 抽象" #: ../../source/contributor-ref-secure-aggregation-protocols.rst:10 #: ../../source/contributor-ref-secure-aggregation-protocols.rst:161 msgid "" "In this implementation, each client will be assigned with a unique index " -"(int) for secure aggregation, and thus many python dictionaries used have" -" keys of int type rather than ClientProxy type." +"(int) for secure aggregation, and thus many python dictionaries used have " +"keys of int type rather than ClientProxy type." msgstr "" +"在此实现中,将为每个客户端分配一个唯一索引(int),以确保聚合的安全性,因此使" +"用的许多 python 字典的键都是 int 类型,而不是 ClientProxy 类型。" #: ../../source/contributor-ref-secure-aggregation-protocols.rst:65 #: ../../source/contributor-ref-secure-aggregation-protocols.rst:198 msgid "" -"The Flower server will execute and process received results in the " -"following order:" -msgstr "" +"The Flower server will execute and process received results in the following " +"order:" +msgstr "Flower 服务器将按以下顺序执行和处理收到的结果:" #: ../../source/contributor-ref-secure-aggregation-protocols.rst:159 msgid "The :code:`LightSecAgg` abstraction" -msgstr "" +msgstr "代码:`LightSecAgg` 抽象" #: ../../source/contributor-ref-secure-aggregation-protocols.rst:271 msgid "Types" -msgstr "" +msgstr "类型" #: ../../source/contributor-tutorial-contribute-on-github.rst:2 msgid "Contribute on GitHub" -msgstr "" +msgstr "在 GitHub 上投稿" #: ../../source/contributor-tutorial-contribute-on-github.rst:4 msgid "" -"This guide is for people who want to get involved with Flower, but who " -"are not used to contributing to GitHub projects." -msgstr "" +"This guide is for people who want to get involved with Flower, but who are " +"not used to contributing to GitHub projects." +msgstr "本指南适用于想参与 Flower,但不习惯为 GitHub 项目贡献的人。" #: ../../source/contributor-tutorial-contribute-on-github.rst:6 msgid "" -"If you're familiar with how contributing on GitHub works, you can " -"directly checkout our `getting started guide for contributors " -"`_ and " -"examples of `good first contributions `_." +"If you're familiar with how contributing on GitHub works, you can directly " +"checkout our `getting started guide for contributors `_ and examples of `good first " +"contributions `_." msgstr "" +"如果您熟悉如何在 GitHub 上贡献,可以直接查看我们的 \"贡献者入门指南\" " +"`_ 和 \"优秀的" +"首次贡献示例\" `_。" #: ../../source/contributor-tutorial-contribute-on-github.rst:12 msgid "Setting up the repository" -msgstr "" +msgstr "建立资源库" #: ../../source/contributor-tutorial-contribute-on-github.rst:23 msgid "**Create a GitHub account and setup Git**" -msgstr "" +msgstr "**创建 GitHub 账户并设置 Git**" #: ../../source/contributor-tutorial-contribute-on-github.rst:15 msgid "" "Git is a distributed version control tool. This allows for an entire " "codebase's history to be stored and every developer's machine. It is a " "software that will need to be installed on your local machine, you can " -"follow this `guide `_ to set it up." +"follow this `guide `_ to set it up." msgstr "" +"Git 是一种分布式版本控制工具。它可以将整个代码库的历史记录保存在每个开发人员" +"的机器上。您需要在本地计算机上安装该软件,可以按照本指南 `_ 进行设置。" #: ../../source/contributor-tutorial-contribute-on-github.rst:18 msgid "" "GitHub, itself, is a code hosting platform for version control and " -"collaboration. It allows for everyone to collaborate and work from " -"anywhere on remote repositories." +"collaboration. It allows for everyone to collaborate and work from anywhere " +"on remote repositories." msgstr "" +"GitHub 本身是一个用于版本控制和协作的代码托管平台。它允许每个人在任何地方对远" +"程仓库进行协作和工作。" #: ../../source/contributor-tutorial-contribute-on-github.rst:20 msgid "" "If you haven't already, you will need to create an account on `GitHub " "`_." msgstr "" +"如果还没有,您需要在 `GitHub `_ 上创建一个账户。" #: ../../source/contributor-tutorial-contribute-on-github.rst:22 msgid "" -"The idea behind the generic Git and GitHub workflow boils down to this: " -"you download code from a remote repository on GitHub, make changes " -"locally and keep track of them using Git and then you upload your new " -"history back to GitHub." +"The idea behind the generic Git and GitHub workflow boils down to this: you " +"download code from a remote repository on GitHub, make changes locally and " +"keep track of them using Git and then you upload your new history back to " +"GitHub." msgstr "" +"通用的 Git 和 GitHub 工作流程背后的理念可以归结为:从 GitHub 上的远程仓库下载" +"代码,在本地进行修改并使用 Git 进行跟踪,然后将新的历史记录上传回 GitHub。" #: ../../source/contributor-tutorial-contribute-on-github.rst:34 msgid "**Forking the Flower repository**" -msgstr "" +msgstr "**叉花仓库**" #: ../../source/contributor-tutorial-contribute-on-github.rst:26 msgid "" -"A fork is a personal copy of a GitHub repository. To create one for " -"Flower, you must navigate to https://github.com/adap/flower (while " -"connected to your GitHub account) and click the ``Fork`` button situated " -"on the top right of the page." +"A fork is a personal copy of a GitHub repository. To create one for Flower, " +"you must navigate to https://github.com/adap/flower (while connected to your " +"GitHub account) and click the ``Fork`` button situated on the top right of " +"the page." msgstr "" +"fork 是 GitHub 仓库的个人副本。要为 Flower 创建一个 fork,您必须导航到 " +"https://github.com/adap/flower(同时连接到您的 GitHub 账户),然后点击页面右" +"上方的 ``Fork`` 按钮。" #: ../../source/contributor-tutorial-contribute-on-github.rst:31 msgid "" "You can change the name if you want, but this is not necessary as this " -"version of Flower will be yours and will sit inside your own account " -"(i.e., in your own list of repositories). Once created, you should see on" -" the top left corner that you are looking at your own version of Flower." +"version of Flower will be yours and will sit inside your own account (i.e., " +"in your own list of repositories). Once created, you should see on the top " +"left corner that you are looking at your own version of Flower." msgstr "" +"您可以更改名称,但没有必要,因为这个版本的 Flower 将是您自己的,并位于您自己" +"的账户中(即,在您自己的版本库列表中)。创建完成后,您会在左上角看到自己的 " +"Flower 版本。" #: ../../source/contributor-tutorial-contribute-on-github.rst:49 msgid "**Cloning your forked repository**" -msgstr "" +msgstr "**克隆你的分叉仓库**" #: ../../source/contributor-tutorial-contribute-on-github.rst:37 msgid "" "The next step is to download the forked repository on your machine to be " -"able to make changes to it. On your forked repository page, you should " -"first click on the ``Code`` button on the right, this will give you the " -"ability to copy the HTTPS link of the repository." +"able to make changes to it. On your forked repository page, you should first " +"click on the ``Code`` button on the right, this will give you the ability to " +"copy the HTTPS link of the repository." msgstr "" +"下一步是在你的机器上下载分叉版本库,以便对其进行修改。在分叉版本库页面上,首" +"先点击右侧的 \"代码 \"按钮,这样就能复制版本库的 HTTPS 链接。" #: ../../source/contributor-tutorial-contribute-on-github.rst:43 msgid "" "Once you copied the \\, you can open a terminal on your machine, " "navigate to the place you want to download the repository to and type:" msgstr "" +"一旦复制了 (),你就可以在你的机器上打开一个终端,导航到你想下载软件" +"源的地方,然后键入:" #: ../../source/contributor-tutorial-contribute-on-github.rst:49 msgid "" -"This will create a `flower/` (or the name of your fork if you renamed it)" -" folder in the current working directory." +"This will create a `flower/` (or the name of your fork if you renamed it) " +"folder in the current working directory." msgstr "" +"这将在当前工作目录下创建一个 `flower/`(如果重命名了,则使用 fork 的名称)文" +"件夹。" #: ../../source/contributor-tutorial-contribute-on-github.rst:68 msgid "**Add origin**" -msgstr "" +msgstr "**添加原产地**" #: ../../source/contributor-tutorial-contribute-on-github.rst:52 msgid "You can then go into the repository folder:" -msgstr "" +msgstr "然后,您就可以进入存储库文件夹:" #: ../../source/contributor-tutorial-contribute-on-github.rst:58 msgid "" -"And here we will need to add an origin to our repository. The origin is " -"the \\ of the remote fork repository. To obtain it, we can do as " -"previously mentioned by going to our fork repository on our GitHub " -"account and copying the link." +"And here we will need to add an origin to our repository. The origin is the " +"\\ of the remote fork repository. To obtain it, we can do as " +"previously mentioned by going to our fork repository on our GitHub account " +"and copying the link." msgstr "" +"在这里,我们需要为我们的版本库添加一个 origin。origin 是远程 fork 仓库的 " +"\\。要获得它,我们可以像前面提到的那样,访问 GitHub 账户上的分叉仓库并" +"复制链接。" #: ../../source/contributor-tutorial-contribute-on-github.rst:63 msgid "" "Once the \\ is copied, we can type the following command in our " "terminal:" -msgstr "" +msgstr "一旦复制了 \\ ,我们就可以在终端中键入以下命令:" #: ../../source/contributor-tutorial-contribute-on-github.rst:92 msgid "**Add upstream**" -msgstr "" +msgstr "**增加上游**" #: ../../source/contributor-tutorial-contribute-on-github.rst:71 msgid "" "Now we will add an upstream address to our repository. Still in the same " "directroy, we must run the following command:" msgstr "" +"现在,我们要为版本库添加一个上游地址。还是在同一目录下,我们必须运行以下命" +"令:" #: ../../source/contributor-tutorial-contribute-on-github.rst:78 -msgid "The following diagram visually explains what we did in the previous steps:" -msgstr "" +msgid "" +"The following diagram visually explains what we did in the previous steps:" +msgstr "下图直观地解释了我们在前面步骤中的操作:" #: ../../source/contributor-tutorial-contribute-on-github.rst:82 msgid "" -"The upstream is the GitHub remote address of the parent repository (in " -"this case Flower), i.e. the one we eventually want to contribute to and " -"therefore need an up-to-date history of. The origin is just the GitHub " -"remote address of the forked repository we created, i.e. the copy (fork) " -"in our own account." +"The upstream is the GitHub remote address of the parent repository (in this " +"case Flower), i.e. the one we eventually want to contribute to and therefore " +"need an up-to-date history of. The origin is just the GitHub remote address " +"of the forked repository we created, i.e. the copy (fork) in our own account." msgstr "" +"上游是父版本库(这里是 Flower)的 GitHub 远程地址,即我们最终要贡献的版本库," +"因此需要最新的历史记录。origin 只是我们创建的分叉仓库的 GitHub 远程地址,即我" +"们自己账户中的副本(分叉)。" #: ../../source/contributor-tutorial-contribute-on-github.rst:86 msgid "" "To make sure our local version of the fork is up-to-date with the latest " "changes from the Flower repository, we can execute the following command:" msgstr "" +"为了确保本地版本的分叉程序与 Flower 代码库的最新更改保持一致,我们可以执行以" +"下命令:" #: ../../source/contributor-tutorial-contribute-on-github.rst:95 msgid "Setting up the coding environment" -msgstr "" +msgstr "设置编码环境" #: ../../source/contributor-tutorial-contribute-on-github.rst:97 msgid "" "This can be achieved by following this `getting started guide for " -"contributors`_ (note that you won't need to clone the repository). Once " -"you are able to write code and test it, you can finally start making " -"changes!" +"contributors`_ (note that you won't need to clone the repository). Once you " +"are able to write code and test it, you can finally start making changes!" msgstr "" +"您可以按照这份 \"贡献者入门指南\"__(注意,您不需要克隆版本库)来实现这一点。" +"一旦您能够编写代码并进行测试,您就可以开始修改了!" #: ../../source/contributor-tutorial-contribute-on-github.rst:102 msgid "Making changes" -msgstr "" +msgstr "做出改变" #: ../../source/contributor-tutorial-contribute-on-github.rst:104 msgid "" -"Before making any changes make sure you are up-to-date with your " -"repository:" -msgstr "" +"Before making any changes make sure you are up-to-date with your repository:" +msgstr "在进行任何更改之前,请确保您的版本库是最新的:" #: ../../source/contributor-tutorial-contribute-on-github.rst:110 msgid "And with Flower's repository:" -msgstr "" +msgstr "还有Flower的存储库:" #: ../../source/contributor-tutorial-contribute-on-github.rst:124 msgid "**Create a new branch**" -msgstr "" +msgstr "**创建一个新分支**" #: ../../source/contributor-tutorial-contribute-on-github.rst:117 msgid "" -"To make the history cleaner and easier to work with, it is good practice " -"to create a new branch for each feature/project that needs to be " -"implemented." +"To make the history cleaner and easier to work with, it is good practice to " +"create a new branch for each feature/project that needs to be implemented." msgstr "" +"为了使历史记录更简洁、更易于操作,为每个需要实现的功能/项目创建一个新分支是个" +"不错的做法。" #: ../../source/contributor-tutorial-contribute-on-github.rst:120 msgid "" -"To do so, just run the following command inside the repository's " -"directory:" -msgstr "" +"To do so, just run the following command inside the repository's directory:" +msgstr "为此,只需在版本库目录下运行以下命令即可:" #: ../../source/contributor-tutorial-contribute-on-github.rst:127 msgid "**Make changes**" -msgstr "" +msgstr "**进行修改**" #: ../../source/contributor-tutorial-contribute-on-github.rst:127 -msgid "Write great code and create wonderful changes using your favorite editor!" -msgstr "" +msgid "" +"Write great code and create wonderful changes using your favorite editor!" +msgstr "使用您最喜欢的编辑器编写优秀的代码并创建精彩的更改!" #: ../../source/contributor-tutorial-contribute-on-github.rst:140 msgid "**Test and format your code**" -msgstr "" +msgstr "**测试并格式化您的代码**" #: ../../source/contributor-tutorial-contribute-on-github.rst:130 msgid "" -"Don't forget to test and format your code! Otherwise your code won't be " -"able to be merged into the Flower repository. This is done so the " -"codebase stays consistent and easy to understand." +"Don't forget to test and format your code! Otherwise your code won't be able " +"to be merged into the Flower repository. This is done so the codebase stays " +"consistent and easy to understand." msgstr "" +"不要忘记测试和格式化您的代码!否则您的代码将无法并入 Flower 代码库。这样做是" +"为了使代码库保持一致并易于理解。" #: ../../source/contributor-tutorial-contribute-on-github.rst:133 msgid "To do so, we have written a few scripts that you can execute:" -msgstr "" +msgstr "为此,我们编写了一些脚本供您执行:" #: ../../source/contributor-tutorial-contribute-on-github.rst:152 msgid "**Stage changes**" -msgstr "" +msgstr "**舞台变化**" #: ../../source/contributor-tutorial-contribute-on-github.rst:143 msgid "" -"Before creating a commit that will update your history, you must specify " -"to Git which files it needs to take into account." -msgstr "" +"Before creating a commit that will update your history, you must specify to " +"Git which files it needs to take into account." +msgstr "在创建更新历史记录的提交之前,必须向 Git 说明需要考虑哪些文件。" #: ../../source/contributor-tutorial-contribute-on-github.rst:145 msgid "This can be done with:" -msgstr "" +msgstr "这可以通过:" #: ../../source/contributor-tutorial-contribute-on-github.rst:151 msgid "" -"To check which files have been modified compared to the last version " -"(last commit) and to see which files are staged for commit, you can use " -"the :code:`git status` command." +"To check which files have been modified compared to the last version (last " +"commit) and to see which files are staged for commit, you can use the :code:" +"`git status` command." msgstr "" +"要查看与上一版本(上次提交)相比哪些文件已被修改,以及哪些文件处于提交阶段," +"可以使用 :code:`git status` 命令。" #: ../../source/contributor-tutorial-contribute-on-github.rst:162 msgid "**Commit changes**" -msgstr "" +msgstr "**提交更改**" #: ../../source/contributor-tutorial-contribute-on-github.rst:155 msgid "" "Once you have added all the files you wanted to commit using :code:`git " "add`, you can finally create your commit using this command:" msgstr "" +"使用 :code:`git add` 添加完所有要提交的文件后,就可以使用此命令创建提交了:" #: ../../source/contributor-tutorial-contribute-on-github.rst:161 msgid "" -"The \\ is there to explain to others what the commit " -"does. It should be written in an imperative style and be concise. An " -"example would be :code:`git commit -m \"Add images to README\"`." +"The \\ is there to explain to others what the commit does. " +"It should be written in an imperative style and be concise. An example would " +"be :code:`git commit -m \"Add images to README\"`." msgstr "" +" 用于向他人解释提交的作用。它应该以命令式风格书写,并且简明" +"扼要。例如 :code:`git commit -m \"Add images to README\"`。" #: ../../source/contributor-tutorial-contribute-on-github.rst:173 msgid "**Push the changes to the fork**" -msgstr "" +msgstr "**将更改推送到分叉**" #: ../../source/contributor-tutorial-contribute-on-github.rst:165 msgid "" -"Once we have committed our changes, we have effectively updated our local" -" history, but GitHub has no way of knowing this unless we push our " -"changes to our origin's remote address:" +"Once we have committed our changes, we have effectively updated our local " +"history, but GitHub has no way of knowing this unless we push our changes to " +"our origin's remote address:" msgstr "" +"一旦提交了修改,我们就有效地更新了本地历史记录,但除非我们将修改推送到原点的" +"远程地址,否则 GitHub 无法得知:" #: ../../source/contributor-tutorial-contribute-on-github.rst:172 msgid "" "Once this is done, you will see on the GitHub that your forked repo was " "updated with the changes you have made." msgstr "" +"完成此操作后,您将在 GitHub 上看到您的分叉仓库已根据您所做的更改进行了更新。" #: ../../source/contributor-tutorial-contribute-on-github.rst:176 msgid "Creating and merging a pull request (PR)" -msgstr "" +msgstr "创建和合并拉取请求 (PR)" #: ../../source/contributor-tutorial-contribute-on-github.rst:203 msgid "**Create the PR**" -msgstr "" +msgstr "**创建 PR**" #: ../../source/contributor-tutorial-contribute-on-github.rst:179 msgid "" -"Once you have pushed changes, on the GitHub webpage of your repository " -"you should see the following message:" -msgstr "" +"Once you have pushed changes, on the GitHub webpage of your repository you " +"should see the following message:" +msgstr "推送更改后,在仓库的 GitHub 网页上应该会看到以下信息:" #: ../../source/contributor-tutorial-contribute-on-github.rst:183 msgid "Otherwise you can always find this option in the `Branches` page." -msgstr "" +msgstr "否则,您可以在 \"分支 \"页面找到该选项。" #: ../../source/contributor-tutorial-contribute-on-github.rst:185 msgid "" -"Once you click the `Compare & pull request` button, you should see " -"something similar to this:" -msgstr "" +"Once you click the `Compare & pull request` button, you should see something " +"similar to this:" +msgstr "点击 \"比较和拉取请求 \"按钮后,您应该会看到类似下面的内容:" #: ../../source/contributor-tutorial-contribute-on-github.rst:189 -msgid "At the top you have an explanation of which branch will be merged where:" -msgstr "" +msgid "" +"At the top you have an explanation of which branch will be merged where:" +msgstr "在顶部,你可以看到关于哪个分支将被合并的说明:" #: ../../source/contributor-tutorial-contribute-on-github.rst:193 msgid "" -"In this example you can see that the request is to merge the branch " -"``doc-fixes`` from my forked repository to branch ``main`` from the " -"Flower repository." +"In this example you can see that the request is to merge the branch ``doc-" +"fixes`` from my forked repository to branch ``main`` from the Flower " +"repository." msgstr "" +"在这个例子中,你可以看到请求将我分叉的版本库中的分支 ``doc-fixes`` 合并到 " +"Flower 版本库中的分支 ``main``。" #: ../../source/contributor-tutorial-contribute-on-github.rst:195 msgid "" -"The input box in the middle is there for you to describe what your PR " -"does and to link it to existing issues. We have placed comments (that " -"won't be rendered once the PR is opened) to guide you through the " -"process." +"The input box in the middle is there for you to describe what your PR does " +"and to link it to existing issues. We have placed comments (that won't be " +"rendered once the PR is opened) to guide you through the process." msgstr "" +"中间的输入框供您描述 PR 的作用,并将其与现有问题联系起来。我们在此放置了注释" +"(一旦 PR 打开,注释将不会显示),以指导您完成整个过程。" #: ../../source/contributor-tutorial-contribute-on-github.rst:198 msgid "" "At the bottom you will find the button to open the PR. This will notify " -"reviewers that a new PR has been opened and that they should look over it" -" to merge or to request changes." +"reviewers that a new PR has been opened and that they should look over it to " +"merge or to request changes." msgstr "" +"在底部,您可以找到打开 PR 的按钮。这将通知审核人员新的 PR 已经打开,他们应该" +"查看该 PR 以进行合并或要求修改。" #: ../../source/contributor-tutorial-contribute-on-github.rst:201 msgid "" -"If your PR is not yet ready for review, and you don't want to notify " -"anyone, you have the option to create a draft pull request:" +"If your PR is not yet ready for review, and you don't want to notify anyone, " +"you have the option to create a draft pull request:" msgstr "" +"如果您的 PR 尚未准备好接受审核,而且您不想通知任何人,您可以选择创建一个草案" +"拉取请求:" #: ../../source/contributor-tutorial-contribute-on-github.rst:206 msgid "**Making new changes**" -msgstr "" +msgstr "**作出新的改变**" #: ../../source/contributor-tutorial-contribute-on-github.rst:206 msgid "" "Once the PR has been opened (as draft or not), you can still push new " -"commits to it the same way we did before, by making changes to the branch" -" associated with the PR." +"commits to it the same way we did before, by making changes to the branch " +"associated with the PR." msgstr "" +"一旦 PR 被打开(无论是否作为草案),你仍然可以像以前一样,通过修改与 PR 关联" +"的分支来推送新的提交。" #: ../../source/contributor-tutorial-contribute-on-github.rst:228 msgid "**Review the PR**" -msgstr "" +msgstr "**审查 PR**" #: ../../source/contributor-tutorial-contribute-on-github.rst:209 msgid "" -"Once the PR has been opened or once the draft PR has been marked as " -"ready, a review from code owners will be automatically requested:" -msgstr "" +"Once the PR has been opened or once the draft PR has been marked as ready, a " +"review from code owners will be automatically requested:" +msgstr "一旦 PR 被打开或 PR 草案被标记为就绪,就会自动要求代码所有者进行审核:" #: ../../source/contributor-tutorial-contribute-on-github.rst:213 msgid "" -"Code owners will then look into the code, ask questions, request changes " -"or validate the PR." -msgstr "" +"Code owners will then look into the code, ask questions, request changes or " +"validate the PR." +msgstr "然后,代码所有者会查看代码、提出问题、要求修改或验证 PR。" #: ../../source/contributor-tutorial-contribute-on-github.rst:215 msgid "Merging will be blocked if there are ongoing requested changes." -msgstr "" +msgstr "如果有正在进行的更改请求,合并将被阻止。" #: ../../source/contributor-tutorial-contribute-on-github.rst:219 msgid "" -"To resolve them, just push the necessary changes to the branch associated" -" with the PR:" -msgstr "" +"To resolve them, just push the necessary changes to the branch associated " +"with the PR:" +msgstr "要解决这些问题,只需将必要的更改推送到与 PR 关联的分支即可:" #: ../../source/contributor-tutorial-contribute-on-github.rst:223 msgid "And resolve the conversation:" -msgstr "" +msgstr "并解决对话:" #: ../../source/contributor-tutorial-contribute-on-github.rst:227 msgid "" -"Once all the conversations have been resolved, you can re-request a " -"review." -msgstr "" +"Once all the conversations have been resolved, you can re-request a review." +msgstr "一旦所有对话都得到解决,您就可以重新申请审核。" #: ../../source/contributor-tutorial-contribute-on-github.rst:248 msgid "**Once the PR is merged**" -msgstr "" +msgstr "**一旦 PR 被合并**" #: ../../source/contributor-tutorial-contribute-on-github.rst:231 msgid "" -"If all the automatic tests have passed and reviewers have no more changes" -" to request, they can approve the PR and merge it." +"If all the automatic tests have passed and reviewers have no more changes to " +"request, they can approve the PR and merge it." msgstr "" +"如果所有自动测试都已通过,且审核员不再需要修改,他们就可以批准 PR 并将其合" +"并。" #: ../../source/contributor-tutorial-contribute-on-github.rst:235 msgid "" "Once it is merged, you can delete the branch on GitHub (a button should " "appear to do so) and also delete it locally by doing:" msgstr "" +"合并后,您可以在 GitHub 上删除该分支(会出现一个删除按钮),也可以在本地删除" +"该分支:" #: ../../source/contributor-tutorial-contribute-on-github.rst:242 msgid "Then you should update your forked repository by doing:" -msgstr "" +msgstr "然后,你应该更新你的分叉仓库:" #: ../../source/contributor-tutorial-contribute-on-github.rst:251 msgid "Example of first contribution" -msgstr "" +msgstr "首次捐款实例" #: ../../source/contributor-tutorial-contribute-on-github.rst:254 msgid "Problem" -msgstr "" +msgstr "问题" #: ../../source/contributor-tutorial-contribute-on-github.rst:256 msgid "" -"For our documentation, we’ve started to use the `Diàtaxis framework " -"`_." +"For our documentation, we’ve started to use the `Diàtaxis framework `_." msgstr "" +"对于我们的文档,我们已经开始使用 \"Diàtaxis 框架 `_\"。" #: ../../source/contributor-tutorial-contribute-on-github.rst:258 msgid "" -"Our “How to” guides should have titles that continue the sencence “How to" -" …”, for example, “How to upgrade to Flower 1.0”." +"Our “How to” guides should have titles that continue the sencence “How to " +"…”, for example, “How to upgrade to Flower 1.0”." msgstr "" +"我们的 \"如何 \"指南的标题应延续 \"如何...... \"的句式,例如 \"如何升级到 " +"Flower 1.0\"。" #: ../../source/contributor-tutorial-contribute-on-github.rst:260 msgid "" "Most of our guides do not follow this new format yet, and changing their " "title is (unfortunately) more involved than one might think." msgstr "" +"我们的大多数指南还没有采用这种新格式,而更改其标题(不幸的是)比人们想象的要" +"复杂得多。" #: ../../source/contributor-tutorial-contribute-on-github.rst:262 msgid "" -"This issue is about changing the title of a doc from present continious " -"to present simple." -msgstr "" +"This issue is about changing the title of a doc from present continious to " +"present simple." +msgstr "这个问题是关于将文档标题从现在进行时改为现在进行时。" #: ../../source/contributor-tutorial-contribute-on-github.rst:264 msgid "" "Let's take the example of “Saving Progress” which we changed to “Save " "Progress”. Does this pass our check?" msgstr "" +"以 \"保存进度 \"为例,我们将其改为 \"保存进度\"。这是否通过了我们的检查?" #: ../../source/contributor-tutorial-contribute-on-github.rst:266 msgid "Before: ”How to saving progress” ❌" -msgstr "" +msgstr "之前: \"如何保存进度\" ❌" #: ../../source/contributor-tutorial-contribute-on-github.rst:268 msgid "After: ”How to save progress” ✅" -msgstr "" +msgstr "之后: \"如何保存进度\"✅" #: ../../source/contributor-tutorial-contribute-on-github.rst:271 msgid "Solution" -msgstr "" +msgstr "解决方案" #: ../../source/contributor-tutorial-contribute-on-github.rst:273 msgid "" "This is a tiny change, but it’ll allow us to test your end-to-end setup. " "After cloning and setting up the Flower repo, here’s what you should do:" msgstr "" +"这只是一个很小的改动,但可以让我们测试你的端到端设置。克隆并设置好 Flower " +"repo 后,你应该这样做:" #: ../../source/contributor-tutorial-contribute-on-github.rst:275 msgid "Find the source file in `doc/source`" -msgstr "" +msgstr "在 `doc/source` 中查找源文件" #: ../../source/contributor-tutorial-contribute-on-github.rst:276 msgid "" "Make the change in the `.rst` file (beware, the dashes under the title " "should be the same length as the title itself)" -msgstr "" +msgstr "在 `.rst` 文件中进行修改(注意,标题下的破折号应与标题本身的长度相同)" #: ../../source/contributor-tutorial-contribute-on-github.rst:277 msgid "" "Build the docs and check the result: ``_" msgstr "" +"构建文档并检查结果: ``_" #: ../../source/contributor-tutorial-contribute-on-github.rst:280 msgid "Rename file" -msgstr "" +msgstr "重命名文件" #: ../../source/contributor-tutorial-contribute-on-github.rst:282 msgid "" -"You might have noticed that the file name still reflects the old wording." -" If we just change the file, then we break all existing links to it - it " -"is **very important** to avoid that, breaking links can harm our search " -"engine ranking." +"You might have noticed that the file name still reflects the old wording. If " +"we just change the file, then we break all existing links to it - it is " +"**very important** to avoid that, breaking links can harm our search engine " +"ranking." msgstr "" +"您可能已经注意到,文件名仍然反映了旧的措辞。如果我们只是更改文件,那么就会破" +"坏与该文件的所有现有链接--避免这种情况是***重要的,破坏链接会损害我们的搜索引" +"擎排名。" #: ../../source/contributor-tutorial-contribute-on-github.rst:285 msgid "Here’s how to change the file name:" -msgstr "" +msgstr "下面是更改文件名的方法:" #: ../../source/contributor-tutorial-contribute-on-github.rst:287 msgid "Change the file name to `save-progress.rst`" -msgstr "" +msgstr "将文件名改为`save-progress.rst`" #: ../../source/contributor-tutorial-contribute-on-github.rst:288 msgid "Add a redirect rule to `doc/source/conf.py`" -msgstr "" +msgstr "在 `doc/source/conf.py` 中添加重定向规则" #: ../../source/contributor-tutorial-contribute-on-github.rst:290 msgid "" -"This will cause a redirect from `saving-progress.html` to `save-" -"progress.html`, old links will continue to work." +"This will cause a redirect from `saving-progress.html` to `save-progress." +"html`, old links will continue to work." msgstr "" +"这将导致从 `saving-progress.html` 重定向到 `save-progress.html`,旧链接将继续" +"工作。" #: ../../source/contributor-tutorial-contribute-on-github.rst:293 msgid "Apply changes in the index file" -msgstr "" +msgstr "应用索引文件中的更改" #: ../../source/contributor-tutorial-contribute-on-github.rst:295 msgid "" @@ -1497,112 +1718,121 @@ msgid "" "update the `index.rst` file as well. This is where we define the whole " "arborescence of the navbar." msgstr "" +"要使横向导航栏正常工作,更新 `index.rst` 文件也非常重要。我们就是在这里定义整" +"个导航栏的结构。" #: ../../source/contributor-tutorial-contribute-on-github.rst:298 msgid "Find and modify the file name in `index.rst`" -msgstr "" +msgstr "查找并修改 `index.rst` 中的文件名" #: ../../source/contributor-tutorial-contribute-on-github.rst:301 msgid "Open PR" -msgstr "" +msgstr "开放式 PR" #: ../../source/contributor-tutorial-contribute-on-github.rst:303 msgid "" -"Commit the changes (commit messages are always imperative: “Do " -"something”, in this case “Change …”)" -msgstr "" +"Commit the changes (commit messages are always imperative: “Do something”, " +"in this case “Change …”)" +msgstr "提交更改(提交信息总是命令式的:\"做某事\",这里是 \"更改......\")" #: ../../source/contributor-tutorial-contribute-on-github.rst:304 msgid "Push the changes to your fork" -msgstr "" +msgstr "将更改推送到分叉" #: ../../source/contributor-tutorial-contribute-on-github.rst:305 msgid "Open a PR (as shown above)" -msgstr "" +msgstr "打开 PR(如上图所示)" #: ../../source/contributor-tutorial-contribute-on-github.rst:306 msgid "Wait for it to be approved!" -msgstr "" +msgstr "等待审批!" #: ../../source/contributor-tutorial-contribute-on-github.rst:307 msgid "Congrats! 🥳 You're now officially a Flower contributor!" -msgstr "" +msgstr "祝贺你 🥳 您现在正式成为 \"Flower \"贡献者!" #: ../../source/contributor-tutorial-contribute-on-github.rst:311 msgid "How to write a good PR title" -msgstr "" +msgstr "如何撰写好的公关标题" #: ../../source/contributor-tutorial-contribute-on-github.rst:313 msgid "" -"A well-crafted PR title helps team members quickly understand the purpose" -" and scope of the changes being proposed. Here's a guide to help you " -"write a good GitHub PR title:" +"A well-crafted PR title helps team members quickly understand the purpose " +"and scope of the changes being proposed. Here's a guide to help you write a " +"good GitHub PR title:" msgstr "" +"一个精心撰写的公关标题能帮助团队成员迅速了解所提修改的目的和范围。以下指南可" +"帮助您撰写一个好的 GitHub PR 标题:" #: ../../source/contributor-tutorial-contribute-on-github.rst:315 msgid "" -"1. Be Clear and Concise: Provide a clear summary of the changes in a " -"concise manner. 1. Use Actionable Verbs: Start with verbs like \"Add,\" " -"\"Update,\" or \"Fix\" to indicate the purpose. 1. Include Relevant " -"Information: Mention the affected feature or module for context. 1. Keep " -"it Short: Avoid lengthy titles for easy readability. 1. Use Proper " -"Capitalization and Punctuation: Follow grammar rules for clarity." +"1. Be Clear and Concise: Provide a clear summary of the changes in a concise " +"manner. 1. Use Actionable Verbs: Start with verbs like \"Add,\" \"Update,\" " +"or \"Fix\" to indicate the purpose. 1. Include Relevant Information: Mention " +"the affected feature or module for context. 1. Keep it Short: Avoid lengthy " +"titles for easy readability. 1. Use Proper Capitalization and Punctuation: " +"Follow grammar rules for clarity." msgstr "" +"1. 简明扼要: 以简明扼要的方式清楚地概述变化。1. 使用可操作的动词: 使用 \"添" +"加\"、\"更新 \"或 \"修复 \"等动词来表明目的。1. 包含相关信息: 提及受影响的功" +"能或模块以了解上下文。1. 简短:避免冗长的标题,以方便阅读。1. 使用正确的大小" +"写和标点符号: 遵守语法规则,以确保清晰。" #: ../../source/contributor-tutorial-contribute-on-github.rst:321 msgid "" -"Let's start with a few examples for titles that should be avoided because" -" they do not provide meaningful information:" -msgstr "" +"Let's start with a few examples for titles that should be avoided because " +"they do not provide meaningful information:" +msgstr "让我们先举例说明几个应该避免使用的标题,因为它们不能提供有意义的信息:" #: ../../source/contributor-tutorial-contribute-on-github.rst:323 msgid "Implement Algorithm" -msgstr "" +msgstr "执行算法" #: ../../source/contributor-tutorial-contribute-on-github.rst:324 msgid "Database" -msgstr "" +msgstr "数据库" #: ../../source/contributor-tutorial-contribute-on-github.rst:325 msgid "Add my_new_file.py to codebase" -msgstr "" +msgstr "在代码库中添加 my_new_file.py" #: ../../source/contributor-tutorial-contribute-on-github.rst:326 msgid "Improve code in module" -msgstr "" +msgstr "改进模块中的代码" #: ../../source/contributor-tutorial-contribute-on-github.rst:327 msgid "Change SomeModule" -msgstr "" +msgstr "更改 SomeModule" #: ../../source/contributor-tutorial-contribute-on-github.rst:329 msgid "" -"Here are a few positive examples which provide helpful information " -"without repeating how they do it, as that is already visible in the " -"\"Files changed\" section of the PR:" +"Here are a few positive examples which provide helpful information without " +"repeating how they do it, as that is already visible in the \"Files " +"changed\" section of the PR:" msgstr "" +"这里有几个正面的例子,提供了有用的信息,但没有重复他们是如何做的,因为在 PR " +"的 \"已更改文件 \"部分已经可以看到:" #: ../../source/contributor-tutorial-contribute-on-github.rst:331 msgid "Update docs banner to mention Flower Summit 2023" -msgstr "" +msgstr "更新文件横幅,提及 2023 年 Flower 峰会" #: ../../source/contributor-tutorial-contribute-on-github.rst:332 msgid "Remove unnecessary XGBoost dependency" -msgstr "" +msgstr "移除不必要的 XGBoost 依赖性" #: ../../source/contributor-tutorial-contribute-on-github.rst:333 msgid "Remove redundant attributes in strategies subclassing FedAvg" -msgstr "" +msgstr "删除 FedAvg 子类化策略中的多余属性" #: ../../source/contributor-tutorial-contribute-on-github.rst:334 msgid "Add CI job to deploy the staging system when the `main` branch changes" -msgstr "" +msgstr "添加 CI 作业,以便在 \"主 \"分支发生变化时部署暂存系统" #: ../../source/contributor-tutorial-contribute-on-github.rst:335 msgid "" -"Add new amazing library which will be used to improve the simulation " -"engine" -msgstr "" +"Add new amazing library which will be used to improve the simulation engine" +msgstr "添加新的惊人库,用于改进模拟引擎" #: ../../source/contributor-tutorial-contribute-on-github.rst:339 #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:548 @@ -1611,249 +1841,298 @@ msgstr "" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:713 #: ../../source/tutorial-series-what-is-federated-learning.ipynb:367 msgid "Next steps" -msgstr "" +msgstr "接下来的步骤" #: ../../source/contributor-tutorial-contribute-on-github.rst:341 msgid "" -"Once you have made your first PR, and want to contribute more, be sure to" -" check out the following :" -msgstr "" +"Once you have made your first PR, and want to contribute more, be sure to " +"check out the following :" +msgstr "一旦您完成了第一份 PR,并希望做出更多贡献,请务必查看以下内容:" #: ../../source/contributor-tutorial-contribute-on-github.rst:343 msgid "" -"`Good first contributions `_, where you should particularly look " -"into the :code:`baselines` contributions." +"`Good first contributions `_, where you should particularly look into " +"the :code:`baselines` contributions." msgstr "" +"好的第一批贡献 `_,在这里你应该特别看看 :code:`baselines` 的贡献。" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:2 msgid "Get started as a contributor" -msgstr "" +msgstr "成为贡献者" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:5 msgid "Prerequisites" -msgstr "" +msgstr "先决条件" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:7 msgid "`Python 3.7 `_ or above" -msgstr "" +msgstr "Python 3.7 `_ 或更高版本" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:8 msgid "`Poetry 1.3 `_ or above" -msgstr "" +msgstr "`Poetry 1.3 `_ 或更高版本" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:9 msgid "(Optional) `pyenv `_" -msgstr "" +msgstr "(可选) `pyenv `_" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:10 -msgid "(Optional) `pyenv-virtualenv `_" +msgid "" +"(Optional) `pyenv-virtualenv `_" msgstr "" +"(可选) `pyenv-virtualenv `_" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:12 msgid "" "Flower uses :code:`pyproject.toml` to manage dependencies and configure " -"development tools (the ones which support it). Poetry is a build tool " -"which supports `PEP 517 `_." +"development tools (the ones which support it). Poetry is a build tool which " +"supports `PEP 517 `_." msgstr "" +"Flower 使用 :code:`pyproject.toml` 来管理依赖关系和配置开发工具(支持它的)。" +"Poetry 是一种支持 `PEP 517 `_ 的构" +"建工具。" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:18 msgid "Developer Machine Setup" -msgstr "" +msgstr "开发者机器设置" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:20 msgid "" -"First, clone the `Flower repository `_ " -"from GitHub::" +"First, clone the `Flower repository `_ from " +"GitHub::" msgstr "" +"首先,从 GitHub 克隆 \"Flower 存储库 `_\":" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:26 msgid "" -"Second, create a virtual environment (and activate it). If you chose to " -"use :code:`pyenv` (with the :code:`pyenv-virtualenv` plugin) and already " -"have it installed , you can use the following convenience script (by " -"default it will use :code:`Python 3.8.17`, but you can change it by " -"providing a specific :code:``)::" +"Second, create a virtual environment (and activate it). If you chose to use :" +"code:`pyenv` (with the :code:`pyenv-virtualenv` plugin) and already have it " +"installed , you can use the following convenience script (by default it will " +"use :code:`Python 3.8.17`, but you can change it by providing a specific :" +"code:``)::" msgstr "" +"其次,创建虚拟环境(并激活它)。如果您选择使用 :code:`pyenv`(使用 :code:" +"`pyenv-virtualenv`插件),并且已经安装了该插件,则可以使用下面的便捷脚本(默" +"认情况下使用 :code:`Python3.8.17`,但您可以通过提供特定的 :code:`<版本>`来更" +"改)::" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:33 msgid "" -"If you don't have :code:`pyenv` installed, you can use the following " -"script that will install pyenv, set it up and create the virtual " -"environment (with :code:`Python 3.8.17` by default)::" +"If you don't have :code:`pyenv` installed, you can use the following script " +"that will install pyenv, set it up and create the virtual environment (with :" +"code:`Python 3.8.17` by default)::" msgstr "" +"如果没有安装 :code:`pyenv`,可以使用以下脚本安装 pyenv、设置并创建虚拟环境" +"(默认使用 :code:`Python3.8.17)::" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:39 msgid "" "Third, install the Flower package in development mode (think :code:`pip " "install -e`) along with all necessary dependencies::" msgstr "" +"第三,在开发模式下安装 Flower 软件包(想想 :code:`pip install -e`)以及所有必" +"要的依赖项::" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:46 msgid "Convenience Scripts" -msgstr "" +msgstr "便捷脚本" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:48 msgid "" "The Flower repository contains a number of convenience scripts to make " -"recurring development tasks easier and less error-prone. See the " -":code:`/dev` subdirectory for a full list. The following scripts are " -"amonst the most important ones:" +"recurring development tasks easier and less error-prone. See the :code:`/" +"dev` subdirectory for a full list. The following scripts are amonst the most " +"important ones:" msgstr "" +"Flower 软件仓库包含大量便捷脚本,可使重复性开发任务更轻松、更不易出错。完整列" +"表请参见 :code:`/dev` 子目录。以下是最重要的脚本:" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:54 msgid "Create/Delete Virtual Environment" -msgstr "" +msgstr "创建/删除虚拟环境" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:62 msgid "Compile ProtoBuf Definitions" -msgstr "" +msgstr "编译 ProtoBuf 定义" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:69 msgid "Auto-Format Code" -msgstr "" +msgstr "自动格式化代码" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:76 msgid "Run Linters and Tests" -msgstr "" +msgstr "运行分类器和测试" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:83 msgid "Run Github Actions (CI) locally" -msgstr "" +msgstr "在本地运行 Github 操作 (CI)" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:85 msgid "" -"Developers could run the full set of Github Actions workflows under their" -" local environment by using `Act _`. " -"Please refer to the installation instructions under the linked repository" -" and run the next command under Flower main cloned repository folder::" +"Developers could run the full set of Github Actions workflows under their " +"local environment by using `Act _`. Please " +"refer to the installation instructions under the linked repository and run " +"the next command under Flower main cloned repository folder::" msgstr "" +"开发人员可以使用 `Act _` 在本地环境下运行全套 " +"Github Actions 工作流程。请参考链接仓库下的安装说明,并在 Flower 主克隆仓库文" +"件夹下运行下一条命令::" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:92 msgid "" "The Flower default workflow would run by setting up the required Docker " "machines underneath." -msgstr "" +msgstr "Flower 默认工作流程将通过在下面设置所需的 Docker 机器来运行。" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:97 msgid "Build Release" -msgstr "" +msgstr "版本发布" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:99 msgid "" -"Flower uses Poetry to build releases. The necessary command is wrapped in" -" a simple script::" -msgstr "" +"Flower uses Poetry to build releases. The necessary command is wrapped in a " +"simple script::" +msgstr "Flower 使用 Poetry 创建发布版本。必要的命令封装在一个简单的脚本中::" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:104 msgid "" -"The resulting :code:`.whl` and :code:`.tar.gz` releases will be stored in" -" the :code:`/dist` subdirectory." +"The resulting :code:`.whl` and :code:`.tar.gz` releases will be stored in " +"the :code:`/dist` subdirectory." msgstr "" +"生成的 :code:`.whl` 和 :code:`.tar.gz` 版本将存储在 :code:`/dist` 子目录中。" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:109 msgid "Build Documentation" -msgstr "" +msgstr "构建文档" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:111 msgid "" -"Flower's documentation uses `Sphinx `_. " -"There's no convenience script to re-build the documentation yet, but it's" -" pretty easy::" +"Flower's documentation uses `Sphinx `_. There's " +"no convenience script to re-build the documentation yet, but it's pretty " +"easy::" msgstr "" +"Flower 的文档使用 `Sphinx `_。目前还没有很方便的" +"脚本来重新构建文档,不过这很容易::" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:117 msgid "This will generate HTML documentation in ``doc/build/html``." -msgstr "" +msgstr "这将在 ``doc/build/html`` 中生成 HTML 文档。" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:2 msgid "Example: FedBN in PyTorch - From Centralized To Federated" -msgstr "" +msgstr "示例: PyTorch 中的 FedBN - 从集中式到联邦式" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:4 msgid "" -"This tutorial will show you how to use Flower to build a federated " -"version of an existing machine learning workload with `FedBN " -"`_, a federated training strategy " -"designed for non-iid data. We are using PyTorch to train a Convolutional " -"Neural Network(with Batch Normalization layers) on the CIFAR-10 dataset. " -"When applying FedBN, only few changes needed compared to `Example: " -"PyTorch - From Centralized To Federated `_." -msgstr "" +"This tutorial will show you how to use Flower to build a federated version " +"of an existing machine learning workload with `FedBN `_, a federated training strategy designed for non-iid data. We " +"are using PyTorch to train a Convolutional Neural Network(with Batch " +"Normalization layers) on the CIFAR-10 dataset. When applying FedBN, only few " +"changes needed compared to `Example: PyTorch - From Centralized To Federated " +"`_." +msgstr "" +"本教程将向您展示如何使用 Flower 为现有的机器学习框架构建一个联邦学习的版本," +"并使用 \"FedBN `_\"(一种针对非 iid 数据设" +"计的联邦训练策略)。我们使用 PyTorch 在 CIFAR-10 数据集上训练一个卷积神经网络" +"(带有Batch Normalization层)。在应用 FedBN 时,只需对 `示例: PyTorch - 从集" +"中式到联邦式 `_ 做少量改动。" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:9 #: ../../source/example-pytorch-from-centralized-to-federated.rst:10 msgid "Centralized Training" -msgstr "" +msgstr "集中式训练" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:10 msgid "" "All files are revised based on `Example: PyTorch - From Centralized To " "Federated `_. The only thing to do is modifying the file called " -":code:`cifar.py`, revised part is shown below:" +"federated.html>`_. The only thing to do is modifying the file called :code:" +"`cifar.py`, revised part is shown below:" msgstr "" +"所有文件均根据 `示例: PyTorch -从集中式到联邦式 `_。唯一要做的就是修改名" +"为 :code:`cifar.py` 的文件,修改部分如下所示:" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:13 msgid "" "The model architecture defined in class Net() is added with Batch " "Normalization layers accordingly." -msgstr "" +msgstr "类 Net() 中定义的模型架构会相应添加Batch Normalization层。" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:41 #: ../../source/example-pytorch-from-centralized-to-federated.rst:157 msgid "You can now run your machine learning workload:" -msgstr "" +msgstr "现在,您可以运行您的机器学习工作了:" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:47 msgid "" -"So far this should all look fairly familiar if you've used PyTorch " -"before. Let's take the next step and use what we've built to create a " -"federated learning system within FedBN, the sytstem consists of one " -"server and two clients." +"So far this should all look fairly familiar if you've used PyTorch before. " +"Let's take the next step and use what we've built to create a federated " +"learning system within FedBN, the sytstem consists of one server and two " +"clients." msgstr "" +"到目前为止,如果您以前使用过 PyTorch,这一切看起来应该相当熟悉。让我们进行下" +"一步,使用我们所构建的内容在 FedBN 中创建一个联邦学习系统,该系统由一个服务器" +"和两个客户端组成。" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:51 #: ../../source/example-pytorch-from-centralized-to-federated.rst:167 msgid "Federated Training" -msgstr "" +msgstr "联邦培训" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:53 msgid "" -"If you have read `Example: PyTorch - From Centralized To Federated " -"`_, the following parts are easy to follow, onyl " -":code:`get_parameters` and :code:`set_parameters` function in " -":code:`client.py` needed to revise. If not, please read the `Example: " -"PyTorch - From Centralized To Federated `_. first." -msgstr "" +"If you have read `Example: PyTorch - From Centralized To Federated `_, the " +"following parts are easy to follow, onyl :code:`get_parameters` and :code:" +"`set_parameters` function in :code:`client.py` needed to revise. If not, " +"please read the `Example: PyTorch - From Centralized To Federated `_. " +"first." +msgstr "" +"如果你读过 `示例: PyTorch - 从集中式到联邦式 `_,下面的部分就很容易理" +"解了,只需要修改 :code:`get_parameters` 和 :code:`set_parameters` 中的 :code:" +"`client.py` 函数。如果没有,请阅读 `示例: PyTorch - 从集中式到联邦式 " +"`_。" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:56 msgid "" -"Our example consists of one *server* and two *clients*. In FedBN, " -":code:`server.py` keeps unchanged, we can start the server directly." +"Our example consists of one *server* and two *clients*. In FedBN, :code:" +"`server.py` keeps unchanged, we can start the server directly." msgstr "" +"我们的示例包括一个*服务器*和两个*客户端*。在 FedBN 中,:code:`server.py` 保持" +"不变,我们可以直接启动服务器。" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:62 msgid "" -"Finally, we will revise our *client* logic by changing " -":code:`get_parameters` and :code:`set_parameters` in :code:`client.py`, " -"we will exclude batch normalization parameters from model parameter list " -"when sending to or receiving from the server." +"Finally, we will revise our *client* logic by changing :code:" +"`get_parameters` and :code:`set_parameters` in :code:`client.py`, we will " +"exclude batch normalization parameters from model parameter list when " +"sending to or receiving from the server." msgstr "" +"最后,我们将修改 *client* 的逻辑,修改 :code:`client.py` 中的 :code:" +"`get_parameters` 和 :code:`set_parameters`,在向服务器发送或从服务器接收时," +"我们将从模型参数列表中排除batch normalization层的参数。" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:85 msgid "Now, you can now open two additional terminal windows and run" -msgstr "" +msgstr "现在,您可以打开另外两个终端窗口并运行程序" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:91 msgid "" -"in each window (make sure that the server is still running before you do " -"so) and see your (previously centralized) PyTorch project run federated " -"learning with FedBN strategy across two clients. Congratulations!" +"in each window (make sure that the server is still running before you do so) " +"and see your (previously centralized) PyTorch project run federated learning " +"with FedBN strategy across two clients. Congratulations!" msgstr "" +"确保服务器仍在运行后,然后您就能看到您的 PyTorch 项目(之前是集中式的)通过 " +"FedBN 策略在两个客户端上运行联合学习。祝贺!" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:94 #: ../../source/example-jax-from-centralized-to-federated.rst:277 @@ -1861,214 +2140,262 @@ msgstr "" #: ../../source/example-pytorch-from-centralized-to-federated.rst:310 #: ../../source/tutorial-quickstart-jax.rst:283 msgid "Next Steps" -msgstr "" +msgstr "下一步工作" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:96 msgid "" -"The full source code for this example can be found `here " -"`_. Our example is of course somewhat over-" -"simplified because both clients load the exact same dataset, which isn't " -"realistic. You're now prepared to explore this topic further. How about " -"using different subsets of CIFAR-10 on each client? How about adding more" -" clients?" +"The full source code for this example can be found `here `_. Our " +"example is of course somewhat over-simplified because both clients load the " +"exact same dataset, which isn't realistic. You're now prepared to explore " +"this topic further. How about using different subsets of CIFAR-10 on each " +"client? How about adding more clients?" msgstr "" +"本示例的完整源代码可在 `_ 找到。当然,我们的示例有些过于简单," +"因为两个客户端都加载了完全相同的数据集,这并不真实。让我们准备好进一步探讨这" +"一主题。如在每个客户端使用不同的 CIFAR-10 子集,或者增加客户端的数量。" #: ../../source/example-jax-from-centralized-to-federated.rst:2 msgid "Example: JAX - Run JAX Federated" -msgstr "" +msgstr "示例: JAX - 运行联邦式 JAX" #: ../../source/example-jax-from-centralized-to-federated.rst:4 #: ../../source/tutorial-quickstart-jax.rst:10 msgid "" -"This tutorial will show you how to use Flower to build a federated " -"version of an existing JAX workload. We are using JAX to train a linear " -"regression model on a scikit-learn dataset. We will structure the example" -" similar to our `PyTorch - From Centralized To Federated " -"`_ walkthrough. First, we build a centralized " -"training approach based on the `Linear Regression with JAX " -"`_" -" tutorial`. Then, we build upon the centralized training code to run the " -"training in a federated fashion." -msgstr "" +"This tutorial will show you how to use Flower to build a federated version " +"of an existing JAX workload. We are using JAX to train a linear regression " +"model on a scikit-learn dataset. We will structure the example similar to " +"our `PyTorch - From Centralized To Federated `_ walkthrough. " +"First, we build a centralized training approach based on the `Linear " +"Regression with JAX `_ tutorial`. Then, we build upon the centralized " +"training code to run the training in a federated fashion." +msgstr "" +"本教程将向您展示如何使用 Flower 构建现有 JAX 的联邦学习版本。我们将使用 JAX " +"在 scikit-learn 数据集上训练线性回归模型。我们将采用与 `PyTorch - 从集中式到" +"联邦式 `_ 教程中类似的示例结构。首先,我们根据 `JAX 的线性" +"回归 `_ 教程构建集中式训练方法。然后,我们在集中式训练代码的基础上以联邦方式" +"运行训练。" #: ../../source/example-jax-from-centralized-to-federated.rst:10 #: ../../source/tutorial-quickstart-jax.rst:16 msgid "" -"Before we start building our JAX example, we need install the packages " -":code:`jax`, :code:`jaxlib`, :code:`scikit-learn`, and :code:`flwr`:" +"Before we start building our JAX example, we need install the packages :code:" +"`jax`, :code:`jaxlib`, :code:`scikit-learn`, and :code:`flwr`:" msgstr "" +"在开始构建 JAX 示例之前,我们需要安装软件包 :code:`jax`、:code:`jaxlib`、:" +"code:`scikit-learn` 和 :code:`flwr`:" #: ../../source/example-jax-from-centralized-to-federated.rst:18 #: ../../source/tutorial-quickstart-jax.rst:24 msgid "Linear Regression with JAX" -msgstr "" +msgstr "使用 JAX 进行线性回归" #: ../../source/example-jax-from-centralized-to-federated.rst:20 #: ../../source/tutorial-quickstart-jax.rst:26 msgid "" -"We begin with a brief description of the centralized training code based " -"on a :code:`Linear Regression` model. If you want a more in-depth " -"explanation of what's going on then have a look at the official `JAX " -"documentation `_." +"We begin with a brief description of the centralized training code based on " +"a :code:`Linear Regression` model. If you want a more in-depth explanation " +"of what's going on then have a look at the official `JAX documentation " +"`_." msgstr "" +"首先,我们将简要介绍基于 :code:`Linear Regression` 模型的集中式训练代码。如果" +"您想获得更深入的解释,请参阅官方的 `JAX 文档 `_。" #: ../../source/example-jax-from-centralized-to-federated.rst:23 #: ../../source/tutorial-quickstart-jax.rst:29 msgid "" "Let's create a new file called :code:`jax_training.py` with all the " "components required for a traditional (centralized) linear regression " -"training. First, the JAX packages :code:`jax` and :code:`jaxlib` need to " -"be imported. In addition, we need to import :code:`sklearn` since we use " -":code:`make_regression` for the dataset and :code:`train_test_split` to " -"split the dataset into a training and test set. You can see that we do " -"not yet import the :code:`flwr` package for federated learning. This will" -" be done later." -msgstr "" +"training. First, the JAX packages :code:`jax` and :code:`jaxlib` need to be " +"imported. In addition, we need to import :code:`sklearn` since we use :code:" +"`make_regression` for the dataset and :code:`train_test_split` to split the " +"dataset into a training and test set. You can see that we do not yet import " +"the :code:`flwr` package for federated learning. This will be done later." +msgstr "" +"让我们创建一个名为 :code:`jax_training.py` 的新文件,其中包含传统(集中式)线" +"性回归训练所需的所有组件。首先,需要导入 JAX 包 :code:`jax` 和 :code:" +"`jaxlib`。此外,我们还需要导入 :code:`sklearn`,因为我们使用 :code:" +"`make_regression` 创建数据集,并使用 :code:`train_test_split` 将数据集拆分成" +"训练集和测试集。您可以看到,我们还没有导入用于联邦学习的 :code:`flwr` 软件" +"包,这将在稍后完成。" #: ../../source/example-jax-from-centralized-to-federated.rst:37 #: ../../source/tutorial-quickstart-jax.rst:43 msgid "" -"The :code:`load_data()` function loads the mentioned training and test " -"sets." -msgstr "" +"The :code:`load_data()` function loads the mentioned training and test sets." +msgstr ":code:`load_data()` 函数会加载上述训练集和测试集。" #: ../../source/example-jax-from-centralized-to-federated.rst:47 #: ../../source/tutorial-quickstart-jax.rst:53 msgid "" -"The model architecture (a very simple :code:`Linear Regression` model) is" -" defined in :code:`load_model()`." +"The model architecture (a very simple :code:`Linear Regression` model) is " +"defined in :code:`load_model()`." msgstr "" +"模型结构(一个非常简单的 :code:`Linear Regression` 线性回归模型)在 :code:" +"`load_model()` 中定义。" #: ../../source/example-jax-from-centralized-to-federated.rst:59 #: ../../source/tutorial-quickstart-jax.rst:65 msgid "" -"We now need to define the training (function :code:`train()`), which " -"loops over the training set and measures the loss (function " -":code:`loss_fn()`) for each batch of training examples. The loss function" -" is separate since JAX takes derivatives with a :code:`grad()` function " -"(defined in the :code:`main()` function and called in :code:`train()`)." +"We now need to define the training (function :code:`train()`), which loops " +"over the training set and measures the loss (function :code:`loss_fn()`) for " +"each batch of training examples. The loss function is separate since JAX " +"takes derivatives with a :code:`grad()` function (defined in the :code:" +"`main()` function and called in :code:`train()`)." msgstr "" +"现在,我们需要定义训练函数( :code:`train()`)。它循环遍历训练集,并计算每批" +"训练数据的损失值(函数 :code:`loss_fn()`)。由于 JAX 使用 :code:`grad()` 函数" +"提取导数(在 :code:`main()` 函数中定义,并在 :code:`train()` 中调用),因此损" +"失函数是独立的。" #: ../../source/example-jax-from-centralized-to-federated.rst:77 #: ../../source/tutorial-quickstart-jax.rst:83 msgid "" -"The evaluation of the model is defined in the function " -":code:`evaluation()`. The function takes all test examples and measures " -"the loss of the linear regression model." +"The evaluation of the model is defined in the function :code:`evaluation()`. " +"The function takes all test examples and measures the loss of the linear " +"regression model." msgstr "" +"模型的评估在函数 :code:`evaluation()` 中定义。该函数获取所有测试数据,并计算" +"线性回归模型的损失值。" #: ../../source/example-jax-from-centralized-to-federated.rst:88 #: ../../source/tutorial-quickstart-jax.rst:94 msgid "" "Having defined the data loading, model architecture, training, and " -"evaluation we can put everything together and train our model using JAX. " -"As already mentioned, the :code:`jax.grad()` function is defined in " -":code:`main()` and passed to :code:`train()`." +"evaluation we can put everything together and train our model using JAX. As " +"already mentioned, the :code:`jax.grad()` function is defined in :code:" +"`main()` and passed to :code:`train()`." msgstr "" +"在定义了数据加载、模型架构、训练和评估之后,我们就可以把这些放在一起,使用 " +"JAX 训练我们的模型了。如前所述,:code:`jax.grad()` 函数在 :code:`main()` 中定" +"义,并传递给 :code:`train()`。" #: ../../source/example-jax-from-centralized-to-federated.rst:105 #: ../../source/tutorial-quickstart-jax.rst:111 msgid "You can now run your (centralized) JAX linear regression workload:" -msgstr "" +msgstr "现在您可以运行(集中式)JAX 线性回归工作了:" #: ../../source/example-jax-from-centralized-to-federated.rst:111 #: ../../source/tutorial-quickstart-jax.rst:117 msgid "" -"So far this should all look fairly familiar if you've used JAX before. " -"Let's take the next step and use what we've built to create a simple " -"federated learning system consisting of one server and two clients." +"So far this should all look fairly familiar if you've used JAX before. Let's " +"take the next step and use what we've built to create a simple federated " +"learning system consisting of one server and two clients." msgstr "" +"到目前为止,如果你以前使用过 JAX,就会对这一切感到很熟悉。下一步,让我们利用" +"已构建的代码创建一个简单的联邦学习系统(一个服务器和两个客户端)。" #: ../../source/example-jax-from-centralized-to-federated.rst:115 #: ../../source/tutorial-quickstart-jax.rst:121 msgid "JAX meets Flower" -msgstr "" +msgstr "JAX 结合 Flower" #: ../../source/example-jax-from-centralized-to-federated.rst:117 #: ../../source/tutorial-quickstart-jax.rst:123 msgid "" -"The concept of federating an existing workload is always the same and " -"easy to understand. We have to start a *server* and then use the code in " -":code:`jax_training.py` for the *clients* that are connected to the " -"*server*. The *server* sends model parameters to the clients. The " -"*clients* run the training and update the parameters. The updated " -"parameters are sent back to the *server*, which averages all received " -"parameter updates. This describes one round of the federated learning " -"process, and we repeat this for multiple rounds." -msgstr "" +"The concept of federating an existing workload is always the same and easy " +"to understand. We have to start a *server* and then use the code in :code:" +"`jax_training.py` for the *clients* that are connected to the *server*. The " +"*server* sends model parameters to the clients. The *clients* run the " +"training and update the parameters. The updated parameters are sent back to " +"the *server*, which averages all received parameter updates. This describes " +"one round of the federated learning process, and we repeat this for multiple " +"rounds." +msgstr "" +"把现有工作联邦化的概念始终是相同的,也很容易理解。我们要启动一个*服务器*,然" +"后对连接到*服务器*的*客户端*运行 :code:`jax_training.py`中的代码。*服务器*向" +"客户端发送模型参数,*客户端*运行训练并更新参数。更新后的参数被发回*服务器*," +"然后服务器对所有收到的参数进行平均聚合。以上的描述构成了一轮联邦学习,我们将" +"重复进行多轮学习。" #: ../../source/example-jax-from-centralized-to-federated.rst:123 #: ../../source/example-mxnet-walk-through.rst:204 #: ../../source/example-pytorch-from-centralized-to-federated.rst:181 #: ../../source/tutorial-quickstart-jax.rst:129 msgid "" -"Our example consists of one *server* and two *clients*. Let's set up " -":code:`server.py` first. The *server* needs to import the Flower package " -":code:`flwr`. Next, we use the :code:`start_server` function to start a " -"server and tell it to perform three rounds of federated learning." +"Our example consists of one *server* and two *clients*. Let's set up :code:" +"`server.py` first. The *server* needs to import the Flower package :code:" +"`flwr`. Next, we use the :code:`start_server` function to start a server and " +"tell it to perform three rounds of federated learning." msgstr "" +"我们的示例包括一个*服务器*和两个*客户端*。让我们先设置 :code:`server.py`。*服" +"务器*需要导入 Flower 软件包 :code:`flwr`。接下来,我们使用 :code:" +"`start_server` 函数启动服务器,并让它执行三轮联邦学习。" #: ../../source/example-jax-from-centralized-to-federated.rst:133 #: ../../source/example-mxnet-walk-through.rst:214 #: ../../source/example-pytorch-from-centralized-to-federated.rst:191 #: ../../source/tutorial-quickstart-jax.rst:139 msgid "We can already start the *server*:" -msgstr "" +msgstr "我们已经可以启动*服务器*了:" #: ../../source/example-jax-from-centralized-to-federated.rst:139 #: ../../source/tutorial-quickstart-jax.rst:145 msgid "" -"Finally, we will define our *client* logic in :code:`client.py` and build" -" upon the previously defined JAX training in :code:`jax_training.py`. Our" -" *client* needs to import :code:`flwr`, but also :code:`jax` and " -":code:`jaxlib` to update the parameters on our JAX model:" +"Finally, we will define our *client* logic in :code:`client.py` and build " +"upon the previously defined JAX training in :code:`jax_training.py`. Our " +"*client* needs to import :code:`flwr`, but also :code:`jax` and :code:" +"`jaxlib` to update the parameters on our JAX model:" msgstr "" +"最后,我们将在 :code:`client.py` 中定义我们的 *client* 逻辑,并以之前在 :" +"code:`jax_training.py` 中定义的 JAX 训练为基础。我们的 *client* 需要导入 :" +"code:`flwr`,还需要导入 :code:`jax` 和 :code:`jaxlib` 以更新 JAX 模型的参数:" #: ../../source/example-jax-from-centralized-to-federated.rst:154 #: ../../source/tutorial-quickstart-jax.rst:160 msgid "" -"Implementing a Flower *client* basically means implementing a subclass of" -" either :code:`flwr.client.Client` or :code:`flwr.client.NumPyClient`. " -"Our implementation will be based on :code:`flwr.client.NumPyClient` and " -"we'll call it :code:`FlowerClient`. :code:`NumPyClient` is slightly " -"easier to implement than :code:`Client` if you use a framework with good " -"NumPy interoperability (like JAX) because it avoids some of the " -"boilerplate that would otherwise be necessary. :code:`FlowerClient` needs" -" to implement four methods, two methods for getting/setting model " -"parameters, one method for training the model, and one method for testing" -" the model:" -msgstr "" +"Implementing a Flower *client* basically means implementing a subclass of " +"either :code:`flwr.client.Client` or :code:`flwr.client.NumPyClient`. Our " +"implementation will be based on :code:`flwr.client.NumPyClient` and we'll " +"call it :code:`FlowerClient`. :code:`NumPyClient` is slightly easier to " +"implement than :code:`Client` if you use a framework with good NumPy " +"interoperability (like JAX) because it avoids some of the boilerplate that " +"would otherwise be necessary. :code:`FlowerClient` needs to implement four " +"methods, two methods for getting/setting model parameters, one method for " +"training the model, and one method for testing the model:" +msgstr "" +"实现一个 Flower *client*基本上意味着去实现一个 :code:`flwr.client.Client` " +"或 :code:`flwr.client.NumPyClient` 的子类。我们的代码实现将基于 :code:`flwr." +"client.NumPyClient`,并将其命名为 :code:`FlowerClient`。如果使用具有良好 " +"NumPy 互操作性的框架(如 JAX),:code:`NumPyClient` 比 :code:`Client`更容易实" +"现,因为它避免了一些不必要的操作。:code:`FlowerClient` 需要实现四个方法,两个" +"用于获取/设置模型参数,一个用于训练模型,一个用于测试模型:" #: ../../source/example-jax-from-centralized-to-federated.rst:161 #: ../../source/example-mxnet-walk-through.rst:242 #: ../../source/tutorial-quickstart-jax.rst:167 msgid ":code:`set_parameters (optional)`" -msgstr "" +msgstr ":code:`set_parameters (可选)`" #: ../../source/example-jax-from-centralized-to-federated.rst:160 #: ../../source/example-mxnet-walk-through.rst:241 #: ../../source/example-pytorch-from-centralized-to-federated.rst:219 #: ../../source/tutorial-quickstart-jax.rst:166 msgid "" -"set the model parameters on the local model that are received from the " -"server" -msgstr "" +"set the model parameters on the local model that are received from the server" +msgstr "在本地模型上设置从服务器接收的模型参数" #: ../../source/example-jax-from-centralized-to-federated.rst:161 #: ../../source/tutorial-quickstart-jax.rst:167 msgid "transform parameters to NumPy :code:`ndarray`'s" -msgstr "" +msgstr "将参数转换为 NumPy :code:`ndarray`格式" #: ../../source/example-jax-from-centralized-to-federated.rst:162 #: ../../source/example-mxnet-walk-through.rst:243 #: ../../source/example-pytorch-from-centralized-to-federated.rst:220 #: ../../source/tutorial-quickstart-jax.rst:168 msgid "" -"loop over the list of model parameters received as NumPy " -":code:`ndarray`'s (think list of neural network layers)" +"loop over the list of model parameters received as NumPy :code:`ndarray`'s " +"(think list of neural network layers)" msgstr "" +"循环遍历以 NumPy :code:`ndarray` 形式接收的模型参数列表(可以看作神经网络的列" +"表)" #: ../../source/example-jax-from-centralized-to-federated.rst:163 #: ../../source/example-mxnet-walk-through.rst:244 @@ -2078,16 +2405,18 @@ msgstr "" #: ../../source/tutorial-quickstart-pytorch.rst:155 #: ../../source/tutorial-quickstart-scikitlearn.rst:108 msgid ":code:`get_parameters`" -msgstr "" +msgstr ":code:`get_parameters`" #: ../../source/example-jax-from-centralized-to-federated.rst:164 #: ../../source/example-mxnet-walk-through.rst:245 #: ../../source/example-pytorch-from-centralized-to-federated.rst:222 #: ../../source/tutorial-quickstart-jax.rst:170 msgid "" -"get the model parameters and return them as a list of NumPy " -":code:`ndarray`'s (which is what :code:`flwr.client.NumPyClient` expects)" +"get the model parameters and return them as a list of NumPy :code:" +"`ndarray`'s (which is what :code:`flwr.client.NumPyClient` expects)" msgstr "" +"获取模型参数,并以 NumPy :code:`ndarray`的列表形式返回(这正是 :code:`flwr." +"client.NumPyClient`所匹配的格式)" #: ../../source/example-jax-from-centralized-to-federated.rst:167 #: ../../source/example-mxnet-walk-through.rst:248 @@ -2097,7 +2426,7 @@ msgstr "" #: ../../source/tutorial-quickstart-pytorch.rst:161 #: ../../source/tutorial-quickstart-scikitlearn.rst:115 msgid ":code:`fit`" -msgstr "" +msgstr ":code:`fit`" #: ../../source/example-jax-from-centralized-to-federated.rst:166 #: ../../source/example-jax-from-centralized-to-federated.rst:170 @@ -2108,21 +2437,21 @@ msgstr "" #: ../../source/tutorial-quickstart-jax.rst:172 #: ../../source/tutorial-quickstart-jax.rst:176 msgid "" -"update the parameters of the local model with the parameters received " -"from the server" -msgstr "" +"update the parameters of the local model with the parameters received from " +"the server" +msgstr "用从服务器接收到的参数更新本地模型的参数" #: ../../source/example-jax-from-centralized-to-federated.rst:167 #: ../../source/example-mxnet-walk-through.rst:248 #: ../../source/example-pytorch-from-centralized-to-federated.rst:225 #: ../../source/tutorial-quickstart-jax.rst:173 msgid "train the model on the local training set" -msgstr "" +msgstr "在本地训练集上训练模型" #: ../../source/example-jax-from-centralized-to-federated.rst:168 #: ../../source/tutorial-quickstart-jax.rst:174 msgid "get the updated local model parameters and return them to the server" -msgstr "" +msgstr "获取更新后的本地模型参数并返回服务器" #: ../../source/example-jax-from-centralized-to-federated.rst:172 #: ../../source/example-mxnet-walk-through.rst:253 @@ -2132,307 +2461,384 @@ msgstr "" #: ../../source/tutorial-quickstart-pytorch.rst:164 #: ../../source/tutorial-quickstart-scikitlearn.rst:118 msgid ":code:`evaluate`" -msgstr "" +msgstr ":code:`evaluate`" #: ../../source/example-jax-from-centralized-to-federated.rst:171 #: ../../source/example-mxnet-walk-through.rst:252 #: ../../source/example-pytorch-from-centralized-to-federated.rst:229 #: ../../source/tutorial-quickstart-jax.rst:177 msgid "evaluate the updated model on the local test set" -msgstr "" +msgstr "在本地测试集上评估更新后的模型" #: ../../source/example-jax-from-centralized-to-federated.rst:172 #: ../../source/tutorial-quickstart-jax.rst:178 msgid "return the local loss to the server" -msgstr "" +msgstr "向服务器返回本地损失值" #: ../../source/example-jax-from-centralized-to-federated.rst:174 #: ../../source/tutorial-quickstart-jax.rst:180 msgid "" -"The challenging part is to transform the JAX model parameters from " -":code:`DeviceArray` to :code:`NumPy ndarray` to make them compatible with" -" `NumPyClient`." +"The challenging part is to transform the JAX model parameters from :code:" +"`DeviceArray` to :code:`NumPy ndarray` to make them compatible with " +"`NumPyClient`." msgstr "" +"具有挑战性的部分是将 JAX 模型参数从 :code:`DeviceArray` 转换为 :code:`NumPy " +"ndarray`,使其与 `NumPyClient` 兼容。" #: ../../source/example-jax-from-centralized-to-federated.rst:176 #: ../../source/tutorial-quickstart-jax.rst:182 msgid "" -"The two :code:`NumPyClient` methods :code:`fit` and :code:`evaluate` make" -" use of the functions :code:`train()` and :code:`evaluate()` previously " +"The two :code:`NumPyClient` methods :code:`fit` and :code:`evaluate` make " +"use of the functions :code:`train()` and :code:`evaluate()` previously " "defined in :code:`jax_training.py`. So what we really do here is we tell " -"Flower through our :code:`NumPyClient` subclass which of our already " -"defined functions to call for training and evaluation. We included type " -"annotations to give you a better understanding of the data types that get" -" passed around." +"Flower through our :code:`NumPyClient` subclass which of our already defined " +"functions to call for training and evaluation. We included type annotations " +"to give you a better understanding of the data types that get passed around." msgstr "" +"这两个 :code:`NumPyClient` 方法 :code:`fit` 和 :code:`evaluate` 使用了之前" +"在 :code:`jax_training.py` 中定义的函数 :code:`train()` 和 :code:" +"`evaluate()`。因此,我们在这里要做的就是通过 :code:`NumPyClient` 子类告知 " +"Flower 在训练和评估时要调用哪些已定义的函数。我们加入了类型注解,以便让您更好" +"地理解传递的数据类型。" #: ../../source/example-jax-from-centralized-to-federated.rst:245 #: ../../source/tutorial-quickstart-jax.rst:251 msgid "Having defined the federation process, we can run it." -msgstr "" +msgstr "定义了联邦进程后,我们就可以运行它了。" #: ../../source/example-jax-from-centralized-to-federated.rst:268 #: ../../source/example-mxnet-walk-through.rst:347 #: ../../source/example-pytorch-from-centralized-to-federated.rst:301 #: ../../source/tutorial-quickstart-jax.rst:274 msgid "And that's it. You can now open two additional terminal windows and run" -msgstr "" +msgstr "就是这样,现在你可以打开另外两个终端窗口,然后运行" #: ../../source/example-jax-from-centralized-to-federated.rst:274 #: ../../source/tutorial-quickstart-jax.rst:280 msgid "" -"in each window (make sure that the server is still running before you do " -"so) and see your JAX project run federated learning across two clients. " +"in each window (make sure that the server is still running before you do so) " +"and see your JAX project run federated learning across two clients. " "Congratulations!" msgstr "" +"确保服务器仍在运行,然后在每个客户端窗口就能看到你的 JAX 项目在两个客户端上运" +"行联邦学习了。祝贺!" #: ../../source/example-jax-from-centralized-to-federated.rst:279 #: ../../source/tutorial-quickstart-jax.rst:285 msgid "" "The source code of this example was improved over time and can be found " -"here: `Quickstart JAX `_. Our example is somewhat over-simplified because both " +"here: `Quickstart JAX `_. Our example is somewhat over-simplified because both " "clients load the same dataset." msgstr "" +"此示例的源代码经过长期改进,可在此处找到: `Quickstart JAX `_。我们的示例有些过于简" +"单,因为两个客户端都加载了相同的数据集。" #: ../../source/example-jax-from-centralized-to-federated.rst:282 #: ../../source/tutorial-quickstart-jax.rst:288 msgid "" -"You're now prepared to explore this topic further. How about using a more" -" sophisticated model or using a different dataset? How about adding more " +"You're now prepared to explore this topic further. How about using a more " +"sophisticated model or using a different dataset? How about adding more " "clients?" msgstr "" +"现在,您已准备好进行更深一步探索了。例如使用更复杂的模型或使用不同的数据集会" +"如何?增加更多客户端会如何?" #: ../../source/example-mxnet-walk-through.rst:2 msgid "Example: MXNet - Run MXNet Federated" -msgstr "" +msgstr "示例: MXNet - 运行联邦式 MXNet" #: ../../source/example-mxnet-walk-through.rst:4 msgid "" -"This tutorial will show you how to use Flower to build a federated " -"version of an existing MXNet workload. We are using MXNet to train a " -"Sequential model on the MNIST dataset. We will structure the example " -"similar to our `PyTorch - From Centralized To Federated " -"`_ walkthrough. MXNet and PyTorch are very " -"similar and a very good comparison between MXNet and PyTorch is given " -"`here `_. First, we build a centralized " -"training approach based on the `Handwritten Digit Recognition " -"`_" -" tutorial. Then, we build upon the centralized training code to run the " -"training in a federated fashion." -msgstr "" +"This tutorial will show you how to use Flower to build a federated version " +"of an existing MXNet workload. We are using MXNet to train a Sequential " +"model on the MNIST dataset. We will structure the example similar to our " +"`PyTorch - From Centralized To Federated `_ walkthrough. " +"MXNet and PyTorch are very similar and a very good comparison between MXNet " +"and PyTorch is given `here `_. First, we " +"build a centralized training approach based on the `Handwritten Digit " +"Recognition `_ tutorial. Then, we build upon " +"the centralized training code to run the training in a federated fashion." +msgstr "" +"本教程将向您展示如何使用 Flower 构建现有 MXNet 的联学习版本。我们将使用 " +"MXNet 在 MNIST 数据集上训练一个序列模型。另外,我们将采用与我们的 `PyTorch - " +"从集中式到联邦式 `_ 教程类似的示例结构。MXNet 和 PyTorch 非常相" +"似,参考 `此处 `_对 MXNet 和 PyTorch 进行了" +"详细的比较。首先,我们根据 `手写数字识别 ` 教" +"程 建立了集中式训练方法。然后,我们在集中式训练代码的基础上,以联邦方式运行训" +"练。" #: ../../source/example-mxnet-walk-through.rst:10 msgid "" -"Before we start setting up our MXNet example, we install the " -":code:`mxnet` and :code:`flwr` packages:" +"Before we start setting up our MXNet example, we install the :code:`mxnet` " +"and :code:`flwr` packages:" msgstr "" +"在开始设置 MXNet 示例之前,我们先安装 :code:`mxnet` 和 :code:`flwr` 软件包:" #: ../../source/example-mxnet-walk-through.rst:19 msgid "MNIST Training with MXNet" -msgstr "" +msgstr "使用 MXNet 进行 MNIST 训练" #: ../../source/example-mxnet-walk-through.rst:21 msgid "" -"We begin with a brief description of the centralized training code based " -"on a :code:`Sequential` model. If you want a more in-depth explanation of" -" what's going on then have a look at the official `MXNet tutorial " -"`_." +"We begin with a brief description of the centralized training code based on " +"a :code:`Sequential` model. If you want a more in-depth explanation of " +"what's going on then have a look at the official `MXNet tutorial `_." msgstr "" +"首先,我们将简要介绍基于 :code:`Sequential` 模型的集中式训练代码。如果您想获" +"得更深入的解释,请参阅官方的 `MXNet教程 `_。" #: ../../source/example-mxnet-walk-through.rst:24 msgid "" -"Let's create a new file called:code:`mxnet_mnist.py` with all the " -"components required for a traditional (centralized) MNIST training. " -"First, the MXNet package :code:`mxnet` needs to be imported. You can see " -"that we do not yet import the :code:`flwr` package for federated " -"learning. This will be done later." +"Let's create a new file called:code:`mxnet_mnist.py` with all the components " +"required for a traditional (centralized) MNIST training. First, the MXNet " +"package :code:`mxnet` needs to be imported. You can see that we do not yet " +"import the :code:`flwr` package for federated learning. This will be done " +"later." msgstr "" +"让我们创建一个名为:code:`mxnet_mnist.py`的新文件,其中包含传统(集中式)" +"MNIST 训练所需的所有组件。首先,需要导入 MXNet 包 :code:`mxnet`。您可以看到," +"我们尚未导入用于联合学习的 :code:`flwr` 包,这将在稍后完成。" #: ../../source/example-mxnet-walk-through.rst:42 -msgid "The :code:`load_data()` function loads the MNIST training and test sets." -msgstr "" +msgid "" +"The :code:`load_data()` function loads the MNIST training and test sets." +msgstr ":code:`load_data()` 函数加载 MNIST 训练集和测试集。" #: ../../source/example-mxnet-walk-through.rst:57 msgid "" "As already mentioned, we will use the MNIST dataset for this machine " -"learning workload. The model architecture (a very simple " -":code:`Sequential` model) is defined in :code:`model()`." +"learning workload. The model architecture (a very simple :code:`Sequential` " +"model) is defined in :code:`model()`." msgstr "" +"如前所述,我们将使用 MNIST 数据集进行机器学习。模型架构(一个非常简单的 :" +"code:`Sequential` 模型)在 :code:`model()` 中定义。" #: ../../source/example-mxnet-walk-through.rst:70 msgid "" -"We now need to define the training (function :code:`train()`) which loops" -" over the training set and measures the loss for each batch of training " +"We now need to define the training (function :code:`train()`) which loops " +"over the training set and measures the loss for each batch of training " "examples." -msgstr "" +msgstr "现在,我们需要定义训练函数( " +":code:`train()`),该函数在训练集上循环训练,并计算每批训练示例的损失值。" #: ../../source/example-mxnet-walk-through.rst:123 msgid "" "The evaluation of the model is defined in function :code:`test()`. The " -"function loops over all test samples and measures the loss and accuracy " -"of the model based on the test dataset." -msgstr "" +"function loops over all test samples and measures the loss and accuracy of " +"the model based on the test dataset." +msgstr "模型的评估在函数 :code:`test()` 中定义。该函数循环遍历所有测试样本,并根据测" +"试数据集计算模型的损失值和准确度。" #: ../../source/example-mxnet-walk-through.rst:158 msgid "" "Having defined the data loading, model architecture, training, and " -"evaluation we can put everything together and train our model on MNIST. " -"Note that the GPU/CPU device for the training and testing is defined " -"within the :code:`ctx` (context)." +"evaluation we can put everything together and train our model on MNIST. Note " +"that the GPU/CPU device for the training and testing is defined within the :" +"code:`ctx` (context)." msgstr "" +"在定义了数据加载、模型架构、训练和评估之后,我们就可以把所有放在一起,在 " +"MNIST 上训练我们的模型了。请注意,用于训练和测试的 GPU/CPU 设备是在 " +":code:`ctx`中定义的。" #: ../../source/example-mxnet-walk-through.rst:184 msgid "You can now run your (centralized) MXNet machine learning workload:" -msgstr "" +msgstr "现在,您可以运行(集中式)MXNet 机器学习工作:" #: ../../source/example-mxnet-walk-through.rst:190 msgid "" -"So far this should all look fairly familiar if you've used MXNet (or even" -" PyTorch) before. Let's take the next step and use what we've built to " -"create a simple federated learning system consisting of one server and " -"two clients." +"So far this should all look fairly familiar if you've used MXNet (or even " +"PyTorch) before. Let's take the next step and use what we've built to create " +"a simple federated learning system consisting of one server and two clients." msgstr "" +"到目前为止,如果你以前使用过 MXNet(甚至 PyTorch),这一切看起来应该相当熟悉" +"。下一步,让我们利用已构建的内容创建一个简单联邦学习系统(由一个服务器和两个" +"客户端组成)。" #: ../../source/example-mxnet-walk-through.rst:194 msgid "MXNet meets Flower" -msgstr "" +msgstr "MXNet 结合 Flower" #: ../../source/example-mxnet-walk-through.rst:196 msgid "" "So far, it was not easily possible to use MXNet workloads for federated " -"learning because federated learning is not supported in MXNet. Since " -"Flower is fully agnostic towards the underlying machine learning " -"framework, it can be used to federated arbitrary machine learning " -"workloads. This section will show you how Flower can be used to federate " -"our centralized MXNet workload." +"learning because federated learning is not supported in MXNet. Since Flower " +"is fully agnostic towards the underlying machine learning framework, it can " +"be used to federated arbitrary machine learning workloads. This section will " +"show you how Flower can be used to federate our centralized MXNet workload." msgstr "" +"由于 MXNet 目前不支持联邦学习,因此无法轻松地直接将 MXNet 用于联邦学习之中。" +"Flower 与底层机器学习框架完全无关,因此它可用于任意联邦式机器学习工作。" +"本节将向你展示如何使用 Flower 将我们的集中式 MXNet 改为联邦式训练。" #: ../../source/example-mxnet-walk-through.rst:198 msgid "" -"The concept to federate an existing workload is always the same and easy " -"to understand. We have to start a *server* and then use the code in " -":code:`mxnet_mnist.py` for the *clients* that are connected to the " -"*server*. The *server* sends model parameters to the clients. The " -"*clients* run the training and update the parameters. The updated " -"parameters are sent back to the *server* which averages all received " -"parameter updates. This describes one round of the federated learning " -"process and we repeat this for multiple rounds." -msgstr "" +"The concept to federate an existing workload is always the same and easy to " +"understand. We have to start a *server* and then use the code in :code:" +"`mxnet_mnist.py` for the *clients* that are connected to the *server*. The " +"*server* sends model parameters to the clients. The *clients* run the " +"training and update the parameters. The updated parameters are sent back to " +"the *server* which averages all received parameter updates. This describes " +"one round of the federated learning process and we repeat this for multiple " +"rounds." +msgstr "" +"将现有模型框架联邦化的概念始终是相同的,也很容易理解。我们必须启动一个*服务器" +"*,然后对连接到*服务器*的*客户端*使用 :code:`mxnet_mnist.py`中的代码。*服务器" +"*向客户端发送模型参数,然后*客户端*运行训练并更新参数。更新后的参数被发回*服" +"务器*,然后会对所有收到的参数更新进行平均聚合。以上描述的是一轮联邦学习过程," +"我们将重复进行多轮学习。" #: ../../source/example-mxnet-walk-through.rst:220 msgid "" -"Finally, we will define our *client* logic in :code:`client.py` and build" -" upon the previously defined MXNet training in :code:`mxnet_mnist.py`. " -"Our *client* needs to import :code:`flwr`, but also :code:`mxnet` to " -"update the parameters on our MXNet model:" +"Finally, we will define our *client* logic in :code:`client.py` and build " +"upon the previously defined MXNet training in :code:`mxnet_mnist.py`. Our " +"*client* needs to import :code:`flwr`, but also :code:`mxnet` to update the " +"parameters on our MXNet model:" msgstr "" +"最后,我们将在 :code:`client.py` 中定义我们的 *client* 逻辑,并以之前在 :" +"code:`mxnet_mnist.py` 中定义的 MXNet 训练为基础。我们的 *client* 不仅需要导" +"入 :code:`flwr`,还需要导入 :code:`mxnet`,以更新 MXNet 模型的参数:" #: ../../source/example-mxnet-walk-through.rst:235 msgid "" -"Implementing a Flower *client* basically means implementing a subclass of" -" either :code:`flwr.client.Client` or :code:`flwr.client.NumPyClient`. " -"Our implementation will be based on :code:`flwr.client.NumPyClient` and " -"we'll call it :code:`MNISTClient`. :code:`NumPyClient` is slighly easier " -"to implement than :code:`Client` if you use a framework with good NumPy " +"Implementing a Flower *client* basically means implementing a subclass of " +"either :code:`flwr.client.Client` or :code:`flwr.client.NumPyClient`. Our " +"implementation will be based on :code:`flwr.client.NumPyClient` and we'll " +"call it :code:`MNISTClient`. :code:`NumPyClient` is slighly easier to " +"implement than :code:`Client` if you use a framework with good NumPy " "interoperability (like PyTorch or MXNet) because it avoids some of the " -"boilerplate that would otherwise be necessary. :code:`MNISTClient` needs " -"to implement four methods, two methods for getting/setting model " -"parameters, one method for training the model, and one method for testing" -" the model:" -msgstr "" +"boilerplate that would otherwise be necessary. :code:`MNISTClient` needs to " +"implement four methods, two methods for getting/setting model parameters, " +"one method for training the model, and one method for testing the model:" +msgstr "" +"实现 Flower *client*基本上意味着要实现 :code:`flwr.client.Client` 或 " +":code:`flwr.client.NumPyClient` 的子类。我们的代码实现将基于 :code:`flwr." +"client.NumPyClient`,并将其命名为 :code:`MNISTClient`。如果使用具有良好 " +"NumPy 互操作性的框架(如 PyTorch 或 MXNet),:code:`NumPyClient` 比 " +":code:`Client`更容易实现,因为它避免了一些不必要的操作。:code:`MNISTClient` " +"需要实现四个方法,两个用于获取/设置模型参数,一个用于训练模型,一个用于测试模" +"型:" #: ../../source/example-mxnet-walk-through.rst:242 msgid "transform MXNet :code:`NDArray`'s to NumPy :code:`ndarray`'s" -msgstr "" +msgstr "将 MXNet :code:`NDArray` 转换为 NumPy :code:`ndarray`" #: ../../source/example-mxnet-walk-through.rst:249 #: ../../source/example-pytorch-from-centralized-to-federated.rst:226 msgid "get the updated local model weights and return them to the server" -msgstr "" +msgstr "获取更新后的本地模型参数并发送回服务器" #: ../../source/example-mxnet-walk-through.rst:253 #: ../../source/example-pytorch-from-centralized-to-federated.rst:230 msgid "return the local loss and accuracy to the server" -msgstr "" +msgstr "向服务器返回本地损失值和精确度" #: ../../source/example-mxnet-walk-through.rst:255 msgid "" -"The challenging part is to transform the MXNet parameters from " -":code:`NDArray` to :code:`NumPy Arrays` to make it readable for Flower." +"The challenging part is to transform the MXNet parameters from :code:" +"`NDArray` to :code:`NumPy Arrays` to make it readable for Flower." msgstr "" +"具有挑战性的部分是将 MXNet 参数从 :code:`NDArray` 转换为 :code:`NumPy " +"Arrays` 以便 Flower 可以读取。" #: ../../source/example-mxnet-walk-through.rst:257 msgid "" -"The two :code:`NumPyClient` methods :code:`fit` and :code:`evaluate` make" -" use of the functions :code:`train()` and :code:`test()` previously " -"defined in :code:`mxnet_mnist.py`. So what we really do here is we tell " -"Flower through our :code:`NumPyClient` subclass which of our already " -"defined functions to call for training and evaluation. We included type " -"annotations to give you a better understanding of the data types that get" -" passed around." +"The two :code:`NumPyClient` methods :code:`fit` and :code:`evaluate` make " +"use of the functions :code:`train()` and :code:`test()` previously defined " +"in :code:`mxnet_mnist.py`. So what we really do here is we tell Flower " +"through our :code:`NumPyClient` subclass which of our already defined " +"functions to call for training and evaluation. We included type annotations " +"to give you a better understanding of the data types that get passed around." msgstr "" +"这两个 :code:`NumPyClient` 方法 :code:`fit` 和 :code:`evaluate` 使用了之前在 " +":code:`mxnet_mnist.py` 中定义的函数 :code:`train()` 和 :code:`test()`。因此," +"我们要做的就是通过 :code:`NumPyClient` 子类告知 Flower 在训练和评估时要调用哪" +"些已定义的函数。我们加入了类型注解,以便让您更好地理解传递的数据类型。" #: ../../source/example-mxnet-walk-through.rst:319 msgid "" -"Having defined data loading, model architecture, training, and evaluation" -" we can put everything together and train our :code:`Sequential` model on" -" MNIST." +"Having defined data loading, model architecture, training, and evaluation we " +"can put everything together and train our :code:`Sequential` model on MNIST." msgstr "" +"在定义了数据加载、模型架构、训练和评估之后,我们就可以将所有内容整合在一起," +"在 MNIST 上训练我们的 :code:`Sequential` 模型。" #: ../../source/example-mxnet-walk-through.rst:353 msgid "" -"in each window (make sure that the server is still running before you do " -"so) and see your MXNet project run federated learning across two clients." -" Congratulations!" -msgstr "" +"in each window (make sure that the server is still running before you do so) " +"and see your MXNet project run federated learning across two clients. " +"Congratulations!" +msgstr "确保服务器仍在运行后,然后就能在每个窗口中看到 MXNet " +"项目在两个客户端上运行联邦学习了。祝贺!" #: ../../source/example-mxnet-walk-through.rst:358 msgid "" -"The full source code for this example: `MXNet: From Centralized To " -"Federated (Code) `_. Our example is of course " -"somewhat over-simplified because both clients load the exact same " -"dataset, which isn't realistic. You're now prepared to explore this topic" -" further. How about using a CNN or using a different dataset? How about " -"adding more clients?" +"The full source code for this example: `MXNet: From Centralized To Federated " +"(Code) `_. Our example is of course somewhat over-" +"simplified because both clients load the exact same dataset, which isn't " +"realistic. You're now prepared to explore this topic further. How about " +"using a CNN or using a different dataset? How about adding more clients?" msgstr "" +"此示例的完整源代码在:\"MXNet: From Centralized To Federated (Code) " +"`_。当然,我们的示例有些过于简单,因为两个客户端都加载了完全相同的" +"数据集,这并不真实。现在您已经准备好进一步探讨了。使用 CNN " +"或使用不同的数据集会如何?添加更多客户端会如何?" #: ../../source/example-pytorch-from-centralized-to-federated.rst:2 msgid "Example: PyTorch - From Centralized To Federated" -msgstr "" +msgstr "实例: PyTorch - 从集中式到联邦式" #: ../../source/example-pytorch-from-centralized-to-federated.rst:4 msgid "" -"This tutorial will show you how to use Flower to build a federated " -"version of an existing machine learning workload. We are using PyTorch to" -" train a Convolutional Neural Network on the CIFAR-10 dataset. First, we " -"introduce this machine learning task with a centralized training approach" -" based on the `Deep Learning with PyTorch " -"`_ " -"tutorial. Then, we build upon the centralized training code to run the " -"training in a federated fashion." +"This tutorial will show you how to use Flower to build a federated version " +"of an existing machine learning workload. We are using PyTorch to train a " +"Convolutional Neural Network on the CIFAR-10 dataset. First, we introduce " +"this machine learning task with a centralized training approach based on the " +"`Deep Learning with PyTorch `_ tutorial. Then, we build upon the centralized " +"training code to run the training in a federated fashion." msgstr "" +"本教程将向您展示如何使用 Flower 构建现有机器学习工作的联邦版本。我们使用 " +"PyTorch 在 CIFAR-10 数据集上训练一个卷积神经网络。首先,我们基于 \"Deep " +"Learning with PyTorch `_\"教程,采用集中式训练方法介绍了这项机器学习任务。然" +"后,我们在集中式训练代码的基础上以联邦方式运行训练。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:12 msgid "" -"We begin with a brief description of the centralized CNN training code. " -"If you want a more in-depth explanation of what's going on then have a " -"look at the official `PyTorch tutorial " -"`_." +"We begin with a brief description of the centralized CNN training code. If " +"you want a more in-depth explanation of what's going on then have a look at " +"the official `PyTorch tutorial `_." msgstr "" +"我们首先简要介绍一下集中式 CNN 训练代码。如果您想获得更深入的解释,请参阅 " +"PyTorch 官方教程`PyTorch tutorial `_。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:15 msgid "" "Let's create a new file called :code:`cifar.py` with all the components " -"required for a traditional (centralized) training on CIFAR-10. First, all" -" required packages (such as :code:`torch` and :code:`torchvision`) need " -"to be imported. You can see that we do not import any package for " -"federated learning. You can keep all these imports as they are even when " -"we add the federated learning components at a later point." +"required for a traditional (centralized) training on CIFAR-10. First, all " +"required packages (such as :code:`torch` and :code:`torchvision`) need to be " +"imported. You can see that we do not import any package for federated " +"learning. You can keep all these imports as they are even when we add the " +"federated learning components at a later point." msgstr "" +"让我们创建一个名为 :code:`cifar.py` 的新文件,其中包含 CIFAR-10 " +"传统(集中)培训所需的所有组件。首先,需要导入所有必需的软件包(如 " +":code:`torch` 和 :code:`torchvision`)。您可以看到,我们没有导入任何用于联邦" +"学习的软件包。即使在以后添加联邦学习组件时,也可以保留所有这些导入。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:32 msgid "" @@ -2440,210 +2846,267 @@ msgid "" "learning workload. The model architecture (a very simple Convolutional " "Neural Network) is defined in :code:`class Net()`." msgstr "" +"如前所述,我们将使用 CIFAR-10 数据集进行机器学习。模型架构(一个非常简单的卷" +"积神经网络)在 :code:`class Net()` 中定义。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:56 msgid "" -"The :code:`load_data()` function loads the CIFAR-10 training and test " -"sets. The :code:`transform` normalized the data after loading." +"The :code:`load_data()` function loads the CIFAR-10 training and test sets. " +"The :code:`transform` normalized the data after loading." msgstr "" +":code:`load_data()` 函数加载 CIFAR-10 训练集和测试集。加载数据后,:code:" +"`transform`函数对数据进行了归一化处理。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:74 msgid "" -"We now need to define the training (function :code:`train()`) which loops" -" over the training set, measures the loss, backpropagates it, and then " -"takes one optimizer step for each batch of training examples." +"We now need to define the training (function :code:`train()`) which loops " +"over the training set, measures the loss, backpropagates it, and then takes " +"one optimizer step for each batch of training examples." msgstr "" +"现在,我们需要定义训练函数(:code:`train()`),该函数在训练集上循环训练,计算" +"损失值并反向传播,然后为每批训练数据在优化器上执行一个优化步骤。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:76 msgid "" -"The evaluation of the model is defined in the function :code:`test()`. " -"The function loops over all test samples and measures the loss of the " -"model based on the test dataset." -msgstr "" +"The evaluation of the model is defined in the function :code:`test()`. The " +"function loops over all test samples and measures the loss of the model " +"based on the test dataset." +msgstr "模型的评估在函数 :code:`test()` " +"中定义。该函数循环遍历所有测试样本,并计算测试数据集的模型损失值。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:136 msgid "" "Having defined the data loading, model architecture, training, and " "evaluation we can put everything together and train our CNN on CIFAR-10." -msgstr "" +msgstr "在确定了数据加载、模型架构、训练和评估之后,我们就可以将所有整合在一起,在 " +"CIFAR-10 上训练我们的 CNN。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:163 msgid "" -"So far, this should all look fairly familiar if you've used PyTorch " -"before. Let's take the next step and use what we've built to create a " -"simple federated learning system consisting of one server and two " -"clients." +"So far, this should all look fairly familiar if you've used PyTorch before. " +"Let's take the next step and use what we've built to create a simple " +"federated learning system consisting of one server and two clients." msgstr "" +"到目前为止,如果你以前用过 PyTorch,这一切看起来应该相当熟悉。让我们进行下一" +"步,利用我们所构建的内容创建一个简单联邦学习系统(由一个服务器和两个客户端组" +"成)。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:169 msgid "" -"The simple machine learning project discussed in the previous section " -"trains the model on a single dataset (CIFAR-10), we call this centralized" -" learning. This concept of centralized learning, as shown in the previous" -" section, is probably known to most of you, and many of you have used it " -"previously. Normally, if you'd want to run machine learning workloads in " -"a federated fashion, then you'd have to change most of your code and set " -"everything up from scratch. This can be a considerable effort." +"The simple machine learning project discussed in the previous section trains " +"the model on a single dataset (CIFAR-10), we call this centralized learning. " +"This concept of centralized learning, as shown in the previous section, is " +"probably known to most of you, and many of you have used it previously. " +"Normally, if you'd want to run machine learning workloads in a federated " +"fashion, then you'd have to change most of your code and set everything up " +"from scratch. This can be a considerable effort." msgstr "" +"上一节讨论的简单机器学习项目在单一数据集(CIFAR-10)上训练模型,我们称之为集" +"中学习。如上一节所示,集中学习的概念可能为大多数人所熟知,而且很多人以前都使" +"用过。通常情况下,如果要以联邦方式运行机器学习工作,就必须更改大部分代码,并" +"从头开始设置一切。这可能是一个相当大的工作量。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:173 msgid "" -"However, with Flower you can evolve your pre-existing code into a " -"federated learning setup without the need for a major rewrite." -msgstr "" +"However, with Flower you can evolve your pre-existing code into a federated " +"learning setup without the need for a major rewrite." +msgstr "不过,有了 " +"Flower,您可以轻松地将已有的代码转变成联邦学习的模式,无需进行大量重写。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:175 msgid "" -"The concept is easy to understand. We have to start a *server* and then " -"use the code in :code:`cifar.py` for the *clients* that are connected to " -"the *server*. The *server* sends model parameters to the clients. The " -"*clients* run the training and update the paramters. The updated " -"parameters are sent back to the *server* which averages all received " -"parameter updates. This describes one round of the federated learning " -"process and we repeat this for multiple rounds." +"The concept is easy to understand. We have to start a *server* and then use " +"the code in :code:`cifar.py` for the *clients* that are connected to the " +"*server*. The *server* sends model parameters to the clients. The *clients* " +"run the training and update the paramters. The updated parameters are sent " +"back to the *server* which averages all received parameter updates. This " +"describes one round of the federated learning process and we repeat this for " +"multiple rounds." msgstr "" +"这个概念很容易理解。我们必须启动一个*服务器*,然后对连接到*服务器*的*客户端*" +"使用 :code:`cifar.py`中的代码。*服务器*向客户端发送模型参数,*客户端*运行训练" +"并更新参数。更新后的参数被发回*服务器*,然后会对所有收到的参数更新进行平均聚" +"合。以上描述的是一轮联邦学习过程,我们将重复进行多轮学习。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:197 msgid "" -"Finally, we will define our *client* logic in :code:`client.py` and build" -" upon the previously defined centralized training in :code:`cifar.py`. " -"Our *client* needs to import :code:`flwr`, but also :code:`torch` to " -"update the paramters on our PyTorch model:" +"Finally, we will define our *client* logic in :code:`client.py` and build " +"upon the previously defined centralized training in :code:`cifar.py`. Our " +"*client* needs to import :code:`flwr`, but also :code:`torch` to update the " +"paramters on our PyTorch model:" msgstr "" +"最后,我们将在 :code:`client.py` 中定义我们的 *client* 逻辑,并以之前在 :" +"code:`cifar.py` 中定义的集中式训练为基础。我们的 *client* 不仅需要导入 :code:" +"`flwr`,还需要导入 :code:`torch`,以更新 PyTorch 模型的参数:" #: ../../source/example-pytorch-from-centralized-to-federated.rst:213 msgid "" -"Implementing a Flower *client* basically means implementing a subclass of" -" either :code:`flwr.client.Client` or :code:`flwr.client.NumPyClient`. " -"Our implementation will be based on :code:`flwr.client.NumPyClient` and " -"we'll call it :code:`CifarClient`. :code:`NumPyClient` is slighly easier " -"to implement than :code:`Client` if you use a framework with good NumPy " -"interoperability (like PyTorch or TensorFlow/Keras) because it avoids " -"some of the boilerplate that would otherwise be necessary. " -":code:`CifarClient` needs to implement four methods, two methods for " -"getting/setting model parameters, one method for training the model, and " -"one method for testing the model:" -msgstr "" +"Implementing a Flower *client* basically means implementing a subclass of " +"either :code:`flwr.client.Client` or :code:`flwr.client.NumPyClient`. Our " +"implementation will be based on :code:`flwr.client.NumPyClient` and we'll " +"call it :code:`CifarClient`. :code:`NumPyClient` is slighly easier to " +"implement than :code:`Client` if you use a framework with good NumPy " +"interoperability (like PyTorch or TensorFlow/Keras) because it avoids some " +"of the boilerplate that would otherwise be necessary. :code:`CifarClient` " +"needs to implement four methods, two methods for getting/setting model " +"parameters, one method for training the model, and one method for testing " +"the model:" +msgstr "" +"实现 Flower *client*基本上意味着实现 :code:`flwr.client.Client` 或 " +":code:`flwr.client.NumPyClient` 的子类。我们的代码实现将基于 :code:`flwr." +"client.NumPyClient`,并将其命名为 :code:`CifarClient`。如果使用具有良好 " +"NumPy 互操作性的框架(如 PyTorch 或 TensorFlow/Keras),:code:`NumPyClient`" +"的实现比 " +":code:`Client`略微容易一些,因为它避免了一些不必要的操作。:code:`CifarClient`" +" 需要实现四个方法,两个用于获取/设置模型参数,一个用于训练模型,一个用于测试" +"模型:" #: ../../source/example-pytorch-from-centralized-to-federated.rst:219 msgid ":code:`set_parameters`" -msgstr "" +msgstr ":code:`set_parameters`" #: ../../source/example-pytorch-from-centralized-to-federated.rst:232 msgid "" -"The two :code:`NumPyClient` methods :code:`fit` and :code:`evaluate` make" -" use of the functions :code:`train()` and :code:`test()` previously " -"defined in :code:`cifar.py`. So what we really do here is we tell Flower " -"through our :code:`NumPyClient` subclass which of our already defined " -"functions to call for training and evaluation. We included type " -"annotations to give you a better understanding of the data types that get" -" passed around." +"The two :code:`NumPyClient` methods :code:`fit` and :code:`evaluate` make " +"use of the functions :code:`train()` and :code:`test()` previously defined " +"in :code:`cifar.py`. So what we really do here is we tell Flower through " +"our :code:`NumPyClient` subclass which of our already defined functions to " +"call for training and evaluation. We included type annotations to give you a " +"better understanding of the data types that get passed around." msgstr "" +"这两个 :code:`NumPyClient` 中的方法 :code:`fit` 和 :code:`evaluate` " +"使用了之前在 :code:`cifar.py` 中定义的函数 :code:`train()` 和 " +":code:`test()`。因此,我们在这里要做的就是通过 :code:`NumPyClient` 子类告知 " +"Flower 在训练和评估时要调用哪些已定义的函数。我们加入了类型注解,以便让你更好" +"地理解传递的数据类型。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:280 msgid "" "All that's left to do it to define a function that loads both model and " -"data, creates a :code:`CifarClient`, and starts this client. You load " -"your data and model by using :code:`cifar.py`. Start :code:`CifarClient` " -"with the function :code:`fl.client.start_client()` by pointing it " -"at the same IP adress we used in :code:`server.py`:" +"data, creates a :code:`CifarClient`, and starts this client. You load your " +"data and model by using :code:`cifar.py`. Start :code:`CifarClient` with the " +"function :code:`fl.client.start_client()` by pointing it at the same IP " +"adress we used in :code:`server.py`:" msgstr "" +"剩下的就是定义模型和数据加载函数了。创建一个:code:`CifarClient`类,并运行这个" +"客服端。您将通过:code:`cifar.py`加载数据和模型。另外,通过:code:`fl.client.st" +"art_client()`函数来运行客户端:code:`CifarClient`,需要保证IP地址和:code:`serv" +"er.py`中所使用的一致:" #: ../../source/example-pytorch-from-centralized-to-federated.rst:307 msgid "" -"in each window (make sure that the server is running before you do so) " -"and see your (previously centralized) PyTorch project run federated " -"learning across two clients. Congratulations!" -msgstr "" +"in each window (make sure that the server is running before you do so) and " +"see your (previously centralized) PyTorch project run federated learning " +"across two clients. Congratulations!" +msgstr "确保服务器正在运行后,您就能看到您的 PyTorch " +"项目(之前是集中式的)在两个客户端上运行联邦学习了。祝贺!" #: ../../source/example-pytorch-from-centralized-to-federated.rst:312 msgid "" "The full source code for this example: `PyTorch: From Centralized To " -"Federated (Code) `_. Our example is, of course, " -"somewhat over-simplified because both clients load the exact same " -"dataset, which isn't realistic. You're now prepared to explore this topic" -" further. How about using different subsets of CIFAR-10 on each client? " -"How about adding more clients?" +"Federated (Code) `_. Our example is, of course, somewhat over-" +"simplified because both clients load the exact same dataset, which isn't " +"realistic. You're now prepared to explore this topic further. How about " +"using different subsets of CIFAR-10 on each client? How about adding more " +"clients?" msgstr "" +"本示例的完整源代码为:`PyTorch: 从集中式到联合式 `_。当然,我" +"们的示例有些过于简单,因为两个客户端都加载了完全相同的数据集,这并不真实。现" +"在,您已经准备好进一步探讨这一主题了。比如在每个客户端使用不同的 CIFAR-10 " +"子集会如何?增加更多客户端会如何?" #: ../../source/example-walkthrough-pytorch-mnist.rst:2 msgid "Example: Walk-Through PyTorch & MNIST" -msgstr "" +msgstr "实例: PyTorch 和 MNIST 的演练" #: ../../source/example-walkthrough-pytorch-mnist.rst:4 msgid "" -"In this tutorial we will learn, how to train a Convolutional Neural " -"Network on MNIST using Flower and PyTorch." +"In this tutorial we will learn, how to train a Convolutional Neural Network " +"on MNIST using Flower and PyTorch." msgstr "" +"在本教程中,我们将学习如何使用 Flower 和 PyTorch 在 MNIST 上训练卷积神经网" +"络。" #: ../../source/example-walkthrough-pytorch-mnist.rst:6 #: ../../source/tutorial-quickstart-mxnet.rst:14 #: ../../source/tutorial-quickstart-pytorch.rst:17 #: ../../source/tutorial-quickstart-scikitlearn.rst:14 msgid "" -"Our example consists of one *server* and two *clients* all having the " -"same model." -msgstr "" +"Our example consists of one *server* and two *clients* all having the same " +"model." +msgstr "我们的例子包括一个*服务器*和两个*客户端*,它们都有相同的模型。" #: ../../source/example-walkthrough-pytorch-mnist.rst:8 #: ../../source/tutorial-quickstart-pytorch.rst:19 msgid "" -"*Clients* are responsible for generating individual weight-updates for " -"the model based on their local datasets. These updates are then sent to " -"the *server* which will aggregate them to produce a better model. " -"Finally, the *server* sends this improved version of the model back to " -"each *client*. A complete cycle of weight updates is called a *round*." +"*Clients* are responsible for generating individual weight-updates for the " +"model based on their local datasets. These updates are then sent to the " +"*server* which will aggregate them to produce a better model. Finally, the " +"*server* sends this improved version of the model back to each *client*. A " +"complete cycle of weight updates is called a *round*." msgstr "" +"*客户端*负责在其本地数据集上更新模型参数。然后,这些参数会被发送到*服务器*," +"由*服务器*聚合后生成一个更好的模型。最后,*服务器*将改进后的模型发送回每个*客" +"户端*。一个完整的模型参数更新周期称为一*轮*。" #: ../../source/example-walkthrough-pytorch-mnist.rst:12 #: ../../source/tutorial-quickstart-pytorch.rst:23 msgid "" "Now that we have a rough idea of what is going on, let's get started. We " "first need to install Flower. You can do this by running :" -msgstr "" +msgstr "现在,我们已经有了一个大致的概念了,那就让我们开始吧。首先,我们需要安装 " +"Flower。可以通过运行 :" #: ../../source/example-walkthrough-pytorch-mnist.rst:18 msgid "" -"Since we want to use PyTorch to solve a computer vision task, let's go " -"ahead an install PyTorch and the **torchvision** library:" -msgstr "" +"Since we want to use PyTorch to solve a computer vision task, let's go ahead " +"an install PyTorch and the **torchvision** library:" +msgstr "我们想用 PyTorch 来做计算机视觉任务,需要先安装 PyTorch 和 **torchvision** " +"库:" #: ../../source/example-walkthrough-pytorch-mnist.rst:26 msgid "Ready... Set... Train!" -msgstr "" +msgstr "准备...设置...训练!" #: ../../source/example-walkthrough-pytorch-mnist.rst:28 msgid "" "Now that we have all our dependencies installed, let's run a simple " -"distributed training with two clients and one server. Our training " -"procedure and network architecture are based on PyTorch's `Basic MNIST " -"Example `_. This " -"will allow you see how easy it is to wrap your code with Flower and begin" -" training in a federated way. We provide you with two helper scripts, " -"namely *run-server.sh*, and *run-clients.sh*. Don't be afraid to look " -"inside, they are simple enough =)." -msgstr "" +"distributed training with two clients and one server. Our training procedure " +"and network architecture are based on PyTorch's `Basic MNIST Example " +"`_. This will allow " +"you see how easy it is to wrap your code with Flower and begin training in a " +"federated way. We provide you with two helper scripts, namely *run-server." +"sh*, and *run-clients.sh*. Don't be afraid to look inside, they are simple " +"enough =)." +msgstr "" +"现在我们已经安装了所有的依赖包,让我们用两个客户端和一个服务器来运行一个简单" +"的分布式训练。我们的训练过程和网络架构基于 PyTorch 的 `Basic MNIST Example " +"`_。您会发现用 Flower " +"来封装您的代码并进行联邦学习训练是多么容易。我们为您提供了两个辅助脚本,即 " +"*run-server.sh* 和 *run-clients.sh*。别害怕,它们很简单 =)。" #: ../../source/example-walkthrough-pytorch-mnist.rst:31 msgid "" "Go ahead and launch on a terminal the *run-server.sh* script first as " "follows:" -msgstr "" +msgstr "首先在终端上启动 *run-server.sh* 脚本,如下所示:" #: ../../source/example-walkthrough-pytorch-mnist.rst:38 msgid "Now that the server is up and running, go ahead and launch the clients." -msgstr "" +msgstr "现在服务器已经启动并运行,请继续启动客户端。" #: ../../source/example-walkthrough-pytorch-mnist.rst:45 msgid "" "Et voilà! You should be seeing the training procedure and, after a few " "iterations, the test accuracy for each client." -msgstr "" +msgstr "然后就可以了!您应该能看到训练过程,以及经过几次反复后,每个客户端的测试准确" +"率。" #: ../../source/example-walkthrough-pytorch-mnist.rst:66 msgid "Now, let's see what is really happening inside." -msgstr "" +msgstr "现在,让我们看看里面到底发生了什么。" #: ../../source/example-walkthrough-pytorch-mnist.rst:69 #: ../../source/tutorial-quickstart-ios.rst:129 @@ -2653,23 +3116,29 @@ msgstr "" #: ../../source/tutorial-quickstart-tensorflow.rst:98 #: ../../source/tutorial-quickstart-xgboost.rst:306 msgid "Flower Server" -msgstr "" +msgstr "Flower 服务器" #: ../../source/example-walkthrough-pytorch-mnist.rst:71 msgid "" -"Inside the server helper script *run-server.sh* you will find the " -"following code that basically runs the :code:`server.py`" +"Inside the server helper script *run-server.sh* you will find the following " +"code that basically runs the :code:`server.py`" msgstr "" +"在服务器辅助脚本 *run-server.sh* 中,你可以找到以下代码,这些代码基本上都是运" +"行 :code:`server.py` 的代码" #: ../../source/example-walkthrough-pytorch-mnist.rst:78 msgid "" "We can go a bit deeper and see that :code:`server.py` simply launches a " "server that will coordinate three rounds of training. Flower Servers are " "very customizable, but for simple workloads, we can start a server using " -"the :ref:`start_server ` function and " -"leave all the configuration possibilities at their default values, as " -"seen below." +"the :ref:`start_server ` function and leave " +"all the configuration possibilities at their default values, as seen below." msgstr "" +"我们可以再深入一点,:code:`server.py` " +"只是启动了一个服务器,该服务器将协调三轮训练。Flower " +"服务器是非常容易修改的,但对于简单的工作,我们可以使用 :ref:`start_server " +"`函数启动服务器,并将所有可能的配置保留为默认值,如下所示。" #: ../../source/example-walkthrough-pytorch-mnist.rst:89 #: ../../source/tutorial-quickstart-ios.rst:34 @@ -2679,446 +3148,553 @@ msgstr "" #: ../../source/tutorial-quickstart-tensorflow.rst:29 #: ../../source/tutorial-quickstart-xgboost.rst:52 msgid "Flower Client" -msgstr "" +msgstr "Flower 客户端" #: ../../source/example-walkthrough-pytorch-mnist.rst:91 msgid "" -"Next, let's take a look at the *run-clients.sh* file. You will see that " -"it contains the main loop that starts a set of *clients*." -msgstr "" +"Next, let's take a look at the *run-clients.sh* file. You will see that it " +"contains the main loop that starts a set of *clients*." +msgstr "接下来,让我们看看 *run-clients.sh* 文件。您会看到它包含了用来启动多个 " +"*客户端* 的代码。" #: ../../source/example-walkthrough-pytorch-mnist.rst:100 msgid "" -"**cid**: is the client ID. It is an integer that uniquely identifies " -"client identifier." -msgstr "" +"**cid**: is the client ID. It is an integer that uniquely identifies client " +"identifier." +msgstr "**cid**:是客户 ID。它是一个整数,可唯一标识客户标识符。" #: ../../source/example-walkthrough-pytorch-mnist.rst:101 msgid "**sever_address**: String that identifies IP and port of the server." -msgstr "" +msgstr "**sever_address**: 标识服务器 IP 和端口的字符串。" #: ../../source/example-walkthrough-pytorch-mnist.rst:102 msgid "" -"**nb_clients**: This defines the number of clients being created. This " -"piece of information is not required by the client, but it helps us " -"partition the original MNIST dataset to make sure that every client is " -"working on unique subsets of both *training* and *test* sets." +"**nb_clients**: This defines the number of clients being created. This piece " +"of information is not required by the client, but it helps us partition the " +"original MNIST dataset to make sure that every client is working on unique " +"subsets of both *training* and *test* sets." msgstr "" +"**nb_clients**: 这定义了正在创建的客户端数量。客户端并不需要这一信息," +"但它有助于我们对原始 MNIST 数据集进行划分,以确保每个客户端都在 *training* " +"和 *test* 数据集上有独立的数据。" #: ../../source/example-walkthrough-pytorch-mnist.rst:104 msgid "" "Again, we can go deeper and look inside :code:`flwr_example/quickstart-" "pytorch/client.py`. After going through the argument parsing code at the " -"beginning of our :code:`main` function, you will find a call to " -":code:`mnist.load_data`. This function is responsible for partitioning " -"the original MNIST datasets (*training* and *test*) and returning a " -":code:`torch.utils.data.DataLoader` s for each of them. We then " -"instantiate a :code:`PytorchMNISTClient` object with our client ID, our " -"DataLoaders, the number of epochs in each round, and which device we want" -" to use for training (CPU or GPU)." -msgstr "" +"beginning of our :code:`main` function, you will find a call to :code:`mnist." +"load_data`. This function is responsible for partitioning the original MNIST " +"datasets (*training* and *test*) and returning a :code:`torch.utils.data." +"DataLoader` s for each of them. We then instantiate a :code:" +"`PytorchMNISTClient` object with our client ID, our DataLoaders, the number " +"of epochs in each round, and which device we want to use for training (CPU " +"or GPU)." +msgstr "" +"我们可以深入看一下 :code:`flwr_example/quickstart-pytorch/client.py`。查看 " +":code:`main` 函数开头的参数解析代码后,你会发现一个对 :code:`mnist.load_data`" +" 的调用。该函数负责分割原始 MNIST 数据集(*training* 和 *test*)," +"并为每个数据集返回一个 :code:`torch.utils.data.DataLoader` 。然后," +"我们实例化一个 :code:`PytorchMNISTClient` 对象,其中包含我们的客户端 ID、 " +"DataLoader、每一轮中的遍历数,以及我们希望用于训练的设备(CPU 或 GPU)。" #: ../../source/example-walkthrough-pytorch-mnist.rst:119 msgid "" -"The :code:`PytorchMNISTClient` object when finally passed to " -":code:`fl.client.start_client` along with the server's address as the " -"training process begins." +"The :code:`PytorchMNISTClient` object when finally passed to :code:`fl." +"client.start_client` along with the server's address as the training process " +"begins." msgstr "" +"当训练过程开始时,:code:`PytorchMNISTClient` 对象会连同服务器地址一起传递给 " +":code:`fl.client.start_client`。" #: ../../source/example-walkthrough-pytorch-mnist.rst:123 msgid "A Closer Look" -msgstr "" +msgstr "仔细看一下" #: ../../source/example-walkthrough-pytorch-mnist.rst:125 msgid "" -"Now, let's look closely into the :code:`PytorchMNISTClient` inside " -":code:`flwr_example.quickstart-pytorch.mnist` and see what it is doing:" +"Now, let's look closely into the :code:`PytorchMNISTClient` inside :code:" +"`flwr_example.quickstart-pytorch.mnist` and see what it is doing:" msgstr "" +"现在,让我们仔细研究一下 :code:`flwr_example.quickstart-pytorch.mnist` 中的 :" +"code:`PytorchMNISTClient`,看看它在做什么:" #: ../../source/example-walkthrough-pytorch-mnist.rst:226 msgid "" -"The first thing to notice is that :code:`PytorchMNISTClient` instantiates" -" a CNN model inside its constructor" +"The first thing to notice is that :code:`PytorchMNISTClient` instantiates a " +"CNN model inside its constructor" msgstr "" +"首先要注意的是 :code:`PytorchMNISTClient` 在其构造函数中实例化了一个 CNN 模型" #: ../../source/example-walkthrough-pytorch-mnist.rst:244 msgid "" -"The code for the CNN is available under :code:`quickstart-pytorch.mnist` " -"and it is reproduced below. It is the same network found in `Basic MNIST " -"Example `_." +"The code for the CNN is available under :code:`quickstart-pytorch.mnist` and " +"it is reproduced below. It is the same network found in `Basic MNIST Example " +"`_." msgstr "" +"CNN 的代码可在 :code:`quickstart-pytorch.mnist` 下找到,现复制如下。它与 `" +"Basic MNIST Example `_中的网络相同。" #: ../../source/example-walkthrough-pytorch-mnist.rst:290 msgid "" -"The second thing to notice is that :code:`PytorchMNISTClient` class " -"inherits from the :code:`fl.client.Client`, and hence it must implement " -"the following methods:" +"The second thing to notice is that :code:`PytorchMNISTClient` class inherits " +"from the :code:`fl.client.Client`, and hence it must implement the following " +"methods:" msgstr "" +"第二件要注意的事是 :code:`PytorchMNISTClient` 类继承自 :code:`fl.client." +"Client`,因此它必须实现以下方法:" #: ../../source/example-walkthrough-pytorch-mnist.rst:315 msgid "" -"When comparing the abstract class to its derived class " -":code:`PytorchMNISTClient` you will notice that :code:`fit` calls a " -":code:`train` function and that :code:`evaluate` calls a :code:`test`: " -"function." +"When comparing the abstract class to its derived class :code:" +"`PytorchMNISTClient` you will notice that :code:`fit` calls a :code:`train` " +"function and that :code:`evaluate` calls a :code:`test`: function." msgstr "" +"将抽象类与其派生类 :code:`PytorchMNISTClient` 进行比较时,您会发现 :code:" +"`fit` 调用了一个 :code:`train` 函数,而 :code:`evaluate` 则调用了一个 :code:" +"`test`: 函数。" #: ../../source/example-walkthrough-pytorch-mnist.rst:317 msgid "" -"These functions can both be found inside the same :code:`quickstart-" -"pytorch.mnist` module:" -msgstr "" +"These functions can both be found inside the same :code:`quickstart-pytorch." +"mnist` module:" +msgstr "这些函数都可以在同一个 :code:`quickstart-pytorch.mnist` 模块中找到:" #: ../../source/example-walkthrough-pytorch-mnist.rst:437 msgid "" -"Observe that these functions encapsulate regular training and test loops " -"and provide :code:`fit` and :code:`evaluate` with final statistics for " -"each round. You could substitute them with your custom train and test " -"loops and change the network architecture, and the entire example would " -"still work flawlessly. As a matter of fact, why not try and modify the " -"code to an example of your liking?" +"Observe that these functions encapsulate regular training and test loops and " +"provide :code:`fit` and :code:`evaluate` with final statistics for each " +"round. You could substitute them with your custom train and test loops and " +"change the network architecture, and the entire example would still work " +"flawlessly. As a matter of fact, why not try and modify the code to an " +"example of your liking?" msgstr "" +"请注意,这些函数封装了常规的训练和测试循环,并为 :code:`fit` 和 :code:" +"`evaluate` 提供了每轮的最终统计数据。您可以用自定义的训练和测试循环来替代它" +"们,并改变网络结构,整个示例仍然可以完美运行。事实上,为什么不按照自己的喜好" +"修改代码呢?" #: ../../source/example-walkthrough-pytorch-mnist.rst:444 msgid "Give It a Try" -msgstr "" +msgstr "试试看" #: ../../source/example-walkthrough-pytorch-mnist.rst:445 msgid "" -"Looking through the quickstart code description above will have given a " -"good understanding of how *clients* and *servers* work in Flower, how to " -"run a simple experiment, and the internals of a client wrapper. Here are " -"a few things you could try on your own and get more experience with " -"Flower:" +"Looking through the quickstart code description above will have given a good " +"understanding of how *clients* and *servers* work in Flower, how to run a " +"simple experiment, and the internals of a client wrapper. Here are a few " +"things you could try on your own and get more experience with Flower:" msgstr "" +"通过上面的快速入门代码描述,你将对 Flower 中*客户端*和*服务器*的工作方式、如" +"何运行一个简单的实验以及客户端封装器的内部结构有一个很好的了解。您可以自己尝" +"试以下内容,以获得更多使用 Flower 的经验:" #: ../../source/example-walkthrough-pytorch-mnist.rst:448 msgid "" "Try and change :code:`PytorchMNISTClient` so it can accept different " "architectures." -msgstr "" +msgstr "尝试修改 :code:`PytorchMNISTClient`,使其可以接受不同的架构。" #: ../../source/example-walkthrough-pytorch-mnist.rst:449 -msgid "Modify the :code:`train` function so that it accepts different optimizers" -msgstr "" +msgid "" +"Modify the :code:`train` function so that it accepts different optimizers" +msgstr "修改 :code:`train` 函数,使其接受不同的优化器" #: ../../source/example-walkthrough-pytorch-mnist.rst:450 msgid "" "Modify the :code:`test` function so that it proves not only the top-1 " "(regular accuracy) but also the top-5 accuracy?" -msgstr "" +msgstr "修改 :code:`test` 函数,使其不仅能输出前 1 名(常规精确度),还能证明前 5 " +"名的精确度?" #: ../../source/example-walkthrough-pytorch-mnist.rst:451 msgid "" -"Go larger! Try to adapt the code to larger images and datasets. Why not " -"try training on ImageNet with a ResNet-50?" -msgstr "" +"Go larger! Try to adapt the code to larger images and datasets. Why not try " +"training on ImageNet with a ResNet-50?" +msgstr "让我们尝试让代码适应更大的图像和数据集。为什么不尝试使用 ResNet-50 在 " +"ImageNet 上进行训练呢?" #: ../../source/example-walkthrough-pytorch-mnist.rst:453 msgid "You are ready now. Enjoy learning in a federated way!" -msgstr "" +msgstr "您现在已经准备就绪。尽情享受联邦学习的乐趣吧!" #: ../../source/explanation-differential-privacy.rst:2 msgid "Differential privacy" -msgstr "" +msgstr "差别隐私" #: ../../source/explanation-differential-privacy.rst:4 msgid "" "Flower provides differential privacy (DP) wrapper classes for the easy " -"integration of the central DP guarantees provided by DP-FedAvg into " -"training pipelines defined in any of the various ML frameworks that " -"Flower is compatible with." +"integration of the central DP guarantees provided by DP-FedAvg into training " +"pipelines defined in any of the various ML frameworks that Flower is " +"compatible with." msgstr "" +"Flower 提供了差分隐私 (DP) 封装类,可将 DP-FedAvg 提供的核心 DP 轻松集成到 " +"Flower 兼容的各种 ML 框架中定义的训练模式中。" #: ../../source/explanation-differential-privacy.rst:7 msgid "" "Please note that these components are still experimental, the correct " "configuration of DP for a specific task is still an unsolved problem." msgstr "" +"请注意,这些组件仍处于试验阶段,如何为特定任务正确配置 DP 仍是一个尚未解决的" +"问题。" #: ../../source/explanation-differential-privacy.rst:10 msgid "" -"The name DP-FedAvg is misleading since it can be applied on top of any FL" -" algorithm that conforms to the general structure prescribed by the " -"FedOpt family of algorithms." +"The name DP-FedAvg is misleading since it can be applied on top of any FL " +"algorithm that conforms to the general structure prescribed by the FedOpt " +"family of algorithms." msgstr "" +"DP-FedAvg 这个名称容易引起误解,因为它可以应用于任何符合 FedOpt 系列算法规定" +"的一般结构的 FL 算法之上。" #: ../../source/explanation-differential-privacy.rst:13 msgid "DP-FedAvg" -msgstr "" +msgstr "DP-FedAvg" #: ../../source/explanation-differential-privacy.rst:15 msgid "" -"DP-FedAvg, originally proposed by McMahan et al. [mcmahan]_ and extended " -"by Andrew et al. [andrew]_, is essentially FedAvg with the following " +"DP-FedAvg, originally proposed by McMahan et al. [mcmahan]_ and extended by " +"Andrew et al. [andrew]_, is essentially FedAvg with the following " "modifications." -msgstr "" +msgstr "DP-FedAvg 最初由McMahan等人提出,并由Andrew等人加以扩展。" #: ../../source/explanation-differential-privacy.rst:17 msgid "" -"**Clipping** : The influence of each client's update is bounded by " -"clipping it. This is achieved by enforcing a cap on the L2 norm of the " -"update, scaling it down if needed." -msgstr "" +"**Clipping** : The influence of each client's update is bounded by clipping " +"it. This is achieved by enforcing a cap on the L2 norm of the update, " +"scaling it down if needed." +msgstr "**裁剪** : 裁剪会影响到每个客户端的模型参数。具体做法是对参数的 L2 " +"准则设置上限,必要时将其缩减。" #: ../../source/explanation-differential-privacy.rst:18 msgid "" "**Noising** : Gaussian noise, calibrated to the clipping threshold, is " "added to the average computed at the server." -msgstr "" +msgstr "**噪声** : " +"在服务器计算出的平均值中加入高斯噪声,该噪声根据剪切阈值进行校准。" #: ../../source/explanation-differential-privacy.rst:20 msgid "" -"The distribution of the update norm has been shown to vary from task-to-" -"task and to evolve as training progresses. Therefore, we use an adaptive " -"approach [andrew]_ that continuously adjusts the clipping threshold to " -"track a prespecified quantile of the update norm distribution." +"The distribution of the update norm has been shown to vary from task-to-task " +"and to evolve as training progresses. Therefore, we use an adaptive approach " +"[andrew]_ that continuously adjusts the clipping threshold to track a " +"prespecified quantile of the update norm distribution." msgstr "" +"事实证明,参数更新准则的分布会随着任务的不同而变化,并随着训练的进展而演变。" +"因此,我们采用了一种自适应方法,该方法会不断调整剪切阈值,以跟踪参数更新准则" +"分布的预设量化值。" #: ../../source/explanation-differential-privacy.rst:23 msgid "Simplifying Assumptions" -msgstr "" +msgstr "简化假设" #: ../../source/explanation-differential-privacy.rst:25 msgid "" "We make (and attempt to enforce) a number of assumptions that must be " -"satisfied to ensure that the training process actually realises the " -":math:`(\\epsilon, \\delta)` guarantees the user has in mind when " -"configuring the setup." +"satisfied to ensure that the training process actually realises the :math:" +"`(\\epsilon, \\delta)` guarantees the user has in mind when configuring the " +"setup." msgstr "" +"我们提出(并试图执行)了一系列必须满足的假设," +"以确保训练过程真正实现用户在配置设置时所定的 :math:`(\\epsilon,\\delta)` 。" #: ../../source/explanation-differential-privacy.rst:27 msgid "" "**Fixed-size subsampling** :Fixed-size subsamples of the clients must be " "taken at each round, as opposed to variable-sized Poisson subsamples." -msgstr "" +msgstr "** 固定大小的子样本** " +":与可变大小的泊松分布子样本相比,每轮必须抽取固定大小的客户端子样本。" #: ../../source/explanation-differential-privacy.rst:28 msgid "" "**Unweighted averaging** : The contributions from all the clients must " "weighted equally in the aggregate to eliminate the requirement for the " -"server to know in advance the sum of the weights of all clients available" -" for selection." -msgstr "" +"server to know in advance the sum of the weights of all clients available " +"for selection." +msgstr "**非加权平均**: " +"所有客户端的贡献必须加权相等,这样服务器就不需要事先知道所有客户的权重总和。" #: ../../source/explanation-differential-privacy.rst:29 msgid "" "**No client failures** : The set of available clients must stay constant " -"across all rounds of training. In other words, clients cannot drop out or" -" fail." -msgstr "" +"across all rounds of training. In other words, clients cannot drop out or " +"fail." +msgstr "**没有失败的客户端** : " +"在各轮训练中,可用客户端的数量必须保持不变。换句话说,客户端不能退出或失败。" #: ../../source/explanation-differential-privacy.rst:31 msgid "" "The first two are useful for eliminating a multitude of complications " -"associated with calibrating the noise to the clipping threshold while the" -" third one is required to comply with the assumptions of the privacy " -"analysis." +"associated with calibrating the noise to the clipping threshold while the " +"third one is required to comply with the assumptions of the privacy analysis." msgstr "" +"前两种方法有助于消除将噪声校准为削波阈值所带来的诸多复杂问题,而第三种方法则" +"需要符合隐私分析的假设。" #: ../../source/explanation-differential-privacy.rst:34 msgid "" "These restrictions are in line with constraints imposed by Andrew et al. " "[andrew]_." -msgstr "" +msgstr "这些限制与 Andrew 等人所施加的限制一致。" #: ../../source/explanation-differential-privacy.rst:37 msgid "Customizable Responsibility for Noise injection" -msgstr "" +msgstr "可定制的噪声注入" #: ../../source/explanation-differential-privacy.rst:38 msgid "" "In contrast to other implementations where the addition of noise is " -"performed at the server, you can configure the site of noise injection to" -" better match your threat model. We provide users with the flexibility to" -" set up the training such that each client independently adds a small " -"amount of noise to the clipped update, with the result that simply " -"aggregating the noisy updates is equivalent to the explicit addition of " -"noise to the non-noisy aggregate at the server." -msgstr "" +"performed at the server, you can configure the site of noise injection to " +"better match your threat model. We provide users with the flexibility to set " +"up the training such that each client independently adds a small amount of " +"noise to the clipped update, with the result that simply aggregating the " +"noisy updates is equivalent to the explicit addition of noise to the non-" +"noisy aggregate at the server." +msgstr "" +"与其他在服务器上添加噪声的实现方法不同,您可以配置噪声注入的位置,以便更好地" +"匹配您的威胁模型。我们为用户提供了设置训练的灵活性,使每个客户端都能独立地为" +"剪切参数更新添加少量噪声,这样,只需聚合噪声更新,就相当于在服务器上为非噪声" +"聚合添加噪声了。" #: ../../source/explanation-differential-privacy.rst:41 msgid "" "To be precise, if we let :math:`m` be the number of clients sampled each " -"round and :math:`\\sigma_\\Delta` be the scale of the total Gaussian " -"noise that needs to be added to the sum of the model updates, we can use " -"simple maths to show that this is equivalent to each client adding noise " -"with scale :math:`\\sigma_\\Delta/\\sqrt{m}`." +"round and :math:`\\sigma_\\Delta` be the scale of the total Gaussian noise " +"that needs to be added to the sum of the model updates, we can use simple " +"maths to show that this is equivalent to each client adding noise with " +"scale :math:`\\sigma_\\Delta/\\sqrt{m}`." msgstr "" +"准确地说,我们假设每轮采样的客户端数量为:math:`m`,:math:`\\sigma_\\Delta` 为" +"需要添加到模型更新总和中的总高斯噪声的规模,我们就可以用简单的数学方法证明了" +",这相当于每个客户端都添加了规模为 :math:`\\sigma_\\Delta/\\sqrt{m}` 的噪声。" #: ../../source/explanation-differential-privacy.rst:44 msgid "Wrapper-based approach" -msgstr "" +msgstr "基于封装的方法" #: ../../source/explanation-differential-privacy.rst:46 msgid "" -"Introducing DP to an existing workload can be thought of as adding an " -"extra layer of security around it. This inspired us to provide the " -"additional server and client-side logic needed to make the training " -"process differentially private as wrappers for instances of the " -":code:`Strategy` and :code:`NumPyClient` abstract classes respectively. " -"This wrapper-based approach has the advantage of being easily composable " -"with other wrappers that someone might contribute to the Flower library " -"in the future, e.g., for secure aggregation. Using Inheritance instead " -"can be tedious because that would require the creation of new sub- " -"classes every time a new class implementing :code:`Strategy` or " -":code:`NumPyClient` is defined." -msgstr "" +"Introducing DP to an existing workload can be thought of as adding an extra " +"layer of security around it. This inspired us to provide the additional " +"server and client-side logic needed to make the training process " +"differentially private as wrappers for instances of the :code:`Strategy` " +"and :code:`NumPyClient` abstract classes respectively. This wrapper-based " +"approach has the advantage of being easily composable with other wrappers " +"that someone might contribute to the Flower library in the future, e.g., for " +"secure aggregation. Using Inheritance instead can be tedious because that " +"would require the creation of new sub- classes every time a new class " +"implementing :code:`Strategy` or :code:`NumPyClient` is defined." +msgstr "" +"在现有工作负载中引入 DP 可以被认为是在其周围增加了一层额外的安全性。受此启发" +",我们提供了额外的服务器端和客户端逻辑,分别作为 :code:`Strategy` 和 " +":code:`NumPyClient` 抽象类实例的封装器,使训练过程具有不同的隐私性。" +"这种基于封装器的方法的优点是可以很容易地与将来有人贡献给 Flower " +"的其他封装器(例如用于安全聚合的封装器)进行组合。使用继承可能会比较繁琐," +"因为每次定义实现 :code:`Strategy` 或 :code:`NumPyClient` " +"的新类时,都需要创建新的子类。" #: ../../source/explanation-differential-privacy.rst:49 msgid "Server-side logic" -msgstr "" +msgstr "服务器端逻辑" #: ../../source/explanation-differential-privacy.rst:51 msgid "" "The first version of our solution was to define a decorator whose " "constructor accepted, among other things, a boolean valued variable " -"indicating whether adaptive clipping was to be enabled or not. We quickly" -" realized that this would clutter its :code:`__init__()` function with " -"variables corresponding to hyperparameters of adaptive clipping that " -"would remain unused when it was disabled. A cleaner implementation could " -"be achieved by splitting the functionality into two decorators, " -":code:`DPFedAvgFixed` and :code:`DPFedAvgAdaptive`, with the latter sub- " -"classing the former. The constructors for both classes accept a boolean " -"parameter :code:`server_side_noising`, which, as the name suggests, " -"determines where noising is to be performed." -msgstr "" +"indicating whether adaptive clipping was to be enabled or not. We quickly " +"realized that this would clutter its :code:`__init__()` function with " +"variables corresponding to hyperparameters of adaptive clipping that would " +"remain unused when it was disabled. A cleaner implementation could be " +"achieved by splitting the functionality into two decorators, :code:" +"`DPFedAvgFixed` and :code:`DPFedAvgAdaptive`, with the latter sub- classing " +"the former. The constructors for both classes accept a boolean parameter :" +"code:`server_side_noising`, which, as the name suggests, determines where " +"noising is to be performed." +msgstr "" +"我们的第一版解决方案是定义一个装饰器,其构造函数接受一个布尔值变量,表示是否" +"启用自适应剪裁。我们很快意识到,这样会使其 :code:`__init__()` 函数中与自适应" +"裁剪超参数相对应的变量变得杂乱无章,而这些变量在自适应裁剪被禁用时将保持未使" +"用状态。要实现更简洁的功能,可以将该功能拆分为两个装饰器,即 " +":code:`DPFedAvgFixed` 和 :code:`DPFedAvgAdaptive`,后者是前者的子类。" +"这两个类的构造函数都接受一个布尔参数 " +":code:`server_side_noising`,顾名思义,它决定了在哪里加噪声。" #: ../../source/explanation-differential-privacy.rst:54 msgid "DPFedAvgFixed" -msgstr "" +msgstr "DPFedAvgFixed" #: ../../source/explanation-differential-privacy.rst:56 msgid "" -"The server-side capabilities required for the original version of DP-" -"FedAvg, i.e., the one which performed fixed clipping, can be completely " -"captured with the help of wrapper logic for just the following two " -"methods of the :code:`Strategy` abstract class." +"The server-side capabilities required for the original version of DP-FedAvg, " +"i.e., the one which performed fixed clipping, can be completely captured " +"with the help of wrapper logic for just the following two methods of the :" +"code:`Strategy` abstract class." msgstr "" +"只需对 :code:`Strategy` 抽象类的以下两个方法进行封装,就能完全捕获 DP-FedAvg " +"原始版本(即执行固定剪裁的版本)所需的服务器端功能。" #: ../../source/explanation-differential-privacy.rst:58 msgid "" -":code:`configure_fit()` : The config dictionary being sent by the wrapped" -" :code:`Strategy` to each client needs to be augmented with an additional" -" value equal to the clipping threshold (keyed under " -":code:`dpfedavg_clip_norm`) and, if :code:`server_side_noising=true`, " -"another one equal to the scale of the Gaussian noise that needs to be " -"added at the client (keyed under :code:`dpfedavg_noise_stddev`). This " -"entails *post*-processing of the results returned by the wrappee's " -"implementation of :code:`configure_fit()`." -msgstr "" +":code:`configure_fit()` : The config dictionary being sent by the wrapped :" +"code:`Strategy` to each client needs to be augmented with an additional " +"value equal to the clipping threshold (keyed under :code:" +"`dpfedavg_clip_norm`) and, if :code:`server_side_noising=true`, another one " +"equal to the scale of the Gaussian noise that needs to be added at the " +"client (keyed under :code:`dpfedavg_noise_stddev`). This entails *post*-" +"processing of the results returned by the wrappee's implementation of :code:" +"`configure_fit()`." +msgstr "" +":code:`configure_fit()` :由封装的 :code:`Strategy` " +"发送到每个客户端的配置字典需要使用等于裁剪阈值的附加值(在 " +":code:`dpfedavg_clip_norm` 下键入)进行扩充。并且,如果 " +"server_side_noising=true,则另一个值等于需要在客户端添加的高斯噪声的大小(在 " +"dpfedavg_noise_stddev 下键入)。这需要对封装后的configure_fit() " +"所返回的结果进行后处理。" #: ../../source/explanation-differential-privacy.rst:59 msgid "" -":code:`aggregate_fit()`: We check whether any of the sampled clients " -"dropped out or failed to upload an update before the round timed out. In " -"that case, we need to abort the current round, discarding any successful " -"updates that were received, and move on to the next one. On the other " -"hand, if all clients responded successfully, we must force the averaging " -"of the updates to happen in an unweighted manner by intercepting the " -":code:`parameters` field of :code:`FitRes` for each received update and " -"setting it to 1. Furthermore, if :code:`server_side_noising=true`, each " -"update is perturbed with an amount of noise equal to what it would have " -"been subjected to had client-side noising being enabled. This entails " -"*pre*-processing of the arguments to this method before passing them on " -"to the wrappee's implementation of :code:`aggregate_fit()`." -msgstr "" +":code:`aggregate_fit()`: We check whether any of the sampled clients dropped " +"out or failed to upload an update before the round timed out. In that case, " +"we need to abort the current round, discarding any successful updates that " +"were received, and move on to the next one. On the other hand, if all " +"clients responded successfully, we must force the averaging of the updates " +"to happen in an unweighted manner by intercepting the :code:`parameters` " +"field of :code:`FitRes` for each received update and setting it to 1. " +"Furthermore, if :code:`server_side_noising=true`, each update is perturbed " +"with an amount of noise equal to what it would have been subjected to had " +"client-side noising being enabled. This entails *pre*-processing of the " +"arguments to this method before passing them on to the wrappee's " +"implementation of :code:`aggregate_fit()`." +msgstr "" +":code:`aggregate_fit()`: 我们会检查是否有任何客户端在本轮超时前退出或未能上" +"传参数更新。在这种情况下,我们需要中止当前一轮,丢弃已收到的所有参数更新,然" +"后继续下一轮。另一方面,如果所有客户端都成功响应,我们就必须通过拦截 " +":code:`FitRes` 的 :code:`parameters` 字段并将其设置为 " +"1,强制以不加权的方式平均更新。此外,如果 :code:`server_side_noising=true`," +"每次更新都会受到一定量的噪声扰动,其扰动量相当于启用客户端噪声时的扰动量。 " +"这就需要在将本方法的参数传递给封装的 :code:`aggregate_fit()` " +"之前,对参数进行*预*处理。" #: ../../source/explanation-differential-privacy.rst:62 msgid "" -"We can't directly change the aggregation function of the wrapped strategy" -" to force it to add noise to the aggregate, hence we simulate client-side" -" noising to implement server-side noising." +"We can't directly change the aggregation function of the wrapped strategy to " +"force it to add noise to the aggregate, hence we simulate client-side " +"noising to implement server-side noising." msgstr "" +"我们无法直接改变封装策略的聚合函数,迫使它在聚合中添加噪声,因此我们模拟客户" +"端噪声来实现服务器端噪声。" #: ../../source/explanation-differential-privacy.rst:64 msgid "" -"These changes have been put together into a class called " -":code:`DPFedAvgFixed`, whose constructor accepts the strategy being " -"decorated, the clipping threshold and the number of clients sampled every" -" round as compulsory arguments. The user is expected to specify the " -"clipping threshold since the order of magnitude of the update norms is " -"highly dependent on the model being trained and providing a default value" -" would be misleading. The number of clients sampled at every round is " -"required to calculate the amount of noise that must be added to each " -"individual update, either by the server or the clients." -msgstr "" +"These changes have been put together into a class called :code:" +"`DPFedAvgFixed`, whose constructor accepts the strategy being decorated, the " +"clipping threshold and the number of clients sampled every round as " +"compulsory arguments. The user is expected to specify the clipping threshold " +"since the order of magnitude of the update norms is highly dependent on the " +"model being trained and providing a default value would be misleading. The " +"number of clients sampled at every round is required to calculate the amount " +"of noise that must be added to each individual update, either by the server " +"or the clients." +msgstr "" +"这些变化被整合到一个名为 :code:`DPFedAvgFixed` 的类中,其构造函数接受被装饰的" +"策略、剪切阈值和每轮采样的客户数作为必选参数。用户需要指定剪切阈值,因为参数" +"更新规范的数量级在很大程度上取决于正在训练的模型,提供默认值会产生误导。每轮" +"采样的客户端数量是计算服务器或客户在每次参数更新时添加的噪音量所必需的。" #: ../../source/explanation-differential-privacy.rst:67 msgid "DPFedAvgAdaptive" -msgstr "" +msgstr "DPFedAvgAdaptive" #: ../../source/explanation-differential-privacy.rst:69 msgid "" -"The additional functionality required to facilitate adaptive clipping has" -" been provided in :code:`DPFedAvgAdaptive`, a subclass of " -":code:`DPFedAvgFixed`. It overrides the above-mentioned methods to do the" -" following." +"The additional functionality required to facilitate adaptive clipping has " +"been provided in :code:`DPFedAvgAdaptive`, a subclass of :code:" +"`DPFedAvgFixed`. It overrides the above-mentioned methods to do the " +"following." msgstr "" +"自适应剪裁所需的附加功能在 :code:`DPFedAvgAdaptive` 中提供,其是 " +":code:`DPFedAvgFixed` 的子类。它重写了上述方法,以实现以下功能。" #: ../../source/explanation-differential-privacy.rst:71 msgid "" -":code:`configure_fit()` : It intercepts the config dict returned by " -":code:`super.configure_fit()` to add the key-value pair " -":code:`dpfedavg_adaptive_clip_enabled:True` to it, which the client " -"interprets as an instruction to include an indicator bit (1 if update " -"norm <= clipping threshold, 0 otherwise) in the results returned by it." +":code:`configure_fit()` : It intercepts the config dict returned by :code:" +"`super.configure_fit()` to add the key-value pair :code:" +"`dpfedavg_adaptive_clip_enabled:True` to it, which the client interprets as " +"an instruction to include an indicator bit (1 if update norm <= clipping " +"threshold, 0 otherwise) in the results returned by it." msgstr "" +":code:`configure_fit()`:它截取由 :code:`super.configure_fit()` 返回的 " +"config 字典,并在其中添加键-值对 :code:`dpfedavg_adaptive_clip_enabled:True\"" +",客户端将其解释为在返回结果中包含一个指示位(如果参数更新范式 <= 剪裁阈值," +"则为 1,否则为 0)的指令。" #: ../../source/explanation-differential-privacy.rst:73 msgid "" -":code:`aggregate_fit()` : It follows a call to " -":code:`super.aggregate_fit()` with one to :code:`__update_clip_norm__()`," -" a procedure which adjusts the clipping threshold on the basis of the " -"indicator bits received from the sampled clients." +":code:`aggregate_fit()` : It follows a call to :code:`super.aggregate_fit()` " +"with one to :code:`__update_clip_norm__()`, a procedure which adjusts the " +"clipping threshold on the basis of the indicator bits received from the " +"sampled clients." msgstr "" +":code:`aggregate_fit()`:在调用:code:`super.aggregate_fit()`后,再调用:code:`" +"__update_clip_norm__()`,该过程根据从采样客户端接收到的指示位调整裁剪阈值。" #: ../../source/explanation-differential-privacy.rst:77 msgid "Client-side logic" -msgstr "" +msgstr "客户端逻辑" #: ../../source/explanation-differential-privacy.rst:79 msgid "" "The client-side capabilities required can be completely captured through " -"wrapper logic for just the :code:`fit()` method of the " -":code:`NumPyClient` abstract class. To be precise, we need to *post-" -"process* the update computed by the wrapped client to clip it, if " -"necessary, to the threshold value supplied by the server as part of the " -"config dictionary. In addition to this, it may need to perform some extra" -" work if either (or both) of the following keys are also present in the " -"dict." -msgstr "" +"wrapper logic for just the :code:`fit()` method of the :code:`NumPyClient` " +"abstract class. To be precise, we need to *post-process* the update computed " +"by the wrapped client to clip it, if necessary, to the threshold value " +"supplied by the server as part of the config dictionary. In addition to " +"this, it may need to perform some extra work if either (or both) of the " +"following keys are also present in the dict." +msgstr "" +"客户端所需的功能完全可以通过 :code:`NumPyClient` 抽象类的 :code:`fit()` 方法" +"的封装逻辑来实现。准确地说,我们需要对封装客户端计算的参数更新进行处理,以便" +"在必要时将其剪切到服务器作为配置字典的一部分提供的阈值。除此之外,如果配置字" +"典中还存在以下任一(或两个)键,客户端可能还需要执行一些额外的工作。" #: ../../source/explanation-differential-privacy.rst:81 msgid "" ":code:`dpfedavg_noise_stddev` : Generate and add the specified amount of " "noise to the clipped update." -msgstr "" +msgstr "code:`dpfedavg_noise_stddev`:生成并在剪切参数更新中添加指定数量的噪声。" #: ../../source/explanation-differential-privacy.rst:82 msgid "" -":code:`dpfedavg_adaptive_clip_enabled` : Augment the metrics dict in the " -":code:`FitRes` object being returned to the server with an indicator bit," -" calculated as described earlier." +":code:`dpfedavg_adaptive_clip_enabled` : Augment the metrics dict in the :" +"code:`FitRes` object being returned to the server with an indicator bit, " +"calculated as described earlier." msgstr "" +":code:`dpfedavg_adaptive_clip_enabled`:在返回给服务器的 :code:`FitRes` " +"对象中的度量值字典中增加一个指标位,计算方法如前所述。" #: ../../source/explanation-differential-privacy.rst:86 msgid "Performing the :math:`(\\epsilon, \\delta)` analysis" -msgstr "" +msgstr "进行 :math:`(epsilon, \\delta)` 分析" #: ../../source/explanation-differential-privacy.rst:88 msgid "" -"Assume you have trained for :math:`n` rounds with sampling fraction " -":math:`q` and noise multiplier :math:`z`. In order to calculate the " -":math:`\\epsilon` value this would result in for a particular " -":math:`\\delta`, the following script may be used." +"Assume you have trained for :math:`n` rounds with sampling fraction :math:" +"`q` and noise multiplier :math:`z`. In order to calculate the :math:" +"`\\epsilon` value this would result in for a particular :math:`\\delta`, the " +"following script may be used." msgstr "" +"假设您已经训练了 :math:`n` 轮,采样比例为 :math:`q`,噪声乘数为 :math:`z`。" +"为了计算特定 :math:`\\delta` 的 :math:`epsilon` 值,可以使用下面的脚本。" #: ../../source/explanation-differential-privacy.rst:98 msgid "" "McMahan, H. Brendan, et al. \"Learning differentially private recurrent " "language models.\" arXiv preprint arXiv:1710.06963 (2017)." msgstr "" +"McMahan, H. Brendan等. \"Learning differentially private recurrent language " +"models.\" arXiv preprint arXiv:1710.06963 (2017)." #: ../../source/explanation-differential-privacy.rst:100 msgid "" @@ -3126,26 +3702,29 @@ msgid "" "clipping.\" Advances in Neural Information Processing Systems 34 (2021): " "17455-17466." msgstr "" +"Andrew, Galen等. \"Differentially private learning with adaptive clipping.\" " +"Advances in Neural Information Processing Systems 34 (2021): 17455-17466." #: ../../source/explanation-federated-evaluation.rst:2 #: ../../source/tutorial-series-what-is-federated-learning.ipynb:292 msgid "Federated evaluation" -msgstr "" +msgstr "联邦学习评估" #: ../../source/explanation-federated-evaluation.rst:4 msgid "" "There are two main approaches to evaluating models in federated learning " -"systems: centralized (or server-side) evaluation and federated (or " -"client-side) evaluation." -msgstr "" +"systems: centralized (or server-side) evaluation and federated (or client-" +"side) evaluation." +msgstr "评估联合学习系统中的模型主要有两种方法:集中(或服务器端)评估和联邦(或客户" +"端)评估。" #: ../../source/explanation-federated-evaluation.rst:8 msgid "Centralized Evaluation" -msgstr "" +msgstr "集中评估" #: ../../source/explanation-federated-evaluation.rst:11 msgid "Built-In Strategies" -msgstr "" +msgstr "内置策略" #: ../../source/explanation-federated-evaluation.rst:13 msgid "" @@ -3154,177 +3733,199 @@ msgid "" "function that can take the current global model parameters as input and " "return evaluation results:" msgstr "" +"所有内置策略都通过在初始化过程中提供一个评估函数来支持集中评估。评估函数是任" +"何可以将当前全局模型参数作为输入并返回评估结果的函数:" #: ../../source/explanation-federated-evaluation.rst:58 msgid "Custom Strategies" -msgstr "" +msgstr "定制策略" #: ../../source/explanation-federated-evaluation.rst:60 msgid "" -"The :code:`Strategy` abstraction provides a method called " -":code:`evaluate` that can directly be used to evaluate the current global" -" model parameters. The current server implementation calls " -":code:`evaluate` after parameter aggregation and before federated " -"evaluation (see next paragraph)." +"The :code:`Strategy` abstraction provides a method called :code:`evaluate` " +"that can directly be used to evaluate the current global model parameters. " +"The current server implementation calls :code:`evaluate` after parameter " +"aggregation and before federated evaluation (see next paragraph)." msgstr "" +":code:`Strategy` 抽象提供了一个名为 :code:`evaluate` " +"的方法,可直接用于评估当前的全局模型参数。" +"服务器会在参数聚合后和联邦评估前调用 :code:`evaluate`(见下段)。" #: ../../source/explanation-federated-evaluation.rst:65 msgid "Federated Evaluation" -msgstr "" +msgstr "联邦评估" #: ../../source/explanation-federated-evaluation.rst:68 msgid "Implementing Federated Evaluation" -msgstr "" +msgstr "实现联邦评估" #: ../../source/explanation-federated-evaluation.rst:70 msgid "" -"Client-side evaluation happens in the :code:`Client.evaluate` method and " -"can be configured from the server side." +"Client-side evaluation happens in the :code:`Client.evaluate` method and can " +"be configured from the server side." msgstr "" +"客户端评估在 :code:`Client.evaluate` 方法中进行,并可从服务器端进行配置。" #: ../../source/explanation-federated-evaluation.rst:101 msgid "Configuring Federated Evaluation" -msgstr "" +msgstr "配置联邦评估" #: ../../source/explanation-federated-evaluation.rst:103 msgid "" "Federated evaluation can be configured from the server side. Built-in " "strategies support the following arguments:" -msgstr "" +msgstr "联邦评估可从服务器端进行配置。内置策略支持以下参数:" #: ../../source/explanation-federated-evaluation.rst:105 msgid "" -":code:`fraction_evaluate`: a :code:`float` defining the fraction of " -"clients that will be selected for evaluation. If " -":code:`fraction_evaluate` is set to :code:`0.1` and :code:`100` clients " -"are connected to the server, then :code:`10` will be randomly selected " -"for evaluation. If :code:`fraction_evaluate` is set to :code:`0.0`, " -"federated evaluation will be disabled." +":code:`fraction_evaluate`: a :code:`float` defining the fraction of clients " +"that will be selected for evaluation. If :code:`fraction_evaluate` is set " +"to :code:`0.1` and :code:`100` clients are connected to the server, then :" +"code:`10` will be randomly selected for evaluation. If :code:" +"`fraction_evaluate` is set to :code:`0.0`, federated evaluation will be " +"disabled." msgstr "" +":code:`fraction_evaluate`: :code:`float`,定义被选中进行评估的客户端的分数。" +"如果 :code:`fraction_evaluate` 设置为 :code:`0.1`,并且 :code:`100` 客户端连" +"接到服务器,那么 :code:`10` 将被随机选中进行评估。如果 :code:" +"`fraction_evaluate` 设置为 :code:`0.0`,联合评估将被禁用。" #: ../../source/explanation-federated-evaluation.rst:106 msgid "" -":code:`min_evaluate_clients`: an :code:`int`: the minimum number of " -"clients to be selected for evaluation. If :code:`fraction_evaluate` is " -"set to :code:`0.1`, :code:`min_evaluate_clients` is set to 20, and " -":code:`100` clients are connected to the server, then :code:`20` clients " -"will be selected for evaluation." +":code:`min_evaluate_clients`: an :code:`int`: the minimum number of clients " +"to be selected for evaluation. If :code:`fraction_evaluate` is set to :code:" +"`0.1`, :code:`min_evaluate_clients` is set to 20, and :code:`100` clients " +"are connected to the server, then :code:`20` clients will be selected for " +"evaluation." msgstr "" +":code:`min_evaluate_clients`:一个 :code:`int`:需要评估的客户的最小数量。如" +"果 :code:`fraction_evaluate` 设置为 :code:`0.1`,:code:" +"`min_evaluate_clients` 设置为 20,并且 :code:`100` 客户端已连接到服务器,那" +"么 :code:`20` 客户端将被选中进行评估。" #: ../../source/explanation-federated-evaluation.rst:107 msgid "" ":code:`min_available_clients`: an :code:`int` that defines the minimum " -"number of clients which need to be connected to the server before a round" -" of federated evaluation can start. If fewer than " -":code:`min_available_clients` are connected to the server, the server " -"will wait until more clients are connected before it continues to sample " -"clients for evaluation." +"number of clients which need to be connected to the server before a round of " +"federated evaluation can start. If fewer than :code:`min_available_clients` " +"are connected to the server, the server will wait until more clients are " +"connected before it continues to sample clients for evaluation." msgstr "" +":code:`min_available_clients`:一个 :code:`int`,定义了在一轮联合评估开始之" +"前,需要连接到服务器的最小客户端数量。如果连接到服务器的客户少于 :code:" +"`min_available_clients`,服务器将等待更多客户连接后,才继续采样客户进行评估。" #: ../../source/explanation-federated-evaluation.rst:108 msgid "" ":code:`on_evaluate_config_fn`: a function that returns a configuration " -"dictionary which will be sent to the selected clients. The function will " -"be called during each round and provides a convenient way to customize " -"client-side evaluation from the server side, for example, to configure " -"the number of validation steps performed." +"dictionary which will be sent to the selected clients. The function will be " +"called during each round and provides a convenient way to customize client-" +"side evaluation from the server side, for example, to configure the number " +"of validation steps performed." msgstr "" +"code:`on_evaluate_config_fn`:返回配置字典的函数,该字典将发送给选定的客户" +"端。该函数将在每一轮中被调用,并提供了一种方便的方法来从服务器端自定义客户端" +"评估,例如,配置执行的验证步骤数。" #: ../../source/explanation-federated-evaluation.rst:135 msgid "Evaluating Local Model Updates During Training" -msgstr "" +msgstr "评估训练期间的本地模型更新" #: ../../source/explanation-federated-evaluation.rst:137 msgid "" -"Model parameters can also be evaluated during training. " -":code:`Client.fit` can return arbitrary evaluation results as a " -"dictionary:" +"Model parameters can also be evaluated during training. :code:`Client.fit` " +"can return arbitrary evaluation results as a dictionary:" msgstr "" +"模型参数也可在训练过程中进行评估。 :code:`Client.fit`可以字典形式返回任意评估" +"结果:" #: ../../source/explanation-federated-evaluation.rst:177 msgid "Full Code Example" -msgstr "" +msgstr "完整代码示例" #: ../../source/explanation-federated-evaluation.rst:179 msgid "" -"For a full code example that uses both centralized and federated " -"evaluation, see the *Advanced TensorFlow Example* (the same approach can " -"be applied to workloads implemented in any other framework): " -"https://github.com/adap/flower/tree/main/examples/advanced-tensorflow" +"For a full code example that uses both centralized and federated evaluation, " +"see the *Advanced TensorFlow Example* (the same approach can be applied to " +"workloads implemented in any other framework): https://github.com/adap/" +"flower/tree/main/examples/advanced-tensorflow" msgstr "" +"有关同时使用集中评估和联合评估的完整代码示例,请参阅 *Advanced TensorFlow " +"Example*(同样的方法也可应用于在任何其他框架中实施的工作负载): https://" +"github.com/adap/flower/tree/main/examples/advanced-tensorflow" #: ../../source/fed/0000-20200102-fed-template.md:10 msgid "FED Template" -msgstr "" +msgstr "FED 模板" #: ../../source/fed/0000-20200102-fed-template.md:12 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:12 msgid "Table of Contents" -msgstr "" +msgstr "目录" #: ../../source/fed/0000-20200102-fed-template.md:14 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:14 msgid "[Table of Contents](#table-of-contents)" -msgstr "" +msgstr "[目录](#table-of-contents)" #: ../../source/fed/0000-20200102-fed-template.md:15 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:15 msgid "[Summary](#summary)" -msgstr "" +msgstr "[Summary](#summary)" #: ../../source/fed/0000-20200102-fed-template.md:16 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:16 msgid "[Motivation](#motivation)" -msgstr "" +msgstr "[Motivation](#motivation)" #: ../../source/fed/0000-20200102-fed-template.md:17 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:17 msgid "[Goals](#goals)" -msgstr "" +msgstr "[Goals](#goals)" #: ../../source/fed/0000-20200102-fed-template.md:18 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:18 msgid "[Non-Goals](#non-goals)" -msgstr "" +msgstr "[Non-Goals](#non-goals)" #: ../../source/fed/0000-20200102-fed-template.md:19 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:19 msgid "[Proposal](#proposal)" -msgstr "" +msgstr "[Proposal](#proposal)" #: ../../source/fed/0000-20200102-fed-template.md:20 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:23 msgid "[Drawbacks](#drawbacks)" -msgstr "" +msgstr "[Drawbacks](#drawbacks)" #: ../../source/fed/0000-20200102-fed-template.md:21 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:24 msgid "[Alternatives Considered](#alternatives-considered)" -msgstr "" +msgstr "[Alternatives Considered](#alternatives-considered)" #: ../../source/fed/0000-20200102-fed-template.md:22 msgid "[Appendix](#appendix)" -msgstr "" +msgstr "[Appendix](#appendix)" #: ../../source/fed/0000-20200102-fed-template.md:24 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:28 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:76 msgid "Summary" -msgstr "" +msgstr "内容摘要" #: ../../source/fed/0000-20200102-fed-template.md:26 msgid "\\[TODO - sentence 1: summary of the problem\\]" -msgstr "" +msgstr "\\[TODO - sentence 1: summary of the problem\\]" #: ../../source/fed/0000-20200102-fed-template.md:28 msgid "\\[TODO - sentence 2: summary of the solution\\]" -msgstr "" +msgstr "\\[TODO - sentence 2: summary of the solution\\]" #: ../../source/fed/0000-20200102-fed-template.md:30 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:47 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:77 msgid "Motivation" -msgstr "" +msgstr "动机" #: ../../source/fed/0000-20200102-fed-template.md:32 #: ../../source/fed/0000-20200102-fed-template.md:36 @@ -3334,669 +3935,782 @@ msgstr "" #: ../../source/fed/0000-20200102-fed-template.md:54 #: ../../source/fed/0000-20200102-fed-template.md:58 msgid "\\[TODO\\]" -msgstr "" +msgstr "\\[TODO\\]" #: ../../source/fed/0000-20200102-fed-template.md:34 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:53 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:78 msgid "Goals" -msgstr "" +msgstr "目标" #: ../../source/fed/0000-20200102-fed-template.md:38 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:59 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:79 msgid "Non-Goals" -msgstr "" +msgstr "非目标" #: ../../source/fed/0000-20200102-fed-template.md:42 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:65 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:80 msgid "Proposal" -msgstr "" +msgstr "提案" #: ../../source/fed/0000-20200102-fed-template.md:46 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:85 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:129 msgid "Drawbacks" -msgstr "" +msgstr "缺点" #: ../../source/fed/0000-20200102-fed-template.md:50 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:86 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:135 msgid "Alternatives Considered" -msgstr "" +msgstr "曾考虑的替代方案" #: ../../source/fed/0000-20200102-fed-template.md:52 +#, fuzzy msgid "\\[Alternative 1\\]" -msgstr "" +msgstr "\\[Alternative 1\\]" #: ../../source/fed/0000-20200102-fed-template.md:56 +#, fuzzy msgid "\\[Alternative 2\\]" -msgstr "" +msgstr "\\[Alternative 2\\]" #: ../../source/fed/0000-20200102-fed-template.md:60 msgid "Appendix" -msgstr "" +msgstr "附录" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:10 msgid "Flower Enhancement Doc" -msgstr "" +msgstr "Flower 增效文件" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:20 +#, fuzzy msgid "[Enhancement Doc Template](#enhancement-doc-template)" -msgstr "" +msgstr "[Enhancement Doc Template](#enhancement-doc-template)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:21 +#, fuzzy msgid "[Metadata](#metadata)" -msgstr "" +msgstr "[Metadata](#metadata)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:22 +#, fuzzy msgid "[Workflow](#workflow)" -msgstr "" +msgstr "[Workflow](#workflow)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:25 +#, fuzzy msgid "[GitHub Issues](#github-issues)" -msgstr "" +msgstr "[GitHub Issues](#github-issues)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:26 +#, fuzzy msgid "[Google Docs](#google-docs)" -msgstr "" +msgstr "[Google Docs](#google-docs)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:30 msgid "A Flower Enhancement is a standardized development process to" -msgstr "" +msgstr "增强 Flower 功能是一个标准化的开发流程,目的是" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:32 msgid "provide a common structure for proposing larger changes" -msgstr "" +msgstr "为提出更大规模的变革提供一个共同的结构" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:33 msgid "ensure that the motivation for a change is clear" -msgstr "" +msgstr "确保变革的动机明确" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:34 msgid "persist project information in a version control system" -msgstr "" +msgstr "将项目信息保存在版本控制系统中" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:35 msgid "document the motivation for impactful user-facing changes" -msgstr "" +msgstr "记录面向用户的具有影响力的变革的动机" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:36 msgid "reserve GitHub issues for tracking work in flight" -msgstr "" +msgstr "保留 GitHub 问题,用于跟踪飞行中的工作" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:37 msgid "" -"ensure community participants can successfully drive changes to " -"completion across one or more releases while stakeholders are adequately " -"represented throughout the process" +"ensure community participants can successfully drive changes to completion " +"across one or more releases while stakeholders are adequately represented " +"throughout the process" msgstr "" +"确保社区参与者能够成功推动变革,完成一个或多个版本,同时利益相关者在整个过程" +"中得到充分代表" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:39 msgid "Hence, an Enhancement Doc combines aspects of" -msgstr "" +msgstr "因此,\"增强文件 \"将以下方面结合起来" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:41 msgid "a feature, and effort-tracking document" -msgstr "" +msgstr "功能,以及努力跟踪文件" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:42 msgid "a product requirements document" -msgstr "" +msgstr "产品要求文件" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:43 msgid "a design document" -msgstr "" +msgstr "设计文件" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:45 msgid "" "into one file, which is created incrementally in collaboration with the " "community." -msgstr "" +msgstr "该文件是与社区合作逐步创建的。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:49 msgid "" "For far-fetching changes or features proposed to Flower, an abstraction " -"beyond a single GitHub issue or pull request is required to understand " -"and communicate upcoming changes to the project." +"beyond a single GitHub issue or pull request is required to understand and " +"communicate upcoming changes to the project." msgstr "" +"对于向 Flower 提出的远期变更或功能,需要一个超越单个 GitHub 问题或拉请求的抽" +"象概念,以了解和沟通项目即将发生的变更。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:51 msgid "" -"The purpose of this process is to reduce the amount of \"tribal " -"knowledge\" in our community. By moving decisions from Slack threads, " -"video calls, and hallway conversations into a well-tracked artifact, this" -" process aims to enhance communication and discoverability." +"The purpose of this process is to reduce the amount of \"tribal knowledge\" " +"in our community. By moving decisions from Slack threads, video calls, and " +"hallway conversations into a well-tracked artifact, this process aims to " +"enhance communication and discoverability." msgstr "" +"这一流程的目的是减少我们社区中 \"部落知识 \"的数量。通过将决策从 Slack 线程、" +"视频通话和走廊对话转移到一个跟踪良好的人工制品中,该流程旨在加强沟通和可发现" +"性。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:55 msgid "" -"Roughly any larger, user-facing enhancement should follow the Enhancement" -" process. If an enhancement would be described in either written or " -"verbal communication to anyone besides the author or developer, then " -"consider creating an Enhancement Doc." +"Roughly any larger, user-facing enhancement should follow the Enhancement " +"process. If an enhancement would be described in either written or verbal " +"communication to anyone besides the author or developer, then consider " +"creating an Enhancement Doc." msgstr "" +"任何较大的、面向用户的增强都应遵循增强流程。如果要以书面或口头形式向作者或开" +"发人员以外的任何人描述增强功能,则应考虑创建增强文档。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:57 msgid "" -"Similarly, any technical effort (refactoring, major architectural change)" -" that will impact a large section of the development community should " -"also be communicated widely. The Enhancement process is suited for this " -"even if it will have zero impact on the typical user or operator." +"Similarly, any technical effort (refactoring, major architectural change) " +"that will impact a large section of the development community should also be " +"communicated widely. The Enhancement process is suited for this even if it " +"will have zero impact on the typical user or operator." msgstr "" +"同样,任何会对开发社区的大部分人产生影响的技术工作(重构、重大架构变更)也应" +"广泛传播。即使对典型用户或操作员的影响为零,改进流程也适用于这种情况。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:61 msgid "" -"For small changes and additions, going through the Enhancement process " -"would be time-consuming and unnecessary. This includes, for example, " -"adding new Federated Learning algorithms, as these only add features " -"without changing how Flower works or is used." +"For small changes and additions, going through the Enhancement process would " +"be time-consuming and unnecessary. This includes, for example, adding new " +"Federated Learning algorithms, as these only add features without changing " +"how Flower works or is used." msgstr "" +"对于小的改动和添加,通过 \"增强 \"程序既耗时又没有必要。例如,这包括添加新的" +"联合学习算法,因为这只会增加功能,而不会改变 \"Flower \"的工作或使用方式。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:63 msgid "" "Enhancements are different from feature requests, as they are already " -"providing a laid-out path for implementation and are championed by " -"members of the community." +"providing a laid-out path for implementation and are championed by members " +"of the community." msgstr "" +"增强功能与功能请求不同,因为它们已经提供了实施路径,并得到了社区成员的支持。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:67 msgid "" "An Enhancement is captured in a Markdown file that follows a defined " -"template and a workflow to review and store enhancement docs for " -"reference — the Enhancement Doc." +"template and a workflow to review and store enhancement docs for reference " +"— the Enhancement Doc." msgstr "" +"增强功能被记录在一个 Markdown 文件中,该文件遵循已定义的模板和工作流程,用于" +"审查和存储增强功能文档(即增强功能文档)以供参考。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:69 msgid "Enhancement Doc Template" -msgstr "" +msgstr "增强文档模板" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:71 msgid "" "Each enhancement doc is provided as a Markdown file having the following " "structure" -msgstr "" +msgstr "每个改进文档都以 Markdown 文件的形式提供,其结构如下" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:73 msgid "Metadata (as [described below](#metadata) in form of a YAML preamble)" -msgstr "" +msgstr "元数据([如下所述](#metadata) 以 YAML 前言的形式出现)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:74 msgid "Title (same as in metadata)" -msgstr "" +msgstr "标题(与元数据中的标题相同)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:75 msgid "Table of Contents (if needed)" -msgstr "" +msgstr "目录(如有需要)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:81 msgid "Notes/Constraints/Caveats (optional)" -msgstr "" +msgstr "注意事项/限制/注意事项(可选)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:82 msgid "Design Details (optional)" -msgstr "" +msgstr "设计细节(可选)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:83 msgid "Graduation Criteria" -msgstr "" +msgstr "毕业标准" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:84 msgid "Upgrade/Downgrade Strategy (if applicable)" -msgstr "" +msgstr "升级/降级策略(如适用)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:88 msgid "As a reference, this document follows the above structure." -msgstr "" +msgstr "作为参考,本文件采用上述结构。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:90 msgid "Metadata" -msgstr "" +msgstr "元数据" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:92 msgid "" -"**fed-number** (Required) The `fed-number` of the last Flower Enhancement" -" Doc + 1. With this number, it becomes easy to reference other proposals." +"**fed-number** (Required) The `fed-number` of the last Flower Enhancement " +"Doc + 1. With this number, it becomes easy to reference other proposals." msgstr "" +"**fed-number**(必填)上一个鲜花增强文件的 \"fed-number \"+1。有了这个编号," +"就很容易参考其他提案。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:94 msgid "**title** (Required) The title of the proposal in plain language." -msgstr "" +msgstr "**标题** (必填)用简明语言写出提案的标题。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:96 msgid "" -"**status** (Required) The current status of the proposal. See " -"[workflow](#workflow) for the possible states." +"**status** (Required) The current status of the proposal. See [workflow]" +"(#workflow) for the possible states." msgstr "" +"**status** (必填)提案的当前状态。有关可能的状态,请参阅 [工作流程]" +"(#workflow)。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:98 msgid "" -"**authors** (Required) A list of authors of the proposal. This is simply " -"the GitHub ID." -msgstr "" +"**authors** (Required) A list of authors of the proposal. This is simply the " +"GitHub ID." +msgstr "**作者**(必填) 提案的作者列表。这只是 GitHub ID。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:100 msgid "" -"**creation-date** (Required) The date that the proposal was first " -"submitted in a PR." -msgstr "" +"**creation-date** (Required) The date that the proposal was first submitted " +"in a PR." +msgstr "**创建日期**(必填) 建议书在 PR 中首次提交的日期。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:102 msgid "" "**last-updated** (Optional) The date that the proposal was last changed " "significantly." -msgstr "" +msgstr "**最后更新** (可选)提案最后一次重大修改的日期。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:104 msgid "" -"**see-also** (Optional) A list of other proposals that are relevant to " -"this one." -msgstr "" +"**see-also** (Optional) A list of other proposals that are relevant to this " +"one." +msgstr "**另见** (可选)与本提案相关的其他提案清单。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:106 msgid "**replaces** (Optional) A list of proposals that this one replaces." -msgstr "" +msgstr "**取代**(可选) 这份提案所取代的提案列表。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:108 -msgid "**superseded-by** (Optional) A list of proposals that this one supersedes." -msgstr "" +msgid "" +"**superseded-by** (Optional) A list of proposals that this one supersedes." +msgstr "**被取代者** (可选) 此提案取代的提案列表。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:111 msgid "Workflow" -msgstr "" +msgstr "工作流程" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:113 msgid "" "The idea forming the enhancement should already have been discussed or " -"pitched in the community. As such, it needs a champion, usually the " -"author, who shepherds the enhancement. This person also has to find " -"committers to Flower willing to review the proposal." +"pitched in the community. As such, it needs a champion, usually the author, " +"who shepherds the enhancement. This person also has to find committers to " +"Flower willing to review the proposal." msgstr "" +"形成增强功能的想法应该已经在社区中讨论过或提出过。因此,它需要一个支持者(通" +"常是作者)来引导增强。这个人还必须找到愿意审核提案的提交者。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:115 msgid "" "New enhancements are checked in with a file name in the form of `NNNN-" -"YYYYMMDD-enhancement-title.md`, with `NNNN` being the Flower Enhancement " -"Doc number, to `enhancements`. All enhancements start in `provisional` " -"state as part of a pull request. Discussions are done as part of the pull" -" request review." +"YYYYMMDD-enhancement-title.md`, with `NNNN` being the Flower Enhancement Doc " +"number, to `enhancements`. All enhancements start in `provisional` state as " +"part of a pull request. Discussions are done as part of the pull request " +"review." msgstr "" +"新的增强功能以 `NNNN-YYYYMMDD-enhancement-title.md` 的文件名签入,其中 " +"`NNNN` 是花朵增强文档的编号,并将其转入 `enhancements`。作为拉取请求的一部" +"分,所有增强功能都从 `provisional` 状态开始。讨论是作为拉取请求审查的一部分进" +"行的。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:117 msgid "" -"Once an enhancement has been reviewed and approved, its status is changed" -" to `implementable`. The actual implementation is then done in separate " -"pull requests. These pull requests should mention the respective " -"enhancement as part of their description. After the implementation is " -"done, the proposal status is changed to `implemented`." +"Once an enhancement has been reviewed and approved, its status is changed to " +"`implementable`. The actual implementation is then done in separate pull " +"requests. These pull requests should mention the respective enhancement as " +"part of their description. After the implementation is done, the proposal " +"status is changed to `implemented`." msgstr "" +"一旦增强功能通过审核和批准,其状态就会变为 \"可实施\"。实际的实施工作将在单独" +"的拉取请求中完成。这些拉取请求应在其描述中提及相应的增强功能。实施完成后,提" +"案状态将更改为 \"已实施\"。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:119 msgid "" -"Under certain conditions, other states are possible. An Enhancement has " -"the following states:" -msgstr "" +"Under certain conditions, other states are possible. An Enhancement has the " +"following states:" +msgstr "在某些条件下,还可能出现其他状态。增强 \"具有以下状态:" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:121 msgid "" "`provisional`: The enhancement has been proposed and is actively being " -"defined. This is the starting state while the proposal is being fleshed " -"out and actively defined and discussed." +"defined. This is the starting state while the proposal is being fleshed out " +"and actively defined and discussed." msgstr "" +"暂定\": 已提出改进建议并正在积极定义。这是在提案得到充实、积极定义和讨论时的" +"起始状态。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:122 msgid "`implementable`: The enhancement has been reviewed and approved." -msgstr "" +msgstr "可实施\": 增强功能已审核通过。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:123 msgid "" "`implemented`: The enhancement has been implemented and is no longer " "actively changed." -msgstr "" +msgstr "已实施`: 增强功能已实施,不再主动更改。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:124 -msgid "`deferred`: The enhancement is proposed but not actively being worked on." -msgstr "" +msgid "" +"`deferred`: The enhancement is proposed but not actively being worked on." +msgstr "\"推迟\": 已提出改进建议,但尚未积极开展工作。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:125 msgid "" -"`rejected`: The authors and reviewers have decided that this enhancement " -"is not moving forward." -msgstr "" +"`rejected`: The authors and reviewers have decided that this enhancement is " +"not moving forward." +msgstr "拒绝\": 作者和审稿人已决定不再推进该增强功能。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:126 msgid "`withdrawn`: The authors have withdrawn the enhancement." -msgstr "" +msgstr "撤回\": 作者已撤回增强功能。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:127 msgid "`replaced`: The enhancement has been replaced by a new enhancement." -msgstr "" +msgstr "`已替换`: 增强功能已被新的增强功能取代。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:131 msgid "" -"Adding an additional process to the ones already provided by GitHub " -"(Issues and Pull Requests) adds more complexity and can be a barrier for " -"potential first-time contributors." +"Adding an additional process to the ones already provided by GitHub (Issues " +"and Pull Requests) adds more complexity and can be a barrier for potential " +"first-time contributors." msgstr "" +"在 GitHub 已提供的流程(问题和拉取请求)之外再增加一个流程,会增加复杂性,并" +"可能成为潜在首次贡献者的障碍。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:133 msgid "" "Expanding the proposal template beyond the single-sentence description " -"currently required in the features issue template may be a heavy burden " -"for non-native English speakers." +"currently required in the features issue template may be a heavy burden for " +"non-native English speakers." msgstr "" +"对于英语非母语者来说,将提案模板扩展到目前要求的单句描述之外可能是一个沉重的" +"负担。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:137 msgid "GitHub Issues" -msgstr "" +msgstr "GitHub 问题" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:139 msgid "" "Using GitHub Issues for these kinds of enhancements is doable. One could " -"use, for example, tags, to differentiate and filter them from other " -"issues. The main issue is in discussing and reviewing an enhancement: " -"GitHub issues only have a single thread for comments. Enhancements " -"usually have multiple threads of discussion at the same time for various " -"parts of the doc. Managing these multiple discussions can be confusing " -"when using GitHub Issues." -msgstr "" +"use, for example, tags, to differentiate and filter them from other issues. " +"The main issue is in discussing and reviewing an enhancement: GitHub issues " +"only have a single thread for comments. Enhancements usually have multiple " +"threads of discussion at the same time for various parts of the doc. " +"Managing these multiple discussions can be confusing when using GitHub " +"Issues." +msgstr "" +"使用 GitHub Issues 进行此类改进是可行的。例如,我们可以使用标签来区分和过滤这" +"些问题。主要的问题在于讨论和审查增强功能: GitHub 问题只有一个评论线程。而增" +"强功能通常会同时有多个讨论线程,针对文档的不同部分。在使用 GitHub 问题时,管" +"理这些多重讨论会很混乱。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:141 msgid "Google Docs" -msgstr "" +msgstr "谷歌文档" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:143 msgid "" -"Google Docs allow for multiple threads of discussions. But as Google Docs" -" are hosted outside the project, their discoverability by the community " -"needs to be taken care of. A list of links to all proposals has to be " -"managed and made available for the community. Compared to shipping " -"proposals as part of Flower's repository, the potential for missing links" -" is much higher." +"Google Docs allow for multiple threads of discussions. But as Google Docs " +"are hosted outside the project, their discoverability by the community needs " +"to be taken care of. A list of links to all proposals has to be managed and " +"made available for the community. Compared to shipping proposals as part of " +"Flower's repository, the potential for missing links is much higher." msgstr "" +"谷歌文档允许多线程讨论。但是,由于谷歌文档是在项目之外托管的,因此需要注意它" +"们是否能被社区发现。我们必须管理所有提案的链接列表,并提供给社区使用。与作为 " +"Flower 资源库一部分的提案相比,丢失链接的可能性要大得多。" #: ../../source/fed/index.md:1 msgid "FED - Flower Enhancement Doc" -msgstr "" +msgstr "FED - Flower 增强文件" #: ../../source/how-to-aggregate-evaluation-results.rst:2 msgid "Aggregate evaluation results" -msgstr "" +msgstr "总体评估结果" #: ../../source/how-to-aggregate-evaluation-results.rst:4 msgid "" -"The Flower server does not prescribe a way to aggregate evaluation " -"results, but it enables the user to fully customize result aggregation." +"The Flower server does not prescribe a way to aggregate evaluation results, " +"but it enables the user to fully customize result aggregation." msgstr "" +"Flower 服务器没有规定汇总评估结果的方法,但用户可以完全自定义结果汇总。" #: ../../source/how-to-aggregate-evaluation-results.rst:8 msgid "Aggregate Custom Evaluation Results" -msgstr "" +msgstr "自定义评估结果汇总" #: ../../source/how-to-aggregate-evaluation-results.rst:10 msgid "" -"The same :code:`Strategy`-customization approach can be used to aggregate" -" custom evaluation results coming from individual clients. Clients can " -"return custom metrics to the server by returning a dictionary:" +"The same :code:`Strategy`-customization approach can be used to aggregate " +"custom evaluation results coming from individual clients. Clients can return " +"custom metrics to the server by returning a dictionary:" msgstr "" +"同样的 :code:`Strategy` 定制方法也可用于汇总来自单个客户端的自定义评估结果。" +"客户端可以通过返回字典的方式向服务器返回自定义指标:" #: ../../source/how-to-aggregate-evaluation-results.rst:36 msgid "" "The server can then use a customized strategy to aggregate the metrics " "provided in these dictionaries:" -msgstr "" +msgstr "然后,服务器可以使用定制的策略来汇总这些字典中提供的指标:" #: ../../source/how-to-configure-clients.rst:2 msgid "Configure clients" -msgstr "" +msgstr "配置客户端" #: ../../source/how-to-configure-clients.rst:4 msgid "" "Along with model parameters, Flower can send configuration values to " -"clients. Configuration values can be used for various purposes. They are," -" for example, a popular way to control client-side hyperparameters from " -"the server." +"clients. Configuration values can be used for various purposes. They are, " +"for example, a popular way to control client-side hyperparameters from the " +"server." msgstr "" +"除了模型参数,Flower 还可以向客户端发送配置值。配置值有多种用途。例如,它们是" +"一种从服务器控制客户端超参数的常用方法。" #: ../../source/how-to-configure-clients.rst:7 msgid "Configuration values" -msgstr "" +msgstr "配置值" #: ../../source/how-to-configure-clients.rst:9 msgid "" -"Configuration values are represented as a dictionary with ``str`` keys " -"and values of type ``bool``, ``bytes``, ``double`` (64-bit precision " -"float), ``int``, or ``str`` (or equivalent types in different languages)." -" Here is an example of a configuration dictionary in Python:" +"Configuration values are represented as a dictionary with ``str`` keys and " +"values of type ``bool``, ``bytes``, ``double`` (64-bit precision float), " +"``int``, or ``str`` (or equivalent types in different languages). Here is an " +"example of a configuration dictionary in Python:" msgstr "" +"配置值以字典的形式表示,字典的键为 ``str``,值的类型为 ``bool``、``bytes``、" +"``double``(64 位精度浮点型)、``int``或 ``str`(或不同语言中的等效类型)。下" +"面是一个 Python 配置字典的示例:" #: ../../source/how-to-configure-clients.rst:20 msgid "" "Flower serializes these configuration dictionaries (or *config dict* for " -"short) to their ProtoBuf representation, transports them to the client " -"using gRPC, and then deserializes them back to Python dictionaries." +"short) to their ProtoBuf representation, transports them to the client using " +"gRPC, and then deserializes them back to Python dictionaries." msgstr "" +"Flower 将这些配置字典(简称 *config dict*)序列化为 ProtoBuf 表示形式,使用 " +"gRPC 将其传输到客户端,然后再反序列化为 Python 字典。" #: ../../source/how-to-configure-clients.rst:24 msgid "" -"Currently, there is no support for directly sending collection types " -"(e.g., ``Set``, ``List``, ``Map``) as values in configuration " -"dictionaries. There are several workarounds to send collections as values" -" by converting them to one of the supported value types (and converting " -"them back on the client-side)." +"Currently, there is no support for directly sending collection types (e.g., " +"``Set``, ``List``, ``Map``) as values in configuration dictionaries. There " +"are several workarounds to send collections as values by converting them to " +"one of the supported value types (and converting them back on the client-" +"side)." msgstr "" +"目前,还不支持在配置字典中直接发送作为值的集合类型(例如,`Set``, `List`, " +"`Map``)。有几种变通方法可将集合转换为受支持的值类型之一(并在客户端将其转换" +"回),从而将集合作为值发送。" #: ../../source/how-to-configure-clients.rst:26 msgid "" "One can, for example, convert a list of floating-point numbers to a JSON " -"string, then send the JSON string using the configuration dictionary, and" -" then convert the JSON string back to a list of floating-point numbers on" -" the client." +"string, then send the JSON string using the configuration dictionary, and " +"then convert the JSON string back to a list of floating-point numbers on the " +"client." msgstr "" +"例如,可以将浮点数列表转换为 JSON 字符串,然后使用配置字典发送 JSON 字符串," +"再在客户端将 JSON 字符串转换回浮点数列表。" #: ../../source/how-to-configure-clients.rst:30 msgid "Configuration through built-in strategies" -msgstr "" +msgstr "通过内置策略进行配置" #: ../../source/how-to-configure-clients.rst:32 msgid "" -"The easiest way to send configuration values to clients is to use a " -"built-in strategy like :code:`FedAvg`. Built-in strategies support so-" -"called configuration functions. A configuration function is a function " -"that the built-in strategy calls to get the configuration dictionary for " -"the current round. It then forwards the configuration dictionary to all " -"the clients selected during that round." +"The easiest way to send configuration values to clients is to use a built-in " +"strategy like :code:`FedAvg`. Built-in strategies support so-called " +"configuration functions. A configuration function is a function that the " +"built-in strategy calls to get the configuration dictionary for the current " +"round. It then forwards the configuration dictionary to all the clients " +"selected during that round." msgstr "" +"向客户端发送配置值的最简单方法是使用内置策略,如 :code:`FedAvg`。内置策略支持" +"所谓的配置函数。配置函数是内置策略调用的函数,用于获取当前回合的配置字典。然" +"后,它会将配置字典转发给该轮中选择的所有客户端。" #: ../../source/how-to-configure-clients.rst:34 msgid "" "Let's start with a simple example. Imagine we want to send (a) the batch " -"size that the client should use, (b) the current global round of " -"federated learning, and (c) the number of epochs to train on the client-" -"side. Our configuration function could look like this:" +"size that the client should use, (b) the current global round of federated " +"learning, and (c) the number of epochs to train on the client-side. Our " +"configuration function could look like this:" msgstr "" +"让我们从一个简单的例子开始。想象一下,我们想要发送(a)客户端应该使用的批次大" +"小,(b)当前联合学习的全局轮次,以及(c)客户端训练的历元数。我们的配置函数" +"可以是这样的:" #: ../../source/how-to-configure-clients.rst:47 msgid "" "To make the built-in strategies use this function, we can pass it to " -"``FedAvg`` during initialization using the parameter " -":code:`on_fit_config_fn`:" +"``FedAvg`` during initialization using the parameter :code:" +"`on_fit_config_fn`:" msgstr "" +"为了让内置策略使用这个函数,我们可以在初始化时使用参数 :code:" +"`on_fit_config_fn` 将它传递给 ``FedAvg`` :" #: ../../source/how-to-configure-clients.rst:56 -msgid "One the client side, we receive the configuration dictionary in ``fit``:" -msgstr "" +msgid "" +"One the client side, we receive the configuration dictionary in ``fit``:" +msgstr "在客户端,我们在 ``fit`` 中接收配置字典:" #: ../../source/how-to-configure-clients.rst:67 msgid "" "There is also an `on_evaluate_config_fn` to configure evaluation, which " -"works the same way. They are separate functions because one might want to" -" send different configuration values to `evaluate` (for example, to use a" -" different batch size)." +"works the same way. They are separate functions because one might want to " +"send different configuration values to `evaluate` (for example, to use a " +"different batch size)." msgstr "" +"还有一个 `on_evaluate_config_fn` 用于配置评估,其工作方式相同。它们是不同的函" +"数,因为可能需要向 `evaluate` 发送不同的配置值(例如,使用不同的批量大小)。" #: ../../source/how-to-configure-clients.rst:69 msgid "" -"The built-in strategies call this function every round (that is, every " -"time `Strategy.configure_fit` or `Strategy.configure_evaluate` runs). " -"Calling `on_evaluate_config_fn` every round allows us to vary/change the " -"config dict over consecutive rounds. If we wanted to implement a " -"hyperparameter schedule, for example, to increase the number of local " -"epochs during later rounds, we could do the following:" +"The built-in strategies call this function every round (that is, every time " +"`Strategy.configure_fit` or `Strategy.configure_evaluate` runs). Calling " +"`on_evaluate_config_fn` every round allows us to vary/change the config dict " +"over consecutive rounds. If we wanted to implement a hyperparameter " +"schedule, for example, to increase the number of local epochs during later " +"rounds, we could do the following:" msgstr "" +"内置策略每轮(即每次运行 `Strategy.configure_fit` 或 `Strategy." +"configure_evaluate` 时)都会调用此函数。每轮调用 `on_evaluate_config_fn` 允许" +"我们在连续几轮中改变配置指令。例如,如果我们想实现一个超参数时间表,以增加后" +"几轮的本地历时次数,我们可以这样做:" #: ../../source/how-to-configure-clients.rst:82 msgid "The :code:`FedAvg` strategy will call this function *every round*." -msgstr "" +msgstr "代码:`FedAvg`策略每轮*都会调用该函数。" #: ../../source/how-to-configure-clients.rst:85 msgid "Configuring individual clients" -msgstr "" +msgstr "配置个人客户" #: ../../source/how-to-configure-clients.rst:87 msgid "" "In some cases, it is necessary to send different configuration values to " "different clients." -msgstr "" +msgstr "在某些情况下,有必要向不同的客户端发送不同的配置值。" #: ../../source/how-to-configure-clients.rst:89 msgid "" -"This can be achieved by customizing an existing strategy or by " -"`implementing a custom strategy from scratch " -"`_. " -"Here's a nonsensical example that customizes :code:`FedAvg` by adding a " -"custom ``\"hello\": \"world\"`` configuration key/value pair to the " -"config dict of a *single client* (only the first client in the list, the " -"other clients in this round to not receive this \"special\" config " -"value):" +"This can be achieved by customizing an existing strategy or by `implementing " +"a custom strategy from scratch `_. Here's a nonsensical example that customizes :" +"code:`FedAvg` by adding a custom ``\"hello\": \"world\"`` configuration key/" +"value pair to the config dict of a *single client* (only the first client in " +"the list, the other clients in this round to not receive this \"special\" " +"config value):" msgstr "" +"这可以通过定制现有策略或 \"从头开始实施一个定制策略 `_\"来实现。下面是一个无厘头的例" +"子,它通过在*单个客户端的配置指令(config dict)中添加自定义的``\"hello\": " +"\"world\"``配置键/值对添加到*单个客户端*(仅列表中的第一个客户端,本轮中的其" +"他客户端不会收到此 \"特殊 \"配置值)的配置 dict 中:" #: ../../source/how-to-configure-logging.rst:2 msgid "Configure logging" -msgstr "" +msgstr "配置日志记录" #: ../../source/how-to-configure-logging.rst:4 msgid "" "The Flower logger keeps track of all core events that take place in " -"federated learning workloads. It presents information by default " -"following a standard message format:" +"federated learning workloads. It presents information by default following a " +"standard message format:" msgstr "" +"Flower 日志记录器会跟踪联合学习工作负载中发生的所有核心事件。它默认按照标准信" +"息格式提供信息:" #: ../../source/how-to-configure-logging.rst:13 msgid "" -"containing relevant information including: log message level (e.g. " -":code:`INFO`, :code:`DEBUG`), a timestamp, the line where the logging " -"took place from, as well as the log message itself. In this way, the " -"logger would typically display information on your terminal as follows:" +"containing relevant information including: log message level (e.g. :code:" +"`INFO`, :code:`DEBUG`), a timestamp, the line where the logging took place " +"from, as well as the log message itself. In this way, the logger would " +"typically display information on your terminal as follows:" msgstr "" +"包含的相关信息包括:日志信息级别(例如 :code:`INFO`、:code:`DEBUG`)、时间" +"戳、日志记录的行以及日志信息本身。这样,日志记录器通常会在终端上显示如下信" +"息:" #: ../../source/how-to-configure-logging.rst:34 msgid "Saving log to file" -msgstr "" +msgstr "将日志保存到文件" #: ../../source/how-to-configure-logging.rst:36 msgid "" "By default, the Flower log is outputted to the terminal where you launch " "your Federated Learning workload from. This applies for both gRPC-based " -"federation (i.e. when you do :code:`fl.server.start_server`) and when " -"using the :code:`VirtualClientEngine` (i.e. when you do " -":code:`fl.simulation.start_simulation`). In some situations you might " -"want to save this log to disk. You can do so by calling the " -"`fl.common.logger.configure() " -"`_" -" function. For example:" -msgstr "" +"federation (i.e. when you do :code:`fl.server.start_server`) and when using " +"the :code:`VirtualClientEngine` (i.e. when you do :code:`fl.simulation." +"start_simulation`). In some situations you might want to save this log to " +"disk. You can do so by calling the `fl.common.logger.configure() `_ function. " +"For example:" +msgstr "" +"默认情况下,Flower 日志会输出到启动联合学习工作负载的终端。这既适用于基于 " +"gRPC 的联合(即执行 :code:`fl.server.start_server` 时),也适用于使用 :code:" +"`VirtualClientEngine` 时(即执行 :code:`fl.simulation.start_simulation` " +"时)。在某些情况下,您可能希望将此日志保存到磁盘。为此,您可以调用 `fl." +"common.logger.configure() `_ 函数。例如:" #: ../../source/how-to-configure-logging.rst:53 msgid "" -"With the above, Flower will record the log you see on your terminal to " -":code:`log.txt`. This file will be created in the same directory as were " -"you are running the code from. If we inspect we see the log above is also" -" recorded but prefixing with :code:`identifier` each line:" +"With the above, Flower will record the log you see on your terminal to :code:" +"`log.txt`. This file will be created in the same directory as were you are " +"running the code from. If we inspect we see the log above is also recorded " +"but prefixing with :code:`identifier` each line:" msgstr "" +"通过上述操作,Flower 会将您在终端上看到的日志记录到 :code:`log.txt`。该文件将" +"创建在运行代码的同一目录下。如果我们检查一下,就会发现上面的日志也被记录了下" +"来,但每一行都以 :code:`identifier` 作为前缀:" #: ../../source/how-to-configure-logging.rst:74 msgid "Log your own messages" -msgstr "" +msgstr "记录自己的信息" #: ../../source/how-to-configure-logging.rst:76 msgid "" -"You might expand the information shown by default with the Flower logger " -"by adding more messages relevant to your application. You can achieve " -"this easily as follows." +"You might expand the information shown by default with the Flower logger by " +"adding more messages relevant to your application. You can achieve this " +"easily as follows." msgstr "" +"您可以通过添加更多与应用程序相关的信息来扩展 Flower 日志记录器默认显示的信" +"息。您可以通过以下方法轻松实现这一目标。" #: ../../source/how-to-configure-logging.rst:102 msgid "" -"In this way your logger will show, in addition to the default messages, " -"the ones introduced by the clients as specified above." +"In this way your logger will show, in addition to the default messages, the " +"ones introduced by the clients as specified above." msgstr "" +"这样,除默认信息外,您的日志记录器还将显示由客户引入的信息,如上文所述。" #: ../../source/how-to-configure-logging.rst:128 msgid "Log to a remote service" -msgstr "" +msgstr "登录远程服务" #: ../../source/how-to-configure-logging.rst:130 msgid "" -"The :code:`fl.common.logger.configure` function, also allows specifying a" -" host to which logs can be pushed (via :code:`POST`) through a native " -"Python :code:`logging.handler.HTTPHandler`. This is a particularly useful" -" feature in :code:`gRPC`-based Federated Learning workloads where " -"otherwise gathering logs from all entities (i.e. the server and the " -"clients) might be cumbersome. Note that in Flower simulation, the server " -"automatically displays all logs. You can still specify a " -":code:`HTTPHandler` should you whish to backup or analyze the logs " -"somewhere else." -msgstr "" +"The :code:`fl.common.logger.configure` function, also allows specifying a " +"host to which logs can be pushed (via :code:`POST`) through a native Python :" +"code:`logging.handler.HTTPHandler`. This is a particularly useful feature " +"in :code:`gRPC`-based Federated Learning workloads where otherwise gathering " +"logs from all entities (i.e. the server and the clients) might be " +"cumbersome. Note that in Flower simulation, the server automatically " +"displays all logs. You can still specify a :code:`HTTPHandler` should you " +"whish to backup or analyze the logs somewhere else." +msgstr "" +"此外,:code:`fl.common.logger.configure`函数还允许指定主机,通过本地 Python :" +"code:`logging.handler.HTTPHandler`,向该主机推送日志(通过 :code:`POST`)。在" +"基于 :code:`gRPC` 的联合学习工作负载中,这是一个特别有用的功能,否则从所有实" +"体(即服务器和客户端)收集日志可能会很麻烦。请注意,在 Flower 模拟中,服务器" +"会自动显示所有日志。如果希望在其他地方备份或分析日志,仍可指定 :code:" +"`HTTPHandler`。" #: ../../source/how-to-enable-ssl-connections.rst:2 msgid "Enable SSL connections" -msgstr "" +msgstr "启用 SSL 连接" #: ../../source/how-to-enable-ssl-connections.rst:4 msgid "" "This guide describes how to a SSL-enabled secure Flower server can be " "started and how a Flower client can establish a secure connections to it." msgstr "" +"本指南介绍如何启动启用 SSL 的安全 Flower 服务器,以及 Flower 客户端如何与其建" +"立安全连接。" #: ../../source/how-to-enable-ssl-connections.rst:7 msgid "" -"A complete code example demonstrating a secure connection can be found " -"`here `_." +"A complete code example demonstrating a secure connection can be found `here " +"`_." msgstr "" +"有关安全连接的完整代码示例,请参见 `_ 。" #: ../../source/how-to-enable-ssl-connections.rst:10 msgid "" -"The code example comes with a README.md file which will explain how to " -"start it. Although it is already SSL-enabled, it might be less " -"descriptive on how. Stick to this guide for a deeper introduction to the " -"topic." +"The code example comes with a README.md file which will explain how to start " +"it. Although it is already SSL-enabled, it might be less descriptive on how. " +"Stick to this guide for a deeper introduction to the topic." msgstr "" +"代码示例附带的 README.md 文件将解释如何启动它。虽然它已经启用了 SSL,但对如何" +"启用可能描述较少。请参考本指南,了解更深入的相关介绍。" #: ../../source/how-to-enable-ssl-connections.rst:16 msgid "Certificates" -msgstr "" +msgstr "证书" #: ../../source/how-to-enable-ssl-connections.rst:18 msgid "" "Using SSL-enabled connections requires certificates to be passed to the " -"server and client. For the purpose of this guide we are going to generate" -" self-signed certificates. As this can become quite complex we are going " -"to ask you to run the script in :code:`examples/advanced-" -"tensorflow/certificates/generate.sh`" +"server and client. For the purpose of this guide we are going to generate " +"self-signed certificates. As this can become quite complex we are going to " +"ask you to run the script in :code:`examples/advanced-tensorflow/" +"certificates/generate.sh`" msgstr "" +"使用支持 SSL 的连接需要向服务器和客户端传递证书。在本指南中,我们将生成自签名" +"证书。由于这可能会变得相当复杂,我们将要求你运行 :code:`examples/advanced-" +"tensorflow/certificates/generate.sh` 中的脚本" #: ../../source/how-to-enable-ssl-connections.rst:23 msgid "with the following command sequence:" -msgstr "" +msgstr "使用以下命令序列:" #: ../../source/how-to-enable-ssl-connections.rst:30 msgid "" -"This will generate the certificates in :code:`examples/advanced-" -"tensorflow/.cache/certificates`." +"This will generate the certificates in :code:`examples/advanced-tensorflow/." +"cache/certificates`." msgstr "" +"这将在 :code:`examples/advanced-tensorflow/.cache/certificates` 中生成证书。" #: ../../source/how-to-enable-ssl-connections.rst:32 msgid "" @@ -4006,185 +4720,215 @@ msgid "" "regarding the issue of correctly generating certificates for production " "environments." msgstr "" +"本示例中生成 SSL 证书的方法可作为一种启发和起点,但不应被视为生产环境的完整方" +"法。有关在生产环境中正确生成证书的问题,请参考其他资料。" #: ../../source/how-to-enable-ssl-connections.rst:36 msgid "" -"In case you are a researcher you might be just fine using the self-signed" -" certificates generated using the scripts which are part of this guide." -msgstr "" +"In case you are a researcher you might be just fine using the self-signed " +"certificates generated using the scripts which are part of this guide." +msgstr "如果你是一名研究人员,使用本指南中的脚本生成的自签名证书就可以了。" #: ../../source/how-to-enable-ssl-connections.rst:41 msgid "Server" -msgstr "" +msgstr "服务器" #: ../../source/how-to-enable-ssl-connections.rst:43 msgid "" "We are now going to show how to write a sever which uses the previously " "generated scripts." -msgstr "" +msgstr "现在,我们将展示如何编写一个使用先前生成的脚本的 sever。" #: ../../source/how-to-enable-ssl-connections.rst:61 msgid "" "When providing certificates, the server expects a tuple of three " -"certificates. :code:`Path` can be used to easily read the contents of " -"those files into byte strings, which is the data type " -":code:`start_server` expects." +"certificates. :code:`Path` can be used to easily read the contents of those " +"files into byte strings, which is the data type :code:`start_server` expects." msgstr "" +"在提供证书时,服务器希望得到由三个证书组成的元组。 :code:`Path` 可用于轻松地" +"将这些文件的内容读取为字节字符串,这就是 :code:`start_server` 期望的数据类" +"型。" #: ../../source/how-to-enable-ssl-connections.rst:65 #: ../../source/how-to-upgrade-to-flower-1.0.rst:37 #: ../../source/ref-api-flwr.rst:15 msgid "Client" -msgstr "" +msgstr "客户端" #: ../../source/how-to-enable-ssl-connections.rst:67 msgid "" "We are now going to show how to write a client which uses the previously " "generated scripts:" -msgstr "" +msgstr "现在我们将演示如何编写一个客户端,使用之前生成的脚本:" #: ../../source/how-to-enable-ssl-connections.rst:84 msgid "" -"When setting :code:`root_certificates`, the client expects the PEM-" -"encoded root certificates as a byte string. We are again using " -":code:`Path` to simplify reading those as byte strings." +"When setting :code:`root_certificates`, the client expects the PEM-encoded " +"root certificates as a byte string. We are again using :code:`Path` to " +"simplify reading those as byte strings." msgstr "" +"当设置 :code:`root_certificates` 时,客户端希望 PEM 编码的根证书是字节字符" +"串。我们再次使用 :code:`Path` 来简化以字节字符串形式读取证书的过程。" #: ../../source/how-to-enable-ssl-connections.rst:89 #: ../../source/tutorial-series-what-is-federated-learning.ipynb:287 msgid "Conclusion" -msgstr "" +msgstr "结论" #: ../../source/how-to-enable-ssl-connections.rst:91 msgid "" -"You should now have learned how to generate self-signed certificates " -"using the given script, start a SSL-enabled server, and have a client " -"establish a secure connection to it." +"You should now have learned how to generate self-signed certificates using " +"the given script, start a SSL-enabled server, and have a client establish a " +"secure connection to it." msgstr "" +"现在,你应该已经学会了如何使用给定的脚本生成自签名证书、启动启用 SSL 的服务器" +"并让客户端与其建立安全连接。" #: ../../source/how-to-enable-ssl-connections.rst:96 msgid "Additional resources" -msgstr "" +msgstr "补充资源" #: ../../source/how-to-enable-ssl-connections.rst:98 msgid "" -"These additional sources might be relevant if you would like to dive " -"deeper into the topic of certificates:" -msgstr "" +"These additional sources might be relevant if you would like to dive deeper " +"into the topic of certificates:" +msgstr "如果您想更深入地了解证书主题,这些额外的资料来源可能与您相关:" #: ../../source/how-to-enable-ssl-connections.rst:100 msgid "`Let's Encrypt `_" -msgstr "" +msgstr "让我们加密 `_" #: ../../source/how-to-enable-ssl-connections.rst:101 msgid "`certbot `_" -msgstr "" +msgstr "`certbot `_" #: ../../source/how-to-implement-strategies.rst:2 msgid "Implement strategies" -msgstr "" +msgstr "实施策略" #: ../../source/how-to-implement-strategies.rst:4 msgid "" -"The strategy abstraction enables implementation of fully custom " -"strategies. A strategy is basically the federated learning algorithm that" -" runs on the server. Strategies decide how to sample clients, how to " -"configure clients for training, how to aggregate updates, and how to " -"evaluate models. Flower provides a few built-in strategies which are " -"based on the same API described below." +"The strategy abstraction enables implementation of fully custom strategies. " +"A strategy is basically the federated learning algorithm that runs on the " +"server. Strategies decide how to sample clients, how to configure clients " +"for training, how to aggregate updates, and how to evaluate models. Flower " +"provides a few built-in strategies which are based on the same API described " +"below." msgstr "" +"策略抽象可以实现完全定制的策略。策略基本上就是在服务器上运行的联合学习算法。" +"策略决定如何对客户端进行采样、如何配置客户端进行训练、如何聚合更新以及如何评" +"估模型。Flower 提供了一些内置策略,这些策略基于下文所述的相同 API。" #: ../../source/how-to-implement-strategies.rst:11 msgid "The :code:`Strategy` abstraction" -msgstr "" +msgstr "代码:\"策略 \"抽象" #: ../../source/how-to-implement-strategies.rst:13 msgid "" -"All strategy implementation are derived from the abstract base class " -":code:`flwr.server.strategy.Strategy`, both built-in implementations and " -"third party implementations. This means that custom strategy " -"implementations have the exact same capabilities at their disposal as " -"built-in ones." +"All strategy implementation are derived from the abstract base class :code:" +"`flwr.server.strategy.Strategy`, both built-in implementations and third " +"party implementations. This means that custom strategy implementations have " +"the exact same capabilities at their disposal as built-in ones." msgstr "" +"所有策略实现均源自抽象基类 :code:`flwr.server.strategy.Strategy`,包括内置实" +"现和第三方实现。这意味着自定义策略实现与内置实现具有完全相同的功能。" #: ../../source/how-to-implement-strategies.rst:18 msgid "" "The strategy abstraction defines a few abstract methods that need to be " "implemented:" -msgstr "" +msgstr "策略抽象定义了一些需要实现的抽象方法:" #: ../../source/how-to-implement-strategies.rst:75 msgid "" -"Creating a new strategy means implementing a new :code:`class` (derived " -"from the abstract base class :code:`Strategy`) that implements for the " -"previously shown abstract methods:" +"Creating a new strategy means implementing a new :code:`class` (derived from " +"the abstract base class :code:`Strategy`) that implements for the previously " +"shown abstract methods:" msgstr "" +"创建一个新策略意味着要实现一个新的 :code:`class`(从抽象基类 :code:" +"`Strategy` 派生),该类要实现前面显示的抽象方法:" #: ../../source/how-to-implement-strategies.rst:100 msgid "The Flower server calls these methods in the following order:" -msgstr "" +msgstr "Flower 服务器按以下顺序调用这些方法:" #: ../../source/how-to-implement-strategies.rst:177 msgid "The following sections describe each of those methods in more detail." -msgstr "" +msgstr "下文将详细介绍每种方法。" #: ../../source/how-to-implement-strategies.rst:180 msgid "The :code:`initialize_parameters` method" -msgstr "" +msgstr "代码: \"初始化参数 \"方法" #: ../../source/how-to-implement-strategies.rst:182 msgid "" -":code:`initialize_parameters` is called only once, at the very beginning " -"of an execution. It is responsible for providing the initial global model" -" parameters in a serialized form (i.e., as a :code:`Parameters` object)." +":code:`initialize_parameters` is called only once, at the very beginning of " +"an execution. It is responsible for providing the initial global model " +"parameters in a serialized form (i.e., as a :code:`Parameters` object)." msgstr "" +":code:`initialize_parameters` 只调用一次,即在执行开始时。它负责以序列化形式" +"(即 :code:`Parameters` 对象)提供初始全局模型参数。" #: ../../source/how-to-implement-strategies.rst:184 msgid "" -"Built-in strategies return user-provided initial parameters. The " -"following example shows how initial parameters can be passed to " -":code:`FedAvg`:" +"Built-in strategies return user-provided initial parameters. The following " +"example shows how initial parameters can be passed to :code:`FedAvg`:" msgstr "" +"内置策略会返回用户提供的初始参数。下面的示例展示了如何将初始参数传递给 :code:" +"`FedAvg`:" #: ../../source/how-to-implement-strategies.rst:209 msgid "" "The Flower server will call :code:`initialize_parameters`, which either " -"returns the parameters that were passed to :code:`initial_parameters`, or" -" :code:`None`. If no parameters are returned from " -":code:`initialize_parameters` (i.e., :code:`None`), the server will " -"randomly select one client and ask it to provide its parameters. This is " -"a convenience feature and not recommended in practice, but it can be " -"useful for prototyping. In practice, it is recommended to always use " -"server-side parameter initialization." -msgstr "" +"returns the parameters that were passed to :code:`initial_parameters`, or :" +"code:`None`. If no parameters are returned from :code:" +"`initialize_parameters` (i.e., :code:`None`), the server will randomly " +"select one client and ask it to provide its parameters. This is a " +"convenience feature and not recommended in practice, but it can be useful " +"for prototyping. In practice, it is recommended to always use server-side " +"parameter initialization." +msgstr "" +"Flower 服务器将调用 :code:`initialize_parameters`,返回传给 :code:" +"`initial_parameters` 的参数或 :code:`None`。如果 :code:" +"`initialize_parameters` 没有返回任何参数(即 :code:`None`),服务器将随机选择" +"一个客户端并要求其提供参数。这只是一个方便的功能,在实际应用中并不推荐使用," +"但在原型开发中可能很有用。在实践中,建议始终使用服务器端参数初始化。" #: ../../source/how-to-implement-strategies.rst:213 msgid "" "Server-side parameter initialization is a powerful mechanism. It can be " -"used, for example, to resume training from a previously saved checkpoint." -" It is also the fundamental capability needed to implement hybrid " -"approaches, for example, to fine-tune a pre-trained model using federated" -" learning." +"used, for example, to resume training from a previously saved checkpoint. It " +"is also the fundamental capability needed to implement hybrid approaches, " +"for example, to fine-tune a pre-trained model using federated learning." msgstr "" +"服务器端参数初始化是一种强大的机制。例如,它可以用来从先前保存的检查点恢复训" +"练。它也是实现混合方法所需的基本能力,例如,使用联合学习对预先训练好的模型进" +"行微调。" #: ../../source/how-to-implement-strategies.rst:216 +#, fuzzy msgid "The :code:`configure_fit` method" -msgstr "" +msgstr "代码:`configure_fit`方法" #: ../../source/how-to-implement-strategies.rst:218 msgid "" -":code:`configure_fit` is responsible for configuring the upcoming round " -"of training. What does *configure* mean in this context? Configuring a " -"round means selecting clients and deciding what instructions to send to " -"these clients. The signature of :code:`configure_fit` makes this clear:" +":code:`configure_fit` is responsible for configuring the upcoming round of " +"training. What does *configure* mean in this context? Configuring a round " +"means selecting clients and deciding what instructions to send to these " +"clients. The signature of :code:`configure_fit` makes this clear:" msgstr "" +":code:`configure_fit` 负责配置即将开始的一轮训练。配置*在这里是什么意思?配置" +"一轮训练意味着选择客户并决定向这些客户发送什么指令。:code:`configure_fit` 的" +"签名说明了这一点:" #: ../../source/how-to-implement-strategies.rst:231 msgid "" "The return value is a list of tuples, each representing the instructions " -"that will be sent to a particular client. Strategy implementations " -"usually perform the following steps in :code:`configure_fit`:" +"that will be sent to a particular client. Strategy implementations usually " +"perform the following steps in :code:`configure_fit`:" msgstr "" +"返回值是一个元组列表,每个元组代表将发送到特定客户端的指令。策略实现通常在 :" +"code:`configure_fit` 中执行以下步骤:" #: ../../source/how-to-implement-strategies.rst:233 #: ../../source/how-to-implement-strategies.rst:280 @@ -4192,342 +4936,405 @@ msgid "" "Use the :code:`client_manager` to randomly sample all (or a subset of) " "available clients (each represented as a :code:`ClientProxy` object)" msgstr "" +"使用 :code:`client_manager` 随机抽样所有(或部分)可用客户端(每个客户端都表" +"示为 :code:`ClientProxy` 对象)" #: ../../source/how-to-implement-strategies.rst:234 msgid "" "Pair each :code:`ClientProxy` with the same :code:`FitIns` holding the " "current global model :code:`parameters` and :code:`config` dict" msgstr "" +"将每个 :code:`ClientProxy` 与持有当前全局模型 :code:`parameters` 和 :code:" +"`config` dict 的 :code:`FitIns` 配对" #: ../../source/how-to-implement-strategies.rst:236 msgid "" "More sophisticated implementations can use :code:`configure_fit` to " -"implement custom client selection logic. A client will only participate " -"in a round if the corresponding :code:`ClientProxy` is included in the " -"the list returned from :code:`configure_fit`." +"implement custom client selection logic. A client will only participate in a " +"round if the corresponding :code:`ClientProxy` is included in the the list " +"returned from :code:`configure_fit`." msgstr "" +"更复杂的实现可以使用 :code:`configure_fit` 来实现自定义的客户端选择逻辑。只有" +"当相应的 :code:`ClientProxy` 包含在 :code:`configure_fit` 返回的列表中时,客" +"户端才会参加比赛。" #: ../../source/how-to-implement-strategies.rst:240 msgid "" "The structure of this return value provides a lot of flexibility to the " "user. Since instructions are defined on a per-client basis, different " -"instructions can be sent to each client. This enables custom strategies " -"to train, for example, different models on different clients, or use " -"different hyperparameters on different clients (via the :code:`config` " -"dict)." +"instructions can be sent to each client. This enables custom strategies to " +"train, for example, different models on different clients, or use different " +"hyperparameters on different clients (via the :code:`config` dict)." msgstr "" +"该返回值的结构为用户提供了很大的灵活性。由于指令是按客户端定义的,因此可以向" +"每个客户端发送不同的指令。这使得自定义策略成为可能,例如在不同的客户端上训练" +"不同的模型,或在不同的客户端上使用不同的超参数(通过 :code:`config` dict)。" #: ../../source/how-to-implement-strategies.rst:243 msgid "The :code:`aggregate_fit` method" -msgstr "" +msgstr ":code:`aggregate_fit` 方法" #: ../../source/how-to-implement-strategies.rst:245 msgid "" -":code:`aggregate_fit` is responsible for aggregating the results returned" -" by the clients that were selected and asked to train in " -":code:`configure_fit`." +":code:`aggregate_fit` is responsible for aggregating the results returned by " +"the clients that were selected and asked to train in :code:`configure_fit`." msgstr "" +":code:`aggregate_fit` 负责汇总在 :code:`configure_fit` 中选择并要求训练的客户" +"端所返回的结果。" #: ../../source/how-to-implement-strategies.rst:258 msgid "" "Of course, failures can happen, so there is no guarantee that the server " -"will get results from all the clients it sent instructions to (via " -":code:`configure_fit`). :code:`aggregate_fit` therefore receives a list " -"of :code:`results`, but also a list of :code:`failures`." +"will get results from all the clients it sent instructions to (via :code:" +"`configure_fit`). :code:`aggregate_fit` therefore receives a list of :code:" +"`results`, but also a list of :code:`failures`." msgstr "" +"当然,失败是有可能发生的,因此无法保证服务器会从它发送指令(通过 :code:" +"`configure_fit`)的所有客户端获得结果。因此 :code:`aggregate_fit` 会收到 :" +"code:`results` 的列表,但也会收到 :code:`failures` 的列表。" #: ../../source/how-to-implement-strategies.rst:260 msgid "" -":code:`aggregate_fit` returns an optional :code:`Parameters` object and a" -" dictionary of aggregated metrics. The :code:`Parameters` return value is" -" optional because :code:`aggregate_fit` might decide that the results " +":code:`aggregate_fit` returns an optional :code:`Parameters` object and a " +"dictionary of aggregated metrics. The :code:`Parameters` return value is " +"optional because :code:`aggregate_fit` might decide that the results " "provided are not sufficient for aggregation (e.g., too many failures)." msgstr "" +":code:`aggregate_fit` 返回一个可选的 :code:`Parameters` 对象和一个聚合度量的" +"字典。:code:`Parameters` 返回值是可选的,因为 :code:`aggregate_fit` 可能会认" +"为所提供的结果不足以进行聚合(例如,失败次数过多)。" #: ../../source/how-to-implement-strategies.rst:263 msgid "The :code:`configure_evaluate` method" -msgstr "" +msgstr "代码:\"配置评估 \"方法" #: ../../source/how-to-implement-strategies.rst:265 msgid "" -":code:`configure_evaluate` is responsible for configuring the upcoming " -"round of evaluation. What does *configure* mean in this context? " -"Configuring a round means selecting clients and deciding what " -"instructions to send to these clients. The signature of " -":code:`configure_evaluate` makes this clear:" +":code:`configure_evaluate` is responsible for configuring the upcoming round " +"of evaluation. What does *configure* mean in this context? Configuring a " +"round means selecting clients and deciding what instructions to send to " +"these clients. The signature of :code:`configure_evaluate` makes this clear:" msgstr "" +":code:`configure_evaluate` 负责配置下一轮评估。配置*在这里是什么意思?配置一" +"轮评估意味着选择客户端并决定向这些客户端发送什么指令。:code:" +"`configure_evaluate` 的签名说明了这一点:" #: ../../source/how-to-implement-strategies.rst:278 msgid "" "The return value is a list of tuples, each representing the instructions " -"that will be sent to a particular client. Strategy implementations " -"usually perform the following steps in :code:`configure_evaluate`:" +"that will be sent to a particular client. Strategy implementations usually " +"perform the following steps in :code:`configure_evaluate`:" msgstr "" +"返回值是一个元组列表,每个元组代表将发送到特定客户端的指令。策略实现通常在 :" +"code:`configure_evaluate` 中执行以下步骤:" #: ../../source/how-to-implement-strategies.rst:281 msgid "" -"Pair each :code:`ClientProxy` with the same :code:`EvaluateIns` holding " -"the current global model :code:`parameters` and :code:`config` dict" +"Pair each :code:`ClientProxy` with the same :code:`EvaluateIns` holding the " +"current global model :code:`parameters` and :code:`config` dict" msgstr "" +"将每个 :code:`ClientProxy` 与持有当前全局模型 :code:`parameters` 和 :code:" +"`config` dict 的 :code:`EvaluateIns` 配对" #: ../../source/how-to-implement-strategies.rst:283 msgid "" "More sophisticated implementations can use :code:`configure_evaluate` to " -"implement custom client selection logic. A client will only participate " -"in a round if the corresponding :code:`ClientProxy` is included in the " -"the list returned from :code:`configure_evaluate`." +"implement custom client selection logic. A client will only participate in a " +"round if the corresponding :code:`ClientProxy` is included in the the list " +"returned from :code:`configure_evaluate`." msgstr "" +"更复杂的实现可以使用 :code:`configure_evaluate` 来实现自定义的客户端选择逻" +"辑。只有当相应的 :code:`ClientProxy` 包含在 :code:`configure_evaluate` 返回的" +"列表中时,客户端才会参与一轮比赛。" #: ../../source/how-to-implement-strategies.rst:287 msgid "" "The structure of this return value provides a lot of flexibility to the " "user. Since instructions are defined on a per-client basis, different " -"instructions can be sent to each client. This enables custom strategies " -"to evaluate, for example, different models on different clients, or use " -"different hyperparameters on different clients (via the :code:`config` " -"dict)." +"instructions can be sent to each client. This enables custom strategies to " +"evaluate, for example, different models on different clients, or use " +"different hyperparameters on different clients (via the :code:`config` dict)." msgstr "" +"该返回值的结构为用户提供了很大的灵活性。由于指令是按客户端定义的,因此可以向" +"每个客户端发送不同的指令。这使得自定义策略可以在不同客户端上评估不同的模型," +"或在不同客户端上使用不同的超参数(通过 :code:`config` dict)。" #: ../../source/how-to-implement-strategies.rst:291 msgid "The :code:`aggregate_evaluate` method" -msgstr "" +msgstr "代码 :`aggregate_evaluate` 方法" #: ../../source/how-to-implement-strategies.rst:293 msgid "" ":code:`aggregate_evaluate` is responsible for aggregating the results " -"returned by the clients that were selected and asked to evaluate in " -":code:`configure_evaluate`." +"returned by the clients that were selected and asked to evaluate in :code:" +"`configure_evaluate`." msgstr "" +":code:`aggregate_evaluate` 负责汇总在 :code:`configure_evaluate` 中选择并要求" +"评估的客户端返回的结果。" #: ../../source/how-to-implement-strategies.rst:306 msgid "" "Of course, failures can happen, so there is no guarantee that the server " -"will get results from all the clients it sent instructions to (via " -":code:`configure_evaluate`). :code:`aggregate_evaluate` therefore " -"receives a list of :code:`results`, but also a list of :code:`failures`." +"will get results from all the clients it sent instructions to (via :code:" +"`configure_evaluate`). :code:`aggregate_evaluate` therefore receives a list " +"of :code:`results`, but also a list of :code:`failures`." msgstr "" +"当然,失败是有可能发生的,因此无法保证服务器会从它发送指令(通过 :code:" +"`configure_evaluate`)的所有客户端获得结果。因此, :code:" +"`aggregate_evaluate` 会接收 :code:`results` 的列表,但也会接收 :code:" +"`failures` 的列表。" #: ../../source/how-to-implement-strategies.rst:308 msgid "" -":code:`aggregate_evaluate` returns an optional :code:`float` (loss) and a" -" dictionary of aggregated metrics. The :code:`float` return value is " -"optional because :code:`aggregate_evaluate` might decide that the results" -" provided are not sufficient for aggregation (e.g., too many failures)." +":code:`aggregate_evaluate` returns an optional :code:`float` (loss) and a " +"dictionary of aggregated metrics. The :code:`float` return value is optional " +"because :code:`aggregate_evaluate` might decide that the results provided " +"are not sufficient for aggregation (e.g., too many failures)." msgstr "" +":code:`aggregate_evaluate` 返回一个可选的 :code:`float`(损失)和一个聚合指标" +"字典。:code:`float` 返回值是可选的,因为 :code:`aggregate_evaluate` 可能会认" +"为所提供的结果不足以进行聚合(例如,失败次数过多)。" #: ../../source/how-to-implement-strategies.rst:311 msgid "The :code:`evaluate` method" -msgstr "" +msgstr "代码:\"评估 \"方法" #: ../../source/how-to-implement-strategies.rst:313 msgid "" ":code:`evaluate` is responsible for evaluating model parameters on the " -"server-side. Having :code:`evaluate` in addition to " -":code:`configure_evaluate`/:code:`aggregate_evaluate` enables strategies " -"to perform both servers-side and client-side (federated) evaluation." +"server-side. Having :code:`evaluate` in addition to :code:" +"`configure_evaluate`/:code:`aggregate_evaluate` enables strategies to " +"perform both servers-side and client-side (federated) evaluation." msgstr "" +":code:`evaluate` 负责在服务器端评估模型参数。除了 :code:" +"`configure_evaluate`/:code:`aggregate_evaluate` 之外,:code:`evaluate` 可以使" +"策略同时执行服务器端和客户端(联合)评估。" #: ../../source/how-to-implement-strategies.rst:323 msgid "" -"The return value is again optional because the strategy might not need to" -" implement server-side evaluation or because the user-defined " -":code:`evaluate` method might not complete successfully (e.g., it might " -"fail to load the server-side evaluation data)." +"The return value is again optional because the strategy might not need to " +"implement server-side evaluation or because the user-defined :code:" +"`evaluate` method might not complete successfully (e.g., it might fail to " +"load the server-side evaluation data)." msgstr "" +"返回值也是可选的,因为策略可能不需要执行服务器端评估,或者因为用户定义的 :" +"code:`evaluate` 方法可能无法成功完成(例如,它可能无法加载服务器端评估数" +"据)。" #: ../../source/how-to-install-flower.rst:2 msgid "Install Flower" -msgstr "" +msgstr "安装Flower" #: ../../source/how-to-install-flower.rst:6 msgid "Python version" -msgstr "" +msgstr "Python 版本" #: ../../source/how-to-install-flower.rst:12 msgid "Install stable release" -msgstr "" +msgstr "安装稳定版" #: ../../source/how-to-install-flower.rst:14 msgid "" -"Stable releases are available on `PyPI " -"`_::" -msgstr "" +"Stable releases are available on `PyPI `_::" +msgstr "稳定版本可在 `PyPI `_::" #: ../../source/how-to-install-flower.rst:18 msgid "" "For simulations that use the Virtual Client Engine, ``flwr`` should be " "installed with the ``simulation`` extra::" msgstr "" +"对于使用虚拟客户端引擎的模拟,`flwr`` 应与`simulation`` 额外:一起安装:" #: ../../source/how-to-install-flower.rst:24 msgid "Verify installation" -msgstr "" +msgstr "验证安装" #: ../../source/how-to-install-flower.rst:26 msgid "" "The following command can be used to verfiy if Flower was successfully " -"installed. If everything worked, it should print the version of Flower to" -" the command line::" +"installed. If everything worked, it should print the version of Flower to " +"the command line::" msgstr "" +"可以使用以下命令来验证 Flower 是否安装成功。如果一切正常,它将在命令行中打印 " +"Flower 的版本::" #: ../../source/how-to-install-flower.rst:33 msgid "Advanced installation options" -msgstr "" +msgstr "高级安装选项" #: ../../source/how-to-install-flower.rst:36 msgid "Install pre-release" -msgstr "" +msgstr "安装预发布版本" #: ../../source/how-to-install-flower.rst:38 msgid "" -"New (possibly unstable) versions of Flower are sometimes available as " -"pre-release versions (alpha, beta, release candidate) before the stable " -"release happens::" +"New (possibly unstable) versions of Flower are sometimes available as pre-" +"release versions (alpha, beta, release candidate) before the stable release " +"happens::" msgstr "" +"在稳定版发布之前,Flower 的新版本(可能是不稳定版)有时会作为预发布版本" +"(alpha、beta、候选发布版本)提供::" #: ../../source/how-to-install-flower.rst:42 msgid "" -"For simulations that use the Virtual Client Engine, ``flwr`` pre-releases" -" should be installed with the ``simulation`` extra::" +"For simulations that use the Virtual Client Engine, ``flwr`` pre-releases " +"should be installed with the ``simulation`` extra::" msgstr "" +"对于使用虚拟客户端引擎的模拟,`flwr``预发行版应与`simulation``额外:一起安" +"装:" #: ../../source/how-to-install-flower.rst:47 msgid "Install nightly release" -msgstr "" +msgstr "安装夜间版本" #: ../../source/how-to-install-flower.rst:49 msgid "" -"The latest (potentially unstable) changes in Flower are available as " -"nightly releases::" -msgstr "" +"The latest (potentially unstable) changes in Flower are available as nightly " +"releases::" +msgstr "Flower 中最新(可能不稳定)的更改以夜间发布的形式提供::" #: ../../source/how-to-install-flower.rst:53 msgid "" -"For simulations that use the Virtual Client Engine, ``flwr-nightly`` " -"should be installed with the ``simulation`` extra::" -msgstr "" +"For simulations that use the Virtual Client Engine, ``flwr-nightly`` should " +"be installed with the ``simulation`` extra::" +msgstr "对于使用虚拟客户端引擎的模拟,`flwr-nightly`应与`simulation`一起安装:" #: ../../source/how-to-monitor-simulation.rst:2 msgid "Monitor simulation" -msgstr "" +msgstr "监控模拟" #: ../../source/how-to-monitor-simulation.rst:4 msgid "" -"Flower allows you to monitor system resources while running your " -"simulation. Moreover, the Flower simulation engine is powerful and " -"enables you to decide how to allocate resources per client manner and " -"constrain the total usage. Insights from resource consumption can help " -"you make smarter decisions and speed up the execution time." +"Flower allows you to monitor system resources while running your simulation. " +"Moreover, the Flower simulation engine is powerful and enables you to decide " +"how to allocate resources per client manner and constrain the total usage. " +"Insights from resource consumption can help you make smarter decisions and " +"speed up the execution time." msgstr "" +"Flower 允许您在运行模拟时监控系统资源。此外,Flower 仿真引擎功能强大,能让您" +"决定如何按客户端方式分配资源并限制总使用量。从资源消耗中获得的洞察力可以帮助" +"您做出更明智的决策,并加快执行时间。" #: ../../source/how-to-monitor-simulation.rst:6 msgid "" -"The specific instructions assume you are using macOS and have the " -"`Homebrew `_ package manager installed." +"The specific instructions assume you are using macOS and have the `Homebrew " +"`_ package manager installed." msgstr "" +"具体说明假定你使用的是 macOS,并且安装了 `Homebrew `_ 软件" +"包管理器。" #: ../../source/how-to-monitor-simulation.rst:10 msgid "Downloads" -msgstr "" +msgstr "下载" #: ../../source/how-to-monitor-simulation.rst:16 msgid "" -"`Prometheus `_ is used for data collection, while" -" `Grafana `_ will enable you to visualize the " -"collected data. They are both well integrated with `Ray " -"`_ which Flower uses under the hood." +"`Prometheus `_ is used for data collection, while " +"`Grafana `_ will enable you to visualize the collected " +"data. They are both well integrated with `Ray `_ which " +"Flower uses under the hood." msgstr "" +"`Prometheus `_ 用于收集数据,而 `Grafana `_ 则能让你将收集到的数据可视化。它们都与 Flower 在引擎盖下使用" +"的 `Ray `_ 紧密集成。" #: ../../source/how-to-monitor-simulation.rst:18 msgid "" "Overwrite the configuration files (depending on your device, it might be " "installed on a different path)." -msgstr "" +msgstr "重写配置文件(根据设备的不同,可能安装在不同的路径上)。" #: ../../source/how-to-monitor-simulation.rst:20 msgid "If you are on an M1 Mac, it should be:" -msgstr "" +msgstr "如果你使用的是 M1 Mac,应该是这样:" #: ../../source/how-to-monitor-simulation.rst:27 msgid "On the previous generation Intel Mac devices, it should be:" -msgstr "" +msgstr "在上一代英特尔 Mac 设备上,应该是这样:" #: ../../source/how-to-monitor-simulation.rst:34 msgid "" -"Open the respective configuration files and change them. Depending on " -"your device, use one of the two following commands:" -msgstr "" +"Open the respective configuration files and change them. Depending on your " +"device, use one of the two following commands:" +msgstr "打开相应的配置文件并修改它们。根据设备情况,使用以下两个命令之一:" #: ../../source/how-to-monitor-simulation.rst:44 msgid "" -"and then delete all the text in the file and paste a new Prometheus " -"config you see below. You may adjust the time intervals to your " -"requirements:" +"and then delete all the text in the file and paste a new Prometheus config " +"you see below. You may adjust the time intervals to your requirements:" msgstr "" +"然后删除文件中的所有文本,粘贴一个新的 Prometheus 配置文件,如下所示。您可以" +"根据需要调整时间间隔:" #: ../../source/how-to-monitor-simulation.rst:59 msgid "" -"Now after you have edited the Prometheus configuration, do the same with " -"the Grafana configuration files. Open those using one of the following " -"commands as before:" +"Now after you have edited the Prometheus configuration, do the same with the " +"Grafana configuration files. Open those using one of the following commands " +"as before:" msgstr "" +"编辑完 Prometheus 配置后,请对 Grafana 配置文件执行同样的操作。与之前一样,使" +"用以下命令之一打开这些文件:" #: ../../source/how-to-monitor-simulation.rst:69 msgid "" "Your terminal editor should open and allow you to apply the following " "configuration as before." -msgstr "" +msgstr "您的终端编辑器应该会打开,并允许您像之前一样应用以下配置。" #: ../../source/how-to-monitor-simulation.rst:84 msgid "" -"Congratulations, you just downloaded all the necessary software needed " -"for metrics tracking. Now, let’s start it." -msgstr "" +"Congratulations, you just downloaded all the necessary software needed for " +"metrics tracking. Now, let’s start it." +msgstr "恭喜您,您刚刚下载了指标跟踪所需的所有软件。现在,让我们开始吧。" #: ../../source/how-to-monitor-simulation.rst:88 msgid "Tracking metrics" -msgstr "" +msgstr "跟踪指标" #: ../../source/how-to-monitor-simulation.rst:90 msgid "" "Before running your Flower simulation, you have to start the monitoring " "tools you have just installed and configured." -msgstr "" +msgstr "在运行 Flower 模拟之前,您必须启动刚刚安装和配置的监控工具。" #: ../../source/how-to-monitor-simulation.rst:97 msgid "" -"Please include the following argument in your Python code when starting a" -" simulation." -msgstr "" +"Please include the following argument in your Python code when starting a " +"simulation." +msgstr "开始模拟时,请在 Python 代码中加入以下参数。" #: ../../source/how-to-monitor-simulation.rst:108 msgid "Now, you are ready to start your workload." -msgstr "" +msgstr "现在,您可以开始工作了。" #: ../../source/how-to-monitor-simulation.rst:110 msgid "" -"Shortly after the simulation starts, you should see the following logs in" -" your terminal:" -msgstr "" +"Shortly after the simulation starts, you should see the following logs in " +"your terminal:" +msgstr "模拟启动后不久,您就会在终端中看到以下日志:" #: ../../source/how-to-monitor-simulation.rst:117 msgid "You can look at everything at ``_ ." -msgstr "" +msgstr "您可以在 ``_ 查看所有内容。" #: ../../source/how-to-monitor-simulation.rst:119 msgid "" -"It's a Ray Dashboard. You can navigate to Metrics (on the left panel, the" -" lowest option)." +"It's a Ray Dashboard. You can navigate to Metrics (on the left panel, the " +"lowest option)." msgstr "" +"这是一个 Ray Dashboard。您可以导航到 \"度量标准\"(左侧面板,最低选项)。" #: ../../source/how-to-monitor-simulation.rst:121 msgid "" -"Or alternatively, you can just see them in Grafana by clicking on the " -"right-up corner, “View in Grafana”. Please note that the Ray dashboard is" -" only accessible during the simulation. After the simulation ends, you " -"can only use Grafana to explore the metrics. You can start Grafana by " -"going to ``http://localhost:3000/``." +"Or alternatively, you can just see them in Grafana by clicking on the right-" +"up corner, “View in Grafana”. Please note that the Ray dashboard is only " +"accessible during the simulation. After the simulation ends, you can only " +"use Grafana to explore the metrics. You can start Grafana by going to " +"``http://localhost:3000/``." msgstr "" +"或者,您也可以点击右上角的 \"在 Grafana 中查看\",在 Grafana 中查看它们。请注" +"意,Ray 仪表盘只能在模拟期间访问。模拟结束后,您只能使用 Grafana 浏览指标。您" +"可以访问 ``http://localhost:3000/``启动 Grafana。" #: ../../source/how-to-monitor-simulation.rst:123 msgid "" @@ -4535,427 +5342,525 @@ msgid "" "important as they will otherwise block, for example port :code:`3000` on " "your machine as long as they are running." msgstr "" +"完成可视化后,请停止 Prometheus 和 Grafana。这一点很重要,否则只要它们在运" +"行,就会阻塞机器上的端口 :code:`3000`。" #: ../../source/how-to-monitor-simulation.rst:132 msgid "Resource allocation" -msgstr "" +msgstr "资源分配" #: ../../source/how-to-monitor-simulation.rst:134 msgid "" -"You must understand how the Ray library works to efficiently allocate " -"system resources to simulation clients on your own." +"You must understand how the Ray library works to efficiently allocate system " +"resources to simulation clients on your own." msgstr "" +"您必须了解 Ray 库是如何工作的,才能有效地为自己的仿真客户端分配系统资源。" #: ../../source/how-to-monitor-simulation.rst:136 msgid "" "Initially, the simulation (which Ray handles under the hood) starts by " "default with all the available resources on the system, which it shares " -"among the clients. It doesn't mean it divides it equally among all of " -"them, nor that the model training happens at all of them simultaneously. " -"You will learn more about that in the later part of this blog. You can " -"check the system resources by running the following:" +"among the clients. It doesn't mean it divides it equally among all of them, " +"nor that the model training happens at all of them simultaneously. You will " +"learn more about that in the later part of this blog. You can check the " +"system resources by running the following:" msgstr "" +"最初,模拟(由 Ray 在引擎盖下处理)默认使用系统上的所有可用资源启动,并在客户" +"端之间共享。但这并不意味着它会将资源平均分配给所有客户端,也不意味着模型训练" +"会在所有客户端同时进行。您将在本博客的后半部分了解到更多相关信息。您可以运行" +"以下命令检查系统资源:" #: ../../source/how-to-monitor-simulation.rst:143 msgid "In Google Colab, the result you see might be similar to this:" -msgstr "" +msgstr "在 Google Colab 中,您看到的结果可能与此类似:" #: ../../source/how-to-monitor-simulation.rst:155 msgid "" -"However, you can overwrite the defaults. When starting a simulation, do " -"the following (you don't need to overwrite all of them):" -msgstr "" +"However, you can overwrite the defaults. When starting a simulation, do the " +"following (you don't need to overwrite all of them):" +msgstr "不过,您可以覆盖默认值。开始模拟时,请执行以下操作(不必全部覆盖):" #: ../../source/how-to-monitor-simulation.rst:175 msgid "Let’s also specify the resource for a single client." -msgstr "" +msgstr "我们还可以为单个客户指定资源。" #: ../../source/how-to-monitor-simulation.rst:205 msgid "" -"Now comes the crucial part. Ray will start a new client only when it has " -"all the required resources (such that they run in parallel) when the " -"resources allow." +"Now comes the crucial part. Ray will start a new client only when it has all " +"the required resources (such that they run in parallel) when the resources " +"allow." msgstr "" +"现在到了关键部分。只有在资源允许的情况下,Ray 才会在拥有所有所需资源(如并行" +"运行)时启动新客户端。" #: ../../source/how-to-monitor-simulation.rst:207 msgid "" -"In the example above, only one client will be run, so your clients won't " -"run concurrently. Setting :code:`client_num_gpus = 0.5` would allow " -"running two clients and therefore enable them to run concurrently. Be " -"careful not to require more resources than available. If you specified " -":code:`client_num_gpus = 2`, the simulation wouldn't start (even if you " -"had 2 GPUs but decided to set 1 in :code:`ray_init_args`)." +"In the example above, only one client will be run, so your clients won't run " +"concurrently. Setting :code:`client_num_gpus = 0.5` would allow running two " +"clients and therefore enable them to run concurrently. Be careful not to " +"require more resources than available. If you specified :code:" +"`client_num_gpus = 2`, the simulation wouldn't start (even if you had 2 GPUs " +"but decided to set 1 in :code:`ray_init_args`)." msgstr "" +"在上面的示例中,将只运行一个客户端,因此您的客户端不会并发运行。设置 :code:" +"`client_num_gpus = 0.5` 将允许运行两个客户端,从而使它们能够并发运行。请注" +"意,所需的资源不要超过可用资源。如果您指定 :code:`client_num_gpus = 2`,模拟" +"将无法启动(即使您有 2 个 GPU,但决定在 :code:`ray_init_args` 中设置为 1)。" #: ../../source/how-to-monitor-simulation.rst:212 ../../source/ref-faq.rst:2 msgid "FAQ" -msgstr "" +msgstr "常见问题" #: ../../source/how-to-monitor-simulation.rst:214 msgid "Q: I don't see any metrics logged." -msgstr "" +msgstr "问:我没有看到任何指标记录。" #: ../../source/how-to-monitor-simulation.rst:216 msgid "" -"A: The timeframe might not be properly set. The setting is in the top " -"right corner (\"Last 30 minutes\" by default). Please change the " -"timeframe to reflect the period when the simulation was running." +"A: The timeframe might not be properly set. The setting is in the top right " +"corner (\"Last 30 minutes\" by default). Please change the timeframe to " +"reflect the period when the simulation was running." msgstr "" +"答:时间范围可能没有正确设置。设置在右上角(默认为 \"最后 30 分钟\")。请更改" +"时间框架,以反映模拟运行的时间段。" #: ../../source/how-to-monitor-simulation.rst:218 msgid "" -"Q: I see “Grafana server not detected. Please make sure the Grafana " -"server is running and refresh this page” after going to the Metrics tab " -"in Ray Dashboard." +"Q: I see “Grafana server not detected. Please make sure the Grafana server " +"is running and refresh this page” after going to the Metrics tab in Ray " +"Dashboard." msgstr "" +"问:我看到 \"未检测到 Grafana 服务器。请确保 Grafana 服务器正在运行并刷新此页" +"面\"。" #: ../../source/how-to-monitor-simulation.rst:220 msgid "" -"A: You probably don't have Grafana running. Please check the running " -"services" -msgstr "" +"A: You probably don't have Grafana running. Please check the running services" +msgstr "答:您可能没有运行 Grafana。请检查正在运行的服务" #: ../../source/how-to-monitor-simulation.rst:226 msgid "" "Q: I see \"This site can't be reached\" when going to " "``_." -msgstr "" +msgstr "问:在访问 ``_时,我看到 \"无法访问该网站\"。" #: ../../source/how-to-monitor-simulation.rst:228 msgid "" -"A: Either the simulation has already finished, or you still need to start" -" Prometheus." -msgstr "" +"A: Either the simulation has already finished, or you still need to start " +"Prometheus." +msgstr "答:要么模拟已经完成,要么您还需要启动普罗米修斯。" #: ../../source/how-to-monitor-simulation.rst:232 msgid "Resources" -msgstr "" +msgstr "资源" #: ../../source/how-to-monitor-simulation.rst:234 +#, fuzzy msgid "" -"Ray Dashboard: ``_" +"Ray Dashboard: ``_" msgstr "" +"Ray Dashboard: ``_" #: ../../source/how-to-monitor-simulation.rst:236 +#, fuzzy msgid "" -"Ray Metrics: ``_" +"Ray Metrics: ``_" msgstr "" +"Ray Metrics: ``_" #: ../../source/how-to-run-simulations.rst:2 msgid "Run simulations" -msgstr "" +msgstr "运行模拟" #: ../../source/how-to-run-simulations.rst:8 msgid "" "Simulating Federated Learning workloads is useful for a multitude of use-" -"cases: you might want to run your workload on a large cohort of clients " -"but without having to source, configure and mange a large number of " -"physical devices; you might want to run your FL workloads as fast as " -"possible on the compute systems you have access to without having to go " -"through a complex setup process; you might want to validate your " -"algorithm on different scenarios at varying levels of data and system " -"heterogeneity, client availability, privacy budgets, etc. These are among" -" some of the use-cases where simulating FL workloads makes sense. Flower " -"can accommodate these scenarios by means of its `VirtualClientEngine " -"`_ or " -"VCE." -msgstr "" +"cases: you might want to run your workload on a large cohort of clients but " +"without having to source, configure and mange a large number of physical " +"devices; you might want to run your FL workloads as fast as possible on the " +"compute systems you have access to without having to go through a complex " +"setup process; you might want to validate your algorithm on different " +"scenarios at varying levels of data and system heterogeneity, client " +"availability, privacy budgets, etc. These are among some of the use-cases " +"where simulating FL workloads makes sense. Flower can accommodate these " +"scenarios by means of its `VirtualClientEngine `_ or VCE." +msgstr "" +"模拟联合学习工作负载可用于多种用例:您可能希望在大量客户端上运行您的工作负" +"载,但无需采购、配置和管理大量物理设备;您可能希望在您可以访问的计算系统上尽" +"可能快地运行您的 FL 工作负载,而无需经过复杂的设置过程;您可能希望在不同数据" +"和系统异构性、客户端可用性、隐私预算等不同水平的场景中验证您的算法。这些都是" +"模拟 FL 工作负载有意义的一些用例。Flower 可以通过其 \"虚拟客户端引擎" +"\"(VirtualClientEngine)_或 VCE 来适应这些情况。" #: ../../source/how-to-run-simulations.rst:10 msgid "" -"The :code:`VirtualClientEngine` schedules, launches and manages `virtual`" -" clients. These clients are identical to `non-virtual` clients (i.e. the " -"ones you launch via the command `flwr.client.start_client `_) in the sense that they can be configure " -"by creating a class inheriting, for example, from " -"`flwr.client.NumPyClient `_ " -"and therefore behave in an identical way. In addition to that, clients " -"managed by the :code:`VirtualClientEngine` are:" +"The :code:`VirtualClientEngine` schedules, launches and manages `virtual` " +"clients. These clients are identical to `non-virtual` clients (i.e. the ones " +"you launch via the command `flwr.client.start_client `_) in the sense that they can be configure by creating a " +"class inheriting, for example, from `flwr.client.NumPyClient `_ and therefore behave in an identical way. In " +"addition to that, clients managed by the :code:`VirtualClientEngine` are:" msgstr "" #: ../../source/how-to-run-simulations.rst:12 msgid "" -"resource-aware: this means that each client gets assigned a portion of " -"the compute and memory on your system. You as a user can control this at " -"the beginning of the simulation and allows you to control the degree of " +"resource-aware: this means that each client gets assigned a portion of the " +"compute and memory on your system. You as a user can control this at the " +"beginning of the simulation and allows you to control the degree of " "parallelism of your Flower FL simulation. The fewer the resources per " "client, the more clients can run concurrently on the same hardware." msgstr "" +"资源感知:这意味着每个客户端都会分配到系统中的一部分计算和内存。作为用户,您" +"可以在模拟开始时对其进行控制,从而控制 Flower FL 模拟的并行程度。每个客户端的" +"资源越少,在同一硬件上并发运行的客户端就越多。" #: ../../source/how-to-run-simulations.rst:13 msgid "" -"self-managed: this means that you as a user do not need to launch clients" -" manually, instead this gets delegated to :code:`VirtualClientEngine`'s " +"self-managed: this means that you as a user do not need to launch clients " +"manually, instead this gets delegated to :code:`VirtualClientEngine`'s " "internals." msgstr "" +"自管理:这意味着用户无需手动启动客户端,而是由 :code:`VirtualClientEngine` 的" +"内部人员负责。" #: ../../source/how-to-run-simulations.rst:14 msgid "" -"ephemeral: this means that a client is only materialized when it is " -"required in the FL process (e.g. to do `fit() `_). The object is destroyed afterwards," -" releasing the resources it was assigned and allowing in this way other " -"clients to participate." +"ephemeral: this means that a client is only materialized when it is required " +"in the FL process (e.g. to do `fit() `_). The object is destroyed afterwards, releasing the resources it was " +"assigned and allowing in this way other clients to participate." msgstr "" +"ephemeral(短暂的):这意味着客户端只有在 FL 进程中需要它时才会被实体化(例如" +"执行 `fit() `_ )。之后该对象将被销" +"毁,释放分配给它的资源,并允许其他客户端以这种方式参与。" #: ../../source/how-to-run-simulations.rst:16 msgid "" "The :code:`VirtualClientEngine` implements `virtual` clients using `Ray " "`_, an open-source framework for scalable Python " -"workloads. In particular, Flower's :code:`VirtualClientEngine` makes use " -"of `Actors `_ to " -"spawn `virtual` clients and run their workload." +"workloads. In particular, Flower's :code:`VirtualClientEngine` makes use of " +"`Actors `_ to spawn " +"`virtual` clients and run their workload." msgstr "" +"代码:`VirtualClientEngine`使用`Ray `_来实现`虚拟`客户" +"端,这是一个用于可扩展 Python 工作负载的开源框架。特别地,Flower 的 :code:" +"`VirtualClientEngine` 使用 `Actors `_ 来生成 `virtual` 客户端并运行它们的工作负载。" #: ../../source/how-to-run-simulations.rst:20 msgid "Launch your Flower simulation" -msgstr "" +msgstr "启动 Flower 模拟" #: ../../source/how-to-run-simulations.rst:22 msgid "" -"Running Flower simulations still require you to define your client class," -" a strategy, and utility functions to download and load (and potentially " -"partition) your dataset. With that out of the way, launching your " -"simulation is done with `start_simulation `_ and a minimal example looks" -" as follows:" +"Running Flower simulations still require you to define your client class, a " +"strategy, and utility functions to download and load (and potentially " +"partition) your dataset. With that out of the way, launching your simulation " +"is done with `start_simulation `_ and a minimal example looks as follows:" msgstr "" +"运行 Flower 仿真仍然需要定义客户端类、策略以及下载和加载(可能还需要分割)数" +"据集的实用程序。在完成这些工作后,就可以使用 \"start_simulation `_\" 来启动模拟了,一个最简单的示" +"例如下:" #: ../../source/how-to-run-simulations.rst:44 msgid "VirtualClientEngine resources" -msgstr "" +msgstr "虚拟客户端引擎资源" #: ../../source/how-to-run-simulations.rst:45 msgid "" -"By default the VCE has access to all system resources (i.e. all CPUs, all" -" GPUs, etc) since that is also the default behavior when starting Ray. " -"However, in some settings you might want to limit how many of your system" -" resources are used for simulation. You can do this via the " -":code:`ray_init_args` input argument to :code:`start_simulation` which " -"the VCE internally passes to Ray's :code:`ray.init` command. For a " -"complete list of settings you can configure check the `ray.init " -"`_" -" documentation. Do not set :code:`ray_init_args` if you want the VCE to " -"use all your system's CPUs and GPUs." -msgstr "" +"By default the VCE has access to all system resources (i.e. all CPUs, all " +"GPUs, etc) since that is also the default behavior when starting Ray. " +"However, in some settings you might want to limit how many of your system " +"resources are used for simulation. You can do this via the :code:" +"`ray_init_args` input argument to :code:`start_simulation` which the VCE " +"internally passes to Ray's :code:`ray.init` command. For a complete list of " +"settings you can configure check the `ray.init `_ documentation. Do not set :" +"code:`ray_init_args` if you want the VCE to use all your system's CPUs and " +"GPUs." +msgstr "" +"默认情况下,VCE 可以访问所有系统资源(即所有 CPU、所有 GPU 等),因为这也是启" +"动 Ray 时的默认行为。不过,在某些设置中,您可能希望限制有多少系统资源用于仿" +"真。您可以通过 :code:`ray_init_args` 输入到 :code:`start_simulation` 的参数来" +"做到这一点,VCE 会在内部将该参数传递给 Ray 的 :code:`ray.init` 命令。有关您可" +"以配置的设置的完整列表,请查看 `ray.init `_ 文档。如果希望 VCE 使用系统中所有的 " +"CPU 和 GPU,请不要设置 :code:`ray_init_args`。" #: ../../source/how-to-run-simulations.rst:62 msgid "Assigning client resources" -msgstr "" +msgstr "分配客户资源" #: ../../source/how-to-run-simulations.rst:63 msgid "" -"By default the :code:`VirtualClientEngine` assigns a single CPU core (and" -" nothing else) to each virtual client. This means that if your system has" -" 10 cores, that many virtual clients can be concurrently running." +"By default the :code:`VirtualClientEngine` assigns a single CPU core (and " +"nothing else) to each virtual client. This means that if your system has 10 " +"cores, that many virtual clients can be concurrently running." msgstr "" +"默认情况下,:code:`VirtualClientEngine` 会为每个虚拟客户端分配一个 CPU 内核" +"(不分配其他任何内核)。这意味着,如果系统有 10 个内核,那么可以同时运行这么" +"多虚拟客户端。" #: ../../source/how-to-run-simulations.rst:65 msgid "" -"More often than not, you would probably like to adjust the resources your" -" clients get assigned based on the complexity (i.e. compute and memory " -"footprint) of your FL workload. You can do so when starting your " -"simulation by setting the argument `client_resources` to " -"`start_simulation `_." -" Two keys are internally used by Ray to schedule and spawn workloads (in " -"our case Flower clients):" +"More often than not, you would probably like to adjust the resources your " +"clients get assigned based on the complexity (i.e. compute and memory " +"footprint) of your FL workload. You can do so when starting your simulation " +"by setting the argument `client_resources` to `start_simulation `_. Two keys are internally used " +"by Ray to schedule and spawn workloads (in our case Flower clients):" msgstr "" +"通常情况下,您可能希望根据 FL 工作负载的复杂性(即计算和内存占用)来调整分配" +"给客户端的资源。您可以在启动仿真时将参数 `client_resources` 设置为 " +"`start_simulation `_ 。" +"Ray 内部使用两个键来调度和生成工作负载(在我们的例子中是 Flower 客户端):" #: ../../source/how-to-run-simulations.rst:67 msgid ":code:`num_cpus` indicates the number of CPU cores a client would get." -msgstr "" +msgstr ":code:`num_cpus` 表示客户端将获得的 CPU 内核数量。" #: ../../source/how-to-run-simulations.rst:68 msgid "" ":code:`num_gpus` indicates the **ratio** of GPU memory a client gets " "assigned." -msgstr "" +msgstr ":code:`num_gpus` 表示分配给客户端的 GPU 内存的***比例。" #: ../../source/how-to-run-simulations.rst:70 msgid "Let's see a few examples:" -msgstr "" +msgstr "让我们来看几个例子:" #: ../../source/how-to-run-simulations.rst:89 msgid "" "While the :code:`client_resources` can be used to control the degree of " "concurrency in your FL simulation, this does not stop you from running " -"dozens, hundreds or even thousands of clients in the same round and " -"having orders of magnitude more `dormant` (i.e. not participating in a " -"round) clients. Let's say you want to have 100 clients per round but your" -" system can only accommodate 8 clients concurrently. The " -":code:`VirtualClientEngine` will schedule 100 jobs to run (each " -"simulating a client sampled by the strategy) and then will execute them " -"in a resource-aware manner in batches of 8." -msgstr "" +"dozens, hundreds or even thousands of clients in the same round and having " +"orders of magnitude more `dormant` (i.e. not participating in a round) " +"clients. Let's say you want to have 100 clients per round but your system " +"can only accommodate 8 clients concurrently. The :code:`VirtualClientEngine` " +"will schedule 100 jobs to run (each simulating a client sampled by the " +"strategy) and then will execute them in a resource-aware manner in batches " +"of 8." +msgstr "" +"虽然 :code:`client_resources` 可用来控制 FL 模拟的并发程度,但这并不能阻止您" +"在同一轮模拟中运行几十、几百甚至上千个客户端,并拥有数量级更多的 \"休眠\"(即" +"不参与一轮模拟)客户端。比方说,您希望每轮有 100 个客户端,但您的系统只能同时" +"容纳 8 个客户端。:code:`VirtualClientEngine` 将安排运行 100 个作业(每个作业" +"模拟策略采样的一个客户端),然后以资源感知的方式分批执行。" #: ../../source/how-to-run-simulations.rst:91 msgid "" "To understand all the intricate details on how resources are used to " -"schedule FL clients and how to define custom resources, please take a " -"look at the `Ray documentation `_." +"schedule FL clients and how to define custom resources, please take a look " +"at the `Ray documentation `_." msgstr "" +"要了解资源如何用于调度 FL 客户端以及如何定义自定义资源的所有复杂细节,请查看 " +"`Ray 文档 `_。" #: ../../source/how-to-run-simulations.rst:94 msgid "Simulation examples" -msgstr "" +msgstr "模拟示例" #: ../../source/how-to-run-simulations.rst:96 msgid "" -"A few ready-to-run complete examples for Flower simulation in " -"Tensorflow/Keras and PyTorch are provided in the `Flower repository " -"`_. You can run them on Google Colab too:" +"A few ready-to-run complete examples for Flower simulation in Tensorflow/" +"Keras and PyTorch are provided in the `Flower repository `_. You can run them on Google Colab too:" msgstr "" +"在 Tensorflow/Keras 和 PyTorch 中进行 Flower 仿真的几个可随时运行的完整示例已" +"在 `Flower 存储库 `_ 中提供。您也可以在 " +"Google Colab 上运行它们:" #: ../../source/how-to-run-simulations.rst:98 msgid "" -"`Tensorflow/Keras Simulation " -"`_: 100 clients collaboratively train a MLP model on MNIST." +"`Tensorflow/Keras Simulation `_: 100 clients collaboratively train a MLP " +"model on MNIST." msgstr "" +"Tensorflow/Keras仿真 `_:100个客户端在MNIST上协作训练一个MLP模型。" #: ../../source/how-to-run-simulations.rst:99 msgid "" -"`PyTorch Simulation `_: 100 clients collaboratively train a CNN model on " +"`PyTorch Simulation `_: 100 clients collaboratively train a CNN model on " "MNIST." msgstr "" +"PyTorch 仿真 `_:100 个客户端在 MNIST 上协作训练一个 CNN 模型。" #: ../../source/how-to-run-simulations.rst:104 msgid "Multi-node Flower simulations" -msgstr "" +msgstr "多节点 Flower 模拟" #: ../../source/how-to-run-simulations.rst:106 msgid "" -"Flower's :code:`VirtualClientEngine` allows you to run FL simulations " -"across multiple compute nodes. Before starting your multi-node simulation" -" ensure that you:" +"Flower's :code:`VirtualClientEngine` allows you to run FL simulations across " +"multiple compute nodes. Before starting your multi-node simulation ensure " +"that you:" msgstr "" +"Flower 的 :code:`VirtualClientEngine` 允许您在多个计算节点上运行 FL 仿真。在" +"开始多节点模拟之前,请确保:" #: ../../source/how-to-run-simulations.rst:108 msgid "Have the same Python environment in all nodes." -msgstr "" +msgstr "所有节点都有相同的 Python 环境。" #: ../../source/how-to-run-simulations.rst:109 msgid "Have a copy of your code (e.g. your entire repo) in all nodes." -msgstr "" +msgstr "在所有节点上都有一份代码副本(例如整个软件包)。" #: ../../source/how-to-run-simulations.rst:110 msgid "" -"Have a copy of your dataset in all nodes (more about this in " -":ref:`simulation considerations `)" +"Have a copy of your dataset in all nodes (more about this in :ref:" +"`simulation considerations `)" msgstr "" +"在所有节点中都有一份数据集副本(更多相关信息请参阅 :ref:`模拟注意事项" +"`)" #: ../../source/how-to-run-simulations.rst:111 msgid "" -"Pass :code:`ray_init_args={\"address\"=\"auto\"}` to `start_simulation " -"`_ so the " -":code:`VirtualClientEngine` attaches to a running Ray instance." +"Pass :code:`ray_init_args={\"address\"=\"auto\"}` to `start_simulation `_ so the :code:" +"`VirtualClientEngine` attaches to a running Ray instance." msgstr "" +"将 :code:`ray_init_args={\"address\"=\"auto\"}`传递给 `start_simulation `_ ,这样 :code:" +"`VirtualClientEngine`就会连接到正在运行的 Ray 实例。" #: ../../source/how-to-run-simulations.rst:112 msgid "" -"Start Ray on you head node: on the terminal type :code:`ray start " -"--head`. This command will print a few lines, one of which indicates how " -"to attach other nodes to the head node." +"Start Ray on you head node: on the terminal type :code:`ray start --head`. " +"This command will print a few lines, one of which indicates how to attach " +"other nodes to the head node." msgstr "" +"在头部节点上启动 Ray:在终端上输入 :code:`raystart--head`。该命令将打印几行," +"其中一行说明如何将其他节点连接到头部节点。" #: ../../source/how-to-run-simulations.rst:113 msgid "" -"Attach other nodes to the head node: copy the command shown after " -"starting the head and execute it on terminal of a new node: for example " -":code:`ray start --address='192.168.1.132:6379'`" +"Attach other nodes to the head node: copy the command shown after starting " +"the head and execute it on terminal of a new node: for example :code:`ray " +"start --address='192.168.1.132:6379'`" msgstr "" +"将其他节点附加到头部节点:复制启动头部后显示的命令,并在新节点的终端上执行:" +"例如 :code:`ray start --address='192.168.1.132:6379'`" #: ../../source/how-to-run-simulations.rst:115 msgid "" "With all the above done, you can run your code from the head node as you " "would if the simulation was running on a single node." msgstr "" +"完成上述所有操作后,您就可以在头部节点上运行代码了,就像在单个节点上运行模拟" +"一样。" #: ../../source/how-to-run-simulations.rst:117 msgid "" -"Once your simulation is finished, if you'd like to dismantle your cluster" -" you simply need to run the command :code:`ray stop` in each node's " -"terminal (including the head node)." +"Once your simulation is finished, if you'd like to dismantle your cluster " +"you simply need to run the command :code:`ray stop` in each node's terminal " +"(including the head node)." msgstr "" +"模拟结束后,如果要拆除集群,只需在每个节点(包括头部节点)的终端运行 :code:" +"`ray stop` 命令即可。" #: ../../source/how-to-run-simulations.rst:120 msgid "Multi-node simulation good-to-know" -msgstr "" +msgstr "了解多节点模拟" #: ../../source/how-to-run-simulations.rst:122 msgid "" "Here we list a few interesting functionality when running multi-node FL " "simulations:" -msgstr "" +msgstr "在此,我们列举了运行多节点 FL 模拟时的一些有趣功能:" #: ../../source/how-to-run-simulations.rst:124 msgid "" -"User :code:`ray status` to check all nodes connected to your head node as" -" well as the total resources available to the " -":code:`VirtualClientEngine`." +"User :code:`ray status` to check all nodes connected to your head node as " +"well as the total resources available to the :code:`VirtualClientEngine`." msgstr "" +"使用 :code:`ray status` 查看连接到头部节点的所有节点,以及 :code:" +"`VirtualClientEngine` 可用的总资源。" #: ../../source/how-to-run-simulations.rst:126 msgid "" -"When attaching a new node to the head, all its resources (i.e. all CPUs, " -"all GPUs) will be visible by the head node. This means that the " -":code:`VirtualClientEngine` can schedule as many `virtual` clients as " -"that node can possible run. In some settings you might want to exclude " -"certain resources from the simulation. You can do this by appending " -"`--num-cpus=` and/or `--num-" -"gpus=` in any :code:`ray start` command (including " -"when starting the head)" +"When attaching a new node to the head, all its resources (i.e. all CPUs, all " +"GPUs) will be visible by the head node. This means that the :code:" +"`VirtualClientEngine` can schedule as many `virtual` clients as that node " +"can possible run. In some settings you might want to exclude certain " +"resources from the simulation. You can do this by appending `--num-" +"cpus=` and/or `--num-gpus=` in any :" +"code:`ray start` command (including when starting the head)" msgstr "" +"将新节点附加到头部节点时,头部节点将可见其所有资源(即所有 CPU 和 GPU)。这意" +"味着 :code:`VirtualClientEngine` 可以调度尽可能多的 \"虚拟 \"客户端来运行该节" +"点。在某些设置中,您可能希望将某些资源排除在模拟之外。为此,您可以在任何 :" +"code:`ray start` 命令(包括启动头部时)中添加 `--num-" +"cpus=`和/或 `--num-gpus=`" #: ../../source/how-to-run-simulations.rst:132 msgid "Considerations for simulations" -msgstr "" +msgstr "模拟的注意事项" #: ../../source/how-to-run-simulations.rst:135 msgid "" -"We are actively working on these fronts so to make it trivial to run any " -"FL workload with Flower simulation." +"We are actively working on these fronts so to make it trivial to run any FL " +"workload with Flower simulation." msgstr "" +"我们正在积极开展这些方面的工作,以便使 FL 工作负载与 Flower 仿真的运行变得轻" +"而易举。" #: ../../source/how-to-run-simulations.rst:138 msgid "" -"The current VCE allows you to run Federated Learning workloads in " -"simulation mode whether you are prototyping simple scenarios on your " -"personal laptop or you want to train a complex FL pipeline across " -"multiple high-performance GPU nodes. While we add more capabilities to " -"the VCE, the points below highlight some of the considerations to keep in" -" mind when designing your FL pipeline with Flower. We also highlight a " -"couple of current limitations in our implementation." +"The current VCE allows you to run Federated Learning workloads in simulation " +"mode whether you are prototyping simple scenarios on your personal laptop or " +"you want to train a complex FL pipeline across multiple high-performance GPU " +"nodes. While we add more capabilities to the VCE, the points below highlight " +"some of the considerations to keep in mind when designing your FL pipeline " +"with Flower. We also highlight a couple of current limitations in our " +"implementation." msgstr "" +"当前的 VCE 允许您在模拟模式下运行 Federated Learning 工作负载,无论您是在个人" +"笔记本电脑上建立简单的场景原型,还是要在多个高性能 GPU 节点上训练复杂的 FL 管" +"道。虽然我们为 VCE 增加了更多的功能,但以下几点强调了在使用 Flower 设计 FL 管" +"道时需要注意的一些事项。我们还强调了我们的实现中目前存在的一些局限性。" #: ../../source/how-to-run-simulations.rst:141 msgid "GPU resources" -msgstr "" +msgstr "GPU 资源" #: ../../source/how-to-run-simulations.rst:143 msgid "" -"The VCE assigns a share of GPU memory to a client that specifies the key " -":code:`num_gpus` in :code:`client_resources`. This being said, Ray (used " +"The VCE assigns a share of GPU memory to a client that specifies the key :" +"code:`num_gpus` in :code:`client_resources`. This being said, Ray (used " "internally by the VCE) is by default:" msgstr "" +"VCE 会为指定 :code:`client_resources` 中 :code:`num_gpus` 关键字的客户端分配 " +"GPU 内存份额。也就是说,Ray(VCE 内部使用)是默认的:" #: ../../source/how-to-run-simulations.rst:146 msgid "" -"not aware of the total VRAM available on the GPUs. This means that if you" -" set :code:`num_gpus=0.5` and you have two GPUs in your system with " -"different (e.g. 32GB and 8GB) VRAM amounts, they both would run 2 clients" -" concurrently." +"not aware of the total VRAM available on the GPUs. This means that if you " +"set :code:`num_gpus=0.5` and you have two GPUs in your system with different " +"(e.g. 32GB and 8GB) VRAM amounts, they both would run 2 clients concurrently." msgstr "" +"不知道 GPU 上可用的总 VRAM。这意味着,如果您设置 :code:`num_gpus=0.5`,而系统" +"中有两个不同(如 32GB 和 8GB)VRAM 的 GPU,它们都将同时运行 2 个客户端。" #: ../../source/how-to-run-simulations.rst:147 msgid "" "not aware of other unrelated (i.e. not created by the VCE) workloads are " "running on the GPU. Two takeaways from this are:" msgstr "" +"不知道 GPU 上正在运行其他无关(即不是由 VCE 创建)的工作负载。从中可以得到以" +"下两点启示:" #: ../../source/how-to-run-simulations.rst:149 msgid "" @@ -4963,171 +5868,210 @@ msgid "" "aggregation (by instance when making use of the `evaluate method `_)" msgstr "" +"您的 Flower 服务器可能需要 GPU 来评估聚合后的 \"全局模型\"(例如在使用 \"评估" +"方法\"`_时)" #: ../../source/how-to-run-simulations.rst:150 msgid "" "If you want to run several independent Flower simulations on the same " -"machine you need to mask-out your GPUs with " -":code:`CUDA_VISIBLE_DEVICES=\"\"` when launching your " -"experiment." +"machine you need to mask-out your GPUs with :code:" +"`CUDA_VISIBLE_DEVICES=\"\"` when launching your experiment." msgstr "" +"如果您想在同一台机器上运行多个独立的 Flower 仿真,则需要在启动实验时使用 :" +"code:`CUDA_VISIBLE_DEVICES=\"\"` 屏蔽 GPU。" #: ../../source/how-to-run-simulations.rst:153 msgid "" -"In addition, the GPU resource limits passed to :code:`client_resources` " -"are not `enforced` (i.e. they can be exceeded) which can result in the " -"situation of client using more VRAM than the ratio specified when " -"starting the simulation." +"In addition, the GPU resource limits passed to :code:`client_resources` are " +"not `enforced` (i.e. they can be exceeded) which can result in the situation " +"of client using more VRAM than the ratio specified when starting the " +"simulation." msgstr "" +"此外,传递给 :code:`client_resources` 的 GPU 资源限制并不是 \"强制 \"的(即可" +"以超出),这可能导致客户端使用的 VRAM 超过启动模拟时指定的比例。" #: ../../source/how-to-run-simulations.rst:156 msgid "TensorFlow with GPUs" -msgstr "" +msgstr "使用 GPU 的 TensorFlow" #: ../../source/how-to-run-simulations.rst:158 msgid "" -"When `using a GPU with TensorFlow " -"`_ nearly your entire GPU memory of" -" all your GPUs visible to the process will be mapped. This is done by " -"TensorFlow for optimization purposes. However, in settings such as FL " -"simulations where we want to split the GPU into multiple `virtual` " -"clients, this is not a desirable mechanism. Luckily we can disable this " -"default behavior by `enabling memory growth " -"`_." +"When `using a GPU with TensorFlow `_ " +"nearly your entire GPU memory of all your GPUs visible to the process will " +"be mapped. This is done by TensorFlow for optimization purposes. However, in " +"settings such as FL simulations where we want to split the GPU into multiple " +"`virtual` clients, this is not a desirable mechanism. Luckily we can disable " +"this default behavior by `enabling memory growth `_." msgstr "" +"在 TensorFlow `_ 中使用 GPU 时,几乎所" +"有进程可见的 GPU 内存都将被映射。TensorFlow 这样做是出于优化目的。然而,在 " +"FL 模拟等设置中,我们希望将 GPU 分割成多个 \"虚拟 \"客户端,这并不是一个理想" +"的机制。幸运的是,我们可以通过 \"启用内存增长 `_\"来禁用这一默认行为。" #: ../../source/how-to-run-simulations.rst:160 msgid "" -"This would need to be done in the main process (which is where the server" -" would run) and in each Actor created by the VCE. By means of " -":code:`actor_kwargs` we can pass the reserved key `\"on_actor_init_fn\"` " -"in order to specify a function to be executed upon actor initialization. " -"In this case, to enable GPU growth for TF workloads. It would look as " -"follows:" +"This would need to be done in the main process (which is where the server " +"would run) and in each Actor created by the VCE. By means of :code:" +"`actor_kwargs` we can pass the reserved key `\"on_actor_init_fn\"` in order " +"to specify a function to be executed upon actor initialization. In this " +"case, to enable GPU growth for TF workloads. It would look as follows:" msgstr "" +"这需要在主进程(也就是服务器运行的地方)和 VCE 创建的每个角色中完成。通过 :" +"code:`actor_kwargs`,我们可以传递保留关键字`\"on_actor_init_fn\"`,以指定在角" +"色初始化时执行的函数。在本例中,为了使 TF 工作负载的 GPU 增长。它看起来如下:" #: ../../source/how-to-run-simulations.rst:179 msgid "" "This is precisely the mechanism used in `Tensorflow/Keras Simulation " -"`_ example." +"`_ " +"example." msgstr "" +"这正是 \"Tensorflow/Keras 仿真 `_\"示例中使用的机制。" #: ../../source/how-to-run-simulations.rst:183 msgid "Multi-node setups" -msgstr "" +msgstr "多节点设置" #: ../../source/how-to-run-simulations.rst:185 msgid "" -"The VCE does not currently offer a way to control on which node a " -"particular `virtual` client is executed. In other words, if more than a " -"single node have the resources needed by a client to run, then any of " -"those nodes could get the client workload scheduled onto. Later in the FL" -" process (i.e. in a different round) the same client could be executed by" -" a different node. Depending on how your clients access their datasets, " -"this might require either having a copy of all dataset partitions on all " -"nodes or a dataset serving mechanism (e.g. using nfs, a database) to " -"circumvent data duplication." -msgstr "" +"The VCE does not currently offer a way to control on which node a particular " +"`virtual` client is executed. In other words, if more than a single node " +"have the resources needed by a client to run, then any of those nodes could " +"get the client workload scheduled onto. Later in the FL process (i.e. in a " +"different round) the same client could be executed by a different node. " +"Depending on how your clients access their datasets, this might require " +"either having a copy of all dataset partitions on all nodes or a dataset " +"serving mechanism (e.g. using nfs, a database) to circumvent data " +"duplication." +msgstr "" +"VCE 目前不提供控制特定 \"虚拟 \"客户端在哪个节点上执行的方法。换句话说,如果" +"不止一个节点拥有客户端运行所需的资源,那么这些节点中的任何一个都可能被调度到" +"客户端工作负载上。在 FL 进程的稍后阶段(即在另一轮中),同一客户端可以由不同" +"的节点执行。根据客户访问数据集的方式,这可能需要在所有节点上复制所有数据集分" +"区,或采用数据集服务机制(如使用 nfs 或数据库)来避免数据重复。" #: ../../source/how-to-run-simulations.rst:187 msgid "" -"By definition virtual clients are `stateless` due to their ephemeral " -"nature. A client state can be implemented as part of the Flower client " -"class but users need to ensure this saved to persistent storage (e.g. a " -"database, disk) and that can be retrieve later by the same client " -"regardless on which node it is running from. This is related to the point" -" above also since, in some way, the client's dataset could be seen as a " -"type of `state`." +"By definition virtual clients are `stateless` due to their ephemeral nature. " +"A client state can be implemented as part of the Flower client class but " +"users need to ensure this saved to persistent storage (e.g. a database, " +"disk) and that can be retrieve later by the same client regardless on which " +"node it is running from. This is related to the point above also since, in " +"some way, the client's dataset could be seen as a type of `state`." msgstr "" +"根据定义,虚拟客户端是 \"无状态 \"的,因为它们具有短暂性。客户机状态可以作为 " +"Flower 客户机类的一部分来实现,但用户需要确保将其保存到持久存储(如数据库、磁" +"盘)中,而且无论客户机在哪个节点上运行,都能在以后检索到。这也与上述观点有" +"关,因为在某种程度上,客户端的数据集可以被视为一种 \"状态\"。" #: ../../source/how-to-save-and-load-model-checkpoints.rst:2 msgid "Save and load model checkpoints" -msgstr "" +msgstr "保存和加载模型检查点" #: ../../source/how-to-save-and-load-model-checkpoints.rst:4 msgid "" -"Flower does not automatically save model updates on the server-side. This" -" how-to guide describes the steps to save (and load) model checkpoints in" -" Flower." +"Flower does not automatically save model updates on the server-side. This " +"how-to guide describes the steps to save (and load) model checkpoints in " +"Flower." msgstr "" +"Flower 不会在服务器端自动保存模型更新。本指南将介绍在 Flower 中保存(和加载)" +"模型检查点的步骤。" #: ../../source/how-to-save-and-load-model-checkpoints.rst:8 msgid "Model checkpointing" -msgstr "" +msgstr "模型检查点" #: ../../source/how-to-save-and-load-model-checkpoints.rst:10 msgid "" -"Model updates can be persisted on the server-side by customizing " -":code:`Strategy` methods. Implementing custom strategies is always an " -"option, but for many cases it may be more convenient to simply customize " -"an existing strategy. The following code example defines a new " -":code:`SaveModelStrategy` which customized the existing built-in " -":code:`FedAvg` strategy. In particular, it customizes " -":code:`aggregate_fit` by calling :code:`aggregate_fit` in the base class " -"(:code:`FedAvg`). It then continues to save returned (aggregated) weights" -" before it returns those aggregated weights to the caller (i.e., the " -"server):" -msgstr "" +"Model updates can be persisted on the server-side by customizing :code:" +"`Strategy` methods. Implementing custom strategies is always an option, but " +"for many cases it may be more convenient to simply customize an existing " +"strategy. The following code example defines a new :code:`SaveModelStrategy` " +"which customized the existing built-in :code:`FedAvg` strategy. In " +"particular, it customizes :code:`aggregate_fit` by calling :code:" +"`aggregate_fit` in the base class (:code:`FedAvg`). It then continues to " +"save returned (aggregated) weights before it returns those aggregated " +"weights to the caller (i.e., the server):" +msgstr "" +"模型更新可通过自定义 :code:`Strategy` 方法在服务器端持久化。实现自定义策略始" +"终是一种选择,但在许多情况下,简单地自定义现有策略可能更方便。下面的代码示例" +"定义了一个新的 :code:`SaveModelStrategy`,它自定义了现有的内置 :code:" +"`FedAvg` 策略。特别是,它通过调用基类(:code:`FedAvg`)中的 :code:" +"`aggregate_fit` 来定制 :code:`aggregate_fit`。然后继续保存返回的(聚合)权" +"重,然后再将这些聚合权重返回给调用者(即服务器):" #: ../../source/how-to-save-and-load-model-checkpoints.rst:47 msgid "Save and load PyTorch checkpoints" -msgstr "" +msgstr "保存和加载 PyTorch 检查点" #: ../../source/how-to-save-and-load-model-checkpoints.rst:49 msgid "" -"Similar to the previous example but with a few extra steps, we'll show " -"how to store a PyTorch checkpoint we'll use the ``torch.save`` function. " -"Firstly, ``aggregate_fit`` returns a ``Parameters`` object that has to be" -" transformed into a list of NumPy ``ndarray``'s, then those are " -"transformed into the PyTorch ``state_dict`` following the ``OrderedDict``" -" class structure." +"Similar to the previous example but with a few extra steps, we'll show how " +"to store a PyTorch checkpoint we'll use the ``torch.save`` function. " +"Firstly, ``aggregate_fit`` returns a ``Parameters`` object that has to be " +"transformed into a list of NumPy ``ndarray``'s, then those are transformed " +"into the PyTorch ``state_dict`` following the ``OrderedDict`` class " +"structure." msgstr "" +"与前面的例子类似,但多了几个步骤,我们将展示如何存储一个 PyTorch 检查点,我们" +"将使用 ``torch.save`` 函数。首先,``aggregate_fit`` 返回一个 ``Parameters`` " +"对象,它必须被转换成一个 NumPy ``ndarray`` 的列表,然后这些对象按照 " +"``OrderedDict`` 类结构被转换成 PyTorch `state_dict` 对象。" #: ../../source/how-to-save-and-load-model-checkpoints.rst:85 msgid "" -"To load your progress, you simply append the following lines to your " -"code. Note that this will iterate over all saved checkpoints and load the" -" latest one:" +"To load your progress, you simply append the following lines to your code. " +"Note that this will iterate over all saved checkpoints and load the latest " +"one:" msgstr "" +"要加载进度,只需在代码中添加以下几行。请注意,这将遍历所有已保存的检查点,并" +"加载最新的检查点:" #: ../../source/how-to-upgrade-to-flower-1.0.rst:2 msgid "Upgrade to Flower 1.0" -msgstr "" +msgstr "升级至 Flower 1.0" #: ../../source/how-to-upgrade-to-flower-1.0.rst:4 msgid "" -"Flower 1.0 is here. Along with new features, Flower 1.0 provides a stable" -" foundation for future growth. Compared to Flower 0.19 (and other 0.x " -"series releases), there are a few breaking changes that make it necessary" -" to change the code of existing 0.x-series projects." +"Flower 1.0 is here. Along with new features, Flower 1.0 provides a stable " +"foundation for future growth. Compared to Flower 0.19 (and other 0.x series " +"releases), there are a few breaking changes that make it necessary to change " +"the code of existing 0.x-series projects." msgstr "" +"Flower 1.0 正式发布。除了新功能,Flower 1.0 还为未来的发展奠定了稳定的基础。" +"与 Flower 0.19(以及其他 0.x 系列版本)相比,有一些破坏性改动需要修改现有 0." +"x 系列项目的代码。" #: ../../source/how-to-upgrade-to-flower-1.0.rst:8 msgid "Install update" -msgstr "" +msgstr "安装更新" #: ../../source/how-to-upgrade-to-flower-1.0.rst:10 msgid "" -"Here's how to update an existing installation to Flower 1.0 using either " -"pip or Poetry:" -msgstr "" +"Here's how to update an existing installation to Flower 1.0 using either pip " +"or Poetry:" +msgstr "下面介绍如何使用 pip 或 Poetry 将现有安装更新到 Flower 1.0:" #: ../../source/how-to-upgrade-to-flower-1.0.rst:12 msgid "pip: add ``-U`` when installing." -msgstr "" +msgstr "pip: 安装时添加 ``-U``." #: ../../source/how-to-upgrade-to-flower-1.0.rst:14 msgid "" "``python -m pip install -U flwr`` (when using ``start_server`` and " "``start_client``)" msgstr "" +"`python -m pip install -U flwr``(当使用`start_server`和`start_client`时)" #: ../../source/how-to-upgrade-to-flower-1.0.rst:15 msgid "" "``python -m pip install -U flwr[simulation]`` (when using " "``start_simulation``)" msgstr "" +"`python -m pip install -U flwr[simulation]``(当使用`start_simulation``时)" #: ../../source/how-to-upgrade-to-flower-1.0.rst:17 msgid "" @@ -5135,134 +6079,164 @@ msgid "" "reinstall (don't forget to delete ``poetry.lock`` via ``rm poetry.lock`` " "before running ``poetry install``)." msgstr "" +"诗歌:更新 ``pyproject.toml`` 中的 ``flwr`` 依赖关系,然后重新安装(运行 " +"``poetry install`` 前,别忘了通过 ``rm poetry.lock` 删除 ``poetry.lock`)。" #: ../../source/how-to-upgrade-to-flower-1.0.rst:19 -msgid "``flwr = \"^1.0.0\"`` (when using ``start_server`` and ``start_client``)" -msgstr "" +msgid "" +"``flwr = \"^1.0.0\"`` (when using ``start_server`` and ``start_client``)" +msgstr "``flwr = \"^1.0.0\"`` (当使用 ``start_server` 和 ``start_client` 时)" #: ../../source/how-to-upgrade-to-flower-1.0.rst:20 msgid "" -"``flwr = { version = \"^1.0.0\", extras = [\"simulation\"] }`` (when " -"using ``start_simulation``)" +"``flwr = { version = \"^1.0.0\", extras = [\"simulation\"] }`` (when using " +"``start_simulation``)" msgstr "" +"``flwr = { version = \"^1.0.0\", extras = [\"simulation\"] }``(当使用" +"``start_simulation``时)" #: ../../source/how-to-upgrade-to-flower-1.0.rst:24 msgid "Required changes" -msgstr "" +msgstr "所需变更" #: ../../source/how-to-upgrade-to-flower-1.0.rst:26 msgid "The following breaking changes require manual updates." -msgstr "" +msgstr "以下更改需要手动更新。" #: ../../source/how-to-upgrade-to-flower-1.0.rst:29 msgid "General" -msgstr "" +msgstr "一般情况" #: ../../source/how-to-upgrade-to-flower-1.0.rst:31 msgid "" "Pass all arguments as keyword arguments (not as positional arguments). " "Here's an example:" -msgstr "" +msgstr "将所有参数作为关键字参数传递(而不是位置参数)。下面是一个例子:" #: ../../source/how-to-upgrade-to-flower-1.0.rst:33 msgid "" "Flower 0.19 (positional arguments): ``start_client(\"127.0.0.1:8080\", " "FlowerClient())``" msgstr "" +"Flower 0.19 (位置参数): ``start_client(\"127.0.0.1:8080\", FlowerClient())``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:34 msgid "" "Flower 1.0 (keyword arguments): " -"``start_client(server_address=\"127.0.0.1:8080\", " -"client=FlowerClient())``" +"``start_client(server_address=\"127.0.0.1:8080\", client=FlowerClient())``" msgstr "" +"Flower 1.0(关键字参数): ``start_client(server_address=\"127.0.0.1:8080\", " +"client=FlowerClient())``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:39 msgid "" "Subclasses of ``NumPyClient``: change ``def get_parameters(self):``` to " "``def get_parameters(self, config):``" msgstr "" +"NumPyClient的子类:将``def get_parameters(self):```改为``def " +"get_parameters(self,config):``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:40 msgid "" "Subclasses of ``Client``: change ``def get_parameters(self):``` to ``def " "get_parameters(self, ins: GetParametersIns):``" msgstr "" +"客户端 \"的子类:将 \"get_parameters(self): \"改为 \"get_parameters(self, " +"ins: GetParametersIns):\"" #: ../../source/how-to-upgrade-to-flower-1.0.rst:43 msgid "Strategies / ``start_server`` / ``start_simulation``" -msgstr "" +msgstr "策略 / ``start_server`` / ``start_simulation``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:45 msgid "" "Pass ``ServerConfig`` (instead of a dictionary) to ``start_server`` and " "``start_simulation``. Here's an example:" msgstr "" +"向 ``start_server`` 和 ``start_simulation` 传递 ``ServerConfig``(而不是 " +"dictionary)。下面是一个例子:" #: ../../source/how-to-upgrade-to-flower-1.0.rst:47 msgid "" "Flower 0.19: ``start_server(..., config={\"num_rounds\": 3, " "\"round_timeout\": 600.0}, ...)``" msgstr "" +"Flower 0.19: ``start_server(..., config={\"num_rounds\": 3, " +"\"round_timeout\": 600.0}, ...)``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:48 +#, fuzzy msgid "" -"Flower 1.0: ``start_server(..., " -"config=flwr.server.ServerConfig(num_rounds=3, round_timeout=600.0), " -"...)``" +"Flower 1.0: ``start_server(..., config=flwr.server." +"ServerConfig(num_rounds=3, round_timeout=600.0), ...)``" msgstr "" +"Flower 1.0: ``start_server(..., config=flwr.server." +"ServerConfig(num_rounds=3, round_timeout=600.0), ...)``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:50 msgid "" "Replace ``num_rounds=1`` in ``start_simulation`` with the new " "``config=ServerConfig(...)`` (see previous item)" msgstr "" +"将`start_simulation``中的`num_rounds=1``替换为新的`config=ServerConfig(...)`" +"(参见前一项)" #: ../../source/how-to-upgrade-to-flower-1.0.rst:51 msgid "" "Remove ``force_final_distributed_eval`` parameter from calls to " -"``start_server``. Distributed evaluation on all clients can be enabled by" -" configuring the strategy to sample all clients for evaluation after the " -"last round of training." +"``start_server``. Distributed evaluation on all clients can be enabled by " +"configuring the strategy to sample all clients for evaluation after the last " +"round of training." msgstr "" +"删除调用 ``start_server`` 时的 ``force_final_distributed_eval` 参数。可以通过" +"配置策略,在最后一轮训练后对所有客户端进行抽样评估,从而启用对所有客户端的分" +"布式评估。" #: ../../source/how-to-upgrade-to-flower-1.0.rst:52 msgid "Rename parameter/ndarray conversion functions:" -msgstr "" +msgstr "重命名参数/数组转换函数:" #: ../../source/how-to-upgrade-to-flower-1.0.rst:54 +#, fuzzy msgid "``parameters_to_weights`` --> ``parameters_to_ndarrays``" -msgstr "" +msgstr "``parameters_to_weights`` --> ``parameters_to_ndarrays``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:55 +#, fuzzy msgid "``weights_to_parameters`` --> ``ndarrays_to_parameters``" -msgstr "" +msgstr "``weights_to_parameters`` --> ``ndarrays_to_parameters``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:57 msgid "" -"Strategy initialization: if the strategy relies on the default values for" -" ``fraction_fit`` and ``fraction_evaluate``, set ``fraction_fit`` and " +"Strategy initialization: if the strategy relies on the default values for " +"``fraction_fit`` and ``fraction_evaluate``, set ``fraction_fit`` and " "``fraction_evaluate`` manually to ``0.1``. Projects that do not manually " "create a strategy (by calling ``start_server`` or ``start_simulation`` " -"without passing a strategy instance) should now manually initialize " -"FedAvg with ``fraction_fit`` and ``fraction_evaluate`` set to ``0.1``." +"without passing a strategy instance) should now manually initialize FedAvg " +"with ``fraction_fit`` and ``fraction_evaluate`` set to ``0.1``." msgstr "" +"策略初始化:如果策略依赖于 ``fraction_fit`` 和 ``fraction_evaluate`` 的默认" +"值,请手动将 ``fraction_fit`` 和 ``fraction_evaluate`` 设置为 ``0.1``。未手动" +"创建策略的项目(调用 ``start_server` 或 ``start_simulation` 时未传递策略实" +"例)现在应手动初始化 FedAvg,并将 `fraction_fit` 和 `fraction_evaluate` 设为 " +"`0.1``。" #: ../../source/how-to-upgrade-to-flower-1.0.rst:58 msgid "Rename built-in strategy parameters (e.g., ``FedAvg``):" -msgstr "" +msgstr "重命名内置策略参数(例如,`FedAvg``):" #: ../../source/how-to-upgrade-to-flower-1.0.rst:60 +#, fuzzy msgid "``fraction_eval`` --> ``fraction_evaluate``" -msgstr "" +msgstr "``fraction_eval`` --> ``fraction_evaluate``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:61 msgid "``min_eval_clients`` --> ``min_evaluate_clients``" -msgstr "" +msgstr "``min_eval_clients`` --> ``min_evaluate_clients``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:62 msgid "``eval_fn`` --> ``evaluate_fn``" -msgstr "" +msgstr "``eval_fn`` --> ``evaluate_fn``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:64 msgid "" @@ -5270,71 +6244,89 @@ msgid "" "functions, for example, ``configure_fit``, ``aggregate_fit``, " "``configure_evaluate``, ``aggregate_evaluate``, and ``evaluate_fn``." msgstr "" +"将 `rnd` 更名为 `server_round`。这会影响多个方法和函数,例如 " +"``configure_fit``、``aggregate_fit``、``configure_evaluate``、" +"`aggregate_evaluate`` 和 ``evaluate_fn``。" #: ../../source/how-to-upgrade-to-flower-1.0.rst:65 msgid "Add ``server_round`` and ``config`` to ``evaluate_fn``:" -msgstr "" +msgstr "在 ``evaluate_fn` 中添加 ``server_round` 和 ``config`:" #: ../../source/how-to-upgrade-to-flower-1.0.rst:67 +#, fuzzy msgid "" -"Flower 0.19: ``def evaluate(parameters: NDArrays) -> " -"Optional[Tuple[float, Dict[str, Scalar]]]:``" +"Flower 0.19: ``def evaluate(parameters: NDArrays) -> Optional[Tuple[float, " +"Dict[str, Scalar]]]:``" msgstr "" +"Flower 0.19: ``def evaluate(parameters: NDArrays) -> Optional[Tuple[float, " +"Dict[str, Scalar]]]:``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:68 +#, fuzzy msgid "" -"Flower 1.0: ``def evaluate(server_round: int, parameters: NDArrays, " -"config: Dict[str, Scalar]) -> Optional[Tuple[float, Dict[str, " -"Scalar]]]:``" +"Flower 1.0: ``def evaluate(server_round: int, parameters: NDArrays, config: " +"Dict[str, Scalar]) -> Optional[Tuple[float, Dict[str, Scalar]]]:``" msgstr "" +"Flower 1.0: ``def evaluate(server_round: int, parameters: NDArrays, config: " +"Dict[str, Scalar]) -> Optional[Tuple[float, Dict[str, Scalar]]]:``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:71 msgid "Custom strategies" -msgstr "" +msgstr "定制战略" #: ../../source/how-to-upgrade-to-flower-1.0.rst:73 msgid "" -"The type of parameter ``failures`` has changed from " -"``List[BaseException]`` to ``List[Union[Tuple[ClientProxy, FitRes], " -"BaseException]]`` (in ``aggregate_fit``) and " -"``List[Union[Tuple[ClientProxy, EvaluateRes], BaseException]]`` (in " -"``aggregate_evaluate``)" +"The type of parameter ``failures`` has changed from ``List[BaseException]`` " +"to ``List[Union[Tuple[ClientProxy, FitRes], BaseException]]`` (in " +"``aggregate_fit``) and ``List[Union[Tuple[ClientProxy, EvaluateRes], " +"BaseException]]`` (in ``aggregate_evaluate``)" msgstr "" +"参数``failures``的类型已从``List[BaseException]``变为" +"``List[Union[Tuple[ClientProxy, FitRes], BaseException]]``(在" +"``agregate_fit``中)和``List[Union[Tuple[ClientProxy, EvaluateRes], " +"BaseException]]``(在``agregate_evaluate``中)" #: ../../source/how-to-upgrade-to-flower-1.0.rst:74 msgid "" "The ``Strategy`` method ``evaluate`` now receives the current round of " "federated learning/evaluation as the first parameter:" -msgstr "" +msgstr "策略 \"方法 \"评估 \"现在会接收当前一轮联合学习/评估作为第一个参数:" #: ../../source/how-to-upgrade-to-flower-1.0.rst:76 msgid "" "Flower 0.19: ``def evaluate(self, parameters: Parameters) -> " "Optional[Tuple[float, Dict[str, Scalar]]]:``" msgstr "" +"Flower 0.19: ``def evaluate(self, parameters: 参数) -> Optional[Tuple[float, " +"Dict[str, Scalar]]]:```" #: ../../source/how-to-upgrade-to-flower-1.0.rst:77 +#, fuzzy msgid "" -"Flower 1.0: ``def evaluate(self, server_round: int, parameters: " -"Parameters) -> Optional[Tuple[float, Dict[str, Scalar]]]:``" +"Flower 1.0: ``def evaluate(self, server_round: int, parameters: Parameters) -" +"> Optional[Tuple[float, Dict[str, Scalar]]]:``" msgstr "" +"Flower 1.0: ``def evaluate(self, server_round: int, parameters: Parameters) -" +"> Optional[Tuple[float, Dict[str, Scalar]]]:``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:80 msgid "Optional improvements" -msgstr "" +msgstr "可选的改进措施" #: ../../source/how-to-upgrade-to-flower-1.0.rst:82 msgid "" "Along with the necessary changes above, there are a number of potential " "improvements that just became possible:" -msgstr "" +msgstr "除了上述必要的改动之外,还有一些潜在的改进措施刚刚成为可能:" #: ../../source/how-to-upgrade-to-flower-1.0.rst:84 msgid "" "Remove \"placeholder\" methods from subclasses of ``Client`` or " -"``NumPyClient``. If you, for example, use server-side evaluation, then " -"empy placeholder implementations of ``evaluate`` are no longer necessary." +"``NumPyClient``. If you, for example, use server-side evaluation, then empy " +"placeholder implementations of ``evaluate`` are no longer necessary." msgstr "" +"删除 ``Client`` 或 ``NumPyClient`` 子类中的 \"占位符 \"方法。例如,如果你使用" +"服务器端评估,那么就不再需要``evaluate``的 \"repy占位符 \"实现。" #: ../../source/how-to-upgrade-to-flower-1.0.rst:85 msgid "" @@ -5342,67 +6334,77 @@ msgid "" "``start_simulation(..., config=flwr.server.ServerConfig(num_rounds=3, " "round_timeout=600.0), ...)``" msgstr "" +"通过 ``start_simulation`` 配置循环超时: ``start_simulation(..., config=flwr." +"server.ServerConfig(num_rounds=3, round_timeout=600.0), ...)``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:89 msgid "Further help" -msgstr "" +msgstr "更多帮助" #: ../../source/how-to-upgrade-to-flower-1.0.rst:91 msgid "" -"Most official `Flower code examples " -"`_ are already updated" -" to Flower 1.0, they can serve as a reference for using the Flower 1.0 " -"API. If there are further questionsm, `join the Flower Slack " -"`_ and use the channgel ``#questions``." +"Most official `Flower code examples `_ are already updated to Flower 1.0, they can serve as a " +"reference for using the Flower 1.0 API. If there are further questionsm, " +"`join the Flower Slack `_ and use the " +"channgel ``#questions``." msgstr "" +"大多数官方的 \"Flower 代码示例 `_ 已经更新到 Flower 1.0,它们可以作为使用 Flower 1.0 API 的参考。如" +"果还有其他问题,请加入 Flower Slack `_ 并使" +"用 \"#questions``\"。" #: ../../source/how-to-use-strategies.rst:2 msgid "Use strategies" -msgstr "" +msgstr "使用策略" #: ../../source/how-to-use-strategies.rst:4 msgid "" -"Flower allows full customization of the learning process through the " -":code:`Strategy` abstraction. A number of built-in strategies are " -"provided in the core framework." +"Flower allows full customization of the learning process through the :code:" +"`Strategy` abstraction. A number of built-in strategies are provided in the " +"core framework." msgstr "" +"Flower 允许通过 :code:`Strategy` 抽象对学习过程进行完全定制。核心框架中提供了" +"许多内置策略。" #: ../../source/how-to-use-strategies.rst:6 msgid "" -"There are three ways to customize the way Flower orchestrates the " -"learning process on the server side:" -msgstr "" +"There are three ways to customize the way Flower orchestrates the learning " +"process on the server side:" +msgstr "有三种方法可以自定义 Flower 在服务器端协调学习过程的方式:" #: ../../source/how-to-use-strategies.rst:8 msgid "Use an existing strategy, for example, :code:`FedAvg`" -msgstr "" +msgstr "使用现有策略,例如 :code:`FedAvg`" #: ../../source/how-to-use-strategies.rst:9 #: ../../source/how-to-use-strategies.rst:40 msgid "Customize an existing strategy with callback functions" -msgstr "" +msgstr "使用回调函数定制现有策略" #: ../../source/how-to-use-strategies.rst:10 #: ../../source/how-to-use-strategies.rst:87 msgid "Implement a novel strategy" -msgstr "" +msgstr "实施新颖战略" #: ../../source/how-to-use-strategies.rst:14 msgid "Use an existing strategy" -msgstr "" +msgstr "使用现有战略" #: ../../source/how-to-use-strategies.rst:16 msgid "" -"Flower comes with a number of popular federated learning strategies " -"built-in. A built-in strategy can be instantiated as follows:" -msgstr "" +"Flower comes with a number of popular federated learning strategies built-" +"in. A built-in strategy can be instantiated as follows:" +msgstr "Flower 内置了许多流行的联合学习策略。内置策略的实例化方法如下:" #: ../../source/how-to-use-strategies.rst:25 msgid "" -"This creates a strategy with all parameters left at their default values " -"and passes it to the :code:`start_server` function. It is usually " -"recommended to adjust a few parameters during instantiation:" +"This creates a strategy with all parameters left at their default values and " +"passes it to the :code:`start_server` function. It is usually recommended to " +"adjust a few parameters during instantiation:" msgstr "" +"这会创建一个所有参数都保持默认值的策略,并将其传递给 :code:`start_server` 函" +"数。通常建议在实例化过程中调整一些参数:" #: ../../source/how-to-use-strategies.rst:42 msgid "" @@ -5410,118 +6412,132 @@ msgid "" "Callback functions allow strategies to call user-provided code during " "execution." msgstr "" +"现有的策略提供了多种自定义行为的方法。回调函数允许策略在执行过程中调用用户提" +"供的代码。" #: ../../source/how-to-use-strategies.rst:45 msgid "Configuring client fit and client evaluate" -msgstr "" +msgstr "配置客户匹配和客户评估" #: ../../source/how-to-use-strategies.rst:47 msgid "" "The server can pass new configuration values to the client each round by " -"providing a function to :code:`on_fit_config_fn`. The provided function " -"will be called by the strategy and must return a dictionary of " -"configuration key values pairs that will be sent to the client. It must " -"return a dictionary of arbitraty configuration values :code:`client.fit`" -" and :code:`client.evaluate` functions during each round of federated " -"learning." +"providing a function to :code:`on_fit_config_fn`. The provided function will " +"be called by the strategy and must return a dictionary of configuration key " +"values pairs that will be sent to the client. It must return a dictionary of " +"arbitraty configuration values :code:`client.fit` and :code:`client." +"evaluate` functions during each round of federated learning." msgstr "" +"服务器可以通过向 :code:`on_fit_config_fn` 提供一个函数,在每一轮向客户端传递" +"新的配置值。提供的函数将被策略调用,并且必须返回一个配置键值对的字典,该字典" +"将被发送到客户端。在每一轮联合学习期间,它必须返回一个任意配置值 dictionary :" +"code:`client.fit`和 :code:`client.evaluate`函数。" #: ../../source/how-to-use-strategies.rst:75 msgid "" "The :code:`on_fit_config_fn` can be used to pass arbitrary configuration " "values from server to client, and poetentially change these values each " -"round, for example, to adjust the learning rate. The client will receive " -"the dictionary returned by the :code:`on_fit_config_fn` in its own " -":code:`client.fit()` function." +"round, for example, to adjust the learning rate. The client will receive the " +"dictionary returned by the :code:`on_fit_config_fn` in its own :code:`client." +"fit()` function." msgstr "" +":code:`on_fit_config_fn`可用于将任意配置值从服务器传递到客户端,并在每一轮诗" +"意地改变这些值,例如,调整学习率。客户端将在自己的 :code:`client.fit()` 函数" +"中接收 :code:`on_fit_config_fn` 返回的字典。" #: ../../source/how-to-use-strategies.rst:78 msgid "" -"Similar to :code:`on_fit_config_fn`, there is also " -":code:`on_evaluate_config_fn` to customize the configuration sent to " -":code:`client.evaluate()`" +"Similar to :code:`on_fit_config_fn`, there is also :code:" +"`on_evaluate_config_fn` to customize the configuration sent to :code:`client." +"evaluate()`" msgstr "" +"与 :code:`on_fit_config_fn` 类似,还有 :code:`on_evaluate_config_fn` 用于定制" +"发送到 :code:`client.evaluate()` 的配置" #: ../../source/how-to-use-strategies.rst:81 msgid "Configuring server-side evaluation" -msgstr "" +msgstr "配置服务器端评估" #: ../../source/how-to-use-strategies.rst:83 msgid "" -"Server-side evaluation can be enabled by passing an evaluation function " -"to :code:`evaluate_fn`." -msgstr "" +"Server-side evaluation can be enabled by passing an evaluation function to :" +"code:`evaluate_fn`." +msgstr "服务器端评估可通过向 :code:`evaluate_fn` 传递评估函数来启用。" #: ../../source/how-to-use-strategies.rst:89 msgid "" -"Writing a fully custom strategy is a bit more involved, but it provides " -"the most flexibility. Read the `Implementing Strategies `_ guide to learn more." +"Writing a fully custom strategy is a bit more involved, but it provides the " +"most flexibility. Read the `Implementing Strategies `_ guide to learn more." msgstr "" +"编写完全自定义的策略涉及的内容较多,但灵活性最高。阅读 \"实施策略\"_ 指南,了解更多信息。" #: ../../source/index.rst:34 msgid "Tutorial" -msgstr "" +msgstr "教程" #: ../../source/index.rst:44 msgid "Quickstart tutorials" -msgstr "" +msgstr "快速入门教程" #: ../../source/index.rst:75 ../../source/index.rst:79 msgid "How-to guides" -msgstr "" +msgstr "操作指南" #: ../../source/index.rst:95 msgid "Legacy example guides" -msgstr "" +msgstr "旧版指南范例" #: ../../source/index.rst:106 ../../source/index.rst:110 msgid "Explanations" -msgstr "" +msgstr "说明" #: ../../source/index.rst:122 msgid "API reference" -msgstr "" +msgstr "应用程序接口参考" #: ../../source/index.rst:129 msgid "Reference docs" -msgstr "" +msgstr "参考文档" #: ../../source/index.rst:145 msgid "Contributor tutorials" -msgstr "" +msgstr "贡献者教程" #: ../../source/index.rst:152 msgid "Contributor how-to guides" -msgstr "" +msgstr "投稿指南" #: ../../source/index.rst:164 msgid "Contributor explanations" -msgstr "" +msgstr "贡献者解释" #: ../../source/index.rst:170 msgid "Contributor references" -msgstr "" +msgstr "贡献者参考资料" #: ../../source/index.rst:-1 msgid "" "Check out the documentation of the main Flower Framework enabling easy " "Python development for Federated Learning." -msgstr "" +msgstr "查看主 Flower Framework 的文档,轻松实现联合学习的 Python 开发。" #: ../../source/index.rst:2 msgid "Flower Framework Documentation" -msgstr "" +msgstr "Flower 框架文档" #: ../../source/index.rst:7 msgid "" "Welcome to Flower's documentation. `Flower `_ is a " "friendly federated learning framework." msgstr "" +"欢迎访问 Flower 文档。`Flower `_ 是一个友好的联合学习框" +"架。" #: ../../source/index.rst:11 msgid "Join the Flower Community" -msgstr "" +msgstr "加入 Flower 社区" #: ../../source/index.rst:13 msgid "" @@ -5529,120 +6545,139 @@ msgid "" "researchers, engineers, students, professionals, academics, and other " "enthusiasts." msgstr "" +"Flower 社区发展迅速--我们是一个由研究人员、工程师、学生、专业人士、学者和其他" +"爱好者组成的友好团体。" #: ../../source/index.rst:15 msgid "Join us on Slack" -msgstr "" +msgstr "在 Slack 上加入我们" #: ../../source/index.rst:23 msgid "Flower Framework" -msgstr "" +msgstr "Flower 框架" #: ../../source/index.rst:25 msgid "" "The user guide is targeted at researchers and developers who want to use " "Flower to bring existing machine learning workloads into a federated " -"setting. One of Flower's design goals was to make this simple. Read on to" -" learn more." +"setting. One of Flower's design goals was to make this simple. Read on to " +"learn more." msgstr "" +"该用户指南面向希望使用 Flower 将现有机器学习工作负载引入联合环境的研究人员和" +"开发人员。Flower 的设计目标之一就是让这一切变得简单。请继续阅读,了解更多信" +"息。" #: ../../source/index.rst:30 msgid "Tutorials" -msgstr "" +msgstr "教程" #: ../../source/index.rst:32 msgid "" -"A learning-oriented series of federated learning tutorials, the best " -"place to start." -msgstr "" +"A learning-oriented series of federated learning tutorials, the best place " +"to start." +msgstr "以学习为导向的联合学习教程系列,最好的起点。" #: ../../source/index.rst:62 -msgid "" -"QUICKSTART TUTORIALS: :doc:`PyTorch ` | " -":doc:`TensorFlow ` | :doc:`🤗 Transformers" -" ` | :doc:`JAX ` | :doc:`Pandas ` | :doc:`fastai " -"` | :doc:`PyTorch Lightning ` | :doc:`MXNet `" -" | :doc:`scikit-learn ` | :doc:`XGBoost " -"` | :doc:`Android ` | :doc:`iOS `" -msgstr "" +#, fuzzy +msgid "" +"QUICKSTART TUTORIALS: :doc:`PyTorch ` | :doc:" +"`TensorFlow ` | :doc:`🤗 Transformers " +"` | :doc:`JAX ` | :" +"doc:`Pandas ` | :doc:`fastai ` | :doc:`PyTorch Lightning ` | :doc:`MXNet ` | :doc:`scikit-learn " +"` | :doc:`XGBoost ` | :doc:`Android ` | :doc:`iOS " +"`" +msgstr "" +"QUICKSTART TUTORIALS: :doc:`PyTorch ` | :doc:" +"`TensorFlow ` | :doc:`🤗 Transformers " +"` | :doc:`JAX ` | :" +"doc:`Pandas ` | :doc:`fastai ` | :doc:`PyTorch Lightning ` | :doc:`MXNet ` | :doc:`scikit-learn " +"` | :doc:`XGBoost ` | :doc:`Android ` | :doc:`iOS " +"`" #: ../../source/index.rst:64 msgid "We also made video tutorials for PyTorch:" -msgstr "" +msgstr "我们还为 PyTorch 制作了视频教程:" #: ../../source/index.rst:69 msgid "And TensorFlow:" -msgstr "" +msgstr "还有 TensorFlow:" #: ../../source/index.rst:77 msgid "" -"Problem-oriented how-to guides show step-by-step how to achieve a " -"specific goal." -msgstr "" +"Problem-oriented how-to guides show step-by-step how to achieve a specific " +"goal." +msgstr "以问题为导向的 \"如何做 \"指南逐步展示如何实现特定目标。" #: ../../source/index.rst:108 msgid "" "Understanding-oriented concept guides explain and discuss key topics and " "underlying ideas behind Flower and collaborative AI." msgstr "" +"以理解为导向的概念指南解释并讨论了花朵和协作式人工智能背后的关键主题和基本思" +"想。" #: ../../source/index.rst:118 msgid "References" -msgstr "" +msgstr "参考资料" #: ../../source/index.rst:120 msgid "Information-oriented API reference and other reference material." -msgstr "" +msgstr "以信息为导向的 API 参考资料和其他参考资料。" #: ../../source/index.rst:140 msgid "Contributor docs" -msgstr "" +msgstr "投稿文档" #: ../../source/index.rst:142 msgid "" -"The Flower community welcomes contributions. The following docs are " -"intended to help along the way." -msgstr "" +"The Flower community welcomes contributions. The following docs are intended " +"to help along the way." +msgstr "Flower 社区欢迎您的贡献。以下文档旨在为您提供帮助。" #: ../../source/ref-api-cli.rst:2 msgid "Flower CLI reference" -msgstr "" +msgstr "Flower CLI 参考" #: ../../source/ref-api-cli.rst:7 msgid "flower-server" -msgstr "" +msgstr "Flower 服务器" #: ../../source/ref-api-cli.rst:17 +#, fuzzy msgid "flower-driver-api" -msgstr "" +msgstr "flower-driver-api" #: ../../source/ref-api-cli.rst:27 +#, fuzzy msgid "flower-fleet-api" -msgstr "" +msgstr "flower-fleet-api" #: ../../source/ref-api-flwr.rst:2 msgid "flwr (Python API reference)" -msgstr "" +msgstr "flwr(Python API 参考)" #: ../../source/ref-api-flwr.rst:8 msgid "client" -msgstr "" +msgstr "客户端" #: flwr.client:1 of msgid "Flower client." -msgstr "" +msgstr "Flower 客户端。" #: flwr.client.client.Client:1 of msgid "Abstract base class for Flower clients." -msgstr "" +msgstr "Flower 客户端的抽象基类。" #: flwr.client.client.Client.evaluate:1 #: flwr.client.numpy_client.NumPyClient.evaluate:1 of msgid "Evaluate the provided parameters using the locally held dataset." -msgstr "" +msgstr "使用本地数据集评估所提供的参数。" #: flwr.client.app.start_client flwr.client.app.start_numpy_client #: flwr.client.client.Client.evaluate flwr.client.client.Client.fit @@ -5674,14 +6709,16 @@ msgstr "" #: flwr.server.strategy.strategy.Strategy.initialize_parameters #: flwr.simulation.app.start_simulation of msgid "Parameters" -msgstr "" +msgstr "参数" #: flwr.client.client.Client.evaluate:3 of msgid "" -"The evaluation instructions containing (global) model parameters received" -" from the server and a dictionary of configuration values used to " -"customize the local evaluation process." +"The evaluation instructions containing (global) model parameters received " +"from the server and a dictionary of configuration values used to customize " +"the local evaluation process." msgstr "" +"评估指令包含从服务器接收的(全局)模型参数,以及用于定制本地评估流程的配置值" +"字典。" #: flwr.client.client.Client.evaluate flwr.client.client.Client.fit #: flwr.client.client.Client.get_parameters @@ -5701,13 +6738,15 @@ msgstr "" #: flwr.server.strategy.strategy.Strategy.initialize_parameters #: flwr.simulation.app.start_simulation of msgid "Returns" -msgstr "" +msgstr "返回" #: flwr.client.client.Client.evaluate:8 of msgid "" "The evaluation result containing the loss on the local dataset and other " "details such as the number of local data examples used for evaluation." msgstr "" +"评估结果包含本地数据集上的损失和其他详细信息,如用于评估的本地数据示例的数" +"量。" #: flwr.client.client.Client.evaluate flwr.client.client.Client.fit #: flwr.client.client.Client.get_parameters @@ -5725,131 +6764,142 @@ msgstr "" #: flwr.server.strategy.strategy.Strategy.initialize_parameters #: flwr.simulation.app.start_simulation of msgid "Return type" -msgstr "" +msgstr "返回类型" #: flwr.client.client.Client.fit:1 of msgid "Refine the provided parameters using the locally held dataset." -msgstr "" +msgstr "利用本地数据集完善所提供的参数。" #: flwr.client.client.Client.fit:3 of msgid "" -"The training instructions containing (global) model parameters received " -"from the server and a dictionary of configuration values used to " -"customize the local training process." +"The training instructions containing (global) model parameters received from " +"the server and a dictionary of configuration values used to customize the " +"local training process." msgstr "" +"训练指令,包含从服务器接收的(全局)模型参数,以及用于定制本地训练过程的配置" +"值字典。" #: flwr.client.client.Client.fit:8 of msgid "" -"The training result containing updated parameters and other details such " -"as the number of local training examples used for training." -msgstr "" +"The training result containing updated parameters and other details such as " +"the number of local training examples used for training." +msgstr "训练结果包含更新的参数和其他详细信息,如用于训练的本地训练示例的数量。" #: flwr.client.client.Client.get_parameters:1 #: flwr.client.numpy_client.NumPyClient.get_parameters:1 of msgid "Return the current local model parameters." -msgstr "" +msgstr "返回当前本地模型参数。" #: flwr.client.client.Client.get_parameters:3 of msgid "" "The get parameters instructions received from the server containing a " "dictionary of configuration values." -msgstr "" +msgstr "从服务器接收的获取参数指令包含配置值字典。" #: flwr.client.client.Client.get_parameters:7 of msgid "The current local model parameters." -msgstr "" +msgstr "当前的本地模型参数。" #: flwr.client.client.Client.get_properties:1 of msgid "Return set of client's properties." -msgstr "" +msgstr "返回客户端的属性集。" #: flwr.client.client.Client.get_properties:3 of msgid "" "The get properties instructions received from the server containing a " "dictionary of configuration values." -msgstr "" +msgstr "从服务器接收的获取属性指令包含配置值字典。" #: flwr.client.client.Client.get_properties:7 of msgid "The current client properties." -msgstr "" +msgstr "当前客户端属性。" #: flwr.client.client.Client.to_client:1 of msgid "Return client (itself)." -msgstr "" +msgstr "返回客户端(本身)。" #: ../../source/ref-api-flwr.rst:24 msgid "start_client" -msgstr "" +msgstr "启动客户端" #: flwr.client.app.start_client:1 of msgid "Start a Flower client node which connects to a Flower server." -msgstr "" +msgstr "启动一个 Flower 客户节点,连接到 Flower 服务器。" #: flwr.client.app.start_client:3 flwr.client.app.start_numpy_client:3 of msgid "" "The IPv4 or IPv6 address of the server. If the Flower server runs on the " -"same machine on port 8080, then `server_address` would be " -"`\"[::]:8080\"`." +"same machine on port 8080, then `server_address` would be `\"[::]:8080\"`." msgstr "" +"服务器的 IPv4 或 IPv6 地址。如果 Flower 服务器在同一台机器上运行,端口为 " +"8080,则`server_address`应为`\"[::]:8080\"`。" #: flwr.client.app.start_client:7 of msgid "..." -msgstr "" +msgstr "..." #: flwr.client.app.start_client:9 of msgid "A callable that instantiates a Client. (default: None)" -msgstr "" +msgstr "用于实例化客户端的可调用程序。(默认值:无)" #: flwr.client.app.start_client:11 of msgid "" -"An implementation of the abstract base class `flwr.client.Client` " -"(default: None)" -msgstr "" +"An implementation of the abstract base class `flwr.client.Client` (default: " +"None)" +msgstr "抽象基类 `flwr.client.Client` 的实现(默认值:无)" #: flwr.client.app.start_client:14 flwr.client.app.start_numpy_client:9 of msgid "" -"The maximum length of gRPC messages that can be exchanged with the Flower" -" server. The default should be sufficient for most models. Users who " -"train very large models might need to increase this value. Note that the " -"Flower server needs to be started with the same value (see " -"`flwr.server.start_server`), otherwise it will not know about the " -"increased limit and block larger messages." +"The maximum length of gRPC messages that can be exchanged with the Flower " +"server. The default should be sufficient for most models. Users who train " +"very large models might need to increase this value. Note that the Flower " +"server needs to be started with the same value (see `flwr.server." +"start_server`), otherwise it will not know about the increased limit and " +"block larger messages." msgstr "" +"可与 Flower 服务器交换的 gRPC 信息的最大长度。默认值对大多数模型都足够了。训" +"练超大模型的用户可能需要增加该值。请注意,Flower 服务器需要以相同的值启动(请" +"参阅 `flwr.server.start_server`),否则它将不知道增加的限制并阻止更大的消息。" #: flwr.client.app.start_client:21 flwr.client.app.start_numpy_client:16 of msgid "" "The PEM-encoded root certificates as a byte string or a path string. If " -"provided, a secure connection using the certificates will be established " -"to an SSL-enabled Flower server." +"provided, a secure connection using the certificates will be established to " +"an SSL-enabled Flower server." msgstr "" +"字节字符串或路径字符串形式的 PEM 编码根证书。如果提供,将使用这些证书与启用 " +"SSL 的 Flower 服务器建立安全连接。" #: flwr.client.app.start_client:25 flwr.client.app.start_numpy_client:20 of msgid "" "Configure the transport layer. Allowed values: - 'grpc-bidi': gRPC, " -"bidirectional streaming - 'grpc-rere': gRPC, request-response " -"(experimental) - 'rest': HTTP (experimental)" +"bidirectional streaming - 'grpc-rere': gRPC, request-response (experimental) " +"- 'rest': HTTP (experimental)" msgstr "" +"配置传输层。允许值 - grpc-bidi\":gRPC,双向流 - \"grpc-rere\":gRPC,请求-响" +"应(实验性) - \"rest\":HTTP(实验性) - \"grpc-rere\":gRPC,双向流 HTTP" +"(试验性)" #: flwr.client.app.start_client:32 flwr.client.app.start_numpy_client:27 #: flwr.server.app.start_server:41 of msgid "Examples" -msgstr "" +msgstr "实例" #: flwr.client.app.start_client:33 of msgid "Starting a gRPC client with an insecure server connection:" -msgstr "" +msgstr "使用不安全的服务器连接启动 gRPC 客户端:" #: flwr.client.app.start_client:43 flwr.client.app.start_numpy_client:35 of msgid "Starting an SSL-enabled gRPC client:" -msgstr "" +msgstr "启动支持 SSL 的 gRPC 客户端:" #: ../../source/ref-api-flwr.rst:32 msgid "NumPyClient" -msgstr "" +msgstr "NumPyClient" #: flwr.client.numpy_client.NumPyClient:1 of msgid "Abstract base class for Flower clients using NumPy." -msgstr "" +msgstr "使用 NumPy 的 Flower 客户端的抽象基类。" #: flwr.client.numpy_client.NumPyClient.evaluate:3 #: flwr.client.numpy_client.NumPyClient.fit:3 @@ -5859,195 +6909,232 @@ msgstr "" #: flwr.server.strategy.strategy.Strategy.configure_fit:5 #: flwr.server.strategy.strategy.Strategy.evaluate:8 of msgid "The current (global) model parameters." -msgstr "" +msgstr "当前(全局)模型参数。" #: flwr.client.numpy_client.NumPyClient.evaluate:5 of msgid "" -"Configuration parameters which allow the server to influence evaluation " -"on the client. It can be used to communicate arbitrary values from the " -"server to the client, for example, to influence the number of examples " -"used for evaluation." +"Configuration parameters which allow the server to influence evaluation on " +"the client. It can be used to communicate arbitrary values from the server " +"to the client, for example, to influence the number of examples used for " +"evaluation." msgstr "" +"允许服务器影响客户端评估的配置参数。它可用于将任意值从服务器传送到客户端,例" +"如,影响用于评估的示例数量。" #: flwr.client.numpy_client.NumPyClient.evaluate:11 of msgid "" "* **loss** (*float*) -- The evaluation loss of the model on the local " "dataset. * **num_examples** (*int*) -- The number of examples used for " "evaluation. * **metrics** (*Dict[str, Scalar]*) -- A dictionary mapping " -"arbitrary string keys to values of type bool, bytes, float, int, or " -"str. It can be used to communicate arbitrary values back to the server." +"arbitrary string keys to values of type bool, bytes, float, int, or str. " +"It can be used to communicate arbitrary values back to the server." msgstr "" +"**loss** (*float*) -- 模型在本地数据集上的评估损失。**num_examples** (*int*) " +"-- 用于评估的示例数量。**metrics** (*Dict[str, Scalar]*) -- 将任意字符串键映" +"射到 bool、bytes、float、int 或 str 类型值的字典。它可用于将任意值传回服务" +"器。" #: flwr.client.numpy_client.NumPyClient.evaluate:11 of msgid "" -"**loss** (*float*) -- The evaluation loss of the model on the local " -"dataset." -msgstr "" +"**loss** (*float*) -- The evaluation loss of the model on the local dataset." +msgstr "**loss** (*float*) -- 模型在本地数据集上的评估损失。" #: flwr.client.numpy_client.NumPyClient.evaluate:12 of msgid "**num_examples** (*int*) -- The number of examples used for evaluation." -msgstr "" +msgstr "**num_examples** (*int*) -- 用于评估的示例数量。" #: flwr.client.numpy_client.NumPyClient.evaluate:13 #: flwr.client.numpy_client.NumPyClient.fit:13 of msgid "" -"**metrics** (*Dict[str, Scalar]*) -- A dictionary mapping arbitrary " -"string keys to values of type bool, bytes, float, int, or str. It can be " -"used to communicate arbitrary values back to the server." +"**metrics** (*Dict[str, Scalar]*) -- A dictionary mapping arbitrary string " +"keys to values of type bool, bytes, float, int, or str. It can be used to " +"communicate arbitrary values back to the server." msgstr "" +"**metrics** (*Dict[str, Scalar]*) -- 将任意字符串键映射到 bool、bytes、" +"float、int 或 str 类型值的字典。它可用于将任意值传回服务器。" #: flwr.client.numpy_client.NumPyClient.evaluate:19 of msgid "" -"The previous return type format (int, float, float) and the extended " -"format (int, float, float, Dict[str, Scalar]) have been deprecated and " -"removed since Flower 0.19." +"The previous return type format (int, float, float) and the extended format " +"(int, float, float, Dict[str, Scalar]) have been deprecated and removed " +"since Flower 0.19." msgstr "" +"自 Flower 0.19 起,之前的返回类型格式(int、float、float)和扩展格式(int、" +"float、float、Dict[str, Scalar])已被弃用和移除。" #: flwr.client.numpy_client.NumPyClient.fit:1 of msgid "Train the provided parameters using the locally held dataset." -msgstr "" +msgstr "使用本地数据集训练所提供的参数。" #: flwr.client.numpy_client.NumPyClient.fit:5 of msgid "" -"Configuration parameters which allow the server to influence training on " -"the client. It can be used to communicate arbitrary values from the " -"server to the client, for example, to set the number of (local) training " -"epochs." +"Configuration parameters which allow the server to influence training on the " +"client. It can be used to communicate arbitrary values from the server to " +"the client, for example, to set the number of (local) training epochs." msgstr "" +"允许服务器影响客户端训练的配置参数。它可用于将任意值从服务器传送到客户端,例" +"如设置(本地)训练历元数。" #: flwr.client.numpy_client.NumPyClient.fit:11 of msgid "" "* **parameters** (*NDArrays*) -- The locally updated model parameters. * " "**num_examples** (*int*) -- The number of examples used for training. * " -"**metrics** (*Dict[str, Scalar]*) -- A dictionary mapping arbitrary " -"string keys to values of type bool, bytes, float, int, or str. It can " -"be used to communicate arbitrary values back to the server." +"**metrics** (*Dict[str, Scalar]*) -- A dictionary mapping arbitrary string " +"keys to values of type bool, bytes, float, int, or str. It can be used to " +"communicate arbitrary values back to the server." msgstr "" +"**parameters** (*NDArrays*) -- 本地更新的模型参数。**num_examples** (*int*) " +"-- 用于训练的示例数量。**metrics** (*Dict[str, Scalar]*) -- 将任意字符串键映" +"射到 bool、bytes、float、int 或 str 类型值的字典。它可用于将任意值传回服务" +"器。" #: flwr.client.numpy_client.NumPyClient.fit:11 of msgid "**parameters** (*NDArrays*) -- The locally updated model parameters." -msgstr "" +msgstr "**parameters** (*NDArrays*) -- 本地更新的模型参数。" #: flwr.client.numpy_client.NumPyClient.fit:12 of msgid "**num_examples** (*int*) -- The number of examples used for training." -msgstr "" +msgstr "**num_examples** (*int*) -- 用于训练的示例数量。" #: flwr.client.numpy_client.NumPyClient.get_parameters:3 of msgid "" -"Configuration parameters requested by the server. This can be used to " -"tell the client which parameters are needed along with some Scalar " -"attributes." +"Configuration parameters requested by the server. This can be used to tell " +"the client which parameters are needed along with some Scalar attributes." msgstr "" +"服务器请求的配置参数。这可以用来告诉客户端需要哪些参数以及一些标量属性。" #: flwr.client.numpy_client.NumPyClient.get_parameters:8 of -msgid "**parameters** -- The local model parameters as a list of NumPy ndarrays." -msgstr "" +msgid "" +"**parameters** -- The local model parameters as a list of NumPy ndarrays." +msgstr "**parameters** -- NumPy ndarrays 的本地模型参数列表。" #: flwr.client.numpy_client.NumPyClient.get_properties:1 of msgid "Return a client's set of properties." -msgstr "" +msgstr "返回客户端的属性集。" #: flwr.client.numpy_client.NumPyClient.get_properties:3 of msgid "" -"Configuration parameters requested by the server. This can be used to " -"tell the client which properties are needed along with some Scalar " -"attributes." +"Configuration parameters requested by the server. This can be used to tell " +"the client which properties are needed along with some Scalar attributes." msgstr "" +"服务器请求的配置参数。这可以用来告诉客户端需要哪些属性以及一些标量属性。" #: flwr.client.numpy_client.NumPyClient.get_properties:8 of msgid "" -"**properties** -- A dictionary mapping arbitrary string keys to values of" -" type bool, bytes, float, int, or str. It can be used to communicate " +"**properties** -- A dictionary mapping arbitrary string keys to values of " +"type bool, bytes, float, int, or str. It can be used to communicate " "arbitrary property values back to the server." msgstr "" +"**properties** -- 将任意字符串键映射到 bool、bytes、float、int 或 str 类型值" +"的字典。它可用于将任意属性值传回服务器。" #: flwr.client.numpy_client.NumPyClient.to_client:1 of msgid "Convert to object to Client type and return it." -msgstr "" +msgstr "将对象转换为客户类型并返回。" #: ../../source/ref-api-flwr.rst:41 msgid "start_numpy_client" -msgstr "" +msgstr "启动_numpy_客户端" #: flwr.client.app.start_numpy_client:1 of msgid "Start a Flower NumPyClient which connects to a gRPC server." -msgstr "" +msgstr "启动 Flower NumPyClient,连接到 gRPC 服务器。" #: flwr.client.app.start_numpy_client:7 of msgid "An implementation of the abstract base class `flwr.client.NumPyClient`." -msgstr "" +msgstr "抽象基类 `flwr.client.NumPyClient` 的实现。" #: flwr.client.app.start_numpy_client:28 of msgid "Starting a client with an insecure server connection:" -msgstr "" +msgstr "使用不安全的服务器连接启动客户端:" #: ../../source/ref-api-flwr.rst:49 msgid "start_simulation" -msgstr "" +msgstr "开始模拟" #: flwr.simulation.app.start_simulation:1 of msgid "Start a Ray-based Flower simulation server." -msgstr "" +msgstr "启动基于 Ray 的花朵模拟服务器。" #: flwr.simulation.app.start_simulation:3 of msgid "" -"A function creating client instances. The function must take a single " -"`str` argument called `cid`. It should return a single client instance of" -" type Client. Note that the created client instances are ephemeral and " -"will often be destroyed after a single method invocation. Since client " -"instances are not long-lived, they should not attempt to carry state over" -" method invocations. Any state required by the instance (model, dataset, " +"A function creating client instances. The function must take a single `str` " +"argument called `cid`. It should return a single client instance of type " +"Client. Note that the created client instances are ephemeral and will often " +"be destroyed after a single method invocation. Since client instances are " +"not long-lived, they should not attempt to carry state over method " +"invocations. Any state required by the instance (model, dataset, " "hyperparameters, ...) should be (re-)created in either the call to " -"`client_fn` or the call to any of the client methods (e.g., load " -"evaluation data in the `evaluate` method itself)." +"`client_fn` or the call to any of the client methods (e.g., load evaluation " +"data in the `evaluate` method itself)." msgstr "" +"创建客户端实例的函数。该函数必须接受一个名为 `cid` 的 `str` 参数。它应返回一" +"个 Client 类型的客户端实例。请注意,创建的客户端实例是短暂的,通常在调用一个" +"方法后就会被销毁。由于客户机实例不是长期存在的,它们不应试图在方法调用时携带" +"状态。实例所需的任何状态(模型、数据集、超参数......)都应在调用 `client_fn` " +"或任何客户端方法(例如,在 `evaluate` 方法中加载评估数据)时(重新)创建。" #: flwr.simulation.app.start_simulation:13 of msgid "" "The total number of clients in this simulation. This must be set if " "`clients_ids` is not set and vice-versa." msgstr "" +"本次模拟的客户总数。如果未设置 `clients_ids`,则必须设置该参数,反之亦然。" #: flwr.simulation.app.start_simulation:16 of msgid "" -"List `client_id`s for each client. This is only required if `num_clients`" -" is not set. Setting both `num_clients` and `clients_ids` with " +"List `client_id`s for each client. This is only required if `num_clients` is " +"not set. Setting both `num_clients` and `clients_ids` with " "`len(clients_ids)` not equal to `num_clients` generates an error." msgstr "" +"列出每个客户的 `client_id`。只有在未设置 `num_clients` 时才需要这样做。同时设" +"置`num_clients`和`clients_ids`,且`len(clients_ids)`不等于`num_clients`,会产" +"生错误。" #: flwr.simulation.app.start_simulation:20 of msgid "" "\"num_gpus\": 0.0}` CPU and GPU resources for a single client. Supported " -"keys are `num_cpus` and `num_gpus`. To understand the GPU utilization " -"caused by `num_gpus`, as well as using custom resources, please consult " -"the Ray documentation." +"keys are `num_cpus` and `num_gpus`. To understand the GPU utilization caused " +"by `num_gpus`, as well as using custom resources, please consult the Ray " +"documentation." msgstr "" +"\"num_gpus\": 0.0}` 单个客户端的 CPU 和 GPU 资源。支持的键值为 `num_cpus` " +"和 `num_gpus`。要了解 `num_gpus` 所导致的 GPU 利用率,以及使用自定义资源的情" +"况,请查阅 Ray 文档。" #: flwr.simulation.app.start_simulation:25 of msgid "" "An implementation of the abstract base class `flwr.server.Server`. If no " "instance is provided, then `start_server` will create one." msgstr "" +"抽象基类 `flwr.server.Server`的实现。如果没有提供实例,`start_server` 将创建" +"一个。" #: flwr.server.app.start_server:9 flwr.simulation.app.start_simulation:28 of msgid "" "Currently supported values are `num_rounds` (int, default: 1) and " "`round_timeout` in seconds (float, default: None)." msgstr "" +"目前支持的值有:`num_rounds`(int,默认值:1)和以秒为单位的`round_timeout`" +"(float,默认值:无)。" #: flwr.simulation.app.start_simulation:31 of msgid "" -"An implementation of the abstract base class `flwr.server.Strategy`. If " -"no strategy is provided, then `start_server` will use " -"`flwr.server.strategy.FedAvg`." +"An implementation of the abstract base class `flwr.server.Strategy`. If no " +"strategy is provided, then `start_server` will use `flwr.server.strategy." +"FedAvg`." msgstr "" +"抽象基类 `flwr.server.strategy` 的实现。如果没有提供策略,`start_server` 将使" +"用 `flwr.server.strategy.FedAvg`。" #: flwr.simulation.app.start_simulation:35 of msgid "" -"An implementation of the abstract base class `flwr.server.ClientManager`." -" If no implementation is provided, then `start_simulation` will use " -"`flwr.server.client_manager.SimpleClientManager`." +"An implementation of the abstract base class `flwr.server.ClientManager`. If " +"no implementation is provided, then `start_simulation` will use `flwr.server." +"client_manager.SimpleClientManager`." msgstr "" +"抽象基类 `flwr.server.ClientManager` 的实现。如果没有提供实现," +"`start_simulation` 将使用 `flwr.server.client_manager.SimpleClientManager`。" #: flwr.simulation.app.start_simulation:39 of msgid "" @@ -6055,9 +7142,12 @@ msgid "" "ray_init_args is None (the default), Ray will be initialized with the " "following default args: { \"ignore_reinit_error\": True, " "\"include_dashboard\": False } An empty dictionary can be used " -"(ray_init_args={}) to prevent any arguments from being passed to " -"ray.init." +"(ray_init_args={}) to prevent any arguments from being passed to ray.init." msgstr "" +"可选字典,包含调用 `ray.init` 时的参数。如果 ray_init_args 为 None(默认" +"值),则将使用以下默认参数初始化 Ray: { \"ignore_reinit_error\": True, " +"\"include_dashboard\": False } 可以使用空字典(ray_init_args={})来防止向 " +"ray.init 传递任何参数。" #: flwr.simulation.app.start_simulation:39 of msgid "" @@ -6065,159 +7155,184 @@ msgid "" "ray_init_args is None (the default), Ray will be initialized with the " "following default args:" msgstr "" +"可选字典,包含调用 `ray.init` 时的参数。如果 ray_init_args 为 None(默认" +"值),则将使用以下默认参数初始化 Ray:" #: flwr.simulation.app.start_simulation:43 of msgid "{ \"ignore_reinit_error\": True, \"include_dashboard\": False }" -msgstr "" +msgstr "{ \"ignore_reinit_error\": True, \"include_dashboard\": False }" #: flwr.simulation.app.start_simulation:45 of msgid "" -"An empty dictionary can be used (ray_init_args={}) to prevent any " -"arguments from being passed to ray.init." -msgstr "" +"An empty dictionary can be used (ray_init_args={}) to prevent any arguments " +"from being passed to ray.init." +msgstr "可以使用空字典 (ray_init_args={}) 来防止向 ray.init 传递任何参数。" #: flwr.simulation.app.start_simulation:48 of msgid "" -"Set to True to prevent `ray.shutdown()` in case " -"`ray.is_initialized()=True`." +"Set to True to prevent `ray.shutdown()` in case `ray.is_initialized()=True`." msgstr "" +"设为 True 可在 `ray.is_initialized()=True` 情况下阻止 `ray.shutdown()` 。" #: flwr.simulation.app.start_simulation:50 of msgid "" "Optionally specify the type of actor to use. The actor object, which " -"persists throughout the simulation, will be the process in charge of " -"running the clients' jobs (i.e. their `fit()` method)." +"persists throughout the simulation, will be the process in charge of running " +"the clients' jobs (i.e. their `fit()` method)." msgstr "" +"可选择指定要使用的角色类型。角色对象将在整个模拟过程中持续存在,它将是负责运" +"行客户端作业(即其 `fit()`方法)的进程。" #: flwr.simulation.app.start_simulation:54 of msgid "" -"If you want to create your own Actor classes, you might need to pass some" -" input argument. You can use this dictionary for such purpose." +"If you want to create your own Actor classes, you might need to pass some " +"input argument. You can use this dictionary for such purpose." msgstr "" +"如果您想创建自己的 Actor 类,可能需要传递一些输入参数。为此,您可以使用本字" +"典。" #: flwr.simulation.app.start_simulation:57 of msgid "" -"(default: \"DEFAULT\") Optional string (\"DEFAULT\" or \"SPREAD\") for " -"the VCE to choose in which node the actor is placed. If you are an " -"advanced user needed more control you can use lower-level scheduling " -"strategies to pin actors to specific compute nodes (e.g. via " -"NodeAffinitySchedulingStrategy). Please note this is an advanced feature." -" For all details, please refer to the Ray documentation: " -"https://docs.ray.io/en/latest/ray-core/scheduling/index.html" +"(default: \"DEFAULT\") Optional string (\"DEFAULT\" or \"SPREAD\") for the " +"VCE to choose in which node the actor is placed. If you are an advanced user " +"needed more control you can use lower-level scheduling strategies to pin " +"actors to specific compute nodes (e.g. via NodeAffinitySchedulingStrategy). " +"Please note this is an advanced feature. For all details, please refer to " +"the Ray documentation: https://docs.ray.io/en/latest/ray-core/scheduling/" +"index.html" msgstr "" +"(默认:\"DEFAULT\")可选字符串(\"DEFAULT \"或 \"SPREAD\"),供 VCE 选择将行" +"为体放置在哪个节点上。如果你是需要更多控制权的高级用户,可以使用低级调度策略" +"将角色固定到特定计算节点(例如,通过 NodeAffinitySchedulingStrategy)。请注" +"意,这是一项高级功能。有关详细信息,请参阅 Ray 文档:https://docs.ray.io/en/" +"latest/ray-core/scheduling/index.html" #: flwr.simulation.app.start_simulation:66 of msgid "**hist** -- Object containing metrics from training." -msgstr "" +msgstr "**hist** -- 包含训练指标的对象。" #: ../../source/ref-api-flwr.rst:57 msgid "server" -msgstr "" +msgstr "服务器" #: flwr.server:1 of msgid "Flower server." -msgstr "" +msgstr "Flower 服务器。" #: ../../source/ref-api-flwr.rst:65 msgid "server.start_server" -msgstr "" +msgstr "server.start_server" #: flwr.server.app.start_server:1 of msgid "Start a Flower server using the gRPC transport layer." -msgstr "" +msgstr "使用 gRPC 传输层启动 Flower 服务器。" #: flwr.server.app.start_server:3 of msgid "The IPv4 or IPv6 address of the server. Defaults to `\"[::]:8080\"`." -msgstr "" +msgstr "服务器的 IPv4 或 IPv6 地址。默认为 `\"[::]:8080\"。" #: flwr.server.app.start_server:5 of msgid "" -"A server implementation, either `flwr.server.Server` or a subclass " -"thereof. If no instance is provided, then `start_server` will create one." +"A server implementation, either `flwr.server.Server` or a subclass thereof. " +"If no instance is provided, then `start_server` will create one." msgstr "" +"服务器实现,可以是 `flwr.server.Server` 或其子类。如果没有提供实例," +"`start_server` 将创建一个。" #: flwr.server.app.start_server:12 of msgid "" -"An implementation of the abstract base class " -"`flwr.server.strategy.Strategy`. If no strategy is provided, then " -"`start_server` will use `flwr.server.strategy.FedAvg`." +"An implementation of the abstract base class `flwr.server.strategy." +"Strategy`. If no strategy is provided, then `start_server` will use `flwr." +"server.strategy.FedAvg`." msgstr "" +"抽象基类 `flwr.server.strategy.Strategy` 的实现。如果没有提供策略," +"`start_server` 将使用 `flwr.server.strategy.FedAvg`。" #: flwr.server.app.start_server:16 of msgid "" -"An implementation of the abstract base class `flwr.server.ClientManager`." -" If no implementation is provided, then `start_server` will use " -"`flwr.server.client_manager.SimpleClientManager`." +"An implementation of the abstract base class `flwr.server.ClientManager`. If " +"no implementation is provided, then `start_server` will use `flwr.server." +"client_manager.SimpleClientManager`." msgstr "" +"抽象基类 `flwr.server.ClientManager` 的实现。如果没有提供实现," +"`start_server` 将使用 `flwr.server.client_manager.SimpleClientManager`。" #: flwr.server.app.start_server:21 of msgid "" -"The maximum length of gRPC messages that can be exchanged with the Flower" -" clients. The default should be sufficient for most models. Users who " -"train very large models might need to increase this value. Note that the " -"Flower clients need to be started with the same value (see " -"`flwr.client.start_client`), otherwise clients will not know about the " -"increased limit and block larger messages." +"The maximum length of gRPC messages that can be exchanged with the Flower " +"clients. The default should be sufficient for most models. Users who train " +"very large models might need to increase this value. Note that the Flower " +"clients need to be started with the same value (see `flwr.client." +"start_client`), otherwise clients will not know about the increased limit " +"and block larger messages." msgstr "" +"可与 Flower 客户端交换的 gRPC 消息的最大长度。默认值对大多数模型都足够了。训" +"练超大模型的用户可能需要增加该值。请注意,Flower 客户端需要以相同的值启动(请" +"参阅 `flwr.client.start_client`),否则客户端将不知道已增加的限制并阻止更大的" +"消息。" #: flwr.server.app.start_server:28 of msgid "" -"Tuple containing root certificate, server certificate, and private key to" -" start a secure SSL-enabled server. The tuple is expected to have three " -"bytes elements in the following order: * CA certificate. * " -"server certificate. * server private key." +"Tuple containing root certificate, server certificate, and private key to " +"start a secure SSL-enabled server. The tuple is expected to have three bytes " +"elements in the following order: * CA certificate. * server " +"certificate. * server private key." msgstr "" +"包含根证书、服务器证书和私钥的元组,用于启动启用 SSL 的安全服务器。元组应按以" +"下顺序包含三个字节元素: * CA 证书。 * 服务器证书。 * 服务器私钥。" #: flwr.server.app.start_server:28 of msgid "" -"Tuple containing root certificate, server certificate, and private key to" -" start a secure SSL-enabled server. The tuple is expected to have three " -"bytes elements in the following order:" +"Tuple containing root certificate, server certificate, and private key to " +"start a secure SSL-enabled server. The tuple is expected to have three bytes " +"elements in the following order:" msgstr "" +"包含根证书、服务器证书和私钥的元组,用于启动启用 SSL 的安全服务器。元组应按以" +"下顺序包含三个字节元素:" #: flwr.server.app.start_server:32 of msgid "CA certificate." -msgstr "" +msgstr "CA 证书。" #: flwr.server.app.start_server:33 of msgid "server certificate." -msgstr "" +msgstr "服务器证书。" #: flwr.server.app.start_server:34 of msgid "server private key." -msgstr "" +msgstr "服务器私人密钥。" #: flwr.server.app.start_server:37 of msgid "**hist** -- Object containing training and evaluation metrics." -msgstr "" +msgstr "**hist** -- 包含训练和评估指标的对象。" #: flwr.server.app.start_server:42 of msgid "Starting an insecure server:" -msgstr "" +msgstr "启动不安全的服务器:" #: flwr.server.app.start_server:46 of msgid "Starting an SSL-enabled server:" -msgstr "" +msgstr "启动支持 SSL 的服务器:" #: ../../source/ref-api-flwr.rst:73 msgid "server.strategy" -msgstr "" +msgstr "服务器策略" #: flwr.server.strategy:1 of msgid "Contains the strategy abstraction and different implementations." -msgstr "" +msgstr "包含策略抽象和不同的实现方法。" #: ../../source/ref-api-flwr.rst:81 msgid "server.strategy.Strategy" -msgstr "" +msgstr "server.strategy.Strategy" #: flwr.server.strategy.strategy.Strategy:1 of msgid "Abstract base class for server strategy implementations." -msgstr "" +msgstr "服务器策略实现的抽象基类。" #: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1 of msgid "Aggregate evaluation results." -msgstr "" +msgstr "综合评估结果。" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate:3 #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:6 @@ -6227,59 +7342,71 @@ msgstr "" #: flwr.server.strategy.strategy.Strategy.configure_fit:3 #: flwr.server.strategy.strategy.Strategy.evaluate:6 of msgid "The current round of federated learning." -msgstr "" +msgstr "本轮联合学习。" #: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:5 of msgid "" -"Successful updates from the previously selected and configured clients. " -"Each pair of `(ClientProxy, FitRes` constitutes a successful update from " -"one of the previously selected clients. Not that not all previously " -"selected clients are necessarily included in this list: a client might " -"drop out and not submit a result. For each client that did not submit an " -"update, there should be an `Exception` in `failures`." +"Successful updates from the previously selected and configured clients. Each " +"pair of `(ClientProxy, FitRes` constitutes a successful update from one of " +"the previously selected clients. Not that not all previously selected " +"clients are necessarily included in this list: a client might drop out and " +"not submit a result. For each client that did not submit an update, there " +"should be an `Exception` in `failures`." msgstr "" +"从先前选定和配置的客户端进行的成功更新。每一对\"(ClientProxy, FitRes)\"都是" +"来自先前选定客户端的一次成功更新。但并非所有先前选定的客户机都一定包含在此列" +"表中:客户机可能会退出,不提交结果。对于每个没有提交更新的客户端,`failures`" +"中都应该有一个`Exception`。" #: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:13 #: flwr.server.strategy.strategy.Strategy.aggregate_fit:13 of -msgid "Exceptions that occurred while the server was waiting for client updates." -msgstr "" +msgid "" +"Exceptions that occurred while the server was waiting for client updates." +msgstr "服务器等待客户端更新时发生的异常。" #: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:16 of msgid "" "**aggregation_result** -- The aggregated evaluation result. Aggregation " "typically uses some variant of a weighted average." -msgstr "" +msgstr "**aggregation_result** -- 汇总的评估结果。聚合通常使用某种加权平均值。" #: flwr.server.strategy.strategy.Strategy.aggregate_fit:1 of msgid "Aggregate training results." -msgstr "" +msgstr "汇总培训结果。" #: flwr.server.strategy.strategy.Strategy.aggregate_fit:5 of msgid "" -"Successful updates from the previously selected and configured clients. " -"Each pair of `(ClientProxy, FitRes)` constitutes a successful update from" -" one of the previously selected clients. Not that not all previously " -"selected clients are necessarily included in this list: a client might " -"drop out and not submit a result. For each client that did not submit an " -"update, there should be an `Exception` in `failures`." +"Successful updates from the previously selected and configured clients. Each " +"pair of `(ClientProxy, FitRes)` constitutes a successful update from one of " +"the previously selected clients. Not that not all previously selected " +"clients are necessarily included in this list: a client might drop out and " +"not submit a result. For each client that did not submit an update, there " +"should be an `Exception` in `failures`." msgstr "" +"来自先前选定和配置的客户端的成功更新。每一对\"(ClientProxy、FitRes)\"都构成" +"先前选定的客户端之一的一次成功更新。但并非所有先前选定的客户机都一定包含在此" +"列表中:客户机可能会退出,不提交结果。对于每个没有提交更新的客户端,\"失败 " +"\"中都应该有一个 \"异常\"。" #: flwr.server.strategy.strategy.Strategy.aggregate_fit:17 of msgid "" "**parameters** -- If parameters are returned, then the server will treat " -"these as the new global model parameters (i.e., it will replace the " -"previous parameters with the ones returned from this method). If `None` " -"is returned (e.g., because there were only failures and no viable " -"results) then the server will no update the previous model parameters, " -"the updates received in this round are discarded, and the global model " -"parameters remain the same." +"these as the new global model parameters (i.e., it will replace the previous " +"parameters with the ones returned from this method). If `None` is returned " +"(e.g., because there were only failures and no viable results) then the " +"server will no update the previous model parameters, the updates received in " +"this round are discarded, and the global model parameters remain the same." msgstr "" +"**parameters** -- 如果返回参数,那么服务器将把这些参数作为新的全局模型参数" +"(即用本方法返回的参数替换之前的参数)。如果返回 \"无\"(例如,因为只有失败而" +"没有可行的结果),那么服务器将不再更新之前的模型参数,本轮收到的更新将被丢" +"弃,全局模型参数保持不变。" #: flwr.server.strategy.fedavg.FedAvg.configure_evaluate:1 #: flwr.server.strategy.qfedavg.QFedAvg.configure_evaluate:1 #: flwr.server.strategy.strategy.Strategy.configure_evaluate:1 of msgid "Configure the next round of evaluation." -msgstr "" +msgstr "配置下一轮评估。" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate:7 #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:10 @@ -6287,17 +7414,20 @@ msgstr "" #: flwr.server.strategy.strategy.Strategy.configure_fit:7 #: flwr.server.strategy.strategy.Strategy.initialize_parameters:3 of msgid "The client manager which holds all currently connected clients." -msgstr "" +msgstr "客户端管理器,用于管理当前连接的所有客户端。" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate:10 #: flwr.server.strategy.strategy.Strategy.configure_evaluate:10 of msgid "" "**evaluate_configuration** -- A list of tuples. Each tuple in the list " "identifies a `ClientProxy` and the `EvaluateIns` for this particular " -"`ClientProxy`. If a particular `ClientProxy` is not included in this " -"list, it means that this `ClientProxy` will not participate in the next " -"round of federated evaluation." +"`ClientProxy`. If a particular `ClientProxy` is not included in this list, " +"it means that this `ClientProxy` will not participate in the next round of " +"federated evaluation." msgstr "" +"**evaluate_configuration** -- 一个元组列表。列表中的每个元组都标识了一个`客户" +"代理'和该特定`客户代理'的`评估Ins'。如果某个特定的 `ClientProxy` 未包含在此列" +"表中,则表示该 `ClientProxy` 将不参与下一轮联合评估。" #: flwr.server.strategy.dpfedavg_adaptive.DPFedAvgAdaptive.configure_fit:1 #: flwr.server.strategy.fedavg.FedAvg.configure_fit:1 @@ -6305,64 +7435,68 @@ msgstr "" #: flwr.server.strategy.qfedavg.QFedAvg.configure_fit:1 #: flwr.server.strategy.strategy.Strategy.configure_fit:1 of msgid "Configure the next round of training." -msgstr "" +msgstr "配置下一轮训练。" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:13 #: flwr.server.strategy.strategy.Strategy.configure_fit:10 of msgid "" -"**fit_configuration** -- A list of tuples. Each tuple in the list " -"identifies a `ClientProxy` and the `FitIns` for this particular " -"`ClientProxy`. If a particular `ClientProxy` is not included in this " -"list, it means that this `ClientProxy` will not participate in the next " -"round of federated learning." +"**fit_configuration** -- A list of tuples. Each tuple in the list identifies " +"a `ClientProxy` and the `FitIns` for this particular `ClientProxy`. If a " +"particular `ClientProxy` is not included in this list, it means that this " +"`ClientProxy` will not participate in the next round of federated learning." msgstr "" +"**fit_configuration** -- 一个元组列表。列表中的每个元组都标识了一个`客户代" +"理'和该特定`客户代理'的`FitIns'。如果某个特定的`客户代理'不在此列表中,则表示" +"该`客户代理'将不参加下一轮联合学习。" #: flwr.server.strategy.strategy.Strategy.evaluate:1 of msgid "Evaluate the current model parameters." -msgstr "" +msgstr "评估当前的模型参数。" #: flwr.server.strategy.strategy.Strategy.evaluate:3 of msgid "" "This function can be used to perform centralized (i.e., server-side) " "evaluation of model parameters." -msgstr "" +msgstr "该函数可用于对模型参数进行集中(即服务器端)评估。" #: flwr.server.strategy.strategy.Strategy.evaluate:11 of msgid "" -"**evaluation_result** -- The evaluation result, usually a Tuple " -"containing loss and a dictionary containing task-specific metrics (e.g., " -"accuracy)." +"**evaluation_result** -- The evaluation result, usually a Tuple containing " +"loss and a dictionary containing task-specific metrics (e.g., accuracy)." msgstr "" +"**evaluation_result** -- 评估结果,通常是一个元组,包含损失和一个字典,字典中" +"包含特定任务的指标(如准确率)。" #: flwr.server.strategy.strategy.Strategy.initialize_parameters:1 of msgid "Initialize the (global) model parameters." -msgstr "" +msgstr "初始化(全局)模型参数。" #: flwr.server.strategy.strategy.Strategy.initialize_parameters:6 of msgid "" "**parameters** -- If parameters are returned, then the server will treat " "these as the initial global model parameters." msgstr "" +"**parameters** -- 如果返回参数,服务器将把这些参数视为初始全局模型参数。" #: ../../source/ref-api-flwr.rst:90 msgid "server.strategy.FedAvg" -msgstr "" +msgstr "server.strategy.FedAvg" #: flwr.server.strategy.fedavg.FedAvg:1 of msgid "Configurable FedAvg strategy implementation." -msgstr "" +msgstr "可配置的 FedAvg 战略实施。" #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:1 #: flwr.server.strategy.fedavg.FedAvg.__init__:1 #: flwr.server.strategy.qfedavg.QFedAvg.__init__:1 of msgid "Federated Averaging strategy." -msgstr "" +msgstr "联邦平均战略。" #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:3 #: flwr.server.strategy.fedavg.FedAvg.__init__:3 #: flwr.server.strategy.qfedavg.QFedAvg.__init__:3 of msgid "Implementation based on https://arxiv.org/abs/1602.05629" -msgstr "" +msgstr "实施基于 https://arxiv.org/abs/1602.05629" #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:5 #: flwr.server.strategy.fedavg.FedAvg.__init__:5 @@ -6370,20 +7504,24 @@ msgstr "" #: flwr.server.strategy.qfedavg.QFedAvg.__init__:5 of msgid "" "Fraction of clients used during training. In case `min_fit_clients` is " -"larger than `fraction_fit * available_clients`, `min_fit_clients` will " -"still be sampled. Defaults to 1.0." +"larger than `fraction_fit * available_clients`, `min_fit_clients` will still " +"be sampled. Defaults to 1.0." msgstr "" +"训练过程中使用的客户端比例。如果 `min_fit_clients` 大于 `fraction_fit * " +"available_clients`,则仍会对 `min_fit_clients` 进行采样。默认为 1.0。" #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:9 #: flwr.server.strategy.fedavg.FedAvg.__init__:9 #: flwr.server.strategy.fedprox.FedProx.__init__:41 #: flwr.server.strategy.qfedavg.QFedAvg.__init__:9 of msgid "" -"Fraction of clients used during validation. In case " -"`min_evaluate_clients` is larger than `fraction_evaluate * " -"available_clients`, `min_evaluate_clients` will still be sampled. " -"Defaults to 1.0." +"Fraction of clients used during validation. In case `min_evaluate_clients` " +"is larger than `fraction_evaluate * available_clients`, " +"`min_evaluate_clients` will still be sampled. Defaults to 1.0." msgstr "" +"验证过程中使用的客户端的分数。如果 `min_evaluate_clients` 大于 " +"`fraction_evaluate * available_clients`,则仍会对 `min_evaluate_clients` 进行" +"采样。默认为 1.0。" #: flwr.server.strategy.bulyan.Bulyan.__init__:9 #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:13 @@ -6398,7 +7536,7 @@ msgstr "" #: flwr.server.strategy.krum.Krum.__init__:7 #: flwr.server.strategy.qfedavg.QFedAvg.__init__:13 of msgid "Minimum number of clients used during training. Defaults to 2." -msgstr "" +msgstr "培训期间使用的最少客户数。默认为 2。" #: flwr.server.strategy.bulyan.Bulyan.__init__:11 #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:15 @@ -6413,7 +7551,7 @@ msgstr "" #: flwr.server.strategy.krum.Krum.__init__:9 #: flwr.server.strategy.qfedavg.QFedAvg.__init__:15 of msgid "Minimum number of clients used during validation. Defaults to 2." -msgstr "" +msgstr "验证过程中使用的最少客户端数量。默认为 2。" #: flwr.server.strategy.bulyan.Bulyan.__init__:13 #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:17 @@ -6428,7 +7566,7 @@ msgstr "" #: flwr.server.strategy.krum.Krum.__init__:11 #: flwr.server.strategy.qfedavg.QFedAvg.__init__:17 of msgid "Minimum number of total clients in the system. Defaults to 2." -msgstr "" +msgstr "系统中客户总数的最小值。默认为 2。" #: flwr.server.strategy.bulyan.Bulyan.__init__:17 #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:19 @@ -6443,7 +7581,7 @@ msgstr "" #: flwr.server.strategy.krum.Krum.__init__:18 #: flwr.server.strategy.qfedavg.QFedAvg.__init__:19 of msgid "Optional function used for validation. Defaults to None." -msgstr "" +msgstr "用于验证的可选函数。默认为 \"无\"。" #: flwr.server.strategy.bulyan.Bulyan.__init__:19 #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:21 @@ -6458,7 +7596,7 @@ msgstr "" #: flwr.server.strategy.krum.Krum.__init__:20 #: flwr.server.strategy.qfedavg.QFedAvg.__init__:21 of msgid "Function used to configure training. Defaults to None." -msgstr "" +msgstr "用于配置训练的功能。默认为 \"无\"。" #: flwr.server.strategy.bulyan.Bulyan.__init__:21 #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:23 @@ -6473,7 +7611,7 @@ msgstr "" #: flwr.server.strategy.krum.Krum.__init__:22 #: flwr.server.strategy.qfedavg.QFedAvg.__init__:23 of msgid "Function used to configure validation. Defaults to None." -msgstr "" +msgstr "用于配置验证的函数。默认为 \"无\"。" #: flwr.server.strategy.bulyan.Bulyan.__init__:23 #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:25 @@ -6488,7 +7626,7 @@ msgstr "" #: flwr.server.strategy.krum.Krum.__init__:24 #: flwr.server.strategy.qfedavg.QFedAvg.__init__:25 of msgid "Whether or not accept rounds containing failures. Defaults to True." -msgstr "" +msgstr "是否接受包含失败的轮询。默认为 True。" #: flwr.server.strategy.bulyan.Bulyan.__init__:25 #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:27 @@ -6503,7 +7641,7 @@ msgstr "" #: flwr.server.strategy.krum.Krum.__init__:26 #: flwr.server.strategy.qfedavg.QFedAvg.__init__:27 of msgid "Initial global model parameters." -msgstr "" +msgstr "初始全球模型参数。" #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:29 #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:31 @@ -6522,13 +7660,13 @@ msgstr "" #: flwr.server.strategy.qfedavg.QFedAvg.__init__:29 #: flwr.server.strategy.qfedavg.QFedAvg.__init__:31 of msgid "Metrics aggregation function, optional." -msgstr "" +msgstr "指标汇总功能,可选。" #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1 #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1 #: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1 of msgid "Aggregate evaluation losses using weighted average." -msgstr "" +msgstr "采用加权平均法计算评估损失总额。" #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_fit:1 #: flwr.server.strategy.fedadagrad.FedAdagrad.aggregate_fit:1 @@ -6539,109 +7677,110 @@ msgstr "" #: flwr.server.strategy.fedyogi.FedYogi.aggregate_fit:1 #: flwr.server.strategy.qfedavg.QFedAvg.aggregate_fit:1 of msgid "Aggregate fit results using weighted average." -msgstr "" +msgstr "使用加权平均法汇总拟合结果。" #: flwr.server.strategy.fedavg.FedAvg.evaluate:1 #: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg.evaluate:1 of msgid "Evaluate model parameters using an evaluation function." -msgstr "" +msgstr "使用评估函数评估模型参数。" #: flwr.server.strategy.fedavg.FedAvg.initialize_parameters:1 #: flwr.server.strategy.fedavgm.FedAvgM.initialize_parameters:1 of msgid "Initialize global model parameters." -msgstr "" +msgstr "初始化全局模型参数。" #: flwr.server.strategy.fedavg.FedAvg.num_evaluation_clients:1 #: flwr.server.strategy.qfedavg.QFedAvg.num_evaluation_clients:1 of msgid "Use a fraction of available clients for evaluation." -msgstr "" +msgstr "使用部分可用客户进行评估。" #: flwr.server.strategy.fedavg.FedAvg.num_fit_clients:1 #: flwr.server.strategy.qfedavg.QFedAvg.num_fit_clients:1 of msgid "Return the sample size and the required number of available clients." -msgstr "" +msgstr "返回样本大小和所需的可用客户数量。" #: ../../source/ref-api-flwr.rst:101 msgid "server.strategy.FedAvgM" -msgstr "" +msgstr "server.strategy.FedAvgM" #: flwr.server.strategy.fedavgm.FedAvgM:1 #: flwr.server.strategy.fedmedian.FedMedian:1 of msgid "Configurable FedAvg with Momentum strategy implementation." -msgstr "" +msgstr "可配置的 FedAvg 动量策略实施。" #: flwr.server.strategy.fedavgm.FedAvgM.__init__:1 of msgid "Federated Averaging with Momentum strategy." -msgstr "" +msgstr "联邦平均动量策略。" #: flwr.server.strategy.fedavgm.FedAvgM.__init__:3 of msgid "Implementation based on https://arxiv.org/pdf/1909.06335.pdf" -msgstr "" +msgstr "实施基于 https://arxiv.org/pdf/1909.06335.pdf" #: flwr.server.strategy.fedavgm.FedAvgM.__init__:5 #: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg.__init__:3 #: flwr.server.strategy.krum.Krum.__init__:3 of msgid "Fraction of clients used during training. Defaults to 0.1." -msgstr "" +msgstr "培训期间使用客户的比例。默认为 0.1。" #: flwr.server.strategy.fedavgm.FedAvgM.__init__:7 #: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg.__init__:5 #: flwr.server.strategy.krum.Krum.__init__:5 of msgid "Fraction of clients used during validation. Defaults to 0.1." -msgstr "" +msgstr "验证过程中使用的客户端比例。默认为 0.1。" #: flwr.server.strategy.fedavgm.FedAvgM.__init__:25 of msgid "" -"Server-side learning rate used in server-side optimization. Defaults to " -"1.0." -msgstr "" +"Server-side learning rate used in server-side optimization. Defaults to 1.0." +msgstr "服务器端优化中使用的服务器端学习率。默认为 1.0。" #: flwr.server.strategy.fedavgm.FedAvgM.__init__:28 of msgid "Server-side momentum factor used for FedAvgM. Defaults to 0.0." -msgstr "" +msgstr "用于 FedAvgM 的服务器端动量因子。默认为 0.0。" #: ../../source/ref-api-flwr.rst:112 msgid "server.strategy.FedMedian" -msgstr "" +msgstr "server.strategy.FedMedian" #: flwr.server.strategy.fedmedian.FedMedian.aggregate_fit:1 of msgid "Aggregate fit results using median." -msgstr "" +msgstr "使用中位数汇总拟合结果。" #: ../../source/ref-api-flwr.rst:122 msgid "server.strategy.QFedAvg" -msgstr "" +msgstr "server.strategy.QFedAvg" #: flwr.server.strategy.qfedavg.QFedAvg:1 of msgid "Configurable QFedAvg strategy implementation." -msgstr "" +msgstr "可配置的 QFedAvg 策略实施。" #: ../../source/ref-api-flwr.rst:133 +#, fuzzy msgid "server.strategy.FaultTolerantFedAvg" -msgstr "" +msgstr "server.strategy.FaultTolerantFedAvg" #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg:1 of msgid "Configurable fault-tolerant FedAvg strategy implementation." -msgstr "" +msgstr "可配置的容错 FedAvg 策略实施。" #: ../../source/ref-api-flwr.rst:144 +#, fuzzy msgid "server.strategy.FedOpt" -msgstr "" +msgstr "server.strategy.FedOpt" #: flwr.server.strategy.fedopt.FedOpt:1 of msgid "Configurable FedAdagrad strategy implementation." -msgstr "" +msgstr "可配置的 FedAdagrad 策略实施。" #: flwr.server.strategy.fedopt.FedOpt.__init__:1 of msgid "Federated Optim strategy interface." -msgstr "" +msgstr "Federated Optim 策略界面。" #: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:3 #: flwr.server.strategy.fedadam.FedAdam.__init__:3 #: flwr.server.strategy.fedopt.FedOpt.__init__:3 #: flwr.server.strategy.fedyogi.FedYogi.__init__:3 of msgid "Implementation based on https://arxiv.org/abs/2003.00295v5" -msgstr "" +msgstr "实施基于 https://arxiv.org/abs/2003.00295v5" #: flwr.server.strategy.bulyan.Bulyan.__init__:5 #: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:5 @@ -6649,7 +7788,7 @@ msgstr "" #: flwr.server.strategy.fedopt.FedOpt.__init__:5 #: flwr.server.strategy.fedyogi.FedYogi.__init__:5 of msgid "Fraction of clients used during training. Defaults to 1.0." -msgstr "" +msgstr "培训期间使用客户的比例。默认为 1.0。" #: flwr.server.strategy.bulyan.Bulyan.__init__:7 #: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:7 @@ -6657,134 +7796,143 @@ msgstr "" #: flwr.server.strategy.fedopt.FedOpt.__init__:7 #: flwr.server.strategy.fedyogi.FedYogi.__init__:7 of msgid "Fraction of clients used during validation. Defaults to 1.0." -msgstr "" +msgstr "验证过程中使用的客户端比例。默认为 1.0。" #: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:29 #: flwr.server.strategy.fedadam.FedAdam.__init__:29 #: flwr.server.strategy.fedopt.FedOpt.__init__:29 #: flwr.server.strategy.fedyogi.FedYogi.__init__:29 of msgid "Server-side learning rate. Defaults to 1e-1." -msgstr "" +msgstr "服务器端学习率。默认为 1e-1。" #: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:31 #: flwr.server.strategy.fedadam.FedAdam.__init__:31 #: flwr.server.strategy.fedopt.FedOpt.__init__:31 #: flwr.server.strategy.fedyogi.FedYogi.__init__:31 of msgid "Client-side learning rate. Defaults to 1e-1." -msgstr "" +msgstr "客户端学习率。默认为 1e-1。" #: flwr.server.strategy.fedopt.FedOpt.__init__:33 of msgid "Momentum parameter. Defaults to 0.0." -msgstr "" +msgstr "动量参数。默认为 0.0。" #: flwr.server.strategy.fedopt.FedOpt.__init__:35 of msgid "Second moment parameter. Defaults to 0.0." -msgstr "" +msgstr "第二矩参数。默认为 0.0。" #: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:33 #: flwr.server.strategy.fedadam.FedAdam.__init__:37 #: flwr.server.strategy.fedopt.FedOpt.__init__:37 #: flwr.server.strategy.fedyogi.FedYogi.__init__:37 of msgid "Controls the algorithm's degree of adaptability. Defaults to 1e-9." -msgstr "" +msgstr "控制算法的适应度。默认为 1e-9。" #: ../../source/ref-api-flwr.rst:155 +#, fuzzy msgid "server.strategy.FedProx" -msgstr "" +msgstr "server.strategy.FedProx" #: flwr.server.strategy.fedprox.FedProx:1 of msgid "Configurable FedProx strategy implementation." -msgstr "" +msgstr "可配置的 FedProx 策略实施。" #: flwr.server.strategy.fedprox.FedProx.__init__:1 of msgid "Federated Optimization strategy." -msgstr "" +msgstr "联邦优化策略。" #: flwr.server.strategy.fedprox.FedProx.__init__:3 of msgid "Implementation based on https://arxiv.org/abs/1812.06127" -msgstr "" +msgstr "实施基于 https://arxiv.org/abs/1812.06127" #: flwr.server.strategy.fedprox.FedProx.__init__:5 of msgid "" -"The strategy in itself will not be different than FedAvg, the client " -"needs to be adjusted. A proximal term needs to be added to the loss " -"function during the training:" +"The strategy in itself will not be different than FedAvg, the client needs " +"to be adjusted. A proximal term needs to be added to the loss function " +"during the training:" msgstr "" +"策略本身与 FedAvg 并无不同,客户需要进行调整。在训练过程中,需要在损失函数中" +"添加一个近端项:" #: flwr.server.strategy.fedprox.FedProx.__init__:9 of msgid "" "\\\\frac{\\\\mu}{2} || w - w^t ||^2\n" "\n" msgstr "" +"\\\\frac{\\\\mu}{2} || w - w^t ||^2\n" +"\n" #: flwr.server.strategy.fedprox.FedProx.__init__:12 of msgid "" "Where $w^t$ are the global parameters and $w$ are the local weights the " "function will be optimized with." -msgstr "" +msgstr "其中,$w^t$ 是全局参数,$w$ 是优化函数的局部权重。" #: flwr.server.strategy.fedprox.FedProx.__init__:15 of msgid "In PyTorch, for example, the loss would go from:" -msgstr "" +msgstr "例如,在 PyTorch 中,损失将从:" #: flwr.server.strategy.fedprox.FedProx.__init__:21 of msgid "To:" -msgstr "" +msgstr "致:" #: flwr.server.strategy.fedprox.FedProx.__init__:30 of msgid "" "With `global_params` being a copy of the parameters before the training " "takes place." -msgstr "" +msgstr "其中,\"global_params \"是训练前的参数副本。" #: flwr.server.strategy.fedprox.FedProx.__init__:65 of msgid "" "The weight of the proximal term used in the optimization. 0.0 makes this " "strategy equivalent to FedAvg, and the higher the coefficient, the more " -"regularization will be used (that is, the client parameters will need to " -"be closer to the server parameters during training)." +"regularization will be used (that is, the client parameters will need to be " +"closer to the server parameters during training)." msgstr "" +"优化中使用的近端项权重。0.0 使该策略等同于 FedAvg,系数越大,使用的正则化就越" +"多(也就是说,在训练过程中,客户端参数需要更接近服务器参数)。" #: flwr.server.strategy.fedprox.FedProx.configure_fit:3 of msgid "Sends the proximal factor mu to the clients" -msgstr "" +msgstr "向客户发送近端因子亩" #: ../../source/ref-api-flwr.rst:166 +#, fuzzy msgid "server.strategy.FedAdagrad" -msgstr "" +msgstr "server.strategy.FedAdagrad" #: flwr.server.strategy.fedadagrad.FedAdagrad:1 of msgid "FedAdagrad strategy - Adaptive Federated Optimization using Adagrad." -msgstr "" +msgstr "FedAdagrad 策略 - 使用 Adagrad 进行自适应联合优化。" #: flwr.server.strategy.fedadagrad.FedAdagrad:3 #: flwr.server.strategy.fedadam.FedAdam:3 #: flwr.server.strategy.fedyogi.FedYogi:5 of msgid "Paper: https://arxiv.org/abs/2003.00295" -msgstr "" +msgstr "论文: https://arxiv.org/abs/2003.00295" #: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:1 #: flwr.server.strategy.fedadam.FedAdam.__init__:1 of msgid "Federated learning strategy using Adagrad on server-side." -msgstr "" +msgstr "在服务器端使用 Adagrad 的联邦学习策略。" #: ../../source/ref-api-flwr.rst:177 +#, fuzzy msgid "server.strategy.FedAdam" -msgstr "" +msgstr "server.strategy.FedAdam" #: flwr.server.strategy.fedadam.FedAdam:1 of msgid "FedAdam - Adaptive Federated Optimization using Adam." -msgstr "" +msgstr "FedAdam - 使用 Adam 进行自适应联合优化。" #: flwr.server.strategy.fedadam.FedAdam.__init__:33 #: flwr.server.strategy.fedyogi.FedYogi.__init__:33 of msgid "Momentum parameter. Defaults to 0.9." -msgstr "" +msgstr "动量参数。默认为 0.9。" #: flwr.server.strategy.fedadam.FedAdam.__init__:35 #: flwr.server.strategy.fedyogi.FedYogi.__init__:35 of msgid "Second moment parameter. Defaults to 0.99." -msgstr "" +msgstr "第二矩参数。默认为 0.99。" #: ../../source/ref-api-flwr.rst:188 msgid "server.strategy.FedYogi" @@ -6792,15 +7940,15 @@ msgstr "" #: flwr.server.strategy.fedyogi.FedYogi:1 of msgid "FedYogi [Reddi et al., 2020] strategy." -msgstr "" +msgstr "FedYogi [Reddi 等人,2020] 策略。" #: flwr.server.strategy.fedyogi.FedYogi:3 of msgid "Adaptive Federated Optimization using Yogi." -msgstr "" +msgstr "使用 Yogi 的自适应联合优化。" #: flwr.server.strategy.fedyogi.FedYogi.__init__:1 of msgid "Federated learning strategy using Yogi on server-side." -msgstr "" +msgstr "在服务器端使用 Yogi 的联邦学习策略。" #: ../../source/ref-api-flwr.rst:199 msgid "server.strategy.FedTrimmedAvg" @@ -6809,19 +7957,19 @@ msgstr "" #: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:1 #: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg.__init__:1 of msgid "Federated Averaging with Trimmed Mean [Dong Yin, et al., 2021]." -msgstr "" +msgstr "带修剪均值的联邦平均法[Dong Yin 等,2021]。" #: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:3 of msgid "Paper: https://arxiv.org/abs/1803.01498" -msgstr "" +msgstr "论文:https://arxiv.org/abs/1803.01498" #: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg.__init__:23 of msgid "Fraction to cut off of both tails of the distribution. Defaults to 0.2." -msgstr "" +msgstr "截取分布两个尾部的分数。默认为 0.2。" #: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg.aggregate_fit:1 of msgid "Aggregate fit results using trimmed average." -msgstr "" +msgstr "使用修剪平均值汇总拟合结果。" #: ../../source/ref-api-flwr.rst:210 msgid "server.strategy.Krum" @@ -6829,26 +7977,28 @@ msgstr "" #: flwr.server.strategy.krum.Krum:1 of msgid "Configurable Krum strategy implementation." -msgstr "" +msgstr "可配置的 Krum 策略实施。" #: flwr.server.strategy.krum.Krum.__init__:1 of msgid "Krum strategy." -msgstr "" +msgstr "Krum 策略。" #: flwr.server.strategy.bulyan.Bulyan.__init__:15 #: flwr.server.strategy.krum.Krum.__init__:13 of msgid "Number of malicious clients in the system. Defaults to 0." -msgstr "" +msgstr "系统中恶意客户端的数量。默认为 0。" #: flwr.server.strategy.krum.Krum.__init__:15 of msgid "" -"Number of clients to keep before averaging (MultiKrum). Defaults to 0, in" -" that case classical Krum is applied." +"Number of clients to keep before averaging (MultiKrum). Defaults to 0, in " +"that case classical Krum is applied." msgstr "" +"求平均值前保留的客户端数量(MultiKrum)。默认值为 0,在这种情况下会应用经典 " +"Krum。" #: flwr.server.strategy.krum.Krum.aggregate_fit:1 of msgid "Aggregate fit results using Krum." -msgstr "" +msgstr "使用 Krum 汇总拟合结果。" #: ../../source/ref-api-flwr.rst:220 msgid "server.strategy.Bulyan" @@ -6856,29 +8006,29 @@ msgstr "" #: flwr.server.strategy.bulyan.Bulyan:1 of msgid "Bulyan strategy implementation." -msgstr "" +msgstr "Bulyan策略的实施。" #: flwr.server.strategy.bulyan.Bulyan.__init__:1 of msgid "Bulyan strategy." -msgstr "" +msgstr "Bulyan 策略。" #: flwr.server.strategy.bulyan.Bulyan.__init__:3 of msgid "Implementation based on https://arxiv.org/abs/1802.07927." -msgstr "" +msgstr "实施基于 https://arxiv.org/abs/1802.07927。" #: flwr.server.strategy.bulyan.Bulyan.__init__:27 of msgid "" -"Byzantine resilient aggregation rule that is used as the first step of " -"the Bulyan (e.g., Krum)" -msgstr "" +"Byzantine resilient aggregation rule that is used as the first step of the " +"Bulyan (e.g., Krum)" +msgstr "拜占庭弹性聚合规则,用作 Bulyan 的第一步(如 Krum)" #: flwr.server.strategy.bulyan.Bulyan.__init__:29 of msgid "arguments to the first_aggregation rule" -msgstr "" +msgstr "第一聚类规则的参数" #: flwr.server.strategy.bulyan.Bulyan.aggregate_fit:1 of msgid "Aggregate fit results using Bulyan." -msgstr "" +msgstr "使用 Bulyan 技术汇总拟合结果。" #: ../../source/ref-api-flwr.rst:231 msgid "server.strategy.FedXgbNnAvg" @@ -6886,15 +8036,15 @@ msgstr "" #: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg:1 of msgid "Configurable FedXgbNnAvg strategy implementation." -msgstr "" +msgstr "可配置的 FedXgbNAvg 策略实施。" #: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg.__init__:1 of msgid "Federated XGBoost [Ma et al., 2023] strategy." -msgstr "" +msgstr "Federated XGBoost [Ma 等人,2023] 策略。" #: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg.__init__:3 of msgid "Implementation based on https://arxiv.org/abs/2304.07537." -msgstr "" +msgstr "实施基于 https://arxiv.org/abs/2304.07537。" #: ../../source/ref-api-flwr.rst:242 msgid "server.strategy.DPFedAvgAdaptive" @@ -6902,11 +8052,11 @@ msgstr "" #: flwr.server.strategy.dpfedavg_adaptive.DPFedAvgAdaptive:1 of msgid "Wrapper for configuring a Strategy for DP with Adaptive Clipping." -msgstr "" +msgstr "用于配置具有自适应剪切功能的 DP 策略的包装器。" #: flwr.server.strategy.dpfedavg_adaptive.DPFedAvgAdaptive.aggregate_fit:1 of msgid "Aggregate training results as in DPFedAvgFixed and update clip norms." -msgstr "" +msgstr "汇总 DPFedAvgFixed 中的训练结果并更新片段标准。" #: ../../source/ref-api-flwr.rst:253 msgid "server.strategy.DPFedAvgFixed" @@ -6914,129 +8064,129 @@ msgstr "" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed:1 of msgid "Wrapper for configuring a Strategy for DP with Fixed Clipping." -msgstr "" +msgstr "封装器,用于为具有固定剪切功能的 DP 配置策略。" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1 of msgid "Aggregate evaluation losses using the given strategy." -msgstr "" +msgstr "使用给定的策略汇总评估损失。" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_fit:1 of msgid "Aggregate training results using unweighted aggregation." -msgstr "" +msgstr "使用非加权汇总法汇总训练结果。" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate:1 of msgid "Configure the next round of evaluation using the specified strategy." -msgstr "" +msgstr "使用指定策略配置下一轮评估。" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:1 of msgid "" -"Configure the next round of training incorporating Differential Privacy " -"(DP)." -msgstr "" +"Configure the next round of training incorporating Differential Privacy (DP)." +msgstr "配置包含差分保密 (DP) 的下一轮训练。" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:3 of msgid "" -"Configuration of the next training round includes information related to " -"DP, such as clip norm and noise stddev." -msgstr "" +"Configuration of the next training round includes information related to DP, " +"such as clip norm and noise stddev." +msgstr "下一轮训练的配置包括与 DP 相关的信息,如片段规范和噪声 stddev。" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.evaluate:1 of -msgid "Evaluate model parameters using an evaluation function from the strategy." -msgstr "" +msgid "" +"Evaluate model parameters using an evaluation function from the strategy." +msgstr "使用策略中的评估函数评估模型参数。" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.initialize_parameters:1 of msgid "Initialize global model parameters using given strategy." -msgstr "" +msgstr "使用给定的策略初始化全局模型参数。" #: ../../source/ref-api-flwr.rst:261 msgid "common" -msgstr "" +msgstr "常见" #: flwr.common:1 of msgid "Common components shared between server and client." -msgstr "" +msgstr "服务器和客户端共享的通用组件。" #: flwr.common.typing.ClientMessage:1 of msgid "ClientMessage is a container used to hold one result message." -msgstr "" +msgstr "ClientMessage 是用于容纳一条结果信息的容器。" #: flwr.common.typing.Code:1 of msgid "Client status codes." -msgstr "" +msgstr "客户端状态代码。" #: flwr.common.typing.DisconnectRes:1 of msgid "DisconnectRes message from client to server." -msgstr "" +msgstr "客户端向服务器发送 DisconnectRes 信息。" #: flwr.common.typing.EvaluateIns:1 of msgid "Evaluate instructions for a client." -msgstr "" +msgstr "评估客户的指示。" #: flwr.common.typing.EvaluateRes:1 of msgid "Evaluate response from a client." -msgstr "" +msgstr "评估客户的反应。" #: flwr.common.telemetry.EventType:1 of msgid "Types of telemetry events." -msgstr "" +msgstr "遥测事件类型。" #: flwr.common.typing.FitIns:1 of msgid "Fit instructions for a client." -msgstr "" +msgstr "为客户提供安装说明。" #: flwr.common.typing.FitRes:1 of msgid "Fit response from a client." -msgstr "" +msgstr "来自客户端的合适回复。" #: flwr.common.typing.GetParametersIns:1 of msgid "Parameters request for a client." -msgstr "" +msgstr "客户端的参数请求。" #: flwr.common.typing.GetParametersRes:1 of msgid "Response when asked to return parameters." -msgstr "" +msgstr "要求返回参数时的响应。" #: flwr.common.typing.GetPropertiesIns:1 of msgid "Properties request for a client." -msgstr "" +msgstr "客户端的属性请求。" #: flwr.common.typing.GetPropertiesRes:1 of msgid "Properties response from a client." -msgstr "" +msgstr "来自客户端的属性响应。" #: flwr.common.typing.Parameters:1 of msgid "Model parameters." -msgstr "" +msgstr "模型参数。" #: flwr.common.typing.ReconnectIns:1 of msgid "ReconnectIns message from server to client." -msgstr "" +msgstr "服务器发送给客户端的重新连接信息。" #: flwr.common.typing.ServerMessage:1 of msgid "ServerMessage is a container used to hold one instruction message." -msgstr "" +msgstr "ServerMessage 是用于容纳一条指令信息的容器。" #: flwr.common.typing.Status:1 of msgid "Client status." -msgstr "" +msgstr "客户端状态。" #: flwr.common.parameter.bytes_to_ndarray:1 of msgid "Deserialize NumPy ndarray from bytes." -msgstr "" +msgstr "从字节反序列化 NumPy ndarray。" #: flwr.common.logger.configure:1 of msgid "Configure logging to file and/or remote log server." -msgstr "" +msgstr "配置将日志记录到文件和/或远程日志服务器。" #: logging.Logger.log:1 of msgid "Log 'msg % args' with the integer severity 'level'." -msgstr "" +msgstr "以整数严重性 \"级别 \"记录 \"msg % args\"。" #: logging.Logger.log:3 of msgid "" -"To pass exception information, use the keyword argument exc_info with a " -"true value, e.g." -msgstr "" +"To pass exception information, use the keyword argument exc_info with a true " +"value, e.g." +msgstr "要传递异常信息,请使用带 true 值的关键字参数 exc_info,例如。" #: logging.Logger.log:6 of #, python-format @@ -7045,27 +8195,27 @@ msgstr "" #: flwr.common.parameter.ndarray_to_bytes:1 of msgid "Serialize NumPy ndarray to bytes." -msgstr "" +msgstr "将 NumPy ndarray 序列化为字节。" #: flwr.common.parameter.ndarrays_to_parameters:1 of msgid "Convert NumPy ndarrays to parameters object." -msgstr "" +msgstr "将 NumPy ndarrays 转换为参数对象。" #: flwr.common.date.now:1 of msgid "Construct a datetime from time.time() with time zone set to UTC." -msgstr "" +msgstr "从 time.time() 生成日期时间,时区设置为 UTC。" #: flwr.common.parameter.parameters_to_ndarrays:1 of msgid "Convert parameters object to NumPy ndarrays." -msgstr "" +msgstr "将参数对象转换为 NumPy ndarrays。" #: ../../source/ref-changelog.md:1 msgid "Changelog" -msgstr "" +msgstr "更新日志" #: ../../source/ref-changelog.md:3 msgid "Unreleased" -msgstr "" +msgstr "尚未发布" #: ../../source/ref-changelog.md:5 ../../source/ref-changelog.md:83 #: ../../source/ref-changelog.md:167 ../../source/ref-changelog.md:231 @@ -7075,95 +8225,114 @@ msgstr "" #: ../../source/ref-changelog.md:707 ../../source/ref-changelog.md:746 #: ../../source/ref-changelog.md:779 ../../source/ref-changelog.md:829 msgid "What's new?" -msgstr "" +msgstr "有什么新内容?" #: ../../source/ref-changelog.md:7 msgid "" -"**Add experimental support for Python 3.12** " -"([#2565](https://github.com/adap/flower/pull/2565))" +"**Add experimental support for Python 3.12** ([#2565](https://github.com/" +"adap/flower/pull/2565))" msgstr "" +"** 增加对 Python 3.12 的实验支持** ([#2565](https://github.com/adap/flower/" +"pull/2565))" #: ../../source/ref-changelog.md:9 msgid "" -"**Support custom** `ClientManager` **in** `start_driver()` " -"([#2292](https://github.com/adap/flower/pull/2292))" +"**Support custom** `ClientManager` **in** `start_driver()` ([#2292](https://" +"github.com/adap/flower/pull/2292))" msgstr "" +"**在***`start_driver()`中支持自定义***`ClientManager([#2292](https://github." +"com/adap/flower/pull/2292))" #: ../../source/ref-changelog.md:11 msgid "" -"**Update REST API to support create and delete nodes** " -"([#2283](https://github.com/adap/flower/pull/2283))" +"**Update REST API to support create and delete nodes** ([#2283](https://" +"github.com/adap/flower/pull/2283))" msgstr "" +"**更新 REST API 以支持创建和删除节点** ([#2283](https://github.com/adap/" +"flower/pull/2283))" #: ../../source/ref-changelog.md:13 msgid "" -"**Update the C++ SDK** " -"([#2537](https://github/com/adap/flower/pull/2537), " -"[#2528](https://github/com/adap/flower/pull/2528), " -"[#2523](https://github.com/adap/flower/pull/2523), " -"[#2522](https://github.com/adap/flower/pull/2522))" +"**Update the C++ SDK** ([#2537](https://github/com/adap/flower/pull/2537), " +"[#2528](https://github/com/adap/flower/pull/2528), [#2523](https://github." +"com/adap/flower/pull/2523), [#2522](https://github.com/adap/flower/" +"pull/2522))" msgstr "" +"** 更新 C++ SDK** ([#2537](https://github/com/adap/flower/pull/2537), [#2528]" +"(https://github/com/adap/flower/pull/2528), [#2523](https://github.com/adap/" +"flower/pull/2523), [#2522](https://github.com/adap/flower/pull/2522))" #: ../../source/ref-changelog.md:15 msgid "Add gRPC request-response capability to the C++ SDK." -msgstr "" +msgstr "为 C++ SDK 添加 gRPC 请求-响应功能。" #: ../../source/ref-changelog.md:17 msgid "" -"**Fix the incorrect return types of Strategy** " -"([#2432](https://github.com/adap/flower/pull/2432/files))" +"**Fix the incorrect return types of Strategy** ([#2432](https://github.com/" +"adap/flower/pull/2432/files))" msgstr "" +"**修复策略的错误返回类型** ([#2432](https://github.com/adap/flower/pull/2432/" +"files))" #: ../../source/ref-changelog.md:19 msgid "" "The types of the return values in the docstrings in two methods " -"(`aggregate_fit` and `aggregate_evaluate`) now match the hint types in " -"the code." +"(`aggregate_fit` and `aggregate_evaluate`) now match the hint types in the " +"code." msgstr "" +"两个方法(\"aggregate_fit \"和 \"aggregate_evaluate\")的文档说明中的返回值类" +"型现在与代码中的提示类型一致。" #: ../../source/ref-changelog.md:21 msgid "" "**Unify client API** ([#2303](https://github.com/adap/flower/pull/2303), " -"[#2390](https://github.com/adap/flower/pull/2390), " -"[#2493](https://github.com/adap/flower/pull/2493))" +"[#2390](https://github.com/adap/flower/pull/2390), [#2493](https://github." +"com/adap/flower/pull/2493))" msgstr "" +"** 统一客户端应用程序接口** ([#2303](https://github.com/adap/flower/" +"pull/2303), [#2390](https://github.com/adap/flower/pull/2390), [#2493]" +"(https://github.com/adap/flower/pull/2493))" #: ../../source/ref-changelog.md:23 msgid "" -"Using the `client_fn`, Flower clients can interchangeably run as " -"standalone processes (i.e. via `start_client`) or in simulation (i.e. via" -" `start_simulation`) without requiring changes to how the client class is" -" defined and instantiated. Calling `start_numpy_client` is now " -"deprecated." +"Using the `client_fn`, Flower clients can interchangeably run as standalone " +"processes (i.e. via `start_client`) or in simulation (i.e. via " +"`start_simulation`) without requiring changes to how the client class is " +"defined and instantiated. Calling `start_numpy_client` is now deprecated." msgstr "" +"使用 `client_fn`,Flower 客户端可以作为独立进程(即通过 `start_client`)或在" +"模拟中(即通过 `start_simulation`)交替运行,而无需更改客户端类的定义和实例化" +"方式。调用 `start_numpy_client` 现已过时。" #: ../../source/ref-changelog.md:25 msgid "**Update Flower Baselines**" -msgstr "" +msgstr "**更新 Flower 基准**" #: ../../source/ref-changelog.md:27 msgid "" -"FedProx ([#2210](https://github.com/adap/flower/pull/2210), " -"[#2286](https://github.com/adap/flower/pull/2286), " -"[#2509](https://github.com/adap/flower/pull/2509))" +"FedProx ([#2210](https://github.com/adap/flower/pull/2210), [#2286](https://" +"github.com/adap/flower/pull/2286), [#2509](https://github.com/adap/flower/" +"pull/2509))" msgstr "" #: ../../source/ref-changelog.md:29 msgid "" -"Baselines Docs ([#2290](https://github.com/adap/flower/pull/2290), " -"[#2400](https://github.com/adap/flower/pull/2400))" +"Baselines Docs ([#2290](https://github.com/adap/flower/pull/2290), [#2400]" +"(https://github.com/adap/flower/pull/2400))" msgstr "" +"基准文件([#2290](https://github.com/adap/flower/pull/2290), [#2400](https://" +"github.com/adap/flower/pull/2400)" #: ../../source/ref-changelog.md:31 msgid "" -"FedMLB ([#2340](https://github.com/adap/flower/pull/2340), " -"[#2507](https://github.com/adap/flower/pull/2507))" +"FedMLB ([#2340](https://github.com/adap/flower/pull/2340), [#2507](https://" +"github.com/adap/flower/pull/2507))" msgstr "" #: ../../source/ref-changelog.md:33 msgid "" -"TAMUNA ([#2254](https://github.com/adap/flower/pull/2254), " -"[#2508](https://github.com/adap/flower/pull/2508))" +"TAMUNA ([#2254](https://github.com/adap/flower/pull/2254), [#2508](https://" +"github.com/adap/flower/pull/2508))" msgstr "" #: ../../source/ref-changelog.md:35 @@ -7196,67 +8365,82 @@ msgstr "" #: ../../source/ref-changelog.md:49 msgid "" -"FedBN ([#2608](https://github.com/adap/flower/pull/2608), " -"[#2615](https://github.com/adap/flower/pull/2615))" +"FedBN ([#2608](https://github.com/adap/flower/pull/2608), [#2615](https://" +"github.com/adap/flower/pull/2615))" msgstr "" #: ../../source/ref-changelog.md:51 msgid "" -"**Update Flower Examples** " -"([#2384](https://github.com/adap/flower/pull/2384),[#2425](https://github.com/adap/flower/pull/2425)," -" [#2526](https://github.com/adap/flower/pull/2526))" +"**Update Flower Examples** ([#2384](https://github.com/adap/flower/" +"pull/2384),[#2425](https://github.com/adap/flower/pull/2425), [#2526]" +"(https://github.com/adap/flower/pull/2526))" msgstr "" +"** 更新 Flower 示例** ([#2384](https://github.com/adap/flower/pull/2384)," +"[#2425](https://github.com/adap/flower/pull/2425), [#2526](https://github." +"com/adap/flower/pull/2526))" #: ../../source/ref-changelog.md:53 msgid "" -"**General updates to baselines** " -"([#2301](https://github.com/adap/flower/pull/2301), " -"[#2305](https://github.com/adap/flower/pull/2305), " -"[#2307](https://github.com/adap/flower/pull/2307), " -"[#2327](https://github.com/adap/flower/pull/2327), " -"[#2435](https://github.com/adap/flower/pull/2435))" +"**General updates to baselines** ([#2301](https://github.com/adap/flower/" +"pull/2301), [#2305](https://github.com/adap/flower/pull/2305), [#2307]" +"(https://github.com/adap/flower/pull/2307), [#2327](https://github.com/adap/" +"flower/pull/2327), [#2435](https://github.com/adap/flower/pull/2435))" msgstr "" +"**基准的一般更新** ([#2301](https://github.com/adap/flower/pull/2301), " +"[#2305](https://github.com/adap/flower/pull/2305), [#2307](https://github." +"com/adap/flower/pull/2307), [#2327](https://github.com/adap/flower/" +"pull/2327), [#2435](https://github.com/adap/flower/pull/2435))" #: ../../source/ref-changelog.md:55 msgid "" -"**General updates to the simulation engine** " -"([#2331](https://github.com/adap/flower/pull/2331), " -"[#2447](https://github.com/adap/flower/pull/2447), " +"**General updates to the simulation engine** ([#2331](https://github.com/" +"adap/flower/pull/2331), [#2447](https://github.com/adap/flower/pull/2447), " "[#2448](https://github.com/adap/flower/pull/2448))" msgstr "" +"**模拟引擎的一般更新** ([#2331](https://github.com/adap/flower/pull/2331), " +"[#2447](https://github.com/adap/flower/pull/2447), [#2448](https://github." +"com/adap/flower/pull/2448))" #: ../../source/ref-changelog.md:57 msgid "" -"**General improvements** " -"([#2309](https://github.com/adap/flower/pull/2309), " -"[#2310](https://github.com/adap/flower/pull/2310), " -"[2313](https://github.com/adap/flower/pull/2313), " -"[#2316](https://github.com/adap/flower/pull/2316), " -"[2317](https://github.com/adap/flower/pull/2317),[#2349](https://github.com/adap/flower/pull/2349)," -" [#2360](https://github.com/adap/flower/pull/2360), " -"[#2402](https://github.com/adap/flower/pull/2402), " -"[#2446](https://github.com/adap/flower/pull/2446) " -"[#2561](https://github.com/adap/flower/pull/2561))" -msgstr "" +"**General improvements** ([#2309](https://github.com/adap/flower/pull/2309), " +"[#2310](https://github.com/adap/flower/pull/2310), [2313](https://github.com/" +"adap/flower/pull/2313), [#2316](https://github.com/adap/flower/pull/2316), " +"[2317](https://github.com/adap/flower/pull/2317),[#2349](https://github.com/" +"adap/flower/pull/2349), [#2360](https://github.com/adap/flower/pull/2360), " +"[#2402](https://github.com/adap/flower/pull/2402), [#2446](https://github." +"com/adap/flower/pull/2446) [#2561](https://github.com/adap/flower/pull/2561))" +msgstr "" +"**一般改进**([#2309](https://github.com/adap/flower/pull/2309), [#2310]" +"(https://github.com/adap/flower/pull/2310), [2313](https://github.com/adap/" +"flower/pull/2313), [#2316](https://github.com/adap/flower/pull/2316), [2317]" +"(https://github.com/adap/flower/pull/2317),[#2349](https://github.com/adap/" +"flower/pull/2349), [#2360](https://github.com/adap/flower/pull/2360), [#2402]" +"(https://github.com/adap/flower/pull/2402), [#2446](https://github.com/adap/" +"flower/pull/2446) [#2561](https://github.com/adap/flower/pull/2561))" #: ../../source/ref-changelog.md:59 ../../source/ref-changelog.md:153 #: ../../source/ref-changelog.md:217 ../../source/ref-changelog.md:271 #: ../../source/ref-changelog.md:338 -msgid "Flower received many improvements under the hood, too many to list here." -msgstr "" +msgid "" +"Flower received many improvements under the hood, too many to list here." +msgstr "Flower 在引擎盖下进行了许多改进,这里就不一一列举了。" #: ../../source/ref-changelog.md:61 msgid "" -"**Add new** `Bulyan` **strategy** " -"([#1817](https://github.com/adap/flower/pull/1817), " -"[#1891](https://github.com/adap/flower/pull/1891))" +"**Add new** `Bulyan` **strategy** ([#1817](https://github.com/adap/flower/" +"pull/1817), [#1891](https://github.com/adap/flower/pull/1891))" msgstr "" +"**添加新**\"Bulyan \"**策略**([#1817](https://github.com/adap/flower/" +"pull/1817), [#1891](https://github.com/adap/flower/pull/1891)" #: ../../source/ref-changelog.md:63 msgid "" -"The new `Bulyan` strategy implements Bulyan by [El Mhamdi et al., " -"2018](https://arxiv.org/abs/1802.07927)" +"The new `Bulyan` strategy implements Bulyan by [El Mhamdi et al., 2018]" +"(https://arxiv.org/abs/1802.07927)" msgstr "" +"新的 \"Bulyan\"策略通过[El Mhamdi 等人,2018](https://arxiv.org/" +"abs/1802.07927)实现" #: ../../source/ref-changelog.md:65 ../../source/ref-changelog.md:155 #: ../../source/ref-changelog.md:219 ../../source/ref-changelog.md:277 @@ -7265,37 +8449,46 @@ msgstr "" #: ../../source/ref-changelog.md:654 ../../source/ref-changelog.md:691 #: ../../source/ref-changelog.md:734 msgid "Incompatible changes" -msgstr "" +msgstr "不兼容的更改" #: ../../source/ref-changelog.md:67 msgid "" -"**Remove support for Python 3.7** " -"([#2280](https://github.com/adap/flower/pull/2280), " -"[#2299](https://github.com/adap/flower/pull/2299), " -"[#2304](https://github.com/adap/flower/pull/2304), " -"[#2306](https://github.com/adap/flower/pull/2306), " -"[#2355](https://github.com/adap/flower/pull/2355), " -"[#2356](https://github.com/adap/flower/pull/2356))" +"**Remove support for Python 3.7** ([#2280](https://github.com/adap/flower/" +"pull/2280), [#2299](https://github.com/adap/flower/pull/2299), [#2304]" +"(https://github.com/adap/flower/pull/2304), [#2306](https://github.com/adap/" +"flower/pull/2306), [#2355](https://github.com/adap/flower/pull/2355), [#2356]" +"(https://github.com/adap/flower/pull/2356))" msgstr "" +"**移除对 Python 3.7 的支持** ([#2280](https://github.com/adap/flower/" +"pull/2280), [#2299](https://github.com/adap/flower/pull/2299), [#2304]" +"(https://github.com/adap/flower/pull/2304), [#2306](https://github.com/adap/" +"flower/pull/2306), [#2355](https://github.com/adap/flower/pull/2355), [#2356]" +"(https://github.com/adap/flower/pull/2356))" #: ../../source/ref-changelog.md:69 msgid "" -"Python 3.7 support was deprecated in Flower 1.5, and this release removes" -" support. Flower now requires Python 3.8." +"Python 3.7 support was deprecated in Flower 1.5, and this release removes " +"support. Flower now requires Python 3.8." msgstr "" +"在 Flower 1.5 中,Python 3.7 支持已被弃用,本版本将删除该支持。Flower 现在需" +"要 Python 3.8。" #: ../../source/ref-changelog.md:71 msgid "" -"**Remove experimental argument** `rest` **from** `start_client` " -"([#2324](https://github.com/adap/flower/pull/2324))" +"**Remove experimental argument** `rest` **from** `start_client` ([#2324]" +"(https://github.com/adap/flower/pull/2324))" msgstr "" +"**从** `start_client` 中移除** `rest` **实验参数 ([#2324](https://github.com/" +"adap/flower/pull/2324))" #: ../../source/ref-changelog.md:73 msgid "" -"The (still experimental) argument `rest` was removed from `start_client` " -"and `start_numpy_client`. Use `transport=\"rest\"` to opt into the " -"experimental REST API instead." +"The (still experimental) argument `rest` was removed from `start_client` and " +"`start_numpy_client`. Use `transport=\"rest\"` to opt into the experimental " +"REST API instead." msgstr "" +"删除了 `start_client` 和 `start_numpy_client` 中的参数 `rest`(仍属试验性" +"质)。请使用 `transport=\"rest\"` 来选择使用试验性 REST API。" #: ../../source/ref-changelog.md:75 msgid "v1.5.0 (2023-08-31)" @@ -7305,14 +8498,16 @@ msgstr "" #: ../../source/ref-changelog.md:225 ../../source/ref-changelog.md:283 #: ../../source/ref-changelog.md:352 ../../source/ref-changelog.md:421 msgid "Thanks to our contributors" -msgstr "" +msgstr "感谢我们的贡献者" #: ../../source/ref-changelog.md:79 ../../source/ref-changelog.md:163 #: ../../source/ref-changelog.md:227 ../../source/ref-changelog.md:285 msgid "" -"We would like to give our special thanks to all the contributors who made" -" the new version of Flower possible (in `git shortlog` order):" +"We would like to give our special thanks to all the contributors who made " +"the new version of Flower possible (in `git shortlog` order):" msgstr "" +"在此,我们要特别感谢所有为 Flower 的新版本做出贡献的人员(按 `git shortlog` " +"顺序排列):" #: ../../source/ref-changelog.md:81 msgid "" @@ -7325,297 +8520,344 @@ msgstr "" #: ../../source/ref-changelog.md:85 msgid "" -"**Introduce new simulation engine** " -"([#1969](https://github.com/adap/flower/pull/1969), " -"[#2221](https://github.com/adap/flower/pull/2221), " -"[#2248](https://github.com/adap/flower/pull/2248))" +"**Introduce new simulation engine** ([#1969](https://github.com/adap/flower/" +"pull/1969), [#2221](https://github.com/adap/flower/pull/2221), [#2248]" +"(https://github.com/adap/flower/pull/2248))" msgstr "" +"**引入新的模拟引擎** ([#1969](https://github.com/adap/flower/pull/1969), " +"[#2221](https://github.com/adap/flower/pull/2221), [#2248](https://github." +"com/adap/flower/pull/2248))" #: ../../source/ref-changelog.md:87 msgid "" "The new simulation engine has been rewritten from the ground up, yet it " -"remains fully backwards compatible. It offers much improved stability and" -" memory handling, especially when working with GPUs. Simulations " -"transparently adapt to different settings to scale simulation in CPU-" -"only, CPU+GPU, multi-GPU, or multi-node multi-GPU environments." +"remains fully backwards compatible. It offers much improved stability and " +"memory handling, especially when working with GPUs. Simulations " +"transparently adapt to different settings to scale simulation in CPU-only, " +"CPU+GPU, multi-GPU, or multi-node multi-GPU environments." msgstr "" +"新的模拟引擎从头开始重新编写,但仍完全向后兼容。它的稳定性和内存处理能力大大" +"提高,尤其是在使用 GPU 时。仿真可透明地适应不同的设置,以在仅 CPU、CPU+GPU、" +"多 GPU 或多节点多 GPU 环境中扩展仿真。" #: ../../source/ref-changelog.md:89 msgid "" -"Comprehensive documentation includes a new [how-to run " -"simulations](https://flower.dev/docs/framework/how-to-run-" -"simulations.html) guide, new [simulation-" -"pytorch](https://flower.dev/docs/examples/simulation-pytorch.html) and " -"[simulation-tensorflow](https://flower.dev/docs/examples/simulation-" -"tensorflow.html) notebooks, and a new [YouTube tutorial " -"series](https://www.youtube.com/watch?v=cRebUIGB5RU&list=PLNG4feLHqCWlnj8a_E1A_n5zr2-8pafTB)." -msgstr "" +"Comprehensive documentation includes a new [how-to run simulations](https://" +"flower.dev/docs/framework/how-to-run-simulations.html) guide, new " +"[simulation-pytorch](https://flower.dev/docs/examples/simulation-pytorch." +"html) and [simulation-tensorflow](https://flower.dev/docs/examples/" +"simulation-tensorflow.html) notebooks, and a new [YouTube tutorial series]" +"(https://www.youtube.com/watch?" +"v=cRebUIGB5RU&list=PLNG4feLHqCWlnj8a_E1A_n5zr2-8pafTB)." +msgstr "" +"综合文档包括新的[如何运行仿真](https://flower.dev/docs/framework/how-to-run-" +"simulations.html) 指南、新的[simulation-pytorch](https://flower.dev/docs/" +"examples/simulation-pytorch.html) 和[simulation-tensorflow](https://flower." +"dev/docs/examples/simulation-tensorflow.html) 笔记本,以及新的[YouTube 教程系" +"列](https://www.youtube.com/watch?" +"v=cRebUIGB5RU&list=PLNG4feLHqCWlnj8a_E1A_n5zr2-8pafTB)。" #: ../../source/ref-changelog.md:91 msgid "" -"**Restructure Flower Docs** " -"([#1824](https://github.com/adap/flower/pull/1824), " -"[#1865](https://github.com/adap/flower/pull/1865), " -"[#1884](https://github.com/adap/flower/pull/1884), " -"[#1887](https://github.com/adap/flower/pull/1887), " -"[#1919](https://github.com/adap/flower/pull/1919), " -"[#1922](https://github.com/adap/flower/pull/1922), " -"[#1920](https://github.com/adap/flower/pull/1920), " -"[#1923](https://github.com/adap/flower/pull/1923), " -"[#1924](https://github.com/adap/flower/pull/1924), " -"[#1962](https://github.com/adap/flower/pull/1962), " -"[#2006](https://github.com/adap/flower/pull/2006), " -"[#2133](https://github.com/adap/flower/pull/2133), " -"[#2203](https://github.com/adap/flower/pull/2203), " -"[#2215](https://github.com/adap/flower/pull/2215), " -"[#2122](https://github.com/adap/flower/pull/2122), " -"[#2223](https://github.com/adap/flower/pull/2223), " -"[#2219](https://github.com/adap/flower/pull/2219), " -"[#2232](https://github.com/adap/flower/pull/2232), " -"[#2233](https://github.com/adap/flower/pull/2233), " -"[#2234](https://github.com/adap/flower/pull/2234), " -"[#2235](https://github.com/adap/flower/pull/2235), " -"[#2237](https://github.com/adap/flower/pull/2237), " -"[#2238](https://github.com/adap/flower/pull/2238), " -"[#2242](https://github.com/adap/flower/pull/2242), " -"[#2231](https://github.com/adap/flower/pull/2231), " -"[#2243](https://github.com/adap/flower/pull/2243), " -"[#2227](https://github.com/adap/flower/pull/2227))" +"**Restructure Flower Docs** ([#1824](https://github.com/adap/flower/" +"pull/1824), [#1865](https://github.com/adap/flower/pull/1865), [#1884]" +"(https://github.com/adap/flower/pull/1884), [#1887](https://github.com/adap/" +"flower/pull/1887), [#1919](https://github.com/adap/flower/pull/1919), [#1922]" +"(https://github.com/adap/flower/pull/1922), [#1920](https://github.com/adap/" +"flower/pull/1920), [#1923](https://github.com/adap/flower/pull/1923), [#1924]" +"(https://github.com/adap/flower/pull/1924), [#1962](https://github.com/adap/" +"flower/pull/1962), [#2006](https://github.com/adap/flower/pull/2006), [#2133]" +"(https://github.com/adap/flower/pull/2133), [#2203](https://github.com/adap/" +"flower/pull/2203), [#2215](https://github.com/adap/flower/pull/2215), [#2122]" +"(https://github.com/adap/flower/pull/2122), [#2223](https://github.com/adap/" +"flower/pull/2223), [#2219](https://github.com/adap/flower/pull/2219), [#2232]" +"(https://github.com/adap/flower/pull/2232), [#2233](https://github.com/adap/" +"flower/pull/2233), [#2234](https://github.com/adap/flower/pull/2234), [#2235]" +"(https://github.com/adap/flower/pull/2235), [#2237](https://github.com/adap/" +"flower/pull/2237), [#2238](https://github.com/adap/flower/pull/2238), [#2242]" +"(https://github.com/adap/flower/pull/2242), [#2231](https://github.com/adap/" +"flower/pull/2231), [#2243](https://github.com/adap/flower/pull/2243), [#2227]" +"(https://github.com/adap/flower/pull/2227))" msgstr "" #: ../../source/ref-changelog.md:93 msgid "" -"Much effort went into a completely restructured Flower docs experience. " -"The documentation on [flower.dev/docs](flower.dev/docs) is now divided " -"into Flower Framework, Flower Baselines, Flower Android SDK, Flower iOS " -"SDK, and code example projects." +"Much effort went into a completely restructured Flower docs experience. The " +"documentation on [flower.dev/docs](flower.dev/docs) is now divided into " +"Flower Framework, Flower Baselines, Flower Android SDK, Flower iOS SDK, and " +"code example projects." msgstr "" +"Flower 文档体验的全面重构耗费了大量精力。现在,[flower.dev/docs](flower.dev/" +"docs)上的文档分为 Flower Framework、Flower Baselines、Flower Android SDK、" +"Flower iOS SDK 和代码示例项目。" #: ../../source/ref-changelog.md:95 msgid "" -"**Introduce Flower Swift SDK** " -"([#1858](https://github.com/adap/flower/pull/1858), " -"[#1897](https://github.com/adap/flower/pull/1897))" +"**Introduce Flower Swift SDK** ([#1858](https://github.com/adap/flower/" +"pull/1858), [#1897](https://github.com/adap/flower/pull/1897))" msgstr "" #: ../../source/ref-changelog.md:97 msgid "" -"This is the first preview release of the Flower Swift SDK. Flower support" -" on iOS is improving, and alongside the Swift SDK and code example, there" -" is now also an iOS quickstart tutorial." +"This is the first preview release of the Flower Swift SDK. Flower support on " +"iOS is improving, and alongside the Swift SDK and code example, there is now " +"also an iOS quickstart tutorial." msgstr "" +"这是 Flower Swift SDK 的首个预览版。Flower 对 iOS 的支持正在不断改进,除了 " +"Swift SDK 和代码示例外,现在还有 iOS 快速入门教程。" #: ../../source/ref-changelog.md:99 msgid "" -"**Introduce Flower Android SDK** " -"([#2131](https://github.com/adap/flower/pull/2131))" +"**Introduce Flower Android SDK** ([#2131](https://github.com/adap/flower/" +"pull/2131))" msgstr "" +"**介绍Flower Android SDK** ([#2131](https://github.com/adap/flower/" +"pull/2131))" #: ../../source/ref-changelog.md:101 msgid "" -"This is the first preview release of the Flower Kotlin SDK. Flower " -"support on Android is improving, and alongside the Kotlin SDK and code " -"example, there is now also an Android quickstart tutorial." +"This is the first preview release of the Flower Kotlin SDK. Flower support " +"on Android is improving, and alongside the Kotlin SDK and code example, " +"there is now also an Android quickstart tutorial." msgstr "" +"这是 Flower Kotlin SDK 的首个预览版。Flower 对 Android 的支持正在不断改进,除" +"了 Kotlin SDK 和代码示例,现在还有 Android 快速入门教程。" #: ../../source/ref-changelog.md:103 msgid "" -"**Introduce new end-to-end testing infrastructure** " -"([#1842](https://github.com/adap/flower/pull/1842), " -"[#2071](https://github.com/adap/flower/pull/2071), " -"[#2072](https://github.com/adap/flower/pull/2072), " -"[#2068](https://github.com/adap/flower/pull/2068), " -"[#2067](https://github.com/adap/flower/pull/2067), " -"[#2069](https://github.com/adap/flower/pull/2069), " -"[#2073](https://github.com/adap/flower/pull/2073), " -"[#2070](https://github.com/adap/flower/pull/2070), " -"[#2074](https://github.com/adap/flower/pull/2074), " -"[#2082](https://github.com/adap/flower/pull/2082), " -"[#2084](https://github.com/adap/flower/pull/2084), " -"[#2093](https://github.com/adap/flower/pull/2093), " -"[#2109](https://github.com/adap/flower/pull/2109), " -"[#2095](https://github.com/adap/flower/pull/2095), " -"[#2140](https://github.com/adap/flower/pull/2140), " -"[#2137](https://github.com/adap/flower/pull/2137), " -"[#2165](https://github.com/adap/flower/pull/2165))" +"**Introduce new end-to-end testing infrastructure** ([#1842](https://github." +"com/adap/flower/pull/1842), [#2071](https://github.com/adap/flower/" +"pull/2071), [#2072](https://github.com/adap/flower/pull/2072), [#2068]" +"(https://github.com/adap/flower/pull/2068), [#2067](https://github.com/adap/" +"flower/pull/2067), [#2069](https://github.com/adap/flower/pull/2069), [#2073]" +"(https://github.com/adap/flower/pull/2073), [#2070](https://github.com/adap/" +"flower/pull/2070), [#2074](https://github.com/adap/flower/pull/2074), [#2082]" +"(https://github.com/adap/flower/pull/2082), [#2084](https://github.com/adap/" +"flower/pull/2084), [#2093](https://github.com/adap/flower/pull/2093), [#2109]" +"(https://github.com/adap/flower/pull/2109), [#2095](https://github.com/adap/" +"flower/pull/2095), [#2140](https://github.com/adap/flower/pull/2140), [#2137]" +"(https://github.com/adap/flower/pull/2137), [#2165](https://github.com/adap/" +"flower/pull/2165))" msgstr "" #: ../../source/ref-changelog.md:105 msgid "" -"A new testing infrastructure ensures that new changes stay compatible " -"with existing framework integrations or strategies." -msgstr "" +"A new testing infrastructure ensures that new changes stay compatible with " +"existing framework integrations or strategies." +msgstr "新的测试基础设施可确保新的变更与现有的框架集成或策略保持兼容。" #: ../../source/ref-changelog.md:107 msgid "**Deprecate Python 3.7**" -msgstr "" +msgstr "** 过时的 Python 3.7**" #: ../../source/ref-changelog.md:109 msgid "" -"Since Python 3.7 reached its end of life (EOL) on 2023-06-27, support for" -" Python 3.7 is now deprecated and will be removed in an upcoming release." +"Since Python 3.7 reached its end of life (EOL) on 2023-06-27, support for " +"Python 3.7 is now deprecated and will be removed in an upcoming release." msgstr "" +"由于 Python 3.7 已于 2023-06-27 结束生命 (EOL),对 Python 3.7 的支持现已废" +"弃,并将在即将发布的版本中移除。" #: ../../source/ref-changelog.md:111 msgid "" -"**Add new** `FedTrimmedAvg` **strategy** " -"([#1769](https://github.com/adap/flower/pull/1769), " -"[#1853](https://github.com/adap/flower/pull/1853))" +"**Add new** `FedTrimmedAvg` **strategy** ([#1769](https://github.com/adap/" +"flower/pull/1769), [#1853](https://github.com/adap/flower/pull/1853))" msgstr "" +"**添加新**`FedTrimmedAvg`**策略**([#1769](https://github.com/adap/flower/" +"pull/1769), [#1853](https://github.com/adap/flower/pull/1853)" #: ../../source/ref-changelog.md:113 msgid "" -"The new `FedTrimmedAvg` strategy implements Trimmed Mean by [Dong Yin, " -"2018](https://arxiv.org/abs/1803.01498)." +"The new `FedTrimmedAvg` strategy implements Trimmed Mean by [Dong Yin, 2018]" +"(https://arxiv.org/abs/1803.01498)." msgstr "" +"新的 \"FedTrimmedAvg \"策略实现了[Dong Yin, 2018](https://arxiv.org/" +"abs/1803.01498)的 \"Trimmed Mean\"。" #: ../../source/ref-changelog.md:115 msgid "" -"**Introduce start_driver** " -"([#1697](https://github.com/adap/flower/pull/1697))" +"**Introduce start_driver** ([#1697](https://github.com/adap/flower/" +"pull/1697))" msgstr "" +"**引入 start_driver**([#1697](https://github.com/adap/flower/pull/1697))" #: ../../source/ref-changelog.md:117 msgid "" -"In addition to `start_server` and using the raw Driver API, there is a " -"new `start_driver` function that allows for running `start_server` " -"scripts as a Flower driver with only a single-line code change. Check out" -" the `mt-pytorch` code example to see a working example using " -"`start_driver`." +"In addition to `start_server` and using the raw Driver API, there is a new " +"`start_driver` function that allows for running `start_server` scripts as a " +"Flower driver with only a single-line code change. Check out the `mt-" +"pytorch` code example to see a working example using `start_driver`." msgstr "" +"除了 `start_server` 和使用原始驱动 API 之外,还有一个新的 `start_driver` 函" +"数,只需修改一行代码,就能将 `start_server` 脚本作为 Flower 驱动程序运行。请" +"查看 `mt-pytorch` 代码示例,了解使用 `start_driver` 的工作示例。" #: ../../source/ref-changelog.md:119 msgid "" -"**Add parameter aggregation to** `mt-pytorch` **code example** " -"([#1785](https://github.com/adap/flower/pull/1785))" +"**Add parameter aggregation to** `mt-pytorch` **code example** ([#1785]" +"(https://github.com/adap/flower/pull/1785))" msgstr "" +"**为** `mt-pytorch` **代码示例**添加参数聚合 ([#1785](https://github.com/" +"adap/flower/pull/1785))" #: ../../source/ref-changelog.md:121 msgid "" -"The `mt-pytorch` example shows how to aggregate parameters when writing a" -" driver script. The included `driver.py` and `server.py` have been " -"aligned to demonstrate both the low-level way and the high-level way of " -"building server-side logic." +"The `mt-pytorch` example shows how to aggregate parameters when writing a " +"driver script. The included `driver.py` and `server.py` have been aligned to " +"demonstrate both the low-level way and the high-level way of building server-" +"side logic." msgstr "" +"mt-pytorch \"示例展示了如何在编写驱动程序脚本时汇总参数。附带的 `driver.py` " +"和 `server.py` 已经进行了调整,以演示构建服务器端逻辑的低级方法和高级方法。" #: ../../source/ref-changelog.md:123 msgid "" -"**Migrate experimental REST API to Starlette** " -"([2171](https://github.com/adap/flower/pull/2171))" +"**Migrate experimental REST API to Starlette** ([2171](https://github.com/" +"adap/flower/pull/2171))" msgstr "" +"**将实验性 REST API 移植到 Starlette** ([2171](https://github.com/adap/" +"flower/pull/2171))" #: ../../source/ref-changelog.md:125 msgid "" -"The (experimental) REST API used to be implemented in " -"[FastAPI](https://fastapi.tiangolo.com/), but it has now been migrated to" -" use [Starlette](https://www.starlette.io/) directly." +"The (experimental) REST API used to be implemented in [FastAPI](https://" +"fastapi.tiangolo.com/), but it has now been migrated to use [Starlette]" +"(https://www.starlette.io/) directly." msgstr "" +"REST API(试验性)曾在 [FastAPI](https://fastapi.tiangolo.com/) 中实现,但现" +"在已迁移到直接使用 [Starlette](https://www.starlette.io/) 。" #: ../../source/ref-changelog.md:127 msgid "" -"Please note: The REST request-response API is still experimental and will" -" likely change significantly over time." +"Please note: The REST request-response API is still experimental and will " +"likely change significantly over time." msgstr "" +"请注意:REST 请求-响应 API 仍处于试验阶段,随着时间的推移可能会发生重大变化。" #: ../../source/ref-changelog.md:129 msgid "" -"**Introduce experimental gRPC request-response API** " -"([#1867](https://github.com/adap/flower/pull/1867), " -"[#1901](https://github.com/adap/flower/pull/1901))" +"**Introduce experimental gRPC request-response API** ([#1867](https://github." +"com/adap/flower/pull/1867), [#1901](https://github.com/adap/flower/" +"pull/1901))" msgstr "" +"**引入实验性 gRPC 请求-响应 API** ([#1867](https://github.com/adap/flower/" +"pull/1867), [#1901](https://github.com/adap/flower/pull/1901)" #: ../../source/ref-changelog.md:131 msgid "" -"In addition to the existing gRPC API (based on bidirectional streaming) " -"and the experimental REST API, there is now a new gRPC API that uses a " -"request-response model to communicate with client nodes." +"In addition to the existing gRPC API (based on bidirectional streaming) and " +"the experimental REST API, there is now a new gRPC API that uses a request-" +"response model to communicate with client nodes." msgstr "" +"除了现有的 gRPC 应用程序接口(基于双向流)和试验性 REST 应用程序接口外,现在" +"还有一个新的 gRPC 应用程序接口,它使用请求-响应模型与客户端节点通信。" #: ../../source/ref-changelog.md:133 msgid "" -"Please note: The gRPC request-response API is still experimental and will" -" likely change significantly over time." +"Please note: The gRPC request-response API is still experimental and will " +"likely change significantly over time." msgstr "" +"请注意:gRPC 请求-响应 API 仍处于试验阶段,随着时间的推移可能会发生重大变化。" #: ../../source/ref-changelog.md:135 msgid "" "**Replace the experimental** `start_client(rest=True)` **with the new** " -"`start_client(transport=\"rest\")` " -"([#1880](https://github.com/adap/flower/pull/1880))" +"`start_client(transport=\"rest\")` ([#1880](https://github.com/adap/flower/" +"pull/1880))" msgstr "" +"**用新的** `start_client(transport=\"rest\")` 替换实验性** " +"`start_client(rest=True)` ([#1880](https://github.com/adap/flower/pull/1880))" #: ../../source/ref-changelog.md:137 msgid "" -"The (experimental) `start_client` argument `rest` was deprecated in " -"favour of a new argument `transport`. `start_client(transport=\"rest\")` " -"will yield the same behaviour as `start_client(rest=True)` did before. " -"All code should migrate to the new argument `transport`. The deprecated " -"argument `rest` will be removed in a future release." +"The (experimental) `start_client` argument `rest` was deprecated in favour " +"of a new argument `transport`. `start_client(transport=\"rest\")` will yield " +"the same behaviour as `start_client(rest=True)` did before. All code should " +"migrate to the new argument `transport`. The deprecated argument `rest` will " +"be removed in a future release." msgstr "" +"已废弃(试验性的)`start_client`参数`rest`,改用新参数`transport`。" +"`start_client(transport=\"rest\")`将产生与以前的`start_client(rest=True)`相同" +"的行为。所有代码都应迁移到新参数 `transport`。过时的参数 `rest` 将在今后的版" +"本中删除。" #: ../../source/ref-changelog.md:139 msgid "" -"**Add a new gRPC option** " -"([#2197](https://github.com/adap/flower/pull/2197))" +"**Add a new gRPC option** ([#2197](https://github.com/adap/flower/pull/2197))" msgstr "" +"** 添加一个新的 gRPC 选项**([#2197](https://github.com/adap/flower/" +"pull/2197))" #: ../../source/ref-changelog.md:141 msgid "" -"We now start a gRPC server with the `grpc.keepalive_permit_without_calls`" -" option set to 0 by default. This prevents the clients from sending " -"keepalive pings when there is no outstanding stream." +"We now start a gRPC server with the `grpc.keepalive_permit_without_calls` " +"option set to 0 by default. This prevents the clients from sending keepalive " +"pings when there is no outstanding stream." msgstr "" +"现在我们启动一个 gRPC 服务器,并将 `grpc.keepalive_permit_without_calls` 选项" +"默认设置为 0。这将防止客户端在没有未处理数据流时发送 keepalive ping。" #: ../../source/ref-changelog.md:143 msgid "" -"**Improve example notebooks** " -"([#2005](https://github.com/adap/flower/pull/2005))" -msgstr "" +"**Improve example notebooks** ([#2005](https://github.com/adap/flower/" +"pull/2005))" +msgstr "**改进示例笔记本** ([#2005](https://github.com/adap/flower/pull/2005))" #: ../../source/ref-changelog.md:145 msgid "There's a new 30min Federated Learning PyTorch tutorial!" -msgstr "" +msgstr "有一个新的 30 分钟 Federated Learning PyTorch 教程!" #: ../../source/ref-changelog.md:147 msgid "" "**Example updates** ([#1772](https://github.com/adap/flower/pull/1772), " -"[#1873](https://github.com/adap/flower/pull/1873), " -"[#1981](https://github.com/adap/flower/pull/1981), " -"[#1988](https://github.com/adap/flower/pull/1988), " -"[#1984](https://github.com/adap/flower/pull/1984), " -"[#1982](https://github.com/adap/flower/pull/1982), " -"[#2112](https://github.com/adap/flower/pull/2112), " -"[#2144](https://github.com/adap/flower/pull/2144), " -"[#2174](https://github.com/adap/flower/pull/2174), " -"[#2225](https://github.com/adap/flower/pull/2225), " -"[#2183](https://github.com/adap/flower/pull/2183))" -msgstr "" +"[#1873](https://github.com/adap/flower/pull/1873), [#1981](https://github." +"com/adap/flower/pull/1981), [#1988](https://github.com/adap/flower/" +"pull/1988), [#1984](https://github.com/adap/flower/pull/1984), [#1982]" +"(https://github.com/adap/flower/pull/1982), [#2112](https://github.com/adap/" +"flower/pull/2112), [#2144](https://github.com/adap/flower/pull/2144), [#2174]" +"(https://github.com/adap/flower/pull/2174), [#2225](https://github.com/adap/" +"flower/pull/2225), [#2183](https://github.com/adap/flower/pull/2183))" +msgstr "" +"**更新示例** ([#1772](https://github.com/adap/flower/pull/1772), [#1873]" +"(https://github.com/adap/flower/pull/1873), [#1981](https://github.com/adap/" +"flower/pull/1981), [#1988](https://github.com/adap/flower/pull/1988), [#1984]" +"(https://github.com/adap/flower/pull/1984), [#1982](https://github.com/adap/" +"flower/pull/1982), [#2112](https://github.com/adap/flower/pull/2112), [#2144]" +"(https://github.com/adap/flower/pull/2144), [#2174](https://github.com/adap/" +"flower/pull/2174), [#2225](https://github.com/adap/flower/pull/2225), [#2183]" +"(https://github.com/adap/flower/pull/2183))" #: ../../source/ref-changelog.md:149 msgid "" "Many examples have received significant updates, including simplified " "advanced-tensorflow and advanced-pytorch examples, improved macOS " -"compatibility of TensorFlow examples, and code examples for simulation. A" -" major upgrade is that all code examples now have a `requirements.txt` " -"(in addition to `pyproject.toml`)." +"compatibility of TensorFlow examples, and code examples for simulation. A " +"major upgrade is that all code examples now have a `requirements.txt` (in " +"addition to `pyproject.toml`)." msgstr "" +"许多示例都进行了重大更新,包括简化了 advanced-tensorflow 和 advanced-pytorch " +"示例,改进了 TensorFlow 示例的 macOS 兼容性,以及仿真代码示例。一项重大升级是" +"所有代码示例现在都有了 \"requirements.txt\"(除 \"pyproject.toml \"外)。" #: ../../source/ref-changelog.md:151 msgid "" -"**General improvements** " -"([#1872](https://github.com/adap/flower/pull/1872), " -"[#1866](https://github.com/adap/flower/pull/1866), " -"[#1884](https://github.com/adap/flower/pull/1884), " -"[#1837](https://github.com/adap/flower/pull/1837), " -"[#1477](https://github.com/adap/flower/pull/1477), " -"[#2171](https://github.com/adap/flower/pull/2171))" +"**General improvements** ([#1872](https://github.com/adap/flower/pull/1872), " +"[#1866](https://github.com/adap/flower/pull/1866), [#1884](https://github." +"com/adap/flower/pull/1884), [#1837](https://github.com/adap/flower/" +"pull/1837), [#1477](https://github.com/adap/flower/pull/1477), [#2171]" +"(https://github.com/adap/flower/pull/2171))" msgstr "" +"**一般改进**([#1872](https://github.com/adap/flower/pull/1872), [#1866]" +"(https://github.com/adap/flower/pull/1866), [#1884](https://github.com/adap/" +"flower/pull/1884), [#1837](https://github.com/adap/flower/pull/1837), [#1477]" +"(https://github.com/adap/flower/pull/1477), [#2171](https://github.com/adap/" +"flower/pull/2171))" #: ../../source/ref-changelog.md:157 ../../source/ref-changelog.md:221 #: ../../source/ref-changelog.md:279 ../../source/ref-changelog.md:348 #: ../../source/ref-changelog.md:410 msgid "None" -msgstr "" +msgstr "无" #: ../../source/ref-changelog.md:159 msgid "v1.4.0 (2023-04-21)" @@ -7624,111 +8866,143 @@ msgstr "" #: ../../source/ref-changelog.md:165 msgid "" "`Adam Narozniak`, `Alexander Viala Bellander`, `Charles Beauville`, " -"`Chenyang Ma (Danny)`, `Daniel J. Beutel`, `Edoardo`, `Gautam Jajoo`, " -"`Iacob-Alexandru-Andrei`, `JDRanpariya`, `Jean Charle Yaacoub`, `Kunal " -"Sarkhel`, `L. Jiang`, `Lennart Behme`, `Max Kapsecker`, `Michał`, `Nic " -"Lane`, `Nikolaos Episkopos`, `Ragy`, `Saurav Maheshkar`, `Semo Yang`, " -"`Steve Laskaridis`, `Steven Hé (Sīchàng)`, `Taner Topal`" +"`Chenyang Ma (Danny)`, `Daniel J. Beutel`, `Edoardo`, `Gautam Jajoo`, `Iacob-" +"Alexandru-Andrei`, `JDRanpariya`, `Jean Charle Yaacoub`, `Kunal Sarkhel`, " +"`L. Jiang`, `Lennart Behme`, `Max Kapsecker`, `Michał`, `Nic Lane`, " +"`Nikolaos Episkopos`, `Ragy`, `Saurav Maheshkar`, `Semo Yang`, `Steve " +"Laskaridis`, `Steven Hé (Sīchàng)`, `Taner Topal`" msgstr "" #: ../../source/ref-changelog.md:169 msgid "" -"**Introduce support for XGBoost (**`FedXgbNnAvg` **strategy and " -"example)** ([#1694](https://github.com/adap/flower/pull/1694), " -"[#1709](https://github.com/adap/flower/pull/1709), " -"[#1715](https://github.com/adap/flower/pull/1715), " -"[#1717](https://github.com/adap/flower/pull/1717), " -"[#1763](https://github.com/adap/flower/pull/1763), " -"[#1795](https://github.com/adap/flower/pull/1795))" +"**Introduce support for XGBoost (**`FedXgbNnAvg` **strategy and example)** " +"([#1694](https://github.com/adap/flower/pull/1694), [#1709](https://github." +"com/adap/flower/pull/1709), [#1715](https://github.com/adap/flower/" +"pull/1715), [#1717](https://github.com/adap/flower/pull/1717), [#1763]" +"(https://github.com/adap/flower/pull/1763), [#1795](https://github.com/adap/" +"flower/pull/1795))" msgstr "" +"**引入对XGBoost的支持(**`FedXgbNnAvg` **策略和示例)** ([#1694](https://" +"github.com/adap/flower/pull/1694), [#1709](https://github.com/adap/flower/" +"pull/1709), [#1715](https://github.com/adap/flower/pull/1715), [#1717]" +"(https://github.com/adap/flower/pull/1717), [#1763](https://github.com/adap/" +"flower/pull/1763), [#1795](https://github.com/adap/flower/pull/1795))" #: ../../source/ref-changelog.md:171 msgid "" "XGBoost is a tree-based ensemble machine learning algorithm that uses " -"gradient boosting to improve model accuracy. We added a new `FedXgbNnAvg`" -" " -"[strategy](https://github.com/adap/flower/tree/main/src/py/flwr/server/strategy/fedxgb_nn_avg.py)," -" and a [code " -"example](https://github.com/adap/flower/tree/main/examples/quickstart_xgboost_horizontal)" -" that demonstrates the usage of this new strategy in an XGBoost project." -msgstr "" +"gradient boosting to improve model accuracy. We added a new `FedXgbNnAvg` " +"[strategy](https://github.com/adap/flower/tree/main/src/py/flwr/server/" +"strategy/fedxgb_nn_avg.py), and a [code example](https://github.com/adap/" +"flower/tree/main/examples/quickstart_xgboost_horizontal) that demonstrates " +"the usage of this new strategy in an XGBoost project." +msgstr "" +"XGBoost 是一种基于树的集合机器学习算法,它使用梯度提升来提高模型的准确性。我" +"们添加了一个新的 \"FedXgbNnAvg\"[策略](https://github.com/adap/flower/tree/" +"main/src/py/flwr/server/strategy/fedxgb_nn_avg.py)和一个[代码示例](https://" +"github.com/adap/flower/tree/main/examples/quickstart_xgboost_horizontal),演" +"示如何在 XGBoost 项目中使用这个新策略。" #: ../../source/ref-changelog.md:173 msgid "" -"**Introduce iOS SDK (preview)** " -"([#1621](https://github.com/adap/flower/pull/1621), " -"[#1764](https://github.com/adap/flower/pull/1764))" +"**Introduce iOS SDK (preview)** ([#1621](https://github.com/adap/flower/" +"pull/1621), [#1764](https://github.com/adap/flower/pull/1764))" msgstr "" +"**介绍 iOS SDK(预览版)** ([#1621](https://github.com/adap/flower/" +"pull/1621), [#1764](https://github.com/adap/flower/pull/1764))" #: ../../source/ref-changelog.md:175 msgid "" -"This is a major update for anyone wanting to implement Federated Learning" -" on iOS mobile devices. We now have a swift iOS SDK present under " -"[src/swift/flwr](https://github.com/adap/flower/tree/main/src/swift/flwr)" -" that will facilitate greatly the app creating process. To showcase its " -"use, the [iOS " +"This is a major update for anyone wanting to implement Federated Learning on " +"iOS mobile devices. We now have a swift iOS SDK present under [src/swift/" +"flwr](https://github.com/adap/flower/tree/main/src/swift/flwr) that will " +"facilitate greatly the app creating process. To showcase its use, the [iOS " "example](https://github.com/adap/flower/tree/main/examples/ios) has also " "been updated!" msgstr "" +"对于想要在 iOS 移动设备上实施联合学习的人来说,这是一次重大更新。现在,我们" +"在 [src/swift/flwr](https://github.com/adap/flower/tree/main/src/swift/flwr) " +"下提供了一个迅捷的 iOS SDK,这将大大方便应用程序的创建过程。为了展示其使用情" +"况,我们还更新了 [iOS 示例](https://github.com/adap/flower/tree/main/" +"examples/ios)!" #: ../../source/ref-changelog.md:177 msgid "" -"**Introduce new \"What is Federated Learning?\" tutorial** " -"([#1657](https://github.com/adap/flower/pull/1657), " -"[#1721](https://github.com/adap/flower/pull/1721))" +"**Introduce new \"What is Federated Learning?\" tutorial** ([#1657](https://" +"github.com/adap/flower/pull/1657), [#1721](https://github.com/adap/flower/" +"pull/1721))" msgstr "" +"**介绍新的 \"什么是联邦学习?\"教程**([#1657](https://github.com/adap/" +"flower/pull/1657), [#1721](https://github.com/adap/flower/pull/1721)" #: ../../source/ref-changelog.md:179 msgid "" -"A new [entry-level tutorial](https://flower.dev/docs/framework/tutorial-" -"what-is-federated-learning.html) in our documentation explains the basics" -" of Fedetated Learning. It enables anyone who's unfamiliar with Federated" -" Learning to start their journey with Flower. Forward it to anyone who's " +"A new [entry-level tutorial](https://flower.dev/docs/framework/tutorial-what-" +"is-federated-learning.html) in our documentation explains the basics of " +"Fedetated Learning. It enables anyone who's unfamiliar with Federated " +"Learning to start their journey with Flower. Forward it to anyone who's " "interested in Federated Learning!" msgstr "" +"我们的文档中新增了一个[入门级教程](https://flower.dev/docs/framework/" +"tutorial-what-is-federated-learning.html),解释了联合学习的基础知识。它让任何" +"不熟悉联合学习的人都能开始 Flower 之旅。请转发给对联合学习感兴趣的人!" #: ../../source/ref-changelog.md:181 msgid "" -"**Introduce new Flower Baseline: FedProx MNIST** " -"([#1513](https://github.com/adap/flower/pull/1513), " -"[#1680](https://github.com/adap/flower/pull/1680), " -"[#1681](https://github.com/adap/flower/pull/1681), " -"[#1679](https://github.com/adap/flower/pull/1679))" +"**Introduce new Flower Baseline: FedProx MNIST** ([#1513](https://github.com/" +"adap/flower/pull/1513), [#1680](https://github.com/adap/flower/pull/1680), " +"[#1681](https://github.com/adap/flower/pull/1681), [#1679](https://github." +"com/adap/flower/pull/1679))" msgstr "" +"**引入新的 Flower 基准: FedProx MNIST** ([#1513](https://github.com/adap/" +"flower/pull/1513), [#1680](https://github.com/adap/flower/pull/1680), [#1681]" +"(https://github.com/adap/flower/pull/1681), [#1679](https://github.com/adap/" +"flower/pull/1679)" #: ../../source/ref-changelog.md:183 msgid "" -"This new baseline replicates the MNIST+CNN task from the paper [Federated" -" Optimization in Heterogeneous Networks (Li et al., " -"2018)](https://arxiv.org/abs/1812.06127). It uses the `FedProx` strategy," -" which aims at making convergence more robust in heterogenous settings." +"This new baseline replicates the MNIST+CNN task from the paper [Federated " +"Optimization in Heterogeneous Networks (Li et al., 2018)](https://arxiv.org/" +"abs/1812.06127). It uses the `FedProx` strategy, which aims at making " +"convergence more robust in heterogenous settings." msgstr "" +"这条新基准复制了论文[Federated Optimization in Heterogeneous Networks (Li et " +"al., 2018)](https://arxiv.org/abs/1812.06127)中的 MNIST+CNN 任务。它使用 " +"\"FedProx \"策略,旨在使收敛在异构环境中更加稳健。" #: ../../source/ref-changelog.md:185 msgid "" -"**Introduce new Flower Baseline: FedAvg FEMNIST** " -"([#1655](https://github.com/adap/flower/pull/1655))" +"**Introduce new Flower Baseline: FedAvg FEMNIST** ([#1655](https://github." +"com/adap/flower/pull/1655))" msgstr "" +"**引入新的 Flower 基准: FedAvg FEMNIST** ([#1655](https://github.com/adap/" +"flower/pull/1655))" #: ../../source/ref-changelog.md:187 msgid "" -"This new baseline replicates an experiment evaluating the performance of " -"the FedAvg algorithm on the FEMNIST dataset from the paper [LEAF: A " -"Benchmark for Federated Settings (Caldas et al., " -"2018)](https://arxiv.org/abs/1812.01097)." +"This new baseline replicates an experiment evaluating the performance of the " +"FedAvg algorithm on the FEMNIST dataset from the paper [LEAF: A Benchmark " +"for Federated Settings (Caldas et al., 2018)](https://arxiv.org/" +"abs/1812.01097)." msgstr "" +"这一新基准复制了论文[LEAF:联合设置的基准(Caldas 等人,2018 年)](https://" +"arxiv.org/abs/1812.01097)中评估 FedAvg 算法在 FEMNIST 数据集上性能的实验。" #: ../../source/ref-changelog.md:189 msgid "" -"**Introduce (experimental) REST API** " -"([#1594](https://github.com/adap/flower/pull/1594), " -"[#1690](https://github.com/adap/flower/pull/1690), " -"[#1695](https://github.com/adap/flower/pull/1695), " -"[#1712](https://github.com/adap/flower/pull/1712), " -"[#1802](https://github.com/adap/flower/pull/1802), " -"[#1770](https://github.com/adap/flower/pull/1770), " -"[#1733](https://github.com/adap/flower/pull/1733))" +"**Introduce (experimental) REST API** ([#1594](https://github.com/adap/" +"flower/pull/1594), [#1690](https://github.com/adap/flower/pull/1690), [#1695]" +"(https://github.com/adap/flower/pull/1695), [#1712](https://github.com/adap/" +"flower/pull/1712), [#1802](https://github.com/adap/flower/pull/1802), [#1770]" +"(https://github.com/adap/flower/pull/1770), [#1733](https://github.com/adap/" +"flower/pull/1733))" msgstr "" +"**引入(试验性)REST API** ([#1594](https://github.com/adap/flower/" +"pull/1594), [#1690](https://github.com/adap/flower/pull/1690), [#1695]" +"(https://github.com/adap/flower/pull/1695), [#1712](https://github.com/adap/" +"flower/pull/1712), [#1802](https://github.com/adap/flower/pull/1802), [#1770]" +"(https://github.com/adap/flower/pull/1770), [#1733](https://github.com/adap/" +"flower/pull/1733))" #: ../../source/ref-changelog.md:191 msgid "" @@ -7736,141 +9010,183 @@ msgid "" "communication stack. In this initial version, the REST API only supports " "anonymous clients." msgstr "" +"作为基于 gRPC 的通信栈的替代方案,我们引入了新的 REST API。在初始版本中," +"REST API 仅支持匿名客户端。" #: ../../source/ref-changelog.md:193 msgid "" "Please note: The REST API is still experimental and will likely change " "significantly over time." -msgstr "" +msgstr "请注意:REST API 仍处于试验阶段,随着时间的推移可能会发生重大变化。" #: ../../source/ref-changelog.md:195 msgid "" -"**Improve the (experimental) Driver API** " -"([#1663](https://github.com/adap/flower/pull/1663), " -"[#1666](https://github.com/adap/flower/pull/1666), " -"[#1667](https://github.com/adap/flower/pull/1667), " -"[#1664](https://github.com/adap/flower/pull/1664), " -"[#1675](https://github.com/adap/flower/pull/1675), " -"[#1676](https://github.com/adap/flower/pull/1676), " -"[#1693](https://github.com/adap/flower/pull/1693), " -"[#1662](https://github.com/adap/flower/pull/1662), " -"[#1794](https://github.com/adap/flower/pull/1794))" -msgstr "" +"**Improve the (experimental) Driver API** ([#1663](https://github.com/adap/" +"flower/pull/1663), [#1666](https://github.com/adap/flower/pull/1666), [#1667]" +"(https://github.com/adap/flower/pull/1667), [#1664](https://github.com/adap/" +"flower/pull/1664), [#1675](https://github.com/adap/flower/pull/1675), [#1676]" +"(https://github.com/adap/flower/pull/1676), [#1693](https://github.com/adap/" +"flower/pull/1693), [#1662](https://github.com/adap/flower/pull/1662), [#1794]" +"(https://github.com/adap/flower/pull/1794))" +msgstr "" +"**改进(试验性)驱动程序应用程序接口** ([#1663](https://github.com/adap/" +"flower/pull/1663), [#1666](https://github.com/adap/flower/pull/1666), [#1667]" +"(https://github.com/adap/flower/pull/1667), [#1664](https://github.com/adap/" +"flower/pull/1664), [#1675](https://github.com/adap/flower/pull/1675), [#1676]" +"(https://github.com/adap/flower/pull/1676), [#1693](https://github.com/adap/" +"flower/pull/1693), [#1662](https://github.com/adap/flower/pull/1662), [#1794]" +"(https://github.com/adap/flower/pull/1794))" #: ../../source/ref-changelog.md:197 msgid "" -"The Driver API is still an experimental feature, but this release " -"introduces some major upgrades. One of the main improvements is the " -"introduction of an SQLite database to store server state on disk (instead" -" of in-memory). Another improvement is that tasks (instructions or " -"results) that have been delivered will now be deleted. This greatly " -"improves the memory efficiency of a long-running Flower server." +"The Driver API is still an experimental feature, but this release introduces " +"some major upgrades. One of the main improvements is the introduction of an " +"SQLite database to store server state on disk (instead of in-memory). " +"Another improvement is that tasks (instructions or results) that have been " +"delivered will now be deleted. This greatly improves the memory efficiency " +"of a long-running Flower server." msgstr "" +"驱动程序应用程序接口(Driver API)仍是一项试验性功能,但这一版本引入了一些重" +"大升级。主要改进之一是引入了 SQLite 数据库,将服务器状态存储在磁盘上(而不是" +"内存中)。另一项改进是,已交付的任务(指令或结果)现在将被删除。这大大提高了" +"长期运行的 Flower 服务器的内存效率。" #: ../../source/ref-changelog.md:199 msgid "" -"**Fix spilling issues related to Ray during simulations** " -"([#1698](https://github.com/adap/flower/pull/1698))" +"**Fix spilling issues related to Ray during simulations** ([#1698](https://" +"github.com/adap/flower/pull/1698))" msgstr "" +"**修复模拟过程中与雷有关的溢出问题** ([#1698](https://github.com/adap/flower/" +"pull/1698))" #: ../../source/ref-changelog.md:201 msgid "" -"While running long simulations, `ray` was sometimes spilling huge amounts" -" of data that would make the training unable to continue. This is now " -"fixed! 🎉" +"While running long simulations, `ray` was sometimes spilling huge amounts of " +"data that would make the training unable to continue. This is now fixed! 🎉" msgstr "" +"在运行长时间模拟时,`ray` 有时会溢出大量数据,导致训练无法继续。现在这个问题" +"已经解决!🎉" #: ../../source/ref-changelog.md:203 msgid "" -"**Add new example using** `TabNet` **and Flower** " -"([#1725](https://github.com/adap/flower/pull/1725))" +"**Add new example using** `TabNet` **and Flower** ([#1725](https://github." +"com/adap/flower/pull/1725))" msgstr "" +"** 添加使用** `TabNet` **和 Flower 的新示例** ([#1725](https://github.com/" +"adap/flower/pull/1725))" #: ../../source/ref-changelog.md:205 msgid "" -"TabNet is a powerful and flexible framework for training machine learning" -" models on tabular data. We now have a federated example using Flower: " -"[https://github.com/adap/flower/tree/main/examples/tabnet](https://github.com/adap/flower/tree/main/examples/quickstart_tabnet)." +"TabNet is a powerful and flexible framework for training machine learning " +"models on tabular data. We now have a federated example using Flower: " +"[https://github.com/adap/flower/tree/main/examples/tabnet](https://github." +"com/adap/flower/tree/main/examples/quickstart_tabnet)." msgstr "" +"TabNet 是一个强大而灵活的框架,用于在表格数据上训练机器学习模型。我们现在有一" +"个使用 Flower 的联合示例:[https://github.com/adap/flower/tree/main/examples/" +"tabnet](https://github.com/adap/flower/tree/main/examples/" +"quickstart_tabnet)。" #: ../../source/ref-changelog.md:207 msgid "" -"**Add new how-to guide for monitoring simulations** " -"([#1649](https://github.com/adap/flower/pull/1649))" +"**Add new how-to guide for monitoring simulations** ([#1649](https://github." +"com/adap/flower/pull/1649))" msgstr "" +"** 添加新的模拟监控指南** ([#1649](https://github.com/adap/flower/pull/1649))" #: ../../source/ref-changelog.md:209 msgid "" -"We now have a documentation guide to help users monitor their performance" -" during simulations." -msgstr "" +"We now have a documentation guide to help users monitor their performance " +"during simulations." +msgstr "我们现在有一份文档指南,可帮助用户在模拟过程中监控其性能。" #: ../../source/ref-changelog.md:211 msgid "" -"**Add training metrics to** `History` **object during simulations** " -"([#1696](https://github.com/adap/flower/pull/1696))" +"**Add training metrics to** `History` **object during simulations** ([#1696]" +"(https://github.com/adap/flower/pull/1696))" msgstr "" +"**在模拟过程中为***`历史`***对象添加训练指标*** ([#1696](https://github.com/" +"adap/flower/pull/1696))" #: ../../source/ref-changelog.md:213 msgid "" -"The `fit_metrics_aggregation_fn` can be used to aggregate training " -"metrics, but previous releases did not save the results in the `History` " -"object. This is now the case!" +"The `fit_metrics_aggregation_fn` can be used to aggregate training metrics, " +"but previous releases did not save the results in the `History` object. This " +"is now the case!" msgstr "" +"ffit_metrics_aggregation_fn \"可用于汇总训练指标,但以前的版本不会将结果保存" +"在 \"History \"对象中。现在情况就是这样!" #: ../../source/ref-changelog.md:215 msgid "" -"**General improvements** " -"([#1659](https://github.com/adap/flower/pull/1659), " -"[#1646](https://github.com/adap/flower/pull/1646), " -"[#1647](https://github.com/adap/flower/pull/1647), " -"[#1471](https://github.com/adap/flower/pull/1471), " -"[#1648](https://github.com/adap/flower/pull/1648), " -"[#1651](https://github.com/adap/flower/pull/1651), " -"[#1652](https://github.com/adap/flower/pull/1652), " -"[#1653](https://github.com/adap/flower/pull/1653), " -"[#1659](https://github.com/adap/flower/pull/1659), " -"[#1665](https://github.com/adap/flower/pull/1665), " -"[#1670](https://github.com/adap/flower/pull/1670), " -"[#1672](https://github.com/adap/flower/pull/1672), " -"[#1677](https://github.com/adap/flower/pull/1677), " -"[#1684](https://github.com/adap/flower/pull/1684), " -"[#1683](https://github.com/adap/flower/pull/1683), " -"[#1686](https://github.com/adap/flower/pull/1686), " -"[#1682](https://github.com/adap/flower/pull/1682), " -"[#1685](https://github.com/adap/flower/pull/1685), " -"[#1692](https://github.com/adap/flower/pull/1692), " -"[#1705](https://github.com/adap/flower/pull/1705), " -"[#1708](https://github.com/adap/flower/pull/1708), " -"[#1711](https://github.com/adap/flower/pull/1711), " -"[#1713](https://github.com/adap/flower/pull/1713), " -"[#1714](https://github.com/adap/flower/pull/1714), " -"[#1718](https://github.com/adap/flower/pull/1718), " -"[#1716](https://github.com/adap/flower/pull/1716), " -"[#1723](https://github.com/adap/flower/pull/1723), " -"[#1735](https://github.com/adap/flower/pull/1735), " -"[#1678](https://github.com/adap/flower/pull/1678), " -"[#1750](https://github.com/adap/flower/pull/1750), " -"[#1753](https://github.com/adap/flower/pull/1753), " -"[#1736](https://github.com/adap/flower/pull/1736), " -"[#1766](https://github.com/adap/flower/pull/1766), " -"[#1760](https://github.com/adap/flower/pull/1760), " -"[#1775](https://github.com/adap/flower/pull/1775), " -"[#1776](https://github.com/adap/flower/pull/1776), " -"[#1777](https://github.com/adap/flower/pull/1777), " -"[#1779](https://github.com/adap/flower/pull/1779), " -"[#1784](https://github.com/adap/flower/pull/1784), " -"[#1773](https://github.com/adap/flower/pull/1773), " -"[#1755](https://github.com/adap/flower/pull/1755), " -"[#1789](https://github.com/adap/flower/pull/1789), " -"[#1788](https://github.com/adap/flower/pull/1788), " -"[#1798](https://github.com/adap/flower/pull/1798), " -"[#1799](https://github.com/adap/flower/pull/1799), " -"[#1739](https://github.com/adap/flower/pull/1739), " -"[#1800](https://github.com/adap/flower/pull/1800), " -"[#1804](https://github.com/adap/flower/pull/1804), " -"[#1805](https://github.com/adap/flower/pull/1805))" -msgstr "" +"**General improvements** ([#1659](https://github.com/adap/flower/pull/1659), " +"[#1646](https://github.com/adap/flower/pull/1646), [#1647](https://github." +"com/adap/flower/pull/1647), [#1471](https://github.com/adap/flower/" +"pull/1471), [#1648](https://github.com/adap/flower/pull/1648), [#1651]" +"(https://github.com/adap/flower/pull/1651), [#1652](https://github.com/adap/" +"flower/pull/1652), [#1653](https://github.com/adap/flower/pull/1653), [#1659]" +"(https://github.com/adap/flower/pull/1659), [#1665](https://github.com/adap/" +"flower/pull/1665), [#1670](https://github.com/adap/flower/pull/1670), [#1672]" +"(https://github.com/adap/flower/pull/1672), [#1677](https://github.com/adap/" +"flower/pull/1677), [#1684](https://github.com/adap/flower/pull/1684), [#1683]" +"(https://github.com/adap/flower/pull/1683), [#1686](https://github.com/adap/" +"flower/pull/1686), [#1682](https://github.com/adap/flower/pull/1682), [#1685]" +"(https://github.com/adap/flower/pull/1685), [#1692](https://github.com/adap/" +"flower/pull/1692), [#1705](https://github.com/adap/flower/pull/1705), [#1708]" +"(https://github.com/adap/flower/pull/1708), [#1711](https://github.com/adap/" +"flower/pull/1711), [#1713](https://github.com/adap/flower/pull/1713), [#1714]" +"(https://github.com/adap/flower/pull/1714), [#1718](https://github.com/adap/" +"flower/pull/1718), [#1716](https://github.com/adap/flower/pull/1716), [#1723]" +"(https://github.com/adap/flower/pull/1723), [#1735](https://github.com/adap/" +"flower/pull/1735), [#1678](https://github.com/adap/flower/pull/1678), [#1750]" +"(https://github.com/adap/flower/pull/1750), [#1753](https://github.com/adap/" +"flower/pull/1753), [#1736](https://github.com/adap/flower/pull/1736), [#1766]" +"(https://github.com/adap/flower/pull/1766), [#1760](https://github.com/adap/" +"flower/pull/1760), [#1775](https://github.com/adap/flower/pull/1775), [#1776]" +"(https://github.com/adap/flower/pull/1776), [#1777](https://github.com/adap/" +"flower/pull/1777), [#1779](https://github.com/adap/flower/pull/1779), [#1784]" +"(https://github.com/adap/flower/pull/1784), [#1773](https://github.com/adap/" +"flower/pull/1773), [#1755](https://github.com/adap/flower/pull/1755), [#1789]" +"(https://github.com/adap/flower/pull/1789), [#1788](https://github.com/adap/" +"flower/pull/1788), [#1798](https://github.com/adap/flower/pull/1798), [#1799]" +"(https://github.com/adap/flower/pull/1799), [#1739](https://github.com/adap/" +"flower/pull/1739), [#1800](https://github.com/adap/flower/pull/1800), [#1804]" +"(https://github.com/adap/flower/pull/1804), [#1805](https://github.com/adap/" +"flower/pull/1805))" +msgstr "" +"**一般改进** ([#1659](https://github.com/adap/flower/pull/1659), [#1646]" +"(https://github.com/adap/flower/pull/1646), [#1647](https://github.com/adap/" +"flower/pull/1647), [#1471](https://github.com/adap/flower/pull/1471), [#1648]" +"(https://github.com/adap/flower/pull/1648), [#1651](https://github.com/adap/" +"flower/pull/1651), [#1652](https://github.com/adap/flower/pull/1652), [#1653]" +"(https://github.com/adap/flower/pull/1653), [#1659](https://github.com/adap/" +"flower/pull/1659), [#1665](https://github.com/adap/flower/pull/1665), [#1670]" +"(https://github.com/adap/flower/pull/1670), [#1672](https://github.com/adap/" +"flower/pull/1672), [#1677](https://github.com/adap/flower/pull/1677), [#1684]" +"(https://github.com/adap/flower/pull/1684), [#1683](https://github.com/adap/" +"flower/pull/1683), [#1686](https://github.com/adap/flower/pull/1686), [#1682]" +"(https://github.com/adap/flower/pull/1682), [#1685](https://github.com/adap/" +"flower/pull/1685), [#1692](https://github.com/adap/flower/pull/1692), [#1705]" +"(https://github.com/adap/flower/pull/1705), [#1708](https://github.com/adap/" +"flower/pull/1708), [#1711](https://github.com/adap/flower/pull/1711), [#1713]" +"(https://github.com/adap/flower/pull/1713), [#1714](https://github.com/adap/" +"flower/pull/1714), [#1718](https://github.com/adap/flower/pull/1718), [#1716]" +"(https://github.com/adap/flower/pull/1716), [#1723](https://github.com/adap/" +"flower/pull/1723), [#1735](https://github.com/adap/flower/pull/1735), [#1678]" +"(https://github.com/adap/flower/pull/1678), [#1750](https://github.com/adap/" +"flower/pull/1750), [#1753](https://github.com/adap/flower/pull/1753), [#1736]" +"(https://github.com/adap/flower/pull/1736), [#1766](https://github.com/adap/" +"flower/pull/1766), [#1760](https://github.com/adap/flower/pull/1760), [#1775]" +"(https://github.com/adap/flower/pull/1775), [#1776](https://github.com/adap/" +"flower/pull/1776), [#1777](https://github.com/adap/flower/pull/1777), [#1779]" +"(https://github.com/adap/flower/pull/1779), [#1784](https://github.com/adap/" +"flower/pull/1784), [#1773](https://github.com/adap/flower/pull/1773), [#1755]" +"(https://github.com/adap/flower/pull/1755), [#1789](https://github.com/adap/" +"flower/pull/1789), [#1788](https://github.com/adap/flower/pull/1788), [#1798]" +"(https://github.com/adap/flower/pull/1798), [#1799](https://github.com/adap/" +"flower/pull/1799), [#1739](https://github.com/adap/flower/pull/1739), [#1800]" +"(https://github.com/adap/flower/pull/1800), [#1804](https://github.com/adap/" +"flower/pull/1804), [#1805](https://github.com/adap/flower/pull/1805))" #: ../../source/ref-changelog.md:223 msgid "v1.3.0 (2023-02-06)" @@ -7878,37 +9194,49 @@ msgstr "" #: ../../source/ref-changelog.md:229 msgid "" -"`Adam Narozniak`, `Alexander Viala Bellander`, `Charles Beauville`, " -"`Daniel J. Beutel`, `JDRanpariya`, `Lennart Behme`, `Taner Topal`" +"`Adam Narozniak`, `Alexander Viala Bellander`, `Charles Beauville`, `Daniel " +"J. Beutel`, `JDRanpariya`, `Lennart Behme`, `Taner Topal`" msgstr "" +"`Adam Narozniak`, `Alexander Viala Bellander`, `Charles Beauville`, `Daniel " +"J. Beutel`, `JDRanpariya`, `Lennart Behme`, `Taner Topal`" #: ../../source/ref-changelog.md:233 msgid "" "**Add support for** `workload_id` **and** `group_id` **in Driver API** " "([#1595](https://github.com/adap/flower/pull/1595))" msgstr "" +"**在驱动程序应用程序接口**中添加对** `workload_id` **和** `group_id` **的支" +"持 ([#1595](https://github.com/adap/flower/pull/1595))" #: ../../source/ref-changelog.md:235 msgid "" -"The (experimental) Driver API now supports a `workload_id` that can be " -"used to identify which workload a task belongs to. It also supports a new" -" `group_id` that can be used, for example, to indicate the current " -"training round. Both the `workload_id` and `group_id` enable client nodes" -" to decide whether they want to handle a task or not." +"The (experimental) Driver API now supports a `workload_id` that can be used " +"to identify which workload a task belongs to. It also supports a new " +"`group_id` that can be used, for example, to indicate the current training " +"round. Both the `workload_id` and `group_id` enable client nodes to decide " +"whether they want to handle a task or not." msgstr "" +"驱动程序 API(试验性)现在支持 \"workload_id\",可用于识别任务所属的工作量。" +"它还支持新的 `group_id`,例如,可用于指示当前的训练轮次。通过 `workload_id` " +"和 `group_id` 客户端节点可以决定是否要处理某个任务。" #: ../../source/ref-changelog.md:237 msgid "" -"**Make Driver API and Fleet API address configurable** " -"([#1637](https://github.com/adap/flower/pull/1637))" +"**Make Driver API and Fleet API address configurable** ([#1637](https://" +"github.com/adap/flower/pull/1637))" msgstr "" +"**使驱动程序应用程序接口和车队应用程序接口地址可配置**([#1637](https://" +"github.com/adap/flower/pull/1637))" #: ../../source/ref-changelog.md:239 msgid "" -"The (experimental) long-running Flower server (Driver API and Fleet API) " -"can now configure the server address of both Driver API (via `--driver-" -"api-address`) and Fleet API (via `--fleet-api-address`) when starting:" +"The (experimental) long-running Flower server (Driver API and Fleet API) can " +"now configure the server address of both Driver API (via `--driver-api-" +"address`) and Fleet API (via `--fleet-api-address`) when starting:" msgstr "" +"长期运行的 Flower 服务器(Driver API 和 Fleet API)现在可以在启动时配置 " +"Driver API(通过 `--driver-api-address`)和 Fleet API(通过 `-fleet-api-" +"address`)的服务器地址:" #: ../../source/ref-changelog.md:241 msgid "" @@ -7918,167 +9246,210 @@ msgstr "" #: ../../source/ref-changelog.md:243 msgid "Both IPv4 and IPv6 addresses are supported." -msgstr "" +msgstr "支持 IPv4 和 IPv6 地址。" #: ../../source/ref-changelog.md:245 msgid "" -"**Add new example of Federated Learning using fastai and Flower** " -"([#1598](https://github.com/adap/flower/pull/1598))" +"**Add new example of Federated Learning using fastai and Flower** ([#1598]" +"(https://github.com/adap/flower/pull/1598))" msgstr "" +"** 添加使用 fastai 和 Flower 进行联合学习的新示例** ([#1598](https://github." +"com/adap/flower/pull/1598))" #: ../../source/ref-changelog.md:247 msgid "" "A new code example (`quickstart_fastai`) demonstrates federated learning " "with [fastai](https://www.fast.ai/) and Flower. You can find it here: " -"[quickstart_fastai](https://github.com/adap/flower/tree/main/examples/quickstart_fastai)." +"[quickstart_fastai](https://github.com/adap/flower/tree/main/examples/" +"quickstart_fastai)." msgstr "" +"一个新的代码示例(`quickstart_fastai`)演示了使用 [fastai](https://www.fast." +"ai/) 和 Flower 的联合学习。您可以在这里找到它: [quickstart_fastai](https://" +"github.com/adap/flower/tree/main/examples/quickstart_fastai)。" #: ../../source/ref-changelog.md:249 msgid "" -"**Make Android example compatible with** `flwr >= 1.0.0` **and the latest" -" versions of Android** " -"([#1603](https://github.com/adap/flower/pull/1603))" +"**Make Android example compatible with** `flwr >= 1.0.0` **and the latest " +"versions of Android** ([#1603](https://github.com/adap/flower/pull/1603))" msgstr "" +"**使安卓示例兼容** `flwr >= 1.0.0` **和最新版本的安卓** ([#1603](https://" +"github.com/adap/flower/pull/1603))" #: ../../source/ref-changelog.md:251 msgid "" -"The Android code example has received a substantial update: the project " -"is compatible with Flower 1.0 (and later), the UI received a full " -"refresh, and the project is updated to be compatible with newer Android " -"tooling." +"The Android code example has received a substantial update: the project is " +"compatible with Flower 1.0 (and later), the UI received a full refresh, and " +"the project is updated to be compatible with newer Android tooling." msgstr "" +"Android 代码示例已进行了大幅更新:项目兼容 Flower 1.0(及更高版本),用户界面" +"已全面刷新,项目已更新为兼容较新的 Android 工具。" #: ../../source/ref-changelog.md:253 msgid "" -"**Add new `FedProx` strategy** " -"([#1619](https://github.com/adap/flower/pull/1619))" +"**Add new `FedProx` strategy** ([#1619](https://github.com/adap/flower/" +"pull/1619))" msgstr "" +"**添加新的 \"FedProx \"策略** ([#1619](https://github.com/adap/flower/" +"pull/1619))" #: ../../source/ref-changelog.md:255 msgid "" -"This " -"[strategy](https://github.com/adap/flower/blob/main/src/py/flwr/server/strategy/fedprox.py)" -" is almost identical to " -"[`FedAvg`](https://github.com/adap/flower/blob/main/src/py/flwr/server/strategy/fedavg.py)," -" but helps users replicate what is described in this " -"[paper](https://arxiv.org/abs/1812.06127). It essentially adds a " -"parameter called `proximal_mu` to regularize the local models with " -"respect to the global models." +"This [strategy](https://github.com/adap/flower/blob/main/src/py/flwr/server/" +"strategy/fedprox.py) is almost identical to [`FedAvg`](https://github.com/" +"adap/flower/blob/main/src/py/flwr/server/strategy/fedavg.py), but helps " +"users replicate what is described in this [paper](https://arxiv.org/" +"abs/1812.06127). It essentially adds a parameter called `proximal_mu` to " +"regularize the local models with respect to the global models." msgstr "" +"该[策略](https://github.com/adap/flower/blob/main/src/py/flwr/server/" +"strategy/fedprox.py)与[`FedAvg`](https://github.com/adap/flower/blob/main/" +"src/py/flwr/server/strategy/fedavg.py)几乎相同,但可以帮助用户复制本文[论文]" +"(https://arxiv.org/abs/1812.06127)中的描述。它的本质是添加一个名为 " +"\"proximal_mu \"的参数,使局部模型与全局模型正则化。" #: ../../source/ref-changelog.md:257 msgid "" -"**Add new metrics to telemetry events** " -"([#1640](https://github.com/adap/flower/pull/1640))" +"**Add new metrics to telemetry events** ([#1640](https://github.com/adap/" +"flower/pull/1640))" msgstr "" +"**为遥测事件添加新指标**([#1640](https://github.com/adap/flower/pull/1640))" #: ../../source/ref-changelog.md:259 msgid "" "An updated event structure allows, for example, the clustering of events " "within the same workload." -msgstr "" +msgstr "例如,更新后的事件结构可以将同一工作负载中的事件集中在一起。" #: ../../source/ref-changelog.md:261 msgid "" -"**Add new custom strategy tutorial section** " -"[#1623](https://github.com/adap/flower/pull/1623)" +"**Add new custom strategy tutorial section** [#1623](https://github.com/adap/" +"flower/pull/1623)" msgstr "" +"**添加新的自定义策略教程部分** [#1623](https://github.com/adap/flower/" +"pull/1623)" #: ../../source/ref-changelog.md:263 msgid "" -"The Flower tutorial now has a new section that covers implementing a " -"custom strategy from scratch: [Open in " -"Colab](https://colab.research.google.com/github/adap/flower/blob/main/doc/source" -"/tutorial-build-a-strategy-from-scratch-pytorch.ipynb)" +"The Flower tutorial now has a new section that covers implementing a custom " +"strategy from scratch: [Open in Colab](https://colab.research.google.com/" +"github/adap/flower/blob/main/doc/source/tutorial-build-a-strategy-from-" +"scratch-pytorch.ipynb)" msgstr "" +"Flower 教程新增了一个章节,介绍如何从零开始实施自定义策略: [在 Colab 中打开]" +"(https://colab.research.google.com/github/adap/flower/blob/main/doc/source/" +"tutorial-build-a-strategy-from-scratch-pytorch.ipynb)" #: ../../source/ref-changelog.md:265 msgid "" -"**Add new custom serialization tutorial section** " -"([#1622](https://github.com/adap/flower/pull/1622))" +"**Add new custom serialization tutorial section** ([#1622](https://github." +"com/adap/flower/pull/1622))" msgstr "" +"** 添加新的自定义序列化教程部分** ([#1622](https://github.com/adap/flower/" +"pull/1622))" #: ../../source/ref-changelog.md:267 msgid "" -"The Flower tutorial now has a new section that covers custom " -"serialization: [Open in " -"Colab](https://colab.research.google.com/github/adap/flower/blob/main/doc/source" -"/tutorial-customize-the-client-pytorch.ipynb)" +"The Flower tutorial now has a new section that covers custom serialization: " +"[Open in Colab](https://colab.research.google.com/github/adap/flower/blob/" +"main/doc/source/tutorial-customize-the-client-pytorch.ipynb)" msgstr "" +"Flower 教程现在新增了一个章节,介绍自定义序列化: [在 Colab 中打开](https://" +"colab.research.google.com/github/adap/flower/blob/main/doc/source/tutorial-" +"customize-the-client-pytorch.ipynb)" #: ../../source/ref-changelog.md:269 msgid "" -"**General improvements** " -"([#1638](https://github.com/adap/flower/pull/1638), " -"[#1634](https://github.com/adap/flower/pull/1634), " -"[#1636](https://github.com/adap/flower/pull/1636), " -"[#1635](https://github.com/adap/flower/pull/1635), " -"[#1633](https://github.com/adap/flower/pull/1633), " -"[#1632](https://github.com/adap/flower/pull/1632), " -"[#1631](https://github.com/adap/flower/pull/1631), " -"[#1630](https://github.com/adap/flower/pull/1630), " -"[#1627](https://github.com/adap/flower/pull/1627), " -"[#1593](https://github.com/adap/flower/pull/1593), " -"[#1616](https://github.com/adap/flower/pull/1616), " -"[#1615](https://github.com/adap/flower/pull/1615), " -"[#1607](https://github.com/adap/flower/pull/1607), " -"[#1609](https://github.com/adap/flower/pull/1609), " -"[#1608](https://github.com/adap/flower/pull/1608), " -"[#1603](https://github.com/adap/flower/pull/1603), " -"[#1590](https://github.com/adap/flower/pull/1590), " -"[#1580](https://github.com/adap/flower/pull/1580), " -"[#1599](https://github.com/adap/flower/pull/1599), " -"[#1600](https://github.com/adap/flower/pull/1600), " -"[#1601](https://github.com/adap/flower/pull/1601), " -"[#1597](https://github.com/adap/flower/pull/1597), " -"[#1595](https://github.com/adap/flower/pull/1595), " -"[#1591](https://github.com/adap/flower/pull/1591), " -"[#1588](https://github.com/adap/flower/pull/1588), " -"[#1589](https://github.com/adap/flower/pull/1589), " -"[#1587](https://github.com/adap/flower/pull/1587), " -"[#1573](https://github.com/adap/flower/pull/1573), " -"[#1581](https://github.com/adap/flower/pull/1581), " -"[#1578](https://github.com/adap/flower/pull/1578), " -"[#1574](https://github.com/adap/flower/pull/1574), " -"[#1572](https://github.com/adap/flower/pull/1572), " -"[#1586](https://github.com/adap/flower/pull/1586))" -msgstr "" +"**General improvements** ([#1638](https://github.com/adap/flower/pull/1638), " +"[#1634](https://github.com/adap/flower/pull/1634), [#1636](https://github." +"com/adap/flower/pull/1636), [#1635](https://github.com/adap/flower/" +"pull/1635), [#1633](https://github.com/adap/flower/pull/1633), [#1632]" +"(https://github.com/adap/flower/pull/1632), [#1631](https://github.com/adap/" +"flower/pull/1631), [#1630](https://github.com/adap/flower/pull/1630), [#1627]" +"(https://github.com/adap/flower/pull/1627), [#1593](https://github.com/adap/" +"flower/pull/1593), [#1616](https://github.com/adap/flower/pull/1616), [#1615]" +"(https://github.com/adap/flower/pull/1615), [#1607](https://github.com/adap/" +"flower/pull/1607), [#1609](https://github.com/adap/flower/pull/1609), [#1608]" +"(https://github.com/adap/flower/pull/1608), [#1603](https://github.com/adap/" +"flower/pull/1603), [#1590](https://github.com/adap/flower/pull/1590), [#1580]" +"(https://github.com/adap/flower/pull/1580), [#1599](https://github.com/adap/" +"flower/pull/1599), [#1600](https://github.com/adap/flower/pull/1600), [#1601]" +"(https://github.com/adap/flower/pull/1601), [#1597](https://github.com/adap/" +"flower/pull/1597), [#1595](https://github.com/adap/flower/pull/1595), [#1591]" +"(https://github.com/adap/flower/pull/1591), [#1588](https://github.com/adap/" +"flower/pull/1588), [#1589](https://github.com/adap/flower/pull/1589), [#1587]" +"(https://github.com/adap/flower/pull/1587), [#1573](https://github.com/adap/" +"flower/pull/1573), [#1581](https://github.com/adap/flower/pull/1581), [#1578]" +"(https://github.com/adap/flower/pull/1578), [#1574](https://github.com/adap/" +"flower/pull/1574), [#1572](https://github.com/adap/flower/pull/1572), [#1586]" +"(https://github.com/adap/flower/pull/1586))" +msgstr "" +"**一般改进** ([#1638](https://github.com/adap/flower/pull/1638), [#1634]" +"(https://github.com/adap/flower/pull/1634), [#1636](https://github.com/adap/" +"flower/pull/1636), [#1635](https://github.com/adap/flower/pull/1635), [#1633]" +"(https://github.com/adap/flower/pull/1633), [#1632](https://github.com/adap/" +"flower/pull/1632), [#1631](https://github.com/adap/flower/pull/1631), [#1630]" +"(https://github.com/adap/flower/pull/1630), [#1627](https://github. com/adap/" +"flower/pull/1627), [#1593](https://github.com/adap/flower/pull/1593), [#1616]" +"(https://github.com/adap/flower/pull/1616), [#1615](https://github.com/adap/" +"flower/pull/1615), [#1607](https://github.com/adap/flower/pull/1607), [#1609]" +"(https://github.com/adap/flower/pull/1609), [#1608](https://github.com/adap/" +"flower/pull/1608), [#1603](https://github.com/adap/flower/pull/1603), [#1590]" +"(https://github. com/adap/flower/pull/1590), [#1580](https://github.com/adap/" +"flower/pull/1580), [#1599](https://github.com/adap/flower/pull/1599), [#1600]" +"(https://github.com/adap/flower/pull/1600), [#1601](https://github.com/adap/" +"flower/pull/1601), [#1597](https://github.com/adap/flower/pull/1597), [#1595]" +"(https://github.com/adap/flower/pull/1595), [#1591](https://github.com/adap/" +"flower/pull/1591), [#1588](https://github. com/adap/flower/pull/1588), " +"[#1589](https://github.com/adap/flower/pull/1589), [#1587](https://github." +"com/adap/flower/pull/1587), [#1573](https://github.com/adap/flower/" +"pull/1573), [#1581](https://github.com/adap/flower/pull/1581), [#1578]" +"(https://github.com/adap/flower/pull/1578), [#1574](https://github.com/adap/" +"flower/pull/1574), [#1572](https://github.com/adap/flower/pull/1572), [#1586]" +"(https://github.com/adap/flower/pull/1586))" #: ../../source/ref-changelog.md:273 msgid "" -"**Updated documentation** " -"([#1629](https://github.com/adap/flower/pull/1629), " -"[#1628](https://github.com/adap/flower/pull/1628), " -"[#1620](https://github.com/adap/flower/pull/1620), " -"[#1618](https://github.com/adap/flower/pull/1618), " -"[#1617](https://github.com/adap/flower/pull/1617), " -"[#1613](https://github.com/adap/flower/pull/1613), " -"[#1614](https://github.com/adap/flower/pull/1614))" +"**Updated documentation** ([#1629](https://github.com/adap/flower/" +"pull/1629), [#1628](https://github.com/adap/flower/pull/1628), [#1620]" +"(https://github.com/adap/flower/pull/1620), [#1618](https://github.com/adap/" +"flower/pull/1618), [#1617](https://github.com/adap/flower/pull/1617), [#1613]" +"(https://github.com/adap/flower/pull/1613), [#1614](https://github.com/adap/" +"flower/pull/1614))" msgstr "" +"** 更新文档** ([#1629](https://github.com/adap/flower/pull/1629), [#1628]" +"(https://github.com/adap/flower/pull/1628), [#1620](https://github.com/adap/" +"flower/pull/1620), [#1618](https://github.com/adap/flower/pull/1618), [#1617]" +"(https://github.com/adap/flower/pull/1617), [#1613](https://github.com/adap/" +"flower/pull/1613), [#1614](https://github.com/adap/flower/pull/1614)))" #: ../../source/ref-changelog.md:275 ../../source/ref-changelog.md:342 msgid "" -"As usual, the documentation has improved quite a bit. It is another step " -"in our effort to make the Flower documentation the best documentation of " -"any project. Stay tuned and as always, feel free to provide feedback!" +"As usual, the documentation has improved quite a bit. It is another step in " +"our effort to make the Flower documentation the best documentation of any " +"project. Stay tuned and as always, feel free to provide feedback!" msgstr "" +"和往常一样,我们的文档有了很大的改进。这是我们努力使 Flower 文档成为所有项目" +"中最好文档的又一步骤。请继续关注,并随时提供反馈意见!" #: ../../source/ref-changelog.md:281 msgid "v1.2.0 (2023-01-13)" -msgstr "" +msgstr "v1.2.0 (2023-01-13)" #: ../../source/ref-changelog.md:287 msgid "" -"`Adam Narozniak`, `Charles Beauville`, `Daniel J. Beutel`, `Edoardo`, `L." -" Jiang`, `Ragy`, `Taner Topal`, `dannymcy`" +"`Adam Narozniak`, `Charles Beauville`, `Daniel J. Beutel`, `Edoardo`, `L. " +"Jiang`, `Ragy`, `Taner Topal`, `dannymcy`" msgstr "" +"`Adam Narozniak`, `Charles Beauville`, `Daniel J. Beutel`, `Edoardo`, `L. " +"Jiang`, `Ragy`, `Taner Topal`, `dannymcy`" #: ../../source/ref-changelog.md:291 msgid "" -"**Introduce new Flower Baseline: FedAvg MNIST** " -"([#1497](https://github.com/adap/flower/pull/1497), " -"[#1552](https://github.com/adap/flower/pull/1552))" +"**Introduce new Flower Baseline: FedAvg MNIST** ([#1497](https://github.com/" +"adap/flower/pull/1497), [#1552](https://github.com/adap/flower/pull/1552))" msgstr "" +"**引入新的 Flower 基线: FedAvg MNIST** ([#1497](https://github.com/adap/" +"flower/pull/1497), [#1552](https://github.com/adap/flower/pull/1552))" #: ../../source/ref-changelog.md:293 msgid "" @@ -8086,524 +9457,639 @@ msgid "" "implementations useful especially to FL newcomers. They will typically " "revisit well known papers from the literature, and be suitable for " "integration in your own application or for experimentation, in order to " -"deepen your knowledge of FL in general. Today's release is the first in " -"this series. [Read more.](https://flower.dev/blog/2023-01-12-fl-starter-" -"pack-fedavg-mnist-cnn/)" +"deepen your knowledge of FL in general. Today's release is the first in this " +"series. [Read more.](https://flower.dev/blog/2023-01-12-fl-starter-pack-" +"fedavg-mnist-cnn/)" msgstr "" +"在未来几周内,我们将发布一些新的参考实现,特别是对 FL 新手有用的实现。它们通" +"常会重温文献中的知名论文,适合集成到您自己的应用程序中或用于实验,以加深您对 " +"FL 的总体了解。今天发布的是该系列中的第一篇。[阅读全文](https://flower.dev/" +"blog/2023-01-12-fl-starter-pack-fedavg-mnist-cnn/)" #: ../../source/ref-changelog.md:295 msgid "" -"**Improve GPU support in simulations** " -"([#1555](https://github.com/adap/flower/pull/1555))" +"**Improve GPU support in simulations** ([#1555](https://github.com/adap/" +"flower/pull/1555))" msgstr "" +"**改进模拟中的 GPU 支持**([#1555](https://github.com/adap/flower/" +"pull/1555))" #: ../../source/ref-changelog.md:297 msgid "" -"The Ray-based Virtual Client Engine (`start_simulation`) has been updated" -" to improve GPU support. The update includes some of the hard-earned " -"lessons from scaling simulations in GPU cluster environments. New " -"defaults make running GPU-based simulations substantially more robust." +"The Ray-based Virtual Client Engine (`start_simulation`) has been updated to " +"improve GPU support. The update includes some of the hard-earned lessons " +"from scaling simulations in GPU cluster environments. New defaults make " +"running GPU-based simulations substantially more robust." msgstr "" +"基于 Ray 的虚拟客户端引擎 (`start_simulation`)已更新,以改进对 GPU 的支持。此" +"次更新包含了在 GPU 集群环境中扩展仿真的一些经验教训。新的默认设置使基于 GPU " +"的模拟运行更加稳健。" #: ../../source/ref-changelog.md:299 msgid "" -"**Improve GPU support in Jupyter Notebook tutorials** " -"([#1527](https://github.com/adap/flower/pull/1527), " -"[#1558](https://github.com/adap/flower/pull/1558))" +"**Improve GPU support in Jupyter Notebook tutorials** ([#1527](https://" +"github.com/adap/flower/pull/1527), [#1558](https://github.com/adap/flower/" +"pull/1558))" msgstr "" +"**改进 Jupyter Notebook 教程中的 GPU 支持** ([#1527](https://github.com/adap/" +"flower/pull/1527), [#1558](https://github.com/adap/flower/pull/1558))" #: ../../source/ref-changelog.md:301 msgid "" -"Some users reported that Jupyter Notebooks have not always been easy to " -"use on GPU instances. We listened and made improvements to all of our " -"Jupyter notebooks! Check out the updated notebooks here:" +"Some users reported that Jupyter Notebooks have not always been easy to use " +"on GPU instances. We listened and made improvements to all of our Jupyter " +"notebooks! Check out the updated notebooks here:" msgstr "" +"一些用户报告说,在 GPU 实例上使用 Jupyter 笔记本并不总是很方便。我们听取了他" +"们的意见,并对所有 Jupyter 笔记本进行了改进!点击这里查看更新后的笔记本:" #: ../../source/ref-changelog.md:303 msgid "" -"[An Introduction to Federated Learning](https://flower.dev/docs/framework" -"/tutorial-get-started-with-flower-pytorch.html)" +"[An Introduction to Federated Learning](https://flower.dev/docs/framework/" +"tutorial-get-started-with-flower-pytorch.html)" msgstr "" +"[Federated Learning 简介](https://flower.dev/docs/framework/tutorial-get-" +"started-with-flower-pytorch.html)" #: ../../source/ref-changelog.md:304 msgid "" -"[Strategies in Federated Learning](https://flower.dev/docs/framework" -"/tutorial-use-a-federated-learning-strategy-pytorch.html)" +"[Strategies in Federated Learning](https://flower.dev/docs/framework/" +"tutorial-use-a-federated-learning-strategy-pytorch.html)" msgstr "" +"[联邦学习策略](https://flower.dev/docs/framework/tutorial-use-a-federated-" +"learning-strategy-pytorch.html)" #: ../../source/ref-changelog.md:305 msgid "" -"[Building a Strategy](https://flower.dev/docs/framework/tutorial-build-a" -"-strategy-from-scratch-pytorch.html)" +"[Building a Strategy](https://flower.dev/docs/framework/tutorial-build-a-" +"strategy-from-scratch-pytorch.html)" msgstr "" +"[制定策略](https://flower.dev/docs/framework/tutorial-build-a-strategy-from-" +"scratch-pytorch.html)" #: ../../source/ref-changelog.md:306 msgid "" "[Client and NumPyClient](https://flower.dev/docs/framework/tutorial-" "customize-the-client-pytorch.html)" msgstr "" +"[客户端和 NumPyClient](https://flower.dev/docs/framework/tutorial-customize-" +"the-client-pytorch.html)" #: ../../source/ref-changelog.md:308 msgid "" -"**Introduce optional telemetry** " -"([#1533](https://github.com/adap/flower/pull/1533), " -"[#1544](https://github.com/adap/flower/pull/1544), " -"[#1584](https://github.com/adap/flower/pull/1584))" +"**Introduce optional telemetry** ([#1533](https://github.com/adap/flower/" +"pull/1533), [#1544](https://github.com/adap/flower/pull/1544), [#1584]" +"(https://github.com/adap/flower/pull/1584))" msgstr "" +"**引入可选遥测**([#1533](https://github.com/adap/flower/pull/1533), [#1544]" +"(https://github.com/adap/flower/pull/1544), [#1584](https://github.com/adap/" +"flower/pull/1584)" #: ../../source/ref-changelog.md:310 msgid "" -"After a [request for " -"feedback](https://github.com/adap/flower/issues/1534) from the community," -" the Flower open-source project introduces optional collection of " -"*anonymous* usage metrics to make well-informed decisions to improve " -"Flower. Doing this enables the Flower team to understand how Flower is " -"used and what challenges users might face." +"After a [request for feedback](https://github.com/adap/flower/issues/1534) " +"from the community, the Flower open-source project introduces optional " +"collection of *anonymous* usage metrics to make well-informed decisions to " +"improve Flower. Doing this enables the Flower team to understand how Flower " +"is used and what challenges users might face." msgstr "" +"在社区发出[反馈请求](https://github.com/adap/flower/issues/1534)之后,Flower " +"开放源码项目引入了可选的*匿名*使用指标收集,以便在充分知情的情况下做出改进 " +"Flower 的决定。这样做能让 Flower 团队了解 Flower 的使用情况以及用户可能面临的" +"挑战。" #: ../../source/ref-changelog.md:312 msgid "" -"**Flower is a friendly framework for collaborative AI and data science.**" -" Staying true to this statement, Flower makes it easy to disable " -"telemetry for users who do not want to share anonymous usage metrics. " -"[Read more.](https://flower.dev/docs/telemetry.html)." +"**Flower is a friendly framework for collaborative AI and data science.** " +"Staying true to this statement, Flower makes it easy to disable telemetry " +"for users who do not want to share anonymous usage metrics. [Read more.]" +"(https://flower.dev/docs/telemetry.html)." msgstr "" +"**Flower 是一个用于协作式人工智能和数据科学的友好框架。** Flower 遵循这一声" +"明,让不想分享匿名使用指标的用户可以轻松禁用遥测技术。[阅读全文](https://" +"flower.dev/docs/telemetry.html)。" #: ../../source/ref-changelog.md:314 msgid "" -"**Introduce (experimental) Driver API** " -"([#1520](https://github.com/adap/flower/pull/1520), " -"[#1525](https://github.com/adap/flower/pull/1525), " -"[#1545](https://github.com/adap/flower/pull/1545), " -"[#1546](https://github.com/adap/flower/pull/1546), " -"[#1550](https://github.com/adap/flower/pull/1550), " -"[#1551](https://github.com/adap/flower/pull/1551), " -"[#1567](https://github.com/adap/flower/pull/1567))" +"**Introduce (experimental) Driver API** ([#1520](https://github.com/adap/" +"flower/pull/1520), [#1525](https://github.com/adap/flower/pull/1525), [#1545]" +"(https://github.com/adap/flower/pull/1545), [#1546](https://github.com/adap/" +"flower/pull/1546), [#1550](https://github.com/adap/flower/pull/1550), [#1551]" +"(https://github.com/adap/flower/pull/1551), [#1567](https://github.com/adap/" +"flower/pull/1567))" msgstr "" +"**引入(试验性)驱动程序应用程序接口** ([#1520](https://github.com/adap/" +"flower/pull/1520), [#1525](https://github.com/adap/flower/pull/1525), [#1545]" +"(https://github.com/adap/flower/pull/1545), [#1546](https://github.com/adap/" +"flower/pull/1546), [#1550](https://github.com/adap/flower/pull/1550), [#1551]" +"(https://github.com/adap/flower/pull/1551), [#1567](https://github.com/adap/" +"flower/pull/1567))" #: ../../source/ref-changelog.md:316 msgid "" "Flower now has a new (experimental) Driver API which will enable fully " "programmable, async, and multi-tenant Federated Learning and Federated " -"Analytics applications. Phew, that's a lot! Going forward, the Driver API" -" will be the abstraction that many upcoming features will be built on - " -"and you can start building those things now, too." +"Analytics applications. Phew, that's a lot! Going forward, the Driver API " +"will be the abstraction that many upcoming features will be built on - and " +"you can start building those things now, too." msgstr "" +"Flower 现在有了一个新的(试验性的)驱动程序应用程序接口(Driver API),它将支" +"持完全可编程、异步和多租户的联合学习(Federated Learning)和联合分析" +"(Federated Analytics)应用程序。呼,真不少!展望未来,Driver API 将成为许多" +"即将推出的功能的抽象基础,您现在就可以开始构建这些功能。" #: ../../source/ref-changelog.md:318 msgid "" -"The Driver API also enables a new execution mode in which the server runs" -" indefinitely. Multiple individual workloads can run concurrently and " -"start and stop their execution independent of the server. This is " -"especially useful for users who want to deploy Flower in production." +"The Driver API also enables a new execution mode in which the server runs " +"indefinitely. Multiple individual workloads can run concurrently and start " +"and stop their execution independent of the server. This is especially " +"useful for users who want to deploy Flower in production." msgstr "" +"驱动程序应用程序接口还支持一种新的执行模式,在这种模式下,服务器可无限期运" +"行。多个单独的工作负载可以同时运行,并独立于服务器启动和停止执行。这对于希望" +"在生产中部署 Flower 的用户来说尤其有用。" #: ../../source/ref-changelog.md:320 msgid "" -"To learn more, check out the `mt-pytorch` code example. We look forward " -"to you feedback!" -msgstr "" +"To learn more, check out the `mt-pytorch` code example. We look forward to " +"you feedback!" +msgstr "要了解更多信息,请查看 `mt-pytorch` 代码示例。我们期待您的反馈!" #: ../../source/ref-changelog.md:322 msgid "" -"Please note: *The Driver API is still experimental and will likely change" -" significantly over time.*" +"Please note: *The Driver API is still experimental and will likely change " +"significantly over time.*" msgstr "" +"请注意:*驱动程序应用程序接口仍处于试验阶段,随着时间的推移可能会发生重大变" +"化。*" #: ../../source/ref-changelog.md:324 msgid "" -"**Add new Federated Analytics with Pandas example** " -"([#1469](https://github.com/adap/flower/pull/1469), " -"[#1535](https://github.com/adap/flower/pull/1535))" +"**Add new Federated Analytics with Pandas example** ([#1469](https://github." +"com/adap/flower/pull/1469), [#1535](https://github.com/adap/flower/" +"pull/1535))" msgstr "" +"** 添加新的使用 Pandas 的联邦分析示例**([#1469](https://github.com/adap/" +"flower/pull/1469), [#1535](https://github.com/adap/flower/pull/1535)" #: ../../source/ref-changelog.md:326 msgid "" -"A new code example (`quickstart_pandas`) demonstrates federated analytics" -" with Pandas and Flower. You can find it here: " -"[quickstart_pandas](https://github.com/adap/flower/tree/main/examples/quickstart_pandas)." +"A new code example (`quickstart_pandas`) demonstrates federated analytics " +"with Pandas and Flower. You can find it here: [quickstart_pandas](https://" +"github.com/adap/flower/tree/main/examples/quickstart_pandas)." msgstr "" +"新代码示例(`quickstart_pandas`)演示了使用 Pandas 和 Flower 进行联合分析。您" +"可以在此处找到它: [quickstart_pandas](https://github.com/adap/flower/tree/" +"main/examples/quickstart_pandas)。" #: ../../source/ref-changelog.md:328 msgid "" -"**Add new strategies: Krum and MultiKrum** " -"([#1481](https://github.com/adap/flower/pull/1481))" +"**Add new strategies: Krum and MultiKrum** ([#1481](https://github.com/adap/" +"flower/pull/1481))" msgstr "" +"**添加新策略: Krum 和 MultiKrum** ([#1481](https://github.com/adap/flower/" +"pull/1481))" #: ../../source/ref-changelog.md:330 msgid "" "Edoardo, a computer science student at the Sapienza University of Rome, " -"contributed a new `Krum` strategy that enables users to easily use Krum " -"and MultiKrum in their workloads." +"contributed a new `Krum` strategy that enables users to easily use Krum and " +"MultiKrum in their workloads." msgstr "" +"罗马萨皮恩扎大学(Sapienza University)计算机科学专业的学生埃多尔多" +"(Edoardo)提出了一种新的 \"Krum \"策略,使用户能够在其工作负载中轻松使用 " +"Krum 和 MultiKrum。" #: ../../source/ref-changelog.md:332 msgid "" -"**Update C++ example to be compatible with Flower v1.2.0** " -"([#1495](https://github.com/adap/flower/pull/1495))" +"**Update C++ example to be compatible with Flower v1.2.0** ([#1495](https://" +"github.com/adap/flower/pull/1495))" msgstr "" +"** 更新 C++ 示例,与 Flower v1.2.0 兼容** ([#1495](https://github.com/adap/" +"flower/pull/1495))" #: ../../source/ref-changelog.md:334 msgid "" -"The C++ code example has received a substantial update to make it " -"compatible with the latest version of Flower." -msgstr "" +"The C++ code example has received a substantial update to make it compatible " +"with the latest version of Flower." +msgstr "为了与最新版本的 Flower 兼容,C++ 示例代码进行了大幅更新。" #: ../../source/ref-changelog.md:336 msgid "" -"**General improvements** " -"([#1491](https://github.com/adap/flower/pull/1491), " -"[#1504](https://github.com/adap/flower/pull/1504), " -"[#1506](https://github.com/adap/flower/pull/1506), " -"[#1514](https://github.com/adap/flower/pull/1514), " -"[#1522](https://github.com/adap/flower/pull/1522), " -"[#1523](https://github.com/adap/flower/pull/1523), " -"[#1526](https://github.com/adap/flower/pull/1526), " -"[#1528](https://github.com/adap/flower/pull/1528), " -"[#1547](https://github.com/adap/flower/pull/1547), " -"[#1549](https://github.com/adap/flower/pull/1549), " -"[#1560](https://github.com/adap/flower/pull/1560), " -"[#1564](https://github.com/adap/flower/pull/1564), " -"[#1566](https://github.com/adap/flower/pull/1566))" -msgstr "" +"**General improvements** ([#1491](https://github.com/adap/flower/pull/1491), " +"[#1504](https://github.com/adap/flower/pull/1504), [#1506](https://github." +"com/adap/flower/pull/1506), [#1514](https://github.com/adap/flower/" +"pull/1514), [#1522](https://github.com/adap/flower/pull/1522), [#1523]" +"(https://github.com/adap/flower/pull/1523), [#1526](https://github.com/adap/" +"flower/pull/1526), [#1528](https://github.com/adap/flower/pull/1528), [#1547]" +"(https://github.com/adap/flower/pull/1547), [#1549](https://github.com/adap/" +"flower/pull/1549), [#1560](https://github.com/adap/flower/pull/1560), [#1564]" +"(https://github.com/adap/flower/pull/1564), [#1566](https://github.com/adap/" +"flower/pull/1566))" +msgstr "" +"**一般改进** ([#1491](https://github.com/adap/flower/pull/1491), [#1504]" +"(https://github.com/adap/flower/pull/1504), [#1506](https://github.com/adap/" +"flower/pull/1506), [#1514](https://github.com/adap/flower/pull/1514), [#1522]" +"(https://github.com/adap/flower/pull/1522), [#1523](https://github.com/adap/" +"flower/pull/1523), [#1526](https://github. com/adap/flower/pull/1526), " +"[#1528](https://github.com/adap/flower/pull/1528), [#1547](https://github." +"com/adap/flower/pull/1547), [#1549](https://github.com/adap/flower/" +"pull/1549), [#1560](https://github.com/adap/flower/pull/1560), [#1564]" +"(https://github.com/adap/flower/pull/1564), [#1566](https://github.com/adap/" +"flower/pull/1566))" #: ../../source/ref-changelog.md:340 msgid "" -"**Updated documentation** " -"([#1494](https://github.com/adap/flower/pull/1494), " -"[#1496](https://github.com/adap/flower/pull/1496), " -"[#1500](https://github.com/adap/flower/pull/1500), " -"[#1503](https://github.com/adap/flower/pull/1503), " -"[#1505](https://github.com/adap/flower/pull/1505), " -"[#1524](https://github.com/adap/flower/pull/1524), " -"[#1518](https://github.com/adap/flower/pull/1518), " -"[#1519](https://github.com/adap/flower/pull/1519), " -"[#1515](https://github.com/adap/flower/pull/1515))" -msgstr "" +"**Updated documentation** ([#1494](https://github.com/adap/flower/" +"pull/1494), [#1496](https://github.com/adap/flower/pull/1496), [#1500]" +"(https://github.com/adap/flower/pull/1500), [#1503](https://github.com/adap/" +"flower/pull/1503), [#1505](https://github.com/adap/flower/pull/1505), [#1524]" +"(https://github.com/adap/flower/pull/1524), [#1518](https://github.com/adap/" +"flower/pull/1518), [#1519](https://github.com/adap/flower/pull/1519), [#1515]" +"(https://github.com/adap/flower/pull/1515))" +msgstr "" +"** 更新文档** ([#1494](https://github.com/adap/flower/pull/1494), [#1496]" +"(https://github.com/adap/flower/pull/1496), [#1500](https://github.com/adap/" +"flower/pull/1500), [#1503](https://github.com/adap/flower/pull/1503), [#1505]" +"(https://github.com/adap/flower/pull/1505), [#1524](https://github.com/adap/" +"flower/pull/1524), [#1518](https://github.com/adap/flower/pull/1518), [#1519]" +"(https://github.com/adap/flower/pull/1519), [#1515](https://github.com/adap/" +"flower/pull/1515))" #: ../../source/ref-changelog.md:344 msgid "" -"One highlight is the new [first time contributor " -"guide](https://flower.dev/docs/first-time-contributors.html): if you've " -"never contributed on GitHub before, this is the perfect place to start!" +"One highlight is the new [first time contributor guide](https://flower.dev/" +"docs/first-time-contributors.html): if you've never contributed on GitHub " +"before, this is the perfect place to start!" msgstr "" +"其中一个亮点是新的[首次贡献者指南](https://flower.dev/docs/first-time-" +"contributors.html):如果你以前从未在 GitHub 上做过贡献,这将是一个完美的开" +"始!" #: ../../source/ref-changelog.md:350 msgid "v1.1.0 (2022-10-31)" -msgstr "" +msgstr "v1.1.0 (2022-10-31)" #: ../../source/ref-changelog.md:354 msgid "" "We would like to give our **special thanks** to all the contributors who " "made the new version of Flower possible (in `git shortlog` order):" msgstr "" +"在此,我们向所有促成 Flower 新版本的贡献者致以**特别的谢意(按 \"git " +"shortlog \"顺序排列):" #: ../../source/ref-changelog.md:356 msgid "" "`Akis Linardos`, `Christopher S`, `Daniel J. Beutel`, `George`, `Jan " "Schlicht`, `Mohammad Fares`, `Pedro Porto Buarque de Gusmão`, `Philipp " -"Wiesner`, `Rob Luke`, `Taner Topal`, `VasundharaAgarwal`, " -"`danielnugraha`, `edogab33`" +"Wiesner`, `Rob Luke`, `Taner Topal`, `VasundharaAgarwal`, `danielnugraha`, " +"`edogab33`" msgstr "" #: ../../source/ref-changelog.md:360 msgid "" -"**Introduce Differential Privacy wrappers (preview)** " -"([#1357](https://github.com/adap/flower/pull/1357), " -"[#1460](https://github.com/adap/flower/pull/1460))" +"**Introduce Differential Privacy wrappers (preview)** ([#1357](https://" +"github.com/adap/flower/pull/1357), [#1460](https://github.com/adap/flower/" +"pull/1460))" msgstr "" +"**引入差分隐私包装器(预览)** ([#1357](https://github.com/adap/flower/" +"pull/1357), [#1460](https://github.com/adap/flower/pull/1460))" #: ../../source/ref-changelog.md:362 msgid "" -"The first (experimental) preview of pluggable Differential Privacy " -"wrappers enables easy configuration and usage of differential privacy " -"(DP). The pluggable DP wrappers enable framework-agnostic **and** " -"strategy-agnostic usage of both client-side DP and server-side DP. Head " -"over to the Flower docs, a new explainer goes into more detail." +"The first (experimental) preview of pluggable Differential Privacy wrappers " +"enables easy configuration and usage of differential privacy (DP). The " +"pluggable DP wrappers enable framework-agnostic **and** strategy-agnostic " +"usage of both client-side DP and server-side DP. Head over to the Flower " +"docs, a new explainer goes into more detail." msgstr "" +"可插拔差分隐私封装器的首个(实验性)预览版可轻松配置和使用差分隐私(DP)。可" +"插拔的差分隐私封装器可实现客户端差分隐私和服务器端差分隐私的框架无关**和**策" +"略无关的使用。请访问 Flower 文档,新的解释器会提供更多细节。" #: ../../source/ref-changelog.md:364 msgid "" -"**New iOS CoreML code example** " -"([#1289](https://github.com/adap/flower/pull/1289))" +"**New iOS CoreML code example** ([#1289](https://github.com/adap/flower/" +"pull/1289))" msgstr "" +"**新的 iOS CoreML 代码示例**([#1289](https://github.com/adap/flower/" +"pull/1289))" #: ../../source/ref-changelog.md:366 msgid "" -"Flower goes iOS! A massive new code example shows how Flower clients can " -"be built for iOS. The code example contains both Flower iOS SDK " -"components that can be used for many tasks, and one task example running " -"on CoreML." +"Flower goes iOS! A massive new code example shows how Flower clients can be " +"built for iOS. The code example contains both Flower iOS SDK components that " +"can be used for many tasks, and one task example running on CoreML." msgstr "" +"Flower 进入 iOS!大量新代码示例展示了如何为 iOS 构建 Flower 客户端。该代码示" +"例包含可用于多种任务的 Flower iOS SDK 组件,以及在 CoreML 上运行的一个任务示" +"例。" #: ../../source/ref-changelog.md:368 msgid "" -"**New FedMedian strategy** " -"([#1461](https://github.com/adap/flower/pull/1461))" +"**New FedMedian strategy** ([#1461](https://github.com/adap/flower/" +"pull/1461))" msgstr "" +"**新的联邦医疗战略** ([#1461](https://github.com/adap/flower/pull/1461))" #: ../../source/ref-changelog.md:370 msgid "" -"The new `FedMedian` strategy implements Federated Median (FedMedian) by " -"[Yin et al., 2018](https://arxiv.org/pdf/1803.01498v1.pdf)." +"The new `FedMedian` strategy implements Federated Median (FedMedian) by [Yin " +"et al., 2018](https://arxiv.org/pdf/1803.01498v1.pdf)." msgstr "" +"新的 \"FedMedian \"战略实现了[Yin 等人,2018]的联邦中值(FedMedian)(https://" +"arxiv.org/pdf/1803.01498v1.pdf)。" #: ../../source/ref-changelog.md:372 msgid "" -"**Log** `Client` **exceptions in Virtual Client Engine** " -"([#1493](https://github.com/adap/flower/pull/1493))" +"**Log** `Client` **exceptions in Virtual Client Engine** ([#1493](https://" +"github.com/adap/flower/pull/1493))" msgstr "" +"**虚拟客户端引擎中的**日志**`客户端`**异常([#1493](https://github.com/adap/" +"flower/pull/1493))" #: ../../source/ref-changelog.md:374 msgid "" -"All `Client` exceptions happening in the VCE are now logged by default " -"and not just exposed to the configured `Strategy` (via the `failures` " -"argument)." +"All `Client` exceptions happening in the VCE are now logged by default and " +"not just exposed to the configured `Strategy` (via the `failures` argument)." msgstr "" +"VCE 中发生的所有 \"客户端 \"异常现在都会被默认记录下来,而不只是暴露给配置的 " +"\"策略\"(通过 \"failures \"参数)。" #: ../../source/ref-changelog.md:376 msgid "" -"**Improve Virtual Client Engine internals** " -"([#1401](https://github.com/adap/flower/pull/1401), " -"[#1453](https://github.com/adap/flower/pull/1453))" +"**Improve Virtual Client Engine internals** ([#1401](https://github.com/adap/" +"flower/pull/1401), [#1453](https://github.com/adap/flower/pull/1453))" msgstr "" +"**改进虚拟客户端引擎内部**([#1401](https://github.com/adap/flower/" +"pull/1401)、[#1453](https://github.com/adap/flower/pull/1453))" #: ../../source/ref-changelog.md:378 msgid "" -"Some internals of the Virtual Client Engine have been revamped. The VCE " -"now uses Ray 2.0 under the hood, the value type of the `client_resources`" -" dictionary changed to `float` to allow fractions of resources to be " +"Some internals of the Virtual Client Engine have been revamped. The VCE now " +"uses Ray 2.0 under the hood, the value type of the `client_resources` " +"dictionary changed to `float` to allow fractions of resources to be " "allocated." msgstr "" +"虚拟客户端引擎的部分内部结构已进行了修改。VCE 现在使用 Ray " +"2.0,\"client_resources \"字典的值类型改为 \"float\",以允许分配分数资源。" #: ../../source/ref-changelog.md:380 msgid "" -"**Support optional** `Client`**/**`NumPyClient` **methods in Virtual " -"Client Engine**" -msgstr "" +"**Support optional** `Client`**/**`NumPyClient` **methods in Virtual Client " +"Engine**" +msgstr "**支持虚拟客户端引擎中的可选** `Client`**/**`NumPyClient` **方法**" #: ../../source/ref-changelog.md:382 msgid "" -"The Virtual Client Engine now has full support for optional `Client` (and" -" `NumPyClient`) methods." -msgstr "" +"The Virtual Client Engine now has full support for optional `Client` (and " +"`NumPyClient`) methods." +msgstr "虚拟客户端引擎现在完全支持可选的 `Client`(和 `NumPyClient`)方法。" #: ../../source/ref-changelog.md:384 msgid "" -"**Provide type information to packages using** `flwr` " -"([#1377](https://github.com/adap/flower/pull/1377))" +"**Provide type information to packages using** `flwr` ([#1377](https://" +"github.com/adap/flower/pull/1377))" msgstr "" +"**使用** `flwr`向软件包提供类型信息 ([#1377](https://github.com/adap/flower/" +"pull/1377))" #: ../../source/ref-changelog.md:386 msgid "" -"The package `flwr` is now bundled with a `py.typed` file indicating that " -"the package is typed. This enables typing support for projects or " -"packages that use `flwr` by enabling them to improve their code using " -"static type checkers like `mypy`." +"The package `flwr` is now bundled with a `py.typed` file indicating that the " +"package is typed. This enables typing support for projects or packages that " +"use `flwr` by enabling them to improve their code using static type checkers " +"like `mypy`." msgstr "" +"软件包 `flwr` 现在捆绑了一个 `py.typed` 文件,表明该软件包是类型化的。这样," +"使用 `flwr` 的项目或软件包就可以使用 `mypy` 等静态类型检查器改进代码,从而获" +"得类型支持。" #: ../../source/ref-changelog.md:388 msgid "" -"**Updated code example** " -"([#1344](https://github.com/adap/flower/pull/1344), " +"**Updated code example** ([#1344](https://github.com/adap/flower/pull/1344), " "[#1347](https://github.com/adap/flower/pull/1347))" msgstr "" +"** 更新代码示例** ([#1344](https://github.com/adap/flower/pull/1344), [#1347]" +"(https://github.com/adap/flower/pull/1347))" #: ../../source/ref-changelog.md:390 msgid "" "The code examples covering scikit-learn and PyTorch Lightning have been " "updated to work with the latest version of Flower." msgstr "" +"涵盖 scikit-learn 和 PyTorch Lightning 的代码示例已更新,以便与最新版本的 " +"Flower 配合使用。" #: ../../source/ref-changelog.md:392 msgid "" -"**Updated documentation** " -"([#1355](https://github.com/adap/flower/pull/1355), " -"[#1558](https://github.com/adap/flower/pull/1558), " -"[#1379](https://github.com/adap/flower/pull/1379), " -"[#1380](https://github.com/adap/flower/pull/1380), " -"[#1381](https://github.com/adap/flower/pull/1381), " -"[#1332](https://github.com/adap/flower/pull/1332), " -"[#1391](https://github.com/adap/flower/pull/1391), " -"[#1403](https://github.com/adap/flower/pull/1403), " -"[#1364](https://github.com/adap/flower/pull/1364), " -"[#1409](https://github.com/adap/flower/pull/1409), " -"[#1419](https://github.com/adap/flower/pull/1419), " -"[#1444](https://github.com/adap/flower/pull/1444), " -"[#1448](https://github.com/adap/flower/pull/1448), " -"[#1417](https://github.com/adap/flower/pull/1417), " -"[#1449](https://github.com/adap/flower/pull/1449), " -"[#1465](https://github.com/adap/flower/pull/1465), " -"[#1467](https://github.com/adap/flower/pull/1467))" -msgstr "" +"**Updated documentation** ([#1355](https://github.com/adap/flower/" +"pull/1355), [#1558](https://github.com/adap/flower/pull/1558), [#1379]" +"(https://github.com/adap/flower/pull/1379), [#1380](https://github.com/adap/" +"flower/pull/1380), [#1381](https://github.com/adap/flower/pull/1381), [#1332]" +"(https://github.com/adap/flower/pull/1332), [#1391](https://github.com/adap/" +"flower/pull/1391), [#1403](https://github.com/adap/flower/pull/1403), [#1364]" +"(https://github.com/adap/flower/pull/1364), [#1409](https://github.com/adap/" +"flower/pull/1409), [#1419](https://github.com/adap/flower/pull/1419), [#1444]" +"(https://github.com/adap/flower/pull/1444), [#1448](https://github.com/adap/" +"flower/pull/1448), [#1417](https://github.com/adap/flower/pull/1417), [#1449]" +"(https://github.com/adap/flower/pull/1449), [#1465](https://github.com/adap/" +"flower/pull/1465), [#1467](https://github.com/adap/flower/pull/1467))" +msgstr "" +"**更新文档** ([#1355](https://github.com/adap/flower/pull/1355), [#1558]" +"(https://github.com/adap/flower/pull/1558), [#1379](https://github.com/adap/" +"flower/pull/1379), [#1380](https://github.com/adap/flower/pull/1380), [#1381]" +"(https://github.com/adap/flower/pull/1381), [#1332](https://github.com/adap/" +"flower/pull/1332), [#1391](https://github.com/adap/flower/pull/1391), [#1403]" +"(https://github.com/adap/flower/pull/1403), [#1364](https://github. com/adap/" +"flower/pull/1364), [#1409](https://github.com/adap/flower/pull/1409), [#1419]" +"(https://github.com/adap/flower/pull/1419), [#1444](https://github.com/adap/" +"flower/pull/1444), [#1448](https://github.com/adap/flower/pull/1448), [#1417]" +"(https://github.com/adap/flower/pull/1417), [#1449](https://github.com/adap/" +"flower/pull/1449), [#1465](https://github.com/adap/flower/pull/1465), [#1467]" +"(https://github.com/adap/flower/pull/1467))" #: ../../source/ref-changelog.md:394 msgid "" "There have been so many documentation updates that it doesn't even make " "sense to list them individually." -msgstr "" +msgstr "文档更新的数量之多,甚至没有必要逐一列出。" #: ../../source/ref-changelog.md:396 msgid "" -"**Restructured documentation** " -"([#1387](https://github.com/adap/flower/pull/1387))" -msgstr "" +"**Restructured documentation** ([#1387](https://github.com/adap/flower/" +"pull/1387))" +msgstr "**重构文档**([#1387](https://github.com/adap/flower/pull/1387))" #: ../../source/ref-changelog.md:398 msgid "" -"The documentation has been restructured to make it easier to navigate. " -"This is just the first step in a larger effort to make the Flower " -"documentation the best documentation of any project ever. Stay tuned!" +"The documentation has been restructured to make it easier to navigate. This " +"is just the first step in a larger effort to make the Flower documentation " +"the best documentation of any project ever. Stay tuned!" msgstr "" +"我们对文档进行了重组,使其更易于浏览。这只是让 Flower 文档成为所有项目中最好" +"文档的第一步。敬请期待!" #: ../../source/ref-changelog.md:400 msgid "" -"**Open in Colab button** " -"([#1389](https://github.com/adap/flower/pull/1389))" +"**Open in Colab button** ([#1389](https://github.com/adap/flower/pull/1389))" msgstr "" +"**在 Colab 中打开按钮** ([#1389](https://github.com/adap/flower/pull/1389))" #: ../../source/ref-changelog.md:402 msgid "" -"The four parts of the Flower Federated Learning Tutorial now come with a " -"new `Open in Colab` button. No need to install anything on your local " -"machine, you can now use and learn about Flower in your browser, it's " -"only a single click away." +"The four parts of the Flower Federated Learning Tutorial now come with a new " +"`Open in Colab` button. No need to install anything on your local machine, " +"you can now use and learn about Flower in your browser, it's only a single " +"click away." msgstr "" +"Flower 联邦学习教程的四个部分现在都带有一个新的 \"在 Colab 中打开 \"按钮。现" +"在,您无需在本地计算机上安装任何软件,只需点击一下,就可以在浏览器中使用和学" +"习 Flower。" #: ../../source/ref-changelog.md:404 msgid "" -"**Improved tutorial** ([#1468](https://github.com/adap/flower/pull/1468)," -" [#1470](https://github.com/adap/flower/pull/1470), " -"[#1472](https://github.com/adap/flower/pull/1472), " -"[#1473](https://github.com/adap/flower/pull/1473), " -"[#1474](https://github.com/adap/flower/pull/1474), " -"[#1475](https://github.com/adap/flower/pull/1475))" +"**Improved tutorial** ([#1468](https://github.com/adap/flower/pull/1468), " +"[#1470](https://github.com/adap/flower/pull/1470), [#1472](https://github." +"com/adap/flower/pull/1472), [#1473](https://github.com/adap/flower/" +"pull/1473), [#1474](https://github.com/adap/flower/pull/1474), [#1475]" +"(https://github.com/adap/flower/pull/1475))" msgstr "" +"**改进教程** ([#1468](https://github.com/adap/flower/pull/1468), [#1470]" +"(https://github.com/adap/flower/pull/1470), [#1472](https://github.com/adap/" +"flower/pull/1472), [#1473](https://github.com/adap/flower/pull/1473), [#1474]" +"(https://github.com/adap/flower/pull/1474), [#1475](https://github.com/adap/" +"flower/pull/1475)))" #: ../../source/ref-changelog.md:406 msgid "" "The Flower Federated Learning Tutorial has two brand-new parts covering " "custom strategies (still WIP) and the distinction between `Client` and " -"`NumPyClient`. The existing parts one and two have also been improved " -"(many small changes and fixes)." +"`NumPyClient`. The existing parts one and two have also been improved (many " +"small changes and fixes)." msgstr "" +"Flower Federated Learning 教程有两个全新的部分,涉及自定义策略(仍处于 WIP 阶" +"段)和 `Client` 与 `NumPyClient` 之间的区别。现有的第一和第二部分也得到了改进" +"(许多小改动和修正)。" #: ../../source/ref-changelog.md:412 msgid "v1.0.0 (2022-07-28)" -msgstr "" +msgstr "v1.0.0 (2022-07-28)" #: ../../source/ref-changelog.md:414 msgid "Highlights" -msgstr "" +msgstr "亮点" #: ../../source/ref-changelog.md:416 msgid "Stable **Virtual Client Engine** (accessible via `start_simulation`)" -msgstr "" +msgstr "稳定的**虚拟客户端引擎**(可通过`start_simulation`访问)" #: ../../source/ref-changelog.md:417 msgid "All `Client`/`NumPyClient` methods are now optional" -msgstr "" +msgstr "所有 `Client`/`NumPyClient` 方法现在都是可选的了" #: ../../source/ref-changelog.md:418 msgid "Configurable `get_parameters`" -msgstr "" +msgstr "可配置的`get_parameters`" #: ../../source/ref-changelog.md:419 msgid "" -"Tons of small API cleanups resulting in a more coherent developer " -"experience" -msgstr "" +"Tons of small API cleanups resulting in a more coherent developer experience" +msgstr "对大量小型应用程序接口进行了清理,使开发人员的体验更加一致" #: ../../source/ref-changelog.md:423 msgid "" "We would like to give our **special thanks** to all the contributors who " -"made Flower 1.0 possible (in reverse [GitHub " -"Contributors](https://github.com/adap/flower/graphs/contributors) order):" +"made Flower 1.0 possible (in reverse [GitHub Contributors](https://github." +"com/adap/flower/graphs/contributors) order):" msgstr "" +"在此,我们谨向所有促成 Flower 1.0 的贡献者致以**特别的谢意(按[GitHub 贡献者]" +"(https://github.com/adap/flower/graphs/contributors) 倒序排列):" #: ../../source/ref-changelog.md:425 msgid "" -"[@rtaiello](https://github.com/rtaiello), " -"[@g-pichler](https://github.com/g-pichler), [@rob-" -"luke](https://github.com/rob-luke), [@andreea-zaharia](https://github.com" -"/andreea-zaharia), [@kinshukdua](https://github.com/kinshukdua), " -"[@nfnt](https://github.com/nfnt), " -"[@tatiana-s](https://github.com/tatiana-s), " -"[@TParcollet](https://github.com/TParcollet), " -"[@vballoli](https://github.com/vballoli), " -"[@negedng](https://github.com/negedng), " -"[@RISHIKESHAVAN](https://github.com/RISHIKESHAVAN), " -"[@hei411](https://github.com/hei411), " -"[@SebastianSpeitel](https://github.com/SebastianSpeitel), " -"[@AmitChaulwar](https://github.com/AmitChaulwar), " -"[@Rubiel1](https://github.com/Rubiel1), [@FANTOME-PAN](https://github.com" -"/FANTOME-PAN), [@Rono-BC](https://github.com/Rono-BC), " -"[@lbhm](https://github.com/lbhm), " -"[@sishtiaq](https://github.com/sishtiaq), " -"[@remde](https://github.com/remde), [@Jueun-Park](https://github.com" -"/Jueun-Park), [@architjen](https://github.com/architjen), " -"[@PratikGarai](https://github.com/PratikGarai), " -"[@mrinaald](https://github.com/mrinaald), " -"[@zliel](https://github.com/zliel), " -"[@MeiruiJiang](https://github.com/MeiruiJiang), " -"[@sandracl72](https://github.com/sandracl72), " -"[@gubertoli](https://github.com/gubertoli), " -"[@Vingt100](https://github.com/Vingt100), " -"[@MakGulati](https://github.com/MakGulati), " -"[@cozek](https://github.com/cozek), " -"[@jafermarq](https://github.com/jafermarq), " -"[@sisco0](https://github.com/sisco0), " -"[@akhilmathurs](https://github.com/akhilmathurs), " -"[@CanTuerk](https://github.com/CanTuerk), " -"[@mariaboerner1987](https://github.com/mariaboerner1987), " -"[@pedropgusmao](https://github.com/pedropgusmao), " -"[@tanertopal](https://github.com/tanertopal), " -"[@danieljanes](https://github.com/danieljanes)." +"[@rtaiello](https://github.com/rtaiello), [@g-pichler](https://github.com/g-" +"pichler), [@rob-luke](https://github.com/rob-luke), [@andreea-zaharia]" +"(https://github.com/andreea-zaharia), [@kinshukdua](https://github.com/" +"kinshukdua), [@nfnt](https://github.com/nfnt), [@tatiana-s](https://github." +"com/tatiana-s), [@TParcollet](https://github.com/TParcollet), [@vballoli]" +"(https://github.com/vballoli), [@negedng](https://github.com/negedng), " +"[@RISHIKESHAVAN](https://github.com/RISHIKESHAVAN), [@hei411](https://github." +"com/hei411), [@SebastianSpeitel](https://github.com/SebastianSpeitel), " +"[@AmitChaulwar](https://github.com/AmitChaulwar), [@Rubiel1](https://github." +"com/Rubiel1), [@FANTOME-PAN](https://github.com/FANTOME-PAN), [@Rono-BC]" +"(https://github.com/Rono-BC), [@lbhm](https://github.com/lbhm), [@sishtiaq]" +"(https://github.com/sishtiaq), [@remde](https://github.com/remde), [@Jueun-" +"Park](https://github.com/Jueun-Park), [@architjen](https://github.com/" +"architjen), [@PratikGarai](https://github.com/PratikGarai), [@mrinaald]" +"(https://github.com/mrinaald), [@zliel](https://github.com/zliel), " +"[@MeiruiJiang](https://github.com/MeiruiJiang), [@sandracl72](https://github." +"com/sandracl72), [@gubertoli](https://github.com/gubertoli), [@Vingt100]" +"(https://github.com/Vingt100), [@MakGulati](https://github.com/MakGulati), " +"[@cozek](https://github.com/cozek), [@jafermarq](https://github.com/" +"jafermarq), [@sisco0](https://github.com/sisco0), [@akhilmathurs](https://" +"github.com/akhilmathurs), [@CanTuerk](https://github.com/CanTuerk), " +"[@mariaboerner1987](https://github.com/mariaboerner1987), [@pedropgusmao]" +"(https://github.com/pedropgusmao), [@tanertopal](https://github.com/" +"tanertopal), [@danieljanes](https://github.com/danieljanes)." msgstr "" #: ../../source/ref-changelog.md:429 msgid "" -"**All arguments must be passed as keyword arguments** " -"([#1338](https://github.com/adap/flower/pull/1338))" +"**All arguments must be passed as keyword arguments** ([#1338](https://" +"github.com/adap/flower/pull/1338))" msgstr "" +"** 所有参数必须作为关键字参数传递** ([#1338](https://github.com/adap/flower/" +"pull/1338))" #: ../../source/ref-changelog.md:431 msgid "" -"Pass all arguments as keyword arguments, positional arguments are not " -"longer supported. Code that uses positional arguments (e.g., " -"`start_client(\"127.0.0.1:8080\", FlowerClient())`) must add the keyword " -"for each positional argument (e.g., " -"`start_client(server_address=\"127.0.0.1:8080\", " -"client=FlowerClient())`)." +"Pass all arguments as keyword arguments, positional arguments are not longer " +"supported. Code that uses positional arguments (e.g., " +"`start_client(\"127.0.0.1:8080\", FlowerClient())`) must add the keyword for " +"each positional argument (e.g., " +"`start_client(server_address=\"127.0.0.1:8080\", client=FlowerClient())`)." msgstr "" +"以关键字参数传递所有参数,不再支持位置参数。使用位置参数的代码(例如," +"`start_client(\"127.0.0.1:8080\", FlowerClient())`)必须为每个位置参数添加关" +"键字(例如,`start_client(server_address=\"127.0.0.1:8080\", " +"client=FlowerClient())`)。" #: ../../source/ref-changelog.md:433 msgid "" "**Introduce configuration object** `ServerConfig` **in** `start_server` " -"**and** `start_simulation` " -"([#1317](https://github.com/adap/flower/pull/1317))" +"**and** `start_simulation` ([#1317](https://github.com/adap/flower/" +"pull/1317))" msgstr "" +"**在*** `start_server` ***和*** `start_simulation` 中引入配置对象*** " +"`ServerConfig` ([#1317](https://github.com/adap/flower/pull/1317))" #: ../../source/ref-changelog.md:435 msgid "" -"Instead of a config dictionary `{\"num_rounds\": 3, \"round_timeout\": " -"600.0}`, `start_server` and `start_simulation` now expect a configuration" -" object of type `flwr.server.ServerConfig`. `ServerConfig` takes the same" -" arguments that as the previous config dict, but it makes writing type-" -"safe code easier and the default parameters values more transparent." +"Instead of a config dictionary `{\"num_rounds\": 3, \"round_timeout\": 600.0}" +"`, `start_server` and `start_simulation` now expect a configuration object " +"of type `flwr.server.ServerConfig`. `ServerConfig` takes the same arguments " +"that as the previous config dict, but it makes writing type-safe code easier " +"and the default parameters values more transparent." msgstr "" +"而不是配置字典`{\"num_rounds\": 3, \"round_timeout\": 600.0}`, " +"`start_server`和 `start_simulation`现在期待一个类型为 `flwr.server." +"ServerConfig`的配置对象。ServerConfig`接收的参数与之前的 config dict 相同,但" +"它使编写类型安全代码变得更容易,默认参数值也更加透明。" #: ../../source/ref-changelog.md:437 msgid "" -"**Rename built-in strategy parameters for clarity** " -"([#1334](https://github.com/adap/flower/pull/1334))" +"**Rename built-in strategy parameters for clarity** ([#1334](https://github." +"com/adap/flower/pull/1334))" msgstr "" +"**重新命名内置策略参数,使其更加清晰** ([#1334](https://github.com/adap/" +"flower/pull/1334))" #: ../../source/ref-changelog.md:439 msgid "" "The following built-in strategy parameters were renamed to improve " "readability and consistency with other API's:" -msgstr "" +msgstr "以下内置策略参数已重新命名,以提高可读性并与其他 API 保持一致:" #: ../../source/ref-changelog.md:441 msgid "`fraction_eval` --> `fraction_evaluate`" @@ -8619,18 +10105,23 @@ msgstr "" #: ../../source/ref-changelog.md:445 msgid "" -"**Update default arguments of built-in strategies** " -"([#1278](https://github.com/adap/flower/pull/1278))" +"**Update default arguments of built-in strategies** ([#1278](https://github." +"com/adap/flower/pull/1278))" msgstr "" +"**更新内置策略的默认参数** ([#1278](https://github.com/adap/flower/" +"pull/1278))" #: ../../source/ref-changelog.md:447 msgid "" "All built-in strategies now use `fraction_fit=1.0` and " -"`fraction_evaluate=1.0`, which means they select *all* currently " -"available clients for training and evaluation. Projects that relied on " -"the previous default values can get the previous behaviour by " -"initializing the strategy in the following way:" +"`fraction_evaluate=1.0`, which means they select *all* currently available " +"clients for training and evaluation. Projects that relied on the previous " +"default values can get the previous behaviour by initializing the strategy " +"in the following way:" msgstr "" +"所有内置策略现在都使用 \"fraction_fit=1.0 \"和 \"fraction_evaluate=1.0\",这" +"意味着它们会选择*所有*当前可用的客户端进行训练和评估。依赖以前默认值的项目可" +"以通过以下方式初始化策略,获得以前的行为:" #: ../../source/ref-changelog.md:449 msgid "`strategy = FedAvg(fraction_fit=0.1, fraction_evaluate=0.1)`" @@ -8638,177 +10129,225 @@ msgstr "" #: ../../source/ref-changelog.md:451 msgid "" -"**Add** `server_round` **to** `Strategy.evaluate` " -"([#1334](https://github.com/adap/flower/pull/1334))" +"**Add** `server_round` **to** `Strategy.evaluate` ([#1334](https://github." +"com/adap/flower/pull/1334))" msgstr "" +"**添加*** `server_round` ***到*** `Strategy.evaluate` ([#1334](https://" +"github.com/adap/flower/pull/1334))" #: ../../source/ref-changelog.md:453 msgid "" -"The `Strategy` method `evaluate` now receives the current round of " -"federated learning/evaluation as the first parameter." -msgstr "" +"The `Strategy` method `evaluate` now receives the current round of federated " +"learning/evaluation as the first parameter." +msgstr "策略 \"方法 \"评估 \"现在会接收当前一轮联邦学习/评估作为第一个参数。" #: ../../source/ref-changelog.md:455 msgid "" "**Add** `server_round` **and** `config` **parameters to** `evaluate_fn` " "([#1334](https://github.com/adap/flower/pull/1334))" msgstr "" +"**将*** `server_round` **和*** `config` **参数添加到*** `evaluate_fn` " +"([#1334](https://github.com/adap/flower/pull/1334))" #: ../../source/ref-changelog.md:457 msgid "" "The `evaluate_fn` passed to built-in strategies like `FedAvg` now takes " "three parameters: (1) The current round of federated learning/evaluation " -"(`server_round`), (2) the model parameters to evaluate (`parameters`), " -"and (3) a config dictionary (`config`)." +"(`server_round`), (2) the model parameters to evaluate (`parameters`), and " +"(3) a config dictionary (`config`)." msgstr "" +"传递给内置策略(如 `FedAvg`)的 `evaluate_fn` 现在需要三个参数:(1) 当前一轮" +"联合学习/评估 (`server_round`),(2) 要评估的模型参数 (`parameters`),(3) 配置" +"字典 (`config`)。" #: ../../source/ref-changelog.md:459 msgid "" -"**Rename** `rnd` **to** `server_round` " -"([#1321](https://github.com/adap/flower/pull/1321))" +"**Rename** `rnd` **to** `server_round` ([#1321](https://github.com/adap/" +"flower/pull/1321))" msgstr "" +"**重新命名** `rnd` ** to** `server_round` ([#1321](https://github.com/adap/" +"flower/pull/1321))" #: ../../source/ref-changelog.md:461 msgid "" "Several Flower methods and functions (`evaluate_fn`, `configure_fit`, " "`aggregate_fit`, `configure_evaluate`, `aggregate_evaluate`) receive the " -"current round of federated learning/evaluation as their first parameter. " -"To improve reaability and avoid confusion with *random*, this parameter " -"has been renamed from `rnd` to `server_round`." +"current round of federated learning/evaluation as their first parameter. To " +"improve reaability and avoid confusion with *random*, this parameter has " +"been renamed from `rnd` to `server_round`." msgstr "" +"几个 Flower 方法和函数(`evaluate_fn`、`configure_fit`、`aggregate_fit`、" +"`configure_evaluate`、`aggregate_evaluate`)的第一个参数是当前一轮的联合学习/" +"评估。为提高可重复性并避免与 *random* 混淆,该参数已从 `rnd` 更名为 " +"`server_round`。" #: ../../source/ref-changelog.md:463 msgid "" -"**Move** `flwr.dataset` **to** `flwr_baselines` " -"([#1273](https://github.com/adap/flower/pull/1273))" +"**Move** `flwr.dataset` **to** `flwr_baselines` ([#1273](https://github.com/" +"adap/flower/pull/1273))" msgstr "" +"**移动*** `flwr.dataset` **到*** `flwr_baselines` ([#1273](https://github." +"com/adap/flower/pull/1273))" #: ../../source/ref-changelog.md:465 -msgid "The experimental package `flwr.dataset` was migrated to Flower Baselines." -msgstr "" +msgid "" +"The experimental package `flwr.dataset` was migrated to Flower Baselines." +msgstr "实验软件包 `flwr.dataset` 已迁移至 Flower Baselines。" #: ../../source/ref-changelog.md:467 msgid "" -"**Remove experimental strategies** " -"([#1280](https://github.com/adap/flower/pull/1280))" -msgstr "" +"**Remove experimental strategies** ([#1280](https://github.com/adap/flower/" +"pull/1280))" +msgstr "**删除实验策略** ([#1280](https://github.com/adap/flower/pull/1280))" #: ../../source/ref-changelog.md:469 msgid "" "Remove unmaintained experimental strategies (`FastAndSlow`, `FedFSv0`, " "`FedFSv1`)." -msgstr "" +msgstr "移除未维护的试验性策略(`FastAndSlow`、`FedFSv0`、`FedFSv1`)。" #: ../../source/ref-changelog.md:471 msgid "" -"**Rename** `Weights` **to** `NDArrays` " -"([#1258](https://github.com/adap/flower/pull/1258), " -"[#1259](https://github.com/adap/flower/pull/1259))" +"**Rename** `Weights` **to** `NDArrays` ([#1258](https://github.com/adap/" +"flower/pull/1258), [#1259](https://github.com/adap/flower/pull/1259))" msgstr "" +"**重新命名** `Weights` **到** `NDArrays` ([#1258](https://github.com/adap/" +"flower/pull/1258), [#1259](https://github.com/adap/flower/pull/1259))" #: ../../source/ref-changelog.md:473 msgid "" "`flwr.common.Weights` was renamed to `flwr.common.NDArrays` to better " "capture what this type is all about." msgstr "" +"flwr.common.Weights \"更名为 \"flwr.common.NDArrays\",以更好地反映该类型的含" +"义。" #: ../../source/ref-changelog.md:475 msgid "" -"**Remove antiquated** `force_final_distributed_eval` **from** " -"`start_server` ([#1258](https://github.com/adap/flower/pull/1258), " -"[#1259](https://github.com/adap/flower/pull/1259))" +"**Remove antiquated** `force_final_distributed_eval` **from** `start_server` " +"([#1258](https://github.com/adap/flower/pull/1258), [#1259](https://github." +"com/adap/flower/pull/1259))" msgstr "" +"**从** `start_server` 中移除过时的** `force_final_distributed_eval` ([#1258]" +"(https://github.com/adap/flower/pull/1258), [#1259](https://github.com/adap/" +"flower/pull/1259))" #: ../../source/ref-changelog.md:477 msgid "" -"The `start_server` parameter `force_final_distributed_eval` has long been" -" a historic artefact, in this release it is finally gone for good." +"The `start_server` parameter `force_final_distributed_eval` has long been a " +"historic artefact, in this release it is finally gone for good." msgstr "" +"start_server \"参数 \"force_final_distributed_eval \"长期以来一直是个历史遗留" +"问题,在此版本中终于永远消失了。" #: ../../source/ref-changelog.md:479 msgid "" -"**Make** `get_parameters` **configurable** " -"([#1242](https://github.com/adap/flower/pull/1242))" +"**Make** `get_parameters` **configurable** ([#1242](https://github.com/adap/" +"flower/pull/1242))" msgstr "" +"**使** `get_parameters` **可配置** ([#1242](https://github.com/adap/flower/" +"pull/1242))" #: ../../source/ref-changelog.md:481 msgid "" "The `get_parameters` method now accepts a configuration dictionary, just " "like `get_properties`, `fit`, and `evaluate`." msgstr "" +"现在,\"get_parameters \"方法与 \"get_properties\"、\"fit \"和 \"evaluate " +"\"一样,都接受配置字典。" #: ../../source/ref-changelog.md:483 msgid "" "**Replace** `num_rounds` **in** `start_simulation` **with new** `config` " "**parameter** ([#1281](https://github.com/adap/flower/pull/1281))" msgstr "" +"**用新的** `config` 参数** 替换** `num_rounds` ** in** `start_simulation` ** " +"([#1281](https://github.com/adap/flower/pull/1281))" #: ../../source/ref-changelog.md:485 msgid "" "The `start_simulation` function now accepts a configuration dictionary " -"`config` instead of the `num_rounds` integer. This improves the " -"consistency between `start_simulation` and `start_server` and makes " -"transitioning between the two easier." +"`config` instead of the `num_rounds` integer. This improves the consistency " +"between `start_simulation` and `start_server` and makes transitioning " +"between the two easier." msgstr "" +"现在,`start_simulation`(开始模拟)` 函数接受配置字典 `config` 而不是 " +"`num_rounds` 整数。这改进了 `start_simulation` 和 `start_server` 之间的一致" +"性,并使两者之间的转换更容易。" #: ../../source/ref-changelog.md:489 msgid "" -"**Support Python 3.10** " -"([#1320](https://github.com/adap/flower/pull/1320))" +"**Support Python 3.10** ([#1320](https://github.com/adap/flower/pull/1320))" msgstr "" +"** 支持 Python 3.10** ([#1320](https://github.com/adap/flower/pull/1320))" #: ../../source/ref-changelog.md:491 msgid "" -"The previous Flower release introduced experimental support for Python " -"3.10, this release declares Python 3.10 support as stable." +"The previous Flower release introduced experimental support for Python 3.10, " +"this release declares Python 3.10 support as stable." msgstr "" +"上一个 Flower 版本引入了对 Python 3.10 的实验支持,而本版本则宣布对 Python " +"3.10 的支持为稳定支持。" #: ../../source/ref-changelog.md:493 msgid "" -"**Make all** `Client` **and** `NumPyClient` **methods optional** " -"([#1260](https://github.com/adap/flower/pull/1260), " -"[#1277](https://github.com/adap/flower/pull/1277))" +"**Make all** `Client` **and** `NumPyClient` **methods optional** ([#1260]" +"(https://github.com/adap/flower/pull/1260), [#1277](https://github.com/adap/" +"flower/pull/1277))" msgstr "" +"**使所有** `Client` **和** `NumPyClient` **方法成为可选** ([#1260](https://" +"github.com/adap/flower/pull/1260), [#1277](https://github.com/adap/flower/" +"pull/1277))" #: ../../source/ref-changelog.md:495 msgid "" "The `Client`/`NumPyClient` methods `get_properties`, `get_parameters`, " -"`fit`, and `evaluate` are all optional. This enables writing clients that" -" implement, for example, only `fit`, but no other method. No need to " +"`fit`, and `evaluate` are all optional. This enables writing clients that " +"implement, for example, only `fit`, but no other method. No need to " "implement `evaluate` when using centralized evaluation!" msgstr "" +"客户端\"/\"NumPyClient \"的 \"get_properties\"、\"get_parameters\"、\"fit " +"\"和 \"evaluate \"方法都是可选的。这样就可以编写只实现 `fit` 而不实现其他方法" +"的客户端。使用集中评估时,无需实现 `evaluate`!" #: ../../source/ref-changelog.md:497 msgid "" -"**Enable passing a** `Server` **instance to** `start_simulation` " -"([#1281](https://github.com/adap/flower/pull/1281))" +"**Enable passing a** `Server` **instance to** `start_simulation` ([#1281]" +"(https://github.com/adap/flower/pull/1281))" msgstr "" +"**启用向** `start_simulation` 传递** `Server` 实例 ([#1281](https://github." +"com/adap/flower/pull/1281))" #: ../../source/ref-changelog.md:499 msgid "" -"Similar to `start_server`, `start_simulation` now accepts a full `Server`" -" instance. This enables users to heavily customize the execution of " -"eperiments and opens the door to running, for example, async FL using the" -" Virtual Client Engine." +"Similar to `start_server`, `start_simulation` now accepts a full `Server` " +"instance. This enables users to heavily customize the execution of " +"eperiments and opens the door to running, for example, async FL using the " +"Virtual Client Engine." msgstr "" +"与 `start_server` 类似,`start_simulation` 现在也接受一个完整的 `Server` 实" +"例。这使得用户可以对实验的执行进行大量自定义,并为使用虚拟客户端引擎运行异步 " +"FL 等打开了大门。" #: ../../source/ref-changelog.md:501 msgid "" -"**Update code examples** " -"([#1291](https://github.com/adap/flower/pull/1291), " -"[#1286](https://github.com/adap/flower/pull/1286), " -"[#1282](https://github.com/adap/flower/pull/1282))" +"**Update code examples** ([#1291](https://github.com/adap/flower/pull/1291), " +"[#1286](https://github.com/adap/flower/pull/1286), [#1282](https://github." +"com/adap/flower/pull/1282))" msgstr "" +"**更新代码示例** ([#1291](https://github.com/adap/flower/pull/1291), [#1286]" +"(https://github.com/adap/flower/pull/1286), [#1282](https://github.com/adap/" +"flower/pull/1282))" #: ../../source/ref-changelog.md:503 msgid "" -"Many code examples received small or even large maintenance updates, " -"among them are" -msgstr "" +"Many code examples received small or even large maintenance updates, among " +"them are" +msgstr "许多代码示例都进行了小规模甚至大规模的维护更新,其中包括" #: ../../source/ref-changelog.md:505 msgid "`scikit-learn`" -msgstr "" +msgstr "`scikit-learn`" #: ../../source/ref-changelog.md:506 msgid "`simulation_pytorch`" @@ -8832,9 +10371,10 @@ msgstr "" #: ../../source/ref-changelog.md:512 msgid "" -"**Remove the obsolete simulation example** " -"([#1328](https://github.com/adap/flower/pull/1328))" +"**Remove the obsolete simulation example** ([#1328](https://github.com/adap/" +"flower/pull/1328))" msgstr "" +"**删除过时的模拟示例** ([#1328](https://github.com/adap/flower/pull/1328))" #: ../../source/ref-changelog.md:514 msgid "" @@ -8842,65 +10382,83 @@ msgid "" "`quickstart_simulation` to `simulation_tensorflow` so it fits withs the " "naming of `simulation_pytorch`" msgstr "" +"删除过时的 \"simulation \"示例,并将 \"quickstart_simulation \"重命名为 " +"\"simulation_tensorflow\",使其与 \"simulation_pytorch \"的命名一致" #: ../../source/ref-changelog.md:516 msgid "" -"**Update documentation** " -"([#1223](https://github.com/adap/flower/pull/1223), " -"[#1209](https://github.com/adap/flower/pull/1209), " -"[#1251](https://github.com/adap/flower/pull/1251), " -"[#1257](https://github.com/adap/flower/pull/1257), " -"[#1267](https://github.com/adap/flower/pull/1267), " -"[#1268](https://github.com/adap/flower/pull/1268), " -"[#1300](https://github.com/adap/flower/pull/1300), " -"[#1304](https://github.com/adap/flower/pull/1304), " -"[#1305](https://github.com/adap/flower/pull/1305), " -"[#1307](https://github.com/adap/flower/pull/1307))" -msgstr "" +"**Update documentation** ([#1223](https://github.com/adap/flower/pull/1223), " +"[#1209](https://github.com/adap/flower/pull/1209), [#1251](https://github." +"com/adap/flower/pull/1251), [#1257](https://github.com/adap/flower/" +"pull/1257), [#1267](https://github.com/adap/flower/pull/1267), [#1268]" +"(https://github.com/adap/flower/pull/1268), [#1300](https://github.com/adap/" +"flower/pull/1300), [#1304](https://github.com/adap/flower/pull/1304), [#1305]" +"(https://github.com/adap/flower/pull/1305), [#1307](https://github.com/adap/" +"flower/pull/1307))" +msgstr "" +"**更新文档** ([#1223](https://github.com/adap/flower/pull/1223), [#1209]" +"(https://github.com/adap/flower/pull/1209), [#1251](https://github.com/adap/" +"flower/pull/1251), [#1257](https://github.com/adap/flower/pull/1257), [#1267]" +"(https://github.com/adap/flower/pull/1267), [#1268](https://github.com/adap/" +"flower/pull/1268), [#1300](https://github.com/adap/flower/pull/1300), [#1304]" +"(https://github.com/adap/flower/pull/1304), [#1305](https://github.com/adap/" +"flower/pull/1305), [#1307](https://github.com/adap/flower/pull/1307))" #: ../../source/ref-changelog.md:518 msgid "" "One substantial documentation update fixes multiple smaller rendering " "issues, makes titles more succinct to improve navigation, removes a " -"deprecated library, updates documentation dependencies, includes the " -"`flwr.common` module in the API reference, includes support for markdown-" -"based documentation, migrates the changelog from `.rst` to `.md`, and " -"fixes a number of smaller details!" +"deprecated library, updates documentation dependencies, includes the `flwr." +"common` module in the API reference, includes support for markdown-based " +"documentation, migrates the changelog from `.rst` to `.md`, and fixes a " +"number of smaller details!" msgstr "" +"其中一个实质性的文档更新修复了多个较小的渲染问题,使标题更加简洁以改善导航," +"删除了一个已废弃的库,更新了文档依赖关系,在 API 参考中包含了 `flwr.common` " +"模块,包含了对基于 markdown 的文档的支持,将更新日志从 `.rst` 移植到了 `." +"md`,并修复了一些较小的细节!" #: ../../source/ref-changelog.md:520 ../../source/ref-changelog.md:575 #: ../../source/ref-changelog.md:644 ../../source/ref-changelog.md:683 msgid "**Minor updates**" -msgstr "" +msgstr "**小规模更新**" #: ../../source/ref-changelog.md:522 msgid "" -"Add round number to fit and evaluate log messages " -"([#1266](https://github.com/adap/flower/pull/1266))" +"Add round number to fit and evaluate log messages ([#1266](https://github." +"com/adap/flower/pull/1266))" msgstr "" +"添加四舍五入数字,以适应和评估日志信息([#1266](https://github.com/adap/" +"flower/pull/1266))" #: ../../source/ref-changelog.md:523 msgid "" -"Add secure gRPC connection to the `advanced_tensorflow` code example " -"([#847](https://github.com/adap/flower/pull/847))" +"Add secure gRPC connection to the `advanced_tensorflow` code example ([#847]" +"(https://github.com/adap/flower/pull/847))" msgstr "" +"为 `advanced_tensorflow` 代码示例添加安全 gRPC 连接 ([#847](https://github." +"com/adap/flower/pull/847))" #: ../../source/ref-changelog.md:524 msgid "" -"Update developer tooling " -"([#1231](https://github.com/adap/flower/pull/1231), " -"[#1276](https://github.com/adap/flower/pull/1276), " -"[#1301](https://github.com/adap/flower/pull/1301), " -"[#1310](https://github.com/adap/flower/pull/1310))" +"Update developer tooling ([#1231](https://github.com/adap/flower/pull/1231), " +"[#1276](https://github.com/adap/flower/pull/1276), [#1301](https://github." +"com/adap/flower/pull/1301), [#1310](https://github.com/adap/flower/" +"pull/1310))" msgstr "" +"更新开发人员工具([#1231](https://github.com/adap/flower/pull/1231), [#1276]" +"(https://github.com/adap/flower/pull/1276), [#1301](https://github.com/adap/" +"flower/pull/1301), [#1310](https://github.com/adap/flower/pull/1310)" #: ../../source/ref-changelog.md:525 msgid "" -"Rename ProtoBuf messages to improve consistency " -"([#1214](https://github.com/adap/flower/pull/1214), " -"[#1258](https://github.com/adap/flower/pull/1258), " +"Rename ProtoBuf messages to improve consistency ([#1214](https://github.com/" +"adap/flower/pull/1214), [#1258](https://github.com/adap/flower/pull/1258), " "[#1259](https://github.com/adap/flower/pull/1259))" msgstr "" +"重命名 ProtoBuf 消息以提高一致性([#1214](https://github.com/adap/flower/" +"pull/1214), [#1258](https://github.com/adap/flower/pull/1258), [#1259]" +"(https://github.com/adap/flower/pull/1259)" #: ../../source/ref-changelog.md:527 msgid "v0.19.0 (2022-05-18)" @@ -8908,236 +10466,301 @@ msgstr "" #: ../../source/ref-changelog.md:531 msgid "" -"**Flower Baselines (preview): FedOpt, FedBN, FedAvgM** " -"([#919](https://github.com/adap/flower/pull/919), " -"[#1127](https://github.com/adap/flower/pull/1127), " -"[#914](https://github.com/adap/flower/pull/914))" +"**Flower Baselines (preview): FedOpt, FedBN, FedAvgM** ([#919](https://" +"github.com/adap/flower/pull/919), [#1127](https://github.com/adap/flower/" +"pull/1127), [#914](https://github.com/adap/flower/pull/914))" msgstr "" +"**Flower 基准(预览): FedOpt、FedBN、FedAvgM** ([#919](https://github.com/" +"adap/flower/pull/919), [#1127](https://github.com/adap/flower/pull/1127), " +"[#914](https://github.com/adap/flower/pull/914))" #: ../../source/ref-changelog.md:533 msgid "" "The first preview release of Flower Baselines has arrived! We're " "kickstarting Flower Baselines with implementations of FedOpt (FedYogi, " -"FedAdam, FedAdagrad), FedBN, and FedAvgM. Check the documentation on how " -"to use [Flower Baselines](https://flower.dev/docs/using-baselines.html). " -"With this first preview release we're also inviting the community to " -"[contribute their own baselines](https://flower.dev/docs/contributing-" -"baselines.html)." +"FedAdam, FedAdagrad), FedBN, and FedAvgM. Check the documentation on how to " +"use [Flower Baselines](https://flower.dev/docs/using-baselines.html). With " +"this first preview release we're also inviting the community to [contribute " +"their own baselines](https://flower.dev/docs/contributing-baselines.html)." msgstr "" +"Flower Baselines 的第一个预览版已经发布!我们通过实现 FedOpt(FedYogi、" +"FedAdam、FedAdagrad)、FedBN 和 FedAvgM 来启动 Flower Baselines。请查阅文档了" +"解如何使用 [Flower Baselines](https://flower.dev/docs/using-baselines.html)。" +"在首次发布预览版时,我们还邀请社区成员[贡献自己的基准](https://flower.dev/" +"docs/contributing-baselines.html)。" #: ../../source/ref-changelog.md:535 msgid "" -"**C++ client SDK (preview) and code example** " -"([#1111](https://github.com/adap/flower/pull/1111))" +"**C++ client SDK (preview) and code example** ([#1111](https://github.com/" +"adap/flower/pull/1111))" msgstr "" +"**C++客户端SDK(预览版)和代码示例**([#1111](https://github.com/adap/flower/" +"pull/1111))" #: ../../source/ref-changelog.md:537 msgid "" -"Preview support for Flower clients written in C++. The C++ preview " -"includes a Flower client SDK and a quickstart code example that " -"demonstrates a simple C++ client using the SDK." +"Preview support for Flower clients written in C++. The C++ preview includes " +"a Flower client SDK and a quickstart code example that demonstrates a simple " +"C++ client using the SDK." msgstr "" +"预览版支持用 C++ 编写的 Flower 客户端。C++ 预览版包括一个 Flower 客户端 SDK " +"和一个快速入门代码示例,使用 SDK 演示了一个简单的 C++ 客户端。" #: ../../source/ref-changelog.md:539 msgid "" -"**Add experimental support for Python 3.10 and Python 3.11** " -"([#1135](https://github.com/adap/flower/pull/1135))" +"**Add experimental support for Python 3.10 and Python 3.11** ([#1135]" +"(https://github.com/adap/flower/pull/1135))" msgstr "" +"** 增加对 Python 3.10 和 Python 3.11 的实验支持** ([#1135](https://github." +"com/adap/flower/pull/1135))" #: ../../source/ref-changelog.md:541 msgid "" -"Python 3.10 is the latest stable release of Python and Python 3.11 is due" -" to be released in October. This Flower release adds experimental support" -" for both Python versions." +"Python 3.10 is the latest stable release of Python and Python 3.11 is due to " +"be released in October. This Flower release adds experimental support for " +"both Python versions." msgstr "" +"Python 3.10 是 Python 的最新稳定版本,Python 3.11 将于 10 月份发布。Flower 版" +"本增加了对这两个 Python 版本的实验支持。" #: ../../source/ref-changelog.md:543 msgid "" -"**Aggregate custom metrics through user-provided functions** " -"([#1144](https://github.com/adap/flower/pull/1144))" +"**Aggregate custom metrics through user-provided functions** ([#1144]" +"(https://github.com/adap/flower/pull/1144))" msgstr "" +"**通过用户提供的函数聚合自定义指标**([#1144](https://github.com/adap/flower/" +"pull/1144))" #: ../../source/ref-changelog.md:545 msgid "" -"Custom metrics (e.g., `accuracy`) can now be aggregated without having to" -" customize the strategy. Built-in strategies support two new arguments, " +"Custom metrics (e.g., `accuracy`) can now be aggregated without having to " +"customize the strategy. Built-in strategies support two new arguments, " "`fit_metrics_aggregation_fn` and `evaluate_metrics_aggregation_fn`, that " "allow passing custom metric aggregation functions." msgstr "" +"现在无需定制策略即可聚合自定义度量(如`准确度`)。内置策略支持两个新参数:" +"`fit_metrics_aggregation_fn` 和`evaluate_metrics_aggregation_fn`,允许传递自" +"定义度量聚合函数。" #: ../../source/ref-changelog.md:547 msgid "" -"**User-configurable round timeout** " -"([#1162](https://github.com/adap/flower/pull/1162))" +"**User-configurable round timeout** ([#1162](https://github.com/adap/flower/" +"pull/1162))" msgstr "" +"**用户可配置的回合超时**([#1162](https://github.com/adap/flower/pull/1162))" #: ../../source/ref-changelog.md:549 msgid "" "A new configuration value allows the round timeout to be set for " -"`start_server` and `start_simulation`. If the `config` dictionary " -"contains a `round_timeout` key (with a `float` value in seconds), the " -"server will wait *at least* `round_timeout` seconds before it closes the " -"connection." +"`start_server` and `start_simulation`. If the `config` dictionary contains a " +"`round_timeout` key (with a `float` value in seconds), the server will wait " +"*at least* `round_timeout` seconds before it closes the connection." msgstr "" +"新的配置值允许为 `start_server` 和 `start_simulation` 设置回合超时。如果 " +"`config` 字典中包含一个 `round_timeout` 键(以秒为单位的 `float`值),服务器" +"将至少等待 ** `round_timeout` 秒后才关闭连接。" #: ../../source/ref-changelog.md:551 msgid "" -"**Enable both federated evaluation and centralized evaluation to be used " -"at the same time in all built-in strategies** " -"([#1091](https://github.com/adap/flower/pull/1091))" +"**Enable both federated evaluation and centralized evaluation to be used at " +"the same time in all built-in strategies** ([#1091](https://github.com/adap/" +"flower/pull/1091))" msgstr "" +"**允许在所有内置策略中同时使用联合评价和集中评价** ([#1091](https://github." +"com/adap/flower/pull/1091))" #: ../../source/ref-changelog.md:553 msgid "" -"Built-in strategies can now perform both federated evaluation (i.e., " -"client-side) and centralized evaluation (i.e., server-side) in the same " -"round. Federated evaluation can be disabled by setting `fraction_eval` to" -" `0.0`." +"Built-in strategies can now perform both federated evaluation (i.e., client-" +"side) and centralized evaluation (i.e., server-side) in the same round. " +"Federated evaluation can be disabled by setting `fraction_eval` to `0.0`." msgstr "" +"内置策略现在可以在同一轮中同时执行联合评估(即客户端)和集中评估(即服务器" +"端)。可以通过将 `fraction_eval` 设置为 `0.0`来禁用联合评估。" #: ../../source/ref-changelog.md:555 msgid "" -"**Two new Jupyter Notebook tutorials** " -"([#1141](https://github.com/adap/flower/pull/1141))" +"**Two new Jupyter Notebook tutorials** ([#1141](https://github.com/adap/" +"flower/pull/1141))" msgstr "" +"**两本新的 Jupyter Notebook 教程** ([#1141](https://github.com/adap/flower/" +"pull/1141))" #: ../../source/ref-changelog.md:557 msgid "" -"Two Jupyter Notebook tutorials (compatible with Google Colab) explain " -"basic and intermediate Flower features:" +"Two Jupyter Notebook tutorials (compatible with Google Colab) explain basic " +"and intermediate Flower features:" msgstr "" +"两本 Jupyter Notebook 教程(与 Google Colab 兼容)介绍了 Flower 的基本和中级" +"功能:" #: ../../source/ref-changelog.md:559 msgid "" -"*An Introduction to Federated Learning*: [Open in " -"Colab](https://colab.research.google.com/github/adap/flower/blob/main/tutorials/Flower-1" -"-Intro-to-FL-PyTorch.ipynb)" +"*An Introduction to Federated Learning*: [Open in Colab](https://colab." +"research.google.com/github/adap/flower/blob/main/tutorials/Flower-1-Intro-to-" +"FL-PyTorch.ipynb)" msgstr "" +"*联邦学习简介*: [在 Colab 中打开](https://colab.research.google.com/github/" +"adap/flower/blob/main/tutorials/Flower-1-Intro-to-FL-PyTorch.ipynb)" #: ../../source/ref-changelog.md:561 msgid "" -"*Using Strategies in Federated Learning*: [Open in " -"Colab](https://colab.research.google.com/github/adap/flower/blob/main/tutorials/Flower-2" -"-Strategies-in-FL-PyTorch.ipynb)" +"*Using Strategies in Federated Learning*: [Open in Colab](https://colab." +"research.google.com/github/adap/flower/blob/main/tutorials/Flower-2-" +"Strategies-in-FL-PyTorch.ipynb)" msgstr "" +"*在联合学习中使用策略*: [在 Colab 中打开](https://colab.research.google.com/" +"github/adap/flower/blob/main/tutorials/Flower-2-Strategies-in-FL-PyTorch." +"ipynb)" #: ../../source/ref-changelog.md:563 msgid "" -"**New FedAvgM strategy (Federated Averaging with Server Momentum)** " -"([#1076](https://github.com/adap/flower/pull/1076))" +"**New FedAvgM strategy (Federated Averaging with Server Momentum)** ([#1076]" +"(https://github.com/adap/flower/pull/1076))" msgstr "" +"**新的 FedAvgM 策略(带服务器动量的联合平均)** ([#1076](https://github.com/" +"adap/flower/pull/1076))" #: ../../source/ref-changelog.md:565 msgid "" "The new `FedAvgM` strategy implements Federated Averaging with Server " "Momentum \\[Hsu et al., 2019\\]." -msgstr "" +msgstr "新的 \"FedAvgM \"策略实现了带服务器动量的联合平均[Hsu et al., 2019\\]." #: ../../source/ref-changelog.md:567 msgid "" -"**New advanced PyTorch code example** " -"([#1007](https://github.com/adap/flower/pull/1007))" +"**New advanced PyTorch code example** ([#1007](https://github.com/adap/" +"flower/pull/1007))" msgstr "" +"**新的 PyTorch 高级代码示例** ([#1007](https://github.com/adap/flower/" +"pull/1007))" #: ../../source/ref-changelog.md:569 msgid "" "A new code example (`advanced_pytorch`) demonstrates advanced Flower " "concepts with PyTorch." -msgstr "" +msgstr "新代码示例 (`advanced_pytorch`) 演示了 PyTorch 的高级 Flower 概念。" #: ../../source/ref-changelog.md:571 msgid "" -"**New JAX code example** " -"([#906](https://github.com/adap/flower/pull/906), " +"**New JAX code example** ([#906](https://github.com/adap/flower/pull/906), " "[#1143](https://github.com/adap/flower/pull/1143))" msgstr "" +"**新的 JAX 代码示例**([#906](https://github.com/adap/flower/pull/906), " +"[#1143](https://github.com/adap/flower/pull/1143)" #: ../../source/ref-changelog.md:573 msgid "" "A new code example (`jax_from_centralized_to_federated`) shows federated " "learning with JAX and Flower." msgstr "" +"新代码示例(`jax_from_centralized_to_federated`)展示了使用 JAX 和 Flower 的" +"联邦学习。" #: ../../source/ref-changelog.md:577 msgid "" "New option to keep Ray running if Ray was already initialized in " "`start_simulation` ([#1177](https://github.com/adap/flower/pull/1177))" msgstr "" +"新增选项,用于在 \"start_simulation\"(开始模拟)中已初始化 Ray 的情况下保持 " +"Ray 运行([#1177](https://github.com/adap/flower/pull/1177))" #: ../../source/ref-changelog.md:578 msgid "" "Add support for custom `ClientManager` as a `start_simulation` parameter " "([#1171](https://github.com/adap/flower/pull/1171))" msgstr "" +"添加对自定义 \"客户端管理器 \"作为 \"start_simulation \"参数的支持([#1171]" +"(https://github.com/adap/flower/pull/1171))" #: ../../source/ref-changelog.md:579 msgid "" -"New documentation for [implementing " -"strategies](https://flower.dev/docs/framework/how-to-implement-" -"strategies.html) ([#1097](https://github.com/adap/flower/pull/1097), " -"[#1175](https://github.com/adap/flower/pull/1175))" +"New documentation for [implementing strategies](https://flower.dev/docs/" +"framework/how-to-implement-strategies.html) ([#1097](https://github.com/adap/" +"flower/pull/1097), [#1175](https://github.com/adap/flower/pull/1175))" msgstr "" +"实施战略](https://flower.dev/docs/framework/how-to-implement-strategies." +"html) 的新文件([#1097](https://github.com/adap/flower/pull/1097), [#1175]" +"(https://github.com/adap/flower/pull/1175)" #: ../../source/ref-changelog.md:580 msgid "" -"New mobile-friendly documentation theme " -"([#1174](https://github.com/adap/flower/pull/1174))" +"New mobile-friendly documentation theme ([#1174](https://github.com/adap/" +"flower/pull/1174))" msgstr "" +"新的移动友好型文档主题 ([#1174](https://github.com/adap/flower/pull/1174))" #: ../../source/ref-changelog.md:581 msgid "" "Limit version range for (optional) `ray` dependency to include only " -"compatible releases (`>=1.9.2,<1.12.0`) " -"([#1205](https://github.com/adap/flower/pull/1205))" +"compatible releases (`>=1.9.2,<1.12.0`) ([#1205](https://github.com/adap/" +"flower/pull/1205))" msgstr "" +"限制(可选)\"ray \"依赖的版本范围,使其仅包含兼容版本(`>=1.9.2,<1.12.0`) " +"([#1205](https://github.com/adap/flower/pull/1205))" #: ../../source/ref-changelog.md:585 msgid "" -"**Remove deprecated support for Python 3.6** " -"([#871](https://github.com/adap/flower/pull/871))" +"**Remove deprecated support for Python 3.6** ([#871](https://github.com/adap/" +"flower/pull/871))" msgstr "" +"**删除对 Python 3.6 的过时支持** ([#871](https://github.com/adap/flower/" +"pull/871))" #: ../../source/ref-changelog.md:586 msgid "" -"**Remove deprecated KerasClient** " -"([#857](https://github.com/adap/flower/pull/857))" +"**Remove deprecated KerasClient** ([#857](https://github.com/adap/flower/" +"pull/857))" msgstr "" +"**移除过时的 KerasClient**([#857](https://github.com/adap/flower/pull/857))" #: ../../source/ref-changelog.md:587 msgid "" -"**Remove deprecated no-op extra installs** " -"([#973](https://github.com/adap/flower/pull/973))" +"**Remove deprecated no-op extra installs** ([#973](https://github.com/adap/" +"flower/pull/973))" msgstr "" +"**移除过时的不操作额外安装** ([#973](https://github.com/adap/flower/" +"pull/973))" #: ../../source/ref-changelog.md:588 msgid "" "**Remove deprecated proto fields from** `FitRes` **and** `EvaluateRes` " "([#869](https://github.com/adap/flower/pull/869))" msgstr "" +"**从** `FitRes` **和** `EvaluateRes` 中移除已废弃的 proto 字段 ([#869]" +"(https://github.com/adap/flower/pull/869))" #: ../../source/ref-changelog.md:589 msgid "" -"**Remove deprecated QffedAvg strategy (replaced by QFedAvg)** " -"([#1107](https://github.com/adap/flower/pull/1107))" +"**Remove deprecated QffedAvg strategy (replaced by QFedAvg)** ([#1107]" +"(https://github.com/adap/flower/pull/1107))" msgstr "" +"**移除过时的 QffedAvg 策略(由 QFedAvg 取代)** ([#1107](https://github.com/" +"adap/flower/pull/1107))" #: ../../source/ref-changelog.md:590 msgid "" -"**Remove deprecated DefaultStrategy strategy** " -"([#1142](https://github.com/adap/flower/pull/1142))" +"**Remove deprecated DefaultStrategy strategy** ([#1142](https://github.com/" +"adap/flower/pull/1142))" msgstr "" +"**删除过时的 DefaultStrategy 策略** ([#1142](https://github.com/adap/flower/" +"pull/1142))" #: ../../source/ref-changelog.md:591 msgid "" -"**Remove deprecated support for eval_fn accuracy return value** " -"([#1142](https://github.com/adap/flower/pull/1142))" +"**Remove deprecated support for eval_fn accuracy return value** ([#1142]" +"(https://github.com/adap/flower/pull/1142))" msgstr "" +"**删除已过时的对 eval_fn 返回值准确性的支持** ([#1142](https://github.com/" +"adap/flower/pull/1142))" #: ../../source/ref-changelog.md:592 msgid "" "**Remove deprecated support for passing initial parameters as NumPy " "ndarrays** ([#1142](https://github.com/adap/flower/pull/1142))" msgstr "" +"**移除对以 NumPy ndarrays 传递初始参数的过时支持** ([#1142](https://github." +"com/adap/flower/pull/1142))" #: ../../source/ref-changelog.md:594 msgid "v0.18.0 (2022-02-28)" @@ -9146,157 +10769,199 @@ msgstr "" #: ../../source/ref-changelog.md:598 msgid "" "**Improved Virtual Client Engine compatibility with Jupyter Notebook / " -"Google Colab** ([#866](https://github.com/adap/flower/pull/866), " -"[#872](https://github.com/adap/flower/pull/872), " -"[#833](https://github.com/adap/flower/pull/833), " -"[#1036](https://github.com/adap/flower/pull/1036))" +"Google Colab** ([#866](https://github.com/adap/flower/pull/866), [#872]" +"(https://github.com/adap/flower/pull/872), [#833](https://github.com/adap/" +"flower/pull/833), [#1036](https://github.com/adap/flower/pull/1036))" msgstr "" +"**改进了虚拟客户端引擎与 Jupyter Notebook / Google Colab 的兼容性** ([#866]" +"(https://github.com/adap/flower/pull/866), [#872](https://github.com/adap/" +"flower/pull/872), [#833](https://github.com/adap/flower/pull/833), [#1036]" +"(https://github.com/adap/flower/pull/1036))" #: ../../source/ref-changelog.md:600 msgid "" -"Simulations (using the Virtual Client Engine through `start_simulation`) " -"now work more smoothly on Jupyter Notebooks (incl. Google Colab) after " +"Simulations (using the Virtual Client Engine through `start_simulation`) now " +"work more smoothly on Jupyter Notebooks (incl. Google Colab) after " "installing Flower with the `simulation` extra (`pip install " "flwr[simulation]`)." msgstr "" +"通过 `start_simulation` 在 Jupyter 笔记本(包括 Google Colab)上安装 Flower " +"并附加 `simulation` (`pip install flwr[simulation]`)后,模拟(通过 " +"`start_simulation` 使用虚拟客户端引擎)现在可以更流畅地运行。" #: ../../source/ref-changelog.md:602 msgid "" -"**New Jupyter Notebook code example** " -"([#833](https://github.com/adap/flower/pull/833))" +"**New Jupyter Notebook code example** ([#833](https://github.com/adap/flower/" +"pull/833))" msgstr "" +"**新的 Jupyter Notebook 代码示例** ([#833](https://github.com/adap/flower/" +"pull/833))" #: ../../source/ref-changelog.md:604 msgid "" -"A new code example (`quickstart_simulation`) demonstrates Flower " -"simulations using the Virtual Client Engine through Jupyter Notebook " -"(incl. Google Colab)." +"A new code example (`quickstart_simulation`) demonstrates Flower simulations " +"using the Virtual Client Engine through Jupyter Notebook (incl. Google " +"Colab)." msgstr "" +"新代码示例(`quickstart_simulation`)通过 Jupyter Notebook(包括 Google " +"Colab)演示了使用虚拟客户端引擎进行 Flower 模拟。" #: ../../source/ref-changelog.md:606 msgid "" -"**Client properties (feature preview)** " -"([#795](https://github.com/adap/flower/pull/795))" +"**Client properties (feature preview)** ([#795](https://github.com/adap/" +"flower/pull/795))" msgstr "" +"**客户端属性(功能预览)** ([#795](https://github.com/adap/flower/pull/795))" #: ../../source/ref-changelog.md:608 msgid "" -"Clients can implement a new method `get_properties` to enable server-side" -" strategies to query client properties." +"Clients can implement a new method `get_properties` to enable server-side " +"strategies to query client properties." msgstr "" +"客户端可以实现一个新方法 `get_properties`,以启用服务器端策略来查询客户端属" +"性。" #: ../../source/ref-changelog.md:610 msgid "" -"**Experimental Android support with TFLite** " -"([#865](https://github.com/adap/flower/pull/865))" +"**Experimental Android support with TFLite** ([#865](https://github.com/adap/" +"flower/pull/865))" msgstr "" +"** 使用 TFLite 实验性支持安卓系统** ([#865](https://github.com/adap/flower/" +"pull/865))" #: ../../source/ref-changelog.md:612 msgid "" "Android support has finally arrived in `main`! Flower is both client-" "agnostic and framework-agnostic by design. One can integrate arbitrary " -"client platforms and with this release, using Flower on Android has " -"become a lot easier." +"client platforms and with this release, using Flower on Android has become a " +"lot easier." msgstr "" +"主 \"终于支持 Android 了!Flower 的设计与客户端和框架无关。我们可以集成任意客" +"户端平台,有了这个版本,在安卓系统上使用 Flower 就变得更容易了。" #: ../../source/ref-changelog.md:614 msgid "" -"The example uses TFLite on the client side, along with a new " -"`FedAvgAndroid` strategy. The Android client and `FedAvgAndroid` are " -"still experimental, but they are a first step towards a fully-fledged " -"Android SDK and a unified `FedAvg` implementation that integrated the new" -" functionality from `FedAvgAndroid`." +"The example uses TFLite on the client side, along with a new `FedAvgAndroid` " +"strategy. The Android client and `FedAvgAndroid` are still experimental, but " +"they are a first step towards a fully-fledged Android SDK and a unified " +"`FedAvg` implementation that integrated the new functionality from " +"`FedAvgAndroid`." msgstr "" +"该示例在客户端使用了 TFLite 以及新的 `FedAvgAndroid`策略。Android 客户端和 " +"`FedAvgAndroid`仍处于试验阶段,但这是向成熟的 Android SDK 和集成了 " +"`FedAvgAndroid`新功能的统一 `FedAvg`实现迈出的第一步。" #: ../../source/ref-changelog.md:616 msgid "" -"**Make gRPC keepalive time user-configurable and decrease default " -"keepalive time** ([#1069](https://github.com/adap/flower/pull/1069))" +"**Make gRPC keepalive time user-configurable and decrease default keepalive " +"time** ([#1069](https://github.com/adap/flower/pull/1069))" msgstr "" +"**使 gRPC 保持连接时间可由用户配置,并缩短默认保持连接时间** ([#1069]" +"(https://github.com/adap/flower/pull/1069))" #: ../../source/ref-changelog.md:618 msgid "" "The default gRPC keepalive time has been reduced to increase the " -"compatibility of Flower with more cloud environments (for example, " -"Microsoft Azure). Users can configure the keepalive time to customize the" -" gRPC stack based on specific requirements." +"compatibility of Flower with more cloud environments (for example, Microsoft " +"Azure). Users can configure the keepalive time to customize the gRPC stack " +"based on specific requirements." msgstr "" +"为提高 Flower 与更多云环境(如 Microsoft Azure)的兼容性,缩短了默认 gRPC 保" +"持时间。用户可以根据具体要求配置 keepalive 时间,自定义 gRPC 堆栈。" #: ../../source/ref-changelog.md:620 msgid "" -"**New differential privacy example using Opacus and PyTorch** " -"([#805](https://github.com/adap/flower/pull/805))" +"**New differential privacy example using Opacus and PyTorch** ([#805]" +"(https://github.com/adap/flower/pull/805))" msgstr "" +"**使用 Opacus 和 PyTorch 的新差分隐私示例** ([#805](https://github.com/adap/" +"flower/pull/805))" #: ../../source/ref-changelog.md:622 msgid "" -"A new code example (`opacus`) demonstrates differentially-private " -"federated learning with Opacus, PyTorch, and Flower." +"A new code example (`opacus`) demonstrates differentially-private federated " +"learning with Opacus, PyTorch, and Flower." msgstr "" +"一个新的代码示例(\"opacus\")演示了使用 Opacus、PyTorch 和 Flower 进行差异化" +"私有联合学习。" #: ../../source/ref-changelog.md:624 msgid "" -"**New Hugging Face Transformers code example** " -"([#863](https://github.com/adap/flower/pull/863))" +"**New Hugging Face Transformers code example** ([#863](https://github.com/" +"adap/flower/pull/863))" msgstr "" +"**新的抱脸变形金刚代码示例** ([#863](https://github.com/adap/flower/" +"pull/863))" #: ../../source/ref-changelog.md:626 msgid "" -"A new code example (`quickstart_huggingface`) demonstrates usage of " -"Hugging Face Transformers with Flower." +"A new code example (`quickstart_huggingface`) demonstrates usage of Hugging " +"Face Transformers with Flower." msgstr "" #: ../../source/ref-changelog.md:628 msgid "" -"**New MLCube code example** " -"([#779](https://github.com/adap/flower/pull/779), " -"[#1034](https://github.com/adap/flower/pull/1034), " -"[#1065](https://github.com/adap/flower/pull/1065), " -"[#1090](https://github.com/adap/flower/pull/1090))" +"**New MLCube code example** ([#779](https://github.com/adap/flower/" +"pull/779), [#1034](https://github.com/adap/flower/pull/1034), [#1065]" +"(https://github.com/adap/flower/pull/1065), [#1090](https://github.com/adap/" +"flower/pull/1090))" msgstr "" +"**新的 MLCube 代码示例** ([#779](https://github.com/adap/flower/pull/779), " +"[#1034](https://github.com/adap/flower/pull/1034), [#1065](https://github." +"com/adap/flower/pull/1065), [#1090](https://github.com/adap/flower/" +"pull/1090))" #: ../../source/ref-changelog.md:630 msgid "" -"A new code example (`quickstart_mlcube`) demonstrates usage of MLCube " -"with Flower." -msgstr "" +"A new code example (`quickstart_mlcube`) demonstrates usage of MLCube with " +"Flower." +msgstr "新代码示例(\"quickstart_mlcube\")演示了 MLCube 与 Flower 的用法。" #: ../../source/ref-changelog.md:632 msgid "" -"**SSL-enabled server and client** " -"([#842](https://github.com/adap/flower/pull/842), " -"[#844](https://github.com/adap/flower/pull/844), " -"[#845](https://github.com/adap/flower/pull/845), " -"[#847](https://github.com/adap/flower/pull/847), " -"[#993](https://github.com/adap/flower/pull/993), " -"[#994](https://github.com/adap/flower/pull/994))" +"**SSL-enabled server and client** ([#842](https://github.com/adap/flower/" +"pull/842), [#844](https://github.com/adap/flower/pull/844), [#845](https://" +"github.com/adap/flower/pull/845), [#847](https://github.com/adap/flower/" +"pull/847), [#993](https://github.com/adap/flower/pull/993), [#994](https://" +"github.com/adap/flower/pull/994))" msgstr "" +"** 支持 SSL 的服务器和客户端** ([#842](https://github.com/adap/flower/" +"pull/842), [#844](https://github.com/adap/flower/pull/844), [#845](https://" +"github.com/adap/flower/pull/845), [#847](https://github.com/adap/flower/" +"pull/847), [#993](https://github.com/adap/flower/pull/993), [#994](https://" +"github.com/adap/flower/pull/994))" #: ../../source/ref-changelog.md:634 msgid "" -"SSL enables secure encrypted connections between clients and servers. " -"This release open-sources the Flower secure gRPC implementation to make " -"encrypted communication channels accessible to all Flower users." +"SSL enables secure encrypted connections between clients and servers. This " +"release open-sources the Flower secure gRPC implementation to make encrypted " +"communication channels accessible to all Flower users." msgstr "" +"SSL 可实现客户端与服务器之间的安全加密连接。该版本开源了 Flower 安全 gRPC 实" +"现,使所有 Flower 用户都能访问加密通信通道。" #: ../../source/ref-changelog.md:636 msgid "" -"**Updated** `FedAdam` **and** `FedYogi` **strategies** " -"([#885](https://github.com/adap/flower/pull/885), " -"[#895](https://github.com/adap/flower/pull/895))" +"**Updated** `FedAdam` **and** `FedYogi` **strategies** ([#885](https://" +"github.com/adap/flower/pull/885), [#895](https://github.com/adap/flower/" +"pull/895))" msgstr "" +"**更新**`FedAdam`**和**`FedYogi`**战略** ([#885](https://github.com/adap/" +"flower/pull/885), [#895](https://github.com/adap/flower/pull/895))" #: ../../source/ref-changelog.md:638 msgid "" -"`FedAdam` and `FedAdam` match the latest version of the Adaptive " -"Federated Optimization paper." -msgstr "" +"`FedAdam` and `FedAdam` match the latest version of the Adaptive Federated " +"Optimization paper." +msgstr "FedAdam \"和 \"FedAdam \"与最新版本的 \"自适应联合优化 \"论文相匹配。" #: ../../source/ref-changelog.md:640 msgid "" -"**Initialize** `start_simulation` **with a list of client IDs** " -"([#860](https://github.com/adap/flower/pull/860))" +"**Initialize** `start_simulation` **with a list of client IDs** ([#860]" +"(https://github.com/adap/flower/pull/860))" msgstr "" +"**初始化** `start_simulation` **使用客户端 ID 列表** ([#860](https://github." +"com/adap/flower/pull/860))" #: ../../source/ref-changelog.md:642 msgid "" @@ -9306,225 +10971,288 @@ msgid "" "easier to load data partitions that are not accessible through `int` " "identifiers." msgstr "" +"现在可以使用客户端 ID 列表(`clients_ids`,类型:`List[str]`)调用 " +"`start_simulation`。每当需要初始化客户端时,这些 ID 就会被传递到 `client_fn` " +"中,这样就能更轻松地加载无法通过 `int` 标识符访问的数据分区。" #: ../../source/ref-changelog.md:646 msgid "" -"Update `num_examples` calculation in PyTorch code examples in " -"([#909](https://github.com/adap/flower/pull/909))" +"Update `num_examples` calculation in PyTorch code examples in ([#909]" +"(https://github.com/adap/flower/pull/909))" msgstr "" +"更新 PyTorch 代码示例中的 \"num_examples \"计算 ([#909](https://github.com/" +"adap/flower/pull/909))" #: ../../source/ref-changelog.md:647 msgid "" -"Expose Flower version through `flwr.__version__` " -"([#952](https://github.com/adap/flower/pull/952))" +"Expose Flower version through `flwr.__version__` ([#952](https://github.com/" +"adap/flower/pull/952))" msgstr "" +"通过 `flwr.__version__` 公开 Flower 版本 ([#952](https://github.com/adap/" +"flower/pull/952))" #: ../../source/ref-changelog.md:648 msgid "" -"`start_server` in `app.py` now returns a `History` object containing " -"metrics from training ([#974](https://github.com/adap/flower/pull/974))" +"`start_server` in `app.py` now returns a `History` object containing metrics " +"from training ([#974](https://github.com/adap/flower/pull/974))" msgstr "" +"app.py \"中的 \"start_server \"现在会返回一个 \"History \"对象,其中包含训练" +"中的指标([#974](https://github.com/adap/flower/pull/974))" #: ../../source/ref-changelog.md:649 msgid "" -"Make `max_workers` (used by `ThreadPoolExecutor`) configurable " -"([#978](https://github.com/adap/flower/pull/978))" +"Make `max_workers` (used by `ThreadPoolExecutor`) configurable ([#978]" +"(https://github.com/adap/flower/pull/978))" msgstr "" +"使 \"max_workers\"(由 \"ThreadPoolExecutor \"使用)可配置([#978](https://" +"github.com/adap/flower/pull/978))" #: ../../source/ref-changelog.md:650 msgid "" -"Increase sleep time after server start to three seconds in all code " -"examples ([#1086](https://github.com/adap/flower/pull/1086))" +"Increase sleep time after server start to three seconds in all code examples " +"([#1086](https://github.com/adap/flower/pull/1086))" msgstr "" +"在所有代码示例中,将服务器启动后的休眠时间延长至三秒([#1086](https://github." +"com/adap/flower/pull/1086))" #: ../../source/ref-changelog.md:651 msgid "" -"Added a new FAQ section to the documentation " -"([#948](https://github.com/adap/flower/pull/948))" +"Added a new FAQ section to the documentation ([#948](https://github.com/adap/" +"flower/pull/948))" msgstr "" +"在文档中添加了新的常见问题部分 ([#948](https://github.com/adap/flower/" +"pull/948))" #: ../../source/ref-changelog.md:652 msgid "" "And many more under-the-hood changes, library updates, documentation " "changes, and tooling improvements!" -msgstr "" +msgstr "还有更多底层更改、库更新、文档更改和工具改进!" #: ../../source/ref-changelog.md:656 msgid "" "**Removed** `flwr_example` **and** `flwr_experimental` **from release " "build** ([#869](https://github.com/adap/flower/pull/869))" msgstr "" +"**从发布版中删除**`flwr_example`**和**`flwr_experimental`** ([#869](https://" +"github.com/adap/flower/pull/869))" #: ../../source/ref-changelog.md:658 msgid "" "The packages `flwr_example` and `flwr_experimental` have been deprecated " "since Flower 0.12.0 and they are not longer included in Flower release " "builds. The associated extras (`baseline`, `examples-pytorch`, `examples-" -"tensorflow`, `http-logger`, `ops`) are now no-op and will be removed in " -"an upcoming release." +"tensorflow`, `http-logger`, `ops`) are now no-op and will be removed in an " +"upcoming release." msgstr "" +"自 Flower 0.12.0 起,软件包 `flwr_example` 和 `flwr_experimental` 已被弃用," +"它们不再包含在 Flower 的发布版本中。相关的额外包(`baseline`, `examples-" +"pytorch`, `examples-tensorflow`, `http-logger`, `ops`)现在已不再使用,并将在" +"即将发布的版本中移除。" #: ../../source/ref-changelog.md:660 msgid "v0.17.0 (2021-09-24)" -msgstr "" +msgstr "v0.17.0 (2021-09-24)" #: ../../source/ref-changelog.md:664 msgid "" -"**Experimental virtual client engine** " -"([#781](https://github.com/adap/flower/pull/781) " -"[#790](https://github.com/adap/flower/pull/790) " -"[#791](https://github.com/adap/flower/pull/791))" +"**Experimental virtual client engine** ([#781](https://github.com/adap/" +"flower/pull/781) [#790](https://github.com/adap/flower/pull/790) [#791]" +"(https://github.com/adap/flower/pull/791))" msgstr "" +"**实验性虚拟客户端引擎** ([#781](https://github.com/adap/flower/pull/781) " +"[#790](https://github.com/adap/flower/pull/790) [#791](https://github.com/" +"adap/flower/pull/791))" #: ../../source/ref-changelog.md:666 msgid "" -"One of Flower's goals is to enable research at scale. This release " -"enables a first (experimental) peek at a major new feature, codenamed the" -" virtual client engine. Virtual clients enable simulations that scale to " -"a (very) large number of clients on a single machine or compute cluster. " -"The easiest way to test the new functionality is to look at the two new " -"code examples called `quickstart_simulation` and `simulation_pytorch`." +"One of Flower's goals is to enable research at scale. This release enables a " +"first (experimental) peek at a major new feature, codenamed the virtual " +"client engine. Virtual clients enable simulations that scale to a (very) " +"large number of clients on a single machine or compute cluster. The easiest " +"way to test the new functionality is to look at the two new code examples " +"called `quickstart_simulation` and `simulation_pytorch`." msgstr "" +"Flower 的目标之一是实现大规模研究。这一版本首次(试验性地)展示了代号为 \"虚" +"拟客户端引擎 \"的重要新功能。虚拟客户端可以在单台机器或计算集群上对大量客户端" +"进行仿真。测试新功能的最简单方法是查看名为 \"quickstart_simulation \"和 " +"\"simulation_pytorch \"的两个新代码示例。" #: ../../source/ref-changelog.md:668 msgid "" -"The feature is still experimental, so there's no stability guarantee for " -"the API. It's also not quite ready for prime time and comes with a few " -"known caveats. However, those who are curious are encouraged to try it " -"out and share their thoughts." +"The feature is still experimental, so there's no stability guarantee for the " +"API. It's also not quite ready for prime time and comes with a few known " +"caveats. However, those who are curious are encouraged to try it out and " +"share their thoughts." msgstr "" +"该功能仍处于试验阶段,因此无法保证 API 的稳定性。此外,它还没有完全准备好进入" +"黄金时间,并有一些已知的注意事项。不过,我们鼓励好奇的用户尝试使用并分享他们" +"的想法。" #: ../../source/ref-changelog.md:670 msgid "" -"**New built-in strategies** " -"([#828](https://github.com/adap/flower/pull/828) " +"**New built-in strategies** ([#828](https://github.com/adap/flower/pull/828) " "[#822](https://github.com/adap/flower/pull/822))" msgstr "" +"**新的内置策略**([#828](https://github.com/adap/flower/pull/828) [#822]" +"(https://github.com/adap/flower/pull/822)" #: ../../source/ref-changelog.md:672 msgid "" "FedYogi - Federated learning strategy using Yogi on server-side. " "Implementation based on https://arxiv.org/abs/2003.00295" msgstr "" +"FedYogi - 在服务器端使用 Yogi 的联合学习策略。基于 https://arxiv.org/" +"abs/2003.00295 实现" #: ../../source/ref-changelog.md:673 msgid "" "FedAdam - Federated learning strategy using Adam on server-side. " "Implementation based on https://arxiv.org/abs/2003.00295" msgstr "" +"FedAdam - 在服务器端使用 Adam 的联邦学习策略。基于 https://arxiv.org/" +"abs/2003.00295 实现" #: ../../source/ref-changelog.md:675 msgid "" -"**New PyTorch Lightning code example** " -"([#617](https://github.com/adap/flower/pull/617))" +"**New PyTorch Lightning code example** ([#617](https://github.com/adap/" +"flower/pull/617))" msgstr "" +"**新的 PyTorch Lightning 代码示例** ([#617](https://github.com/adap/flower/" +"pull/617))" #: ../../source/ref-changelog.md:677 msgid "" -"**New Variational Auto-Encoder code example** " -"([#752](https://github.com/adap/flower/pull/752))" +"**New Variational Auto-Encoder code example** ([#752](https://github.com/" +"adap/flower/pull/752))" msgstr "" +"**新的变分自动编码器代码示例** ([#752](https://github.com/adap/flower/" +"pull/752))" #: ../../source/ref-changelog.md:679 msgid "" -"**New scikit-learn code example** " -"([#748](https://github.com/adap/flower/pull/748))" +"**New scikit-learn code example** ([#748](https://github.com/adap/flower/" +"pull/748))" msgstr "" +"**新的 scikit-learn 代码示例** ([#748](https://github.com/adap/flower/" +"pull/748))" #: ../../source/ref-changelog.md:681 msgid "" -"**New experimental TensorBoard strategy** " -"([#789](https://github.com/adap/flower/pull/789))" +"**New experimental TensorBoard strategy** ([#789](https://github.com/adap/" +"flower/pull/789))" msgstr "" +"**新的实验性 TensorBoard 策略**([#789](https://github.com/adap/flower/" +"pull/789))" #: ../../source/ref-changelog.md:685 msgid "" -"Improved advanced TensorFlow code example " -"([#769](https://github.com/adap/flower/pull/769))" +"Improved advanced TensorFlow code example ([#769](https://github.com/adap/" +"flower/pull/769))" msgstr "" +"改进的高级 TensorFlow 代码示例([#769](https://github.com/adap/flower/" +"pull/769)" #: ../../source/ref-changelog.md:686 msgid "" -"Warning when `min_available_clients` is misconfigured " -"([#830](https://github.com/adap/flower/pull/830))" +"Warning when `min_available_clients` is misconfigured ([#830](https://github." +"com/adap/flower/pull/830))" msgstr "" +"当 `min_available_clients` 配置错误时发出警告 ([#830](https://github.com/" +"adap/flower/pull/830))" #: ../../source/ref-changelog.md:687 msgid "" -"Improved gRPC server docs " -"([#841](https://github.com/adap/flower/pull/841))" +"Improved gRPC server docs ([#841](https://github.com/adap/flower/pull/841))" msgstr "" +"改进了 gRPC 服务器文档([#841](https://github.com/adap/flower/pull/841))" #: ../../source/ref-changelog.md:688 msgid "" -"Improved error message in `NumPyClient` " -"([#851](https://github.com/adap/flower/pull/851))" +"Improved error message in `NumPyClient` ([#851](https://github.com/adap/" +"flower/pull/851))" msgstr "" +"改进了 `NumPyClient` 中的错误信息 ([#851](https://github.com/adap/flower/" +"pull/851))" #: ../../source/ref-changelog.md:689 msgid "" -"Improved PyTorch quickstart code example " -"([#852](https://github.com/adap/flower/pull/852))" +"Improved PyTorch quickstart code example ([#852](https://github.com/adap/" +"flower/pull/852))" msgstr "" +"改进的 PyTorch 快速启动代码示例 ([#852](https://github.com/adap/flower/" +"pull/852))" #: ../../source/ref-changelog.md:693 msgid "" -"**Disabled final distributed evaluation** " -"([#800](https://github.com/adap/flower/pull/800))" +"**Disabled final distributed evaluation** ([#800](https://github.com/adap/" +"flower/pull/800))" msgstr "" +"**禁用最终分布式评价** ([#800](https://github.com/adap/flower/pull/800))" #: ../../source/ref-changelog.md:695 msgid "" -"Prior behaviour was to perform a final round of distributed evaluation on" -" all connected clients, which is often not required (e.g., when using " -"server-side evaluation). The prior behaviour can be enabled by passing " +"Prior behaviour was to perform a final round of distributed evaluation on " +"all connected clients, which is often not required (e.g., when using server-" +"side evaluation). The prior behaviour can be enabled by passing " "`force_final_distributed_eval=True` to `start_server`." msgstr "" +"之前的行为是在所有连接的客户端上执行最后一轮分布式评估,而这通常是不需要的" +"(例如,在使用服务器端评估时)。可以通过向 `start_server` 传递 " +"`force_final_distributed_eval=True` 来启用之前的行为。" #: ../../source/ref-changelog.md:697 msgid "" -"**Renamed q-FedAvg strategy** " -"([#802](https://github.com/adap/flower/pull/802))" +"**Renamed q-FedAvg strategy** ([#802](https://github.com/adap/flower/" +"pull/802))" msgstr "" +"**更名为 q-FedAvg 策略** ([#802](https://github.com/adap/flower/pull/802))" #: ../../source/ref-changelog.md:699 msgid "" -"The strategy named `QffedAvg` was renamed to `QFedAvg` to better reflect " -"the notation given in the original paper (q-FFL is the optimization " -"objective, q-FedAvg is the proposed solver). Note the the original (now " -"deprecated) `QffedAvg` class is still available for compatibility reasons" -" (it will be removed in a future release)." +"The strategy named `QffedAvg` was renamed to `QFedAvg` to better reflect the " +"notation given in the original paper (q-FFL is the optimization objective, q-" +"FedAvg is the proposed solver). Note the the original (now deprecated) " +"`QffedAvg` class is still available for compatibility reasons (it will be " +"removed in a future release)." msgstr "" +"名为 `QffedAvg` 的策略已更名为 `QFedAvg`,以更好地反映原始论文中给出的符号" +"(q-FFL 是优化目标,q-FedAvg 是建议的求解器)。请注意,出于兼容性原因,原始" +"(现已废弃)的 `QffedAvg` 类仍然可用(它将在未来的版本中移除)。" #: ../../source/ref-changelog.md:701 msgid "" "**Deprecated and renamed code example** `simulation_pytorch` **to** " -"`simulation_pytorch_legacy` " -"([#791](https://github.com/adap/flower/pull/791))" +"`simulation_pytorch_legacy` ([#791](https://github.com/adap/flower/pull/791))" msgstr "" +"**删除并重命名代码示例**`simulation_pytorch`**为" +"**`simulation_pytorch_legacy` ([#791](https://github.com/adap/flower/" +"pull/791))" #: ../../source/ref-changelog.md:703 msgid "" -"This example has been replaced by a new example. The new example is based" -" on the experimental virtual client engine, which will become the new " -"default way of doing most types of large-scale simulations in Flower. The" -" existing example was kept for reference purposes, but it might be " -"removed in the future." +"This example has been replaced by a new example. The new example is based on " +"the experimental virtual client engine, which will become the new default " +"way of doing most types of large-scale simulations in Flower. The existing " +"example was kept for reference purposes, but it might be removed in the " +"future." msgstr "" +"该示例已被新示例取代。新示例基于试验性虚拟客户端引擎,它将成为在 Flower 中进" +"行大多数类型大规模模拟的新的默认方式。现有示例将作为参考保留,但将来可能会删" +"除。" #: ../../source/ref-changelog.md:705 msgid "v0.16.0 (2021-05-11)" -msgstr "" +msgstr "v0.16.0 (2021-05-11)" #: ../../source/ref-changelog.md:709 msgid "" -"**New built-in strategies** " -"([#549](https://github.com/adap/flower/pull/549))" -msgstr "" +"**New built-in strategies** ([#549](https://github.com/adap/flower/pull/549))" +msgstr "**新的内置策略** ([#549](https://github.com/adap/flower/pull/549))" #: ../../source/ref-changelog.md:711 msgid "(abstract) FedOpt" -msgstr "" +msgstr "(摘要) FedOpt" #: ../../source/ref-changelog.md:712 msgid "FedAdagrad" @@ -9532,9 +11260,11 @@ msgstr "" #: ../../source/ref-changelog.md:714 msgid "" -"**Custom metrics for server and strategies** " -"([#717](https://github.com/adap/flower/pull/717))" +"**Custom metrics for server and strategies** ([#717](https://github.com/adap/" +"flower/pull/717))" msgstr "" +"**服务器和策略的自定义指标** ([#717](https://github.com/adap/flower/" +"pull/717))" #: ../../source/ref-changelog.md:716 msgid "" @@ -9544,109 +11274,135 @@ msgid "" "dictionary containing custom metrics from client to server. As of this " "release, custom metrics replace task-specific metrics on the server." msgstr "" +"Flower 服务器现在完全与任务无关,所有剩余的任务特定度量(如 \"准确度\")都已" +"被自定义度量字典取代。Flower 0.15 引入了从客户端向服务器传递包含自定义指标的" +"字典的功能。从本版本开始,自定义指标将取代服务器上的特定任务指标。" #: ../../source/ref-changelog.md:718 msgid "" -"Custom metric dictionaries are now used in two user-facing APIs: they are" -" returned from Strategy methods `aggregate_fit`/`aggregate_evaluate` and " -"they enable evaluation functions passed to build-in strategies (via " -"`eval_fn`) to return more than two evaluation metrics. Strategies can " -"even return *aggregated* metrics dictionaries for the server to keep " -"track of." +"Custom metric dictionaries are now used in two user-facing APIs: they are " +"returned from Strategy methods `aggregate_fit`/`aggregate_evaluate` and they " +"enable evaluation functions passed to build-in strategies (via `eval_fn`) to " +"return more than two evaluation metrics. Strategies can even return " +"*aggregated* metrics dictionaries for the server to keep track of." msgstr "" +"自定义度量字典现在可在两个面向用户的 API 中使用:它们可从策略方法 " +"`aggregate_fit`/`aggregate_evaluate` 返回,还可使传递给内置策略(通过 " +"`eval_fn`)的评估函数返回两个以上的评估度量。策略甚至可以返回 *aggregated* 指" +"标字典,以便服务器跟踪。" #: ../../source/ref-changelog.md:720 msgid "" "Stratey implementations should migrate their `aggregate_fit` and " "`aggregate_evaluate` methods to the new return type (e.g., by simply " -"returning an empty `{}`), server-side evaluation functions should migrate" -" from `return loss, accuracy` to `return loss, {\"accuracy\": accuracy}`." +"returning an empty `{}`), server-side evaluation functions should migrate " +"from `return loss, accuracy` to `return loss, {\"accuracy\": accuracy}`." msgstr "" +"Stratey 实现应将其 `aggregate_fit` 和 `aggregate_evaluate` 方法迁移到新的返回" +"类型(例如,只需返回空的 `{}`),服务器端评估函数应从 `return loss, " +"accuracy` 迁移到 `return loss, {\"accuracy\": accuracy}`。" #: ../../source/ref-changelog.md:722 msgid "" "Flower 0.15-style return types are deprecated (but still supported), " "compatibility will be removed in a future release." msgstr "" +"Flower 0.15 风格的返回类型已被弃用(但仍受支持),兼容性将在未来的版本中移" +"除。" #: ../../source/ref-changelog.md:724 msgid "" -"**Migration warnings for deprecated functionality** " -"([#690](https://github.com/adap/flower/pull/690))" +"**Migration warnings for deprecated functionality** ([#690](https://github." +"com/adap/flower/pull/690))" msgstr "" +"** 过时功能的迁移警告** ([#690](https://github.com/adap/flower/pull/690))" #: ../../source/ref-changelog.md:726 msgid "" "Earlier versions of Flower were often migrated to new APIs, while " -"maintaining compatibility with legacy APIs. This release introduces " -"detailed warning messages if usage of deprecated APIs is detected. The " -"new warning messages often provide details on how to migrate to more " -"recent APIs, thus easing the transition from one release to another." +"maintaining compatibility with legacy APIs. This release introduces detailed " +"warning messages if usage of deprecated APIs is detected. The new warning " +"messages often provide details on how to migrate to more recent APIs, thus " +"easing the transition from one release to another." msgstr "" +"Flower 早期版本通常会迁移到新的应用程序接口,同时保持与旧版应用程序接口的兼" +"容。如果检测到使用了过时的 API,本版本将引入详细的警告信息。新的警告信息通常" +"会详细说明如何迁移到更新的 API,从而简化从一个版本到另一个版本的过渡。" #: ../../source/ref-changelog.md:728 msgid "" -"Improved docs and docstrings " -"([#691](https://github.com/adap/flower/pull/691) " -"[#692](https://github.com/adap/flower/pull/692) " -"[#713](https://github.com/adap/flower/pull/713))" +"Improved docs and docstrings ([#691](https://github.com/adap/flower/" +"pull/691) [#692](https://github.com/adap/flower/pull/692) [#713](https://" +"github.com/adap/flower/pull/713))" msgstr "" +"改进了文档和文档说明 ([#691](https://github.com/adap/flower/pull/691) [#692]" +"(https://github.com/adap/flower/pull/692) [#713](https://github.com/adap/" +"flower/pull/713))" #: ../../source/ref-changelog.md:730 msgid "MXNet example and documentation" -msgstr "" +msgstr "MXNet 示例和文档" #: ../../source/ref-changelog.md:732 msgid "" "FedBN implementation in example PyTorch: From Centralized To Federated " -"([#696](https://github.com/adap/flower/pull/696) " -"[#702](https://github.com/adap/flower/pull/702) " -"[#705](https://github.com/adap/flower/pull/705))" +"([#696](https://github.com/adap/flower/pull/696) [#702](https://github.com/" +"adap/flower/pull/702) [#705](https://github.com/adap/flower/pull/705))" msgstr "" +"PyTorch 示例中的 FedBN 实现: 从集中到联合 ([#696](https://github.com/adap/" +"flower/pull/696) [#702](https://github.com/adap/flower/pull/702) [#705]" +"(https://github.com/adap/flower/pull/705))" #: ../../source/ref-changelog.md:736 msgid "" -"**Serialization-agnostic server** " -"([#721](https://github.com/adap/flower/pull/721))" -msgstr "" +"**Serialization-agnostic server** ([#721](https://github.com/adap/flower/" +"pull/721))" +msgstr "**序列化无关服务器** ([#721](https://github.com/adap/flower/pull/721))" #: ../../source/ref-changelog.md:738 msgid "" -"The Flower server is now fully serialization-agnostic. Prior usage of " -"class `Weights` (which represents parameters as deserialized NumPy " -"ndarrays) was replaced by class `Parameters` (e.g., in `Strategy`). " -"`Parameters` objects are fully serialization-agnostic and represents " -"parameters as byte arrays, the `tensor_type` attributes indicates how " -"these byte arrays should be interpreted (e.g., for " -"serialization/deserialization)." +"The Flower server is now fully serialization-agnostic. Prior usage of class " +"`Weights` (which represents parameters as deserialized NumPy ndarrays) was " +"replaced by class `Parameters` (e.g., in `Strategy`). `Parameters` objects " +"are fully serialization-agnostic and represents parameters as byte arrays, " +"the `tensor_type` attributes indicates how these byte arrays should be " +"interpreted (e.g., for serialization/deserialization)." msgstr "" +"Flower 服务器现在完全不依赖序列化。之前使用的 `Weights` 类(以反序列化的 " +"NumPy ndarrays 表示参数)已被 `Parameters` 类取代(例如在 `Strategy`中)。参" +"数 \"对象与序列化完全无关,它以字节数组的形式表示参数,\"tensor_type \"属性表" +"示如何解释这些字节数组(例如,用于序列化/反序列化)。" #: ../../source/ref-changelog.md:740 msgid "" -"Built-in strategies implement this approach by handling serialization and" -" deserialization to/from `Weights` internally. Custom/3rd-party Strategy " +"Built-in strategies implement this approach by handling serialization and " +"deserialization to/from `Weights` internally. Custom/3rd-party Strategy " "implementations should update to the slighly changed Strategy method " -"definitions. Strategy authors can consult PR " -"[#721](https://github.com/adap/flower/pull/721) to see how strategies can" -" easily migrate to the new format." +"definitions. Strategy authors can consult PR [#721](https://github.com/adap/" +"flower/pull/721) to see how strategies can easily migrate to the new format." msgstr "" +"内置策略通过在内部处理序列化和反序列化到/从 \"权重 \"来实现这种方法。自定义/" +"第三方策略实现应更新为稍有改动的策略方法定义。策略作者可查阅 PR [#721]" +"(https://github.com/adap/flower/pull/721) 以了解如何将策略轻松迁移到新格式。" #: ../../source/ref-changelog.md:742 msgid "" -"Deprecated `flwr.server.Server.evaluate`, use " -"`flwr.server.Server.evaluate_round` instead " -"([#717](https://github.com/adap/flower/pull/717))" +"Deprecated `flwr.server.Server.evaluate`, use `flwr.server.Server." +"evaluate_round` instead ([#717](https://github.com/adap/flower/pull/717))" msgstr "" +"已弃用 `flwr.server.Server.evaluate`,改用 `flwr.server.Server." +"evaluate_round`([#717](https://github.com/adap/flower/pull/717)" #: ../../source/ref-changelog.md:744 msgid "v0.15.0 (2021-03-12)" -msgstr "" +msgstr "v0.15.0 (2021-03-12)" #: ../../source/ref-changelog.md:748 msgid "" -"**Server-side parameter initialization** " -"([#658](https://github.com/adap/flower/pull/658))" +"**Server-side parameter initialization** ([#658](https://github.com/adap/" +"flower/pull/658))" msgstr "" +"**服务器端参数初始化** ([#658](https://github.com/adap/flower/pull/658))" #: ../../source/ref-changelog.md:750 msgid "" @@ -9654,14 +11410,18 @@ msgid "" "parameter initialization works via a new `Strategy` method called " "`initialize_parameters`." msgstr "" +"现在可以在服务器端初始化模型参数。服务器端参数初始化通过名为 " +"\"initialize_parameters \"的新 \"Strategy \"方法进行。" #: ../../source/ref-changelog.md:752 msgid "" "Built-in strategies support a new constructor argument called " -"`initial_parameters` to set the initial parameters. Built-in strategies " -"will provide these initial parameters to the server on startup and then " -"delete them to free the memory afterwards." +"`initial_parameters` to set the initial parameters. Built-in strategies will " +"provide these initial parameters to the server on startup and then delete " +"them to free the memory afterwards." msgstr "" +"内置策略支持名为 \"initial_parameters \"的新构造函数参数,用于设置初始参数。" +"内置策略会在启动时向服务器提供这些初始参数,然后删除它们以释放内存。" #: ../../source/ref-changelog.md:771 msgid "" @@ -9670,133 +11430,163 @@ msgid "" "connected clients for its parameters and use these as the initial global " "parameters)." msgstr "" +"如果没有向策略提供初始参数,服务器将继续使用当前行为(即向其中一个已连接的客" +"户端询问参数,并将这些参数用作初始全局参数)。" #: ../../source/ref-changelog.md:773 msgid "Deprecations" -msgstr "" +msgstr "停用" #: ../../source/ref-changelog.md:775 msgid "" -"Deprecate `flwr.server.strategy.DefaultStrategy` (migrate to " -"`flwr.server.strategy.FedAvg`, which is equivalent)" +"Deprecate `flwr.server.strategy.DefaultStrategy` (migrate to `flwr.server." +"strategy.FedAvg`, which is equivalent)" msgstr "" +"停用 `flwr.server.strategy.DefaultStrategy`(迁移到等价的 `flwr.server." +"strategy.FedAvg`)" #: ../../source/ref-changelog.md:777 msgid "v0.14.0 (2021-02-18)" -msgstr "" +msgstr "v0.14.0 (2021-02-18)" #: ../../source/ref-changelog.md:781 msgid "" "**Generalized** `Client.fit` **and** `Client.evaluate` **return values** " -"([#610](https://github.com/adap/flower/pull/610) " -"[#572](https://github.com/adap/flower/pull/572) " -"[#633](https://github.com/adap/flower/pull/633))" +"([#610](https://github.com/adap/flower/pull/610) [#572](https://github.com/" +"adap/flower/pull/572) [#633](https://github.com/adap/flower/pull/633))" msgstr "" +"**通用** `Client.fit` **和** `Client.evaluate` **返回值** ([#610](https://" +"github.com/adap/flower/pull/610) [#572](https://github.com/adap/flower/" +"pull/572) [#633](https://github.com/adap/flower/pull/633))" #: ../../source/ref-changelog.md:783 msgid "" -"Clients can now return an additional dictionary mapping `str` keys to " -"values of the following types: `bool`, `bytes`, `float`, `int`, `str`. " -"This means one can return almost arbitrary values from `fit`/`evaluate` " -"and make use of them on the server side!" +"Clients can now return an additional dictionary mapping `str` keys to values " +"of the following types: `bool`, `bytes`, `float`, `int`, `str`. This means " +"one can return almost arbitrary values from `fit`/`evaluate` and make use of " +"them on the server side!" msgstr "" +"客户端现在可以返回一个额外的字典,将 `str` 键映射为以下类型的值: bool`、" +"`bytes`、`float`、`int`、`str`。这意味着我们可以从 `fit`/`evaluate` 返回几乎" +"任意的值,并在服务器端使用它们!" #: ../../source/ref-changelog.md:785 msgid "" -"This improvement also allowed for more consistent return types between " -"`fit` and `evaluate`: `evaluate` should now return a tuple `(float, int, " -"dict)` representing the loss, number of examples, and a dictionary " -"holding arbitrary problem-specific values like accuracy." +"This improvement also allowed for more consistent return types between `fit` " +"and `evaluate`: `evaluate` should now return a tuple `(float, int, dict)` " +"representing the loss, number of examples, and a dictionary holding " +"arbitrary problem-specific values like accuracy." msgstr "" +"这一改进还使 `fit` 和 `evaluate` 之间的返回类型更加一致:`evaluate` 现在应返" +"回一个元组`(float, int, dict)`,代表损失、示例数和一个包含特定问题任意值(如" +"准确度)的字典。" #: ../../source/ref-changelog.md:787 msgid "" -"In case you wondered: this feature is compatible with existing projects, " -"the additional dictionary return value is optional. New code should " -"however migrate to the new return types to be compatible with upcoming " -"Flower releases (`fit`: `List[np.ndarray], int, Dict[str, Scalar]`, " -"`evaluate`: `float, int, Dict[str, Scalar]`). See the example below for " -"details." +"In case you wondered: this feature is compatible with existing projects, the " +"additional dictionary return value is optional. New code should however " +"migrate to the new return types to be compatible with upcoming Flower " +"releases (`fit`: `List[np.ndarray], int, Dict[str, Scalar]`, `evaluate`: " +"`float, int, Dict[str, Scalar]`). See the example below for details." msgstr "" +"如果你想知道:此功能与现有项目兼容,额外的字典返回值是可选的。不过,新代码应" +"迁移到新的返回类型,以便与即将发布的 Flower 版本兼容(`fit`: `List[np." +"ndarray], int, Dict[str, Scalar]`,`evaluate`: `float, int, Dict[str, " +"Scalar]`)。详见下面的示例。" #: ../../source/ref-changelog.md:789 msgid "" "*Code example:* note the additional dictionary return values in both " "`FlwrClient.fit` and `FlwrClient.evaluate`:" msgstr "" +"*代码示例:* 注意 `FlwrClient.fit` 和 `FlwrClient.evaluate` 中的附加字典返回" +"值:" #: ../../source/ref-changelog.md:804 msgid "" -"**Generalized** `config` **argument in** `Client.fit` **and** " -"`Client.evaluate` ([#595](https://github.com/adap/flower/pull/595))" +"**Generalized** `config` **argument in** `Client.fit` **and** `Client." +"evaluate` ([#595](https://github.com/adap/flower/pull/595))" msgstr "" +"**在**`Client.fit` **和**`Client.evaluate`中泛化**`config`参数([#595]" +"(https://github.com/adap/flower/pull/595))" #: ../../source/ref-changelog.md:806 msgid "" -"The `config` argument used to be of type `Dict[str, str]`, which means " -"that dictionary values were expected to be strings. The new release " -"generalizes this to enable values of the following types: `bool`, " -"`bytes`, `float`, `int`, `str`." +"The `config` argument used to be of type `Dict[str, str]`, which means that " +"dictionary values were expected to be strings. The new release generalizes " +"this to enable values of the following types: `bool`, `bytes`, `float`, " +"`int`, `str`." msgstr "" +"配置 \"参数曾是 \"字典[str, str]\"类型,这意味着字典值应是字符串。新版本将其" +"扩展为以下类型的值: bool`、`bytes`、`float`、`int`、`str`。" #: ../../source/ref-changelog.md:808 msgid "" "This means one can now pass almost arbitrary values to `fit`/`evaluate` " -"using the `config` dictionary. Yay, no more `str(epochs)` on the server-" -"side and `int(config[\"epochs\"])` on the client side!" +"using the `config` dictionary. Yay, no more `str(epochs)` on the server-side " +"and `int(config[\"epochs\"])` on the client side!" msgstr "" +"这意味着现在可以使用 `config` 字典向 `fit`/`evaluate` 传递几乎任意的值。耶," +"服务器端不再需要 `str(epochs)`,客户端不再需要 `int(config[\"epochs\"])`!" #: ../../source/ref-changelog.md:810 msgid "" "*Code example:* note that the `config` dictionary now contains non-`str` " "values in both `Client.fit` and `Client.evaluate`:" msgstr "" +"*代码示例:* 注意 `config` 字典现在在 `Client.fit` 和 `Client.evaluate` 中都" +"包含非 `str` 值:" #: ../../source/ref-changelog.md:827 msgid "v0.13.0 (2021-01-08)" -msgstr "" +msgstr "v0.13.0 (2021-01-08)" #: ../../source/ref-changelog.md:831 msgid "" -"New example: PyTorch From Centralized To Federated " -"([#549](https://github.com/adap/flower/pull/549))" +"New example: PyTorch From Centralized To Federated ([#549](https://github." +"com/adap/flower/pull/549))" msgstr "" +"新示例: PyTorch 从集中到联合 ([#549](https://github.com/adap/flower/" +"pull/549))" #: ../../source/ref-changelog.md:832 msgid "Improved documentation" -msgstr "" +msgstr "改进文件" #: ../../source/ref-changelog.md:833 -msgid "New documentation theme ([#551](https://github.com/adap/flower/pull/551))" -msgstr "" +msgid "" +"New documentation theme ([#551](https://github.com/adap/flower/pull/551))" +msgstr "新文档主题 ([#551](https://github.com/adap/flower/pull/551))" #: ../../source/ref-changelog.md:834 msgid "New API reference ([#554](https://github.com/adap/flower/pull/554))" -msgstr "" +msgstr "新的 API 参考 ([#554](https://github.com/adap/flower/pull/554))" #: ../../source/ref-changelog.md:835 msgid "" -"Updated examples documentation " -"([#549](https://github.com/adap/flower/pull/549))" -msgstr "" +"Updated examples documentation ([#549](https://github.com/adap/flower/" +"pull/549))" +msgstr "更新了示例文档 ([#549](https://github.com/adap/flower/pull/549))" #: ../../source/ref-changelog.md:836 msgid "" -"Removed obsolete documentation " -"([#548](https://github.com/adap/flower/pull/548))" -msgstr "" +"Removed obsolete documentation ([#548](https://github.com/adap/flower/" +"pull/548))" +msgstr "删除了过时的文档 ([#548](https://github.com/adap/flower/pull/548))" #: ../../source/ref-changelog.md:838 msgid "Bugfix:" -msgstr "" +msgstr "错误修正:" #: ../../source/ref-changelog.md:840 msgid "" -"`Server.fit` does not disconnect clients when finished, disconnecting the" -" clients is now handled in `flwr.server.start_server` " -"([#553](https://github.com/adap/flower/pull/553) " -"[#540](https://github.com/adap/flower/issues/540))." +"`Server.fit` does not disconnect clients when finished, disconnecting the " +"clients is now handled in `flwr.server.start_server` ([#553](https://github." +"com/adap/flower/pull/553) [#540](https://github.com/adap/flower/issues/540))." msgstr "" +"Server.fit \"完成后不会断开客户端连接,现在断开客户端连接是在 \"flwr.server." +"start_server \"中处理的([#553](https://github.com/adap/flower/pull/553) " +"[#540](https://github.com/adap/flower/issues/540))。" #: ../../source/ref-changelog.md:842 msgid "v0.12.0 (2020-12-07)" @@ -9804,526 +11594,607 @@ msgstr "" #: ../../source/ref-changelog.md:844 ../../source/ref-changelog.md:860 msgid "Important changes:" -msgstr "" +msgstr "重要变更:" #: ../../source/ref-changelog.md:846 msgid "" -"Added an example for embedded devices " -"([#507](https://github.com/adap/flower/pull/507))" -msgstr "" +"Added an example for embedded devices ([#507](https://github.com/adap/flower/" +"pull/507))" +msgstr "添加了嵌入式设备示例 ([#507](https://github.com/adap/flower/pull/507))" #: ../../source/ref-changelog.md:847 msgid "" -"Added a new NumPyClient (in addition to the existing KerasClient) " -"([#504](https://github.com/adap/flower/pull/504) " -"[#508](https://github.com/adap/flower/pull/508))" +"Added a new NumPyClient (in addition to the existing KerasClient) ([#504]" +"(https://github.com/adap/flower/pull/504) [#508](https://github.com/adap/" +"flower/pull/508))" msgstr "" +"添加了一个新的 NumPyClient(除现有的 KerasClient 之外)([#504](https://" +"github.com/adap/flower/pull/504) [#508](https://github.com/adap/flower/" +"pull/508)" #: ../../source/ref-changelog.md:848 msgid "" -"Deprecated `flwr_example` package and started to migrate examples into " -"the top-level `examples` directory " -"([#494](https://github.com/adap/flower/pull/494) " -"[#512](https://github.com/adap/flower/pull/512))" +"Deprecated `flwr_example` package and started to migrate examples into the " +"top-level `examples` directory ([#494](https://github.com/adap/flower/" +"pull/494) [#512](https://github.com/adap/flower/pull/512))" msgstr "" +"弃用 `flwr_example` 软件包,并开始将示例迁移到顶层的 `examples` 目录 ([#494]" +"(https://github.com/adap/flower/pull/494) [#512](https://github.com/adap/" +"flower/pull/512))" #: ../../source/ref-changelog.md:850 msgid "v0.11.0 (2020-11-30)" -msgstr "" +msgstr "v0.11.0 (2020-11-30)" #: ../../source/ref-changelog.md:852 msgid "Incompatible changes:" -msgstr "" +msgstr "不兼容的更改:" #: ../../source/ref-changelog.md:854 msgid "" -"Renamed strategy methods " -"([#486](https://github.com/adap/flower/pull/486)) to unify the naming of " -"Flower's public APIs. Other public methods/functions (e.g., every method " -"in `Client`, but also `Strategy.evaluate`) do not use the `on_` prefix, " -"which is why we're removing it from the four methods in Strategy. To " -"migrate rename the following `Strategy` methods accordingly:" +"Renamed strategy methods ([#486](https://github.com/adap/flower/pull/486)) " +"to unify the naming of Flower's public APIs. Other public methods/functions " +"(e.g., every method in `Client`, but also `Strategy.evaluate`) do not use " +"the `on_` prefix, which is why we're removing it from the four methods in " +"Strategy. To migrate rename the following `Strategy` methods accordingly:" msgstr "" +"重命名了策略方法([#486](https://github.com/adap/flower/pull/486)),以统一 " +"\"花朵 \"公共 API 的命名。其他公共方法/函数(例如 `Client` 中的每个方法,以" +"及 `Strategy.evaluate`)不使用 `on_` 前缀,这就是我们从 Strategy 中的四个方法" +"中移除它的原因。迁移时,请相应地重命名以下 `Strategy` 方法:" #: ../../source/ref-changelog.md:855 msgid "`on_configure_evaluate` => `configure_evaluate`" -msgstr "" +msgstr "`on_configure_evaluate` => `configure_evaluate`" #: ../../source/ref-changelog.md:856 msgid "`on_aggregate_evaluate` => `aggregate_evaluate`" -msgstr "" +msgstr "`on_aggregate_evaluate` => `aggregate_evaluate`" #: ../../source/ref-changelog.md:857 msgid "`on_configure_fit` => `configure_fit`" -msgstr "" +msgstr "`on_configure_fit` => `configure_fit`" #: ../../source/ref-changelog.md:858 msgid "`on_aggregate_fit` => `aggregate_fit`" -msgstr "" +msgstr "`on_aggregate_fit` => `aggregate_fit`" #: ../../source/ref-changelog.md:862 msgid "" -"Deprecated `DefaultStrategy` " -"([#479](https://github.com/adap/flower/pull/479)). To migrate use " -"`FedAvg` instead." +"Deprecated `DefaultStrategy` ([#479](https://github.com/adap/flower/" +"pull/479)). To migrate use `FedAvg` instead." msgstr "" +"已废弃的 `DefaultStrategy` ([#479](https://github.com/adap/flower/" +"pull/479)) 。迁移时请使用 `FedAvg`。" #: ../../source/ref-changelog.md:863 msgid "" -"Simplified examples and baselines " -"([#484](https://github.com/adap/flower/pull/484))." -msgstr "" +"Simplified examples and baselines ([#484](https://github.com/adap/flower/" +"pull/484))." +msgstr "简化示例和基线([#484](https://github.com/adap/flower/pull/484))。" #: ../../source/ref-changelog.md:864 msgid "" -"Removed presently unused `on_conclude_round` from strategy interface " -"([#483](https://github.com/adap/flower/pull/483))." +"Removed presently unused `on_conclude_round` from strategy interface ([#483]" +"(https://github.com/adap/flower/pull/483))." msgstr "" +"删除了策略界面中目前未使用的 \"on_conclude_round\"([#483](https://github." +"com/adap/flower/pull/483))。" #: ../../source/ref-changelog.md:865 msgid "" -"Set minimal Python version to 3.6.1 instead of 3.6.9 " -"([#471](https://github.com/adap/flower/pull/471))." +"Set minimal Python version to 3.6.1 instead of 3.6.9 ([#471](https://github." +"com/adap/flower/pull/471))." msgstr "" +"将最小 Python 版本设为 3.6.1,而不是 3.6.9 ([#471](https://github.com/adap/" +"flower/pull/471))." #: ../../source/ref-changelog.md:866 msgid "" -"Improved `Strategy` docstrings " -"([#470](https://github.com/adap/flower/pull/470))." +"Improved `Strategy` docstrings ([#470](https://github.com/adap/flower/" +"pull/470))." msgstr "" +"改进了 `Strategy` docstrings([#470](https://github.com/adap/flower/" +"pull/470))。" #: ../../source/ref-example-projects.rst:2 msgid "Example projects" -msgstr "" +msgstr "项目实例" #: ../../source/ref-example-projects.rst:4 msgid "" -"Flower comes with a number of usage examples. The examples demonstrate " -"how Flower can be used to federate different kinds of existing machine " -"learning pipelines, usually leveraging popular machine learning " -"frameworks such as `PyTorch `_ or `TensorFlow " -"`_." +"Flower comes with a number of usage examples. The examples demonstrate how " +"Flower can be used to federate different kinds of existing machine learning " +"pipelines, usually leveraging popular machine learning frameworks such as " +"`PyTorch `_ or `TensorFlow `_." msgstr "" +"Flower 附带了许多使用示例。这些示例演示了如何使用 Flower 联合不同类型的现有机" +"器学习管道,通常是利用流行的机器学习框架,如 `PyTorch `_ 或 `TensorFlow `_。" #: ../../source/ref-example-projects.rst:11 msgid "" "Flower usage examples used to be bundled with Flower in a package called " -"``flwr_example``. We are migrating those examples to standalone projects " -"to make them easier to use. All new examples are based in the directory " +"``flwr_example``. We are migrating those examples to standalone projects to " +"make them easier to use. All new examples are based in the directory " "`examples `_." msgstr "" +"Flower 的使用示例曾与 Flower 捆绑在一个名为 ``flwr_example`` 的软件包中。我们" +"正在将这些示例迁移到独立项目中,以使它们更易于使用。所有新示例都位于目录 " +"`examples `_。" #: ../../source/ref-example-projects.rst:16 msgid "The following examples are available as standalone projects." -msgstr "" +msgstr "以下示例可作为独立项目使用。" #: ../../source/ref-example-projects.rst:20 msgid "Quickstart TensorFlow/Keras" -msgstr "" +msgstr "快速入门 TensorFlow/Keras" #: ../../source/ref-example-projects.rst:22 msgid "" -"The TensorFlow/Keras quickstart example shows CIFAR-10 image " -"classification with MobileNetV2:" +"The TensorFlow/Keras quickstart example shows CIFAR-10 image classification " +"with MobileNetV2:" msgstr "" +"TensorFlow/Keras 快速入门示例展示了使用 MobileNetV2 进行的 CIFAR-10 图像分" +"类:" #: ../../source/ref-example-projects.rst:25 msgid "" -"`Quickstart TensorFlow (Code) " -"`_" +"`Quickstart TensorFlow (Code) `_" msgstr "" +"`Quickstart TensorFlow (Code) `_" #: ../../source/ref-example-projects.rst:26 msgid "" -"`Quickstart TensorFlow (Tutorial) `_" +"`Quickstart TensorFlow (Tutorial) `_" msgstr "" #: ../../source/ref-example-projects.rst:27 msgid "" -"`Quickstart TensorFlow (Blog Post) `_" +"`Quickstart TensorFlow (Blog Post) `_" msgstr "" #: ../../source/ref-example-projects.rst:31 #: ../../source/tutorial-quickstart-pytorch.rst:5 msgid "Quickstart PyTorch" -msgstr "" +msgstr "快速入门 PyTorch" #: ../../source/ref-example-projects.rst:33 msgid "" -"The PyTorch quickstart example shows CIFAR-10 image classification with a" -" simple Convolutional Neural Network:" +"The PyTorch quickstart example shows CIFAR-10 image classification with a " +"simple Convolutional Neural Network:" msgstr "" +"PyTorch 快速入门范例展示了使用简单卷积神经网络进行 CIFAR-10 图像分类的情况:" #: ../../source/ref-example-projects.rst:36 msgid "" -"`Quickstart PyTorch (Code) " -"`_" +"`Quickstart PyTorch (Code) `_" msgstr "" #: ../../source/ref-example-projects.rst:37 msgid "" -"`Quickstart PyTorch (Tutorial) `_" +"`Quickstart PyTorch (Tutorial) `_" msgstr "" #: ../../source/ref-example-projects.rst:41 msgid "PyTorch: From Centralized To Federated" -msgstr "" +msgstr "PyTorch: 从集中到联合" #: ../../source/ref-example-projects.rst:43 msgid "" "This example shows how a regular PyTorch project can be federated using " "Flower:" -msgstr "" +msgstr "本例展示了如何使用 Flower 联合一个普通的 PyTorch 项目:" #: ../../source/ref-example-projects.rst:45 msgid "" -"`PyTorch: From Centralized To Federated (Code) " -"`_" +"`PyTorch: From Centralized To Federated (Code) `_" msgstr "" +"PyTorch: 从集中到联合(代码) `_" #: ../../source/ref-example-projects.rst:46 msgid "" -"`PyTorch: From Centralized To Federated (Tutorial) " -"`_" +"`PyTorch: From Centralized To Federated (Tutorial) `_" msgstr "" +"PyTorch: 从集中到联合(教程) `_" #: ../../source/ref-example-projects.rst:50 msgid "Federated Learning on Raspberry Pi and Nvidia Jetson" -msgstr "" +msgstr "树莓派和 Nvidia Jetson 上的联合学习" #: ../../source/ref-example-projects.rst:52 msgid "" "This example shows how Flower can be used to build a federated learning " "system that run across Raspberry Pi and Nvidia Jetson:" msgstr "" +"本示例展示了如何利用 Flower 建立一个跨 Raspberry Pi 和 Nvidia Jetson 运行的联" +"合学习系统:" #: ../../source/ref-example-projects.rst:54 msgid "" -"`Federated Learning on Raspberry Pi and Nvidia Jetson (Code) " -"`_" +"`Federated Learning on Raspberry Pi and Nvidia Jetson (Code) `_" msgstr "" +"树莓派和 Nvidia Jetson 上的联合学习(代码) `_" #: ../../source/ref-example-projects.rst:55 msgid "" -"`Federated Learning on Raspberry Pi and Nvidia Jetson (Blog Post) " -"`_" +"`Federated Learning on Raspberry Pi and Nvidia Jetson (Blog Post) `_" msgstr "" +"树莓派和 Nvidia Jetson 上的联合学习(博文) `_" #: ../../source/ref-example-projects.rst:60 msgid "Legacy Examples (`flwr_example`)" -msgstr "" +msgstr "传统示例 (`flwr_example`)" #: ../../source/ref-example-projects.rst:63 msgid "" -"The useage examples in `flwr_example` are deprecated and will be removed " -"in the future. New examples are provided as standalone projects in " -"`examples `_." +"The useage examples in `flwr_example` are deprecated and will be removed in " +"the future. New examples are provided as standalone projects in `examples " +"`_." msgstr "" +"在 `flwr_example` 中的使用示例已被弃用,今后将被移除。新示例将作为独立项目在 " +"`examples `_ 中提供。" #: ../../source/ref-example-projects.rst:69 msgid "Extra Dependencies" -msgstr "" +msgstr "额外依赖" #: ../../source/ref-example-projects.rst:71 msgid "" -"The core Flower framework keeps a minimal set of dependencies. The " -"examples demonstrate Flower in the context of different machine learning " -"frameworks, so additional dependencies need to be installed before an " -"example can be run." +"The core Flower framework keeps a minimal set of dependencies. The examples " +"demonstrate Flower in the context of different machine learning frameworks, " +"so additional dependencies need to be installed before an example can be run." msgstr "" +"Flower 核心框架只保留了最低限度的依赖项。这些示例在不同机器学习框架的背景下演" +"示了 Flower,因此在运行示例之前需要安装额外的依赖项。" #: ../../source/ref-example-projects.rst:75 msgid "For PyTorch examples::" -msgstr "" +msgstr "PyTorch 示例::" #: ../../source/ref-example-projects.rst:79 msgid "For TensorFlow examples::" -msgstr "" +msgstr "TensorFlow 示例::" #: ../../source/ref-example-projects.rst:83 msgid "For both PyTorch and TensorFlow examples::" -msgstr "" +msgstr "PyTorch 和 TensorFlow 示例::" #: ../../source/ref-example-projects.rst:87 msgid "" "Please consult :code:`pyproject.toml` for a full list of possible extras " "(section :code:`[tool.poetry.extras]`)." msgstr "" +"请参阅 :code:`pyproject.toml`,了解可能的 extras 的完整列表(章节 :code:" +"`[tool.poems.extras]`)。" #: ../../source/ref-example-projects.rst:92 msgid "PyTorch Examples" -msgstr "" +msgstr "PyTorch 示例" #: ../../source/ref-example-projects.rst:94 msgid "" -"Our PyTorch examples are based on PyTorch 1.7. They should work with " -"other releases as well. So far, we provide the following examples." +"Our PyTorch examples are based on PyTorch 1.7. They should work with other " +"releases as well. So far, we provide the following examples." msgstr "" +"我们的 PyTorch 示例基于 PyTorch 1.7。它们应该也能在其他版本中使用。到目前为" +"止,我们提供了以下示例。" #: ../../source/ref-example-projects.rst:98 msgid "CIFAR-10 Image Classification" -msgstr "" +msgstr "CIFAR-10 图像分类" #: ../../source/ref-example-projects.rst:100 msgid "" -"`CIFAR-10 and CIFAR-100 `_ " -"are popular RGB image datasets. The Flower CIFAR-10 example uses PyTorch " -"to train a simple CNN classifier in a federated learning setup with two " -"clients." +"`CIFAR-10 and CIFAR-100 `_ are " +"popular RGB image datasets. The Flower CIFAR-10 example uses PyTorch to " +"train a simple CNN classifier in a federated learning setup with two clients." msgstr "" +"CIFAR-10 和 CIFAR-100 ``_ 是流行" +"的 RGB 图像数据集。Flower CIFAR-10 示例使用 PyTorch 在有两个客户端的联合学习" +"设置中训练一个简单的 CNN 分类器。" #: ../../source/ref-example-projects.rst:104 #: ../../source/ref-example-projects.rst:121 #: ../../source/ref-example-projects.rst:146 msgid "First, start a Flower server:" -msgstr "" +msgstr "首先,启动 Flower 服务器:" #: ../../source/ref-example-projects.rst:106 msgid "$ ./src/py/flwr_example/pytorch_cifar/run-server.sh" -msgstr "" +msgstr "$ ./src/py/flwr_example/pytorch_cifar/run-server.sh" #: ../../source/ref-example-projects.rst:108 #: ../../source/ref-example-projects.rst:125 #: ../../source/ref-example-projects.rst:150 msgid "Then, start the two clients in a new terminal window:" -msgstr "" +msgstr "然后,在新的终端窗口中启动两个客户端:" #: ../../source/ref-example-projects.rst:110 msgid "$ ./src/py/flwr_example/pytorch_cifar/run-clients.sh" -msgstr "" +msgstr "$ ./src/py/flwr_example/pytorch_cifar/run-clients.sh" #: ../../source/ref-example-projects.rst:112 msgid "For more details, see :code:`src/py/flwr_example/pytorch_cifar`." -msgstr "" +msgstr "更多详情,请参阅 :code:`src/py/flwr_example/pytorch_cifar`。" #: ../../source/ref-example-projects.rst:115 msgid "ImageNet-2012 Image Classification" -msgstr "" +msgstr "ImageNet-2012 图像分类" #: ../../source/ref-example-projects.rst:117 msgid "" -"`ImageNet-2012 `_ is one of the major computer" -" vision datasets. The Flower ImageNet example uses PyTorch to train a " +"`ImageNet-2012 `_ is one of the major computer " +"vision datasets. The Flower ImageNet example uses PyTorch to train a " "ResNet-18 classifier in a federated learning setup with ten clients." msgstr "" +"ImageNet-2012 `_ 是主要的计算机视觉数据集之一。" +"Flower ImageNet 示例使用 PyTorch 在有十个客户端的联合学习设置中训练 " +"ResNet-18 分类器。" #: ../../source/ref-example-projects.rst:123 msgid "$ ./src/py/flwr_example/pytorch_imagenet/run-server.sh" -msgstr "" +msgstr "$ ./src/py/flwr_example/pytorch_imagenet/run-server.sh" #: ../../source/ref-example-projects.rst:127 msgid "$ ./src/py/flwr_example/pytorch_imagenet/run-clients.sh" -msgstr "" +msgstr "$ ./src/py/flwr_example/pytorch_imagenet/run-clients.sh" #: ../../source/ref-example-projects.rst:129 msgid "For more details, see :code:`src/py/flwr_example/pytorch_imagenet`." -msgstr "" +msgstr "更多详情,请参阅 :code:`src/py/flwr_example/pytorch_imagenet`。" #: ../../source/ref-example-projects.rst:133 msgid "TensorFlow Examples" -msgstr "" +msgstr "TensorFlow 示例" #: ../../source/ref-example-projects.rst:135 msgid "" "Our TensorFlow examples are based on TensorFlow 2.0 or newer. So far, we " "provide the following examples." msgstr "" +"我们的 TensorFlow 示例基于 TensorFlow 2.0 或更新版本。到目前为止,我们提供了" +"以下示例。" #: ../../source/ref-example-projects.rst:139 msgid "Fashion-MNIST Image Classification" -msgstr "" +msgstr "时尚-MNIST 图像分类" #: ../../source/ref-example-projects.rst:141 msgid "" -"`Fashion-MNIST `_ is " -"often used as the \"Hello, world!\" of machine learning. We follow this " -"tradition and provide an example which samples random local datasets from" -" Fashion-MNIST and trains a simple image classification model over those " -"partitions." +"`Fashion-MNIST `_ is often " +"used as the \"Hello, world!\" of machine learning. We follow this tradition " +"and provide an example which samples random local datasets from Fashion-" +"MNIST and trains a simple image classification model over those partitions." msgstr "" +"`Fashion-MNIST `_ 经常被用" +"作机器学习的 \"你好,世界!\"。我们遵循这一传统,提供了一个从时尚-MNIST 中随" +"机抽样本地数据集的示例,并在这些分区上训练一个简单的图像分类模型。" #: ../../source/ref-example-projects.rst:148 msgid "$ ./src/py/flwr_example/tensorflow_fashion_mnist/run-server.sh" -msgstr "" +msgstr "$ ./src/py/flwr_example/tensorflow_fashion_mnist/run-server.sh" #: ../../source/ref-example-projects.rst:152 msgid "$ ./src/py/flwr_example/tensorflow_fashion_mnist/run-clients.sh" -msgstr "" +msgstr "$ ./src/py/flwr_example/tensorflow_fashion_mnist/run-clients.sh" #: ../../source/ref-example-projects.rst:154 msgid "" -"For more details, see " -":code:`src/py/flwr_example/tensorflow_fashion_mnist`." +"For more details, see :code:`src/py/flwr_example/tensorflow_fashion_mnist`." msgstr "" +"更多详情,请参阅 :code:`src/py/flwr_example/tensorflow_fashion_mnist`。" #: ../../source/ref-faq.rst:4 msgid "" "This page collects answers to commonly asked questions about Federated " "Learning with Flower." -msgstr "" +msgstr "本页收集了有关 \"Flower 联合学习 \"常见问题的答案。" #: ../../source/ref-faq.rst msgid ":fa:`eye,mr-1` Can Flower run on Juptyter Notebooks / Google Colab?" msgstr "" +":fa:`eye,mr-1` Flower 可以在 Juptyter Notebooks / Google Colab 上运行吗?" #: ../../source/ref-faq.rst:8 msgid "" -"Yes, it can! Flower even comes with a few under-the-hood optimizations to" -" make it work even better on Colab. Here's a quickstart example:" +"Yes, it can! Flower even comes with a few under-the-hood optimizations to " +"make it work even better on Colab. Here's a quickstart example:" msgstr "" +"是的,它可以!Flower 甚至还进行了一些底层优化,使其在 Colab 上运行得更好。下" +"面是一个快速启动示例:" #: ../../source/ref-faq.rst:10 msgid "" -"`Flower simulation PyTorch " -"`_" +"`Flower simulation PyTorch `_" msgstr "" +"`Flower 模拟 PyTorch `_" #: ../../source/ref-faq.rst:11 msgid "" -"`Flower simulation TensorFlow/Keras " -"`_" +"`Flower simulation TensorFlow/Keras `_" msgstr "" +"`Flower模拟TensorFlow/Keras `_" #: ../../source/ref-faq.rst msgid ":fa:`eye,mr-1` How can I run Federated Learning on a Raspberry Pi?" -msgstr "" +msgstr ":fa:`eye,mr-1` 如何在 Raspberry Pi 上运行联合学习?" #: ../../source/ref-faq.rst:15 msgid "" "Find the `blog post about federated learning on embedded device here " -"`_" -" and the corresponding `GitHub code example " -"`_." +"`_ " +"and the corresponding `GitHub code example `_." msgstr "" +"请点击此处查看有关嵌入式设备联合学习的 \"博文\"`_和" +"相应的 \"GitHub 代码示例\"`_。" #: ../../source/ref-faq.rst -msgid ":fa:`eye,mr-1` Does Flower support federated learning on Android devices?" -msgstr "" +msgid "" +":fa:`eye,mr-1` Does Flower support federated learning on Android devices?" +msgstr ":fa:`eye,mr-1` Flower 是否支持安卓设备上的联合学习?" #: ../../source/ref-faq.rst:19 msgid "" -"Yes, it does. Please take a look at our `blog post " -"`_ or check out the code examples:" +"Yes, it does. Please take a look at our `blog post `_ or " +"check out the code examples:" msgstr "" +"是的,确实如此。请查看我们的 \"博客文章 `_\" 或查看代码示例:" #: ../../source/ref-faq.rst:21 msgid "" -"`Android Kotlin example `_" +"`Android Kotlin example `_" msgstr "" +"`Android Kotlin 示例 `_" #: ../../source/ref-faq.rst:22 msgid "`Android Java example `_" -msgstr "" +msgstr "Android Java 示例 `_" #: ../../source/ref-faq.rst msgid ":fa:`eye,mr-1` Can I combine federated learning with blockchain?" -msgstr "" +msgstr ":fa:`eye,mr-1` 我可以将联合学习与区块链结合起来吗?" #: ../../source/ref-faq.rst:26 msgid "" "Yes, of course. A list of available examples using Flower within a " "blockchain environment is available here:" -msgstr "" +msgstr "当然可以。有关在区块链环境中使用 Flower 的可用示例列表,请点击此处:" #: ../../source/ref-faq.rst:28 msgid "" -"`Flower meets Nevermined GitHub Repository `_." +"`Flower meets Nevermined GitHub Repository `_." msgstr "" +"`Flower meets Nevermined GitHub Repository `_." #: ../../source/ref-faq.rst:29 msgid "" -"`Flower meets Nevermined YouTube video " -"`_." +"`Flower meets Nevermined YouTube video `_." msgstr "" #: ../../source/ref-faq.rst:30 msgid "" -"`Flower meets KOSMoS `_." +"`Flower meets KOSMoS `_." msgstr "" #: ../../source/ref-faq.rst:31 msgid "" "`Flower meets Talan blog post `_ ." +"learning-same-mask-different-faces-imen-ayari/?" +"trackingId=971oIlxLQ9%2BA9RB0IQ73XQ%3D%3D>`_ ." msgstr "" +"\"Flower 与 Talan 的邂逅 \"博文 `_ 。" #: ../../source/ref-faq.rst:32 msgid "" -"`Flower meets Talan GitHub Repository " -"`_ ." +"`Flower meets Talan GitHub Repository `_ ." msgstr "" #: ../../source/ref-telemetry.md:1 msgid "Telemetry" -msgstr "" +msgstr "遥测功能" #: ../../source/ref-telemetry.md:3 msgid "" -"The Flower open-source project collects **anonymous** usage metrics to " -"make well-informed decisions to improve Flower. Doing this enables the " -"Flower team to understand how Flower is used and what challenges users " -"might face." +"The Flower open-source project collects **anonymous** usage metrics to make " +"well-informed decisions to improve Flower. Doing this enables the Flower " +"team to understand how Flower is used and what challenges users might face." msgstr "" +"Flower 开源项目收集**匿名**使用指标,以便在充分知情的情况下做出改进 Flower 的" +"决定。这样做能让 Flower 团队了解 Flower 的使用情况以及用户可能面临的挑战。" #: ../../source/ref-telemetry.md:5 msgid "" -"**Flower is a friendly framework for collaborative AI and data science.**" -" Staying true to this statement, Flower makes it easy to disable " -"telemetry for users that do not want to share anonymous usage metrics." +"**Flower is a friendly framework for collaborative AI and data science.** " +"Staying true to this statement, Flower makes it easy to disable telemetry " +"for users that do not want to share anonymous usage metrics." msgstr "" +"**Flower 是一个用于协作式人工智能和数据科学的友好框架。** Flower 遵循这一声" +"明,让不想分享匿名使用指标的用户可以轻松禁用遥测技术。" #: ../../source/ref-telemetry.md:7 msgid "Principles" -msgstr "" +msgstr "原则" #: ../../source/ref-telemetry.md:9 -msgid "We follow strong principles guarding anonymous usage metrics collection:" -msgstr "" +msgid "" +"We follow strong principles guarding anonymous usage metrics collection:" +msgstr "我们遵循严格的匿名使用指标收集原则:" #: ../../source/ref-telemetry.md:11 msgid "" -"**Optional:** You will always be able to disable telemetry; read on to " -"learn “[How to opt-out](#how-to-opt-out)”." +"**Optional:** You will always be able to disable telemetry; read on to learn " +"“[How to opt-out](#how-to-opt-out)”." msgstr "" +"**可选:** 您始终可以禁用遥测功能;请继续阅读\"[如何退出](#how-to-opt-" +"out)\"。" #: ../../source/ref-telemetry.md:12 msgid "" -"**Anonymous:** The reported usage metrics are anonymous and do not " -"contain any personally identifiable information (PII). See “[Collected " -"metrics](#collected-metrics)” to understand what metrics are being " -"reported." +"**Anonymous:** The reported usage metrics are anonymous and do not contain " +"any personally identifiable information (PII). See “[Collected metrics]" +"(#collected-metrics)” to understand what metrics are being reported." msgstr "" +"**匿名:** 报告的使用指标是匿名的,不包含任何个人身份信息 (PII)。请参阅\"[收" +"集的指标](#collected-metrics) \"了解报告的指标。" #: ../../source/ref-telemetry.md:13 msgid "" "**Transparent:** You can easily inspect what anonymous metrics are being " -"reported; see the section “[How to inspect what is being reported](#how-" -"to-inspect-what-is-being-reported)”" +"reported; see the section “[How to inspect what is being reported](#how-to-" +"inspect-what-is-being-reported)”" msgstr "" +"**透明:** 您可以轻松查看正在报告的匿名指标;请参阅\"[如何查看正在报告的指标]" +"(#how-to-inspect-what-is-being-reported)\"部分" #: ../../source/ref-telemetry.md:14 msgid "" -"**Open for feedback:** You can always reach out to us if you have " -"feedback; see the section “[How to contact us](#how-to-contact-us)” for " -"details." +"**Open for feedback:** You can always reach out to us if you have feedback; " +"see the section “[How to contact us](#how-to-contact-us)” for details." msgstr "" +"**欢迎反馈:** 如果您有反馈意见,可以随时联系我们;详情请参见\"[如何联系我们]" +"(#how-to-contact-us) \"部分。" #: ../../source/ref-telemetry.md:16 msgid "How to opt-out" -msgstr "" +msgstr "如何退订" #: ../../source/ref-telemetry.md:18 msgid "" @@ -10332,35 +12203,44 @@ msgid "" "`FLWR_TELEMETRY_ENABLED=0`. Assuming you are starting a Flower server or " "client, simply do so by prepending your command as in:" msgstr "" +"Flower 启动时,会检查环境变量 `FLWR_TELEMETRY_ENABLED` 是否存在。通过设置 " +"`FLWR_TELEMETRY_ENABLED=0` 可以轻松禁用遥测功能。假设你启动的是 Flower 服务器" +"或客户端,只需在命令前添加以下内容即可:" #: ../../source/ref-telemetry.md:24 msgid "" -"Alternatively, you can export `FLWR_TELEMETRY_ENABLED=0` in, for example," -" `.bashrc` (or whatever configuration file applies to your environment) " -"to disable Flower telemetry permanently." +"Alternatively, you can export `FLWR_TELEMETRY_ENABLED=0` in, for example, `." +"bashrc` (or whatever configuration file applies to your environment) to " +"disable Flower telemetry permanently." msgstr "" +"或者,你也可以在 `.bashrc`(或任何适用于你的环境的配置文件)中导出 " +"`FLWR_TELEMETRY_ENABLED=0` 来永久禁用 Flower telemetry。" #: ../../source/ref-telemetry.md:26 msgid "Collected metrics" -msgstr "" +msgstr "收集的指标" #: ../../source/ref-telemetry.md:28 msgid "Flower telemetry collects the following metrics:" -msgstr "" +msgstr "Flower 遥测技术收集以下指标:" #: ../../source/ref-telemetry.md:30 msgid "" -"**Flower version.** Understand which versions of Flower are currently " -"being used. This helps us to decide whether we should invest effort into " -"releasing a patch version for an older version of Flower or instead use " -"the bandwidth to build new features." +"**Flower version.** Understand which versions of Flower are currently being " +"used. This helps us to decide whether we should invest effort into releasing " +"a patch version for an older version of Flower or instead use the bandwidth " +"to build new features." msgstr "" +"**了解目前使用的 Flower 版本。这有助于我们决定是否应该投入精力为旧版本的 " +"Flower 发布补丁版本,还是利用带宽来构建新功能。" #: ../../source/ref-telemetry.md:32 msgid "" "**Operating system.** Enables us to answer questions such as: *Should we " "create more guides for Linux, macOS, or Windows?*" msgstr "" +"**操作系统**使我们能够回答以下问题: *我们应该为 Linux、macOS 还是 Windows 创" +"建更多指南?*" #: ../../source/ref-telemetry.md:34 msgid "" @@ -10369,57 +12249,72 @@ msgid "" "Python or stop supporting them and start taking advantage of new Python " "features." msgstr "" +"**例如,了解 Python 版本有助于我们决定是否应该投入精力支持旧版本的 Python,还" +"是停止支持这些版本并开始利用新的 Python 功能。" #: ../../source/ref-telemetry.md:36 msgid "" -"**Hardware properties.** Understanding the hardware environment that " -"Flower is being used in helps to decide whether we should, for example, " -"put more effort into supporting low-resource environments." +"**Hardware properties.** Understanding the hardware environment that Flower " +"is being used in helps to decide whether we should, for example, put more " +"effort into supporting low-resource environments." msgstr "" +"**硬件属性** 了解 Flower 的硬件使用环境,有助于决定我们是否应在支持低资源环境" +"等方面投入更多精力。" #: ../../source/ref-telemetry.md:38 msgid "" -"**Execution mode.** Knowing what execution mode Flower starts in enables " -"us to understand how heavily certain features are being used and better " +"**Execution mode.** Knowing what execution mode Flower starts in enables us " +"to understand how heavily certain features are being used and better " "prioritize based on that." msgstr "" +"** 执行模式** 了解 Flower 的启动执行模式,能让我们了解某些功能的使用率,并据" +"此更好地确定优先级。" #: ../../source/ref-telemetry.md:40 msgid "" "**Cluster.** Flower telemetry assigns a random in-memory cluster ID each " "time a Flower workload starts. This allows us to understand which device " -"types not only start Flower workloads but also successfully complete " -"them." +"types not only start Flower workloads but also successfully complete them." msgstr "" +"**每次 Flower 工作负载启动时,Flower 遥测都会随机分配一个内存集群 ID。这样," +"我们就能了解哪些设备类型不仅启动了 Flower 工作负载,而且还成功完成了它们。" #: ../../source/ref-telemetry.md:42 msgid "" -"**Source.** Flower telemetry tries to store a random source ID in " -"`~/.flwr/source` the first time a telemetry event is generated. The " -"source ID is important to identify whether an issue is recurring or " -"whether an issue is triggered by multiple clusters running concurrently " -"(which often happens in simulation). For example, if a device runs " -"multiple workloads at the same time, and this results in an issue, then, " -"in order to reproduce the issue, multiple workloads must be started at " -"the same time." +"**Source.** Flower telemetry tries to store a random source ID in `~/.flwr/" +"source` the first time a telemetry event is generated. The source ID is " +"important to identify whether an issue is recurring or whether an issue is " +"triggered by multiple clusters running concurrently (which often happens in " +"simulation). For example, if a device runs multiple workloads at the same " +"time, and this results in an issue, then, in order to reproduce the issue, " +"multiple workloads must be started at the same time." msgstr "" +"**Source.** Flower 遥测会在第一次生成遥测事件时,尝试在 `~/.flwr/source` 中存" +"储一个随机源 ID。源 ID 对于识别问题是否反复出现或问题是否由多个集群同时运行触" +"发(这在模拟中经常发生)非常重要。例如,如果设备同时运行多个工作负载并导致问" +"题,那么为了重现问题,必须同时启动多个工作负载。" #: ../../source/ref-telemetry.md:44 msgid "" -"You may delete the source ID at any time. If you wish for all events " -"logged under a specific source ID to be deleted, you can send a deletion " -"request mentioning the source ID to `telemetry@flower.dev`. All events " -"related to that source ID will then be permanently deleted." +"You may delete the source ID at any time. If you wish for all events logged " +"under a specific source ID to be deleted, you can send a deletion request " +"mentioning the source ID to `telemetry@flower.dev`. All events related to " +"that source ID will then be permanently deleted." msgstr "" +"您可以随时删除源 ID。如果您希望删除特定源 ID 下记录的所有事件,可以向 " +"`telemetry@flower.dev` 发送删除请求,并提及该源 ID。届时,与该源 ID 相关的所" +"有事件都将被永久删除。" #: ../../source/ref-telemetry.md:46 msgid "" -"We will not collect any personally identifiable information. If you think" -" any of the metrics collected could be misused in any way, please [get in" -" touch with us](#how-to-contact-us). We will update this page to reflect " -"any changes to the metrics collected and publish changes in the " -"changelog." +"We will not collect any personally identifiable information. If you think " +"any of the metrics collected could be misused in any way, please [get in " +"touch with us](#how-to-contact-us). We will update this page to reflect any " +"changes to the metrics collected and publish changes in the changelog." msgstr "" +"我们不会收集任何个人身份信息。如果您认为所收集的任何指标可能以任何方式被滥" +"用,请[与我们联系](#how-to-contact-us)。我们将更新本页面,以反映对所收集指" +"标的任何更改,并在更新日志中公布更改内容。" #: ../../source/ref-telemetry.md:48 msgid "" @@ -10427,30 +12322,37 @@ msgid "" "decisions, please let us know! We will carefully review them; if we are " "confident that they do not compromise user privacy, we may add them." msgstr "" +"如果您认为其他指标有助于我们更好地指导决策,请告诉我们!我们将仔细审查这些指" +"标;如果我们确信它们不会损害用户隐私,我们可能会添加这些指标。" #: ../../source/ref-telemetry.md:50 msgid "How to inspect what is being reported" -msgstr "" +msgstr "如何检查报告中的内容" #: ../../source/ref-telemetry.md:52 msgid "" "We wanted to make it very easy for you to inspect what anonymous usage " -"metrics are reported. You can view all the reported telemetry information" -" by setting the environment variable `FLWR_TELEMETRY_LOGGING=1`. Logging " -"is disabled by default. You may use logging independently from " +"metrics are reported. You can view all the reported telemetry information by " +"setting the environment variable `FLWR_TELEMETRY_LOGGING=1`. Logging is " +"disabled by default. You may use logging independently from " "`FLWR_TELEMETRY_ENABLED` so that you can inspect the telemetry feature " "without sending any metrics." msgstr "" +"我们希望能让您轻松查看所报告的匿名使用指标。通过设置环境变量 " +"`FLWR_TELEMETRY_LOGGING=1` 可以查看所有报告的遥测信息。日志记录默认为禁用。您" +"可以不使用 `FLWR_TELEMETRY_ENABLED` 而单独使用日志记录,这样就可以在不发送任" +"何指标的情况下检查遥测功能。" #: ../../source/ref-telemetry.md:58 msgid "" -"The inspect Flower telemetry without sending any anonymous usage metrics," -" use both environment variables:" +"The inspect Flower telemetry without sending any anonymous usage metrics, " +"use both environment variables:" msgstr "" +"在不发送任何匿名使用指标的情况下检查 Flower 遥测,可使用这两个环境变量:" #: ../../source/ref-telemetry.md:64 msgid "How to contact us" -msgstr "" +msgstr "如何联系我们" #: ../../source/ref-telemetry.md:66 msgid "" @@ -10459,56 +12361,66 @@ msgid "" "[Slack](https://flower.dev/join-slack/) (channel `#telemetry`) or email " "(`telemetry@flower.dev`)." msgstr "" +"我们希望听到您的意见。如果您对如何改进我们处理匿名使用指标的方式有任何反馈或" +"想法,请通过 [Slack](https://flower.dev/join-slack/) (频道 `#telemetry`)或" +"电子邮件 (`telemetry@flower.dev`)与我们联系。" #: ../../source/tutorial-quickstart-android.rst:-1 msgid "" -"Read this Federated Learning quickstart tutorial for creating an Android " -"app using Flower." +"Read this Federated Learning quickstart tutorial for creating an Android app " +"using Flower." msgstr "" +"阅读本 Federated Learning 快速入门教程,了解如何使用 Flower 创建 Android 应用" +"程序。" #: ../../source/tutorial-quickstart-android.rst:5 msgid "Quickstart Android" -msgstr "" +msgstr "快速入门 Android" #: ../../source/tutorial-quickstart-android.rst:10 msgid "" -"Let's build a federated learning system using TFLite and Flower on " -"Android!" -msgstr "" +"Let's build a federated learning system using TFLite and Flower on Android!" +msgstr "让我们在 Android 上使用 TFLite 和 Flower 构建一个联合学习系统!" #: ../../source/tutorial-quickstart-android.rst:12 msgid "" -"Please refer to the `full code example " -"`_ to learn " -"more." +"Please refer to the `full code example `_ to learn more." msgstr "" +"请参阅 \"完整代码示例 `_\" 了解更多信息。" #: ../../source/tutorial-quickstart-fastai.rst:-1 msgid "" -"Check out this Federated Learning quickstart tutorial for using Flower " -"with FastAI to train a vision model on CIFAR-10." +"Check out this Federated Learning quickstart tutorial for using Flower with " +"FastAI to train a vision model on CIFAR-10." msgstr "" +"查看此 Federated Learning 快速入门教程,了解如何使用 Flower 和 FastAI 在 " +"CIFAR-10 上训练视觉模型。" #: ../../source/tutorial-quickstart-fastai.rst:5 msgid "Quickstart fastai" -msgstr "" +msgstr "快速入门 fastai" #: ../../source/tutorial-quickstart-fastai.rst:10 msgid "Let's build a federated learning system using fastai and Flower!" -msgstr "" +msgstr "让我们用 fastai 和 Flower 建立一个联合学习系统!" #: ../../source/tutorial-quickstart-fastai.rst:12 msgid "" -"Please refer to the `full code example " -"`_ " -"to learn more." +"Please refer to the `full code example `_ to learn more." msgstr "" +"请参阅 \"完整代码示例 `_\" 了解更多信息。" #: ../../source/tutorial-quickstart-huggingface.rst:-1 msgid "" -"Check out this Federating Learning quickstart tutorial for using Flower " -"with HuggingFace Transformers in order to fine-tune an LLM." +"Check out this Federating Learning quickstart tutorial for using Flower with " +"HuggingFace Transformers in order to fine-tune an LLM." msgstr "" +"查看此 Federating Learning 快速入门教程,了解如何使用 Flower 和 HuggingFace " +"Transformers 来微调 LLM。" #: ../../source/tutorial-quickstart-huggingface.rst:5 msgid "Quickstart 🤗 Transformers" @@ -10516,30 +12428,35 @@ msgstr "" #: ../../source/tutorial-quickstart-huggingface.rst:10 msgid "" -"Let's build a federated learning system using Hugging Face Transformers " -"and Flower!" +"Let's build a federated learning system using Hugging Face Transformers and " +"Flower!" msgstr "" #: ../../source/tutorial-quickstart-huggingface.rst:12 msgid "" -"We will leverage Hugging Face to federate the training of language models" -" over multiple clients using Flower. More specifically, we will fine-tune" -" a pre-trained Transformer model (distilBERT) for sequence classification" -" over a dataset of IMDB ratings. The end goal is to detect if a movie " -"rating is positive or negative." +"We will leverage Hugging Face to federate the training of language models " +"over multiple clients using Flower. More specifically, we will fine-tune a " +"pre-trained Transformer model (distilBERT) for sequence classification over " +"a dataset of IMDB ratings. The end goal is to detect if a movie rating is " +"positive or negative." msgstr "" +"我们将利用 \"拥抱面孔 \"技术,使用 Flower 在多个客户端上联合训练语言模型。更" +"具体地说,我们将对预先训练好的 Transformer 模型(distilBERT)进行微调,以便" +"在 IMDB 评分数据集上进行序列分类。最终目标是检测电影评分是正面还是负面。" #: ../../source/tutorial-quickstart-huggingface.rst:18 msgid "Dependencies" -msgstr "" +msgstr "依赖关系" #: ../../source/tutorial-quickstart-huggingface.rst:20 msgid "" "To follow along this tutorial you will need to install the following " -"packages: :code:`datasets`, :code:`evaluate`, :code:`flwr`, " -":code:`torch`, and :code:`transformers`. This can be done using " -":code:`pip`:" +"packages: :code:`datasets`, :code:`evaluate`, :code:`flwr`, :code:`torch`, " +"and :code:`transformers`. This can be done using :code:`pip`:" msgstr "" +"要学习本教程,您需要安装以下软件包: :code:`datasets`、 :code:`evaluate`、 :" +"code:`flwr`、 :code:`torch`和 :code:`transformers`。这可以通过 :code:`pip` 来" +"完成:" #: ../../source/tutorial-quickstart-huggingface.rst:30 msgid "Standard Hugging Face workflow" @@ -10547,7 +12464,7 @@ msgstr "" #: ../../source/tutorial-quickstart-huggingface.rst:33 msgid "Handling the data" -msgstr "" +msgstr "处理数据" #: ../../source/tutorial-quickstart-huggingface.rst:35 msgid "" @@ -10555,125 +12472,153 @@ msgid "" "library. We then need to tokenize the data and create :code:`PyTorch` " "dataloaders, this is all done in the :code:`load_data` function:" msgstr "" +"为了获取 IMDB 数据集,我们将使用 Hugging Face 的 :code:`datasets` 库。然后," +"我们需要对数据进行标记化,并创建 :code:`PyTorch` 数据加载器,这些都将在 :" +"code:`load_data` 函数中完成:" #: ../../source/tutorial-quickstart-huggingface.rst:81 msgid "Training and testing the model" -msgstr "" +msgstr "训练和测试模型" #: ../../source/tutorial-quickstart-huggingface.rst:83 msgid "" -"Once we have a way of creating our trainloader and testloader, we can " -"take care of the training and testing. This is very similar to any " -":code:`PyTorch` training or testing loop:" +"Once we have a way of creating our trainloader and testloader, we can take " +"care of the training and testing. This is very similar to any :code:" +"`PyTorch` training or testing loop:" msgstr "" +"有了创建 trainloader 和 testloader 的方法后,我们就可以进行训练和测试了。这与" +"任何 :code:`PyTorch` 训练或测试循环都非常相似:" #: ../../source/tutorial-quickstart-huggingface.rst:121 msgid "Creating the model itself" -msgstr "" +msgstr "创建模型本身" #: ../../source/tutorial-quickstart-huggingface.rst:123 msgid "" -"To create the model itself, we will just load the pre-trained distillBERT" -" model using Hugging Face’s :code:`AutoModelForSequenceClassification` :" +"To create the model itself, we will just load the pre-trained distillBERT " +"model using Hugging Face’s :code:`AutoModelForSequenceClassification` :" msgstr "" +"要创建模型本身,我们只需使用 Hugging Face 的 :code:" +"`AutoModelForSequenceClassification` 加载预训练的 distillBERT 模型:" #: ../../source/tutorial-quickstart-huggingface.rst:136 msgid "Federating the example" -msgstr "" +msgstr "将示例联合起来" #: ../../source/tutorial-quickstart-huggingface.rst:139 msgid "Creating the IMDBClient" -msgstr "" +msgstr "创建 IMDBClient" #: ../../source/tutorial-quickstart-huggingface.rst:141 msgid "" "To federate our example to multiple clients, we first need to write our " -"Flower client class (inheriting from :code:`flwr.client.NumPyClient`). " -"This is very easy, as our model is a standard :code:`PyTorch` model:" +"Flower client class (inheriting from :code:`flwr.client.NumPyClient`). This " +"is very easy, as our model is a standard :code:`PyTorch` model:" msgstr "" +"要将我们的示例联合到多个客户端,我们首先需要编写 Flower 客户端类(继承自 :" +"code:`flwr.client.NumPyClient`)。这很容易,因为我们的模型是一个标准的 :code:" +"`PyTorch` 模型:" #: ../../source/tutorial-quickstart-huggingface.rst:169 msgid "" "The :code:`get_parameters` function lets the server get the client's " -"parameters. Inversely, the :code:`set_parameters` function allows the " -"server to send its parameters to the client. Finally, the :code:`fit` " -"function trains the model locally for the client, and the " -":code:`evaluate` function tests the model locally and returns the " -"relevant metrics." +"parameters. Inversely, the :code:`set_parameters` function allows the server " +"to send its parameters to the client. Finally, the :code:`fit` function " +"trains the model locally for the client, and the :code:`evaluate` function " +"tests the model locally and returns the relevant metrics." msgstr "" +":code:`get_parameters` 函数允许服务器获取客户端的参数。相反,:code:" +"`set_parameters`函数允许服务器将其参数发送给客户端。最后,:code:`fit`函数在本" +"地为客户端训练模型,:code:`evaluate`函数在本地测试模型并返回相关指标。" #: ../../source/tutorial-quickstart-huggingface.rst:175 msgid "Starting the server" -msgstr "" +msgstr "启动服务器" #: ../../source/tutorial-quickstart-huggingface.rst:177 msgid "" -"Now that we have a way to instantiate clients, we need to create our " -"server in order to aggregate the results. Using Flower, this can be done " -"very easily by first choosing a strategy (here, we are using " -":code:`FedAvg`, which will define the global weights as the average of " -"all the clients' weights at each round) and then using the " -":code:`flwr.server.start_server` function:" +"Now that we have a way to instantiate clients, we need to create our server " +"in order to aggregate the results. Using Flower, this can be done very " +"easily by first choosing a strategy (here, we are using :code:`FedAvg`, " +"which will define the global weights as the average of all the clients' " +"weights at each round) and then using the :code:`flwr.server.start_server` " +"function:" msgstr "" +"现在我们有了实例化客户端的方法,我们需要创建服务器,以便汇总结果。使用 " +"Flower,首先选择一个策略(这里我们使用 :code:`FedAvg`,它将把全局权重定义为每" +"轮所有客户端权重的平均值),然后使用 :code:`flwr.server.start_server`函数,就" +"可以非常轻松地完成这项工作:" #: ../../source/tutorial-quickstart-huggingface.rst:205 msgid "" -"The :code:`weighted_average` function is there to provide a way to " -"aggregate the metrics distributed amongst the clients (basically this " -"allows us to display a nice average accuracy and loss for every round)." +"The :code:`weighted_average` function is there to provide a way to aggregate " +"the metrics distributed amongst the clients (basically this allows us to " +"display a nice average accuracy and loss for every round)." msgstr "" +"使用 :code:`weighted_average` 函数是为了提供一种方法来汇总分布在客户端的指标" +"(基本上,这可以让我们显示每一轮的平均精度和损失)。" #: ../../source/tutorial-quickstart-huggingface.rst:209 msgid "Putting everything together" -msgstr "" +msgstr "把所有东西放在一起" #: ../../source/tutorial-quickstart-huggingface.rst:211 msgid "We can now start client instances using:" -msgstr "" +msgstr "现在我们可以使用:" #: ../../source/tutorial-quickstart-huggingface.rst:221 msgid "" "And they will be able to connect to the server and start the federated " "training." -msgstr "" +msgstr "他们就能连接到服务器,开始联合培训。" #: ../../source/tutorial-quickstart-huggingface.rst:223 msgid "" -"If you want to check out everything put together, you should check out " -"the full code example: [https://github.com/adap/flower/tree/main/examples" -"/quickstart-" -"huggingface](https://github.com/adap/flower/tree/main/examples" -"/quickstart-huggingface)." +"If you want to check out everything put together, you should check out the " +"full code example: [https://github.com/adap/flower/tree/main/examples/" +"quickstart-huggingface](https://github.com/adap/flower/tree/main/examples/" +"quickstart-huggingface)." msgstr "" +"如果您想查看所有内容,请查看完整的代码示例: [https://github.com/adap/flower/" +"tree/main/examples/quickstart-huggingface](https://github.com/adap/flower/" +"tree/main/examples/quickstart-huggingface)." #: ../../source/tutorial-quickstart-huggingface.rst:227 msgid "" -"Of course, this is a very basic example, and a lot can be added or " -"modified, it was just to showcase how simply we could federate a Hugging " -"Face workflow using Flower." +"Of course, this is a very basic example, and a lot can be added or modified, " +"it was just to showcase how simply we could federate a Hugging Face workflow " +"using Flower." msgstr "" +"当然,这只是一个非常基本的示例,还可以添加或修改很多内容,只是为了展示我们可" +"以如何简单地使用 Flower 联合 \"拥抱的脸 \"工作流程。" #: ../../source/tutorial-quickstart-huggingface.rst:230 msgid "" -"Note that in this example we used :code:`PyTorch`, but we could have very" -" well used :code:`TensorFlow`." +"Note that in this example we used :code:`PyTorch`, but we could have very " +"well used :code:`TensorFlow`." msgstr "" +"请注意,在本例中我们使用了 :code:`PyTorch`,但也完全可以使用 :code:" +"`TensorFlow`。" #: ../../source/tutorial-quickstart-ios.rst:-1 msgid "" "Read this Federated Learning quickstart tutorial for creating an iOS app " "using Flower to train a neural network on MNIST." msgstr "" +"阅读本 Federated Learning 快速入门教程,了解如何使用 Flower 创建 iOS 应用程" +"序,并在 MNIST 上训练神经网络。" #: ../../source/tutorial-quickstart-ios.rst:5 msgid "Quickstart iOS" -msgstr "" +msgstr "快速入门 iOS" #: ../../source/tutorial-quickstart-ios.rst:10 msgid "" -"In this tutorial we will learn how to train a Neural Network on MNIST " -"using Flower and CoreML on iOS devices." +"In this tutorial we will learn how to train a Neural Network on MNIST using " +"Flower and CoreML on iOS devices." msgstr "" +"在本教程中,我们将学习如何在 iOS 设备上使用 Flower 和 CoreML 在 MNIST 上训练" +"神经网络。" #: ../../source/tutorial-quickstart-ios.rst:12 msgid "" @@ -10682,28 +12627,38 @@ msgid "" "`_. For the Flower " "client implementation in iOS, it is recommended to use Xcode as our IDE." msgstr "" +"首先,为了运行 Flower Python 服务器,建议创建一个虚拟环境,并在 `virtualenv " +"`_ 中运行一切。对于在 " +"iOS 中实现 Flower 客户端,建议使用 Xcode 作为我们的集成开发环境。" #: ../../source/tutorial-quickstart-ios.rst:15 msgid "" -"Our example consists of one Python *server* and two iPhone *clients* that" -" all have the same model." +"Our example consists of one Python *server* and two iPhone *clients* that " +"all have the same model." msgstr "" +"我们的示例包括一个 Python 服务器*和两个 iPhone 客户端*,它们都具有相同的模" +"型。" #: ../../source/tutorial-quickstart-ios.rst:17 msgid "" -"*Clients* are responsible for generating individual weight updates for " -"the model based on their local datasets. These updates are then sent to " -"the *server* which will aggregate them to produce a better model. " -"Finally, the *server* sends this improved version of the model back to " -"each *client*. A complete cycle of weight updates is called a *round*." +"*Clients* are responsible for generating individual weight updates for the " +"model based on their local datasets. These updates are then sent to the " +"*server* which will aggregate them to produce a better model. Finally, the " +"*server* sends this improved version of the model back to each *client*. A " +"complete cycle of weight updates is called a *round*." msgstr "" +"*客户*负责根据其本地数据集为模型生成单独的权重更新。然后,这些更新会被发送到*" +"服务器,由*服务器汇总后生成一个更好的模型。最后,*服务器*将改进后的模型发送回" +"每个*客户端*。一个完整的权重更新周期称为一个*轮*。" #: ../../source/tutorial-quickstart-ios.rst:21 msgid "" "Now that we have a rough idea of what is going on, let's get started to " -"setup our Flower server environment. We first need to install Flower. You" -" can do this by using pip:" +"setup our Flower server environment. We first need to install Flower. You " +"can do this by using pip:" msgstr "" +"现在我们已经有了一个大致的概念,让我们开始设置 Flower 服务器环境吧。首先,我" +"们需要安装 Flower。你可以使用 pip 来安装:" #: ../../source/tutorial-quickstart-ios.rst:27 msgid "Or Poetry:" @@ -10712,69 +12667,88 @@ msgstr "" #: ../../source/tutorial-quickstart-ios.rst:36 msgid "" "Now that we have all our dependencies installed, let's run a simple " -"distributed training using CoreML as our local training pipeline and " -"MNIST as our dataset. For simplicity reasons we will use the complete " -"Flower client with CoreML, that has been implemented and stored inside " -"the Swift SDK. The client implementation can be seen below:" +"distributed training using CoreML as our local training pipeline and MNIST " +"as our dataset. For simplicity reasons we will use the complete Flower " +"client with CoreML, that has been implemented and stored inside the Swift " +"SDK. The client implementation can be seen below:" msgstr "" +"现在我们已经安装了所有依赖项,让我们使用 CoreML 作为本地训练管道和 MNIST 作为" +"数据集,运行一个简单的分布式训练。为了简单起见,我们将使用 CoreML 的完整 " +"Flower 客户端,该客户端已在 Swift SDK 中实现并存储。客户端实现如下:" #: ../../source/tutorial-quickstart-ios.rst:72 msgid "" -"Let's create a new application project in Xcode and add :code:`flwr` as a" -" dependency in your project. For our application, we will store the logic" -" of our app in :code:`FLiOSModel.swift` and the UI elements in " -":code:`ContentView.swift`. We will focus more on :code:`FLiOSModel.swift`" -" in this quickstart. Please refer to the `full code example " -"`_ to learn more " -"about the app." +"Let's create a new application project in Xcode and add :code:`flwr` as a " +"dependency in your project. For our application, we will store the logic of " +"our app in :code:`FLiOSModel.swift` and the UI elements in :code:" +"`ContentView.swift`. We will focus more on :code:`FLiOSModel.swift` in this " +"quickstart. Please refer to the `full code example `_ to learn more about the app." msgstr "" +"让我们在 Xcode 中创建一个新的应用程序项目,并在项目中添加 :code:`flwr` 作为依" +"赖关系。对于我们的应用程序,我们将在 :code:`FLiOSModel.swift` 中存储应用程序" +"的逻辑,在 :code:`ContentView.swift` 中存储 UI 元素。在本快速入门中,我们将更" +"多地关注 :code:`FLiOSModel.swift`。请参阅 \"完整代码示例 `_\" 以了解更多有关应用程序的信息。" #: ../../source/tutorial-quickstart-ios.rst:75 msgid "Import Flower and CoreML related packages in :code:`FLiOSModel.swift`:" -msgstr "" +msgstr "在 :code:`FLiOSModel.swift` 中导入 Flower 和 CoreML 相关软件包:" #: ../../source/tutorial-quickstart-ios.rst:83 msgid "" "Then add the mlmodel to the project simply by drag-and-drop, the mlmodel " -"will be bundled inside the application during deployment to your iOS " -"device. We need to pass the url to access mlmodel and run CoreML machine " -"learning processes, it can be retrieved by calling the function " -":code:`Bundle.main.url`. For the MNIST dataset, we need to preprocess it " -"into :code:`MLBatchProvider` object. The preprocessing is done inside " -":code:`DataLoader.swift`." -msgstr "" +"will be bundled inside the application during deployment to your iOS device. " +"We need to pass the url to access mlmodel and run CoreML machine learning " +"processes, it can be retrieved by calling the function :code:`Bundle.main." +"url`. For the MNIST dataset, we need to preprocess it into :code:" +"`MLBatchProvider` object. The preprocessing is done inside :code:`DataLoader." +"swift`." +msgstr "" +"然后通过拖放将 mlmodel 添加到项目中,在部署到 iOS 设备时,mlmodel 将被捆绑到" +"应用程序中。我们需要传递 url 以访问 mlmodel 并运行 CoreML 机器学习进程,可通" +"过调用函数 :code:`Bundle.main.url` 获取。对于 MNIST 数据集,我们需要将其预处" +"理为 :code:`MLBatchProvider` 对象。预处理在 :code:`DataLoader.swift` 中完成。" #: ../../source/tutorial-quickstart-ios.rst:99 msgid "" -"Since CoreML does not allow the model parameters to be seen before " -"training, and accessing the model parameters during or after the training" -" can only be done by specifying the layer name, we need to know this " -"informations beforehand, through looking at the model specification, " -"which are written as proto files. The implementation can be seen in " -":code:`MLModelInspect`." +"Since CoreML does not allow the model parameters to be seen before training, " +"and accessing the model parameters during or after the training can only be " +"done by specifying the layer name, we need to know this informations " +"beforehand, through looking at the model specification, which are written as " +"proto files. The implementation can be seen in :code:`MLModelInspect`." msgstr "" +"由于 CoreML 不允许在训练前查看模型参数,而在训练过程中或训练后访问模型参数只" +"能通过指定层名来完成,因此我们需要事先通过查看模型规范(写成 proto 文件)来了" +"解这些信息。具体实现可参见 :code:`MLModelInspect`。" #: ../../source/tutorial-quickstart-ios.rst:102 msgid "" "After we have all of the necessary informations, let's create our Flower " "client." -msgstr "" +msgstr "获得所有必要信息后,让我们创建 Flower 客户端。" #: ../../source/tutorial-quickstart-ios.rst:117 msgid "" -"Then start the Flower gRPC client and start communicating to the server " -"by passing our Flower client to the function :code:`startFlwrGRPC`." +"Then start the Flower gRPC client and start communicating to the server by " +"passing our Flower client to the function :code:`startFlwrGRPC`." msgstr "" +"然后启动 Flower gRPC 客户端,并通过将 Flower 客户端传递给函数 :code:" +"`startFlwrGRPC` 来开始与服务器通信。" #: ../../source/tutorial-quickstart-ios.rst:124 msgid "" -"That's it for the client. We only have to implement :code:`Client` or " -"call the provided :code:`MLFlwrClient` and call :code:`startFlwrGRPC()`. " -"The attribute :code:`hostname` and :code:`port` tells the client which " -"server to connect to. This can be done by entering the hostname and port " -"in the application before clicking the start button to start the " -"federated learning process." +"That's it for the client. We only have to implement :code:`Client` or call " +"the provided :code:`MLFlwrClient` and call :code:`startFlwrGRPC()`. The " +"attribute :code:`hostname` and :code:`port` tells the client which server to " +"connect to. This can be done by entering the hostname and port in the " +"application before clicking the start button to start the federated learning " +"process." msgstr "" +"这就是客户端。我们只需实现 :code:`Client` 或调用提供的 :code:`MLFlwrClient` " +"并调用 :code:`startFlwrGRPC()`。属性 :code:`hostname` 和 :code:`port` 会告诉" +"客户端要连接到哪个服务器。这可以通过在应用程序中输入主机名和端口来实现,然后" +"再点击开始按钮启动联合学习进程。" #: ../../source/tutorial-quickstart-ios.rst:131 #: ../../source/tutorial-quickstart-mxnet.rst:226 @@ -10782,9 +12756,11 @@ msgstr "" #: ../../source/tutorial-quickstart-tensorflow.rst:100 msgid "" "For simple workloads we can start a Flower server and leave all the " -"configuration possibilities at their default values. In a file named " -":code:`server.py`, import Flower and start the server:" +"configuration possibilities at their default values. In a file named :code:" +"`server.py`, import Flower and start the server:" msgstr "" +"对于简单的工作负载,我们可以启动 Flower 服务器,并将所有配置选项保留为默认" +"值。在名为 :code:`server.py` 的文件中,导入 Flower 并启动服务器:" #: ../../source/tutorial-quickstart-ios.rst:142 #: ../../source/tutorial-quickstart-mxnet.rst:237 @@ -10792,7 +12768,7 @@ msgstr "" #: ../../source/tutorial-quickstart-scikitlearn.rst:215 #: ../../source/tutorial-quickstart-tensorflow.rst:112 msgid "Train the model, federated!" -msgstr "" +msgstr "联合训练模型!" #: ../../source/tutorial-quickstart-ios.rst:144 #: ../../source/tutorial-quickstart-pytorch.rst:218 @@ -10800,72 +12776,89 @@ msgstr "" #: ../../source/tutorial-quickstart-xgboost.rst:522 msgid "" "With both client and server ready, we can now run everything and see " -"federated learning in action. FL systems usually have a server and " -"multiple clients. We therefore have to start the server first:" +"federated learning in action. FL systems usually have a server and multiple " +"clients. We therefore have to start the server first:" msgstr "" +"客户端和服务器都已准备就绪,我们现在可以运行一切,看看联合学习的实际效果。FL " +"系统通常有一个服务器和多个客户端。因此,我们必须先启动服务器:" #: ../../source/tutorial-quickstart-ios.rst:152 msgid "" -"Once the server is running we can start the clients in different " -"terminals. Build and run the client through your Xcode, one through Xcode" -" Simulator and the other by deploying it to your iPhone. To see more " -"about how to deploy your app to iPhone or Simulator visit `here " -"`_." +"Once the server is running we can start the clients in different terminals. " +"Build and run the client through your Xcode, one through Xcode Simulator and " +"the other by deploying it to your iPhone. To see more about how to deploy " +"your app to iPhone or Simulator visit `here `_." msgstr "" +"服务器运行后,我们就可以在不同的终端启动客户端。通过 Xcode 构建并运行客户端," +"一个通过 Xcode 模拟器,另一个通过部署到 iPhone。要了解更多有关如何将应用程序" +"部署到 iPhone 或模拟器的信息,请访问 `此处 `_。" #: ../../source/tutorial-quickstart-ios.rst:156 msgid "" "Congratulations! You've successfully built and run your first federated " -"learning system in your ios device. The full `source code " -"`_ for this " -"example can be found in :code:`examples/ios`." +"learning system in your ios device. The full `source code `_ for this example can be found in :" +"code:`examples/ios`." msgstr "" +"恭喜您 您已经成功地在 ios 设备中构建并运行了第一个联合学习系统。本示例的完整" +"源代码 `_ 可在 :code:" +"`examples/ios` 中找到。" #: ../../source/tutorial-quickstart-jax.rst:-1 msgid "" -"Check out this Federated Learning quickstart tutorial for using Flower " -"with Jax to train a linear regression model on a scikit-learn dataset." +"Check out this Federated Learning quickstart tutorial for using Flower with " +"Jax to train a linear regression model on a scikit-learn dataset." msgstr "" +"查看此 Federated Learning 快速入门教程,了解如何使用 Flower 和 Jax 在 scikit-" +"learn 数据集上训练线性回归模型。" #: ../../source/tutorial-quickstart-jax.rst:5 msgid "Quickstart JAX" -msgstr "" +msgstr "快速入门 JAX" #: ../../source/tutorial-quickstart-mxnet.rst:-1 msgid "" -"Check out this Federated Learning quickstart tutorial for using Flower " -"with MXNet to train a Sequential model on MNIST." +"Check out this Federated Learning quickstart tutorial for using Flower with " +"MXNet to train a Sequential model on MNIST." msgstr "" +"查看此 Federated Learning 快速入门教程,了解如何使用 Flower 和 MXNet 在 " +"MNIST 上训练序列模型。" #: ../../source/tutorial-quickstart-mxnet.rst:5 msgid "Quickstart MXNet" -msgstr "" +msgstr "快速入门 MXNet" #: ../../source/tutorial-quickstart-mxnet.rst:10 msgid "" -"In this tutorial, we will learn how to train a :code:`Sequential` model " -"on MNIST using Flower and MXNet." +"In this tutorial, we will learn how to train a :code:`Sequential` model on " +"MNIST using Flower and MXNet." msgstr "" +"在本教程中,我们将学习如何使用 Flower 和 MXNet 在 MNIST 上训练 :code:" +"`Sequential` 模型。" #: ../../source/tutorial-quickstart-mxnet.rst:12 #: ../../source/tutorial-quickstart-scikitlearn.rst:12 msgid "" -"It is recommended to create a virtual environment and run everything " -"within this `virtualenv `_." +"It is recommended to create a virtual environment and run everything within " +"this `virtualenv `_." msgstr "" +"建议创建一个虚拟环境,并在此 `virtualenv `_ 中运行所有内容。" #: ../../source/tutorial-quickstart-mxnet.rst:16 #: ../../source/tutorial-quickstart-scikitlearn.rst:16 msgid "" -"*Clients* are responsible for generating individual model parameter " -"updates for the model based on their local datasets. These updates are " -"then sent to the *server* which will aggregate them to produce an updated" -" global model. Finally, the *server* sends this improved version of the " -"model back to each *client*. A complete cycle of parameters updates is " -"called a *round*." +"*Clients* are responsible for generating individual model parameter updates " +"for the model based on their local datasets. These updates are then sent to " +"the *server* which will aggregate them to produce an updated global model. " +"Finally, the *server* sends this improved version of the model back to each " +"*client*. A complete cycle of parameters updates is called a *round*." msgstr "" +"*客户*负责根据其本地数据集为模型生成单独的模型参数更新。然后,这些更新将被发" +"送到*服务器,由*服务器汇总后生成一个更新的全局模型。最后,*服务器*将这一改进" +"版模型发回给每个*客户端*。一个完整的参数更新周期称为*轮*。" #: ../../source/tutorial-quickstart-mxnet.rst:20 #: ../../source/tutorial-quickstart-scikitlearn.rst:20 @@ -10873,150 +12866,171 @@ msgid "" "Now that we have a rough idea of what is going on, let's get started. We " "first need to install Flower. You can do this by running:" msgstr "" +"现在,我们已经有了一个大致的概念,让我们开始吧。首先,我们需要安装 Flower。运" +"行:" #: ../../source/tutorial-quickstart-mxnet.rst:26 msgid "Since we want to use MXNet, let's go ahead and install it:" -msgstr "" +msgstr "既然我们要使用 MXNet,那就继续安装吧:" #: ../../source/tutorial-quickstart-mxnet.rst:36 msgid "" "Now that we have all our dependencies installed, let's run a simple " -"distributed training with two clients and one server. Our training " -"procedure and network architecture are based on MXNet´s `Hand-written " -"Digit Recognition tutorial " -"`_." +"distributed training with two clients and one server. Our training procedure " +"and network architecture are based on MXNet´s `Hand-written Digit " +"Recognition tutorial `_." msgstr "" +"现在,我们已经安装了所有依赖项,让我们用两个客户端和一个服务器来运行一个简单" +"的分布式训练。我们的训练程序和网络架构基于 MXNet 的 \"手写数字识别教程 " +"`_\"。" #: ../../source/tutorial-quickstart-mxnet.rst:38 msgid "" -"In a file called :code:`client.py`, import Flower and MXNet related " -"packages:" -msgstr "" +"In a file called :code:`client.py`, import Flower and MXNet related packages:" +msgstr "在名为 :code:`client.py` 的文件中,导入 Flower 和 MXNet 相关软件包:" #: ../../source/tutorial-quickstart-mxnet.rst:53 msgid "In addition, define the device allocation in MXNet with:" -msgstr "" +msgstr "此外,还可以在 MXNet 中定义设备分配:" #: ../../source/tutorial-quickstart-mxnet.rst:59 msgid "" "We use MXNet to load MNIST, a popular image classification dataset of " -"handwritten digits for machine learning. The MXNet utility " -":code:`mx.test_utils.get_mnist()` downloads the training and test data." +"handwritten digits for machine learning. The MXNet utility :code:`mx." +"test_utils.get_mnist()` downloads the training and test data." msgstr "" +"我们使用 MXNet 加载 MNIST,这是一个用于机器学习的流行手写数字图像分类数据集。" +"MXNet 工具 :code:`mx.test_utils.get_mnist()` 会下载训练和测试数据。" #: ../../source/tutorial-quickstart-mxnet.rst:73 msgid "" -"Define the training and loss with MXNet. We train the model by looping " -"over the dataset, measure the corresponding loss, and optimize it." +"Define the training and loss with MXNet. We train the model by looping over " +"the dataset, measure the corresponding loss, and optimize it." msgstr "" +"用 MXNet 定义训练和损失。我们在数据集上循环训练模型,测量相应的损失,并对其进" +"行优化。" #: ../../source/tutorial-quickstart-mxnet.rst:111 msgid "" -"Next, we define the validation of our machine learning model. We loop " -"over the test set and measure both loss and accuracy on the test set." +"Next, we define the validation of our machine learning model. We loop over " +"the test set and measure both loss and accuracy on the test set." msgstr "" +"接下来,我们定义机器学习模型的验证。我们在测试集上循环,测量测试集上的损失和" +"准确率。" #: ../../source/tutorial-quickstart-mxnet.rst:135 msgid "" -"After defining the training and testing of a MXNet machine learning " -"model, we use these functions to implement a Flower client." +"After defining the training and testing of a MXNet machine learning model, " +"we use these functions to implement a Flower client." msgstr "" +"在定义了 MXNet 机器学习模型的训练和测试后,我们使用这些函数实现了 Flower 客户" +"端。" #: ../../source/tutorial-quickstart-mxnet.rst:137 msgid "Our Flower clients will use a simple :code:`Sequential` model:" -msgstr "" +msgstr "我们的 Flower 客户端将使用简单的 :code:`Sequential` 模型:" #: ../../source/tutorial-quickstart-mxnet.rst:156 msgid "" -"After loading the dataset with :code:`load_data()` we perform one forward" -" propagation to initialize the model and model parameters with " -":code:`model(init)`. Next, we implement a Flower client." +"After loading the dataset with :code:`load_data()` we perform one forward " +"propagation to initialize the model and model parameters with :code:" +"`model(init)`. Next, we implement a Flower client." msgstr "" +"使用 :code:`load_data()` 加载数据集后,我们会执行一次前向传播,使用 :code:" +"`model(init)` 初始化模型和模型参数。接下来,我们实现一个 Flower 客户端。" #: ../../source/tutorial-quickstart-mxnet.rst:158 #: ../../source/tutorial-quickstart-pytorch.rst:144 #: ../../source/tutorial-quickstart-tensorflow.rst:54 msgid "" -"The Flower server interacts with clients through an interface called " -":code:`Client`. When the server selects a particular client for training," -" it sends training instructions over the network. The client receives " -"those instructions and calls one of the :code:`Client` methods to run " -"your code (i.e., to train the neural network we defined earlier)." +"The Flower server interacts with clients through an interface called :code:" +"`Client`. When the server selects a particular client for training, it sends " +"training instructions over the network. The client receives those " +"instructions and calls one of the :code:`Client` methods to run your code (i." +"e., to train the neural network we defined earlier)." msgstr "" +"Flower 服务器通过一个名为 :code:`Client` 的接口与客户端交互。当服务器选择一个" +"特定的客户端进行训练时,它会通过网络发送训练指令。客户端接收到这些指令后,会" +"调用 :code:`Client` 方法之一来运行你的代码(即训练我们之前定义的神经网络)。" #: ../../source/tutorial-quickstart-mxnet.rst:164 msgid "" -"Flower provides a convenience class called :code:`NumPyClient` which " -"makes it easier to implement the :code:`Client` interface when your " -"workload uses MXNet. Implementing :code:`NumPyClient` usually means " -"defining the following methods (:code:`set_parameters` is optional " -"though):" +"Flower provides a convenience class called :code:`NumPyClient` which makes " +"it easier to implement the :code:`Client` interface when your workload uses " +"MXNet. Implementing :code:`NumPyClient` usually means defining the following " +"methods (:code:`set_parameters` is optional though):" msgstr "" +"Flower 提供了一个名为 :code:`NumPyClient` 的便利类,当您的工作负载使用 MXNet " +"时,它可以让您更轻松地实现 :code:`Client` 接口。实现 :code:`NumPyClient` 通常" +"意味着定义以下方法(:code:`set_parameters` 是可选的):" #: ../../source/tutorial-quickstart-mxnet.rst:170 #: ../../source/tutorial-quickstart-pytorch.rst:156 #: ../../source/tutorial-quickstart-scikitlearn.rst:109 msgid "return the model weight as a list of NumPy ndarrays" -msgstr "" +msgstr "以 NumPy ndarrays 列表形式返回模型权重" #: ../../source/tutorial-quickstart-mxnet.rst:171 #: ../../source/tutorial-quickstart-pytorch.rst:157 #: ../../source/tutorial-quickstart-scikitlearn.rst:111 msgid ":code:`set_parameters` (optional)" -msgstr "" +msgstr ":code:`set_parameters` (可选)" #: ../../source/tutorial-quickstart-mxnet.rst:172 #: ../../source/tutorial-quickstart-pytorch.rst:158 #: ../../source/tutorial-quickstart-scikitlearn.rst:111 msgid "" -"update the local model weights with the parameters received from the " -"server" -msgstr "" +"update the local model weights with the parameters received from the server" +msgstr "用从服务器接收到的参数更新本地模型权重" #: ../../source/tutorial-quickstart-mxnet.rst:174 #: ../../source/tutorial-quickstart-pytorch.rst:160 #: ../../source/tutorial-quickstart-scikitlearn.rst:114 msgid "set the local model weights" -msgstr "" +msgstr "设置本地模型权重" #: ../../source/tutorial-quickstart-mxnet.rst:175 #: ../../source/tutorial-quickstart-pytorch.rst:161 #: ../../source/tutorial-quickstart-scikitlearn.rst:115 msgid "train the local model" -msgstr "" +msgstr "训练本地模型" #: ../../source/tutorial-quickstart-mxnet.rst:176 #: ../../source/tutorial-quickstart-pytorch.rst:162 #: ../../source/tutorial-quickstart-scikitlearn.rst:116 msgid "receive the updated local model weights" -msgstr "" +msgstr "接收更新的本地模型权重" #: ../../source/tutorial-quickstart-mxnet.rst:178 #: ../../source/tutorial-quickstart-pytorch.rst:164 #: ../../source/tutorial-quickstart-scikitlearn.rst:118 msgid "test the local model" -msgstr "" +msgstr "测试本地模型" #: ../../source/tutorial-quickstart-mxnet.rst:180 msgid "They can be implemented in the following way:" -msgstr "" +msgstr "它们可以通过以下方式实现:" #: ../../source/tutorial-quickstart-mxnet.rst:210 msgid "" -"We can now create an instance of our class :code:`MNISTClient` and add " -"one line to actually run this client:" +"We can now create an instance of our class :code:`MNISTClient` and add one " +"line to actually run this client:" msgstr "" +"现在我们可以创建一个 :code:`MNISTClient` 类的实例,并添加一行来实际运行该客户" +"端:" #: ../../source/tutorial-quickstart-mxnet.rst:217 #: ../../source/tutorial-quickstart-scikitlearn.rst:150 msgid "" -"That's it for the client. We only have to implement :code:`Client` or " -":code:`NumPyClient` and call :code:`fl.client.start_client()`. The string " -":code:`\"0.0.0.0:8080\"` tells the client which server to connect to. In " -"our case we can run the server and the client on the same machine, " -"therefore we use :code:`\"0.0.0.0:8080\"`. If we run a truly federated " -"workload with the server and clients running on different machines, all " -"that needs to change is the :code:`server_address` we pass to the client." +"That's it for the client. We only have to implement :code:`Client` or :code:" +"`NumPyClient` and call :code:`fl.client.start_client()`. The string :code:" +"`\"0.0.0.0:8080\"` tells the client which server to connect to. In our case " +"we can run the server and the client on the same machine, therefore we use :" +"code:`\"0.0.0.0:8080\"`. If we run a truly federated workload with the " +"server and clients running on different machines, all that needs to change " +"is the :code:`server_address` we pass to the client." msgstr "" #: ../../source/tutorial-quickstart-mxnet.rst:239 @@ -11025,6 +13039,8 @@ msgid "" "federated learning in action. Federated learning systems usually have a " "server and multiple clients. We therefore have to start the server first:" msgstr "" +"客户端和服务器都准备就绪后,我们现在就可以运行一切,看看联合学习的运行情况。" +"联合学习系统通常有一个服务器和多个客户端。因此,我们必须先启动服务器:" #: ../../source/tutorial-quickstart-mxnet.rst:247 #: ../../source/tutorial-quickstart-pytorch.rst:226 @@ -11032,9 +13048,11 @@ msgstr "" #: ../../source/tutorial-quickstart-tensorflow.rst:122 #: ../../source/tutorial-quickstart-xgboost.rst:530 msgid "" -"Once the server is running we can start the clients in different " -"terminals. Open a new terminal and start the first client:" +"Once the server is running we can start the clients in different terminals. " +"Open a new terminal and start the first client:" msgstr "" +"服务器运行后,我们就可以在不同终端启动客户端了。打开一个新终端,启动第一个客" +"户端:" #: ../../source/tutorial-quickstart-mxnet.rst:254 #: ../../source/tutorial-quickstart-pytorch.rst:233 @@ -11042,59 +13060,69 @@ msgstr "" #: ../../source/tutorial-quickstart-tensorflow.rst:129 #: ../../source/tutorial-quickstart-xgboost.rst:537 msgid "Open another terminal and start the second client:" -msgstr "" +msgstr "打开另一台终端,启动第二个客户端:" #: ../../source/tutorial-quickstart-mxnet.rst:260 #: ../../source/tutorial-quickstart-pytorch.rst:239 #: ../../source/tutorial-quickstart-scikitlearn.rst:237 #: ../../source/tutorial-quickstart-xgboost.rst:543 msgid "" -"Each client will have its own dataset. You should now see how the " -"training does in the very first terminal (the one that started the " -"server):" +"Each client will have its own dataset. You should now see how the training " +"does in the very first terminal (the one that started the server):" msgstr "" +"每个客户端都有自己的数据集。现在你应该看到第一个终端(启动服务器的终端)的训" +"练效果了:" #: ../../source/tutorial-quickstart-mxnet.rst:292 msgid "" "Congratulations! You've successfully built and run your first federated " -"learning system. The full `source code " -"`_ for this example can be found in :code:`examples" -"/quickstart-mxnet`." +"learning system. The full `source code `_ for this example can be found " +"in :code:`examples/quickstart-mxnet`." msgstr "" +"恭喜您!您已经成功构建并运行了第一个联合学习系统。本示例的完整源代码 " +"`_ 可在 :code:`examples/quickstart-mxnet` 中找到。" #: ../../source/tutorial-quickstart-pandas.rst:-1 msgid "" -"Check out this Federated Learning quickstart tutorial for using Flower " -"with Pandas to perform Federated Analytics." +"Check out this Federated Learning quickstart tutorial for using Flower with " +"Pandas to perform Federated Analytics." msgstr "" +"查看此 Federated Learning 快速入门教程,了解如何使用 Flower 和 Pandas 执行 " +"Federated Analytics。" #: ../../source/tutorial-quickstart-pandas.rst:5 msgid "Quickstart Pandas" -msgstr "" +msgstr "快速入门熊猫" #: ../../source/tutorial-quickstart-pandas.rst:10 msgid "Let's build a federated analytics system using Pandas and Flower!" -msgstr "" +msgstr "让我们使用 Pandas 和 Flower 建立一个联合分析系统!" #: ../../source/tutorial-quickstart-pandas.rst:12 msgid "" -"Please refer to the `full code example " -"`_ " -"to learn more." +"Please refer to the `full code example `_ to learn more." msgstr "" +"请参阅 \"完整代码示例 `_\" 了解更多信息。" #: ../../source/tutorial-quickstart-pytorch.rst:-1 msgid "" -"Check out this Federated Learning quickstart tutorial for using Flower " -"with PyTorch to train a CNN model on MNIST." +"Check out this Federated Learning quickstart tutorial for using Flower with " +"PyTorch to train a CNN model on MNIST." msgstr "" +"查看此 Federated Learning 快速入门教程,了解如何使用 Flower 和 PyTorch 在 " +"MNIST 上训练 CNN 模型。" #: ../../source/tutorial-quickstart-pytorch.rst:13 msgid "" -"In this tutorial we will learn how to train a Convolutional Neural " -"Network on CIFAR10 using Flower and PyTorch." +"In this tutorial we will learn how to train a Convolutional Neural Network " +"on CIFAR10 using Flower and PyTorch." msgstr "" +"在本教程中,我们将学习如何使用 Flower 和 PyTorch 在 CIFAR10 上训练卷积神经网" +"络。" #: ../../source/tutorial-quickstart-pytorch.rst:15 #: ../../source/tutorial-quickstart-xgboost.rst:36 @@ -11103,139 +13131,164 @@ msgid "" "everything within a `virtualenv `_." msgstr "" +"首先,建议创建一个虚拟环境,并在 `virtualenv `_ 中运行一切。" #: ../../source/tutorial-quickstart-pytorch.rst:29 msgid "" -"Since we want to use PyTorch to solve a computer vision task, let's go " -"ahead and install PyTorch and the **torchvision** library:" +"Since we want to use PyTorch to solve a computer vision task, let's go ahead " +"and install PyTorch and the **torchvision** library:" msgstr "" +"既然我们想用 PyTorch 解决计算机视觉任务,那就继续安装 PyTorch 和 " +"**torchvision** 库吧:" #: ../../source/tutorial-quickstart-pytorch.rst:39 msgid "" "Now that we have all our dependencies installed, let's run a simple " -"distributed training with two clients and one server. Our training " -"procedure and network architecture are based on PyTorch's `Deep Learning " -"with PyTorch " +"distributed training with two clients and one server. Our training procedure " +"and network architecture are based on PyTorch's `Deep Learning with PyTorch " "`_." msgstr "" +"现在我们已经安装了所有的依赖项,让我们用两个客户端和一个服务器来运行一个简单" +"的分布式训练。我们的训练过程和网络架构基于 PyTorch 的《Deep Learning with " +"PyTorch `_》。" #: ../../source/tutorial-quickstart-pytorch.rst:41 msgid "" "In a file called :code:`client.py`, import Flower and PyTorch related " "packages:" -msgstr "" +msgstr "在名为 :code:`client.py` 的文件中,导入 Flower 和 PyTorch 相关软件包:" #: ../../source/tutorial-quickstart-pytorch.rst:56 msgid "In addition, we define the device allocation in PyTorch with:" -msgstr "" +msgstr "此外,我们还在 PyTorch 中定义了设备分配:" #: ../../source/tutorial-quickstart-pytorch.rst:62 msgid "" "We use PyTorch to load CIFAR10, a popular colored image classification " -"dataset for machine learning. The PyTorch :code:`DataLoader()` downloads " -"the training and test data that are then normalized." +"dataset for machine learning. The PyTorch :code:`DataLoader()` downloads the " +"training and test data that are then normalized." msgstr "" +"我们使用 PyTorch 来加载 CIFAR10,这是一个用于机器学习的流行彩色图像分类数据" +"集。PyTorch :code:`DataLoader()`下载训练数据和测试数据,然后进行归一化处理。" #: ../../source/tutorial-quickstart-pytorch.rst:78 msgid "" -"Define the loss and optimizer with PyTorch. The training of the dataset " -"is done by looping over the dataset, measure the corresponding loss and " +"Define the loss and optimizer with PyTorch. The training of the dataset is " +"done by looping over the dataset, measure the corresponding loss and " "optimize it." msgstr "" +"使用 PyTorch 定义损失和优化器。数据集的训练是通过循环数据集、测量相应的损失并" +"对其进行优化来完成的。" #: ../../source/tutorial-quickstart-pytorch.rst:94 msgid "" -"Define then the validation of the machine learning network. We loop over" -" the test set and measure the loss and accuracy of the test set." +"Define then the validation of the machine learning network. We loop over " +"the test set and measure the loss and accuracy of the test set." msgstr "" +"然后定义机器学习网络的验证。我们在测试集上循环,测量测试集的损失和准确率。" #: ../../source/tutorial-quickstart-pytorch.rst:113 msgid "" -"After defining the training and testing of a PyTorch machine learning " -"model, we use the functions for the Flower clients." +"After defining the training and testing of a PyTorch machine learning model, " +"we use the functions for the Flower clients." msgstr "" +"在定义了 PyTorch 机器学习模型的训练和测试之后,我们将这些功能用于 Flower 客户" +"端。" #: ../../source/tutorial-quickstart-pytorch.rst:115 msgid "" -"The Flower clients will use a simple CNN adapted from 'PyTorch: A 60 " -"Minute Blitz':" -msgstr "" +"The Flower clients will use a simple CNN adapted from 'PyTorch: A 60 Minute " +"Blitz':" +msgstr "Flower 客户端将使用一个简单的从“PyTorch: 60 分钟突击\"改编的CNN:" #: ../../source/tutorial-quickstart-pytorch.rst:142 msgid "" "After loading the data set with :code:`load_data()` we define the Flower " "interface." -msgstr "" +msgstr "使用 :code:`load_data()` 加载数据集后,我们定义了 Flower 接口。" #: ../../source/tutorial-quickstart-pytorch.rst:150 msgid "" -"Flower provides a convenience class called :code:`NumPyClient` which " -"makes it easier to implement the :code:`Client` interface when your " -"workload uses PyTorch. Implementing :code:`NumPyClient` usually means " -"defining the following methods (:code:`set_parameters` is optional " -"though):" +"Flower provides a convenience class called :code:`NumPyClient` which makes " +"it easier to implement the :code:`Client` interface when your workload uses " +"PyTorch. Implementing :code:`NumPyClient` usually means defining the " +"following methods (:code:`set_parameters` is optional though):" msgstr "" +"Flower 提供了一个名为 :code:`NumPyClient` 的便利类,当您的工作负载使用 " +"PyTorch 时,它使 :code:`Client` 接口的实现变得更容易。实现 :code:" +"`NumPyClient` 通常意味着定义以下方法(:code:`set_parameters` 是可选的):" #: ../../source/tutorial-quickstart-pytorch.rst:166 msgid "which can be implemented in the following way:" -msgstr "" +msgstr "可以通过以下方式实现:" #: ../../source/tutorial-quickstart-pytorch.rst:189 #: ../../source/tutorial-quickstart-tensorflow.rst:82 msgid "" -"We can now create an instance of our class :code:`CifarClient` and add " -"one line to actually run this client:" +"We can now create an instance of our class :code:`CifarClient` and add one " +"line to actually run this client:" msgstr "" +"现在我们可以创建一个 :code:`CifarClient` 类的实例,并添加一行来实际运行该客户" +"端:" #: ../../source/tutorial-quickstart-pytorch.rst:196 #: ../../source/tutorial-quickstart-tensorflow.rst:90 msgid "" -"That's it for the client. We only have to implement :code:`Client` or " -":code:`NumPyClient` and call :code:`fl.client.start_client()`. The string :code:`\"[::]:8080\"` " -"tells the client which server to connect to. In our case we can run the " -"server and the client on the same machine, therefore we use " -":code:`\"[::]:8080\"`. If we run a truly federated workload with the " -"server and clients running on different machines, all that needs to " -"change is the :code:`server_address` we point the client at." +"That's it for the client. We only have to implement :code:`Client` or :code:" +"`NumPyClient` and call :code:`fl.client.start_client()`. The string :code:" +"`\"[::]:8080\"` tells the client which server to connect to. In our case we " +"can run the server and the client on the same machine, therefore we use :" +"code:`\"[::]:8080\"`. If we run a truly federated workload with the server " +"and clients running on different machines, all that needs to change is the :" +"code:`server_address` we point the client at." msgstr "" #: ../../source/tutorial-quickstart-pytorch.rst:271 msgid "" "Congratulations! You've successfully built and run your first federated " -"learning system. The full `source code " -"`_ for this example can be found in :code:`examples" -"/quickstart-pytorch`." +"learning system. The full `source code `_ for this example can be found " +"in :code:`examples/quickstart-pytorch`." msgstr "" +"恭喜您!您已经成功构建并运行了第一个联合学习系统。本示例的完整源代码 " +"`_ 可以在 :code:`examples/quickstart-pytorch` 中找到。" #: ../../source/tutorial-quickstart-pytorch-lightning.rst:-1 msgid "" -"Check out this Federated Learning quickstart tutorial for using Flower " -"with PyTorch Lightning to train an Auto Encoder model on MNIST." +"Check out this Federated Learning quickstart tutorial for using Flower with " +"PyTorch Lightning to train an Auto Encoder model on MNIST." msgstr "" +"查看此 Federated Learning 快速入门教程,了解如何使用 Flower 和 PyTorch " +"Lightning 在 MNIST 上训练自动编码器模型。" #: ../../source/tutorial-quickstart-pytorch-lightning.rst:5 msgid "Quickstart PyTorch Lightning" -msgstr "" +msgstr "快速入门 PyTorch Lightning" #: ../../source/tutorial-quickstart-pytorch-lightning.rst:10 msgid "" -"Let's build a horizontal federated learning system using PyTorch " -"Lightning and Flower!" -msgstr "" +"Let's build a horizontal federated learning system using PyTorch Lightning " +"and Flower!" +msgstr "让我们使用 PyTorch Lightning 和 Flower 构建一个水平联合学习系统!" #: ../../source/tutorial-quickstart-pytorch-lightning.rst:12 msgid "" -"Please refer to the `full code example " -"`_ to learn more." +"Please refer to the `full code example `_ to learn more." msgstr "" +"请参阅 \"完整代码示例 `_\" 了解更多信息。" #: ../../source/tutorial-quickstart-scikitlearn.rst:-1 msgid "" -"Check out this Federated Learning quickstart tutorial for using Flower " -"with scikit-learn to train a linear regression model." +"Check out this Federated Learning quickstart tutorial for using Flower with " +"scikit-learn to train a linear regression model." msgstr "" +"查看此 Federated Learning 快速入门教程,了解如何使用 Flower 和 scikit-learn " +"训练线性回归模型。" #: ../../source/tutorial-quickstart-scikitlearn.rst:5 msgid "Quickstart scikit-learn" @@ -11243,35 +13296,41 @@ msgstr "" #: ../../source/tutorial-quickstart-scikitlearn.rst:10 msgid "" -"In this tutorial, we will learn how to train a :code:`Logistic " -"Regression` model on MNIST using Flower and scikit-learn." +"In this tutorial, we will learn how to train a :code:`Logistic Regression` " +"model on MNIST using Flower and scikit-learn." msgstr "" +"在本教程中,我们将学习如何使用 Flower 和 scikit-learn 在 MNIST 上训练一个 :" +"code:`Logistic Regression` 模型。" #: ../../source/tutorial-quickstart-scikitlearn.rst:26 msgid "Since we want to use scikt-learn, let's go ahead and install it:" -msgstr "" +msgstr "既然我们要使用 scikt-learn,那就继续安装吧:" #: ../../source/tutorial-quickstart-scikitlearn.rst:32 msgid "Or simply install all dependencies using Poetry:" -msgstr "" +msgstr "或者直接使用 Poetry 安装所有依赖项:" #: ../../source/tutorial-quickstart-scikitlearn.rst:42 msgid "" "Now that we have all our dependencies installed, let's run a simple " "distributed training with two clients and one server. However, before " -"setting up the client and server, we will define all functionalities that" -" we need for our federated learning setup within :code:`utils.py`. The " -":code:`utils.py` contains different functions defining all the machine " -"learning basics:" +"setting up the client and server, we will define all functionalities that we " +"need for our federated learning setup within :code:`utils.py`. The :code:" +"`utils.py` contains different functions defining all the machine learning " +"basics:" msgstr "" +"现在我们已经安装了所有的依赖项,让我们用两个客户端和一个服务器来运行一个简单" +"的分布式训练。不过,在设置客户端和服务器之前,我们将在 :code:`utils.py` 中定" +"义联合学习设置所需的所有功能。:code:`utils.py`包含定义所有机器学习基础知识的" +"不同函数:" #: ../../source/tutorial-quickstart-scikitlearn.rst:45 msgid ":code:`get_model_parameters()`" -msgstr "" +msgstr "代码:`get_model_parameters()` 获取模型参数" #: ../../source/tutorial-quickstart-scikitlearn.rst:46 msgid "Returns the paramters of a :code:`sklearn` LogisticRegression model" -msgstr "" +msgstr "返回 :code:`sklearn` LogisticRegression 模型的参数" #: ../../source/tutorial-quickstart-scikitlearn.rst:47 msgid ":code:`set_model_params()`" @@ -11287,7 +13346,7 @@ msgstr "" #: ../../source/tutorial-quickstart-scikitlearn.rst:50 msgid "Initializes the model parameters that the Flower server will ask for" -msgstr "" +msgstr "初始化 Flower 服务器将要求的模型参数" #: ../../source/tutorial-quickstart-scikitlearn.rst:51 msgid ":code:`load_mnist()`" @@ -11295,7 +13354,7 @@ msgstr "" #: ../../source/tutorial-quickstart-scikitlearn.rst:52 msgid "Loads the MNIST dataset using OpenML" -msgstr "" +msgstr "使用 OpenML 加载 MNIST 数据集" #: ../../source/tutorial-quickstart-scikitlearn.rst:53 msgid ":code:`shuffle()`" @@ -11303,7 +13362,7 @@ msgstr "" #: ../../source/tutorial-quickstart-scikitlearn.rst:54 msgid "Shuffles data and its label" -msgstr "" +msgstr "对数据及其标签进行洗牌" #: ../../source/tutorial-quickstart-scikitlearn.rst:56 msgid ":code:`partition()`" @@ -11311,186 +13370,227 @@ msgstr "" #: ../../source/tutorial-quickstart-scikitlearn.rst:56 msgid "Splits datasets into a number of partitions" -msgstr "" +msgstr "将数据集分割成多个分区" #: ../../source/tutorial-quickstart-scikitlearn.rst:58 msgid "" -"Please check out :code:`utils.py` `here " -"`_ for more details. The pre-defined functions are used in" -" the :code:`client.py` and imported. The :code:`client.py` also requires " -"to import several packages such as Flower and scikit-learn:" +"Please check out :code:`utils.py` `here `_ for more details. The pre-" +"defined functions are used in the :code:`client.py` and imported. The :code:" +"`client.py` also requires to import several packages such as Flower and " +"scikit-learn:" msgstr "" +"更多详情请查看 :code:`utils.py`` 这里 `_。在 :code:`client.py` 中使用并" +"导入了预定义函数。:code:`client.py` 还需要导入几个软件包,如 Flower 和 " +"scikit-learn:" #: ../../source/tutorial-quickstart-scikitlearn.rst:73 msgid "" -"We load the MNIST dataset from `OpenML `_, " -"a popular image classification dataset of handwritten digits for machine " -"learning. The utility :code:`utils.load_mnist()` downloads the training " -"and test data. The training set is split afterwards into 10 partitions " -"with :code:`utils.partition()`." +"We load the MNIST dataset from `OpenML `_, a " +"popular image classification dataset of handwritten digits for machine " +"learning. The utility :code:`utils.load_mnist()` downloads the training and " +"test data. The training set is split afterwards into 10 partitions with :" +"code:`utils.partition()`." msgstr "" +"我们从 `OpenML `_ 中加载 MNIST 数据集,这是一个" +"用于机器学习的流行手写数字图像分类数据集。实用程序 :code:`utils." +"load_mnist()` 下载训练和测试数据。然后使用 :code:`utils.partition()`将训练集" +"分割成 10 个分区。" #: ../../source/tutorial-quickstart-scikitlearn.rst:85 msgid "" -"Next, the logistic regression model is defined and initialized with " -":code:`utils.set_initial_params()`." +"Next, the logistic regression model is defined and initialized with :code:" +"`utils.set_initial_params()`." msgstr "" +"接下来,使用 :code:`utils.set_initial_params()` 对逻辑回归模型进行定义和初始" +"化。" #: ../../source/tutorial-quickstart-scikitlearn.rst:97 msgid "" -"The Flower server interacts with clients through an interface called " -":code:`Client`. When the server selects a particular client for training," -" it sends training instructions over the network. The client receives " -"those instructions and calls one of the :code:`Client` methods to run " -"your code (i.e., to fit the logistic regression we defined earlier)." +"The Flower server interacts with clients through an interface called :code:" +"`Client`. When the server selects a particular client for training, it sends " +"training instructions over the network. The client receives those " +"instructions and calls one of the :code:`Client` methods to run your code (i." +"e., to fit the logistic regression we defined earlier)." msgstr "" +"Flower 服务器通过一个名为 :code:`Client` 的接口与客户端交互。当服务器选择一个" +"特定的客户端进行训练时,它会通过网络发送训练指令。客户端接收到这些指令后,会" +"调用 :code:`Client` 方法之一来运行您的代码(即拟合我们之前定义的逻辑回归)。" #: ../../source/tutorial-quickstart-scikitlearn.rst:103 msgid "" -"Flower provides a convenience class called :code:`NumPyClient` which " -"makes it easier to implement the :code:`Client` interface when your " -"workload uses scikit-learn. Implementing :code:`NumPyClient` usually " -"means defining the following methods (:code:`set_parameters` is optional " -"though):" +"Flower provides a convenience class called :code:`NumPyClient` which makes " +"it easier to implement the :code:`Client` interface when your workload uses " +"scikit-learn. Implementing :code:`NumPyClient` usually means defining the " +"following methods (:code:`set_parameters` is optional though):" msgstr "" +"Flower 提供了一个名为 :code:`NumPyClient` 的便利类,当你的工作负载使用 " +"scikit-learn 时,它可以让你更容易地实现 :code:`Client` 接口。实现 :code:" +"`NumPyClient` 通常意味着定义以下方法(:code:`set_parameters` 是可选的):" #: ../../source/tutorial-quickstart-scikitlearn.rst:112 msgid "is directly imported with :code:`utils.set_model_params()`" -msgstr "" +msgstr "直接导入 :code:`utils.set_model_params()`" #: ../../source/tutorial-quickstart-scikitlearn.rst:120 msgid "The methods can be implemented in the following way:" -msgstr "" +msgstr "这些方法可以通过以下方式实现:" #: ../../source/tutorial-quickstart-scikitlearn.rst:143 msgid "" -"We can now create an instance of our class :code:`MnistClient` and add " -"one line to actually run this client:" +"We can now create an instance of our class :code:`MnistClient` and add one " +"line to actually run this client:" msgstr "" +"现在我们可以创建一个 :code:`MnistClient` 类的实例,并添加一行来实际运行该客户" +"端:" #: ../../source/tutorial-quickstart-scikitlearn.rst:159 msgid "" "The following Flower server is a little bit more advanced and returns an " -"evaluation function for the server-side evaluation. First, we import " -"again all required libraries such as Flower and scikit-learn." +"evaluation function for the server-side evaluation. First, we import again " +"all required libraries such as Flower and scikit-learn." msgstr "" +"下面的 Flower 服务器更先进一些,会返回一个用于服务器端评估的评估函数。首先," +"我们再次导入所有需要的库,如 Flower 和 scikit-learn。" #: ../../source/tutorial-quickstart-scikitlearn.rst:162 msgid ":code:`server.py`, import Flower and start the server:" -msgstr "" +msgstr ":code:`server.py`, import Flower 并启动服务器:" #: ../../source/tutorial-quickstart-scikitlearn.rst:173 msgid "" -"The number of federated learning rounds is set in :code:`fit_round()` and" -" the evaluation is defined in :code:`get_evaluate_fn()`. The evaluation " +"The number of federated learning rounds is set in :code:`fit_round()` and " +"the evaluation is defined in :code:`get_evaluate_fn()`. The evaluation " "function is called after each federated learning round and gives you " "information about loss and accuracy." msgstr "" +"联合学习轮数在 :code:`fit_round()` 中设置,评估在 :code:`get_evaluate_fn()` " +"中定义。每轮联合学习后都会调用评估函数,并提供有关损失和准确率的信息。" #: ../../source/tutorial-quickstart-scikitlearn.rst:198 msgid "" -"The :code:`main` contains the server-side parameter initialization " -":code:`utils.set_initial_params()` as well as the aggregation strategy " -":code:`fl.server.strategy:FedAvg()`. The strategy is the default one, " -"federated averaging (or FedAvg), with two clients and evaluation after " -"each federated learning round. The server can be started with the command" -" :code:`fl.server.start_server(server_address=\"0.0.0.0:8080\", " -"strategy=strategy, config=fl.server.ServerConfig(num_rounds=3))`." +"The :code:`main` contains the server-side parameter initialization :code:" +"`utils.set_initial_params()` as well as the aggregation strategy :code:`fl." +"server.strategy:FedAvg()`. The strategy is the default one, federated " +"averaging (or FedAvg), with two clients and evaluation after each federated " +"learning round. The server can be started with the command :code:`fl.server." +"start_server(server_address=\"0.0.0.0:8080\", strategy=strategy, config=fl." +"server.ServerConfig(num_rounds=3))`." msgstr "" +"代码:`main`包含服务器端参数初始化 :代码:`utils.set_initial_params()`以及聚合" +"策略 :代码:`fl.server.strategy:FedAvg()`。该策略是默认的联合平均(或 FedAvg)" +"策略,有两个客户端,在每轮联合学习后进行评估。可以使用 :code:`fl.server." +"start_server(server_address=\"0.0.0.0:8080\", strategy=strategy, config=fl." +"server.ServerConfig(num_rounds=3))` 命令启动服务器。" #: ../../source/tutorial-quickstart-scikitlearn.rst:217 msgid "" "With both client and server ready, we can now run everything and see " "federated learning in action. Federated learning systems usually have a " -"server and multiple clients. We, therefore, have to start the server " -"first:" +"server and multiple clients. We, therefore, have to start the server first:" msgstr "" +"客户端和服务器都准备就绪后,我们现在就可以运行一切,看看联合学习的运行情况。" +"联合学习系统通常有一个服务器和多个客户端。因此,我们必须先启动服务器:" #: ../../source/tutorial-quickstart-scikitlearn.rst:271 msgid "" "Congratulations! You've successfully built and run your first federated " -"learning system. The full `source code " -"`_ for this example can be found in :code:`examples/sklearn-logreg-" -"mnist`." +"learning system. The full `source code `_ for this example can be found in :code:" +"`examples/sklearn-logreg-mnist`." msgstr "" +"恭喜您!您已经成功构建并运行了第一个联合学习系统。本示例的完整源代码 " +"`_ 可" +"以在 :code:`examples/sklearn-logreg-mnist` 中找到。" #: ../../source/tutorial-quickstart-tensorflow.rst:-1 msgid "" -"Check out this Federated Learning quickstart tutorial for using Flower " -"with TensorFlow to train a MobilNetV2 model on CIFAR-10." +"Check out this Federated Learning quickstart tutorial for using Flower with " +"TensorFlow to train a MobilNetV2 model on CIFAR-10." msgstr "" +"查看此 Federated Learning 快速入门教程,了解如何使用 Flower 和 TensorFlow 在 " +"CIFAR-10 上训练 MobilNetV2 模型。" #: ../../source/tutorial-quickstart-tensorflow.rst:5 msgid "Quickstart TensorFlow" -msgstr "" +msgstr "快速入门 TensorFlow" #: ../../source/tutorial-quickstart-tensorflow.rst:13 msgid "Let's build a federated learning system in less than 20 lines of code!" -msgstr "" +msgstr "让我们用不到 20 行代码构建一个联邦学习系统!" #: ../../source/tutorial-quickstart-tensorflow.rst:15 msgid "Before Flower can be imported we have to install it:" -msgstr "" +msgstr "在导入 Flower 之前,我们必须先安装它:" #: ../../source/tutorial-quickstart-tensorflow.rst:21 msgid "" -"Since we want to use the Keras API of TensorFlow (TF), we have to install" -" TF as well:" -msgstr "" +"Since we want to use the Keras API of TensorFlow (TF), we have to install TF " +"as well:" +msgstr "由于我们要使用 TensorFlow (TF) 的 Keras API,因此还必须安装 TF:" #: ../../source/tutorial-quickstart-tensorflow.rst:31 msgid "Next, in a file called :code:`client.py`, import Flower and TensorFlow:" -msgstr "" +msgstr "接下来,在名为 :code:`client.py` 的文件中导入 Flower 和 TensorFlow:" #: ../../source/tutorial-quickstart-tensorflow.rst:38 msgid "" -"We use the Keras utilities of TF to load CIFAR10, a popular colored image" -" classification dataset for machine learning. The call to " -":code:`tf.keras.datasets.cifar10.load_data()` downloads CIFAR10, caches " -"it locally, and then returns the entire training and test set as NumPy " -"ndarrays." +"We use the Keras utilities of TF to load CIFAR10, a popular colored image " +"classification dataset for machine learning. The call to :code:`tf.keras." +"datasets.cifar10.load_data()` downloads CIFAR10, caches it locally, and then " +"returns the entire training and test set as NumPy ndarrays." msgstr "" +"我们使用 TF 的 Keras 实用程序加载 CIFAR10,这是一个用于机器学习的流行彩色图像" +"分类数据集。调用 :code:`tf.keras.datasets.cifar10.load_data()` 会下载 " +"CIFAR10,将其缓存到本地,然后以 NumPy ndarrays 的形式返回整个训练集和测试集。" #: ../../source/tutorial-quickstart-tensorflow.rst:47 msgid "" -"Next, we need a model. For the purpose of this tutorial, we use " -"MobilNetV2 with 10 output classes:" +"Next, we need a model. For the purpose of this tutorial, we use MobilNetV2 " +"with 10 output classes:" msgstr "" +"接下来,我们需要一个模型。在本教程中,我们使用带有 10 个输出类的 MobilNetV2:" #: ../../source/tutorial-quickstart-tensorflow.rst:60 msgid "" -"Flower provides a convenience class called :code:`NumPyClient` which " -"makes it easier to implement the :code:`Client` interface when your " -"workload uses Keras. The :code:`NumPyClient` interface defines three " -"methods which can be implemented in the following way:" +"Flower provides a convenience class called :code:`NumPyClient` which makes " +"it easier to implement the :code:`Client` interface when your workload uses " +"Keras. The :code:`NumPyClient` interface defines three methods which can be " +"implemented in the following way:" msgstr "" +"Flower 提供了一个名为 :code:`NumPyClient` 的便利类,当您的工作负载使用 Keras " +"时,该类可以更轻松地实现 :code:`Client` 接口。:code:`NumPyClient` 接口定义了" +"三个方法,可以通过以下方式实现:" #: ../../source/tutorial-quickstart-tensorflow.rst:135 msgid "Each client will have its own dataset." -msgstr "" +msgstr "每个客户都有自己的数据集。" #: ../../source/tutorial-quickstart-tensorflow.rst:137 msgid "" -"You should now see how the training does in the very first terminal (the " -"one that started the server):" -msgstr "" +"You should now see how the training does in the very first terminal (the one " +"that started the server):" +msgstr "现在你应该能在第一个终端(启动服务器的终端)看到训练的效果了:" #: ../../source/tutorial-quickstart-tensorflow.rst:169 msgid "" "Congratulations! You've successfully built and run your first federated " -"learning system. The full `source code " -"`_ for this can be found in :code:`examples" -"/quickstart-tensorflow/client.py`." +"learning system. The full `source code `_ for this can be found in :" +"code:`examples/quickstart-tensorflow/client.py`." msgstr "" +"恭喜您!您已经成功构建并运行了第一个联合学习系统。完整的源代码 `_ " +"可以在 :code:`examples/quickstart-tensorflow/client.py` 中找到。" #: ../../source/tutorial-quickstart-xgboost.rst:-1 msgid "" -"Check out this Federated Learning quickstart tutorial for using Flower " -"with XGBoost to train classification models on trees." +"Check out this Federated Learning quickstart tutorial for using Flower with " +"XGBoost to train classification models on trees." msgstr "" +"查看此 Federated Learning 快速入门教程,了解如何使用 Flower 和 XGBoost 在树上" +"训练分类模型。" #: ../../source/tutorial-quickstart-xgboost.rst:5 msgid "Quickstart XGBoost" @@ -11498,438 +13598,554 @@ msgstr "" #: ../../source/tutorial-quickstart-xgboost.rst:11 msgid "Federated XGBoost" -msgstr "" +msgstr "联邦 XGBoost" #: ../../source/tutorial-quickstart-xgboost.rst:13 msgid "" "EXtreme Gradient Boosting (**XGBoost**) is a robust and efficient " -"implementation of gradient-boosted decision tree (**GBDT**), that " -"maximises the computational boundaries for boosted tree methods. It's " -"primarily designed to enhance both the performance and computational " -"speed of machine learning models. In XGBoost, trees are constructed " -"concurrently, unlike the sequential approach taken by GBDT." +"implementation of gradient-boosted decision tree (**GBDT**), that maximises " +"the computational boundaries for boosted tree methods. It's primarily " +"designed to enhance both the performance and computational speed of machine " +"learning models. In XGBoost, trees are constructed concurrently, unlike the " +"sequential approach taken by GBDT." msgstr "" +"EXtreme Gradient Boosting(**XGBoost**)是梯度提升决策树(**GBDT**)的一种稳" +"健而高效的实现方法,能最大限度地提高提升树方法的计算边界。它主要用于提高机器" +"学习模型的性能和计算速度。在 XGBoost 中,决策树是并发构建的,与 GBDT 采用的顺" +"序方法不同。" #: ../../source/tutorial-quickstart-xgboost.rst:17 msgid "" "Often, for tabular data on medium-sized datasets with fewer than 10k " -"training examples, XGBoost surpasses the results of deep learning " -"techniques." +"training examples, XGBoost surpasses the results of deep learning techniques." msgstr "" +"对于训练示例少于 10k 的中型数据集上的表格数据,XGBoost 的结果往往超过深度学习" +"技术。" #: ../../source/tutorial-quickstart-xgboost.rst:20 msgid "Why federated XGBoost?" -msgstr "" +msgstr "为什么选择联邦 XGBoost?" #: ../../source/tutorial-quickstart-xgboost.rst:22 msgid "" "Indeed, as the demand for data privacy and decentralized learning grows, " -"there's an increasing requirement to implement federated XGBoost systems " -"for specialised applications, like survival analysis and financial fraud " +"there's an increasing requirement to implement federated XGBoost systems for " +"specialised applications, like survival analysis and financial fraud " "detection." msgstr "" +"事实上,随着对数据隐私和分散学习的需求不断增长,越来越多的专业应用(如生存分" +"析和金融欺诈检测)需要实施联邦 XGBoost 系统。" #: ../../source/tutorial-quickstart-xgboost.rst:24 msgid "" -"Federated learning ensures that raw data remains on the local device, " -"making it an attractive approach for sensitive domains where data " -"security and privacy are paramount. Given the robustness and efficiency " -"of XGBoost, combining it with federated learning offers a promising " -"solution for these specific challenges." +"Federated learning ensures that raw data remains on the local device, making " +"it an attractive approach for sensitive domains where data security and " +"privacy are paramount. Given the robustness and efficiency of XGBoost, " +"combining it with federated learning offers a promising solution for these " +"specific challenges." msgstr "" +"联邦学习可确保原始数据保留在本地设备上,因此对于数据安全和隐私至关重要的敏感" +"领域来说,这是一种极具吸引力的方法。鉴于 XGBoost 的稳健性和高效性,将其与联邦" +"学习相结合为应对这些特定挑战提供了一种前景广阔的解决方案。" #: ../../source/tutorial-quickstart-xgboost.rst:27 msgid "" "In this tutorial we will learn how to train a federated XGBoost model on " "HIGGS dataset using Flower and :code:`xgboost` package. We use a simple " -"example (`full code xgboost-quickstart " -"`_)" -" with two *clients* and one *server* to demonstrate how federated XGBoost" -" works, and then we dive into a more complex example (`full code xgboost-" -"comprehensive `_) to run various experiments." -msgstr "" +"example (`full code xgboost-quickstart `_) with two *clients* and one *server* to " +"demonstrate how federated XGBoost works, and then we dive into a more " +"complex example (`full code xgboost-comprehensive `_) to run various " +"experiments." +msgstr "" +"在本教程中,我们将学习如何使用 Flower 和 :code:`xgboost` 软件包在 HIGGS 数据" +"集上训练联邦 XGBoost 模型。我们将使用一个包含两个 * 客户端* 和一个 * 服务器* " +"的简单示例 (`完整代码 xgboost-quickstart `_)来演示联邦 XGBoost 如何工作,然后我" +"们将深入到一个更复杂的示例 (`完整代码 xgboost-comprehensive `_),以运行各种实" +"验。" #: ../../source/tutorial-quickstart-xgboost.rst:34 msgid "Environment Setup" -msgstr "" +msgstr "环境设定" #: ../../source/tutorial-quickstart-xgboost.rst:38 msgid "" "We first need to install Flower and Flower Datasets. You can do this by " "running :" -msgstr "" +msgstr "我们首先需要安装 Flower 和 Flower Datasets。您可以通过运行 :" #: ../../source/tutorial-quickstart-xgboost.rst:44 msgid "" "Since we want to use :code:`xgboost` package to build up XGBoost trees, " "let's go ahead and install :code:`xgboost`:" msgstr "" +"既然我们要使用 :code:`xgboost` 软件包来构建 XGBoost 树,那就继续安装 :code:" +"`xgboost`:" #: ../../source/tutorial-quickstart-xgboost.rst:54 msgid "" -"*Clients* are responsible for generating individual weight-updates for " -"the model based on their local datasets. Now that we have all our " -"dependencies installed, let's run a simple distributed training with two " -"clients and one server." +"*Clients* are responsible for generating individual weight-updates for the " +"model based on their local datasets. Now that we have all our dependencies " +"installed, let's run a simple distributed training with two clients and one " +"server." msgstr "" +"*客户*负责根据其本地数据集为模型生成单独的权重更新。现在我们已经安装了所有的" +"依赖项,让我们用两个客户端和一个服务器来运行一个简单的分布式训练。" #: ../../source/tutorial-quickstart-xgboost.rst:57 msgid "" -"In a file called :code:`client.py`, import xgboost, Flower, Flower " -"Datasets and other related functions:" +"In a file called :code:`client.py`, import xgboost, Flower, Flower Datasets " +"and other related functions:" msgstr "" +"在名为 :code:`client.py` 的文件中,导入 xgboost、Flower、Flower Datasets 和其" +"他相关函数:" #: ../../source/tutorial-quickstart-xgboost.rst:84 msgid "Dataset partition and hyper-parameter selection" -msgstr "" +msgstr "数据集划分和超参数选择" #: ../../source/tutorial-quickstart-xgboost.rst:86 msgid "" -"Prior to local training, we require loading the HIGGS dataset from Flower" -" Datasets and conduct data partitioning for FL:" +"Prior to local training, we require loading the HIGGS dataset from Flower " +"Datasets and conduct data partitioning for FL:" msgstr "" +"在本地训练之前,我们需要从 Flower Datasets 加载 HIGGS 数据集,并对 FL 进行数" +"据分区:" #: ../../source/tutorial-quickstart-xgboost.rst:99 msgid "" "In this example, we split the dataset into two partitions with uniform " -"distribution (:code:`IidPartitioner(num_partitions=2)`). Then, we load " -"the partition for the given client based on :code:`node_id`:" +"distribution (:code:`IidPartitioner(num_partitions=2)`). Then, we load the " +"partition for the given client based on :code:`node_id`:" msgstr "" +"在此示例中,我们将数据集分割成两个均匀分布的分区(:code:" +"`IidPartitioner(num_partitions=2)`)。然后,我们根据 :code:`node_id` 为给定客" +"户端加载分区:" #: ../../source/tutorial-quickstart-xgboost.rst:118 msgid "" "After that, we do train/test splitting on the given partition (client's " "local data), and transform data format for :code:`xgboost` package." msgstr "" +"然后,我们在给定的分区(客户端的本地数据)上进行训练/测试分割,并为 :code:" +"`xgboost` 软件包转换数据格式。" #: ../../source/tutorial-quickstart-xgboost.rst:131 msgid "" -"The functions of :code:`train_test_split` and " -":code:`transform_dataset_to_dmatrix` are defined as below:" +"The functions of :code:`train_test_split` and :code:" +"`transform_dataset_to_dmatrix` are defined as below:" msgstr "" +":code:`train_test_split` 和 :code:`transform_dataset_too_dmatrix` 的函数定义" +"如下:" #: ../../source/tutorial-quickstart-xgboost.rst:155 msgid "Finally, we define the hyper-parameters used for XGBoost training." -msgstr "" +msgstr "最后,我们定义了用于 XGBoost 训练的超参数。" #: ../../source/tutorial-quickstart-xgboost.rst:171 msgid "" -"The :code:`num_local_round` represents the number of iterations for local" -" tree boost. We use CPU for the training in default. One can shift it to " -"GPU by setting :code:`tree_method` to :code:`gpu_hist`. We use AUC as " -"evaluation metric." +"The :code:`num_local_round` represents the number of iterations for local " +"tree boost. We use CPU for the training in default. One can shift it to GPU " +"by setting :code:`tree_method` to :code:`gpu_hist`. We use AUC as evaluation " +"metric." msgstr "" +"代码:`num_local_round`表示本地树提升的迭代次数。我们默认使用 CPU 进行训练。可" +"以通过将 :code:`tree_method` 设置为 :code:`gpu_hist`,将其转换为 GPU。我们使" +"用 AUC 作为评估指标。" #: ../../source/tutorial-quickstart-xgboost.rst:178 msgid "Flower client definition for XGBoost" -msgstr "" +msgstr "用于 XGBoost 的 Flower 客户端定义" #: ../../source/tutorial-quickstart-xgboost.rst:180 msgid "" -"After loading the dataset we define the Flower client. We follow the " -"general rule to define :code:`XgbClient` class inherited from " -":code:`fl.client.Client`." +"After loading the dataset we define the Flower client. We follow the general " +"rule to define :code:`XgbClient` class inherited from :code:`fl.client." +"Client`." msgstr "" +"加载数据集后,我们定义 Flower 客户端。我们按照一般规则定义从 :code:`fl." +"client.Client` 继承而来的 :code:`XgbClient` 类。" #: ../../source/tutorial-quickstart-xgboost.rst:190 msgid "" "The :code:`self.bst` is used to keep the Booster objects that remain " "consistent across rounds, allowing them to store predictions from trees " -"integrated in earlier rounds and maintain other essential data structures" -" for training." +"integrated in earlier rounds and maintain other essential data structures " +"for training." msgstr "" +"代码:`self.bst`用于保存在各轮中保持一致的 Booster 对象,使其能够存储在前几轮" +"中集成的树的预测结果,并维护其他用于训练的重要数据结构。" #: ../../source/tutorial-quickstart-xgboost.rst:193 msgid "" -"Then, we override :code:`get_parameters`, :code:`fit` and " -":code:`evaluate` methods insides :code:`XgbClient` class as follows." +"Then, we override :code:`get_parameters`, :code:`fit` and :code:`evaluate` " +"methods insides :code:`XgbClient` class as follows." msgstr "" +"然后,我们在 :code:`XgbClient` 类中覆盖 :code:`get_parameters`、:code:`fit` " +"和 :code:`evaluate` 方法如下。" #: ../../source/tutorial-quickstart-xgboost.rst:207 msgid "" "Unlike neural network training, XGBoost trees are not started from a " -"specified random weights. In this case, we do not use " -":code:`get_parameters` and :code:`set_parameters` to initialise model " -"parameters for XGBoost. As a result, let's return an empty tensor in " -":code:`get_parameters` when it is called by the server at the first " -"round." +"specified random weights. In this case, we do not use :code:`get_parameters` " +"and :code:`set_parameters` to initialise model parameters for XGBoost. As a " +"result, let's return an empty tensor in :code:`get_parameters` when it is " +"called by the server at the first round." msgstr "" +"与神经网络训练不同,XGBoost 树不是从指定的随机权重开始的。在这种情况下,我们" +"不使用 :code:`get_parameters` 和 :code:`set_parameters` 来初始化 XGBoost 的模" +"型参数。因此,当服务器在第一轮调用 :code:`get_parameters` 时,让我们在 :code:" +"`get_parameters` 中返回一个空张量。" #: ../../source/tutorial-quickstart-xgboost.rst:248 msgid "" -"In :code:`fit`, at the first round, we call :code:`xgb.train()` to build " -"up the first set of trees. the returned Booster object and config are " -"stored in :code:`self.bst` and :code:`self.config`, respectively. From " -"the second round, we load the global model sent from server to " -":code:`self.bst`, and then update model weights on local training data " -"with function :code:`local_boost` as follows:" +"In :code:`fit`, at the first round, we call :code:`xgb.train()` to build up " +"the first set of trees. the returned Booster object and config are stored " +"in :code:`self.bst` and :code:`self.config`, respectively. From the second " +"round, we load the global model sent from server to :code:`self.bst`, and " +"then update model weights on local training data with function :code:" +"`local_boost` as follows:" msgstr "" +"在 :code:`fit`中,第一轮我们调用 :code:`xgb.train()`来建立第一组树,返回的 " +"Booster 对象和 config 分别存储在 :code:`self.bst` 和 :code:`self.config` 中。" +"从第二轮开始,我们将服务器发送的全局模型加载到 :code:`self.bst`,然后使用函" +"数 :code:`local_boost`更新本地训练数据的模型权重,如下所示:" #: ../../source/tutorial-quickstart-xgboost.rst:266 msgid "" -"Given :code:`num_local_round`, we update trees by calling " -":code:`self.bst.update` method. After training, the last " -":code:`N=num_local_round` trees will be extracted to send to the server." +"Given :code:`num_local_round`, we update trees by calling :code:`self.bst." +"update` method. After training, the last :code:`N=num_local_round` trees " +"will be extracted to send to the server." msgstr "" +"给定 :code:`num_local_round`,我们通过调用 :code:`self.bst.update`方法更新" +"树。训练结束后,我们将提取最后一个 :code:`N=num_local_round` 树并发送给服务" +"器。" #: ../../source/tutorial-quickstart-xgboost.rst:288 msgid "" -"In :code:`evaluate`, we call :code:`self.bst.eval_set` function to " -"conduct evaluation on valid set. The AUC value will be returned." +"In :code:`evaluate`, we call :code:`self.bst.eval_set` function to conduct " +"evaluation on valid set. The AUC value will be returned." msgstr "" +"在 :code:`evaluate`中,我们调用 :code:`self.bst.eval_set`函数对有效集合进行评" +"估。将返回 AUC 值。" #: ../../source/tutorial-quickstart-xgboost.rst:291 msgid "" -"Now, we can create an instance of our class :code:`XgbClient` and add one" -" line to actually run this client:" +"Now, we can create an instance of our class :code:`XgbClient` and add one " +"line to actually run this client:" msgstr "" +"现在,我们可以创建一个 :code:`XgbClient` 类的实例,并添加一行来实际运行该客户" +"端:" #: ../../source/tutorial-quickstart-xgboost.rst:297 msgid "" -"That's it for the client. We only have to implement :code:`Client`and " -"call :code:`fl.client.start_client()`. The string :code:`\"[::]:8080\"` " -"tells the client which server to connect to. In our case we can run the " -"server and the client on the same machine, therefore we use " -":code:`\"[::]:8080\"`. If we run a truly federated workload with the " -"server and clients running on different machines, all that needs to " -"change is the :code:`server_address` we point the client at." +"That's it for the client. We only have to implement :code:`Client`and call :" +"code:`fl.client.start_client()`. The string :code:`\"[::]:8080\"` tells the " +"client which server to connect to. In our case we can run the server and the " +"client on the same machine, therefore we use :code:`\"[::]:8080\"`. If we " +"run a truly federated workload with the server and clients running on " +"different machines, all that needs to change is the :code:`server_address` " +"we point the client at." msgstr "" +"这就是客户端。我们只需实现 :code:`客户端`并调用 :code:`fl.client." +"start_client()`。字符串 :code:`\"[::]:8080\"`会告诉客户端要连接的服务器。在本" +"例中,我们可以在同一台机器上运行服务器和客户端,因此我们使用 :code:" +"`\"[::]:8080\"`。如果我们运行的是真正的联合工作负载,服务器和客户端运行在不同" +"的机器上,那么需要改变的只是客户端指向的 :code:`server_address`。" #: ../../source/tutorial-quickstart-xgboost.rst:308 msgid "" "These updates are then sent to the *server* which will aggregate them to " -"produce a better model. Finally, the *server* sends this improved version" -" of the model back to each *client* to finish a complete FL round." +"produce a better model. Finally, the *server* sends this improved version of " +"the model back to each *client* to finish a complete FL round." msgstr "" +"然后,这些更新会被发送到*服务器,由*服务器汇总后生成一个更好的模型。最后,*服" +"务器*将这个改进版的模型发回给每个*客户端*,以完成一轮完整的 FL。" #: ../../source/tutorial-quickstart-xgboost.rst:311 msgid "" -"In a file named :code:`server.py`, import Flower and FedXgbBagging from " -":code:`flwr.server.strategy`." +"In a file named :code:`server.py`, import Flower and FedXgbBagging from :" +"code:`flwr.server.strategy`." msgstr "" +"在名为 :code:`server.py` 的文件中,从 :code:`flwr.server.strategy` 导入 " +"Flower 和 FedXgbBagging。" #: ../../source/tutorial-quickstart-xgboost.rst:313 msgid "We first define a strategy for XGBoost bagging aggregation." -msgstr "" +msgstr "我们首先定义了 XGBoost 袋式聚合策略。" #: ../../source/tutorial-quickstart-xgboost.rst:336 msgid "" -"We use two clients for this example. An " -":code:`evaluate_metrics_aggregation` function is defined to collect and " -"wighted average the AUC values from clients." +"We use two clients for this example. An :code:`evaluate_metrics_aggregation` " +"function is defined to collect and wighted average the AUC values from " +"clients." msgstr "" +"本示例使用两个客户端。我们定义了一个 :code:`evaluate_metrics_aggregation` 函" +"数,用于收集客户机的 AUC 值并求取平均值。" #: ../../source/tutorial-quickstart-xgboost.rst:339 msgid "Then, we start the server:" -msgstr "" +msgstr "然后,我们启动服务器:" #: ../../source/tutorial-quickstart-xgboost.rst:351 msgid "Tree-based bagging aggregation" -msgstr "" +msgstr "基于树的袋式聚合" #: ../../source/tutorial-quickstart-xgboost.rst:353 msgid "" -"You must be curious about how bagging aggregation works. Let's look into " -"the details." -msgstr "" +"You must be curious about how bagging aggregation works. Let's look into the " +"details." +msgstr "你一定很好奇袋式聚合是如何工作的。让我们来详细了解一下。" #: ../../source/tutorial-quickstart-xgboost.rst:355 msgid "" -"In file :code:`flwr.server.strategy.fedxgb_bagging.py`, we define " -":code:`FedXgbBagging` inherited from :code:`flwr.server.strategy.FedAvg`." -" Then, we override the :code:`aggregate_fit`, :code:`aggregate_evaluate` " -"and :code:`evaluate` methods as follows:" +"In file :code:`flwr.server.strategy.fedxgb_bagging.py`, we define :code:" +"`FedXgbBagging` inherited from :code:`flwr.server.strategy.FedAvg`. Then, we " +"override the :code:`aggregate_fit`, :code:`aggregate_evaluate` and :code:" +"`evaluate` methods as follows:" msgstr "" +"在文件 :code:`flwr.server.strategy.fedxgb_bagging.py`中,我们定义了从 :code:" +"`flwr.server.strategy.FedAvg`继承的 :code:`FedXgbBagging`。然后,我们覆盖 :" +"code:`aggregate_fit`、:code:`aggregate_evaluate` 和 :code:`evaluate` 方法如" +"下:" #: ../../source/tutorial-quickstart-xgboost.rst:451 msgid "" "In :code:`aggregate_fit`, we sequentially aggregate the clients' XGBoost " "trees by calling :code:`aggregate()` function:" msgstr "" +"在 :code:`aggregate_fit` 中,我们通过调用 :code:`aggregate()` 函数,按顺序聚" +"合客户的 XGBoost 树:" #: ../../source/tutorial-quickstart-xgboost.rst:510 msgid "" "In this function, we first fetch the number of trees and the number of " -"parallel trees for the current and previous model by calling " -":code:`_get_tree_nums`. Then, the fetched information will be aggregated." -" After that, the trees (containing model weights) are aggregated to " -"generate a new tree model." +"parallel trees for the current and previous model by calling :code:" +"`_get_tree_nums`. Then, the fetched information will be aggregated. After " +"that, the trees (containing model weights) are aggregated to generate a new " +"tree model." msgstr "" +"在该函数中,我们首先通过调用 :code:`_get_tree_nums` 获取当前模型和上一个模型" +"的树数和并行树数。然后,对获取的信息进行汇总。然后,汇总树(包含模型权重)," +"生成新的树模型。" #: ../../source/tutorial-quickstart-xgboost.rst:515 msgid "" "After traversal of all clients' models, a new global model is generated, " "followed by the serialisation, and sending back to each client." msgstr "" +"在遍历所有客户的模型后,会生成一个新的全局模型,然后进行序列化,并发回给每个" +"客户。" #: ../../source/tutorial-quickstart-xgboost.rst:520 msgid "Launch Federated XGBoost!" -msgstr "" +msgstr "启动联邦 XGBoost!" #: ../../source/tutorial-quickstart-xgboost.rst:582 msgid "" "Congratulations! You've successfully built and run your first federated " -"XGBoost system. The AUC values can be checked in " -":code:`metrics_distributed`. One can see that the average AUC increases " -"over FL rounds." +"XGBoost system. The AUC values can be checked in :code:" +"`metrics_distributed`. One can see that the average AUC increases over FL " +"rounds." msgstr "" +"恭喜您!您已成功构建并运行了第一个联合 XGBoost 系统。可以在 :code:" +"`metrics_distributed` 中查看 AUC 值。我们可以看到,平均 AUC 随 FL 轮数的增加" +"而增加。" #: ../../source/tutorial-quickstart-xgboost.rst:587 msgid "" -"The full `source code `_ for this example can be found in :code:`examples" -"/xgboost-quickstart`." +"The full `source code `_ for this example can be found in :code:`examples/" +"xgboost-quickstart`." msgstr "" +"此示例的完整源代码 `_ 可在 :code:`examples/xgboost-quickstart` 中找到。" #: ../../source/tutorial-quickstart-xgboost.rst:591 msgid "Comprehensive Federated XGBoost" -msgstr "" +msgstr "全面的联邦 XGBoost" #: ../../source/tutorial-quickstart-xgboost.rst:593 msgid "" -"Now that you have known how federated XGBoost work with Flower, it's time" -" to run some more comprehensive experiments by customising the " -"experimental settings. In the xgboost-comprehensive example (`full code " -"`_), we provide more options to define various experimental" -" setups, including data partitioning and centralised/distributed " -"evaluation. Let's take a look!" +"Now that you have known how federated XGBoost work with Flower, it's time to " +"run some more comprehensive experiments by customising the experimental " +"settings. In the xgboost-comprehensive example (`full code `_), we provide " +"more options to define various experimental setups, including data " +"partitioning and centralised/distributed evaluation. Let's take a look!" msgstr "" +"既然您已经知道联合 XGBoost 如何与 Flower 协同工作,那么现在就该通过自定义实验" +"设置来运行一些更全面的实验了。在 xgboost-comprehensive 示例 (`完整代码 " +"`_)" +"中,我们提供了更多选项来定义各种实验设置,包括数据分区和集中/分布式评估。让我" +"们一起来看看!" #: ../../source/tutorial-quickstart-xgboost.rst:599 msgid "Customised data partitioning" -msgstr "" +msgstr "定制数据分区" #: ../../source/tutorial-quickstart-xgboost.rst:601 msgid "" -"In :code:`dataset.py`, we have a function :code:`instantiate_partitioner`" -" to instantiate the data partitioner based on the given " -":code:`num_partitions` and :code:`partitioner_type`. Currently, we " -"provide four supported partitioner type to simulate the uniformity/non-" -"uniformity in data quantity (uniform, linear, square, exponential)." +"In :code:`dataset.py`, we have a function :code:`instantiate_partitioner` to " +"instantiate the data partitioner based on the given :code:`num_partitions` " +"and :code:`partitioner_type`. Currently, we provide four supported " +"partitioner type to simulate the uniformity/non-uniformity in data quantity " +"(uniform, linear, square, exponential)." msgstr "" +"在 :code:`dataset.py` 中,我们有一个函数 :code:`instantiate_partitioner` 来根" +"据给定的 :code:`num_partitions` 和 :code:`partitioner_type` 来实例化数据分区" +"器。目前,我们提供四种支持的分区器类型(均匀、线性、正方形、指数)来模拟数据" +"量的均匀性/非均匀性。" #: ../../source/tutorial-quickstart-xgboost.rst:632 msgid "Customised centralised/distributed evaluation" -msgstr "" +msgstr "定制的集中/分布式评估" #: ../../source/tutorial-quickstart-xgboost.rst:634 msgid "" -"To facilitate centralised evaluation, we define a function in " -":code:`server.py`:" -msgstr "" +"To facilitate centralised evaluation, we define a function in :code:`server." +"py`:" +msgstr "为便于集中评估,我们在 :code:`server.py` 中定义了一个函数:" #: ../../source/tutorial-quickstart-xgboost.rst:666 msgid "" -"This function returns a evaluation function which instantiates a " -":code:`Booster` object and loads the global model weights to it. The " -"evaluation is conducted by calling :code:`eval_set()` method, and the " -"tested AUC value is reported." +"This function returns a evaluation function which instantiates a :code:" +"`Booster` object and loads the global model weights to it. The evaluation is " +"conducted by calling :code:`eval_set()` method, and the tested AUC value is " +"reported." msgstr "" +"此函数返回一个评估函数,该函数实例化一个 :code:`Booster` 对象,并向其加载全局" +"模型权重。评估通过调用 :code:`eval_set()` 方法进行,并报告测试的 AUC 值。" #: ../../source/tutorial-quickstart-xgboost.rst:669 msgid "" -"As for distributed evaluation on the clients, it's same as the quick-" -"start example by overriding the :code:`evaluate()` method insides the " -":code:`XgbClient` class in :code:`client.py`." +"As for distributed evaluation on the clients, it's same as the quick-start " +"example by overriding the :code:`evaluate()` method insides the :code:" +"`XgbClient` class in :code:`client.py`." msgstr "" +"至于客户端上的分布式评估,与快速启动示例相同,通过覆盖 :code:`client.py` 中 :" +"code:`XgbClient` 类内部的 :code:`evaluate()` 方法。" #: ../../source/tutorial-quickstart-xgboost.rst:673 msgid "Arguments parser" -msgstr "" +msgstr "参数 解析器" #: ../../source/tutorial-quickstart-xgboost.rst:675 msgid "" -"In :code:`utils.py`, we define the arguments parsers for clients and " -"server, allowing users to specify different experimental settings. Let's " -"first see the sever side:" +"In :code:`utils.py`, we define the arguments parsers for clients and server, " +"allowing users to specify different experimental settings. Let's first see " +"the sever side:" msgstr "" +"在 :code:`utils.py` 中,我们定义了客户端和服务器端的参数解析器,允许用户指定" +"不同的实验设置。让我们先看看服务器端:" #: ../../source/tutorial-quickstart-xgboost.rst:714 msgid "" "This allows user to specify the number of total clients / FL rounds / " -"participating clients / clients for evaluation, and evaluation fashion. " -"Note that with :code:`--centralised-eval`, the sever will do centralised " -"evaluation and all functionalities for client evaluation will be " -"disabled." +"participating clients / clients for evaluation, and evaluation fashion. Note " +"that with :code:`--centralised-eval`, the sever will do centralised " +"evaluation and all functionalities for client evaluation will be disabled." msgstr "" +"这允许用户指定总客户数/FL 轮数/参与客户数/评估客户数以及评估方式。请注意,如" +"果使用 :code:`--centralised-eval`,S sever 将进行集中评估,客户端评估的所有功" +"能将被禁用。" #: ../../source/tutorial-quickstart-xgboost.rst:718 msgid "Then, the argument parser on client side:" -msgstr "" +msgstr "然后是客户端的参数解析器:" #: ../../source/tutorial-quickstart-xgboost.rst:760 msgid "" -"This defines various options for client data partitioning. Besides, " -"clients also have a option to conduct evaluation on centralised test set " -"by setting :code:`--centralised-eval`." +"This defines various options for client data partitioning. Besides, clients " +"also have a option to conduct evaluation on centralised test set by setting :" +"code:`--centralised-eval`." msgstr "" +"这定义了客户端数据分区的各种选项。此外,通过设置 :code:`-centralised-eval`," +"客户端还可以选择在集中测试集上进行评估。" #: ../../source/tutorial-quickstart-xgboost.rst:764 msgid "Example commands" -msgstr "" +msgstr "命令示例" #: ../../source/tutorial-quickstart-xgboost.rst:766 msgid "" "To run a centralised evaluated experiment on 5 clients with exponential " "distribution for 50 rounds, we first start the server as below:" msgstr "" +"为了在 5 个客户端上进行 50 轮指数分布的集中评估实验,我们首先启动服务器,如下" +"所示:" #: ../../source/tutorial-quickstart-xgboost.rst:773 msgid "Then, on each client terminal, we start the clients:" -msgstr "" +msgstr "然后,我们在每个客户终端上启动客户机:" #: ../../source/tutorial-quickstart-xgboost.rst:779 msgid "" -"The full `source code `_ for this comprehensive example can be found in" -" :code:`examples/xgboost-comprehensive`." +"The full `source code `_ for this comprehensive example can be found in :" +"code:`examples/xgboost-comprehensive`." msgstr "" +"此综合示例的全部源代码 `_ 可在 :code:`examples/xgboost-comprehensive` 中找" +"到。" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:9 msgid "Build a strategy from scratch" -msgstr "" +msgstr "从零开始制定策略" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:11 msgid "" "Welcome to the third part of the Flower federated learning tutorial. In " "previous parts of this tutorial, we introduced federated learning with " -"PyTorch and Flower (`part 1 `__) and we learned how strategies " -"can be used to customize the execution on both the server and the clients" -" (`part 2 `__)." +"PyTorch and Flower (`part 1 `__) and we learned how strategies can be " +"used to customize the execution on both the server and the clients (`part 2 " +"`__)." msgstr "" +"欢迎来到 Flower 联合学习教程的第三部分。在本教程的前几部分,我们介绍了 " +"PyTorch 和 Flower 的联合学习(`part 1 `__),并学习了如何使用策略来定" +"制服务器和客户端的执行(`part 2 `__)。" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:13 msgid "" -"In this notebook, we'll continue to customize the federated learning " -"system we built previously by creating a custom version of FedAvg (again," -" using `Flower `__ and `PyTorch " -"`__)." +"In this notebook, we'll continue to customize the federated learning system " +"we built previously by creating a custom version of FedAvg (again, using " +"`Flower `__ and `PyTorch `__)." msgstr "" +"在本笔记本中,我们将通过创建 FedAvg 的自定义版本(再次使用 `Flower `__ 和 `PyTorch `__),继续定制我们之前构建" +"的联合学习系统。" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:15 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:16 #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:15 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:15 msgid "" -"`Star Flower on GitHub `__ ⭐️ and join " -"the Flower community on Slack to connect, ask questions, and get help: " -"`Join Slack `__ 🌼 We'd love to hear from " -"you in the ``#introductions`` channel! And if anything is unclear, head " -"over to the ``#questions`` channel." +"`Star Flower on GitHub `__ ⭐️ and join the " +"Flower community on Slack to connect, ask questions, and get help: `Join " +"Slack `__ 🌼 We'd love to hear from you in " +"the ``#introductions`` channel! And if anything is unclear, head over to the " +"``#questions`` channel." msgstr "" +"`Star Flower on GitHub `__ ⭐️ 并加入 Slack 上" +"的 Flower 社区,进行交流、提问并获得帮助: 加入 Slack `__ 🌼 我们希望在 ``#introductions`` 频道听到您的声音!如果有任何" +"不清楚的地方,请访问 ``#questions`` 频道。" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:17 msgid "Let's build a new ``Strategy`` from scratch!" -msgstr "" +msgstr "让我们从头开始构建一个新的 \"策略\"!" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:29 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:29 msgid "Preparation" -msgstr "" +msgstr "准备工作" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:31 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:32 @@ -11937,20 +14153,20 @@ msgstr "" msgid "" "Before we begin with the actual code, let's make sure that we have " "everything we need." -msgstr "" +msgstr "在开始实际代码之前,让我们先确保我们已经准备好了所需的一切。" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:43 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:44 #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:43 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:43 msgid "Installing dependencies" -msgstr "" +msgstr "安装依赖项" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:45 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:46 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:45 msgid "First, we install the necessary packages:" -msgstr "" +msgstr "首先,我们安装必要的软件包:" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:65 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:66 @@ -11959,106 +14175,127 @@ msgstr "" msgid "" "Now that we have all dependencies installed, we can import everything we " "need for this tutorial:" -msgstr "" +msgstr "现在我们已经安装了所有依赖项,可以导入本教程所需的所有内容:" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:101 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:102 #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:104 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:101 msgid "" -"It is possible to switch to a runtime that has GPU acceleration enabled " -"(on Google Colab: ``Runtime > Change runtime type > Hardware acclerator: " -"GPU > Save``). Note, however, that Google Colab is not always able to " -"offer GPU acceleration. If you see an error related to GPU availability " -"in one of the following sections, consider switching back to CPU-based " -"execution by setting ``DEVICE = torch.device(\"cpu\")``. If the runtime " -"has GPU acceleration enabled, you should see the output ``Training on " -"cuda``, otherwise it'll say ``Training on cpu``." -msgstr "" +"It is possible to switch to a runtime that has GPU acceleration enabled (on " +"Google Colab: ``Runtime > Change runtime type > Hardware acclerator: GPU > " +"Save``). Note, however, that Google Colab is not always able to offer GPU " +"acceleration. If you see an error related to GPU availability in one of the " +"following sections, consider switching back to CPU-based execution by " +"setting ``DEVICE = torch.device(\"cpu\")``. If the runtime has GPU " +"acceleration enabled, you should see the output ``Training on cuda``, " +"otherwise it'll say ``Training on cpu``." +msgstr "" +"可以切换到已启用 GPU 加速的运行时(在 Google Colab 上: 运行时 > 更改运行时类" +"型 > 硬件加速: GPU > 保存``)。但请注意,Google Colab 并非总能提供 GPU 加" +"速。如果在以下部分中看到与 GPU 可用性相关的错误,请考虑通过设置 ``DEVICE = " +"torch.device(\"cpu\")`` 切回基于 CPU 的执行。如果运行时已启用 GPU 加速,你应" +"该会看到输出``Training on cuda``,否则会显示``Training on cpu``。" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:114 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:115 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:114 msgid "Data loading" -msgstr "" +msgstr "数据加载" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:116 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:116 msgid "" -"Let's now load the CIFAR-10 training and test set, partition them into " -"ten smaller datasets (each split into training and validation set), and " -"wrap everything in their own ``DataLoader``. We introduce a new parameter" -" ``num_clients`` which allows us to call ``load_datasets`` with different" -" numbers of clients." +"Let's now load the CIFAR-10 training and test set, partition them into ten " +"smaller datasets (each split into training and validation set), and wrap " +"everything in their own ``DataLoader``. We introduce a new parameter " +"``num_clients`` which allows us to call ``load_datasets`` with different " +"numbers of clients." msgstr "" +"现在,让我们加载 CIFAR-10 训练集和测试集,将它们分割成 10 个较小的数据集(每" +"个数据集又分为训练集和验证集),并将所有数据都封装在各自的 ``DataLoader`` " +"中。我们引入了一个新参数 ``num_clients``,它允许我们使用不同数量的客户端调用 " +"``load_datasets``。" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:167 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:168 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:167 msgid "Model training/evaluation" -msgstr "" +msgstr "模型培训/评估" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:169 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:170 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:169 msgid "" -"Let's continue with the usual model definition (including " -"``set_parameters`` and ``get_parameters``), training and test functions:" +"Let's continue with the usual model definition (including ``set_parameters`` " +"and ``get_parameters``), training and test functions:" msgstr "" +"让我们继续使用常见的模型定义(包括 `set_parameters` 和 `get_parameters`)、训" +"练和测试函数:" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:258 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:258 msgid "Flower client" -msgstr "" +msgstr "Flower 客户端" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:260 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:260 msgid "" -"To implement the Flower client, we (again) create a subclass of " -"``flwr.client.NumPyClient`` and implement the three methods " -"``get_parameters``, ``fit``, and ``evaluate``. Here, we also pass the " -"``cid`` to the client and use it log additional details:" +"To implement the Flower client, we (again) create a subclass of ``flwr." +"client.NumPyClient`` and implement the three methods ``get_parameters``, " +"``fit``, and ``evaluate``. Here, we also pass the ``cid`` to the client and " +"use it log additional details:" msgstr "" +"为了实现 Flower 客户端,我们(再次)创建了 ``flwr.client.NumPyClient`` 的子" +"类,并实现了 ``get_parameters``、``fit`` 和 ``evaluate``三个方法。在这里,我" +"们还将 ``cid`` 传递给客户端,并使用它记录其他详细信息:" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:308 msgid "Let's test what we have so far before we continue:" -msgstr "" +msgstr "在继续之前,让我们先测试一下我们目前掌握的情况:" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:339 msgid "Build a Strategy from scratch" -msgstr "" +msgstr "从零开始构建策略" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:341 msgid "" -"Let’s overwrite the ``configure_fit`` method such that it passes a higher" -" learning rate (potentially also other hyperparameters) to the optimizer " -"of a fraction of the clients. We will keep the sampling of the clients as" -" it is in ``FedAvg`` and then change the configuration dictionary (one of" -" the ``FitIns`` attributes)." +"Let’s overwrite the ``configure_fit`` method such that it passes a higher " +"learning rate (potentially also other hyperparameters) to the optimizer of a " +"fraction of the clients. We will keep the sampling of the clients as it is " +"in ``FedAvg`` and then change the configuration dictionary (one of the " +"``FitIns`` attributes)." msgstr "" +"让我们重写 ``configure_fit`` 方法,使其向一部分客户的优化器传递更高的学习率" +"(可能还有其他超参数)。我们将保持 ``FedAvg`` 中的客户端采样,然后更改配置字" +"典(``FitIns`` 属性之一)。" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:507 msgid "" "The only thing left is to use the newly created custom Strategy " "``FedCustom`` when starting the experiment:" -msgstr "" +msgstr "剩下的唯一工作就是在启动实验时使用新创建的自定义策略 ``FedCustom`` :" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:534 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:932 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:697 msgid "Recap" -msgstr "" +msgstr "回顾" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:536 msgid "" -"In this notebook, we’ve seen how to implement a custom strategy. A custom" -" strategy enables granular control over client node configuration, result" -" aggregation, and more. To define a custom strategy, you only have to " -"overwrite the abstract methods of the (abstract) base class ``Strategy``." -" To make custom strategies even more powerful, you can pass custom " -"functions to the constructor of your new class (``__init__``) and then " -"call these functions whenever needed." +"In this notebook, we’ve seen how to implement a custom strategy. A custom " +"strategy enables granular control over client node configuration, result " +"aggregation, and more. To define a custom strategy, you only have to " +"overwrite the abstract methods of the (abstract) base class ``Strategy``. To " +"make custom strategies even more powerful, you can pass custom functions to " +"the constructor of your new class (``__init__``) and then call these " +"functions whenever needed." msgstr "" +"在本笔记本中,我们了解了如何实施自定义策略。自定义策略可以对客户端节点配置、" +"结果聚合等进行细粒度控制。要定义自定义策略,只需覆盖(抽象)基类 " +"``Strategy`` 的抽象方法即可。为使自定义策略更加强大,您可以将自定义函数传递给" +"新类的构造函数(`__init__``),然后在需要时调用这些函数。" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:550 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:948 @@ -12066,9 +14303,11 @@ msgstr "" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:715 #: ../../source/tutorial-series-what-is-federated-learning.ipynb:369 msgid "" -"Before you continue, make sure to join the Flower community on Slack: " -"`Join Slack `__" +"Before you continue, make sure to join the Flower community on Slack: `Join " +"Slack `__" msgstr "" +"在继续之前,请务必加入 Slack 上的 Flower 社区:`Join Slack `__" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:552 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:950 @@ -12076,75 +14315,96 @@ msgstr "" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:717 #: ../../source/tutorial-series-what-is-federated-learning.ipynb:371 msgid "" -"There's a dedicated ``#questions`` channel if you need help, but we'd " -"also love to hear who you are in ``#introductions``!" +"There's a dedicated ``#questions`` channel if you need help, but we'd also " +"love to hear who you are in ``#introductions``!" msgstr "" +"如果您需要帮助,我们有专门的 ``#questions`` 频道,但我们也很乐意在 " +"``#introductions`` 中了解您是谁!" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:554 msgid "" -"The `Flower Federated Learning Tutorial - Part 4 " -"`__ introduces ``Client``, the flexible API underlying " -"``NumPyClient``." +"The `Flower Federated Learning Tutorial - Part 4 `__ introduces " +"``Client``, the flexible API underlying ``NumPyClient``." msgstr "" +"Flower联邦学习教程 - 第4部分 `__ 介绍了``Client``,它是``NumPyClient``底" +"层的灵活应用程序接口。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:9 msgid "Customize the client" -msgstr "" +msgstr "自定义客户端" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:11 msgid "" -"Welcome to the fourth part of the Flower federated learning tutorial. In " -"the previous parts of this tutorial, we introduced federated learning " -"with PyTorch and Flower (`part 1 `__), we learned how " -"strategies can be used to customize the execution on both the server and " -"the clients (`part 2 `__), and we built our own " -"custom strategy from scratch (`part 3 `__)." -msgstr "" +"Welcome to the fourth part of the Flower federated learning tutorial. In the " +"previous parts of this tutorial, we introduced federated learning with " +"PyTorch and Flower (`part 1 `__), we learned how strategies can be used " +"to customize the execution on both the server and the clients (`part 2 " +"`__), and we built our own custom strategy from " +"scratch (`part 3 `__)." +msgstr "" +"欢迎来到 Flower 联邦学习教程的第四部分。在本教程的前几部分中,我们介绍了 " +"PyTorch 和 Flower 的联邦学习(`part 1 `__),了解了如何使用策略来定制" +"服务器和客户端的执行(`part 2 `__),并从头开始构建了我们自" +"己的定制策略(`part 3 `__)。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:14 msgid "" -"In this notebook, we revisit ``NumPyClient`` and introduce a new " -"baseclass for building clients, simply named ``Client``. In previous " -"parts of this tutorial, we've based our client on ``NumPyClient``, a " -"convenience class which makes it easy to work with machine learning " -"libraries that have good NumPy interoperability. With ``Client``, we gain" -" a lot of flexibility that we didn't have before, but we'll also have to " -"do a few things the we didn't have to do before." +"In this notebook, we revisit ``NumPyClient`` and introduce a new baseclass " +"for building clients, simply named ``Client``. In previous parts of this " +"tutorial, we've based our client on ``NumPyClient``, a convenience class " +"which makes it easy to work with machine learning libraries that have good " +"NumPy interoperability. With ``Client``, we gain a lot of flexibility that " +"we didn't have before, but we'll also have to do a few things the we didn't " +"have to do before." msgstr "" +"在本笔记中,我们将重温 ``NumPyClient`` 并引入一个用于构建客户端的新基类,简单" +"命名为 ``Client``。在本教程的前几部分中,我们的客户端基于``NumPyClient``,这" +"是一个方便类,可以让我们轻松地与具有良好 NumPy 互操作性的机器学习库协同工作。" +"有了 ``Client``,我们获得了很多以前没有的灵活性,但我们也必须做一些以前不需要" +"做的事情。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:18 msgid "" "Let's go deeper and see what it takes to move from ``NumPyClient`` to " "``Client``!" -msgstr "" +msgstr "让我们深入了解一下从 ``NumPyClient`` 到 ``Client`` 的过程!" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:30 #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:29 msgid "Step 0: Preparation" -msgstr "" +msgstr "步骤 0:准备工作" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:117 msgid "" -"Let's now load the CIFAR-10 training and test set, partition them into " -"ten smaller datasets (each split into training and validation set), and " -"wrap everything in their own ``DataLoader``." +"Let's now load the CIFAR-10 training and test set, partition them into ten " +"smaller datasets (each split into training and validation set), and wrap " +"everything in their own ``DataLoader``." msgstr "" +"现在,让我们加载 CIFAR-10 训练集和测试集,将它们分割成十个较小的数据集(每个" +"数据集又分为训练集和验证集),并将所有数据都封装在各自的 ``DataLoader`` 中。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:259 msgid "Step 1: Revisiting NumPyClient" -msgstr "" +msgstr "步骤 1:重温 NumPyClient" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:261 msgid "" -"So far, we've implemented our client by subclassing " -"``flwr.client.NumPyClient``. The three methods we implemented are " -"``get_parameters``, ``fit``, and ``evaluate``. Finally, we wrap the " -"creation of instances of this class in a function called ``client_fn``:" +"So far, we've implemented our client by subclassing ``flwr.client." +"NumPyClient``. The three methods we implemented are ``get_parameters``, " +"``fit``, and ``evaluate``. Finally, we wrap the creation of instances of " +"this class in a function called ``client_fn``:" msgstr "" +"到目前为止,我们通过子类化 ``flwr.client.NumPyClient`` 实现了我们的客户端。我" +"们实现了三个方法:``get_parameters``, ``fit`, 和``evaluate``。最后,我们用一" +"个名为 ``client_fn`` 的函数来创建该类的实例:" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:309 msgid "" @@ -12153,125 +14413,160 @@ msgid "" "``FlowerClient`` to ``FlowerNumPyClient`` and ``client_fn`` to " "``numpyclient_fn``. Let's run it to see the output we get:" msgstr "" +"我们以前见过这种情况,目前没有什么新东西。与之前的笔记本相比,唯一*小*的不同" +"是命名,我们把 ``FlowerClient`` 改成了 ``FlowerNumPyClient``,把 `client_fn` " +"改成了 ``numpyclient_fn``。让我们运行它看看输出结果:" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:339 msgid "" "This works as expected, two clients are training for three rounds of " "federated learning." -msgstr "" +msgstr "结果不出所料,两个客户端正在进行三轮联合学习培训。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:341 msgid "" "Let's dive a little bit deeper and discuss how Flower executes this " "simulation. Whenever a client is selected to do some work, " "``start_simulation`` calls the function ``numpyclient_fn`` to create an " -"instance of our ``FlowerNumPyClient`` (along with loading the model and " -"the data)." +"instance of our ``FlowerNumPyClient`` (along with loading the model and the " +"data)." msgstr "" +"让我们再深入一点,讨论一下 Flower 是如何执行模拟的。每当一个客户端被选中进行" +"工作时,`start_simulation`` 就会调用函数 `numpyclient_fn` 来创建我们的 " +"``FlowerNumPyClient`` 实例(同时加载模型和数据)。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:343 msgid "" "But here's the perhaps surprising part: Flower doesn't actually use the " -"``FlowerNumPyClient`` object directly. Instead, it wraps the object to " -"makes it look like a subclass of ``flwr.client.Client``, not " -"``flwr.client.NumPyClient``. In fact, the Flower core framework doesn't " -"know how to handle ``NumPyClient``'s, it only knows how to handle " -"``Client``'s. ``NumPyClient`` is just a convenience abstraction built on " -"top of ``Client``." -msgstr "" +"``FlowerNumPyClient`` object directly. Instead, it wraps the object to makes " +"it look like a subclass of ``flwr.client.Client``, not ``flwr.client." +"NumPyClient``. In fact, the Flower core framework doesn't know how to handle " +"``NumPyClient``'s, it only knows how to handle ``Client``'s. ``NumPyClient`` " +"is just a convenience abstraction built on top of ``Client``." +msgstr "" +"但令人惊讶的部分也许就在这里: Flower 实际上并不直接使用 " +"``FlowerNumPyClient`` 对象。相反,它封装了该对象,使其看起来像 ``flwr.client." +"Client`` 的子类,而不是 ``flwr.client.NumPyClient``。事实上,Flower 核心框架" +"不知道如何处理 ``NumPyClient``,它只知道如何处理 ``Client``。``NumPyClient`` " +"只是建立在``Client``之上的方便抽象。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:345 msgid "" -"Instead of building on top of ``NumPyClient``, we can directly build on " -"top of ``Client``." -msgstr "" +"Instead of building on top of ``NumPyClient``, we can directly build on top " +"of ``Client``." +msgstr "与其在 ``NumPyClient`` 上构建,我们可以直接在 ``Client`` 上构建。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:357 msgid "Step 2: Moving from ``NumPyClient`` to ``Client``" -msgstr "" +msgstr "步骤 2:从 ``NumPyClient`` 移至 ``Client``" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:359 msgid "" -"Let's try to do the same thing using ``Client`` instead of " -"``NumPyClient``." -msgstr "" +"Let's try to do the same thing using ``Client`` instead of ``NumPyClient``." +msgstr "让我们尝试使用 ``Client`` 代替 ``NumPyClient`` 做同样的事情。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:465 msgid "" -"Before we discuss the code in more detail, let's try to run it! Gotta " -"make sure our new ``Client``-based client works, right?" +"Before we discuss the code in more detail, let's try to run it! Gotta make " +"sure our new ``Client``-based client works, right?" msgstr "" +"在详细讨论代码之前,让我们试着运行它!必须确保我们基于 ``Client`` 的新客户端" +"能正常运行,对吗?" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:490 msgid "" "That's it, we're now using ``Client``. It probably looks similar to what " "we've done with ``NumPyClient``. So what's the difference?" msgstr "" +"就是这样,我们现在开始使用 ``Client``。它看起来可能与我们使用 " +"``NumPyClient`` 所做的类似。那么有什么不同呢?" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:492 msgid "" -"First of all, it's more code. But why? The difference comes from the fact" -" that ``Client`` expects us to take care of parameter serialization and " -"deserialization. For Flower to be able to send parameters over the " -"network, it eventually needs to turn these parameters into ``bytes``. " -"Turning parameters (e.g., NumPy ``ndarray``'s) into raw bytes is called " +"First of all, it's more code. But why? The difference comes from the fact " +"that ``Client`` expects us to take care of parameter serialization and " +"deserialization. For Flower to be able to send parameters over the network, " +"it eventually needs to turn these parameters into ``bytes``. Turning " +"parameters (e.g., NumPy ``ndarray``'s) into raw bytes is called " "serialization. Turning raw bytes into something more useful (like NumPy " -"``ndarray``'s) is called deserialization. Flower needs to do both: it " -"needs to serialize parameters on the server-side and send them to the " -"client, the client needs to deserialize them to use them for local " -"training, and then serialize the updated parameters again to send them " -"back to the server, which (finally!) deserializes them again in order to " -"aggregate them with the updates received from other clients." -msgstr "" +"``ndarray``'s) is called deserialization. Flower needs to do both: it needs " +"to serialize parameters on the server-side and send them to the client, the " +"client needs to deserialize them to use them for local training, and then " +"serialize the updated parameters again to send them back to the server, " +"which (finally!) deserializes them again in order to aggregate them with the " +"updates received from other clients." +msgstr "" +"首先,它的代码更多。但为什么呢?区别在于 ``Client`` 希望我们处理参数的序列化" +"和反序列化。Flower 要想通过网络发送参数,最终需要将这些参数转化为 ``字节``。" +"把参数(例如 NumPy 的 ``ndarray``'s 参数)变成原始字节叫做序列化。将原始字节" +"转换成更有用的东西(如 NumPy ``ndarray``s)称为反序列化。Flower 需要同时做这" +"两件事:它需要在服务器端序列化参数并将其发送到客户端,客户端需要反序列化参数" +"以便将其用于本地训练,然后再次序列化更新后的参数并将其发送回服务器,服务器" +"(最后!)再次反序列化参数以便将其与从其他客户端接收到的更新汇总在一起。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:495 msgid "" "The only *real* difference between Client and NumPyClient is that " -"NumPyClient takes care of serialization and deserialization for you. It " -"can do so because it expects you to return parameters as NumPy ndarray's," -" and it knows how to handle these. This makes working with machine " -"learning libraries that have good NumPy support (most of them) a breeze." +"NumPyClient takes care of serialization and deserialization for you. It can " +"do so because it expects you to return parameters as NumPy ndarray's, and it " +"knows how to handle these. This makes working with machine learning " +"libraries that have good NumPy support (most of them) a breeze." msgstr "" +"Client 与 NumPyClient 之间的唯一**真正区别在于,NumPyClient 会为你处理序列化" +"和反序列化。NumPyClient之所以能做到这一点,是因为它预计你会以NumPy ndarray的" +"形式返回参数,而且它知道如何处理这些参数。这使得与具有良好 NumPy 支持的机器学" +"习库(大多数)一起工作变得轻而易举。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:497 msgid "" -"In terms of API, there's one major difference: all methods in Client take" -" exactly one argument (e.g., ``FitIns`` in ``Client.fit``) and return " -"exactly one value (e.g., ``FitRes`` in ``Client.fit``). The methods in " +"In terms of API, there's one major difference: all methods in Client take " +"exactly one argument (e.g., ``FitIns`` in ``Client.fit``) and return exactly " +"one value (e.g., ``FitRes`` in ``Client.fit``). The methods in " "``NumPyClient`` on the other hand have multiple arguments (e.g., " -"``parameters`` and ``config`` in ``NumPyClient.fit``) and multiple return" -" values (e.g., ``parameters``, ``num_example``, and ``metrics`` in " -"``NumPyClient.fit``) if there are multiple things to handle. These " -"``*Ins`` and ``*Res`` objects in ``Client`` wrap all the individual " -"values you're used to from ``NumPyClient``." -msgstr "" +"``parameters`` and ``config`` in ``NumPyClient.fit``) and multiple return " +"values (e.g., ``parameters``, ``num_example``, and ``metrics`` in " +"``NumPyClient.fit``) if there are multiple things to handle. These ``*Ins`` " +"and ``*Res`` objects in ``Client`` wrap all the individual values you're " +"used to from ``NumPyClient``." +msgstr "" +"在 API 方面,有一个主要区别:Client 中的所有方法都只接受一个参数(例如," +"``Client.fit`` 中的 ``FitIns``),并只返回一个值(例如,``Client.fit`` 中的 " +"``FitRes``)。另一方面,``NumPyClient``中的方法有多个参数(例如," +"``NumPyClient.fit``中的``parameters``和``config``)和多个返回值(例如," +"``NumPyClient.fit``中的``parameters``、``num_example``和``metrics``)。在 " +"``Client`` 中的这些 ``*Ins`` 和 ``*Res`` 对象封装了你在 ``NumPyClient`` 中习" +"惯使用的所有单个值。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:510 msgid "Step 3: Custom serialization" -msgstr "" +msgstr "步骤 3:自定义序列化" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:512 msgid "" "Here we will explore how to implement custom serialization with a simple " "example." -msgstr "" +msgstr "下面我们将通过一个简单的示例来探讨如何实现自定义序列化。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:514 msgid "" "But first what is serialization? Serialization is just the process of " "converting an object into raw bytes, and equally as important, " -"deserialization is the process of converting raw bytes back into an " -"object. This is very useful for network communication. Indeed, without " +"deserialization is the process of converting raw bytes back into an object. " +"This is very useful for network communication. Indeed, without " "serialization, you could not just a Python object through the internet." msgstr "" +"首先,什么是序列化?序列化只是将对象转换为原始字节的过程,同样重要的是,反序" +"列化是将原始字节转换回对象的过程。这对网络通信非常有用。事实上,如果没有序列" +"化,你就无法通过互联网传输一个 Python 对象。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:516 msgid "" -"Federated Learning relies heavily on internet communication for training " -"by sending Python objects back and forth between the clients and the " -"server. This means that serialization is an essential part of Federated " -"Learning." +"Federated Learning relies heavily on internet communication for training by " +"sending Python objects back and forth between the clients and the server. " +"This means that serialization is an essential part of Federated Learning." msgstr "" +"通过在客户端和服务器之间来回发送 Python 对象,联合学习在很大程度上依赖于互联" +"网通信进行训练。这意味着序列化是 Federated Learning 的重要组成部分。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:518 msgid "" @@ -12283,230 +14578,278 @@ msgid "" "entries), converting them to a sparse matrix can greatly improve their " "bytesize." msgstr "" +"在下面的章节中,我们将编写一个基本示例,在发送包含参数的 ``ndarray`` s 之前," +"我们将首先把 ``ndarray`` 转换为稀疏矩阵,而不是发送序列化版本。这种技术可以用" +"来节省带宽,因为在某些情况下,模型的权重是稀疏的(包含许多 0 条目),将它们转" +"换成稀疏矩阵可以大大提高它们的字节数。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:521 msgid "Our custom serialization/deserialization functions" -msgstr "" +msgstr "我们的定制序列化/反序列化功能" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:523 msgid "" -"This is where the real serialization/deserialization will happen, " -"especially in ``ndarray_to_sparse_bytes`` for serialization and " +"This is where the real serialization/deserialization will happen, especially " +"in ``ndarray_to_sparse_bytes`` for serialization and " "``sparse_bytes_to_ndarray`` for deserialization." msgstr "" +"这才是真正的序列化/反序列化,尤其是在用于序列化的 " +"``ndarray_too_sparse_bytes`` 和用于反序列化的 ``sparse_bytes_too_ndarray`` " +"中。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:525 msgid "" -"Note that we imported the ``scipy.sparse`` library in order to convert " -"our arrays." -msgstr "" +"Note that we imported the ``scipy.sparse`` library in order to convert our " +"arrays." +msgstr "请注意,为了转换数组,我们导入了 ``scipy.sparse`` 库。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:613 msgid "Client-side" -msgstr "" +msgstr "客户端" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:615 msgid "" -"To be able to able to serialize our ``ndarray``\\ s into sparse " -"parameters, we will just have to call our custom functions in our " -"``flwr.client.Client``." +"To be able to able to serialize our ``ndarray``\\ s into sparse parameters, " +"we will just have to call our custom functions in our ``flwr.client.Client``." msgstr "" +"为了能够将我们的 ``ndarray``s 序列化为稀疏参数,我们只需在 ``flwr.client." +"Client`` 中调用我们的自定义函数。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:617 msgid "" "Indeed, in ``get_parameters`` we need to serialize the parameters we got " -"from our network using our custom ``ndarrays_to_sparse_parameters`` " -"defined above." +"from our network using our custom ``ndarrays_to_sparse_parameters`` defined " +"above." msgstr "" +"事实上,在 `get_parameters` 中,我们需要使用上文定义的自定义 " +"`ndarrays_too_sparse_parameters` 序列化从网络中获取的参数。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:619 msgid "" "In ``fit``, we first need to deserialize the parameters coming from the " -"server using our custom ``sparse_parameters_to_ndarrays`` and then we " -"need to serialize our local results with " -"``ndarrays_to_sparse_parameters``." +"server using our custom ``sparse_parameters_to_ndarrays`` and then we need " +"to serialize our local results with ``ndarrays_to_sparse_parameters``." msgstr "" +"在 ``fit`` 中,我们首先需要使用自定义的 ``sparse_parameters_too_ndarrays`` 反" +"序列化来自服务器的参数,然后使用 ``ndarrays_too_sparse_parameters`` 序列化本" +"地结果。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:621 msgid "" -"In ``evaluate``, we will only need to deserialize the global parameters " -"with our custom function." -msgstr "" +"In ``evaluate``, we will only need to deserialize the global parameters with " +"our custom function." +msgstr "在 ``evaluate`` 中,我们只需要用自定义函数反序列化全局参数。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:725 msgid "Server-side" -msgstr "" +msgstr "服务器端" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:727 msgid "" -"For this example, we will just use ``FedAvg`` as a strategy. To change " -"the serialization and deserialization here, we only need to reimplement " -"the ``evaluate`` and ``aggregate_fit`` functions of ``FedAvg``. The other" -" functions of the strategy will be inherited from the super class " -"``FedAvg``." +"For this example, we will just use ``FedAvg`` as a strategy. To change the " +"serialization and deserialization here, we only need to reimplement the " +"``evaluate`` and ``aggregate_fit`` functions of ``FedAvg``. The other " +"functions of the strategy will be inherited from the super class ``FedAvg``." msgstr "" +"在本例中,我们将只使用 ``FedAvg`` 作为策略。要改变这里的序列化和反序列化,我" +"们只需重新实现 ``FedAvg`` 的 ``evaluate`` 和 ``aggregate_fit`` 函数。策略的其" +"他函数将从超类 ``FedAvg`` 继承。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:729 msgid "As you can see only one line as change in ``evaluate``:" -msgstr "" +msgstr "正如你所看到的,``evaluate``中只修改了一行:" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:735 msgid "" "And for ``aggregate_fit``, we will first deserialize every result we " "received:" -msgstr "" +msgstr "而对于 ``aggregate_fit``,我们将首先反序列化收到的每个结果:" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:744 msgid "And then serialize the aggregated result:" -msgstr "" +msgstr "然后将汇总结果序列化:" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:903 msgid "We can now run our custom serialization example!" -msgstr "" +msgstr "现在我们可以运行自定义序列化示例!" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:934 msgid "" "In this part of the tutorial, we've seen how we can build clients by " "subclassing either ``NumPyClient`` or ``Client``. ``NumPyClient`` is a " -"convenience abstraction that makes it easier to work with machine " -"learning libraries that have good NumPy interoperability. ``Client`` is a" -" more flexible abstraction that allows us to do things that are not " -"possible in ``NumPyClient``. In order to do so, it requires us to handle " -"parameter serialization and deserialization ourselves." +"convenience abstraction that makes it easier to work with machine learning " +"libraries that have good NumPy interoperability. ``Client`` is a more " +"flexible abstraction that allows us to do things that are not possible in " +"``NumPyClient``. In order to do so, it requires us to handle parameter " +"serialization and deserialization ourselves." msgstr "" +"在本部分教程中,我们已经了解了如何通过子类化 ``NumPyClient`` 或 ``Client`` 来" +"构建客户端。NumPyClient \"是一个方便的抽象,可以让我们更容易地与具有良好NumPy" +"互操作性的机器学习库一起工作。Client``是一个更灵活的抽象,允许我们做一些在" +"`NumPyClient``中做不到的事情。为此,它要求我们自己处理参数序列化和反序列化。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:952 msgid "" -"This is the final part of the Flower tutorial (for now!), " -"congratulations! You're now well equipped to understand the rest of the " -"documentation. There are many topics we didn't cover in the tutorial, we " -"recommend the following resources:" +"This is the final part of the Flower tutorial (for now!), congratulations! " +"You're now well equipped to understand the rest of the documentation. There " +"are many topics we didn't cover in the tutorial, we recommend the following " +"resources:" msgstr "" +"这是 Flower 教程的最后一部分(暂时!),恭喜你!你现在已经具备了理解其余文档" +"的能力。本教程还有许多内容没有涉及,我们推荐您参考以下资源:" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:954 msgid "`Read Flower Docs `__" -msgstr "" +msgstr "阅读花朵文档 `__" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:955 msgid "" -"`Check out Flower Code Examples " -"`__" +"`Check out Flower Code Examples `__" msgstr "" +"查看 Flower 代码示例 `__" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:956 msgid "" -"`Use Flower Baselines for your research " -"`__" -msgstr "" +"`Use Flower Baselines for your research `__" +msgstr "使用 \"Flower基准 \"进行研究 `__" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:957 msgid "" -"`Watch Flower Summit 2023 videos `__" +"`Watch Flower Summit 2023 videos `__" msgstr "" +"观看 2023 年Flower峰会视频 `__" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:9 msgid "Get started with Flower" -msgstr "" +msgstr "开始使用Flower" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:11 #: ../../source/tutorial-series-what-is-federated-learning.ipynb:11 msgid "Welcome to the Flower federated learning tutorial!" -msgstr "" +msgstr "欢迎阅读Flower联合学习教程!" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:13 msgid "" -"In this notebook, we'll build a federated learning system using Flower " -"and PyTorch. In part 1, we use PyTorch for the model training pipeline " -"and data loading. In part 2, we continue to federate the PyTorch-based " -"pipeline using Flower." +"In this notebook, we'll build a federated learning system using Flower and " +"PyTorch. In part 1, we use PyTorch for the model training pipeline and data " +"loading. In part 2, we continue to federate the PyTorch-based pipeline using " +"Flower." msgstr "" +"在本笔记本中,我们将使用 Flower 和 PyTorch 构建一个联合学习系统。在第一部分" +"中,我们使用 PyTorch 进行模型训练和数据加载。在第二部分中,我们将继续使用 " +"Flower 联合基于 PyTorch 的管道。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:17 msgid "Let's get stated!" -msgstr "" +msgstr "让我们开始吧!" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:31 msgid "" "Before we begin with any actual code, let's make sure that we have " "everything we need." -msgstr "" +msgstr "在开始编写实际代码之前,让我们先确保我们已经准备好了所需的一切。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:45 msgid "" "Next, we install the necessary packages for PyTorch (``torch`` and " "``torchvision``) and Flower (``flwr``):" msgstr "" +"接下来,我们为 PyTorch(`torch`` 和`torchvision``)和 Flower(`flwr`)安装必" +"要的软件包:" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:117 msgid "Loading the data" -msgstr "" +msgstr "加载数据" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:119 msgid "" -"Federated learning can be applied to many different types of tasks across" -" different domains. In this tutorial, we introduce federated learning by " -"training a simple convolutional neural network (CNN) on the popular " -"CIFAR-10 dataset. CIFAR-10 can be used to train image classifiers that " -"distinguish between images from ten different classes:" +"Federated learning can be applied to many different types of tasks across " +"different domains. In this tutorial, we introduce federated learning by " +"training a simple convolutional neural network (CNN) on the popular CIFAR-10 " +"dataset. CIFAR-10 can be used to train image classifiers that distinguish " +"between images from ten different classes:" msgstr "" +"联邦学习可应用于不同领域的多种不同类型任务。在本教程中,我们将通过在流行的 " +"CIFAR-10 数据集上训练一个简单的卷积神经网络 (CNN) 来介绍联合学习。CIFAR-10 可" +"用于训练图像分类器,以区分来自十个不同类别的图像:" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:150 msgid "" "We simulate having multiple datasets from multiple organizations (also " -"called the \"cross-silo\" setting in federated learning) by splitting the" -" original CIFAR-10 dataset into multiple partitions. Each partition will " -"represent the data from a single organization. We're doing this purely " -"for experimentation purposes, in the real world there's no need for data " -"splitting because each organization already has their own data (so the " -"data is naturally partitioned)." -msgstr "" +"called the \"cross-silo\" setting in federated learning) by splitting the " +"original CIFAR-10 dataset into multiple partitions. Each partition will " +"represent the data from a single organization. We're doing this purely for " +"experimentation purposes, in the real world there's no need for data " +"splitting because each organization already has their own data (so the data " +"is naturally partitioned)." +msgstr "" +"我们通过将原始 CIFAR-10 数据集拆分成多个分区来模拟来自多个组织的多个数据集" +"(也称为联合学习中的 \"跨分区 \"设置)。每个分区代表一个组织的数据。我们这样" +"做纯粹是为了实验目的,在现实世界中不需要拆分数据,因为每个组织都已经有了自己" +"的数据(所以数据是自然分区的)。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:152 msgid "" -"Each organization will act as a client in the federated learning system. " -"So having ten organizations participate in a federation means having ten " +"Each organization will act as a client in the federated learning system. So " +"having ten organizations participate in a federation means having ten " "clients connected to the federated learning server:" msgstr "" +"每个组织都将充当联合学习系统中的客户端。因此,有十个组织参与联邦学习,就意味" +"着有十个客户端连接到联邦学习服务器:" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:172 msgid "" -"Let's now load the CIFAR-10 training and test set, partition them into " -"ten smaller datasets (each split into training and validation set), and " -"wrap the resulting partitions by creating a PyTorch ``DataLoader`` for " -"each of them:" +"Let's now load the CIFAR-10 training and test set, partition them into ten " +"smaller datasets (each split into training and validation set), and wrap the " +"resulting partitions by creating a PyTorch ``DataLoader`` for each of them:" msgstr "" +"现在,让我们加载 CIFAR-10 训练集和测试集,将它们分割成 10 个较小的数据集(每" +"个数据集又分为训练集和验证集),并通过为每个数据集创建 PyTorch " +"``DataLoader`` 来包装由此产生的分割集:" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:222 msgid "" "We now have a list of ten training sets and ten validation sets " -"(``trainloaders`` and ``valloaders``) representing the data of ten " -"different organizations. Each ``trainloader``/``valloader`` pair contains" -" 4500 training examples and 500 validation examples. There's also a " -"single ``testloader`` (we did not split the test set). Again, this is " -"only necessary for building research or educational systems, actual " -"federated learning systems have their data naturally distributed across " -"multiple partitions." +"(``trainloaders`` and ``valloaders``) representing the data of ten different " +"organizations. Each ``trainloader``/``valloader`` pair contains 4500 " +"training examples and 500 validation examples. There's also a single " +"``testloader`` (we did not split the test set). Again, this is only " +"necessary for building research or educational systems, actual federated " +"learning systems have their data naturally distributed across multiple " +"partitions." msgstr "" +"现在,我们有一个包含十个训练集和十个验证集(`trainloaders`` 和`valloaders``)" +"的列表,代表十个不同组织的数据。每对 ``trainloader``/``valloader`` 都包含 " +"4500 个训练示例和 500 个验证示例。还有一个单独的 ``测试加载器``(我们没有拆分" +"测试集)。同样,这只有在构建研究或教育系统时才有必要,实际的联合学习系统的数" +"据自然分布在多个分区中。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:225 msgid "" "Let's take a look at the first batch of images and labels in the first " "training set (i.e., ``trainloaders[0]``) before we move on:" msgstr "" +"在继续之前,让我们先看看第一个训练集中的第一批图像和标签(即 " +"``trainloaders[0]``):" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:264 msgid "" "The output above shows a random batch of images from the first " "``trainloader`` in our list of ten ``trainloaders``. It also prints the " "labels associated with each image (i.e., one of the ten possible labels " -"we've seen above). If you run the cell again, you should see another " -"batch of images." +"we've seen above). If you run the cell again, you should see another batch " +"of images." msgstr "" +"上面的输出显示了来自十个 \"trainloader \"列表中第一个 \"trainloader \"的随机" +"图像。它还打印了与每幅图像相关的标签(即我们上面看到的十个可能标签之一)。如" +"果您再次运行该单元,应该会看到另一批图像。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:276 msgid "Step 1: Centralized Training with PyTorch" -msgstr "" +msgstr "步骤 1:使用 PyTorch 进行集中培训" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:287 msgid "" @@ -12514,131 +14857,165 @@ msgid "" "network. This introduction assumes basic familiarity with PyTorch, so it " "doesn't cover the PyTorch-related aspects in full detail. If you want to " "dive deeper into PyTorch, we recommend `DEEP LEARNING WITH PYTORCH: A 60 " -"MINUTE BLITZ " -"`__." +"MINUTE BLITZ `__." msgstr "" +"接下来,我们将使用 PyTorch 来定义一个简单的卷积神经网络。本介绍假定您对 " +"PyTorch 有基本的了解,因此不会详细介绍与 PyTorch 相关的内容。如果你想更深入地" +"了解 PyTorch,我们推荐你阅读 \"DEEP LEARNING WITH PYTORCH: a 60 minute " +"blitz `__。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:299 msgid "Defining the model" -msgstr "" +msgstr "确定模式" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:301 msgid "" -"We use the simple CNN described in the `PyTorch tutorial " -"`__:" +"We use the simple CNN described in the `PyTorch tutorial `__:" msgstr "" +"我们使用 PyTorch 教程 `__ 中描述的简单 " +"CNN:" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:338 msgid "Let's continue with the usual training and test functions:" -msgstr "" +msgstr "让我们继续进行常规的训练和测试功能:" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:398 msgid "Training the model" -msgstr "" +msgstr "训练模型" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:400 msgid "" "We now have all the basic building blocks we need: a dataset, a model, a " -"training function, and a test function. Let's put them together to train " -"the model on the dataset of one of our organizations " -"(``trainloaders[0]``). This simulates the reality of most machine " -"learning projects today: each organization has their own data and trains " -"models only on this internal data:" +"training function, and a test function. Let's put them together to train the " +"model on the dataset of one of our organizations (``trainloaders[0]``). This " +"simulates the reality of most machine learning projects today: each " +"organization has their own data and trains models only on this internal data:" msgstr "" +"现在我们拥有了所需的所有基本构件:数据集、模型、训练函数和测试函数。让我们把" +"它们放在一起,在我们其中一个组织的数据集(``trainloaders[0]``)上训练模型。这" +"模拟了当今大多数机器学习项目的实际情况:每个组织都有自己的数据,并且只在这些" +"内部数据上训练模型:" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:430 msgid "" -"Training the simple CNN on our CIFAR-10 split for 5 epochs should result " -"in a test set accuracy of about 41%, which is not good, but at the same " -"time, it doesn't really matter for the purposes of this tutorial. The " -"intent was just to show a simplistic centralized training pipeline that " -"sets the stage for what comes next - federated learning!" +"Training the simple CNN on our CIFAR-10 split for 5 epochs should result in " +"a test set accuracy of about 41%, which is not good, but at the same time, " +"it doesn't really matter for the purposes of this tutorial. The intent was " +"just to show a simplistic centralized training pipeline that sets the stage " +"for what comes next - federated learning!" msgstr "" +"在我们的 CIFAR-10 分片上对简单 CNN 进行 5 个历元的训练后,测试集的准确率应为 " +"41%,这并不理想,但同时对本教程而言也并不重要。我们只是想展示一个简单的集中式" +"训练管道,为接下来的联合学习做好铺垫!" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:442 msgid "Step 2: Federated Learning with Flower" -msgstr "" +msgstr "步骤 2:与 Flower 联合学习" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:444 msgid "" -"Step 1 demonstrated a simple centralized training pipeline. All data was " -"in one place (i.e., a single ``trainloader`` and a single ``valloader``)." -" Next, we'll simulate a situation where we have multiple datasets in " -"multiple organizations and where we train a model over these " -"organizations using federated learning." +"Step 1 demonstrated a simple centralized training pipeline. All data was in " +"one place (i.e., a single ``trainloader`` and a single ``valloader``). Next, " +"we'll simulate a situation where we have multiple datasets in multiple " +"organizations and where we train a model over these organizations using " +"federated learning." msgstr "" +"步骤 1 演示了一个简单的集中式训练管道。所有数据都在一个地方(即一个 " +"\"trainloader \"和一个 \"valloader\")。接下来,我们将模拟在多个组织中拥有多" +"个数据集的情况,并使用联合学习在这些组织中训练一个模型。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:456 msgid "Updating model parameters" -msgstr "" +msgstr "更新模型参数" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:458 msgid "" -"In federated learning, the server sends the global model parameters to " -"the client, and the client updates the local model with the parameters " -"received from the server. It then trains the model on the local data " -"(which changes the model parameters locally) and sends the " -"updated/changed model parameters back to the server (or, alternatively, " -"it sends just the gradients back to the server, not the full model " -"parameters)." +"In federated learning, the server sends the global model parameters to the " +"client, and the client updates the local model with the parameters received " +"from the server. It then trains the model on the local data (which changes " +"the model parameters locally) and sends the updated/changed model parameters " +"back to the server (or, alternatively, it sends just the gradients back to " +"the server, not the full model parameters)." msgstr "" +"在联邦学习中,服务器将全局模型参数发送给客户端,客户端根据从服务器接收到的参" +"数更新本地模型。然后,客户端根据本地数据对模型进行训练(在本地更改模型参" +"数),并将更新/更改后的模型参数发回服务器(或者,客户端只将梯度参数发回服务" +"器,而不是全部模型参数)。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:460 msgid "" "We need two helper functions to update the local model with parameters " -"received from the server and to get the updated model parameters from the" -" local model: ``set_parameters`` and ``get_parameters``. The following " -"two functions do just that for the PyTorch model above." +"received from the server and to get the updated model parameters from the " +"local model: ``set_parameters`` and ``get_parameters``. The following two " +"functions do just that for the PyTorch model above." msgstr "" +"我们需要两个辅助函数,用从服务器接收到的参数更新本地模型,并从本地模型获取更" +"新后的模型参数: set_parameters```和`get_parameters``。下面两个函数就是为上面" +"的 PyTorch 模型做这些工作的。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:462 msgid "" -"The details of how this works are not really important here (feel free to" -" consult the PyTorch documentation if you want to learn more). In " -"essence, we use ``state_dict`` to access PyTorch model parameter tensors." -" The parameter tensors are then converted to/from a list of NumPy " -"ndarray's (which Flower knows how to serialize/deserialize):" +"The details of how this works are not really important here (feel free to " +"consult the PyTorch documentation if you want to learn more). In essence, we " +"use ``state_dict`` to access PyTorch model parameter tensors. The parameter " +"tensors are then converted to/from a list of NumPy ndarray's (which Flower " +"knows how to serialize/deserialize):" msgstr "" +"在这里,如何工作的细节并不重要(如果你想了解更多,请随时查阅 PyTorch 文档)。" +"本质上,我们使用 ``state_dict`` 访问 PyTorch 模型参数张量。然后,参数张量会被" +"转换成/转换成 NumPy ndarray 列表(Flower 知道如何序列化/反序列化):" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:490 msgid "Implementing a Flower client" -msgstr "" +msgstr "实施 Flower 客户端" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:492 msgid "" -"With that out of the way, let's move on to the interesting part. " -"Federated learning systems consist of a server and multiple clients. In " -"Flower, we create clients by implementing subclasses of " -"``flwr.client.Client`` or ``flwr.client.NumPyClient``. We use " -"``NumPyClient`` in this tutorial because it is easier to implement and " -"requires us to write less boilerplate." +"With that out of the way, let's move on to the interesting part. Federated " +"learning systems consist of a server and multiple clients. In Flower, we " +"create clients by implementing subclasses of ``flwr.client.Client`` or " +"``flwr.client.NumPyClient``. We use ``NumPyClient`` in this tutorial because " +"it is easier to implement and requires us to write less boilerplate." msgstr "" +"说完这些,让我们进入有趣的部分。联合学习系统由一个服务器和多个客户端组成。在 " +"Flower 中,我们通过实现 ``flwr.client.Client`` 或 ``flwr.client." +"NumPyClient`` 的子类来创建客户端。在本教程中,我们使用``NumPyClient``,因为它" +"更容易实现,需要我们编写的模板也更少。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:494 msgid "" -"To implement the Flower client, we create a subclass of " -"``flwr.client.NumPyClient`` and implement the three methods " -"``get_parameters``, ``fit``, and ``evaluate``:" +"To implement the Flower client, we create a subclass of ``flwr.client." +"NumPyClient`` and implement the three methods ``get_parameters``, ``fit``, " +"and ``evaluate``:" msgstr "" +"为实现 Flower 客户端,我们创建了 ``flwr.client.NumPyClient`` 的子类,并实现" +"了 ``get_parameters``、``fit`` 和``evaluate`` 三个方法:" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:496 msgid "``get_parameters``: Return the current local model parameters" -msgstr "" +msgstr "`get_parameters``: 返回当前本地模型参数" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:497 msgid "" "``fit``: Receive model parameters from the server, train the model " -"parameters on the local data, and return the (updated) model parameters " -"to the server" +"parameters on the local data, and return the (updated) model parameters to " +"the server" msgstr "" +"`fit``: 从服务器接收模型参数,在本地数据上训练模型参数,并将(更新的)模型参" +"数返回服务器" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:498 msgid "" -"``evaluate``: Receive model parameters from the server, evaluate the " -"model parameters on the local data, and return the evaluation result to " -"the server" +"``evaluate``: Receive model parameters from the server, evaluate the model " +"parameters on the local data, and return the evaluation result to the server" msgstr "" +"`评估``: 从服务器接收模型参数,在本地数据上评估模型参数,并将评估结果返回服" +"务器" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:500 msgid "" @@ -12646,36 +15023,48 @@ msgid "" "components for model training and evaluation. Let's see a simple Flower " "client implementation that brings everything together:" msgstr "" +"我们提到,我们的客户端将使用之前定义的 PyTorch 组件进行模型训练和评估。让我们" +"来看看一个简单的 Flower 客户端实现,它将一切都整合在一起:" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:537 msgid "" "Our class ``FlowerClient`` defines how local training/evaluation will be " -"performed and allows Flower to call the local training/evaluation through" -" ``fit`` and ``evaluate``. Each instance of ``FlowerClient`` represents a" -" *single client* in our federated learning system. Federated learning " -"systems have multiple clients (otherwise, there's not much to federate), " -"so each client will be represented by its own instance of " -"``FlowerClient``. If we have, for example, three clients in our workload," -" then we'd have three instances of ``FlowerClient``. Flower calls " -"``FlowerClient.fit`` on the respective instance when the server selects a" -" particular client for training (and ``FlowerClient.evaluate`` for " -"evaluation)." -msgstr "" +"performed and allows Flower to call the local training/evaluation through " +"``fit`` and ``evaluate``. Each instance of ``FlowerClient`` represents a " +"*single client* in our federated learning system. Federated learning systems " +"have multiple clients (otherwise, there's not much to federate), so each " +"client will be represented by its own instance of ``FlowerClient``. If we " +"have, for example, three clients in our workload, then we'd have three " +"instances of ``FlowerClient``. Flower calls ``FlowerClient.fit`` on the " +"respective instance when the server selects a particular client for training " +"(and ``FlowerClient.evaluate`` for evaluation)." +msgstr "" +"我们的类 ``FlowerClient`` 定义了本地训练/评估的执行方式,并允许 Flower 通过 " +"``fit`` 和 ``evaluate`` 调用本地训练/评估。每个 ``FlowerClient`` 实例都代表联" +"合学习系统中的*单个客户端*。联合学习系统有多个客户端(否则就没有什么可联合" +"的),因此每个客户端都将由自己的 ``FlowerClient`` 实例来代表。例如,如果我们" +"的工作负载中有三个客户端,那么我们就会有三个 ``FlowerClient`` 实例。当服务器" +"选择特定客户端进行训练时,Flower 会调用相应实例上的 ``FlowerClient.fit`` (评" +"估时调用 ``FlowerClient.evaluate``)。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:541 msgid "Using the Virtual Client Engine" -msgstr "" +msgstr "使用虚拟客户端引擎" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:543 msgid "" -"In this notebook, we want to simulate a federated learning system with 10" -" clients on a single machine. This means that the server and all 10 " -"clients will live on a single machine and share resources such as CPU, " -"GPU, and memory. Having 10 clients would mean having 10 instances of " -"``FlowerClient`` in memory. Doing this on a single machine can quickly " -"exhaust the available memory resources, even if only a subset of these " -"clients participates in a single round of federated learning." +"In this notebook, we want to simulate a federated learning system with 10 " +"clients on a single machine. This means that the server and all 10 clients " +"will live on a single machine and share resources such as CPU, GPU, and " +"memory. Having 10 clients would mean having 10 instances of ``FlowerClient`` " +"in memory. Doing this on a single machine can quickly exhaust the available " +"memory resources, even if only a subset of these clients participates in a " +"single round of federated learning." msgstr "" +"在本笔记本中,我们要模拟一个联合学习系统,在一台机器上有 10 个客户端。这意味" +"着服务器和所有 10 个客户端都将位于一台机器上,并共享 CPU、GPU 和内存等资源。" +"有 10 个客户端就意味着内存中有 10 个 ``FlowerClient`` 实例。在单台机器上这样" +"做会很快耗尽可用的内存资源,即使这些客户端中只有一个子集参与了一轮联合学习。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:545 msgid "" @@ -12683,358 +15072,464 @@ msgid "" "multiple machines, Flower, therefore, provides special simulation " "capabilities that create ``FlowerClient`` instances only when they are " "actually necessary for training or evaluation. To enable the Flower " -"framework to create clients when necessary, we need to implement a " -"function called ``client_fn`` that creates a ``FlowerClient`` instance on" -" demand. Flower calls ``client_fn`` whenever it needs an instance of one " -"particular client to call ``fit`` or ``evaluate`` (those instances are " -"usually discarded after use, so they should not keep any local state). " -"Clients are identified by a client ID, or short ``cid``. The ``cid`` can " -"be used, for example, to load different local data partitions for " -"different clients, as can be seen below:" -msgstr "" +"framework to create clients when necessary, we need to implement a function " +"called ``client_fn`` that creates a ``FlowerClient`` instance on demand. " +"Flower calls ``client_fn`` whenever it needs an instance of one particular " +"client to call ``fit`` or ``evaluate`` (those instances are usually " +"discarded after use, so they should not keep any local state). Clients are " +"identified by a client ID, or short ``cid``. The ``cid`` can be used, for " +"example, to load different local data partitions for different clients, as " +"can be seen below:" +msgstr "" +"除了服务器和客户端在多台机器上运行的常规功能外,Flower 还提供了特殊的模拟功" +"能,即只有在训练或评估实际需要时才创建 ``FlowerClient`` 实例。为了让 Flower " +"框架能在必要时创建客户端,我们需要实现一个名为 ``client_fn`` 的函数,它能按需" +"创建一个 ``FlowerClient`` 实例。每当 Flower 需要一个特定的客户端实例来调用 " +"``fit`` 或 ``evaluate`` 时,它就会调用 ``client_fn``(这些实例在使用后通常会" +"被丢弃,因此它们不应保留任何本地状态)。客户端由一个客户端 ID 或简短的 " +"``cid`` 标识。例如,可以使用 ``cid`` 为不同的客户端加载不同的本地数据分区,如" +"下所示:" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:580 msgid "Starting the training" -msgstr "" +msgstr "开始训练" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:582 msgid "" -"We now have the class ``FlowerClient`` which defines client-side " -"training/evaluation and ``client_fn`` which allows Flower to create " -"``FlowerClient`` instances whenever it needs to call ``fit`` or " -"``evaluate`` on one particular client. The last step is to start the " -"actual simulation using ``flwr.simulation.start_simulation``." +"We now have the class ``FlowerClient`` which defines client-side training/" +"evaluation and ``client_fn`` which allows Flower to create ``FlowerClient`` " +"instances whenever it needs to call ``fit`` or ``evaluate`` on one " +"particular client. The last step is to start the actual simulation using " +"``flwr.simulation.start_simulation``." msgstr "" +"现在我们有了定义客户端训练/评估的类 ``FlowerClient`` 和允许 Flower 在需要调用" +"某个客户端的 ``fit` 或 ``evaluate` 时创建 ``FlowerClient`` 实例的 " +"``client_fn` 类。最后一步是使用 ``flwr.simulation.start_simulation`` 启动实际" +"模拟。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:584 msgid "" "The function ``start_simulation`` accepts a number of arguments, amongst " -"them the ``client_fn`` used to create ``FlowerClient`` instances, the " -"number of clients to simulate (``num_clients``), the number of federated " -"learning rounds (``num_rounds``), and the strategy. The strategy " -"encapsulates the federated learning approach/algorithm, for example, " -"*Federated Averaging* (FedAvg)." +"them the ``client_fn`` used to create ``FlowerClient`` instances, the number " +"of clients to simulate (``num_clients``), the number of federated learning " +"rounds (``num_rounds``), and the strategy. The strategy encapsulates the " +"federated learning approach/algorithm, for example, *Federated Averaging* " +"(FedAvg)." msgstr "" +"函数 ``start_simulation`` 接受许多参数,其中包括用于创建 ``FlowerClient`` 实" +"例的 ``client_fn``、要模拟的客户端数量(``num_clients``)、联合学习轮数" +"(``num_rounds``)和策略。策略封装了联合学习方法/算法,例如*联合平均* " +"(FedAvg)。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:586 msgid "" "Flower has a number of built-in strategies, but we can also use our own " -"strategy implementations to customize nearly all aspects of the federated" -" learning approach. For this example, we use the built-in ``FedAvg`` " -"implementation and customize it using a few basic parameters. The last " -"step is the actual call to ``start_simulation`` which - you guessed it - " -"starts the simulation:" +"strategy implementations to customize nearly all aspects of the federated " +"learning approach. For this example, we use the built-in ``FedAvg`` " +"implementation and customize it using a few basic parameters. The last step " +"is the actual call to ``start_simulation`` which - you guessed it - starts " +"the simulation:" msgstr "" +"Flower 有许多内置策略,但我们也可以使用自己的策略实现来定制联合学习方法的几乎" +"所有方面。在本例中,我们使用内置的 ``FedAvg`` 实现,并使用一些基本参数对其进" +"行定制。最后一步是实际调用 ``start_simulation``,你猜对了,就是开始模拟:" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:628 msgid "Behind the scenes" -msgstr "" +msgstr "幕后花絮" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:630 msgid "So how does this work? How does Flower execute this simulation?" -msgstr "" +msgstr "那么它是如何工作的呢?Flower \"如何进行模拟?" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:632 #, python-format msgid "" -"When we call ``start_simulation``, we tell Flower that there are 10 " -"clients (``num_clients=10``). Flower then goes ahead an asks the " -"``FedAvg`` strategy to select clients. ``FedAvg`` knows that it should " -"select 100% of the available clients (``fraction_fit=1.0``), so it goes " -"ahead and selects 10 random clients (i.e., 100% of 10)." +"When we call ``start_simulation``, we tell Flower that there are 10 clients " +"(``num_clients=10``). Flower then goes ahead an asks the ``FedAvg`` strategy " +"to select clients. ``FedAvg`` knows that it should select 100% of the " +"available clients (``fraction_fit=1.0``), so it goes ahead and selects 10 " +"random clients (i.e., 100% of 10)." msgstr "" +"当我们调用 ``start_simulation`` 时,我们会告诉 Flower 有 10 个客户" +"(`num_clients=10``)。然后,Flower 会要求 ``FedAvg`` 策略选择客户。" +"``FedAvg`` 知道它应该选择 100%的可用客户(``fraction_fit=1.0``),所以它会随" +"机选择 10 个客户(即 10 的 100%)。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:634 msgid "" -"Flower then asks the selected 10 clients to train the model. When the " -"server receives the model parameter updates from the clients, it hands " -"those updates over to the strategy (*FedAvg*) for aggregation. The " -"strategy aggregates those updates and returns the new global model, which" -" then gets used in the next round of federated learning." +"Flower then asks the selected 10 clients to train the model. When the server " +"receives the model parameter updates from the clients, it hands those " +"updates over to the strategy (*FedAvg*) for aggregation. The strategy " +"aggregates those updates and returns the new global model, which then gets " +"used in the next round of federated learning." msgstr "" +"然后,\"Flower \"会要求选定的 10 个客户端对模型进行训练。服务器收到客户端的模" +"型参数更新后,会将这些更新交给策略(*FedAvg*)进行汇总。策略会汇总这些更新并" +"返回新的全局模型,然后将其用于下一轮联合学习。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:646 msgid "Where's the accuracy?" -msgstr "" +msgstr "准确性体现在哪里?" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:648 msgid "" -"You may have noticed that all metrics except for ``losses_distributed`` " -"are empty. Where did the ``{\"accuracy\": float(accuracy)}`` go?" +"You may have noticed that all metrics except for ``losses_distributed`` are " +"empty. Where did the ``{\"accuracy\": float(accuracy)}`` go?" msgstr "" +"您可能已经注意到,除了 ``losses_distributed`` 以外,所有指标都是空的。{\"准确" +"度\": float(准确度)}``去哪儿了?" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:650 msgid "" -"Flower can automatically aggregate losses returned by individual clients," -" but it cannot do the same for metrics in the generic metrics dictionary " -"(the one with the ``accuracy`` key). Metrics dictionaries can contain " -"very different kinds of metrics and even key/value pairs that are not " -"metrics at all, so the framework does not (and can not) know how to " -"handle these automatically." +"Flower can automatically aggregate losses returned by individual clients, " +"but it cannot do the same for metrics in the generic metrics dictionary (the " +"one with the ``accuracy`` key). Metrics dictionaries can contain very " +"different kinds of metrics and even key/value pairs that are not metrics at " +"all, so the framework does not (and can not) know how to handle these " +"automatically." msgstr "" +"Flower 可以自动汇总单个客户端返回的损失,但无法对通用度量字典中的度量进行同样" +"的处理(即带有 \"准确度 \"键的度量字典)。度量值字典可以包含非常不同种类的度" +"量值,甚至包含根本不是度量值的键/值对,因此框架不知道(也无法知道)如何自动处" +"理这些度量值。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:652 msgid "" -"As users, we need to tell the framework how to handle/aggregate these " -"custom metrics, and we do so by passing metric aggregation functions to " -"the strategy. The strategy will then call these functions whenever it " -"receives fit or evaluate metrics from clients. The two possible functions" -" are ``fit_metrics_aggregation_fn`` and " -"``evaluate_metrics_aggregation_fn``." +"As users, we need to tell the framework how to handle/aggregate these custom " +"metrics, and we do so by passing metric aggregation functions to the " +"strategy. The strategy will then call these functions whenever it receives " +"fit or evaluate metrics from clients. The two possible functions are " +"``fit_metrics_aggregation_fn`` and ``evaluate_metrics_aggregation_fn``." msgstr "" +"作为用户,我们需要告诉框架如何处理/聚合这些自定义指标,为此,我们将指标聚合函" +"数传递给策略。然后,只要从客户端接收到拟合或评估指标,策略就会调用这些函数。" +"两个可能的函数是 ``fit_metrics_aggregation_fn`` 和 " +"``evaluate_metrics_aggregation_fn``。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:654 msgid "" "Let's create a simple weighted averaging function to aggregate the " "``accuracy`` metric we return from ``evaluate``:" msgstr "" +"让我们创建一个简单的加权平均函数来汇总从 ``evaluate`` 返回的 ``accuracy`` 指" +"标:" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:680 msgid "" "The only thing left to do is to tell the strategy to call this function " "whenever it receives evaluation metric dictionaries from the clients:" msgstr "" +"剩下要做的就是告诉策略,每当它从客户端接收到评估度量字典时,都要调用这个函" +"数:" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:717 msgid "" "We now have a full system that performs federated training and federated " -"evaluation. It uses the ``weighted_average`` function to aggregate custom" -" evaluation metrics and calculates a single ``accuracy`` metric across " -"all clients on the server side." +"evaluation. It uses the ``weighted_average`` function to aggregate custom " +"evaluation metrics and calculates a single ``accuracy`` metric across all " +"clients on the server side." msgstr "" +"我们现在有了一个完整的系统,可以执行联合训练和联合评估。它使用 " +"``weighted_average`` 函数汇总自定义评估指标,并在服务器端计算所有客户端的单" +"一 ``accuracy`` 指标。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:719 msgid "" "The other two categories of metrics (``losses_centralized`` and " "``metrics_centralized``) are still empty because they only apply when " -"centralized evaluation is being used. Part two of the Flower tutorial " -"will cover centralized evaluation." +"centralized evaluation is being used. Part two of the Flower tutorial will " +"cover centralized evaluation." msgstr "" +"其他两类指标(`losses_centralized`` 和 `metrics_centralized`)仍然是空的,因" +"为它们只适用于集中评估。Flower 教程的第二部分将介绍集中式评估。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:731 #: ../../source/tutorial-series-what-is-federated-learning.ipynb:351 msgid "Final remarks" -msgstr "" +msgstr "结束语" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:733 msgid "" -"Congratulations, you just trained a convolutional neural network, " -"federated over 10 clients! With that, you understand the basics of " -"federated learning with Flower. The same approach you've seen can be used" -" with other machine learning frameworks (not just PyTorch) and tasks (not" -" just CIFAR-10 images classification), for example NLP with Hugging Face " -"Transformers or speech with SpeechBrain." +"Congratulations, you just trained a convolutional neural network, federated " +"over 10 clients! With that, you understand the basics of federated learning " +"with Flower. The same approach you've seen can be used with other machine " +"learning frameworks (not just PyTorch) and tasks (not just CIFAR-10 images " +"classification), for example NLP with Hugging Face Transformers or speech " +"with SpeechBrain." msgstr "" +"恭喜你,你刚刚训练了一个由 10 个客户端组成的卷积神经网络!这样,你就了解了使" +"用 Flower 进行联合学习的基础知识。你所看到的方法同样适用于其他机器学习框架" +"(不只是 PyTorch)和任务(不只是 CIFAR-10 图像分类),例如使用 Hugging Face " +"Transformers 的 NLP 或使用 SpeechBrain 的语音。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:735 msgid "" -"In the next notebook, we're going to cover some more advanced concepts. " -"Want to customize your strategy? Initialize parameters on the server " -"side? Or evaluate the aggregated model on the server side? We'll cover " -"all this and more in the next tutorial." +"In the next notebook, we're going to cover some more advanced concepts. Want " +"to customize your strategy? Initialize parameters on the server side? Or " +"evaluate the aggregated model on the server side? We'll cover all this and " +"more in the next tutorial." msgstr "" +"在下一个笔记本中,我们将介绍一些更先进的概念。想定制你的策略吗?在服务器端初" +"始化参数?或者在服务器端评估聚合模型?我们将在下一个教程中介绍所有这些内容以" +"及更多。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:753 msgid "" -"The `Flower Federated Learning Tutorial - Part 2 " -"`__ goes into more depth about strategies and all " -"the advanced things you can build with them." +"The `Flower Federated Learning Tutorial - Part 2 `__ goes " +"into more depth about strategies and all the advanced things you can build " +"with them." msgstr "" +"Flower 联合学习教程 - 第 2 部分 `__ 更深入地介绍了策略以及可以" +"使用策略构建的所有高级功能。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:9 msgid "Use a federated learning strategy" -msgstr "" +msgstr "使用联邦学习策略" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:11 msgid "" "Welcome to the next part of the federated learning tutorial. In previous " -"parts of this tutorial, we introduced federated learning with PyTorch and" -" Flower (`part 1 `__)." +"parts of this tutorial, we introduced federated learning with PyTorch and " +"Flower (`part 1 `__)." msgstr "" +"欢迎来到联合学习教程的下一部分。在本教程的前几部分,我们介绍了使用 PyTorch " +"和 Flower 进行联合学习(\"第 1 部分 `___\")。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:13 msgid "" -"In this notebook, we'll begin to customize the federated learning system " -"we built in the introductory notebook (again, using `Flower " -"`__ and `PyTorch `__)." +"In this notebook, we'll begin to customize the federated learning system we " +"built in the introductory notebook (again, using `Flower `__ and `PyTorch `__)." msgstr "" +"在本笔记本中,我们将开始定制在入门笔记本中构建的联合学习系统(再次使用 " +"`Flower `__ 和 `PyTorch `__)。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:17 msgid "Let's move beyond FedAvg with Flower strategies!" -msgstr "" +msgstr "让我们超越 FedAvg,采用Flower策略!" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:309 msgid "Strategy customization" -msgstr "" +msgstr "战略定制" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:311 msgid "" "So far, everything should look familiar if you've worked through the " -"introductory notebook. With that, we're ready to introduce a number of " -"new features." +"introductory notebook. With that, we're ready to introduce a number of new " +"features." msgstr "" +"到目前为止,如果您已经阅读过入门笔记本,那么一切都应该很熟悉了。接下来,我们" +"将介绍一些新功能。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:323 msgid "Server-side parameter **initialization**" -msgstr "" +msgstr "服务器端参数 **初始化**" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:325 msgid "" -"Flower, by default, initializes the global model by asking one random " -"client for the initial parameters. In many cases, we want more control " -"over parameter initialization though. Flower therefore allows you to " -"directly pass the initial parameters to the Strategy:" +"Flower, by default, initializes the global model by asking one random client " +"for the initial parameters. In many cases, we want more control over " +"parameter initialization though. Flower therefore allows you to directly " +"pass the initial parameters to the Strategy:" msgstr "" +"默认情况下,Flower 会通过向一个随机客户端询问初始参数来初始化全局模型。但在许" +"多情况下,我们需要对参数初始化进行更多控制。因此,Flower 允许您直接将初始参数" +"传递给策略:" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:370 msgid "" -"Passing ``initial_parameters`` to the ``FedAvg`` strategy prevents Flower" -" from asking one of the clients for the initial parameters. If we look " +"Passing ``initial_parameters`` to the ``FedAvg`` strategy prevents Flower " +"from asking one of the clients for the initial parameters. If we look " "closely, we can see that the logs do not show any calls to the " "``FlowerClient.get_parameters`` method." msgstr "" +"向 ``FedAvg`` 策略传递 ``initial_parameters`` 可以防止 Flower 向其中一个客户" +"端询问初始参数。如果我们仔细观察,就会发现日志中没有显示对 ``FlowerClient." +"get_parameters`` 方法的任何调用。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:382 msgid "Starting with a customized strategy" -msgstr "" +msgstr "从定制战略开始" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:384 msgid "" -"We've seen the function ``start_simulation`` before. It accepts a number " -"of arguments, amongst them the ``client_fn`` used to create " -"``FlowerClient`` instances, the number of clients to simulate " -"``num_clients``, the number of rounds ``num_rounds``, and the strategy." +"We've seen the function ``start_simulation`` before. It accepts a number of " +"arguments, amongst them the ``client_fn`` used to create ``FlowerClient`` " +"instances, the number of clients to simulate ``num_clients``, the number of " +"rounds ``num_rounds``, and the strategy." msgstr "" +"我们以前见过函数 ``start_simulation``。它接受许多参数,其中包括用于创建 " +"``FlowerClient`` 实例的 ``client_fn``、要模拟的客户数量 ``num_clients``、回合" +"数 ``num_rounds``和策略。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:386 msgid "" "The strategy encapsulates the federated learning approach/algorithm, for " -"example, ``FedAvg`` or ``FedAdagrad``. Let's try to use a different " -"strategy this time:" +"example, ``FedAvg`` or ``FedAdagrad``. Let's try to use a different strategy " +"this time:" msgstr "" +"该策略封装了联合学习方法/算法,例如`FedAvg``或`FedAdagrad``。这次让我们尝试使" +"用不同的策略:" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:424 msgid "Server-side parameter **evaluation**" -msgstr "" +msgstr "服务器端参数**评估**" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:426 msgid "" -"Flower can evaluate the aggregated model on the server-side or on the " -"client-side. Client-side and server-side evaluation are similar in some " -"ways, but different in others." +"Flower can evaluate the aggregated model on the server-side or on the client-" +"side. Client-side and server-side evaluation are similar in some ways, but " +"different in others." msgstr "" +"Flower 可以在服务器端或客户端评估聚合模型。客户端和服务器端评估在某些方面相" +"似,但也有不同之处。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:428 msgid "" "**Centralized Evaluation** (or *server-side evaluation*) is conceptually " "simple: it works the same way that evaluation in centralized machine " "learning does. If there is a server-side dataset that can be used for " -"evaluation purposes, then that's great. We can evaluate the newly " -"aggregated model after each round of training without having to send the " -"model to clients. We're also fortunate in the sense that our entire " -"evaluation dataset is available at all times." +"evaluation purposes, then that's great. We can evaluate the newly aggregated " +"model after each round of training without having to send the model to " +"clients. We're also fortunate in the sense that our entire evaluation " +"dataset is available at all times." msgstr "" +"**集中评估**(或*服务器端评估*)在概念上很简单:它的工作方式与集中式机器学习" +"中的评估方式相同。如果有一个服务器端数据集可用于评估目的,那就太好了。我们可" +"以在每一轮训练后对新聚合的模型进行评估,而无需将模型发送给客户端。我们也很幸" +"运,因为我们的整个评估数据集随时可用。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:430 msgid "" -"**Federated Evaluation** (or *client-side evaluation*) is more complex, " -"but also more powerful: it doesn't require a centralized dataset and " -"allows us to evaluate models over a larger set of data, which often " -"yields more realistic evaluation results. In fact, many scenarios require" -" us to use **Federated Evaluation** if we want to get representative " -"evaluation results at all. But this power comes at a cost: once we start " -"to evaluate on the client side, we should be aware that our evaluation " -"dataset can change over consecutive rounds of learning if those clients " -"are not always available. Moreover, the dataset held by each client can " -"also change over consecutive rounds. This can lead to evaluation results " -"that are not stable, so even if we would not change the model, we'd see " -"our evaluation results fluctuate over consecutive rounds." -msgstr "" +"**Federated Evaluation** (or *client-side evaluation*) is more complex, but " +"also more powerful: it doesn't require a centralized dataset and allows us " +"to evaluate models over a larger set of data, which often yields more " +"realistic evaluation results. In fact, many scenarios require us to use " +"**Federated Evaluation** if we want to get representative evaluation results " +"at all. But this power comes at a cost: once we start to evaluate on the " +"client side, we should be aware that our evaluation dataset can change over " +"consecutive rounds of learning if those clients are not always available. " +"Moreover, the dataset held by each client can also change over consecutive " +"rounds. This can lead to evaluation results that are not stable, so even if " +"we would not change the model, we'd see our evaluation results fluctuate " +"over consecutive rounds." +msgstr "" +"**联邦评估**(或*客户端评估*)更为复杂,但也更为强大:它不需要集中的数据集," +"允许我们在更大的数据集上对模型进行评估,这通常会产生更真实的评估结果。事实" +"上,如果我们想得到有代表性的评估结果,很多情况下都需要使用**联邦评估**。但" +"是,这种能力是有代价的:一旦我们开始在客户端进行评估,我们就应该意识到,如果" +"这些客户端并不总是可用,我们的评估数据集可能会在连续几轮学习中发生变化。此" +"外,每个客户端所拥有的数据集也可能在连续几轮学习中发生变化。这可能会导致评估" +"结果不稳定,因此即使我们不改变模型,也会看到评估结果在连续几轮中波动。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:433 msgid "" "We've seen how federated evaluation works on the client side (i.e., by " -"implementing the ``evaluate`` method in ``FlowerClient``). Now let's see " -"how we can evaluate aggregated model parameters on the server-side:" +"implementing the ``evaluate`` method in ``FlowerClient``). Now let's see how " +"we can evaluate aggregated model parameters on the server-side:" msgstr "" +"我们已经了解了联合评估如何在客户端工作(即通过在 ``FlowerClient`` 中实现 " +"``evaluate`` 方法)。现在让我们看看如何在服务器端评估聚合模型参数:" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:490 msgid "Sending/receiving arbitrary values to/from clients" -msgstr "" +msgstr "向/从客户端发送/接收任意值" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:492 msgid "" -"In some situations, we want to configure client-side execution (training," -" evaluation) from the server-side. One example for that is the server " -"asking the clients to train for a certain number of local epochs. Flower " -"provides a way to send configuration values from the server to the " -"clients using a dictionary. Let's look at an example where the clients " -"receive values from the server through the ``config`` parameter in " -"``fit`` (``config`` is also available in ``evaluate``). The ``fit`` " -"method receives the configuration dictionary through the ``config`` " -"parameter and can then read values from this dictionary. In this example," -" it reads ``server_round`` and ``local_epochs`` and uses those values to " -"improve the logging and configure the number of local training epochs:" -msgstr "" +"In some situations, we want to configure client-side execution (training, " +"evaluation) from the server-side. One example for that is the server asking " +"the clients to train for a certain number of local epochs. Flower provides a " +"way to send configuration values from the server to the clients using a " +"dictionary. Let's look at an example where the clients receive values from " +"the server through the ``config`` parameter in ``fit`` (``config`` is also " +"available in ``evaluate``). The ``fit`` method receives the configuration " +"dictionary through the ``config`` parameter and can then read values from " +"this dictionary. In this example, it reads ``server_round`` and " +"``local_epochs`` and uses those values to improve the logging and configure " +"the number of local training epochs:" +msgstr "" +"在某些情况下,我们希望从服务器端配置客户端的执行(训练、评估)。其中一个例子" +"就是服务器要求客户端训练一定数量的本地历元。Flower 提供了一种使用字典从服务器" +"向客户端发送配置值的方法。让我们来看一个例子:客户端通过 ``fit`` 中的 " +"``config`` 参数从服务器接收配置值(``evaluate`` 中也有 ``config`` 参数)。" +"``fit`` 方法通过 ``config`` 参数接收配置字典,然后从字典中读取值。在本例中," +"它读取了 ``server_round`` 和 ``local_epochs``,并使用这些值来改进日志记录和配" +"置本地训练历元的数量:" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:546 msgid "" -"So how can we send this config dictionary from server to clients? The " -"built-in Flower Strategies provide way to do this, and it works similarly" -" to the way server-side evaluation works. We provide a function to the " -"strategy, and the strategy calls this function for every round of " -"federated learning:" +"So how can we send this config dictionary from server to clients? The built-" +"in Flower Strategies provide way to do this, and it works similarly to the " +"way server-side evaluation works. We provide a function to the strategy, and " +"the strategy calls this function for every round of federated learning:" msgstr "" +"那么,如何将配置字典从服务器发送到客户端呢?内置的 \"Flower策略\"(Flower " +"Strategies)提供了这样的方法,其工作原理与服务器端评估的工作原理类似。我们为" +"策略提供一个函数,策略会在每一轮联合学习中调用这个函数:" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:576 msgid "" -"Next, we'll just pass this function to the FedAvg strategy before " -"starting the simulation:" -msgstr "" +"Next, we'll just pass this function to the FedAvg strategy before starting " +"the simulation:" +msgstr "接下来,我们只需在开始模拟前将此函数传递给 FedAvg 策略即可:" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:613 msgid "" -"As we can see, the client logs now include the current round of federated" -" learning (which they read from the ``config`` dictionary). We can also " -"configure local training to run for one epoch during the first and second" -" round of federated learning, and then for two epochs during the third " -"round." +"As we can see, the client logs now include the current round of federated " +"learning (which they read from the ``config`` dictionary). We can also " +"configure local training to run for one epoch during the first and second " +"round of federated learning, and then for two epochs during the third round." msgstr "" +"我们可以看到,客户端日志现在包含了当前一轮的联合学习(从 ``config`` 字典中读" +"取)。我们还可以将本地训练配置为在第一轮和第二轮联合学习期间运行一个历元,然" +"后在第三轮联合学习期间运行两个历元。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:615 msgid "" "Clients can also return arbitrary values to the server. To do so, they " -"return a dictionary from ``fit`` and/or ``evaluate``. We have seen and " -"used this concept throughout this notebook without mentioning it " -"explicitly: our ``FlowerClient`` returns a dictionary containing a custom" -" key/value pair as the third return value in ``evaluate``." +"return a dictionary from ``fit`` and/or ``evaluate``. We have seen and used " +"this concept throughout this notebook without mentioning it explicitly: our " +"``FlowerClient`` returns a dictionary containing a custom key/value pair as " +"the third return value in ``evaluate``." msgstr "" +"客户端还可以向服务器返回任意值。为此,它们会从 ``fit`` 和/或 ``evaluate`` 返" +"回一个字典。我们在本笔记本中看到并使用了这一概念,但并未明确提及:我们的 " +"``FlowerClient`` 返回一个包含自定义键/值对的 dictionary,作为 ``evaluate`` 中" +"的第三个返回值。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:627 msgid "Scaling federated learning" -msgstr "" +msgstr "扩大联合学习的规模" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:629 msgid "" "As a last step in this notebook, let's see how we can use Flower to " "experiment with a large number of clients." -msgstr "" +msgstr "作为本笔记本的最后一步,让我们看看如何使用 Flower 对大量客户进行实验。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:651 #, python-format msgid "" "We now have 1000 partitions, each holding 45 training and 5 validation " -"examples. Given that the number of training examples on each client is " -"quite small, we should probably train the model a bit longer, so we " -"configure the clients to perform 3 local training epochs. We should also " -"adjust the fraction of clients selected for training during each round " -"(we don't want all 1000 clients participating in every round), so we " -"adjust ``fraction_fit`` to ``0.05``, which means that only 5% of " -"available clients (so 50 clients) will be selected for training each " -"round:" -msgstr "" +"examples. Given that the number of training examples on each client is quite " +"small, we should probably train the model a bit longer, so we configure the " +"clients to perform 3 local training epochs. We should also adjust the " +"fraction of clients selected for training during each round (we don't want " +"all 1000 clients participating in every round), so we adjust " +"``fraction_fit`` to ``0.05``, which means that only 5% of available clients " +"(so 50 clients) will be selected for training each round:" +msgstr "" +"现在我们有 1000 个分区,每个分区有 45 个训练示例和 5 个验证示例。鉴于每个客户" +"端上的训练示例数量较少,我们可能需要对模型进行更长时间的训练,因此我们将客户" +"端配置为执行 3 个本地训练历元。我们还应该调整每轮训练中被选中的客户端的比例" +"(我们不希望每轮训练都有 1000 个客户端参与),因此我们将 ``fraction_fit`` 调" +"整为 ``0.05``,这意味着每轮训练只选中 5%的可用客户端(即 50 个客户端):" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:699 msgid "" @@ -13043,72 +15538,93 @@ msgid "" "choosing a different strategy, and evaluating models on the server-side. " "That's quite a bit of flexibility with so little code, right?" msgstr "" +"在本笔记本中,我们看到了如何通过自定义策略、在服务器端初始化参数、选择不同的" +"策略以及在服务器端评估模型来逐步增强我们的系统。用这么少的代码就能实现这么大" +"的灵活性,不是吗?" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:701 msgid "" -"In the later sections, we've seen how we can communicate arbitrary values" -" between server and clients to fully customize client-side execution. " -"With that capability, we built a large-scale Federated Learning " -"simulation using the Flower Virtual Client Engine and ran an experiment " -"involving 1000 clients in the same workload - all in a Jupyter Notebook!" +"In the later sections, we've seen how we can communicate arbitrary values " +"between server and clients to fully customize client-side execution. With " +"that capability, we built a large-scale Federated Learning simulation using " +"the Flower Virtual Client Engine and ran an experiment involving 1000 " +"clients in the same workload - all in a Jupyter Notebook!" msgstr "" +"在后面的章节中,我们将看到如何在服务器和客户端之间传递任意值,以完全自定义客" +"户端执行。有了这种能力,我们使用 Flower 虚拟客户端引擎构建了一个大规模的联合" +"学习模拟,并在 Jupyter Notebook 中进行了一次实验,在相同的工作负载中运行了 " +"1000 个客户端!" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:719 msgid "" -"The `Flower Federated Learning Tutorial - Part 3 " -"`__ shows how to build a fully custom ``Strategy`` " -"from scratch." +"The `Flower Federated Learning Tutorial - Part 3 `__ shows how " +"to build a fully custom ``Strategy`` from scratch." msgstr "" +"Flower 联合学习教程 - 第 3 部分 `__ 展示了如何从头开始构建完全自定" +"义的 \"策略\"。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:9 msgid "What is Federated Learning?" -msgstr "" +msgstr "什么是联合学习?" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:13 msgid "" "In this tutorial, you will learn what federated learning is, build your " "first system in Flower, and gradually extend it. If you work through all " -"parts of the tutorial, you will be able to build advanced federated " -"learning systems that approach the current state of the art in the field." +"parts of the tutorial, you will be able to build advanced federated learning " +"systems that approach the current state of the art in the field." msgstr "" +"在本教程中,你将了解什么是联合学习,用 Flower 搭建第一个系统,并逐步对其进行" +"扩展。如果你能完成本教程的所有部分,你就能构建高级的联合学习系统,从而接近该" +"领域当前的技术水平。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:15 msgid "" -"🧑‍🏫 This tutorial starts at zero and expects no familiarity with " -"federated learning. Only a basic understanding of data science and Python" -" programming is assumed." +"🧑‍🏫 This tutorial starts at zero and expects no familiarity with federated " +"learning. Only a basic understanding of data science and Python programming " +"is assumed." msgstr "" +"🧑‍🏫 本教程从零开始,不要求熟悉联合学习。仅假定对数据科学和 Python 编程有基本" +"了解。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:17 msgid "" -"`Star Flower on GitHub `__ ⭐️ and join " -"the open-source Flower community on Slack to connect, ask questions, and " -"get help: `Join Slack `__ 🌼 We'd love to " -"hear from you in the ``#introductions`` channel! And if anything is " -"unclear, head over to the ``#questions`` channel." +"`Star Flower on GitHub `__ ⭐️ and join the " +"open-source Flower community on Slack to connect, ask questions, and get " +"help: `Join Slack `__ 🌼 We'd love to hear " +"from you in the ``#introductions`` channel! And if anything is unclear, head " +"over to the ``#questions`` channel." msgstr "" +"`Star Flower on GitHub `__ ⭐️ 并加入 Slack 上" +"的开源 Flower 社区,进行交流、提问并获得帮助: 加入 Slack `__ 🌼 我们希望在 ``#introductions`` 频道听到您的声音!如果有" +"任何不清楚的地方,请访问 ``#questions`` 频道。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:19 msgid "Let's get started!" -msgstr "" +msgstr "让我们开始吧!" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:31 msgid "Classic machine learning" -msgstr "" +msgstr "经典机器学习" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:33 msgid "" -"Before we begin to discuss federated learning, let us quickly recap how " -"most machine learning works today." +"Before we begin to discuss federated learning, let us quickly recap how most " +"machine learning works today." msgstr "" +"在开始讨论联合学习之前,让我们先快速回顾一下目前大多数机器学习的工作原理。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:35 msgid "" -"In machine learning, we have a model, and we have data. The model could " -"be a neural network (as depicted here), or something else, like classical" -" linear regression." +"In machine learning, we have a model, and we have data. The model could be a " +"neural network (as depicted here), or something else, like classical linear " +"regression." msgstr "" +"在机器学习中,我们有一个模型和数据。模型可以是一个神经网络(如图所示),也可" +"以是其他东西,比如经典的线性回归。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:41 msgid "|e1dd4b4129b040bea23a894266227080|" @@ -13116,28 +15632,31 @@ msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:109 msgid "Model and data" -msgstr "" +msgstr "模型和数据" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:47 msgid "" -"We train the model using the data to perform a useful task. A task could " -"be to detect objects in images, transcribe an audio recording, or play a " -"game like Go." +"We train the model using the data to perform a useful task. A task could be " +"to detect objects in images, transcribe an audio recording, or play a game " +"like Go." msgstr "" +"我们使用数据来训练模型,以完成一项有用的任务。任务可以是检测图像中的物体、转" +"录音频或玩围棋等游戏。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:53 msgid "|c0d4cc6a442948dca8da40d2440068d9|" -msgstr "" +msgstr "|c0d4cc6a442948dca8da40d2440068d9|" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:111 msgid "Train model using data" -msgstr "" +msgstr "使用数据训练模型" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:59 msgid "" -"Now, in practice, the training data we work with doesn't originate on the" -" machine we train the model on. It gets created somewhere else." +"Now, in practice, the training data we work with doesn't originate on the " +"machine we train the model on. It gets created somewhere else." msgstr "" +"实际上,我们使用的训练数据并不来自我们训练模型的机器。它是在其他地方创建的。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:61 msgid "" @@ -13145,6 +15664,8 @@ msgid "" "collecting sensor data, a laptop receiving input via the keyboard, or a " "smart speaker listening to someone trying to sing a song." msgstr "" +"它源于智能手机上用户与应用程序的交互、汽车上传感器数据的收集、笔记本电脑上键" +"盘输入的接收,或者智能扬声器上某人试着唱的歌。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:67 msgid "|174e1e4fa1f149a19bfbc8bc1126f46a|" @@ -13152,15 +15673,17 @@ msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:113 msgid "Data on a phone" -msgstr "" +msgstr "手机上的数据" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:73 msgid "" "What's also important to mention, this \"somewhere else\" is usually not " -"just one place, it's many places. It could be several devices all running" -" the same app. But it could also be several organizations, all generating" -" data for the same task." +"just one place, it's many places. It could be several devices all running " +"the same app. But it could also be several organizations, all generating " +"data for the same task." msgstr "" +"值得一提的是,这个 \"其他地方 \"通常不只是一个地方,而是很多地方。它可能是多" +"个运行同一应用程序的设备。但也可能是多个组织,都在为同一任务生成数据。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:79 msgid "|4e021a3dc08249d2a89daa3ab03c2714|" @@ -13168,15 +15691,16 @@ msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:115 msgid "Data is on many devices" -msgstr "" +msgstr "数据存在于多种设备中" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:85 msgid "" -"So to use machine learning, or any kind of data analysis, the approach " -"that has been used in the past was to collect all data on a central " -"server. This server can be somewhere in a data center, or somewhere in " -"the cloud." +"So to use machine learning, or any kind of data analysis, the approach that " +"has been used in the past was to collect all data on a central server. This " +"server can be somewhere in a data center, or somewhere in the cloud." msgstr "" +"因此,要使用机器学习或任何类型的数据分析,过去使用的方法是在中央服务器上收集" +"所有数据。这个服务器可以在数据中心的某个地方,也可以在云端的某个地方。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:91 msgid "|e74a1d5ce7eb49688651f2167a59065b|" @@ -13184,7 +15708,7 @@ msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:117 msgid "Central data collection" -msgstr "" +msgstr "中央数据收集" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:97 msgid "" @@ -13192,6 +15716,8 @@ msgid "" "learning algorithms to train our model on the data. This is the machine " "learning approach that we've basically always relied on." msgstr "" +"一旦所有数据都收集到一处,我们最终就可以使用机器学习算法在数据上训练我们的模" +"型。这就是我们基本上一直依赖的机器学习方法。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:103 msgid "|eb29ec4c7aef4e93976795ed72df647e|" @@ -13199,19 +15725,21 @@ msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:119 msgid "Central model training" -msgstr "" +msgstr "中央模型训练" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:130 msgid "Challenges of classical machine learning" -msgstr "" +msgstr "经典机器学习面临的挑战" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:132 msgid "" -"The classic machine learning approach we've just seen can be used in some" -" cases. Great examples include categorizing holiday photos, or analyzing " -"web traffic. Cases, where all the data is naturally available on a " -"centralized server." +"The classic machine learning approach we've just seen can be used in some " +"cases. Great examples include categorizing holiday photos, or analyzing web " +"traffic. Cases, where all the data is naturally available on a centralized " +"server." msgstr "" +"我们刚刚看到的经典机器学习方法可以在某些情况下使用。很好的例子包括对假日照片" +"进行分类或分析网络流量。在这些案例中,所有数据自然都可以在中央服务器上获得。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:138 msgid "|c2f699d8ac484f5081721a6f1511f70d|" @@ -13219,14 +15747,16 @@ msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:173 msgid "Centralized possible" -msgstr "" +msgstr "可集中管理" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:144 msgid "" -"But the approach can not be used in many other cases. Cases, where the " -"data is not available on a centralized server, or cases where the data " -"available on one server is not enough to train a good model." +"But the approach can not be used in many other cases. Cases, where the data " +"is not available on a centralized server, or cases where the data available " +"on one server is not enough to train a good model." msgstr "" +"但这种方法并不适用于许多其他情况。例如,集中服务器上没有数据,或者一台服务器" +"上的数据不足以训练出一个好的模型。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:150 msgid "|cf42accdacbf4e5eb4fa0503108ba7a7|" @@ -13234,14 +15764,16 @@ msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:175 msgid "Centralized impossible" -msgstr "" +msgstr "无法集中" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:156 msgid "" -"There are many reasons why the classic centralized machine learning " -"approach does not work for a large number of highly important real-world " -"use cases. Those reasons include:" +"There are many reasons why the classic centralized machine learning approach " +"does not work for a large number of highly important real-world use cases. " +"Those reasons include:" msgstr "" +"传统的集中式机器学习方法无法满足现实世界中大量极为重要的使用案例,原因有很" +"多。这些原因包括:" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:158 msgid "" @@ -13250,123 +15782,151 @@ msgid "" "(Russia), CDPR (China), PDPB (India), PIPA (Korea), APPI (Japan), PDP " "(Indonesia), PDPA (Singapore), APP (Australia), and other regulations " "protect sensitive data from being moved. In fact, those regulations " -"sometimes even prevent single organizations from combining their own " -"users' data for artificial intelligence training because those users live" -" in different parts of the world, and their data is governed by different" -" data protection regulations." -msgstr "" +"sometimes even prevent single organizations from combining their own users' " +"data for artificial intelligence training because those users live in " +"different parts of the world, and their data is governed by different data " +"protection regulations." +msgstr "" +"**法规**: GDPR(欧洲)、CCPA(加利福尼亚)、PIPEDA(加拿大)、LGPD(巴西)、" +"PDPL(阿根廷)、KVKK(土耳其)、POPI(南非)、FSS(俄罗斯)、CDPR(中国)、" +"PDPB(印度)、PIPA(韩国)、APPI(日本)、PDP(印度尼西亚)、PDPA(新加坡)、" +"APP(澳大利亚)等法规保护敏感数据不被移动。事实上,这些法规有时甚至会阻止单个" +"组织将自己的用户数据用于人工智能培训,因为这些用户生活在世界不同地区,他们的" +"数据受不同的数据保护法规管辖。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:160 msgid "" -"**User preference**: In addition to regulation, there are use cases where" -" users just expect that no data leaves their device, ever. If you type " -"your passwords and credit card info into the digital keyboard of your " -"phone, you don't expect those passwords to end up on the server of the " -"company that developed that keyboard, do you? In fact, that use case was " -"the reason federated learning was invented in the first place." +"**User preference**: In addition to regulation, there are use cases where " +"users just expect that no data leaves their device, ever. If you type your " +"passwords and credit card info into the digital keyboard of your phone, you " +"don't expect those passwords to end up on the server of the company that " +"developed that keyboard, do you? In fact, that use case was the reason " +"federated learning was invented in the first place." msgstr "" +"**用户偏好**: 除了法规之外,在一些使用案例中,用户只是希望数据永远不会离开他" +"们的设备。如果你在手机的数字键盘上输入密码和信用卡信息,你不会希望这些密码最" +"终出现在开发该键盘的公司的服务器上吧?事实上,这种用例正是联合学习发明的初" +"衷。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:161 msgid "" -"**Data volume**: Some sensors, like cameras, produce such a high data " -"volume that it is neither feasible nor economic to collect all the data " -"(due to, for example, bandwidth or communication efficiency). Think about" -" a national rail service with hundreds of train stations across the " -"country. If each of these train stations is outfitted with a number of " -"security cameras, the volume of raw on-device data they produce requires " -"incredibly powerful and exceedingly expensive infrastructure to process " -"and store. And most of the data isn't even useful." -msgstr "" +"**Data volume**: Some sensors, like cameras, produce such a high data volume " +"that it is neither feasible nor economic to collect all the data (due to, " +"for example, bandwidth or communication efficiency). Think about a national " +"rail service with hundreds of train stations across the country. If each of " +"these train stations is outfitted with a number of security cameras, the " +"volume of raw on-device data they produce requires incredibly powerful and " +"exceedingly expensive infrastructure to process and store. And most of the " +"data isn't even useful." +msgstr "" +"**数据量**: 有些传感器(如摄像头)产生的数据量很大,收集所有数据既不可行,也" +"不经济(例如,由于带宽或通信效率的原因)。试想一下全国铁路服务,全国有数百个" +"火车站。如果每个火车站都安装了许多安全摄像头,那么它们所产生的大量原始设备数" +"据就需要功能强大且极其昂贵的基础设施来处理和存储。而大部分数据甚至都是无用" +"的。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:164 msgid "Examples where centralized machine learning does not work include:" -msgstr "" +msgstr "集中式机器学习不起作用的例子包括:" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:166 msgid "" "Sensitive healthcare records from multiple hospitals to train cancer " "detection models" -msgstr "" +msgstr "用多家医院的敏感医疗记录训练癌症检测模型" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:167 msgid "" -"Financial information from different organizations to detect financial " -"fraud" -msgstr "" +"Financial information from different organizations to detect financial fraud" +msgstr "不同组织的财务信息,以侦查财务欺诈行为" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:168 msgid "Location data from your electric car to make better range prediction" -msgstr "" +msgstr "通过电动汽车的定位数据更好地预测续航里程" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:169 msgid "End-to-end encrypted messages to train better auto-complete models" -msgstr "" +msgstr "端到端加密信息可训练出更好的自动完成模型" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:171 msgid "" -"The popularity of privacy-enhancing systems like the `Brave " -"`__ browser or the `Signal `__ " -"messenger shows that users care about privacy. In fact, they choose the " -"privacy-enhancing version over other alternatives, if such an alernative " -"exists. But what can we do to apply machine learning and data science to " -"these cases to utilize private data? After all, these are all areas that " -"would benefit significantly from recent advances in AI." +"The popularity of privacy-enhancing systems like the `Brave `__ browser or the `Signal `__ messenger shows " +"that users care about privacy. In fact, they choose the privacy-enhancing " +"version over other alternatives, if such an alernative exists. But what can " +"we do to apply machine learning and data science to these cases to utilize " +"private data? After all, these are all areas that would benefit " +"significantly from recent advances in AI." msgstr "" +"像 \"Brave `__\"浏览器或 \"Signal `__\"信使这样的隐私增强系统的流行表明,用户关心隐私。事实上,他们会选择隐私" +"增强版,而不是其他替代品(如果存在这种替代品的话)。但是,我们能做些什么来将" +"机器学习和数据科学应用到这些情况中,以利用隐私数据呢?毕竟,这些领域都将从人" +"工智能的最新进展中受益匪浅。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:186 msgid "Federated learning" -msgstr "" +msgstr "联合学习" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:188 msgid "" "Federated learning simply reverses this approach. It enables machine " -"learning on distributed data by moving the training to the data, instead " -"of moving the data to the training. Here's the single-sentence " -"explanation:" +"learning on distributed data by moving the training to the data, instead of " +"moving the data to the training. Here's the single-sentence explanation:" msgstr "" +"联合学习简单地颠覆了这种方法。它通过将训练转移到数据上,而不是将数据转移到训" +"练上,在分布式数据上实现机器学习。下面是一句话的解释:" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:190 msgid "Central machine learning: move the data to the computation" -msgstr "" +msgstr "中央机器学习:将数据转移到计算中" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:191 msgid "Federated (machine) learning: move the computation to the data" -msgstr "" +msgstr "联合(机器)学习:将计算转移到数据上" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:193 msgid "" -"By doing so, it enables us to use machine learning (and other data " -"science approaches) in areas where it wasn't possible before. We can now " -"train excellent medical AI models by enabling different hospitals to work" -" together. We can solve financial fraud by training AI models on the data" -" of different financial institutions. We can build novel privacy-" -"enhancing applications (such as secure messaging) that have better built-" -"in AI than their non-privacy-enhancing alternatives. And those are just a" -" few of the examples that come to mind. As we deploy federated learning, " -"we discover more and more areas that can suddenly be reinvented because " -"they now have access to vast amounts of previously inaccessible data." -msgstr "" +"By doing so, it enables us to use machine learning (and other data science " +"approaches) in areas where it wasn't possible before. We can now train " +"excellent medical AI models by enabling different hospitals to work " +"together. We can solve financial fraud by training AI models on the data of " +"different financial institutions. We can build novel privacy-enhancing " +"applications (such as secure messaging) that have better built-in AI than " +"their non-privacy-enhancing alternatives. And those are just a few of the " +"examples that come to mind. As we deploy federated learning, we discover " +"more and more areas that can suddenly be reinvented because they now have " +"access to vast amounts of previously inaccessible data." +msgstr "" +"这样,我们就能在以前不可能的领域使用机器学习(和其他数据科学方法)。现在,我" +"们可以通过让不同的医院协同工作来训练优秀的医疗人工智能模型。我们可以通过在不" +"同金融机构的数据上训练人工智能模型来解决金融欺诈问题。我们可以构建新颖的隐私" +"增强型应用(如安全信息),其内置的人工智能比非隐私增强型应用更好。以上只是我" +"想到的几个例子。随着联合学习的部署,我们会发现越来越多的领域可以突然重获新" +"生,因为它们现在可以访问大量以前无法访问的数据。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:196 msgid "" -"So how does federated learning work, exactly? Let's start with an " -"intuitive explanation." -msgstr "" +"So how does federated learning work, exactly? Let's start with an intuitive " +"explanation." +msgstr "那么,联合学习究竟是如何运作的呢?让我们从直观的解释开始。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:199 msgid "Federated learning in five steps" -msgstr "" +msgstr "联合学习的五个步骤" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:202 msgid "Step 0: Initialize global model" -msgstr "" +msgstr "步骤 0:初始化全局模型" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:204 msgid "" -"We start by initializing the model on the server. This is exactly the " -"same in classic centralized learning: we initialize the model parameters," -" either randomly or from a previously saved checkpoint." +"We start by initializing the model on the server. This is exactly the same " +"in classic centralized learning: we initialize the model parameters, either " +"randomly or from a previously saved checkpoint." msgstr "" +"我们首先在服务器上初始化模型。这与经典的集中式学习完全相同:我们随机或从先前" +"保存的检查点初始化模型参数。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:210 msgid "|5ec8356bc2564fa09178b1ceed5beccc|" @@ -13374,23 +15934,27 @@ msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:307 msgid "Initialize global model" -msgstr "" +msgstr "初始化全局模型" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:217 msgid "" -"Step 1: Send model to a number of connected organizations/devices (client" -" nodes)" -msgstr "" +"Step 1: Send model to a number of connected organizations/devices (client " +"nodes)" +msgstr "第 1 步:将模型发送到多个连接的组织/设备(客户节点)" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:219 msgid "" "Next, we send the parameters of the global model to the connected client " "nodes (think: edge devices like smartphones or servers belonging to " -"organizations). This is to ensure that each participating node starts " -"their local training using the same model parameters. We often use only a" -" few of the connected nodes instead of all nodes. The reason for this is " -"that selecting more and more client nodes has diminishing returns." +"organizations). This is to ensure that each participating node starts their " +"local training using the same model parameters. We often use only a few of " +"the connected nodes instead of all nodes. The reason for this is that " +"selecting more and more client nodes has diminishing returns." msgstr "" +"接下来,我们会将全局模型的参数发送到连接的客户端节点(如智能手机等边缘设备或" +"企业的服务器)。这是为了确保每个参与节点都使用相同的模型参数开始本地训练。我" +"们通常只使用几个连接节点,而不是所有节点。这样做的原因是,选择越来越多的客户" +"端节点会导致收益递减。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:225 msgid "|7c9329e97bd0430bad335ab605a897a7|" @@ -13398,23 +15962,27 @@ msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:309 msgid "Send global model" -msgstr "" +msgstr "发送全球模式" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:232 msgid "" -"Step 2: Train model locally on the data of each organization/device " -"(client node)" -msgstr "" +"Step 2: Train model locally on the data of each organization/device (client " +"node)" +msgstr "步骤 2:在本地对每个机构/设备(客户端节点)的数据进行模型训练" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:234 msgid "" -"Now that all (selected) client nodes have the latest version of the " -"global model parameters, they start the local training. They use their " -"own local dataset to train their own local model. They don't train the " -"model until full convergence, but they only train for a little while. " -"This could be as little as one epoch on the local data, or even just a " -"few steps (mini-batches)." +"Now that all (selected) client nodes have the latest version of the global " +"model parameters, they start the local training. They use their own local " +"dataset to train their own local model. They don't train the model until " +"full convergence, but they only train for a little while. This could be as " +"little as one epoch on the local data, or even just a few steps (mini-" +"batches)." msgstr "" +"现在,所有(选定的)客户端节点都有了最新版本的全局模型参数,它们开始进行本地" +"训练。它们使用自己的本地数据集来训练自己的本地模型。它们不会一直训练到模型完" +"全收敛为止,而只是训练一小段时间。这可能只是本地数据上的一个历元,甚至只是几" +"个步骤(迷你批次)。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:240 msgid "|88002bbce1094ba1a83c9151df18f707|" @@ -13422,22 +15990,25 @@ msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:311 msgid "Train on local data" -msgstr "" +msgstr "根据本地数据进行培训" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:247 msgid "Step 3: Return model updates back to the server" -msgstr "" +msgstr "步骤 3:将模型更新返回服务器" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:249 msgid "" -"After local training, each client node has a slightly different version " -"of the model parameters they originally received. The parameters are all " +"After local training, each client node has a slightly different version of " +"the model parameters they originally received. The parameters are all " "different because each client node has different examples in its local " -"dataset. The client nodes then send those model updates back to the " -"server. The model updates they send can either be the full model " -"parameters or just the gradients that were accumulated during local " -"training." +"dataset. The client nodes then send those model updates back to the server. " +"The model updates they send can either be the full model parameters or just " +"the gradients that were accumulated during local training." msgstr "" +"经过本地训练后,每个客户节点最初收到的模型参数都会略有不同。参数之所以不同," +"是因为每个客户端节点的本地数据集中都有不同的示例。然后,客户端节点将这些模型" +"更新发回服务器。它们发送的模型更新既可以是完整的模型参数,也可以只是本地训练" +"过程中积累的梯度。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:255 msgid "|391766aee87c482c834c93f7c22225e2|" @@ -13445,37 +16016,47 @@ msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:313 msgid "Send model updates" -msgstr "" +msgstr "发送模型更新" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:262 msgid "Step 4: Aggregate model updates into a new global model" -msgstr "" +msgstr "步骤 4:将模型更新汇总到新的全局模型中" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:264 msgid "" "The server receives model updates from the selected client nodes. If it " -"selected 100 client nodes, it now has 100 slightly different versions of " -"the original global model, each trained on the local data of one client. " -"But didn't we want to have one model that contains the learnings from the" -" data of all 100 client nodes?" +"selected 100 client nodes, it now has 100 slightly different versions of the " +"original global model, each trained on the local data of one client. But " +"didn't we want to have one model that contains the learnings from the data " +"of all 100 client nodes?" msgstr "" +"服务器从选定的客户端节点接收模型更新。如果服务器选择了 100 个客户端节点,那么" +"它现在就拥有 100 个略有不同的原始全局模型版本,每个版本都是根据一个客户端的本" +"地数据训练出来的。难道我们不希望有一个包含所有 100 个客户节点数据的模型吗?" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:266 msgid "" -"In order to get one single model, we have to combine all the model " -"updates we received from the client nodes. This process is called " -"*aggregation*, and there are many different ways to do it. The most basic" -" way to do it is called *Federated Averaging* (`McMahan et al., 2016 " -"`__), often abbreviated as *FedAvg*. " -"*FedAvg* takes the 100 model updates and, as the name suggests, averages " -"them. To be more precise, it takes the *weighted average* of the model " -"updates, weighted by the number of examples each client used for " -"training. The weighting is important to make sure that each data example " -"has the same \"influence\" on the resulting global model. If one client " -"has 10 examples, and another client has 100 examples, then - without " -"weighting - each of the 10 examples would influence the global model ten " -"times as much as each of the 100 examples." -msgstr "" +"In order to get one single model, we have to combine all the model updates " +"we received from the client nodes. This process is called *aggregation*, and " +"there are many different ways to do it. The most basic way to do it is " +"called *Federated Averaging* (`McMahan et al., 2016 `__), often abbreviated as *FedAvg*. *FedAvg* takes the 100 " +"model updates and, as the name suggests, averages them. To be more precise, " +"it takes the *weighted average* of the model updates, weighted by the number " +"of examples each client used for training. The weighting is important to " +"make sure that each data example has the same \"influence\" on the resulting " +"global model. If one client has 10 examples, and another client has 100 " +"examples, then - without weighting - each of the 10 examples would influence " +"the global model ten times as much as each of the 100 examples." +msgstr "" +"为了得到一个单一的模型,我们必须将从客户端节点收到的所有模型更新合并起来。这" +"个过程称为*聚合*,有许多不同的方法。最基本的方法称为 *Federated Averaging* " +"(`McMahan等人,2016 `__),通常缩写为" +"*FedAvg*。*FedAvg* 采用 100 个模型更新,顾名思义,就是对它们进行平均。更准确" +"地说,它取的是模型更新的*加权平均值*,根据每个客户端用于训练的示例数量进行加" +"权。加权对于确保每个数据示例对生成的全局模型具有相同的 \"影响 \"非常重要。如" +"果一个客户有 10 个示例,而另一个客户有 100 个示例,那么在不加权的情况下,10 " +"个示例对全局模型的影响是 100 个示例的 10 倍。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:273 msgid "|93b9a15bd27f4e91b40f642c253dfaac|" @@ -13483,97 +16064,120 @@ msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:315 msgid "Aggregate model updates" -msgstr "" +msgstr "汇总模型更新" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:280 msgid "Step 5: Repeat steps 1 to 4 until the model converges" -msgstr "" +msgstr "步骤 5:重复步骤 1 至 4,直至模型收敛" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:282 msgid "" "Steps 1 to 4 are what we call a single round of federated learning. The " -"global model parameters get sent to the participating client nodes (step " -"1), the client nodes train on their local data (step 2), they send their " -"updated models to the server (step 3), and the server then aggregates the" -" model updates to get a new version of the global model (step 4)." +"global model parameters get sent to the participating client nodes (step 1), " +"the client nodes train on their local data (step 2), they send their updated " +"models to the server (step 3), and the server then aggregates the model " +"updates to get a new version of the global model (step 4)." msgstr "" +"步骤 1 至 4 就是我们所说的单轮联合学习。全局模型参数被发送到参与的客户端节点" +"(第 1 步),客户端节点对其本地数据进行训练(第 2 步),然后将更新后的模型发" +"送到服务器(第 3 步),服务器汇总模型更新,得到新版本的全局模型(第 4 步)。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:284 msgid "" -"During a single round, each client node that participates in that " -"iteration only trains for a little while. This means that after the " -"aggregation step (step 4), we have a model that has been trained on all " -"the data of all participating client nodes, but only for a little while. " -"We then have to repeat this training process over and over again to " -"eventually arrive at a fully trained model that performs well across the " -"data of all client nodes." +"During a single round, each client node that participates in that iteration " +"only trains for a little while. This means that after the aggregation step " +"(step 4), we have a model that has been trained on all the data of all " +"participating client nodes, but only for a little while. We then have to " +"repeat this training process over and over again to eventually arrive at a " +"fully trained model that performs well across the data of all client nodes." msgstr "" +"在一轮迭代中,每个参与迭代的客户节点只训练一小段时间。这意味着,在聚合步骤" +"(步骤 4)之后,我们的模型已经在所有参与的客户节点的所有数据上训练过了,但只" +"训练了一小会儿。然后,我们必须一次又一次地重复这一训练过程,最终得到一个经过" +"全面训练的模型,该模型在所有客户节点的数据中都表现良好。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:289 msgid "" "Congratulations, you now understand the basics of federated learning. " -"There's a lot more to discuss, of course, but that was federated learning" -" in a nutshell. In later parts of this tutorial, we will go into more " -"detail. Interesting questions include: How can we select the best client " -"nodes that should participate in the next round? What's the best way to " -"aggregate model updates? How can we handle failing client nodes " -"(stragglers)?" +"There's a lot more to discuss, of course, but that was federated learning in " +"a nutshell. In later parts of this tutorial, we will go into more detail. " +"Interesting questions include: How can we select the best client nodes that " +"should participate in the next round? What's the best way to aggregate model " +"updates? How can we handle failing client nodes (stragglers)?" msgstr "" +"恭喜你,现在你已经了解了联合学习的基础知识。当然,要讨论的内容还有很多,但这" +"只是联合学习的一个缩影。在本教程的后半部分,我们将进行更详细的介绍。有趣的问" +"题包括 我们如何选择最好的客户端节点参与下一轮学习?聚合模型更新的最佳方法是什" +"么?如何处理失败的客户端节点(落伍者)?" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:294 msgid "" -"Just like we can train a model on the decentralized data of different " -"client nodes, we can also evaluate the model on that data to receive " -"valuable metrics. This is called federated evaluation, sometimes " -"abbreviated as FE. In fact, federated evaluation is an integral part of " -"most federated learning systems." +"Just like we can train a model on the decentralized data of different client " +"nodes, we can also evaluate the model on that data to receive valuable " +"metrics. This is called federated evaluation, sometimes abbreviated as FE. " +"In fact, federated evaluation is an integral part of most federated learning " +"systems." msgstr "" +"就像我们可以在不同客户节点的分散数据上训练一个模型一样,我们也可以在这些数据" +"上对模型进行评估,以获得有价值的指标。这就是所谓的联合评估,有时简称为 FE。事" +"实上,联合评估是大多数联合学习系统不可或缺的一部分。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:297 msgid "Federated analytics" -msgstr "" +msgstr "联合分析" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:299 msgid "" -"In many cases, machine learning isn't necessary to derive value from " -"data. Data analysis can yield valuable insights, but again, there's often" -" not enough data to get a clear answer. What's the average age at which " -"people develop a certain type of health condition? Federated analytics " -"enables such queries over multiple client nodes. It is usually used in " -"conjunction with other privacy-enhancing technologies like secure " -"aggregation to prevent the server from seeing the results submitted by " -"individual client nodes." +"In many cases, machine learning isn't necessary to derive value from data. " +"Data analysis can yield valuable insights, but again, there's often not " +"enough data to get a clear answer. What's the average age at which people " +"develop a certain type of health condition? Federated analytics enables such " +"queries over multiple client nodes. It is usually used in conjunction with " +"other privacy-enhancing technologies like secure aggregation to prevent the " +"server from seeing the results submitted by individual client nodes." msgstr "" +"在很多情况下,机器学习并不是从数据中获取价值的必要条件。数据分析可以产生有价" +"值的见解,但同样,往往没有足够的数据来获得明确的答案。人们患某种健康疾病的平" +"均年龄是多少?联合分析可以通过多个客户端节点进行此类查询。它通常与安全聚合等" +"其他隐私增强技术结合使用,以防止服务器看到单个客户端节点提交的结果。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:303 msgid "Differential Privacy" -msgstr "" +msgstr "差异化隐私" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:305 msgid "" "Differential privacy (DP) is often mentioned in the context of Federated " -"Learning. It is a privacy-preserving method used when analyzing and " -"sharing statistical data, ensuring the privacy of individual " -"participants. DP achieves this by adding statistical noise to the model " -"updates, ensuring any individual participants’ information cannot be " -"distinguished or re-identified. This technique can be considered an " -"optimization that provides a quantifiable privacy protection measure." -msgstr "" +"Learning. It is a privacy-preserving method used when analyzing and sharing " +"statistical data, ensuring the privacy of individual participants. DP " +"achieves this by adding statistical noise to the model updates, ensuring any " +"individual participants’ information cannot be distinguished or re-" +"identified. This technique can be considered an optimization that provides a " +"quantifiable privacy protection measure." +msgstr "" +"差异隐私(DP)经常在联合学习中被提及。这是一种在分析和共享统计数据时使用的隐" +"私保护方法,可确保单个参与者的隐私。DP 通过在模型更新中添加统计噪声来实现这一" +"目的,确保任何个体参与者的信息都无法被区分或重新识别。这种技术可被视为一种优" +"化,提供了一种可量化的隐私保护措施。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:326 msgid "Flower" -msgstr "" +msgstr "Flower" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:328 msgid "" -"Federated learning, federated evaluation, and federated analytics require" -" infrastructure to move machine learning models back and forth, train and" -" evaluate them on local data, and then aggregate the updated models. " -"Flower provides the infrastructure to do exactly that in an easy, " -"scalable, and secure way. In short, Flower presents a unified approach to" -" federated learning, analytics, and evaluation. It allows the user to " -"federate any workload, any ML framework, and any programming language." +"Federated learning, federated evaluation, and federated analytics require " +"infrastructure to move machine learning models back and forth, train and " +"evaluate them on local data, and then aggregate the updated models. Flower " +"provides the infrastructure to do exactly that in an easy, scalable, and " +"secure way. In short, Flower presents a unified approach to federated " +"learning, analytics, and evaluation. It allows the user to federate any " +"workload, any ML framework, and any programming language." msgstr "" +"联合学习、联合评估和联合分析需要基础设施来来回移动机器学习模型,在本地数据上" +"对其进行训练和评估,然后汇总更新的模型。Flower 提供的基础架构正是以简单、可扩" +"展和安全的方式实现这些目标的。简而言之,Flower 为联合学习、分析和评估提供了一" +"种统一的方法。它允许用户联合任何工作负载、任何 ML 框架和任何编程语言。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:334 msgid "|a23d9638f96342ef9d25209951e2d564|" @@ -13581,26 +16185,114 @@ msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:340 msgid "" -"Flower federated learning server and client nodes (car, scooter, personal" -" computer, roomba, and phone)" +"Flower federated learning server and client nodes (car, scooter, personal " +"computer, roomba, and phone)" msgstr "" +"Flower联合学习服务器和客户端节点(汽车、滑板车、个人电脑、roomba 和电话)" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:353 msgid "" -"Congratulations, you just learned the basics of federated learning and " -"how it relates to the classic (centralized) machine learning!" +"Congratulations, you just learned the basics of federated learning and how " +"it relates to the classic (centralized) machine learning!" msgstr "" +"恭喜你,你刚刚了解了联合学习的基础知识,以及它与传统(集中式)机器学习的关" +"系!" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:355 msgid "" -"In the next part of this tutorial, we are going to build a first " -"federated learning system with Flower." -msgstr "" +"In the next part of this tutorial, we are going to build a first federated " +"learning system with Flower." +msgstr "在本教程的下一部分,我们将用 Flower 建立第一个联合学习系统。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:373 msgid "" -"The `Flower Federated Learning Tutorial - Part 1 " -"`__ shows how to build a simple federated learning system " -"with PyTorch and Flower." +"The `Flower Federated Learning Tutorial - Part 1 `__ shows how to " +"build a simple federated learning system with PyTorch and Flower." +msgstr "" +"Flower 联合学习教程 - 第 1 部分 `__ 展示了如何使用 PyTorch 和 Flower 构" +"建一个简单的联合学习系统。" + +#: ../../source/contributor-how-to-install-development-versions.rst:62 +msgid "Upload the whl (e.g., ``flwr-1.6.0-py3-none-any.whl``)" +msgstr "上传 whl(例如 ``flwr-1.6.0-py3-none-any.whl``)" + +#: ../../source/contributor-how-to-install-development-versions.rst:63 +msgid "" +"Change ``!pip install -q 'flwr[simulation]' torch torchvision matplotlib`` " +"to ``!pip install -q 'flwr-1.6.0-py3-none-any.whl[simulation]' torch " +"torchvision matplotlib``" msgstr "" +"将``!pip install -q 'flwr[simulation]' torch torchvision matplotlib``更改为" +"``!pip install -q 'flwr-1.6.0-py3-none-any.whl[simulation]' torch torch " +"torchvision matplotlib``" + +#: ../../source/example-pytorch-from-centralized-to-federated.rst:280 +msgid "" +"All that's left to do it to define a function that loads both model and " +"data, creates a :code:`CifarClient`, and starts this client. You load your " +"data and model by using :code:`cifar.py`. Start :code:`CifarClient` with the " +"function :code:`fl.client.start_numpy_client()` by pointing it at the same " +"IP adress we used in :code:`server.py`:" +msgstr "" +"剩下要做的就是定义一个加载模型和数据的函数,创建一个 :code:`CifarClient` 并启" +"动该客户端。使用 :code:`cifar.py` 加载数据和模型。使用函数 :code:`fl.client." +"start_numpy_client()` 启动 :code:`CifarClient`,将其指向我们在 :code:`server." +"py` 中使用的相同 IP 地址:" + +#: ../../source/how-to-run-simulations.rst:10 +msgid "" +"The :code:`VirtualClientEngine` schedules, launches and manages `virtual` " +"clients. These clients are identical to `non-virtual` clients (i.e. the ones " +"you launch via the command `flwr.client.start_numpy_client `_) in the sense that they can be configure by " +"creating a class inheriting, for example, from `flwr.client.NumPyClient `_ and therefore behave in an " +"identical way. In addition to that, clients managed by the :code:" +"`VirtualClientEngine` are:" +msgstr "" +"代码:`VirtualClientEngine`调度、启动和管理`虚拟`客户端。这些客户端与 \"非虚" +"拟 \"客户端(即通过命令 \"flwr.client.start_numpy_client `_\"启动的客户端)完全相同,它们可以通过创建一个继承" +"自 \"flwr.client.NumPyClient `_\" " +"的类来配置,因此行为方式也完全相同。除此之外,由 :code:`VirtualClientEngine` " +"管理的客户端还包括:" + +#: ../../source/tutorial-quickstart-mxnet.rst:217 +#: ../../source/tutorial-quickstart-scikitlearn.rst:150 +msgid "" +"That's it for the client. We only have to implement :code:`Client` or :code:" +"`NumPyClient` and call :code:`fl.client.start_client()` or :code:`fl.client." +"start_numpy_client()`. The string :code:`\"0.0.0.0:8080\"` tells the client " +"which server to connect to. In our case we can run the server and the client " +"on the same machine, therefore we use :code:`\"0.0.0.0:8080\"`. If we run a " +"truly federated workload with the server and clients running on different " +"machines, all that needs to change is the :code:`server_address` we pass to " +"the client." +msgstr "" +"这就是客户端。我们只需实现 :code:`Client` 或 :code:`NumPyClient` 并调用 :" +"code:`fl.client.start_client()` 或 :code:`fl.client.start_numpy_client()`。字" +"符串 :code:`\"0.0.0.0:8080\"`会告诉客户端要连接的服务器。在本例中,我们可以在" +"同一台机器上运行服务器和客户端,因此我们使用 :code:`\"0.0.0.0:8080\"`。如果我" +"们运行的是真正的联合工作负载,服务器和客户端运行在不同的机器上,那么需要改变" +"的只是传递给客户端的 :code:`server_address`。" + +#: ../../source/tutorial-quickstart-pytorch.rst:196 +#: ../../source/tutorial-quickstart-tensorflow.rst:90 +msgid "" +"That's it for the client. We only have to implement :code:`Client` or :code:" +"`NumPyClient` and call :code:`fl.client.start_client()` or :code:`fl.client." +"start_numpy_client()`. The string :code:`\"[::]:8080\"` tells the client " +"which server to connect to. In our case we can run the server and the client " +"on the same machine, therefore we use :code:`\"[::]:8080\"`. If we run a " +"truly federated workload with the server and clients running on different " +"machines, all that needs to change is the :code:`server_address` we point " +"the client at." +msgstr "" +"这就是客户端。我们只需实现 :code:`Client` 或 :code:`NumPyClient` 并调用 :" +"code:`fl.client.start_client()` 或 :code:`fl.client.start_numpy_client()`。字" +"符串 :code:`\"[::]:8080\"`会告诉客户端要连接的服务器。在本例中,我们可以在同" +"一台机器上运行服务器和客户端,因此使用 :code:`\"[::]:8080\"。如果我们运行的是" +"真正的联合工作负载,服务器和客户端运行在不同的机器上,那么需要改变的只是客户" +"端指向的 :code:`server_address`。" From 40d44955b12f58d55dc72da20fc17cd364787d76 Mon Sep 17 00:00:00 2001 From: Charles Beauville Date: Sat, 10 Feb 2024 17:43:12 +0100 Subject: [PATCH 086/113] Add all translations from backup (#2919) --- .../zh_Hans/LC_MESSAGES/framework-docs.po | 2476 +++++++++-------- 1 file changed, 1274 insertions(+), 1202 deletions(-) diff --git a/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po b/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po index 47a12f4437a4..5ac2ba81b324 100644 --- a/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po +++ b/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: Flower main\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-11-23 18:31+0100\n" -"PO-Revision-Date: 2024-02-09 14:19+0000\n" +"PO-Revision-Date: 2024-02-10 11:56+0000\n" "Last-Translator: Yan Gao \n" "Language-Team: Chinese (Simplified) \n" @@ -612,7 +612,7 @@ msgstr "在左侧的垂直图标网格中,选择 \"文件\">\"上传到会话 #: ../../source/contributor-how-to-install-development-versions.rst:62 msgid "Upload the whl (e.g., ``flwr-1.7.0-py3-none-any.whl``)" -msgstr "" +msgstr "更新 whl (e.g., ``flwr-1.7.0-py3-none-any.whl``)" #: ../../source/contributor-how-to-install-development-versions.rst:63 msgid "" @@ -620,6 +620,9 @@ msgid "" "to ``!pip install -q 'flwr-1.7.0-py3-none-any.whl[simulation]' torch " "torchvision matplotlib``" msgstr "" +"把``!pip install -q 'flwr[simulation]' torch torchvision matplotlib``变为``" +"!pip install -q 'flwr-1.7.0-py3-none-any.whl[simulation]' torch torchvision " +"matplotlib``" #: ../../source/contributor-how-to-release-flower.rst:2 msgid "Release Flower" @@ -3785,10 +3788,11 @@ msgid "" "`fraction_evaluate` is set to :code:`0.0`, federated evaluation will be " "disabled." msgstr "" -":code:`fraction_evaluate`: :code:`float`,定义被选中进行评估的客户端的分数。" -"如果 :code:`fraction_evaluate` 设置为 :code:`0.1`,并且 :code:`100` 客户端连" -"接到服务器,那么 :code:`10` 将被随机选中进行评估。如果 :code:" -"`fraction_evaluate` 设置为 :code:`0.0`,联合评估将被禁用。" +":code:`fraction_evaluate`: " +":code:`float`,定义了被选中进行评估的客户端的比例。如果 " +":code:`fraction_evaluate` 设置为 :code:`0.1`,并且 :code:`100` " +"个客户端连接到服务器,那么 :code:`10` 个客户端将被随机选中进行评估。如果 " +":code:`fraction_evaluate` 设置为 :code:`0.0`,联邦评估将被禁用。" #: ../../source/explanation-federated-evaluation.rst:106 msgid "" @@ -3798,10 +3802,10 @@ msgid "" "are connected to the server, then :code:`20` clients will be selected for " "evaluation." msgstr "" -":code:`min_evaluate_clients`:一个 :code:`int`:需要评估的客户的最小数量。如" -"果 :code:`fraction_evaluate` 设置为 :code:`0.1`,:code:" -"`min_evaluate_clients` 设置为 20,并且 :code:`100` 客户端已连接到服务器,那" -"么 :code:`20` 客户端将被选中进行评估。" +":code:`min_evaluate_clients`:一个 :code:`int`,需要评估的客户的最小数量。" +"如果 :code:`fraction_evaluate` 设置为 :code:`0." +"1`,:code:`min_evaluate_clients` 设置为 20,并且有 :code:`100` " +"个客户端已连接到服务器,那么 :code:`20` 个客户端将被选中进行评估。" #: ../../source/explanation-federated-evaluation.rst:107 msgid "" @@ -3811,9 +3815,10 @@ msgid "" "are connected to the server, the server will wait until more clients are " "connected before it continues to sample clients for evaluation." msgstr "" -":code:`min_available_clients`:一个 :code:`int`,定义了在一轮联合评估开始之" -"前,需要连接到服务器的最小客户端数量。如果连接到服务器的客户少于 :code:" -"`min_available_clients`,服务器将等待更多客户连接后,才继续采样客户进行评估。" +":code:`min_available_clients`: " +":code:`int`,定义了在一轮联邦评估开始之前,需要连接到服务器的最小客户端数量。" +"如果连接到服务器的客户端数量少于 :code:`min_available_clients`,服务器将等待" +"更多客户端连接后,才继续采样客户端进行评估。" #: ../../source/explanation-federated-evaluation.rst:108 msgid "" @@ -3850,9 +3855,9 @@ msgid "" "workloads implemented in any other framework): https://github.com/adap/" "flower/tree/main/examples/advanced-tensorflow" msgstr "" -"有关同时使用集中评估和联合评估的完整代码示例,请参阅 *Advanced TensorFlow " -"Example*(同样的方法也可应用于在任何其他框架中实施的工作负载): https://" -"github.com/adap/flower/tree/main/examples/advanced-tensorflow" +"有关同时使用集中评估和联邦评估的完整代码示例,请参阅 *Advanced TensorFlow " +"Example*(同样的方法也可应用于任何其他框架中): https://github.com/adap/" +"flower/tree/main/examples/advanced-tensorflow" #: ../../source/fed/0000-20200102-fed-template.md:10 msgid "FED Template" @@ -3871,55 +3876,55 @@ msgstr "[目录](#table-of-contents)" #: ../../source/fed/0000-20200102-fed-template.md:15 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:15 msgid "[Summary](#summary)" -msgstr "[Summary](#summary)" +msgstr "[总结](#summary)" #: ../../source/fed/0000-20200102-fed-template.md:16 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:16 msgid "[Motivation](#motivation)" -msgstr "[Motivation](#motivation)" +msgstr "[动机](#motivation)" #: ../../source/fed/0000-20200102-fed-template.md:17 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:17 msgid "[Goals](#goals)" -msgstr "[Goals](#goals)" +msgstr "[目标](#goals)" #: ../../source/fed/0000-20200102-fed-template.md:18 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:18 msgid "[Non-Goals](#non-goals)" -msgstr "[Non-Goals](#non-goals)" +msgstr "[非目标](#non-goals)" #: ../../source/fed/0000-20200102-fed-template.md:19 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:19 msgid "[Proposal](#proposal)" -msgstr "[Proposal](#proposal)" +msgstr "[计划](#proposal)" #: ../../source/fed/0000-20200102-fed-template.md:20 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:23 msgid "[Drawbacks](#drawbacks)" -msgstr "[Drawbacks](#drawbacks)" +msgstr "[缺点](#drawbacks)" #: ../../source/fed/0000-20200102-fed-template.md:21 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:24 msgid "[Alternatives Considered](#alternatives-considered)" -msgstr "[Alternatives Considered](#alternatives-considered)" +msgstr "[备选方案](#alternatives-considered)" #: ../../source/fed/0000-20200102-fed-template.md:22 msgid "[Appendix](#appendix)" -msgstr "[Appendix](#appendix)" +msgstr "[附录](#appendix)" #: ../../source/fed/0000-20200102-fed-template.md:24 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:28 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:76 msgid "Summary" -msgstr "内容摘要" +msgstr "总结" #: ../../source/fed/0000-20200102-fed-template.md:26 msgid "\\[TODO - sentence 1: summary of the problem\\]" -msgstr "\\[TODO - sentence 1: summary of the problem\\]" +msgstr "\\[TODO - 句子 1: 问题概括\\]" #: ../../source/fed/0000-20200102-fed-template.md:28 msgid "\\[TODO - sentence 2: summary of the solution\\]" -msgstr "\\[TODO - sentence 2: summary of the solution\\]" +msgstr "\\[TODO - 句子 2: 解决方案概括\\]" #: ../../source/fed/0000-20200102-fed-template.md:30 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:47 @@ -3965,17 +3970,15 @@ msgstr "缺点" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:86 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:135 msgid "Alternatives Considered" -msgstr "曾考虑的替代方案" +msgstr "备选方案" #: ../../source/fed/0000-20200102-fed-template.md:52 -#, fuzzy msgid "\\[Alternative 1\\]" -msgstr "\\[Alternative 1\\]" +msgstr "\\[备选 1\\]" #: ../../source/fed/0000-20200102-fed-template.md:56 -#, fuzzy msgid "\\[Alternative 2\\]" -msgstr "\\[Alternative 2\\]" +msgstr "\\[备选 2\\]" #: ../../source/fed/0000-20200102-fed-template.md:60 msgid "Appendix" @@ -3983,44 +3986,39 @@ msgstr "附录" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:10 msgid "Flower Enhancement Doc" -msgstr "Flower 增效文件" +msgstr "Flower 改善文档" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:20 -#, fuzzy msgid "[Enhancement Doc Template](#enhancement-doc-template)" -msgstr "[Enhancement Doc Template](#enhancement-doc-template)" +msgstr "[增强文档模版](#enhancement-doc-template)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:21 -#, fuzzy msgid "[Metadata](#metadata)" -msgstr "[Metadata](#metadata)" +msgstr "[描述数据](#metadata)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:22 -#, fuzzy msgid "[Workflow](#workflow)" -msgstr "[Workflow](#workflow)" +msgstr "[工作流程](#workflow)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:25 -#, fuzzy msgid "[GitHub Issues](#github-issues)" -msgstr "[GitHub Issues](#github-issues)" +msgstr "[GitHub 问题](#github-issues)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:26 -#, fuzzy msgid "[Google Docs](#google-docs)" -msgstr "[Google Docs](#google-docs)" +msgstr "[谷歌文档](#google-docs)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:30 msgid "A Flower Enhancement is a standardized development process to" -msgstr "增强 Flower 功能是一个标准化的开发流程,目的是" +msgstr "改善 Flower 功能是一个标准化的开发流程,目的是" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:32 msgid "provide a common structure for proposing larger changes" -msgstr "为提出更大规模的变革提供一个共同的结构" +msgstr "为提出更大规模的改动提供一个共同的结构" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:33 msgid "ensure that the motivation for a change is clear" -msgstr "确保变革的动机明确" +msgstr "确保改动的动机明确" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:34 msgid "persist project information in a version control system" @@ -4028,36 +4026,35 @@ msgstr "将项目信息保存在版本控制系统中" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:35 msgid "document the motivation for impactful user-facing changes" -msgstr "记录面向用户的具有影响力的变革的动机" +msgstr "记录面向用户的具有影响力的改动的动机" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:36 msgid "reserve GitHub issues for tracking work in flight" -msgstr "保留 GitHub 问题,用于跟踪飞行中的工作" +msgstr "保留 GitHub 问题,用于跟踪进行中的工作" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:37 msgid "" "ensure community participants can successfully drive changes to completion " "across one or more releases while stakeholders are adequately represented " "throughout the process" -msgstr "" -"确保社区参与者能够成功推动变革,完成一个或多个版本,同时利益相关者在整个过程" -"中得到充分代表" +msgstr "确保社区参与者能够成功推动改动,完成一个或多个版本,同时利益相关者在整个过程" +"中得到充分展现" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:39 msgid "Hence, an Enhancement Doc combines aspects of" -msgstr "因此,\"增强文件 \"将以下方面结合起来" +msgstr "因此,\"增强文件\"将以下方面结合起来" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:41 msgid "a feature, and effort-tracking document" -msgstr "功能,以及努力跟踪文件" +msgstr "一个功能和效力跟踪文档" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:42 msgid "a product requirements document" -msgstr "产品要求文件" +msgstr "一个产品需要文档" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:43 msgid "a design document" -msgstr "设计文件" +msgstr "一个设计文档" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:45 msgid "" @@ -4071,8 +4068,8 @@ msgid "" "beyond a single GitHub issue or pull request is required to understand and " "communicate upcoming changes to the project." msgstr "" -"对于向 Flower 提出的远期变更或功能,需要一个超越单个 GitHub 问题或拉请求的抽" -"象概念,以了解和沟通项目即将发生的变更。" +"对于向 Flower 提出的远期变更或功能,需要一个超越单个 GitHub 问题或拉取请求(" +"pull request)的抽象概念,以了解和沟通项目即将发生的变更。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:51 msgid "" @@ -4082,7 +4079,7 @@ msgid "" "enhance communication and discoverability." msgstr "" "这一流程的目的是减少我们社区中 \"部落知识 \"的数量。通过将决策从 Slack 线程、" -"视频通话和走廊对话转移到一个跟踪良好的人工制品中,该流程旨在加强沟通和可发现" +"视频通话和走廊对话转移到一个跟踪良好的工作环境中,该流程旨在加强沟通和可发现" "性。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:55 @@ -4091,9 +4088,8 @@ msgid "" "process. If an enhancement would be described in either written or verbal " "communication to anyone besides the author or developer, then consider " "creating an Enhancement Doc." -msgstr "" -"任何较大的、面向用户的增强都应遵循增强流程。如果要以书面或口头形式向作者或开" -"发人员以外的任何人描述增强功能,则应考虑创建增强文档。" +msgstr "任何较大的、面向用户的增强都应遵循增强流程。如果要以书面或口头形式向作者或开" +"发人员以外的任何人描述增强功能,则应考虑创建改善文档。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:57 msgid "" @@ -4112,8 +4108,9 @@ msgid "" "Federated Learning algorithms, as these only add features without changing " "how Flower works or is used." msgstr "" -"对于小的改动和添加,通过 \"增强 \"程序既耗时又没有必要。例如,这包括添加新的" -"联合学习算法,因为这只会增加功能,而不会改变 \"Flower \"的工作或使用方式。" +"对于小的改动和添加,通过 \"改善\"程序既耗时又没有必要" +"。例如,这包括添加新的联邦学习算法,因为这只会增加功能,而不会改变 \"Flower " +"\"的工作或使用方式。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:63 msgid "" @@ -4140,15 +4137,15 @@ msgstr "增强文档模板" msgid "" "Each enhancement doc is provided as a Markdown file having the following " "structure" -msgstr "每个改进文档都以 Markdown 文件的形式提供,其结构如下" +msgstr "每个增强文档都以 Markdown 文件的形式提供,其结构如下" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:73 msgid "Metadata (as [described below](#metadata) in form of a YAML preamble)" -msgstr "元数据([如下所述](#metadata) 以 YAML 前言的形式出现)" +msgstr "描述数据([如下所述](#metadata) 以 YAML 前言的形式出现)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:74 msgid "Title (same as in metadata)" -msgstr "标题(与元数据中的标题相同)" +msgstr "标题(与描述数据中的标题相同)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:75 msgid "Table of Contents (if needed)" @@ -4156,7 +4153,7 @@ msgstr "目录(如有需要)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:81 msgid "Notes/Constraints/Caveats (optional)" -msgstr "注意事项/限制/注意事项(可选)" +msgstr "注意事项/限制/警告(可选)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:82 msgid "Design Details (optional)" @@ -4176,15 +4173,14 @@ msgstr "作为参考,本文件采用上述结构。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:90 msgid "Metadata" -msgstr "元数据" +msgstr "描述数据" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:92 msgid "" "**fed-number** (Required) The `fed-number` of the last Flower Enhancement " "Doc + 1. With this number, it becomes easy to reference other proposals." -msgstr "" -"**fed-number**(必填)上一个鲜花增强文件的 \"fed-number \"+1。有了这个编号," -"就很容易参考其他提案。" +msgstr "**fed-number**(必填)上一个Flower增强文件的 \"fed-number \"" +"+1。有了这个编号,就很容易参考其他提案。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:94 msgid "**title** (Required) The title of the proposal in plain language." @@ -4253,10 +4249,10 @@ msgid "" "part of a pull request. Discussions are done as part of the pull request " "review." msgstr "" -"新的增强功能以 `NNNN-YYYYMMDD-enhancement-title.md` 的文件名签入,其中 " -"`NNNN` 是花朵增强文档的编号,并将其转入 `enhancements`。作为拉取请求的一部" -"分,所有增强功能都从 `provisional` 状态开始。讨论是作为拉取请求审查的一部分进" -"行的。" +"新的增强功能以 `NNNN-YYYYMMDD-enhancement-title.md` 的文件名签入,其中 `NNNN`" +" 是花朵增强文档的编号,并将其转入 `enhancements`。作为拉取请求(pull " +"request)的一部分,所有增强功能都从 `provisional` " +"状态开始。讨论是作为拉取请求审查的一部分进行的。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:117 msgid "" @@ -4266,49 +4262,48 @@ msgid "" "part of their description. After the implementation is done, the proposal " "status is changed to `implemented`." msgstr "" -"一旦增强功能通过审核和批准,其状态就会变为 \"可实施\"。实际的实施工作将在单独" -"的拉取请求中完成。这些拉取请求应在其描述中提及相应的增强功能。实施完成后,提" -"案状态将更改为 \"已实施\"。" +"一旦增强功能通过审核和批准,其状态就会变为 `可实施`。实际的实施工作将在单独的" +"拉取请求中完成。这些拉取请求应在其描述中提及相应的增强功能。实施完成后," +"提案状态将更改为 `已实施`。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:119 msgid "" "Under certain conditions, other states are possible. An Enhancement has the " "following states:" -msgstr "在某些条件下,还可能出现其他状态。增强 \"具有以下状态:" +msgstr "在某些条件下,还可能出现其他状态。增强提案具有以下状态:" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:121 msgid "" "`provisional`: The enhancement has been proposed and is actively being " "defined. This is the starting state while the proposal is being fleshed out " "and actively defined and discussed." -msgstr "" -"暂定\": 已提出改进建议并正在积极定义。这是在提案得到充实、积极定义和讨论时的" +msgstr "`暂定`: 已提出改进建议并正在积极定义。这是在提案得到充实、积极定义和讨论时的" "起始状态。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:122 msgid "`implementable`: The enhancement has been reviewed and approved." -msgstr "可实施\": 增强功能已审核通过。" +msgstr "`可实施`: 增强功能已审核通过。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:123 msgid "" "`implemented`: The enhancement has been implemented and is no longer " "actively changed." -msgstr "已实施`: 增强功能已实施,不再主动更改。" +msgstr "`已实施`: 增强功能已实施,不再主动更改。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:124 msgid "" "`deferred`: The enhancement is proposed but not actively being worked on." -msgstr "\"推迟\": 已提出改进建议,但尚未积极开展工作。" +msgstr "`推迟`: 已提出改进建议,但尚未积极开展工作。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:125 msgid "" "`rejected`: The authors and reviewers have decided that this enhancement is " "not moving forward." -msgstr "拒绝\": 作者和审稿人已决定不再推进该增强功能。" +msgstr "`拒绝`: 作者和审稿人已决定不再推进该增强功能。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:126 msgid "`withdrawn`: The authors have withdrawn the enhancement." -msgstr "撤回\": 作者已撤回增强功能。" +msgstr "`撤回`: 作者已撤回增强功能。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:127 msgid "`replaced`: The enhancement has been replaced by a new enhancement." @@ -4373,18 +4368,17 @@ msgstr "FED - Flower 增强文件" #: ../../source/how-to-aggregate-evaluation-results.rst:2 msgid "Aggregate evaluation results" -msgstr "总体评估结果" +msgstr "整合评估结果" #: ../../source/how-to-aggregate-evaluation-results.rst:4 msgid "" "The Flower server does not prescribe a way to aggregate evaluation results, " "but it enables the user to fully customize result aggregation." -msgstr "" -"Flower 服务器没有规定汇总评估结果的方法,但用户可以完全自定义结果汇总。" +msgstr "Flower 服务器没有规定整合评估结果的方法,但用户可以完全自定义如何整合。" #: ../../source/how-to-aggregate-evaluation-results.rst:8 msgid "Aggregate Custom Evaluation Results" -msgstr "自定义评估结果汇总" +msgstr "自定义整合评估结果" #: ../../source/how-to-aggregate-evaluation-results.rst:10 msgid "" @@ -4411,9 +4405,8 @@ msgid "" "clients. Configuration values can be used for various purposes. They are, " "for example, a popular way to control client-side hyperparameters from the " "server." -msgstr "" -"除了模型参数,Flower 还可以向客户端发送配置值。配置值有多种用途。例如,它们是" -"一种从服务器控制客户端超参数的常用方法。" +msgstr "除了模型参数,Flower 还可以向客户端发送配置值。配置值有多种用途。它们是一种从" +"服务器控制客户端超参数的常用方法。" #: ../../source/how-to-configure-clients.rst:7 msgid "Configuration values" @@ -4447,9 +4440,9 @@ msgid "" "one of the supported value types (and converting them back on the client-" "side)." msgstr "" -"目前,还不支持在配置字典中直接发送作为值的集合类型(例如,`Set``, `List`, " -"`Map``)。有几种变通方法可将集合转换为受支持的值类型之一(并在客户端将其转换" -"回),从而将集合作为值发送。" +"目前,还不支持在配置字典中直接发送作为值的集合类型(例如,`Set``, `List`, `Ma" +"p``)。有几种变通方法可将集合转换为支持的值类型之一(并在客户端将其转换回)," +"从而将集合作为值发送。" #: ../../source/how-to-configure-clients.rst:26 msgid "" @@ -4475,8 +4468,8 @@ msgid "" "selected during that round." msgstr "" "向客户端发送配置值的最简单方法是使用内置策略,如 :code:`FedAvg`。内置策略支持" -"所谓的配置函数。配置函数是内置策略调用的函数,用于获取当前回合的配置字典。然" -"后,它会将配置字典转发给该轮中选择的所有客户端。" +"所谓的配置函数。配置函数是内置策略调用的函数,用于获取当前轮的配置字典。然后" +",它会将配置字典转发给该轮中选择的所有客户端。" #: ../../source/how-to-configure-clients.rst:34 msgid "" @@ -4485,9 +4478,9 @@ msgid "" "learning, and (c) the number of epochs to train on the client-side. Our " "configuration function could look like this:" msgstr "" -"让我们从一个简单的例子开始。想象一下,我们想要发送(a)客户端应该使用的批次大" -"小,(b)当前联合学习的全局轮次,以及(c)客户端训练的历元数。我们的配置函数" -"可以是这样的:" +"让我们从一个简单的例子开始。想象一下,我们想要发送给客户端(a)应该使用的批次" +"大小,(b)当前联邦学习的全局轮次,以及(c)客户端训练的遍历数。我们的配置函" +"数可以是这样的:" #: ../../source/how-to-configure-clients.rst:47 msgid "" @@ -4522,18 +4515,18 @@ msgid "" "schedule, for example, to increase the number of local epochs during later " "rounds, we could do the following:" msgstr "" -"内置策略每轮(即每次运行 `Strategy.configure_fit` 或 `Strategy." -"configure_evaluate` 时)都会调用此函数。每轮调用 `on_evaluate_config_fn` 允许" -"我们在连续几轮中改变配置指令。例如,如果我们想实现一个超参数时间表,以增加后" -"几轮的本地历时次数,我们可以这样做:" +"内置策略每轮都会调用此函数(即每次运行 `Strategy.configure_fit` 或 `Strategy." +"configure_evaluate` 时)。每轮调用 `on_evaluate_config_fn` 允许我们在连续几轮" +"中改变配置指令。例如,如果我们想实现一个超参数时间表,以增加后几轮的本地遍历" +"次数,我们可以这样做:" #: ../../source/how-to-configure-clients.rst:82 msgid "The :code:`FedAvg` strategy will call this function *every round*." -msgstr "代码:`FedAvg`策略每轮*都会调用该函数。" +msgstr "代码:`FedAvg`策略*每轮*都会调用该函数。" #: ../../source/how-to-configure-clients.rst:85 msgid "Configuring individual clients" -msgstr "配置个人客户" +msgstr "配置个别客户端" #: ../../source/how-to-configure-clients.rst:87 msgid "" @@ -4551,11 +4544,12 @@ msgid "" "the list, the other clients in this round to not receive this \"special\" " "config value):" msgstr "" -"这可以通过定制现有策略或 \"从头开始实施一个定制策略 `_\"来实现。下面是一个无厘头的例" -"子,它通过在*单个客户端的配置指令(config dict)中添加自定义的``\"hello\": " -"\"world\"``配置键/值对添加到*单个客户端*(仅列表中的第一个客户端,本轮中的其" -"他客户端不会收到此 \"特殊 \"配置值)的配置 dict 中:" +"这可以通过定制现有策略或 `从头开始实施一个定制策略 `_来实现。下面是一个无厘头的例子,`FedAvg`通过在*单个客户端*的配置指令(" +"config dict)中添加自定义的``\"hello\": \"world\"``配置键/" +"值对添加到此的配置 dict 中(仅列表中的第一个客户端," +"本轮中的其他客户端不会收到此 \"特殊 \"配置值):" #: ../../source/how-to-configure-logging.rst:2 msgid "Configure logging" @@ -4566,8 +4560,7 @@ msgid "" "The Flower logger keeps track of all core events that take place in " "federated learning workloads. It presents information by default following a " "standard message format:" -msgstr "" -"Flower 日志记录器会跟踪联合学习工作负载中发生的所有核心事件。它默认按照标准信" +msgstr "Flower 日志记录器会跟踪联邦学习工作负载中发生的所有核心事件。它默认按照标准信" "息格式提供信息:" #: ../../source/how-to-configure-logging.rst:13 @@ -4577,9 +4570,8 @@ msgid "" "from, as well as the log message itself. In this way, the logger would " "typically display information on your terminal as follows:" msgstr "" -"包含的相关信息包括:日志信息级别(例如 :code:`INFO`、:code:`DEBUG`)、时间" -"戳、日志记录的行以及日志信息本身。这样,日志记录器通常会在终端上显示如下信" -"息:" +"相关信息包括:日志信息级别(例如 :code:`INFO`、:code:`DEBUG`)、时间戳、日志" +"记录的行以及日志信息本身。这样,日志记录器通常会在终端上显示如下信息:" #: ../../source/how-to-configure-logging.rst:34 msgid "Saving log to file" @@ -4596,10 +4588,10 @@ msgid "" "github.com/adap/flower/blob/main/src/py/flwr/common/logger.py>`_ function. " "For example:" msgstr "" -"默认情况下,Flower 日志会输出到启动联合学习工作负载的终端。这既适用于基于 " -"gRPC 的联合(即执行 :code:`fl.server.start_server` 时),也适用于使用 :code:" -"`VirtualClientEngine` 时(即执行 :code:`fl.simulation.start_simulation` " -"时)。在某些情况下,您可能希望将此日志保存到磁盘。为此,您可以调用 `fl." +"默认情况下,Flower 日志会输出到启动联邦学习工作负载的终端。这既适用于基于 " +"gRPC 的联邦学习(即执行 :code:`fl.server.start_server` 时),也适用于使用 " +":code:`VirtualClientEngine` 时(即执行 :code:`fl.simulation.start_simulation`" +" 时)。在某些情况下,您可能希望将此日志保存到磁盘。为此,您可以调用 `fl." "common.logger.configure() `_ 函数。例如:" @@ -4649,12 +4641,12 @@ msgid "" "displays all logs. You can still specify a :code:`HTTPHandler` should you " "whish to backup or analyze the logs somewhere else." msgstr "" -"此外,:code:`fl.common.logger.configure`函数还允许指定主机,通过本地 Python :" -"code:`logging.handler.HTTPHandler`,向该主机推送日志(通过 :code:`POST`)。在" -"基于 :code:`gRPC` 的联合学习工作负载中,这是一个特别有用的功能,否则从所有实" -"体(即服务器和客户端)收集日志可能会很麻烦。请注意,在 Flower 模拟中,服务器" -"会自动显示所有日志。如果希望在其他地方备份或分析日志,仍可指定 :code:" -"`HTTPHandler`。" +"此外,:code:`fl.common.logger.configure`函数还允许指定主机,通过本地 Python " +":code:`logging.handler.HTTPHandler`,向该主机推送日志(通过 :code:`POST`)。" +"在基于 :code:`gRPC` 的联邦学习工作负载中,这是一个特别有用的功能,否则从所有" +"实体(即服务器和客户端)收集日志可能会很麻烦。请注意,在 Flower " +"模拟器中,服务器会自动显示所有日志。如果希望在其他地方备份或分析日志," +"仍可指定 :code:`HTTPHandler`。" #: ../../source/how-to-enable-ssl-connections.rst:2 msgid "Enable SSL connections" @@ -4719,9 +4711,8 @@ msgid "" "complete for production environments. Please refer to other sources " "regarding the issue of correctly generating certificates for production " "environments." -msgstr "" -"本示例中生成 SSL 证书的方法可作为一种启发和起点,但不应被视为生产环境的完整方" -"法。有关在生产环境中正确生成证书的问题,请参考其他资料。" +msgstr "本示例中生成 SSL 证书的方法可作为启发和起点,但不应被视为生产环境的完整方法。" +"有关在生产环境中正确生成证书的问题,请参考其他资料。" #: ../../source/how-to-enable-ssl-connections.rst:36 msgid "" @@ -4737,7 +4728,7 @@ msgstr "服务器" msgid "" "We are now going to show how to write a sever which uses the previously " "generated scripts." -msgstr "现在,我们将展示如何编写一个使用先前生成的脚本的 sever。" +msgstr "现在,我们将展示如何编写一个使用先前生成的脚本的服务器。" #: ../../source/how-to-enable-ssl-connections.rst:61 msgid "" @@ -4773,7 +4764,7 @@ msgstr "" #: ../../source/how-to-enable-ssl-connections.rst:89 #: ../../source/tutorial-series-what-is-federated-learning.ipynb:287 msgid "Conclusion" -msgstr "结论" +msgstr "总结" #: ../../source/how-to-enable-ssl-connections.rst:91 msgid "" @@ -4792,11 +4783,11 @@ msgstr "补充资源" msgid "" "These additional sources might be relevant if you would like to dive deeper " "into the topic of certificates:" -msgstr "如果您想更深入地了解证书主题,这些额外的资料来源可能与您相关:" +msgstr "如果您想更深入地了解证书主题,这些额外的资料来源可能有帮助:" #: ../../source/how-to-enable-ssl-connections.rst:100 msgid "`Let's Encrypt `_" -msgstr "让我们加密 `_" +msgstr "`让我们加密 `_" #: ../../source/how-to-enable-ssl-connections.rst:101 msgid "`certbot `_" @@ -4815,13 +4806,13 @@ msgid "" "provides a few built-in strategies which are based on the same API described " "below." msgstr "" -"策略抽象可以实现完全定制的策略。策略基本上就是在服务器上运行的联合学习算法。" -"策略决定如何对客户端进行采样、如何配置客户端进行训练、如何聚合更新以及如何评" -"估模型。Flower 提供了一些内置策略,这些策略基于下文所述的相同 API。" +"策略抽象类可以实现完全定制的策略。策略基本上就是在服务器上运行的联邦学习算法" +"。策略决定如何对客户端进行采样、如何配置客户端进行训练、如何聚合参数更新以及" +"如何评估模型。Flower 提供了一些内置策略,这些策略基于下文所述的相同 API。" #: ../../source/how-to-implement-strategies.rst:11 msgid "The :code:`Strategy` abstraction" -msgstr "代码:\"策略 \"抽象" +msgstr ":code:`策略 ` 抽象类" #: ../../source/how-to-implement-strategies.rst:13 msgid "" @@ -4858,7 +4849,7 @@ msgstr "下文将详细介绍每种方法。" #: ../../source/how-to-implement-strategies.rst:180 msgid "The :code:`initialize_parameters` method" -msgstr "代码: \"初始化参数 \"方法" +msgstr ":code:`初始化参数` 方法" #: ../../source/how-to-implement-strategies.rst:182 msgid "" @@ -4888,11 +4879,11 @@ msgid "" "for prototyping. In practice, it is recommended to always use server-side " "parameter initialization." msgstr "" -"Flower 服务器将调用 :code:`initialize_parameters`,返回传给 :code:" -"`initial_parameters` 的参数或 :code:`None`。如果 :code:" -"`initialize_parameters` 没有返回任何参数(即 :code:`None`),服务器将随机选择" -"一个客户端并要求其提供参数。这只是一个方便的功能,在实际应用中并不推荐使用," -"但在原型开发中可能很有用。在实践中,建议始终使用服务器端参数初始化。" +"Flower 服务器将调用 :code:`initialize_parameters`,返回传给 " +":code:`initial_parameters` 的参数或 :code:`None`。如果 " +":code:`initialize_parameters` 没有返回任何参数(即 :code:`None`),服务器将随" +"机选择一个客户端并要求其提供参数。这只是一个便捷的功能,在实际应用中并不推荐" +"使用,但在原型开发中可能很有用。在实践中,建议始终使用服务器端参数初始化。" #: ../../source/how-to-implement-strategies.rst:213 msgid "" @@ -4902,13 +4893,12 @@ msgid "" "for example, to fine-tune a pre-trained model using federated learning." msgstr "" "服务器端参数初始化是一种强大的机制。例如,它可以用来从先前保存的检查点恢复训" -"练。它也是实现混合方法所需的基本能力,例如,使用联合学习对预先训练好的模型进" +"练。它也是实现混合方法所需的基本能力,例如,使用联邦学习对预先训练好的模型进" "行微调。" #: ../../source/how-to-implement-strategies.rst:216 -#, fuzzy msgid "The :code:`configure_fit` method" -msgstr "代码:`configure_fit`方法" +msgstr ":code:`configure_fit`方法" #: ../../source/how-to-implement-strategies.rst:218 msgid "" @@ -4917,9 +4907,9 @@ msgid "" "means selecting clients and deciding what instructions to send to these " "clients. The signature of :code:`configure_fit` makes this clear:" msgstr "" -":code:`configure_fit` 负责配置即将开始的一轮训练。配置*在这里是什么意思?配置" -"一轮训练意味着选择客户并决定向这些客户发送什么指令。:code:`configure_fit` 的" -"签名说明了这一点:" +":code:`configure_fit` 负责配置即将开始的一轮训练。*配置*在这里是什么意思?配" +"置一轮训练意味着选择客户并决定向这些客户发送什么指令。:code:`configure_fit` " +"说明了这一点:" #: ../../source/how-to-implement-strategies.rst:231 msgid "" @@ -4954,9 +4944,9 @@ msgid "" "round if the corresponding :code:`ClientProxy` is included in the the list " "returned from :code:`configure_fit`." msgstr "" -"更复杂的实现可以使用 :code:`configure_fit` 来实现自定义的客户端选择逻辑。只有" -"当相应的 :code:`ClientProxy` 包含在 :code:`configure_fit` 返回的列表中时,客" -"户端才会参加比赛。" +"更复杂的实现可以使用 :code:`configure_fit` 来实现自定义的客户端选择逻辑。" +"只有当相应的 :code:`ClientProxy` 包含在 :code:`configure_fit` " +"返回的列表中时,客户端才会参与进来。" #: ../../source/how-to-implement-strategies.rst:240 msgid "" @@ -5006,7 +4996,7 @@ msgstr "" #: ../../source/how-to-implement-strategies.rst:263 msgid "The :code:`configure_evaluate` method" -msgstr "代码:\"配置评估 \"方法" +msgstr ":code:`configure_evaluate`方法" #: ../../source/how-to-implement-strategies.rst:265 msgid "" @@ -5015,9 +5005,9 @@ msgid "" "round means selecting clients and deciding what instructions to send to " "these clients. The signature of :code:`configure_evaluate` makes this clear:" msgstr "" -":code:`configure_evaluate` 负责配置下一轮评估。配置*在这里是什么意思?配置一" -"轮评估意味着选择客户端并决定向这些客户端发送什么指令。:code:" -"`configure_evaluate` 的签名说明了这一点:" +":code:`configure_evaluate` 负责配置下一轮评估。*配置*在这里是什么意思?配置一" +"轮评估意味着选择客户端并决定向这些客户端发送什么指令。:code:`configure_evalua" +"te` 说明了这一点:" #: ../../source/how-to-implement-strategies.rst:278 msgid "" @@ -5043,9 +5033,9 @@ msgid "" "round if the corresponding :code:`ClientProxy` is included in the the list " "returned from :code:`configure_evaluate`." msgstr "" -"更复杂的实现可以使用 :code:`configure_evaluate` 来实现自定义的客户端选择逻" -"辑。只有当相应的 :code:`ClientProxy` 包含在 :code:`configure_evaluate` 返回的" -"列表中时,客户端才会参与一轮比赛。" +"更复杂的实现可以使用 :code:`configure_evaluate` " +"来实现自定义的客户端选择逻辑。只有当相应的 :code:`ClientProxy` 包含在 " +":code:`configure_evaluate` 返回的列表中时,客户端才会参与进来。" #: ../../source/how-to-implement-strategies.rst:287 msgid "" @@ -5061,7 +5051,7 @@ msgstr "" #: ../../source/how-to-implement-strategies.rst:291 msgid "The :code:`aggregate_evaluate` method" -msgstr "代码 :`aggregate_evaluate` 方法" +msgstr ":code:`aggregate_evaluate` 方法" #: ../../source/how-to-implement-strategies.rst:293 msgid "" @@ -5091,13 +5081,14 @@ msgid "" "because :code:`aggregate_evaluate` might decide that the results provided " "are not sufficient for aggregation (e.g., too many failures)." msgstr "" -":code:`aggregate_evaluate` 返回一个可选的 :code:`float`(损失)和一个聚合指标" -"字典。:code:`float` 返回值是可选的,因为 :code:`aggregate_evaluate` 可能会认" -"为所提供的结果不足以进行聚合(例如,失败次数过多)。" +":code:`aggregate_evaluate` 返回一个可选的 " +":code:`float`(损失值)和一个聚合指标字典。:code:`float` 返回值是可选的," +"因为 :code:`aggregate_evaluate` " +"可能会认为所提供的结果不足以进行聚合(例如,失败次数过多)。" #: ../../source/how-to-implement-strategies.rst:311 msgid "The :code:`evaluate` method" -msgstr "代码:\"评估 \"方法" +msgstr ":code:`evaluate`方法" #: ../../source/how-to-implement-strategies.rst:313 msgid "" @@ -5106,9 +5097,9 @@ msgid "" "`configure_evaluate`/:code:`aggregate_evaluate` enables strategies to " "perform both servers-side and client-side (federated) evaluation." msgstr "" -":code:`evaluate` 负责在服务器端评估模型参数。除了 :code:" -"`configure_evaluate`/:code:`aggregate_evaluate` 之外,:code:`evaluate` 可以使" -"策略同时执行服务器端和客户端(联合)评估。" +":code:`evaluate` 负责在服务器端评估模型参数。除了 " +":code:`configure_evaluate`/:code:`aggregate_evaluate` 之外,:code:`evaluate` " +"可以使策略同时执行服务器端和客户端(联邦)评估。" #: ../../source/how-to-implement-strategies.rst:323 msgid "" @@ -5142,8 +5133,7 @@ msgstr "稳定版本可在 `PyPI `_::" msgid "" "For simulations that use the Virtual Client Engine, ``flwr`` should be " "installed with the ``simulation`` extra::" -msgstr "" -"对于使用虚拟客户端引擎的模拟,`flwr`` 应与`simulation`` 额外:一起安装:" +msgstr "对于使用虚拟客户端引擎的模拟,`flwr`` 应与`simulation`` 一起安装:" #: ../../source/how-to-install-flower.rst:24 msgid "Verify installation" @@ -5179,19 +5169,17 @@ msgstr "" msgid "" "For simulations that use the Virtual Client Engine, ``flwr`` pre-releases " "should be installed with the ``simulation`` extra::" -msgstr "" -"对于使用虚拟客户端引擎的模拟,`flwr``预发行版应与`simulation``额外:一起安" -"装:" +msgstr "对于使用虚拟客户端引擎的模拟,`flwr``预发行版应与`simulation``一起安装:" #: ../../source/how-to-install-flower.rst:47 msgid "Install nightly release" -msgstr "安装夜间版本" +msgstr "安装隔夜版本" #: ../../source/how-to-install-flower.rst:49 msgid "" "The latest (potentially unstable) changes in Flower are available as nightly " "releases::" -msgstr "Flower 中最新(可能不稳定)的更改以夜间发布的形式提供::" +msgstr "Flower 中最新(可能不稳定)的更改以隔夜发布的形式提供::" #: ../../source/how-to-install-flower.rst:53 msgid "" @@ -5212,8 +5200,8 @@ msgid "" "speed up the execution time." msgstr "" "Flower 允许您在运行模拟时监控系统资源。此外,Flower 仿真引擎功能强大,能让您" -"决定如何按客户端方式分配资源并限制总使用量。从资源消耗中获得的洞察力可以帮助" -"您做出更明智的决策,并加快执行时间。" +"决定如何按客户端方式分配资源并限制总使用量。从资源消耗中获得的观察可以帮助您" +"做出更明智的决策,并加快执行时间。" #: ../../source/how-to-monitor-simulation.rst:6 msgid "" @@ -5234,9 +5222,9 @@ msgid "" "data. They are both well integrated with `Ray `_ which " "Flower uses under the hood." msgstr "" -"`Prometheus `_ 用于收集数据,而 `Grafana `_ 则能让你将收集到的数据可视化。它们都与 Flower 在引擎盖下使用" -"的 `Ray `_ 紧密集成。" +"`Prometheus `_ 用于收集数据,而 `Grafana " +"`_ 则能让你将收集到的数据可视化。它们都与 Flower " +"在引擎下使用的 `Ray `_ 紧密集成。" #: ../../source/how-to-monitor-simulation.rst:18 msgid "" @@ -5365,10 +5353,10 @@ msgid "" "learn more about that in the later part of this blog. You can check the " "system resources by running the following:" msgstr "" -"最初,模拟(由 Ray 在引擎盖下处理)默认使用系统上的所有可用资源启动,并在客户" -"端之间共享。但这并不意味着它会将资源平均分配给所有客户端,也不意味着模型训练" -"会在所有客户端同时进行。您将在本博客的后半部分了解到更多相关信息。您可以运行" -"以下命令检查系统资源:" +"最初,模拟(由 Ray 在引擎下处理)默认使用系统上的所有可用资源启动,并在客户端" +"之间共享。但这并不意味着它会将资源平均分配给所有客户端,也不意味着模型训练会" +"在所有客户端同时进行。您将在本博客的后半部分了解到更多相关信息。您可以运行以" +"下命令检查系统资源:" #: ../../source/how-to-monitor-simulation.rst:143 msgid "In Google Colab, the result you see might be similar to this:" @@ -5448,26 +5436,23 @@ msgstr "问:在访问 ``_时,我看到 \"无法访问 msgid "" "A: Either the simulation has already finished, or you still need to start " "Prometheus." -msgstr "答:要么模拟已经完成,要么您还需要启动普罗米修斯。" +msgstr "答:要么模拟已经完成,要么您还需要启动Prometheus。" #: ../../source/how-to-monitor-simulation.rst:232 msgid "Resources" msgstr "资源" #: ../../source/how-to-monitor-simulation.rst:234 -#, fuzzy msgid "" "Ray Dashboard: ``_" -msgstr "" -"Ray Dashboard: ``_" +msgstr "Ray 仪表盘: ``_" #: ../../source/how-to-monitor-simulation.rst:236 -#, fuzzy msgid "" "Ray Metrics: ``_" msgstr "" -"Ray Metrics: ``_" #: ../../source/how-to-run-simulations.rst:2 @@ -5488,13 +5473,13 @@ msgid "" "scenarios by means of its `VirtualClientEngine `_ or VCE." msgstr "" -"模拟联合学习工作负载可用于多种用例:您可能希望在大量客户端上运行您的工作负" -"载,但无需采购、配置和管理大量物理设备;您可能希望在您可以访问的计算系统上尽" -"可能快地运行您的 FL 工作负载,而无需经过复杂的设置过程;您可能希望在不同数据" -"和系统异构性、客户端可用性、隐私预算等不同水平的场景中验证您的算法。这些都是" -"模拟 FL 工作负载有意义的一些用例。Flower 可以通过其 \"虚拟客户端引擎" -"\"(VirtualClientEngine)_或 VCE 来适应这些情况。" +"模拟联邦学习工作负载可用于多种案例:您可能希望在大量客户端上运行您的工作负载" +",但无需采购、配置和管理大量物理设备;" +"您可能希望在您可以访问的计算系统上尽可能快地运行您的 FL 工作负载,而无需经过" +"复杂的设置过程;您可能希望在不同数据和系统异构性、客户端可用性、隐私预算等不" +"同水平的场景中验证您的算法。这些都是模拟 FL 工作负载的一些案例。Flower " +"可以通过其 \"虚拟客户端引擎\"(VirtualClientEngine)_或 VCE 来匹配这些情况。" #: ../../source/how-to-run-simulations.rst:10 msgid "" @@ -5506,6 +5491,12 @@ msgid "" "html#flwr.client.NumPyClient>`_ and therefore behave in an identical way. In " "addition to that, clients managed by the :code:`VirtualClientEngine` are:" msgstr "" +":code:`VirtualClientEngine`用来规划,启动和管理`虚拟`客户端。这些客户端跟`非" +"虚拟`客户端是一样的(即为您通过`flwr.client.start_client `_启动的客户端),因为它们可以通过创建一个继承自 `" +"flwr.client.NumPyClient `_ " +"的类进行配置,因此其行为方式相同。另外,由 `VirtualClientEngine` " +"管理的客户端有:" #: ../../source/how-to-run-simulations.rst:12 msgid "" @@ -5524,9 +5515,8 @@ msgid "" "self-managed: this means that you as a user do not need to launch clients " "manually, instead this gets delegated to :code:`VirtualClientEngine`'s " "internals." -msgstr "" -"自管理:这意味着用户无需手动启动客户端,而是由 :code:`VirtualClientEngine` 的" -"内部人员负责。" +msgstr "自管理:这意味着用户无需手动启动客户端,而是由 :code:`VirtualClientEngine` " +"负责。" #: ../../source/how-to-run-simulations.rst:14 msgid "" @@ -5535,9 +5525,9 @@ msgid "" "fit>`_). The object is destroyed afterwards, releasing the resources it was " "assigned and allowing in this way other clients to participate." msgstr "" -"ephemeral(短暂的):这意味着客户端只有在 FL 进程中需要它时才会被实体化(例如" -"执行 `fit() `_ )。之后该对象将被销" -"毁,释放分配给它的资源,并允许其他客户端以这种方式参与。" +"即时性:这意味着客户端只有在 FL 进程中需要它时才会被实体化(例如执行 `fit() " +"`_ " +")。之后该对象将被销毁,释放分配给它的资源,并允许其他客户端以这种方式参与。" #: ../../source/how-to-run-simulations.rst:16 msgid "" @@ -5547,10 +5537,10 @@ msgid "" "`Actors `_ to spawn " "`virtual` clients and run their workload." msgstr "" -"代码:`VirtualClientEngine`使用`Ray `_来实现`虚拟`客户" -"端,这是一个用于可扩展 Python 工作负载的开源框架。特别地,Flower 的 :code:" -"`VirtualClientEngine` 使用 `Actors `_ 来生成 `virtual` 客户端并运行它们的工作负载。" +":code:`VirtualClientEngine`使用`Ray `_来实现`虚拟`客户端,这是一个用于可扩展 Python 工作负载的开源框架。特别地," +"Flower 的 :code:`VirtualClientEngine` 使用 `Actors `_ 来生成 `virtual` 客户端并运行它们的工作负载。" #: ../../source/how-to-run-simulations.rst:20 msgid "Launch your Flower simulation" @@ -5564,10 +5554,10 @@ msgid "" "is done with `start_simulation `_ and a minimal example looks as follows:" msgstr "" -"运行 Flower 仿真仍然需要定义客户端类、策略以及下载和加载(可能还需要分割)数" -"据集的实用程序。在完成这些工作后,就可以使用 \"start_simulation `_\" 来启动模拟了,一个最简单的示" -"例如下:" +"运行 Flower 模拟器仍然需要定义客户端类、策略以及下载和加载(可能还需要分割)" +"数据集的实用程序。在完成这些工作后,就可以使用 \"start_simulation `_\" " +"来启动模拟了,一个最简单的示例如下:" #: ../../source/how-to-run-simulations.rst:44 msgid "VirtualClientEngine resources" @@ -5586,17 +5576,18 @@ msgid "" "code:`ray_init_args` if you want the VCE to use all your system's CPUs and " "GPUs." msgstr "" -"默认情况下,VCE 可以访问所有系统资源(即所有 CPU、所有 GPU 等),因为这也是启" -"动 Ray 时的默认行为。不过,在某些设置中,您可能希望限制有多少系统资源用于仿" -"真。您可以通过 :code:`ray_init_args` 输入到 :code:`start_simulation` 的参数来" -"做到这一点,VCE 会在内部将该参数传递给 Ray 的 :code:`ray.init` 命令。有关您可" -"以配置的设置的完整列表,请查看 `ray.init `_ 文档。如果希望 VCE 使用系统中所有的 " -"CPU 和 GPU,请不要设置 :code:`ray_init_args`。" +"默认情况下,VCE 可以访问所有系统资源(即所有 CPU、所有 GPU 等)," +"因为这也是启动 Ray " +"时的默认行为。不过,在某些设置中,您可能希望限制有多少系统资源用于模拟。" +"您可以通过 :code:`ray_init_args` 输入到 :code:`start_simulation` " +"的参数来做到这一点,VCE 会在内部将该参数传递给 Ray 的 :code:`ray.init` " +"命令。有关您可以配置的设置的完整列表,请查看 `ray.init `_ 文档。如果希望 VCE " +"使用系统中所有的 CPU 和 GPU,请不要设置 :code:`ray_init_args`。" #: ../../source/how-to-run-simulations.rst:62 msgid "Assigning client resources" -msgstr "分配客户资源" +msgstr "分配客户端资源" #: ../../source/how-to-run-simulations.rst:63 msgid "" @@ -5617,10 +5608,11 @@ msgid "" "flwr.html#flwr.simulation.start_simulation>`_. Two keys are internally used " "by Ray to schedule and spawn workloads (in our case Flower clients):" msgstr "" -"通常情况下,您可能希望根据 FL 工作负载的复杂性(即计算和内存占用)来调整分配" -"给客户端的资源。您可以在启动仿真时将参数 `client_resources` 设置为 " -"`start_simulation `_ 。" -"Ray 内部使用两个键来调度和生成工作负载(在我们的例子中是 Flower 客户端):" +"通常情况下,您可能希望根据 FL " +"工作负载的复杂性(即计算和内存占用)来调整分配给客户端的资源。" +"您可以在启动模拟时将参数 `client_resources` 设置为 `start_simulation `_ 。Ray " +"内部使用两个键来调度和生成工作负载(在我们的例子中是 Flower 客户端):" #: ../../source/how-to-run-simulations.rst:67 msgid ":code:`num_cpus` indicates the number of CPU cores a client would get." @@ -5630,7 +5622,7 @@ msgstr ":code:`num_cpus` 表示客户端将获得的 CPU 内核数量。" msgid "" ":code:`num_gpus` indicates the **ratio** of GPU memory a client gets " "assigned." -msgstr ":code:`num_gpus` 表示分配给客户端的 GPU 内存的***比例。" +msgstr ":code:`num_gpus` 表示分配给客户端的 GPU 内存的**比例**。" #: ../../source/how-to-run-simulations.rst:70 msgid "Let's see a few examples:" @@ -5649,10 +5641,11 @@ msgid "" "of 8." msgstr "" "虽然 :code:`client_resources` 可用来控制 FL 模拟的并发程度,但这并不能阻止您" -"在同一轮模拟中运行几十、几百甚至上千个客户端,并拥有数量级更多的 \"休眠\"(即" -"不参与一轮模拟)客户端。比方说,您希望每轮有 100 个客户端,但您的系统只能同时" -"容纳 8 个客户端。:code:`VirtualClientEngine` 将安排运行 100 个作业(每个作业" -"模拟策略采样的一个客户端),然后以资源感知的方式分批执行。" +"在同一轮模拟中运行几十、几百甚至上千个客户端,并拥有数量级更多的 \"休眠\"" +"(即不参与一轮模拟)客户端。比方说,您希望每轮有 100 个客户端," +"但您的系统只能同时容纳 8 个客户端。:code:`VirtualClientEngine` 将安排运行 " +"100 " +"个工作(每个工作模拟策略采样的一个客户端),然后以资源感知的方式分批执行。" #: ../../source/how-to-run-simulations.rst:91 msgid "" @@ -5675,9 +5668,9 @@ msgid "" "Keras and PyTorch are provided in the `Flower repository `_. You can run them on Google Colab too:" msgstr "" -"在 Tensorflow/Keras 和 PyTorch 中进行 Flower 仿真的几个可随时运行的完整示例已" -"在 `Flower 存储库 `_ 中提供。您也可以在 " -"Google Colab 上运行它们:" +"在 Tensorflow/Keras 和 PyTorch 中进行 Flower " +"模拟的几个可随时运行的完整示例已在 `Flower 库 `_ 中提供。您也可以在 Google Colab 上运行它们:" #: ../../source/how-to-run-simulations.rst:98 msgid "" @@ -5685,7 +5678,7 @@ msgid "" "examples/simulation-tensorflow>`_: 100 clients collaboratively train a MLP " "model on MNIST." msgstr "" -"Tensorflow/Keras仿真 `_:100个客户端在MNIST上协作训练一个MLP模型。" #: ../../source/how-to-run-simulations.rst:99 @@ -5694,7 +5687,7 @@ msgid "" "simulation-pytorch>`_: 100 clients collaboratively train a CNN model on " "MNIST." msgstr "" -"PyTorch 仿真 `_:100 个客户端在 MNIST 上协作训练一个 CNN 模型。" #: ../../source/how-to-run-simulations.rst:104 @@ -5707,8 +5700,8 @@ msgid "" "multiple compute nodes. Before starting your multi-node simulation ensure " "that you:" msgstr "" -"Flower 的 :code:`VirtualClientEngine` 允许您在多个计算节点上运行 FL 仿真。在" -"开始多节点模拟之前,请确保:" +"Flower 的 :code:`VirtualClientEngine` 允许您在多个计算节点上运行 FL " +"模拟。在开始多节点模拟之前,请确保:" #: ../../source/how-to-run-simulations.rst:108 msgid "Have the same Python environment in all nodes." @@ -5742,8 +5735,8 @@ msgid "" "This command will print a few lines, one of which indicates how to attach " "other nodes to the head node." msgstr "" -"在头部节点上启动 Ray:在终端上输入 :code:`raystart--head`。该命令将打印几行," -"其中一行说明如何将其他节点连接到头部节点。" +"在头部节点上启动 Ray:在终端上输入 :code:`raystart--" +"head`。该命令将打印几行输出,其中一行说明如何将其他节点连接到头部节点。" #: ../../source/how-to-run-simulations.rst:113 msgid "" @@ -5813,9 +5806,8 @@ msgstr "模拟的注意事项" msgid "" "We are actively working on these fronts so to make it trivial to run any FL " "workload with Flower simulation." -msgstr "" -"我们正在积极开展这些方面的工作,以便使 FL 工作负载与 Flower 仿真的运行变得轻" -"而易举。" +msgstr "我们正在积极开展这些方面的工作,以便使 FL 工作负载与 Flower " +"模拟的运行变得轻而易举。" #: ../../source/how-to-run-simulations.rst:138 msgid "" @@ -5827,10 +5819,10 @@ msgid "" "with Flower. We also highlight a couple of current limitations in our " "implementation." msgstr "" -"当前的 VCE 允许您在模拟模式下运行 Federated Learning 工作负载,无论您是在个人" -"笔记本电脑上建立简单的场景原型,还是要在多个高性能 GPU 节点上训练复杂的 FL 管" -"道。虽然我们为 VCE 增加了更多的功能,但以下几点强调了在使用 Flower 设计 FL 管" -"道时需要注意的一些事项。我们还强调了我们的实现中目前存在的一些局限性。" +"当前的 VCE 允许您在模拟模式下运行联邦学习工作负载,无论您是在个人笔记本电脑上" +"建立简单的场景原型,还是要在多个高性能 GPU 节点上训练复杂的 FL情景。" +"虽然我们为 VCE 增加了更多的功能,但以下几点强调了在使用 Flower 设计 FL " +"时需要注意的一些事项。我们还强调了我们的实现中目前存在的一些局限性。" #: ../../source/how-to-run-simulations.rst:141 msgid "GPU resources" @@ -5877,8 +5869,8 @@ msgid "" "machine you need to mask-out your GPUs with :code:" "`CUDA_VISIBLE_DEVICES=\"\"` when launching your experiment." msgstr "" -"如果您想在同一台机器上运行多个独立的 Flower 仿真,则需要在启动实验时使用 :" -"code:`CUDA_VISIBLE_DEVICES=\"\"` 屏蔽 GPU。" +"如果您想在同一台机器上运行多个独立的 Flower 模拟,则需要在启动实验时使用 " +":code:`CUDA_VISIBLE_DEVICES=\"\"` 屏蔽 GPU。" #: ../../source/how-to-run-simulations.rst:153 msgid "" @@ -5904,11 +5896,12 @@ msgid "" "this default behavior by `enabling memory growth `_." msgstr "" -"在 TensorFlow `_ 中使用 GPU 时,几乎所" -"有进程可见的 GPU 内存都将被映射。TensorFlow 这样做是出于优化目的。然而,在 " -"FL 模拟等设置中,我们希望将 GPU 分割成多个 \"虚拟 \"客户端,这并不是一个理想" -"的机制。幸运的是,我们可以通过 \"启用内存增长 `_\"来禁用这一默认行为。" +"在 TensorFlow `_ 中使用 GPU 时," +"几乎所有进程可见的 GPU 内存都将被映射。TensorFlow " +"这样做是出于优化目的。然而,在 FL 模拟等设置中,我们希望将 GPU 分割成多个 " +"\"虚拟 \"客户端,这并不是一个理想的机制。幸运的是,我们可以通过 `" +"启用内存增长 `_来禁用这一默认行为。" #: ../../source/how-to-run-simulations.rst:160 msgid "" @@ -5918,9 +5911,10 @@ msgid "" "to specify a function to be executed upon actor initialization. In this " "case, to enable GPU growth for TF workloads. It would look as follows:" msgstr "" -"这需要在主进程(也就是服务器运行的地方)和 VCE 创建的每个角色中完成。通过 :" -"code:`actor_kwargs`,我们可以传递保留关键字`\"on_actor_init_fn\"`,以指定在角" -"色初始化时执行的函数。在本例中,为了使 TF 工作负载的 GPU 增长。它看起来如下:" +"这需要在主进程(也就是服务器运行的地方)和 VCE 创建的每个角色中完成。通过 " +":code:`actor_kwargs`,我们可以传递保留关键字`\"on_actor_init_fn\"" +"`,以指定在角色初始化时执行的函数。在本例中,为了使 TF 工作负载的 GPU " +"增长,它看起来如下:" #: ../../source/how-to-run-simulations.rst:179 msgid "" @@ -5928,7 +5922,7 @@ msgid "" "`_ " "example." msgstr "" -"这正是 \"Tensorflow/Keras 仿真 `_\"示例中使用的机制。" #: ../../source/how-to-run-simulations.rst:183 @@ -5962,10 +5956,10 @@ msgid "" "node it is running from. This is related to the point above also since, in " "some way, the client's dataset could be seen as a type of `state`." msgstr "" -"根据定义,虚拟客户端是 \"无状态 \"的,因为它们具有短暂性。客户机状态可以作为 " +"根据定义,虚拟客户端是 \"无状态 \"的,因为它们具有即时性。客户机状态可以作为 " "Flower 客户机类的一部分来实现,但用户需要确保将其保存到持久存储(如数据库、磁" -"盘)中,而且无论客户机在哪个节点上运行,都能在以后检索到。这也与上述观点有" -"关,因为在某种程度上,客户端的数据集可以被视为一种 \"状态\"。" +"盘)中,而且无论客户机在哪个节点上运行,都能在以后检索到。这也与上述观点有关" +",因为在某种程度上,客户端的数据集可以被视为一种 \"状态\"。" #: ../../source/how-to-save-and-load-model-checkpoints.rst:2 msgid "Save and load model checkpoints" @@ -5997,11 +5991,11 @@ msgid "" "weights to the caller (i.e., the server):" msgstr "" "模型更新可通过自定义 :code:`Strategy` 方法在服务器端持久化。实现自定义策略始" -"终是一种选择,但在许多情况下,简单地自定义现有策略可能更方便。下面的代码示例" -"定义了一个新的 :code:`SaveModelStrategy`,它自定义了现有的内置 :code:" -"`FedAvg` 策略。特别是,它通过调用基类(:code:`FedAvg`)中的 :code:" -"`aggregate_fit` 来定制 :code:`aggregate_fit`。然后继续保存返回的(聚合)权" -"重,然后再将这些聚合权重返回给调用者(即服务器):" +"终是一种选择,但在许多情况下,简单地自定义现有策略可能更方便。" +"下面的代码示例定义了一个新的 :code:`SaveModelStrategy`,它自定义了现有的内置 " +":code:`FedAvg` 策略。特别是,它通过调用基类(:code:`FedAvg`)中的 " +":code:`aggregate_fit` 来定制 :code:`aggregate_fit`。然后继续保存返回的(聚合" +")参数,然后再将这些聚合参数返回给调用者(即服务器):" #: ../../source/how-to-save-and-load-model-checkpoints.rst:47 msgid "Save and load PyTorch checkpoints" @@ -6079,8 +6073,8 @@ msgid "" "reinstall (don't forget to delete ``poetry.lock`` via ``rm poetry.lock`` " "before running ``poetry install``)." msgstr "" -"诗歌:更新 ``pyproject.toml`` 中的 ``flwr`` 依赖关系,然后重新安装(运行 " -"``poetry install`` 前,别忘了通过 ``rm poetry.lock` 删除 ``poetry.lock`)。" +"Poetry:更新 ``pyproject.toml`` 中的 ``flwr`` 依赖包,然后重新安装(运行 ``" +"poetry install`` 前,别忘了通过 ``rm poetry.lock` 删除 ``poetry.lock`)。" #: ../../source/how-to-upgrade-to-flower-1.0.rst:19 msgid "" @@ -6165,13 +6159,12 @@ msgstr "" "\"round_timeout\": 600.0}, ...)``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:48 -#, fuzzy msgid "" "Flower 1.0: ``start_server(..., config=flwr.server." "ServerConfig(num_rounds=3, round_timeout=600.0), ...)``" msgstr "" -"Flower 1.0: ``start_server(..., config=flwr.server." -"ServerConfig(num_rounds=3, round_timeout=600.0), ...)``" +"Flower 1.0: ``start_server(..., config=flwr.server.ServerConfig(" +"num_rounds=3, round_timeout=600.0), ...)``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:50 msgid "" @@ -6197,12 +6190,10 @@ msgid "Rename parameter/ndarray conversion functions:" msgstr "重命名参数/数组转换函数:" #: ../../source/how-to-upgrade-to-flower-1.0.rst:54 -#, fuzzy msgid "``parameters_to_weights`` --> ``parameters_to_ndarrays``" msgstr "``parameters_to_weights`` --> ``parameters_to_ndarrays``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:55 -#, fuzzy msgid "``weights_to_parameters`` --> ``ndarrays_to_parameters``" msgstr "``weights_to_parameters`` --> ``ndarrays_to_parameters``" @@ -6226,7 +6217,6 @@ msgid "Rename built-in strategy parameters (e.g., ``FedAvg``):" msgstr "重命名内置策略参数(例如,`FedAvg``):" #: ../../source/how-to-upgrade-to-flower-1.0.rst:60 -#, fuzzy msgid "``fraction_eval`` --> ``fraction_evaluate``" msgstr "``fraction_eval`` --> ``fraction_evaluate``" @@ -6253,7 +6243,6 @@ msgid "Add ``server_round`` and ``config`` to ``evaluate_fn``:" msgstr "在 ``evaluate_fn` 中添加 ``server_round` 和 ``config`:" #: ../../source/how-to-upgrade-to-flower-1.0.rst:67 -#, fuzzy msgid "" "Flower 0.19: ``def evaluate(parameters: NDArrays) -> Optional[Tuple[float, " "Dict[str, Scalar]]]:``" @@ -6262,7 +6251,6 @@ msgstr "" "Dict[str, Scalar]]]:``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:68 -#, fuzzy msgid "" "Flower 1.0: ``def evaluate(server_round: int, parameters: NDArrays, config: " "Dict[str, Scalar]) -> Optional[Tuple[float, Dict[str, Scalar]]]:``" @@ -6272,7 +6260,7 @@ msgstr "" #: ../../source/how-to-upgrade-to-flower-1.0.rst:71 msgid "Custom strategies" -msgstr "定制战略" +msgstr "定制策略" #: ../../source/how-to-upgrade-to-flower-1.0.rst:73 msgid "" @@ -6290,18 +6278,18 @@ msgstr "" msgid "" "The ``Strategy`` method ``evaluate`` now receives the current round of " "federated learning/evaluation as the first parameter:" -msgstr "策略 \"方法 \"评估 \"现在会接收当前一轮联合学习/评估作为第一个参数:" +msgstr "``Strategy``方法 " +"的``evaluate``现在会接收当前一轮联邦学习/评估作为第一个参数:" #: ../../source/how-to-upgrade-to-flower-1.0.rst:76 msgid "" "Flower 0.19: ``def evaluate(self, parameters: Parameters) -> " "Optional[Tuple[float, Dict[str, Scalar]]]:``" msgstr "" -"Flower 0.19: ``def evaluate(self, parameters: 参数) -> Optional[Tuple[float, " -"Dict[str, Scalar]]]:```" +"Flower 0.19: ``def evaluate(self, parameters: Parameters) -> Optional[Tuple[" +"float, Dict[str, Scalar]]]:```" #: ../../source/how-to-upgrade-to-flower-1.0.rst:77 -#, fuzzy msgid "" "Flower 1.0: ``def evaluate(self, server_round: int, parameters: Parameters) -" "> Optional[Tuple[float, Dict[str, Scalar]]]:``" @@ -6317,7 +6305,7 @@ msgstr "可选的改进措施" msgid "" "Along with the necessary changes above, there are a number of potential " "improvements that just became possible:" -msgstr "除了上述必要的改动之外,还有一些潜在的改进措施刚刚成为可能:" +msgstr "除了上述必要的改动之外,还有一些潜在的改进措施:" #: ../../source/how-to-upgrade-to-flower-1.0.rst:84 msgid "" @@ -6325,8 +6313,9 @@ msgid "" "``NumPyClient``. If you, for example, use server-side evaluation, then empy " "placeholder implementations of ``evaluate`` are no longer necessary." msgstr "" -"删除 ``Client`` 或 ``NumPyClient`` 子类中的 \"占位符 \"方法。例如,如果你使用" -"服务器端评估,那么就不再需要``evaluate``的 \"repy占位符 \"实现。" +"删除 ``Client`` 或 ``NumPyClient`` 子类中的 \"占位符 \"方法" +"。例如,如果你使用服务器端评估,那么就不再需要``evaluate``的 \"空占位符 " +"\"实现。" #: ../../source/how-to-upgrade-to-flower-1.0.rst:85 msgid "" @@ -6349,10 +6338,10 @@ msgid "" "`join the Flower Slack `_ and use the " "channgel ``#questions``." msgstr "" -"大多数官方的 \"Flower 代码示例 `_ 已经更新到 Flower 1.0,它们可以作为使用 Flower 1.0 API 的参考。如" -"果还有其他问题,请加入 Flower Slack `_ 并使" -"用 \"#questions``\"。" +"大多数官方的 `Flower 代码示例 `_ 已经更新到 Flower 1.0,它们可以作为使用 Flower 1.0 API " +"的参考。如果还有其他问题,请加入 Flower Slack `_ 并使用 \"#questions``\"。" #: ../../source/how-to-use-strategies.rst:2 msgid "Use strategies" @@ -6363,9 +6352,8 @@ msgid "" "Flower allows full customization of the learning process through the :code:" "`Strategy` abstraction. A number of built-in strategies are provided in the " "core framework." -msgstr "" -"Flower 允许通过 :code:`Strategy` 抽象对学习过程进行完全定制。核心框架中提供了" -"许多内置策略。" +msgstr "Flower 允许通过 :code:`Strategy` " +"抽象类对学习过程进行完全定制。核心框架中提供了许多内置策略。" #: ../../source/how-to-use-strategies.rst:6 msgid "" @@ -6385,17 +6373,17 @@ msgstr "使用回调函数定制现有策略" #: ../../source/how-to-use-strategies.rst:10 #: ../../source/how-to-use-strategies.rst:87 msgid "Implement a novel strategy" -msgstr "实施新颖战略" +msgstr "实施新策略" #: ../../source/how-to-use-strategies.rst:14 msgid "Use an existing strategy" -msgstr "使用现有战略" +msgstr "使用现有策略" #: ../../source/how-to-use-strategies.rst:16 msgid "" "Flower comes with a number of popular federated learning strategies built-" "in. A built-in strategy can be instantiated as follows:" -msgstr "Flower 内置了许多流行的联合学习策略。内置策略的实例化方法如下:" +msgstr "Flower 内置了许多流行的联邦学习策略。内置策略的实例化方法如下:" #: ../../source/how-to-use-strategies.rst:25 msgid "" @@ -6430,8 +6418,8 @@ msgid "" msgstr "" "服务器可以通过向 :code:`on_fit_config_fn` 提供一个函数,在每一轮向客户端传递" "新的配置值。提供的函数将被策略调用,并且必须返回一个配置键值对的字典,该字典" -"将被发送到客户端。在每一轮联合学习期间,它必须返回一个任意配置值 dictionary :" -"code:`client.fit`和 :code:`client.evaluate`函数。" +"将被发送到客户端。在每一轮联邦学习期间,它必须返回一个任意配置值 dictionary " +":code:`client.fit`和 :code:`client.evaluate`函数。" #: ../../source/how-to-use-strategies.rst:75 msgid "" @@ -6441,9 +6429,9 @@ msgid "" "dictionary returned by the :code:`on_fit_config_fn` in its own :code:`client." "fit()` function." msgstr "" -":code:`on_fit_config_fn`可用于将任意配置值从服务器传递到客户端,并在每一轮诗" -"意地改变这些值,例如,调整学习率。客户端将在自己的 :code:`client.fit()` 函数" -"中接收 :code:`on_fit_config_fn` 返回的字典。" +":code:`on_fit_config_fn`可用于将任意配置值从服务器传递到客户端,并在每一轮改" +"变这些值,例如,调整学习率。客户端将在自己的 :code:`client.fit()` 函数中接收 " +":code:`on_fit_config_fn` 返回的字典。" #: ../../source/how-to-use-strategies.rst:78 msgid "" @@ -6470,7 +6458,7 @@ msgid "" "most flexibility. Read the `Implementing Strategies `_ guide to learn more." msgstr "" -"编写完全自定义的策略涉及的内容较多,但灵活性最高。阅读 \"实施策略\"_ 指南,了解更多信息。" #: ../../source/index.rst:34 @@ -6521,7 +6509,7 @@ msgstr "贡献者参考资料" msgid "" "Check out the documentation of the main Flower Framework enabling easy " "Python development for Federated Learning." -msgstr "查看主 Flower Framework 的文档,轻松实现联合学习的 Python 开发。" +msgstr "查看主 Flower Framework 的文档,轻松实现联邦学习的 Python 开发。" #: ../../source/index.rst:2 msgid "Flower Framework Documentation" @@ -6531,9 +6519,8 @@ msgstr "Flower 框架文档" msgid "" "Welcome to Flower's documentation. `Flower `_ is a " "friendly federated learning framework." -msgstr "" -"欢迎访问 Flower 文档。`Flower `_ 是一个友好的联合学习框" -"架。" +msgstr "欢迎访问 Flower 文档。`Flower `_ " +"是一个友好的联邦学习框架。" #: ../../source/index.rst:11 msgid "Join the Flower Community" @@ -6563,9 +6550,9 @@ msgid "" "setting. One of Flower's design goals was to make this simple. Read on to " "learn more." msgstr "" -"该用户指南面向希望使用 Flower 将现有机器学习工作负载引入联合环境的研究人员和" -"开发人员。Flower 的设计目标之一就是让这一切变得简单。请继续阅读,了解更多信" -"息。" +"该用户指南面向希望使用 Flower " +"将现有机器学习工作负载引入联邦环境的研究人员和开发人员。Flower " +"的设计目标之一就是让这一切变得简单。请继续阅读,了解更多信息。" #: ../../source/index.rst:30 msgid "Tutorials" @@ -6575,10 +6562,9 @@ msgstr "教程" msgid "" "A learning-oriented series of federated learning tutorials, the best place " "to start." -msgstr "以学习为导向的联合学习教程系列,最好的起点。" +msgstr "以学习为导向的联邦学习教程系列,最好的起点。" #: ../../source/index.rst:62 -#, fuzzy msgid "" "QUICKSTART TUTORIALS: :doc:`PyTorch ` | :doc:" "`TensorFlow ` | :doc:`🤗 Transformers " @@ -6590,10 +6576,10 @@ msgid "" "xgboost>` | :doc:`Android ` | :doc:`iOS " "`" msgstr "" -"QUICKSTART TUTORIALS: :doc:`PyTorch ` | :doc:" -"`TensorFlow ` | :doc:`🤗 Transformers " -"` | :doc:`JAX ` | :" -"doc:`Pandas ` | :doc:`fastai ` | :doc:`" +"TensorFlow ` | :doc:`🤗 Transformers " +"` | :doc:`JAX ` | " +":doc:`Pandas ` | :doc:`fastai ` | :doc:`PyTorch Lightning ` | :doc:`MXNet ` | :doc:`scikit-learn " "` | :doc:`XGBoost " msgstr "" +"`Adam Narozniak`, `Anass Anhari`, `Charles Beauville`, `Dana-Farber`, `" +"Daniel J. Beutel`, `Daniel Nata Nugraha`, `Edoardo Gabrielli`, `Gustavo " +"Bertoli`, `Heng Pan`, `Javier`, `Mahdi`, `Steven Hé (Sīchàng)`, `Taner Topal`" +", `achiverram28`, `danielnugraha`, `eunchung`, `ruthgal` " #: ../../source/ref-changelog.md:85 msgid "" @@ -8538,7 +8525,7 @@ msgid "" msgstr "" "新的模拟引擎从头开始重新编写,但仍完全向后兼容。它的稳定性和内存处理能力大大" "提高,尤其是在使用 GPU 时。仿真可透明地适应不同的设置,以在仅 CPU、CPU+GPU、" -"多 GPU 或多节点多 GPU 环境中扩展仿真。" +"多 GPU 或多节点多 GPU 环境中扩展模拟。" #: ../../source/ref-changelog.md:89 msgid "" @@ -8550,12 +8537,12 @@ msgid "" "(https://www.youtube.com/watch?" "v=cRebUIGB5RU&list=PLNG4feLHqCWlnj8a_E1A_n5zr2-8pafTB)." msgstr "" -"综合文档包括新的[如何运行仿真](https://flower.dev/docs/framework/how-to-run-" -"simulations.html) 指南、新的[simulation-pytorch](https://flower.dev/docs/" -"examples/simulation-pytorch.html) 和[simulation-tensorflow](https://flower." -"dev/docs/examples/simulation-tensorflow.html) 笔记本,以及新的[YouTube 教程系" -"列](https://www.youtube.com/watch?" -"v=cRebUIGB5RU&list=PLNG4feLHqCWlnj8a_E1A_n5zr2-8pafTB)。" +"综合文档包括新的[how-to run simulations](https://flower.dev/docs/framework/" +"how-to-run-simulations.html) guide, new [simulation-pytorch](https://flower." +"dev/docs/examples/simulation-pytorch.html) and [simulation-" +"tensorflow](https://flower.dev/docs/examples/simulation-tensorflow.html) " +"notebooks, and a new [YouTube tutorial series](https://www.youtube.com/" +"watch?v=cRebUIGB5RU&list=PLNG4feLHqCWlnj8a_E1A_n5zr2-8pafTB)。" #: ../../source/ref-changelog.md:91 msgid "" @@ -8579,6 +8566,25 @@ msgid "" "flower/pull/2231), [#2243](https://github.com/adap/flower/pull/2243), [#2227]" "(https://github.com/adap/flower/pull/2227))" msgstr "" +"**重构 Flower 文档** ([#1824](https://github.com/adap/flower/pull/1824), " +"[#1865](https://github.com/adap/flower/pull/1865), [#1884](https://github." +"com/adap/flower/pull/1884), [#1887](https://github.com/adap/flower/pull/1887)" +", [#1919](https://github.com/adap/flower/pull/1919), [#1922](https://github." +"com/adap/flower/pull/1922), [#1920](https://github.com/adap/flower/pull/1920)" +", [#1923](https://github.com/adap/flower/pull/1923), [#1924](https://github." +"com/adap/flower/pull/1924), [#1962](https://github.com/adap/flower/pull/1962)" +", [#2006](https://github.com/adap/flower/pull/2006), [#2133](https://github." +"com/adap/flower/pull/2133), [#2203](https://github.com/adap/flower/pull/2203)" +", [#2215](https://github.com/adap/flower/pull/2215), [#2122](https://github." +"com/adap/flower/pull/2122), [#2223](https://github.com/adap/flower/pull/2223)" +", [#2219](https://github.com/adap/flower/pull/2219), [#2232](https://github." +"com/adap/flower/pull/2232), [#2233](https://github.com/adap/flower/pull/2233)" +", [#2234](https://github.com/adap/flower/pull/2234), [#2235](https://github." +"com/adap/flower/pull/2235), [#2237](https://github.com/adap/flower/pull/2237)" +", [#2238](https://github.com/adap/flower/pull/2238), [#2242](https://github." +"com/adap/flower/pull/2242), [#2231](https://github.com/adap/flower/pull/2231)" +", [#2243](https://github.com/adap/flower/pull/2243), [#2227](https://github." +"com/adap/flower/pull/2227))" #: ../../source/ref-changelog.md:93 msgid "" @@ -8596,6 +8602,8 @@ msgid "" "**Introduce Flower Swift SDK** ([#1858](https://github.com/adap/flower/" "pull/1858), [#1897](https://github.com/adap/flower/pull/1897))" msgstr "" +"**介绍 Flower Swift SDK** ([#1858](https://github.com/adap/flower/pull/1858)" +", [#1897](https://github.com/adap/flower/pull/1897))" #: ../../source/ref-changelog.md:97 msgid "" @@ -8639,12 +8647,24 @@ msgid "" "(https://github.com/adap/flower/pull/2137), [#2165](https://github.com/adap/" "flower/pull/2165))" msgstr "" +"*介绍新的端到端测试** ([#1842](https://github.com/adap/flower/pull/1842), " +"[#2071](https://github.com/adap/flower/pull/2071), [#2072](https://github." +"com/adap/flower/pull/2072), [#2068](https://github.com/adap/flower/pull/2068)" +", [#2067](https://github.com/adap/flower/pull/2067), [#2069](https://github." +"com/adap/flower/pull/2069), [#2073](https://github.com/adap/flower/pull/2073)" +", [#2070](https://github.com/adap/flower/pull/2070), [#2074](https://github." +"com/adap/flower/pull/2074), [#2082](https://github.com/adap/flower/pull/2082)" +", [#2084](https://github.com/adap/flower/pull/2084), [#2093](https://github." +"com/adap/flower/pull/2093), [#2109](https://github.com/adap/flower/pull/2109)" +", [#2095](https://github.com/adap/flower/pull/2095), [#2140](https://github." +"com/adap/flower/pull/2140), [#2137](https://github.com/adap/flower/pull/2137)" +", [#2165](https://github.com/adap/flower/pull/2165))" #: ../../source/ref-changelog.md:105 msgid "" "A new testing infrastructure ensures that new changes stay compatible with " "existing framework integrations or strategies." -msgstr "新的测试基础设施可确保新的变更与现有的框架集成或策略保持兼容。" +msgstr "新的测试设施可确保新的变更与现有的框架集成或策略保持兼容。" #: ../../source/ref-changelog.md:107 msgid "**Deprecate Python 3.7**" @@ -8655,15 +8675,15 @@ msgid "" "Since Python 3.7 reached its end of life (EOL) on 2023-06-27, support for " "Python 3.7 is now deprecated and will be removed in an upcoming release." msgstr "" -"由于 Python 3.7 已于 2023-06-27 结束生命 (EOL),对 Python 3.7 的支持现已废" -"弃,并将在即将发布的版本中移除。" +"由于 Python 3.7 已于 2023-06-27 弃用 (EOL),对 Python 3.7 " +"的支持现已废弃,并将在即将发布的版本中移除。" #: ../../source/ref-changelog.md:111 msgid "" "**Add new** `FedTrimmedAvg` **strategy** ([#1769](https://github.com/adap/" "flower/pull/1769), [#1853](https://github.com/adap/flower/pull/1853))" msgstr "" -"**添加新**`FedTrimmedAvg`**策略**([#1769](https://github.com/adap/flower/" +"**添加新的**`FedTrimmedAvg`**策略**([#1769](https://github.com/adap/flower/" "pull/1769), [#1853](https://github.com/adap/flower/pull/1853)" #: ../../source/ref-changelog.md:113 @@ -8697,8 +8717,8 @@ msgid "" "**Add parameter aggregation to** `mt-pytorch` **code example** ([#1785]" "(https://github.com/adap/flower/pull/1785))" msgstr "" -"**为** `mt-pytorch` **代码示例**添加参数聚合 ([#1785](https://github.com/" -"adap/flower/pull/1785))" +"为 `mt-pytorch` **代码示例**添加参数聚合 ([#1785](https://github.com/adap/" +"flower/pull/1785))" #: ../../source/ref-changelog.md:121 msgid "" @@ -8707,7 +8727,7 @@ msgid "" "demonstrate both the low-level way and the high-level way of building server-" "side logic." msgstr "" -"mt-pytorch \"示例展示了如何在编写驱动程序脚本时汇总参数。附带的 `driver.py` " +"`mt-pytorch`示例展示了如何在编写驱动程序脚本时聚合参数。附带的 `driver.py` " "和 `server.py` 已经进行了调整,以演示构建服务器端逻辑的低级方法和高级方法。" #: ../../source/ref-changelog.md:123 @@ -8794,18 +8814,18 @@ msgid "" "option set to 0 by default. This prevents the clients from sending keepalive " "pings when there is no outstanding stream." msgstr "" -"现在我们启动一个 gRPC 服务器,并将 `grpc.keepalive_permit_without_calls` 选项" -"默认设置为 0。这将防止客户端在没有未处理数据流时发送 keepalive ping。" +"现在我们启动一个 gRPC 服务器,并将 `grpc.keepalive_permit_without_calls` " +"选项默认设置为 0。这将防止客户端在没有未处理数据流时发送 keepalive pings。" #: ../../source/ref-changelog.md:143 msgid "" "**Improve example notebooks** ([#2005](https://github.com/adap/flower/" "pull/2005))" -msgstr "**改进示例笔记本** ([#2005](https://github.com/adap/flower/pull/2005))" +msgstr "**改进示例笔记** ([#2005](https://github.com/adap/flower/pull/2005))" #: ../../source/ref-changelog.md:145 msgid "There's a new 30min Federated Learning PyTorch tutorial!" -msgstr "有一个新的 30 分钟 Federated Learning PyTorch 教程!" +msgstr "有一个新的 30 分钟的联邦学习 PyTorch 教程!" #: ../../source/ref-changelog.md:147 msgid "" @@ -8818,14 +8838,14 @@ msgid "" "(https://github.com/adap/flower/pull/2174), [#2225](https://github.com/adap/" "flower/pull/2225), [#2183](https://github.com/adap/flower/pull/2183))" msgstr "" -"**更新示例** ([#1772](https://github.com/adap/flower/pull/1772), [#1873]" -"(https://github.com/adap/flower/pull/1873), [#1981](https://github.com/adap/" -"flower/pull/1981), [#1988](https://github.com/adap/flower/pull/1988), [#1984]" -"(https://github.com/adap/flower/pull/1984), [#1982](https://github.com/adap/" -"flower/pull/1982), [#2112](https://github.com/adap/flower/pull/2112), [#2144]" -"(https://github.com/adap/flower/pull/2144), [#2174](https://github.com/adap/" -"flower/pull/2174), [#2225](https://github.com/adap/flower/pull/2225), [#2183]" -"(https://github.com/adap/flower/pull/2183))" +"**更新Example** ([#1772](https://github.com/adap/flower/pull/1772), " +"[#1873](https://github.com/adap/flower/pull/1873), [#1981](https://github." +"com/adap/flower/pull/1981), [#1988](https://github.com/adap/flower/pull/1988)" +", [#1984](https://github.com/adap/flower/pull/1984), [#1982](https://github." +"com/adap/flower/pull/1982), [#2112](https://github.com/adap/flower/pull/2112)" +", [#2144](https://github.com/adap/flower/pull/2144), [#2174](https://github." +"com/adap/flower/pull/2174), [#2225](https://github.com/adap/flower/pull/2225)" +", [#2183](https://github.com/adap/flower/pull/2183))" #: ../../source/ref-changelog.md:149 msgid "" @@ -8836,8 +8856,9 @@ msgid "" "addition to `pyproject.toml`)." msgstr "" "许多示例都进行了重大更新,包括简化了 advanced-tensorflow 和 advanced-pytorch " -"示例,改进了 TensorFlow 示例的 macOS 兼容性,以及仿真代码示例。一项重大升级是" -"所有代码示例现在都有了 \"requirements.txt\"(除 \"pyproject.toml \"外)。" +"示例,改进了 TensorFlow 示例的 macOS 兼容性,以及模拟代码示例。" +"一项重大升级是所有代码示例现在都有了 \"requirements.txt\"(除 \"pyproject." +"toml \"外)。" #: ../../source/ref-changelog.md:151 msgid "" @@ -8847,11 +8868,11 @@ msgid "" "pull/1837), [#1477](https://github.com/adap/flower/pull/1477), [#2171]" "(https://github.com/adap/flower/pull/2171))" msgstr "" -"**一般改进**([#1872](https://github.com/adap/flower/pull/1872), [#1866]" -"(https://github.com/adap/flower/pull/1866), [#1884](https://github.com/adap/" -"flower/pull/1884), [#1837](https://github.com/adap/flower/pull/1837), [#1477]" -"(https://github.com/adap/flower/pull/1477), [#2171](https://github.com/adap/" -"flower/pull/2171))" +"**普通改进**([#1872](https://github.com/adap/flower/pull/1872), " +"[#1866](https://github.com/adap/flower/pull/1866), [#1884](https://github." +"com/adap/flower/pull/1884), [#1837](https://github.com/adap/flower/pull/1837)" +", [#1477](https://github.com/adap/flower/pull/1477), [#2171](https://github." +"com/adap/flower/pull/2171))" #: ../../source/ref-changelog.md:157 ../../source/ref-changelog.md:221 #: ../../source/ref-changelog.md:279 ../../source/ref-changelog.md:348 @@ -8861,7 +8882,7 @@ msgstr "无" #: ../../source/ref-changelog.md:159 msgid "v1.4.0 (2023-04-21)" -msgstr "" +msgstr "v1.4.0 (2023-04-21)" #: ../../source/ref-changelog.md:165 msgid "" @@ -8872,6 +8893,12 @@ msgid "" "`Nikolaos Episkopos`, `Ragy`, `Saurav Maheshkar`, `Semo Yang`, `Steve " "Laskaridis`, `Steven Hé (Sīchàng)`, `Taner Topal`" msgstr "" +"`Adam Narozniak`, `Alexander Viala Bellander`, `Charles Beauville`, `" +"Chenyang Ma (Danny)`, `Daniel J. Beutel`, `Edoardo`, `Gautam Jajoo`, `Iacob-" +"Alexandru-Andrei`, `JDRanpariya`, `Jean Charle Yaacoub`, `Kunal Sarkhel`, `" +"L. Jiang`, `Lennart Behme`, `Max Kapsecker`, `Michał`, `Nic Lane`, `Nikolaos " +"Episkopos`, `Ragy`, `Saurav Maheshkar`, `Semo Yang`, `Steve Laskaridis`, `" +"Steven Hé (Sīchàng)`, `Taner Topal`" #: ../../source/ref-changelog.md:169 msgid "" @@ -8920,11 +8947,11 @@ msgid "" "example](https://github.com/adap/flower/tree/main/examples/ios) has also " "been updated!" msgstr "" -"对于想要在 iOS 移动设备上实施联合学习的人来说,这是一次重大更新。现在,我们" -"在 [src/swift/flwr](https://github.com/adap/flower/tree/main/src/swift/flwr) " -"下提供了一个迅捷的 iOS SDK,这将大大方便应用程序的创建过程。为了展示其使用情" -"况,我们还更新了 [iOS 示例](https://github.com/adap/flower/tree/main/" -"examples/ios)!" +"对于想要在 iOS 移动设备上实施联邦学习的人来说,这是一次重大更新。现在," +"我们在 [src/swift/flwr](https://github.com/adap/flower/tree/main/src/swift/" +"flwr) 下提供了一个迅捷的 iOS " +"SDK,这将大大方便应用程序的创建过程。为了展示其使用情况,我们还更新了 [iOS " +"示例](https://github.com/adap/flower/tree/main/examples/ios)!" #: ../../source/ref-changelog.md:177 msgid "" @@ -8932,7 +8959,7 @@ msgid "" "github.com/adap/flower/pull/1657), [#1721](https://github.com/adap/flower/" "pull/1721))" msgstr "" -"**介绍新的 \"什么是联邦学习?\"教程**([#1657](https://github.com/adap/" +"**引入新的 \"什么是联邦学习?\"教程**([#1657](https://github.com/adap/" "flower/pull/1657), [#1721](https://github.com/adap/flower/pull/1721)" #: ../../source/ref-changelog.md:179 @@ -8944,8 +8971,9 @@ msgid "" "interested in Federated Learning!" msgstr "" "我们的文档中新增了一个[入门级教程](https://flower.dev/docs/framework/" -"tutorial-what-is-federated-learning.html),解释了联合学习的基础知识。它让任何" -"不熟悉联合学习的人都能开始 Flower 之旅。请转发给对联合学习感兴趣的人!" +"tutorial-what-is-federated-learning.html),解释了联邦学习的基础知识。" +"它让任何不熟悉联邦学习的人都能开始 Flower " +"之旅。请转发给对联邦学习感兴趣的人!" #: ../../source/ref-changelog.md:181 msgid "" @@ -8954,10 +8982,10 @@ msgid "" "[#1681](https://github.com/adap/flower/pull/1681), [#1679](https://github." "com/adap/flower/pull/1679))" msgstr "" -"**引入新的 Flower 基准: FedProx MNIST** ([#1513](https://github.com/adap/" -"flower/pull/1513), [#1680](https://github.com/adap/flower/pull/1680), [#1681]" -"(https://github.com/adap/flower/pull/1681), [#1679](https://github.com/adap/" -"flower/pull/1679)" +"**引入新的 Flower Baseline: FedProx MNIST** ([#1513](https://github.com/" +"adap/flower/pull/1513), [#1680](https://github.com/adap/flower/pull/1680), " +"[#1681](https://github.com/adap/flower/pull/1681), [#1679](https://github." +"com/adap/flower/pull/1679)" #: ../../source/ref-changelog.md:183 msgid "" @@ -8966,17 +8994,17 @@ msgid "" "abs/1812.06127). It uses the `FedProx` strategy, which aims at making " "convergence more robust in heterogenous settings." msgstr "" -"这条新基准复制了论文[Federated Optimization in Heterogeneous Networks (Li et " -"al., 2018)](https://arxiv.org/abs/1812.06127)中的 MNIST+CNN 任务。它使用 " -"\"FedProx \"策略,旨在使收敛在异构环境中更加稳健。" +"这条新Baseline复现了论文[Federated Optimization in Heterogeneous Networks (" +"Li et al., 2018)](https://arxiv.org/abs/1812.06127)中的 MNIST+CNN 任务。" +"它使用 \"FedProx \"策略,旨在使收敛在异构环境中更加稳健。" #: ../../source/ref-changelog.md:185 msgid "" "**Introduce new Flower Baseline: FedAvg FEMNIST** ([#1655](https://github." "com/adap/flower/pull/1655))" msgstr "" -"**引入新的 Flower 基准: FedAvg FEMNIST** ([#1655](https://github.com/adap/" -"flower/pull/1655))" +"**引入新的 Flower Baseline: FedAvg FEMNIST** ([#1655](https://github.com/" +"adap/flower/pull/1655))" #: ../../source/ref-changelog.md:187 msgid "" @@ -8985,8 +9013,9 @@ msgid "" "for Federated Settings (Caldas et al., 2018)](https://arxiv.org/" "abs/1812.01097)." msgstr "" -"这一新基准复制了论文[LEAF:联合设置的基准(Caldas 等人,2018 年)](https://" -"arxiv.org/abs/1812.01097)中评估 FedAvg 算法在 FEMNIST 数据集上性能的实验。" +"这一新Baseline复现了论文[LEAF: A Benchmark for Federated Settings(Caldas " +"等人,2018 年)](https://arxiv.org/abs/1812.01097)中评估 FedAvg 算法在 " +"FEMNIST 数据集上性能的实验。" #: ../../source/ref-changelog.md:189 msgid "" @@ -9056,8 +9085,8 @@ msgid "" "**Fix spilling issues related to Ray during simulations** ([#1698](https://" "github.com/adap/flower/pull/1698))" msgstr "" -"**修复模拟过程中与雷有关的溢出问题** ([#1698](https://github.com/adap/flower/" -"pull/1698))" +"**修复模拟过程中与Ray有关的溢出问题** ([#1698](https://github.com/adap/" +"flower/pull/1698))" #: ../../source/ref-changelog.md:201 msgid "" @@ -9072,8 +9101,8 @@ msgid "" "**Add new example using** `TabNet` **and Flower** ([#1725](https://github." "com/adap/flower/pull/1725))" msgstr "" -"** 添加使用** `TabNet` **和 Flower 的新示例** ([#1725](https://github.com/" -"adap/flower/pull/1725))" +"** 添加使用** `TabNet` ** 的新示例** ([#1725](https://github.com/adap/flower/" +"pull/1725))" #: ../../source/ref-changelog.md:205 msgid "" @@ -9082,9 +9111,9 @@ msgid "" "[https://github.com/adap/flower/tree/main/examples/tabnet](https://github." "com/adap/flower/tree/main/examples/quickstart_tabnet)." msgstr "" -"TabNet 是一个强大而灵活的框架,用于在表格数据上训练机器学习模型。我们现在有一" -"个使用 Flower 的联合示例:[https://github.com/adap/flower/tree/main/examples/" -"tabnet](https://github.com/adap/flower/tree/main/examples/" +"TabNet 是一个强大而灵活的框架,用于在表格数据上训练机器学习模型。" +"我们现在有一个使用 Flower 的联邦示例:[https://github.com/adap/flower/tree/" +"main/examples/tabnet](https://github.com/adap/flower/tree/main/examples/" "quickstart_tabnet)。" #: ../../source/ref-changelog.md:207 @@ -9114,8 +9143,8 @@ msgid "" "but previous releases did not save the results in the `History` object. This " "is now the case!" msgstr "" -"ffit_metrics_aggregation_fn \"可用于汇总训练指标,但以前的版本不会将结果保存" -"在 \"History \"对象中。现在情况就是这样!" +"`fit_metrics_aggregation_fn`可用于汇总训练指标,但以前的版本不会将结果保存在 " +"\"History \"对象中。现在可以了!" #: ../../source/ref-changelog.md:215 msgid "" @@ -9154,43 +9183,44 @@ msgid "" "(https://github.com/adap/flower/pull/1804), [#1805](https://github.com/adap/" "flower/pull/1805))" msgstr "" -"**一般改进** ([#1659](https://github.com/adap/flower/pull/1659), [#1646]" -"(https://github.com/adap/flower/pull/1646), [#1647](https://github.com/adap/" -"flower/pull/1647), [#1471](https://github.com/adap/flower/pull/1471), [#1648]" -"(https://github.com/adap/flower/pull/1648), [#1651](https://github.com/adap/" -"flower/pull/1651), [#1652](https://github.com/adap/flower/pull/1652), [#1653]" -"(https://github.com/adap/flower/pull/1653), [#1659](https://github.com/adap/" -"flower/pull/1659), [#1665](https://github.com/adap/flower/pull/1665), [#1670]" -"(https://github.com/adap/flower/pull/1670), [#1672](https://github.com/adap/" -"flower/pull/1672), [#1677](https://github.com/adap/flower/pull/1677), [#1684]" -"(https://github.com/adap/flower/pull/1684), [#1683](https://github.com/adap/" -"flower/pull/1683), [#1686](https://github.com/adap/flower/pull/1686), [#1682]" -"(https://github.com/adap/flower/pull/1682), [#1685](https://github.com/adap/" -"flower/pull/1685), [#1692](https://github.com/adap/flower/pull/1692), [#1705]" -"(https://github.com/adap/flower/pull/1705), [#1708](https://github.com/adap/" -"flower/pull/1708), [#1711](https://github.com/adap/flower/pull/1711), [#1713]" -"(https://github.com/adap/flower/pull/1713), [#1714](https://github.com/adap/" -"flower/pull/1714), [#1718](https://github.com/adap/flower/pull/1718), [#1716]" -"(https://github.com/adap/flower/pull/1716), [#1723](https://github.com/adap/" -"flower/pull/1723), [#1735](https://github.com/adap/flower/pull/1735), [#1678]" -"(https://github.com/adap/flower/pull/1678), [#1750](https://github.com/adap/" -"flower/pull/1750), [#1753](https://github.com/adap/flower/pull/1753), [#1736]" -"(https://github.com/adap/flower/pull/1736), [#1766](https://github.com/adap/" -"flower/pull/1766), [#1760](https://github.com/adap/flower/pull/1760), [#1775]" -"(https://github.com/adap/flower/pull/1775), [#1776](https://github.com/adap/" -"flower/pull/1776), [#1777](https://github.com/adap/flower/pull/1777), [#1779]" -"(https://github.com/adap/flower/pull/1779), [#1784](https://github.com/adap/" -"flower/pull/1784), [#1773](https://github.com/adap/flower/pull/1773), [#1755]" -"(https://github.com/adap/flower/pull/1755), [#1789](https://github.com/adap/" -"flower/pull/1789), [#1788](https://github.com/adap/flower/pull/1788), [#1798]" -"(https://github.com/adap/flower/pull/1798), [#1799](https://github.com/adap/" -"flower/pull/1799), [#1739](https://github.com/adap/flower/pull/1739), [#1800]" -"(https://github.com/adap/flower/pull/1800), [#1804](https://github.com/adap/" -"flower/pull/1804), [#1805](https://github.com/adap/flower/pull/1805))" +"**普通改进** ([#1659](https://github.com/adap/flower/pull/1659), " +"[#1646](https://github.com/adap/flower/pull/1646), [#1647](https://github." +"com/adap/flower/pull/1647), [#1471](https://github.com/adap/flower/pull/1471)" +", [#1648](https://github.com/adap/flower/pull/1648), [#1651](https://github." +"com/adap/flower/pull/1651), [#1652](https://github.com/adap/flower/pull/1652)" +", [#1653](https://github.com/adap/flower/pull/1653), [#1659](https://github." +"com/adap/flower/pull/1659), [#1665](https://github.com/adap/flower/pull/1665)" +", [#1670](https://github.com/adap/flower/pull/1670), [#1672](https://github." +"com/adap/flower/pull/1672), [#1677](https://github.com/adap/flower/pull/1677)" +", [#1684](https://github.com/adap/flower/pull/1684), [#1683](https://github." +"com/adap/flower/pull/1683), [#1686](https://github.com/adap/flower/pull/1686)" +", [#1682](https://github.com/adap/flower/pull/1682), [#1685](https://github." +"com/adap/flower/pull/1685), [#1692](https://github.com/adap/flower/pull/1692)" +", [#1705](https://github.com/adap/flower/pull/1705), [#1708](https://github." +"com/adap/flower/pull/1708), [#1711](https://github.com/adap/flower/pull/1711)" +", [#1713](https://github.com/adap/flower/pull/1713), [#1714](https://github." +"com/adap/flower/pull/1714), [#1718](https://github.com/adap/flower/pull/1718)" +", [#1716](https://github.com/adap/flower/pull/1716), [#1723](https://github." +"com/adap/flower/pull/1723), [#1735](https://github.com/adap/flower/pull/1735)" +", [#1678](https://github.com/adap/flower/pull/1678), [#1750](https://github." +"com/adap/flower/pull/1750), [#1753](https://github.com/adap/flower/pull/1753)" +", [#1736](https://github.com/adap/flower/pull/1736), [#1766](https://github." +"com/adap/flower/pull/1766), [#1760](https://github.com/adap/flower/pull/1760)" +", [#1775](https://github.com/adap/flower/pull/1775), [#1776](https://github." +"com/adap/flower/pull/1776), [#1777](https://github.com/adap/flower/pull/1777)" +", [#1779](https://github.com/adap/flower/pull/1779), [#1784](https://github." +"com/adap/flower/pull/1784), [#1773](https://github.com/adap/flower/pull/1773)" +", [#1755](https://github.com/adap/flower/pull/1755), [#1789](https://github." +"com/adap/flower/pull/1789), [#1788](https://github.com/adap/flower/pull/1788)" +", [#1798](https://github.com/adap/flower/pull/1798), [#1799](https://github." +"com/adap/flower/pull/1799), [#1739](https://github.com/adap/flower/pull/1739)" +", [#1800](https://github.com/adap/flower/pull/1800), [#1804](https://github." +"com/adap/flower/pull/1804), [#1805](https://github.com/adap/flower/pull/" +"1805))" #: ../../source/ref-changelog.md:223 msgid "v1.3.0 (2023-02-06)" -msgstr "" +msgstr "v1.3.0 (2023-02-06)" #: ../../source/ref-changelog.md:229 msgid "" @@ -9205,8 +9235,8 @@ msgid "" "**Add support for** `workload_id` **and** `group_id` **in Driver API** " "([#1595](https://github.com/adap/flower/pull/1595))" msgstr "" -"**在驱动程序应用程序接口**中添加对** `workload_id` **和** `group_id` **的支" -"持 ([#1595](https://github.com/adap/flower/pull/1595))" +"**在驱动程序应用程序接口中添加对** `workload_id` **和** `group_id` **的支持**" +" ([#1595](https://github.com/adap/flower/pull/1595))" #: ../../source/ref-changelog.md:235 msgid "" @@ -9216,7 +9246,7 @@ msgid "" "round. Both the `workload_id` and `group_id` enable client nodes to decide " "whether they want to handle a task or not." msgstr "" -"驱动程序 API(试验性)现在支持 \"workload_id\",可用于识别任务所属的工作量。" +"驱动程序 API(试验性)现在支持 `workload_id`,可用于识别任务所属的工作量。" "它还支持新的 `group_id`,例如,可用于指示当前的训练轮次。通过 `workload_id` " "和 `group_id` 客户端节点可以决定是否要处理某个任务。" @@ -9225,8 +9255,8 @@ msgid "" "**Make Driver API and Fleet API address configurable** ([#1637](https://" "github.com/adap/flower/pull/1637))" msgstr "" -"**使驱动程序应用程序接口和车队应用程序接口地址可配置**([#1637](https://" -"github.com/adap/flower/pull/1637))" +"**使Driver API 和Fleet API地址可配置**([#1637](https://github.com/adap/" +"flower/pull/1637))" #: ../../source/ref-changelog.md:239 msgid "" @@ -9243,6 +9273,8 @@ msgid "" "`flower-server --driver-api-address \"0.0.0.0:8081\" --fleet-api-address " "\"0.0.0.0:8086\"`" msgstr "" +"`flower-server --driver-api-address \"0.0.0.0:8081\" --fleet-api-address \"0." +"0.0.0:8086\"`" #: ../../source/ref-changelog.md:243 msgid "Both IPv4 and IPv6 addresses are supported." @@ -9253,7 +9285,7 @@ msgid "" "**Add new example of Federated Learning using fastai and Flower** ([#1598]" "(https://github.com/adap/flower/pull/1598))" msgstr "" -"** 添加使用 fastai 和 Flower 进行联合学习的新示例** ([#1598](https://github." +"** 添加使用 fastai 和 Flower 进行联邦学习的新示例** ([#1598](https://github." "com/adap/flower/pull/1598))" #: ../../source/ref-changelog.md:247 @@ -9264,8 +9296,9 @@ msgid "" "quickstart_fastai)." msgstr "" "一个新的代码示例(`quickstart_fastai`)演示了使用 [fastai](https://www.fast." -"ai/) 和 Flower 的联合学习。您可以在这里找到它: [quickstart_fastai](https://" -"github.com/adap/flower/tree/main/examples/quickstart_fastai)。" +"ai/) 和 Flower 的联邦学习。您可以在这里找到它: " +"[quickstart_fastai](https://github.com/adap/flower/tree/main/examples/" +"quickstart_fastai)。" #: ../../source/ref-changelog.md:249 msgid "" @@ -9288,9 +9321,8 @@ msgstr "" msgid "" "**Add new `FedProx` strategy** ([#1619](https://github.com/adap/flower/" "pull/1619))" -msgstr "" -"**添加新的 \"FedProx \"策略** ([#1619](https://github.com/adap/flower/" -"pull/1619))" +msgstr "**添加新的`FedProx`策略** ([#1619](https://github.com/adap/flower/pull/" +"1619))" #: ../../source/ref-changelog.md:255 msgid "" @@ -9303,9 +9335,10 @@ msgid "" msgstr "" "该[策略](https://github.com/adap/flower/blob/main/src/py/flwr/server/" "strategy/fedprox.py)与[`FedAvg`](https://github.com/adap/flower/blob/main/" -"src/py/flwr/server/strategy/fedavg.py)几乎相同,但可以帮助用户复制本文[论文]" -"(https://arxiv.org/abs/1812.06127)中的描述。它的本质是添加一个名为 " -"\"proximal_mu \"的参数,使局部模型与全局模型正则化。" +"src/py/flwr/server/strategy/fedavg." +"py)几乎相同,但可以帮助用户复现本[论文](https://arxiv.org/abs/1812." +"06127)中的描述。它的本质是添加一个名为 " +"`proximal_mu`的参数,使局部模型与全局模型正则化。" #: ../../source/ref-changelog.md:257 msgid "" @@ -9383,29 +9416,29 @@ msgid "" "flower/pull/1574), [#1572](https://github.com/adap/flower/pull/1572), [#1586]" "(https://github.com/adap/flower/pull/1586))" msgstr "" -"**一般改进** ([#1638](https://github.com/adap/flower/pull/1638), [#1634]" -"(https://github.com/adap/flower/pull/1634), [#1636](https://github.com/adap/" -"flower/pull/1636), [#1635](https://github.com/adap/flower/pull/1635), [#1633]" -"(https://github.com/adap/flower/pull/1633), [#1632](https://github.com/adap/" -"flower/pull/1632), [#1631](https://github.com/adap/flower/pull/1631), [#1630]" -"(https://github.com/adap/flower/pull/1630), [#1627](https://github. com/adap/" -"flower/pull/1627), [#1593](https://github.com/adap/flower/pull/1593), [#1616]" -"(https://github.com/adap/flower/pull/1616), [#1615](https://github.com/adap/" -"flower/pull/1615), [#1607](https://github.com/adap/flower/pull/1607), [#1609]" -"(https://github.com/adap/flower/pull/1609), [#1608](https://github.com/adap/" -"flower/pull/1608), [#1603](https://github.com/adap/flower/pull/1603), [#1590]" -"(https://github. com/adap/flower/pull/1590), [#1580](https://github.com/adap/" -"flower/pull/1580), [#1599](https://github.com/adap/flower/pull/1599), [#1600]" -"(https://github.com/adap/flower/pull/1600), [#1601](https://github.com/adap/" -"flower/pull/1601), [#1597](https://github.com/adap/flower/pull/1597), [#1595]" -"(https://github.com/adap/flower/pull/1595), [#1591](https://github.com/adap/" -"flower/pull/1591), [#1588](https://github. com/adap/flower/pull/1588), " -"[#1589](https://github.com/adap/flower/pull/1589), [#1587](https://github." -"com/adap/flower/pull/1587), [#1573](https://github.com/adap/flower/" -"pull/1573), [#1581](https://github.com/adap/flower/pull/1581), [#1578]" -"(https://github.com/adap/flower/pull/1578), [#1574](https://github.com/adap/" -"flower/pull/1574), [#1572](https://github.com/adap/flower/pull/1572), [#1586]" -"(https://github.com/adap/flower/pull/1586))" +"**普通改进** ([#1638](https://github.com/adap/flower/pull/1638), " +"[#1634](https://github.com/adap/flower/pull/1634), [#1636](https://github." +"com/adap/flower/pull/1636), [#1635](https://github.com/adap/flower/pull/1635)" +", [#1633](https://github.com/adap/flower/pull/1633), [#1632](https://github." +"com/adap/flower/pull/1632), [#1631](https://github.com/adap/flower/pull/1631)" +", [#1630](https://github.com/adap/flower/pull/1630), [#1627](https://github. " +"com/adap/flower/pull/1627), [#1593](https://github.com/adap/flower/pull/1593)" +", [#1616](https://github.com/adap/flower/pull/1616), [#1615](https://github." +"com/adap/flower/pull/1615), [#1607](https://github.com/adap/flower/pull/1607)" +", [#1609](https://github.com/adap/flower/pull/1609), [#1608](https://github." +"com/adap/flower/pull/1608), [#1603](https://github.com/adap/flower/pull/1603)" +", [#1590](https://github. com/adap/flower/pull/1590), [#1580](https://github." +"com/adap/flower/pull/1580), [#1599](https://github.com/adap/flower/pull/1599)" +", [#1600](https://github.com/adap/flower/pull/1600), [#1601](https://github." +"com/adap/flower/pull/1601), [#1597](https://github.com/adap/flower/pull/1597)" +", [#1595](https://github.com/adap/flower/pull/1595), [#1591](https://github." +"com/adap/flower/pull/1591), [#1588](https://github. com/adap/flower/pull/" +"1588), [#1589](https://github.com/adap/flower/pull/1589), " +"[#1587](https://github.com/adap/flower/pull/1587), [#1573](https://github." +"com/adap/flower/pull/1573), [#1581](https://github.com/adap/flower/pull/1581)" +", [#1578](https://github.com/adap/flower/pull/1578), [#1574](https://github." +"com/adap/flower/pull/1574), [#1572](https://github.com/adap/flower/pull/1572)" +", [#1586](https://github.com/adap/flower/pull/1586))" #: ../../source/ref-changelog.md:273 msgid "" @@ -9448,7 +9481,7 @@ msgid "" "**Introduce new Flower Baseline: FedAvg MNIST** ([#1497](https://github.com/" "adap/flower/pull/1497), [#1552](https://github.com/adap/flower/pull/1552))" msgstr "" -"**引入新的 Flower 基线: FedAvg MNIST** ([#1497](https://github.com/adap/" +"**引入新的 Flower Baseline: FedAvg MNIST** ([#1497](https://github.com/adap/" "flower/pull/1497), [#1552](https://github.com/adap/flower/pull/1552))" #: ../../source/ref-changelog.md:293 @@ -9461,10 +9494,10 @@ msgid "" "series. [Read more.](https://flower.dev/blog/2023-01-12-fl-starter-pack-" "fedavg-mnist-cnn/)" msgstr "" -"在未来几周内,我们将发布一些新的参考实现,特别是对 FL 新手有用的实现。它们通" -"常会重温文献中的知名论文,适合集成到您自己的应用程序中或用于实验,以加深您对 " -"FL 的总体了解。今天发布的是该系列中的第一篇。[阅读全文](https://flower.dev/" -"blog/2023-01-12-fl-starter-pack-fedavg-mnist-cnn/)" +"在未来几周内,我们将发布一些新的参考,特别是对 FL 新手有用的方法。它们通常会" +"重温文献中的知名论文,适合集成到您自己的应用程序中或用于实验,以加深您对 FL " +"的总体了解。今天发布的是该系列中的第一篇。[阅读全文](https://flower.dev/blog/" +"2023-01-12-fl-starter-pack-fedavg-mnist-cnn/)" #: ../../source/ref-changelog.md:295 msgid "" @@ -9481,9 +9514,9 @@ msgid "" "from scaling simulations in GPU cluster environments. New defaults make " "running GPU-based simulations substantially more robust." msgstr "" -"基于 Ray 的虚拟客户端引擎 (`start_simulation`)已更新,以改进对 GPU 的支持。此" -"次更新包含了在 GPU 集群环境中扩展仿真的一些经验教训。新的默认设置使基于 GPU " -"的模拟运行更加稳健。" +"基于 Ray 的虚拟客户端引擎 (`start_simulation`)已更新,以改进对 GPU 的支持。" +"此次更新包含了在 GPU 集群环境中扩展模拟的一些经验教训。新的默认设置使基于 " +"GPU 的模拟运行更加稳健。" #: ../../source/ref-changelog.md:299 msgid "" @@ -9500,16 +9533,17 @@ msgid "" "on GPU instances. We listened and made improvements to all of our Jupyter " "notebooks! Check out the updated notebooks here:" msgstr "" -"一些用户报告说,在 GPU 实例上使用 Jupyter 笔记本并不总是很方便。我们听取了他" -"们的意见,并对所有 Jupyter 笔记本进行了改进!点击这里查看更新后的笔记本:" +"一些用户报告说,在 GPU 实例上使用 Jupyter " +"笔记本并不是很方便。我们听取了他们的意见,并对所有 Jupyter " +"笔记本进行了改进!点击这里查看更新后的笔记本:" #: ../../source/ref-changelog.md:303 msgid "" "[An Introduction to Federated Learning](https://flower.dev/docs/framework/" "tutorial-get-started-with-flower-pytorch.html)" msgstr "" -"[Federated Learning 简介](https://flower.dev/docs/framework/tutorial-get-" -"started-with-flower-pytorch.html)" +"[联邦学习简介](https://flower.dev/docs/framework/tutorial-get-started-with-" +"flower-pytorch.html)" #: ../../source/ref-changelog.md:304 msgid "" @@ -9578,12 +9612,12 @@ msgid "" "(https://github.com/adap/flower/pull/1551), [#1567](https://github.com/adap/" "flower/pull/1567))" msgstr "" -"**引入(试验性)驱动程序应用程序接口** ([#1520](https://github.com/adap/" -"flower/pull/1520), [#1525](https://github.com/adap/flower/pull/1525), [#1545]" -"(https://github.com/adap/flower/pull/1545), [#1546](https://github.com/adap/" -"flower/pull/1546), [#1550](https://github.com/adap/flower/pull/1550), [#1551]" -"(https://github.com/adap/flower/pull/1551), [#1567](https://github.com/adap/" -"flower/pull/1567))" +"**引入(试验性)Driver API** ([#1520](https://github.com/adap/flower/pull/" +"1520), [#1525](https://github.com/adap/flower/pull/1525), " +"[#1545](https://github.com/adap/flower/pull/1545), [#1546](https://github." +"com/adap/flower/pull/1546), [#1550](https://github.com/adap/flower/pull/1550)" +", [#1551](https://github.com/adap/flower/pull/1551), [#1567](https://github." +"com/adap/flower/pull/1567))" #: ../../source/ref-changelog.md:316 msgid "" @@ -9593,10 +9627,10 @@ msgid "" "will be the abstraction that many upcoming features will be built on - and " "you can start building those things now, too." msgstr "" -"Flower 现在有了一个新的(试验性的)驱动程序应用程序接口(Driver API),它将支" -"持完全可编程、异步和多租户的联合学习(Federated Learning)和联合分析" -"(Federated Analytics)应用程序。呼,真不少!展望未来,Driver API 将成为许多" -"即将推出的功能的抽象基础,您现在就可以开始构建这些功能。" +"Flower 现在有了一个新的(试验性的)驱动程序应用程序接口(Driver " +"API),它将支持完全可编程、异步和多租户的联邦学习(Federated " +"Learning)和联邦分析(Federated Analytics)应用程序。展望未来,Driver API " +"将成为许多即将推出的功能的抽象基础,您现在就可以开始构建这些功能。" #: ../../source/ref-changelog.md:318 msgid "" @@ -9619,9 +9653,7 @@ msgstr "要了解更多信息,请查看 `mt-pytorch` 代码示例。我们期 msgid "" "Please note: *The Driver API is still experimental and will likely change " "significantly over time.*" -msgstr "" -"请注意:*驱动程序应用程序接口仍处于试验阶段,随着时间的推移可能会发生重大变" -"化。*" +msgstr "请注意:Driver API仍处于试验阶段,随着时间的推移可能会发生重大变化。*" #: ../../source/ref-changelog.md:324 msgid "" @@ -9638,9 +9670,9 @@ msgid "" "with Pandas and Flower. You can find it here: [quickstart_pandas](https://" "github.com/adap/flower/tree/main/examples/quickstart_pandas)." msgstr "" -"新代码示例(`quickstart_pandas`)演示了使用 Pandas 和 Flower 进行联合分析。您" -"可以在此处找到它: [quickstart_pandas](https://github.com/adap/flower/tree/" -"main/examples/quickstart_pandas)。" +"新代码示例(`quickstart_pandas`)演示了使用 Pandas 和 Flower " +"进行联邦分析。您可以在此处找到它: [quickstart_pandas](https://github.com/" +"adap/flower/tree/main/examples/quickstart_pandas)。" #: ../../source/ref-changelog.md:328 msgid "" @@ -9687,16 +9719,16 @@ msgid "" "(https://github.com/adap/flower/pull/1564), [#1566](https://github.com/adap/" "flower/pull/1566))" msgstr "" -"**一般改进** ([#1491](https://github.com/adap/flower/pull/1491), [#1504]" -"(https://github.com/adap/flower/pull/1504), [#1506](https://github.com/adap/" -"flower/pull/1506), [#1514](https://github.com/adap/flower/pull/1514), [#1522]" -"(https://github.com/adap/flower/pull/1522), [#1523](https://github.com/adap/" -"flower/pull/1523), [#1526](https://github. com/adap/flower/pull/1526), " -"[#1528](https://github.com/adap/flower/pull/1528), [#1547](https://github." -"com/adap/flower/pull/1547), [#1549](https://github.com/adap/flower/" -"pull/1549), [#1560](https://github.com/adap/flower/pull/1560), [#1564]" -"(https://github.com/adap/flower/pull/1564), [#1566](https://github.com/adap/" -"flower/pull/1566))" +"**普通改进** ([#1491](https://github.com/adap/flower/pull/1491), " +"[#1504](https://github.com/adap/flower/pull/1504), [#1506](https://github." +"com/adap/flower/pull/1506), [#1514](https://github.com/adap/flower/pull/1514)" +", [#1522](https://github.com/adap/flower/pull/1522), [#1523](https://github." +"com/adap/flower/pull/1523), [#1526](https://github. com/adap/flower/pull/" +"1526), [#1528](https://github.com/adap/flower/pull/1528), " +"[#1547](https://github.com/adap/flower/pull/1547), [#1549](https://github." +"com/adap/flower/pull/1549), [#1560](https://github.com/adap/flower/pull/1560)" +", [#1564](https://github.com/adap/flower/pull/1564), [#1566](https://github." +"com/adap/flower/pull/1566))" #: ../../source/ref-changelog.md:340 msgid "" @@ -9745,6 +9777,10 @@ msgid "" "Wiesner`, `Rob Luke`, `Taner Topal`, `VasundharaAgarwal`, `danielnugraha`, " "`edogab33`" msgstr "" +"`Akis Linardos`, `Christopher S`, `Daniel J. Beutel`, `George`, `Jan " +"Schlicht`, `Mohammad Fares`, `Pedro Porto Buarque de Gusmão`, `Philipp " +"Wiesner`, `Rob Luke`, `Taner Topal`, `VasundharaAgarwal`, `danielnugraha`, " +"`edogab33`" #: ../../source/ref-changelog.md:360 msgid "" @@ -9764,8 +9800,8 @@ msgid "" "docs, a new explainer goes into more detail." msgstr "" "可插拔差分隐私封装器的首个(实验性)预览版可轻松配置和使用差分隐私(DP)。可" -"插拔的差分隐私封装器可实现客户端差分隐私和服务器端差分隐私的框架无关**和**策" -"略无关的使用。请访问 Flower 文档,新的解释器会提供更多细节。" +"插拔的差分隐私封装器可实现客户端差分隐私和服务器端差分隐私的框架无关**以及**" +"策略无关的使用。请访问 Flower 文档,新的解释器会提供更多细节。" #: ../../source/ref-changelog.md:364 msgid "" @@ -9789,8 +9825,7 @@ msgstr "" msgid "" "**New FedMedian strategy** ([#1461](https://github.com/adap/flower/" "pull/1461))" -msgstr "" -"**新的联邦医疗战略** ([#1461](https://github.com/adap/flower/pull/1461))" +msgstr "**新的联邦医疗策略** ([#1461](https://github.com/adap/flower/pull/1461))" #: ../../source/ref-changelog.md:370 msgid "" @@ -9814,7 +9849,7 @@ msgid "" "not just exposed to the configured `Strategy` (via the `failures` argument)." msgstr "" "VCE 中发生的所有 \"客户端 \"异常现在都会被默认记录下来,而不只是暴露给配置的 " -"\"策略\"(通过 \"failures \"参数)。" +"`Strategy`(通过 `failures`参数)。" #: ../../source/ref-changelog.md:376 msgid "" @@ -9968,9 +10003,9 @@ msgid "" "`NumPyClient`. The existing parts one and two have also been improved (many " "small changes and fixes)." msgstr "" -"Flower Federated Learning 教程有两个全新的部分,涉及自定义策略(仍处于 WIP 阶" -"段)和 `Client` 与 `NumPyClient` 之间的区别。现有的第一和第二部分也得到了改进" -"(许多小改动和修正)。" +"Flower 联邦学习教程有两个全新的部分,涉及自定义策略(仍处于 WIP 阶段)和 " +"`Client` 与 `NumPyClient` " +"之间的区别。现有的第一和第二部分也得到了改进(许多小改动和修正)。" #: ../../source/ref-changelog.md:412 msgid "v1.0.0 (2022-07-28)" @@ -10033,6 +10068,32 @@ msgid "" "(https://github.com/pedropgusmao), [@tanertopal](https://github.com/" "tanertopal), [@danieljanes](https://github.com/danieljanes)." msgstr "" +"[@rtaiello](https://github.com/rtaiello), [@g-pichler](https://github.com/" +"g-pichler), [@rob-luke](https://github.com/rob-luke), [@andreea-" +"zaharia](https://github.com/andreea-zaharia), [@kinshukdua](https://github." +"com/kinshukdua), [@nfnt](https://github.com/nfnt), " +"[@tatiana-s](https://github.com/tatiana-s), [@TParcollet](https://github.com/" +"TParcollet), [@vballoli](https://github.com/vballoli), " +"[@negedng](https://github.com/negedng), [@RISHIKESHAVAN](https://github.com/" +"RISHIKESHAVAN), [@hei411](https://github.com/hei411), " +"[@SebastianSpeitel](https://github.com/SebastianSpeitel), " +"[@AmitChaulwar](https://github.com/AmitChaulwar), [@Rubiel1](https://github." +"com/Rubiel1), [@FANTOME-PAN](https://github.com/FANTOME-PAN), [@Rono-" +"BC](https://github.com/Rono-BC), [@lbhm](https://github.com/lbhm), " +"[@sishtiaq](https://github.com/sishtiaq), [@remde](https://github.com/remde)" +", [@Jueun-Park](https://github.com/Jueun-Park), [@architjen](https://github." +"com/architjen), [@PratikGarai](https://github.com/PratikGarai), " +"[@mrinaald](https://github.com/mrinaald), [@zliel](https://github.com/zliel)" +", [@MeiruiJiang](https://github.com/MeiruiJiang), " +"[@sandracl72](https://github.com/sandracl72), [@gubertoli](https://github." +"com/gubertoli), [@Vingt100](https://github.com/Vingt100), " +"[@MakGulati](https://github.com/MakGulati), [@cozek](https://github.com/" +"cozek), [@jafermarq](https://github.com/jafermarq), [@sisco0](https://github." +"com/sisco0), [@akhilmathurs](https://github.com/akhilmathurs), " +"[@CanTuerk](https://github.com/CanTuerk), [@mariaboerner1987](https://github." +"com/mariaboerner1987), [@pedropgusmao](https://github.com/pedropgusmao), " +"[@tanertopal](https://github.com/tanertopal), [@danieljanes](https://github." +"com/danieljanes)." #: ../../source/ref-changelog.md:429 msgid "" @@ -10072,10 +10133,10 @@ msgid "" "that as the previous config dict, but it makes writing type-safe code easier " "and the default parameters values more transparent." msgstr "" -"而不是配置字典`{\"num_rounds\": 3, \"round_timeout\": 600.0}`, " -"`start_server`和 `start_simulation`现在期待一个类型为 `flwr.server." -"ServerConfig`的配置对象。ServerConfig`接收的参数与之前的 config dict 相同,但" -"它使编写类型安全代码变得更容易,默认参数值也更加透明。" +"并非配置字典`{\"num_rounds\": 3, \"round_timeout\": 600.0}`, `start_server`" +"和 `start_simulation`现在用一个类型为 `flwr.server." +"ServerConfig`的配置对象。`ServerConfig`接收的参数与之前的 config dict " +"相同,但它使编写类型安全代码变得更容易,默认参数值也更加透明。" #: ../../source/ref-changelog.md:437 msgid "" @@ -10093,15 +10154,15 @@ msgstr "以下内置策略参数已重新命名,以提高可读性并与其他 #: ../../source/ref-changelog.md:441 msgid "`fraction_eval` --> `fraction_evaluate`" -msgstr "" +msgstr "`fraction_eval` --> `fraction_evaluate`" #: ../../source/ref-changelog.md:442 msgid "`min_eval_clients` --> `min_evaluate_clients`" -msgstr "" +msgstr "`min_eval_clients` --> `min_evaluate_clients`" #: ../../source/ref-changelog.md:443 msgid "`eval_fn` --> `evaluate_fn`" -msgstr "" +msgstr "`eval_fn` --> `evaluate_fn`" #: ../../source/ref-changelog.md:445 msgid "" @@ -10125,7 +10186,7 @@ msgstr "" #: ../../source/ref-changelog.md:449 msgid "`strategy = FedAvg(fraction_fit=0.1, fraction_evaluate=0.1)`" -msgstr "" +msgstr "`strategy = FedAvg(fraction_fit=0.1, fraction_evaluate=0.1)`" #: ../../source/ref-changelog.md:451 msgid "" @@ -10139,7 +10200,7 @@ msgstr "" msgid "" "The `Strategy` method `evaluate` now receives the current round of federated " "learning/evaluation as the first parameter." -msgstr "策略 \"方法 \"评估 \"现在会接收当前一轮联邦学习/评估作为第一个参数。" +msgstr "`Strategy`的`evaluate` 方法现在会接收当前一轮联邦学习/评估作为第一个参数。" #: ../../source/ref-changelog.md:455 msgid "" @@ -10156,9 +10217,9 @@ msgid "" "(`server_round`), (2) the model parameters to evaluate (`parameters`), and " "(3) a config dictionary (`config`)." msgstr "" -"传递给内置策略(如 `FedAvg`)的 `evaluate_fn` 现在需要三个参数:(1) 当前一轮" -"联合学习/评估 (`server_round`),(2) 要评估的模型参数 (`parameters`),(3) 配置" -"字典 (`config`)。" +"传递给内置策略(如 `FedAvg`)的 `evaluate_fn` 现在需要三个参数:(1) " +"当前一轮联邦学习/评估 (`server_round`),(2) 要评估的模型参数 " +"(`parameters`),(3) 配置字典 (`config`)。" #: ../../source/ref-changelog.md:459 msgid "" @@ -10176,9 +10237,9 @@ msgid "" "improve reaability and avoid confusion with *random*, this parameter has " "been renamed from `rnd` to `server_round`." msgstr "" -"几个 Flower 方法和函数(`evaluate_fn`、`configure_fit`、`aggregate_fit`、" -"`configure_evaluate`、`aggregate_evaluate`)的第一个参数是当前一轮的联合学习/" -"评估。为提高可重复性并避免与 *random* 混淆,该参数已从 `rnd` 更名为 " +"几个 Flower 方法和函数(`evaluate_fn`、`configure_fit`、`aggregate_fit`、`con" +"figure_evaluate`、`aggregate_evaluate`)的第一个参数是当前一轮的联邦学习/评估" +"。为提高可重复性并避免与 *random* 混淆,该参数已从 `rnd` 更名为 " "`server_round`。" #: ../../source/ref-changelog.md:463 @@ -10306,9 +10367,9 @@ msgid "" "implement, for example, only `fit`, but no other method. No need to " "implement `evaluate` when using centralized evaluation!" msgstr "" -"客户端\"/\"NumPyClient \"的 \"get_properties\"、\"get_parameters\"、\"fit " -"\"和 \"evaluate \"方法都是可选的。这样就可以编写只实现 `fit` 而不实现其他方法" -"的客户端。使用集中评估时,无需实现 `evaluate`!" +"`Client`/`NumPyClient`的 \"get_properties\"、\"get_parameters\"、\"fit \"和 " +"\"evaluate \"方法都是可选的。这样就可以编写只实现 `fit` " +"而不实现其他方法的客户端。使用集中评估时,无需实现 `evaluate`!" #: ../../source/ref-changelog.md:497 msgid "" @@ -10351,23 +10412,23 @@ msgstr "`scikit-learn`" #: ../../source/ref-changelog.md:506 msgid "`simulation_pytorch`" -msgstr "" +msgstr "`simulation_pytorch`" #: ../../source/ref-changelog.md:507 msgid "`quickstart_pytorch`" -msgstr "" +msgstr "`quickstart_pytorch`" #: ../../source/ref-changelog.md:508 msgid "`quickstart_simulation`" -msgstr "" +msgstr "`quickstart_simulation`" #: ../../source/ref-changelog.md:509 msgid "`quickstart_tensorflow`" -msgstr "" +msgstr "`quickstart_tensorflow`" #: ../../source/ref-changelog.md:510 msgid "`advanced_tensorflow`" -msgstr "" +msgstr "`advanced_tensorflow`" #: ../../source/ref-changelog.md:512 msgid "" @@ -10462,7 +10523,7 @@ msgstr "" #: ../../source/ref-changelog.md:527 msgid "v0.19.0 (2022-05-18)" -msgstr "" +msgstr "v0.19.0 (2022-05-18)" #: ../../source/ref-changelog.md:531 msgid "" @@ -10470,9 +10531,9 @@ msgid "" "github.com/adap/flower/pull/919), [#1127](https://github.com/adap/flower/" "pull/1127), [#914](https://github.com/adap/flower/pull/914))" msgstr "" -"**Flower 基准(预览): FedOpt、FedBN、FedAvgM** ([#919](https://github.com/" -"adap/flower/pull/919), [#1127](https://github.com/adap/flower/pull/1127), " -"[#914](https://github.com/adap/flower/pull/914))" +"**Flower Baselines(预览): FedOpt、FedBN、FedAvgM** ([#919](https://github." +"com/adap/flower/pull/919), [#1127](https://github.com/adap/flower/pull/1127)" +", [#914](https://github.com/adap/flower/pull/914))" #: ../../source/ref-changelog.md:533 msgid "" @@ -10483,11 +10544,11 @@ msgid "" "this first preview release we're also inviting the community to [contribute " "their own baselines](https://flower.dev/docs/contributing-baselines.html)." msgstr "" -"Flower Baselines 的第一个预览版已经发布!我们通过实现 FedOpt(FedYogi、" -"FedAdam、FedAdagrad)、FedBN 和 FedAvgM 来启动 Flower Baselines。请查阅文档了" -"解如何使用 [Flower Baselines](https://flower.dev/docs/using-baselines.html)。" -"在首次发布预览版时,我们还邀请社区成员[贡献自己的基准](https://flower.dev/" -"docs/contributing-baselines.html)。" +"Flower Baselines 的第一个预览版已经发布!我们通过实现 " +"FedOpt(FedYogi、FedAdam、FedAdagrad)、FedBN 和 FedAvgM 来启动 Flower " +"Baselines。请查阅文档了解如何使用 [Flower Baselines](https://flower.dev/docs/" +"using-baselines.html)。在首次发布预览版时,我们还邀请社区成员[贡献自己的Basel" +"ines](https://flower.dev/docs/contributing-baselines.html)。" #: ../../source/ref-changelog.md:535 msgid "" @@ -10566,7 +10627,7 @@ msgid "" "the same time in all built-in strategies** ([#1091](https://github.com/adap/" "flower/pull/1091))" msgstr "" -"**允许在所有内置策略中同时使用联合评价和集中评价** ([#1091](https://github." +"**允许在所有内置策略中同时使用联邦评价和集中评估** ([#1091](https://github." "com/adap/flower/pull/1091))" #: ../../source/ref-changelog.md:553 @@ -10575,8 +10636,8 @@ msgid "" "side) and centralized evaluation (i.e., server-side) in the same round. " "Federated evaluation can be disabled by setting `fraction_eval` to `0.0`." msgstr "" -"内置策略现在可以在同一轮中同时执行联合评估(即客户端)和集中评估(即服务器" -"端)。可以通过将 `fraction_eval` 设置为 `0.0`来禁用联合评估。" +"内置策略现在可以在同一轮中同时执行联邦评估(即客户端)和集中评估(即服务器端" +")。可以通过将 `fraction_eval` 设置为 `0.0`来禁用联邦评估。" #: ../../source/ref-changelog.md:555 msgid "" @@ -10609,7 +10670,7 @@ msgid "" "research.google.com/github/adap/flower/blob/main/tutorials/Flower-2-" "Strategies-in-FL-PyTorch.ipynb)" msgstr "" -"*在联合学习中使用策略*: [在 Colab 中打开](https://colab.research.google.com/" +"*在联邦学习中使用策略*: [在 Colab 中打开](https://colab.research.google.com/" "github/adap/flower/blob/main/tutorials/Flower-2-Strategies-in-FL-PyTorch." "ipynb)" @@ -10618,14 +10679,14 @@ msgid "" "**New FedAvgM strategy (Federated Averaging with Server Momentum)** ([#1076]" "(https://github.com/adap/flower/pull/1076))" msgstr "" -"**新的 FedAvgM 策略(带服务器动量的联合平均)** ([#1076](https://github.com/" +"**新的 FedAvgM 策略(带服务器动量的联邦平均)** ([#1076](https://github.com/" "adap/flower/pull/1076))" #: ../../source/ref-changelog.md:565 msgid "" "The new `FedAvgM` strategy implements Federated Averaging with Server " "Momentum \\[Hsu et al., 2019\\]." -msgstr "新的 \"FedAvgM \"策略实现了带服务器动量的联合平均[Hsu et al., 2019\\]." +msgstr "新的 \"FedAvgM \"策略实现了带服务器动量的联邦平均[Hsu et al., 2019\\]." #: ../../source/ref-changelog.md:567 msgid "" @@ -10679,9 +10740,9 @@ msgid "" "framework/how-to-implement-strategies.html) ([#1097](https://github.com/adap/" "flower/pull/1097), [#1175](https://github.com/adap/flower/pull/1175))" msgstr "" -"实施战略](https://flower.dev/docs/framework/how-to-implement-strategies." -"html) 的新文件([#1097](https://github.com/adap/flower/pull/1097), [#1175]" -"(https://github.com/adap/flower/pull/1175)" +"[实施战略](https://flower.dev/docs/framework/how-to-implement-strategies." +"html) 的新文件([#1097](https://github.com/adap/flower/pull/1097), " +"[#1175](https://github.com/adap/flower/pull/1175)" #: ../../source/ref-changelog.md:580 msgid "" @@ -10696,7 +10757,7 @@ msgid "" "compatible releases (`>=1.9.2,<1.12.0`) ([#1205](https://github.com/adap/" "flower/pull/1205))" msgstr "" -"限制(可选)\"ray \"依赖的版本范围,使其仅包含兼容版本(`>=1.9.2,<1.12.0`) " +"限制(可选)`ray`依赖的版本范围,使其仅包含兼容版本(`>=1.9.2,<1.12.0`) " "([#1205](https://github.com/adap/flower/pull/1205))" #: ../../source/ref-changelog.md:585 @@ -10764,7 +10825,7 @@ msgstr "" #: ../../source/ref-changelog.md:594 msgid "v0.18.0 (2022-02-28)" -msgstr "" +msgstr "v0.18.0 (2022-02-28)" #: ../../source/ref-changelog.md:598 msgid "" @@ -10836,8 +10897,9 @@ msgid "" "client platforms and with this release, using Flower on Android has become a " "lot easier." msgstr "" -"主 \"终于支持 Android 了!Flower 的设计与客户端和框架无关。我们可以集成任意客" -"户端平台,有了这个版本,在安卓系统上使用 Flower 就变得更容易了。" +"`main`终于支持 Android 了!Flower " +"的设计与客户端和框架无关。我们可以集成任意客户端平台,有了这个版本," +"在安卓系统上使用 Flower 就变得更容易了。" #: ../../source/ref-changelog.md:614 msgid "" @@ -10881,23 +10943,24 @@ msgstr "" msgid "" "A new code example (`opacus`) demonstrates differentially-private federated " "learning with Opacus, PyTorch, and Flower." -msgstr "" -"一个新的代码示例(\"opacus\")演示了使用 Opacus、PyTorch 和 Flower 进行差异化" -"私有联合学习。" +msgstr "一个新的代码示例(\"opacus\")演示了使用 Opacus、PyTorch 和 Flower " +"进行差分隐私的联邦学习。" #: ../../source/ref-changelog.md:624 msgid "" "**New Hugging Face Transformers code example** ([#863](https://github.com/" "adap/flower/pull/863))" msgstr "" -"**新的抱脸变形金刚代码示例** ([#863](https://github.com/adap/flower/" -"pull/863))" +"**新的Hugging Face Transformers代码示例** ([#863](https://github.com/adap/" +"flower/pull/863))" #: ../../source/ref-changelog.md:626 msgid "" "A new code example (`quickstart_huggingface`) demonstrates usage of Hugging " "Face Transformers with Flower." msgstr "" +"新的代码示例(`quickstart_huggingface`)证明了结合Flower和Hugging Face " +"Transformers的实用性。" #: ../../source/ref-changelog.md:628 msgid "" @@ -10953,7 +11016,7 @@ msgstr "" msgid "" "`FedAdam` and `FedAdam` match the latest version of the Adaptive Federated " "Optimization paper." -msgstr "FedAdam \"和 \"FedAdam \"与最新版本的 \"自适应联合优化 \"论文相匹配。" +msgstr "FedAdam \"和 \"FedAdam \"与最新版本的 \"自适应联邦优化 \"论文相匹配。" #: ../../source/ref-changelog.md:640 msgid "" @@ -10996,16 +11059,16 @@ msgid "" "`start_server` in `app.py` now returns a `History` object containing metrics " "from training ([#974](https://github.com/adap/flower/pull/974))" msgstr "" -"app.py \"中的 \"start_server \"现在会返回一个 \"History \"对象,其中包含训练" -"中的指标([#974](https://github.com/adap/flower/pull/974))" +"`app.py`中的 `start_server`现在会返回一个 `History` " +"对象,其中包含训练中的指标([#974](https://github.com/adap/flower/pull/974))" #: ../../source/ref-changelog.md:649 msgid "" "Make `max_workers` (used by `ThreadPoolExecutor`) configurable ([#978]" "(https://github.com/adap/flower/pull/978))" msgstr "" -"使 \"max_workers\"(由 \"ThreadPoolExecutor \"使用)可配置([#978](https://" -"github.com/adap/flower/pull/978))" +"使 `max_workers`(由 `ThreadPoolExecutor`使用)可配置([#978](https://github." +"com/adap/flower/pull/978))" #: ../../source/ref-changelog.md:650 msgid "" @@ -11073,9 +11136,10 @@ msgid "" "way to test the new functionality is to look at the two new code examples " "called `quickstart_simulation` and `simulation_pytorch`." msgstr "" -"Flower 的目标之一是实现大规模研究。这一版本首次(试验性地)展示了代号为 \"虚" -"拟客户端引擎 \"的重要新功能。虚拟客户端可以在单台机器或计算集群上对大量客户端" -"进行仿真。测试新功能的最简单方法是查看名为 \"quickstart_simulation \"和 " +"Flower 的目标之一是实现大规模研究。这一版本首次(试验性地)展示了代号为 " +"\"虚拟客户端引擎 \"的重要新功能" +"。虚拟客户端可以在单台机器或计算集群上对大量客户端进行模拟。" +"测试新功能的最简单方法是查看名为 \"quickstart_simulation \"和 " "\"simulation_pytorch \"的两个新代码示例。" #: ../../source/ref-changelog.md:668 @@ -11101,9 +11165,8 @@ msgstr "" msgid "" "FedYogi - Federated learning strategy using Yogi on server-side. " "Implementation based on https://arxiv.org/abs/2003.00295" -msgstr "" -"FedYogi - 在服务器端使用 Yogi 的联合学习策略。基于 https://arxiv.org/" -"abs/2003.00295 实现" +msgstr "FedYogi - 在服务器端使用 Yogi 的联邦学习策略。基于 https://arxiv.org/abs/" +"2003.00295 实现" #: ../../source/ref-changelog.md:673 msgid "" @@ -11256,7 +11319,7 @@ msgstr "(摘要) FedOpt" #: ../../source/ref-changelog.md:712 msgid "FedAdagrad" -msgstr "" +msgstr "FedAdagrad" #: ../../source/ref-changelog.md:714 msgid "" @@ -11349,9 +11412,9 @@ msgid "" "([#696](https://github.com/adap/flower/pull/696) [#702](https://github.com/" "adap/flower/pull/702) [#705](https://github.com/adap/flower/pull/705))" msgstr "" -"PyTorch 示例中的 FedBN 实现: 从集中到联合 ([#696](https://github.com/adap/" -"flower/pull/696) [#702](https://github.com/adap/flower/pull/702) [#705]" -"(https://github.com/adap/flower/pull/705))" +"PyTorch 示例中的 FedBN 实现: 从集中到联邦 ([#696](https://github.com/adap/" +"flower/pull/696) [#702](https://github.com/adap/flower/pull/702) " +"[#705](https://github.com/adap/flower/pull/705))" #: ../../source/ref-changelog.md:736 msgid "" @@ -11381,9 +11444,10 @@ msgid "" "definitions. Strategy authors can consult PR [#721](https://github.com/adap/" "flower/pull/721) to see how strategies can easily migrate to the new format." msgstr "" -"内置策略通过在内部处理序列化和反序列化到/从 \"权重 \"来实现这种方法。自定义/" -"第三方策略实现应更新为稍有改动的策略方法定义。策略作者可查阅 PR [#721]" -"(https://github.com/adap/flower/pull/721) 以了解如何将策略轻松迁移到新格式。" +"内置策略通过在内部处理序列化和反序列化到/从`Weights`来实现这种方法。自定义/第" +"三方策略实现应更新为稍有改动的策略方法定义。策略作者可查阅 PR " +"[#721](https://github.com/adap/flower/pull/721) " +"以了解如何将策略轻松迁移到新格式。" #: ../../source/ref-changelog.md:742 msgid "" @@ -11517,8 +11581,9 @@ msgid "" "this to enable values of the following types: `bool`, `bytes`, `float`, " "`int`, `str`." msgstr "" -"配置 \"参数曾是 \"字典[str, str]\"类型,这意味着字典值应是字符串。新版本将其" -"扩展为以下类型的值: bool`、`bytes`、`float`、`int`、`str`。" +"`config`参数曾是 \"字典[str, str]\"类型" +",这意味着字典值应是字符串。新版本将其扩展为以下类型的值: " +"bool`、`bytes`、`float`、`int`、`str`。" #: ../../source/ref-changelog.md:808 msgid "" @@ -11545,13 +11610,12 @@ msgstr "v0.13.0 (2021-01-08)" msgid "" "New example: PyTorch From Centralized To Federated ([#549](https://github." "com/adap/flower/pull/549))" -msgstr "" -"新示例: PyTorch 从集中到联合 ([#549](https://github.com/adap/flower/" -"pull/549))" +msgstr "新示例: PyTorch 从集中到联邦 ([#549](https://github.com/adap/flower/pull/" +"549))" #: ../../source/ref-changelog.md:832 msgid "Improved documentation" -msgstr "改进文件" +msgstr "改进文档" #: ../../source/ref-changelog.md:833 msgid "" @@ -11590,7 +11654,7 @@ msgstr "" #: ../../source/ref-changelog.md:842 msgid "v0.12.0 (2020-12-07)" -msgstr "" +msgstr "v0.12.0 (2020-12-07)" #: ../../source/ref-changelog.md:844 ../../source/ref-changelog.md:860 msgid "Important changes:" @@ -11639,9 +11703,9 @@ msgid "" "Strategy. To migrate rename the following `Strategy` methods accordingly:" msgstr "" "重命名了策略方法([#486](https://github.com/adap/flower/pull/486)),以统一 " -"\"花朵 \"公共 API 的命名。其他公共方法/函数(例如 `Client` 中的每个方法,以" -"及 `Strategy.evaluate`)不使用 `on_` 前缀,这就是我们从 Strategy 中的四个方法" -"中移除它的原因。迁移时,请相应地重命名以下 `Strategy` 方法:" +"Flower公共 API 的命名。其他公共方法/函数(例如 `Client` 中的每个方法,以及 " +"`Strategy.evaluate`)不使用 `on_` 前缀,这就是我们从 Strategy " +"中的四个方法中移除它的原因。迁移时,请相应地重命名以下 `Strategy` 方法:" #: ../../source/ref-changelog.md:855 msgid "`on_configure_evaluate` => `configure_evaluate`" @@ -11671,7 +11735,7 @@ msgstr "" msgid "" "Simplified examples and baselines ([#484](https://github.com/adap/flower/" "pull/484))." -msgstr "简化示例和基线([#484](https://github.com/adap/flower/pull/484))。" +msgstr "简化示例和baselines([#484](https://github.com/adap/flower/pull/484))。" #: ../../source/ref-changelog.md:864 msgid "" @@ -11709,9 +11773,9 @@ msgid "" "`PyTorch `_ or `TensorFlow `_." msgstr "" -"Flower 附带了许多使用示例。这些示例演示了如何使用 Flower 联合不同类型的现有机" -"器学习管道,通常是利用流行的机器学习框架,如 `PyTorch `_ 或 `TensorFlow `_。" +"Flower 附带了许多使用示例。这些示例演示了如何使用 Flower " +"联邦不同类型的现有机器学习形式,通常是利用流行的机器学习框架,如 `PyTorch " +"`_ 或 `TensorFlow `_。" #: ../../source/ref-example-projects.rst:11 msgid "" @@ -11745,7 +11809,7 @@ msgid "" "`Quickstart TensorFlow (Code) `_" msgstr "" -"`Quickstart TensorFlow (Code) `_" #: ../../source/ref-example-projects.rst:26 @@ -11753,17 +11817,21 @@ msgid "" "`Quickstart TensorFlow (Tutorial) `_" msgstr "" +"`TensorFlow快速入门 (教程) `_" #: ../../source/ref-example-projects.rst:27 msgid "" "`Quickstart TensorFlow (Blog Post) `_" msgstr "" +"`TensorFlow快速入门 (博客) `_" #: ../../source/ref-example-projects.rst:31 #: ../../source/tutorial-quickstart-pytorch.rst:5 msgid "Quickstart PyTorch" -msgstr "快速入门 PyTorch" +msgstr "PyTorch快速入门" #: ../../source/ref-example-projects.rst:33 msgid "" @@ -11777,29 +11845,33 @@ msgid "" "`Quickstart PyTorch (Code) `_" msgstr "" +"`PyTorch快速入门 (代码) `_" #: ../../source/ref-example-projects.rst:37 msgid "" "`Quickstart PyTorch (Tutorial) `_" msgstr "" +"`PyTorch快速入门 (教程) `_" #: ../../source/ref-example-projects.rst:41 msgid "PyTorch: From Centralized To Federated" -msgstr "PyTorch: 从集中到联合" +msgstr "PyTorch: 从集中式到联邦式" #: ../../source/ref-example-projects.rst:43 msgid "" "This example shows how a regular PyTorch project can be federated using " "Flower:" -msgstr "本例展示了如何使用 Flower 联合一个普通的 PyTorch 项目:" +msgstr "本例展示了如何使用 Flower 联邦化一个普通的 PyTorch 项目:" #: ../../source/ref-example-projects.rst:45 msgid "" "`PyTorch: From Centralized To Federated (Code) `_" msgstr "" -"PyTorch: 从集中到联合(代码) `_" #: ../../source/ref-example-projects.rst:46 @@ -11807,28 +11879,27 @@ msgid "" "`PyTorch: From Centralized To Federated (Tutorial) `_" msgstr "" -"PyTorch: 从集中到联合(教程) `_" +"PyTorch: 从集中式到联邦式(教程) `_" #: ../../source/ref-example-projects.rst:50 msgid "Federated Learning on Raspberry Pi and Nvidia Jetson" -msgstr "树莓派和 Nvidia Jetson 上的联合学习" +msgstr "树莓派和 Nvidia Jetson 上的联邦学习" #: ../../source/ref-example-projects.rst:52 msgid "" "This example shows how Flower can be used to build a federated learning " "system that run across Raspberry Pi and Nvidia Jetson:" -msgstr "" -"本示例展示了如何利用 Flower 建立一个跨 Raspberry Pi 和 Nvidia Jetson 运行的联" -"合学习系统:" +msgstr "本示例展示了如何利用 Flower 建立一个跨 Raspberry Pi 和 Nvidia Jetson " +"运行的联邦学习系统:" #: ../../source/ref-example-projects.rst:54 msgid "" "`Federated Learning on Raspberry Pi and Nvidia Jetson (Code) `_" msgstr "" -"树莓派和 Nvidia Jetson 上的联合学习(代码) `_" +"Raspberry Pi 和 Nvidia Jetson 上的联邦学习(代码) `_" #: ../../source/ref-example-projects.rst:55 msgid "" @@ -11836,9 +11907,9 @@ msgid "" "flower.dev/blog/2020-12-16-" "running_federated_learning_applications_on_embedded_devices_with_flower>`_" msgstr "" -"树莓派和 Nvidia Jetson 上的联合学习(博文) `_" +"Raspberry Pi和 Nvidia Jetson 上的联邦学习(博客) `_" #: ../../source/ref-example-projects.rst:60 msgid "Legacy Examples (`flwr_example`)" @@ -11908,9 +11979,9 @@ msgid "" "popular RGB image datasets. The Flower CIFAR-10 example uses PyTorch to " "train a simple CNN classifier in a federated learning setup with two clients." msgstr "" -"CIFAR-10 和 CIFAR-100 ``_ 是流行" -"的 RGB 图像数据集。Flower CIFAR-10 示例使用 PyTorch 在有两个客户端的联合学习" -"设置中训练一个简单的 CNN 分类器。" +"CIFAR-10 和 CIFAR-100 ``_ " +"是流行的 RGB 图像数据集。Flower CIFAR-10 示例使用 PyTorch " +"在有两个客户端的联邦学习设置中训练一个简单的 CNN 分类器。" #: ../../source/ref-example-projects.rst:104 #: ../../source/ref-example-projects.rst:121 @@ -11947,8 +12018,8 @@ msgid "" "ResNet-18 classifier in a federated learning setup with ten clients." msgstr "" "ImageNet-2012 `_ 是主要的计算机视觉数据集之一。" -"Flower ImageNet 示例使用 PyTorch 在有十个客户端的联合学习设置中训练 " -"ResNet-18 分类器。" +"Flower ImageNet 示例使用 PyTorch 在有十个客户端的联邦学习设置中训练 ResNet-" +"18 分类器。" #: ../../source/ref-example-projects.rst:123 msgid "$ ./src/py/flwr_example/pytorch_imagenet/run-server.sh" @@ -11976,7 +12047,7 @@ msgstr "" #: ../../source/ref-example-projects.rst:139 msgid "Fashion-MNIST Image Classification" -msgstr "时尚-MNIST 图像分类" +msgstr "Fashion-MNIST 图像分类" #: ../../source/ref-example-projects.rst:141 msgid "" @@ -11985,9 +12056,9 @@ msgid "" "and provide an example which samples random local datasets from Fashion-" "MNIST and trains a simple image classification model over those partitions." msgstr "" -"`Fashion-MNIST `_ 经常被用" -"作机器学习的 \"你好,世界!\"。我们遵循这一传统,提供了一个从时尚-MNIST 中随" -"机抽样本地数据集的示例,并在这些分区上训练一个简单的图像分类模型。" +"`Fashion-MNIST `_ " +"经常被用作机器学习的 \"你好,世界!\"。我们遵循这一传统,提供了一个从Fashion-" +"MNIST 中随机抽样本地数据集的示例,并在这些分区上训练一个简单的图像分类模型。" #: ../../source/ref-example-projects.rst:148 msgid "$ ./src/py/flwr_example/tensorflow_fashion_mnist/run-server.sh" @@ -12007,7 +12078,7 @@ msgstr "" msgid "" "This page collects answers to commonly asked questions about Federated " "Learning with Flower." -msgstr "本页收集了有关 \"Flower 联合学习 \"常见问题的答案。" +msgstr "本页收集了有关 \"Flower 联邦学习 \"常见问题的答案。" #: ../../source/ref-faq.rst msgid ":fa:`eye,mr-1` Can Flower run on Juptyter Notebooks / Google Colab?" @@ -12040,7 +12111,7 @@ msgstr "" #: ../../source/ref-faq.rst msgid ":fa:`eye,mr-1` How can I run Federated Learning on a Raspberry Pi?" -msgstr ":fa:`eye,mr-1` 如何在 Raspberry Pi 上运行联合学习?" +msgstr ":fa:`eye,mr-1` 如何在 Raspberry Pi 上运行联邦学习?" #: ../../source/ref-faq.rst:15 msgid "" @@ -12050,16 +12121,15 @@ msgid "" "and the corresponding `GitHub code example `_." msgstr "" -"请点击此处查看有关嵌入式设备联合学习的 \"博文\"`_和" -"相应的 \"GitHub 代码示例\"`_。" +"请点击此处查看有关嵌入式设备联邦学习的 \"博文\"`_和相应的 \"GitHub 代码示例\"`_。" #: ../../source/ref-faq.rst msgid "" ":fa:`eye,mr-1` Does Flower support federated learning on Android devices?" -msgstr ":fa:`eye,mr-1` Flower 是否支持安卓设备上的联合学习?" +msgstr ":fa:`eye,mr-1` Flower 是否支持安卓设备上的联邦学习?" #: ../../source/ref-faq.rst:19 msgid "" @@ -12083,7 +12153,7 @@ msgstr "Android Java 示例 `_" #: ../../source/ref-faq.rst msgid ":fa:`eye,mr-1` Can I combine federated learning with blockchain?" -msgstr ":fa:`eye,mr-1` 我可以将联合学习与区块链结合起来吗?" +msgstr ":fa:`eye,mr-1` 我可以将联邦学习与区块链结合起来吗?" #: ../../source/ref-faq.rst:26 msgid "" @@ -12104,12 +12174,16 @@ msgid "" "`Flower meets Nevermined YouTube video `_." msgstr "" +"`Flower meets Nevermined YouTube 视频 `_." #: ../../source/ref-faq.rst:30 msgid "" "`Flower meets KOSMoS `_." msgstr "" +"`Flower meets KOSMoS `_." #: ../../source/ref-faq.rst:31 msgid "" @@ -12117,15 +12191,17 @@ msgid "" "learning-same-mask-different-faces-imen-ayari/?" "trackingId=971oIlxLQ9%2BA9RB0IQ73XQ%3D%3D>`_ ." msgstr "" -"\"Flower 与 Talan 的邂逅 \"博文 `_ 。" +"`Flower meets Talan博文 `_ 。" #: ../../source/ref-faq.rst:32 msgid "" "`Flower meets Talan GitHub Repository `_ ." msgstr "" +"`Flower meets Talan GitHub Repository `_ ." #: ../../source/ref-telemetry.md:1 msgid "Telemetry" @@ -12194,7 +12270,7 @@ msgstr "" #: ../../source/ref-telemetry.md:16 msgid "How to opt-out" -msgstr "如何退订" +msgstr "如何退出" #: ../../source/ref-telemetry.md:18 msgid "" @@ -12369,9 +12445,7 @@ msgstr "" msgid "" "Read this Federated Learning quickstart tutorial for creating an Android app " "using Flower." -msgstr "" -"阅读本 Federated Learning 快速入门教程,了解如何使用 Flower 创建 Android 应用" -"程序。" +msgstr "阅读本联邦学习快速入门教程,了解如何使用 Flower 创建 Android 应用程序。" #: ../../source/tutorial-quickstart-android.rst:5 msgid "Quickstart Android" @@ -12380,23 +12454,22 @@ msgstr "快速入门 Android" #: ../../source/tutorial-quickstart-android.rst:10 msgid "" "Let's build a federated learning system using TFLite and Flower on Android!" -msgstr "让我们在 Android 上使用 TFLite 和 Flower 构建一个联合学习系统!" +msgstr "让我们在 Android 上使用 TFLite 和 Flower 构建一个联邦学习系统!" #: ../../source/tutorial-quickstart-android.rst:12 msgid "" "Please refer to the `full code example `_ to learn more." msgstr "" -"请参阅 \"完整代码示例 `_\" 了解更多信息。" +"请参阅`完整代码示例 `_了解更多信息。" #: ../../source/tutorial-quickstart-fastai.rst:-1 msgid "" "Check out this Federated Learning quickstart tutorial for using Flower with " "FastAI to train a vision model on CIFAR-10." -msgstr "" -"查看此 Federated Learning 快速入门教程,了解如何使用 Flower 和 FastAI 在 " -"CIFAR-10 上训练视觉模型。" +msgstr "查看此联邦学习快速入门教程,了解如何使用 Flower 和 FastAI 在 CIFAR-10 " +"上训练视觉模型。" #: ../../source/tutorial-quickstart-fastai.rst:5 msgid "Quickstart fastai" @@ -12404,33 +12477,32 @@ msgstr "快速入门 fastai" #: ../../source/tutorial-quickstart-fastai.rst:10 msgid "Let's build a federated learning system using fastai and Flower!" -msgstr "让我们用 fastai 和 Flower 建立一个联合学习系统!" +msgstr "让我们用 fastai 和 Flower 建立一个联邦学习系统!" #: ../../source/tutorial-quickstart-fastai.rst:12 msgid "" "Please refer to the `full code example `_ to learn more." msgstr "" -"请参阅 \"完整代码示例 `_\" 了解更多信息。" +"请参阅 `完整代码示例 `_了解更多信息。" #: ../../source/tutorial-quickstart-huggingface.rst:-1 msgid "" "Check out this Federating Learning quickstart tutorial for using Flower with " "HuggingFace Transformers in order to fine-tune an LLM." -msgstr "" -"查看此 Federating Learning 快速入门教程,了解如何使用 Flower 和 HuggingFace " -"Transformers 来微调 LLM。" +msgstr "查看此联邦学习 快速入门教程,了解如何使用 Flower 和 HuggingFace Transformers " +"来微调 LLM。" #: ../../source/tutorial-quickstart-huggingface.rst:5 msgid "Quickstart 🤗 Transformers" -msgstr "" +msgstr "🤗 Transformers快速入门" #: ../../source/tutorial-quickstart-huggingface.rst:10 msgid "" "Let's build a federated learning system using Hugging Face Transformers and " "Flower!" -msgstr "" +msgstr "让我们用Hugging Face Transformers和Flower来构建一个联邦学习系统!" #: ../../source/tutorial-quickstart-huggingface.rst:12 msgid "" @@ -12440,9 +12512,10 @@ msgid "" "a dataset of IMDB ratings. The end goal is to detect if a movie rating is " "positive or negative." msgstr "" -"我们将利用 \"拥抱面孔 \"技术,使用 Flower 在多个客户端上联合训练语言模型。更" -"具体地说,我们将对预先训练好的 Transformer 模型(distilBERT)进行微调,以便" -"在 IMDB 评分数据集上进行序列分类。最终目标是检测电影评分是正面还是负面。" +"我们将利用Hugging Face技术,使用 Flower " +"在多个客户端上联邦训练语言模型。更具体地说,我们将对预先训练好的 Transformer " +"模型(distilBERT)进行微调,以便在 IMDB " +"评分数据集上进行序列分类。最终目标是检测电影评分是正面还是负面。" #: ../../source/tutorial-quickstart-huggingface.rst:18 msgid "Dependencies" @@ -12460,7 +12533,7 @@ msgstr "" #: ../../source/tutorial-quickstart-huggingface.rst:30 msgid "Standard Hugging Face workflow" -msgstr "" +msgstr "标准Hugging Face工作流程" #: ../../source/tutorial-quickstart-huggingface.rst:33 msgid "Handling the data" @@ -12503,7 +12576,7 @@ msgstr "" #: ../../source/tutorial-quickstart-huggingface.rst:136 msgid "Federating the example" -msgstr "将示例联合起来" +msgstr "将示例联邦化" #: ../../source/tutorial-quickstart-huggingface.rst:139 msgid "Creating the IMDBClient" @@ -12515,9 +12588,9 @@ msgid "" "Flower client class (inheriting from :code:`flwr.client.NumPyClient`). This " "is very easy, as our model is a standard :code:`PyTorch` model:" msgstr "" -"要将我们的示例联合到多个客户端,我们首先需要编写 Flower 客户端类(继承自 :" -"code:`flwr.client.NumPyClient`)。这很容易,因为我们的模型是一个标准的 :code:" -"`PyTorch` 模型:" +"要将我们的示例联邦到多个客户端,我们首先需要编写 Flower 客户端类(继承自 " +":code:`flwr.client.NumPyClient`)。这很容易,因为我们的模型是一个标准的 " +":code:`PyTorch` 模型:" #: ../../source/tutorial-quickstart-huggingface.rst:169 msgid "" @@ -12545,9 +12618,9 @@ msgid "" "function:" msgstr "" "现在我们有了实例化客户端的方法,我们需要创建服务器,以便汇总结果。使用 " -"Flower,首先选择一个策略(这里我们使用 :code:`FedAvg`,它将把全局权重定义为每" -"轮所有客户端权重的平均值),然后使用 :code:`flwr.server.start_server`函数,就" -"可以非常轻松地完成这项工作:" +"Flower,首先选择一个策略(这里我们使用 " +":code:`FedAvg`,它将把全局模型参数定义为每轮所有客户端模型参数的平均值)," +"然后使用 :code:`flwr.server.start_server`函数,就可以非常轻松地完成这项工作:" #: ../../source/tutorial-quickstart-huggingface.rst:205 msgid "" @@ -12556,7 +12629,7 @@ msgid "" "display a nice average accuracy and loss for every round)." msgstr "" "使用 :code:`weighted_average` 函数是为了提供一种方法来汇总分布在客户端的指标" -"(基本上,这可以让我们显示每一轮的平均精度和损失)。" +"(基本上,这可以让我们显示每一轮的平均精度和损失值)。" #: ../../source/tutorial-quickstart-huggingface.rst:209 msgid "Putting everything together" @@ -12570,7 +12643,7 @@ msgstr "现在我们可以使用:" msgid "" "And they will be able to connect to the server and start the federated " "training." -msgstr "他们就能连接到服务器,开始联合培训。" +msgstr "他们就能连接到服务器,开始联邦训练。" #: ../../source/tutorial-quickstart-huggingface.rst:223 msgid "" @@ -12589,8 +12662,8 @@ msgid "" "it was just to showcase how simply we could federate a Hugging Face workflow " "using Flower." msgstr "" -"当然,这只是一个非常基本的示例,还可以添加或修改很多内容,只是为了展示我们可" -"以如何简单地使用 Flower 联合 \"拥抱的脸 \"工作流程。" +"当然,这只是一个非常基本的示例,还可以添加或修改很多内容," +"只是为了展示我们可以如何简单地使用 Flower 联合Hugging Face的工作流程。" #: ../../source/tutorial-quickstart-huggingface.rst:230 msgid "" @@ -12604,9 +12677,8 @@ msgstr "" msgid "" "Read this Federated Learning quickstart tutorial for creating an iOS app " "using Flower to train a neural network on MNIST." -msgstr "" -"阅读本 Federated Learning 快速入门教程,了解如何使用 Flower 创建 iOS 应用程" -"序,并在 MNIST 上训练神经网络。" +msgstr "阅读本联邦学习快速入门教程,了解如何使用 Flower 创建 iOS 应用程序,并在 " +"MNIST 上训练神经网络。" #: ../../source/tutorial-quickstart-ios.rst:5 msgid "Quickstart iOS" @@ -12635,9 +12707,8 @@ msgstr "" msgid "" "Our example consists of one Python *server* and two iPhone *clients* that " "all have the same model." -msgstr "" -"我们的示例包括一个 Python 服务器*和两个 iPhone 客户端*,它们都具有相同的模" -"型。" +msgstr "我们的示例包括一个 Python *服务器*和两个 iPhone " +"*客户端*,它们都具有相同的模型。" #: ../../source/tutorial-quickstart-ios.rst:17 msgid "" @@ -12647,9 +12718,9 @@ msgid "" "*server* sends this improved version of the model back to each *client*. A " "complete cycle of weight updates is called a *round*." msgstr "" -"*客户*负责根据其本地数据集为模型生成单独的权重更新。然后,这些更新会被发送到*" -"服务器,由*服务器汇总后生成一个更好的模型。最后,*服务器*将改进后的模型发送回" -"每个*客户端*。一个完整的权重更新周期称为一个*轮*。" +"*客户端*负责根据其本地数据集为模型生成独立的模型参数。然后,这些参数更新会被" +"发送到*服务器*,由*服务器*汇总后生成一个更好的模型。最后,*服务器*将改进后的" +"模型发送回每个*客户端*。一个完整的参数更新周期称为一*轮*。" #: ../../source/tutorial-quickstart-ios.rst:21 msgid "" @@ -12662,7 +12733,7 @@ msgstr "" #: ../../source/tutorial-quickstart-ios.rst:27 msgid "Or Poetry:" -msgstr "" +msgstr "或者Poetry:" #: ../../source/tutorial-quickstart-ios.rst:36 msgid "" @@ -12672,8 +12743,8 @@ msgid "" "client with CoreML, that has been implemented and stored inside the Swift " "SDK. The client implementation can be seen below:" msgstr "" -"现在我们已经安装了所有依赖项,让我们使用 CoreML 作为本地训练管道和 MNIST 作为" -"数据集,运行一个简单的分布式训练。为了简单起见,我们将使用 CoreML 的完整 " +"现在我们已经安装了所有依赖项,让我们使用 CoreML 作为本地训练框架和 MNIST " +"作为数据集,运行一个简单的分布式训练。为了简单起见,我们将使用 CoreML 的完整 " "Flower 客户端,该客户端已在 Swift SDK 中实现并存储。客户端实现如下:" #: ../../source/tutorial-quickstart-ios.rst:72 @@ -12685,11 +12756,12 @@ msgid "" "quickstart. Please refer to the `full code example `_ to learn more about the app." msgstr "" -"让我们在 Xcode 中创建一个新的应用程序项目,并在项目中添加 :code:`flwr` 作为依" -"赖关系。对于我们的应用程序,我们将在 :code:`FLiOSModel.swift` 中存储应用程序" -"的逻辑,在 :code:`ContentView.swift` 中存储 UI 元素。在本快速入门中,我们将更" -"多地关注 :code:`FLiOSModel.swift`。请参阅 \"完整代码示例 `_\" 以了解更多有关应用程序的信息。" +"让我们在 Xcode 中创建一个新的应用程序项目,并在项目中添加 :code:`flwr` " +"作为依赖关系。对于我们的应用程序,我们将在 :code:`FLiOSModel.swift` " +"中存储应用程序的逻辑,在 :code:`ContentView.swift` 中存储 UI " +"元素。在本快速入门中,我们将更多地关注 :code:`FLiOSModel.swift`。请参阅 `" +"完整代码示例 `_ " +"以了解更多有关应用程序的信息。" #: ../../source/tutorial-quickstart-ios.rst:75 msgid "Import Flower and CoreML related packages in :code:`FLiOSModel.swift`:" @@ -12748,7 +12820,7 @@ msgstr "" "这就是客户端。我们只需实现 :code:`Client` 或调用提供的 :code:`MLFlwrClient` " "并调用 :code:`startFlwrGRPC()`。属性 :code:`hostname` 和 :code:`port` 会告诉" "客户端要连接到哪个服务器。这可以通过在应用程序中输入主机名和端口来实现,然后" -"再点击开始按钮启动联合学习进程。" +"再点击开始按钮启动联邦学习进程。" #: ../../source/tutorial-quickstart-ios.rst:131 #: ../../source/tutorial-quickstart-mxnet.rst:226 @@ -12768,7 +12840,7 @@ msgstr "" #: ../../source/tutorial-quickstart-scikitlearn.rst:215 #: ../../source/tutorial-quickstart-tensorflow.rst:112 msgid "Train the model, federated!" -msgstr "联合训练模型!" +msgstr "联邦训练模型!" #: ../../source/tutorial-quickstart-ios.rst:144 #: ../../source/tutorial-quickstart-pytorch.rst:218 @@ -12778,8 +12850,7 @@ msgid "" "With both client and server ready, we can now run everything and see " "federated learning in action. FL systems usually have a server and multiple " "clients. We therefore have to start the server first:" -msgstr "" -"客户端和服务器都已准备就绪,我们现在可以运行一切,看看联合学习的实际效果。FL " +msgstr "客户端和服务器都已准备就绪,我们现在可以运行一切,看看联邦学习的实际效果。FL " "系统通常有一个服务器和多个客户端。因此,我们必须先启动服务器:" #: ../../source/tutorial-quickstart-ios.rst:152 @@ -12802,17 +12873,16 @@ msgid "" "com/adap/flower/blob/main/examples/ios>`_ for this example can be found in :" "code:`examples/ios`." msgstr "" -"恭喜您 您已经成功地在 ios 设备中构建并运行了第一个联合学习系统。本示例的完整" -"源代码 `_ 可在 :code:" -"`examples/ios` 中找到。" +"恭喜您! 您已经成功地在 ios 设备中构建并运行了第一个联邦学习系统。本示例的`" +"完整源代码 `_ 可在 " +":code:`examples/ios` 中找到。" #: ../../source/tutorial-quickstart-jax.rst:-1 msgid "" "Check out this Federated Learning quickstart tutorial for using Flower with " "Jax to train a linear regression model on a scikit-learn dataset." -msgstr "" -"查看此 Federated Learning 快速入门教程,了解如何使用 Flower 和 Jax 在 scikit-" -"learn 数据集上训练线性回归模型。" +msgstr "查看此联邦学习快速入门教程,了解如何使用 Flower 和 Jax 在 scikit-learn " +"数据集上训练线性回归模型。" #: ../../source/tutorial-quickstart-jax.rst:5 msgid "Quickstart JAX" @@ -12822,9 +12892,8 @@ msgstr "快速入门 JAX" msgid "" "Check out this Federated Learning quickstart tutorial for using Flower with " "MXNet to train a Sequential model on MNIST." -msgstr "" -"查看此 Federated Learning 快速入门教程,了解如何使用 Flower 和 MXNet 在 " -"MNIST 上训练序列模型。" +msgstr "查看此联邦学习 快速入门教程,了解如何使用 Flower 和 MXNet 在 MNIST " +"上训练序列模型。" #: ../../source/tutorial-quickstart-mxnet.rst:5 msgid "Quickstart MXNet" @@ -12856,9 +12925,9 @@ msgid "" "Finally, the *server* sends this improved version of the model back to each " "*client*. A complete cycle of parameters updates is called a *round*." msgstr "" -"*客户*负责根据其本地数据集为模型生成单独的模型参数更新。然后,这些更新将被发" -"送到*服务器,由*服务器汇总后生成一个更新的全局模型。最后,*服务器*将这一改进" -"版模型发回给每个*客户端*。一个完整的参数更新周期称为*轮*。" +"*客户端*负责根据其本地数据集为模型生成单独的模型参数更新。然后,这些参数更新" +"将被发送到*服务器*,由*服务器*汇总后生成一个更新的全局模型。最后,*服务器*将" +"这一改进版模型发回给每个*客户端*。一个完整的参数更新周期称为一*轮*。" #: ../../source/tutorial-quickstart-mxnet.rst:20 #: ../../source/tutorial-quickstart-scikitlearn.rst:20 @@ -12882,7 +12951,7 @@ msgid "" "packages/gluon/image/mnist.html>`_." msgstr "" "现在,我们已经安装了所有依赖项,让我们用两个客户端和一个服务器来运行一个简单" -"的分布式训练。我们的训练程序和网络架构基于 MXNet 的 \"手写数字识别教程 " +"的分布式训练。我们的训练程序和网络架构基于 MXNet 的 `手写数字识别教程 " "`_\"。" @@ -12908,17 +12977,15 @@ msgstr "" msgid "" "Define the training and loss with MXNet. We train the model by looping over " "the dataset, measure the corresponding loss, and optimize it." -msgstr "" -"用 MXNet 定义训练和损失。我们在数据集上循环训练模型,测量相应的损失,并对其进" -"行优化。" +msgstr "用 MXNet 定义训练和损失值。我们在数据集上循环训练模型,测量相应的损失值,并对" +"其进行优化。" #: ../../source/tutorial-quickstart-mxnet.rst:111 msgid "" "Next, we define the validation of our machine learning model. We loop over " "the test set and measure both loss and accuracy on the test set." -msgstr "" -"接下来,我们定义机器学习模型的验证。我们在测试集上循环,测量测试集上的损失和" -"准确率。" +msgstr "接下来,我们定义机器学习模型的验证。我们在测试集上循环,测量测试集上的损失值" +"和准确率。" #: ../../source/tutorial-quickstart-mxnet.rst:135 msgid "" @@ -12952,8 +13019,9 @@ msgid "" "e., to train the neural network we defined earlier)." msgstr "" "Flower 服务器通过一个名为 :code:`Client` 的接口与客户端交互。当服务器选择一个" -"特定的客户端进行训练时,它会通过网络发送训练指令。客户端接收到这些指令后,会" -"调用 :code:`Client` 方法之一来运行你的代码(即训练我们之前定义的神经网络)。" +"特定的客户端进行训练时,它会通过网络发送训练指令。客户端接收到这些指令后," +"会调用 :code:`Client` " +"方法之一来运行您的代码(即训练我们之前定义的神经网络)。" #: ../../source/tutorial-quickstart-mxnet.rst:164 msgid "" @@ -12962,15 +13030,15 @@ msgid "" "MXNet. Implementing :code:`NumPyClient` usually means defining the following " "methods (:code:`set_parameters` is optional though):" msgstr "" -"Flower 提供了一个名为 :code:`NumPyClient` 的便利类,当您的工作负载使用 MXNet " -"时,它可以让您更轻松地实现 :code:`Client` 接口。实现 :code:`NumPyClient` 通常" -"意味着定义以下方法(:code:`set_parameters` 是可选的):" +"Flower 提供了一个名为 :code:`NumPyClient` 的便捷类,当您的工作负载使用 MXNet " +"时,它可以让您更轻松地实现 :code:`Client` 接口。实现 :code:`NumPyClient` " +"通常意味着定义以下方法(:code:`set_parameters` 是可选的):" #: ../../source/tutorial-quickstart-mxnet.rst:170 #: ../../source/tutorial-quickstart-pytorch.rst:156 #: ../../source/tutorial-quickstart-scikitlearn.rst:109 msgid "return the model weight as a list of NumPy ndarrays" -msgstr "以 NumPy ndarrays 列表形式返回模型权重" +msgstr "以 NumPy ndarrays 列表形式返回模型参数" #: ../../source/tutorial-quickstart-mxnet.rst:171 #: ../../source/tutorial-quickstart-pytorch.rst:157 @@ -12983,13 +13051,13 @@ msgstr ":code:`set_parameters` (可选)" #: ../../source/tutorial-quickstart-scikitlearn.rst:111 msgid "" "update the local model weights with the parameters received from the server" -msgstr "用从服务器接收到的参数更新本地模型权重" +msgstr "用从服务器接收到的参数更新本地模型参数" #: ../../source/tutorial-quickstart-mxnet.rst:174 #: ../../source/tutorial-quickstart-pytorch.rst:160 #: ../../source/tutorial-quickstart-scikitlearn.rst:114 msgid "set the local model weights" -msgstr "设置本地模型权重" +msgstr "设置本地模型参数" #: ../../source/tutorial-quickstart-mxnet.rst:175 #: ../../source/tutorial-quickstart-pytorch.rst:161 @@ -13001,7 +13069,7 @@ msgstr "训练本地模型" #: ../../source/tutorial-quickstart-pytorch.rst:162 #: ../../source/tutorial-quickstart-scikitlearn.rst:116 msgid "receive the updated local model weights" -msgstr "接收更新的本地模型权重" +msgstr "接收更新的本地模型参数" #: ../../source/tutorial-quickstart-mxnet.rst:178 #: ../../source/tutorial-quickstart-pytorch.rst:164 @@ -13032,6 +13100,13 @@ msgid "" "server and clients running on different machines, all that needs to change " "is the :code:`server_address` we pass to the client." msgstr "" +"对于客户端就需要做这么多。我们仅需要实现 " +":code:`Client`或者:code:`NumPyClient`然后调用:code:`fl.client." +"start_client()`。字符串 :code:`\"0.0.0.0:8080\"` 告诉客户端要连接到哪个服务器" +"。在我们的例子中,我们可以在同一台机器上运行服务器和客户端,因此我们使用:code" +":`\"0.0.0.0:8080\"" +"`。如果我们运行真正联邦学习的工作负载,服务器和客户端在不同的机器上运行," +"则需要更改的只是我们传递给客户端的 server_address 。" #: ../../source/tutorial-quickstart-mxnet.rst:239 msgid "" @@ -13039,8 +13114,8 @@ msgid "" "federated learning in action. Federated learning systems usually have a " "server and multiple clients. We therefore have to start the server first:" msgstr "" -"客户端和服务器都准备就绪后,我们现在就可以运行一切,看看联合学习的运行情况。" -"联合学习系统通常有一个服务器和多个客户端。因此,我们必须先启动服务器:" +"客户端和服务器都准备就绪后,我们现在就可以运行一切,看看联邦学习的运行情况。" +"联邦学习系统通常有一个服务器和多个客户端。因此,我们必须先启动服务器:" #: ../../source/tutorial-quickstart-mxnet.rst:247 #: ../../source/tutorial-quickstart-pytorch.rst:226 @@ -13080,7 +13155,7 @@ msgid "" "main/examples/quickstart-mxnet/client.py>`_ for this example can be found " "in :code:`examples/quickstart-mxnet`." msgstr "" -"恭喜您!您已经成功构建并运行了第一个联合学习系统。本示例的完整源代码 " +"恭喜您!您已经成功构建并运行了第一个联邦学习系统。本示例的`完整源代码 " "`_ 可在 :code:`examples/quickstart-mxnet` 中找到。" @@ -13088,33 +13163,30 @@ msgstr "" msgid "" "Check out this Federated Learning quickstart tutorial for using Flower with " "Pandas to perform Federated Analytics." -msgstr "" -"查看此 Federated Learning 快速入门教程,了解如何使用 Flower 和 Pandas 执行 " -"Federated Analytics。" +msgstr "查看此联邦学习快速入门教程,了解如何使用 Flower 和 Pandas 执行联邦分析。" #: ../../source/tutorial-quickstart-pandas.rst:5 msgid "Quickstart Pandas" -msgstr "快速入门熊猫" +msgstr "快速入门Pandas" #: ../../source/tutorial-quickstart-pandas.rst:10 msgid "Let's build a federated analytics system using Pandas and Flower!" -msgstr "让我们使用 Pandas 和 Flower 建立一个联合分析系统!" +msgstr "让我们使用 Pandas 和 Flower 建立一个联邦分析系统!" #: ../../source/tutorial-quickstart-pandas.rst:12 msgid "" "Please refer to the `full code example `_ to learn more." msgstr "" -"请参阅 \"完整代码示例 `_\" 了解更多信息。" #: ../../source/tutorial-quickstart-pytorch.rst:-1 msgid "" "Check out this Federated Learning quickstart tutorial for using Flower with " "PyTorch to train a CNN model on MNIST." -msgstr "" -"查看此 Federated Learning 快速入门教程,了解如何使用 Flower 和 PyTorch 在 " -"MNIST 上训练 CNN 模型。" +msgstr "查看此联邦学习快速入门教程,了解如何使用 Flower 和 PyTorch 在 MNIST 上训练 " +"CNN 模型。" #: ../../source/tutorial-quickstart-pytorch.rst:13 msgid "" @@ -13178,16 +13250,14 @@ msgid "" "Define the loss and optimizer with PyTorch. The training of the dataset is " "done by looping over the dataset, measure the corresponding loss and " "optimize it." -msgstr "" -"使用 PyTorch 定义损失和优化器。数据集的训练是通过循环数据集、测量相应的损失并" -"对其进行优化来完成的。" +msgstr "使用 PyTorch 定义损失和优化器。数据集的训练是通过循环数据集、测量相应的损失值" +"并对其进行优化来完成的。" #: ../../source/tutorial-quickstart-pytorch.rst:94 msgid "" "Define then the validation of the machine learning network. We loop over " "the test set and measure the loss and accuracy of the test set." -msgstr "" -"然后定义机器学习网络的验证。我们在测试集上循环,测量测试集的损失和准确率。" +msgstr "然后定义机器学习网络的验证。我们在测试集上循环,计算测试集的损失值和准确率。" #: ../../source/tutorial-quickstart-pytorch.rst:113 msgid "" @@ -13216,9 +13286,10 @@ msgid "" "PyTorch. Implementing :code:`NumPyClient` usually means defining the " "following methods (:code:`set_parameters` is optional though):" msgstr "" -"Flower 提供了一个名为 :code:`NumPyClient` 的便利类,当您的工作负载使用 " -"PyTorch 时,它使 :code:`Client` 接口的实现变得更容易。实现 :code:" -"`NumPyClient` 通常意味着定义以下方法(:code:`set_parameters` 是可选的):" +"Flower 提供了一个名为 :code:`NumPyClient` 的便捷类,当您的工作负载使用 " +"PyTorch 时,它使 :code:`Client` 接口的实现变得更容易。实现 " +":code:`NumPyClient` 通常意味着定义以下方法(:code:`set_parameters` " +"是可选的):" #: ../../source/tutorial-quickstart-pytorch.rst:166 msgid "which can be implemented in the following way:" @@ -13244,6 +13315,12 @@ msgid "" "and clients running on different machines, all that needs to change is the :" "code:`server_address` we point the client at." msgstr "" +"对于客户来说就是这样了。我们只需实现 :code:`Client` 或 :code:`NumPyClient` " +"并调用:code:`fl.client.start_client()` 即可。字符串 :code:`\"[::]:8080\"` 告" +"诉客户端要连接到哪个服务器。在我们的例子中,我们可以在同一台机器上运行服务器" +"和客户端,因此我们使用 :code:`\"[::]:8080\"" +"`。如果我们运行真正联邦的工作负载,服务器和客户端运行在不同的机器上," +"则需要更改的只是我们指向客户端的 server_address 。" #: ../../source/tutorial-quickstart-pytorch.rst:271 msgid "" @@ -13252,7 +13329,7 @@ msgid "" "main/examples/quickstart-pytorch/client.py>`_ for this example can be found " "in :code:`examples/quickstart-pytorch`." msgstr "" -"恭喜您!您已经成功构建并运行了第一个联合学习系统。本示例的完整源代码 " +"恭喜您!您已经成功构建并运行了第一个联邦学习系统。本示例的`完整源代码 " "`_ 可以在 :code:`examples/quickstart-pytorch` 中找到。" @@ -13260,9 +13337,8 @@ msgstr "" msgid "" "Check out this Federated Learning quickstart tutorial for using Flower with " "PyTorch Lightning to train an Auto Encoder model on MNIST." -msgstr "" -"查看此 Federated Learning 快速入门教程,了解如何使用 Flower 和 PyTorch " -"Lightning 在 MNIST 上训练自动编码器模型。" +msgstr "查看此联邦学习快速入门教程,了解如何使用 Flower 和 PyTorch Lightning 在 " +"MNIST 上训练自动编码器模型。" #: ../../source/tutorial-quickstart-pytorch-lightning.rst:5 msgid "Quickstart PyTorch Lightning" @@ -13272,27 +13348,26 @@ msgstr "快速入门 PyTorch Lightning" msgid "" "Let's build a horizontal federated learning system using PyTorch Lightning " "and Flower!" -msgstr "让我们使用 PyTorch Lightning 和 Flower 构建一个水平联合学习系统!" +msgstr "让我们使用 PyTorch Lightning 和 Flower 构建一个水平联邦学习系统!" #: ../../source/tutorial-quickstart-pytorch-lightning.rst:12 msgid "" "Please refer to the `full code example `_ to learn more." msgstr "" -"请参阅 \"完整代码示例 `_\" 了解更多信息。" +"请参阅 `完整代码示例 `_ 了解更多信息。" #: ../../source/tutorial-quickstart-scikitlearn.rst:-1 msgid "" "Check out this Federated Learning quickstart tutorial for using Flower with " "scikit-learn to train a linear regression model." -msgstr "" -"查看此 Federated Learning 快速入门教程,了解如何使用 Flower 和 scikit-learn " +msgstr "查看此联邦学习快速入门教程,了解如何使用 Flower 和 scikit-learn " "训练线性回归模型。" #: ../../source/tutorial-quickstart-scikitlearn.rst:5 msgid "Quickstart scikit-learn" -msgstr "" +msgstr "scikit-learn快速入门" #: ../../source/tutorial-quickstart-scikitlearn.rst:10 msgid "" @@ -13320,13 +13395,13 @@ msgid "" "basics:" msgstr "" "现在我们已经安装了所有的依赖项,让我们用两个客户端和一个服务器来运行一个简单" -"的分布式训练。不过,在设置客户端和服务器之前,我们将在 :code:`utils.py` 中定" -"义联合学习设置所需的所有功能。:code:`utils.py`包含定义所有机器学习基础知识的" -"不同函数:" +"的分布式训练。不过,在设置客户端和服务器之前,我们将在 :code:`utils.py` " +"中定义联邦学习设置所需的所有功能。:code:`utils." +"py`包含定义所有机器学习基础知识的不同函数:" #: ../../source/tutorial-quickstart-scikitlearn.rst:45 msgid ":code:`get_model_parameters()`" -msgstr "代码:`get_model_parameters()` 获取模型参数" +msgstr ":code:`get_model_parameters()`" #: ../../source/tutorial-quickstart-scikitlearn.rst:46 msgid "Returns the paramters of a :code:`sklearn` LogisticRegression model" @@ -13334,15 +13409,15 @@ msgstr "返回 :code:`sklearn` LogisticRegression 模型的参数" #: ../../source/tutorial-quickstart-scikitlearn.rst:47 msgid ":code:`set_model_params()`" -msgstr "" +msgstr ":code:`set_model_params()`" #: ../../source/tutorial-quickstart-scikitlearn.rst:48 msgid "Sets the parameters of a :code:`sklean` LogisticRegression model" -msgstr "" +msgstr "设置:code:`sklean`的LogisticRegression模型的参数" #: ../../source/tutorial-quickstart-scikitlearn.rst:49 msgid ":code:`set_initial_params()`" -msgstr "" +msgstr ":code:`set_initial_params()`" #: ../../source/tutorial-quickstart-scikitlearn.rst:50 msgid "Initializes the model parameters that the Flower server will ask for" @@ -13350,7 +13425,7 @@ msgstr "初始化 Flower 服务器将要求的模型参数" #: ../../source/tutorial-quickstart-scikitlearn.rst:51 msgid ":code:`load_mnist()`" -msgstr "" +msgstr ":code:`load_mnist()`" #: ../../source/tutorial-quickstart-scikitlearn.rst:52 msgid "Loads the MNIST dataset using OpenML" @@ -13358,7 +13433,7 @@ msgstr "使用 OpenML 加载 MNIST 数据集" #: ../../source/tutorial-quickstart-scikitlearn.rst:53 msgid ":code:`shuffle()`" -msgstr "" +msgstr ":code:`shuffle()`" #: ../../source/tutorial-quickstart-scikitlearn.rst:54 msgid "Shuffles data and its label" @@ -13366,7 +13441,7 @@ msgstr "对数据及其标签进行洗牌" #: ../../source/tutorial-quickstart-scikitlearn.rst:56 msgid ":code:`partition()`" -msgstr "" +msgstr ":code:`partition()`" #: ../../source/tutorial-quickstart-scikitlearn.rst:56 msgid "Splits datasets into a number of partitions" @@ -13425,9 +13500,10 @@ msgid "" "scikit-learn. Implementing :code:`NumPyClient` usually means defining the " "following methods (:code:`set_parameters` is optional though):" msgstr "" -"Flower 提供了一个名为 :code:`NumPyClient` 的便利类,当你的工作负载使用 " -"scikit-learn 时,它可以让你更容易地实现 :code:`Client` 接口。实现 :code:" -"`NumPyClient` 通常意味着定义以下方法(:code:`set_parameters` 是可选的):" +"Flower 提供了一个名为 :code:`NumPyClient` 的便捷类,当你的工作负载使用 " +"scikit-learn 时,它可以让你更容易地实现 :code:`Client` 接口。实现 " +":code:`NumPyClient` 通常意味着定义以下方法(:code:`set_parameters` " +"是可选的):" #: ../../source/tutorial-quickstart-scikitlearn.rst:112 msgid "is directly imported with :code:`utils.set_model_params()`" @@ -13456,7 +13532,7 @@ msgstr "" #: ../../source/tutorial-quickstart-scikitlearn.rst:162 msgid ":code:`server.py`, import Flower and start the server:" -msgstr ":code:`server.py`, import Flower 并启动服务器:" +msgstr ":code:`server.py`, 导入 Flower 并启动服务器:" #: ../../source/tutorial-quickstart-scikitlearn.rst:173 msgid "" @@ -13465,8 +13541,8 @@ msgid "" "function is called after each federated learning round and gives you " "information about loss and accuracy." msgstr "" -"联合学习轮数在 :code:`fit_round()` 中设置,评估在 :code:`get_evaluate_fn()` " -"中定义。每轮联合学习后都会调用评估函数,并提供有关损失和准确率的信息。" +"联邦学习轮数在 :code:`fit_round()` 中设置,评估在 :code:`get_evaluate_fn()` " +"中定义。每轮联邦学习后都会调用评估函数,并提供有关损失值和准确率的信息。" #: ../../source/tutorial-quickstart-scikitlearn.rst:198 msgid "" @@ -13478,11 +13554,11 @@ msgid "" "start_server(server_address=\"0.0.0.0:8080\", strategy=strategy, config=fl." "server.ServerConfig(num_rounds=3))`." msgstr "" -"代码:`main`包含服务器端参数初始化 :代码:`utils.set_initial_params()`以及聚合" -"策略 :代码:`fl.server.strategy:FedAvg()`。该策略是默认的联合平均(或 FedAvg)" -"策略,有两个客户端,在每轮联合学习后进行评估。可以使用 :code:`fl.server." -"start_server(server_address=\"0.0.0.0:8080\", strategy=strategy, config=fl." -"server.ServerConfig(num_rounds=3))` 命令启动服务器。" +":code:`main`包含服务器端参数初始化:code:`utils.set_initial_params()`" +"以及聚合策略 :code:`fl.server.strategy:FedAvg()`。该策略是默认的联邦平均(或 " +"FedAvg)策略,有两个客户端,在每轮联邦学习后进行评估。可以使用 :code:`fl." +"server.start_server(server_address=\"0.0.0.0:8080\", strategy=strategy, " +"config=fl.server.ServerConfig(num_rounds=3))` 命令启动服务器。" #: ../../source/tutorial-quickstart-scikitlearn.rst:217 msgid "" @@ -13490,8 +13566,8 @@ msgid "" "federated learning in action. Federated learning systems usually have a " "server and multiple clients. We, therefore, have to start the server first:" msgstr "" -"客户端和服务器都准备就绪后,我们现在就可以运行一切,看看联合学习的运行情况。" -"联合学习系统通常有一个服务器和多个客户端。因此,我们必须先启动服务器:" +"客户端和服务器都准备就绪后,我们现在就可以运行一切,看看联邦学习的运行情况。" +"联邦学习系统通常有一个服务器和多个客户端。因此,我们必须先启动服务器:" #: ../../source/tutorial-quickstart-scikitlearn.rst:271 msgid "" @@ -13500,17 +13576,16 @@ msgid "" "main/examples/sklearn-logreg-mnist>`_ for this example can be found in :code:" "`examples/sklearn-logreg-mnist`." msgstr "" -"恭喜您!您已经成功构建并运行了第一个联合学习系统。本示例的完整源代码 " -"`_ 可" -"以在 :code:`examples/sklearn-logreg-mnist` 中找到。" +"恭喜您!您已经成功构建并运行了第一个联邦学习系统。本示例的`完整源代码 " +"`_ " +"可以在 :code:`examples/sklearn-logreg-mnist` 中找到。" #: ../../source/tutorial-quickstart-tensorflow.rst:-1 msgid "" "Check out this Federated Learning quickstart tutorial for using Flower with " "TensorFlow to train a MobilNetV2 model on CIFAR-10." -msgstr "" -"查看此 Federated Learning 快速入门教程,了解如何使用 Flower 和 TensorFlow 在 " -"CIFAR-10 上训练 MobilNetV2 模型。" +msgstr "查看此联邦学习快速入门教程,了解如何使用 Flower 和 TensorFlow 在 CIFAR-10 " +"上训练 MobilNetV2 模型。" #: ../../source/tutorial-quickstart-tensorflow.rst:5 msgid "Quickstart TensorFlow" @@ -13559,9 +13634,9 @@ msgid "" "Keras. The :code:`NumPyClient` interface defines three methods which can be " "implemented in the following way:" msgstr "" -"Flower 提供了一个名为 :code:`NumPyClient` 的便利类,当您的工作负载使用 Keras " -"时,该类可以更轻松地实现 :code:`Client` 接口。:code:`NumPyClient` 接口定义了" -"三个方法,可以通过以下方式实现:" +"Flower 提供了一个名为 :code:`NumPyClient` 的便捷类,当您的工作负载使用 Keras " +"时,该类可以更轻松地实现 :code:`Client` 接口。:code:`NumPyClient` " +"接口定义了三个方法,可以通过以下方式实现:" #: ../../source/tutorial-quickstart-tensorflow.rst:135 msgid "Each client will have its own dataset." @@ -13580,25 +13655,23 @@ msgid "" "main/examples/quickstart-tensorflow/client.py>`_ for this can be found in :" "code:`examples/quickstart-tensorflow/client.py`." msgstr "" -"恭喜您!您已经成功构建并运行了第一个联合学习系统。完整的源代码 `_ " -"可以在 :code:`examples/quickstart-tensorflow/client.py` 中找到。" +"恭喜您!您已经成功构建并运行了第一个联邦学习系统。`完整的源代码 " +"`_ 可以在 :code:`examples/quickstart-tensorflow/client.py` 中找到。" #: ../../source/tutorial-quickstart-xgboost.rst:-1 msgid "" "Check out this Federated Learning quickstart tutorial for using Flower with " "XGBoost to train classification models on trees." -msgstr "" -"查看此 Federated Learning 快速入门教程,了解如何使用 Flower 和 XGBoost 在树上" -"训练分类模型。" +msgstr "查看此联邦学习 快速入门教程,了解如何使用 Flower 和 XGBoost 上训练分类模型。" #: ../../source/tutorial-quickstart-xgboost.rst:5 msgid "Quickstart XGBoost" -msgstr "" +msgstr "XGBoost快速入门" #: ../../source/tutorial-quickstart-xgboost.rst:11 msgid "Federated XGBoost" -msgstr "联邦 XGBoost" +msgstr "联邦化 XGBoost" #: ../../source/tutorial-quickstart-xgboost.rst:13 msgid "" @@ -13692,8 +13765,8 @@ msgid "" "installed, let's run a simple distributed training with two clients and one " "server." msgstr "" -"*客户*负责根据其本地数据集为模型生成单独的权重更新。现在我们已经安装了所有的" -"依赖项,让我们用两个客户端和一个服务器来运行一个简单的分布式训练。" +"*客户端*负责根据其本地数据集为模型生成单独的模型参数更新。现在我们已经安装了" +"所有的依赖项,让我们用两个客户端和一个服务器来运行一个简单的分布式训练。" #: ../../source/tutorial-quickstart-xgboost.rst:57 msgid "" @@ -13752,9 +13825,9 @@ msgid "" "by setting :code:`tree_method` to :code:`gpu_hist`. We use AUC as evaluation " "metric." msgstr "" -"代码:`num_local_round`表示本地树提升的迭代次数。我们默认使用 CPU 进行训练。可" -"以通过将 :code:`tree_method` 设置为 :code:`gpu_hist`,将其转换为 GPU。我们使" -"用 AUC 作为评估指标。" +"代码:`num_local_round`表示本地树的迭代次数。我们默认使用 CPU 进行训练。" +"可以通过将 :code:`tree_method` 设置为 :code:`gpu_hist`,将其转换为 GPU。" +"我们使用 AUC 作为评估指标。" #: ../../source/tutorial-quickstart-xgboost.rst:178 msgid "Flower client definition for XGBoost" @@ -13784,7 +13857,7 @@ msgid "" "Then, we override :code:`get_parameters`, :code:`fit` and :code:`evaluate` " "methods insides :code:`XgbClient` class as follows." msgstr "" -"然后,我们在 :code:`XgbClient` 类中覆盖 :code:`get_parameters`、:code:`fit` " +"然后,我们在 :code:`XgbClient` 类中重写 :code:`get_parameters`、:code:`fit` " "和 :code:`evaluate` 方法如下。" #: ../../source/tutorial-quickstart-xgboost.rst:207 @@ -13795,10 +13868,10 @@ msgid "" "result, let's return an empty tensor in :code:`get_parameters` when it is " "called by the server at the first round." msgstr "" -"与神经网络训练不同,XGBoost 树不是从指定的随机权重开始的。在这种情况下,我们" -"不使用 :code:`get_parameters` 和 :code:`set_parameters` 来初始化 XGBoost 的模" -"型参数。因此,当服务器在第一轮调用 :code:`get_parameters` 时,让我们在 :code:" -"`get_parameters` 中返回一个空张量。" +"与神经网络训练不同,XGBoost 树不是从指定的随机参数开始的。在这种情况下," +"我们不使用 :code:`get_parameters` 和 :code:`set_parameters` 来初始化 XGBoost " +"的模型参数。因此,当服务器在第一轮调用 :code:`get_parameters` 时,让我们在 " +":code:`get_parameters` 中返回一个空张量。" #: ../../source/tutorial-quickstart-xgboost.rst:248 msgid "" @@ -13852,9 +13925,10 @@ msgid "" msgstr "" "这就是客户端。我们只需实现 :code:`客户端`并调用 :code:`fl.client." "start_client()`。字符串 :code:`\"[::]:8080\"`会告诉客户端要连接的服务器。在本" -"例中,我们可以在同一台机器上运行服务器和客户端,因此我们使用 :code:" -"`\"[::]:8080\"`。如果我们运行的是真正的联合工作负载,服务器和客户端运行在不同" -"的机器上,那么需要改变的只是客户端指向的 :code:`server_address`。" +"例中,我们可以在同一台机器上运行服务器和客户端,因此我们使用 :code:`\"[::]:" +"8080\"" +"`。如果我们运行的是真正的联邦工作负载,服务器和客户端运行在不同的机器上," +"那么需要改变的只是客户端指向的 :code:`server_address`。" #: ../../source/tutorial-quickstart-xgboost.rst:308 msgid "" @@ -13862,8 +13936,8 @@ msgid "" "produce a better model. Finally, the *server* sends this improved version of " "the model back to each *client* to finish a complete FL round." msgstr "" -"然后,这些更新会被发送到*服务器,由*服务器汇总后生成一个更好的模型。最后,*服" -"务器*将这个改进版的模型发回给每个*客户端*,以完成一轮完整的 FL。" +"然后,这些更新会被发送到*服务器*,由*服务器*聚合后生成一个更好的模型。最后,*" +"服务器*将这个改进版的模型发回给每个*客户端*,以完成一轮完整的 FL。" #: ../../source/tutorial-quickstart-xgboost.rst:311 msgid "" @@ -13875,7 +13949,7 @@ msgstr "" #: ../../source/tutorial-quickstart-xgboost.rst:313 msgid "We first define a strategy for XGBoost bagging aggregation." -msgstr "我们首先定义了 XGBoost 袋式聚合策略。" +msgstr "我们首先定义了 XGBoost bagging聚合策略。" #: ../../source/tutorial-quickstart-xgboost.rst:336 msgid "" @@ -13892,13 +13966,13 @@ msgstr "然后,我们启动服务器:" #: ../../source/tutorial-quickstart-xgboost.rst:351 msgid "Tree-based bagging aggregation" -msgstr "基于树的袋式聚合" +msgstr "基于树的bagging聚合" #: ../../source/tutorial-quickstart-xgboost.rst:353 msgid "" "You must be curious about how bagging aggregation works. Let's look into the " "details." -msgstr "你一定很好奇袋式聚合是如何工作的。让我们来详细了解一下。" +msgstr "您一定很好奇bagging聚合是如何工作的。让我们来详细了解一下。" #: ../../source/tutorial-quickstart-xgboost.rst:355 msgid "" @@ -13917,8 +13991,8 @@ msgid "" "In :code:`aggregate_fit`, we sequentially aggregate the clients' XGBoost " "trees by calling :code:`aggregate()` function:" msgstr "" -"在 :code:`aggregate_fit` 中,我们通过调用 :code:`aggregate()` 函数,按顺序聚" -"合客户的 XGBoost 树:" +"在 :code:`aggregate_fit` 中,我们通过调用 :code:`aggregate()` 函数," +"按顺序聚合客户端的 XGBoost 树:" #: ../../source/tutorial-quickstart-xgboost.rst:510 msgid "" @@ -13929,16 +14003,15 @@ msgid "" "tree model." msgstr "" "在该函数中,我们首先通过调用 :code:`_get_tree_nums` 获取当前模型和上一个模型" -"的树数和并行树数。然后,对获取的信息进行汇总。然后,汇总树(包含模型权重)," -"生成新的树模型。" +"的树数和并行树数。然后,对获取的信息进行聚合。然后,聚合树(包含模型参数)生" +"成新的树模型。" #: ../../source/tutorial-quickstart-xgboost.rst:515 msgid "" "After traversal of all clients' models, a new global model is generated, " "followed by the serialisation, and sending back to each client." -msgstr "" -"在遍历所有客户的模型后,会生成一个新的全局模型,然后进行序列化,并发回给每个" -"客户。" +msgstr "在遍历所有客户端的模型后,会生成一个新的全局模型,然后进行序列化,并发回给每" +"个客户端。" #: ../../source/tutorial-quickstart-xgboost.rst:520 msgid "Launch Federated XGBoost!" @@ -13951,9 +14024,9 @@ msgid "" "`metrics_distributed`. One can see that the average AUC increases over FL " "rounds." msgstr "" -"恭喜您!您已成功构建并运行了第一个联合 XGBoost 系统。可以在 :code:" -"`metrics_distributed` 中查看 AUC 值。我们可以看到,平均 AUC 随 FL 轮数的增加" -"而增加。" +"恭喜您!您已成功构建并运行了第一个联邦 XGBoost 系统。可以在 " +":code:`metrics_distributed` 中查看 AUC 值。我们可以看到,平均 AUC 随 FL " +"轮数的增加而增加。" #: ../../source/tutorial-quickstart-xgboost.rst:587 msgid "" @@ -13961,12 +14034,12 @@ msgid "" "xgboost-quickstart/>`_ for this example can be found in :code:`examples/" "xgboost-quickstart`." msgstr "" -"此示例的完整源代码 `_ 可在 :code:`examples/xgboost-quickstart` 中找到。" #: ../../source/tutorial-quickstart-xgboost.rst:591 msgid "Comprehensive Federated XGBoost" -msgstr "全面的联邦 XGBoost" +msgstr "综合的联邦 XGBoost" #: ../../source/tutorial-quickstart-xgboost.rst:593 msgid "" @@ -13977,11 +14050,11 @@ msgid "" "more options to define various experimental setups, including data " "partitioning and centralised/distributed evaluation. Let's take a look!" msgstr "" -"既然您已经知道联合 XGBoost 如何与 Flower 协同工作,那么现在就该通过自定义实验" -"设置来运行一些更全面的实验了。在 xgboost-comprehensive 示例 (`完整代码 " -"`_)" -"中,我们提供了更多选项来定义各种实验设置,包括数据分区和集中/分布式评估。让我" -"们一起来看看!" +"既然您已经知道联合 XGBoost 如何与 Flower " +"协同工作,那么现在就该通过自定义实验设置来运行一些更综合的实验了。在 xgboost-" +"comprehensive 示例 (`完整代码 `_)中,我们提供了更多选项来定义各种实验设置," +"包括数据分区和集中/分布式评估。让我们一起来看看!" #: ../../source/tutorial-quickstart-xgboost.rst:599 msgid "Customised data partitioning" @@ -14017,8 +14090,9 @@ msgid "" "conducted by calling :code:`eval_set()` method, and the tested AUC value is " "reported." msgstr "" -"此函数返回一个评估函数,该函数实例化一个 :code:`Booster` 对象,并向其加载全局" -"模型权重。评估通过调用 :code:`eval_set()` 方法进行,并报告测试的 AUC 值。" +"此函数返回一个评估函数,该函数实例化一个 :code:`Booster` " +"对象,并向其加载全局模型参数。评估通过调用 :code:`eval_set()` 方法进行," +"并报告测试的 AUC 值。" #: ../../source/tutorial-quickstart-xgboost.rst:669 msgid "" @@ -14031,7 +14105,7 @@ msgstr "" #: ../../source/tutorial-quickstart-xgboost.rst:673 msgid "Arguments parser" -msgstr "参数 解析器" +msgstr "参数解析器" #: ../../source/tutorial-quickstart-xgboost.rst:675 msgid "" @@ -14049,9 +14123,9 @@ msgid "" "that with :code:`--centralised-eval`, the sever will do centralised " "evaluation and all functionalities for client evaluation will be disabled." msgstr "" -"这允许用户指定总客户数/FL 轮数/参与客户数/评估客户数以及评估方式。请注意,如" -"果使用 :code:`--centralised-eval`,S sever 将进行集中评估,客户端评估的所有功" -"能将被禁用。" +"这允许用户指定总客户数/FL 轮数/参与客户数/评估客户数以及评估方式。请注意," +"如果使用 :code:`--centralised-" +"eval`,服务器将进行集中评估,客户端评估的所有功能将被禁用。" #: ../../source/tutorial-quickstart-xgboost.rst:718 msgid "Then, the argument parser on client side:" @@ -14088,9 +14162,9 @@ msgid "" "xgboost-comprehensive/>`_ for this comprehensive example can be found in :" "code:`examples/xgboost-comprehensive`." msgstr "" -"此综合示例的全部源代码 `_ 可在 :code:`examples/xgboost-comprehensive` 中找" -"到。" +"此综合示例的全部`源代码 `_ 可在 :code:`examples/xgboost-comprehensive` " +"中找到。" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:9 msgid "Build a strategy from scratch" @@ -14106,11 +14180,12 @@ msgid "" "`__)." msgstr "" -"欢迎来到 Flower 联合学习教程的第三部分。在本教程的前几部分,我们介绍了 " -"PyTorch 和 Flower 的联合学习(`part 1 `__),并学习了如何使用策略来定" -"制服务器和客户端的执行(`part 2 `__)。" +"欢迎来到 Flower 联邦学习教程的第三部分。在本教程的前几部分,我们介绍了 " +"PyTorch 和 Flower 的联邦学习(`part 1 `__),并学习了如何使用策略来定制服务器和客户端的执行(`part 2 " +"`__)。" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:13 msgid "" @@ -14118,9 +14193,9 @@ msgid "" "we built previously by creating a custom version of FedAvg (again, using " "`Flower `__ and `PyTorch `__)." msgstr "" -"在本笔记本中,我们将通过创建 FedAvg 的自定义版本(再次使用 `Flower `__ 和 `PyTorch `__),继续定制我们之前构建" -"的联合学习系统。" +"在本笔记中,我们将通过创建 FedAvg 的自定义版本(再次使用 `Flower " +"`__ 和 `PyTorch `__),继续定制我们之前构建的联邦学习系统。" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:15 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:16 @@ -14140,7 +14215,7 @@ msgstr "" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:17 msgid "Let's build a new ``Strategy`` from scratch!" -msgstr "让我们从头开始构建一个新的 \"策略\"!" +msgstr "让我们从头开始构建一个新的``Strategy``!" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:29 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:29 @@ -14292,10 +14367,10 @@ msgid "" "the constructor of your new class (``__init__``) and then call these " "functions whenever needed." msgstr "" -"在本笔记本中,我们了解了如何实施自定义策略。自定义策略可以对客户端节点配置、" -"结果聚合等进行细粒度控制。要定义自定义策略,只需覆盖(抽象)基类 " -"``Strategy`` 的抽象方法即可。为使自定义策略更加强大,您可以将自定义函数传递给" -"新类的构造函数(`__init__``),然后在需要时调用这些函数。" +"在本笔记中,我们了解了如何实施自定义策略。自定义策略可以对客户端节点配置、结" +"果聚合等进行细粒度控制。要定义自定义策略,只需覆盖(抽象)基类 ``Strategy`` " +"的抽象方法即可。为使自定义策略更加强大,您可以将自定义函数传递给新类的构造函" +"数(`__init__``),然后在需要时调用这些函数。" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:550 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:948 @@ -14365,11 +14440,11 @@ msgid "" "we didn't have before, but we'll also have to do a few things the we didn't " "have to do before." msgstr "" -"在本笔记中,我们将重温 ``NumPyClient`` 并引入一个用于构建客户端的新基类,简单" -"命名为 ``Client``。在本教程的前几部分中,我们的客户端基于``NumPyClient``,这" -"是一个方便类,可以让我们轻松地与具有良好 NumPy 互操作性的机器学习库协同工作。" -"有了 ``Client``,我们获得了很多以前没有的灵活性,但我们也必须做一些以前不需要" -"做的事情。" +"在本笔记中,我们将重温 ``NumPyClient`` 并引入一个用于构建客户端的新基类," +"简单命名为 ``Client``。在本教程的前几部分中,我们的客户端基于``NumPyClient``" +",这是一个便捷类,可以让我们轻松地与具有良好 NumPy " +"互操作性的机器学习库协同工作。有了 ``Client``,我们获得了很多以前没有的灵活性" +",但我们也必须做一些以前不需要做的事情。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:18 msgid "" @@ -14413,15 +14488,15 @@ msgid "" "``FlowerClient`` to ``FlowerNumPyClient`` and ``client_fn`` to " "``numpyclient_fn``. Let's run it to see the output we get:" msgstr "" -"我们以前见过这种情况,目前没有什么新东西。与之前的笔记本相比,唯一*小*的不同" -"是命名,我们把 ``FlowerClient`` 改成了 ``FlowerNumPyClient``,把 `client_fn` " +"我们以前见过这种情况,目前没有什么新东西。与之前的笔记相比,唯一*小*的不同是" +"命名,我们把 ``FlowerClient`` 改成了 ``FlowerNumPyClient``,把 `client_fn` " "改成了 ``numpyclient_fn``。让我们运行它看看输出结果:" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:339 msgid "" "This works as expected, two clients are training for three rounds of " "federated learning." -msgstr "结果不出所料,两个客户端正在进行三轮联合学习培训。" +msgstr "结果不出所料,两个客户端正在进行三轮联邦学习训练。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:341 msgid "" @@ -14446,9 +14521,9 @@ msgid "" msgstr "" "但令人惊讶的部分也许就在这里: Flower 实际上并不直接使用 " "``FlowerNumPyClient`` 对象。相反,它封装了该对象,使其看起来像 ``flwr.client." -"Client`` 的子类,而不是 ``flwr.client.NumPyClient``。事实上,Flower 核心框架" -"不知道如何处理 ``NumPyClient``,它只知道如何处理 ``Client``。``NumPyClient`` " -"只是建立在``Client``之上的方便抽象。" +"Client`` 的子类,而不是 ``flwr.client.NumPyClient``。事实上,Flower " +"核心框架不知道如何处理 ``NumPyClient``,它只知道如何处理 " +"``Client``。``NumPyClient`` 只是建立在``Client``之上的便捷抽象类。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:345 msgid "" @@ -14496,13 +14571,14 @@ msgid "" "which (finally!) deserializes them again in order to aggregate them with the " "updates received from other clients." msgstr "" -"首先,它的代码更多。但为什么呢?区别在于 ``Client`` 希望我们处理参数的序列化" -"和反序列化。Flower 要想通过网络发送参数,最终需要将这些参数转化为 ``字节``。" -"把参数(例如 NumPy 的 ``ndarray``'s 参数)变成原始字节叫做序列化。将原始字节" -"转换成更有用的东西(如 NumPy ``ndarray``s)称为反序列化。Flower 需要同时做这" -"两件事:它需要在服务器端序列化参数并将其发送到客户端,客户端需要反序列化参数" -"以便将其用于本地训练,然后再次序列化更新后的参数并将其发送回服务器,服务器" -"(最后!)再次反序列化参数以便将其与从其他客户端接收到的更新汇总在一起。" +"首先,它的代码更多。但为什么呢?区别在于 ``Client`` " +"希望我们处理参数的序列化和反序列化。Flower 要想通过网络发送参数," +"最终需要将这些参数转化为 ``字节``。把参数(例如 NumPy 的 ``ndarray`` " +"参数)变成原始字节叫做序列化。将原始字节转换成更有用的东西(如 NumPy " +"``ndarray`)称为反序列化。Flower 需要同时做这两件事:它需要在服务器端序列化参" +"数并将其发送到客户端,客户端需要反序列化参数以便将其用于本地训练,然后再次序" +"列化更新后的参数并将其发送回服务器,服务器(最后)再次反序列化参数以便将其与" +"从其他客户端接收到的更新汇总在一起。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:495 msgid "" @@ -14512,10 +14588,10 @@ msgid "" "knows how to handle these. This makes working with machine learning " "libraries that have good NumPy support (most of them) a breeze." msgstr "" -"Client 与 NumPyClient 之间的唯一**真正区别在于,NumPyClient 会为你处理序列化" -"和反序列化。NumPyClient之所以能做到这一点,是因为它预计你会以NumPy ndarray的" -"形式返回参数,而且它知道如何处理这些参数。这使得与具有良好 NumPy 支持的机器学" -"习库(大多数)一起工作变得轻而易举。" +"Client 与 NumPyClient 之间的唯一**真正区别在于,NumPyClient " +"会为你处理序列化和反序列化。NumPyClient之所以能做到这一点," +"是因为它预计你会以NumPy ndarray的形式返回参数,而且它知道如何处理这些参数。" +"这使得与具有良好 NumPy 支持的大多数机器学习库一起工作变得轻而易举。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:497 msgid "" @@ -14564,9 +14640,8 @@ msgid "" "Federated Learning relies heavily on internet communication for training by " "sending Python objects back and forth between the clients and the server. " "This means that serialization is an essential part of Federated Learning." -msgstr "" -"通过在客户端和服务器之间来回发送 Python 对象,联合学习在很大程度上依赖于互联" -"网通信进行训练。这意味着序列化是 Federated Learning 的重要组成部分。" +msgstr "通过在客户端和服务器之间来回发送 Python 对象,联合学习在很大程度上依赖于互联" +"网通信进行训练。这意味着序列化是联邦学习的重要组成部分。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:518 msgid "" @@ -14578,10 +14653,10 @@ msgid "" "entries), converting them to a sparse matrix can greatly improve their " "bytesize." msgstr "" -"在下面的章节中,我们将编写一个基本示例,在发送包含参数的 ``ndarray`` s 之前," +"在下面的章节中,我们将编写一个基本示例,在发送包含参数的 ``ndarray`` 前," "我们将首先把 ``ndarray`` 转换为稀疏矩阵,而不是发送序列化版本。这种技术可以用" -"来节省带宽,因为在某些情况下,模型的权重是稀疏的(包含许多 0 条目),将它们转" -"换成稀疏矩阵可以大大提高它们的字节数。" +"来节省带宽,因为在某些情况下,模型的参数是稀疏的(包含许多 0 " +"条目),将它们转换成稀疏矩阵可以大大提高它们的字节数。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:521 msgid "Our custom serialization/deserialization functions" @@ -14611,8 +14686,7 @@ msgstr "客户端" msgid "" "To be able to able to serialize our ``ndarray``\\ s into sparse parameters, " "we will just have to call our custom functions in our ``flwr.client.Client``." -msgstr "" -"为了能够将我们的 ``ndarray``s 序列化为稀疏参数,我们只需在 ``flwr.client." +msgstr "为了能够将我们的 ``ndarray`` 序列化为稀疏参数,我们只需在 ``flwr.client." "Client`` 中调用我们的自定义函数。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:617 @@ -14630,9 +14704,9 @@ msgid "" "server using our custom ``sparse_parameters_to_ndarrays`` and then we need " "to serialize our local results with ``ndarrays_to_sparse_parameters``." msgstr "" -"在 ``fit`` 中,我们首先需要使用自定义的 ``sparse_parameters_too_ndarrays`` 反" -"序列化来自服务器的参数,然后使用 ``ndarrays_too_sparse_parameters`` 序列化本" -"地结果。" +"在 ``fit`` 中,我们首先需要使用自定义的 ``sparse_parameters_to_ndarrays`` " +"反序列化来自服务器的参数,然后使用 ``ndarrays_to_sparse_parameters`` " +"序列化本地结果。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:621 msgid "" @@ -14683,10 +14757,11 @@ msgid "" "``NumPyClient``. In order to do so, it requires us to handle parameter " "serialization and deserialization ourselves." msgstr "" -"在本部分教程中,我们已经了解了如何通过子类化 ``NumPyClient`` 或 ``Client`` 来" -"构建客户端。NumPyClient \"是一个方便的抽象,可以让我们更容易地与具有良好NumPy" -"互操作性的机器学习库一起工作。Client``是一个更灵活的抽象,允许我们做一些在" -"`NumPyClient``中做不到的事情。为此,它要求我们自己处理参数序列化和反序列化。" +"在本部分教程中,我们已经了解了如何通过子类化 ``NumPyClient`` 或 ``Client`` " +"来构建客户端。NumPyClient \"是一个便捷的抽象类,可以让我们更容易地与具有良好N" +"umPy互操作性的机器学习库一起工作。``Client``是一个更灵活的抽象类,允许我们做" +"一些在`NumPyClient``中做不到的事情。为此,它要求我们自己处理参数序列化和反序" +"列化。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:952 msgid "" @@ -14694,13 +14769,12 @@ msgid "" "You're now well equipped to understand the rest of the documentation. There " "are many topics we didn't cover in the tutorial, we recommend the following " "resources:" -msgstr "" -"这是 Flower 教程的最后一部分(暂时!),恭喜你!你现在已经具备了理解其余文档" -"的能力。本教程还有许多内容没有涉及,我们推荐您参考以下资源:" +msgstr "这暂时是 Flower 教程的最后一部分,恭喜您!您现在已经具备了理解其余文档的能力" +"。本教程还有许多内容没有涉及,我们推荐您参考以下资源:" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:954 msgid "`Read Flower Docs `__" -msgstr "阅读花朵文档 `__" +msgstr "阅读Flower文档 `__" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:955 msgid "" @@ -14713,7 +14787,7 @@ msgstr "" msgid "" "`Use Flower Baselines for your research `__" -msgstr "使用 \"Flower基准 \"进行研究 `__" +msgstr "使用 \"Flower Baselines \"进行研究 `__" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:957 msgid "" @@ -14729,7 +14803,7 @@ msgstr "开始使用Flower" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:11 #: ../../source/tutorial-series-what-is-federated-learning.ipynb:11 msgid "Welcome to the Flower federated learning tutorial!" -msgstr "欢迎阅读Flower联合学习教程!" +msgstr "欢迎阅读Flower联邦学习教程!" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:13 msgid "" @@ -14738,9 +14812,9 @@ msgid "" "loading. In part 2, we continue to federate the PyTorch-based pipeline using " "Flower." msgstr "" -"在本笔记本中,我们将使用 Flower 和 PyTorch 构建一个联合学习系统。在第一部分" -"中,我们使用 PyTorch 进行模型训练和数据加载。在第二部分中,我们将继续使用 " -"Flower 联合基于 PyTorch 的管道。" +"在本笔记中,我们将使用 Flower 和 PyTorch 构建一个联邦学习系统。在第一部分中," +"我们使用 PyTorch 进行模型训练和数据加载。在第二部分中,我们将继续使用 Flower " +"联邦化基于 PyTorch 的框架。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:17 msgid "Let's get stated!" @@ -14786,18 +14860,17 @@ msgid "" "splitting because each organization already has their own data (so the data " "is naturally partitioned)." msgstr "" -"我们通过将原始 CIFAR-10 数据集拆分成多个分区来模拟来自多个组织的多个数据集" -"(也称为联合学习中的 \"跨分区 \"设置)。每个分区代表一个组织的数据。我们这样" -"做纯粹是为了实验目的,在现实世界中不需要拆分数据,因为每个组织都已经有了自己" -"的数据(所以数据是自然分区的)。" +"我们通过将原始 CIFAR-10 数据集拆分成多个分区来模拟来自多个组织的多个数据集(" +"也称为联邦学习中的 \"跨分区 \"设置)。每个分区代表一个组织的数据。我们这样做" +"纯粹是为了实验目的,在现实世界中不需要拆分数据,因为每个组织都已经有了自己的" +"数据(所以数据是自然分区的)。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:152 msgid "" "Each organization will act as a client in the federated learning system. So " "having ten organizations participate in a federation means having ten " "clients connected to the federated learning server:" -msgstr "" -"每个组织都将充当联合学习系统中的客户端。因此,有十个组织参与联邦学习,就意味" +msgstr "每个组织都将充当联邦学习系统中的客户端。因此,有十个组织参与联邦学习,就意味" "着有十个客户端连接到联邦学习服务器:" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:172 @@ -14821,11 +14894,11 @@ msgid "" "learning systems have their data naturally distributed across multiple " "partitions." msgstr "" -"现在,我们有一个包含十个训练集和十个验证集(`trainloaders`` 和`valloaders``)" -"的列表,代表十个不同组织的数据。每对 ``trainloader``/``valloader`` 都包含 " -"4500 个训练示例和 500 个验证示例。还有一个单独的 ``测试加载器``(我们没有拆分" -"测试集)。同样,这只有在构建研究或教育系统时才有必要,实际的联合学习系统的数" -"据自然分布在多个分区中。" +"现在,我们有一个包含十个训练集和十个验证集(`trainloaders`` " +"和`valloaders``)的列表,代表十个不同组织的数据。每对 " +"``trainloader``/``valloader`` 都包含 4500 个训练示例和 500 个验证数据。" +"还有一个单独的 ``测试加载器``(我们没有拆分测试集)。同样,这只有在构建研究或" +"教育系统时才有必要,实际的联邦学习系统的数据自然分布在多个分区中。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:225 msgid "" @@ -14849,7 +14922,7 @@ msgstr "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:276 msgid "Step 1: Centralized Training with PyTorch" -msgstr "步骤 1:使用 PyTorch 进行集中培训" +msgstr "步骤 1:使用 PyTorch 进行集中训练" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:287 msgid "" @@ -14861,14 +14934,14 @@ msgid "" "deep_learning_60min_blitz.html>`__." msgstr "" "接下来,我们将使用 PyTorch 来定义一个简单的卷积神经网络。本介绍假定您对 " -"PyTorch 有基本的了解,因此不会详细介绍与 PyTorch 相关的内容。如果你想更深入地" -"了解 PyTorch,我们推荐你阅读 \"DEEP LEARNING WITH PYTORCH: a 60 minute " -"blitz `__。" +"PyTorch 有基本的了解,因此不会详细介绍与 PyTorch 相关的内容。" +"如果你想更深入地了解 PyTorch,我们推荐你阅读 `DEEP LEARNING WITH PYTORCH: a " +"60 minute blitz `__。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:299 msgid "Defining the model" -msgstr "确定模式" +msgstr "定义模型" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:301 msgid "" @@ -14876,7 +14949,7 @@ msgid "" "org/tutorials/beginner/blitz/cifar10_tutorial.html#define-a-convolutional-" "neural-network>`__:" msgstr "" -"我们使用 PyTorch 教程 `__ 中描述的简单 " "CNN:" @@ -14909,13 +14982,13 @@ msgid "" "just to show a simplistic centralized training pipeline that sets the stage " "for what comes next - federated learning!" msgstr "" -"在我们的 CIFAR-10 分片上对简单 CNN 进行 5 个历元的训练后,测试集的准确率应为 " +"在我们的 CIFAR-10 分片上对简单 CNN 进行 5 个遍历的训练后,测试集的准确率应为 " "41%,这并不理想,但同时对本教程而言也并不重要。我们只是想展示一个简单的集中式" -"训练管道,为接下来的联合学习做好铺垫!" +"训练流程,为接下来的联邦学习做好铺垫!" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:442 msgid "Step 2: Federated Learning with Flower" -msgstr "步骤 2:与 Flower 联合学习" +msgstr "步骤 2:使用 Flower 联邦学习" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:444 msgid "" @@ -14925,9 +14998,9 @@ msgid "" "organizations and where we train a model over these organizations using " "federated learning." msgstr "" -"步骤 1 演示了一个简单的集中式训练管道。所有数据都在一个地方(即一个 " +"步骤 1 演示了一个简单的集中式训练流程。所有数据都在一个地方(即一个 " "\"trainloader \"和一个 \"valloader\")。接下来,我们将模拟在多个组织中拥有多" -"个数据集的情况,并使用联合学习在这些组织中训练一个模型。" +"个数据集的情况,并使用联邦学习在这些组织中训练一个模型。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:456 msgid "Updating model parameters" @@ -14955,8 +15028,8 @@ msgid "" "functions do just that for the PyTorch model above." msgstr "" "我们需要两个辅助函数,用从服务器接收到的参数更新本地模型,并从本地模型获取更" -"新后的模型参数: set_parameters```和`get_parameters``。下面两个函数就是为上面" -"的 PyTorch 模型做这些工作的。" +"新后的模型参数:`` set_parameters```和`get_parameters``。" +"下面两个函数就是为上面的 PyTorch 模型做这些工作的。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:462 msgid "" @@ -14972,7 +15045,7 @@ msgstr "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:490 msgid "Implementing a Flower client" -msgstr "实施 Flower 客户端" +msgstr "实现 Flower 客户端" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:492 msgid "" @@ -14982,10 +15055,10 @@ msgid "" "``flwr.client.NumPyClient``. We use ``NumPyClient`` in this tutorial because " "it is easier to implement and requires us to write less boilerplate." msgstr "" -"说完这些,让我们进入有趣的部分。联合学习系统由一个服务器和多个客户端组成。在 " -"Flower 中,我们通过实现 ``flwr.client.Client`` 或 ``flwr.client." -"NumPyClient`` 的子类来创建客户端。在本教程中,我们使用``NumPyClient``,因为它" -"更容易实现,需要我们编写的模板也更少。" +"说完这些,让我们进入有趣的部分。联邦学习系统由一个服务器和多个客户端组成。在 " +"Flower 中,我们通过实现 ``flwr.client.Client`` 或 ``flwr.client.NumPyClient``" +" 的子类来创建客户端。在本教程中,我们使用``NumPyClient``,因为它更容易实现," +"需要我们编写的模板也更少。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:494 msgid "" @@ -14998,24 +15071,22 @@ msgstr "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:496 msgid "``get_parameters``: Return the current local model parameters" -msgstr "`get_parameters``: 返回当前本地模型参数" +msgstr "``get_parameters``: 返回当前本地模型参数" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:497 msgid "" "``fit``: Receive model parameters from the server, train the model " "parameters on the local data, and return the (updated) model parameters to " "the server" -msgstr "" -"`fit``: 从服务器接收模型参数,在本地数据上训练模型参数,并将(更新的)模型参" -"数返回服务器" +msgstr "``fit``: 从服务器接收模型参数,在本地数据上训练模型参数,并将(更新的)模型" +"参数返回服务器" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:498 msgid "" "``evaluate``: Receive model parameters from the server, evaluate the model " "parameters on the local data, and return the evaluation result to the server" -msgstr "" -"`评估``: 从服务器接收模型参数,在本地数据上评估模型参数,并将评估结果返回服" -"务器" +msgstr "``evaluate ``: " +"从服务器接收模型参数,在本地数据上评估模型参数,并将评估结果返回服务器" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:500 msgid "" @@ -15041,11 +15112,12 @@ msgid "" msgstr "" "我们的类 ``FlowerClient`` 定义了本地训练/评估的执行方式,并允许 Flower 通过 " "``fit`` 和 ``evaluate`` 调用本地训练/评估。每个 ``FlowerClient`` 实例都代表联" -"合学习系统中的*单个客户端*。联合学习系统有多个客户端(否则就没有什么可联合" -"的),因此每个客户端都将由自己的 ``FlowerClient`` 实例来代表。例如,如果我们" -"的工作负载中有三个客户端,那么我们就会有三个 ``FlowerClient`` 实例。当服务器" -"选择特定客户端进行训练时,Flower 会调用相应实例上的 ``FlowerClient.fit`` (评" -"估时调用 ``FlowerClient.evaluate``)。" +"邦学习系统中的*单个客户端*。联邦学习系统有多个客户端(否则就没有什么可联邦的" +"),因此每个客户端都将由自己的 ``FlowerClient`` " +"实例来代表。例如,如果我们的工作负载中有三个客户端,那么我们就会有三个 " +"``FlowerClient`` 实例。当服务器选择特定客户端进行训练时,Flower " +"会调用相应实例上的 ``FlowerClient.fit`` (评估时调用 ``FlowerClient." +"evaluate``)。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:541 msgid "Using the Virtual Client Engine" @@ -15061,10 +15133,11 @@ msgid "" "memory resources, even if only a subset of these clients participates in a " "single round of federated learning." msgstr "" -"在本笔记本中,我们要模拟一个联合学习系统,在一台机器上有 10 个客户端。这意味" -"着服务器和所有 10 个客户端都将位于一台机器上,并共享 CPU、GPU 和内存等资源。" -"有 10 个客户端就意味着内存中有 10 个 ``FlowerClient`` 实例。在单台机器上这样" -"做会很快耗尽可用的内存资源,即使这些客户端中只有一个子集参与了一轮联合学习。" +"在本笔记中,我们要模拟一个联邦学习系统,在一台机器上有 10 个客户端。" +"这意味着服务器和所有 10 个客户端都将位于一台机器上,并共享 CPU、GPU " +"和内存等资源。有 10 个客户端就意味着内存中有 10 个 ``FlowerClient`` 实例。在" +"单台机器上这样做会很快耗尽可用的内存资源,即使这些客户端中只有一个子集参与了" +"一轮联邦学习。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:545 msgid "" @@ -15116,10 +15189,9 @@ msgid "" "federated learning approach/algorithm, for example, *Federated Averaging* " "(FedAvg)." msgstr "" -"函数 ``start_simulation`` 接受许多参数,其中包括用于创建 ``FlowerClient`` 实" -"例的 ``client_fn``、要模拟的客户端数量(``num_clients``)、联合学习轮数" -"(``num_rounds``)和策略。策略封装了联合学习方法/算法,例如*联合平均* " -"(FedAvg)。" +"函数 ``start_simulation`` 接受许多参数,其中包括用于创建 ``FlowerClient`` " +"实例的 ``client_fn``、要模拟的客户端数量(``num_clients``)、联邦学习轮数(``" +"num_rounds``)和策略。策略封装了联邦学习方法/算法,例如*联邦平均* (FedAvg)。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:586 msgid "" @@ -15130,17 +15202,18 @@ msgid "" "is the actual call to ``start_simulation`` which - you guessed it - starts " "the simulation:" msgstr "" -"Flower 有许多内置策略,但我们也可以使用自己的策略实现来定制联合学习方法的几乎" -"所有方面。在本例中,我们使用内置的 ``FedAvg`` 实现,并使用一些基本参数对其进" -"行定制。最后一步是实际调用 ``start_simulation``,你猜对了,就是开始模拟:" +"Flower 有许多内置策略,但我们也可以使用自己的策略实现来定制联邦学习方法的几乎" +"所有方面。在本例中,我们使用内置的 ``FedAvg`` " +"实现,并使用一些基本参数对其进行定制。最后一步是实际调用 " +"``start_simulation``开始模拟:" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:628 msgid "Behind the scenes" -msgstr "幕后花絮" +msgstr "幕后" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:630 msgid "So how does this work? How does Flower execute this simulation?" -msgstr "那么它是如何工作的呢?Flower \"如何进行模拟?" +msgstr "那么它是如何工作的呢?Flower 如何进行模拟?" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:632 #, python-format @@ -15164,13 +15237,13 @@ msgid "" "aggregates those updates and returns the new global model, which then gets " "used in the next round of federated learning." msgstr "" -"然后,\"Flower \"会要求选定的 10 个客户端对模型进行训练。服务器收到客户端的模" -"型参数更新后,会将这些更新交给策略(*FedAvg*)进行汇总。策略会汇总这些更新并" -"返回新的全局模型,然后将其用于下一轮联合学习。" +"然后,Flower 会要求选定的 10 个客户端对模型进行训练。服务器收到客户端的模型参" +"数更新后,会将这些更新交给策略(*FedAvg*)进行聚合。策略会聚合这些更新并返回" +"新的全局模型,然后将其用于下一轮联邦学习。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:646 msgid "Where's the accuracy?" -msgstr "准确性体现在哪里?" +msgstr "准确度在哪里找?" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:648 msgid "" @@ -15189,10 +15262,10 @@ msgid "" "all, so the framework does not (and can not) know how to handle these " "automatically." msgstr "" -"Flower 可以自动汇总单个客户端返回的损失,但无法对通用度量字典中的度量进行同样" -"的处理(即带有 \"准确度 \"键的度量字典)。度量值字典可以包含非常不同种类的度" -"量值,甚至包含根本不是度量值的键/值对,因此框架不知道(也无法知道)如何自动处" -"理这些度量值。" +"Flower 可以自动汇总单个客户端返回的损失值,但无法对通用度量字典中的度量进行同" +"样的处理(即带有 \"准确度 \"键的度量字典)。度量值字典可以包含非常不同种类的" +"度量值,甚至包含根本不是度量值的键/值对,因此框架不知道(也无法知道)如何自动" +"处理这些度量值。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:652 msgid "" @@ -15230,9 +15303,9 @@ msgid "" "evaluation metrics and calculates a single ``accuracy`` metric across all " "clients on the server side." msgstr "" -"我们现在有了一个完整的系统,可以执行联合训练和联合评估。它使用 " -"``weighted_average`` 函数汇总自定义评估指标,并在服务器端计算所有客户端的单" -"一 ``accuracy`` 指标。" +"我们现在有了一个完整的系统,可以执行联邦训练和联邦评估。它使用 " +"``weighted_average`` 函数汇总自定义评估指标," +"并在服务器端计算所有客户端的单一 ``accuracy`` 指标。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:719 msgid "" @@ -15258,9 +15331,10 @@ msgid "" "classification), for example NLP with Hugging Face Transformers or speech " "with SpeechBrain." msgstr "" -"恭喜你,你刚刚训练了一个由 10 个客户端组成的卷积神经网络!这样,你就了解了使" -"用 Flower 进行联合学习的基础知识。你所看到的方法同样适用于其他机器学习框架" -"(不只是 PyTorch)和任务(不只是 CIFAR-10 图像分类),例如使用 Hugging Face " +"恭喜您,你刚刚训练了一个由 10 个客户端组成的卷积神经网络!这样," +"你就了解了使用 Flower " +"进行联邦学习的基础知识。你所看到的方法同样适用于其他机器学习框架(不只是 " +"PyTorch)和任务(不只是 CIFAR-10 图像分类),例如使用 Hugging Face " "Transformers 的 NLP 或使用 SpeechBrain 的语音。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:735 @@ -15270,9 +15344,9 @@ msgid "" "evaluate the aggregated model on the server side? We'll cover all this and " "more in the next tutorial." msgstr "" -"在下一个笔记本中,我们将介绍一些更先进的概念。想定制你的策略吗?在服务器端初" -"始化参数?或者在服务器端评估聚合模型?我们将在下一个教程中介绍所有这些内容以" -"及更多。" +"在下一个笔记中,我们将介绍一些更先进的概念。想定制你的策略吗?在服务器端初始" +"化参数?或者在服务器端评估聚合模型?我们将在下一个教程中介绍所有这些内容以及" +"更多。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:753 msgid "" @@ -15281,9 +15355,9 @@ msgid "" "into more depth about strategies and all the advanced things you can build " "with them." msgstr "" -"Flower 联合学习教程 - 第 2 部分 `__ 更深入地介绍了策略以及可以" -"使用策略构建的所有高级功能。" +"`Flower 联邦学习教程 - 第 2 部分 `__ " +"更深入地介绍了策略以及可以使用策略构建的所有高级功能。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:9 msgid "Use a federated learning strategy" @@ -15296,9 +15370,9 @@ msgid "" "Flower (`part 1 `__)." msgstr "" -"欢迎来到联合学习教程的下一部分。在本教程的前几部分,我们介绍了使用 PyTorch " -"和 Flower 进行联合学习(\"第 1 部分 `___\")。" +"欢迎来到联邦学习教程的下一部分。在本教程的前几部分,我们介绍了使用 PyTorch " +"和 Flower 进行联邦学习(`第 1 部分 `___)。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:13 msgid "" @@ -15306,8 +15380,8 @@ msgid "" "built in the introductory notebook (again, using `Flower `__ and `PyTorch `__)." msgstr "" -"在本笔记本中,我们将开始定制在入门笔记本中构建的联合学习系统(再次使用 " -"`Flower `__ 和 `PyTorch `__)。" +"在本笔记中,我们将开始定制在入门笔记中构建的联邦学习系统(再次使用 `Flower " +"`__ 和 `PyTorch `__)。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:17 msgid "Let's move beyond FedAvg with Flower strategies!" @@ -15315,7 +15389,7 @@ msgstr "让我们超越 FedAvg,采用Flower策略!" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:309 msgid "Strategy customization" -msgstr "战略定制" +msgstr "策略定制" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:311 msgid "" @@ -15372,8 +15446,7 @@ msgid "" "The strategy encapsulates the federated learning approach/algorithm, for " "example, ``FedAvg`` or ``FedAdagrad``. Let's try to use a different strategy " "this time:" -msgstr "" -"该策略封装了联合学习方法/算法,例如`FedAvg``或`FedAdagrad``。这次让我们尝试使" +msgstr "该策略封装了联邦学习方法/算法,例如`FedAvg``或`FedAdagrad``。这次让我们尝试使" "用不同的策略:" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:424 @@ -15433,7 +15506,7 @@ msgid "" "implementing the ``evaluate`` method in ``FlowerClient``). Now let's see how " "we can evaluate aggregated model parameters on the server-side:" msgstr "" -"我们已经了解了联合评估如何在客户端工作(即通过在 ``FlowerClient`` 中实现 " +"我们已经了解了联邦评估如何在客户端工作(即通过在 ``FlowerClient`` 中实现 " "``evaluate`` 方法)。现在让我们看看如何在服务器端评估聚合模型参数:" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:490 @@ -15455,12 +15528,12 @@ msgid "" "the number of local training epochs:" msgstr "" "在某些情况下,我们希望从服务器端配置客户端的执行(训练、评估)。其中一个例子" -"就是服务器要求客户端训练一定数量的本地历元。Flower 提供了一种使用字典从服务器" -"向客户端发送配置值的方法。让我们来看一个例子:客户端通过 ``fit`` 中的 " -"``config`` 参数从服务器接收配置值(``evaluate`` 中也有 ``config`` 参数)。" -"``fit`` 方法通过 ``config`` 参数接收配置字典,然后从字典中读取值。在本例中," -"它读取了 ``server_round`` 和 ``local_epochs``,并使用这些值来改进日志记录和配" -"置本地训练历元的数量:" +"就是服务器要求客户端训练一定数量的本地遍历。Flower " +"提供了一种使用字典从服务器向客户端发送配置值的方法。让我们来看一个例子:" +"客户端通过 ``fit`` 中的 ``config`` 参数从服务器接收配置值(``evaluate`` " +"中也有 ``config`` 参数)。``fit`` 方法通过 ``config`` " +"参数接收配置字典,然后从字典中读取值。在本例中,它读取了 ``server_round`` 和 " +"``local_epochs``,并使用这些值来改进日志记录和配置本地训练遍历的数量:" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:546 msgid "" @@ -15469,9 +15542,9 @@ msgid "" "way server-side evaluation works. We provide a function to the strategy, and " "the strategy calls this function for every round of federated learning:" msgstr "" -"那么,如何将配置字典从服务器发送到客户端呢?内置的 \"Flower策略\"(Flower " -"Strategies)提供了这样的方法,其工作原理与服务器端评估的工作原理类似。我们为" -"策略提供一个函数,策略会在每一轮联合学习中调用这个函数:" +"那么,如何将配置字典从服务器发送到客户端呢?内置的 \"Flower策略\"(Flower Str" +"ategies)提供了这样的方法,其工作原理与服务器端评估的工作原理类似。我们为策略" +"提供一个函数,策略会在每一轮联邦学习中调用这个函数:" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:576 msgid "" @@ -15486,9 +15559,9 @@ msgid "" "configure local training to run for one epoch during the first and second " "round of federated learning, and then for two epochs during the third round." msgstr "" -"我们可以看到,客户端日志现在包含了当前一轮的联合学习(从 ``config`` 字典中读" -"取)。我们还可以将本地训练配置为在第一轮和第二轮联合学习期间运行一个历元,然" -"后在第三轮联合学习期间运行两个历元。" +"我们可以看到,客户端日志现在包含了当前一轮的联邦学习(从 ``config`` 字典中读" +"取)。我们还可以将本地训练配置为在第一轮和第二轮联邦学习期间运行一个遍历,然" +"后在第三轮联邦学习期间运行两个遍历。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:615 msgid "" @@ -15498,20 +15571,20 @@ msgid "" "``FlowerClient`` returns a dictionary containing a custom key/value pair as " "the third return value in ``evaluate``." msgstr "" -"客户端还可以向服务器返回任意值。为此,它们会从 ``fit`` 和/或 ``evaluate`` 返" -"回一个字典。我们在本笔记本中看到并使用了这一概念,但并未明确提及:我们的 " -"``FlowerClient`` 返回一个包含自定义键/值对的 dictionary,作为 ``evaluate`` 中" -"的第三个返回值。" +"客户端还可以向服务器返回任意值。为此,它们会从 ``fit`` 和/或 ``evaluate`` " +"返回一个字典。我们在本笔记中看到并使用了这一概念,但并未明确提及:我们的 " +"``FlowerClient`` 返回一个包含自定义键/值对的字典,作为 ``evaluate`` " +"中的第三个返回值。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:627 msgid "Scaling federated learning" -msgstr "扩大联合学习的规模" +msgstr "扩大联邦学习的规模" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:629 msgid "" "As a last step in this notebook, let's see how we can use Flower to " "experiment with a large number of clients." -msgstr "作为本笔记本的最后一步,让我们看看如何使用 Flower 对大量客户进行实验。" +msgstr "作为本笔记的最后一步,让我们看看如何使用 Flower 对大量客户端进行实验。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:651 #, python-format @@ -15525,11 +15598,12 @@ msgid "" "``fraction_fit`` to ``0.05``, which means that only 5% of available clients " "(so 50 clients) will be selected for training each round:" msgstr "" -"现在我们有 1000 个分区,每个分区有 45 个训练示例和 5 个验证示例。鉴于每个客户" -"端上的训练示例数量较少,我们可能需要对模型进行更长时间的训练,因此我们将客户" -"端配置为执行 3 个本地训练历元。我们还应该调整每轮训练中被选中的客户端的比例" -"(我们不希望每轮训练都有 1000 个客户端参与),因此我们将 ``fraction_fit`` 调" -"整为 ``0.05``,这意味着每轮训练只选中 5%的可用客户端(即 50 个客户端):" +"现在我们有 1000 个分区,每个分区有 45 个训练数据和 5 个验证数据。鉴于每个客户" +"端上的训练示例数量较少,我们可能需要对模型进行更长时间的训练," +"因此我们将客户端配置为执行 3 " +"个本地训练遍历。我们还应该调整每轮训练中被选中的客户端的比例(" +"我们不希望每轮训练都有 1000 个客户端参与),因此我们将 ``fraction_fit`` " +"调整为 ``0.05``,这意味着每轮训练只选中 5%的可用客户端(即 50 个客户端):" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:699 msgid "" @@ -15538,9 +15612,9 @@ msgid "" "choosing a different strategy, and evaluating models on the server-side. " "That's quite a bit of flexibility with so little code, right?" msgstr "" -"在本笔记本中,我们看到了如何通过自定义策略、在服务器端初始化参数、选择不同的" -"策略以及在服务器端评估模型来逐步增强我们的系统。用这么少的代码就能实现这么大" -"的灵活性,不是吗?" +"在本笔记中,我们看到了如何通过自定义策略、在服务器端初始化参数、选择不同的策" +"略以及在服务器端评估模型来逐步增强我们的系统。用这么少的代码就能实现这么大的" +"灵活性,不是吗?" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:701 msgid "" @@ -15551,9 +15625,9 @@ msgid "" "clients in the same workload - all in a Jupyter Notebook!" msgstr "" "在后面的章节中,我们将看到如何在服务器和客户端之间传递任意值,以完全自定义客" -"户端执行。有了这种能力,我们使用 Flower 虚拟客户端引擎构建了一个大规模的联合" -"学习模拟,并在 Jupyter Notebook 中进行了一次实验,在相同的工作负载中运行了 " -"1000 个客户端!" +"户端执行。有了这种能力,我们使用 Flower " +"虚拟客户端引擎构建了一个大规模的联邦学习模拟,并在 Jupyter Notebook " +"中进行了一次实验,在相同的工作负载中运行了 1000 个客户端!" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:719 msgid "" @@ -15561,13 +15635,13 @@ msgid "" "framework/tutorial-build-a-strategy-from-scratch-pytorch.html>`__ shows how " "to build a fully custom ``Strategy`` from scratch." msgstr "" -"Flower 联合学习教程 - 第 3 部分 `__ 展示了如何从头开始构建完全自定" -"义的 \"策略\"。" +"`Flower 联邦学习教程 - 第 3 部分 `__ " +"展示了如何从头开始构建完全自定义的 \"策略\"。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:9 msgid "What is Federated Learning?" -msgstr "什么是联合学习?" +msgstr "什么是联邦学习?" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:13 msgid "" @@ -15576,8 +15650,8 @@ msgid "" "parts of the tutorial, you will be able to build advanced federated learning " "systems that approach the current state of the art in the field." msgstr "" -"在本教程中,你将了解什么是联合学习,用 Flower 搭建第一个系统,并逐步对其进行" -"扩展。如果你能完成本教程的所有部分,你就能构建高级的联合学习系统,从而接近该" +"在本教程中,你将了解什么是联邦学习,用 Flower 搭建第一个系统,并逐步对其进行" +"扩展。如果你能完成本教程的所有部分,你就能构建高级的联邦学习系统,从而接近该" "领域当前的技术水平。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:15 @@ -15585,9 +15659,8 @@ msgid "" "🧑‍🏫 This tutorial starts at zero and expects no familiarity with federated " "learning. Only a basic understanding of data science and Python programming " "is assumed." -msgstr "" -"🧑‍🏫 本教程从零开始,不要求熟悉联合学习。仅假定对数据科学和 Python 编程有基本" -"了解。" +msgstr "🧑‍🏫 本教程从零开始,不要求熟悉联邦学习。仅假定对数据科学和 Python " +"编程有基本了解。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:17 msgid "" @@ -15614,8 +15687,7 @@ msgstr "经典机器学习" msgid "" "Before we begin to discuss federated learning, let us quickly recap how most " "machine learning works today." -msgstr "" -"在开始讨论联合学习之前,让我们先快速回顾一下目前大多数机器学习的工作原理。" +msgstr "在开始讨论联邦学习之前,让我们先快速回顾一下目前大多数机器学习的工作原理。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:35 msgid "" @@ -15628,7 +15700,7 @@ msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:41 msgid "|e1dd4b4129b040bea23a894266227080|" -msgstr "" +msgstr "|e1dd4b4129b040bea23a894266227080|" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:109 msgid "Model and data" @@ -15669,7 +15741,7 @@ msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:67 msgid "|174e1e4fa1f149a19bfbc8bc1126f46a|" -msgstr "" +msgstr "|174e1e4fa1f149a19bfbc8bc1126f46a|" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:113 msgid "Data on a phone" @@ -15687,7 +15759,7 @@ msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:79 msgid "|4e021a3dc08249d2a89daa3ab03c2714|" -msgstr "" +msgstr "|4e021a3dc08249d2a89daa3ab03c2714|" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:115 msgid "Data is on many devices" @@ -15704,11 +15776,11 @@ msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:91 msgid "|e74a1d5ce7eb49688651f2167a59065b|" -msgstr "" +msgstr "|e74a1d5ce7eb49688651f2167a59065b|" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:117 msgid "Central data collection" -msgstr "中央数据收集" +msgstr "集中数据收集" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:97 msgid "" @@ -15721,11 +15793,11 @@ msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:103 msgid "|eb29ec4c7aef4e93976795ed72df647e|" -msgstr "" +msgstr "|eb29ec4c7aef4e93976795ed72df647e|" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:119 msgid "Central model training" -msgstr "中央模型训练" +msgstr "集中模型训练" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:130 msgid "Challenges of classical machine learning" @@ -15743,7 +15815,7 @@ msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:138 msgid "|c2f699d8ac484f5081721a6f1511f70d|" -msgstr "" +msgstr "|c2f699d8ac484f5081721a6f1511f70d|" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:173 msgid "Centralized possible" @@ -15760,7 +15832,7 @@ msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:150 msgid "|cf42accdacbf4e5eb4fa0503108ba7a7|" -msgstr "" +msgstr "|cf42accdacbf4e5eb4fa0503108ba7a7|" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:175 msgid "Centralized impossible" @@ -15805,8 +15877,8 @@ msgid "" msgstr "" "**用户偏好**: 除了法规之外,在一些使用案例中,用户只是希望数据永远不会离开他" "们的设备。如果你在手机的数字键盘上输入密码和信用卡信息,你不会希望这些密码最" -"终出现在开发该键盘的公司的服务器上吧?事实上,这种用例正是联合学习发明的初" -"衷。" +"终出现在开发该键盘的公司的服务器上吧?事实上,这种用例正是联邦学习发明的初衷" +"。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:161 msgid "" @@ -15858,32 +15930,30 @@ msgid "" "private data? After all, these are all areas that would benefit " "significantly from recent advances in AI." msgstr "" -"像 \"Brave `__\"浏览器或 \"Signal `__\"信使这样的隐私增强系统的流行表明,用户关心隐私。事实上,他们会选择隐私" -"增强版,而不是其他替代品(如果存在这种替代品的话)。但是,我们能做些什么来将" -"机器学习和数据科学应用到这些情况中,以利用隐私数据呢?毕竟,这些领域都将从人" -"工智能的最新进展中受益匪浅。" +"像 `Brave `__浏览器或 `Signal `__信" +"息管理器这样的隐私增强系统的流行表明,用户关心隐私。事实上,他们会选择隐私性" +"更好的产品。但是,我们能做些什么来将机器学习和数据科学应用到这些情况中,以利" +"用隐私数据呢?毕竟,这些领域都将从人工智能的最新进展中受益匪浅。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:186 msgid "Federated learning" -msgstr "联合学习" +msgstr "联邦学习" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:188 msgid "" "Federated learning simply reverses this approach. It enables machine " "learning on distributed data by moving the training to the data, instead of " "moving the data to the training. Here's the single-sentence explanation:" -msgstr "" -"联合学习简单地颠覆了这种方法。它通过将训练转移到数据上,而不是将数据转移到训" +msgstr "联邦学习简单地颠覆了这种方法。它通过将训练转移到数据上,而不是将数据转移到训" "练上,在分布式数据上实现机器学习。下面是一句话的解释:" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:190 msgid "Central machine learning: move the data to the computation" -msgstr "中央机器学习:将数据转移到计算中" +msgstr "集中式机器学习:将数据转移到计算中心" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:191 msgid "Federated (machine) learning: move the computation to the data" -msgstr "联合(机器)学习:将计算转移到数据上" +msgstr "联邦式(机器)学习:将计算转移到数据上" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:193 msgid "" @@ -15902,18 +15972,18 @@ msgstr "" "们可以通过让不同的医院协同工作来训练优秀的医疗人工智能模型。我们可以通过在不" "同金融机构的数据上训练人工智能模型来解决金融欺诈问题。我们可以构建新颖的隐私" "增强型应用(如安全信息),其内置的人工智能比非隐私增强型应用更好。以上只是我" -"想到的几个例子。随着联合学习的部署,我们会发现越来越多的领域可以突然重获新" -"生,因为它们现在可以访问大量以前无法访问的数据。" +"想到的几个例子。随着联邦学习的部署,我们会发现越来越多的领域可以突然重获新生" +",因为它们现在可以访问大量以前无法访问的数据。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:196 msgid "" "So how does federated learning work, exactly? Let's start with an intuitive " "explanation." -msgstr "那么,联合学习究竟是如何运作的呢?让我们从直观的解释开始。" +msgstr "那么,联邦学习究竟是如何运作的呢?让我们从直观的解释开始。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:199 msgid "Federated learning in five steps" -msgstr "联合学习的五个步骤" +msgstr "联邦学习的五个步骤" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:202 msgid "Step 0: Initialize global model" @@ -15930,7 +16000,7 @@ msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:210 msgid "|5ec8356bc2564fa09178b1ceed5beccc|" -msgstr "" +msgstr "|5ec8356bc2564fa09178b1ceed5beccc|" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:307 msgid "Initialize global model" @@ -15958,11 +16028,11 @@ msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:225 msgid "|7c9329e97bd0430bad335ab605a897a7|" -msgstr "" +msgstr "|7c9329e97bd0430bad335ab605a897a7|" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:309 msgid "Send global model" -msgstr "发送全球模式" +msgstr "发送全局模型" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:232 msgid "" @@ -15981,20 +16051,20 @@ msgid "" msgstr "" "现在,所有(选定的)客户端节点都有了最新版本的全局模型参数,它们开始进行本地" "训练。它们使用自己的本地数据集来训练自己的本地模型。它们不会一直训练到模型完" -"全收敛为止,而只是训练一小段时间。这可能只是本地数据上的一个历元,甚至只是几" -"个步骤(迷你批次)。" +"全收敛为止,而只是训练一小段时间。这可能只是本地数据上的一个遍历,甚至只是几" +"个步骤(mini-batches)。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:240 msgid "|88002bbce1094ba1a83c9151df18f707|" -msgstr "" +msgstr "|88002bbce1094ba1a83c9151df18f707|" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:311 msgid "Train on local data" -msgstr "根据本地数据进行培训" +msgstr "根据本地数据进行训练" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:247 msgid "Step 3: Return model updates back to the server" -msgstr "步骤 3:将模型更新返回服务器" +msgstr "步骤 3:将模型参数更新返回服务器" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:249 msgid "" @@ -16006,21 +16076,21 @@ msgid "" "the gradients that were accumulated during local training." msgstr "" "经过本地训练后,每个客户节点最初收到的模型参数都会略有不同。参数之所以不同," -"是因为每个客户端节点的本地数据集中都有不同的示例。然后,客户端节点将这些模型" +"是因为每个客户端节点的本地数据集中都有不同的数据。然后,客户端节点将这些模型" "更新发回服务器。它们发送的模型更新既可以是完整的模型参数,也可以只是本地训练" "过程中积累的梯度。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:255 msgid "|391766aee87c482c834c93f7c22225e2|" -msgstr "" +msgstr "|391766aee87c482c834c93f7c22225e2|" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:313 msgid "Send model updates" -msgstr "发送模型更新" +msgstr "发送模型参数更新" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:262 msgid "Step 4: Aggregate model updates into a new global model" -msgstr "步骤 4:将模型更新汇总到新的全局模型中" +msgstr "步骤 4:将模型更新聚合到新的全局模型中" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:264 msgid "" @@ -16051,20 +16121,21 @@ msgid "" msgstr "" "为了得到一个单一的模型,我们必须将从客户端节点收到的所有模型更新合并起来。这" "个过程称为*聚合*,有许多不同的方法。最基本的方法称为 *Federated Averaging* " -"(`McMahan等人,2016 `__),通常缩写为" -"*FedAvg*。*FedAvg* 采用 100 个模型更新,顾名思义,就是对它们进行平均。更准确" -"地说,它取的是模型更新的*加权平均值*,根据每个客户端用于训练的示例数量进行加" -"权。加权对于确保每个数据示例对生成的全局模型具有相同的 \"影响 \"非常重要。如" -"果一个客户有 10 个示例,而另一个客户有 100 个示例,那么在不加权的情况下,10 " -"个示例对全局模型的影响是 100 个示例的 10 倍。" +"(`McMahan等人,2016 `__),通常缩写为*FedAvg*。*FedAvg* 可以把100 个模型更新进行平均。更准确" +"地说,它取的是模型更新的*加权平均值*,根据每个客户端用于训练的数据数量进行加" +"权。加权对于确保每个数据示例对生成的全局模型具有相同的 \"影响 \"非常重要。" +"如果一个客户端有 10 个数据点,而另一个客户有 100 " +"个数据点,那么在不加权的情况下,10 个示例对全局模型的影响是 100 个示例的 10 " +"倍。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:273 msgid "|93b9a15bd27f4e91b40f642c253dfaac|" -msgstr "" +msgstr "|93b9a15bd27f4e91b40f642c253dfaac|" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:315 msgid "Aggregate model updates" -msgstr "汇总模型更新" +msgstr "聚合模型参数更新" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:280 msgid "Step 5: Repeat steps 1 to 4 until the model converges" @@ -16078,9 +16149,11 @@ msgid "" "models to the server (step 3), and the server then aggregates the model " "updates to get a new version of the global model (step 4)." msgstr "" -"步骤 1 至 4 就是我们所说的单轮联合学习。全局模型参数被发送到参与的客户端节点" -"(第 1 步),客户端节点对其本地数据进行训练(第 2 步),然后将更新后的模型发" -"送到服务器(第 3 步),服务器汇总模型更新,得到新版本的全局模型(第 4 步)。" +"步骤 1 至 4 " +"就是我们所说的单轮联邦学习。全局模型参数被发送到参与的客户端节点(第 1 " +"步),客户端节点对其本地数据进行训练(第 2 " +"步),然后将更新后的模型发送到服务器(第 3 " +"步),服务器汇总模型更新,得到新版本的全局模型(第 4 步)。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:284 msgid "" @@ -16105,10 +16178,10 @@ msgid "" "should participate in the next round? What's the best way to aggregate model " "updates? How can we handle failing client nodes (stragglers)?" msgstr "" -"恭喜你,现在你已经了解了联合学习的基础知识。当然,要讨论的内容还有很多,但这" -"只是联合学习的一个缩影。在本教程的后半部分,我们将进行更详细的介绍。有趣的问" -"题包括 我们如何选择最好的客户端节点参与下一轮学习?聚合模型更新的最佳方法是什" -"么?如何处理失败的客户端节点(落伍者)?" +"恭喜您,现在您已经了解了联邦学习的基础知识。当然,要讨论的内容还有很多,但这" +"只是联邦学习的一个缩影。在本教程的后半部分,我们将进行更详细的介绍。" +"有趣的问题包括 我们如何选择最好的客户端节点参与下一轮学习?聚合模型更新的最佳" +"方法是什么?如何处理失败的客户端节点(落伍者)?" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:294 msgid "" @@ -16119,12 +16192,12 @@ msgid "" "systems." msgstr "" "就像我们可以在不同客户节点的分散数据上训练一个模型一样,我们也可以在这些数据" -"上对模型进行评估,以获得有价值的指标。这就是所谓的联合评估,有时简称为 FE。事" -"实上,联合评估是大多数联合学习系统不可或缺的一部分。" +"上对模型进行评估,以获得有价值的指标。这就是所谓的联邦评估,有时简称为 " +"FE。事实上,联邦评估是大多数联邦学习系统不可或缺的一部分。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:297 msgid "Federated analytics" -msgstr "联合分析" +msgstr "联邦分析" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:299 msgid "" @@ -16138,12 +16211,12 @@ msgid "" msgstr "" "在很多情况下,机器学习并不是从数据中获取价值的必要条件。数据分析可以产生有价" "值的见解,但同样,往往没有足够的数据来获得明确的答案。人们患某种健康疾病的平" -"均年龄是多少?联合分析可以通过多个客户端节点进行此类查询。它通常与安全聚合等" +"均年龄是多少?联邦分析可以通过多个客户端节点进行此类查询。它通常与安全聚合等" "其他隐私增强技术结合使用,以防止服务器看到单个客户端节点提交的结果。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:303 msgid "Differential Privacy" -msgstr "差异化隐私" +msgstr "差分隐私" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:305 msgid "" @@ -16155,7 +16228,7 @@ msgid "" "identified. This technique can be considered an optimization that provides a " "quantifiable privacy protection measure." msgstr "" -"差异隐私(DP)经常在联合学习中被提及。这是一种在分析和共享统计数据时使用的隐" +"差分隐私(DP)经常在联邦学习中被提及。这是一种在分析和共享统计数据时使用的隐" "私保护方法,可确保单个参与者的隐私。DP 通过在模型更新中添加统计噪声来实现这一" "目的,确保任何个体参与者的信息都无法被区分或重新识别。这种技术可被视为一种优" "化,提供了一种可量化的隐私保护措施。" @@ -16174,35 +16247,34 @@ msgid "" "learning, analytics, and evaluation. It allows the user to federate any " "workload, any ML framework, and any programming language." msgstr "" -"联合学习、联合评估和联合分析需要基础设施来来回移动机器学习模型,在本地数据上" -"对其进行训练和评估,然后汇总更新的模型。Flower 提供的基础架构正是以简单、可扩" -"展和安全的方式实现这些目标的。简而言之,Flower 为联合学习、分析和评估提供了一" -"种统一的方法。它允许用户联合任何工作负载、任何 ML 框架和任何编程语言。" +"联邦学习、联邦评估和联邦分析需要基础框架来来回移动机器学习模型,在本地数据上" +"对其进行训练和评估,然后汇总更新的模型。Flower " +"提供的基础架构正是以简单、可扩展和安全的方式实现这些目标的。简而言之,Flower " +"为联邦学习、分析和评估提供了一种统一的方法。它允许用户联邦化任何工作负载、" +"任何 ML 框架和任何编程语言。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:334 msgid "|a23d9638f96342ef9d25209951e2d564|" -msgstr "" +msgstr "|a23d9638f96342ef9d25209951e2d564|" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:340 msgid "" "Flower federated learning server and client nodes (car, scooter, personal " "computer, roomba, and phone)" -msgstr "" -"Flower联合学习服务器和客户端节点(汽车、滑板车、个人电脑、roomba 和电话)" +msgstr "Flower联邦学习服务器和客户端节点(汽车、滑板车、个人电脑、roomba 和电话)" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:353 msgid "" "Congratulations, you just learned the basics of federated learning and how " "it relates to the classic (centralized) machine learning!" -msgstr "" -"恭喜你,你刚刚了解了联合学习的基础知识,以及它与传统(集中式)机器学习的关" -"系!" +msgstr "恭喜您,您刚刚了解了联邦学习的基础知识,以及它与传统(集中式)机器学习的关系" +"!" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:355 msgid "" "In the next part of this tutorial, we are going to build a first federated " "learning system with Flower." -msgstr "在本教程的下一部分,我们将用 Flower 建立第一个联合学习系统。" +msgstr "在本教程的下一部分,我们将用 Flower 建立第一个联邦学习系统。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:373 msgid "" @@ -16210,9 +16282,9 @@ msgid "" "framework/tutorial-get-started-with-flower-pytorch.html>`__ shows how to " "build a simple federated learning system with PyTorch and Flower." msgstr "" -"Flower 联合学习教程 - 第 1 部分 `__ 展示了如何使用 PyTorch 和 Flower 构" -"建一个简单的联合学习系统。" +"`Flower 联邦学习教程 - 第 1 部分 `__ 展示了如何使用 PyTorch 和 Flower " +"构建一个简单的联邦学习系统。" #: ../../source/contributor-how-to-install-development-versions.rst:62 msgid "Upload the whl (e.g., ``flwr-1.6.0-py3-none-any.whl``)" @@ -16252,10 +16324,10 @@ msgid "" "identical way. In addition to that, clients managed by the :code:" "`VirtualClientEngine` are:" msgstr "" -"代码:`VirtualClientEngine`调度、启动和管理`虚拟`客户端。这些客户端与 \"非虚" -"拟 \"客户端(即通过命令 \"flwr.client.start_numpy_client `_\"启动的客户端)完全相同,它们可以通过创建一个继承" -"自 \"flwr.client.NumPyClient `_\" " +"代码:`VirtualClientEngine`调度、启动和管理`虚拟`客户端。这些客户端与 \"非虚拟" +" \"客户端(即通过命令 `flwr.client.start_numpy_client `_启动的客户端)完全相同,它们可以通过创建一个继承自 " +"\"flwr.client.NumPyClient `_\" " "的类来配置,因此行为方式也完全相同。除此之外,由 :code:`VirtualClientEngine` " "管理的客户端还包括:" @@ -16271,12 +16343,12 @@ msgid "" "machines, all that needs to change is the :code:`server_address` we pass to " "the client." msgstr "" -"这就是客户端。我们只需实现 :code:`Client` 或 :code:`NumPyClient` 并调用 :" -"code:`fl.client.start_client()` 或 :code:`fl.client.start_numpy_client()`。字" -"符串 :code:`\"0.0.0.0:8080\"`会告诉客户端要连接的服务器。在本例中,我们可以在" -"同一台机器上运行服务器和客户端,因此我们使用 :code:`\"0.0.0.0:8080\"`。如果我" -"们运行的是真正的联合工作负载,服务器和客户端运行在不同的机器上,那么需要改变" -"的只是传递给客户端的 :code:`server_address`。" +"这就是客户端。我们只需实现 :code:`Client` 或 :code:`NumPyClient` 并调用 " +":code:`fl.client.start_client()` 或 :code:`fl.client.start_numpy_client()`。" +"字符串 :code:`\"0.0.0.0:8080\"`会告诉客户端要连接的服务器。在本例中,我们可以" +"在同一台机器上运行服务器和客户端,因此我们使用 :code:`\"0.0.0.0:8080\"" +"`。如果我们运行的是真正的联邦工作负载,服务器和客户端运行在不同的机器上," +"那么需要改变的只是传递给客户端的 :code:`server_address`。" #: ../../source/tutorial-quickstart-pytorch.rst:196 #: ../../source/tutorial-quickstart-tensorflow.rst:90 @@ -16290,9 +16362,9 @@ msgid "" "machines, all that needs to change is the :code:`server_address` we point " "the client at." msgstr "" -"这就是客户端。我们只需实现 :code:`Client` 或 :code:`NumPyClient` 并调用 :" -"code:`fl.client.start_client()` 或 :code:`fl.client.start_numpy_client()`。字" -"符串 :code:`\"[::]:8080\"`会告诉客户端要连接的服务器。在本例中,我们可以在同" -"一台机器上运行服务器和客户端,因此使用 :code:`\"[::]:8080\"。如果我们运行的是" -"真正的联合工作负载,服务器和客户端运行在不同的机器上,那么需要改变的只是客户" -"端指向的 :code:`server_address`。" +"这就是客户端。我们只需实现 :code:`Client` 或 :code:`NumPyClient` 并调用 " +":code:`fl.client.start_client()` 或 :code:`fl.client.start_numpy_client()`。" +"字符串 :code:`\"[::]:8080\"`会告诉客户端要连接的服务器。在本例中,我们可以在" +"同一台机器上运行服务器和客户端,因此使用 :code:`\"[::]:8080\"" +"。如果我们运行的是真正的联邦工作负载,服务器和客户端运行在不同的机器上," +"那么需要改变的只是客户端指向的 :code:`server_address`。" From 2a838d41138d7025ae75e106ff397c1f18578ae5 Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Sun, 11 Feb 2024 14:42:51 +0100 Subject: [PATCH 087/113] Merge mt-pytorch examples (#2918) --- examples/mt-pytorch-callable/README.md | 49 ------- examples/mt-pytorch-callable/client.py | 123 ------------------ examples/mt-pytorch-callable/driver.py | 25 ---- examples/mt-pytorch-callable/pyproject.toml | 16 --- examples/mt-pytorch-callable/requirements.txt | 4 - examples/mt-pytorch-callable/run.sh | 20 --- examples/mt-pytorch-callable/server.py | 25 ---- examples/mt-pytorch/README.md | 65 ++++----- examples/mt-pytorch/client.py | 21 ++- examples/mt-pytorch/start_driver.py | 13 +- examples/mt-pytorch/start_server.py | 41 ------ 11 files changed, 45 insertions(+), 357 deletions(-) delete mode 100644 examples/mt-pytorch-callable/README.md delete mode 100644 examples/mt-pytorch-callable/client.py delete mode 100644 examples/mt-pytorch-callable/driver.py delete mode 100644 examples/mt-pytorch-callable/pyproject.toml delete mode 100644 examples/mt-pytorch-callable/requirements.txt delete mode 100755 examples/mt-pytorch-callable/run.sh delete mode 100644 examples/mt-pytorch-callable/server.py delete mode 100644 examples/mt-pytorch/start_server.py diff --git a/examples/mt-pytorch-callable/README.md b/examples/mt-pytorch-callable/README.md deleted file mode 100644 index 5bfa94d026e5..000000000000 --- a/examples/mt-pytorch-callable/README.md +++ /dev/null @@ -1,49 +0,0 @@ -# Deploy 🧪 - -🧪 = this page covers experimental features that might change in future versions of Flower - -This how-to guide describes the deployment of a long-running Flower server. - -## Preconditions - -Let's assume the following project structure: - -```bash -$ tree . -. -└── client.py -├── driver.py -├── requirements.txt -``` - -## Install dependencies - -```bash -pip install -r requirements.txt -``` - -## Start the long-running Flower server - -```bash -flower-server --insecure -``` - -## Start the long-running Flower client - -In a new terminal window, start the first long-running Flower client: - -```bash -flower-client client:app --insecure -``` - -In yet another new terminal window, start the second long-running Flower client: - -```bash -flower-client client:app --insecure -``` - -## Start the Driver script - -```bash -python driver.py -``` diff --git a/examples/mt-pytorch-callable/client.py b/examples/mt-pytorch-callable/client.py deleted file mode 100644 index ca88fc3c9824..000000000000 --- a/examples/mt-pytorch-callable/client.py +++ /dev/null @@ -1,123 +0,0 @@ -import warnings -from collections import OrderedDict - -import flwr as fl -import torch -import torch.nn as nn -import torch.nn.functional as F -from torch.utils.data import DataLoader -from torchvision.datasets import CIFAR10 -from torchvision.transforms import Compose, Normalize, ToTensor -from tqdm import tqdm - - -# ############################################################################# -# 1. Regular PyTorch pipeline: nn.Module, train, test, and DataLoader -# ############################################################################# - -warnings.filterwarnings("ignore", category=UserWarning) -DEVICE = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") - - -class Net(nn.Module): - """Model (simple CNN adapted from 'PyTorch: A 60 Minute Blitz')""" - - def __init__(self) -> None: - super(Net, self).__init__() - self.conv1 = nn.Conv2d(3, 6, 5) - self.pool = nn.MaxPool2d(2, 2) - self.conv2 = nn.Conv2d(6, 16, 5) - self.fc1 = nn.Linear(16 * 5 * 5, 120) - self.fc2 = nn.Linear(120, 84) - self.fc3 = nn.Linear(84, 10) - - def forward(self, x: torch.Tensor) -> torch.Tensor: - x = self.pool(F.relu(self.conv1(x))) - x = self.pool(F.relu(self.conv2(x))) - x = x.view(-1, 16 * 5 * 5) - x = F.relu(self.fc1(x)) - x = F.relu(self.fc2(x)) - return self.fc3(x) - - -def train(net, trainloader, epochs): - """Train the model on the training set.""" - criterion = torch.nn.CrossEntropyLoss() - optimizer = torch.optim.SGD(net.parameters(), lr=0.001, momentum=0.9) - for _ in range(epochs): - for images, labels in tqdm(trainloader): - optimizer.zero_grad() - criterion(net(images.to(DEVICE)), labels.to(DEVICE)).backward() - optimizer.step() - - -def test(net, testloader): - """Validate the model on the test set.""" - criterion = torch.nn.CrossEntropyLoss() - correct, loss = 0, 0.0 - with torch.no_grad(): - for images, labels in tqdm(testloader): - outputs = net(images.to(DEVICE)) - labels = labels.to(DEVICE) - loss += criterion(outputs, labels).item() - correct += (torch.max(outputs.data, 1)[1] == labels).sum().item() - accuracy = correct / len(testloader.dataset) - return loss, accuracy - - -def load_data(): - """Load CIFAR-10 (training and test set).""" - trf = Compose([ToTensor(), Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) - trainset = CIFAR10("./data", train=True, download=True, transform=trf) - testset = CIFAR10("./data", train=False, download=True, transform=trf) - return DataLoader(trainset, batch_size=32, shuffle=True), DataLoader(testset) - - -# ############################################################################# -# 2. Federation of the pipeline with Flower -# ############################################################################# - -# Load model and data (simple CNN, CIFAR-10) -net = Net().to(DEVICE) -trainloader, testloader = load_data() - - -# Define Flower client -class FlowerClient(fl.client.NumPyClient): - def get_parameters(self, config): - return [val.cpu().numpy() for _, val in net.state_dict().items()] - - def set_parameters(self, parameters): - params_dict = zip(net.state_dict().keys(), parameters) - state_dict = OrderedDict({k: torch.tensor(v) for k, v in params_dict}) - net.load_state_dict(state_dict, strict=True) - - def fit(self, parameters, config): - self.set_parameters(parameters) - train(net, trainloader, epochs=1) - return self.get_parameters(config={}), len(trainloader.dataset), {} - - def evaluate(self, parameters, config): - self.set_parameters(parameters) - loss, accuracy = test(net, testloader) - return loss, len(testloader.dataset), {"accuracy": accuracy} - - -def client_fn(cid: str): - """.""" - return FlowerClient().to_client() - - -# To run this: `flower-client client:app` -app = fl.client.ClientApp( - client_fn=client_fn, -) - - -if __name__ == "__main__": - # Start Flower client - fl.client.start_client( - server_address="0.0.0.0:9092", - client=FlowerClient().to_client(), - transport="grpc-rere", - ) diff --git a/examples/mt-pytorch-callable/driver.py b/examples/mt-pytorch-callable/driver.py deleted file mode 100644 index 1248672b6813..000000000000 --- a/examples/mt-pytorch-callable/driver.py +++ /dev/null @@ -1,25 +0,0 @@ -from typing import List, Tuple - -import flwr as fl -from flwr.common import Metrics - - -# Define metric aggregation function -def weighted_average(metrics: List[Tuple[int, Metrics]]) -> Metrics: - # Multiply accuracy of each client by number of examples used - accuracies = [num_examples * m["accuracy"] for num_examples, m in metrics] - examples = [num_examples for num_examples, _ in metrics] - - # Aggregate and return custom metric (weighted average) - return {"accuracy": sum(accuracies) / sum(examples)} - - -# Define strategy -strategy = fl.server.strategy.FedAvg(evaluate_metrics_aggregation_fn=weighted_average) - -# Start Flower driver -fl.driver.start_driver( - server_address="0.0.0.0:9091", - config=fl.server.ServerConfig(num_rounds=3), - strategy=strategy, -) diff --git a/examples/mt-pytorch-callable/pyproject.toml b/examples/mt-pytorch-callable/pyproject.toml deleted file mode 100644 index 0d1a91836006..000000000000 --- a/examples/mt-pytorch-callable/pyproject.toml +++ /dev/null @@ -1,16 +0,0 @@ -[build-system] -requires = ["poetry-core>=1.4.0"] -build-backend = "poetry.core.masonry.api" - -[tool.poetry] -name = "quickstart-pytorch" -version = "0.1.0" -description = "PyTorch Federated Learning Quickstart with Flower" -authors = ["The Flower Authors "] - -[tool.poetry.dependencies] -python = ">=3.8,<3.11" -flwr = { path = "../../", develop = true, extras = ["simulation", "rest"] } -torch = "1.13.1" -torchvision = "0.14.1" -tqdm = "4.65.0" diff --git a/examples/mt-pytorch-callable/requirements.txt b/examples/mt-pytorch-callable/requirements.txt deleted file mode 100644 index 797ca6db6244..000000000000 --- a/examples/mt-pytorch-callable/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -flwr>=1.0, <2.0 -torch==1.13.1 -torchvision==0.14.1 -tqdm==4.65.0 diff --git a/examples/mt-pytorch-callable/run.sh b/examples/mt-pytorch-callable/run.sh deleted file mode 100755 index d2bf34f834b1..000000000000 --- a/examples/mt-pytorch-callable/run.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash -set -e -cd "$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"/ - -# Download the CIFAR-10 dataset -python -c "from torchvision.datasets import CIFAR10; CIFAR10('./data', download=True)" - -echo "Starting server" -python server.py & -sleep 3 # Sleep for 3s to give the server enough time to start - -for i in `seq 0 1`; do - echo "Starting client $i" - python client.py & -done - -# Enable CTRL+C to stop all background processes -trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM -# Wait for all background processes to complete -wait diff --git a/examples/mt-pytorch-callable/server.py b/examples/mt-pytorch-callable/server.py deleted file mode 100644 index fe691a88aba0..000000000000 --- a/examples/mt-pytorch-callable/server.py +++ /dev/null @@ -1,25 +0,0 @@ -from typing import List, Tuple - -import flwr as fl -from flwr.common import Metrics - - -# Define metric aggregation function -def weighted_average(metrics: List[Tuple[int, Metrics]]) -> Metrics: - # Multiply accuracy of each client by number of examples used - accuracies = [num_examples * m["accuracy"] for num_examples, m in metrics] - examples = [num_examples for num_examples, _ in metrics] - - # Aggregate and return custom metric (weighted average) - return {"accuracy": sum(accuracies) / sum(examples)} - - -# Define strategy -strategy = fl.server.strategy.FedAvg(evaluate_metrics_aggregation_fn=weighted_average) - -# Start Flower server -fl.server.start_server( - server_address="0.0.0.0:8080", - config=fl.server.ServerConfig(num_rounds=3), - strategy=strategy, -) diff --git a/examples/mt-pytorch/README.md b/examples/mt-pytorch/README.md index ef9516314e26..721a26ed814d 100644 --- a/examples/mt-pytorch/README.md +++ b/examples/mt-pytorch/README.md @@ -1,73 +1,52 @@ -# Multi-Tenant Federated Learning with Flower and PyTorch +# Flower App (PyTorch) 🧪 -This example contains experimental code. Please consult the regular PyTorch code examples ([quickstart](https://github.com/adap/flower/tree/main/examples/quickstart-pytorch), [advanced](https://github.com/adap/flower/tree/main/examples/advanced-pytorch)) to learn how to use Flower with PyTorch. +🧪 = This example covers experimental features that might change in future versions of Flower -## Setup +Please consult the regular PyTorch code examples ([quickstart](https://github.com/adap/flower/tree/main/examples/quickstart-pytorch), [advanced](https://github.com/adap/flower/tree/main/examples/advanced-pytorch)) to learn how to use Flower with PyTorch. -```bash -./dev/venv-reset.sh -``` +This how-to guide describes the deployment of a long-running Flower server. -## Run with Driver API +## Preconditions -Terminal 1: start Flower server +Let's assume the following project structure: ```bash -flower-server +$ tree . +. +├── client.py +├── server.py +├── task.py +└── requirements.txt ``` -Terminal 2+3: start two Flower client nodes +## Install dependencies ```bash -python client.py +pip install -r requirements.txt ``` -Terminal 4: start Driver script - -Using: +## Start the SuperLink ```bash -python start_driver.py +flower-superlink --insecure ``` -Or, alternatively: - -```bash -python driver.py -``` - -## Run in legacy mode - -Terminal 1: start Flower server +## Start the long-running Flower client -```bash -python server.py -``` - -Terminal 2+3: start two clients +In a new terminal window, start the first long-running Flower client: ```bash -python client.py +flower-client client:app --insecure ``` -## Run with Driver API (REST transport layer) - -Terminal 1: start Flower server and enable REST transport layer +In yet another new terminal window, start the second long-running Flower client: ```bash -flower-server --rest +flower-client client:app --insecure ``` -Terminal 2: start Driver script +## Start the driver ```bash python driver.py ``` - -Open file `client.py` adjust `server_address` and `transport`. - -Terminal 3+4: start two Flower client nodes - -```bash -python client.py -``` diff --git a/examples/mt-pytorch/client.py b/examples/mt-pytorch/client.py index 295770a802bd..1f2db323ac34 100644 --- a/examples/mt-pytorch/client.py +++ b/examples/mt-pytorch/client.py @@ -34,9 +34,20 @@ def evaluate(self, parameters, config): return loss, len(testloader.dataset), {"accuracy": accuracy} -# Start Flower client -fl.client.start_client( - server_address="0.0.0.0:9092", # "0.0.0.0:9093" for REST - client=FlowerClient().to_client(), - transport="grpc-rere", # "rest" for REST +def client_fn(cid: str): + return FlowerClient().to_client() + + +# To run this: `flower-client client:app` +app = fl.client.ClientApp( + client_fn=client_fn, ) + + +if __name__ == "__main__": + # Start Flower client + fl.client.start_client( + server_address="0.0.0.0:9092", # "0.0.0.0:9093" for REST + client_fn=client_fn, + transport="grpc-rere", # "rest" for REST + ) diff --git a/examples/mt-pytorch/start_driver.py b/examples/mt-pytorch/start_driver.py index 3241a548950a..1a921c2e149a 100644 --- a/examples/mt-pytorch/start_driver.py +++ b/examples/mt-pytorch/start_driver.py @@ -33,9 +33,10 @@ def weighted_average(metrics: List[Tuple[int, Metrics]]) -> Metrics: fit_metrics_aggregation_fn=weighted_average, ) -# Start Flower server -fl.driver.start_driver( - server_address="0.0.0.0:9091", - config=fl.server.ServerConfig(num_rounds=3), - strategy=strategy, -) +if __name__ == "__main__": + # Start Flower server + fl.driver.start_driver( + server_address="0.0.0.0:9091", + config=fl.server.ServerConfig(num_rounds=3), + strategy=strategy, + ) diff --git a/examples/mt-pytorch/start_server.py b/examples/mt-pytorch/start_server.py deleted file mode 100644 index d96edd7d45ad..000000000000 --- a/examples/mt-pytorch/start_server.py +++ /dev/null @@ -1,41 +0,0 @@ -from typing import List, Tuple - -import flwr as fl -from flwr.common import Metrics - - -# Define metric aggregation function -def weighted_average(metrics: List[Tuple[int, Metrics]]) -> Metrics: - examples = [num_examples for num_examples, _ in metrics] - - # Multiply accuracy of each client by number of examples used - train_losses = [num_examples * m["train_loss"] for num_examples, m in metrics] - train_accuracies = [ - num_examples * m["train_accuracy"] for num_examples, m in metrics - ] - val_losses = [num_examples * m["val_loss"] for num_examples, m in metrics] - val_accuracies = [num_examples * m["val_accuracy"] for num_examples, m in metrics] - - # Aggregate and return custom metric (weighted average) - return { - "train_loss": sum(train_losses) / sum(examples), - "train_accuracy": sum(train_accuracies) / sum(examples), - "val_loss": sum(val_losses) / sum(examples), - "val_accuracy": sum(val_accuracies) / sum(examples), - } - - -# Define strategy -strategy = fl.server.strategy.FedAvg( - fraction_fit=1.0, # Select all available clients - fraction_evaluate=0.0, # Disable evaluation - min_available_clients=2, - fit_metrics_aggregation_fn=weighted_average, -) - -# Start Flower server -fl.server.start_server( - server_address="0.0.0.0:9092", - config=fl.server.ServerConfig(num_rounds=3), - strategy=strategy, -) From b3269cf8c4f1d9defe92b50ebf3204370e92d1f4 Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Sun, 11 Feb 2024 14:54:57 +0100 Subject: [PATCH 088/113] Fix typo in whisper example (#2921) --- examples/whisper-federated-finetuning/client.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/whisper-federated-finetuning/client.py b/examples/whisper-federated-finetuning/client.py index 07abc641f8fe..d3bb217933f8 100644 --- a/examples/whisper-federated-finetuning/client.py +++ b/examples/whisper-federated-finetuning/client.py @@ -151,8 +151,8 @@ def client_fn(cid: str): return client_fn -def run_client(): - """Run clinet.""" +def main(): + """Run client.""" # Parse input arguments args = parser.parse_args() @@ -175,9 +175,10 @@ def run_client(): ) fl.client.start_client( - server_address=f"{args.server_address}:8080", client=client_fn(args.cid) + server_address=f"{args.server_address}:8080", + client=client_fn(args.cid), ) if __name__ == "__main__": - run_client() + main() From f5feed9d4d0da2512bb427222a24a8a1b6ca88b0 Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Sun, 11 Feb 2024 15:06:56 +0100 Subject: [PATCH 089/113] Rename flower-server to flower-superlink (#2916) Co-authored-by: Taner Topal --- doc/locales/fr/LC_MESSAGES/framework-docs.po | 8 ++++---- doc/locales/pt_BR/LC_MESSAGES/framework-docs.po | 4 ++-- doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po | 6 +++--- doc/source/ref-api-cli.rst | 8 ++++---- e2e/test_driver.sh | 7 +++++-- examples/secaggplus-mt/run.sh | 10 +++++----- pyproject.toml | 2 +- src/docker/server/Dockerfile | 4 ++-- src/py/flwr/common/telemetry.py | 4 ++-- src/py/flwr/server/__init__.py | 4 ++-- src/py/flwr/server/app.py | 6 +++--- 11 files changed, 33 insertions(+), 30 deletions(-) diff --git a/doc/locales/fr/LC_MESSAGES/framework-docs.po b/doc/locales/fr/LC_MESSAGES/framework-docs.po index 07ed245bf36f..833ba6411b5e 100644 --- a/doc/locales/fr/LC_MESSAGES/framework-docs.po +++ b/doc/locales/fr/LC_MESSAGES/framework-docs.po @@ -7275,8 +7275,8 @@ msgid "Flower CLI reference" msgstr "Client de Flower" #: ../../source/ref-api-cli.rst:7 -msgid "flower-server" -msgstr "flower-server" +msgid "flower-superlink" +msgstr "flower-superlink" #: ../../source/ref-api-cli.rst:17 msgid "flower-driver-api" @@ -8372,10 +8372,10 @@ msgstr "" #: ../../source/ref-changelog.md:179 #, fuzzy msgid "" -"`flower-server --driver-api-address \"0.0.0.0:8081\" --fleet-api-address " +"`flower-superlink --driver-api-address \"0.0.0.0:8081\" --fleet-api-address " "\"0.0.0.0:8086\"`" msgstr "" -"``flower-server --driver-api-address \"0.0.0.0:8081\" --fleet-api-address" +"``flower-superlink --driver-api-address \"0.0.0.0:8081\" --fleet-api-address" " \"0.0.0.0:8086\" ``" #: ../../source/ref-changelog.md:181 diff --git a/doc/locales/pt_BR/LC_MESSAGES/framework-docs.po b/doc/locales/pt_BR/LC_MESSAGES/framework-docs.po index 1dd6a27fe17e..22c28a05caa4 100644 --- a/doc/locales/pt_BR/LC_MESSAGES/framework-docs.po +++ b/doc/locales/pt_BR/LC_MESSAGES/framework-docs.po @@ -5609,7 +5609,7 @@ msgid "Flower CLI reference" msgstr "" #: ../../source/ref-api-cli.rst:7 -msgid "flower-server" +msgid "flower-superlink" msgstr "" #: ../../source/ref-api-cli.rst:17 @@ -6621,7 +6621,7 @@ msgstr "" #: ../../source/ref-changelog.md:217 msgid "" -"`flower-server --driver-api-address \"0.0.0.0:8081\" --fleet-api-address " +"`flower-superlink --driver-api-address \"0.0.0.0:8081\" --fleet-api-address " "\"0.0.0.0:8086\"`" msgstr "" diff --git a/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po b/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po index 5ac2ba81b324..4d63193f8e9e 100644 --- a/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po +++ b/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po @@ -6630,8 +6630,8 @@ msgid "Flower CLI reference" msgstr "Flower CLI 参考" #: ../../source/ref-api-cli.rst:7 -msgid "flower-server" -msgstr "Flower 服务器" +msgid "flower-superlink" +msgstr "flower-superlink" #: ../../source/ref-api-cli.rst:17 msgid "flower-driver-api" @@ -9270,7 +9270,7 @@ msgstr "" #: ../../source/ref-changelog.md:241 msgid "" -"`flower-server --driver-api-address \"0.0.0.0:8081\" --fleet-api-address " +"`flower-superlink --driver-api-address \"0.0.0.0:8081\" --fleet-api-address " "\"0.0.0.0:8086\"`" msgstr "" "`flower-server --driver-api-address \"0.0.0.0:8081\" --fleet-api-address \"0." diff --git a/doc/source/ref-api-cli.rst b/doc/source/ref-api-cli.rst index 039a2ea27cf8..6d5408f76a35 100644 --- a/doc/source/ref-api-cli.rst +++ b/doc/source/ref-api-cli.rst @@ -1,15 +1,15 @@ Flower CLI reference ==================== -.. _flower-server-apiref: +.. _flower-superlink-apiref: -flower-server -~~~~~~~~~~~~~ +flower-superlink +~~~~~~~~~~~~~~~~ .. argparse:: :module: flwr.server.app :func: _parse_args_server - :prog: flower-server + :prog: flower-superlink .. _flower-driver-apiref: diff --git a/e2e/test_driver.sh b/e2e/test_driver.sh index 989f89039019..ffac1f8d30db 100755 --- a/e2e/test_driver.sh +++ b/e2e/test_driver.sh @@ -31,13 +31,16 @@ case "$2" in ;; esac -timeout 2m flower-server $server_arg $db_arg $rest_arg & +timeout 2m flower-superlink $server_arg $db_arg $rest_arg & +sl_pid=$! sleep 3 timeout 2m flower-client client:app $client_arg $rest_arg --server $server_address & +cl1_pid=$! sleep 3 timeout 2m flower-client client:app $client_arg $rest_arg --server $server_address & +cl2_pid=$! sleep 3 timeout 2m python driver.py & @@ -47,7 +50,7 @@ wait $pid res=$? if [[ "$res" = "0" ]]; - then echo "Training worked correctly" && pkill flower-client && pkill flower-server; + then echo "Training worked correctly"; kill $cl1_pid; kill $cl2_pid; kill $sl_pid; else echo "Training had an issue" && exit 1; fi diff --git a/examples/secaggplus-mt/run.sh b/examples/secaggplus-mt/run.sh index e2c16bbe3541..7a0f1592f646 100755 --- a/examples/secaggplus-mt/run.sh +++ b/examples/secaggplus-mt/run.sh @@ -2,12 +2,12 @@ # Kill any currently running client.py processes pkill -f 'flower-client' -# Kill any currently running flower-server processes -pkill -f 'flower-server' +# Kill any currently running flower-superlink processes +pkill -f 'flower-superlink' # Start the flower server echo "Starting flower server in background..." -flower-server --insecure > /dev/null 2>&1 & +flower-superlink --insecure > /dev/null 2>&1 & sleep 2 # Number of client processes to start @@ -30,5 +30,5 @@ echo "Clearing background processes..." # Kill any currently running client.py processes pkill -f 'flower-client' -# Kill any currently running flower-server processes -pkill -f 'flower-server' +# Kill any currently running flower-superlink processes +pkill -f 'flower-superlink' diff --git a/pyproject.toml b/pyproject.toml index 2c3a265c4516..3b2dff937107 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,7 +54,7 @@ exclude = [ [tool.poetry.scripts] flower-driver-api = "flwr.server:run_driver_api" flower-fleet-api = "flwr.server:run_fleet_api" -flower-server = "flwr.server:run_server" +flower-superlink = "flwr.server:run_superlink" flower-client = "flwr.client:run_client" [tool.poetry.dependencies] diff --git a/src/docker/server/Dockerfile b/src/docker/server/Dockerfile index c42246b16104..faa9cf2e56fe 100644 --- a/src/docker/server/Dockerfile +++ b/src/docker/server/Dockerfile @@ -7,8 +7,8 @@ FROM $BASE_REPOSITORY:$BASE_IMAGE_TAG as server WORKDIR /app ARG FLWR_VERSION RUN python -m pip install -U --no-cache-dir flwr[rest]==${FLWR_VERSION} -ENTRYPOINT ["python", "-c", "from flwr.server import run_server; run_server()"] +ENTRYPOINT ["python", "-c", "from flwr.server import run_superlink; run_superlink()"] # Test if Flower can be successfully installed and imported FROM server as test -RUN python -c "from flwr.server import run_server" +RUN python -c "from flwr.server import run_superlink" diff --git a/src/py/flwr/common/telemetry.py b/src/py/flwr/common/telemetry.py index fed8b5a978bc..bbf7a3a60b4f 100644 --- a/src/py/flwr/common/telemetry.py +++ b/src/py/flwr/common/telemetry.py @@ -137,8 +137,8 @@ def _generate_next_value_(name: str, start: int, count: int, last_values: List[A RUN_FLEET_API_LEAVE = auto() # Driver API and Fleet API - RUN_SERVER_ENTER = auto() - RUN_SERVER_LEAVE = auto() + RUN_SUPERLINK_ENTER = auto() + RUN_SUPERLINK_LEAVE = auto() # Simulation START_SIMULATION_ENTER = auto() diff --git a/src/py/flwr/server/__init__.py b/src/py/flwr/server/__init__.py index 74abe8dd463c..7db95ac07ab1 100644 --- a/src/py/flwr/server/__init__.py +++ b/src/py/flwr/server/__init__.py @@ -19,7 +19,7 @@ from .app import ServerConfig as ServerConfig from .app import run_driver_api as run_driver_api from .app import run_fleet_api as run_fleet_api -from .app import run_server as run_server +from .app import run_superlink as run_superlink from .app import start_server as start_server from .client_manager import ClientManager as ClientManager from .client_manager import SimpleClientManager as SimpleClientManager @@ -31,7 +31,7 @@ "History", "run_driver_api", "run_fleet_api", - "run_server", + "run_superlink", "Server", "ServerConfig", "SimpleClientManager", diff --git a/src/py/flwr/server/app.py b/src/py/flwr/server/app.py index 079d6923b23c..3f58dceac894 100644 --- a/src/py/flwr/server/app.py +++ b/src/py/flwr/server/app.py @@ -344,10 +344,10 @@ def run_fleet_api() -> None: # pylint: disable=too-many-branches, too-many-locals, too-many-statements -def run_server() -> None: +def run_superlink() -> None: """Run Flower server (Driver API and Fleet API).""" log(INFO, "Starting Flower server") - event(EventType.RUN_SERVER_ENTER) + event(EventType.RUN_SUPERLINK_ENTER) args = _parse_args_server().parse_args() # Parse IP address @@ -419,7 +419,7 @@ def run_server() -> None: _register_exit_handlers( grpc_servers=grpc_servers, bckg_threads=bckg_threads, - event_type=EventType.RUN_SERVER_LEAVE, + event_type=EventType.RUN_SUPERLINK_LEAVE, ) # Block From c6f292999278f6bfa59a038976c116fe362b9f93 Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Sun, 11 Feb 2024 17:24:07 +0100 Subject: [PATCH 090/113] Rename flower-client to flower-client-app (#2922) --- doc/source/ref-api-cli.rst | 14 +++++++++++--- e2e/test_driver.sh | 4 ++-- examples/secaggplus-mt/client.py | 2 +- examples/secaggplus-mt/run.sh | 6 +++--- pyproject.toml | 2 +- src/py/flwr/client/__init__.py | 4 ++-- src/py/flwr/client/app.py | 14 +++++++------- src/py/flwr/client/clientapp.py | 2 +- src/py/flwr/common/telemetry.py | 6 +++--- 9 files changed, 31 insertions(+), 23 deletions(-) diff --git a/doc/source/ref-api-cli.rst b/doc/source/ref-api-cli.rst index 6d5408f76a35..0326567dc1bd 100644 --- a/doc/source/ref-api-cli.rst +++ b/doc/source/ref-api-cli.rst @@ -31,10 +31,18 @@ flower-fleet-api :func: _parse_args_fleet :prog: flower-fleet-api -.. .. _flower-client-apiref: +.. _flower-client-app-apiref: + +flower-client-app +~~~~~~~~~~~~~~~~~ + +.. argparse:: + :filename: flwr.client + :func: run_client_app + :prog: flower-client-app + +.. _flower-server-app-apiref: -.. flower-client -.. ~~~~~~~~~~~~~ .. argparse:: .. :filename: flwr.client diff --git a/e2e/test_driver.sh b/e2e/test_driver.sh index ffac1f8d30db..3d4864a1b0fb 100755 --- a/e2e/test_driver.sh +++ b/e2e/test_driver.sh @@ -35,11 +35,11 @@ timeout 2m flower-superlink $server_arg $db_arg $rest_arg & sl_pid=$! sleep 3 -timeout 2m flower-client client:app $client_arg $rest_arg --server $server_address & +timeout 2m flower-client-app client:app $client_arg $rest_arg --server $server_address & cl1_pid=$! sleep 3 -timeout 2m flower-client client:app $client_arg $rest_arg --server $server_address & +timeout 2m flower-client-app client:app $client_arg $rest_arg --server $server_address & cl2_pid=$! sleep 3 diff --git a/examples/secaggplus-mt/client.py b/examples/secaggplus-mt/client.py index dc9deef7d605..164a261213be 100644 --- a/examples/secaggplus-mt/client.py +++ b/examples/secaggplus-mt/client.py @@ -32,7 +32,7 @@ def client_fn(cid: str): return FlowerClient().to_client() -# To run this: `flower-client client:app` +# To run this: `flower-client-app client:app` app = fl.client.ClientApp( client_fn=client_fn, mods=[secaggplus_mod], diff --git a/examples/secaggplus-mt/run.sh b/examples/secaggplus-mt/run.sh index 7a0f1592f646..659c1aaee8ce 100755 --- a/examples/secaggplus-mt/run.sh +++ b/examples/secaggplus-mt/run.sh @@ -1,6 +1,6 @@ #!/bin/bash # Kill any currently running client.py processes -pkill -f 'flower-client' +pkill -f 'flower-client-app' # Kill any currently running flower-superlink processes pkill -f 'flower-superlink' @@ -18,7 +18,7 @@ echo "Starting $N clients in background..." # Start N client processes for i in $(seq 1 $N) do - flower-client --insecure client:app > /dev/null 2>&1 & + flower-client-app --insecure client:app > /dev/null 2>&1 & sleep 0.1 done @@ -28,7 +28,7 @@ python driver.py echo "Clearing background processes..." # Kill any currently running client.py processes -pkill -f 'flower-client' +pkill -f 'flower-client-app' # Kill any currently running flower-superlink processes pkill -f 'flower-superlink' diff --git a/pyproject.toml b/pyproject.toml index 3b2dff937107..9ee44ba2b6af 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,7 +55,7 @@ exclude = [ flower-driver-api = "flwr.server:run_driver_api" flower-fleet-api = "flwr.server:run_fleet_api" flower-superlink = "flwr.server:run_superlink" -flower-client = "flwr.client:run_client" +flower-client-app = "flwr.client:run_client_app" [tool.poetry.dependencies] python = "^3.8" diff --git a/src/py/flwr/client/__init__.py b/src/py/flwr/client/__init__.py index a3bd3bf33e78..f359fb472cbe 100644 --- a/src/py/flwr/client/__init__.py +++ b/src/py/flwr/client/__init__.py @@ -15,7 +15,7 @@ """Flower client.""" -from .app import run_client as run_client +from .app import run_client_app as run_client_app from .app import start_client as start_client from .app import start_numpy_client as start_numpy_client from .client import Client as Client @@ -28,7 +28,7 @@ "ClientApp", "ClientFn", "NumPyClient", - "run_client", + "run_client_app", "start_client", "start_numpy_client", ] diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index 56520f76db6c..7b82d41c293a 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -45,13 +45,13 @@ from .numpy_client import NumPyClient -def run_client() -> None: - """Run Flower client.""" - event(EventType.RUN_CLIENT_ENTER) +def run_client_app() -> None: + """Run Flower client app.""" + event(EventType.RUN_CLIENT_APP_ENTER) log(INFO, "Long-running Flower client starting") - args = _parse_args_client().parse_args() + args = _parse_args_run_client_app().parse_args() # Obtain certificates if args.insecure: @@ -105,11 +105,11 @@ def _load() -> ClientApp: root_certificates=root_certificates, insecure=args.insecure, ) - event(EventType.RUN_CLIENT_LEAVE) + event(EventType.RUN_CLIENT_APP_LEAVE) -def _parse_args_client() -> argparse.ArgumentParser: - """Parse command line arguments.""" +def _parse_args_run_client_app() -> argparse.ArgumentParser: + """Parse flower-client-app command line arguments.""" parser = argparse.ArgumentParser( description="Start a long-running Flower client", ) diff --git a/src/py/flwr/client/clientapp.py b/src/py/flwr/client/clientapp.py index fbd443cc7500..51c912890c7e 100644 --- a/src/py/flwr/client/clientapp.py +++ b/src/py/flwr/client/clientapp.py @@ -46,7 +46,7 @@ class ClientApp: If the above code is in a Python module called `client`, it can be started as follows: - >>> flower-client client:app --insecure + >>> flower-client-app client:app --insecure In this `client:app` example, `client` refers to the Python module `client.py` in which the previous code lives in and `app` refers to the global attribute `app` that diff --git a/src/py/flwr/common/telemetry.py b/src/py/flwr/common/telemetry.py index bbf7a3a60b4f..9c97fc567b20 100644 --- a/src/py/flwr/common/telemetry.py +++ b/src/py/flwr/common/telemetry.py @@ -152,9 +152,9 @@ def _generate_next_value_(name: str, start: int, count: int, last_values: List[A START_DRIVER_ENTER = auto() START_DRIVER_LEAVE = auto() - # SuperNode: flower-client - RUN_CLIENT_ENTER = auto() - RUN_CLIENT_LEAVE = auto() + # flower-client-app + RUN_CLIENT_APP_ENTER = auto() + RUN_CLIENT_APP_LEAVE = auto() # Use the ThreadPoolExecutor with max_workers=1 to have a queue From 046ec4e20a90ae038bc23f97a65849d7d804e433 Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Sun, 11 Feb 2024 17:36:50 +0100 Subject: [PATCH 091/113] Move driver/fleet/state into superlink subpackage (#2924) --- .../flwr/client/grpc_client/connection_test.py | 6 ++++-- src/py/flwr/driver/app.py | 2 +- src/py/flwr/server/app.py | 18 +++++++++--------- src/py/flwr/server/client_manager_test.py | 2 +- src/py/flwr/server/criterion_test.py | 2 +- src/py/flwr/server/strategy/fedadagrad_test.py | 2 +- src/py/flwr/server/strategy/fedmedian_test.py | 2 +- src/py/flwr/server/strategy/krum_test.py | 2 +- src/py/flwr/server/strategy/multikrum_test.py | 2 +- src/py/flwr/server/superlink/__init__.py | 15 +++++++++++++++ .../server/{ => superlink}/driver/__init__.py | 0 .../{ => superlink}/driver/driver_servicer.py | 2 +- .../driver/driver_servicer_test.py | 2 +- .../server/{ => superlink}/fleet/__init__.py | 0 .../fleet/grpc_bidi/__init__.py | 0 .../fleet/grpc_bidi/flower_service_servicer.py | 8 ++++++-- .../grpc_bidi/flower_service_servicer_test.py | 4 ++-- .../fleet/grpc_bidi/grpc_bridge.py | 0 .../fleet/grpc_bidi/grpc_bridge_test.py | 2 +- .../fleet/grpc_bidi/grpc_client_proxy.py | 6 +++++- .../fleet/grpc_bidi/grpc_client_proxy_test.py | 4 ++-- .../fleet/grpc_bidi/grpc_server.py | 8 +++++--- .../fleet/grpc_bidi/grpc_server_test.py | 4 ++-- .../fleet/grpc_rere/__init__.py | 0 .../fleet/grpc_rere/fleet_servicer.py | 4 ++-- .../fleet/message_handler/__init__.py | 0 .../fleet/message_handler/message_handler.py | 2 +- .../message_handler/message_handler_test.py | 0 .../fleet/rest_rere/__init__.py | 0 .../fleet/rest_rere/rest_api.py | 4 ++-- .../server/{ => superlink}/state/__init__.py | 0 .../{ => superlink}/state/in_memory_state.py | 2 +- .../{ => superlink}/state/sqlite_state.py | 0 .../{ => superlink}/state/sqlite_state_test.py | 4 ++-- .../flwr/server/{ => superlink}/state/state.py | 0 .../{ => superlink}/state/state_factory.py | 0 .../server/{ => superlink}/state/state_test.py | 2 +- 37 files changed, 69 insertions(+), 42 deletions(-) create mode 100644 src/py/flwr/server/superlink/__init__.py rename src/py/flwr/server/{ => superlink}/driver/__init__.py (100%) rename src/py/flwr/server/{ => superlink}/driver/driver_servicer.py (98%) rename src/py/flwr/server/{ => superlink}/driver/driver_servicer_test.py (95%) rename src/py/flwr/server/{ => superlink}/fleet/__init__.py (100%) rename src/py/flwr/server/{ => superlink}/fleet/grpc_bidi/__init__.py (100%) rename src/py/flwr/server/{ => superlink}/fleet/grpc_bidi/flower_service_servicer.py (96%) rename src/py/flwr/server/{ => superlink}/fleet/grpc_bidi/flower_service_servicer_test.py (96%) rename src/py/flwr/server/{ => superlink}/fleet/grpc_bidi/grpc_bridge.py (100%) rename src/py/flwr/server/{ => superlink}/fleet/grpc_bidi/grpc_bridge_test.py (98%) rename src/py/flwr/server/{ => superlink}/fleet/grpc_bidi/grpc_client_proxy.py (97%) rename src/py/flwr/server/{ => superlink}/fleet/grpc_bidi/grpc_client_proxy_test.py (96%) rename src/py/flwr/server/{ => superlink}/fleet/grpc_bidi/grpc_server.py (97%) rename src/py/flwr/server/{ => superlink}/fleet/grpc_bidi/grpc_server_test.py (96%) rename src/py/flwr/server/{ => superlink}/fleet/grpc_rere/__init__.py (100%) rename src/py/flwr/server/{ => superlink}/fleet/grpc_rere/fleet_servicer.py (95%) rename src/py/flwr/server/{ => superlink}/fleet/message_handler/__init__.py (100%) rename src/py/flwr/server/{ => superlink}/fleet/message_handler/message_handler.py (98%) rename src/py/flwr/server/{ => superlink}/fleet/message_handler/message_handler_test.py (100%) rename src/py/flwr/server/{ => superlink}/fleet/rest_rere/__init__.py (100%) rename src/py/flwr/server/{ => superlink}/fleet/rest_rere/rest_api.py (98%) rename src/py/flwr/server/{ => superlink}/state/__init__.py (100%) rename src/py/flwr/server/{ => superlink}/state/in_memory_state.py (99%) rename src/py/flwr/server/{ => superlink}/state/sqlite_state.py (100%) rename src/py/flwr/server/{ => superlink}/state/sqlite_state_test.py (92%) rename src/py/flwr/server/{ => superlink}/state/state.py (100%) rename src/py/flwr/server/{ => superlink}/state/state_factory.py (100%) rename src/py/flwr/server/{ => superlink}/state/state_test.py (99%) diff --git a/src/py/flwr/client/grpc_client/connection_test.py b/src/py/flwr/client/grpc_client/connection_test.py index 8631c4a9b12b..54fd41d79325 100644 --- a/src/py/flwr/client/grpc_client/connection_test.py +++ b/src/py/flwr/client/grpc_client/connection_test.py @@ -34,7 +34,7 @@ ServerMessage, ) from flwr.server.client_manager import SimpleClientManager -from flwr.server.fleet.grpc_bidi.grpc_server import start_grpc_server +from flwr.server.superlink.fleet.grpc_bidi.grpc_server import start_grpc_server from .connection import grpc_connection @@ -100,7 +100,9 @@ def mock_join( # type: ignore # pylint: disable=invalid-name @patch( - "flwr.server.fleet.grpc_bidi.flower_service_servicer.FlowerServiceServicer.Join", + # pylint: disable=line-too-long + "flwr.server.superlink.fleet.grpc_bidi.flower_service_servicer.FlowerServiceServicer.Join", # noqa: E501 + # pylint: enable=line-too-long mock_join, ) def test_integration_connection() -> None: diff --git a/src/py/flwr/driver/app.py b/src/py/flwr/driver/app.py index 2c0576bde8ff..ae47c58f4e9c 100644 --- a/src/py/flwr/driver/app.py +++ b/src/py/flwr/driver/app.py @@ -72,7 +72,7 @@ def start_driver( # pylint: disable=too-many-arguments, too-many-locals An implementation of the abstract base class `flwr.server.strategy.Strategy`. If no strategy is provided, then `start_server` will use `flwr.server.strategy.FedAvg`. - client_manager : Optional[flwr.server.DriverClientManager] (default: None) + client_manager : Optional[flwr.server.ClientManager] (default: None) An implementation of the class `flwr.server.ClientManager`. If no implementation is provided, then `start_driver` will use `flwr.server.SimpleClientManager`. diff --git a/src/py/flwr/server/app.py b/src/py/flwr/server/app.py index 3f58dceac894..895a6be300f2 100644 --- a/src/py/flwr/server/app.py +++ b/src/py/flwr/server/app.py @@ -44,16 +44,16 @@ add_FleetServicer_to_server, ) from flwr.server.client_manager import ClientManager, SimpleClientManager -from flwr.server.driver.driver_servicer import DriverServicer -from flwr.server.fleet.grpc_bidi.grpc_server import ( - generic_create_grpc_server, - start_grpc_server, -) -from flwr.server.fleet.grpc_rere.fleet_servicer import FleetServicer from flwr.server.history import History from flwr.server.server import Server -from flwr.server.state import StateFactory from flwr.server.strategy import FedAvg, Strategy +from flwr.server.superlink.driver.driver_servicer import DriverServicer +from flwr.server.superlink.fleet.grpc_bidi.grpc_server import ( + generic_create_grpc_server, + start_grpc_server, +) +from flwr.server.superlink.fleet.grpc_rere.fleet_servicer import FleetServicer +from flwr.server.superlink.state import StateFactory ADDRESS_DRIVER_API = "0.0.0.0:9091" ADDRESS_FLEET_API_GRPC_RERE = "0.0.0.0:9092" @@ -561,7 +561,7 @@ def _run_fleet_api_rest( try: import uvicorn - from flwr.server.fleet.rest_rere.rest_api import app as fast_api_app + from flwr.server.superlink.fleet.rest_rere.rest_api import app as fast_api_app except ModuleNotFoundError: sys.exit(MISSING_EXTRA_REST) if workers != 1: @@ -584,7 +584,7 @@ def _run_fleet_api_rest( raise ValueError(validation_exceptions) uvicorn.run( - app="flwr.server.fleet.rest_rere.rest_api:app", + app="flwr.server.superlink.fleet.rest_rere.rest_api:app", port=port, host=host, reload=False, diff --git a/src/py/flwr/server/client_manager_test.py b/src/py/flwr/server/client_manager_test.py index 8145b9b2ab7f..5820881b6aad 100644 --- a/src/py/flwr/server/client_manager_test.py +++ b/src/py/flwr/server/client_manager_test.py @@ -18,7 +18,7 @@ from unittest.mock import MagicMock from flwr.server.client_manager import SimpleClientManager -from flwr.server.fleet.grpc_bidi.grpc_client_proxy import GrpcClientProxy +from flwr.server.superlink.fleet.grpc_bidi.grpc_client_proxy import GrpcClientProxy def test_simple_client_manager_register() -> None: diff --git a/src/py/flwr/server/criterion_test.py b/src/py/flwr/server/criterion_test.py index a7e5b62b5977..f678825f064e 100644 --- a/src/py/flwr/server/criterion_test.py +++ b/src/py/flwr/server/criterion_test.py @@ -20,7 +20,7 @@ from flwr.server.client_manager import SimpleClientManager from flwr.server.client_proxy import ClientProxy from flwr.server.criterion import Criterion -from flwr.server.fleet.grpc_bidi.grpc_client_proxy import GrpcClientProxy +from flwr.server.superlink.fleet.grpc_bidi.grpc_client_proxy import GrpcClientProxy def test_criterion_applied() -> None: diff --git a/src/py/flwr/server/strategy/fedadagrad_test.py b/src/py/flwr/server/strategy/fedadagrad_test.py index b3380a5be2f9..0c966442ecaf 100644 --- a/src/py/flwr/server/strategy/fedadagrad_test.py +++ b/src/py/flwr/server/strategy/fedadagrad_test.py @@ -30,7 +30,7 @@ parameters_to_ndarrays, ) from flwr.server.client_proxy import ClientProxy -from flwr.server.fleet.grpc_bidi.grpc_client_proxy import GrpcClientProxy +from flwr.server.superlink.fleet.grpc_bidi.grpc_client_proxy import GrpcClientProxy from .fedadagrad import FedAdagrad diff --git a/src/py/flwr/server/strategy/fedmedian_test.py b/src/py/flwr/server/strategy/fedmedian_test.py index 180503df6c80..57cf08d8c01d 100644 --- a/src/py/flwr/server/strategy/fedmedian_test.py +++ b/src/py/flwr/server/strategy/fedmedian_test.py @@ -30,7 +30,7 @@ parameters_to_ndarrays, ) from flwr.server.client_proxy import ClientProxy -from flwr.server.fleet.grpc_bidi.grpc_client_proxy import GrpcClientProxy +from flwr.server.superlink.fleet.grpc_bidi.grpc_client_proxy import GrpcClientProxy from .fedmedian import FedMedian diff --git a/src/py/flwr/server/strategy/krum_test.py b/src/py/flwr/server/strategy/krum_test.py index 81e59230739a..653dc9a8475d 100644 --- a/src/py/flwr/server/strategy/krum_test.py +++ b/src/py/flwr/server/strategy/krum_test.py @@ -30,7 +30,7 @@ parameters_to_ndarrays, ) from flwr.server.client_proxy import ClientProxy -from flwr.server.fleet.grpc_bidi.grpc_client_proxy import GrpcClientProxy +from flwr.server.superlink.fleet.grpc_bidi.grpc_client_proxy import GrpcClientProxy from .krum import Krum diff --git a/src/py/flwr/server/strategy/multikrum_test.py b/src/py/flwr/server/strategy/multikrum_test.py index 1469db104252..f874dc2f9800 100644 --- a/src/py/flwr/server/strategy/multikrum_test.py +++ b/src/py/flwr/server/strategy/multikrum_test.py @@ -30,7 +30,7 @@ parameters_to_ndarrays, ) from flwr.server.client_proxy import ClientProxy -from flwr.server.fleet.grpc_bidi.grpc_client_proxy import GrpcClientProxy +from flwr.server.superlink.fleet.grpc_bidi.grpc_client_proxy import GrpcClientProxy from .krum import Krum diff --git a/src/py/flwr/server/superlink/__init__.py b/src/py/flwr/server/superlink/__init__.py new file mode 100644 index 000000000000..94102100de26 --- /dev/null +++ b/src/py/flwr/server/superlink/__init__.py @@ -0,0 +1,15 @@ +# Copyright 2024 Flower Labs GmbH. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Flower SuperLink.""" diff --git a/src/py/flwr/server/driver/__init__.py b/src/py/flwr/server/superlink/driver/__init__.py similarity index 100% rename from src/py/flwr/server/driver/__init__.py rename to src/py/flwr/server/superlink/driver/__init__.py diff --git a/src/py/flwr/server/driver/driver_servicer.py b/src/py/flwr/server/superlink/driver/driver_servicer.py similarity index 98% rename from src/py/flwr/server/driver/driver_servicer.py rename to src/py/flwr/server/superlink/driver/driver_servicer.py index 275cc8ac6a03..ca2cd69b2f20 100644 --- a/src/py/flwr/server/driver/driver_servicer.py +++ b/src/py/flwr/server/superlink/driver/driver_servicer.py @@ -35,7 +35,7 @@ ) from flwr.proto.node_pb2 import Node # pylint: disable=E0611 from flwr.proto.task_pb2 import TaskRes # pylint: disable=E0611 -from flwr.server.state import State, StateFactory +from flwr.server.superlink.state import State, StateFactory from flwr.server.utils.validator import validate_task_ins_or_res diff --git a/src/py/flwr/server/driver/driver_servicer_test.py b/src/py/flwr/server/superlink/driver/driver_servicer_test.py similarity index 95% rename from src/py/flwr/server/driver/driver_servicer_test.py rename to src/py/flwr/server/superlink/driver/driver_servicer_test.py index c432c026a632..99f7cc007a89 100644 --- a/src/py/flwr/server/driver/driver_servicer_test.py +++ b/src/py/flwr/server/superlink/driver/driver_servicer_test.py @@ -15,7 +15,7 @@ """DriverServicer tests.""" -from flwr.server.driver.driver_servicer import _raise_if +from flwr.server.superlink.driver.driver_servicer import _raise_if # pylint: disable=broad-except diff --git a/src/py/flwr/server/fleet/__init__.py b/src/py/flwr/server/superlink/fleet/__init__.py similarity index 100% rename from src/py/flwr/server/fleet/__init__.py rename to src/py/flwr/server/superlink/fleet/__init__.py diff --git a/src/py/flwr/server/fleet/grpc_bidi/__init__.py b/src/py/flwr/server/superlink/fleet/grpc_bidi/__init__.py similarity index 100% rename from src/py/flwr/server/fleet/grpc_bidi/__init__.py rename to src/py/flwr/server/superlink/fleet/grpc_bidi/__init__.py diff --git a/src/py/flwr/server/fleet/grpc_bidi/flower_service_servicer.py b/src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py similarity index 96% rename from src/py/flwr/server/fleet/grpc_bidi/flower_service_servicer.py rename to src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py index 1397a026a33c..6f94ea844e38 100644 --- a/src/py/flwr/server/fleet/grpc_bidi/flower_service_servicer.py +++ b/src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py @@ -30,8 +30,12 @@ ServerMessage, ) from flwr.server.client_manager import ClientManager -from flwr.server.fleet.grpc_bidi.grpc_bridge import GrpcBridge, InsWrapper, ResWrapper -from flwr.server.fleet.grpc_bidi.grpc_client_proxy import GrpcClientProxy +from flwr.server.superlink.fleet.grpc_bidi.grpc_bridge import ( + GrpcBridge, + InsWrapper, + ResWrapper, +) +from flwr.server.superlink.fleet.grpc_bidi.grpc_client_proxy import GrpcClientProxy def default_bridge_factory() -> GrpcBridge: diff --git a/src/py/flwr/server/fleet/grpc_bidi/flower_service_servicer_test.py b/src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer_test.py similarity index 96% rename from src/py/flwr/server/fleet/grpc_bidi/flower_service_servicer_test.py rename to src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer_test.py index 37eef167879c..bd93554a6a32 100644 --- a/src/py/flwr/server/fleet/grpc_bidi/flower_service_servicer_test.py +++ b/src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer_test.py @@ -23,11 +23,11 @@ ClientMessage, ServerMessage, ) -from flwr.server.fleet.grpc_bidi.flower_service_servicer import ( +from flwr.server.superlink.fleet.grpc_bidi.flower_service_servicer import ( FlowerServiceServicer, register_client_proxy, ) -from flwr.server.fleet.grpc_bidi.grpc_bridge import InsWrapper, ResWrapper +from flwr.server.superlink.fleet.grpc_bidi.grpc_bridge import InsWrapper, ResWrapper CLIENT_MESSAGE = ClientMessage() SERVER_MESSAGE = ServerMessage() diff --git a/src/py/flwr/server/fleet/grpc_bidi/grpc_bridge.py b/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py similarity index 100% rename from src/py/flwr/server/fleet/grpc_bidi/grpc_bridge.py rename to src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py diff --git a/src/py/flwr/server/fleet/grpc_bidi/grpc_bridge_test.py b/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge_test.py similarity index 98% rename from src/py/flwr/server/fleet/grpc_bidi/grpc_bridge_test.py rename to src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge_test.py index 6527c45d7d6c..f7c236acd7a1 100644 --- a/src/py/flwr/server/fleet/grpc_bidi/grpc_bridge_test.py +++ b/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge_test.py @@ -23,7 +23,7 @@ ClientMessage, ServerMessage, ) -from flwr.server.fleet.grpc_bidi.grpc_bridge import ( +from flwr.server.superlink.fleet.grpc_bidi.grpc_bridge import ( GrpcBridge, GrpcBridgeClosed, InsWrapper, diff --git a/src/py/flwr/server/fleet/grpc_bidi/grpc_client_proxy.py b/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py similarity index 97% rename from src/py/flwr/server/fleet/grpc_bidi/grpc_client_proxy.py rename to src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py index 46185896561e..026e8dfe51ef 100644 --- a/src/py/flwr/server/fleet/grpc_bidi/grpc_client_proxy.py +++ b/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py @@ -24,7 +24,11 @@ ServerMessage, ) from flwr.server.client_proxy import ClientProxy -from flwr.server.fleet.grpc_bidi.grpc_bridge import GrpcBridge, InsWrapper, ResWrapper +from flwr.server.superlink.fleet.grpc_bidi.grpc_bridge import ( + GrpcBridge, + InsWrapper, + ResWrapper, +) class GrpcClientProxy(ClientProxy): diff --git a/src/py/flwr/server/fleet/grpc_bidi/grpc_client_proxy_test.py b/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy_test.py similarity index 96% rename from src/py/flwr/server/fleet/grpc_bidi/grpc_client_proxy_test.py rename to src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy_test.py index 1a417ae433d5..360570eb663d 100644 --- a/src/py/flwr/server/fleet/grpc_bidi/grpc_client_proxy_test.py +++ b/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy_test.py @@ -27,8 +27,8 @@ Parameters, Scalar, ) -from flwr.server.fleet.grpc_bidi.grpc_bridge import ResWrapper -from flwr.server.fleet.grpc_bidi.grpc_client_proxy import GrpcClientProxy +from flwr.server.superlink.fleet.grpc_bidi.grpc_bridge import ResWrapper +from flwr.server.superlink.fleet.grpc_bidi.grpc_client_proxy import GrpcClientProxy MESSAGE_PARAMETERS = Parameters(tensors=[], tensor_type="np") MESSAGE_FIT_RES = ClientMessage( diff --git a/src/py/flwr/server/fleet/grpc_bidi/grpc_server.py b/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server.py similarity index 97% rename from src/py/flwr/server/fleet/grpc_bidi/grpc_server.py rename to src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server.py index e05df88dcd12..82f049844bd6 100644 --- a/src/py/flwr/server/fleet/grpc_bidi/grpc_server.py +++ b/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server.py @@ -28,9 +28,11 @@ add_FlowerServiceServicer_to_server, ) from flwr.server.client_manager import ClientManager -from flwr.server.driver.driver_servicer import DriverServicer -from flwr.server.fleet.grpc_bidi.flower_service_servicer import FlowerServiceServicer -from flwr.server.fleet.grpc_rere.fleet_servicer import FleetServicer +from flwr.server.superlink.driver.driver_servicer import DriverServicer +from flwr.server.superlink.fleet.grpc_bidi.flower_service_servicer import ( + FlowerServiceServicer, +) +from flwr.server.superlink.fleet.grpc_rere.fleet_servicer import FleetServicer INVALID_CERTIFICATES_ERR_MSG = """ When setting any of root_certificate, certificate, or private_key, diff --git a/src/py/flwr/server/fleet/grpc_bidi/grpc_server_test.py b/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server_test.py similarity index 96% rename from src/py/flwr/server/fleet/grpc_bidi/grpc_server_test.py rename to src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server_test.py index 4cd093d6ab0f..8afa37515950 100644 --- a/src/py/flwr/server/fleet/grpc_bidi/grpc_server_test.py +++ b/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server_test.py @@ -23,12 +23,12 @@ from typing import Tuple, cast from flwr.server.client_manager import SimpleClientManager -from flwr.server.fleet.grpc_bidi.grpc_server import ( +from flwr.server.superlink.fleet.grpc_bidi.grpc_server import ( start_grpc_server, valid_certificates, ) -root_dir = dirname(abspath(join(__file__, "../../../../../.."))) +root_dir = dirname(abspath(join(__file__, "../../../../../../.."))) def load_certificates() -> Tuple[str, str, str]: diff --git a/src/py/flwr/server/fleet/grpc_rere/__init__.py b/src/py/flwr/server/superlink/fleet/grpc_rere/__init__.py similarity index 100% rename from src/py/flwr/server/fleet/grpc_rere/__init__.py rename to src/py/flwr/server/superlink/fleet/grpc_rere/__init__.py diff --git a/src/py/flwr/server/fleet/grpc_rere/fleet_servicer.py b/src/py/flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py similarity index 95% rename from src/py/flwr/server/fleet/grpc_rere/fleet_servicer.py rename to src/py/flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py index 25707b6247fa..278474477379 100644 --- a/src/py/flwr/server/fleet/grpc_rere/fleet_servicer.py +++ b/src/py/flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py @@ -31,8 +31,8 @@ PushTaskResRequest, PushTaskResResponse, ) -from flwr.server.fleet.message_handler import message_handler -from flwr.server.state import StateFactory +from flwr.server.superlink.fleet.message_handler import message_handler +from flwr.server.superlink.state import StateFactory class FleetServicer(fleet_pb2_grpc.FleetServicer): diff --git a/src/py/flwr/server/fleet/message_handler/__init__.py b/src/py/flwr/server/superlink/fleet/message_handler/__init__.py similarity index 100% rename from src/py/flwr/server/fleet/message_handler/__init__.py rename to src/py/flwr/server/superlink/fleet/message_handler/__init__.py diff --git a/src/py/flwr/server/fleet/message_handler/message_handler.py b/src/py/flwr/server/superlink/fleet/message_handler/message_handler.py similarity index 98% rename from src/py/flwr/server/fleet/message_handler/message_handler.py rename to src/py/flwr/server/superlink/fleet/message_handler/message_handler.py index 8d451c896ed9..5fe815180823 100644 --- a/src/py/flwr/server/fleet/message_handler/message_handler.py +++ b/src/py/flwr/server/superlink/fleet/message_handler/message_handler.py @@ -31,7 +31,7 @@ ) from flwr.proto.node_pb2 import Node # pylint: disable=E0611 from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611 -from flwr.server.state import State +from flwr.server.superlink.state import State def create_node( diff --git a/src/py/flwr/server/fleet/message_handler/message_handler_test.py b/src/py/flwr/server/superlink/fleet/message_handler/message_handler_test.py similarity index 100% rename from src/py/flwr/server/fleet/message_handler/message_handler_test.py rename to src/py/flwr/server/superlink/fleet/message_handler/message_handler_test.py diff --git a/src/py/flwr/server/fleet/rest_rere/__init__.py b/src/py/flwr/server/superlink/fleet/rest_rere/__init__.py similarity index 100% rename from src/py/flwr/server/fleet/rest_rere/__init__.py rename to src/py/flwr/server/superlink/fleet/rest_rere/__init__.py diff --git a/src/py/flwr/server/fleet/rest_rere/rest_api.py b/src/py/flwr/server/superlink/fleet/rest_rere/rest_api.py similarity index 98% rename from src/py/flwr/server/fleet/rest_rere/rest_api.py rename to src/py/flwr/server/superlink/fleet/rest_rere/rest_api.py index b815558cb099..b022b34c68c8 100644 --- a/src/py/flwr/server/fleet/rest_rere/rest_api.py +++ b/src/py/flwr/server/superlink/fleet/rest_rere/rest_api.py @@ -24,8 +24,8 @@ PullTaskInsRequest, PushTaskResRequest, ) -from flwr.server.fleet.message_handler import message_handler -from flwr.server.state import State +from flwr.server.superlink.fleet.message_handler import message_handler +from flwr.server.superlink.state import State try: from starlette.applications import Starlette diff --git a/src/py/flwr/server/state/__init__.py b/src/py/flwr/server/superlink/state/__init__.py similarity index 100% rename from src/py/flwr/server/state/__init__.py rename to src/py/flwr/server/superlink/state/__init__.py diff --git a/src/py/flwr/server/state/in_memory_state.py b/src/py/flwr/server/superlink/state/in_memory_state.py similarity index 99% rename from src/py/flwr/server/state/in_memory_state.py rename to src/py/flwr/server/superlink/state/in_memory_state.py index f21845fcb909..ecb39f18300a 100644 --- a/src/py/flwr/server/state/in_memory_state.py +++ b/src/py/flwr/server/superlink/state/in_memory_state.py @@ -23,7 +23,7 @@ from flwr.common import log, now from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611 -from flwr.server.state.state import State +from flwr.server.superlink.state.state import State from flwr.server.utils import validate_task_ins_or_res diff --git a/src/py/flwr/server/state/sqlite_state.py b/src/py/flwr/server/superlink/state/sqlite_state.py similarity index 100% rename from src/py/flwr/server/state/sqlite_state.py rename to src/py/flwr/server/superlink/state/sqlite_state.py diff --git a/src/py/flwr/server/state/sqlite_state_test.py b/src/py/flwr/server/superlink/state/sqlite_state_test.py similarity index 92% rename from src/py/flwr/server/state/sqlite_state_test.py rename to src/py/flwr/server/superlink/state/sqlite_state_test.py index f9d88ee07853..9eef71e396e3 100644 --- a/src/py/flwr/server/state/sqlite_state_test.py +++ b/src/py/flwr/server/superlink/state/sqlite_state_test.py @@ -17,8 +17,8 @@ import unittest -from flwr.server.state.sqlite_state import task_ins_to_dict -from flwr.server.state.state_test import create_task_ins +from flwr.server.superlink.state.sqlite_state import task_ins_to_dict +from flwr.server.superlink.state.state_test import create_task_ins class SqliteStateTest(unittest.TestCase): diff --git a/src/py/flwr/server/state/state.py b/src/py/flwr/server/superlink/state/state.py similarity index 100% rename from src/py/flwr/server/state/state.py rename to src/py/flwr/server/superlink/state/state.py diff --git a/src/py/flwr/server/state/state_factory.py b/src/py/flwr/server/superlink/state/state_factory.py similarity index 100% rename from src/py/flwr/server/state/state_factory.py rename to src/py/flwr/server/superlink/state/state_factory.py diff --git a/src/py/flwr/server/state/state_test.py b/src/py/flwr/server/superlink/state/state_test.py similarity index 99% rename from src/py/flwr/server/state/state_test.py rename to src/py/flwr/server/superlink/state/state_test.py index 95d764792ff3..d0470a7ce7f7 100644 --- a/src/py/flwr/server/state/state_test.py +++ b/src/py/flwr/server/superlink/state/state_test.py @@ -25,7 +25,7 @@ from flwr.proto.node_pb2 import Node # pylint: disable=E0611 from flwr.proto.recordset_pb2 import RecordSet # pylint: disable=E0611 from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611 -from flwr.server.state import InMemoryState, SqliteState, State +from flwr.server.superlink.state import InMemoryState, SqliteState, State class StateTest(unittest.TestCase): From d6e35ccaa60fb25c90e512e086e70655665528fa Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Sun, 11 Feb 2024 17:50:09 +0100 Subject: [PATCH 092/113] Add flower-server-app command (#2923) --- doc/source/ref-api-cli.rst | 14 ++++++++------ pyproject.toml | 1 + src/py/flwr/common/telemetry.py | 4 ++++ src/py/flwr/server/__init__.py | 2 ++ src/py/flwr/server/app.py | 7 +++++++ 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/doc/source/ref-api-cli.rst b/doc/source/ref-api-cli.rst index 0326567dc1bd..b5f7ce7bae65 100644 --- a/doc/source/ref-api-cli.rst +++ b/doc/source/ref-api-cli.rst @@ -11,7 +11,7 @@ flower-superlink :func: _parse_args_server :prog: flower-superlink -.. _flower-driver-apiref: +.. _flower-driver-api-apiref: flower-driver-api ~~~~~~~~~~~~~~~~~ @@ -21,7 +21,7 @@ flower-driver-api :func: _parse_args_driver :prog: flower-driver-api -.. _flower-fleet-apiref: +.. _flower-fleet-api-apiref: flower-fleet-api ~~~~~~~~~~~~~~~~ @@ -43,8 +43,10 @@ flower-client-app .. _flower-server-app-apiref: +flower-server-app +~~~~~~~~~~~~~~~~~ - .. argparse:: -.. :filename: flwr.client -.. :func: run_client -.. :prog: flower-client +.. argparse:: + :filename: flwr.server + :func: run_server_app + :prog: flower-server-app diff --git a/pyproject.toml b/pyproject.toml index 9ee44ba2b6af..16688268f7be 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,6 +56,7 @@ flower-driver-api = "flwr.server:run_driver_api" flower-fleet-api = "flwr.server:run_fleet_api" flower-superlink = "flwr.server:run_superlink" flower-client-app = "flwr.client:run_client_app" +flower-server-app = "flwr.server:run_server_app" [tool.poetry.dependencies] python = "^3.8" diff --git a/src/py/flwr/common/telemetry.py b/src/py/flwr/common/telemetry.py index 9c97fc567b20..2087c8b66ab5 100644 --- a/src/py/flwr/common/telemetry.py +++ b/src/py/flwr/common/telemetry.py @@ -156,6 +156,10 @@ def _generate_next_value_(name: str, start: int, count: int, last_values: List[A RUN_CLIENT_APP_ENTER = auto() RUN_CLIENT_APP_LEAVE = auto() + # flower-server-app + RUN_SERVER_APP_ENTER = auto() + RUN_SERVER_APP_LEAVE = auto() + # Use the ThreadPoolExecutor with max_workers=1 to have a queue # and also ensure that telemetry calls are not blocking. diff --git a/src/py/flwr/server/__init__.py b/src/py/flwr/server/__init__.py index 7db95ac07ab1..12d420c48ea8 100644 --- a/src/py/flwr/server/__init__.py +++ b/src/py/flwr/server/__init__.py @@ -19,6 +19,7 @@ from .app import ServerConfig as ServerConfig from .app import run_driver_api as run_driver_api from .app import run_fleet_api as run_fleet_api +from .app import run_server_app as run_server_app from .app import run_superlink as run_superlink from .app import start_server as start_server from .client_manager import ClientManager as ClientManager @@ -31,6 +32,7 @@ "History", "run_driver_api", "run_fleet_api", + "run_server_app", "run_superlink", "Server", "ServerConfig", diff --git a/src/py/flwr/server/app.py b/src/py/flwr/server/app.py index 895a6be300f2..8eff48763ec7 100644 --- a/src/py/flwr/server/app.py +++ b/src/py/flwr/server/app.py @@ -75,6 +75,13 @@ class ServerConfig: round_timeout: Optional[float] = None +def run_server_app() -> None: + """Run Flower server app.""" + event(EventType.RUN_SERVER_APP_ENTER) + log(WARN, "Not implemented: run_server_app") + event(EventType.RUN_SERVER_APP_LEAVE) + + def start_server( # pylint: disable=too-many-arguments,too-many-locals *, server_address: str = ADDRESS_FLEET_API_GRPC_BIDI, From 27682fe8df325e3cee091f5c5ce81f2422d614d0 Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Sun, 11 Feb 2024 21:08:23 +0100 Subject: [PATCH 093/113] Move `driver` package into `server` package (#2926) --- e2e/bare-https/driver.py | 2 +- e2e/bare/driver.py | 2 +- e2e/fastai/driver.py | 2 +- e2e/jax/driver.py | 2 +- e2e/opacus/driver.py | 2 +- e2e/pandas/driver.py | 2 +- e2e/pytorch-lightning/driver.py | 2 +- e2e/pytorch/driver.py | 2 +- e2e/scikit-learn/driver.py | 2 +- e2e/tabnet/driver.py | 2 +- e2e/tensorflow/driver.py | 2 +- examples/mt-pytorch/driver.py | 2 +- examples/mt-pytorch/start_driver.py | 2 +- examples/quickstart-cpp/driver.py | 2 +- examples/secaggplus-mt/driver.py | 2 +- src/py/flwr/__init__.py | 3 +-- src/py/flwr/server/__init__.py | 3 ++- src/py/flwr/{ => server}/driver/__init__.py | 0 src/py/flwr/{ => server}/driver/app.py | 0 src/py/flwr/{ => server}/driver/app_test.py | 2 +- src/py/flwr/{ => server}/driver/driver.py | 2 +- src/py/flwr/{ => server}/driver/driver_client_proxy.py | 0 src/py/flwr/{ => server}/driver/driver_client_proxy_test.py | 2 +- src/py/flwr/{ => server}/driver/driver_test.py | 4 ++-- src/py/flwr/{ => server}/driver/grpc_driver.py | 0 25 files changed, 23 insertions(+), 23 deletions(-) rename src/py/flwr/{ => server}/driver/__init__.py (100%) rename src/py/flwr/{ => server}/driver/app.py (100%) rename src/py/flwr/{ => server}/driver/app_test.py (98%) rename src/py/flwr/{ => server}/driver/driver.py (97%) rename src/py/flwr/{ => server}/driver/driver_client_proxy.py (100%) rename src/py/flwr/{ => server}/driver/driver_client_proxy_test.py (99%) rename src/py/flwr/{ => server}/driver/driver_test.py (97%) rename src/py/flwr/{ => server}/driver/grpc_driver.py (100%) diff --git a/e2e/bare-https/driver.py b/e2e/bare-https/driver.py index 5c44e4c641ae..dd7c9eab7248 100644 --- a/e2e/bare-https/driver.py +++ b/e2e/bare-https/driver.py @@ -3,7 +3,7 @@ # Start Flower server -hist = fl.driver.start_driver( +hist = fl.server.driver.start_driver( server_address="127.0.0.1:9091", config=fl.server.ServerConfig(num_rounds=3), root_certificates=Path("certificates/ca.crt").read_bytes(), diff --git a/e2e/bare/driver.py b/e2e/bare/driver.py index 6bd61e344ad1..d428fe757aa9 100644 --- a/e2e/bare/driver.py +++ b/e2e/bare/driver.py @@ -2,7 +2,7 @@ # Start Flower server -hist = fl.driver.start_driver( +hist = fl.server.driver.start_driver( server_address="0.0.0.0:9091", config=fl.server.ServerConfig(num_rounds=3), ) diff --git a/e2e/fastai/driver.py b/e2e/fastai/driver.py index 2b1b35d9e89c..b7b1c41ff5a3 100644 --- a/e2e/fastai/driver.py +++ b/e2e/fastai/driver.py @@ -1,6 +1,6 @@ import flwr as fl -hist = fl.driver.start_driver( +hist = fl.server.driver.start_driver( server_address="0.0.0.0:9091", config=fl.server.ServerConfig(num_rounds=3), ) diff --git a/e2e/jax/driver.py b/e2e/jax/driver.py index 2b1b35d9e89c..b7b1c41ff5a3 100644 --- a/e2e/jax/driver.py +++ b/e2e/jax/driver.py @@ -1,6 +1,6 @@ import flwr as fl -hist = fl.driver.start_driver( +hist = fl.server.driver.start_driver( server_address="0.0.0.0:9091", config=fl.server.ServerConfig(num_rounds=3), ) diff --git a/e2e/opacus/driver.py b/e2e/opacus/driver.py index 5a0309914ee0..5bc40800c33c 100644 --- a/e2e/opacus/driver.py +++ b/e2e/opacus/driver.py @@ -1,6 +1,6 @@ import flwr as fl -hist = fl.driver.start_driver( +hist = fl.server.driver.start_driver( server_address="0.0.0.0:9091", config=fl.server.ServerConfig(num_rounds=3), ) diff --git a/e2e/pandas/driver.py b/e2e/pandas/driver.py index b33e1e54f4a0..78120fc946f2 100644 --- a/e2e/pandas/driver.py +++ b/e2e/pandas/driver.py @@ -3,7 +3,7 @@ from strategy import FedAnalytics # Start Flower server -hist = fl.driver.start_driver( +hist = fl.server.driver.start_driver( server_address="0.0.0.0:9091", config=fl.server.ServerConfig(num_rounds=1), strategy=FedAnalytics(), diff --git a/e2e/pytorch-lightning/driver.py b/e2e/pytorch-lightning/driver.py index 2b1b35d9e89c..b7b1c41ff5a3 100644 --- a/e2e/pytorch-lightning/driver.py +++ b/e2e/pytorch-lightning/driver.py @@ -1,6 +1,6 @@ import flwr as fl -hist = fl.driver.start_driver( +hist = fl.server.driver.start_driver( server_address="0.0.0.0:9091", config=fl.server.ServerConfig(num_rounds=3), ) diff --git a/e2e/pytorch/driver.py b/e2e/pytorch/driver.py index ca860ea47b2d..9f9b076ee75b 100644 --- a/e2e/pytorch/driver.py +++ b/e2e/pytorch/driver.py @@ -18,7 +18,7 @@ def weighted_average(metrics: List[Tuple[int, Metrics]]) -> Metrics: strategy = fl.server.strategy.FedAvg(evaluate_metrics_aggregation_fn=weighted_average) # Start Flower server -hist = fl.driver.start_driver( +hist = fl.server.driver.start_driver( server_address="0.0.0.0:9091", config=fl.server.ServerConfig(num_rounds=3), strategy=strategy, diff --git a/e2e/scikit-learn/driver.py b/e2e/scikit-learn/driver.py index 032a2f7a0dc6..e7ce124e5ead 100644 --- a/e2e/scikit-learn/driver.py +++ b/e2e/scikit-learn/driver.py @@ -36,7 +36,7 @@ def evaluate(server_round, parameters: fl.common.NDArrays, config): evaluate_fn=get_evaluate_fn(model), on_fit_config_fn=fit_round, ) - hist = fl.driver.start_driver( + hist = fl.server.driver.start_driver( server_address="0.0.0.0:9091", strategy=strategy, config=fl.server.ServerConfig(num_rounds=3), diff --git a/e2e/tabnet/driver.py b/e2e/tabnet/driver.py index 2b1b35d9e89c..b7b1c41ff5a3 100644 --- a/e2e/tabnet/driver.py +++ b/e2e/tabnet/driver.py @@ -1,6 +1,6 @@ import flwr as fl -hist = fl.driver.start_driver( +hist = fl.server.driver.start_driver( server_address="0.0.0.0:9091", config=fl.server.ServerConfig(num_rounds=3), ) diff --git a/e2e/tensorflow/driver.py b/e2e/tensorflow/driver.py index ca860ea47b2d..9f9b076ee75b 100644 --- a/e2e/tensorflow/driver.py +++ b/e2e/tensorflow/driver.py @@ -18,7 +18,7 @@ def weighted_average(metrics: List[Tuple[int, Metrics]]) -> Metrics: strategy = fl.server.strategy.FedAvg(evaluate_metrics_aggregation_fn=weighted_average) # Start Flower server -hist = fl.driver.start_driver( +hist = fl.server.driver.start_driver( server_address="0.0.0.0:9091", config=fl.server.ServerConfig(num_rounds=3), strategy=strategy, diff --git a/examples/mt-pytorch/driver.py b/examples/mt-pytorch/driver.py index 184ee683818d..06091c954cef 100644 --- a/examples/mt-pytorch/driver.py +++ b/examples/mt-pytorch/driver.py @@ -2,7 +2,7 @@ import random import time -from flwr.driver import GrpcDriver +from flwr.server.driver import GrpcDriver from flwr.common import ( ServerMessage, FitIns, diff --git a/examples/mt-pytorch/start_driver.py b/examples/mt-pytorch/start_driver.py index 1a921c2e149a..307f4ebd1a3b 100644 --- a/examples/mt-pytorch/start_driver.py +++ b/examples/mt-pytorch/start_driver.py @@ -35,7 +35,7 @@ def weighted_average(metrics: List[Tuple[int, Metrics]]) -> Metrics: if __name__ == "__main__": # Start Flower server - fl.driver.start_driver( + fl.server.driver.start_driver( server_address="0.0.0.0:9091", config=fl.server.ServerConfig(num_rounds=3), strategy=strategy, diff --git a/examples/quickstart-cpp/driver.py b/examples/quickstart-cpp/driver.py index 037623ee77cf..3b3036f7e928 100644 --- a/examples/quickstart-cpp/driver.py +++ b/examples/quickstart-cpp/driver.py @@ -3,7 +3,7 @@ # Start Flower server for three rounds of federated learning if __name__ == "__main__": - fl.driver.start_driver( + fl.server.driver.start_driver( server_address="0.0.0.0:9091", config=fl.server.ServerConfig(num_rounds=3), strategy=FedAvgCpp(), diff --git a/examples/secaggplus-mt/driver.py b/examples/secaggplus-mt/driver.py index 4a7d629924fb..42559c2f4a21 100644 --- a/examples/secaggplus-mt/driver.py +++ b/examples/secaggplus-mt/driver.py @@ -6,7 +6,7 @@ from workflows import get_workflow_factory from flwr.common import Metrics, ndarrays_to_parameters -from flwr.driver import GrpcDriver +from flwr.server.driver import GrpcDriver from flwr.proto import driver_pb2, node_pb2, task_pb2 from flwr.server import History diff --git a/src/py/flwr/__init__.py b/src/py/flwr/__init__.py index d3cbf00747a4..ccaf07c6012f 100644 --- a/src/py/flwr/__init__.py +++ b/src/py/flwr/__init__.py @@ -17,12 +17,11 @@ from flwr.common.version import package_version as _package_version -from . import client, common, driver, server, simulation +from . import client, common, server, simulation __all__ = [ "client", "common", - "driver", "server", "simulation", ] diff --git a/src/py/flwr/server/__init__.py b/src/py/flwr/server/__init__.py index 12d420c48ea8..84c24b4bc2c1 100644 --- a/src/py/flwr/server/__init__.py +++ b/src/py/flwr/server/__init__.py @@ -15,7 +15,7 @@ """Flower server.""" -from . import strategy +from . import driver, strategy from .app import ServerConfig as ServerConfig from .app import run_driver_api as run_driver_api from .app import run_fleet_api as run_fleet_api @@ -29,6 +29,7 @@ __all__ = [ "ClientManager", + "driver", "History", "run_driver_api", "run_fleet_api", diff --git a/src/py/flwr/driver/__init__.py b/src/py/flwr/server/driver/__init__.py similarity index 100% rename from src/py/flwr/driver/__init__.py rename to src/py/flwr/server/driver/__init__.py diff --git a/src/py/flwr/driver/app.py b/src/py/flwr/server/driver/app.py similarity index 100% rename from src/py/flwr/driver/app.py rename to src/py/flwr/server/driver/app.py diff --git a/src/py/flwr/driver/app_test.py b/src/py/flwr/server/driver/app_test.py similarity index 98% rename from src/py/flwr/driver/app_test.py rename to src/py/flwr/server/driver/app_test.py index bfa0098f68e2..03f490807876 100644 --- a/src/py/flwr/driver/app_test.py +++ b/src/py/flwr/server/driver/app_test.py @@ -20,13 +20,13 @@ import unittest from unittest.mock import MagicMock -from flwr.driver.app import update_client_manager from flwr.proto.driver_pb2 import ( # pylint: disable=E0611 CreateRunResponse, GetNodesResponse, ) from flwr.proto.node_pb2 import Node # pylint: disable=E0611 from flwr.server.client_manager import SimpleClientManager +from flwr.server.driver.app import update_client_manager class TestClientManagerWithDriver(unittest.TestCase): diff --git a/src/py/flwr/driver/driver.py b/src/py/flwr/server/driver/driver.py similarity index 97% rename from src/py/flwr/driver/driver.py rename to src/py/flwr/server/driver/driver.py index b68f7c8de5fe..0a7cb36f8847 100644 --- a/src/py/flwr/driver/driver.py +++ b/src/py/flwr/server/driver/driver.py @@ -17,7 +17,6 @@ from typing import Iterable, List, Optional, Tuple -from flwr.driver.grpc_driver import DEFAULT_SERVER_ADDRESS_DRIVER, GrpcDriver from flwr.proto.driver_pb2 import ( # pylint: disable=E0611 CreateRunRequest, GetNodesRequest, @@ -26,6 +25,7 @@ ) from flwr.proto.node_pb2 import Node # pylint: disable=E0611 from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611 +from flwr.server.driver.grpc_driver import DEFAULT_SERVER_ADDRESS_DRIVER, GrpcDriver class Driver: diff --git a/src/py/flwr/driver/driver_client_proxy.py b/src/py/flwr/server/driver/driver_client_proxy.py similarity index 100% rename from src/py/flwr/driver/driver_client_proxy.py rename to src/py/flwr/server/driver/driver_client_proxy.py diff --git a/src/py/flwr/driver/driver_client_proxy_test.py b/src/py/flwr/server/driver/driver_client_proxy_test.py similarity index 99% rename from src/py/flwr/driver/driver_client_proxy_test.py rename to src/py/flwr/server/driver/driver_client_proxy_test.py index 4e9a02a6cbf9..18277a7ce80c 100644 --- a/src/py/flwr/driver/driver_client_proxy_test.py +++ b/src/py/flwr/server/driver/driver_client_proxy_test.py @@ -43,8 +43,8 @@ Properties, Status, ) -from flwr.driver.driver_client_proxy import DriverClientProxy from flwr.proto import driver_pb2, node_pb2, task_pb2 # pylint: disable=E0611 +from flwr.server.driver.driver_client_proxy import DriverClientProxy MESSAGE_PARAMETERS = Parameters(tensors=[b"abc"], tensor_type="np") diff --git a/src/py/flwr/driver/driver_test.py b/src/py/flwr/server/driver/driver_test.py similarity index 97% rename from src/py/flwr/driver/driver_test.py rename to src/py/flwr/server/driver/driver_test.py index 1854a92b5ebe..0ee7fbfec37e 100644 --- a/src/py/flwr/driver/driver_test.py +++ b/src/py/flwr/server/driver/driver_test.py @@ -18,13 +18,13 @@ import unittest from unittest.mock import Mock, patch -from flwr.driver.driver import Driver from flwr.proto.driver_pb2 import ( # pylint: disable=E0611 GetNodesRequest, PullTaskResRequest, PushTaskInsRequest, ) from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611 +from flwr.server.driver.driver import Driver class TestDriver(unittest.TestCase): @@ -37,7 +37,7 @@ def setUp(self) -> None: self.mock_grpc_driver = Mock() self.mock_grpc_driver.create_run.return_value = mock_response self.patcher = patch( - "flwr.driver.driver.GrpcDriver", return_value=self.mock_grpc_driver + "flwr.server.driver.driver.GrpcDriver", return_value=self.mock_grpc_driver ) self.patcher.start() self.driver = Driver() diff --git a/src/py/flwr/driver/grpc_driver.py b/src/py/flwr/server/driver/grpc_driver.py similarity index 100% rename from src/py/flwr/driver/grpc_driver.py rename to src/py/flwr/server/driver/grpc_driver.py From 8d0438ba236002fecc0538f1db0f7ad91f3ca626 Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Sun, 11 Feb 2024 21:39:05 +0100 Subject: [PATCH 094/113] Add agrparse to flower-server-app (#2927) --- src/py/flwr/client/app.py | 6 +-- src/py/flwr/server/app.py | 88 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 4 deletions(-) diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index 7b82d41c293a..15f7c5057a20 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -86,7 +86,7 @@ def run_client_app() -> None: log( DEBUG, - "Flower will load ClientApp `%s` to execute tasks", + "Flower will load ClientApp `%s`", getattr(args, "client-app"), ) @@ -111,7 +111,7 @@ def _load() -> ClientApp: def _parse_args_run_client_app() -> argparse.ArgumentParser: """Parse flower-client-app command line arguments.""" parser = argparse.ArgumentParser( - description="Start a long-running Flower client", + description="Start a Flower client app", ) parser.add_argument( @@ -145,7 +145,7 @@ def _parse_args_run_client_app() -> argparse.ArgumentParser: "--dir", default="", help="Add specified directory to the PYTHONPATH and load Flower " - "callable from there." + "app from there." " Default: current working directory.", ) diff --git a/src/py/flwr/server/app.py b/src/py/flwr/server/app.py index 8eff48763ec7..aef53a5fc6af 100644 --- a/src/py/flwr/server/app.py +++ b/src/py/flwr/server/app.py @@ -20,7 +20,7 @@ import sys import threading from dataclasses import dataclass -from logging import ERROR, INFO, WARN +from logging import DEBUG, ERROR, INFO, WARN from os.path import isfile from pathlib import Path from signal import SIGINT, SIGTERM, signal @@ -78,7 +78,54 @@ class ServerConfig: def run_server_app() -> None: """Run Flower server app.""" event(EventType.RUN_SERVER_APP_ENTER) + + args = _parse_args_run_server_app().parse_args() + + # Obtain certificates + if args.insecure: + if args.root_certificates is not None: + sys.exit( + "Conflicting options: The '--insecure' flag disables HTTPS, " + "but '--root-certificates' was also specified. Please remove " + "the '--root-certificates' option when running in insecure mode, " + "or omit '--insecure' to use HTTPS." + ) + log( + WARN, + "Option `--insecure` was set. " + "Starting insecure HTTP client connected to %s.", + args.server, + ) + root_certificates = None + else: + # Load the certificates if provided, or load the system certificates + cert_path = args.root_certificates + if cert_path is None: + root_certificates = None + else: + root_certificates = Path(cert_path).read_bytes() + log( + DEBUG, + "Starting secure HTTPS client connected to %s " + "with the following certificates: %s.", + args.server, + cert_path, + ) + + log( + DEBUG, + "Flower will load ServerApp `%s`", + getattr(args, "server-app"), + ) + + log( + DEBUG, + "root_certificates: `%s`", + root_certificates, + ) + log(WARN, "Not implemented: run_server_app") + event(EventType.RUN_SERVER_APP_LEAVE) @@ -767,3 +814,42 @@ def _add_args_fleet_api(parser: argparse.ArgumentParser) -> None: type=int, default=1, ) + + +def _parse_args_run_server_app() -> argparse.ArgumentParser: + """Parse flower-server-app command line arguments.""" + parser = argparse.ArgumentParser( + description="Start a Flower server app", + ) + + parser.add_argument( + "server-app", + help="For example: `server:app` or `project.package.module:wrapper.app`", + ) + parser.add_argument( + "--insecure", + action="store_true", + help="Run the server app without HTTPS. By default, the app runs with " + "HTTPS enabled. Use this flag only if you understand the risks.", + ) + parser.add_argument( + "--root-certificates", + metavar="ROOT_CERT", + type=str, + help="Specifies the path to the PEM-encoded root certificate file for " + "establishing secure HTTPS connections.", + ) + parser.add_argument( + "--server", + default="0.0.0.0:9092", + help="Server address", + ) + parser.add_argument( + "--dir", + default="", + help="Add specified directory to the PYTHONPATH and load Flower " + "app from there." + " Default: current working directory.", + ) + + return parser From 04898c24dd558baff40abc776f3c3c4e6a15fe24 Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Sun, 11 Feb 2024 22:26:14 +0100 Subject: [PATCH 095/113] Fix framework docs (#2928) --- ...tributor-tutorial-contribute-on-github.rst | 3 +- doc/source/how-to-run-flower-using-docker.rst | 2 +- doc/source/ref-api-cli.rst | 34 +++++++++---------- src/py/flwr/server/app.py | 12 +++---- 4 files changed, 25 insertions(+), 26 deletions(-) diff --git a/doc/source/contributor-tutorial-contribute-on-github.rst b/doc/source/contributor-tutorial-contribute-on-github.rst index 20d0bd0e5e0d..d409802897e4 100644 --- a/doc/source/contributor-tutorial-contribute-on-github.rst +++ b/doc/source/contributor-tutorial-contribute-on-github.rst @@ -4,8 +4,7 @@ Contribute on GitHub This guide is for people who want to get involved with Flower, but who are not used to contributing to GitHub projects. If you're familiar with how contributing on GitHub works, you can directly checkout our -`getting started guide for contributors `_ -and examples of `good first contributions `_. +`getting started guide for contributors `_. Setting up the repository diff --git a/doc/source/how-to-run-flower-using-docker.rst b/doc/source/how-to-run-flower-using-docker.rst index 8d47dcd3f2ab..40df1ffcb63c 100644 --- a/doc/source/how-to-run-flower-using-docker.rst +++ b/doc/source/how-to-run-flower-using-docker.rst @@ -1,5 +1,5 @@ Run Flower using Docker -==================== +======================= The simplest way to get started with Flower is by using the pre-made Docker images, which you can find on `Docker Hub `_. diff --git a/doc/source/ref-api-cli.rst b/doc/source/ref-api-cli.rst index b5f7ce7bae65..c0e8940061fc 100644 --- a/doc/source/ref-api-cli.rst +++ b/doc/source/ref-api-cli.rst @@ -8,7 +8,7 @@ flower-superlink .. argparse:: :module: flwr.server.app - :func: _parse_args_server + :func: _parse_args_run_superlink :prog: flower-superlink .. _flower-driver-api-apiref: @@ -18,7 +18,7 @@ flower-driver-api .. argparse:: :module: flwr.server.app - :func: _parse_args_driver + :func: _parse_args_run_driver_api :prog: flower-driver-api .. _flower-fleet-api-apiref: @@ -28,25 +28,25 @@ flower-fleet-api .. argparse:: :module: flwr.server.app - :func: _parse_args_fleet + :func: _parse_args_run_fleet_api :prog: flower-fleet-api -.. _flower-client-app-apiref: +.. .. _flower-client-app-apiref: -flower-client-app -~~~~~~~~~~~~~~~~~ +.. flower-client-app +.. ~~~~~~~~~~~~~~~~~ -.. argparse:: - :filename: flwr.client - :func: run_client_app - :prog: flower-client-app +.. .. argparse:: +.. :filename: flwr.client +.. :func: _parse_args_run_client_app +.. :prog: flower-client-app -.. _flower-server-app-apiref: +.. .. _flower-server-app-apiref: -flower-server-app -~~~~~~~~~~~~~~~~~ +.. flower-server-app +.. ~~~~~~~~~~~~~~~~~ -.. argparse:: - :filename: flwr.server - :func: run_server_app - :prog: flower-server-app +.. .. argparse:: +.. :filename: flwr.server +.. :func: _parse_args_run_server_app +.. :prog: flower-server-app diff --git a/src/py/flwr/server/app.py b/src/py/flwr/server/app.py index aef53a5fc6af..6e2f1f7dc88d 100644 --- a/src/py/flwr/server/app.py +++ b/src/py/flwr/server/app.py @@ -293,7 +293,7 @@ def run_driver_api() -> None: """Run Flower server (Driver API).""" log(INFO, "Starting Flower server (Driver API)") event(EventType.RUN_DRIVER_API_ENTER) - args = _parse_args_driver().parse_args() + args = _parse_args_run_driver_api().parse_args() # Parse IP address parsed_address = parse_address(args.driver_api_address) @@ -330,7 +330,7 @@ def run_fleet_api() -> None: """Run Flower server (Fleet API).""" log(INFO, "Starting Flower server (Fleet API)") event(EventType.RUN_FLEET_API_ENTER) - args = _parse_args_fleet().parse_args() + args = _parse_args_run_fleet_api().parse_args() # Obtain certificates certificates = _try_obtain_certificates(args) @@ -402,7 +402,7 @@ def run_superlink() -> None: """Run Flower server (Driver API and Fleet API).""" log(INFO, "Starting Flower server") event(EventType.RUN_SUPERLINK_ENTER) - args = _parse_args_server().parse_args() + args = _parse_args_run_superlink().parse_args() # Parse IP address parsed_address = parse_address(args.driver_api_address) @@ -675,7 +675,7 @@ def _validate_ssl_files( return validation_exceptions -def _parse_args_driver() -> argparse.ArgumentParser: +def _parse_args_run_driver_api() -> argparse.ArgumentParser: """Parse command line arguments for Driver API.""" parser = argparse.ArgumentParser( description="Start a Flower Driver API server. " @@ -692,7 +692,7 @@ def _parse_args_driver() -> argparse.ArgumentParser: return parser -def _parse_args_fleet() -> argparse.ArgumentParser: +def _parse_args_run_fleet_api() -> argparse.ArgumentParser: """Parse command line arguments for Fleet API.""" parser = argparse.ArgumentParser( description="Start a Flower Fleet API server." @@ -709,7 +709,7 @@ def _parse_args_fleet() -> argparse.ArgumentParser: return parser -def _parse_args_server() -> argparse.ArgumentParser: +def _parse_args_run_superlink() -> argparse.ArgumentParser: """Parse command line arguments for both Driver API and Fleet API.""" parser = argparse.ArgumentParser( description="This will start a Flower server " From 41e9e90d0cb561f4c69648be516ae50dae6552f8 Mon Sep 17 00:00:00 2001 From: Heng Pan <134433891+panh99@users.noreply.github.com> Date: Mon, 12 Feb 2024 19:45:39 +0000 Subject: [PATCH 096/113] Rename Message.message to Message.content (#2932) --- src/py/flwr/client/grpc_client/connection.py | 4 +-- .../client/grpc_client/connection_test.py | 4 +-- .../client/message_handler/message_handler.py | 14 +++++----- .../message_handler/message_handler_test.py | 8 +++--- .../mod/secure_aggregation/secaggplus_mod.py | 6 ++--- .../secure_aggregation/secaggplus_mod_test.py | 6 ++--- src/py/flwr/client/mod/utils_test.py | 26 +++++++++---------- src/py/flwr/common/message.py | 4 +-- src/py/flwr/common/serde.py | 8 +++--- src/py/flwr/common/serde_test.py | 8 +++--- 10 files changed, 44 insertions(+), 44 deletions(-) diff --git a/src/py/flwr/client/grpc_client/connection.py b/src/py/flwr/client/grpc_client/connection.py index bd1ea5fab307..c7d8494b8fde 100644 --- a/src/py/flwr/client/grpc_client/connection.py +++ b/src/py/flwr/client/grpc_client/connection.py @@ -175,12 +175,12 @@ def receive() -> Message: ttl="", task_type=task_type, ), - message=recordset, + content=recordset, ) def send(message: Message) -> None: # Retrieve RecordSet and task_type - recordset = message.message + recordset = message.content task_type = message.metadata.task_type # RecordSet --> *Res --> *Res proto -> ClientMessage proto diff --git a/src/py/flwr/client/grpc_client/connection_test.py b/src/py/flwr/client/grpc_client/connection_test.py index 54fd41d79325..7ba39568f0a4 100644 --- a/src/py/flwr/client/grpc_client/connection_test.py +++ b/src/py/flwr/client/grpc_client/connection_test.py @@ -51,7 +51,7 @@ ttl="", task_type=TASK_TYPE_GET_PROPERTIES, ), - message=compat.getpropertiesres_to_recordset( + content=compat.getpropertiesres_to_recordset( GetPropertiesRes(Status(Code.OK, ""), {}) ), ) @@ -63,7 +63,7 @@ ttl="", task_type="reconnect", ), - message=RecordSet(configs={"config": ConfigsRecord({"reason": 0})}), + content=RecordSet(configs={"config": ConfigsRecord({"reason": 0})}), ) diff --git a/src/py/flwr/client/message_handler/message_handler.py b/src/py/flwr/client/message_handler/message_handler.py index 451da089eaf0..c45d13d43f94 100644 --- a/src/py/flwr/client/message_handler/message_handler.py +++ b/src/py/flwr/client/message_handler/message_handler.py @@ -77,7 +77,7 @@ def handle_control_message(message: Message) -> Tuple[Optional[Message], int]: """ if message.metadata.task_type == "reconnect": # Retrieve ReconnectIns from recordset - recordset = message.message + recordset = message.content seconds = cast(int, recordset.get_configs("config")["seconds"]) # Construct ReconnectIns and call _reconnect disconnect_msg, sleep_duration = _reconnect( @@ -95,7 +95,7 @@ def handle_control_message(message: Message) -> Tuple[Optional[Message], int]: ttl="", task_type="reconnect", ), - message=recordset, + content=recordset, ) # Return TaskRes and sleep duration return out_message, sleep_duration @@ -118,14 +118,14 @@ def handle_legacy_message_from_tasktype( if task_type == TASK_TYPE_GET_PROPERTIES: get_properties_res = maybe_call_get_properties( client=client, - get_properties_ins=recordset_to_getpropertiesins(message.message), + get_properties_ins=recordset_to_getpropertiesins(message.content), ) out_recordset = getpropertiesres_to_recordset(get_properties_res) # Handle GetParametersIns elif task_type == TASK_TYPE_GET_PARAMETERS: get_parameters_res = maybe_call_get_parameters( client=client, - get_parameters_ins=recordset_to_getparametersins(message.message), + get_parameters_ins=recordset_to_getparametersins(message.content), ) out_recordset = getparametersres_to_recordset( get_parameters_res, keep_input=False @@ -134,14 +134,14 @@ def handle_legacy_message_from_tasktype( elif task_type == TASK_TYPE_FIT: fit_res = maybe_call_fit( client=client, - fit_ins=recordset_to_fitins(message.message, keep_input=True), + fit_ins=recordset_to_fitins(message.content, keep_input=True), ) out_recordset = fitres_to_recordset(fit_res, keep_input=False) # Handle EvaluateIns elif task_type == TASK_TYPE_EVALUATE: evaluate_res = maybe_call_evaluate( client=client, - evaluate_ins=recordset_to_evaluateins(message.message, keep_input=True), + evaluate_ins=recordset_to_evaluateins(message.content, keep_input=True), ) out_recordset = evaluateres_to_recordset(evaluate_res) else: @@ -156,7 +156,7 @@ def handle_legacy_message_from_tasktype( ttl="", task_type=task_type, ), - message=out_recordset, + content=out_recordset, ) return out_message diff --git a/src/py/flwr/client/message_handler/message_handler_test.py b/src/py/flwr/client/message_handler/message_handler_test.py index ad09ca95abc7..288597b764f4 100644 --- a/src/py/flwr/client/message_handler/message_handler_test.py +++ b/src/py/flwr/client/message_handler/message_handler_test.py @@ -127,7 +127,7 @@ def test_client_without_get_properties() -> None: ttl="", task_type=TASK_TYPE_GET_PROPERTIES, ), - message=recordset, + content=recordset, ) # Execute @@ -148,7 +148,7 @@ def test_client_without_get_properties() -> None: expected_rs = compat.getpropertiesres_to_recordset(expected_get_properties_res) expected_msg = Message(message.metadata, expected_rs) - assert actual_msg.message == expected_msg.message + assert actual_msg.content == expected_msg.content assert actual_msg.metadata.task_type == expected_msg.metadata.task_type @@ -165,7 +165,7 @@ def test_client_with_get_properties() -> None: ttl="", task_type=TASK_TYPE_GET_PROPERTIES, ), - message=recordset, + content=recordset, ) # Execute @@ -186,5 +186,5 @@ def test_client_with_get_properties() -> None: expected_rs = compat.getpropertiesres_to_recordset(expected_get_properties_res) expected_msg = Message(message.metadata, expected_rs) - assert actual_msg.message == expected_msg.message + assert actual_msg.content == expected_msg.content assert actual_msg.metadata.task_type == expected_msg.metadata.task_type diff --git a/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py b/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py index 850e02a2b5f9..a6f59b736911 100644 --- a/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py +++ b/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py @@ -156,7 +156,7 @@ def _get_fit_fn( def fit() -> FitRes: out_msg = call_next(msg, ctxt) - return compat.recordset_to_fitres(out_msg.message, keep_input=False) + return compat.recordset_to_fitres(out_msg.content, keep_input=False) return fit @@ -178,7 +178,7 @@ def secaggplus_mod( state = SecAggPlusState(**state_dict) # Retrieve incoming configs - configs = msg.message.get_configs(RECORD_KEY_CONFIGS).data + configs = msg.content.get_configs(RECORD_KEY_CONFIGS).data # Check the validity of the next stage check_stage(state.current_stage, configs) @@ -208,7 +208,7 @@ def secaggplus_mod( # Return message return Message( metadata=Metadata(0, "", "", "", TASK_TYPE_FIT), - message=RecordSet(configs={RECORD_KEY_CONFIGS: ConfigsRecord(res, False)}), + content=RecordSet(configs={RECORD_KEY_CONFIGS: ConfigsRecord(res, False)}), ) diff --git a/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod_test.py b/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod_test.py index 80d607318651..2ca9748f8219 100644 --- a/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod_test.py +++ b/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod_test.py @@ -58,7 +58,7 @@ def get_test_handler( def empty_ffn(_: Message, _2: Context) -> Message: return Message( metadata=Metadata(0, "", "", "", TASK_TYPE_FIT), - message=RecordSet(), + content=RecordSet(), ) app = make_ffn(empty_ffn, [secaggplus_mod]) @@ -66,10 +66,10 @@ def empty_ffn(_: Message, _2: Context) -> Message: def func(configs: Dict[str, ConfigsRecordValues]) -> Dict[str, ConfigsRecordValues]: in_msg = Message( metadata=Metadata(0, "", "", "", TASK_TYPE_FIT), - message=RecordSet(configs={RECORD_KEY_CONFIGS: ConfigsRecord(configs)}), + content=RecordSet(configs={RECORD_KEY_CONFIGS: ConfigsRecord(configs)}), ) out_msg = app(in_msg, ctxt) - return out_msg.message.get_configs(RECORD_KEY_CONFIGS).data + return out_msg.content.get_configs(RECORD_KEY_CONFIGS).data return func diff --git a/src/py/flwr/client/mod/utils_test.py b/src/py/flwr/client/mod/utils_test.py index 782ca8b0f97e..00c0ef850dc0 100644 --- a/src/py/flwr/client/mod/utils_test.py +++ b/src/py/flwr/client/mod/utils_test.py @@ -45,13 +45,13 @@ def make_mock_mod(name: str, footprint: List[str]) -> Mod: def mod(message: Message, context: Context, app: ClientAppCallable) -> Message: footprint.append(name) # add empty ConfigRecord to in_message for this mod - message.message.set_configs(name=name, record=ConfigsRecord()) + message.content.set_configs(name=name, record=ConfigsRecord()) _increment_context_counter(context) out_message: Message = app(message, context) footprint.append(name) _increment_context_counter(context) # add empty ConfigRegcord to out_message for this mod - out_message.message.set_configs(name=name, record=ConfigsRecord()) + out_message.content.set_configs(name=name, record=ConfigsRecord()) return out_message return mod @@ -62,9 +62,9 @@ def make_mock_app(name: str, footprint: List[str]) -> ClientAppCallable: def app(message: Message, context: Context) -> Message: footprint.append(name) - message.message.set_configs(name=name, record=ConfigsRecord()) - out_message = Message(metadata=message.metadata, message=RecordSet()) - out_message.message.set_configs(name=name, record=ConfigsRecord()) + message.content.set_configs(name=name, record=ConfigsRecord()) + out_message = Message(metadata=message.metadata, content=RecordSet()) + out_message.content.set_configs(name=name, record=ConfigsRecord()) print(context) return out_message @@ -73,7 +73,7 @@ def app(message: Message, context: Context) -> Message: def _get_dummy_flower_message() -> Message: return Message( - message=RecordSet(), + content=RecordSet(), metadata=Metadata(run_id=0, task_id="", group_id="", ttl="", task_type="mock"), ) @@ -102,9 +102,9 @@ def test_multiple_mods(self) -> None: trace = mock_mod_names + ["app"] self.assertEqual(footprint, trace + list(reversed(mock_mod_names))) # pylint: disable-next=no-member - self.assertEqual("".join(message.message.configs.keys()), "".join(trace)) + self.assertEqual("".join(message.content.configs.keys()), "".join(trace)) self.assertEqual( - "".join(out_message.message.configs.keys()), "".join(reversed(trace)) + "".join(out_message.content.configs.keys()), "".join(reversed(trace)) ) self.assertEqual(state.get_metrics(METRIC)[COUNTER], 2 * len(mock_mods)) @@ -122,9 +122,9 @@ def filter_mod( _2: ClientAppCallable, ) -> Message: footprint.append("filter") - message.message.set_configs(name="filter", record=ConfigsRecord()) - out_message = Message(metadata=message.metadata, message=RecordSet()) - out_message.message.set_configs(name="filter", record=ConfigsRecord()) + message.content.set_configs(name="filter", record=ConfigsRecord()) + out_message = Message(metadata=message.metadata, content=RecordSet()) + out_message.content.set_configs(name="filter", record=ConfigsRecord()) # Skip calling app return out_message @@ -135,5 +135,5 @@ def filter_mod( # Assert self.assertEqual(footprint, ["filter"]) # pylint: disable-next=no-member - self.assertEqual(list(message.message.configs.keys())[0], "filter") - self.assertEqual(list(out_message.message.configs.keys())[0], "filter") + self.assertEqual(list(message.content.configs.keys())[0], "filter") + self.assertEqual(list(out_message.content.configs.keys())[0], "filter") diff --git a/src/py/flwr/common/message.py b/src/py/flwr/common/message.py index f693d8e27bc3..1a971749966e 100644 --- a/src/py/flwr/common/message.py +++ b/src/py/flwr/common/message.py @@ -55,10 +55,10 @@ class Message: ---------- metadata : Metadata A dataclass including information about the task to be executed. - message : RecordSet + content : RecordSet Holds records either sent by another entity (e.g. sent by the server-side logic to a client, or vice-versa) or that will be sent to it. """ metadata: Metadata - message: RecordSet + content: RecordSet diff --git a/src/py/flwr/common/serde.py b/src/py/flwr/common/serde.py index 92c4e2cdad00..3b8e4c3a1c2c 100644 --- a/src/py/flwr/common/serde.py +++ b/src/py/flwr/common/serde.py @@ -551,7 +551,7 @@ def message_to_taskins(message: Message) -> TaskIns: task=Task( ttl=message.metadata.ttl, task_type=message.metadata.task_type, - recordset=recordset_to_proto(message.message), + recordset=recordset_to_proto(message.content), ), ) @@ -570,7 +570,7 @@ def message_from_taskins(taskins: TaskIns) -> Message: # Return the Message return Message( metadata=metadata, - message=recordset_from_proto(taskins.task.recordset), + content=recordset_from_proto(taskins.task.recordset), ) @@ -580,7 +580,7 @@ def message_to_taskres(message: Message) -> TaskRes: task=Task( ttl=message.metadata.ttl, task_type=message.metadata.task_type, - recordset=recordset_to_proto(message.message), + recordset=recordset_to_proto(message.content), ), ) @@ -599,5 +599,5 @@ def message_from_taskres(taskres: TaskRes) -> Message: # Return the Message return Message( metadata=metadata, - message=recordset_from_proto(taskres.task.recordset), + content=recordset_from_proto(taskres.task.recordset), ) diff --git a/src/py/flwr/common/serde_test.py b/src/py/flwr/common/serde_test.py index 2a229a87e399..c30f24d3700c 100644 --- a/src/py/flwr/common/serde_test.py +++ b/src/py/flwr/common/serde_test.py @@ -312,7 +312,7 @@ def test_message_to_and_from_taskins() -> None: ttl=metadata.ttl, task_type=metadata.task_type, ), - message=maker.recordset(1, 1, 1), + content=maker.recordset(1, 1, 1), ) # Execute @@ -323,7 +323,7 @@ def test_message_to_and_from_taskins() -> None: deserialized = message_from_taskins(taskins) # Assert - assert original.message == deserialized.message + assert original.content == deserialized.content assert metadata == deserialized.metadata @@ -340,7 +340,7 @@ def test_message_to_and_from_taskres() -> None: ttl=metadata.ttl, task_type=metadata.task_type, ), - message=maker.recordset(1, 1, 1), + content=maker.recordset(1, 1, 1), ) # Execute @@ -351,5 +351,5 @@ def test_message_to_and_from_taskres() -> None: deserialized = message_from_taskres(taskres) # Assert - assert original.message == deserialized.message + assert original.content == deserialized.content assert metadata == deserialized.metadata From cf8f740dd5dc178e04290cda3b4a6cf47d32d383 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 21:36:55 +0000 Subject: [PATCH 097/113] Bump actions/download-artifact from 4.1.1 to 4.1.2 (#2929) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4.1.1 to 4.1.2. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/6b208ae046db98c579e8a3aa621ab581ff575935...eaceaf801fd36c7dee90939fad912460b18a1ffe) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Daniel J. Beutel --- .github/workflows/_docker-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/_docker-build.yml b/.github/workflows/_docker-build.yml index 4a1289d9175a..99ec0671db66 100644 --- a/.github/workflows/_docker-build.yml +++ b/.github/workflows/_docker-build.yml @@ -114,7 +114,7 @@ jobs: metadata: ${{ steps.meta.outputs.json }} steps: - name: Download digests - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: pattern: digests-${{ needs.build.outputs.build-id }}-* path: /tmp/digests From 9e95c2296a7592f83732b81ccbeba4f6e6add3a5 Mon Sep 17 00:00:00 2001 From: Robert Steiner Date: Tue, 13 Feb 2024 09:45:43 +0100 Subject: [PATCH 098/113] Update events URL top level domain (#2937) --- src/py/flwr/common/telemetry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/common/telemetry.py b/src/py/flwr/common/telemetry.py index 2087c8b66ab5..8eb594085d31 100644 --- a/src/py/flwr/common/telemetry.py +++ b/src/py/flwr/common/telemetry.py @@ -32,7 +32,7 @@ FLWR_TELEMETRY_ENABLED = os.getenv("FLWR_TELEMETRY_ENABLED", "1") FLWR_TELEMETRY_LOGGING = os.getenv("FLWR_TELEMETRY_LOGGING", "0") -TELEMETRY_EVENTS_URL = "https://telemetry.flower.dev/api/v1/event" +TELEMETRY_EVENTS_URL = "https://telemetry.flower.ai/api/v1/event" LOGGER_NAME = "flwr-telemetry" LOGGER_LEVEL = logging.DEBUG From e0dbe0d4b1b8a688acb31b0bf7118762147f22ba Mon Sep 17 00:00:00 2001 From: Charles Beauville Date: Tue, 13 Feb 2024 12:21:15 +0100 Subject: [PATCH 099/113] Update locales text (#2939) --- doc/locales/fr/LC_MESSAGES/framework-docs.po | 19525 +++++++++----- .../pt_BR/LC_MESSAGES/framework-docs.po | 8536 +++++- .../zh_Hans/LC_MESSAGES/framework-docs.po | 21516 +++++++++------- 3 files changed, 33518 insertions(+), 16059 deletions(-) diff --git a/doc/locales/fr/LC_MESSAGES/framework-docs.po b/doc/locales/fr/LC_MESSAGES/framework-docs.po index 833ba6411b5e..6c8cf7e88486 100644 --- a/doc/locales/fr/LC_MESSAGES/framework-docs.po +++ b/doc/locales/fr/LC_MESSAGES/framework-docs.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: Flower Docs\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2023-08-30 18:55+0200\n" +"POT-Creation-Date: 2024-02-13 11:23+0100\n" "PO-Revision-Date: 2023-09-05 17:54+0000\n" "Last-Translator: Charles Beauville \n" "Language: fr\n" @@ -13,7 +13,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.12.1\n" +"Generated-By: Babel 2.13.1\n" #: ../../source/contributor-explanation-architecture.rst:2 msgid "Flower Architecture" @@ -55,11 +55,353 @@ msgstr "" "`Flower `_ architecture de base avec un moteur de " "client virtuel et un moteur de client périphérique" -#: ../../source/contributor-how-create-new-messages.rst:2 +#: ../../source/contributor-how-to-build-docker-images.rst:2 +msgid "How to build Docker Flower images locally" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:4 +msgid "" +"Flower provides pre-made docker images on `Docker Hub " +"`_ that include all necessary " +"dependencies for running the server. You can also build your own custom " +"docker images from scratch with a different version of Python or Ubuntu " +"if that is what you need. In this guide, we will explain what images " +"exist and how to build them locally." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:9 +msgid "" +"Before we can start, we need to meet a few prerequisites in our local " +"development environment." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:11 +#, fuzzy +msgid "Clone the flower repository." +msgstr "**Fourche le dépôt de Flower**" + +#: ../../source/contributor-how-to-build-docker-images.rst:17 +msgid "Verify the Docker daemon is running." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:19 +msgid "" +"Please follow the first section on `Run Flower using Docker " +"`_ " +"which covers this step in more detail." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:23 +msgid "" +"Currently, Flower provides two images, a base image and a server image. " +"There will also be a client image soon. The base image, as the name " +"suggests, contains basic dependencies that both the server and the client" +" need. This includes system dependencies, Python and Python tools. The " +"server image is based on the base image, but it additionally installs the" +" Flower server using ``pip``." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:28 +msgid "" +"The build instructions that assemble the images are located in the " +"respective Dockerfiles. You can find them in the subdirectories of " +"``src/docker``." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:31 +msgid "" +"Both, base and server image are configured via build arguments. Through " +"build arguments, we can make our build more flexible. For example, in the" +" base image, we can specify the version of Python to install using the " +"``PYTHON_VERSION`` build argument. Some of the build arguments have " +"default values, others must be specified when building the image. All " +"available build arguments for each image are listed in one of the tables " +"below." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:38 +#, fuzzy +msgid "Building the base image" +msgstr "Chargement des données" + +#: ../../source/contributor-how-to-build-docker-images.rst:44 +#: ../../source/contributor-how-to-build-docker-images.rst:86 +#, fuzzy +msgid "Build argument" +msgstr "Amélioration de la documentation" + +#: ../../source/contributor-how-to-build-docker-images.rst:45 +#: ../../source/contributor-how-to-build-docker-images.rst:87 +#, fuzzy +msgid "Description" +msgstr "Dépréciations" + +#: ../../source/contributor-how-to-build-docker-images.rst:46 +#: ../../source/contributor-how-to-build-docker-images.rst:88 +#, fuzzy +msgid "Required" +msgstr "Changements nécessaires" + +#: ../../source/contributor-how-to-build-docker-images.rst:47 +#: ../../source/contributor-how-to-build-docker-images.rst:89 +#, fuzzy +msgid "Example" +msgstr "Exemples de PyTorch" + +#: ../../source/contributor-how-to-build-docker-images.rst:48 +#, fuzzy +msgid "``PYTHON_VERSION``" +msgstr "Version Python" + +#: ../../source/contributor-how-to-build-docker-images.rst:49 +msgid "Version of ``python`` to be installed." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:50 +#: ../../source/contributor-how-to-build-docker-images.rst:54 +#: ../../source/contributor-how-to-build-docker-images.rst:58 +#: ../../source/contributor-how-to-build-docker-images.rst:100 +#, fuzzy +msgid "Yes" +msgstr "Types" + +#: ../../source/contributor-how-to-build-docker-images.rst:51 +#, fuzzy +msgid "``3.11``" +msgstr "1.0.0rc1" + +#: ../../source/contributor-how-to-build-docker-images.rst:52 +msgid "``PIP_VERSION``" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:53 +msgid "Version of ``pip`` to be installed." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:55 +#, fuzzy +msgid "``23.0.1``" +msgstr "1.0.0rc1" + +#: ../../source/contributor-how-to-build-docker-images.rst:56 +msgid "``SETUPTOOLS_VERSION``" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:57 +msgid "Version of ``setuptools`` to be installed." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:59 +#, fuzzy +msgid "``69.0.2``" +msgstr "``1.0.0b0``" + +#: ../../source/contributor-how-to-build-docker-images.rst:60 +msgid "``UBUNTU_VERSION``" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:61 +msgid "Version of the official Ubuntu Docker image." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:62 +msgid "Defaults to ``22.04``." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:65 +msgid "" +"The following example creates a base image with Python 3.11.0, pip 23.0.1" +" and setuptools 69.0.2:" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:76 +msgid "" +"The name of image is ``flwr_base`` and the tag ``0.1.0``. Remember that " +"the build arguments as well as the name and tag can be adapted to your " +"needs. These values serve as examples only." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:80 +#, fuzzy +msgid "Building the server image" +msgstr "Démarrer le serveur" + +#: ../../source/contributor-how-to-build-docker-images.rst:90 +msgid "``BASE_REPOSITORY``" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:91 +msgid "The repository name of the base image." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:92 +msgid "Defaults to ``flwr/server``." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:94 +msgid "``BASE_IMAGE_TAG``" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:95 +msgid "The image tag of the base image." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:96 +msgid "Defaults to ``py3.11-ubuntu22.04``." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:98 +msgid "``FLWR_VERSION``" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:99 +msgid "Version of Flower to be installed." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:101 +#, fuzzy +msgid "``1.7.0``" +msgstr "``1.0.0b0``" + +#: ../../source/contributor-how-to-build-docker-images.rst:103 +msgid "" +"The following example creates a server image with the official Flower " +"base image py3.11-ubuntu22.04 and Flower 1.7.0:" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:114 +msgid "" +"The name of image is ``flwr_server`` and the tag ``0.1.0``. Remember that" +" the build arguments as well as the name and tag can be adapted to your " +"needs. These values serve as examples only." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:117 +msgid "" +"If you want to use your own base image instead of the official Flower " +"base image, all you need to do is set the ``BASE_REPOSITORY`` and " +"``BASE_IMAGE_TAG`` build arguments. The value of ``BASE_REPOSITORY`` must" +" match the name of your image and the value of ``BASE_IMAGE_TAG`` must " +"match the tag of your image." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:131 +msgid "After creating the image, we can test whether the image is working:" +msgstr "" + +#: ../../source/contributor-how-to-contribute-translations.rst:2 +#, fuzzy +msgid "Contribute translations" +msgstr "Explications" + +#: ../../source/contributor-how-to-contribute-translations.rst:4 +msgid "" +"Since `Flower 1.5 `_ we have introduced translations to " +"our doc pages, but, as you might have noticed, the translations are often" +" imperfect. If you speak languages other than English, you might be able " +"to help us in our effort to make Federated Learning accessible to as many" +" people as possible by contributing to those translations! This might " +"also be a great opportunity for those wanting to become open source " +"contributors with little prerequistes." +msgstr "" + +#: ../../source/contributor-how-to-contribute-translations.rst:13 +msgid "" +"Our translation project is publicly available over on `Weblate " +"`_, this " +"where most of the work will happen." +msgstr "" + +#: ../../source/contributor-how-to-contribute-translations.rst:18 +#, fuzzy +msgid "Contribute to existing languages" +msgstr "Explications" + +#: ../../source/contributor-how-to-contribute-translations.rst:23 +msgid "" +"The first thing you will need to do in order to contribute is to create a" +" free Weblate account on this `page " +"`_. More information about" +" profile settings can be found `here " +"`_." +msgstr "" + +#: ../../source/contributor-how-to-contribute-translations.rst:29 +msgid "" +"Once you are signed in to Weblate, you can navigate to the `Flower " +"Framework project `_. Here, you should see the different existing languages" +" that can be found on the website." +msgstr "" + +#: ../../source/contributor-how-to-contribute-translations.rst:34 +msgid "" +"Once you have selected the language you want to contribute to, you should" +" see a similar interface to this:" +msgstr "" + +#: ../../source/contributor-how-to-contribute-translations.rst:39 +msgid "" +"The most straight forward option here is to click on the ``Translate`` " +"button on the top right (in the ``Translation status`` section). This " +"will automatically bring you to the translation interface for " +"untranslated strings." +msgstr "" + +#: ../../source/contributor-how-to-contribute-translations.rst:43 +msgid "This is what the interface looks like:" +msgstr "" + +#: ../../source/contributor-how-to-contribute-translations.rst:47 +msgid "" +"You input your translation in the textbox at the top and then, once you " +"are happy with it, you either press ``Save and continue`` (to save the " +"translation and go to the next untranslated string), ``Save and stay`` " +"(to save the translation and stay on the same page), ``Suggest`` (to add " +"your translation to suggestions for other users to view), or ``Skip`` (to" +" go to the next untranslated string without saving anything)." +msgstr "" + +#: ../../source/contributor-how-to-contribute-translations.rst:54 +msgid "" +"In order to help with the translations, you can see on the bottom the " +"``Nearby strings``, the ``Comments`` (from other contributors), the " +"``Automatic suggestions`` (from machine translation engines), the " +"translations in ``Other languages``, and the ``History`` of translations " +"for this string." +msgstr "" + +#: ../../source/contributor-how-to-contribute-translations.rst:59 +msgid "" +"On the right, under the ``String information`` section, you can also " +"click the link under ``Source string location`` in order to view the " +"source of the doc file containing the string." +msgstr "" + +#: ../../source/contributor-how-to-contribute-translations.rst:63 +msgid "" +"For more information about translating using Weblate, you can check out " +"this `in-depth guide " +"`_." +msgstr "" + +#: ../../source/contributor-how-to-contribute-translations.rst:67 +msgid "Add new languages" +msgstr "" + +#: ../../source/contributor-how-to-contribute-translations.rst:69 +msgid "" +"If you want to add a new language, you will first have to contact us, " +"either on `Slack `_, or by opening an " +"issue on our `GitHub repo `_." +msgstr "" + +#: ../../source/contributor-how-to-create-new-messages.rst:2 msgid "Creating New Messages" msgstr "Création de nouveaux messages" -#: ../../source/contributor-how-create-new-messages.rst:4 +#: ../../source/contributor-how-to-create-new-messages.rst:4 msgid "" "This is a simple guide for creating a new type of message between the " "server and clients in Flower." @@ -67,7 +409,7 @@ msgstr "" "Voici un guide simple pour créer un nouveau type de message entre le " "serveur et les clients dans Flower." -#: ../../source/contributor-how-create-new-messages.rst:6 +#: ../../source/contributor-how-to-create-new-messages.rst:6 msgid "" "Let's suppose we have the following example functions in " ":code:`server.py` and :code:`numpy_client.py`..." @@ -75,15 +417,15 @@ msgstr "" "Supposons que nous ayons les fonctions suivantes dans :code:`server.py` " "et :code:`numpy_client.py`..." -#: ../../source/contributor-how-create-new-messages.rst:8 +#: ../../source/contributor-how-to-create-new-messages.rst:8 msgid "Server's side:" msgstr "Côté serveur :" -#: ../../source/contributor-how-create-new-messages.rst:17 +#: ../../source/contributor-how-to-create-new-messages.rst:17 msgid "Client's side:" msgstr "Côté client :" -#: ../../source/contributor-how-create-new-messages.rst:26 +#: ../../source/contributor-how-to-create-new-messages.rst:26 msgid "" "Let's now see what we need to implement in order to get this simple " "function between the server and client to work!" @@ -91,11 +433,11 @@ msgstr "" "Voyons maintenant ce que nous devons mettre en œuvre pour que cette " "simple fonction entre le serveur et le client fonctionne !" -#: ../../source/contributor-how-create-new-messages.rst:30 +#: ../../source/contributor-how-to-create-new-messages.rst:30 msgid "Message Types for Protocol Buffers" msgstr "Types de messages pour les tampons de protocole" -#: ../../source/contributor-how-create-new-messages.rst:32 +#: ../../source/contributor-how-to-create-new-messages.rst:32 msgid "" "The first thing we need to do is to define a message type for the RPC " "system in :code:`transport.proto`. Note that we have to do it for both " @@ -110,15 +452,15 @@ msgstr "" "officielle `_." -#: ../../source/contributor-how-create-new-messages.rst:35 +#: ../../source/contributor-how-to-create-new-messages.rst:35 msgid "Within the :code:`ServerMessage` block:" msgstr "Dans le bloc :code:`ServerMessage` :" -#: ../../source/contributor-how-create-new-messages.rst:52 +#: ../../source/contributor-how-to-create-new-messages.rst:52 msgid "Within the ClientMessage block:" msgstr "Dans le bloc ClientMessage :" -#: ../../source/contributor-how-create-new-messages.rst:70 +#: ../../source/contributor-how-to-create-new-messages.rst:70 msgid "" "Make sure to also add a field of the newly created message type in " ":code:`oneof msg`." @@ -126,19 +468,19 @@ msgstr "" "Veille à ajouter également un champ du type de message nouvellement créé " "dans :code:`oneof msg`." -#: ../../source/contributor-how-create-new-messages.rst:72 +#: ../../source/contributor-how-to-create-new-messages.rst:72 msgid "Once that is done, we will compile the file with:" msgstr "Une fois que c'est fait, nous compilerons le fichier avec :" -#: ../../source/contributor-how-create-new-messages.rst:78 +#: ../../source/contributor-how-to-create-new-messages.rst:78 msgid "If it compiles succesfully, you should see the following message:" msgstr "S'il se compile avec succès, tu devrais voir le message suivant :" -#: ../../source/contributor-how-create-new-messages.rst:87 +#: ../../source/contributor-how-to-create-new-messages.rst:87 msgid "Serialization and Deserialization Functions" msgstr "Fonctions de sérialisation et de désérialisation" -#: ../../source/contributor-how-create-new-messages.rst:89 +#: ../../source/contributor-how-to-create-new-messages.rst:89 msgid "" "Our next step is to add functions to serialize and deserialize Python " "datatypes to or from our defined RPC message types. You should add these " @@ -149,15 +491,15 @@ msgstr "" "messages RPC définis. Tu dois ajouter ces fonctions dans " ":code:`serde.py`." -#: ../../source/contributor-how-create-new-messages.rst:91 +#: ../../source/contributor-how-to-create-new-messages.rst:91 msgid "The four functions:" msgstr "Les quatre fonctions :" -#: ../../source/contributor-how-create-new-messages.rst:112 +#: ../../source/contributor-how-to-create-new-messages.rst:112 msgid "Sending the Message from the Server" msgstr "Envoi du message à partir du serveur" -#: ../../source/contributor-how-create-new-messages.rst:114 +#: ../../source/contributor-how-to-create-new-messages.rst:114 msgid "" "Now write the request function in your Client Proxy class (e.g., " ":code:`grpc_client_proxy.py`) using the serde functions you just created:" @@ -166,11 +508,11 @@ msgstr "" "exemple, :code:`grpc_client_proxy.py`) en utilisant les fonctions serde " "que tu viens de créer :" -#: ../../source/contributor-how-create-new-messages.rst:128 +#: ../../source/contributor-how-to-create-new-messages.rst:128 msgid "Receiving the Message by the Client" msgstr "Réception du message par le client" -#: ../../source/contributor-how-create-new-messages.rst:130 +#: ../../source/contributor-how-to-create-new-messages.rst:130 msgid "" "Last step! Modify the code in :code:`message_handler.py` to check the " "field of your message and call the :code:`example_response` function. " @@ -180,15 +522,15 @@ msgstr "" "vérifier le champ de ton message et appeler la fonction " ":code:`example_response`. N'oublie pas d'utiliser les fonctions serde !" -#: ../../source/contributor-how-create-new-messages.rst:132 +#: ../../source/contributor-how-to-create-new-messages.rst:132 msgid "Within the handle function:" msgstr "Dans le cadre de la fonction de poignée :" -#: ../../source/contributor-how-create-new-messages.rst:139 +#: ../../source/contributor-how-to-create-new-messages.rst:139 msgid "And add a new function:" msgstr "Et ajoute une nouvelle fonction :" -#: ../../source/contributor-how-create-new-messages.rst:149 +#: ../../source/contributor-how-to-create-new-messages.rst:149 msgid "Hopefully, when you run your program you will get the intended result!" msgstr "" "Avec un peu de chance, lorsque tu exécuteras ton programme, tu obtiendras" @@ -262,13 +604,15 @@ msgid "Getting started" msgstr "Pour commencer" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:17 +#, fuzzy msgid "" "Configuring and setting up the :code:`Dockerfile` as well the " "configuration for the devcontainer can be a bit more involved. The good " -"thing is you want have to do it. Usually it should be enough to install " -"Docker on your system and ensure its available on your command line. " -"Additionally, install the `VSCode Containers Extension `_." +"thing is you don't have to do it. Usually it should be enough to install " +"`Docker `_ on your system and " +"ensure its available on your command line. Additionally, install the " +"`VSCode Containers Extension `_." msgstr "" "La configuration et le paramétrage du :code:`Dockerfile` ainsi que la " "configuration du devcontainer peuvent être un peu plus complexes. " @@ -385,16 +729,18 @@ msgid "Install ``flwr`` from a local wheel file via ``pyproject.toml``:" msgstr "Installez ``flwr`` à partir d'un fichier local via ``pyproject.toml`` :" #: ../../source/contributor-how-to-install-development-versions.rst:22 +#, fuzzy msgid "" -"``flwr = { path = \"../../dist/flwr-1.0.0-py3-none-any.whl\" }`` (without" +"``flwr = { path = \"../../dist/flwr-1.8.0-py3-none-any.whl\" }`` (without" " extras)" msgstr "" "``flwr = { path = \"../../dist/flwr-1.0.0-py3-none-any.whl\" }`` (sans " "extras)" #: ../../source/contributor-how-to-install-development-versions.rst:23 +#, fuzzy msgid "" -"``flwr = { path = \"../../dist/flwr-1.0.0-py3-none-any.whl\", extras = " +"``flwr = { path = \"../../dist/flwr-1.8.0-py3-none-any.whl\", extras = " "[\"simulation\"] }`` (with extras)" msgstr "" "``flwr = { path = \"../../dist/flwr-1.0.0-py3-none-any.whl\", extras = " @@ -514,6 +860,27 @@ msgstr "" "https://colab.research.google.com/github/adap/flower/blob/branch-" "name/doc/source/tutorial-get-started-with-flower-pytorch.ipynb" +#: ../../source/contributor-how-to-install-development-versions.rst:59 +msgid "Install a `whl` on Google Colab:" +msgstr "" + +#: ../../source/contributor-how-to-install-development-versions.rst:61 +msgid "" +"In the vertical icon grid on the left hand side, select ``Files`` > " +"``Upload to session storage``" +msgstr "" + +#: ../../source/contributor-how-to-install-development-versions.rst:62 +msgid "Upload the whl (e.g., ``flwr-1.8.0-py3-none-any.whl``)" +msgstr "" + +#: ../../source/contributor-how-to-install-development-versions.rst:63 +msgid "" +"Change ``!pip install -q 'flwr[simulation]' torch torchvision " +"matplotlib`` to ``!pip install -q 'flwr-1.8.0-py3-none-" +"any.whl[simulation]' torch torchvision matplotlib``" +msgstr "" + #: ../../source/contributor-how-to-release-flower.rst:2 msgid "Release Flower" msgstr "Publier Flower" @@ -527,45 +894,10 @@ msgstr "" "changer à l'avenir." #: ../../source/contributor-how-to-release-flower.rst:7 -msgid "Before the release" -msgstr "Avant la sortie" - -#: ../../source/contributor-how-to-release-flower.rst:9 -msgid "" -"Update the changelog (``changelog.md``) with all relevant changes that " -"happened after the last release. If the last release was tagged " -"``v1.2.0``, you can use the following URL to see all commits that got " -"merged into ``main`` since then:" -msgstr "" -"Mettez à jour le journal des modifications (``changelog.md``) avec tous " -"les changements pertinents qui se sont produits après la dernière " -"version. Si la dernière version a été étiquetée ``v1.2.0``, vous pouvez " -"utiliser l'URL suivante pour voir tous les commits qui ont été fusionnés " -"dans ``main`` depuis lors :" - -#: ../../source/contributor-how-to-release-flower.rst:11 -msgid "" -"`GitHub: Compare v1.2.0...main " -"`_" -msgstr "" -"`GitHub : Compare v1.2.0...main " -"`_" - -#: ../../source/contributor-how-to-release-flower.rst:13 -msgid "" -"Thank the authors who contributed since the last release. This command " -"helps extract them: ``git log --format='%aN' v1.1.0..HEAD | sort -u``. " -"The command has the same order as ``git shortlog``." -msgstr "" -"Remerciez les auteurs qui ont contribué depuis la dernière version. Cette" -" commande permet de les extraire : ``git log --format='%aN' v1.1.0..HEAD " -"| sort -u``. La commande a le même ordre que ``git shortlog``." - -#: ../../source/contributor-how-to-release-flower.rst:17 msgid "During the release" msgstr "Lors de la sortie" -#: ../../source/contributor-how-to-release-flower.rst:19 +#: ../../source/contributor-how-to-release-flower.rst:9 msgid "" "The version number of a release is stated in ``pyproject.toml``. To " "release a new version of Flower, the following things need to happen (in " @@ -575,65 +907,59 @@ msgstr "" "Pour publier une nouvelle version de Flower, les choses suivantes doivent" " se produire (dans cet ordre) :" -#: ../../source/contributor-how-to-release-flower.rst:21 +#: ../../source/contributor-how-to-release-flower.rst:11 msgid "" -"Update the ``changelog.md`` section header ``Unreleased`` to contain the " -"version number and date for the release you are building. Create a pull " -"request with the change." +"Run ``python3 src/py/flwr_tool/update_changelog.py `` in " +"order to add every new change to the changelog (feel free to make manual " +"changes to the changelog afterwards until it looks good)." msgstr "" -"Mettez à jour l'en-tête de section ``changelog.md`` ``Unreleased`` pour " -"qu'il contienne le numéro de version et la date de la version que vous " -"construisez. Créez une demande de traction avec le changement." -#: ../../source/contributor-how-to-release-flower.rst:22 +#: ../../source/contributor-how-to-release-flower.rst:12 msgid "" -"Tag the release commit with the version number as soon as the PR is " -"merged: ``git tag v0.12.3``, then ``git push --tags``" +"Once the changelog has been updated with all the changes, run ``./dev" +"/prepare-release-changelog.sh v``, where ```` " +"is the version stated in ``pyproject.toml`` (notice the ``v`` added " +"before it). This will replace the ``Unreleased`` header of the changelog " +"by the version and current date, and it will add a thanking message for " +"the contributors. Open a pull request with those changes." msgstr "" -"Marquez le commit de la version avec le numéro de version dès que le PR " -"est fusionné : ``git tag v0.12.3``, puis ``git push --tags``" -#: ../../source/contributor-how-to-release-flower.rst:23 +#: ../../source/contributor-how-to-release-flower.rst:13 msgid "" -"Build the release with ``./dev/build.sh``, then publish it with " -"``./dev/publish.sh``" +"Once the pull request is merged, tag the release commit with the version " +"number as soon as the PR is merged: ``git tag v`` (notice " +"the ``v`` added before the version number), then ``git push --tags``. " +"This will create a draft release on GitHub containing the correct " +"artifacts and the relevant part of the changelog." msgstr "" -"Construisez la version avec ``./dev/build.sh``, puis publiez-la avec " -"``./dev/publish.sh``" -#: ../../source/contributor-how-to-release-flower.rst:24 -msgid "" -"Create an entry in GitHub releases with the release notes for the " -"previously tagged commit and attach the build artifacts (:code:`.whl` and" -" :code:`.tar.gz`)." +#: ../../source/contributor-how-to-release-flower.rst:14 +msgid "Check the draft release on GitHub, and if everything is good, publish it." msgstr "" -"Crée une entrée dans GitHub releases avec les notes de version pour le " -"commit précédemment étiqueté et attache les artefacts de construction " -"(:code:`.whl` et :code:`.tar.gz`)." -#: ../../source/contributor-how-to-release-flower.rst:27 +#: ../../source/contributor-how-to-release-flower.rst:17 msgid "After the release" msgstr "Après la publication" -#: ../../source/contributor-how-to-release-flower.rst:29 +#: ../../source/contributor-how-to-release-flower.rst:19 msgid "Create a pull request which contains the following changes:" msgstr "Crée une demande de pull qui contient les modifications suivantes :" -#: ../../source/contributor-how-to-release-flower.rst:31 +#: ../../source/contributor-how-to-release-flower.rst:21 msgid "Increase the minor version in ``pyproject.toml`` by one." msgstr "Augmente la version mineure de ``pyproject.toml`` d'une unité." -#: ../../source/contributor-how-to-release-flower.rst:32 +#: ../../source/contributor-how-to-release-flower.rst:22 msgid "Update all files which contain the current version number if necessary." msgstr "" "Mets à jour tous les fichiers qui contiennent le numéro de version actuel" " si nécessaire." -#: ../../source/contributor-how-to-release-flower.rst:33 +#: ../../source/contributor-how-to-release-flower.rst:23 msgid "Add a new ``Unreleased`` section in ``changelog.md``." msgstr "Ajoute une nouvelle section ``Unreleased`` dans ``changelog.md``." -#: ../../source/contributor-how-to-release-flower.rst:35 +#: ../../source/contributor-how-to-release-flower.rst:25 msgid "" "Merge the pull request on the same day (i.e., before a new nighly release" " gets published to PyPI)." @@ -641,15 +967,15 @@ msgstr "" "Fusionne la pull request le jour même (c'est-à-dire avant qu'une nouvelle" " version nighly ne soit publiée sur PyPI)." -#: ../../source/contributor-how-to-release-flower.rst:38 +#: ../../source/contributor-how-to-release-flower.rst:28 msgid "Publishing a pre-release" msgstr "Publier une pré-version" -#: ../../source/contributor-how-to-release-flower.rst:41 +#: ../../source/contributor-how-to-release-flower.rst:31 msgid "Pre-release naming" msgstr "Nom de la pré-version" -#: ../../source/contributor-how-to-release-flower.rst:43 +#: ../../source/contributor-how-to-release-flower.rst:33 msgid "" "PyPI supports pre-releases (alpha, beta, release candiate). Pre-releases " "MUST use one of the following naming patterns:" @@ -657,39 +983,39 @@ msgstr "" "PyPI prend en charge les préversions (alpha, bêta, version candiate). Les" " préversions DOIVENT utiliser l'un des modèles de dénomination suivants :" -#: ../../source/contributor-how-to-release-flower.rst:45 +#: ../../source/contributor-how-to-release-flower.rst:35 msgid "Alpha: ``MAJOR.MINOR.PATCHaN``" msgstr "Alpha : ``MAJOR.MINOR.PATCHaN``" -#: ../../source/contributor-how-to-release-flower.rst:46 +#: ../../source/contributor-how-to-release-flower.rst:36 msgid "Beta: ``MAJOR.MINOR.PATCHbN``" msgstr "Bêta : ``MAJOR.MINOR.PATCHbN``" -#: ../../source/contributor-how-to-release-flower.rst:47 +#: ../../source/contributor-how-to-release-flower.rst:37 msgid "Release candiate (RC): ``MAJOR.MINOR.PATCHrcN``" msgstr "Candidat à la publication (RC) : ``MAJOR.MINOR.PATCHrcN``" -#: ../../source/contributor-how-to-release-flower.rst:49 +#: ../../source/contributor-how-to-release-flower.rst:39 msgid "Examples include:" msgstr "Voici quelques exemples :" -#: ../../source/contributor-how-to-release-flower.rst:51 +#: ../../source/contributor-how-to-release-flower.rst:41 msgid "``1.0.0a0``" msgstr "``1.0.0a0``" -#: ../../source/contributor-how-to-release-flower.rst:52 +#: ../../source/contributor-how-to-release-flower.rst:42 msgid "``1.0.0b0``" msgstr "``1.0.0b0``" -#: ../../source/contributor-how-to-release-flower.rst:53 +#: ../../source/contributor-how-to-release-flower.rst:43 msgid "``1.0.0rc0``" msgstr "``1.0.0rc0``" -#: ../../source/contributor-how-to-release-flower.rst:54 +#: ../../source/contributor-how-to-release-flower.rst:44 msgid "``1.0.0rc1``" msgstr "1.0.0rc1" -#: ../../source/contributor-how-to-release-flower.rst:56 +#: ../../source/contributor-how-to-release-flower.rst:46 msgid "" "This is in line with PEP-440 and the recommendations from the Python " "Packaging Authority (PyPA):" @@ -697,11 +1023,11 @@ msgstr "" "Ceci est conforme au PEP-440 et aux recommandations de l'Autorité de " "l'emballage Python (PyPA) :" -#: ../../source/contributor-how-to-release-flower.rst:59 +#: ../../source/contributor-how-to-release-flower.rst:49 msgid "`PEP-440 `_" msgstr "`PEP-440 `_" -#: ../../source/contributor-how-to-release-flower.rst:60 +#: ../../source/contributor-how-to-release-flower.rst:50 msgid "" "`PyPA Choosing a versioning scheme " "`_" -#: ../../source/contributor-how-to-release-flower.rst:62 +#: ../../source/contributor-how-to-release-flower.rst:52 msgid "" "Note that the approach defined by PyPA is not compatible with SemVer " "2.0.0 spec, for details consult the `Semantic Versioning Specification " @@ -723,17 +1049,17 @@ msgstr "" "Versioning Specification `_ (en particulier le point 11 sur la préséance)." -#: ../../source/contributor-how-to-release-flower.rst:65 +#: ../../source/contributor-how-to-release-flower.rst:55 msgid "Pre-release classification" msgstr "Classification avant publication" -#: ../../source/contributor-how-to-release-flower.rst:67 +#: ../../source/contributor-how-to-release-flower.rst:57 msgid "Should the next pre-release be called alpha, beta, or release candidate?" msgstr "" "La prochaine préversion doit-elle être appelée alpha, bêta ou release " "candidate ?" -#: ../../source/contributor-how-to-release-flower.rst:69 +#: ../../source/contributor-how-to-release-flower.rst:59 msgid "" "RC: feature complete, no known issues (apart from issues that are " "classified as \"won't fix\" for the next stable release) - if no issues " @@ -744,11 +1070,11 @@ msgstr "" "version stable) - si aucun problème n'apparaît, cette version deviendra " "la prochaine version stable" -#: ../../source/contributor-how-to-release-flower.rst:70 +#: ../../source/contributor-how-to-release-flower.rst:60 msgid "Beta: feature complete, allowed to have known issues" msgstr "Bêta : fonctionnalité complète, autorisée à avoir des problèmes connus" -#: ../../source/contributor-how-to-release-flower.rst:71 +#: ../../source/contributor-how-to-release-flower.rst:61 msgid "Alpha: not feature complete, allowed to have known issues" msgstr "" "Alpha : les fonctionnalités ne sont pas complètes, les problèmes connus " @@ -894,11 +1220,12 @@ msgstr "" "reStructuredText (fichiers `.rst`) et Markdown (fichiers `.md`)." #: ../../source/contributor-how-to-write-documentation.rst:10 -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:119 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:142 +#, fuzzy msgid "" "Note that, in order to build the documentation locally (with ``poetry run" " make html``, like described below), `Pandoc " -"_` needs to be installed on the " +"`_ needs to be installed on the " "system." msgstr "" "Noter que, pour compiler la documentation localement (avec ``poetry run " @@ -1114,12 +1441,12 @@ msgstr "" "GitHub." #: ../../source/contributor-tutorial-contribute-on-github.rst:6 +#, fuzzy msgid "" "If you're familiar with how contributing on GitHub works, you can " "directly checkout our `getting started guide for contributors " -"`_ and " -"examples of `good first contributions `_." +"`_." msgstr "" "Si tu es familier avec le fonctionnement des contributions sur GitHub, tu" " peux directement consulter notre `guide de démarrage pour les " @@ -1127,15 +1454,15 @@ msgstr "" "contributors.html>`_ et des exemples de `bonnes premières contributions " "`_." -#: ../../source/contributor-tutorial-contribute-on-github.rst:12 +#: ../../source/contributor-tutorial-contribute-on-github.rst:11 msgid "Setting up the repository" msgstr "Mise en place du référentiel" -#: ../../source/contributor-tutorial-contribute-on-github.rst:23 +#: ../../source/contributor-tutorial-contribute-on-github.rst:22 msgid "**Create a GitHub account and setup Git**" msgstr "**Créer un compte GitHub et configurer Git**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:15 +#: ../../source/contributor-tutorial-contribute-on-github.rst:14 msgid "" "Git is a distributed version control tool. This allows for an entire " "codebase's history to be stored and every developer's machine. It is a " @@ -1149,7 +1476,7 @@ msgstr "" "locale, tu peux suivre ce `guide `_ pour le mettre en place." -#: ../../source/contributor-tutorial-contribute-on-github.rst:18 +#: ../../source/contributor-tutorial-contribute-on-github.rst:17 msgid "" "GitHub, itself, is a code hosting platform for version control and " "collaboration. It allows for everyone to collaborate and work from " @@ -1159,7 +1486,7 @@ msgstr "" "contrôle des versions et la collaboration. Il permet à chacun de " "collaborer et de travailler de n'importe où sur des dépôts à distance." -#: ../../source/contributor-tutorial-contribute-on-github.rst:20 +#: ../../source/contributor-tutorial-contribute-on-github.rst:19 msgid "" "If you haven't already, you will need to create an account on `GitHub " "`_." @@ -1167,7 +1494,7 @@ msgstr "" "Si ce n'est pas déjà fait, tu devras créer un compte sur `GitHub " "`_." -#: ../../source/contributor-tutorial-contribute-on-github.rst:22 +#: ../../source/contributor-tutorial-contribute-on-github.rst:21 msgid "" "The idea behind the generic Git and GitHub workflow boils down to this: " "you download code from a remote repository on GitHub, make changes " @@ -1179,11 +1506,11 @@ msgstr "" " des modifications localement et tu en gardes une trace à l'aide de Git, " "puis tu télécharges ton nouvel historique à nouveau sur GitHub." -#: ../../source/contributor-tutorial-contribute-on-github.rst:34 +#: ../../source/contributor-tutorial-contribute-on-github.rst:33 msgid "**Forking the Flower repository**" msgstr "**Fourche le dépôt de Flower**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:26 +#: ../../source/contributor-tutorial-contribute-on-github.rst:25 msgid "" "A fork is a personal copy of a GitHub repository. To create one for " "Flower, you must navigate to https://github.com/adap/flower (while " @@ -1195,7 +1522,7 @@ msgstr "" "étant connecté à ton compte GitHub) et cliquer sur le bouton ``Fork`` " "situé en haut à droite de la page." -#: ../../source/contributor-tutorial-contribute-on-github.rst:31 +#: ../../source/contributor-tutorial-contribute-on-github.rst:30 msgid "" "You can change the name if you want, but this is not necessary as this " "version of Flower will be yours and will sit inside your own account " @@ -1208,11 +1535,11 @@ msgstr "" " devrais voir dans le coin supérieur gauche que tu es en train de " "regarder ta propre version de Flower." -#: ../../source/contributor-tutorial-contribute-on-github.rst:49 +#: ../../source/contributor-tutorial-contribute-on-github.rst:48 msgid "**Cloning your forked repository**" msgstr "**Clonage de ton dépôt forké**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:37 +#: ../../source/contributor-tutorial-contribute-on-github.rst:36 msgid "" "The next step is to download the forked repository on your machine to be " "able to make changes to it. On your forked repository page, you should " @@ -1224,7 +1551,7 @@ msgstr "" "forké, tu dois d'abord cliquer sur le bouton ``Code`` à droite, ce qui te" " permettra de copier le lien HTTPS du dépôt." -#: ../../source/contributor-tutorial-contribute-on-github.rst:43 +#: ../../source/contributor-tutorial-contribute-on-github.rst:42 msgid "" "Once you copied the \\, you can open a terminal on your machine, " "navigate to the place you want to download the repository to and type:" @@ -1233,23 +1560,24 @@ msgstr "" "machine, naviguer jusqu'à l'endroit où tu veux télécharger le référentiel" " et taper :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:49 +#: ../../source/contributor-tutorial-contribute-on-github.rst:48 +#, fuzzy msgid "" -"This will create a `flower/` (or the name of your fork if you renamed it)" -" folder in the current working directory." +"This will create a ``flower/`` (or the name of your fork if you renamed " +"it) folder in the current working directory." msgstr "" "Cela créera un dossier `flower/` (ou le nom de ta fourche si tu l'as " "renommée) dans le répertoire de travail actuel." -#: ../../source/contributor-tutorial-contribute-on-github.rst:68 +#: ../../source/contributor-tutorial-contribute-on-github.rst:67 msgid "**Add origin**" msgstr "**Ajouter l'origine**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:52 +#: ../../source/contributor-tutorial-contribute-on-github.rst:51 msgid "You can then go into the repository folder:" msgstr "Tu peux ensuite aller dans le dossier du référentiel :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:58 +#: ../../source/contributor-tutorial-contribute-on-github.rst:57 msgid "" "And here we will need to add an origin to our repository. The origin is " "the \\ of the remote fork repository. To obtain it, we can do as " @@ -1261,7 +1589,7 @@ msgstr "" "indiqué précédemment en allant sur notre dépôt fork sur notre compte " "GitHub et en copiant le lien." -#: ../../source/contributor-tutorial-contribute-on-github.rst:63 +#: ../../source/contributor-tutorial-contribute-on-github.rst:62 msgid "" "Once the \\ is copied, we can type the following command in our " "terminal:" @@ -1269,11 +1597,11 @@ msgstr "" "Une fois que le \\ est copié, nous pouvons taper la commande " "suivante dans notre terminal :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:92 +#: ../../source/contributor-tutorial-contribute-on-github.rst:91 msgid "**Add upstream**" msgstr "**Ajouter en amont**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:71 +#: ../../source/contributor-tutorial-contribute-on-github.rst:70 msgid "" "Now we will add an upstream address to our repository. Still in the same " "directroy, we must run the following command:" @@ -1282,13 +1610,13 @@ msgstr "" "Toujours dans le même directroy, nous devons exécuter la commande " "suivante :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:78 +#: ../../source/contributor-tutorial-contribute-on-github.rst:77 msgid "The following diagram visually explains what we did in the previous steps:" msgstr "" "Le schéma suivant explique visuellement ce que nous avons fait dans les " "étapes précédentes :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:82 +#: ../../source/contributor-tutorial-contribute-on-github.rst:81 msgid "" "The upstream is the GitHub remote address of the parent repository (in " "this case Flower), i.e. the one we eventually want to contribute to and " @@ -1302,7 +1630,7 @@ msgstr "" "simplement l'adresse distante GitHub du dépôt forké que nous avons créé, " "c'est-à-dire la copie (fork) dans notre propre compte." -#: ../../source/contributor-tutorial-contribute-on-github.rst:86 +#: ../../source/contributor-tutorial-contribute-on-github.rst:85 msgid "" "To make sure our local version of the fork is up-to-date with the latest " "changes from the Flower repository, we can execute the following command:" @@ -1311,11 +1639,11 @@ msgstr "" "dernières modifications du dépôt Flower, nous pouvons exécuter la " "commande suivante :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:95 +#: ../../source/contributor-tutorial-contribute-on-github.rst:94 msgid "Setting up the coding environment" msgstr "Mise en place de l'environnement de codage" -#: ../../source/contributor-tutorial-contribute-on-github.rst:97 +#: ../../source/contributor-tutorial-contribute-on-github.rst:96 msgid "" "This can be achieved by following this `getting started guide for " "contributors`_ (note that you won't need to clone the repository). Once " @@ -1327,11 +1655,11 @@ msgstr "" "fois que tu es capable d'écrire du code et de le tester, tu peux enfin " "commencer à faire des changements !" -#: ../../source/contributor-tutorial-contribute-on-github.rst:102 +#: ../../source/contributor-tutorial-contribute-on-github.rst:101 msgid "Making changes" msgstr "Apporter des changements" -#: ../../source/contributor-tutorial-contribute-on-github.rst:104 +#: ../../source/contributor-tutorial-contribute-on-github.rst:103 msgid "" "Before making any changes make sure you are up-to-date with your " "repository:" @@ -1339,15 +1667,15 @@ msgstr "" "Avant de faire des changements, assure-toi que tu es à jour avec ton " "référentiel :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:110 +#: ../../source/contributor-tutorial-contribute-on-github.rst:109 msgid "And with Flower's repository:" msgstr "Et avec le référentiel de Flower :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:124 +#: ../../source/contributor-tutorial-contribute-on-github.rst:123 msgid "**Create a new branch**" msgstr "**Créer une nouvelle branche**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:117 +#: ../../source/contributor-tutorial-contribute-on-github.rst:116 msgid "" "To make the history cleaner and easier to work with, it is good practice " "to create a new branch for each feature/project that needs to be " @@ -1357,7 +1685,7 @@ msgstr "" "une bonne pratique de créer une nouvelle branche pour chaque " "fonctionnalité/projet qui doit être mis en œuvre." -#: ../../source/contributor-tutorial-contribute-on-github.rst:120 +#: ../../source/contributor-tutorial-contribute-on-github.rst:119 msgid "" "To do so, just run the following command inside the repository's " "directory:" @@ -1365,21 +1693,21 @@ msgstr "" "Pour ce faire, il suffit d'exécuter la commande suivante dans le " "répertoire du référentiel :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:127 +#: ../../source/contributor-tutorial-contribute-on-github.rst:126 msgid "**Make changes**" msgstr "**Apporter des modifications**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:127 +#: ../../source/contributor-tutorial-contribute-on-github.rst:126 msgid "Write great code and create wonderful changes using your favorite editor!" msgstr "" "Écris du bon code et crée de merveilleuses modifications à l'aide de ton " "éditeur préféré !" -#: ../../source/contributor-tutorial-contribute-on-github.rst:140 +#: ../../source/contributor-tutorial-contribute-on-github.rst:139 msgid "**Test and format your code**" msgstr "**Teste et mets en forme ton code**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:130 +#: ../../source/contributor-tutorial-contribute-on-github.rst:129 msgid "" "Don't forget to test and format your code! Otherwise your code won't be " "able to be merged into the Flower repository. This is done so the " @@ -1389,15 +1717,15 @@ msgstr "" "pourra pas être fusionné dans le dépôt Flower, et ce, afin que la base de" " code reste cohérente et facile à comprendre." -#: ../../source/contributor-tutorial-contribute-on-github.rst:133 +#: ../../source/contributor-tutorial-contribute-on-github.rst:132 msgid "To do so, we have written a few scripts that you can execute:" msgstr "Pour ce faire, nous avons écrit quelques scripts que tu peux exécuter :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:152 +#: ../../source/contributor-tutorial-contribute-on-github.rst:151 msgid "**Stage changes**" msgstr "**Changements de scène**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:143 +#: ../../source/contributor-tutorial-contribute-on-github.rst:142 msgid "" "Before creating a commit that will update your history, you must specify " "to Git which files it needs to take into account." @@ -1405,11 +1733,11 @@ msgstr "" "Avant de créer un commit qui mettra à jour ton historique, tu dois " "spécifier à Git les fichiers qu'il doit prendre en compte." -#: ../../source/contributor-tutorial-contribute-on-github.rst:145 +#: ../../source/contributor-tutorial-contribute-on-github.rst:144 msgid "This can be done with:" msgstr "Cela peut se faire avec :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:151 +#: ../../source/contributor-tutorial-contribute-on-github.rst:150 msgid "" "To check which files have been modified compared to the last version " "(last commit) and to see which files are staged for commit, you can use " @@ -1419,11 +1747,11 @@ msgstr "" "version (last commit) et pour voir quels fichiers sont mis à disposition " "pour le commit, tu peux utiliser la commande :code:`git status`." -#: ../../source/contributor-tutorial-contribute-on-github.rst:162 +#: ../../source/contributor-tutorial-contribute-on-github.rst:161 msgid "**Commit changes**" msgstr "**Commit changes**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:155 +#: ../../source/contributor-tutorial-contribute-on-github.rst:154 msgid "" "Once you have added all the files you wanted to commit using :code:`git " "add`, you can finally create your commit using this command:" @@ -1432,7 +1760,7 @@ msgstr "" "l'aide de :code:`git add`, tu peux enfin créer ta livraison à l'aide de " "cette commande :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:161 +#: ../../source/contributor-tutorial-contribute-on-github.rst:160 msgid "" "The \\ is there to explain to others what the commit " "does. It should be written in an imperative style and be concise. An " @@ -1442,11 +1770,11 @@ msgstr "" "commit. Il doit être écrit dans un style impératif et être concis. Un " "exemple serait :code:`git commit -m \"Ajouter des images au README\"`." -#: ../../source/contributor-tutorial-contribute-on-github.rst:173 +#: ../../source/contributor-tutorial-contribute-on-github.rst:172 msgid "**Push the changes to the fork**" msgstr "**Pousser les changements vers la fourche**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:165 +#: ../../source/contributor-tutorial-contribute-on-github.rst:164 msgid "" "Once we have committed our changes, we have effectively updated our local" " history, but GitHub has no way of knowing this unless we push our " @@ -1457,7 +1785,7 @@ msgstr "" "moyen de le savoir à moins que nous ne poussions nos modifications vers " "l'adresse distante de notre origine :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:172 +#: ../../source/contributor-tutorial-contribute-on-github.rst:171 msgid "" "Once this is done, you will see on the GitHub that your forked repo was " "updated with the changes you have made." @@ -1465,15 +1793,15 @@ msgstr "" "Une fois que c'est fait, tu verras sur GitHub que ton repo forké a été " "mis à jour avec les modifications que tu as apportées." -#: ../../source/contributor-tutorial-contribute-on-github.rst:176 +#: ../../source/contributor-tutorial-contribute-on-github.rst:175 msgid "Creating and merging a pull request (PR)" msgstr "Créer et fusionner une pull request (PR)" -#: ../../source/contributor-tutorial-contribute-on-github.rst:203 +#: ../../source/contributor-tutorial-contribute-on-github.rst:206 msgid "**Create the PR**" msgstr "**Créer le PR**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:179 +#: ../../source/contributor-tutorial-contribute-on-github.rst:178 msgid "" "Once you have pushed changes, on the GitHub webpage of your repository " "you should see the following message:" @@ -1481,25 +1809,27 @@ msgstr "" "Une fois que tu as poussé les modifications, sur la page web GitHub de " "ton dépôt, tu devrais voir le message suivant :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:183 -msgid "Otherwise you can always find this option in the `Branches` page." +#: ../../source/contributor-tutorial-contribute-on-github.rst:182 +#, fuzzy +msgid "Otherwise you can always find this option in the ``Branches`` page." msgstr "Sinon, tu peux toujours trouver cette option dans la page `Branches`." -#: ../../source/contributor-tutorial-contribute-on-github.rst:185 +#: ../../source/contributor-tutorial-contribute-on-github.rst:184 +#, fuzzy msgid "" -"Once you click the `Compare & pull request` button, you should see " +"Once you click the ``Compare & pull request`` button, you should see " "something similar to this:" msgstr "" "Une fois que tu as cliqué sur le bouton `Compare & pull request`, tu " "devrais voir quelque chose de similaire à ceci :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:189 +#: ../../source/contributor-tutorial-contribute-on-github.rst:188 msgid "At the top you have an explanation of which branch will be merged where:" msgstr "" "En haut, tu as une explication de quelle branche sera fusionnée à quel " "endroit :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:193 +#: ../../source/contributor-tutorial-contribute-on-github.rst:192 msgid "" "In this example you can see that the request is to merge the branch " "``doc-fixes`` from my forked repository to branch ``main`` from the " @@ -1509,7 +1839,7 @@ msgstr "" "branche ``doc-fixes`` de mon dépôt forké à la branche ``main`` du dépôt " "Flower." -#: ../../source/contributor-tutorial-contribute-on-github.rst:195 +#: ../../source/contributor-tutorial-contribute-on-github.rst:194 msgid "" "The input box in the middle is there for you to describe what your PR " "does and to link it to existing issues. We have placed comments (that " @@ -1521,7 +1851,16 @@ msgstr "" "commentaires (qui ne seront pas rendus une fois le PR ouvert) pour te " "guider tout au long du processus." -#: ../../source/contributor-tutorial-contribute-on-github.rst:198 +#: ../../source/contributor-tutorial-contribute-on-github.rst:197 +msgid "" +"It is important to follow the instructions described in comments. For " +"instance, in order to not break how our changelog system works, you " +"should read the information above the ``Changelog entry`` section " +"carefully. You can also checkout some examples and details in the " +":ref:`changelogentry` appendix." +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:201 msgid "" "At the bottom you will find the button to open the PR. This will notify " "reviewers that a new PR has been opened and that they should look over it" @@ -1531,7 +1870,7 @@ msgstr "" "qui informera les réviseurs qu'un nouveau PR a été ouvert et qu'ils " "doivent le consulter pour le fusionner ou demander des modifications." -#: ../../source/contributor-tutorial-contribute-on-github.rst:201 +#: ../../source/contributor-tutorial-contribute-on-github.rst:204 msgid "" "If your PR is not yet ready for review, and you don't want to notify " "anyone, you have the option to create a draft pull request:" @@ -1540,11 +1879,11 @@ msgstr "" " personne, tu as la possibilité de créer un brouillon de demande de " "traction :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:206 +#: ../../source/contributor-tutorial-contribute-on-github.rst:209 msgid "**Making new changes**" msgstr "**Faire de nouveaux changements**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:206 +#: ../../source/contributor-tutorial-contribute-on-github.rst:209 msgid "" "Once the PR has been opened (as draft or not), you can still push new " "commits to it the same way we did before, by making changes to the branch" @@ -1554,11 +1893,11 @@ msgstr "" "toujours y pousser de nouveaux commits de la même manière qu'auparavant, " "en apportant des modifications à la branche associée au PR." -#: ../../source/contributor-tutorial-contribute-on-github.rst:228 +#: ../../source/contributor-tutorial-contribute-on-github.rst:231 msgid "**Review the PR**" msgstr "**Review the PR**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:209 +#: ../../source/contributor-tutorial-contribute-on-github.rst:212 msgid "" "Once the PR has been opened or once the draft PR has been marked as " "ready, a review from code owners will be automatically requested:" @@ -1567,7 +1906,7 @@ msgstr "" " étant prêt, une révision des propriétaires de code sera automatiquement " "demandée :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:213 +#: ../../source/contributor-tutorial-contribute-on-github.rst:216 msgid "" "Code owners will then look into the code, ask questions, request changes " "or validate the PR." @@ -1575,11 +1914,11 @@ msgstr "" "Les propriétaires du code vont alors se pencher sur le code, poser des " "questions, demander des modifications ou valider le RP." -#: ../../source/contributor-tutorial-contribute-on-github.rst:215 +#: ../../source/contributor-tutorial-contribute-on-github.rst:218 msgid "Merging will be blocked if there are ongoing requested changes." msgstr "La fusion sera bloquée s'il y a des changements demandés en cours." -#: ../../source/contributor-tutorial-contribute-on-github.rst:219 +#: ../../source/contributor-tutorial-contribute-on-github.rst:222 msgid "" "To resolve them, just push the necessary changes to the branch associated" " with the PR:" @@ -1587,11 +1926,11 @@ msgstr "" "Pour les résoudre, il suffit de pousser les changements nécessaires vers " "la branche associée au PR :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:223 +#: ../../source/contributor-tutorial-contribute-on-github.rst:226 msgid "And resolve the conversation:" msgstr "Et résous la conversation :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:227 +#: ../../source/contributor-tutorial-contribute-on-github.rst:230 msgid "" "Once all the conversations have been resolved, you can re-request a " "review." @@ -1599,11 +1938,11 @@ msgstr "" "Une fois que toutes les conversations ont été résolues, tu peux " "redemander un examen." -#: ../../source/contributor-tutorial-contribute-on-github.rst:248 +#: ../../source/contributor-tutorial-contribute-on-github.rst:251 msgid "**Once the PR is merged**" msgstr "**Une fois que le PR est fusionné**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:231 +#: ../../source/contributor-tutorial-contribute-on-github.rst:234 msgid "" "If all the automatic tests have passed and reviewers have no more changes" " to request, they can approve the PR and merge it." @@ -1612,7 +1951,7 @@ msgstr "" " de modifications à demander, ils peuvent approuver le PR et le " "fusionner." -#: ../../source/contributor-tutorial-contribute-on-github.rst:235 +#: ../../source/contributor-tutorial-contribute-on-github.rst:238 msgid "" "Once it is merged, you can delete the branch on GitHub (a button should " "appear to do so) and also delete it locally by doing:" @@ -1621,19 +1960,19 @@ msgstr "" "(un bouton devrait apparaître pour le faire) et aussi la supprimer " "localement en faisant :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:242 +#: ../../source/contributor-tutorial-contribute-on-github.rst:245 msgid "Then you should update your forked repository by doing:" msgstr "Ensuite, tu dois mettre à jour ton dépôt forké en faisant :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:251 +#: ../../source/contributor-tutorial-contribute-on-github.rst:254 msgid "Example of first contribution" msgstr "Exemple de première contribution" -#: ../../source/contributor-tutorial-contribute-on-github.rst:254 +#: ../../source/contributor-tutorial-contribute-on-github.rst:257 msgid "Problem" msgstr "Problème" -#: ../../source/contributor-tutorial-contribute-on-github.rst:256 +#: ../../source/contributor-tutorial-contribute-on-github.rst:259 msgid "" "For our documentation, we’ve started to use the `Diàtaxis framework " "`_." @@ -1641,7 +1980,7 @@ msgstr "" "Pour notre documentation, nous avons commencé à utiliser le cadre " "`Diàtaxis `_." -#: ../../source/contributor-tutorial-contribute-on-github.rst:258 +#: ../../source/contributor-tutorial-contribute-on-github.rst:261 msgid "" "Our “How to” guides should have titles that continue the sencence “How to" " …”, for example, “How to upgrade to Flower 1.0”." @@ -1650,7 +1989,7 @@ msgstr "" "la phrase \"Comment faire pour...\", par exemple, \"Comment passer à " "Flower 1.0\"." -#: ../../source/contributor-tutorial-contribute-on-github.rst:260 +#: ../../source/contributor-tutorial-contribute-on-github.rst:263 msgid "" "Most of our guides do not follow this new format yet, and changing their " "title is (unfortunately) more involved than one might think." @@ -1659,7 +1998,7 @@ msgstr "" "changer leur titre est (malheureusement) plus compliqué qu'on ne le " "pense." -#: ../../source/contributor-tutorial-contribute-on-github.rst:262 +#: ../../source/contributor-tutorial-contribute-on-github.rst:265 msgid "" "This issue is about changing the title of a doc from present continious " "to present simple." @@ -1667,7 +2006,7 @@ msgstr "" "Cette question porte sur le changement du titre d'un document du présent " "continu au présent simple." -#: ../../source/contributor-tutorial-contribute-on-github.rst:264 +#: ../../source/contributor-tutorial-contribute-on-github.rst:267 msgid "" "Let's take the example of “Saving Progress” which we changed to “Save " "Progress”. Does this pass our check?" @@ -1676,19 +2015,19 @@ msgstr "" "remplacé par \"Sauvegarder la progression\". Est-ce que cela passe notre " "contrôle ?" -#: ../../source/contributor-tutorial-contribute-on-github.rst:266 +#: ../../source/contributor-tutorial-contribute-on-github.rst:269 msgid "Before: ”How to saving progress” ❌" msgstr "Avant : \"Comment sauvegarder les progrès\" ❌" -#: ../../source/contributor-tutorial-contribute-on-github.rst:268 +#: ../../source/contributor-tutorial-contribute-on-github.rst:271 msgid "After: ”How to save progress” ✅" msgstr "Après : \"Comment sauvegarder la progression\" ✅" -#: ../../source/contributor-tutorial-contribute-on-github.rst:271 +#: ../../source/contributor-tutorial-contribute-on-github.rst:274 msgid "Solution" msgstr "Solution" -#: ../../source/contributor-tutorial-contribute-on-github.rst:273 +#: ../../source/contributor-tutorial-contribute-on-github.rst:276 msgid "" "This is a tiny change, but it’ll allow us to test your end-to-end setup. " "After cloning and setting up the Flower repo, here’s what you should do:" @@ -1697,19 +2036,21 @@ msgstr "" "configuration de bout en bout. Après avoir cloné et configuré le repo " "Flower, voici ce que tu dois faire :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:275 -msgid "Find the source file in `doc/source`" +#: ../../source/contributor-tutorial-contribute-on-github.rst:278 +#, fuzzy +msgid "Find the source file in ``doc/source``" msgstr "Trouve le fichier source dans `doc/source`" -#: ../../source/contributor-tutorial-contribute-on-github.rst:276 +#: ../../source/contributor-tutorial-contribute-on-github.rst:279 +#, fuzzy msgid "" -"Make the change in the `.rst` file (beware, the dashes under the title " +"Make the change in the ``.rst`` file (beware, the dashes under the title " "should be the same length as the title itself)" msgstr "" "Effectue la modification dans le fichier `.rst` (attention, les tirets " "sous le titre doivent être de la même longueur que le titre lui-même)" -#: ../../source/contributor-tutorial-contribute-on-github.rst:277 +#: ../../source/contributor-tutorial-contribute-on-github.rst:280 msgid "" "Build the docs and check the result: ``_" @@ -1718,11 +2059,11 @@ msgstr "" "``_" -#: ../../source/contributor-tutorial-contribute-on-github.rst:280 +#: ../../source/contributor-tutorial-contribute-on-github.rst:283 msgid "Rename file" msgstr "Renommer le fichier" -#: ../../source/contributor-tutorial-contribute-on-github.rst:282 +#: ../../source/contributor-tutorial-contribute-on-github.rst:285 msgid "" "You might have noticed that the file name still reflects the old wording." " If we just change the file, then we break all existing links to it - it " @@ -1735,49 +2076,54 @@ msgstr "" "important** d'éviter cela, car briser des liens peut nuire à notre " "classement dans les moteurs de recherche." -#: ../../source/contributor-tutorial-contribute-on-github.rst:285 +#: ../../source/contributor-tutorial-contribute-on-github.rst:288 msgid "Here’s how to change the file name:" msgstr "Voici comment changer le nom du fichier :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:287 -msgid "Change the file name to `save-progress.rst`" +#: ../../source/contributor-tutorial-contribute-on-github.rst:290 +#, fuzzy +msgid "Change the file name to ``save-progress.rst``" msgstr "Change le nom du fichier en `save-progress.rst`" -#: ../../source/contributor-tutorial-contribute-on-github.rst:288 -msgid "Add a redirect rule to `doc/source/conf.py`" +#: ../../source/contributor-tutorial-contribute-on-github.rst:291 +#, fuzzy +msgid "Add a redirect rule to ``doc/source/conf.py``" msgstr "Ajouter une règle de redirection à `doc/source/conf.py`" -#: ../../source/contributor-tutorial-contribute-on-github.rst:290 +#: ../../source/contributor-tutorial-contribute-on-github.rst:293 +#, fuzzy msgid "" -"This will cause a redirect from `saving-progress.html` to `save-" -"progress.html`, old links will continue to work." +"This will cause a redirect from ``saving-progress.html`` to ``save-" +"progress.html``, old links will continue to work." msgstr "" "Cela entraînera une redirection de `saving-progress.html` vers `save-" "progress.html`, les anciens liens continueront à fonctionner." -#: ../../source/contributor-tutorial-contribute-on-github.rst:293 +#: ../../source/contributor-tutorial-contribute-on-github.rst:296 msgid "Apply changes in the index file" msgstr "Applique les changements dans le fichier d'index" -#: ../../source/contributor-tutorial-contribute-on-github.rst:295 +#: ../../source/contributor-tutorial-contribute-on-github.rst:298 +#, fuzzy msgid "" "For the lateral navigation bar to work properly, it is very important to " -"update the `index.rst` file as well. This is where we define the whole " +"update the ``index.rst`` file as well. This is where we define the whole " "arborescence of the navbar." msgstr "" "Pour que la barre de navigation latérale fonctionne correctement, il est " "très important de mettre également à jour le fichier `index.rst`. C'est " "là que nous définissons toute l'arborescence de la barre de navigation." -#: ../../source/contributor-tutorial-contribute-on-github.rst:298 -msgid "Find and modify the file name in `index.rst`" +#: ../../source/contributor-tutorial-contribute-on-github.rst:301 +#, fuzzy +msgid "Find and modify the file name in ``index.rst``" msgstr "Trouve et modifie le nom du fichier dans `index.rst`" -#: ../../source/contributor-tutorial-contribute-on-github.rst:301 +#: ../../source/contributor-tutorial-contribute-on-github.rst:304 msgid "Open PR" msgstr "Open PR" -#: ../../source/contributor-tutorial-contribute-on-github.rst:303 +#: ../../source/contributor-tutorial-contribute-on-github.rst:306 msgid "" "Commit the changes (commit messages are always imperative: “Do " "something”, in this case “Change …”)" @@ -1785,29 +2131,29 @@ msgstr "" "Valide les modifications (les messages de validation sont toujours " "impératifs : \"Fais quelque chose\", dans ce cas \"Modifie...\")" -#: ../../source/contributor-tutorial-contribute-on-github.rst:304 +#: ../../source/contributor-tutorial-contribute-on-github.rst:307 msgid "Push the changes to your fork" msgstr "Transmets les changements à ta fourchette" -#: ../../source/contributor-tutorial-contribute-on-github.rst:305 +#: ../../source/contributor-tutorial-contribute-on-github.rst:308 msgid "Open a PR (as shown above)" msgstr "Ouvre un RP (comme indiqué ci-dessus)" -#: ../../source/contributor-tutorial-contribute-on-github.rst:306 +#: ../../source/contributor-tutorial-contribute-on-github.rst:309 msgid "Wait for it to be approved!" msgstr "Attends qu'elle soit approuvée !" -#: ../../source/contributor-tutorial-contribute-on-github.rst:307 +#: ../../source/contributor-tutorial-contribute-on-github.rst:310 msgid "Congrats! 🥳 You're now officially a Flower contributor!" msgstr "" "Félicitations 🥳 Tu es désormais officiellement une contributrice de " "Flower !" -#: ../../source/contributor-tutorial-contribute-on-github.rst:311 +#: ../../source/contributor-tutorial-contribute-on-github.rst:314 msgid "How to write a good PR title" msgstr "Comment écrire un bon titre de PR" -#: ../../source/contributor-tutorial-contribute-on-github.rst:313 +#: ../../source/contributor-tutorial-contribute-on-github.rst:316 msgid "" "A well-crafted PR title helps team members quickly understand the purpose" " and scope of the changes being proposed. Here's a guide to help you " @@ -1817,7 +2163,7 @@ msgstr "" "comprendre l'intérêt et le scope des changements proposés. Voici un guide" " pour vous aider à écrire des bons titres de PR :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:315 +#: ../../source/contributor-tutorial-contribute-on-github.rst:318 msgid "" "1. Be Clear and Concise: Provide a clear summary of the changes in a " "concise manner. 1. Use Actionable Verbs: Start with verbs like \"Add,\" " @@ -1835,7 +2181,7 @@ msgstr "" "capitalisation et une ponctuation : Suivre les règles de grammaire pour " "la clarté." -#: ../../source/contributor-tutorial-contribute-on-github.rst:321 +#: ../../source/contributor-tutorial-contribute-on-github.rst:324 msgid "" "Let's start with a few examples for titles that should be avoided because" " they do not provide meaningful information:" @@ -1843,27 +2189,27 @@ msgstr "" "Commençons par quelques exemples de titres qui devraient être évités " "parce qu'ils ne fournissent pas d'information significative :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:323 +#: ../../source/contributor-tutorial-contribute-on-github.rst:326 msgid "Implement Algorithm" msgstr "Implement Algorithm" -#: ../../source/contributor-tutorial-contribute-on-github.rst:324 +#: ../../source/contributor-tutorial-contribute-on-github.rst:327 msgid "Database" msgstr "Database" -#: ../../source/contributor-tutorial-contribute-on-github.rst:325 +#: ../../source/contributor-tutorial-contribute-on-github.rst:328 msgid "Add my_new_file.py to codebase" msgstr "Add my_new_file.py to codebase" -#: ../../source/contributor-tutorial-contribute-on-github.rst:326 +#: ../../source/contributor-tutorial-contribute-on-github.rst:329 msgid "Improve code in module" msgstr "Improve code in module" -#: ../../source/contributor-tutorial-contribute-on-github.rst:327 +#: ../../source/contributor-tutorial-contribute-on-github.rst:330 msgid "Change SomeModule" msgstr "Change SomeModule" -#: ../../source/contributor-tutorial-contribute-on-github.rst:329 +#: ../../source/contributor-tutorial-contribute-on-github.rst:332 msgid "" "Here are a few positive examples which provide helpful information " "without repeating how they do it, as that is already visible in the " @@ -1873,23 +2219,24 @@ msgstr "" "répéter comment ils le font, comme cela est déjà visible dans la section " "\"Files changed\" de la PR :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:331 +#: ../../source/contributor-tutorial-contribute-on-github.rst:334 msgid "Update docs banner to mention Flower Summit 2023" msgstr "Update docs banner to mention Flower Summit 2023" -#: ../../source/contributor-tutorial-contribute-on-github.rst:332 +#: ../../source/contributor-tutorial-contribute-on-github.rst:335 msgid "Remove unnecessary XGBoost dependency" msgstr "Remove unnecessary XGBoost dependency" -#: ../../source/contributor-tutorial-contribute-on-github.rst:333 +#: ../../source/contributor-tutorial-contribute-on-github.rst:336 msgid "Remove redundant attributes in strategies subclassing FedAvg" msgstr "Remove redundant attributes in strategies subclassing FedAvg" -#: ../../source/contributor-tutorial-contribute-on-github.rst:334 -msgid "Add CI job to deploy the staging system when the `main` branch changes" +#: ../../source/contributor-tutorial-contribute-on-github.rst:337 +#, fuzzy +msgid "Add CI job to deploy the staging system when the ``main`` branch changes" msgstr "Add CI job to deploy the staging system when the `main` branch changes" -#: ../../source/contributor-tutorial-contribute-on-github.rst:335 +#: ../../source/contributor-tutorial-contribute-on-github.rst:338 msgid "" "Add new amazing library which will be used to improve the simulation " "engine" @@ -1897,16 +2244,16 @@ msgstr "" "Add new amazing library which will be used to improve the simulation " "engine" -#: ../../source/contributor-tutorial-contribute-on-github.rst:339 -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:548 -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:946 -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:747 -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:713 -#: ../../source/tutorial-what-is-federated-learning.ipynb:367 +#: ../../source/contributor-tutorial-contribute-on-github.rst:342 +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:548 +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:946 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:727 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:713 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:367 msgid "Next steps" msgstr "Prochaines étapes" -#: ../../source/contributor-tutorial-contribute-on-github.rst:341 +#: ../../source/contributor-tutorial-contribute-on-github.rst:344 msgid "" "Once you have made your first PR, and want to contribute more, be sure to" " check out the following :" @@ -1914,7 +2261,7 @@ msgstr "" "Une fois que tu auras fait ton premier RP, et que tu voudras contribuer " "davantage, ne manque pas de consulter les sites suivants :" -#: ../../source/contributor-tutorial-contribute-on-github.rst:343 +#: ../../source/contributor-tutorial-contribute-on-github.rst:346 msgid "" "`Good first contributions `_, where you should particularly look " @@ -1924,6 +2271,143 @@ msgstr "" "/contributor-ref-good-first-contributions.html>`_, où vous devriez " "particulièrement regarder les contributions :code:`baselines`." +#: ../../source/contributor-tutorial-contribute-on-github.rst:350 +#: ../../source/fed/0000-20200102-fed-template.md:60 +msgid "Appendix" +msgstr "Annexe" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:355 +#, fuzzy +msgid "Changelog entry" +msgstr "Changelog" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:357 +msgid "" +"When opening a new PR, inside its description, there should be a " +"``Changelog entry`` header." +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:359 +msgid "" +"Above this header you should see the following comment that explains how " +"to write your changelog entry:" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:361 +msgid "" +"Inside the following 'Changelog entry' section, you should put the " +"description of your changes that will be added to the changelog alongside" +" your PR title." +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:364 +msgid "" +"If the section is completely empty (without any token) or non-existant, " +"the changelog will just contain the title of the PR for the changelog " +"entry, without any description." +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:367 +msgid "" +"If the section contains some text other than tokens, it will use it to " +"add a description to the change." +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:369 +msgid "" +"If the section contains one of the following tokens it will ignore any " +"other text and put the PR under the corresponding section of the " +"changelog:" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:371 +msgid " is for classifying a PR as a general improvement." +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:373 +msgid " is to not add the PR to the changelog" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:375 +msgid " is to add a general baselines change to the PR" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:377 +msgid " is to add a general examples change to the PR" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:379 +msgid " is to add a general sdk change to the PR" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:381 +msgid " is to add a general simulations change to the PR" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:383 +msgid "Note that only one token should be used." +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:385 +msgid "" +"Its content must have a specific format. We will break down what each " +"possibility does:" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:387 +msgid "" +"If the ``### Changelog entry`` section contains nothing or doesn't exist," +" the following text will be added to the changelog::" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:391 +msgid "" +"If the ``### Changelog entry`` section contains a description (and no " +"token), the following text will be added to the changelog::" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:397 +msgid "" +"If the ``### Changelog entry`` section contains ````, nothing will " +"change in the changelog." +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:399 +msgid "" +"If the ``### Changelog entry`` section contains ````, the " +"following text will be added to the changelog::" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:403 +msgid "" +"If the ``### Changelog entry`` section contains ````, the " +"following text will be added to the changelog::" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:407 +msgid "" +"If the ``### Changelog entry`` section contains ````, the " +"following text will be added to the changelog::" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:411 +msgid "" +"If the ``### Changelog entry`` section contains ````, the following " +"text will be added to the changelog::" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:415 +msgid "" +"If the ``### Changelog entry`` section contains ````, the " +"following text will be added to the changelog::" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:419 +msgid "" +"Note that only one token must be provided, otherwise, only the first " +"action (in the order listed above), will be performed." +msgstr "" + #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:2 msgid "Get started as a contributor" msgstr "Devenez un·e contributeur·ice" @@ -1933,7 +2417,8 @@ msgid "Prerequisites" msgstr "Prérequis" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:7 -msgid "`Python 3.7 `_ or above" +#, fuzzy +msgid "`Python 3.8 `_ or above" msgstr "`Python 3.7 `_ ou plus" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:8 @@ -1965,51 +2450,99 @@ msgstr "" msgid "Developer Machine Setup" msgstr "Setup de la machine" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:20 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:21 +msgid "Preliminarities" +msgstr "" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:22 +msgid "Some system-wide dependencies are needed." +msgstr "" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:25 +msgid "For macOS" +msgstr "" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:27 +msgid "" +"Install `homebrew `_. Don't forget the post-" +"installation actions to add `brew` to your PATH." +msgstr "" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:28 +msgid "" +"Install `xz` (to install different Python versions) and `pandoc` to build" +" the docs::" +msgstr "" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:34 +msgid "For Ubuntu" +msgstr "" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:35 +msgid "" +"Ensure you system (Ubuntu 22.04+) is up-to-date, and you have all " +"necessary packages::" +msgstr "" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:44 +#, fuzzy +msgid "Create Flower Dev Environment" +msgstr "Créer/Supprimer l'environment virtuel" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:46 +#, fuzzy msgid "" -"First, clone the `Flower repository `_ " -"from GitHub::" +"1. Clone the `Flower repository `_ from " +"GitHub::" msgstr "" "Pour commencer, cloner la `repo Flower `_" " depuis GitHub::" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:26 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:52 msgid "" -"Second, create a virtual environment (and activate it). If you chose to " -"use :code:`pyenv` (with the :code:`pyenv-virtualenv` plugin) and already " -"have it installed , you can use the following convenience script (by " -"default it will use :code:`Python 3.8.17`, but you can change it by " -"providing a specific :code:``)::" +"Let's create the Python environment for all-things Flower. If you wish to" +" use :code:`pyenv`, we provide two convenience scripts that you can use. " +"If you prefer using something else than :code:`pyenv`, create a new " +"environment, activate and skip to the last point where all packages are " +"installed." msgstr "" -"Deuxièmement, créer un environnement virtuel (et l'activer). Si vous " -"choisissez d'utiliser :code:`pyenv` (avec le plugin :code:`pyenv-" -"virtualenv`) et que vous l'avez déjà installé, vous pouvez utiliser le " -"script suivant (par défaut il utilisera :code:`Python 3.8.17`, mais vous " -"pouvez le changer en fournissant une :code:`` spécifique)::" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:33 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:54 +#, fuzzy +msgid "" +"If you don't have :code:`pyenv` installed, the following script that will" +" install it, set it up, and create the virtual environment (with " +":code:`Python 3.8.17` by default)::" +msgstr "" +"Si vous n'avez pas :code:`pyenv` installé, vous pouvez utiliser le script" +" suivant qui l'installera, le configurera et créera l'environnement " +"virtuel (avec :code:`Python 3.8.17` par défaut)::" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:58 +#, fuzzy msgid "" -"If you don't have :code:`pyenv` installed, you can use the following " -"script that will install pyenv, set it up and create the virtual " -"environment (with :code:`Python 3.8.17` by default)::" +"If you already have :code:`pyenv` installed (along with the :code:`pyenv-" +"virtualenv` plugin), you can use the following convenience script (with " +":code:`Python 3.8.17` by default)::" msgstr "" "Si vous n'avez pas :code:`pyenv` installé, vous pouvez utiliser le script" " suivant qui l'installera, le configurera et créera l'environnement " "virtuel (avec :code:`Python 3.8.17` par défaut)::" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:39 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:62 +#, fuzzy msgid "" -"Third, install the Flower package in development mode (think :code:`pip " +"3. Install the Flower package in development mode (think :code:`pip " "install -e`) along with all necessary dependencies::" msgstr "" "Troisièmement, installez le paquet Flower en mode de développement ( " ":code :`pip install -e`) avec toutes les dépendances nécessaires :" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:46 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:69 msgid "Convenience Scripts" msgstr "Scripts pratiques" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:48 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:71 msgid "" "The Flower repository contains a number of convenience scripts to make " "recurring development tasks easier and less error-prone. See the " @@ -2021,61 +2554,62 @@ msgstr "" "problématiques. Voir le sous-répertoire :code :`/dev` pour une liste " "complète. Les scripts suivants sont parmis les plus importants :" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:54 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:77 msgid "Create/Delete Virtual Environment" msgstr "Créer/Supprimer l'environment virtuel" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:62 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:85 msgid "Compile ProtoBuf Definitions" msgstr "Compiler les définitions ProtoBuf" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:69 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:92 msgid "Auto-Format Code" msgstr "Formatter le code" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:76 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:99 msgid "Run Linters and Tests" msgstr "Vérifier le format et tester le code" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:83 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:106 msgid "Run Github Actions (CI) locally" msgstr "Exécuter les GitHub Actions (CI) localement" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:85 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:108 +#, fuzzy msgid "" "Developers could run the full set of Github Actions workflows under their" -" local environment by using `Act _`. " +" local environment by using `Act `_. " "Please refer to the installation instructions under the linked repository" " and run the next command under Flower main cloned repository folder::" msgstr "" "Il est possible d'exécuter l'ensemble des Github Actions sous leur " -"environnement local en utilisant `Act _`. En " -"suivant le lien vous trouverez les instructions d'installation. Une fois " -"installé, exécuter la commande suivante dans le dossier principale de Flower " -":" +"environnement local en utilisant `Act _`." +" En suivant le lien vous trouverez les instructions d'installation. Une " +"fois installé, exécuter la commande suivante dans le dossier principale " +"de Flower :" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:92 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:115 msgid "" "The Flower default workflow would run by setting up the required Docker " "machines underneath." msgstr "" -"Le workflow par défaut de Flower sera exécuté en configurant les machines " -"Docker requises en arrière plan." +"Le workflow par défaut de Flower sera exécuté en configurant les machines" +" Docker requises en arrière plan." -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:97 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:120 #, fuzzy msgid "Build Release" msgstr "Inédit" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:99 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:122 msgid "" "Flower uses Poetry to build releases. The necessary command is wrapped in" " a simple script::" msgstr "" -"Flower utilise Poetry pour construire les nouvelles versions. La commande " -"nécessaire est comprise dans un script simple ::" +"Flower utilise Poetry pour construire les nouvelles versions. La commande" +" nécessaire est comprise dans un script simple ::" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:104 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:127 msgid "" "The resulting :code:`.whl` and :code:`.tar.gz` releases will be stored in" " the :code:`/dist` subdirectory." @@ -2083,19 +2617,19 @@ msgstr "" "Les versions résultantes :code:`.whl` et :code:`.tar.gz` seront stockées " "dans le sous-répertoire:code:`/dist`." -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:109 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:132 #, fuzzy msgid "Build Documentation" msgstr "Amélioration de la documentation" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:111 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:134 msgid "" "Flower's documentation uses `Sphinx `_. " "There's no convenience script to re-build the documentation yet, but it's" " pretty easy::" msgstr "" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:117 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:140 msgid "This will generate HTML documentation in ``doc/build/html``." msgstr "" @@ -2104,6 +2638,7 @@ msgid "Example: FedBN in PyTorch - From Centralized To Federated" msgstr "Exemple : FedBN dans PyTorch - De la centralisation à la fédération" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:4 +#, fuzzy msgid "" "This tutorial will show you how to use Flower to build a federated " "version of an existing machine learning workload with `FedBN " @@ -2111,8 +2646,8 @@ msgid "" "designed for non-iid data. We are using PyTorch to train a Convolutional " "Neural Network(with Batch Normalization layers) on the CIFAR-10 dataset. " "When applying FedBN, only few changes needed compared to `Example: " -"PyTorch - From Centralized To Federated `_." +"PyTorch - From Centralized To Federated `_." msgstr "" "Ce tutoriel te montrera comment utiliser Flower pour construire une " "version fédérée d'une charge de travail d'apprentissage automatique " @@ -2131,9 +2666,10 @@ msgid "Centralized Training" msgstr "Formation centralisée" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:10 +#, fuzzy msgid "" "All files are revised based on `Example: PyTorch - From Centralized To " -"Federated `_. The only thing to do is modifying the file called " ":code:`cifar.py`, revised part is shown below:" msgstr "" @@ -2176,14 +2712,15 @@ msgid "Federated Training" msgstr "Formation fédérée" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:53 +#, fuzzy msgid "" "If you have read `Example: PyTorch - From Centralized To Federated " -"`_, the following parts are easy to follow, onyl " ":code:`get_parameters` and :code:`set_parameters` function in " ":code:`client.py` needed to revise. If not, please read the `Example: " -"PyTorch - From Centralized To Federated `_. first." +"PyTorch - From Centralized To Federated `_. first." msgstr "" "Si vous avez lu `Exemple : PyTorch - From Centralized To Federated " "`_." #: ../../source/example-jax-from-centralized-to-federated.rst:23 -#: ../../source/tutorial-quickstart-jax.rst:26 +#: ../../source/tutorial-quickstart-jax.rst:29 msgid "" "Let's create a new file called :code:`jax_training.py` with all the " "components required for a traditional (centralized) linear regression " @@ -2342,7 +2879,7 @@ msgstr "" "fédéré, ce qui sera fait plus tard." #: ../../source/example-jax-from-centralized-to-federated.rst:37 -#: ../../source/tutorial-quickstart-jax.rst:40 +#: ../../source/tutorial-quickstart-jax.rst:43 msgid "" "The :code:`load_data()` function loads the mentioned training and test " "sets." @@ -2351,7 +2888,7 @@ msgstr "" " test mentionnés." #: ../../source/example-jax-from-centralized-to-federated.rst:47 -#: ../../source/tutorial-quickstart-jax.rst:50 +#: ../../source/tutorial-quickstart-jax.rst:53 msgid "" "The model architecture (a very simple :code:`Linear Regression` model) is" " defined in :code:`load_model()`." @@ -2360,7 +2897,7 @@ msgstr "" "simple) est définie dans :code:`load_model()`." #: ../../source/example-jax-from-centralized-to-federated.rst:59 -#: ../../source/tutorial-quickstart-jax.rst:62 +#: ../../source/tutorial-quickstart-jax.rst:65 msgid "" "We now need to define the training (function :code:`train()`), which " "loops over the training set and measures the loss (function " @@ -2376,7 +2913,7 @@ msgstr "" ":code:`train()`)." #: ../../source/example-jax-from-centralized-to-federated.rst:77 -#: ../../source/tutorial-quickstart-jax.rst:80 +#: ../../source/tutorial-quickstart-jax.rst:83 msgid "" "The evaluation of the model is defined in the function " ":code:`evaluation()`. The function takes all test examples and measures " @@ -2387,7 +2924,7 @@ msgstr "" " de régression linéaire." #: ../../source/example-jax-from-centralized-to-federated.rst:88 -#: ../../source/tutorial-quickstart-jax.rst:91 +#: ../../source/tutorial-quickstart-jax.rst:94 msgid "" "Having defined the data loading, model architecture, training, and " "evaluation we can put everything together and train our model using JAX. " @@ -2401,14 +2938,14 @@ msgstr "" "à :code:`train()`." #: ../../source/example-jax-from-centralized-to-federated.rst:105 -#: ../../source/tutorial-quickstart-jax.rst:108 +#: ../../source/tutorial-quickstart-jax.rst:111 msgid "You can now run your (centralized) JAX linear regression workload:" msgstr "" "Tu peux maintenant exécuter ta charge de travail (centralisée) de " "régression linéaire JAX :" #: ../../source/example-jax-from-centralized-to-federated.rst:111 -#: ../../source/tutorial-quickstart-jax.rst:114 +#: ../../source/tutorial-quickstart-jax.rst:117 msgid "" "So far this should all look fairly familiar if you've used JAX before. " "Let's take the next step and use what we've built to create a simple " @@ -2420,12 +2957,12 @@ msgstr "" "composé d'un serveur et de deux clients." #: ../../source/example-jax-from-centralized-to-federated.rst:115 -#: ../../source/tutorial-quickstart-jax.rst:118 +#: ../../source/tutorial-quickstart-jax.rst:121 msgid "JAX meets Flower" msgstr "JAX rencontre Flower" #: ../../source/example-jax-from-centralized-to-federated.rst:117 -#: ../../source/tutorial-quickstart-jax.rst:120 +#: ../../source/tutorial-quickstart-jax.rst:123 msgid "" "The concept of federating an existing workload is always the same and " "easy to understand. We have to start a *server* and then use the code in " @@ -2449,7 +2986,7 @@ msgstr "" #: ../../source/example-jax-from-centralized-to-federated.rst:123 #: ../../source/example-mxnet-walk-through.rst:204 #: ../../source/example-pytorch-from-centralized-to-federated.rst:181 -#: ../../source/tutorial-quickstart-jax.rst:126 +#: ../../source/tutorial-quickstart-jax.rst:129 msgid "" "Our example consists of one *server* and two *clients*. Let's set up " ":code:`server.py` first. The *server* needs to import the Flower package " @@ -2465,12 +3002,12 @@ msgstr "" #: ../../source/example-jax-from-centralized-to-federated.rst:133 #: ../../source/example-mxnet-walk-through.rst:214 #: ../../source/example-pytorch-from-centralized-to-federated.rst:191 -#: ../../source/tutorial-quickstart-jax.rst:136 +#: ../../source/tutorial-quickstart-jax.rst:139 msgid "We can already start the *server*:" msgstr "Nous pouvons déjà démarrer le *serveur* :" #: ../../source/example-jax-from-centralized-to-federated.rst:139 -#: ../../source/tutorial-quickstart-jax.rst:142 +#: ../../source/tutorial-quickstart-jax.rst:145 msgid "" "Finally, we will define our *client* logic in :code:`client.py` and build" " upon the previously defined JAX training in :code:`jax_training.py`. Our" @@ -2484,7 +3021,7 @@ msgstr "" " les paramètres de notre modèle JAX :" #: ../../source/example-jax-from-centralized-to-federated.rst:154 -#: ../../source/tutorial-quickstart-jax.rst:157 +#: ../../source/tutorial-quickstart-jax.rst:160 msgid "" "Implementing a Flower *client* basically means implementing a subclass of" " either :code:`flwr.client.Client` or :code:`flwr.client.NumPyClient`. " @@ -2511,28 +3048,28 @@ msgstr "" #: ../../source/example-jax-from-centralized-to-federated.rst:161 #: ../../source/example-mxnet-walk-through.rst:242 -#: ../../source/tutorial-quickstart-jax.rst:164 +#: ../../source/tutorial-quickstart-jax.rst:167 msgid ":code:`set_parameters (optional)`" msgstr ":code:`set_parameters (optional)`" #: ../../source/example-jax-from-centralized-to-federated.rst:160 #: ../../source/example-mxnet-walk-through.rst:241 #: ../../source/example-pytorch-from-centralized-to-federated.rst:219 -#: ../../source/tutorial-quickstart-jax.rst:163 +#: ../../source/tutorial-quickstart-jax.rst:166 msgid "" "set the model parameters on the local model that are received from the " "server" msgstr "règle les paramètres du modèle local reçus du serveur" #: ../../source/example-jax-from-centralized-to-federated.rst:161 -#: ../../source/tutorial-quickstart-jax.rst:164 +#: ../../source/tutorial-quickstart-jax.rst:167 msgid "transform parameters to NumPy :code:`ndarray`'s" msgstr "transforme les paramètres en NumPy :code:`ndarray`'s" #: ../../source/example-jax-from-centralized-to-federated.rst:162 #: ../../source/example-mxnet-walk-through.rst:243 #: ../../source/example-pytorch-from-centralized-to-federated.rst:220 -#: ../../source/tutorial-quickstart-jax.rst:165 +#: ../../source/tutorial-quickstart-jax.rst:168 msgid "" "loop over the list of model parameters received as NumPy " ":code:`ndarray`'s (think list of neural network layers)" @@ -2543,17 +3080,17 @@ msgstr "" #: ../../source/example-jax-from-centralized-to-federated.rst:163 #: ../../source/example-mxnet-walk-through.rst:244 #: ../../source/example-pytorch-from-centralized-to-federated.rst:221 -#: ../../source/tutorial-quickstart-jax.rst:166 -#: ../../source/tutorial-quickstart-mxnet.rst:166 -#: ../../source/tutorial-quickstart-pytorch.rst:152 -#: ../../source/tutorial-quickstart-scikitlearn.rst:105 +#: ../../source/tutorial-quickstart-jax.rst:169 +#: ../../source/tutorial-quickstart-mxnet.rst:171 +#: ../../source/tutorial-quickstart-pytorch.rst:155 +#: ../../source/tutorial-quickstart-scikitlearn.rst:108 msgid ":code:`get_parameters`" msgstr ":code:`get_parameters`" #: ../../source/example-jax-from-centralized-to-federated.rst:164 #: ../../source/example-mxnet-walk-through.rst:245 #: ../../source/example-pytorch-from-centralized-to-federated.rst:222 -#: ../../source/tutorial-quickstart-jax.rst:167 +#: ../../source/tutorial-quickstart-jax.rst:170 msgid "" "get the model parameters and return them as a list of NumPy " ":code:`ndarray`'s (which is what :code:`flwr.client.NumPyClient` expects)" @@ -2565,10 +3102,10 @@ msgstr "" #: ../../source/example-jax-from-centralized-to-federated.rst:167 #: ../../source/example-mxnet-walk-through.rst:248 #: ../../source/example-pytorch-from-centralized-to-federated.rst:225 -#: ../../source/tutorial-quickstart-jax.rst:170 -#: ../../source/tutorial-quickstart-mxnet.rst:172 -#: ../../source/tutorial-quickstart-pytorch.rst:158 -#: ../../source/tutorial-quickstart-scikitlearn.rst:112 +#: ../../source/tutorial-quickstart-jax.rst:173 +#: ../../source/tutorial-quickstart-mxnet.rst:177 +#: ../../source/tutorial-quickstart-pytorch.rst:161 +#: ../../source/tutorial-quickstart-scikitlearn.rst:115 msgid ":code:`fit`" msgstr ":code:`fit`" @@ -2578,8 +3115,8 @@ msgstr ":code:`fit`" #: ../../source/example-mxnet-walk-through.rst:251 #: ../../source/example-pytorch-from-centralized-to-federated.rst:224 #: ../../source/example-pytorch-from-centralized-to-federated.rst:228 -#: ../../source/tutorial-quickstart-jax.rst:169 -#: ../../source/tutorial-quickstart-jax.rst:173 +#: ../../source/tutorial-quickstart-jax.rst:172 +#: ../../source/tutorial-quickstart-jax.rst:176 msgid "" "update the parameters of the local model with the parameters received " "from the server" @@ -2590,12 +3127,12 @@ msgstr "" #: ../../source/example-jax-from-centralized-to-federated.rst:167 #: ../../source/example-mxnet-walk-through.rst:248 #: ../../source/example-pytorch-from-centralized-to-federated.rst:225 -#: ../../source/tutorial-quickstart-jax.rst:170 +#: ../../source/tutorial-quickstart-jax.rst:173 msgid "train the model on the local training set" msgstr "entraîne le modèle sur l'ensemble d'apprentissage local" #: ../../source/example-jax-from-centralized-to-federated.rst:168 -#: ../../source/tutorial-quickstart-jax.rst:171 +#: ../../source/tutorial-quickstart-jax.rst:174 msgid "get the updated local model parameters and return them to the server" msgstr "" "récupère les paramètres du modèle local mis à jour et les renvoie au " @@ -2604,27 +3141,27 @@ msgstr "" #: ../../source/example-jax-from-centralized-to-federated.rst:172 #: ../../source/example-mxnet-walk-through.rst:253 #: ../../source/example-pytorch-from-centralized-to-federated.rst:230 -#: ../../source/tutorial-quickstart-jax.rst:175 -#: ../../source/tutorial-quickstart-mxnet.rst:175 -#: ../../source/tutorial-quickstart-pytorch.rst:161 -#: ../../source/tutorial-quickstart-scikitlearn.rst:115 +#: ../../source/tutorial-quickstart-jax.rst:178 +#: ../../source/tutorial-quickstart-mxnet.rst:180 +#: ../../source/tutorial-quickstart-pytorch.rst:164 +#: ../../source/tutorial-quickstart-scikitlearn.rst:118 msgid ":code:`evaluate`" msgstr ":code:`évaluer`" #: ../../source/example-jax-from-centralized-to-federated.rst:171 #: ../../source/example-mxnet-walk-through.rst:252 #: ../../source/example-pytorch-from-centralized-to-federated.rst:229 -#: ../../source/tutorial-quickstart-jax.rst:174 +#: ../../source/tutorial-quickstart-jax.rst:177 msgid "evaluate the updated model on the local test set" msgstr "évaluer le modèle mis à jour sur l'ensemble de test local" #: ../../source/example-jax-from-centralized-to-federated.rst:172 -#: ../../source/tutorial-quickstart-jax.rst:175 +#: ../../source/tutorial-quickstart-jax.rst:178 msgid "return the local loss to the server" msgstr "renvoie la perte locale au serveur" #: ../../source/example-jax-from-centralized-to-federated.rst:174 -#: ../../source/tutorial-quickstart-jax.rst:177 +#: ../../source/tutorial-quickstart-jax.rst:180 msgid "" "The challenging part is to transform the JAX model parameters from " ":code:`DeviceArray` to :code:`NumPy ndarray` to make them compatible with" @@ -2635,7 +3172,7 @@ msgstr "" "rendre compatibles avec `NumPyClient`." #: ../../source/example-jax-from-centralized-to-federated.rst:176 -#: ../../source/tutorial-quickstart-jax.rst:179 +#: ../../source/tutorial-quickstart-jax.rst:182 msgid "" "The two :code:`NumPyClient` methods :code:`fit` and :code:`evaluate` make" " use of the functions :code:`train()` and :code:`evaluate()` previously " @@ -2655,21 +3192,21 @@ msgstr "" "de données qui sont transmis." #: ../../source/example-jax-from-centralized-to-federated.rst:245 -#: ../../source/tutorial-quickstart-jax.rst:248 +#: ../../source/tutorial-quickstart-jax.rst:251 msgid "Having defined the federation process, we can run it." msgstr "Après avoir défini le processus de fédération, nous pouvons l'exécuter." #: ../../source/example-jax-from-centralized-to-federated.rst:268 #: ../../source/example-mxnet-walk-through.rst:347 #: ../../source/example-pytorch-from-centralized-to-federated.rst:301 -#: ../../source/tutorial-quickstart-jax.rst:271 +#: ../../source/tutorial-quickstart-jax.rst:274 msgid "And that's it. You can now open two additional terminal windows and run" msgstr "" "Tu peux maintenant ouvrir deux autres fenêtres de terminal et exécuter " "les commandes suivantes" #: ../../source/example-jax-from-centralized-to-federated.rst:274 -#: ../../source/tutorial-quickstart-jax.rst:277 +#: ../../source/tutorial-quickstart-jax.rst:280 msgid "" "in each window (make sure that the server is still running before you do " "so) and see your JAX project run federated learning across two clients. " @@ -2680,7 +3217,7 @@ msgstr "" "l'apprentissage fédéré sur deux clients. Félicitations !" #: ../../source/example-jax-from-centralized-to-federated.rst:279 -#: ../../source/tutorial-quickstart-jax.rst:282 +#: ../../source/tutorial-quickstart-jax.rst:285 #, fuzzy msgid "" "The source code of this example was improved over time and can be found " @@ -2695,7 +3232,7 @@ msgstr "" "chargent le même jeu de données." #: ../../source/example-jax-from-centralized-to-federated.rst:282 -#: ../../source/tutorial-quickstart-jax.rst:285 +#: ../../source/tutorial-quickstart-jax.rst:288 msgid "" "You're now prepared to explore this topic further. How about using a more" " sophisticated model or using a different dataset? How about adding more " @@ -3239,15 +3776,15 @@ msgid "" "All that's left to do it to define a function that loads both model and " "data, creates a :code:`CifarClient`, and starts this client. You load " "your data and model by using :code:`cifar.py`. Start :code:`CifarClient` " -"with the function :code:`fl.client.start_client()` by pointing it " -"at the same IP adress we used in :code:`server.py`:" +"with the function :code:`fl.client.start_client()` by pointing it at the " +"same IP adress we used in :code:`server.py`:" msgstr "" "Il ne reste plus qu'à définir une fonction qui charge le modèle et les " "données, crée un :code:`CifarClient` et démarre ce client. Tu charges tes" " données et ton modèle en utilisant :code:`cifar.py`. Démarre " -":code:`CifarClient` avec la fonction " -":code:`fl.client.start_client()` en la faisant pointer sur la même " -"adresse IP que celle que nous avons utilisée dans :code:`server.py` :" +":code:`CifarClient` avec la fonction :code:`fl.client.start_client()` en " +"la faisant pointer sur la même adresse IP que celle que nous avons " +"utilisée dans :code:`server.py` :" #: ../../source/example-pytorch-from-centralized-to-federated.rst:307 msgid "" @@ -3292,9 +3829,9 @@ msgstr "" "neuronal convolutif sur MNIST en utilisant Flower et PyTorch." #: ../../source/example-walkthrough-pytorch-mnist.rst:6 -#: ../../source/tutorial-quickstart-mxnet.rst:11 -#: ../../source/tutorial-quickstart-pytorch.rst:14 -#: ../../source/tutorial-quickstart-scikitlearn.rst:11 +#: ../../source/tutorial-quickstart-mxnet.rst:16 +#: ../../source/tutorial-quickstart-pytorch.rst:17 +#: ../../source/tutorial-quickstart-scikitlearn.rst:14 msgid "" "Our example consists of one *server* and two *clients* all having the " "same model." @@ -3303,7 +3840,7 @@ msgstr "" "même modèle." #: ../../source/example-walkthrough-pytorch-mnist.rst:8 -#: ../../source/tutorial-quickstart-pytorch.rst:16 +#: ../../source/tutorial-quickstart-pytorch.rst:19 msgid "" "*Clients* are responsible for generating individual weight-updates for " "the model based on their local datasets. These updates are then sent to " @@ -3319,7 +3856,7 @@ msgstr "" "mises à jour de poids s'appelle un *round*." #: ../../source/example-walkthrough-pytorch-mnist.rst:12 -#: ../../source/tutorial-quickstart-pytorch.rst:20 +#: ../../source/tutorial-quickstart-pytorch.rst:23 msgid "" "Now that we have a rough idea of what is going on, let's get started. We " "first need to install Flower. You can do this by running :" @@ -3385,11 +3922,12 @@ msgid "Now, let's see what is really happening inside." msgstr "Maintenant, voyons ce qui se passe réellement à l'intérieur." #: ../../source/example-walkthrough-pytorch-mnist.rst:69 -#: ../../source/tutorial-quickstart-ios.rst:126 -#: ../../source/tutorial-quickstart-mxnet.rst:221 -#: ../../source/tutorial-quickstart-pytorch.rst:200 -#: ../../source/tutorial-quickstart-scikitlearn.rst:154 -#: ../../source/tutorial-quickstart-tensorflow.rst:95 +#: ../../source/tutorial-quickstart-ios.rst:129 +#: ../../source/tutorial-quickstart-mxnet.rst:226 +#: ../../source/tutorial-quickstart-pytorch.rst:203 +#: ../../source/tutorial-quickstart-scikitlearn.rst:157 +#: ../../source/tutorial-quickstart-tensorflow.rst:98 +#: ../../source/tutorial-quickstart-xgboost.rst:309 msgid "Flower Server" msgstr "Serveur de Flower" @@ -3419,11 +3957,12 @@ msgstr "" "peut le voir ci-dessous." #: ../../source/example-walkthrough-pytorch-mnist.rst:89 -#: ../../source/tutorial-quickstart-ios.rst:31 -#: ../../source/tutorial-quickstart-mxnet.rst:31 -#: ../../source/tutorial-quickstart-pytorch.rst:34 -#: ../../source/tutorial-quickstart-scikitlearn.rst:37 -#: ../../source/tutorial-quickstart-tensorflow.rst:26 +#: ../../source/tutorial-quickstart-ios.rst:34 +#: ../../source/tutorial-quickstart-mxnet.rst:36 +#: ../../source/tutorial-quickstart-pytorch.rst:37 +#: ../../source/tutorial-quickstart-scikitlearn.rst:40 +#: ../../source/tutorial-quickstart-tensorflow.rst:29 +#: ../../source/tutorial-quickstart-xgboost.rst:55 msgid "Flower Client" msgstr "Client de la fleur" @@ -3646,8 +4185,9 @@ msgstr "" "des divers cadres de ML avec lesquels Flower est compatible." #: ../../source/explanation-differential-privacy.rst:7 +#, fuzzy msgid "" -"Please note that these components are still experimental, the correct " +"Please note that these components are still experimental; the correct " "configuration of DP for a specific task is still an unsolved problem." msgstr "" "Note que ces composants sont encore expérimentaux, la configuration " @@ -3697,11 +4237,14 @@ msgstr "" "ajouté à la moyenne calculée au niveau du serveur." #: ../../source/explanation-differential-privacy.rst:20 +#, fuzzy msgid "" "The distribution of the update norm has been shown to vary from task-to-" -"task and to evolve as training progresses. Therefore, we use an adaptive " -"approach [andrew]_ that continuously adjusts the clipping threshold to " -"track a prespecified quantile of the update norm distribution." +"task and to evolve as training progresses. This variability is crucial in" +" understanding its impact on differential privacy guarantees, emphasizing" +" the need for an adaptive approach [andrew]_ that continuously adjusts " +"the clipping threshold to track a prespecified quantile of the update " +"norm distribution." msgstr "" "Il a été démontré que la distribution de la norme de mise à jour varie " "d'une tâche à l'autre et évolue au fur et à mesure de la formation. C'est" @@ -3714,9 +4257,10 @@ msgid "Simplifying Assumptions" msgstr "Simplifier les hypothèses" #: ../../source/explanation-differential-privacy.rst:25 +#, fuzzy msgid "" "We make (and attempt to enforce) a number of assumptions that must be " -"satisfied to ensure that the training process actually realises the " +"satisfied to ensure that the training process actually realizes the " ":math:`(\\epsilon, \\delta)` guarantees the user has in mind when " "configuring the setup." msgstr "" @@ -3757,10 +4301,11 @@ msgstr "" "termes, les clients ne peuvent pas abandonner ou échouer." #: ../../source/explanation-differential-privacy.rst:31 +#, fuzzy msgid "" "The first two are useful for eliminating a multitude of complications " -"associated with calibrating the noise to the clipping threshold while the" -" third one is required to comply with the assumptions of the privacy " +"associated with calibrating the noise to the clipping threshold, while " +"the third one is required to comply with the assumptions of the privacy " "analysis." msgstr "" "Les deux premiers sont utiles pour éliminer une multitude de " @@ -3851,9 +4396,10 @@ msgid "Server-side logic" msgstr "Logique côté serveur" #: ../../source/explanation-differential-privacy.rst:51 +#, fuzzy msgid "" "The first version of our solution was to define a decorator whose " -"constructor accepted, among other things, a boolean valued variable " +"constructor accepted, among other things, a boolean-valued variable " "indicating whether adaptive clipping was to be enabled or not. We quickly" " realized that this would clutter its :code:`__init__()` function with " "variables corresponding to hyperparameters of adaptive clipping that " @@ -3878,6 +4424,7 @@ msgstr "" "l'indique, détermine l'endroit où le noising doit être effectué." #: ../../source/explanation-differential-privacy.rst:54 +#: ../../source/ref-api/flwr.server.strategy.DPFedAvgFixed.rst:2 msgid "DPFedAvgFixed" msgstr "DPFedAvgFixed" @@ -3912,6 +4459,7 @@ msgstr "" "client (indiqué sous :code:`dpfedavg_noise_stddev`)." #: ../../source/explanation-differential-privacy.rst:59 +#, fuzzy msgid "" ":code:`aggregate_fit()`: We check whether any of the sampled clients " "dropped out or failed to upload an update before the round timed out. In " @@ -3922,7 +4470,7 @@ msgid "" ":code:`parameters` field of :code:`FitRes` for each received update and " "setting it to 1. Furthermore, if :code:`server_side_noising=true`, each " "update is perturbed with an amount of noise equal to what it would have " -"been subjected to had client-side noising being enabled. This entails " +"been subjected to had client-side noising being enabled. This entails " "*pre*-processing of the arguments to this method before passing them on " "to the wrappee's implementation of :code:`aggregate_fit()`." msgstr "" @@ -3974,6 +4522,7 @@ msgstr "" "clients." #: ../../source/explanation-differential-privacy.rst:67 +#: ../../source/ref-api/flwr.server.strategy.DPFedAvgAdaptive.rst:2 msgid "DPFedAvgAdaptive" msgstr "DPFedAvgAdaptive" @@ -4075,25 +4624,28 @@ msgstr "" "pour un :math:`\\delta` particulier, le script suivant peut être utilisé." #: ../../source/explanation-differential-privacy.rst:98 +#, fuzzy msgid "" -"McMahan, H. Brendan, et al. \"Learning differentially private recurrent " -"language models.\" arXiv preprint arXiv:1710.06963 (2017)." +"McMahan et al. \"Learning Differentially Private Recurrent Language " +"Models.\" International Conference on Learning Representations (ICLR), " +"2017." msgstr "" "McMahan, H. Brendan, et al. \"Learning differentially private recurrent " "language models\", arXiv preprint arXiv:1710.06963 (2017)." #: ../../source/explanation-differential-privacy.rst:100 +#, fuzzy msgid "" -"Andrew, Galen, et al. \"Differentially private learning with adaptive " -"clipping.\" Advances in Neural Information Processing Systems 34 (2021): " -"17455-17466." +"Andrew, Galen, et al. \"Differentially Private Learning with Adaptive " +"Clipping.\" Advances in Neural Information Processing Systems (NeurIPS), " +"2021." msgstr "" "Andrew, Galen, et al. \"Differentially private learning with adaptive " "clipping\" Advances in Neural Information Processing Systems 34 (2021) : " "17455-17466." #: ../../source/explanation-federated-evaluation.rst:2 -#: ../../source/tutorial-what-is-federated-learning.ipynb:292 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:292 msgid "Federated evaluation" msgstr "Évaluation fédérée" @@ -4391,10 +4943,6 @@ msgstr "[Alternative 1]" msgid "\\[Alternative 2\\]" msgstr "[Alternative 2]" -#: ../../source/fed/0000-20200102-fed-template.md:60 -msgid "Appendix" -msgstr "Annexe" - #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:10 msgid "Flower Enhancement Doc" msgstr "Doc sur l'amélioration des fleurs" @@ -5047,22 +5595,24 @@ msgstr "" "configuration différentes à des clients différents." #: ../../source/how-to-configure-clients.rst:89 +#, fuzzy msgid "" "This can be achieved by customizing an existing strategy or by " -"`implementing a custom strategy from scratch `_. Here's a nonsensical example that " -"customizes :code:`FedAvg` by adding a custom ``\"hello\": \"world\"`` " -"configuration key/value pair to the config dict of a *single client* " -"(only the first client in the list, the other clients in this round to " -"not receive this \"special\" config value):" +"`implementing a custom strategy from scratch " +"`_. " +"Here's a nonsensical example that customizes :code:`FedAvg` by adding a " +"custom ``\"hello\": \"world\"`` configuration key/value pair to the " +"config dict of a *single client* (only the first client in the list, the " +"other clients in this round to not receive this \"special\" config " +"value):" msgstr "" "Ceci peut être réalisé en personnalisant une stratégie existante ou en " "`mettant en œuvre une stratégie personnalisée à partir de zéro " -"`_. Voici un " -"exemple absurde qui personnalise :code:`FedAvg` en ajoutant une paire " -"clé/valeur de configuration personnalisée ``\"hello\" : \"world\"`` au " -"config dict d'un *seul client* (uniquement le premier client de la liste," -" les autres clients de cette série ne recevant pas cette valeur de " +"`_. " +"Voici un exemple absurde qui personnalise :code:`FedAvg` en ajoutant une " +"paire clé/valeur de configuration personnalisée ``\"hello\" : \"world\"``" +" au config dict d'un *seul client* (uniquement le premier client de la " +"liste, les autres clients de cette série ne recevant pas cette valeur de " "configuration \"spéciale\") :" #: ../../source/how-to-configure-logging.rst:2 @@ -5111,9 +5661,9 @@ msgid "" msgstr "" "Avec ce qui précède, Flower enregistrera le log que vous voyez sur votre " "terminal dans :code:`log.txt`. Ce fichier sera créé dans le répertoire " -"depuis lequel le code est exécuté. Si nous inspectons nous voyons que le log " -"ci-dessous est également enregistré mais préfixé avec :code:`identifier` sur " -"chaque ligne :" +"depuis lequel le code est exécuté. Si nous inspectons nous voyons que le " +"log ci-dessous est également enregistré mais préfixé avec " +":code:`identifier` sur chaque ligne :" #: ../../source/how-to-configure-logging.rst:74 msgid "Log your own messages" @@ -5239,6 +5789,7 @@ msgstr "" "signés générés à l'aide des scripts qui font partie de ce guide." #: ../../source/how-to-enable-ssl-connections.rst:41 +#: ../../source/ref-api/flwr.server.Server.rst:2 msgid "Server" msgstr "Serveur" @@ -5264,7 +5815,7 @@ msgstr "" #: ../../source/how-to-enable-ssl-connections.rst:65 #: ../../source/how-to-upgrade-to-flower-1.0.rst:37 -#: ../../source/ref-api-flwr.rst:15 +#: ../../source/ref-api/flwr.client.Client.rst:2 msgid "Client" msgstr "Client" @@ -5288,7 +5839,8 @@ msgstr "" "certificats sous forme de chaînes d'octets." #: ../../source/how-to-enable-ssl-connections.rst:89 -#: ../../source/tutorial-what-is-federated-learning.ipynb:287 +#: ../../source/how-to-use-built-in-mods.rst:85 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:287 msgid "Conclusion" msgstr "Conclusion" @@ -5713,7 +6265,11 @@ msgstr "Version Python" msgid "Install stable release" msgstr "Installe la version stable" -#: ../../source/how-to-install-flower.rst:14 +#: ../../source/how-to-install-flower.rst:15 +msgid "Using pip" +msgstr "" + +#: ../../source/how-to-install-flower.rst:17 msgid "" "Stable releases are available on `PyPI " "`_::" @@ -5721,7 +6277,7 @@ msgstr "" "Les versions stables sont disponibles sur `PyPI " "`_: :" -#: ../../source/how-to-install-flower.rst:18 +#: ../../source/how-to-install-flower.rst:21 msgid "" "For simulations that use the Virtual Client Engine, ``flwr`` should be " "installed with the ``simulation`` extra::" @@ -5729,13 +6285,38 @@ msgstr "" "Pour les simulations qui utilisent le moteur de client virtuel, ``flwr`` " "doit être installé avec l'option ``simulation``: :" -#: ../../source/how-to-install-flower.rst:24 +#: ../../source/how-to-install-flower.rst:27 +msgid "Using conda (or mamba)" +msgstr "" + +#: ../../source/how-to-install-flower.rst:29 +msgid "Flower can also be installed from the ``conda-forge`` channel." +msgstr "" + +#: ../../source/how-to-install-flower.rst:31 +msgid "" +"If you have not added ``conda-forge`` to your channels, you will first " +"need to run the following::" +msgstr "" + +#: ../../source/how-to-install-flower.rst:36 +msgid "" +"Once the ``conda-forge`` channel has been enabled, ``flwr`` can be " +"installed with ``conda``::" +msgstr "" + +#: ../../source/how-to-install-flower.rst:40 +msgid "or with ``mamba``::" +msgstr "" + +#: ../../source/how-to-install-flower.rst:46 msgid "Verify installation" msgstr "Vérifie l'installation" -#: ../../source/how-to-install-flower.rst:26 +#: ../../source/how-to-install-flower.rst:48 +#, fuzzy msgid "" -"The following command can be used to verfiy if Flower was successfully " +"The following command can be used to verify if Flower was successfully " "installed. If everything worked, it should print the version of Flower to" " the command line::" msgstr "" @@ -5743,15 +6324,26 @@ msgstr "" "installé avec succès. Si tout a fonctionné, la version de Flower devrait " "être imprimée sur la ligne de commande: :" -#: ../../source/how-to-install-flower.rst:33 +#: ../../source/how-to-install-flower.rst:55 msgid "Advanced installation options" msgstr "Options d'installation avancées" -#: ../../source/how-to-install-flower.rst:36 +#: ../../source/how-to-install-flower.rst:58 +#, fuzzy +msgid "Install via Docker" +msgstr "Installer Flower" + +#: ../../source/how-to-install-flower.rst:60 +msgid "" +"`How to run Flower using Docker `_" +msgstr "" + +#: ../../source/how-to-install-flower.rst:63 msgid "Install pre-release" msgstr "Installer la version pre-release" -#: ../../source/how-to-install-flower.rst:38 +#: ../../source/how-to-install-flower.rst:65 msgid "" "New (possibly unstable) versions of Flower are sometimes available as " "pre-release versions (alpha, beta, release candidate) before the stable " @@ -5761,7 +6353,7 @@ msgstr "" "disponibles en tant que versions préliminaires (alpha, bêta, release " "candidate) avant que la version stable n'arrive : :" -#: ../../source/how-to-install-flower.rst:42 +#: ../../source/how-to-install-flower.rst:69 msgid "" "For simulations that use the Virtual Client Engine, ``flwr`` pre-releases" " should be installed with the ``simulation`` extra::" @@ -5770,11 +6362,11 @@ msgstr "" "versions de ``flwr`` doivent être installées avec l'option " "``simulation``: :" -#: ../../source/how-to-install-flower.rst:47 +#: ../../source/how-to-install-flower.rst:74 msgid "Install nightly release" msgstr "Installer la version nightly" -#: ../../source/how-to-install-flower.rst:49 +#: ../../source/how-to-install-flower.rst:76 msgid "" "The latest (potentially unstable) changes in Flower are available as " "nightly releases::" @@ -5782,7 +6374,7 @@ msgstr "" "Les dernières modifications (potentiellement instables) de Flower sont " "disponibles sous forme de versions nocturnes: :" -#: ../../source/how-to-install-flower.rst:53 +#: ../../source/how-to-install-flower.rst:80 msgid "" "For simulations that use the Virtual Client Engine, ``flwr-nightly`` " "should be installed with the ``simulation`` extra::" @@ -6112,42 +6704,225 @@ msgstr "" "Ray Metrics : ``_" -#: ../../source/how-to-run-simulations.rst:2 -#, fuzzy -msgid "Run simulations" -msgstr "Simulation de moniteur" +#: ../../source/how-to-run-flower-using-docker.rst:2 +msgid "Run Flower using Docker" +msgstr "" -#: ../../source/how-to-run-simulations.rst:8 +#: ../../source/how-to-run-flower-using-docker.rst:4 msgid "" -"Simulating Federated Learning workloads is useful for a multitude of use-" -"cases: you might want to run your workload on a large cohort of clients " -"but without having to source, configure and mange a large number of " -"physical devices; you might want to run your FL workloads as fast as " -"possible on the compute systems you have access to without having to go " -"through a complex setup process; you might want to validate your " -"algorithm on different scenarios at varying levels of data and system " -"heterogeneity, client availability, privacy budgets, etc. These are among" -" some of the use-cases where simulating FL workloads makes sense. Flower " -"can accommodate these scenarios by means of its `VirtualClientEngine " -"`_ or " -"VCE." +"The simplest way to get started with Flower is by using the pre-made " +"Docker images, which you can find on `Docker Hub " +"`_." msgstr "" -#: ../../source/how-to-run-simulations.rst:10 +#: ../../source/how-to-run-flower-using-docker.rst:7 +msgid "Before you start, make sure that the Docker daemon is running:" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:14 msgid "" -"The :code:`VirtualClientEngine` schedules, launches and manages `virtual`" -" clients. These clients are identical to `non-virtual` clients (i.e. the " -"ones you launch via the command `flwr.client.start_client `_) in the sense that they can be configure " -"by creating a class inheriting, for example, from " -"`flwr.client.NumPyClient `_ " -"and therefore behave in an identical way. In addition to that, clients " -"managed by the :code:`VirtualClientEngine` are:" +"If you do not see the version of Docker but instead get an error saying " +"that the command was not found, you will need to install Docker first. " +"You can find installation instruction `here `_." msgstr "" -#: ../../source/how-to-run-simulations.rst:12 +#: ../../source/how-to-run-flower-using-docker.rst:20 msgid "" -"resource-aware: this means that each client gets assigned a portion of " +"On Linux, Docker commands require ``sudo`` privilege. If you want to " +"avoid using ``sudo``, you can follow the `Post-installation steps " +"`_ on the " +"official Docker website." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:25 +#, fuzzy +msgid "Flower server" +msgstr "Serveur de Flower" + +#: ../../source/how-to-run-flower-using-docker.rst:28 +#, fuzzy +msgid "Quickstart" +msgstr "Démarrage rapide de JAX" + +#: ../../source/how-to-run-flower-using-docker.rst:30 +msgid "If you're looking to try out Flower, you can use the following command:" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:37 +msgid "" +"The command will pull the Docker image with the tag " +"``1.7.0-py3.11-ubuntu22.04`` from Docker Hub. The tag contains the " +"information which Flower, Python and Ubuntu is used. In this case, it " +"uses Flower 1.7.0, Python 3.11 and Ubuntu 22.04. The ``--rm`` flag tells " +"Docker to remove the container after it exits." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:44 +msgid "" +"By default, the Flower server keeps state in-memory. When using the " +"Docker flag ``--rm``, the state is not persisted between container " +"starts. We will show below how to save the state in a file on your host " +"system." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:48 +msgid "" +"The ``-p :`` flag tells Docker to map the ports " +"``9091``/``9092`` of the host to ``9091``/``9092`` of the container, " +"allowing you to access the Driver API on ``http://localhost:9091`` and " +"the Fleet API on ``http://localhost:9092``. Lastly, any flag that comes " +"after the tag is passed to the Flower server. Here, we are passing the " +"flag ``--insecure``." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:55 +msgid "" +"The ``--insecure`` flag enables insecure communication (using HTTP, not " +"HTTPS) and should only be used for testing purposes. We strongly " +"recommend enabling `SSL `_ when " +"deploying to a production environment." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:60 +msgid "" +"You can use ``--help`` to view all available flags that the server " +"supports:" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:67 +msgid "Mounting a volume to store the state on the host system" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:69 +msgid "" +"If you want to persist the state of the server on your host system, all " +"you need to do is specify a path where you want to save the file on your " +"host system and a name for the database file. In the example below, we " +"tell Docker via the flag ``-v`` to mount the user's home directory " +"(``~/`` on your host) into the ``/app/`` directory of the container. " +"Furthermore, we use the flag ``--database`` to specify the name of the " +"database file." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:82 +msgid "" +"As soon as the server starts, the file ``state.db`` is created in the " +"user's home directory on your host system. If the file already exists, " +"the server tries to restore the state from the file. To start the server " +"with an empty database, simply remove the ``state.db`` file." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:87 +#, fuzzy +msgid "Enabling SSL for secure connections" +msgstr "Collecte centralisée des données" + +#: ../../source/how-to-run-flower-using-docker.rst:89 +msgid "" +"To enable SSL, you will need a CA certificate, a server certificate and a" +" server private key." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:92 +msgid "" +"For testing purposes, you can generate your own self-signed certificates." +" The `Enable SSL connections `_ page contains a section that " +"will guide you through the process." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:96 +msgid "" +"Assuming all files we need are in the local ``certificates`` directory, " +"we can use the flag ``-v`` to mount the local directory into the " +"``/app/`` directory of the container. This allows the server to access " +"the files within the container. Finally, we pass the names of the " +"certificates to the server with the ``--certificates`` flag." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:108 +msgid "Using a different Flower or Python version" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:110 +msgid "" +"If you want to use a different version of Flower or Python, you can do so" +" by changing the tag. All versions we provide are available on `Docker " +"Hub `_." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:114 +msgid "Pinning a Docker image to a specific version" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:116 +msgid "" +"It may happen that we update the images behind the tags. Such updates " +"usually include security updates of system dependencies that should not " +"change the functionality of Flower. However, if you want to ensure that " +"you always use the same image, you can specify the hash of the image " +"instead of the tag." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:121 +msgid "" +"The following command returns the current image hash referenced by the " +"``server:1.7.0-py3.11-ubuntu22.04`` tag:" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:128 +msgid "Next, we can pin the hash when running a new server container:" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:137 +#, fuzzy +msgid "Setting environment variables" +msgstr "Mise en place de l'environnement de codage" + +#: ../../source/how-to-run-flower-using-docker.rst:139 +msgid "" +"To set a variable inside a Docker container, you can use the ``-e " +"=`` flag." +msgstr "" + +#: ../../source/how-to-run-simulations.rst:2 +#, fuzzy +msgid "Run simulations" +msgstr "Simulation de moniteur" + +#: ../../source/how-to-run-simulations.rst:8 +msgid "" +"Simulating Federated Learning workloads is useful for a multitude of use-" +"cases: you might want to run your workload on a large cohort of clients " +"but without having to source, configure and mange a large number of " +"physical devices; you might want to run your FL workloads as fast as " +"possible on the compute systems you have access to without having to go " +"through a complex setup process; you might want to validate your " +"algorithm on different scenarios at varying levels of data and system " +"heterogeneity, client availability, privacy budgets, etc. These are among" +" some of the use-cases where simulating FL workloads makes sense. Flower " +"can accommodate these scenarios by means of its `VirtualClientEngine " +"`_ or " +"VCE." +msgstr "" + +#: ../../source/how-to-run-simulations.rst:10 +msgid "" +"The :code:`VirtualClientEngine` schedules, launches and manages `virtual`" +" clients. These clients are identical to `non-virtual` clients (i.e. the " +"ones you launch via the command `flwr.client.start_client `_) in the sense that they can be configure by " +"creating a class inheriting, for example, from `flwr.client.NumPyClient " +"`_ and therefore behave in an " +"identical way. In addition to that, clients managed by the " +":code:`VirtualClientEngine` are:" +msgstr "" + +#: ../../source/how-to-run-simulations.rst:12 +msgid "" +"resource-aware: this means that each client gets assigned a portion of " "the compute and memory on your system. You as a user can control this at " "the beginning of the simulation and allows you to control the degree of " "parallelism of your Flower FL simulation. The fewer the resources per " @@ -6600,6 +7375,12 @@ msgstr "" "à ton code. Note que cela va itérer sur tous les points de contrôle " "sauvegardés et charger le plus récent :" +#: ../../source/how-to-save-and-load-model-checkpoints.rst:97 +msgid "" +"Return/use this object of type ``Parameters`` wherever necessary, such as" +" in the ``initial_parameters`` when defining a ``Strategy``." +msgstr "" + #: ../../source/how-to-upgrade-to-flower-1.0.rst:2 msgid "Upgrade to Flower 1.0" msgstr "Passe à Flower 1.0" @@ -6950,6 +7731,126 @@ msgstr "" "Flower `_ et utilise le canal " "``#questions``." +#: ../../source/how-to-use-built-in-mods.rst:2 +msgid "Use Built-in Mods" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:4 +msgid "" +"**Note: This tutorial covers experimental features. The functionality and" +" interfaces may change in future versions.**" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:6 +msgid "" +"In this tutorial, we will learn how to utilize built-in mods to augment " +"the behavior of a ``ClientApp``. Mods (sometimes also called Modifiers) " +"allow us to perform operations before and after a task is processed in " +"the ``ClientApp``." +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:9 +msgid "What are Mods?" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:11 +msgid "" +"A Mod is a callable that wraps around a ``ClientApp``. It can manipulate " +"or inspect the incoming ``Message`` and the resulting outgoing " +"``Message``. The signature for a ``Mod`` is as follows:" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:18 +msgid "A typical mod function might look something like this:" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:31 +msgid "Using Mods" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:33 +msgid "To use mods in your ``ClientApp``, you can follow these steps:" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:36 +msgid "1. Import the required mods" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:38 +msgid "First, import the built-in mod you intend to use:" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:46 +msgid "2. Define your client function" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:48 +msgid "" +"Define your client function (``client_fn``) that will be wrapped by the " +"mod(s):" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:57 +msgid "3. Create the ``ClientApp`` with mods" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:59 +msgid "" +"Create your ``ClientApp`` and pass the mods as a list to the ``mods`` " +"argument. The order in which you provide the mods matters:" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:72 +#, fuzzy +msgid "Order of execution" +msgstr "Dépréciations" + +#: ../../source/how-to-use-built-in-mods.rst:74 +msgid "" +"When the ``ClientApp`` runs, the mods are executed in the order they are " +"provided in the list:" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:76 +msgid "``example_mod_1`` (outermost mod)" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:77 +msgid "``example_mod_2`` (next mod)" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:78 +msgid "" +"Message handler (core function that handles the incoming ``Message`` and " +"returns the outgoing ``Message``)" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:79 +msgid "``example_mod_2`` (on the way back)" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:80 +msgid "``example_mod_1`` (outermost mod on the way back)" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:82 +msgid "" +"Each mod has a chance to inspect and modify the incoming ``Message`` " +"before passing it to the next mod, and likewise with the outgoing " +"``Message`` before returning it up the stack." +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:87 +msgid "" +"By following this guide, you have learned how to effectively use mods to " +"enhance your ``ClientApp``'s functionality. Remember that the order of " +"mods is crucial and affects how the input and output are processed." +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:89 +msgid "Enjoy building more robust and flexible ``ClientApp``s with mods!" +msgstr "" + #: ../../source/how-to-use-strategies.rst:2 #, fuzzy msgid "Use strategies" @@ -7080,70 +7981,77 @@ msgstr "" "d'évaluation à :code:`evaluate_fn`." #: ../../source/how-to-use-strategies.rst:89 +#, fuzzy msgid "" "Writing a fully custom strategy is a bit more involved, but it provides " -"the most flexibility. Read the `Implementing Strategies `_ guide to learn more." +"the most flexibility. Read the `Implementing Strategies `_ guide to learn more." msgstr "" "L'écriture d'une stratégie entièrement personnalisée est un peu plus " "complexe, mais c'est celle qui offre le plus de souplesse. Lis le guide " -"`Implémentation des stratégies `_ pour en " -"savoir plus." +"`Implémentation des stratégies `_ pour " +"en savoir plus." -#: ../../source/index.rst:31 +#: ../../source/index.rst:34 msgid "Tutorial" msgstr "Tutoriel" -#: ../../source/index.rst:41 +#: ../../source/index.rst:44 msgid "Quickstart tutorials" msgstr "Quickstart tutorials" -#: ../../source/index.rst:74 ../../source/index.rst:78 +#: ../../source/index.rst:75 ../../source/index.rst:79 msgid "How-to guides" msgstr "Guides" -#: ../../source/index.rst:94 +#: ../../source/index.rst:97 msgid "Legacy example guides" msgstr "" -#: ../../source/index.rst:105 ../../source/index.rst:109 +#: ../../source/index.rst:108 ../../source/index.rst:112 msgid "Explanations" msgstr "Explications" -#: ../../source/index.rst:121 +#: None:-1 msgid "API reference" msgstr "Référence pour l'API" -#: ../../source/index.rst:128 +#: ../../source/index.rst:137 msgid "Reference docs" msgstr "Référence pour la documentation" -#: ../../source/index.rst:144 +#: ../../source/index.rst:153 #, fuzzy msgid "Contributor tutorials" msgstr "Configuration du contributeur" -#: ../../source/index.rst:151 +#: ../../source/index.rst:160 #, fuzzy msgid "Contributor how-to guides" msgstr "Guide pour les contributeurs" -#: ../../source/index.rst:162 +#: ../../source/index.rst:173 #, fuzzy msgid "Contributor explanations" msgstr "Explications" -#: ../../source/index.rst:168 +#: ../../source/index.rst:179 #, fuzzy msgid "Contributor references" msgstr "Configuration du contributeur" +#: ../../source/index.rst:-1 +msgid "" +"Check out the documentation of the main Flower Framework enabling easy " +"Python development for Federated Learning." +msgstr "" + #: ../../source/index.rst:2 #, fuzzy msgid "Flower Framework Documentation" msgstr "Rédiger de la documentation" -#: ../../source/index.rst:4 +#: ../../source/index.rst:7 msgid "" "Welcome to Flower's documentation. `Flower `_ is a " "friendly federated learning framework." @@ -7151,11 +8059,11 @@ msgstr "" "Bienvenue sur la documentation de Flower. `Flower `_ " "est un framework de federated learning convivial et facile à utiliser." -#: ../../source/index.rst:8 +#: ../../source/index.rst:11 msgid "Join the Flower Community" msgstr "Rejoignez la communauté de Flower" -#: ../../source/index.rst:10 +#: ../../source/index.rst:13 msgid "" "The Flower Community is growing quickly - we're a friendly group of " "researchers, engineers, students, professionals, academics, and other " @@ -7165,15 +8073,15 @@ msgstr "" " chercheurs, ingénieurs, étudiants, professionnels, académiques, et " "autres hobbyistes." -#: ../../source/index.rst:12 +#: ../../source/index.rst:15 msgid "Join us on Slack" msgstr "Join us on Slack" -#: ../../source/index.rst:20 +#: ../../source/index.rst:23 msgid "Flower Framework" msgstr "Flower Framework" -#: ../../source/index.rst:22 +#: ../../source/index.rst:25 msgid "" "The user guide is targeted at researchers and developers who want to use " "Flower to bring existing machine learning workloads into a federated " @@ -7185,11 +8093,11 @@ msgstr "" " existantes dans un scenario fédéré. Un des buts de Flower est de rendre " "cela le plus evident possible. Lisez la suite pour en apprendre plus." -#: ../../source/index.rst:27 +#: ../../source/index.rst:30 msgid "Tutorials" msgstr "Tutoriels" -#: ../../source/index.rst:29 +#: ../../source/index.rst:32 msgid "" "A learning-oriented series of federated learning tutorials, the best " "place to start." @@ -7197,7 +8105,7 @@ msgstr "" "Une serie de tutoriels de Federated Learning, l'endroit parfait pour " "débuter." -#: ../../source/index.rst:59 +#: ../../source/index.rst:62 #, fuzzy msgid "" "QUICKSTART TUTORIALS: :doc:`PyTorch ` | " @@ -7219,17 +8127,16 @@ msgstr "" "` | :ref:`Android ` | :ref:`iOS " "`" -#: ../../source/index.rst:63 -#, fuzzy -msgid "PyTorch" -msgstr "Exemples de PyTorch" +#: ../../source/index.rst:64 +msgid "We also made video tutorials for PyTorch:" +msgstr "" -#: ../../source/index.rst:68 +#: ../../source/index.rst:69 #, fuzzy -msgid "TensorFlow" +msgid "And TensorFlow:" msgstr "Exemples de TensorFlow" -#: ../../source/index.rst:76 +#: ../../source/index.rst:77 msgid "" "Problem-oriented how-to guides show step-by-step how to achieve a " "specific goal." @@ -7237,7 +8144,7 @@ msgstr "" "Guides orientés sur la résolutions étapes par étapes de problèmes ou " "objectifs specifiques." -#: ../../source/index.rst:107 +#: ../../source/index.rst:110 msgid "" "Understanding-oriented concept guides explain and discuss key topics and " "underlying ideas behind Flower and collaborative AI." @@ -7245,21 +8152,29 @@ msgstr "" "Guides orientés sur la compréhension et l'explication des sujets et idées" " de fonds sur lesquels sont construits Flower et l'IA collaborative." -#: ../../source/index.rst:117 +#: ../../source/index.rst:120 #, fuzzy msgid "References" msgstr "Référence" -#: ../../source/index.rst:119 +#: ../../source/index.rst:122 msgid "Information-oriented API reference and other reference material." msgstr "Référence de l'API orientée sur l'information pure." -#: ../../source/index.rst:139 +#: ../../source/index.rst:131::1 +msgid ":py:obj:`flwr `\\" +msgstr "" + +#: ../../source/index.rst:131::1 flwr:1 of +msgid "Flower main package." +msgstr "" + +#: ../../source/index.rst:148 #, fuzzy msgid "Contributor docs" msgstr "Configuration du contributeur" -#: ../../source/index.rst:141 +#: ../../source/index.rst:150 #, fuzzy msgid "" "The Flower community welcomes contributions. The following docs are " @@ -7286,7459 +8201,13204 @@ msgstr "flower-driver-api" msgid "flower-fleet-api" msgstr "flower-fleet-api" -#: ../../source/ref-api-flwr.rst:2 +#: ../../source/ref-api/flwr.rst:2 #, fuzzy -msgid "flwr (Python API reference)" -msgstr "Référence pour l'API" +msgid "flwr" +msgstr "Fleur" -#: ../../source/ref-api-flwr.rst:8 -msgid "client" -msgstr "client" +#: ../../source/ref-api/flwr.rst:25 ../../source/ref-api/flwr.server.rst:48 +msgid "Modules" +msgstr "" -#: ../../source/ref-api-flwr.rst:24 -msgid "start_client" -msgstr "start_client" +#: ../../source/ref-api/flwr.rst:35::1 +msgid ":py:obj:`flwr.client `\\" +msgstr "" -#: ../../source/ref-api-flwr.rst:32 -msgid "NumPyClient" -msgstr "NumPyClient" +#: ../../source/ref-api/flwr.rst:35::1 flwr.client:1 of +#, fuzzy +msgid "Flower client." +msgstr "Client de Flower" -#: ../../source/ref-api-flwr.rst:41 -msgid "start_numpy_client" -msgstr "start_numpy_client" +#: ../../source/ref-api/flwr.rst:35::1 +msgid ":py:obj:`flwr.common `\\" +msgstr "" -#: ../../source/ref-api-flwr.rst:49 -msgid "start_simulation" -msgstr "démarrer_simulation" +#: ../../source/ref-api/flwr.rst:35::1 flwr.common:1 of +msgid "Common components shared between server and client." +msgstr "Composants communs partagés entre le serveur et le client." -#: ../../source/ref-api-flwr.rst:57 -msgid "server" -msgstr "serveur" +#: ../../source/ref-api/flwr.rst:35::1 +msgid ":py:obj:`flwr.server `\\" +msgstr "" -#: ../../source/ref-api-flwr.rst:65 -msgid "server.start_server" -msgstr "serveur.start_server" +#: ../../source/ref-api/flwr.rst:35::1 +#: ../../source/ref-api/flwr.server.rst:37::1 flwr.server:1 +#: flwr.server.server.Server:1 of +#, fuzzy +msgid "Flower server." +msgstr "Serveur de Flower" -#: ../../source/ref-api-flwr.rst:73 -msgid "server.strategy" -msgstr "stratégie.du.serveur" +#: ../../source/ref-api/flwr.rst:35::1 +msgid ":py:obj:`flwr.simulation `\\" +msgstr "" -#: ../../source/ref-api-flwr.rst:81 -msgid "server.strategy.Strategy" -msgstr "serveur.stratégie.Stratégie" +#: ../../source/ref-api/flwr.rst:35::1 flwr.simulation:1 of +#, fuzzy +msgid "Flower simulation." +msgstr "Simulation de moniteur" -#: ../../source/ref-api-flwr.rst:90 -msgid "server.strategy.FedAvg" -msgstr "serveur.stratégie.FedAvg" +#: ../../source/ref-api/flwr.client.rst:2 +msgid "client" +msgstr "client" -#: ../../source/ref-api-flwr.rst:101 -msgid "server.strategy.FedAvgM" -msgstr "stratégie.serveur.FedAvgM" +#: ../../source/ref-api/flwr.client.rst:13 +#: ../../source/ref-api/flwr.common.rst:13 +#: ../../source/ref-api/flwr.server.driver.rst:13 +#: ../../source/ref-api/flwr.server.rst:13 +#: ../../source/ref-api/flwr.simulation.rst:13 +#, fuzzy +msgid "Functions" +msgstr "Les quatre fonctions :" -#: ../../source/ref-api-flwr.rst:112 -msgid "server.strategy.QFedAvg" -msgstr "server.strategy.QFedAvg" +#: ../../source/ref-api/flwr.client.rst:24::1 +msgid ":py:obj:`run_client_app `\\ \\(\\)" +msgstr "" -#: ../../source/ref-api-flwr.rst:123 -msgid "server.strategy.FaultTolerantFedAvg" -msgstr "server.strategy.FaultTolerantFedAvg" +#: ../../source/ref-api/flwr.client.rst:24::1 +#: flwr.client.app.run_client_app:1 of +#, fuzzy +msgid "Run Flower client app." +msgstr "Client de Flower" -#: ../../source/ref-api-flwr.rst:134 -msgid "server.strategy.FedOpt" -msgstr "serveur.stratégie.FedOpt" +#: ../../source/ref-api/flwr.client.rst:24::1 +msgid "" +":py:obj:`start_client `\\ \\(\\*\\, " +"server\\_address\\[\\, client\\_fn\\, ...\\]\\)" +msgstr "" -#: ../../source/ref-api-flwr.rst:145 -msgid "server.strategy.FedProx" -msgstr "serveur.stratégie.FedProx" +#: ../../source/ref-api/flwr.client.rst:24::1 +#: flwr.client.app.start_client:1 of +msgid "Start a Flower client node which connects to a Flower server." +msgstr "" -#: ../../source/ref-api-flwr.rst:156 -msgid "server.strategy.FedAdagrad" -msgstr "serveur.stratégie.FedAdagrad" +#: ../../source/ref-api/flwr.client.rst:24::1 +msgid "" +":py:obj:`start_numpy_client `\\ \\(\\*\\," +" server\\_address\\, client\\)" +msgstr "" -#: ../../source/ref-api-flwr.rst:167 -msgid "server.strategy.FedAdam" -msgstr "serveur.stratégie.FedAdam" +#: ../../source/ref-api/flwr.client.rst:24::1 +#: flwr.client.app.start_numpy_client:1 of +msgid "Start a Flower NumPyClient which connects to a gRPC server." +msgstr "" -#: ../../source/ref-api-flwr.rst:178 -msgid "server.strategy.FedYogi" -msgstr "serveur.stratégie.FedYogi" +#: ../../source/ref-api/flwr.client.rst:26 +#: ../../source/ref-api/flwr.common.rst:31 +#: ../../source/ref-api/flwr.server.driver.rst:24 +#: ../../source/ref-api/flwr.server.rst:28 +#: ../../source/ref-api/flwr.server.strategy.rst:17 +msgid "Classes" +msgstr "" -#: ../../source/ref-api-flwr.rst:186 -msgid "common" -msgstr "commun" +#: ../../source/ref-api/flwr.client.rst:33::1 +msgid ":py:obj:`Client `\\ \\(\\)" +msgstr "" -#: flwr.common:1 of -msgid "Common components shared between server and client." -msgstr "Composants communs partagés entre le serveur et le client." +#: ../../source/ref-api/flwr.client.rst:33::1 +#: flwr.client.client.Client:1 of +msgid "Abstract base class for Flower clients." +msgstr "" -#: flwr.common.typing.ClientMessage:1 of -msgid "ClientMessage is a container used to hold one result message." +#: ../../source/ref-api/flwr.client.rst:33::1 +msgid "" +":py:obj:`ClientApp `\\ \\(client\\_fn\\[\\, " +"mods\\]\\)" msgstr "" -"ClientMessage est un conteneur utilisé pour contenir un message de " -"résultat." -#: flwr.common.typing.Code:1 of -msgid "Client status codes." -msgstr "Codes d'état du client." +#: ../../source/ref-api/flwr.client.rst:33::1 +#: flwr.client.clientapp.ClientApp:1 of +#, fuzzy +msgid "Flower ClientApp." +msgstr "Client de Flower" -#: flwr.common.typing.DisconnectRes:1 of -msgid "DisconnectRes message from client to server." -msgstr "Message DisconnectRes envoyé par le client au serveur." +#: ../../source/ref-api/flwr.client.rst:33::1 +msgid ":py:obj:`NumPyClient `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.rst:33::1 +#: flwr.client.numpy_client.NumPyClient:1 of +msgid "Abstract base class for Flower clients using NumPy." +msgstr "" + +#: flwr.client.client.Client:1 flwr.client.numpy_client.NumPyClient:1 +#: flwr.server.client_manager.ClientManager:1 +#: flwr.server.strategy.strategy.Strategy:1 of +msgid "Bases: :py:class:`~abc.ABC`" +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:15 +#: ../../source/ref-api/flwr.client.ClientApp.rst:15 +#: ../../source/ref-api/flwr.client.NumPyClient.rst:15 +#: ../../source/ref-api/flwr.common.ClientMessage.rst:15 +#: ../../source/ref-api/flwr.common.DisconnectRes.rst:15 +#: ../../source/ref-api/flwr.common.EvaluateIns.rst:15 +#: ../../source/ref-api/flwr.common.EvaluateRes.rst:15 +#: ../../source/ref-api/flwr.common.FitIns.rst:15 +#: ../../source/ref-api/flwr.common.FitRes.rst:15 +#: ../../source/ref-api/flwr.common.GetParametersIns.rst:15 +#: ../../source/ref-api/flwr.common.GetParametersRes.rst:15 +#: ../../source/ref-api/flwr.common.GetPropertiesIns.rst:15 +#: ../../source/ref-api/flwr.common.GetPropertiesRes.rst:15 +#: ../../source/ref-api/flwr.common.Parameters.rst:15 +#: ../../source/ref-api/flwr.common.ReconnectIns.rst:15 +#: ../../source/ref-api/flwr.common.ServerMessage.rst:15 +#: ../../source/ref-api/flwr.common.Status.rst:15 +#: ../../source/ref-api/flwr.server.ClientManager.rst:15 +#: ../../source/ref-api/flwr.server.History.rst:15 +#: ../../source/ref-api/flwr.server.Server.rst:15 +#: ../../source/ref-api/flwr.server.ServerConfig.rst:15 +#: ../../source/ref-api/flwr.server.SimpleClientManager.rst:15 +#: ../../source/ref-api/flwr.server.driver.Driver.rst:15 +#: ../../source/ref-api/flwr.server.driver.GrpcDriver.rst:15 +#: ../../source/ref-api/flwr.server.strategy.Bulyan.rst:15 +#: ../../source/ref-api/flwr.server.strategy.DPFedAvgAdaptive.rst:15 +#: ../../source/ref-api/flwr.server.strategy.DPFedAvgFixed.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FaultTolerantFedAvg.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedAdagrad.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedAdam.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedAvg.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedAvgAndroid.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedAvgM.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedMedian.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedOpt.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedProx.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedTrimmedAvg.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedXgbBagging.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedXgbCyclic.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedXgbNnAvg.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedYogi.rst:15 +#: ../../source/ref-api/flwr.server.strategy.Krum.rst:15 +#: ../../source/ref-api/flwr.server.strategy.QFedAvg.rst:15 +#: ../../source/ref-api/flwr.server.strategy.Strategy.rst:15 +msgid "Methods" +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +msgid ":py:obj:`evaluate `\\ \\(ins\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +#: flwr.client.client.Client.evaluate:1 +#: flwr.client.numpy_client.NumPyClient.evaluate:1 of +#, fuzzy +msgid "Evaluate the provided parameters using the locally held dataset." +msgstr "évaluer le modèle mis à jour sur l'ensemble de test local" -#: flwr.common.typing.EvaluateIns:1 of -msgid "Evaluate instructions for a client." -msgstr "Évaluer les instructions pour un client." +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +msgid ":py:obj:`fit `\\ \\(ins\\)" +msgstr "" -#: flwr.common.typing.EvaluateRes:1 of -msgid "Evaluate response from a client." -msgstr "Évaluer la réponse d'un client." +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +#: flwr.client.client.Client.fit:1 of +msgid "Refine the provided parameters using the locally held dataset." +msgstr "" -#: flwr.common.telemetry.EventType:1 of -msgid "Types of telemetry events." -msgstr "Types d'événements télémétriques." +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +msgid ":py:obj:`get_context `\\ \\(\\)" +msgstr "" -#: flwr.common.typing.FitIns:1 of -msgid "Fit instructions for a client." -msgstr "Instructions d'ajustement pour un client." +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +#: flwr.client.client.Client.get_context:1 +#: flwr.client.numpy_client.NumPyClient.get_context:1 of +#, fuzzy +msgid "Get the run context from this client." +msgstr "Évaluer la réponse d'un client." -#: flwr.common.typing.FitRes:1 of -msgid "Fit response from a client." -msgstr "Réponse adaptée d'un client." +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +msgid ":py:obj:`get_parameters `\\ \\(ins\\)" +msgstr "" -#: flwr.common.typing.GetParametersIns:1 of -msgid "Parameters request for a client." -msgstr "Demande de paramètres pour un client." - -#: flwr.common.typing.GetParametersRes:1 of -msgid "Response when asked to return parameters." -msgstr "Réponse lorsqu'on te demande de renvoyer des paramètres." - -#: flwr.common.typing.GetPropertiesIns:1 of -msgid "Properties request for a client." -msgstr "Demande de propriétés pour un client." - -#: flwr.common.typing.GetPropertiesRes:1 of -msgid "Properties response from a client." -msgstr "Réponse des propriétés d'un client." +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +#: flwr.client.client.Client.get_parameters:1 +#: flwr.client.numpy_client.NumPyClient.get_parameters:1 of +#, fuzzy +msgid "Return the current local model parameters." +msgstr "``get_parameters`` : renvoie les paramètres du modèle local actuel" -#: flwr.common.typing.Parameters:1 of -msgid "Model parameters." +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +msgid ":py:obj:`get_properties `\\ \\(ins\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +#: flwr.client.client.Client.get_properties:1 of +msgid "Return set of client's properties." +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +msgid ":py:obj:`set_context `\\ \\(context\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +#: flwr.client.client.Client.set_context:1 +#: flwr.client.numpy_client.NumPyClient.set_context:1 of +msgid "Apply a run context to this client." +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +msgid ":py:obj:`to_client `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +#: flwr.client.client.Client.to_client:1 of +msgid "Return client (itself)." +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:46 +#: ../../source/ref-api/flwr.client.NumPyClient.rst:46 +#: ../../source/ref-api/flwr.common.ClientMessage.rst:25 +#: ../../source/ref-api/flwr.common.Code.rst:19 +#: ../../source/ref-api/flwr.common.DisconnectRes.rst:25 +#: ../../source/ref-api/flwr.common.EvaluateIns.rst:25 +#: ../../source/ref-api/flwr.common.EvaluateRes.rst:25 +#: ../../source/ref-api/flwr.common.EventType.rst:19 +#: ../../source/ref-api/flwr.common.FitIns.rst:25 +#: ../../source/ref-api/flwr.common.FitRes.rst:25 +#: ../../source/ref-api/flwr.common.GetParametersIns.rst:25 +#: ../../source/ref-api/flwr.common.GetParametersRes.rst:25 +#: ../../source/ref-api/flwr.common.GetPropertiesIns.rst:25 +#: ../../source/ref-api/flwr.common.GetPropertiesRes.rst:25 +#: ../../source/ref-api/flwr.common.Parameters.rst:25 +#: ../../source/ref-api/flwr.common.ReconnectIns.rst:25 +#: ../../source/ref-api/flwr.common.ServerMessage.rst:25 +#: ../../source/ref-api/flwr.common.Status.rst:25 +#: ../../source/ref-api/flwr.server.ServerConfig.rst:25 +msgid "Attributes" +msgstr "" + +#: flwr.client.client.Client.evaluate:1::1 of +msgid ":py:obj:`context `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.Parameters.rst:2 +#: flwr.client.app.start_client flwr.client.app.start_numpy_client +#: flwr.client.client.Client.evaluate flwr.client.client.Client.fit +#: flwr.client.client.Client.get_parameters +#: flwr.client.client.Client.get_properties +#: flwr.client.numpy_client.NumPyClient.evaluate +#: flwr.client.numpy_client.NumPyClient.fit +#: flwr.client.numpy_client.NumPyClient.get_parameters +#: flwr.client.numpy_client.NumPyClient.get_properties +#: flwr.server.app.start_server +#: flwr.server.client_manager.ClientManager.register +#: flwr.server.client_manager.ClientManager.unregister +#: flwr.server.client_manager.SimpleClientManager.register +#: flwr.server.client_manager.SimpleClientManager.unregister +#: flwr.server.client_manager.SimpleClientManager.wait_for +#: flwr.server.driver.app.start_driver flwr.server.driver.driver.Driver +#: flwr.server.strategy.bulyan.Bulyan +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit +#: flwr.server.strategy.fedadagrad.FedAdagrad +#: flwr.server.strategy.fedadam.FedAdam flwr.server.strategy.fedavg.FedAvg +#: flwr.server.strategy.fedavg_android.FedAvgAndroid +#: flwr.server.strategy.fedavgm.FedAvgM flwr.server.strategy.fedopt.FedOpt +#: flwr.server.strategy.fedprox.FedProx +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg +#: flwr.server.strategy.fedyogi.FedYogi flwr.server.strategy.krum.Krum +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate +#: flwr.server.strategy.strategy.Strategy.aggregate_fit +#: flwr.server.strategy.strategy.Strategy.configure_evaluate +#: flwr.server.strategy.strategy.Strategy.configure_fit +#: flwr.server.strategy.strategy.Strategy.evaluate +#: flwr.server.strategy.strategy.Strategy.initialize_parameters +#: flwr.simulation.app.start_simulation of +#, fuzzy +msgid "Parameters" msgstr "Paramètres du modèle." -#: flwr.common.typing.ReconnectIns:1 of -msgid "ReconnectIns message from server to client." -msgstr "Message de reconnexion du serveur au client." +#: flwr.client.client.Client.evaluate:3 of +msgid "" +"The evaluation instructions containing (global) model parameters received" +" from the server and a dictionary of configuration values used to " +"customize the local evaluation process." +msgstr "" + +#: flwr.client.client.Client.evaluate flwr.client.client.Client.fit +#: flwr.client.client.Client.get_parameters +#: flwr.client.client.Client.get_properties +#: flwr.client.numpy_client.NumPyClient.evaluate +#: flwr.client.numpy_client.NumPyClient.fit +#: flwr.client.numpy_client.NumPyClient.get_parameters +#: flwr.client.numpy_client.NumPyClient.get_properties +#: flwr.server.app.start_server +#: flwr.server.client_manager.ClientManager.num_available +#: flwr.server.client_manager.ClientManager.register +#: flwr.server.client_manager.SimpleClientManager.num_available +#: flwr.server.client_manager.SimpleClientManager.register +#: flwr.server.client_manager.SimpleClientManager.wait_for +#: flwr.server.driver.app.start_driver +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate +#: flwr.server.strategy.strategy.Strategy.aggregate_fit +#: flwr.server.strategy.strategy.Strategy.configure_evaluate +#: flwr.server.strategy.strategy.Strategy.configure_fit +#: flwr.server.strategy.strategy.Strategy.evaluate +#: flwr.server.strategy.strategy.Strategy.initialize_parameters +#: flwr.simulation.app.start_simulation of +#, fuzzy +msgid "Returns" +msgstr "Ressources" -#: flwr.common.typing.ServerMessage:1 of -msgid "ServerMessage is a container used to hold one instruction message." +#: flwr.client.client.Client.evaluate:8 of +msgid "" +"The evaluation result containing the loss on the local dataset and other " +"details such as the number of local data examples used for evaluation." msgstr "" -"ServerMessage est un conteneur utilisé pour contenir un message " -"d'instruction." - -#: flwr.common.typing.Status:1 of -msgid "Client status." -msgstr "Statut du client." -#: flwr.common.parameter.bytes_to_ndarray:1 of -msgid "Deserialize NumPy ndarray from bytes." -msgstr "Désérialise le tableau numérique NumPy à partir d'octets." - -#: flwr.common.logger.configure:1 of -msgid "Configure logging to file and/or remote log server." +#: flwr.client.client.Client.evaluate flwr.client.client.Client.fit +#: flwr.client.client.Client.get_parameters +#: flwr.client.client.Client.get_properties +#: flwr.client.numpy_client.NumPyClient.get_parameters +#: flwr.client.numpy_client.NumPyClient.get_properties +#: flwr.server.app.start_server +#: flwr.server.client_manager.ClientManager.num_available +#: flwr.server.client_manager.ClientManager.register +#: flwr.server.client_manager.SimpleClientManager.num_available +#: flwr.server.client_manager.SimpleClientManager.register +#: flwr.server.client_manager.SimpleClientManager.wait_for +#: flwr.server.driver.app.start_driver +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate +#: flwr.server.strategy.strategy.Strategy.aggregate_fit +#: flwr.server.strategy.strategy.Strategy.configure_evaluate +#: flwr.server.strategy.strategy.Strategy.configure_fit +#: flwr.server.strategy.strategy.Strategy.evaluate +#: flwr.server.strategy.strategy.Strategy.initialize_parameters +#: flwr.simulation.app.start_simulation of +msgid "Return type" msgstr "" -"Configure la journalisation vers un fichier et/ou un serveur de " -"journalisation distant." -#: logging.Logger.log:1 of -msgid "Log 'msg % args' with the integer severity 'level'." -msgstr "Enregistre 'msg % args' avec le niveau de sévérité entier 'level'." - -#: logging.Logger.log:3 of +#: flwr.client.client.Client.fit:3 of msgid "" -"To pass exception information, use the keyword argument exc_info with a " -"true value, e.g." +"The training instructions containing (global) model parameters received " +"from the server and a dictionary of configuration values used to " +"customize the local training process." msgstr "" -"Pour transmettre des informations sur les exceptions, utilise l'argument " -"mot-clé exc_info avec une valeur vraie, par ex." -#: logging.Logger.log:6 of -#, python-format -msgid "logger.log(level, \"We have a %s\", \"mysterious problem\", exc_info=1)" -msgstr "logger.log(level, \"We have a %s\", \"mysterious problem\", exc_info=1)" +#: flwr.client.client.Client.fit:8 of +msgid "" +"The training result containing updated parameters and other details such " +"as the number of local training examples used for training." +msgstr "" -#: flwr.common.parameter.ndarray_to_bytes:1 of -msgid "Serialize NumPy ndarray to bytes." -msgstr "Sérialise le tableau numérique NumPy en octets." +#: flwr.client.client.Client.get_parameters:3 of +msgid "" +"The get parameters instructions received from the server containing a " +"dictionary of configuration values." +msgstr "" -#: flwr.common.parameter.ndarrays_to_parameters:1 of -msgid "Convert NumPy ndarrays to parameters object." -msgstr "Convertit les ndarrays NumPy en objets de paramètres." +#: flwr.client.client.Client.get_parameters:7 of +#, fuzzy +msgid "The current local model parameters." +msgstr "``get_parameters`` : renvoie les paramètres du modèle local actuel" -#: flwr.common.date.now:1 of -msgid "Construct a datetime from time.time() with time zone set to UTC." +#: flwr.client.client.Client.get_properties:3 of +msgid "" +"The get properties instructions received from the server containing a " +"dictionary of configuration values." msgstr "" -"Construit une date à partir de time.time() avec le fuseau horaire réglé " -"sur UTC." -#: flwr.common.parameter.parameters_to_ndarrays:1 of -msgid "Convert parameters object to NumPy ndarrays." -msgstr "Convertit l'objet des paramètres en ndarrays NumPy." +#: flwr.client.client.Client.get_properties:7 of +msgid "The current client properties." +msgstr "" -#: ../../source/ref-changelog.md:1 -msgid "Changelog" -msgstr "Changelog" +#: ../../source/ref-api/flwr.client.ClientApp.rst:2 +#, fuzzy +msgid "ClientApp" +msgstr "client" -#: ../../source/ref-changelog.md:3 +#: flwr.client.clientapp.ClientApp:1 flwr.common.typing.ClientMessage:1 +#: flwr.common.typing.DisconnectRes:1 flwr.common.typing.EvaluateIns:1 +#: flwr.common.typing.EvaluateRes:1 flwr.common.typing.FitIns:1 +#: flwr.common.typing.FitRes:1 flwr.common.typing.GetParametersIns:1 +#: flwr.common.typing.GetParametersRes:1 flwr.common.typing.GetPropertiesIns:1 +#: flwr.common.typing.GetPropertiesRes:1 flwr.common.typing.Parameters:1 +#: flwr.common.typing.ReconnectIns:1 flwr.common.typing.ServerMessage:1 +#: flwr.common.typing.Status:1 flwr.server.app.ServerConfig:1 +#: flwr.server.driver.driver.Driver:1 +#: flwr.server.driver.grpc_driver.GrpcDriver:1 flwr.server.history.History:1 +#: flwr.server.server.Server:1 of +msgid "Bases: :py:class:`object`" +msgstr "" + +#: flwr.client.app.start_client:33 flwr.client.app.start_numpy_client:36 +#: flwr.client.clientapp.ClientApp:4 flwr.server.app.start_server:41 +#: flwr.server.driver.app.start_driver:30 of #, fuzzy -msgid "Unreleased" -msgstr "Inédit" +msgid "Examples" +msgstr "Exemples de PyTorch" -#: ../../source/ref-changelog.md:5 ../../source/ref-changelog.md:21 -#: ../../source/ref-changelog.md:105 ../../source/ref-changelog.md:169 -#: ../../source/ref-changelog.md:227 ../../source/ref-changelog.md:296 -#: ../../source/ref-changelog.md:425 ../../source/ref-changelog.md:467 -#: ../../source/ref-changelog.md:534 ../../source/ref-changelog.md:600 -#: ../../source/ref-changelog.md:645 ../../source/ref-changelog.md:684 -#: ../../source/ref-changelog.md:717 ../../source/ref-changelog.md:767 -msgid "What's new?" -msgstr "Quoi de neuf ?" +#: flwr.client.clientapp.ClientApp:5 of +msgid "" +"Assuming a typical `Client` implementation named `FlowerClient`, you can " +"wrap it in a `ClientApp` as follows:" +msgstr "" -#: ../../source/ref-changelog.md:7 ../../source/ref-changelog.md:93 -#: ../../source/ref-changelog.md:157 ../../source/ref-changelog.md:215 -#: ../../source/ref-changelog.md:284 ../../source/ref-changelog.md:346 -#: ../../source/ref-changelog.md:365 ../../source/ref-changelog.md:521 -#: ../../source/ref-changelog.md:592 ../../source/ref-changelog.md:629 -#: ../../source/ref-changelog.md:672 -msgid "Incompatible changes" -msgstr "Changements incompatibles" +#: flwr.client.clientapp.ClientApp:16 of +msgid "" +"If the above code is in a Python module called `client`, it can be " +"started as follows:" +msgstr "" -#: ../../source/ref-changelog.md:9 -#, fuzzy +#: flwr.client.clientapp.ClientApp:21 of msgid "" -"**Remove support for Python 3.7** " -"([#2280](https://github.com/adap/flower/pull/2280), " -"[#2299](https://github.com/adap/flower/pull/2299))" +"In this `client:app` example, `client` refers to the Python module " +"`client.py` in which the previous code lives in and `app` refers to the " +"global attribute `app` that points to an object of type `ClientApp`." msgstr "" -"**Nouvelles stratégies intégrées** " -"([#828](https://github.com/adap/flower/pull/828) " -"[#822](https://github.com/adap/flower/pull/822))" -#: ../../source/ref-changelog.md:11 +#: ../../source/ref-api/flwr.client.NumPyClient.rst:2 +msgid "NumPyClient" +msgstr "NumPyClient" + +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 msgid "" -"Python 3.7 support was deprecated in Flower 1.5, and this release removes" -" support. Flower now requires Python 3.8." +":py:obj:`evaluate `\\ \\(parameters\\, " +"config\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +msgid ":py:obj:`fit `\\ \\(parameters\\, config\\)" msgstr "" -#: ../../source/ref-changelog.md:13 +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +#: flwr.client.numpy_client.NumPyClient.fit:1 of #, fuzzy -msgid "v1.5.0 (2023-08-31)" -msgstr "v1.4.0 (2023-04-21)" +msgid "Train the provided parameters using the locally held dataset." +msgstr "entraîne le modèle sur l'ensemble d'apprentissage local" -#: ../../source/ref-changelog.md:15 ../../source/ref-changelog.md:99 -#: ../../source/ref-changelog.md:163 ../../source/ref-changelog.md:221 -#: ../../source/ref-changelog.md:290 ../../source/ref-changelog.md:359 -msgid "Thanks to our contributors" -msgstr "Merci à nos contributeurs" +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +msgid ":py:obj:`get_context `\\ \\(\\)" +msgstr "" -#: ../../source/ref-changelog.md:17 ../../source/ref-changelog.md:101 -#: ../../source/ref-changelog.md:165 ../../source/ref-changelog.md:223 +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 msgid "" -"We would like to give our special thanks to all the contributors who made" -" the new version of Flower possible (in `git shortlog` order):" +":py:obj:`get_parameters `\\ " +"\\(config\\)" msgstr "" -"Nous tenons à remercier tout particulièrement tous les contributeurs qui " -"ont rendu possible la nouvelle version de Flower (dans l'ordre `git " -"shortlog`) :" -#: ../../source/ref-changelog.md:19 +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 msgid "" -"`achiverram28`, `Adam Narozniak`, `Anass Anhari`, `Charles Beauville`, " -"`Dana-Farber`, `Daniel J. Beutel`, `Daniel Nata Nugraha`, `Edoardo " -"Gabrielli`, `eunchung`, `Gustavo Bertoli`, `Heng Pan`, `Javier`, `Mahdi`," -" `Ruth Galindo`, `Steven Hé (Sīchàng)`, `Taner Topal`" +":py:obj:`get_properties `\\ " +"\\(config\\)" msgstr "" -#: ../../source/ref-changelog.md:23 +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +#: flwr.client.numpy_client.NumPyClient.get_properties:1 of +msgid "Return a client's set of properties." +msgstr "" + +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +msgid "" +":py:obj:`set_context `\\ " +"\\(context\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +msgid ":py:obj:`to_client `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +#: flwr.client.numpy_client.NumPyClient.to_client:1 of +#, fuzzy +msgid "Convert to object to Client type and return it." +msgstr "Convertit l'objet des paramètres en ndarrays NumPy." + +#: flwr.client.numpy_client.NumPyClient.evaluate:1::1 of +msgid ":py:obj:`context `\\" +msgstr "" + +#: flwr.client.numpy_client.NumPyClient.evaluate:3 +#: flwr.client.numpy_client.NumPyClient.fit:3 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate:5 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:8 +#: flwr.server.strategy.strategy.Strategy.configure_evaluate:5 +#: flwr.server.strategy.strategy.Strategy.configure_fit:5 +#: flwr.server.strategy.strategy.Strategy.evaluate:8 of #, fuzzy +msgid "The current (global) model parameters." +msgstr "``get_parameters`` : renvoie les paramètres du modèle local actuel" + +#: flwr.client.numpy_client.NumPyClient.evaluate:5 of msgid "" -"**Introduce new simulation engine** " -"([#1969](https://github.com/adap/flower/pull/1969), " -"[#2221](https://github.com/adap/flower/pull/2221), " -"[#2248](https://github.com/adap/flower/pull/2248))" +"Configuration parameters which allow the server to influence evaluation " +"on the client. It can be used to communicate arbitrary values from the " +"server to the client, for example, to influence the number of examples " +"used for evaluation." msgstr "" -"**Introduire la télémétrie optionnelle** " -"([#1533](https://github.com/adap/flower/pull/1533), " -"[#1544](https://github.com/adap/flower/pull/1544), " -"[#1584](https://github.com/adap/flower/pull/1584))" -#: ../../source/ref-changelog.md:25 +#: flwr.client.numpy_client.NumPyClient.evaluate:11 of msgid "" -"The new simulation engine has been rewritten from the ground up, yet it " -"remains fully backwards compatible. It offers much improved stability and" -" memory handling, especially when working with GPUs. Simulations " -"transparently adapt to different settings to scale simulation in CPU-" -"only, CPU+GPU, multi-GPU, or multi-node multi-GPU environments." +"* **loss** (*float*) -- The evaluation loss of the model on the local " +"dataset. * **num_examples** (*int*) -- The number of examples used for " +"evaluation. * **metrics** (*Dict[str, Scalar]*) -- A dictionary mapping " +"arbitrary string keys to values of type bool, bytes, float, int, or " +"str. It can be used to communicate arbitrary values back to the server." msgstr "" -#: ../../source/ref-changelog.md:27 +#: flwr.client.numpy_client.NumPyClient.evaluate:11 of msgid "" -"Comprehensive documentation includes a new [how-to run " -"simulations](https://flower.dev/docs/framework/how-to-run-" -"simulations.html) guide, new [simulation-" -"pytorch](https://flower.dev/docs/examples/simulation-pytorch.html) and " -"[simulation-tensorflow](https://flower.dev/docs/examples/simulation-" -"tensorflow.html) notebooks, and a new [YouTube tutorial " -"series](https://www.youtube.com/watch?v=cRebUIGB5RU&list=PLNG4feLHqCWlnj8a_E1A_n5zr2-8pafTB)." +"**loss** (*float*) -- The evaluation loss of the model on the local " +"dataset." msgstr "" -#: ../../source/ref-changelog.md:29 +#: flwr.client.numpy_client.NumPyClient.evaluate:12 of +msgid "**num_examples** (*int*) -- The number of examples used for evaluation." +msgstr "" + +#: flwr.client.numpy_client.NumPyClient.evaluate:13 +#: flwr.client.numpy_client.NumPyClient.fit:13 of msgid "" -"**Restructure Flower Docs** " -"([#1824](https://github.com/adap/flower/pull/1824), " -"[#1865](https://github.com/adap/flower/pull/1865), " -"[#1884](https://github.com/adap/flower/pull/1884), " -"[#1887](https://github.com/adap/flower/pull/1887), " -"[#1919](https://github.com/adap/flower/pull/1919), " -"[#1922](https://github.com/adap/flower/pull/1922), " -"[#1920](https://github.com/adap/flower/pull/1920), " -"[#1923](https://github.com/adap/flower/pull/1923), " -"[#1924](https://github.com/adap/flower/pull/1924), " -"[#1962](https://github.com/adap/flower/pull/1962), " -"[#2006](https://github.com/adap/flower/pull/2006), " -"[#2133](https://github.com/adap/flower/pull/2133), " -"[#2203](https://github.com/adap/flower/pull/2203), " -"[#2215](https://github.com/adap/flower/pull/2215), " -"[#2122](https://github.com/adap/flower/pull/2122), " -"[#2223](https://github.com/adap/flower/pull/2223), " -"[#2219](https://github.com/adap/flower/pull/2219), " -"[#2232](https://github.com/adap/flower/pull/2232), " -"[#2233](https://github.com/adap/flower/pull/2233), " -"[#2234](https://github.com/adap/flower/pull/2234), " -"[#2235](https://github.com/adap/flower/pull/2235), " -"[#2237](https://github.com/adap/flower/pull/2237), " -"[#2238](https://github.com/adap/flower/pull/2238), " -"[#2242](https://github.com/adap/flower/pull/2242), " -"[#2231](https://github.com/adap/flower/pull/2231), " -"[#2243](https://github.com/adap/flower/pull/2243), " -"[#2227](https://github.com/adap/flower/pull/2227))" +"**metrics** (*Dict[str, Scalar]*) -- A dictionary mapping arbitrary " +"string keys to values of type bool, bytes, float, int, or str. It can be " +"used to communicate arbitrary values back to the server." msgstr "" -#: ../../source/ref-changelog.md:31 +#: flwr.client.numpy_client.NumPyClient.evaluate:19 of msgid "" -"Much effort went into a completely restructured Flower docs experience. " -"The documentation on [flower.dev/docs](flower.dev/docs) is now divided " -"into Flower Framework, Flower Baselines, Flower Android SDK, Flower iOS " -"SDK, and code example projects." +"The previous return type format (int, float, float) and the extended " +"format (int, float, float, Dict[str, Scalar]) have been deprecated and " +"removed since Flower 0.19." msgstr "" -#: ../../source/ref-changelog.md:33 -#, fuzzy +#: flwr.client.numpy_client.NumPyClient.fit:5 of msgid "" -"**Introduce Flower Swift SDK** " -"([#1858](https://github.com/adap/flower/pull/1858), " -"[#1897](https://github.com/adap/flower/pull/1897))" +"Configuration parameters which allow the server to influence training on " +"the client. It can be used to communicate arbitrary values from the " +"server to the client, for example, to set the number of (local) training " +"epochs." msgstr "" -"**Introduction du SDK iOS (aperçu)** " -"([#1621](https://github.com/adap/flower/pull/1621), " -"[#1764](https://github.com/adap/flower/pull/1764))" -#: ../../source/ref-changelog.md:35 +#: flwr.client.numpy_client.NumPyClient.fit:11 of msgid "" -"This is the first preview release of the Flower Swift SDK. Flower support" -" on iOS is improving, and alongside the Swift SDK and code example, there" -" is now also an iOS quickstart tutorial." +"* **parameters** (*NDArrays*) -- The locally updated model parameters. * " +"**num_examples** (*int*) -- The number of examples used for training. * " +"**metrics** (*Dict[str, Scalar]*) -- A dictionary mapping arbitrary " +"string keys to values of type bool, bytes, float, int, or str. It can " +"be used to communicate arbitrary values back to the server." msgstr "" -#: ../../source/ref-changelog.md:37 +#: flwr.client.numpy_client.NumPyClient.fit:11 of #, fuzzy -msgid "" -"**Introduce Flower Android SDK** " -"([#2131](https://github.com/adap/flower/pull/2131))" +msgid "**parameters** (*NDArrays*) -- The locally updated model parameters." +msgstr "``get_parameters`` : renvoie les paramètres du modèle local actuel" + +#: flwr.client.numpy_client.NumPyClient.fit:12 of +msgid "**num_examples** (*int*) -- The number of examples used for training." msgstr "" -"**Introduire une nouvelle ligne de base pour les fleurs : FedAvg " -"FEMNIST** ([#1655](https://github.com/adap/flower/pull/1655))" -#: ../../source/ref-changelog.md:39 +#: flwr.client.numpy_client.NumPyClient.get_parameters:3 of msgid "" -"This is the first preview release of the Flower Kotlin SDK. Flower " -"support on Android is improving, and alongside the Kotlin SDK and code " -"example, there is now also an Android quickstart tutorial." +"Configuration parameters requested by the server. This can be used to " +"tell the client which parameters are needed along with some Scalar " +"attributes." msgstr "" -#: ../../source/ref-changelog.md:41 +#: flwr.client.numpy_client.NumPyClient.get_parameters:8 of #, fuzzy +msgid "**parameters** -- The local model parameters as a list of NumPy ndarrays." +msgstr "renvoie le poids du modèle sous la forme d'une liste de ndarrays NumPy" + +#: flwr.client.numpy_client.NumPyClient.get_properties:3 of msgid "" -"**Introduce new end-to-end testing infrastructure** " -"([#1842](https://github.com/adap/flower/pull/1842), " -"[#2071](https://github.com/adap/flower/pull/2071), " -"[#2072](https://github.com/adap/flower/pull/2072), " -"[#2068](https://github.com/adap/flower/pull/2068), " -"[#2067](https://github.com/adap/flower/pull/2067), " -"[#2069](https://github.com/adap/flower/pull/2069), " -"[#2073](https://github.com/adap/flower/pull/2073), " -"[#2070](https://github.com/adap/flower/pull/2070), " -"[#2074](https://github.com/adap/flower/pull/2074), " -"[#2082](https://github.com/adap/flower/pull/2082), " -"[#2084](https://github.com/adap/flower/pull/2084), " -"[#2093](https://github.com/adap/flower/pull/2093), " -"[#2109](https://github.com/adap/flower/pull/2109), " -"[#2095](https://github.com/adap/flower/pull/2095), " -"[#2140](https://github.com/adap/flower/pull/2140), " -"[#2137](https://github.com/adap/flower/pull/2137), " -"[#2165](https://github.com/adap/flower/pull/2165))" +"Configuration parameters requested by the server. This can be used to " +"tell the client which properties are needed along with some Scalar " +"attributes." msgstr "" -"**Améliorer l'API (expérimentale) du pilote** " -"([#1663](https://github.com/adap/flower/pull/1663), " -"[#1666](https://github.com/adap/flower/pull/1666), " -"[#1667](https://github.com/adap/flower/pull/1667), " -"[#1664](https://github.com/adap/flower/pull/1664), " -"[#1675](https://github.com/adap/flower/pull/1675), " -"[#1676](https://github.com/adap/flower/pull/1676), " -"[#1693](https://github.com/adap/flower/pull/1693), " -"[#1662](https://github.com/adap/flower/pull/1662), " -"[#1794](https://github.com/adap/flower/pull/1794))" -#: ../../source/ref-changelog.md:43 +#: flwr.client.numpy_client.NumPyClient.get_properties:8 of msgid "" -"A new testing infrastructure ensures that new changes stay compatible " -"with existing framework integrations or strategies." +"**properties** -- A dictionary mapping arbitrary string keys to values of" +" type bool, bytes, float, int, or str. It can be used to communicate " +"arbitrary property values back to the server." msgstr "" -#: ../../source/ref-changelog.md:45 +#: ../../source/ref-api/flwr.client.run_client_app.rst:2 +msgid "run\\_client\\_app" +msgstr "" + +#: ../../source/ref-api/flwr.client.start_client.rst:2 #, fuzzy -msgid "**Deprecate Python 3.7**" -msgstr "**Créer le PR**" +msgid "start\\_client" +msgstr "start_client" -#: ../../source/ref-changelog.md:47 +#: flwr.client.app.start_client:3 flwr.client.app.start_numpy_client:9 of msgid "" -"Since Python 3.7 reached its end of life (EOL) on 2023-06-27, support for" -" Python 3.7 is now deprecated and will be removed in an upcoming release." +"The IPv4 or IPv6 address of the server. If the Flower server runs on the " +"same machine on port 8080, then `server_address` would be " +"`\"[::]:8080\"`." msgstr "" -#: ../../source/ref-changelog.md:49 -#, fuzzy -msgid "" -"**Add new** `FedTrimmedAvg` **strategy** " -"([#1769](https://github.com/adap/flower/pull/1769), " -"[#1853](https://github.com/adap/flower/pull/1853))" +#: flwr.client.app.start_client:7 of +msgid "A callable that instantiates a Client. (default: None)" msgstr "" -"**Ajouter un nouvel exemple de Federated Analytics avec Pandas** " -"([#1469](https://github.com/adap/flower/pull/1469), " -"[#1535](https://github.com/adap/flower/pull/1535))" -#: ../../source/ref-changelog.md:51 -#, fuzzy +#: flwr.client.app.start_client:9 of msgid "" -"The new `FedTrimmedAvg` strategy implements Trimmed Mean by [Dong Yin, " -"2018](https://arxiv.org/abs/1803.01498)." +"An implementation of the abstract base class `flwr.client.Client` " +"(default: None)" msgstr "" -"La nouvelle stratégie `FedMedian` met en œuvre Federated Median " -"(FedMedian) par [Yin et al., 2018] " -"(https://arxiv.org/pdf/1803.01498v1.pdf)." -#: ../../source/ref-changelog.md:53 -#, fuzzy +#: flwr.client.app.start_client:12 flwr.client.app.start_numpy_client:15 of msgid "" -"**Introduce start_driver** " -"([#1697](https://github.com/adap/flower/pull/1697))" +"The maximum length of gRPC messages that can be exchanged with the Flower" +" server. The default should be sufficient for most models. Users who " +"train very large models might need to increase this value. Note that the " +"Flower server needs to be started with the same value (see " +"`flwr.server.start_server`), otherwise it will not know about the " +"increased limit and block larger messages." msgstr "" -"**Ajouter une nouvelle stratégie `FedProx`** " -"([#1619](https://github.com/adap/flower/pull/1619))" -#: ../../source/ref-changelog.md:55 +#: flwr.client.app.start_client:19 flwr.client.app.start_numpy_client:22 +#: flwr.server.driver.app.start_driver:21 of msgid "" -"In addition to `start_server` and using the raw Driver API, there is a " -"new `start_driver` function that allows for running `start_server` " -"scripts as a Flower driver with only a single-line code change. Check out" -" the `mt-pytorch` code example to see a working example using " -"`start_driver`." +"The PEM-encoded root certificates as a byte string or a path string. If " +"provided, a secure connection using the certificates will be established " +"to an SSL-enabled Flower server." msgstr "" -#: ../../source/ref-changelog.md:57 -#, fuzzy +#: flwr.client.app.start_client:23 flwr.client.app.start_numpy_client:26 of msgid "" -"**Add parameter aggregation to** `mt-pytorch` **code example** " -"([#1785](https://github.com/adap/flower/pull/1785))" +"Starts an insecure gRPC connection when True. Enables HTTPS connection " +"when False, using system certificates if `root_certificates` is None." msgstr "" -"**Nouvel exemple de code PyTorch avancé** " -"([#1007](https://github.com/adap/flower/pull/1007))" -#: ../../source/ref-changelog.md:59 +#: flwr.client.app.start_client:26 flwr.client.app.start_numpy_client:29 of msgid "" -"The `mt-pytorch` example shows how to aggregate parameters when writing a" -" driver script. The included `driver.py` and `server.py` have been " -"aligned to demonstrate both the low-level way and the high-level way of " -"building server-side logic." +"Configure the transport layer. Allowed values: - 'grpc-bidi': gRPC, " +"bidirectional streaming - 'grpc-rere': gRPC, request-response " +"(experimental) - 'rest': HTTP (experimental)" msgstr "" -#: ../../source/ref-changelog.md:61 -#, fuzzy -msgid "" -"**Migrate experimental REST API to Starlette** " -"([2171](https://github.com/adap/flower/pull/2171))" +#: flwr.client.app.start_client:34 flwr.client.app.start_numpy_client:37 of +msgid "Starting a gRPC client with an insecure server connection:" msgstr "" -"**Nouvelle stratégie expérimentale TensorBoard** " -"([#789](https://github.com/adap/flower/pull/789))" -#: ../../source/ref-changelog.md:63 -msgid "" -"The (experimental) REST API used to be implemented in " -"[FastAPI](https://fastapi.tiangolo.com/), but it has now been migrated to" -" use [Starlette](https://www.starlette.io/) directly." +#: flwr.client.app.start_client:41 flwr.client.app.start_numpy_client:44 of +msgid "Starting an SSL-enabled gRPC client using system certificates:" msgstr "" -#: ../../source/ref-changelog.md:65 -#, fuzzy -msgid "" -"Please note: The REST request-response API is still experimental and will" -" likely change significantly over time." +#: flwr.client.app.start_client:52 flwr.client.app.start_numpy_client:52 of +msgid "Starting an SSL-enabled gRPC client using provided certificates:" msgstr "" -"Remarque : l'API REST est encore expérimentale et est susceptible de " -"changer de manière significative au fil du temps." -#: ../../source/ref-changelog.md:67 +#: ../../source/ref-api/flwr.client.start_numpy_client.rst:2 #, fuzzy +msgid "start\\_numpy\\_client" +msgstr "start_numpy_client" + +#: flwr.client.app.start_numpy_client:5 of msgid "" -"**Introduce experimental gRPC request-response API** " -"([#1867](https://github.com/adap/flower/pull/1867), " -"[#1901](https://github.com/adap/flower/pull/1901))" +"This function is deprecated since 1.7.0. Use " +":code:`flwr.client.start_client` instead and first convert your " +":code:`NumPyClient` to type :code:`flwr.client.Client` by executing its " +":code:`to_client()` method." msgstr "" -"**Introduire les enveloppes de confidentialité différentielle (aperçu)** " -"([#1357](https://github.com/adap/flower/pull/1357), " -"[#1460](https://github.com/adap/flower/pull/1460))" -#: ../../source/ref-changelog.md:69 -msgid "" -"In addition to the existing gRPC API (based on bidirectional streaming) " -"and the experimental REST API, there is now a new gRPC API that uses a " -"request-response model to communicate with client nodes." +#: flwr.client.app.start_numpy_client:13 of +msgid "An implementation of the abstract base class `flwr.client.NumPyClient`." msgstr "" -#: ../../source/ref-changelog.md:71 -#, fuzzy -msgid "" -"Please note: The gRPC request-response API is still experimental and will" -" likely change significantly over time." +#: ../../source/ref-api/flwr.common.rst:2 +msgid "common" +msgstr "commun" + +#: ../../source/ref-api/flwr.common.rst:29::1 +msgid ":py:obj:`bytes_to_ndarray `\\ \\(tensor\\)" msgstr "" -"Remarque : l'API REST est encore expérimentale et est susceptible de " -"changer de manière significative au fil du temps." -#: ../../source/ref-changelog.md:73 -#, fuzzy +#: ../../source/ref-api/flwr.common.rst:29::1 +#: flwr.common.parameter.bytes_to_ndarray:1 of +msgid "Deserialize NumPy ndarray from bytes." +msgstr "Désérialise le tableau numérique NumPy à partir d'octets." + +#: ../../source/ref-api/flwr.common.rst:29::1 msgid "" -"**Replace the experimental** `start_client(rest=True)` **with the new** " -"`start_client(transport=\"rest\")` " -"([#1880](https://github.com/adap/flower/pull/1880))" +":py:obj:`configure `\\ \\(identifier\\[\\, " +"filename\\, host\\]\\)" msgstr "" -"**Initialise** `start_simulation` **avec une liste d'ID de clients** " -"([#860](https://github.com/adap/flower/pull/860))" -#: ../../source/ref-changelog.md:75 -msgid "" -"The (experimental) `start_client` argument `rest` was deprecated in " -"favour of a new argument `transport`. `start_client(transport=\"rest\")` " -"will yield the same behaviour as `start_client(rest=True)` did before. " -"All code should migrate to the new argument `transport`. The deprecated " -"argument `rest` will be removed in a future release." +#: ../../source/ref-api/flwr.common.rst:29::1 +#: flwr.common.logger.configure:1 of +msgid "Configure logging to file and/or remote log server." msgstr "" +"Configure la journalisation vers un fichier et/ou un serveur de " +"journalisation distant." -#: ../../source/ref-changelog.md:77 -#, fuzzy +#: ../../source/ref-api/flwr.common.rst:29::1 msgid "" -"**Add a new gRPC option** " -"([#2197](https://github.com/adap/flower/pull/2197))" +":py:obj:`event `\\ \\(event\\_type\\[\\, " +"event\\_details\\]\\)" msgstr "" -"**Ajouter une nouvelle stratégie `FedProx`** " -"([#1619](https://github.com/adap/flower/pull/1619))" -#: ../../source/ref-changelog.md:79 -msgid "" -"We now start a gRPC server with the `grpc.keepalive_permit_without_calls`" -" option set to 0 by default. This prevents the clients from sending " -"keepalive pings when there is no outstanding stream." +#: ../../source/ref-api/flwr.common.rst:29::1 +#: flwr.common.telemetry.event:1 of +msgid "Submit create_event to ThreadPoolExecutor to avoid blocking." msgstr "" -#: ../../source/ref-changelog.md:81 -#, fuzzy +#: ../../source/ref-api/flwr.common.rst:29::1 msgid "" -"**Improve example notebooks** " -"([#2005](https://github.com/adap/flower/pull/2005))" +":py:obj:`log `\\ \\(level\\, msg\\, \\*args\\, " +"\\*\\*kwargs\\)" msgstr "" -"**Supprimer les stratégies expérimentales** " -"([#1280](https://github.com/adap/flower/pull/1280))" -#: ../../source/ref-changelog.md:83 -#, fuzzy -msgid "There's a new 30min Federated Learning PyTorch tutorial!" -msgstr "Bienvenue au tutoriel sur l'apprentissage fédéré de la fleur !" +#: ../../source/ref-api/flwr.common.rst:29::1 logging.Logger.log:1 +#: of +msgid "Log 'msg % args' with the integer severity 'level'." +msgstr "Enregistre 'msg % args' avec le niveau de sévérité entier 'level'." + +#: ../../source/ref-api/flwr.common.rst:29::1 +msgid ":py:obj:`ndarray_to_bytes `\\ \\(ndarray\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:29::1 +#: flwr.common.parameter.ndarray_to_bytes:1 of +msgid "Serialize NumPy ndarray to bytes." +msgstr "Sérialise le tableau numérique NumPy en octets." + +#: ../../source/ref-api/flwr.common.rst:29::1 +msgid ":py:obj:`now `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:29::1 +#: flwr.common.date.now:1 of +msgid "Construct a datetime from time.time() with time zone set to UTC." +msgstr "" +"Construit une date à partir de time.time() avec le fuseau horaire réglé " +"sur UTC." -#: ../../source/ref-changelog.md:85 +#: ../../source/ref-api/flwr.common.rst:29::1 msgid "" -"**Example updates** ([#1772](https://github.com/adap/flower/pull/1772), " -"[#1873](https://github.com/adap/flower/pull/1873), " -"[#1981](https://github.com/adap/flower/pull/1981), " -"[#1988](https://github.com/adap/flower/pull/1988), " -"[#1984](https://github.com/adap/flower/pull/1984), " -"[#1982](https://github.com/adap/flower/pull/1982), " -"[#2112](https://github.com/adap/flower/pull/2112), " -"[#2144](https://github.com/adap/flower/pull/2144), " -"[#2174](https://github.com/adap/flower/pull/2174), " -"[#2225](https://github.com/adap/flower/pull/2225), " -"[#2183](https://github.com/adap/flower/pull/2183))" +":py:obj:`ndarrays_to_parameters `\\ " +"\\(ndarrays\\)" msgstr "" -#: ../../source/ref-changelog.md:87 +#: ../../source/ref-api/flwr.common.rst:29::1 +#: flwr.common.parameter.ndarrays_to_parameters:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.ndarrays_to_parameters:1 +#: of +msgid "Convert NumPy ndarrays to parameters object." +msgstr "Convertit les ndarrays NumPy en objets de paramètres." + +#: ../../source/ref-api/flwr.common.rst:29::1 msgid "" -"Many examples have received significant updates, including simplified " -"advanced-tensorflow and advanced-pytorch examples, improved macOS " -"compatibility of TensorFlow examples, and code examples for simulation. A" -" major upgrade is that all code examples now have a `requirements.txt` " -"(in addition to `pyproject.toml`)." +":py:obj:`parameters_to_ndarrays `\\ " +"\\(parameters\\)" msgstr "" -#: ../../source/ref-changelog.md:89 -#, fuzzy +#: ../../source/ref-api/flwr.common.rst:29::1 +#: flwr.common.parameter.parameters_to_ndarrays:1 of +msgid "Convert parameters object to NumPy ndarrays." +msgstr "Convertit l'objet des paramètres en ndarrays NumPy." + +#: ../../source/ref-api/flwr.common.rst:52::1 msgid "" -"**General improvements** " -"([#1872](https://github.com/adap/flower/pull/1872), " -"[#1866](https://github.com/adap/flower/pull/1866), " -"[#1884](https://github.com/adap/flower/pull/1884), " -"[#1837](https://github.com/adap/flower/pull/1837), " -"[#1477](https://github.com/adap/flower/pull/1477), " -"[#2171](https://github.com/adap/flower/pull/2171))" +":py:obj:`ClientMessage `\\ " +"\\(\\[get\\_properties\\_res\\, ...\\]\\)" msgstr "" -"**Mise à jour de la documentation** " -"([#1629](https://github.com/adap/flower/pull/1629), " -"[#1628](https://github.com/adap/flower/pull/1628), " -"[#1620](https://github.com/adap/flower/pull/1620), " -"[#1618](https://github.com/adap/flower/pull/1618), " -"[#1617](https://github.com/adap/flower/pull/1617), " -"[#1613](https://github.com/adap/flower/pull/1613), " -"[#1614](https://github.com/adap/flower/pull/1614))" -#: ../../source/ref-changelog.md:91 ../../source/ref-changelog.md:155 -#: ../../source/ref-changelog.md:209 ../../source/ref-changelog.md:276 -msgid "Flower received many improvements under the hood, too many to list here." +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.ClientMessage:1 of +msgid "ClientMessage is a container used to hold one result message." msgstr "" -"Flower a reçu de nombreuses améliorations sous le capot, trop nombreuses " -"pour être énumérées ici." +"ClientMessage est un conteneur utilisé pour contenir un message de " +"résultat." -#: ../../source/ref-changelog.md:95 ../../source/ref-changelog.md:159 -#: ../../source/ref-changelog.md:217 ../../source/ref-changelog.md:286 -#: ../../source/ref-changelog.md:348 -msgid "None" -msgstr "Aucun" +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`Code `\\ \\(value\\)" +msgstr "" -#: ../../source/ref-changelog.md:97 -msgid "v1.4.0 (2023-04-21)" -msgstr "v1.4.0 (2023-04-21)" +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.Code:1 of +msgid "Client status codes." +msgstr "Codes d'état du client." -#: ../../source/ref-changelog.md:103 -msgid "" -"`Adam Narozniak`, `Alexander Viala Bellander`, `Charles Beauville`, " -"`Chenyang Ma (Danny)`, `Daniel J. Beutel`, `Edoardo`, `Gautam Jajoo`, " -"`Iacob-Alexandru-Andrei`, `JDRanpariya`, `Jean Charle Yaacoub`, `Kunal " -"Sarkhel`, `L. Jiang`, `Lennart Behme`, `Max Kapsecker`, `Michał`, `Nic " -"Lane`, `Nikolaos Episkopos`, `Ragy`, `Saurav Maheshkar`, `Semo Yang`, " -"`Steve Laskaridis`, `Steven Hé (Sīchàng)`, `Taner Topal`" +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`DisconnectRes `\\ \\(reason\\)" msgstr "" -"`Adam Narozniak`, `Alexander Viala Bellander`, `Charles Beauville`, " -"`Chenyang Ma (Danny)`, `Daniel J. Beutel`, `Edoardo`, `Gautam Jajoo`, " -"`Iacob-Alexandru-Andrei`, `JDRanpariya`, `Jean Charle Yaacoub`, `Kunal " -"Sarkhel`, `L. Jiang`, `Lennart Behme`, `Max Kapsecker`, `Michał`, `Nic " -"Lane`, `Nikolaos Episkopos`, `Ragy`, `Saurav Maheshkar`, `Semo Yang`, " -"`Steve Laskaridis`, `Steven Hé (Sīchàng)`, `Taner Topal`" -#: ../../source/ref-changelog.md:107 +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.DisconnectRes:1 of +msgid "DisconnectRes message from client to server." +msgstr "Message DisconnectRes envoyé par le client au serveur." + +#: ../../source/ref-api/flwr.common.rst:52::1 msgid "" -"**Introduce support for XGBoost (**`FedXgbNnAvg` **strategy and " -"example)** ([#1694](https://github.com/adap/flower/pull/1694), " -"[#1709](https://github.com/adap/flower/pull/1709), " -"[#1715](https://github.com/adap/flower/pull/1715), " -"[#1717](https://github.com/adap/flower/pull/1717), " -"[#1763](https://github.com/adap/flower/pull/1763), " -"[#1795](https://github.com/adap/flower/pull/1795))" +":py:obj:`EvaluateIns `\\ \\(parameters\\, " +"config\\)" msgstr "" -"**Introduire la prise en charge de XGBoost (**`FedXgbNnAvg` **stratégie " -"et exemple)** ([#1694](https://github.com/adap/flower/pull/1694), " -"[#1709](https://github.com/adap/flower/pull/1709), " -"[#1715](https://github.com/adap/flower/pull/1715), " -"[#1717](https://github.com/adap/flower/pull/1717), " -"[#1763](https://github.com/adap/flower/pull/1763), " -"[#1795](https://github.com/adap/flower/pull/1795))" -#: ../../source/ref-changelog.md:109 +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.EvaluateIns:1 of +msgid "Evaluate instructions for a client." +msgstr "Évaluer les instructions pour un client." + +#: ../../source/ref-api/flwr.common.rst:52::1 msgid "" -"XGBoost is a tree-based ensemble machine learning algorithm that uses " -"gradient boosting to improve model accuracy. We added a new `FedXgbNnAvg`" -" " -"[strategy](https://github.com/adap/flower/tree/main/src/py/flwr/server/strategy/fedxgb_nn_avg.py)," -" and a [code " -"example](https://github.com/adap/flower/tree/main/examples/quickstart_xgboost_horizontal)" -" that demonstrates the usage of this new strategy in an XGBoost project." +":py:obj:`EvaluateRes `\\ \\(status\\, loss\\, " +"num\\_examples\\, metrics\\)" msgstr "" -"Nous avons ajouté une nouvelle [stratégie] `FedXgbNnAvg` " -"(https://github.com/adap/flower/tree/main/src/py/flwr/server/strategy/fedxgb_nn_avg.py)," -" et un [exemple de code] " -"(https://github.com/adap/flower/tree/main/examples/quickstart_xgboost_horizontal)" -" qui démontre l'utilisation de cette nouvelle stratégie dans un projet " -"XGBoost." -#: ../../source/ref-changelog.md:111 -msgid "" -"**Introduce iOS SDK (preview)** " -"([#1621](https://github.com/adap/flower/pull/1621), " -"[#1764](https://github.com/adap/flower/pull/1764))" +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.EvaluateRes:1 of +msgid "Evaluate response from a client." +msgstr "Évaluer la réponse d'un client." + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`EventType `\\ \\(value\\)" msgstr "" -"**Introduction du SDK iOS (aperçu)** " -"([#1621](https://github.com/adap/flower/pull/1621), " -"[#1764](https://github.com/adap/flower/pull/1764))" -#: ../../source/ref-changelog.md:113 +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.telemetry.EventType:1 of +msgid "Types of telemetry events." +msgstr "Types d'événements télémétriques." + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`FitIns `\\ \\(parameters\\, config\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.FitIns:1 of +msgid "Fit instructions for a client." +msgstr "Instructions d'ajustement pour un client." + +#: ../../source/ref-api/flwr.common.rst:52::1 msgid "" -"This is a major update for anyone wanting to implement Federated Learning" -" on iOS mobile devices. We now have a swift iOS SDK present under " -"[src/swift/flwr](https://github.com/adap/flower/tree/main/src/swift/flwr)" -" that will facilitate greatly the app creating process. To showcase its " -"use, the [iOS " -"example](https://github.com/adap/flower/tree/main/examples/ios) has also " -"been updated!" +":py:obj:`FitRes `\\ \\(status\\, parameters\\, " +"num\\_examples\\, metrics\\)" msgstr "" -"Il s'agit d'une mise à jour majeure pour tous ceux qui souhaitent mettre " -"en œuvre l'apprentissage fédéré sur les appareils mobiles iOS. Nous " -"disposons désormais d'un SDK swift iOS présent sous " -"[src/swift/flwr](https://github.com/adap/flower/tree/main/src/swift/flwr)" -" qui facilitera grandement le processus de création d'applications. Pour " -"présenter son utilisation, l'[exemple " -"iOS](https://github.com/adap/flower/tree/main/examples/ios) a également " -"été mis à jour !" -#: ../../source/ref-changelog.md:115 -msgid "" -"**Introduce new \"What is Federated Learning?\" tutorial** " -"([#1657](https://github.com/adap/flower/pull/1657), " -"[#1721](https://github.com/adap/flower/pull/1721))" +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.FitRes:1 of +msgid "Fit response from a client." +msgstr "Réponse adaptée d'un client." + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`GetParametersIns `\\ \\(config\\)" msgstr "" -"**Introduire un nouveau tutoriel \"Qu'est-ce que l'apprentissage fédéré ?" -" \"** ([#1657](https://github.com/adap/flower/pull/1657), " -"[#1721](https://github.com/adap/flower/pull/1721))" -#: ../../source/ref-changelog.md:117 -#, fuzzy +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.GetParametersIns:1 of +msgid "Parameters request for a client." +msgstr "Demande de paramètres pour un client." + +#: ../../source/ref-api/flwr.common.rst:52::1 msgid "" -"A new [entry-level tutorial](https://flower.dev/docs/framework/tutorial-" -"what-is-federated-learning.html) in our documentation explains the basics" -" of Fedetated Learning. It enables anyone who's unfamiliar with Federated" -" Learning to start their journey with Flower. Forward it to anyone who's " -"interested in Federated Learning!" +":py:obj:`GetParametersRes `\\ \\(status\\, " +"parameters\\)" msgstr "" -"Un nouveau [tutoriel d'entrée de gamme] " -"(https://flower.dev/docs/tutorial/Flower-0-What-is-FL.html) dans notre " -"documentation explique les bases de l'apprentissage fédéré. Il permet à " -"tous ceux qui ne connaissent pas l'apprentissage fédéré de commencer leur" -" voyage avec Flower. Fais-le suivre à tous ceux qui s'intéressent à " -"l'apprentissage fédéré !" -#: ../../source/ref-changelog.md:119 -msgid "" -"**Introduce new Flower Baseline: FedProx MNIST** " -"([#1513](https://github.com/adap/flower/pull/1513), " -"[#1680](https://github.com/adap/flower/pull/1680), " -"[#1681](https://github.com/adap/flower/pull/1681), " -"[#1679](https://github.com/adap/flower/pull/1679))" +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.GetParametersRes:1 of +msgid "Response when asked to return parameters." +msgstr "Réponse lorsqu'on te demande de renvoyer des paramètres." + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`GetPropertiesIns `\\ \\(config\\)" msgstr "" -"**Introduire une nouvelle fleur Référence : FedProx MNIST** " -"([#1513](https://github.com/adap/flower/pull/1513), " -"[#1680](https://github.com/adap/flower/pull/1680), " -"[#1681](https://github.com/adap/flower/pull/1681), " -"[#1679](https://github.com/adap/flower/pull/1679))" -#: ../../source/ref-changelog.md:121 +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.GetPropertiesIns:1 of +msgid "Properties request for a client." +msgstr "Demande de propriétés pour un client." + +#: ../../source/ref-api/flwr.common.rst:52::1 msgid "" -"This new baseline replicates the MNIST+CNN task from the paper [Federated" -" Optimization in Heterogeneous Networks (Li et al., " -"2018)](https://arxiv.org/abs/1812.06127). It uses the `FedProx` strategy," -" which aims at making convergence more robust in heterogenous settings." +":py:obj:`GetPropertiesRes `\\ \\(status\\, " +"properties\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.GetPropertiesRes:1 of +msgid "Properties response from a client." +msgstr "Réponse des propriétés d'un client." + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`NDArray `\\" msgstr "" -"Cette nouvelle ligne de base reproduit la tâche MNIST+CNN de l'article " -"[Federated Optimization in Heterogeneous Networks (Li et al., 2018)] " -"(https://arxiv.org/abs/1812.06127). Elle utilise la stratégie `FedProx`, " -"qui vise à rendre la convergence plus robuste dans des contextes " -"hétérogènes." -#: ../../source/ref-changelog.md:123 +#: ../../source/ref-api/flwr.common.rst:52::1 msgid "" -"**Introduce new Flower Baseline: FedAvg FEMNIST** " -"([#1655](https://github.com/adap/flower/pull/1655))" +"alias of :py:class:`~numpy.ndarray`\\ [:py:obj:`~typing.Any`, " +":py:class:`~numpy.dtype`\\ [:py:obj:`~typing.Any`]]" msgstr "" -"**Introduire une nouvelle ligne de base pour les fleurs : FedAvg " -"FEMNIST** ([#1655](https://github.com/adap/flower/pull/1655))" -#: ../../source/ref-changelog.md:125 +#: ../../source/ref-api/flwr.common.rst:52::1 msgid "" -"This new baseline replicates an experiment evaluating the performance of " -"the FedAvg algorithm on the FEMNIST dataset from the paper [LEAF: A " -"Benchmark for Federated Settings (Caldas et al., " -"2018)](https://arxiv.org/abs/1812.01097)." +":py:obj:`Parameters `\\ \\(tensors\\, " +"tensor\\_type\\)" msgstr "" -"Cette nouvelle ligne de base reproduit une expérience évaluant les " -"performances de l'algorithme FedAvg sur le jeu de données FEMNIST tiré de" -" l'article [LEAF : A Benchmark for Federated Settings (Caldas et al., " -"2018)] (https://arxiv.org/abs/1812.01097)." -#: ../../source/ref-changelog.md:127 +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.Parameters:1 of +msgid "Model parameters." +msgstr "Paramètres du modèle." + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`ReconnectIns `\\ \\(seconds\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.ReconnectIns:1 of +msgid "ReconnectIns message from server to client." +msgstr "Message de reconnexion du serveur au client." + +#: ../../source/ref-api/flwr.common.rst:52::1 msgid "" -"**Introduce (experimental) REST API** " -"([#1594](https://github.com/adap/flower/pull/1594), " -"[#1690](https://github.com/adap/flower/pull/1690), " -"[#1695](https://github.com/adap/flower/pull/1695), " -"[#1712](https://github.com/adap/flower/pull/1712), " -"[#1802](https://github.com/adap/flower/pull/1802), " -"[#1770](https://github.com/adap/flower/pull/1770), " -"[#1733](https://github.com/adap/flower/pull/1733))" +":py:obj:`ServerMessage `\\ " +"\\(\\[get\\_properties\\_ins\\, ...\\]\\)" msgstr "" -"**Introduire l'API REST (expérimentale)** " -"([#1594](https://github.com/adap/flower/pull/1594), " -"[#1690](https://github.com/adap/flower/pull/1690), " -"[#1695](https://github.com/adap/flower/pull/1695), " -"[#1712](https://github.com/adap/flower/pull/1712), " -"[#1802](https://github.com/adap/flower/pull/1802), " -"[#1770](https://github.com/adap/flower/pull/1770), " -"[#1733](https://github.com/adap/flower/pull/1733))" -#: ../../source/ref-changelog.md:129 +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.ServerMessage:1 of +msgid "ServerMessage is a container used to hold one instruction message." +msgstr "" +"ServerMessage est un conteneur utilisé pour contenir un message " +"d'instruction." + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`Status `\\ \\(code\\, message\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.Status:1 of +msgid "Client status." +msgstr "Statut du client." + +#: ../../source/ref-api/flwr.common.ClientMessage.rst:2 +#, fuzzy +msgid "ClientMessage" +msgstr "Côté client" + +#: ../../source/ref-api/flwr.common.ClientMessage.rst:31::1 +msgid ":py:obj:`evaluate_res `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.ClientMessage.rst:31::1 +msgid ":py:obj:`fit_res `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.ClientMessage.rst:31::1 msgid "" -"A new REST API has been introduced as an alternative to the gRPC-based " -"communication stack. In this initial version, the REST API only supports " -"anonymous clients." +":py:obj:`get_parameters_res " +"`\\" msgstr "" -"Une nouvelle API REST a été introduite comme alternative à la pile de " -"communication basée sur gRPC. Dans cette version initiale, l'API REST ne " -"prend en charge que les clients anonymes." -#: ../../source/ref-changelog.md:131 +#: ../../source/ref-api/flwr.common.ClientMessage.rst:31::1 msgid "" -"Please note: The REST API is still experimental and will likely change " -"significantly over time." +":py:obj:`get_properties_res " +"`\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.Code.rst:2 +msgid "Code" msgstr "" -"Remarque : l'API REST est encore expérimentale et est susceptible de " -"changer de manière significative au fil du temps." -#: ../../source/ref-changelog.md:133 +#: flwr.common.typing.Code:1 of +msgid "Bases: :py:class:`~enum.Enum`" +msgstr "" + +#: ../../source/ref-api/flwr.common.Code.rst:26::1 +msgid ":py:obj:`OK `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.Code.rst:26::1 msgid "" -"**Improve the (experimental) Driver API** " -"([#1663](https://github.com/adap/flower/pull/1663), " -"[#1666](https://github.com/adap/flower/pull/1666), " -"[#1667](https://github.com/adap/flower/pull/1667), " -"[#1664](https://github.com/adap/flower/pull/1664), " -"[#1675](https://github.com/adap/flower/pull/1675), " -"[#1676](https://github.com/adap/flower/pull/1676), " -"[#1693](https://github.com/adap/flower/pull/1693), " -"[#1662](https://github.com/adap/flower/pull/1662), " -"[#1794](https://github.com/adap/flower/pull/1794))" +":py:obj:`GET_PROPERTIES_NOT_IMPLEMENTED " +"`\\" msgstr "" -"**Améliorer l'API (expérimentale) du pilote** " -"([#1663](https://github.com/adap/flower/pull/1663), " -"[#1666](https://github.com/adap/flower/pull/1666), " -"[#1667](https://github.com/adap/flower/pull/1667), " -"[#1664](https://github.com/adap/flower/pull/1664), " -"[#1675](https://github.com/adap/flower/pull/1675), " -"[#1676](https://github.com/adap/flower/pull/1676), " -"[#1693](https://github.com/adap/flower/pull/1693), " -"[#1662](https://github.com/adap/flower/pull/1662), " -"[#1794](https://github.com/adap/flower/pull/1794))" -#: ../../source/ref-changelog.md:135 +#: ../../source/ref-api/flwr.common.Code.rst:26::1 msgid "" -"The Driver API is still an experimental feature, but this release " -"introduces some major upgrades. One of the main improvements is the " -"introduction of an SQLite database to store server state on disk (instead" -" of in-memory). Another improvement is that tasks (instructions or " -"results) that have been delivered will now be deleted. This greatly " -"improves the memory efficiency of a long-running Flower server." +":py:obj:`GET_PARAMETERS_NOT_IMPLEMENTED " +"`\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.Code.rst:26::1 +msgid ":py:obj:`FIT_NOT_IMPLEMENTED `\\" msgstr "" -"L'API du pilote est encore une fonction expérimentale, mais cette version" -" introduit quelques améliorations majeures. L'une des principales " -"améliorations est l'introduction d'une base de données SQLite pour " -"stocker l'état du serveur sur le disque (au lieu de la mémoire). Une " -"autre amélioration est que les tâches (instructions ou résultats) qui ont" -" été livrées seront désormais supprimées, ce qui améliore " -"considérablement l'efficacité de la mémoire d'un serveur Flower " -"fonctionnant depuis longtemps." -#: ../../source/ref-changelog.md:137 +#: ../../source/ref-api/flwr.common.Code.rst:26::1 msgid "" -"**Fix spilling issues related to Ray during simulations** " -"([#1698](https://github.com/adap/flower/pull/1698))" +":py:obj:`EVALUATE_NOT_IMPLEMENTED " +"`\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.DisconnectRes.rst:2 +msgid "DisconnectRes" +msgstr "" + +#: ../../source/ref-api/flwr.common.DisconnectRes.rst:28::1 +msgid ":py:obj:`reason `\\" msgstr "" -"**Répare les problèmes de déversement liés à Ray pendant les " -"simulations** ([#1698](https://github.com/adap/flower/pull/1698))" -#: ../../source/ref-changelog.md:139 +#: ../../source/ref-api/flwr.common.EvaluateIns.rst:2 #, fuzzy +msgid "EvaluateIns" +msgstr "Explications" + +#: ../../source/ref-api/flwr.common.EvaluateIns.rst:29::1 +msgid ":py:obj:`parameters `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EvaluateIns.rst:29::1 +msgid ":py:obj:`config `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EvaluateRes.rst:2 +msgid "EvaluateRes" +msgstr "" + +#: ../../source/ref-api/flwr.common.EvaluateRes.rst:31::1 +msgid ":py:obj:`status `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EvaluateRes.rst:31::1 +msgid ":py:obj:`loss `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EvaluateRes.rst:31::1 +msgid ":py:obj:`num_examples `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EvaluateRes.rst:31::1 +msgid ":py:obj:`metrics `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:2 +msgid "EventType" +msgstr "" + +#: flwr.common.telemetry.EventType:1 of +msgid "Bases: :py:class:`str`, :py:class:`~enum.Enum`" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`PING `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`START_CLIENT_ENTER `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`START_CLIENT_LEAVE `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`START_SERVER_ENTER `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`START_SERVER_LEAVE `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 msgid "" -"While running long simulations, `ray` was sometimes spilling huge amounts" -" of data that would make the training unable to continue. This is now " -"fixed! 🎉" +":py:obj:`RUN_DRIVER_API_ENTER " +"`\\" msgstr "" -"Lors de l'exécution de longues simulations, `ray` déversait parfois " -"d'énormes quantités de données qui rendaient l'entraînement incapable de " -"continuer. ce problème est maintenant corrigé ! 🎉" -#: ../../source/ref-changelog.md:141 +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 msgid "" -"**Add new example using** `TabNet` **and Flower** " -"([#1725](https://github.com/adap/flower/pull/1725))" +":py:obj:`RUN_DRIVER_API_LEAVE " +"`\\" msgstr "" -"**Ajouter un nouvel exemple utilisant** `TabNet` **et Flower** " -"([#1725](https://github.com/adap/flower/pull/1725))" -#: ../../source/ref-changelog.md:143 +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 msgid "" -"TabNet is a powerful and flexible framework for training machine learning" -" models on tabular data. We now have a federated example using Flower: " -"[https://github.com/adap/flower/tree/main/examples/tabnet](https://github.com/adap/flower/tree/main/examples/quickstart_tabnet)." +":py:obj:`RUN_FLEET_API_ENTER " +"`\\" msgstr "" -"TabNet est un cadre puissant et flexible pour former des modèles " -"d'apprentissage automatique sur des données tabulaires. Nous avons " -"maintenant un exemple fédéré utilisant Flower : " -"[https://github.com/adap/flower/tree/main/examples/tabnet](https://github.com/adap/flower/tree/main/examples/quickstart_tabnet)." -#: ../../source/ref-changelog.md:145 +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 msgid "" -"**Add new how-to guide for monitoring simulations** " -"([#1649](https://github.com/adap/flower/pull/1649))" +":py:obj:`RUN_FLEET_API_LEAVE " +"`\\" msgstr "" -"**Ajouter un nouveau guide pratique pour le suivi des simulations** " -"([#1649](https://github.com/adap/flower/pull/1649))" -#: ../../source/ref-changelog.md:147 +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 msgid "" -"We now have a documentation guide to help users monitor their performance" -" during simulations." +":py:obj:`RUN_SUPERLINK_ENTER " +"`\\" msgstr "" -"Nous avons maintenant un guide de documentation pour aider les " -"utilisateurs à surveiller leurs performances pendant les simulations." -#: ../../source/ref-changelog.md:149 +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 msgid "" -"**Add training metrics to** `History` **object during simulations** " -"([#1696](https://github.com/adap/flower/pull/1696))" +":py:obj:`RUN_SUPERLINK_LEAVE " +"`\\" msgstr "" -"**Ajouter des mesures de formation à** `History` **objet pendant les " -"simulations** ([#1696](https://github.com/adap/flower/pull/1696))" -#: ../../source/ref-changelog.md:151 +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 msgid "" -"The `fit_metrics_aggregation_fn` can be used to aggregate training " -"metrics, but previous releases did not save the results in the `History` " -"object. This is now the case!" +":py:obj:`START_SIMULATION_ENTER " +"`\\" msgstr "" -"La fonction `fit_metrics_aggregation_fn` peut être utilisée pour agréger " -"les mesures d'entraînement, mais les versions précédentes " -"n'enregistraient pas les résultats dans l'objet `History`. c'est " -"désormais le cas !" -#: ../../source/ref-changelog.md:153 +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 msgid "" -"**General improvements** " -"([#1659](https://github.com/adap/flower/pull/1659), " -"[#1646](https://github.com/adap/flower/pull/1646), " -"[#1647](https://github.com/adap/flower/pull/1647), " -"[#1471](https://github.com/adap/flower/pull/1471), " -"[#1648](https://github.com/adap/flower/pull/1648), " -"[#1651](https://github.com/adap/flower/pull/1651), " -"[#1652](https://github.com/adap/flower/pull/1652), " -"[#1653](https://github.com/adap/flower/pull/1653), " -"[#1659](https://github.com/adap/flower/pull/1659), " -"[#1665](https://github.com/adap/flower/pull/1665), " -"[#1670](https://github.com/adap/flower/pull/1670), " -"[#1672](https://github.com/adap/flower/pull/1672), " -"[#1677](https://github.com/adap/flower/pull/1677), " -"[#1684](https://github.com/adap/flower/pull/1684), " -"[#1683](https://github.com/adap/flower/pull/1683), " -"[#1686](https://github.com/adap/flower/pull/1686), " -"[#1682](https://github.com/adap/flower/pull/1682), " -"[#1685](https://github.com/adap/flower/pull/1685), " -"[#1692](https://github.com/adap/flower/pull/1692), " -"[#1705](https://github.com/adap/flower/pull/1705), " -"[#1708](https://github.com/adap/flower/pull/1708), " -"[#1711](https://github.com/adap/flower/pull/1711), " -"[#1713](https://github.com/adap/flower/pull/1713), " -"[#1714](https://github.com/adap/flower/pull/1714), " -"[#1718](https://github.com/adap/flower/pull/1718), " -"[#1716](https://github.com/adap/flower/pull/1716), " -"[#1723](https://github.com/adap/flower/pull/1723), " -"[#1735](https://github.com/adap/flower/pull/1735), " -"[#1678](https://github.com/adap/flower/pull/1678), " -"[#1750](https://github.com/adap/flower/pull/1750), " -"[#1753](https://github.com/adap/flower/pull/1753), " -"[#1736](https://github.com/adap/flower/pull/1736), " -"[#1766](https://github.com/adap/flower/pull/1766), " -"[#1760](https://github.com/adap/flower/pull/1760), " -"[#1775](https://github.com/adap/flower/pull/1775), " -"[#1776](https://github.com/adap/flower/pull/1776), " -"[#1777](https://github.com/adap/flower/pull/1777), " -"[#1779](https://github.com/adap/flower/pull/1779), " -"[#1784](https://github.com/adap/flower/pull/1784), " -"[#1773](https://github.com/adap/flower/pull/1773), " -"[#1755](https://github.com/adap/flower/pull/1755), " -"[#1789](https://github.com/adap/flower/pull/1789), " -"[#1788](https://github.com/adap/flower/pull/1788), " -"[#1798](https://github.com/adap/flower/pull/1798), " -"[#1799](https://github.com/adap/flower/pull/1799), " -"[#1739](https://github.com/adap/flower/pull/1739), " -"[#1800](https://github.com/adap/flower/pull/1800), " -"[#1804](https://github.com/adap/flower/pull/1804), " -"[#1805](https://github.com/adap/flower/pull/1805))" +":py:obj:`START_SIMULATION_LEAVE " +"`\\" msgstr "" -"**General improvements** " -"([#1659](https://github.com/adap/flower/pull/1659), " -"[#1646](https://github.com/adap/flower/pull/1646), " -"[#1647](https://github.com/adap/flower/pull/1647), " -"[#1471](https://github.com/adap/flower/pull/1471), " -"[#1648](https://github.com/adap/flower/pull/1648), " -"[#1651](https://github.com/adap/flower/pull/1651), " -"[#1652](https://github.com/adap/flower/pull/1652), " -"[#1653](https://github.com/adap/flower/pull/1653), " -"[#1659](https://github.com/adap/flower/pull/1659), " -"[#1665](https://github.com/adap/flower/pull/1665), " -"[#1670](https://github.com/adap/flower/pull/1670), " -"[#1672](https://github.com/adap/flower/pull/1672), " -"[#1677](https://github.com/adap/flower/pull/1677), " -"[#1684](https://github.com/adap/flower/pull/1684), " -"[#1683](https://github.com/adap/flower/pull/1683), " -"[#1686](https://github.com/adap/flower/pull/1686), " -"[#1682](https://github.com/adap/flower/pull/1682), " -"[#1685](https://github.com/adap/flower/pull/1685), " -"[#1692](https://github.com/adap/flower/pull/1692), " -"[#1705](https://github.com/ada" -#: ../../source/ref-changelog.md:161 -msgid "v1.3.0 (2023-02-06)" -msgstr "v1.3.0 (2023-02-06)" +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`DRIVER_CONNECT `\\" +msgstr "" -#: ../../source/ref-changelog.md:167 -msgid "" -"`Adam Narozniak`, `Alexander Viala Bellander`, `Charles Beauville`, " -"`Daniel J. Beutel`, `JDRanpariya`, `Lennart Behme`, `Taner Topal`" +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`DRIVER_DISCONNECT `\\" msgstr "" -"`Adam Narozniak`, `Alexander Viala Bellander`, `Charles Beauville`, " -"`Daniel J. Beutel`, `JDRanpariya`, `Lennart Behme`, `Taner Topal`" -#: ../../source/ref-changelog.md:171 -msgid "" -"**Add support for** `workload_id` **and** `group_id` **in Driver API** " -"([#1595](https://github.com/adap/flower/pull/1595))" +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`START_DRIVER_ENTER `\\" msgstr "" -"**Ajouter la prise en charge de** `workload_id` **et** `group_id` **dans " -"l'API du pilote** ([#1595](https://github.com/adap/flower/pull/1595))" -#: ../../source/ref-changelog.md:173 +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`START_DRIVER_LEAVE `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 msgid "" -"The (experimental) Driver API now supports a `workload_id` that can be " -"used to identify which workload a task belongs to. It also supports a new" -" `group_id` that can be used, for example, to indicate the current " -"training round. Both the `workload_id` and `group_id` enable client nodes" -" to decide whether they want to handle a task or not." +":py:obj:`RUN_CLIENT_APP_ENTER " +"`\\" msgstr "" -"L'API (expérimentale) Driver prend désormais en charge un `workload_id` " -"qui peut être utilisé pour identifier la charge de travail à laquelle une" -" tâche appartient. Elle prend également en charge un nouveau `group_id` " -"qui peut être utilisé, par exemple, pour indiquer le cycle de formation " -"en cours. Le `workload_id` et le `group_id` permettent tous deux aux " -"nœuds clients de décider s'ils veulent traiter une tâche ou non." -#: ../../source/ref-changelog.md:175 +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 msgid "" -"**Make Driver API and Fleet API address configurable** " -"([#1637](https://github.com/adap/flower/pull/1637))" +":py:obj:`RUN_CLIENT_APP_LEAVE " +"`\\" msgstr "" -"**Faire en sorte que l'adresse de l'API du conducteur et de l'API de la " -"flotte soit configurable** " -"([#1637](https://github.com/adap/flower/pull/1637))" -#: ../../source/ref-changelog.md:177 +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 msgid "" -"The (experimental) long-running Flower server (Driver API and Fleet API) " -"can now configure the server address of both Driver API (via `--driver-" -"api-address`) and Fleet API (via `--fleet-api-address`) when starting:" +":py:obj:`RUN_SERVER_APP_ENTER " +"`\\" msgstr "" -"Le serveur Flower (expérimental) de longue durée (Driver API et Fleet " -"API) peut maintenant configurer l'adresse du serveur de Driver API (via " -"`--driver-api-address`) et de Fleet API (via `--fleet-api-address`) lors " -"de son démarrage :" -#: ../../source/ref-changelog.md:179 -#, fuzzy +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 msgid "" -"`flower-superlink --driver-api-address \"0.0.0.0:8081\" --fleet-api-address " -"\"0.0.0.0:8086\"`" +":py:obj:`RUN_SERVER_APP_LEAVE " +"`\\" msgstr "" -"``flower-superlink --driver-api-address \"0.0.0.0:8081\" --fleet-api-address" -" \"0.0.0.0:8086\" ``" -#: ../../source/ref-changelog.md:181 -msgid "Both IPv4 and IPv6 addresses are supported." -msgstr "Les adresses IPv4 et IPv6 sont toutes deux prises en charge." +#: ../../source/ref-api/flwr.common.FitIns.rst:2 +msgid "FitIns" +msgstr "" -#: ../../source/ref-changelog.md:183 -msgid "" -"**Add new example of Federated Learning using fastai and Flower** " -"([#1598](https://github.com/adap/flower/pull/1598))" +#: ../../source/ref-api/flwr.common.FitIns.rst:29::1 +msgid ":py:obj:`parameters `\\" msgstr "" -"**Ajouter un nouvel exemple d'apprentissage fédéré utilisant fastai et " -"Flower** ([#1598](https://github.com/adap/flower/pull/1598))" -#: ../../source/ref-changelog.md:185 -msgid "" -"A new code example (`quickstart_fastai`) demonstrates federated learning " -"with [fastai](https://www.fast.ai/) and Flower. You can find it here: " -"[quickstart_fastai](https://github.com/adap/flower/tree/main/examples/quickstart_fastai)." +#: ../../source/ref-api/flwr.common.FitIns.rst:29::1 +msgid ":py:obj:`config `\\" msgstr "" -"Un nouvel exemple de code (`quickstart_fastai`) démontre l'apprentissage " -"fédéré avec [fastai](https://www.fast.ai/) et Flower. Tu peux le trouver " -"ici : " -"[quickstart_fastai](https://github.com/adap/flower/tree/main/examples/quickstart_fastai)." -#: ../../source/ref-changelog.md:187 -msgid "" -"**Make Android example compatible with** `flwr >= 1.0.0` **and the latest" -" versions of Android** " -"([#1603](https://github.com/adap/flower/pull/1603))" +#: ../../source/ref-api/flwr.common.FitRes.rst:2 +msgid "FitRes" +msgstr "" + +#: ../../source/ref-api/flwr.common.FitRes.rst:31::1 +msgid ":py:obj:`status `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.FitRes.rst:31::1 +msgid ":py:obj:`parameters `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.FitRes.rst:31::1 +msgid ":py:obj:`num_examples `\\" msgstr "" -"**Rendre l'exemple Android compatible avec** `flwr >= 1.0.0` **et les " -"dernières versions d'Android** " -"([#1603](https://github.com/adap/flower/pull/1603))" -#: ../../source/ref-changelog.md:189 +#: ../../source/ref-api/flwr.common.FitRes.rst:31::1 +msgid ":py:obj:`metrics `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.GetParametersIns.rst:2 #, fuzzy -msgid "" -"The Android code example has received a substantial update: the project " -"is compatible with Flower 1.0 (and later), the UI received a full " -"refresh, and the project is updated to be compatible with newer Android " -"tooling." +msgid "GetParametersIns" +msgstr ":code:`get_parameters`" + +#: ../../source/ref-api/flwr.common.GetParametersIns.rst:28::1 +msgid ":py:obj:`config `\\" msgstr "" -"L'exemple de code Android a reçu une mise à jour substantielle : le " -"projet est compatible avec Flower 1.0 et les versions ultérieures, " -"l'interface utilisateur a reçu un rafraîchissement complet, et le projet " -"est mis à jour pour être compatible avec les outils Android les plus " -"récents." -#: ../../source/ref-changelog.md:191 -msgid "" -"**Add new `FedProx` strategy** " -"([#1619](https://github.com/adap/flower/pull/1619))" +#: ../../source/ref-api/flwr.common.GetParametersRes.rst:2 +#, fuzzy +msgid "GetParametersRes" +msgstr ":code:`get_parameters`" + +#: ../../source/ref-api/flwr.common.GetParametersRes.rst:29::1 +msgid ":py:obj:`status `\\" msgstr "" -"**Ajouter une nouvelle stratégie `FedProx`** " -"([#1619](https://github.com/adap/flower/pull/1619))" -#: ../../source/ref-changelog.md:193 -msgid "" -"This " -"[strategy](https://github.com/adap/flower/blob/main/src/py/flwr/server/strategy/fedprox.py)" -" is almost identical to " -"[`FedAvg`](https://github.com/adap/flower/blob/main/src/py/flwr/server/strategy/fedavg.py)," -" but helps users replicate what is described in this " -"[paper](https://arxiv.org/abs/1812.06127). It essentially adds a " -"parameter called `proximal_mu` to regularize the local models with " -"respect to the global models." +#: ../../source/ref-api/flwr.common.GetParametersRes.rst:29::1 +msgid ":py:obj:`parameters `\\" msgstr "" -"Cette " -"[stratégie](https://github.com/adap/flower/blob/main/src/py/flwr/server/strategy/fedprox.py)" -" est presque identique à " -"[`FedAvg`](https://github.com/adap/flower/blob/main/src/py/flwr/server/strategy/fedavg.py)," -" mais aide les utilisateurs à reproduire ce qui est décrit dans cet " -"[article](https://arxiv.org/abs/1812.06127). Elle ajoute essentiellement " -"un paramètre appelé `proximal_mu` pour régulariser les modèles locaux par" -" rapport aux modèles globaux." -#: ../../source/ref-changelog.md:195 -msgid "" -"**Add new metrics to telemetry events** " -"([#1640](https://github.com/adap/flower/pull/1640))" +#: ../../source/ref-api/flwr.common.GetPropertiesIns.rst:2 +msgid "GetPropertiesIns" msgstr "" -"**Ajouter de nouvelles métriques aux événements de télémétrie** " -"([#1640](https://github.com/adap/flower/pull/1640))" -#: ../../source/ref-changelog.md:197 -msgid "" -"An updated event structure allows, for example, the clustering of events " -"within the same workload." +#: ../../source/ref-api/flwr.common.GetPropertiesIns.rst:28::1 +msgid ":py:obj:`config `\\" msgstr "" -"Une structure d'événements mise à jour permet, par exemple, de regrouper " -"des événements au sein d'une même charge de travail." -#: ../../source/ref-changelog.md:199 -msgid "" -"**Add new custom strategy tutorial section** " -"[#1623](https://github.com/adap/flower/pull/1623)" +#: ../../source/ref-api/flwr.common.GetPropertiesRes.rst:2 +msgid "GetPropertiesRes" +msgstr "" + +#: ../../source/ref-api/flwr.common.GetPropertiesRes.rst:29::1 +msgid ":py:obj:`status `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.GetPropertiesRes.rst:29::1 +msgid ":py:obj:`properties `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.NDArray.rst:2 +msgid "NDArray" +msgstr "" + +#: ../../source/ref-api/flwr.common.Parameters.rst:29::1 +msgid ":py:obj:`tensors `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.Parameters.rst:29::1 +msgid ":py:obj:`tensor_type `\\" msgstr "" -"**Ajouter une nouvelle section de tutoriel sur les stratégies " -"personnalisées** [#1623](https://github.com/adap/flower/pull/1623)" -#: ../../source/ref-changelog.md:201 +#: ../../source/ref-api/flwr.common.ReconnectIns.rst:2 #, fuzzy +msgid "ReconnectIns" +msgstr "Collecte centralisée des données" + +#: ../../source/ref-api/flwr.common.ReconnectIns.rst:28::1 +msgid ":py:obj:`seconds `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.ServerMessage.rst:2 +#, fuzzy +msgid "ServerMessage" +msgstr "Côté serveur" + +#: ../../source/ref-api/flwr.common.ServerMessage.rst:31::1 +msgid ":py:obj:`evaluate_ins `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.ServerMessage.rst:31::1 +msgid ":py:obj:`fit_ins `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.ServerMessage.rst:31::1 msgid "" -"The Flower tutorial now has a new section that covers implementing a " -"custom strategy from scratch: [Open in " -"Colab](https://colab.research.google.com/github/adap/flower/blob/main/doc/source" -"/tutorial-build-a-strategy-from-scratch-pytorch.ipynb)" +":py:obj:`get_parameters_ins " +"`\\" msgstr "" -"Le tutoriel sur les fleurs comporte désormais une nouvelle section qui " -"traite de la mise en œuvre d'une stratégie personnalisée à partir de zéro" -" : [Ouvrir dans " -"Colab](https://colab.research.google.com/github/adap/flower/blob/main/doc/source/tutorial/Flower-3-Building-a" -"-Strategy-PyTorch.ipynb)" -#: ../../source/ref-changelog.md:203 +#: ../../source/ref-api/flwr.common.ServerMessage.rst:31::1 msgid "" -"**Add new custom serialization tutorial section** " -"([#1622](https://github.com/adap/flower/pull/1622))" +":py:obj:`get_properties_ins " +"`\\" msgstr "" -"**Ajouter une nouvelle section de tutoriel sur la sérialisation " -"personnalisée** ([#1622](https://github.com/adap/flower/pull/1622))" -#: ../../source/ref-changelog.md:205 +#: ../../source/ref-api/flwr.common.Status.rst:2 #, fuzzy -msgid "" -"The Flower tutorial now has a new section that covers custom " -"serialization: [Open in " -"Colab](https://colab.research.google.com/github/adap/flower/blob/main/doc/source" -"/tutorial-customize-the-client-pytorch.ipynb)" +msgid "Status" +msgstr "Statut du client." + +#: ../../source/ref-api/flwr.common.Status.rst:29::1 +msgid ":py:obj:`code `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.Status.rst:29::1 +msgid ":py:obj:`message `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.bytes_to_ndarray.rst:2 +msgid "bytes\\_to\\_ndarray" +msgstr "" + +#: ../../source/ref-api/flwr.common.configure.rst:2 +#, fuzzy +msgid "configure" +msgstr "Configurer les clients" + +#: ../../source/ref-api/flwr.common.event.rst:2 +msgid "event" msgstr "" -"Le tutoriel sur les fleurs comporte désormais une nouvelle section qui " -"traite de la sérialisation personnalisée : [Ouvrir dans " -"Colab](https://colab.research.google.com/github/adap/flower/blob/main/doc/source/tutorial/Flower-4" -"-Client-and-NumPyClient-PyTorch.ipynb)" -#: ../../source/ref-changelog.md:207 +#: ../../source/ref-api/flwr.common.log.rst:2 +msgid "log" +msgstr "" + +#: logging.Logger.log:3 of msgid "" -"**General improvements** " -"([#1638](https://github.com/adap/flower/pull/1638), " -"[#1634](https://github.com/adap/flower/pull/1634), " -"[#1636](https://github.com/adap/flower/pull/1636), " -"[#1635](https://github.com/adap/flower/pull/1635), " -"[#1633](https://github.com/adap/flower/pull/1633), " -"[#1632](https://github.com/adap/flower/pull/1632), " -"[#1631](https://github.com/adap/flower/pull/1631), " -"[#1630](https://github.com/adap/flower/pull/1630), " -"[#1627](https://github.com/adap/flower/pull/1627), " -"[#1593](https://github.com/adap/flower/pull/1593), " -"[#1616](https://github.com/adap/flower/pull/1616), " -"[#1615](https://github.com/adap/flower/pull/1615), " -"[#1607](https://github.com/adap/flower/pull/1607), " -"[#1609](https://github.com/adap/flower/pull/1609), " -"[#1608](https://github.com/adap/flower/pull/1608), " -"[#1603](https://github.com/adap/flower/pull/1603), " -"[#1590](https://github.com/adap/flower/pull/1590), " -"[#1580](https://github.com/adap/flower/pull/1580), " -"[#1599](https://github.com/adap/flower/pull/1599), " -"[#1600](https://github.com/adap/flower/pull/1600), " -"[#1601](https://github.com/adap/flower/pull/1601), " -"[#1597](https://github.com/adap/flower/pull/1597), " -"[#1595](https://github.com/adap/flower/pull/1595), " -"[#1591](https://github.com/adap/flower/pull/1591), " -"[#1588](https://github.com/adap/flower/pull/1588), " -"[#1589](https://github.com/adap/flower/pull/1589), " -"[#1587](https://github.com/adap/flower/pull/1587), " -"[#1573](https://github.com/adap/flower/pull/1573), " -"[#1581](https://github.com/adap/flower/pull/1581), " -"[#1578](https://github.com/adap/flower/pull/1578), " -"[#1574](https://github.com/adap/flower/pull/1574), " -"[#1572](https://github.com/adap/flower/pull/1572), " -"[#1586](https://github.com/adap/flower/pull/1586))" +"To pass exception information, use the keyword argument exc_info with a " +"true value, e.g." msgstr "" -"**General improvements** " -"([#1638](https://github.com/adap/flower/pull/1638), " -"[#1634](https://github.com/adap/flower/pull/1634), " -"[#1636](https://github.com/adap/flower/pull/1636), " -"[#1635](https://github.com/adap/flower/pull/1635), " -"[#1633](https://github.com/adap/flower/pull/1633), " -"[#1632](https://github.com/adap/flower/pull/1632), " -"[#1631](https://github.com/adap/flower/pull/1631), " -"[#1630](https://github.com/adap/flower/pull/1630), " -"[#1627](https://github.com/adap/flower/pull/1627), " -"[#1593](https://github.com/adap/flower/pull/1593), " -"[#1616](https://github.com/adap/flower/pull/1616), " -"[#1615](https://github.com/adap/flower/pull/1615), " -"[#1607](https://github.com/adap/flower/pull/1607), " -"[#1609](https://github.com/adap/flower/pull/1609), " -"[#1608](https://github.com/adap/flower/pull/1608), " -"[#1603](https://github.com/adap/flower/pull/1603), " -"[#1590](https://github.com/adap/flower/pull/1590), " -"[#1580](https://github.com/adap/flower/pull/1580), " -"[#1599](https://github.com/adap/flower/pull/1599), " -"[#1600](https://github.com/ada" +"Pour transmettre des informations sur les exceptions, utilise l'argument " +"mot-clé exc_info avec une valeur vraie, par ex." -#: ../../source/ref-changelog.md:211 -msgid "" -"**Updated documentation** " -"([#1629](https://github.com/adap/flower/pull/1629), " -"[#1628](https://github.com/adap/flower/pull/1628), " -"[#1620](https://github.com/adap/flower/pull/1620), " -"[#1618](https://github.com/adap/flower/pull/1618), " -"[#1617](https://github.com/adap/flower/pull/1617), " -"[#1613](https://github.com/adap/flower/pull/1613), " -"[#1614](https://github.com/adap/flower/pull/1614))" +#: logging.Logger.log:6 of +#, python-format +msgid "logger.log(level, \"We have a %s\", \"mysterious problem\", exc_info=1)" +msgstr "logger.log(level, \"We have a %s\", \"mysterious problem\", exc_info=1)" + +#: ../../source/ref-api/flwr.common.ndarray_to_bytes.rst:2 +msgid "ndarray\\_to\\_bytes" msgstr "" -"**Mise à jour de la documentation** " -"([#1629](https://github.com/adap/flower/pull/1629), " -"[#1628](https://github.com/adap/flower/pull/1628), " -"[#1620](https://github.com/adap/flower/pull/1620), " -"[#1618](https://github.com/adap/flower/pull/1618), " -"[#1617](https://github.com/adap/flower/pull/1617), " -"[#1613](https://github.com/adap/flower/pull/1613), " -"[#1614](https://github.com/adap/flower/pull/1614))" -#: ../../source/ref-changelog.md:213 ../../source/ref-changelog.md:280 -msgid "" -"As usual, the documentation has improved quite a bit. It is another step " -"in our effort to make the Flower documentation the best documentation of " -"any project. Stay tuned and as always, feel free to provide feedback!" +#: ../../source/ref-api/flwr.common.ndarrays_to_parameters.rst:2 +msgid "ndarrays\\_to\\_parameters" msgstr "" -"Comme d'habitude, la documentation s'est beaucoup améliorée. C'est une " -"autre étape dans notre effort pour faire de la documentation de Flower la" -" meilleure documentation de tout projet. Reste à l'écoute et comme " -"toujours, n'hésite pas à nous faire part de tes commentaires !" -#: ../../source/ref-changelog.md:219 -msgid "v1.2.0 (2023-01-13)" -msgstr "v1.2.0 (2023-01-13)" +#: ../../source/ref-api/flwr.common.now.rst:2 +msgid "now" +msgstr "" -#: ../../source/ref-changelog.md:225 -msgid "" -"`Adam Narozniak`, `Charles Beauville`, `Daniel J. Beutel`, `Edoardo`, `L." -" Jiang`, `Ragy`, `Taner Topal`, `dannymcy`" +#: ../../source/ref-api/flwr.common.parameters_to_ndarrays.rst:2 +msgid "parameters\\_to\\_ndarrays" msgstr "" -"adam Narozniak`, `Charles Beauville`, `Daniel J. Beutel`, `Edoardo`, `L. " -"Jiang`, `Ragy`, `Taner Topal`, `dannymcy`" -#: ../../source/ref-changelog.md:229 -msgid "" -"**Introduce new Flower Baseline: FedAvg MNIST** " -"([#1497](https://github.com/adap/flower/pull/1497), " -"[#1552](https://github.com/adap/flower/pull/1552))" +#: ../../source/ref-api/flwr.server.rst:2 +msgid "server" +msgstr "serveur" + +#: ../../source/ref-api/flwr.server.rst:26::1 +msgid ":py:obj:`run_driver_api `\\ \\(\\)" msgstr "" -"**Introduire une nouvelle fleur Référence : FedAvg MNIST** " -"([#1497](https://github.com/adap/flower/pull/1497), " -"[#1552](https://github.com/adap/flower/pull/1552))" -#: ../../source/ref-changelog.md:231 -msgid "" -"Over the coming weeks, we will be releasing a number of new reference " -"implementations useful especially to FL newcomers. They will typically " -"revisit well known papers from the literature, and be suitable for " -"integration in your own application or for experimentation, in order to " -"deepen your knowledge of FL in general. Today's release is the first in " -"this series. [Read more.](https://flower.dev/blog/2023-01-12-fl-starter-" -"pack-fedavg-mnist-cnn/)" +#: ../../source/ref-api/flwr.server.rst:26::1 +#: flwr.server.app.run_driver_api:1 of +#, fuzzy +msgid "Run Flower server (Driver API)." +msgstr "flower-driver-api" + +#: ../../source/ref-api/flwr.server.rst:26::1 +msgid ":py:obj:`run_fleet_api `\\ \\(\\)" msgstr "" -"Au cours des prochaines semaines, nous publierons un certain nombre de " -"nouvelles implémentations de référence utiles en particulier pour les " -"nouveaux venus en FL. Elles revisiteront généralement des articles bien " -"connus de la littérature, et seront adaptées à l'intégration dans votre " -"propre application ou à l'expérimentation, afin d'approfondir votre " -"connaissance de FL en général. La publication d'aujourd'hui est la " -"première de cette série. [Lire la " -"suite.](https://flower.dev/blog/2023-01-12-fl-starter-pack-fedavg-mnist-" -"cnn/)" -#: ../../source/ref-changelog.md:233 -msgid "" -"**Improve GPU support in simulations** " -"([#1555](https://github.com/adap/flower/pull/1555))" +#: ../../source/ref-api/flwr.server.rst:26::1 +#: flwr.server.app.run_fleet_api:1 of +#, fuzzy +msgid "Run Flower server (Fleet API)." +msgstr "flower-fleet-api" + +#: ../../source/ref-api/flwr.server.rst:26::1 +msgid ":py:obj:`run_server_app `\\ \\(\\)" msgstr "" -"**Améliorer la prise en charge des GPU dans les simulations** " -"([#1555](https://github.com/adap/flower/pull/1555))" -#: ../../source/ref-changelog.md:235 -msgid "" -"The Ray-based Virtual Client Engine (`start_simulation`) has been updated" -" to improve GPU support. The update includes some of the hard-earned " -"lessons from scaling simulations in GPU cluster environments. New " -"defaults make running GPU-based simulations substantially more robust." +#: ../../source/ref-api/flwr.server.rst:26::1 +#: flwr.server.app.run_server_app:1 of +#, fuzzy +msgid "Run Flower server app." +msgstr "Serveur de Flower" + +#: ../../source/ref-api/flwr.server.rst:26::1 +msgid ":py:obj:`run_superlink `\\ \\(\\)" msgstr "" -"Le moteur client virtuel basé sur Ray (`start_simulation`) a été mis à " -"jour pour améliorer la prise en charge des GPU. La mise à jour inclut " -"certaines des leçons durement apprises lors de la mise à l'échelle des " -"simulations dans des environnements de grappes de GPU. De nouveaux " -"paramètres par défaut rendent l'exécution des simulations basées sur les " -"GPU beaucoup plus robuste." -#: ../../source/ref-changelog.md:237 +#: ../../source/ref-api/flwr.server.rst:26::1 +#: flwr.server.app.run_superlink:1 of +msgid "Run Flower server (Driver API and Fleet API)." +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:26::1 msgid "" -"**Improve GPU support in Jupyter Notebook tutorials** " -"([#1527](https://github.com/adap/flower/pull/1527), " -"[#1558](https://github.com/adap/flower/pull/1558))" +":py:obj:`start_server `\\ \\(\\*\\[\\, " +"server\\_address\\, server\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:26::1 +#: flwr.server.app.start_server:1 of +msgid "Start a Flower server using the gRPC transport layer." +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:37::1 +msgid ":py:obj:`ClientManager `\\ \\(\\)" msgstr "" -"**Améliorer la prise en charge du GPU dans les tutoriels Jupyter " -"Notebook** ([#1527](https://github.com/adap/flower/pull/1527), " -"[#1558](https://github.com/adap/flower/pull/1558))" -#: ../../source/ref-changelog.md:239 +#: ../../source/ref-api/flwr.server.rst:37::1 +#: flwr.server.client_manager.ClientManager:1 of +msgid "Abstract base class for managing Flower clients." +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:37::1 +msgid ":py:obj:`History `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:37::1 +#: flwr.server.history.History:1 of +msgid "History class for training and/or evaluation metrics collection." +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:37::1 msgid "" -"Some users reported that Jupyter Notebooks have not always been easy to " -"use on GPU instances. We listened and made improvements to all of our " -"Jupyter notebooks! Check out the updated notebooks here:" +":py:obj:`Server `\\ \\(\\*\\, client\\_manager\\[\\, " +"strategy\\]\\)" msgstr "" -"Certains utilisateurs ont signalé que les carnets Jupyter n'ont pas " -"toujours été faciles à utiliser sur les instances GPU. Nous les avons " -"écoutés et avons apporté des améliorations à tous nos carnets Jupyter ! " -"Découvre les carnets mis à jour ici :" -#: ../../source/ref-changelog.md:241 +#: ../../source/ref-api/flwr.server.rst:37::1 #, fuzzy msgid "" -"[An Introduction to Federated Learning](https://flower.dev/docs/framework" -"/tutorial-get-started-with-flower-pytorch.html)" +":py:obj:`ServerConfig `\\ \\(\\[num\\_rounds\\," +" round\\_timeout\\]\\)" msgstr "" -"[Une introduction à l'apprentissage fédéré] " -"(https://flower.dev/docs/tutorial/Flower-1-Intro-to-FL-PyTorch.html)" +"Flower 1.0 : ``start_server(..., " +"config=flwr.server.ServerConfig(num_rounds=3, round_timeout=600.0), " +"...)``" -#: ../../source/ref-changelog.md:242 +#: ../../source/ref-api/flwr.server.rst:37::1 +#: flwr.server.app.ServerConfig:1 of #, fuzzy -msgid "" -"[Strategies in Federated Learning](https://flower.dev/docs/framework" -"/tutorial-use-a-federated-learning-strategy-pytorch.html)" +msgid "Flower server config." +msgstr "Serveur de Flower" + +#: ../../source/ref-api/flwr.server.rst:37::1 +msgid ":py:obj:`SimpleClientManager `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:37::1 +#: flwr.server.client_manager.SimpleClientManager:1 of +msgid "Provides a pool of available clients." +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:56::1 +msgid ":py:obj:`flwr.server.driver `\\" msgstr "" -"[Stratégies d'apprentissage fédéré] " -"(https://flower.dev/docs/tutorial/Flower-2-Strategies-in-FL-PyTorch.html)" -#: ../../source/ref-changelog.md:243 +#: ../../source/ref-api/flwr.server.rst:56::1 flwr.server.driver:1 +#: of #, fuzzy -msgid "" -"[Building a Strategy](https://flower.dev/docs/framework/tutorial-build-a" -"-strategy-from-scratch-pytorch.html)" +msgid "Flower driver SDK." +msgstr "Serveur de Flower" + +#: ../../source/ref-api/flwr.server.rst:56::1 +#, fuzzy +msgid ":py:obj:`flwr.server.strategy `\\" +msgstr "serveur.stratégie.Stratégie" + +#: ../../source/ref-api/flwr.server.rst:56::1 +#: flwr.server.strategy:1 of +msgid "Contains the strategy abstraction and different implementations." msgstr "" -"[Construire une stratégie] " -"(https://flower.dev/docs/tutorial/Flower-3-Building-a-Strategy-" -"PyTorch.html)" -#: ../../source/ref-changelog.md:244 +#: ../../source/ref-api/flwr.server.ClientManager.rst:2 #, fuzzy -msgid "" -"[Client and NumPyClient](https://flower.dev/docs/framework/tutorial-" -"customize-the-client-pytorch.html)" +msgid "ClientManager" +msgstr "client" + +#: flwr.server.client_manager.ClientManager.all:1::1 of +msgid ":py:obj:`all `\\ \\(\\)" msgstr "" -"[Client et NumPyClient] (https://flower.dev/docs/tutorial/Flower-4" -"-Client-and-NumPyClient-PyTorch.html)" -#: ../../source/ref-changelog.md:246 -msgid "" -"**Introduce optional telemetry** " -"([#1533](https://github.com/adap/flower/pull/1533), " -"[#1544](https://github.com/adap/flower/pull/1544), " -"[#1584](https://github.com/adap/flower/pull/1584))" +#: flwr.server.client_manager.ClientManager.all:1 +#: flwr.server.client_manager.ClientManager.all:1::1 +#: flwr.server.client_manager.SimpleClientManager.all:1 +#: flwr.server.client_manager.SimpleClientManager.all:1::1 of +msgid "Return all available clients." msgstr "" -"**Introduire la télémétrie optionnelle** " -"([#1533](https://github.com/adap/flower/pull/1533), " -"[#1544](https://github.com/adap/flower/pull/1544), " -"[#1584](https://github.com/adap/flower/pull/1584))" -#: ../../source/ref-changelog.md:248 -msgid "" -"After a [request for " -"feedback](https://github.com/adap/flower/issues/1534) from the community," -" the Flower open-source project introduces optional collection of " -"*anonymous* usage metrics to make well-informed decisions to improve " -"Flower. Doing this enables the Flower team to understand how Flower is " -"used and what challenges users might face." +#: flwr.server.client_manager.ClientManager.all:1::1 of +msgid ":py:obj:`num_available `\\ \\(\\)" msgstr "" -"À la suite d'une [demande de commentaires] " -"(https://github.com/adap/flower/issues/1534) de la part de la communauté," -" le projet open-source Flower introduit la collecte optionnelle de " -"mesures d'utilisation *anonymes* afin de prendre des décisions éclairées " -"pour améliorer Flower. Cela permet à l'équipe de Flower de comprendre " -"comment Flower est utilisé et quels sont les défis auxquels les " -"utilisateurs peuvent être confrontés." -#: ../../source/ref-changelog.md:250 -#, fuzzy -msgid "" -"**Flower is a friendly framework for collaborative AI and data science.**" -" Staying true to this statement, Flower makes it easy to disable " -"telemetry for users who do not want to share anonymous usage metrics. " -"[Read more.](https://flower.dev/docs/telemetry.html)." +#: flwr.server.client_manager.ClientManager.all:1::1 +#: flwr.server.client_manager.ClientManager.num_available:1 +#: flwr.server.client_manager.SimpleClientManager.all:1::1 +#: flwr.server.client_manager.SimpleClientManager.num_available:1 of +msgid "Return the number of available clients." msgstr "" -"**Flower est un cadre convivial pour l'IA collaborative et la science des" -" données.** Restant fidèle à cette déclaration, Flower permet de " -"désactiver facilement la télémétrie pour les utilisateurs qui ne " -"souhaitent pas partager des métriques d'utilisation anonymes.[Lire la " -"suite.](https://flower.dev/docs/telemetry.html)." -#: ../../source/ref-changelog.md:252 +#: flwr.server.client_manager.ClientManager.all:1::1 of +msgid ":py:obj:`register `\\ \\(client\\)" +msgstr "" + +#: flwr.server.client_manager.ClientManager.all:1::1 +#: flwr.server.client_manager.ClientManager.register:1 +#: flwr.server.client_manager.SimpleClientManager.all:1::1 +#: flwr.server.client_manager.SimpleClientManager.register:1 of +msgid "Register Flower ClientProxy instance." +msgstr "" + +#: flwr.server.client_manager.ClientManager.all:1::1 of msgid "" -"**Introduce (experimental) Driver API** " -"([#1520](https://github.com/adap/flower/pull/1520), " -"[#1525](https://github.com/adap/flower/pull/1525), " -"[#1545](https://github.com/adap/flower/pull/1545), " -"[#1546](https://github.com/adap/flower/pull/1546), " -"[#1550](https://github.com/adap/flower/pull/1550), " -"[#1551](https://github.com/adap/flower/pull/1551), " -"[#1567](https://github.com/adap/flower/pull/1567))" +":py:obj:`sample `\\ " +"\\(num\\_clients\\[\\, min\\_num\\_clients\\, criterion\\]\\)" msgstr "" -"**([#1520](https://github.com/adap/flower/pull/1520), " -"[#1525](https://github.com/adap/flower/pull/1525), " -"[#1545](https://github.com/adap/flower/pull/1545), " -"[#1546](https://github.com/adap/flower/pull/1546), " -"[#1550](https://github.com/adap/flower/pull/1550), " -"[#1551](https://github.com/adap/flower/pull/1551), " -"[#1567](https://github.com/adap/flower/pull/1567))" -#: ../../source/ref-changelog.md:254 -msgid "" -"Flower now has a new (experimental) Driver API which will enable fully " -"programmable, async, and multi-tenant Federated Learning and Federated " -"Analytics applications. Phew, that's a lot! Going forward, the Driver API" -" will be the abstraction that many upcoming features will be built on - " -"and you can start building those things now, too." +#: flwr.server.client_manager.ClientManager.all:1::1 +#: flwr.server.client_manager.ClientManager.sample:1 +#: flwr.server.client_manager.SimpleClientManager.all:1::1 +#: flwr.server.client_manager.SimpleClientManager.sample:1 of +msgid "Sample a number of Flower ClientProxy instances." msgstr "" -"Flower dispose désormais d'une nouvelle API de pilote (expérimentale) qui" -" permettra de créer des applications Federated Learning et Federated " -"Analytics entièrement programmables, asynchrones et multi-tenant. Ouf, " -"c'est beaucoup ! À l'avenir, l'API de pilote sera l'abstraction sur " -"laquelle de nombreuses fonctionnalités à venir seront construites - et tu" -" peux commencer à construire ces choses dès maintenant, aussi." -#: ../../source/ref-changelog.md:256 -msgid "" -"The Driver API also enables a new execution mode in which the server runs" -" indefinitely. Multiple individual workloads can run concurrently and " -"start and stop their execution independent of the server. This is " -"especially useful for users who want to deploy Flower in production." +#: flwr.server.client_manager.ClientManager.all:1::1 of +msgid ":py:obj:`unregister `\\ \\(client\\)" msgstr "" -"L'API du pilote permet également un nouveau mode d'exécution dans lequel " -"le serveur s'exécute indéfiniment. Plusieurs charges de travail " -"individuelles peuvent s'exécuter simultanément et démarrer et arrêter " -"leur exécution indépendamment du serveur. Ceci est particulièrement utile" -" pour les utilisateurs qui souhaitent déployer Flower en production." -#: ../../source/ref-changelog.md:258 -msgid "" -"To learn more, check out the `mt-pytorch` code example. We look forward " -"to you feedback!" +#: flwr.server.client_manager.ClientManager.all:1::1 +#: flwr.server.client_manager.ClientManager.unregister:1 +#: flwr.server.client_manager.SimpleClientManager.all:1::1 +#: flwr.server.client_manager.SimpleClientManager.unregister:1 of +msgid "Unregister Flower ClientProxy instance." msgstr "" -"Pour en savoir plus, consulte l'exemple de code `mt-pytorch`. Nous " -"attendons tes commentaires avec impatience !" -#: ../../source/ref-changelog.md:260 +#: flwr.server.client_manager.ClientManager.all:1::1 of msgid "" -"Please note: *The Driver API is still experimental and will likely change" -" significantly over time.*" +":py:obj:`wait_for `\\ " +"\\(num\\_clients\\, timeout\\)" msgstr "" -"Remarque : *L'API du pilote est encore expérimentale et est susceptible " -"de changer de manière significative au fil du temps.*" -#: ../../source/ref-changelog.md:262 -msgid "" -"**Add new Federated Analytics with Pandas example** " -"([#1469](https://github.com/adap/flower/pull/1469), " -"[#1535](https://github.com/adap/flower/pull/1535))" +#: flwr.server.client_manager.ClientManager.all:1::1 +#: flwr.server.client_manager.ClientManager.wait_for:1 +#: flwr.server.client_manager.SimpleClientManager.all:1::1 +#: flwr.server.client_manager.SimpleClientManager.wait_for:1 of +msgid "Wait until at least `num_clients` are available." msgstr "" -"**Ajouter un nouvel exemple de Federated Analytics avec Pandas** " -"([#1469](https://github.com/adap/flower/pull/1469), " -"[#1535](https://github.com/adap/flower/pull/1535))" -#: ../../source/ref-changelog.md:264 -msgid "" -"A new code example (`quickstart_pandas`) demonstrates federated analytics" -" with Pandas and Flower. You can find it here: " -"[quickstart_pandas](https://github.com/adap/flower/tree/main/examples/quickstart_pandas)." +#: flwr.server.client_manager.ClientManager.num_available:3 +#: flwr.server.client_manager.SimpleClientManager.num_available:3 of +msgid "**num_available** -- The number of currently available clients." msgstr "" -"Un nouvel exemple de code (`quickstart_pandas`) démontre l'analyse " -"fédérée avec Pandas et Flower. Tu peux le trouver ici : " -"[quickstart_pandas](https://github.com/adap/flower/tree/main/examples/quickstart_pandas)." -#: ../../source/ref-changelog.md:266 +#: flwr.server.client_manager.ClientManager.register:6 +#: flwr.server.client_manager.SimpleClientManager.register:6 of msgid "" -"**Add new strategies: Krum and MultiKrum** " -"([#1481](https://github.com/adap/flower/pull/1481))" +"**success** -- Indicating if registration was successful. False if " +"ClientProxy is already registered or can not be registered for any " +"reason." msgstr "" -"**Ajouter de nouvelles stratégies : Krum et MultiKrum** " -"([#1481](https://github.com/adap/flower/pull/1481))" -#: ../../source/ref-changelog.md:268 -msgid "" -"Edoardo, a computer science student at the Sapienza University of Rome, " -"contributed a new `Krum` strategy that enables users to easily use Krum " -"and MultiKrum in their workloads." +#: flwr.server.client_manager.ClientManager.unregister:3 +#: flwr.server.client_manager.SimpleClientManager.unregister:3 of +msgid "This method is idempotent." msgstr "" -"Edoardo, étudiant en informatique à l'Université Sapienza de Rome, a " -"contribué à une nouvelle stratégie `Krum` qui permet aux utilisateurs " -"d'utiliser facilement Krum et MultiKrum dans leurs charges de travail." -#: ../../source/ref-changelog.md:270 -msgid "" -"**Update C++ example to be compatible with Flower v1.2.0** " -"([#1495](https://github.com/adap/flower/pull/1495))" +#: ../../source/ref-api/flwr.server.History.rst:2 +msgid "History" msgstr "" -"**Mettre à jour l'exemple C++ pour qu'il soit compatible avec Flower " -"v1.2.0** ([#1495](https://github.com/adap/flower/pull/1495))" -#: ../../source/ref-changelog.md:272 +#: flwr.server.history.History.add_loss_centralized:1::1 of msgid "" -"The C++ code example has received a substantial update to make it " -"compatible with the latest version of Flower." +":py:obj:`add_loss_centralized " +"`\\ \\(server\\_round\\, " +"loss\\)" msgstr "" -"L'exemple de code C++ a reçu une mise à jour substantielle pour le rendre" -" compatible avec la dernière version de Flower." -#: ../../source/ref-changelog.md:274 +#: flwr.server.history.History.add_loss_centralized:1 +#: flwr.server.history.History.add_loss_centralized:1::1 of +#, fuzzy +msgid "Add one loss entry (from centralized evaluation)." +msgstr "Évaluation centralisée" + +#: flwr.server.history.History.add_loss_centralized:1::1 of msgid "" -"**General improvements** " -"([#1491](https://github.com/adap/flower/pull/1491), " -"[#1504](https://github.com/adap/flower/pull/1504), " -"[#1506](https://github.com/adap/flower/pull/1506), " -"[#1514](https://github.com/adap/flower/pull/1514), " -"[#1522](https://github.com/adap/flower/pull/1522), " -"[#1523](https://github.com/adap/flower/pull/1523), " -"[#1526](https://github.com/adap/flower/pull/1526), " -"[#1528](https://github.com/adap/flower/pull/1528), " -"[#1547](https://github.com/adap/flower/pull/1547), " -"[#1549](https://github.com/adap/flower/pull/1549), " -"[#1560](https://github.com/adap/flower/pull/1560), " -"[#1564](https://github.com/adap/flower/pull/1564), " -"[#1566](https://github.com/adap/flower/pull/1566))" +":py:obj:`add_loss_distributed " +"`\\ \\(server\\_round\\, " +"loss\\)" msgstr "" -"**Améliorations générales** " -"([#1491](https://github.com/adap/flower/pull/1491), " -"[#1504](https://github.com/adap/flower/pull/1504), " -"[#1506](https://github.com/adap/flower/pull/1506), " -"[#1514](https://github.com/adap/flower/pull/1514), " -"[#1522](https://github.com/adap/flower/pull/1522), " -"[#1523](https://github.com/adap/flower/pull/1523), " -"[#1526](https://github.com/adap/flower/pull/1526), " -"[#1528](https://github.com/adap/flower/pull/1528), " -"[#1547](https://github.com/adap/flower/pull/1547), " -"[#1549](https://github.com/adap/flower/pull/1549), " -"[#1560](https://github.com/adap/flower/pull/1560), " -"[#1564](https://github.com/adap/flower/pull/1564), " -"[#1566](https://github.com/adap/flower/pull/1566))" -#: ../../source/ref-changelog.md:278 -msgid "" -"**Updated documentation** " -"([#1494](https://github.com/adap/flower/pull/1494), " -"[#1496](https://github.com/adap/flower/pull/1496), " -"[#1500](https://github.com/adap/flower/pull/1500), " -"[#1503](https://github.com/adap/flower/pull/1503), " -"[#1505](https://github.com/adap/flower/pull/1505), " -"[#1524](https://github.com/adap/flower/pull/1524), " -"[#1518](https://github.com/adap/flower/pull/1518), " -"[#1519](https://github.com/adap/flower/pull/1519), " -"[#1515](https://github.com/adap/flower/pull/1515))" +#: flwr.server.history.History.add_loss_centralized:1::1 +#: flwr.server.history.History.add_loss_distributed:1 of +msgid "Add one loss entry (from distributed evaluation)." msgstr "" -"**Documentation mise à jour** " -"([#1494](https://github.com/adap/flower/pull/1494), " -"[#1496](https://github.com/adap/flower/pull/1496), " -"[#1500](https://github.com/adap/flower/pull/1500), " -"[#1503](https://github.com/adap/flower/pull/1503), " -"[#1505](https://github.com/adap/flower/pull/1505), " -"[#1524](https://github.com/adap/flower/pull/1524), " -"[#1518](https://github.com/adap/flower/pull/1518), " -"[#1519](https://github.com/adap/flower/pull/1519), " -"[#1515](https://github.com/adap/flower/pull/1515))" -#: ../../source/ref-changelog.md:282 +#: flwr.server.history.History.add_loss_centralized:1::1 of msgid "" -"One highlight is the new [first time contributor " -"guide](https://flower.dev/docs/first-time-contributors.html): if you've " -"never contributed on GitHub before, this is the perfect place to start!" +":py:obj:`add_metrics_centralized " +"`\\ \\(server\\_round\\, " +"metrics\\)" msgstr "" -"L'un des points forts est le nouveau [guide du premier contributeur] " -"(https://flower.dev/docs/first-time-contributors.html) : si tu n'as " -"jamais contribué sur GitHub auparavant, c'est l'endroit idéal pour " -"commencer !" -#: ../../source/ref-changelog.md:288 -msgid "v1.1.0 (2022-10-31)" -msgstr "v1.1.0 (2022-10-31)" +#: flwr.server.history.History.add_loss_centralized:1::1 +#: flwr.server.history.History.add_metrics_centralized:1 of +#, fuzzy +msgid "Add metrics entries (from centralized evaluation)." +msgstr "Évaluation centralisée" -#: ../../source/ref-changelog.md:292 +#: flwr.server.history.History.add_loss_centralized:1::1 of msgid "" -"We would like to give our **special thanks** to all the contributors who " -"made the new version of Flower possible (in `git shortlog` order):" +":py:obj:`add_metrics_distributed " +"`\\ \\(server\\_round\\, " +"metrics\\)" msgstr "" -"Nous aimerions **remercier tout particulièrement** tous les contributeurs" -" qui ont rendu possible la nouvelle version de Flower (dans l'ordre `git " -"shortlog`) :" -#: ../../source/ref-changelog.md:294 -msgid "" -"`Akis Linardos`, `Christopher S`, `Daniel J. Beutel`, `George`, `Jan " -"Schlicht`, `Mohammad Fares`, `Pedro Porto Buarque de Gusmão`, `Philipp " -"Wiesner`, `Rob Luke`, `Taner Topal`, `VasundharaAgarwal`, " -"`danielnugraha`, `edogab33`" +#: flwr.server.history.History.add_loss_centralized:1::1 +#: flwr.server.history.History.add_metrics_distributed:1 of +msgid "Add metrics entries (from distributed evaluation)." msgstr "" -"`Akis Linardos`, `Christopher S`, `Daniel J. Beutel`, `George`, `Jan " -"Schlicht`, `Mohammad Fares`, `Pedro Porto Buarque de Gusmão`, `Philipp " -"Wiesner`, `Rob Luke`, `Taner Topal`, `VasundharaAgarwal`, " -"`danielnugraha`, `edogab33`" -#: ../../source/ref-changelog.md:298 +#: flwr.server.history.History.add_loss_centralized:1::1 of msgid "" -"**Introduce Differential Privacy wrappers (preview)** " -"([#1357](https://github.com/adap/flower/pull/1357), " -"[#1460](https://github.com/adap/flower/pull/1460))" +":py:obj:`add_metrics_distributed_fit " +"`\\ \\(server\\_round\\," +" ...\\)" msgstr "" -"**Introduire les enveloppes de confidentialité différentielle (aperçu)** " -"([#1357](https://github.com/adap/flower/pull/1357), " -"[#1460](https://github.com/adap/flower/pull/1460))" -#: ../../source/ref-changelog.md:300 -msgid "" -"The first (experimental) preview of pluggable Differential Privacy " -"wrappers enables easy configuration and usage of differential privacy " -"(DP). The pluggable DP wrappers enable framework-agnostic **and** " -"strategy-agnostic usage of both client-side DP and server-side DP. Head " -"over to the Flower docs, a new explainer goes into more detail." +#: flwr.server.history.History.add_loss_centralized:1::1 +#: flwr.server.history.History.add_metrics_distributed_fit:1 of +msgid "Add metrics entries (from distributed fit)." msgstr "" -"Le premier aperçu (expérimental) des wrappers enfichables de " -"confidentialité différentielle permet de configurer et d'utiliser " -"facilement la confidentialité différentielle (DP). Les wrappers DP " -"enfichables permettent une utilisation agnostique du cadre **et** de la " -"stratégie à la fois de la DP côté client et de la DP côté serveur. Va " -"voir les documents de Flower, un nouvel explicatif va plus loin dans les " -"détails." -#: ../../source/ref-changelog.md:302 -msgid "" -"**New iOS CoreML code example** " -"([#1289](https://github.com/adap/flower/pull/1289))" +#: flwr.server.server.Server.client_manager:1::1 of +msgid ":py:obj:`client_manager `\\ \\(\\)" msgstr "" -"**Nouvel exemple de code CoreML pour iOS** " -"([#1289](https://github.com/adap/flower/pull/1289))" -#: ../../source/ref-changelog.md:304 -msgid "" -"Flower goes iOS! A massive new code example shows how Flower clients can " -"be built for iOS. The code example contains both Flower iOS SDK " -"components that can be used for many tasks, and one task example running " -"on CoreML." +#: flwr.server.server.Server.client_manager:1 +#: flwr.server.server.Server.client_manager:1::1 of +msgid "Return ClientManager." msgstr "" -"Flower passe à iOS ! Un nouvel exemple de code massif montre comment les " -"clients Flower peuvent être construits pour iOS. L'exemple de code " -"contient à la fois des composants Flower iOS SDK qui peuvent être " -"utilisés pour de nombreuses tâches, et un exemple de tâche fonctionnant " -"sur CoreML." -#: ../../source/ref-changelog.md:306 +#: flwr.server.server.Server.client_manager:1::1 of msgid "" -"**New FedMedian strategy** " -"([#1461](https://github.com/adap/flower/pull/1461))" +":py:obj:`disconnect_all_clients " +"`\\ \\(timeout\\)" msgstr "" -"**Nouvelle stratégie de FedMedian** " -"([#1461](https://github.com/adap/flower/pull/1461))" -#: ../../source/ref-changelog.md:308 -msgid "" -"The new `FedMedian` strategy implements Federated Median (FedMedian) by " -"[Yin et al., 2018](https://arxiv.org/pdf/1803.01498v1.pdf)." +#: flwr.server.server.Server.client_manager:1::1 +#: flwr.server.server.Server.disconnect_all_clients:1 of +msgid "Send shutdown signal to all clients." msgstr "" -"La nouvelle stratégie `FedMedian` met en œuvre Federated Median " -"(FedMedian) par [Yin et al., 2018] " -"(https://arxiv.org/pdf/1803.01498v1.pdf)." -#: ../../source/ref-changelog.md:310 +#: flwr.server.server.Server.client_manager:1::1 of msgid "" -"**Log** `Client` **exceptions in Virtual Client Engine** " -"([#1493](https://github.com/adap/flower/pull/1493))" +":py:obj:`evaluate_round `\\ " +"\\(server\\_round\\, timeout\\)" msgstr "" -"**Log** `Client` **exceptions dans le moteur de client virtuel** " -"([#1493](https://github.com/adap/flower/pull/1493))" -#: ../../source/ref-changelog.md:312 -msgid "" -"All `Client` exceptions happening in the VCE are now logged by default " -"and not just exposed to the configured `Strategy` (via the `failures` " -"argument)." +#: flwr.server.server.Server.client_manager:1::1 +#: flwr.server.server.Server.evaluate_round:1 of +msgid "Validate current global model on a number of clients." msgstr "" -"Toutes les exceptions `Client` qui se produisent dans le VCE sont " -"maintenant enregistrées par défaut et ne sont pas seulement exposées à la" -" `Stratégie` configurée (via l'argument `failures`)." -#: ../../source/ref-changelog.md:314 -msgid "" -"**Improve Virtual Client Engine internals** " -"([#1401](https://github.com/adap/flower/pull/1401), " -"[#1453](https://github.com/adap/flower/pull/1453))" +#: flwr.server.server.Server.client_manager:1::1 of +msgid ":py:obj:`fit `\\ \\(num\\_rounds\\, timeout\\)" msgstr "" -"**Améliorer le moteur du client virtuel** " -"([#1401](https://github.com/adap/flower/pull/1401), " -"[#1453](https://github.com/adap/flower/pull/1453))" -#: ../../source/ref-changelog.md:316 -msgid "" -"Some internals of the Virtual Client Engine have been revamped. The VCE " -"now uses Ray 2.0 under the hood, the value type of the `client_resources`" -" dictionary changed to `float` to allow fractions of resources to be " -"allocated." +#: flwr.server.server.Server.client_manager:1::1 +#: flwr.server.server.Server.fit:1 of +msgid "Run federated averaging for a number of rounds." msgstr "" -"Le VCE utilise maintenant Ray 2.0 sous le capot, le type de valeur du " -"dictionnaire `client_resources` a été remplacé par `float` pour permettre" -" l'allocation de fractions de ressources." -#: ../../source/ref-changelog.md:318 +#: flwr.server.server.Server.client_manager:1::1 of msgid "" -"**Support optional** `Client`**/**`NumPyClient` **methods in Virtual " -"Client Engine**" +":py:obj:`fit_round `\\ \\(server\\_round\\," +" timeout\\)" msgstr "" -"**Support optional** `Client`**/**`NumPyClient` **methods in Virtual " -"Client Engine**" -#: ../../source/ref-changelog.md:320 -msgid "" -"The Virtual Client Engine now has full support for optional `Client` (and" -" `NumPyClient`) methods." +#: flwr.server.server.Server.client_manager:1::1 +#: flwr.server.server.Server.fit_round:1 of +msgid "Perform a single round of federated averaging." msgstr "" -"Le moteur de client virtuel prend désormais en charge les méthodes " -"optionnelles `Client` (et `NumPyClient`)." -#: ../../source/ref-changelog.md:322 +#: flwr.server.server.Server.client_manager:1::1 of msgid "" -"**Provide type information to packages using** `flwr` " -"([#1377](https://github.com/adap/flower/pull/1377))" +":py:obj:`set_max_workers `\\ " +"\\(max\\_workers\\)" msgstr "" -"**Fournir des informations de type aux paquets en utilisant** `flwr` " -"([#1377](https://github.com/adap/flower/pull/1377))" -#: ../../source/ref-changelog.md:324 -msgid "" -"The package `flwr` is now bundled with a `py.typed` file indicating that " -"the package is typed. This enables typing support for projects or " -"packages that use `flwr` by enabling them to improve their code using " -"static type checkers like `mypy`." +#: flwr.server.server.Server.client_manager:1::1 +#: flwr.server.server.Server.set_max_workers:1 of +msgid "Set the max_workers used by ThreadPoolExecutor." msgstr "" -"Le paquet `flwr` est maintenant accompagné d'un fichier `py.typed` " -"indiquant que le paquet est typé. Cela permet de prendre en charge le " -"typage pour les projets ou les paquets qui utilisent `flwr` en leur " -"permettant d'améliorer leur code à l'aide de vérificateurs de types " -"statiques comme `mypy`." -#: ../../source/ref-changelog.md:326 -msgid "" -"**Updated code example** " -"([#1344](https://github.com/adap/flower/pull/1344), " -"[#1347](https://github.com/adap/flower/pull/1347))" +#: flwr.server.server.Server.client_manager:1::1 of +msgid ":py:obj:`set_strategy `\\ \\(strategy\\)" msgstr "" -"**Exemple de code mis à jour** " -"([#1344](https://github.com/adap/flower/pull/1344), " -"[#1347](https://github.com/adap/flower/pull/1347))" -#: ../../source/ref-changelog.md:328 +#: flwr.server.server.Server.client_manager:1::1 +#: flwr.server.server.Server.set_strategy:1 of +#, fuzzy +msgid "Replace server strategy." +msgstr "stratégie.du.serveur" + +#: ../../source/ref-api/flwr.server.ServerConfig.rst:2 +#, fuzzy +msgid "ServerConfig" +msgstr "serveur" + +#: flwr.server.app.ServerConfig:3 of msgid "" -"The code examples covering scikit-learn and PyTorch Lightning have been " -"updated to work with the latest version of Flower." +"All attributes have default values which allows users to configure just " +"the ones they care about." msgstr "" -"Les exemples de code couvrant scikit-learn et PyTorch Lightning ont été " -"mis à jour pour fonctionner avec la dernière version de Flower." -#: ../../source/ref-changelog.md:330 -msgid "" -"**Updated documentation** " -"([#1355](https://github.com/adap/flower/pull/1355), " -"[#1558](https://github.com/adap/flower/pull/1558), " -"[#1379](https://github.com/adap/flower/pull/1379), " -"[#1380](https://github.com/adap/flower/pull/1380), " -"[#1381](https://github.com/adap/flower/pull/1381), " -"[#1332](https://github.com/adap/flower/pull/1332), " -"[#1391](https://github.com/adap/flower/pull/1391), " -"[#1403](https://github.com/adap/flower/pull/1403), " -"[#1364](https://github.com/adap/flower/pull/1364), " -"[#1409](https://github.com/adap/flower/pull/1409), " -"[#1419](https://github.com/adap/flower/pull/1419), " -"[#1444](https://github.com/adap/flower/pull/1444), " -"[#1448](https://github.com/adap/flower/pull/1448), " -"[#1417](https://github.com/adap/flower/pull/1417), " -"[#1449](https://github.com/adap/flower/pull/1449), " -"[#1465](https://github.com/adap/flower/pull/1465), " -"[#1467](https://github.com/adap/flower/pull/1467))" +#: ../../source/ref-api/flwr.server.ServerConfig.rst:29::1 +msgid ":py:obj:`num_rounds `\\" msgstr "" -"**Documentation mise à jour** " -"([#1355](https://github.com/adap/flower/pull/1355), " -"[#1558](https://github.com/adap/flower/pull/1558), " -"[#1379](https://github.com/adap/flower/pull/1379), " -"[#1380](https://github.com/adap/flower/pull/1380), " -"[#1381](https://github.com/adap/flower/pull/1381), " -"[#1332](https://github.com/adap/flower/pull/1332), " -"[#1391](https://github.com/adap/flower/pull/1391), " -"[#1403](https://github.com/adap/flower/pull/1403), " -"[#1364](https://github.com/adap/flower/pull/1364), " -"[#1409](https://github.com/adap/flower/pull/1409), " -"[#1419](https://github.com/adap/flower/pull/1419), " -"[#1444](https://github.com/adap/flower/pull/1444), " -"[#1448](https://github.com/adap/flower/pull/1448), " -"[#1417](https://github.com/adap/flower/pull/1417), " -"[#1449](https://github.com/adap/flower/pull/1449), " -"[#1465](https://github.com/adap/flower/pull/1465), " -"[#1467](https://github.com/adap/flower/pull/1467))" -#: ../../source/ref-changelog.md:332 -msgid "" -"There have been so many documentation updates that it doesn't even make " -"sense to list them individually." +#: ../../source/ref-api/flwr.server.ServerConfig.rst:29::1 +msgid ":py:obj:`round_timeout `\\" msgstr "" -"Il y a eu tellement de mises à jour de la documentation que cela n'a même" -" pas de sens de les énumérer individuellement." -#: ../../source/ref-changelog.md:334 -msgid "" -"**Restructured documentation** " -"([#1387](https://github.com/adap/flower/pull/1387))" +#: ../../source/ref-api/flwr.server.SimpleClientManager.rst:2 +msgid "SimpleClientManager" msgstr "" -"**Documentation restructurée** " -"([#1387](https://github.com/adap/flower/pull/1387))" -#: ../../source/ref-changelog.md:336 +#: flwr.server.client_manager.SimpleClientManager:1 of +msgid "Bases: :py:class:`~flwr.server.client_manager.ClientManager`" +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager.all:1::1 of +msgid ":py:obj:`all `\\ \\(\\)" +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager.all:1::1 of msgid "" -"The documentation has been restructured to make it easier to navigate. " -"This is just the first step in a larger effort to make the Flower " -"documentation the best documentation of any project ever. Stay tuned!" +":py:obj:`num_available `\\" +" \\(\\)" msgstr "" -"La documentation a été restructurée pour faciliter la navigation. Ce " -"n'est que la première étape d'un effort plus important visant à faire de " -"la documentation de Flower la meilleure documentation de tous les projets" -#: ../../source/ref-changelog.md:338 +#: flwr.server.client_manager.SimpleClientManager.all:1::1 of msgid "" -"**Open in Colab button** " -"([#1389](https://github.com/adap/flower/pull/1389))" +":py:obj:`register `\\ " +"\\(client\\)" msgstr "" -"**Ouvrir dans le bouton Colab** " -"([#1389](https://github.com/adap/flower/pull/1389))" -#: ../../source/ref-changelog.md:340 +#: flwr.server.client_manager.SimpleClientManager.all:1::1 of msgid "" -"The four parts of the Flower Federated Learning Tutorial now come with a " -"new `Open in Colab` button. No need to install anything on your local " -"machine, you can now use and learn about Flower in your browser, it's " -"only a single click away." +":py:obj:`sample `\\ " +"\\(num\\_clients\\[\\, min\\_num\\_clients\\, criterion\\]\\)" msgstr "" -"Les quatre parties du didacticiel d'apprentissage fédéré Flower sont " -"maintenant accompagnées d'un nouveau bouton \"Ouvrir dans Colab\". Pas " -"besoin d'installer quoi que ce soit sur ta machine locale, tu peux " -"maintenant utiliser et apprendre à connaître Flower dans ton navigateur, " -"il te suffit d'un simple clic." -#: ../../source/ref-changelog.md:342 +#: flwr.server.client_manager.SimpleClientManager.all:1::1 of msgid "" -"**Improved tutorial** ([#1468](https://github.com/adap/flower/pull/1468)," -" [#1470](https://github.com/adap/flower/pull/1470), " -"[#1472](https://github.com/adap/flower/pull/1472), " -"[#1473](https://github.com/adap/flower/pull/1473), " -"[#1474](https://github.com/adap/flower/pull/1474), " -"[#1475](https://github.com/adap/flower/pull/1475))" +":py:obj:`unregister `\\ " +"\\(client\\)" msgstr "" -"**Tutoriel amélioré** ([#1468](https://github.com/adap/flower/pull/1468)," -" [#1470](https://github.com/adap/flower/pull/1470), " -"[#1472](https://github.com/adap/flower/pull/1472), " -"[#1473](https://github.com/adap/flower/pull/1473), " -"[#1474](https://github.com/adap/flower/pull/1474), " -"[#1475](https://github.com/adap/flower/pull/1475))" -#: ../../source/ref-changelog.md:344 +#: flwr.server.client_manager.SimpleClientManager.all:1::1 of msgid "" -"The Flower Federated Learning Tutorial has two brand-new parts covering " -"custom strategies (still WIP) and the distinction between `Client` and " -"`NumPyClient`. The existing parts one and two have also been improved " -"(many small changes and fixes)." +":py:obj:`wait_for `\\ " +"\\(num\\_clients\\[\\, timeout\\]\\)" msgstr "" -"Le tutoriel sur l'apprentissage fédéré des fleurs a deux toutes nouvelles" -" parties couvrant les stratégies personnalisées (encore WIP) et la " -"distinction entre `Client` et `NumPyClient`. Les parties un et deux " -"existantes ont également été améliorées (beaucoup de petits changements " -"et de corrections)." -#: ../../source/ref-changelog.md:350 -msgid "v1.0.0 (2022-07-28)" -msgstr "v1.0.0 (2022-07-28)" +#: flwr.server.client_manager.SimpleClientManager.wait_for:3 of +msgid "" +"Blocks until the requested number of clients is available or until a " +"timeout is reached. Current timeout default: 1 day." +msgstr "" -#: ../../source/ref-changelog.md:352 -msgid "Highlights" -msgstr "Points forts" +#: flwr.server.client_manager.SimpleClientManager.wait_for:6 of +msgid "The number of clients to wait for." +msgstr "" -#: ../../source/ref-changelog.md:354 -msgid "Stable **Virtual Client Engine** (accessible via `start_simulation`)" -msgstr "Moteur de client virtuel stable** (accessible via `start_simulation`)" +#: flwr.server.client_manager.SimpleClientManager.wait_for:8 of +msgid "The time in seconds to wait for, defaults to 86400 (24h)." +msgstr "" -#: ../../source/ref-changelog.md:355 -msgid "All `Client`/`NumPyClient` methods are now optional" -msgstr "Toutes les méthodes `Client`/`NumPyClient` sont maintenant optionnelles" +#: flwr.server.client_manager.SimpleClientManager.wait_for:11 of +msgid "**success**" +msgstr "" -#: ../../source/ref-changelog.md:356 -msgid "Configurable `get_parameters`" -msgstr "`get_parameters` configurable" +#: ../../source/ref-api/flwr.server.driver.rst:2 +#, fuzzy +msgid "driver" +msgstr "serveur" -#: ../../source/ref-changelog.md:357 +#: ../../source/ref-api/flwr.server.driver.rst:22::1 msgid "" -"Tons of small API cleanups resulting in a more coherent developer " -"experience" +":py:obj:`start_driver `\\ \\(\\*\\[\\, " +"server\\_address\\, server\\, ...\\]\\)" msgstr "" -"Des tonnes de petits nettoyages d'API résultant en une expérience plus " -"cohérente pour les développeurs" -#: ../../source/ref-changelog.md:361 +#: ../../source/ref-api/flwr.server.driver.rst:22::1 +#: flwr.server.driver.app.start_driver:1 of +#, fuzzy +msgid "Start a Flower Driver API server." +msgstr "Tout d'abord, démarre un serveur Flower :" + +#: ../../source/ref-api/flwr.server.driver.rst:30::1 msgid "" -"We would like to give our **special thanks** to all the contributors who " -"made Flower 1.0 possible (in reverse [GitHub " -"Contributors](https://github.com/adap/flower/graphs/contributors) order):" +":py:obj:`Driver `\\ " +"\\(\\[driver\\_service\\_address\\, ...\\]\\)" msgstr "" -"Nous tenons à remercier **particulièrement** tous les contributeurs qui " -"ont rendu Flower 1.0 possible (dans l'ordre inverse de [GitHub " -"Contributors](https://github.com/adap/flower/graphs/contributors)) :" -#: ../../source/ref-changelog.md:363 -msgid "" -"[@rtaiello](https://github.com/rtaiello), " -"[@g-pichler](https://github.com/g-pichler), [@rob-" -"luke](https://github.com/rob-luke), [@andreea-zaharia](https://github.com" -"/andreea-zaharia), [@kinshukdua](https://github.com/kinshukdua), " -"[@nfnt](https://github.com/nfnt), " -"[@tatiana-s](https://github.com/tatiana-s), " -"[@TParcollet](https://github.com/TParcollet), " -"[@vballoli](https://github.com/vballoli), " -"[@negedng](https://github.com/negedng), " -"[@RISHIKESHAVAN](https://github.com/RISHIKESHAVAN), " -"[@hei411](https://github.com/hei411), " -"[@SebastianSpeitel](https://github.com/SebastianSpeitel), " -"[@AmitChaulwar](https://github.com/AmitChaulwar), " -"[@Rubiel1](https://github.com/Rubiel1), [@FANTOME-PAN](https://github.com" -"/FANTOME-PAN), [@Rono-BC](https://github.com/Rono-BC), " -"[@lbhm](https://github.com/lbhm), " -"[@sishtiaq](https://github.com/sishtiaq), " -"[@remde](https://github.com/remde), [@Jueun-Park](https://github.com" -"/Jueun-Park), [@architjen](https://github.com/architjen), " -"[@PratikGarai](https://github.com/PratikGarai), " -"[@mrinaald](https://github.com/mrinaald), " -"[@zliel](https://github.com/zliel), " -"[@MeiruiJiang](https://github.com/MeiruiJiang), " -"[@sandracl72](https://github.com/sandracl72), " -"[@gubertoli](https://github.com/gubertoli), " -"[@Vingt100](https://github.com/Vingt100), " -"[@MakGulati](https://github.com/MakGulati), " -"[@cozek](https://github.com/cozek), " -"[@jafermarq](https://github.com/jafermarq), " -"[@sisco0](https://github.com/sisco0), " -"[@akhilmathurs](https://github.com/akhilmathurs), " -"[@CanTuerk](https://github.com/CanTuerk), " -"[@mariaboerner1987](https://github.com/mariaboerner1987), " -"[@pedropgusmao](https://github.com/pedropgusmao), " -"[@tanertopal](https://github.com/tanertopal), " -"[@danieljanes](https://github.com/danieljanes)." +#: ../../source/ref-api/flwr.server.driver.rst:30::1 +#: flwr.server.driver.driver.Driver:1 of +msgid "`Driver` class provides an interface to the Driver API." msgstr "" -"[@rtaiello](https://github.com/rtaiello), " -"[@g-pichler](https://github.com/g-pichler), [@rob-" -"luke](https://github.com/rob-luke), [@andreea-zaharia](https://github.com" -"/andreea-zaharia), [@kinshukdua](https://github.com/kinshukdua), " -"[@nfnt](https://github.com/nfnt), " -"[@tatiana-s](https://github.com/tatiana-s), " -"[@TParcollet](https://github.com/TParcollet), " -"[@vballoli](https://github.com/vballoli), " -"[@negedng](https://github.com/negedng), " -"[@RISHIKESHAVAN](https://github.com/RISHIKESHAVAN), " -"[@hei411](https://github.com/hei411), " -"[@SebastianSpeitel](https://github.com/SebastianSpeitel), " -"[@AmitChaulwar](https://github.com/AmitChaulwar), " -"[@Rubiel1](https://github.com/Rubiel1), [@FANTOME-PAN](https://github.com" -"/FANTOME-PAN), [@Rono-BC](https://github.com/Rono-BC), " -"[@lbhm](https://github.com/lbhm), " -"[@sishtiaq](https://github.com/sishtiaq), " -"[@remde](https://github.com/remde), [@Jueun-Park](https://github.com" -"/Jueun-Park), [@architjen](https://github.com/architjen), " -"[@PratikGarai](https://github.com/PratikGarai), [@mrinaald](" -#: ../../source/ref-changelog.md:367 +#: ../../source/ref-api/flwr.server.driver.rst:30::1 msgid "" -"**All arguments must be passed as keyword arguments** " -"([#1338](https://github.com/adap/flower/pull/1338))" +":py:obj:`GrpcDriver `\\ " +"\\(\\[driver\\_service\\_address\\, ...\\]\\)" msgstr "" -"**Tous les arguments doivent être passés comme des arguments de mot-clé**" -" ([#1338](https://github.com/adap/flower/pull/1338))" -#: ../../source/ref-changelog.md:369 +#: ../../source/ref-api/flwr.server.driver.rst:30::1 +#: flwr.server.driver.grpc_driver.GrpcDriver:1 of +msgid "`GrpcDriver` provides access to the gRPC Driver API/service." +msgstr "" + +#: ../../source/ref-api/flwr.server.driver.Driver.rst:2 #, fuzzy +msgid "Driver" +msgstr "serveur" + +#: flwr.server.driver.driver.Driver:3 of msgid "" -"Pass all arguments as keyword arguments, positional arguments are not " -"longer supported. Code that uses positional arguments (e.g., " -"`start_client(\"127.0.0.1:8080\", FlowerClient())`) must add the keyword " -"for each positional argument (e.g., " -"`start_client(server_address=\"127.0.0.1:8080\", " -"client=FlowerClient())`)." +"The IPv4 or IPv6 address of the Driver API server. Defaults to " +"`\"[::]:9091\"`." msgstr "" -"Le code qui utilise des arguments positionnels (par exemple, " -"``start_client(\"127.0.0.1:8080\", FlowerClient())`) doit ajouter le mot-" -"clé pour chaque argument positionnel (par exemple, " -"``start_client(server_address=\"127.0.0.1:8080\", " -"client=FlowerClient())`)." -#: ../../source/ref-changelog.md:371 +#: flwr.server.app.start_server:28 flwr.server.driver.driver.Driver:6 of msgid "" -"**Introduce configuration object** `ServerConfig` **in** `start_server` " -"**and** `start_simulation` " -"([#1317](https://github.com/adap/flower/pull/1317))" +"Tuple containing root certificate, server certificate, and private key to" +" start a secure SSL-enabled server. The tuple is expected to have three " +"bytes elements in the following order: * CA certificate. * " +"server certificate. * server private key." msgstr "" -"**Introduire l'objet de configuration** `ServerConfig` **dans** " -"`start_server` **et** `start_simulation` " -"([#1317](https://github.com/adap/flower/pull/1317))" -#: ../../source/ref-changelog.md:373 +#: flwr.server.app.start_server:28 flwr.server.driver.driver.Driver:6 of msgid "" -"Instead of a config dictionary `{\"num_rounds\": 3, \"round_timeout\": " -"600.0}`, `start_server` and `start_simulation` now expect a configuration" -" object of type `flwr.server.ServerConfig`. `ServerConfig` takes the same" -" arguments that as the previous config dict, but it makes writing type-" -"safe code easier and the default parameters values more transparent." +"Tuple containing root certificate, server certificate, and private key to" +" start a secure SSL-enabled server. The tuple is expected to have three " +"bytes elements in the following order:" +msgstr "" + +#: flwr.server.app.start_server:32 flwr.server.driver.driver.Driver:10 of +#, fuzzy +msgid "CA certificate." +msgstr "Certificats" + +#: flwr.server.app.start_server:33 flwr.server.driver.driver.Driver:11 of +#, fuzzy +msgid "server certificate." +msgstr "Certificats" + +#: flwr.server.app.start_server:34 flwr.server.driver.driver.Driver:12 of +#, fuzzy +msgid "server private key." +msgstr "stratégie.du.serveur" + +#: flwr.server.driver.driver.Driver.get_nodes:1::1 of +msgid ":py:obj:`get_nodes `\\ \\(\\)" msgstr "" -"Au lieu d'un dictionnaire de configuration `{\"num_rounds\" : 3, " -"\"round_timeout\" : 600.0}`, `start_server` et `start_simulation` " -"attendent maintenant un objet de configuration de type " -"`flwr.server.ServerConfig`. `ServerConfig` prend les mêmes arguments que " -"le dict de configuration précédent, mais il rend l'écriture de code " -"sécurisé plus facile et les valeurs des paramètres par défaut plus " -"transparentes." -#: ../../source/ref-changelog.md:375 +#: flwr.server.driver.driver.Driver.get_nodes:1 +#: flwr.server.driver.driver.Driver.get_nodes:1::1 of +msgid "Get node IDs." +msgstr "" + +#: flwr.server.driver.driver.Driver.get_nodes:1::1 of msgid "" -"**Rename built-in strategy parameters for clarity** " -"([#1334](https://github.com/adap/flower/pull/1334))" +":py:obj:`pull_task_res `\\ " +"\\(task\\_ids\\)" +msgstr "" + +#: flwr.server.driver.driver.Driver.get_nodes:1::1 +#: flwr.server.driver.driver.Driver.pull_task_res:1 +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 +#: flwr.server.driver.grpc_driver.GrpcDriver.pull_task_res:1 of +msgid "Get task results." msgstr "" -"**Renommer les paramètres de la stratégie intégrée pour plus de clarté** " -"([#1334](https://github.com/adap/flower/pull/1334))" -#: ../../source/ref-changelog.md:377 +#: flwr.server.driver.driver.Driver.get_nodes:1::1 of msgid "" -"The following built-in strategy parameters were renamed to improve " -"readability and consistency with other API's:" +":py:obj:`push_task_ins `\\ " +"\\(task\\_ins\\_list\\)" msgstr "" -"Les paramètres de stratégie intégrés suivants ont été renommés pour " -"améliorer la lisibilité et la cohérence avec d'autres API :" -#: ../../source/ref-changelog.md:379 -msgid "`fraction_eval` --> `fraction_evaluate`" -msgstr "`fraction_eval` --> `fraction_evaluate`" +#: flwr.server.driver.driver.Driver.get_nodes:1::1 +#: flwr.server.driver.driver.Driver.push_task_ins:1 +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 +#: flwr.server.driver.grpc_driver.GrpcDriver.push_task_ins:1 of +msgid "Schedule tasks." +msgstr "" -#: ../../source/ref-changelog.md:380 -msgid "`min_eval_clients` --> `min_evaluate_clients`" -msgstr "`min_eval_clients` --> `min_evaluate_clients`" +#: ../../source/ref-api/flwr.server.driver.GrpcDriver.rst:2 +msgid "GrpcDriver" +msgstr "" -#: ../../source/ref-changelog.md:381 -msgid "`eval_fn` --> `evaluate_fn`" -msgstr "`eval_fn` --> `evaluate_fn`" +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 of +msgid ":py:obj:`connect `\\ \\(\\)" +msgstr "" -#: ../../source/ref-changelog.md:383 -msgid "" -"**Update default arguments of built-in strategies** " -"([#1278](https://github.com/adap/flower/pull/1278))" +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1 +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 of +msgid "Connect to the Driver API." msgstr "" -"**Mettre à jour les arguments par défaut des stratégies intégrées** " -"([#1278](https://github.com/adap/flower/pull/1278))" -#: ../../source/ref-changelog.md:385 +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 of msgid "" -"All built-in strategies now use `fraction_fit=1.0` and " -"`fraction_evaluate=1.0`, which means they select *all* currently " -"available clients for training and evaluation. Projects that relied on " -"the previous default values can get the previous behaviour by " -"initializing the strategy in the following way:" +":py:obj:`create_run `\\ " +"\\(req\\)" msgstr "" -"Toutes les stratégies intégrées utilisent désormais `fraction_fit=1.0` et" -" `fraction_evaluate=1.0`, ce qui signifie qu'elles sélectionnent *tous* " -"les clients actuellement disponibles pour l'entraînement et l'évaluation." -" Les projets qui s'appuyaient sur les valeurs par défaut précédentes " -"peuvent retrouver le comportement antérieur en initialisant la stratégie " -"de la manière suivante :" -#: ../../source/ref-changelog.md:387 -msgid "`strategy = FedAvg(fraction_fit=0.1, fraction_evaluate=0.1)`" -msgstr "`stratégie = FedAvg(fraction_fit=0.1, fraction_evaluate=0.1)`" +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 +#: flwr.server.driver.grpc_driver.GrpcDriver.create_run:1 of +#, fuzzy +msgid "Request for run ID." +msgstr "Demande pour une nouvelle Flower Baseline" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 of +msgid ":py:obj:`disconnect `\\ \\(\\)" +msgstr "" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 +#: flwr.server.driver.grpc_driver.GrpcDriver.disconnect:1 of +msgid "Disconnect from the Driver API." +msgstr "" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 of +msgid ":py:obj:`get_nodes `\\ \\(req\\)" +msgstr "" -#: ../../source/ref-changelog.md:389 +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 +#: flwr.server.driver.grpc_driver.GrpcDriver.get_nodes:1 of +#, fuzzy +msgid "Get client IDs." +msgstr "Moteur client Edge" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 of msgid "" -"**Add** `server_round` **to** `Strategy.evaluate` " -"([#1334](https://github.com/adap/flower/pull/1334))" +":py:obj:`pull_task_res `\\ " +"\\(req\\)" msgstr "" -"**Ajouter** `server_round` **à** `Strategy.evaluate` " -"([#1334](https://github.com/adap/flower/pull/1334))" -#: ../../source/ref-changelog.md:391 +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 of msgid "" -"The `Strategy` method `evaluate` now receives the current round of " -"federated learning/evaluation as the first parameter." +":py:obj:`push_task_ins `\\ " +"\\(req\\)" msgstr "" -"La méthode `Stratégie` `évaluer` reçoit maintenant le cycle actuel " -"d'apprentissage/évaluation fédéré comme premier paramètre." -#: ../../source/ref-changelog.md:393 +#: ../../source/ref-api/flwr.server.driver.start_driver.rst:2 +#, fuzzy +msgid "start\\_driver" +msgstr "start_client" + +#: flwr.server.driver.app.start_driver:3 of msgid "" -"**Add** `server_round` **and** `config` **parameters to** `evaluate_fn` " -"([#1334](https://github.com/adap/flower/pull/1334))" +"The IPv4 or IPv6 address of the Driver API server. Defaults to " +"`\"[::]:8080\"`." msgstr "" -"**Ajouter** `server_round` **et** `config` **paramètres à** `evaluate_fn`" -" ([#1334](https://github.com/adap/flower/pull/1334))" -#: ../../source/ref-changelog.md:395 +#: flwr.server.driver.app.start_driver:6 of msgid "" -"The `evaluate_fn` passed to built-in strategies like `FedAvg` now takes " -"three parameters: (1) The current round of federated learning/evaluation " -"(`server_round`), (2) the model parameters to evaluate (`parameters`), " -"and (3) a config dictionary (`config`)." +"A server implementation, either `flwr.server.Server` or a subclass " +"thereof. If no instance is provided, then `start_driver` will create one." msgstr "" -"Le `evaluate_fn` passé aux stratégies intégrées comme `FedAvg` prend " -"maintenant trois paramètres : (1) le cycle actuel " -"d'apprentissage/évaluation fédéré (`server_round`), (2) les paramètres du" -" modèle à évaluer (`parameters`), et (3) un dictionnaire de configuration" -" (`config`)." -#: ../../source/ref-changelog.md:397 +#: flwr.server.app.start_server:9 flwr.server.driver.app.start_driver:10 +#: flwr.simulation.app.start_simulation:28 of msgid "" -"**Rename** `rnd` **to** `server_round` " -"([#1321](https://github.com/adap/flower/pull/1321))" +"Currently supported values are `num_rounds` (int, default: 1) and " +"`round_timeout` in seconds (float, default: None)." msgstr "" -"**Rename** `rnd` **to** `server_round` " -"([#1321](https://github.com/adap/flower/pull/1321))" -#: ../../source/ref-changelog.md:399 +#: flwr.server.app.start_server:12 flwr.server.driver.app.start_driver:13 of msgid "" -"Several Flower methods and functions (`evaluate_fn`, `configure_fit`, " -"`aggregate_fit`, `configure_evaluate`, `aggregate_evaluate`) receive the " -"current round of federated learning/evaluation as their first parameter. " -"To improve reaability and avoid confusion with *random*, this parameter " -"has been renamed from `rnd` to `server_round`." +"An implementation of the abstract base class " +"`flwr.server.strategy.Strategy`. If no strategy is provided, then " +"`start_server` will use `flwr.server.strategy.FedAvg`." msgstr "" -"Plusieurs méthodes et fonctions de Flower (`evaluate_fn`, " -"`configure_fit`, `aggregate_fit`, `configure_evaluate`, " -"`aggregate_evaluate`) reçoivent le cycle actuel " -"d'apprentissage/évaluation fédéré comme premier paramètre. Pour améliorer" -" la fiabilité et éviter la confusion avec *random*, ce paramètre a été " -"renommé de `rnd` à `server_round`." -#: ../../source/ref-changelog.md:401 +#: flwr.server.driver.app.start_driver:17 of msgid "" -"**Move** `flwr.dataset` **to** `flwr_baselines` " -"([#1273](https://github.com/adap/flower/pull/1273))" +"An implementation of the class `flwr.server.ClientManager`. If no " +"implementation is provided, then `start_driver` will use " +"`flwr.server.SimpleClientManager`." msgstr "" -"**Déplacer** `flwr.dataset` **vers** `flwr_baselines` " -"([#1273](https://github.com/adap/flower/pull/1273))" -#: ../../source/ref-changelog.md:403 -msgid "The experimental package `flwr.dataset` was migrated to Flower Baselines." -msgstr "Le paquet expérimental `flwr.dataset` a été migré vers Flower Baselines." +#: flwr.server.app.start_server:37 flwr.server.driver.app.start_driver:26 of +msgid "**hist** -- Object containing training and evaluation metrics." +msgstr "" -#: ../../source/ref-changelog.md:405 -msgid "" -"**Remove experimental strategies** " -"([#1280](https://github.com/adap/flower/pull/1280))" +#: flwr.server.driver.app.start_driver:31 of +msgid "Starting a driver that connects to an insecure server:" msgstr "" -"**Supprimer les stratégies expérimentales** " -"([#1280](https://github.com/adap/flower/pull/1280))" -#: ../../source/ref-changelog.md:407 -msgid "" -"Remove unmaintained experimental strategies (`FastAndSlow`, `FedFSv0`, " -"`FedFSv1`)." +#: flwr.server.driver.app.start_driver:35 of +msgid "Starting a driver that connects to an SSL-enabled server:" msgstr "" -"Supprimer les stratégies expérimentales non maintenues (`FastAndSlow`, " -"`FedFSv0`, `FedFSv1`)." -#: ../../source/ref-changelog.md:409 -msgid "" -"**Rename** `Weights` **to** `NDArrays` " -"([#1258](https://github.com/adap/flower/pull/1258), " -"[#1259](https://github.com/adap/flower/pull/1259))" +#: ../../source/ref-api/flwr.server.run_driver_api.rst:2 +#, fuzzy +msgid "run\\_driver\\_api" +msgstr "flower-driver-api" + +#: ../../source/ref-api/flwr.server.run_fleet_api.rst:2 +msgid "run\\_fleet\\_api" msgstr "" -"**Rename** `Weights` **to** `NDArrays` " -"([#1258](https://github.com/adap/flower/pull/1258), " -"[#1259](https://github.com/adap/flower/pull/1259))" -#: ../../source/ref-changelog.md:411 -msgid "" -"`flwr.common.Weights` was renamed to `flwr.common.NDArrays` to better " -"capture what this type is all about." +#: ../../source/ref-api/flwr.server.run_server_app.rst:2 +msgid "run\\_server\\_app" msgstr "" -"`flwr.common.Weights` a été renommé en `flwr.common.NDArys` pour mieux " -"rendre compte de la nature de ce type." -#: ../../source/ref-changelog.md:413 -msgid "" -"**Remove antiquated** `force_final_distributed_eval` **from** " -"`start_server` ([#1258](https://github.com/adap/flower/pull/1258), " -"[#1259](https://github.com/adap/flower/pull/1259))" +#: ../../source/ref-api/flwr.server.run_superlink.rst:2 +#, fuzzy +msgid "run\\_superlink" +msgstr "flower-superlink" + +#: ../../source/ref-api/flwr.server.start_server.rst:2 +#, fuzzy +msgid "start\\_server" +msgstr "serveur.start_server" + +#: flwr.server.app.start_server:3 of +msgid "The IPv4 or IPv6 address of the server. Defaults to `\"[::]:8080\"`." msgstr "" -"**Supprimez l'ancien** `force_final_distributed_eval` **de** " -"`start_server` ([#1258](https://github.com/adap/flower/pull/1258), " -"[#1259](https://github.com/adap/flower/pull/1259))" -#: ../../source/ref-changelog.md:415 +#: flwr.server.app.start_server:5 of msgid "" -"The `start_server` parameter `force_final_distributed_eval` has long been" -" a historic artefact, in this release it is finally gone for good." +"A server implementation, either `flwr.server.Server` or a subclass " +"thereof. If no instance is provided, then `start_server` will create one." msgstr "" -"Le paramètre `start_server` `force_final_distributed_eval` a longtemps " -"été un artefact historique, dans cette version il a finalement disparu " -"pour de bon." -#: ../../source/ref-changelog.md:417 +#: flwr.server.app.start_server:16 of msgid "" -"**Make** `get_parameters` **configurable** " -"([#1242](https://github.com/adap/flower/pull/1242))" +"An implementation of the abstract base class `flwr.server.ClientManager`." +" If no implementation is provided, then `start_server` will use " +"`flwr.server.client_manager.SimpleClientManager`." msgstr "" -"**Make** `get_parameters` **configurable** " -"([#1242](https://github.com/adap/flower/pull/1242))" -#: ../../source/ref-changelog.md:419 +#: flwr.server.app.start_server:21 of msgid "" -"The `get_parameters` method now accepts a configuration dictionary, just " -"like `get_properties`, `fit`, and `evaluate`." +"The maximum length of gRPC messages that can be exchanged with the Flower" +" clients. The default should be sufficient for most models. Users who " +"train very large models might need to increase this value. Note that the " +"Flower clients need to be started with the same value (see " +"`flwr.client.start_client`), otherwise clients will not know about the " +"increased limit and block larger messages." msgstr "" -"La méthode `get_parameters` accepte maintenant un dictionnaire de " -"configuration, tout comme `get_properties`, `fit`, et `evaluate`." -#: ../../source/ref-changelog.md:421 +#: flwr.server.app.start_server:42 of +#, fuzzy +msgid "Starting an insecure server:" +msgstr "Démarrer le serveur" + +#: flwr.server.app.start_server:46 of +#, fuzzy +msgid "Starting an SSL-enabled server:" +msgstr "Démarrer le serveur" + +#: ../../source/ref-api/flwr.server.strategy.rst:2 +#, fuzzy +msgid "strategy" +msgstr "stratégie.du.serveur" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 msgid "" -"**Replace** `num_rounds` **in** `start_simulation` **with new** `config` " -"**parameter** ([#1281](https://github.com/adap/flower/pull/1281))" +":py:obj:`FaultTolerantFedAvg " +"`\\ \\(\\*\\[\\, " +"fraction\\_fit\\, ...\\]\\)" msgstr "" -"**Remplace** `num_rounds` **dans** `start_simulation` **avec le nouveau**" -" `config` **paramètre** " -"([#1281](https://github.com/adap/flower/pull/1281))" -#: ../../source/ref-changelog.md:423 -msgid "" -"The `start_simulation` function now accepts a configuration dictionary " -"`config` instead of the `num_rounds` integer. This improves the " -"consistency between `start_simulation` and `start_server` and makes " -"transitioning between the two easier." +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg:1 of +msgid "Configurable fault-tolerant FedAvg strategy implementation." msgstr "" -"La fonction `start_simulation` accepte maintenant un dictionnaire de " -"configuration `config` au lieu de l'entier `num_rounds`. Cela améliore la" -" cohérence entre `start_simulation` et `start_server` et facilite la " -"transition entre les deux." -#: ../../source/ref-changelog.md:427 +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 msgid "" -"**Support Python 3.10** " -"([#1320](https://github.com/adap/flower/pull/1320))" +":py:obj:`FedAdagrad `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, ...\\]\\)" msgstr "" -"**Support Python 3.10** " -"([#1320](https://github.com/adap/flower/pull/1320))" -#: ../../source/ref-changelog.md:429 +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedadagrad.FedAdagrad:1 of +#, fuzzy +msgid "FedAdagrad strategy - Adaptive Federated Optimization using Adagrad." +msgstr "" +"`FedAdam` et `FedAdam` correspondent à la dernière version de l'article " +"sur l'optimisation fédérée adaptative." + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 msgid "" -"The previous Flower release introduced experimental support for Python " -"3.10, this release declares Python 3.10 support as stable." +":py:obj:`FedAdam `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, ...\\]\\)" msgstr "" -"La version précédente de Flower a introduit la prise en charge " -"expérimentale de Python 3.10, cette version déclare la prise en charge de" -" Python 3.10 comme stable." -#: ../../source/ref-changelog.md:431 +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedadam.FedAdam:1 of +msgid "FedAdam - Adaptive Federated Optimization using Adam." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 msgid "" -"**Make all** `Client` **and** `NumPyClient` **methods optional** " -"([#1260](https://github.com/adap/flower/pull/1260), " -"[#1277](https://github.com/adap/flower/pull/1277))" +":py:obj:`FedAvg `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, fraction\\_evaluate\\, ...\\]\\)" msgstr "" -"**Rendre toutes les **méthodes `Client` **et** `NumPyClient` " -"**facultatives** ([#1260](https://github.com/adap/flower/pull/1260), " -"[#1277](https://github.com/adap/flower/pull/1277))" -#: ../../source/ref-changelog.md:433 +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedavg.FedAvg:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:1 of +#, fuzzy +msgid "Federated Averaging strategy." +msgstr "Stratégie de moyenne fédérée." + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 msgid "" -"The `Client`/`NumPyClient` methods `get_properties`, `get_parameters`, " -"`fit`, and `evaluate` are all optional. This enables writing clients that" -" implement, for example, only `fit`, but no other method. No need to " -"implement `evaluate` when using centralized evaluation!" +":py:obj:`FedXgbNnAvg `\\ \\(\\*args\\, " +"\\*\\*kwargs\\)" msgstr "" -"Les méthodes `Client`/`NumPyClient` `get_properties`, `get_parameters`, " -"`fit`, et `evaluate` sont toutes optionnelles. Cela permet d'écrire des " -"clients qui n'implémentent, par exemple, que `fit`, mais aucune autre " -"méthode. Pas besoin d'implémenter `evaluate` quand on utilise " -"l'évaluation centralisée !" -#: ../../source/ref-changelog.md:435 +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg:1 of +msgid "Configurable FedXgbNnAvg strategy implementation." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 msgid "" -"**Enable passing a** `Server` **instance to** `start_simulation` " -"([#1281](https://github.com/adap/flower/pull/1281))" +":py:obj:`FedXgbBagging `\\ " +"\\(\\[evaluate\\_function\\]\\)" msgstr "" -"**Autoriser le passage d'une **instance `Server` à** `start_simulation` " -"([#1281](https://github.com/adap/flower/pull/1281))" -#: ../../source/ref-changelog.md:437 +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging:1 of +msgid "Configurable FedXgbBagging strategy implementation." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 msgid "" -"Similar to `start_server`, `start_simulation` now accepts a full `Server`" -" instance. This enables users to heavily customize the execution of " -"eperiments and opens the door to running, for example, async FL using the" -" Virtual Client Engine." +":py:obj:`FedXgbCyclic `\\ " +"\\(\\*\\*kwargs\\)" msgstr "" -"Comme pour `start_server`, `start_simulation` accepte maintenant une " -"instance complète de `Server`. Cela permet aux utilisateurs de " -"personnaliser fortement l'exécution des expériences et ouvre la porte à " -"l'exécution, par exemple, de FL asynchrones à l'aide du moteur de client " -"virtuel." -#: ../../source/ref-changelog.md:439 +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic:1 of +msgid "Configurable FedXgbCyclic strategy implementation." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 msgid "" -"**Update code examples** " -"([#1291](https://github.com/adap/flower/pull/1291), " -"[#1286](https://github.com/adap/flower/pull/1286), " -"[#1282](https://github.com/adap/flower/pull/1282))" +":py:obj:`FedAvgAndroid `\\ " +"\\(\\*\\[\\, fraction\\_fit\\, ...\\]\\)" msgstr "" -"**Mettre à jour les exemples de code** " -"([#1291](https://github.com/adap/flower/pull/1291), " -"[#1286](https://github.com/adap/flower/pull/1286), " -"[#1282](https://github.com/adap/flower/pull/1282))" -#: ../../source/ref-changelog.md:441 +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 msgid "" -"Many code examples received small or even large maintenance updates, " -"among them are" +":py:obj:`FedAvgM `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, ...\\]\\)" msgstr "" -"De nombreux exemples de code ont reçu de petites ou même de grandes mises" -" à jour de maintenance" - -#: ../../source/ref-changelog.md:443 -msgid "`scikit-learn`" -msgstr "`scikit-learn`" -#: ../../source/ref-changelog.md:444 -msgid "`simulation_pytorch`" -msgstr "`simulation_pytorch`" +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedavgm.FedAvgM:1 of +#, fuzzy +msgid "Federated Averaging with Momentum strategy." +msgstr "Stratégie de moyenne fédérée." -#: ../../source/ref-changelog.md:445 -msgid "`quickstart_pytorch`" -msgstr "`quickstart_pytorch` (démarrage rapide)" +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedOpt `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, fraction\\_evaluate\\, ...\\]\\)" +msgstr "" -#: ../../source/ref-changelog.md:446 -msgid "`quickstart_simulation`" -msgstr "`quickstart_simulation`" +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedopt.FedOpt:1 of +#, fuzzy +msgid "Federated Optim strategy." +msgstr "Stratégie de moyenne fédérée." -#: ../../source/ref-changelog.md:447 -msgid "`quickstart_tensorflow`" -msgstr "`quickstart_tensorflow`" +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedProx `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, ...\\]\\)" +msgstr "" -#: ../../source/ref-changelog.md:448 -msgid "`advanced_tensorflow`" -msgstr "`advanced_tensorflow` (en anglais)" +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedprox.FedProx:1 of +#, fuzzy +msgid "Federated Optimization strategy." +msgstr "Stratégie de moyenne fédérée." -#: ../../source/ref-changelog.md:450 +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 msgid "" -"**Remove the obsolete simulation example** " -"([#1328](https://github.com/adap/flower/pull/1328))" +":py:obj:`FedYogi `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, ...\\]\\)" msgstr "" -"**Supprime l'exemple de simulation obsolète** " -"([#1328](https://github.com/adap/flower/pull/1328))" -#: ../../source/ref-changelog.md:452 -msgid "" -"Removes the obsolete `simulation` example and renames " -"`quickstart_simulation` to `simulation_tensorflow` so it fits withs the " -"naming of `simulation_pytorch`" +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedyogi.FedYogi:1 of +msgid "FedYogi [Reddi et al., 2020] strategy." msgstr "" -"Supprime l'exemple obsolète `simulation` et renomme " -"`quickstart_simulation` en `simulation_tensorflow` pour qu'il corresponde" -" au nom de `simulation_pytorch`" -#: ../../source/ref-changelog.md:454 +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 msgid "" -"**Update documentation** " -"([#1223](https://github.com/adap/flower/pull/1223), " -"[#1209](https://github.com/adap/flower/pull/1209), " -"[#1251](https://github.com/adap/flower/pull/1251), " -"[#1257](https://github.com/adap/flower/pull/1257), " -"[#1267](https://github.com/adap/flower/pull/1267), " -"[#1268](https://github.com/adap/flower/pull/1268), " -"[#1300](https://github.com/adap/flower/pull/1300), " -"[#1304](https://github.com/adap/flower/pull/1304), " -"[#1305](https://github.com/adap/flower/pull/1305), " -"[#1307](https://github.com/adap/flower/pull/1307))" +":py:obj:`QFedAvg `\\ \\(\\*\\[\\, " +"q\\_param\\, qffl\\_learning\\_rate\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.qfedavg.QFedAvg:1 of +msgid "Configurable QFedAvg strategy implementation." msgstr "" -"**Mise à jour de la documentation** " -"([#1223](https://github.com/adap/flower/pull/1223), " -"[#1209](https://github.com/adap/flower/pull/1209), " -"[#1251](https://github.com/adap/flower/pull/1251), " -"[#1257](https://github.com/adap/flower/pull/1257), " -"[#1267](https://github.com/adap/flower/pull/1267), " -"[#1268](https://github.com/adap/flower/pull/1268), " -"[#1300](https://github.com/adap/flower/pull/1300), " -"[#1304](https://github.com/adap/flower/pull/1304), " -"[#1305](https://github.com/adap/flower/pull/1305), " -"[#1307](https://github.com/adap/flower/pull/1307))" -#: ../../source/ref-changelog.md:456 +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 msgid "" -"One substantial documentation update fixes multiple smaller rendering " -"issues, makes titles more succinct to improve navigation, removes a " -"deprecated library, updates documentation dependencies, includes the " -"`flwr.common` module in the API reference, includes support for markdown-" -"based documentation, migrates the changelog from `.rst` to `.md`, and " -"fixes a number of smaller details!" +":py:obj:`FedMedian `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, ...\\]\\)" msgstr "" -"Une mise à jour substantielle de la documentation corrige plusieurs " -"petits problèmes de rendu, rend les titres plus succincts pour améliorer " -"la navigation, supprime une bibliothèque obsolète, met à jour les " -"dépendances de la documentation, inclut le module `flwr.common` dans la " -"référence de l'API, inclut le support de la documentation basée sur le " -"markdown, migre le changelog de `.rst` vers `.md`, et corrige un certain " -"nombre de détails plus petits !" -#: ../../source/ref-changelog.md:458 ../../source/ref-changelog.md:513 -#: ../../source/ref-changelog.md:582 ../../source/ref-changelog.md:621 -msgid "**Minor updates**" -msgstr "**Mises à jour mineures**" +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedmedian.FedMedian:1 of +#, fuzzy +msgid "Configurable FedMedian strategy implementation." +msgstr "Configuration de l'évaluation fédérée" -#: ../../source/ref-changelog.md:460 +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 msgid "" -"Add round number to fit and evaluate log messages " -"([#1266](https://github.com/adap/flower/pull/1266))" +":py:obj:`FedTrimmedAvg `\\ " +"\\(\\*\\[\\, fraction\\_fit\\, ...\\]\\)" msgstr "" -"Ajoute un chiffre rond pour ajuster et évaluer les messages du journal " -"([#1266](https://github.com/adap/flower/pull/1266))" -#: ../../source/ref-changelog.md:461 -msgid "" -"Add secure gRPC connection to the `advanced_tensorflow` code example " -"([#847](https://github.com/adap/flower/pull/847))" +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:1 of +msgid "Federated Averaging with Trimmed Mean [Dong Yin, et al., 2021]." msgstr "" -"Ajouter une connexion gRPC sécurisée à l'exemple de code " -"`advanced_tensorflow` ([#847](https://github.com/adap/flower/pull/847))" -#: ../../source/ref-changelog.md:462 +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 msgid "" -"Update developer tooling " -"([#1231](https://github.com/adap/flower/pull/1231), " -"[#1276](https://github.com/adap/flower/pull/1276), " -"[#1301](https://github.com/adap/flower/pull/1301), " -"[#1310](https://github.com/adap/flower/pull/1310))" +":py:obj:`Krum `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, fraction\\_evaluate\\, ...\\]\\)" msgstr "" -"Mettre à jour les outils de développement " -"([#1231](https://github.com/adap/flower/pull/1231), " -"[#1276](https://github.com/adap/flower/pull/1276), " -"[#1301](https://github.com/adap/flower/pull/1301), " -"[#1310](https://github.com/adap/flower/pull/1310))" -#: ../../source/ref-changelog.md:463 +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.krum.Krum:1 of +msgid "Krum [Blanchard et al., 2017] strategy." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 msgid "" -"Rename ProtoBuf messages to improve consistency " -"([#1214](https://github.com/adap/flower/pull/1214), " -"[#1258](https://github.com/adap/flower/pull/1258), " -"[#1259](https://github.com/adap/flower/pull/1259))" +":py:obj:`Bulyan `\\ \\(\\*\\, " +"fraction\\_fit\\, fraction\\_evaluate\\, ...\\)" msgstr "" -"Renomme les messages ProtoBuf pour améliorer la cohérence " -"([#1214](https://github.com/adap/flower/pull/1214), " -"[#1258](https://github.com/adap/flower/pull/1258), " -"[#1259](https://github.com/adap/flower/pull/1259))" -#: ../../source/ref-changelog.md:465 -msgid "v0.19.0 (2022-05-18)" -msgstr "v0.19.0 (2022-05-18)" +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.bulyan.Bulyan:1 of +#, fuzzy +msgid "Bulyan strategy." +msgstr "Stratégies intégrées" -#: ../../source/ref-changelog.md:469 +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 msgid "" -"**Flower Baselines (preview): FedOpt, FedBN, FedAvgM** " -"([#919](https://github.com/adap/flower/pull/919), " -"[#1127](https://github.com/adap/flower/pull/1127), " -"[#914](https://github.com/adap/flower/pull/914))" +":py:obj:`DPFedAvgAdaptive `\\ " +"\\(strategy\\, num\\_sampled\\_clients\\)" msgstr "" -"**Flower Baselines (preview) : FedOpt, FedBN, FedAvgM** " -"([#919](https://github.com/adap/flower/pull/919), " -"[#1127](https://github.com/adap/flower/pull/1127), " -"[#914](https://github.com/adap/flower/pull/914))" -#: ../../source/ref-changelog.md:471 -msgid "" -"The first preview release of Flower Baselines has arrived! We're " -"kickstarting Flower Baselines with implementations of FedOpt (FedYogi, " -"FedAdam, FedAdagrad), FedBN, and FedAvgM. Check the documentation on how " -"to use [Flower Baselines](https://flower.dev/docs/using-baselines.html). " -"With this first preview release we're also inviting the community to " -"[contribute their own baselines](https://flower.dev/docs/contributing-" -"baselines.html)." +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.dpfedavg_adaptive.DPFedAvgAdaptive:1 of +msgid "Wrapper for configuring a Strategy for DP with Adaptive Clipping." msgstr "" -"La première version préliminaire de Flower Baselines est arrivée ! Nous " -"démarrons Flower Baselines avec des implémentations de FedOpt (FedYogi, " -"FedAdam, FedAdagrad), FedBN, et FedAvgM. Consultez la documentation sur " -"l'utilisation de [Flower Baselines](https://flower.dev/docs/using-" -"baselines.html). Avec cette première version préliminaire, nous invitons " -"également la communauté à [contribuer à leurs propres lignes de " -"base](https://flower.dev/docs/contributing-baselines.html)." -#: ../../source/ref-changelog.md:473 +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 msgid "" -"**C++ client SDK (preview) and code example** " -"([#1111](https://github.com/adap/flower/pull/1111))" +":py:obj:`DPFedAvgFixed `\\ " +"\\(strategy\\, num\\_sampled\\_clients\\, ...\\)" msgstr "" -"**SDK client C++ (aperçu) et exemple de code** " -"([#1111](https://github.com/adap/flower/pull/1111))" -#: ../../source/ref-changelog.md:475 -msgid "" -"Preview support for Flower clients written in C++. The C++ preview " -"includes a Flower client SDK and a quickstart code example that " -"demonstrates a simple C++ client using the SDK." +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed:1 of +msgid "Wrapper for configuring a Strategy for DP with Fixed Clipping." msgstr "" -"L'aperçu C++ comprend un SDK pour les clients Flower et un exemple de " -"code de démarrage rapide qui démontre un client C++ simple utilisant le " -"SDK." -#: ../../source/ref-changelog.md:477 +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#, fuzzy +msgid ":py:obj:`Strategy `\\ \\(\\)" +msgstr "serveur.stratégie.Stratégie" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.strategy.Strategy:1 of +msgid "Abstract base class for server strategy implementations." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.Bulyan.rst:2 +msgid "Bulyan" +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:1 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg:1 +#: flwr.server.strategy.fedavgm.FedAvgM:1 +#: flwr.server.strategy.fedmedian.FedMedian:1 +#: flwr.server.strategy.fedopt.FedOpt:1 flwr.server.strategy.fedprox.FedProx:1 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging:1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic:1 +#: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg:1 +#: flwr.server.strategy.krum.Krum:1 flwr.server.strategy.qfedavg.QFedAvg:1 of +msgid "Bases: :py:class:`~flwr.server.strategy.fedavg.FedAvg`" +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:3 of +msgid "Implementation based on https://arxiv.org/abs/1802.07927." +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:5 +#: flwr.server.strategy.fedadagrad.FedAdagrad:5 +#: flwr.server.strategy.fedadam.FedAdam:5 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:5 +#: flwr.server.strategy.fedavgm.FedAvgM:5 flwr.server.strategy.fedopt.FedOpt:5 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:5 +#: flwr.server.strategy.fedyogi.FedYogi:5 flwr.server.strategy.krum.Krum:5 of +msgid "Fraction of clients used during training. Defaults to 1.0." +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:7 +#: flwr.server.strategy.fedadagrad.FedAdagrad:7 +#: flwr.server.strategy.fedadam.FedAdam:7 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:7 +#: flwr.server.strategy.fedavgm.FedAvgM:7 flwr.server.strategy.fedopt.FedOpt:7 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:7 +#: flwr.server.strategy.fedyogi.FedYogi:7 flwr.server.strategy.krum.Krum:7 of +msgid "Fraction of clients used during validation. Defaults to 1.0." +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:9 +#: flwr.server.strategy.fedadagrad.FedAdagrad:9 +#: flwr.server.strategy.fedadam.FedAdam:9 flwr.server.strategy.fedavg.FedAvg:13 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:9 +#: flwr.server.strategy.fedavgm.FedAvgM:9 flwr.server.strategy.fedopt.FedOpt:9 +#: flwr.server.strategy.fedprox.FedProx:45 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:9 +#: flwr.server.strategy.fedyogi.FedYogi:9 flwr.server.strategy.krum.Krum:9 of +msgid "Minimum number of clients used during training. Defaults to 2." +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:11 +#: flwr.server.strategy.fedadagrad.FedAdagrad:11 +#: flwr.server.strategy.fedadam.FedAdam:11 +#: flwr.server.strategy.fedavg.FedAvg:15 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:11 +#: flwr.server.strategy.fedavgm.FedAvgM:11 +#: flwr.server.strategy.fedopt.FedOpt:11 +#: flwr.server.strategy.fedprox.FedProx:47 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:11 +#: flwr.server.strategy.fedyogi.FedYogi:11 flwr.server.strategy.krum.Krum:11 of +msgid "Minimum number of clients used during validation. Defaults to 2." +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:13 +#: flwr.server.strategy.fedadagrad.FedAdagrad:13 +#: flwr.server.strategy.fedadam.FedAdam:13 +#: flwr.server.strategy.fedavg.FedAvg:17 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:13 +#: flwr.server.strategy.fedavgm.FedAvgM:13 +#: flwr.server.strategy.fedopt.FedOpt:13 +#: flwr.server.strategy.fedprox.FedProx:49 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:13 +#: flwr.server.strategy.fedyogi.FedYogi:13 flwr.server.strategy.krum.Krum:13 of +msgid "Minimum number of total clients in the system. Defaults to 2." +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:15 flwr.server.strategy.krum.Krum:15 of +msgid "Number of malicious clients in the system. Defaults to 0." +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:17 +#: flwr.server.strategy.fedadagrad.FedAdagrad:15 +#: flwr.server.strategy.fedadam.FedAdam:15 +#: flwr.server.strategy.fedavg.FedAvg:19 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:15 +#: flwr.server.strategy.fedavgm.FedAvgM:15 +#: flwr.server.strategy.fedopt.FedOpt:15 +#: flwr.server.strategy.fedprox.FedProx:51 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:15 +#: flwr.server.strategy.fedyogi.FedYogi:17 +#: flwr.server.strategy.fedyogi.FedYogi:18 +#: flwr.server.strategy.fedyogi.FedYogi:19 flwr.server.strategy.krum.Krum:20 of +msgid "Optional function used for validation. Defaults to None." +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:19 +#: flwr.server.strategy.fedadagrad.FedAdagrad:17 +#: flwr.server.strategy.fedadam.FedAdam:17 +#: flwr.server.strategy.fedavg.FedAvg:21 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:17 +#: flwr.server.strategy.fedavgm.FedAvgM:17 +#: flwr.server.strategy.fedopt.FedOpt:17 +#: flwr.server.strategy.fedprox.FedProx:53 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:17 +#: flwr.server.strategy.fedyogi.FedYogi:20 flwr.server.strategy.krum.Krum:22 of +msgid "Function used to configure training. Defaults to None." +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:21 +#: flwr.server.strategy.fedadagrad.FedAdagrad:19 +#: flwr.server.strategy.fedadam.FedAdam:19 +#: flwr.server.strategy.fedavg.FedAvg:23 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:19 +#: flwr.server.strategy.fedavgm.FedAvgM:19 +#: flwr.server.strategy.fedopt.FedOpt:19 +#: flwr.server.strategy.fedprox.FedProx:55 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:19 +#: flwr.server.strategy.fedyogi.FedYogi:22 flwr.server.strategy.krum.Krum:24 of +msgid "Function used to configure validation. Defaults to None." +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:23 +#: flwr.server.strategy.fedadagrad.FedAdagrad:25 +#: flwr.server.strategy.fedadam.FedAdam:21 +#: flwr.server.strategy.fedavg.FedAvg:25 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:21 +#: flwr.server.strategy.fedavgm.FedAvgM:21 +#: flwr.server.strategy.fedopt.FedOpt:21 +#: flwr.server.strategy.fedprox.FedProx:57 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:21 +#: flwr.server.strategy.fedyogi.FedYogi:24 flwr.server.strategy.krum.Krum:26 of +msgid "Whether or not accept rounds containing failures. Defaults to True." +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:25 +#: flwr.server.strategy.fedadagrad.FedAdagrad:27 +#: flwr.server.strategy.fedadam.FedAdam:23 +#: flwr.server.strategy.fedavg.FedAvg:27 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:24 +#: flwr.server.strategy.fedavgm.FedAvgM:23 +#: flwr.server.strategy.fedopt.FedOpt:23 +#: flwr.server.strategy.fedprox.FedProx:59 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:23 +#: flwr.server.strategy.fedyogi.FedYogi:26 flwr.server.strategy.krum.Krum:28 of +#, fuzzy +msgid "Initial global model parameters." +msgstr "Initialise le modèle global" + +#: flwr.server.strategy.bulyan.Bulyan:27 of msgid "" -"**Add experimental support for Python 3.10 and Python 3.11** " -"([#1135](https://github.com/adap/flower/pull/1135))" +"Byzantine resilient aggregation rule that is used as the first step of " +"the Bulyan (e.g., Krum)" msgstr "" -"**Ajouter la prise en charge expérimentale de Python 3.10 et Python " -"3.11** ([#1135](https://github.com/adap/flower/pull/1135))" -#: ../../source/ref-changelog.md:479 -msgid "" -"Python 3.10 is the latest stable release of Python and Python 3.11 is due" -" to be released in October. This Flower release adds experimental support" -" for both Python versions." +#: flwr.server.strategy.bulyan.Bulyan:29 of +msgid "arguments to the first_aggregation rule" msgstr "" -"Python 3.10 est la dernière version stable de Python et Python 3.11 " -"devrait sortir en octobre. Cette version de Flower ajoute une prise en " -"charge expérimentale pour les deux versions de Python." -#: ../../source/ref-changelog.md:481 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"**Aggregate custom metrics through user-provided functions** " -"([#1144](https://github.com/adap/flower/pull/1144))" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\, " +"results\\, ...\\)" msgstr "" -"**Agréger des mesures personnalisées grâce à des fonctions fournies par " -"l'utilisateur** ([#1144](https://github.com/adap/flower/pull/1144))" -#: ../../source/ref-changelog.md:483 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +#, fuzzy +msgid "Aggregate evaluation losses using weighted average." +msgstr "Résultats globaux de l'évaluation." + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Custom metrics (e.g., `accuracy`) can now be aggregated without having to" -" customize the strategy. Built-in strategies support two new arguments, " -"`fit_metrics_aggregation_fn` and `evaluate_metrics_aggregation_fn`, that " -"allow passing custom metric aggregation functions." +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" msgstr "" -"Les stratégies intégrées prennent en charge deux nouveaux arguments, " -"`fit_metrics_aggregation_fn` et `evaluate_metrics_aggregation_fn`, qui " -"permettent de passer des fonctions d'agrégation de métriques " -"personnalisées." -#: ../../source/ref-changelog.md:485 +#: flwr.server.strategy.bulyan.Bulyan.aggregate_fit:1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +#, fuzzy +msgid "Aggregate fit results using Bulyan." +msgstr "Résultats globaux de l'évaluation." + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\, " +"parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.configure_evaluate:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.configure_evaluate:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.configure_evaluate:1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.configure_evaluate:1 +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: flwr.server.strategy.strategy.Strategy.configure_evaluate:1 of +#, fuzzy +msgid "Configure the next round of evaluation." +msgstr "Configuration de l'évaluation côté serveur" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_adaptive.DPFedAvgAdaptive.configure_fit:1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.configure_fit:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.configure_fit:1 +#: flwr.server.strategy.fedprox.FedProx.configure_fit:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.configure_fit:1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.configure_fit:1 +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: flwr.server.strategy.strategy.Strategy.configure_fit:1 of +msgid "Configure the next round of training." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.evaluate:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.evaluate:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.evaluate:1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg.evaluate:1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "Evaluate model parameters using an evaluation function." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.initialize_parameters:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.initialize_parameters:1 +#: flwr.server.strategy.fedavgm.FedAvgM.initialize_parameters:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +#, fuzzy +msgid "Initialize global model parameters." +msgstr "Initialise le modèle global" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"**User-configurable round timeout** " -"([#1162](https://github.com/adap/flower/pull/1162))" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"**Temps d'attente configurable par l'utilisateur** " -"([#1162](https://github.com/adap/flower/pull/1162))" -#: ../../source/ref-changelog.md:487 -msgid "" -"A new configuration value allows the round timeout to be set for " -"`start_server` and `start_simulation`. If the `config` dictionary " -"contains a `round_timeout` key (with a `float` value in seconds), the " -"server will wait *at least* `round_timeout` seconds before it closes the " -"connection." +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.num_evaluation_clients:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.num_evaluation_clients:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.num_evaluation_clients:1 of +msgid "Use a fraction of available clients for evaluation." msgstr "" -"Si le dictionnaire `config` contient une clé `round_timeout` (avec une " -"valeur `float` en secondes), le serveur attendra *au moins* " -"`round_timeout` secondes avant de fermer la connexion." -#: ../../source/ref-changelog.md:489 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"**Enable both federated evaluation and centralized evaluation to be used " -"at the same time in all built-in strategies** " -"([#1091](https://github.com/adap/flower/pull/1091))" +":py:obj:`num_fit_clients `\\" +" \\(num\\_available\\_clients\\)" msgstr "" -"**Permettre l'utilisation simultanée de l'évaluation fédérée et de " -"l'évaluation centralisée dans toutes les stratégies intégrées** " -"([#1091](https://github.com/adap/flower/pull/1091))" -#: ../../source/ref-changelog.md:491 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.num_fit_clients:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.num_fit_clients:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.num_fit_clients:1 of +msgid "Return the sample size and the required number of available clients." +msgstr "" + +#: flwr.server.strategy.dpfedavg_adaptive.DPFedAvgAdaptive:1 of +msgid "Bases: :py:class:`~flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed`" +msgstr "" + +#: flwr.server.strategy.dpfedavg_adaptive.DPFedAvgAdaptive:3 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed:3 of +msgid "This class is deprecated and will be removed in a future release." +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of msgid "" -"Built-in strategies can now perform both federated evaluation (i.e., " -"client-side) and centralized evaluation (i.e., server-side) in the same " -"round. Federated evaluation can be disabled by setting `fraction_eval` to" -" `0.0`." +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" msgstr "" -"Les stratégies intégrées peuvent maintenant effectuer une évaluation " -"fédérée (c'est-à-dire côté client) et une évaluation centralisée " -"(c'est-à-dire côté serveur) dans le même tour. L'évaluation fédérée peut " -"être désactivée en réglant `fraction_eval` sur `0.0`." -#: ../../source/ref-changelog.md:493 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +#, fuzzy +msgid "Aggregate evaluation losses using the given strategy." +msgstr "Résultats globaux de l'évaluation." + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of msgid "" -"**Two new Jupyter Notebook tutorials** " -"([#1141](https://github.com/adap/flower/pull/1141))" +":py:obj:`aggregate_fit " +"`\\ " +"\\(server\\_round\\, results\\, failures\\)" msgstr "" -"**Deux nouveaux tutoriels Jupyter Notebook** " -"([#1141](https://github.com/adap/flower/pull/1141))" -#: ../../source/ref-changelog.md:495 +#: flwr.server.strategy.dpfedavg_adaptive.DPFedAvgAdaptive.aggregate_fit:1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "Aggregate training results as in DPFedAvgFixed and update clip norms." +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of msgid "" -"Two Jupyter Notebook tutorials (compatible with Google Colab) explain " -"basic and intermediate Flower features:" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" -"Deux tutoriels Jupyter Notebook (compatibles avec Google Colab) " -"expliquent les fonctionnalités de base et intermédiaires de Flower :" -#: ../../source/ref-changelog.md:497 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate:1 of +msgid "Configure the next round of evaluation using the specified strategy." +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of msgid "" -"*An Introduction to Federated Learning*: [Open in " -"Colab](https://colab.research.google.com/github/adap/flower/blob/main/tutorials/Flower-1" -"-Intro-to-FL-PyTorch.ipynb)" +":py:obj:`configure_fit " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" -"*Introduction à l'apprentissage fédéré* : [Open in " -"Colab](https://colab.research.google.com/github/adap/flower/blob/main/tutorials/Flower-1" -"-Intro-to-FL-PyTorch.ipynb)" -#: ../../source/ref-changelog.md:499 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of msgid "" -"*Using Strategies in Federated Learning*: [Open in " -"Colab](https://colab.research.google.com/github/adap/flower/blob/main/tutorials/Flower-2" -"-Strategies-in-FL-PyTorch.ipynb)" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" msgstr "" -"*Utiliser des stratégies dans l'apprentissage fédéré* : [Open in " -"Colab](https://colab.research.google.com/github/adap/flower/blob/main/tutorials/Flower-2" -"-Strategies-in-FL-PyTorch.ipynb)" -#: ../../source/ref-changelog.md:501 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.evaluate:1 of +msgid "Evaluate model parameters using an evaluation function from the strategy." +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of msgid "" -"**New FedAvgM strategy (Federated Averaging with Server Momentum)** " -"([#1076](https://github.com/adap/flower/pull/1076))" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" msgstr "" -"**Nouvelle stratégie FedAvgM (Federated Averaging with Server Momentum)**" -" ([#1076](https://github.com/adap/flower/pull/1076))" -#: ../../source/ref-changelog.md:503 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.initialize_parameters:1 of +msgid "Initialize global model parameters using given strategy." +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate:3 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:6 +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:3 +#: flwr.server.strategy.strategy.Strategy.aggregate_fit:3 +#: flwr.server.strategy.strategy.Strategy.configure_evaluate:3 +#: flwr.server.strategy.strategy.Strategy.configure_fit:3 +#: flwr.server.strategy.strategy.Strategy.evaluate:6 of #, fuzzy +msgid "The current round of federated learning." +msgstr "Qu'est-ce que l'apprentissage fédéré ?" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate:7 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:10 +#: flwr.server.strategy.strategy.Strategy.configure_evaluate:7 +#: flwr.server.strategy.strategy.Strategy.configure_fit:7 +#: flwr.server.strategy.strategy.Strategy.initialize_parameters:3 of +msgid "The client manager which holds all currently connected clients." +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate:10 +#: flwr.server.strategy.strategy.Strategy.configure_evaluate:10 of msgid "" -"The new `FedAvgM` strategy implements Federated Averaging with Server " -"Momentum \\[Hsu et al., 2019\\]." +"**evaluate_configuration** -- A list of tuples. Each tuple in the list " +"identifies a `ClientProxy` and the `EvaluateIns` for this particular " +"`ClientProxy`. If a particular `ClientProxy` is not included in this " +"list, it means that this `ClientProxy` will not participate in the next " +"round of federated evaluation." msgstr "" -"La nouvelle stratégie `FedAvgM` met en œuvre la moyenne fédérée avec le " -"momentum du serveur [Hsu et al., 2019]." -#: ../../source/ref-changelog.md:505 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed:1 +#: flwr.server.strategy.fedavg.FedAvg:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:1 of +msgid "Bases: :py:class:`~flwr.server.strategy.strategy.Strategy`" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of msgid "" -"**New advanced PyTorch code example** " -"([#1007](https://github.com/adap/flower/pull/1007))" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" msgstr "" -"**Nouvel exemple de code PyTorch avancé** " -"([#1007](https://github.com/adap/flower/pull/1007))" -#: ../../source/ref-changelog.md:507 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of msgid "" -"A new code example (`advanced_pytorch`) demonstrates advanced Flower " -"concepts with PyTorch." +":py:obj:`aggregate_fit " +"`\\ " +"\\(server\\_round\\, results\\, failures\\)" msgstr "" -"Un nouvel exemple de code (`advanced_pytorch`) démontre des concepts de " -"fleur avancés avec PyTorch." -#: ../../source/ref-changelog.md:509 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_fit:1 of +msgid "Aggregate training results using unweighted aggregation." +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of msgid "" -"**New JAX code example** " -"([#906](https://github.com/adap/flower/pull/906), " -"[#1143](https://github.com/adap/flower/pull/1143))" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" -"**Nouvel exemple de code JAX** " -"([#906](https://github.com/adap/flower/pull/906), " -"[#1143](https://github.com/adap/flower/pull/1143))" -#: ../../source/ref-changelog.md:511 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of msgid "" -"A new code example (`jax_from_centralized_to_federated`) shows federated " -"learning with JAX and Flower." +":py:obj:`configure_fit " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" -"Un nouvel exemple de code (`jax_from_centralized_to_federated`) montre " -"l'apprentissage fédéré avec JAX et Flower." -#: ../../source/ref-changelog.md:515 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:1 of msgid "" -"New option to keep Ray running if Ray was already initialized in " -"`start_simulation` ([#1177](https://github.com/adap/flower/pull/1177))" +"Configure the next round of training incorporating Differential Privacy " +"(DP)." msgstr "" -"Nouvelle option pour continuer à faire fonctionner Ray si Ray a déjà été " -"initialisé dans `start_simulation` " -"([#1177](https://github.com/adap/flower/pull/1177))" -#: ../../source/ref-changelog.md:516 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of msgid "" -"Add support for custom `ClientManager` as a `start_simulation` parameter " -"([#1171](https://github.com/adap/flower/pull/1171))" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" msgstr "" -"Ajout de la prise en charge d'un `ClientManager` personnalisé comme " -"paramètre de `start_simulation` " -"([#1171](https://github.com/adap/flower/pull/1171))" -#: ../../source/ref-changelog.md:517 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of msgid "" -"New documentation for [implementing strategies](https://flower.dev/docs" -"/how-to-implement-strategies.html) " -"([#1097](https://github.com/adap/flower/pull/1097), " -"[#1175](https://github.com/adap/flower/pull/1175))" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" msgstr "" -"Nouvelle documentation pour [mettre en œuvre des " -"stratégies](https://flower.dev/docs/framework/how-to-implement-strategies.html) " -"([#1097](https://github.com/adap/flower/pull/1097), " -"[#1175](https://github.com/adap/flower/pull/1175))" -#: ../../source/ref-changelog.md:518 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:3 of msgid "" -"New mobile-friendly documentation theme " -"([#1174](https://github.com/adap/flower/pull/1174))" +"Configuration of the next training round includes information related to " +"DP, such as clip norm and noise stddev." msgstr "" -"Nouveau thème de documentation adapté aux mobiles " -"([#1174](https://github.com/adap/flower/pull/1174))" -#: ../../source/ref-changelog.md:519 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:13 +#: flwr.server.strategy.strategy.Strategy.configure_fit:10 of msgid "" -"Limit version range for (optional) `ray` dependency to include only " -"compatible releases (`>=1.9.2,<1.12.0`) " -"([#1205](https://github.com/adap/flower/pull/1205))" +"**fit_configuration** -- A list of tuples. Each tuple in the list " +"identifies a `ClientProxy` and the `FitIns` for this particular " +"`ClientProxy`. If a particular `ClientProxy` is not included in this " +"list, it means that this `ClientProxy` will not participate in the next " +"round of federated learning." msgstr "" -"Limite la plage de versions pour la dépendance (optionnelle) `ray` pour " -"n'inclure que les versions compatibles (`>=1.9.2,<1.12.0`) " -"([#1205](https://github.com/adap/flower/pull/1205))" -#: ../../source/ref-changelog.md:523 +#: ../../source/ref-api/flwr.server.strategy.FaultTolerantFedAvg.rst:2 +#, fuzzy +msgid "FaultTolerantFedAvg" +msgstr "server.strategy.FaultTolerantFedAvg" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of msgid "" -"**Remove deprecated support for Python 3.6** " -"([#871](https://github.com/adap/flower/pull/871))" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" msgstr "" -"**Supprime la prise en charge obsolète de Python 3.6** " -"([#871](https://github.com/adap/flower/pull/871))" -#: ../../source/ref-changelog.md:524 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of msgid "" -"**Remove deprecated KerasClient** " -"([#857](https://github.com/adap/flower/pull/857))" +":py:obj:`aggregate_fit " +"`\\ " +"\\(server\\_round\\, results\\, failures\\)" msgstr "" -"**Supprimez KerasClient** " -"([#857](https://github.com/adap/flower/pull/857))" -#: ../../source/ref-changelog.md:525 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_fit:1 +#: flwr.server.strategy.fedadagrad.FedAdagrad.aggregate_fit:1 +#: flwr.server.strategy.fedadam.FedAdam.aggregate_fit:1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_fit:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_fit:1 +#: flwr.server.strategy.fedavgm.FedAvgM.aggregate_fit:1 +#: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg.aggregate_fit:1 +#: flwr.server.strategy.fedyogi.FedYogi.aggregate_fit:1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_fit:1 of +msgid "Aggregate fit results using weighted average." +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of msgid "" -"**Remove deprecated no-op extra installs** " -"([#973](https://github.com/adap/flower/pull/973))" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" -"**Supprimer les installations supplémentaires no-op dépréciées** " -"([#973](https://github.com/adap/flower/pull/973))" -#: ../../source/ref-changelog.md:526 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of msgid "" -"**Remove deprecated proto fields from** `FitRes` **and** `EvaluateRes` " -"([#869](https://github.com/adap/flower/pull/869))" +":py:obj:`configure_fit " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" -"**Supprimez les champs proto obsolètes de** `FitRes` **et** `EvaluateRes`" -" ([#869](https://github.com/adap/flower/pull/869))" -#: ../../source/ref-changelog.md:527 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of msgid "" -"**Remove deprecated QffedAvg strategy (replaced by QFedAvg)** " -"([#1107](https://github.com/adap/flower/pull/1107))" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" msgstr "" -"**Supprime la stratégie QffedAvg (remplacée par QFedAvg)** " -"([#1107](https://github.com/adap/flower/pull/1107))" -#: ../../source/ref-changelog.md:528 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of msgid "" -"**Remove deprecated DefaultStrategy strategy** " -"([#1142](https://github.com/adap/flower/pull/1142))" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" msgstr "" -"**Supprime la stratégie DefaultStrategy qui est obsolète** " -"([#1142](https://github.com/adap/flower/pull/1142))" -#: ../../source/ref-changelog.md:529 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of msgid "" -"**Remove deprecated support for eval_fn accuracy return value** " -"([#1142](https://github.com/adap/flower/pull/1142))" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"**Supprimer la prise en charge obsolète de la valeur de retour de la " -"précision eval_fn** ([#1142](https://github.com/adap/flower/pull/1142))" -#: ../../source/ref-changelog.md:530 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of msgid "" -"**Remove deprecated support for passing initial parameters as NumPy " -"ndarrays** ([#1142](https://github.com/adap/flower/pull/1142))" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"**Supprime la prise en charge obsolète du passage des paramètres initiaux" -" en tant que ndarrays NumPy** " -"([#1142](https://github.com/adap/flower/pull/1142))" -#: ../../source/ref-changelog.md:532 -msgid "v0.18.0 (2022-02-28)" -msgstr "v0.18.0 (2022-02-28)" +#: ../../source/ref-api/flwr.server.strategy.FedAdagrad.rst:2 +#: ../../source/ref-changelog.md:839 +msgid "FedAdagrad" +msgstr "FedAdagrad" -#: ../../source/ref-changelog.md:536 -msgid "" -"**Improved Virtual Client Engine compatibility with Jupyter Notebook / " -"Google Colab** ([#866](https://github.com/adap/flower/pull/866), " -"[#872](https://github.com/adap/flower/pull/872), " -"[#833](https://github.com/adap/flower/pull/833), " -"[#1036](https://github.com/adap/flower/pull/1036))" +#: flwr.server.strategy.fedadagrad.FedAdagrad:1 +#: flwr.server.strategy.fedadam.FedAdam:1 +#: flwr.server.strategy.fedyogi.FedYogi:1 of +msgid "Bases: :py:class:`~flwr.server.strategy.fedopt.FedOpt`" +msgstr "" + +#: flwr.server.strategy.fedadagrad.FedAdagrad:3 +#: flwr.server.strategy.fedadam.FedAdam:3 flwr.server.strategy.fedopt.FedOpt:3 +#: flwr.server.strategy.fedyogi.FedYogi:3 of +#, fuzzy +msgid "Implementation based on https://arxiv.org/abs/2003.00295v5" +msgstr "" +"FedYogi - Stratégie d'apprentissage fédéré utilisant Yogi côté serveur. " +"Mise en oeuvre basée sur https://arxiv.org/abs/2003.00295" + +#: flwr.server.strategy.fedadagrad.FedAdagrad:21 +#: flwr.server.strategy.fedadagrad.FedAdagrad:23 +#: flwr.server.strategy.fedadam.FedAdam:25 +#: flwr.server.strategy.fedadam.FedAdam:27 +#: flwr.server.strategy.fedavg.FedAvg:29 flwr.server.strategy.fedavg.FedAvg:31 +#: flwr.server.strategy.fedopt.FedOpt:25 flwr.server.strategy.fedopt.FedOpt:27 +#: flwr.server.strategy.fedprox.FedProx:61 +#: flwr.server.strategy.fedprox.FedProx:63 +#: flwr.server.strategy.fedyogi.FedYogi:28 +#: flwr.server.strategy.fedyogi.FedYogi:30 of +msgid "Metrics aggregation function, optional." +msgstr "" + +#: flwr.server.strategy.fedadagrad.FedAdagrad:29 +#: flwr.server.strategy.fedadam.FedAdam:29 +#: flwr.server.strategy.fedopt.FedOpt:29 of +msgid "Server-side learning rate. Defaults to 1e-1." +msgstr "" + +#: flwr.server.strategy.fedadagrad.FedAdagrad:31 +#: flwr.server.strategy.fedadam.FedAdam:31 +#: flwr.server.strategy.fedopt.FedOpt:31 of +msgid "Client-side learning rate. Defaults to 1e-1." +msgstr "" + +#: flwr.server.strategy.fedadagrad.FedAdagrad:33 +#: flwr.server.strategy.fedadam.FedAdam:37 +#: flwr.server.strategy.fedopt.FedOpt:37 of +msgid "Controls the algorithm's degree of adaptability. Defaults to 1e-9." msgstr "" -"**Amélioration de la compatibilité du moteur de client virtuel avec " -"Jupyter Notebook / Google Colab** " -"([#866](https://github.com/adap/flower/pull/866), " -"[#872](https://github.com/adap/flower/pull/872), " -"[#833](https://github.com/adap/flower/pull/833), " -"[#1036](https://github.com/adap/flower/pull/1036))" -#: ../../source/ref-changelog.md:538 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Simulations (using the Virtual Client Engine through `start_simulation`) " -"now work more smoothly on Jupyter Notebooks (incl. Google Colab) after " -"installing Flower with the `simulation` extra (`pip install " -"flwr[simulation]`)." +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" msgstr "" -"Les simulations (utilisant le moteur de client virtuel via " -"`start_simulation`) fonctionnent maintenant plus facilement sur les " -"Notebooks Jupyter (y compris Google Colab) après avoir installé Flower " -"avec l'option `simulation` (`pip install flwr[simulation]`)." -#: ../../source/ref-changelog.md:540 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"**New Jupyter Notebook code example** " -"([#833](https://github.com/adap/flower/pull/833))" +":py:obj:`aggregate_fit `\\" +" \\(server\\_round\\, results\\, failures\\)" msgstr "" -"**Nouvel exemple de code Jupyter Notebook** " -"([#833](https://github.com/adap/flower/pull/833))" -#: ../../source/ref-changelog.md:542 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"A new code example (`quickstart_simulation`) demonstrates Flower " -"simulations using the Virtual Client Engine through Jupyter Notebook " -"(incl. Google Colab)." +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" -"Un nouvel exemple de code (`quickstart_simulation`) démontre des " -"simulations de Flower en utilisant le moteur de client virtuel via " -"Jupyter Notebook (y compris Google Colab)." -#: ../../source/ref-changelog.md:544 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"**Client properties (feature preview)** " -"([#795](https://github.com/adap/flower/pull/795))" +":py:obj:`configure_fit `\\" +" \\(server\\_round\\, parameters\\, ...\\)" msgstr "" -"**Propriétés du client (aperçu des fonctionnalités)** " -"([#795](https://github.com/adap/flower/pull/795))" -#: ../../source/ref-changelog.md:546 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Clients can implement a new method `get_properties` to enable server-side" -" strategies to query client properties." +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" msgstr "" -"Les clients peuvent implémenter une nouvelle méthode `get_properties` " -"pour permettre aux stratégies côté serveur d'interroger les propriétés du" -" client." -#: ../../source/ref-changelog.md:548 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"**Experimental Android support with TFLite** " -"([#865](https://github.com/adap/flower/pull/865))" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" msgstr "" -"**Support expérimental d'Android avec TFLite** " -"([#865](https://github.com/adap/flower/pull/865))" -#: ../../source/ref-changelog.md:550 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Android support has finally arrived in `main`! Flower is both client-" -"agnostic and framework-agnostic by design. One can integrate arbitrary " -"client platforms and with this release, using Flower on Android has " -"become a lot easier." +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"La prise en charge d'Android est enfin arrivée dans `main` ! Flower est à" -" la fois agnostique au niveau du client et du cadre de travail. On peut " -"intégrer des plates-formes client arbitraires et avec cette version, " -"l'utilisation de Flower sur Android est devenue beaucoup plus facile." -#: ../../source/ref-changelog.md:552 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"The example uses TFLite on the client side, along with a new " -"`FedAvgAndroid` strategy. The Android client and `FedAvgAndroid` are " -"still experimental, but they are a first step towards a fully-fledged " -"Android SDK and a unified `FedAvg` implementation that integrated the new" -" functionality from `FedAvgAndroid`." +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"L'exemple utilise TFLite du côté client, ainsi qu'une nouvelle stratégie " -"`FedAvgAndroid`. Le client Android et `FedAvgAndroid` sont encore " -"expérimentaux, mais ils constituent un premier pas vers un SDK Android à " -"part entière et une implémentation unifiée de `FedAvg` intégrant la " -"nouvelle fonctionnalité de `FedAvgAndroid`." -#: ../../source/ref-changelog.md:554 +#: ../../source/ref-api/flwr.server.strategy.FedAdam.rst:2 +#, fuzzy +msgid "FedAdam" +msgstr "FedAdagrad" + +#: flwr.server.strategy.fedadam.FedAdam:33 +#: flwr.server.strategy.fedyogi.FedYogi:36 of +msgid "Momentum parameter. Defaults to 0.9." +msgstr "" + +#: flwr.server.strategy.fedadam.FedAdam:35 +#: flwr.server.strategy.fedyogi.FedYogi:38 of +msgid "Second moment parameter. Defaults to 0.99." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"**Make gRPC keepalive time user-configurable and decrease default " -"keepalive time** ([#1069](https://github.com/adap/flower/pull/1069))" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\," +" results\\, ...\\)" msgstr "" -"**Rendre le temps de garde gRPC configurable par l'utilisateur et " -"diminuer le temps de garde par défaut** " -"([#1069](https://github.com/adap/flower/pull/1069))" -#: ../../source/ref-changelog.md:556 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"The default gRPC keepalive time has been reduced to increase the " -"compatibility of Flower with more cloud environments (for example, " -"Microsoft Azure). Users can configure the keepalive time to customize the" -" gRPC stack based on specific requirements." +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" msgstr "" -"Le temps de keepalive gRPC par défaut a été réduit pour augmenter la " -"compatibilité de Flower avec davantage d'environnements cloud (par " -"exemple, Microsoft Azure). Les utilisateurs peuvent configurer le temps " -"de keepalive pour personnaliser la pile gRPC en fonction d'exigences " -"spécifiques." -#: ../../source/ref-changelog.md:558 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"**New differential privacy example using Opacus and PyTorch** " -"([#805](https://github.com/adap/flower/pull/805))" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\," +" parameters\\, ...\\)" msgstr "" -"**Nouvel exemple de confidentialité différentielle utilisant Opacus et " -"PyTorch** ([#805](https://github.com/adap/flower/pull/805))" -#: ../../source/ref-changelog.md:560 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"A new code example (`opacus`) demonstrates differentially-private " -"federated learning with Opacus, PyTorch, and Flower." +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" -"Un nouvel exemple de code (`opacus`) démontre l'apprentissage fédéré " -"différentiellement privé avec Opacus, PyTorch et Flower." -#: ../../source/ref-changelog.md:562 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"**New Hugging Face Transformers code example** " -"([#863](https://github.com/adap/flower/pull/863))" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" msgstr "" -"**Nouvel exemple de code pour les Transformers à visage embrassant** " -"([#863](https://github.com/adap/flower/pull/863))" -#: ../../source/ref-changelog.md:564 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"A new code example (`quickstart_huggingface`) demonstrates usage of " -"Hugging Face Transformers with Flower." +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" msgstr "" -"Un nouvel exemple de code (`quickstart_huggingface`) démontre " -"l'utilisation des transformateurs Hugging Face avec Flower." -#: ../../source/ref-changelog.md:566 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"**New MLCube code example** " -"([#779](https://github.com/adap/flower/pull/779), " -"[#1034](https://github.com/adap/flower/pull/1034), " -"[#1065](https://github.com/adap/flower/pull/1065), " -"[#1090](https://github.com/adap/flower/pull/1090))" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"**Nouvel exemple de code MLCube** " -"([#779](https://github.com/adap/flower/pull/779), " -"[#1034](https://github.com/adap/flower/pull/1034), " -"[#1065](https://github.com/adap/flower/pull/1065), " -"[#1090](https://github.com/adap/flower/pull/1090))" -#: ../../source/ref-changelog.md:568 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"A new code example (`quickstart_mlcube`) demonstrates usage of MLCube " -"with Flower." +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"Un nouvel exemple de code (`quickstart_mlcube`) démontre l'utilisation de" -" MLCube avec Flower." -#: ../../source/ref-changelog.md:570 -msgid "" -"**SSL-enabled server and client** " -"([#842](https://github.com/adap/flower/pull/842), " -"[#844](https://github.com/adap/flower/pull/844), " -"[#845](https://github.com/adap/flower/pull/845), " -"[#847](https://github.com/adap/flower/pull/847), " -"[#993](https://github.com/adap/flower/pull/993), " -"[#994](https://github.com/adap/flower/pull/994))" +#: ../../source/ref-api/flwr.server.strategy.FedAvg.rst:2 +#, fuzzy +msgid "FedAvg" +msgstr "DP-FedAvg" + +#: flwr.server.strategy.fedavg.FedAvg:3 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:3 of +msgid "Implementation based on https://arxiv.org/abs/1602.05629" msgstr "" -"**([#842](https://github.com/adap/flower/pull/842), " -"[#844](https://github.com/adap/flower/pull/844), " -"[#845](https://github.com/adap/flower/pull/845), " -"[#847](https://github.com/adap/flower/pull/847), " -"[#993](https://github.com/adap/flower/pull/993), " -"[#994](https://github.com/adap/flower/pull/994))" -#: ../../source/ref-changelog.md:572 +#: flwr.server.strategy.fedavg.FedAvg:5 flwr.server.strategy.fedprox.FedProx:37 +#: of msgid "" -"SSL enables secure encrypted connections between clients and servers. " -"This release open-sources the Flower secure gRPC implementation to make " -"encrypted communication channels accessible to all Flower users." +"Fraction of clients used during training. In case `min_fit_clients` is " +"larger than `fraction_fit * available_clients`, `min_fit_clients` will " +"still be sampled. Defaults to 1.0." msgstr "" -"SSL permet d'établir des connexions cryptées et sécurisées entre les " -"clients et les serveurs. Cette version met en open-source " -"l'implémentation gRPC sécurisée de Flower afin de rendre les canaux de " -"communication cryptés accessibles à tous les utilisateurs de Flower." -#: ../../source/ref-changelog.md:574 +#: flwr.server.strategy.fedavg.FedAvg:9 flwr.server.strategy.fedprox.FedProx:41 +#: of msgid "" -"**Updated** `FedAdam` **and** `FedYogi` **strategies** " -"([#885](https://github.com/adap/flower/pull/885), " -"[#895](https://github.com/adap/flower/pull/895))" +"Fraction of clients used during validation. In case " +"`min_evaluate_clients` is larger than `fraction_evaluate * " +"available_clients`, `min_evaluate_clients` will still be sampled. " +"Defaults to 1.0." msgstr "" -"**Mise à jour** `FedAdam` **et** `FedYogi` **stratégies** " -"([#885](https://github.com/adap/flower/pull/885), " -"[#895](https://github.com/adap/flower/pull/895))" -#: ../../source/ref-changelog.md:576 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"`FedAdam` and `FedAdam` match the latest version of the Adaptive " -"Federated Optimization paper." +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\, " +"results\\, ...\\)" msgstr "" -"`FedAdam` et `FedAdam` correspondent à la dernière version de l'article " -"sur l'optimisation fédérée adaptative." -#: ../../source/ref-changelog.md:578 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"**Initialize** `start_simulation` **with a list of client IDs** " -"([#860](https://github.com/adap/flower/pull/860))" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" msgstr "" -"**Initialise** `start_simulation` **avec une liste d'ID de clients** " -"([#860](https://github.com/adap/flower/pull/860))" -#: ../../source/ref-changelog.md:580 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"`start_simulation` can now be called with a list of client IDs " -"(`clients_ids`, type: `List[str]`). Those IDs will be passed to the " -"`client_fn` whenever a client needs to be initialized, which can make it " -"easier to load data partitions that are not accessible through `int` " -"identifiers." +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\, " +"parameters\\, ...\\)" msgstr "" -"`start_simulation` peut maintenant être appelé avec une liste " -"d'identifiants de clients (`clients_ids`, type : `List[str]`). Ces " -"identifiants seront passés à `client_fn` chaque fois qu'un client doit " -"être initialisé, ce qui peut faciliter le chargement de partitions de " -"données qui ne sont pas accessibles par des identifiants `int`." -#: ../../source/ref-changelog.md:584 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Update `num_examples` calculation in PyTorch code examples in " -"([#909](https://github.com/adap/flower/pull/909))" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" -"Mettre à jour le calcul de `num_examples` dans les exemples de code " -"PyTorch dans ([#909](https://github.com/adap/flower/pull/909))" -#: ../../source/ref-changelog.md:585 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Expose Flower version through `flwr.__version__` " -"([#952](https://github.com/adap/flower/pull/952))" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" msgstr "" -"Exposer la version de Flower à travers `flwr.__version__` " -"([#952](https://github.com/adap/flower/pull/952))" -#: ../../source/ref-changelog.md:586 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"`start_server` in `app.py` now returns a `History` object containing " -"metrics from training ([#974](https://github.com/adap/flower/pull/974))" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" msgstr "" -"`start_server` dans `app.py` renvoie maintenant un objet `History` " -"contenant les métriques de l'entraînement " -"([#974](https://github.com/adap/flower/pull/974))" -#: ../../source/ref-changelog.md:587 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Make `max_workers` (used by `ThreadPoolExecutor`) configurable " -"([#978](https://github.com/adap/flower/pull/978))" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"Rendre `max_workers` (utilisé par `ThreadPoolExecutor`) configurable " -"([#978](https://github.com/adap/flower/pull/978))" -#: ../../source/ref-changelog.md:588 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Increase sleep time after server start to three seconds in all code " -"examples ([#1086](https://github.com/adap/flower/pull/1086))" +":py:obj:`num_fit_clients `\\" +" \\(num\\_available\\_clients\\)" msgstr "" -"Augmente le temps de sommeil après le démarrage du serveur à trois " -"secondes dans tous les exemples de code " -"([#1086](https://github.com/adap/flower/pull/1086))" -#: ../../source/ref-changelog.md:589 +#: ../../source/ref-api/flwr.server.strategy.FedAvgAndroid.rst:2 +#, fuzzy +msgid "FedAvgAndroid" +msgstr "DPFedAvgAdaptive" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of msgid "" -"Added a new FAQ section to the documentation " -"([#948](https://github.com/adap/flower/pull/948))" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" msgstr "" -"Ajout d'une nouvelle section FAQ à la documentation " -"([#948](https://github.com/adap/flower/pull/948))" -#: ../../source/ref-changelog.md:590 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of msgid "" -"And many more under-the-hood changes, library updates, documentation " -"changes, and tooling improvements!" +":py:obj:`aggregate_fit " +"`\\ " +"\\(server\\_round\\, results\\, failures\\)" msgstr "" -"Et bien d'autres changements sous le capot, des mises à jour de la " -"bibliothèque, des modifications de la documentation et des améliorations " -"de l'outillage !" -#: ../../source/ref-changelog.md:594 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of msgid "" -"**Removed** `flwr_example` **and** `flwr_experimental` **from release " -"build** ([#869](https://github.com/adap/flower/pull/869))" +":py:obj:`bytes_to_ndarray " +"`\\ \\(tensor\\)" msgstr "" -"**Supprimé** `flwr_example` **et** `flwr_experimental` **de la version " -"release build** ([#869](https://github.com/adap/flower/pull/869))" -#: ../../source/ref-changelog.md:596 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.bytes_to_ndarray:1 of +#, fuzzy +msgid "Deserialize NumPy array from bytes." +msgstr "Désérialise le tableau numérique NumPy à partir d'octets." + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of msgid "" -"The packages `flwr_example` and `flwr_experimental` have been deprecated " -"since Flower 0.12.0 and they are not longer included in Flower release " -"builds. The associated extras (`baseline`, `examples-pytorch`, `examples-" -"tensorflow`, `http-logger`, `ops`) are now no-op and will be removed in " -"an upcoming release." +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" -"Les paquets `flwr_example` et `flwr_experimental` ont été dépréciés " -"depuis Flower 0.12.0 et ils ne sont plus inclus dans les builds de " -"Flower. Les extras associés (`baseline`, `examples-pytorch`, `examples-" -"tensorflow`, `http-logger`, `ops`) sont maintenant no-op et seront " -"supprimés dans une prochaine version." -#: ../../source/ref-changelog.md:598 -msgid "v0.17.0 (2021-09-24)" -msgstr "v0.17.0 (2021-09-24)" +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_fit " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" -#: ../../source/ref-changelog.md:602 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of msgid "" -"**Experimental virtual client engine** " -"([#781](https://github.com/adap/flower/pull/781) " -"[#790](https://github.com/adap/flower/pull/790) " -"[#791](https://github.com/adap/flower/pull/791))" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" msgstr "" -"**Moteur expérimental de client virtuel** " -"([#781](https://github.com/adap/flower/pull/781) " -"[#790](https://github.com/adap/flower/pull/790) " -"[#791](https://github.com/adap/flower/pull/791))" -#: ../../source/ref-changelog.md:604 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of msgid "" -"One of Flower's goals is to enable research at scale. This release " -"enables a first (experimental) peek at a major new feature, codenamed the" -" virtual client engine. Virtual clients enable simulations that scale to " -"a (very) large number of clients on a single machine or compute cluster. " -"The easiest way to test the new functionality is to look at the two new " -"code examples called `quickstart_simulation` and `simulation_pytorch`." +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" msgstr "" -"L'un des objectifs de Flower est de permettre la recherche à grande " -"échelle. Cette version donne un premier aperçu (expérimental) d'une " -"nouvelle fonctionnalité majeure, connue sous le nom de code de moteur de " -"client virtuel. Les clients virtuels permettent des simulations qui " -"s'étendent à un (très) grand nombre de clients sur une seule machine ou " -"une grappe de calcul. La façon la plus simple de tester la nouvelle " -"fonctionnalité est de regarder les deux nouveaux exemples de code appelés" -" `quickstart_simulation` et `simulation_pytorch`." -#: ../../source/ref-changelog.md:606 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of msgid "" -"The feature is still experimental, so there's no stability guarantee for " -"the API. It's also not quite ready for prime time and comes with a few " -"known caveats. However, those who are curious are encouraged to try it " -"out and share their thoughts." +":py:obj:`ndarray_to_bytes " +"`\\ \\(ndarray\\)" msgstr "" -"La fonction est encore expérimentale, il n'y a donc aucune garantie de " -"stabilité pour l'API. Elle n'est pas non plus tout à fait prête pour le " -"prime time et s'accompagne de quelques mises en garde connues. Cependant," -" les personnes curieuses sont encouragées à l'essayer et à faire part de " -"leurs réflexions." -#: ../../source/ref-changelog.md:608 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.ndarray_to_bytes:1 of +#, fuzzy +msgid "Serialize NumPy array to bytes." +msgstr "Sérialise le tableau numérique NumPy en octets." + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of msgid "" -"**New built-in strategies** " -"([#828](https://github.com/adap/flower/pull/828) " -"[#822](https://github.com/adap/flower/pull/822))" +":py:obj:`ndarrays_to_parameters " +"`\\ " +"\\(ndarrays\\)" msgstr "" -"**Nouvelles stratégies intégrées** " -"([#828](https://github.com/adap/flower/pull/828) " -"[#822](https://github.com/adap/flower/pull/822))" -#: ../../source/ref-changelog.md:610 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of msgid "" -"FedYogi - Federated learning strategy using Yogi on server-side. " -"Implementation based on https://arxiv.org/abs/2003.00295" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"FedYogi - Stratégie d'apprentissage fédéré utilisant Yogi côté serveur. " -"Mise en oeuvre basée sur https://arxiv.org/abs/2003.00295" -#: ../../source/ref-changelog.md:611 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of msgid "" -"FedAdam - Federated learning strategy using Adam on server-side. " -"Implementation based on https://arxiv.org/abs/2003.00295" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"FedAdam - Stratégie d'apprentissage fédéré utilisant Adam côté serveur. " -"Mise en œuvre basée sur https://arxiv.org/abs/2003.00295" -#: ../../source/ref-changelog.md:613 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of msgid "" -"**New PyTorch Lightning code example** " -"([#617](https://github.com/adap/flower/pull/617))" +":py:obj:`parameters_to_ndarrays " +"`\\ " +"\\(parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.parameters_to_ndarrays:1 +#: of +#, fuzzy +msgid "Convert parameters object to NumPy weights." +msgstr "Convertit l'objet des paramètres en ndarrays NumPy." + +#: ../../source/ref-api/flwr.server.strategy.FedAvgM.rst:2 +#, fuzzy +msgid "FedAvgM" +msgstr "DP-FedAvg" + +#: flwr.server.strategy.fedavgm.FedAvgM:3 of +msgid "Implementation based on https://arxiv.org/abs/1909.06335" msgstr "" -"**Nouvel exemple de code PyTorch Lightning** " -"([#617](https://github.com/adap/flower/pull/617))" -#: ../../source/ref-changelog.md:615 +#: flwr.server.strategy.fedavgm.FedAvgM:25 of msgid "" -"**New Variational Auto-Encoder code example** " -"([#752](https://github.com/adap/flower/pull/752))" +"Server-side learning rate used in server-side optimization. Defaults to " +"1.0." +msgstr "" + +#: flwr.server.strategy.fedavgm.FedAvgM:28 of +msgid "Server-side momentum factor used for FedAvgM. Defaults to 0.0." msgstr "" -"**Nouvel exemple de code d'autocodage variationnel** " -"([#752](https://github.com/adap/flower/pull/752))" -#: ../../source/ref-changelog.md:617 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"**New scikit-learn code example** " -"([#748](https://github.com/adap/flower/pull/748))" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\," +" results\\, ...\\)" msgstr "" -"**Nouvel exemple de code scikit-learn** " -"([#748](https://github.com/adap/flower/pull/748))" -#: ../../source/ref-changelog.md:619 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"**New experimental TensorBoard strategy** " -"([#789](https://github.com/adap/flower/pull/789))" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" msgstr "" -"**Nouvelle stratégie expérimentale TensorBoard** " -"([#789](https://github.com/adap/flower/pull/789))" -#: ../../source/ref-changelog.md:623 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Improved advanced TensorFlow code example " -"([#769](https://github.com/adap/flower/pull/769))" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\," +" parameters\\, ...\\)" msgstr "" -"Amélioration de l'exemple de code TensorFlow avancé " -"([#769](https://github.com/adap/flower/pull/769))" -#: ../../source/ref-changelog.md:624 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Warning when `min_available_clients` is misconfigured " -"([#830](https://github.com/adap/flower/pull/830))" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" -"Avertissement lorsque `min_available_clients` est mal configuré " -"([#830](https://github.com/adap/flower/pull/830))" -#: ../../source/ref-changelog.md:625 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Improved gRPC server docs " -"([#841](https://github.com/adap/flower/pull/841))" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" msgstr "" -"Amélioration de la documentation sur le serveur gRPC " -"([#841](https://github.com/adap/flower/pull/841))" -#: ../../source/ref-changelog.md:626 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Improved error message in `NumPyClient` " -"([#851](https://github.com/adap/flower/pull/851))" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" msgstr "" -"Amélioration du message d'erreur dans `NumPyClient` " -"([#851](https://github.com/adap/flower/pull/851))" -#: ../../source/ref-changelog.md:627 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Improved PyTorch quickstart code example " -"([#852](https://github.com/adap/flower/pull/852))" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"Exemple de code de démarrage rapide PyTorch amélioré " -"([#852](https://github.com/adap/flower/pull/852))" -#: ../../source/ref-changelog.md:631 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"**Disabled final distributed evaluation** " -"([#800](https://github.com/adap/flower/pull/800))" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"**Désactivé l'évaluation finale distribuée** " -"([#800](https://github.com/adap/flower/pull/800))" -#: ../../source/ref-changelog.md:633 +#: ../../source/ref-api/flwr.server.strategy.FedMedian.rst:2 +msgid "FedMedian" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Prior behaviour was to perform a final round of distributed evaluation on" -" all connected clients, which is often not required (e.g., when using " -"server-side evaluation). The prior behaviour can be enabled by passing " -"`force_final_distributed_eval=True` to `start_server`." +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" msgstr "" -"Le comportement précédent consistait à effectuer un dernier tour " -"d'évaluation distribuée sur tous les clients connectés, ce qui n'est " -"souvent pas nécessaire (par exemple, lors de l'utilisation de " -"l'évaluation côté serveur). Le comportement précédent peut être activé en" -" passant `force_final_distributed_eval=True` à `start_server`." -#: ../../source/ref-changelog.md:635 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"**Renamed q-FedAvg strategy** " -"([#802](https://github.com/adap/flower/pull/802))" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" msgstr "" -"**Renommé stratégie q-FedAvg** " -"([#802](https://github.com/adap/flower/pull/802))" -#: ../../source/ref-changelog.md:637 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedmedian.FedMedian.aggregate_fit:1 of +#, fuzzy +msgid "Aggregate fit results using median." +msgstr "Résultats globaux de l'évaluation." + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"The strategy named `QffedAvg` was renamed to `QFedAvg` to better reflect " -"the notation given in the original paper (q-FFL is the optimization " -"objective, q-FedAvg is the proposed solver). Note the the original (now " -"deprecated) `QffedAvg` class is still available for compatibility reasons" -" (it will be removed in a future release)." +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" -"La stratégie nommée `QffedAvg` a été renommée en `QFedAvg` pour mieux " -"refléter la notation donnée dans l'article original (q-FFL est l'objectif" -" d'optimisation, q-FedAvg est le solveur proposé). Notez que la classe " -"`QffedAvg` originale (maintenant obsolète) est toujours disponible pour " -"des raisons de compatibilité (elle sera supprimée dans une prochaine " -"version)." -#: ../../source/ref-changelog.md:639 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"**Deprecated and renamed code example** `simulation_pytorch` **to** " -"`simulation_pytorch_legacy` " -"([#791](https://github.com/adap/flower/pull/791))" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" -"**Exemple de code déprécié et renommé** `simulation_pytorch` **en** " -"`simulation_pytorch_legacy` " -"([#791](https://github.com/adap/flower/pull/791))" -#: ../../source/ref-changelog.md:641 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"This example has been replaced by a new example. The new example is based" -" on the experimental virtual client engine, which will become the new " -"default way of doing most types of large-scale simulations in Flower. The" -" existing example was kept for reference purposes, but it might be " -"removed in the future." +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" msgstr "" -"Cet exemple a été remplacé par un nouvel exemple. Le nouvel exemple est " -"basé sur le moteur expérimental du client virtuel, qui deviendra la " -"nouvelle méthode par défaut pour effectuer la plupart des types de " -"simulations à grande échelle dans Flower. L'exemple existant a été " -"conservé à des fins de référence, mais il pourrait être supprimé à " -"l'avenir." -#: ../../source/ref-changelog.md:643 -msgid "v0.16.0 (2021-05-11)" -msgstr "v0.16.0 (2021-05-11)" +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" -#: ../../source/ref-changelog.md:647 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"**New built-in strategies** " -"([#549](https://github.com/adap/flower/pull/549))" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"**Nouvelles stratégies intégrées** " -"([#549](https://github.com/adap/flower/pull/549))" -#: ../../source/ref-changelog.md:649 -msgid "(abstract) FedOpt" -msgstr "(résumé) FedOpt" +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" -#: ../../source/ref-changelog.md:650 -msgid "FedAdagrad" -msgstr "FedAdagrad" +#: ../../source/ref-api/flwr.server.strategy.FedOpt.rst:2 +msgid "FedOpt" +msgstr "" -#: ../../source/ref-changelog.md:652 +#: flwr.server.strategy.fedopt.FedOpt:33 of +msgid "Momentum parameter. Defaults to 0.0." +msgstr "" + +#: flwr.server.strategy.fedopt.FedOpt:35 of +msgid "Second moment parameter. Defaults to 0.0." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"**Custom metrics for server and strategies** " -"([#717](https://github.com/adap/flower/pull/717))" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\, " +"results\\, ...\\)" msgstr "" -"**Métriques personnalisées pour le serveur et les stratégies** " -"([#717](https://github.com/adap/flower/pull/717))" -#: ../../source/ref-changelog.md:654 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"The Flower server is now fully task-agnostic, all remaining instances of " -"task-specific metrics (such as `accuracy`) have been replaced by custom " -"metrics dictionaries. Flower 0.15 introduced the capability to pass a " -"dictionary containing custom metrics from client to server. As of this " -"release, custom metrics replace task-specific metrics on the server." +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" msgstr "" -"Le serveur Flower est maintenant totalement agnostique, toutes les " -"instances restantes de métriques spécifiques à une tâche (telles que " -"`accuracy`) ont été remplacées par des dictionnaires de métriques " -"personnalisées. Flower 0.15 a introduit la possibilité de passer un " -"dictionnaire contenant des métriques personnalisées du client au serveur." -" À partir de cette version, les métriques personnalisées remplacent les " -"métriques spécifiques à une tâche sur le serveur." -#: ../../source/ref-changelog.md:656 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Custom metric dictionaries are now used in two user-facing APIs: they are" -" returned from Strategy methods `aggregate_fit`/`aggregate_evaluate` and " -"they enable evaluation functions passed to build-in strategies (via " -"`eval_fn`) to return more than two evaluation metrics. Strategies can " -"even return *aggregated* metrics dictionaries for the server to keep " -"track of." +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\, " +"parameters\\, ...\\)" msgstr "" -"Les dictionnaires de métriques personnalisés sont maintenant utilisés " -"dans deux API orientées vers l'utilisateur : ils sont renvoyés par les " -"méthodes de stratégie `aggregate_fit`/`aggregate_evaluate` et ils " -"permettent aux fonctions d'évaluation passées aux stratégies intégrées " -"(via `eval_fn`) de renvoyer plus de deux métriques d'évaluation. Les " -"stratégies peuvent même renvoyer des dictionnaires de métriques " -"*agrégées* pour que le serveur puisse en garder la trace." -#: ../../source/ref-changelog.md:658 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Stratey implementations should migrate their `aggregate_fit` and " -"`aggregate_evaluate` methods to the new return type (e.g., by simply " -"returning an empty `{}`), server-side evaluation functions should migrate" -" from `return loss, accuracy` to `return loss, {\"accuracy\": accuracy}`." +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" -"Les implémentations de Stratey doivent migrer leurs méthodes " -"`aggregate_fit` et `aggregate_evaluate` vers le nouveau type de retour " -"(par exemple, en renvoyant simplement un `{}` vide), les fonctions " -"d'évaluation côté serveur doivent migrer de `return loss, accuracy` à " -"`return loss, {\"accuracy\" : accuracy}`." -#: ../../source/ref-changelog.md:660 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Flower 0.15-style return types are deprecated (but still supported), " -"compatibility will be removed in a future release." +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" msgstr "" -"Les types de retour du style Flower 0.15 sont dépréciés (mais toujours " -"pris en charge), la compatibilité sera supprimée dans une prochaine " -"version." -#: ../../source/ref-changelog.md:662 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"**Migration warnings for deprecated functionality** " -"([#690](https://github.com/adap/flower/pull/690))" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" msgstr "" -"**Avertissements de migration pour les fonctionnalités obsolètes** " -"([#690](https://github.com/adap/flower/pull/690))" -#: ../../source/ref-changelog.md:664 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Earlier versions of Flower were often migrated to new APIs, while " -"maintaining compatibility with legacy APIs. This release introduces " -"detailed warning messages if usage of deprecated APIs is detected. The " -"new warning messages often provide details on how to migrate to more " -"recent APIs, thus easing the transition from one release to another." +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"Les versions antérieures de Flower ont souvent été migrées vers de " -"nouvelles API, tout en maintenant la compatibilité avec les anciennes " -"API. Cette version introduit des messages d'avertissement détaillés si " -"l'utilisation d'API obsolètes est détectée. Les nouveaux messages " -"d'avertissement fournissent souvent des détails sur la façon de migrer " -"vers des API plus récentes, facilitant ainsi la transition d'une version " -"à l'autre." -#: ../../source/ref-changelog.md:666 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Improved docs and docstrings " -"([#691](https://github.com/adap/flower/pull/691) " -"[#692](https://github.com/adap/flower/pull/692) " -"[#713](https://github.com/adap/flower/pull/713))" +":py:obj:`num_fit_clients `\\" +" \\(num\\_available\\_clients\\)" msgstr "" -"Amélioration des docs et des docstrings " -"([#691](https://github.com/adap/flower/pull/691) " -"[#692](https://github.com/adap/flower/pull/692) " -"[#713](https://github.com/adap/flower/pull/713))" -#: ../../source/ref-changelog.md:668 -msgid "MXNet example and documentation" -msgstr "Exemple et documentation MXNet" +#: ../../source/ref-api/flwr.server.strategy.FedProx.rst:2 +msgid "FedProx" +msgstr "" -#: ../../source/ref-changelog.md:670 -msgid "" -"FedBN implementation in example PyTorch: From Centralized To Federated " -"([#696](https://github.com/adap/flower/pull/696) " -"[#702](https://github.com/adap/flower/pull/702) " -"[#705](https://github.com/adap/flower/pull/705))" +#: flwr.server.strategy.fedprox.FedProx:3 of +msgid "Implementation based on https://arxiv.org/abs/1812.06127" msgstr "" -"Mise en œuvre de FedBN dans l'exemple PyTorch : De la centralisation à la" -" fédération ([#696](https://github.com/adap/flower/pull/696) " -"[#702](https://github.com/adap/flower/pull/702) " -"[#705](https://github.com/adap/flower/pull/705))" -#: ../../source/ref-changelog.md:674 +#: flwr.server.strategy.fedprox.FedProx:5 of msgid "" -"**Serialization-agnostic server** " -"([#721](https://github.com/adap/flower/pull/721))" +"The strategy in itself will not be different than FedAvg, the client " +"needs to be adjusted. A proximal term needs to be added to the loss " +"function during the training:" msgstr "" -"**Serveur agnostique de sérialisation** " -"([#721](https://github.com/adap/flower/pull/721))" -#: ../../source/ref-changelog.md:676 +#: flwr.server.strategy.fedprox.FedProx:9 of msgid "" -"The Flower server is now fully serialization-agnostic. Prior usage of " -"class `Weights` (which represents parameters as deserialized NumPy " -"ndarrays) was replaced by class `Parameters` (e.g., in `Strategy`). " -"`Parameters` objects are fully serialization-agnostic and represents " -"parameters as byte arrays, the `tensor_type` attributes indicates how " -"these byte arrays should be interpreted (e.g., for " -"serialization/deserialization)." +"\\\\frac{\\\\mu}{2} || w - w^t ||^2\n" +"\n" msgstr "" -"Le serveur Flower est désormais totalement agnostique en matière de " -"sérialisation. L'utilisation antérieure de la classe `Weights` (qui " -"représente les paramètres sous forme de tableaux NumPy désérialisés) a " -"été remplacée par la classe `Parameters` (par exemple, dans `Strategy`). " -"Les objets `Parameters` sont totalement agnostiques en matière de " -"sérialisation et représentent les paramètres sous forme de tableaux " -"d'octets, les attributs `tensor_type` indiquent comment ces tableaux " -"d'octets doivent être interprétés (par exemple, pour la " -"sérialisation/désérialisation)." -#: ../../source/ref-changelog.md:678 +#: flwr.server.strategy.fedprox.FedProx:12 of msgid "" -"Built-in strategies implement this approach by handling serialization and" -" deserialization to/from `Weights` internally. Custom/3rd-party Strategy " -"implementations should update to the slighly changed Strategy method " -"definitions. Strategy authors can consult PR " -"[#721](https://github.com/adap/flower/pull/721) to see how strategies can" -" easily migrate to the new format." +"Where $w^t$ are the global parameters and $w$ are the local weights the " +"function will be optimized with." msgstr "" -"Les stratégies intégrées mettent en œuvre cette approche en gérant en " -"interne la sérialisation et la désérialisation de `Weights`. Les " -"implémentations de stratégies personnalisées ou tierces doivent être " -"mises à jour avec les définitions de méthodes de stratégie légèrement " -"modifiées. Les auteurs de stratégies peuvent consulter le PR " -"[#721](https://github.com/adap/flower/pull/721) pour voir comment les " -"stratégies peuvent facilement migrer vers le nouveau format." -#: ../../source/ref-changelog.md:680 -msgid "" -"Deprecated `flwr.server.Server.evaluate`, use " -"`flwr.server.Server.evaluate_round` instead " -"([#717](https://github.com/adap/flower/pull/717))" +#: flwr.server.strategy.fedprox.FedProx:15 of +msgid "In PyTorch, for example, the loss would go from:" msgstr "" -"Déclassé `flwr.server.Server.evaluate`, utiliser " -"`flwr.server.Server.evaluate_round` à la place " -"([#717](https://github.com/adap/flower/pull/717))" -#: ../../source/ref-changelog.md:682 -msgid "v0.15.0 (2021-03-12)" -msgstr "v0.15.0 (2021-03-12)" +#: flwr.server.strategy.fedprox.FedProx:21 of +msgid "To:" +msgstr "" -#: ../../source/ref-changelog.md:686 +#: flwr.server.strategy.fedprox.FedProx:30 of msgid "" -"**Server-side parameter initialization** " -"([#658](https://github.com/adap/flower/pull/658))" +"With `global_params` being a copy of the parameters before the training " +"takes place." msgstr "" -"**Initialisation des paramètres côté serveur** " -"([#658](https://github.com/adap/flower/pull/658))" -#: ../../source/ref-changelog.md:688 +#: flwr.server.strategy.fedprox.FedProx:65 of msgid "" -"Model parameters can now be initialized on the server-side. Server-side " -"parameter initialization works via a new `Strategy` method called " -"`initialize_parameters`." +"The weight of the proximal term used in the optimization. 0.0 makes this " +"strategy equivalent to FedAvg, and the higher the coefficient, the more " +"regularization will be used (that is, the client parameters will need to " +"be closer to the server parameters during training)." msgstr "" -"Les paramètres du modèle peuvent maintenant être initialisés côté " -"serveur. L'initialisation des paramètres côté serveur fonctionne via une " -"nouvelle méthode `Strategy` appelée `initialize_parameters`." -#: ../../source/ref-changelog.md:690 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Built-in strategies support a new constructor argument called " -"`initial_parameters` to set the initial parameters. Built-in strategies " -"will provide these initial parameters to the server on startup and then " -"delete them to free the memory afterwards." +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\," +" results\\, ...\\)" msgstr "" -"Les stratégies intégrées prennent en charge un nouvel argument du " -"constructeur appelé `initial_parameters` pour définir les paramètres " -"initiaux. Les stratégies intégrées fourniront ces paramètres initiaux au " -"serveur au démarrage et les supprimeront ensuite pour libérer la mémoire." -#: ../../source/ref-changelog.md:709 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"If no initial parameters are provided to the strategy, the server will " -"continue to use the current behaviour (namely, it will ask one of the " -"connected clients for its parameters and use these as the initial global " -"parameters)." +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" msgstr "" -"Si aucun paramètre initial n'est fourni à la stratégie, le serveur " -"continuera à utiliser le comportement actuel (à savoir qu'il demandera à " -"l'un des clients connectés ses paramètres et les utilisera comme " -"paramètres globaux initiaux)." - -#: ../../source/ref-changelog.md:711 -msgid "Deprecations" -msgstr "Dépréciations" -#: ../../source/ref-changelog.md:713 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Deprecate `flwr.server.strategy.DefaultStrategy` (migrate to " -"`flwr.server.strategy.FedAvg`, which is equivalent)" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\," +" parameters\\, ...\\)" msgstr "" -"Déclasser `flwr.server.strategy.DefaultStrategy` (migrer vers " -"`flwr.server.strategy.FedAvg`, qui est équivalent)" -#: ../../source/ref-changelog.md:715 -msgid "v0.14.0 (2021-02-18)" -msgstr "v0.14.0 (2021-02-18)" +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" -#: ../../source/ref-changelog.md:719 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"**Generalized** `Client.fit` **and** `Client.evaluate` **return values** " -"([#610](https://github.com/adap/flower/pull/610) " -"[#572](https://github.com/adap/flower/pull/572) " -"[#633](https://github.com/adap/flower/pull/633))" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" msgstr "" -"**Généralisé** `Client.fit` **et** `Client.evaluate` **valeurs de " -"retour** ([#610](https://github.com/adap/flower/pull/610) " -"[#572](https://github.com/adap/flower/pull/572) " -"[#633](https://github.com/adap/flower/pull/633))" -#: ../../source/ref-changelog.md:721 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Clients can now return an additional dictionary mapping `str` keys to " -"values of the following types: `bool`, `bytes`, `float`, `int`, `str`. " -"This means one can return almost arbitrary values from `fit`/`evaluate` " -"and make use of them on the server side!" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" msgstr "" -"Les clients peuvent maintenant renvoyer un dictionnaire supplémentaire " -"associant les clés `str` aux valeurs des types suivants : `bool`, " -"`bytes`, `float`, `int`, `str`. Cela signifie que l'on peut renvoyer des " -"valeurs presque arbitraires de `fit`/`evaluate` et les utiliser du côté " -"du serveur !" -#: ../../source/ref-changelog.md:723 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"This improvement also allowed for more consistent return types between " -"`fit` and `evaluate`: `evaluate` should now return a tuple `(float, int, " -"dict)` representing the loss, number of examples, and a dictionary " -"holding arbitrary problem-specific values like accuracy." +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"Cette amélioration a également permis de rendre plus cohérents les types " -"de retour entre `fit` et `evaluate` : `evaluate` devrait maintenant " -"retourner un tuple `(float, int, dict)` représentant la perte, le nombre " -"d'exemples, et un dictionnaire contenant des valeurs arbitraires " -"spécifiques au problème comme la précision." -#: ../../source/ref-changelog.md:725 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"In case you wondered: this feature is compatible with existing projects, " -"the additional dictionary return value is optional. New code should " -"however migrate to the new return types to be compatible with upcoming " -"Flower releases (`fit`: `List[np.ndarray], int, Dict[str, Scalar]`, " -"`evaluate`: `float, int, Dict[str, Scalar]`). See the example below for " -"details." +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"Au cas où tu te poserais la question : cette fonctionnalité est " -"compatible avec les projets existants, la valeur de retour supplémentaire" -" du dictionnaire est facultative. Le nouveau code doit cependant migrer " -"vers les nouveaux types de retour pour être compatible avec les " -"prochaines versions de Flower (`fit` : `List[np.ndarray], int, Dict[str, " -"Scalar]`, `evaluate` : `float, int, Dict[str, Scalar]`). Voir l'exemple " -"ci-dessous pour plus de détails." -#: ../../source/ref-changelog.md:727 -msgid "" -"*Code example:* note the additional dictionary return values in both " -"`FlwrClient.fit` and `FlwrClient.evaluate`:" +#: flwr.server.strategy.fedprox.FedProx.configure_fit:3 of +msgid "Sends the proximal factor mu to the clients" msgstr "" -"*Exemple de code:* note les valeurs de retour du dictionnaire " -"supplémentaires dans `FlwrClient.fit` et `FlwrClient.evaluate` :" -#: ../../source/ref-changelog.md:742 -msgid "" -"**Generalized** `config` **argument in** `Client.fit` **and** " -"`Client.evaluate` ([#595](https://github.com/adap/flower/pull/595))" +#: ../../source/ref-api/flwr.server.strategy.FedTrimmedAvg.rst:2 +msgid "FedTrimmedAvg" msgstr "" -"**Généralisé** `config` **argument dans** `Client.fit` **et** " -"`Client.evaluate` ([#595](https://github.com/adap/flower/pull/595))" -#: ../../source/ref-changelog.md:744 -msgid "" -"The `config` argument used to be of type `Dict[str, str]`, which means " -"that dictionary values were expected to be strings. The new release " -"generalizes this to enable values of the following types: `bool`, " -"`bytes`, `float`, `int`, `str`." +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:3 of +msgid "Implemented based on: https://arxiv.org/abs/1803.01498" msgstr "" -"L'argument `config` était auparavant de type `Dict[str, str]`, ce qui " -"signifie que les valeurs du dictionnaire devaient être des chaînes. La " -"nouvelle version généralise cela pour permettre les valeurs des types " -"suivants : `bool`, `bytes`, `float`, `int`, `str`." -#: ../../source/ref-changelog.md:746 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:25 of +msgid "Fraction to cut off of both tails of the distribution. Defaults to 0.2." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"This means one can now pass almost arbitrary values to `fit`/`evaluate` " -"using the `config` dictionary. Yay, no more `str(epochs)` on the server-" -"side and `int(config[\"epochs\"])` on the client side!" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" msgstr "" -"Cela signifie que l'on peut maintenant passer des valeurs presque " -"arbitraires à `fit`/`evaluate` en utilisant le dictionnaire `config`. " -"Yay, plus de `str(epochs)` du côté serveur et `int(config[\"epochs\"])` " -"du côté client !" -#: ../../source/ref-changelog.md:748 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"*Code example:* note that the `config` dictionary now contains non-`str` " -"values in both `Client.fit` and `Client.evaluate`:" +":py:obj:`aggregate_fit " +"`\\ " +"\\(server\\_round\\, results\\, failures\\)" msgstr "" -"*Exemple de code:* Notez que le dictionnaire `config` contient maintenant" -" des valeurs autres que `str` dans `Client.fit` et `Client.evaluate` :" -#: ../../source/ref-changelog.md:765 -msgid "v0.13.0 (2021-01-08)" -msgstr "v0.13.0 (2021-01-08)" +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg.aggregate_fit:1 of +msgid "Aggregate fit results using trimmed average." +msgstr "" -#: ../../source/ref-changelog.md:769 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"New example: PyTorch From Centralized To Federated " -"([#549](https://github.com/adap/flower/pull/549))" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" -"Nouvel exemple : PyTorch de centralisé à fédéré " -"([#549](https://github.com/adap/flower/pull/549))" -#: ../../source/ref-changelog.md:770 -msgid "Improved documentation" -msgstr "Amélioration de la documentation" +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" -#: ../../source/ref-changelog.md:771 -msgid "New documentation theme ([#551](https://github.com/adap/flower/pull/551))" +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" msgstr "" -"Nouveau thème de documentation " -"([#551](https://github.com/adap/flower/pull/551))" -#: ../../source/ref-changelog.md:772 -msgid "New API reference ([#554](https://github.com/adap/flower/pull/554))" -msgstr "Nouvelle référence API ([#554](https://github.com/adap/flower/pull/554))" +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" -#: ../../source/ref-changelog.md:773 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Updated examples documentation " -"([#549](https://github.com/adap/flower/pull/549))" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"Mise à jour de la documentation des exemples " -"([#549](https://github.com/adap/flower/pull/549))" -#: ../../source/ref-changelog.md:774 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Removed obsolete documentation " -"([#548](https://github.com/adap/flower/pull/548))" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"Suppression de la documentation obsolète " -"([#548](https://github.com/adap/flower/pull/548))" -#: ../../source/ref-changelog.md:776 -msgid "Bugfix:" -msgstr "Correction de bogues :" +#: ../../source/ref-api/flwr.server.strategy.FedXgbBagging.rst:2 +msgid "FedXgbBagging" +msgstr "" -#: ../../source/ref-changelog.md:778 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of msgid "" -"`Server.fit` does not disconnect clients when finished, disconnecting the" -" clients is now handled in `flwr.server.start_server` " -"([#553](https://github.com/adap/flower/pull/553) " -"[#540](https://github.com/adap/flower/issues/540))." +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" msgstr "" -"`Server.fit` ne déconnecte pas les clients lorsqu'il est terminé, la " -"déconnexion des clients est maintenant gérée dans " -"`flwr.server.start_server` " -"([#553](https://github.com/adap/flower/pull/553) " -"[#540](https://github.com/adap/flower/issues/540))." -#: ../../source/ref-changelog.md:780 -msgid "v0.12.0 (2020-12-07)" -msgstr "v0.12.0 (2020-12-07)" +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of +#, fuzzy +msgid "Aggregate evaluation metrics using average." +msgstr "Résultats globaux de l'évaluation." -#: ../../source/ref-changelog.md:782 ../../source/ref-changelog.md:798 -msgid "Important changes:" -msgstr "Changements importants :" +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_fit " +"`\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_fit:1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_fit:1 of +msgid "Aggregate fit results using bagging." +msgstr "" -#: ../../source/ref-changelog.md:784 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of msgid "" -"Added an example for embedded devices " -"([#507](https://github.com/adap/flower/pull/507))" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" -"Ajout d'un exemple pour les périphériques embarqués " -"([#507](https://github.com/adap/flower/pull/507))" -#: ../../source/ref-changelog.md:785 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of msgid "" -"Added a new NumPyClient (in addition to the existing KerasClient) " -"([#504](https://github.com/adap/flower/pull/504) " -"[#508](https://github.com/adap/flower/pull/508))" +":py:obj:`configure_fit " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" -"Ajout d'un nouveau NumPyClient (en plus du KerasClient existant) " -"([#504](https://github.com/adap/flower/pull/504) " -"[#508](https://github.com/adap/flower/pull/508))" -#: ../../source/ref-changelog.md:786 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of msgid "" -"Deprecated `flwr_example` package and started to migrate examples into " -"the top-level `examples` directory " -"([#494](https://github.com/adap/flower/pull/494) " -"[#512](https://github.com/adap/flower/pull/512))" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" msgstr "" -"Déclassement du paquet `flwr_example` et migration des exemples dans le " -"répertoire de premier niveau `examples` " -"([#494](https://github.com/adap/flower/pull/494) " -"[#512](https://github.com/adap/flower/pull/512))" -#: ../../source/ref-changelog.md:788 -msgid "v0.11.0 (2020-11-30)" -msgstr "v0.11.0 (2020-11-30)" +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" -#: ../../source/ref-changelog.md:790 -msgid "Incompatible changes:" -msgstr "Changements incompatibles :" +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" -#: ../../source/ref-changelog.md:792 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of msgid "" -"Renamed strategy methods " -"([#486](https://github.com/adap/flower/pull/486)) to unify the naming of " -"Flower's public APIs. Other public methods/functions (e.g., every method " -"in `Client`, but also `Strategy.evaluate`) do not use the `on_` prefix, " -"which is why we're removing it from the four methods in Strategy. To " -"migrate rename the following `Strategy` methods accordingly:" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"Renommé les méthodes de stratégie " -"([#486](https://github.com/adap/flower/pull/486)) pour unifier le nommage" -" des API publiques de Flower. D'autres méthodes/fonctions publiques (par " -"exemple, toutes les méthodes de `Client`, mais aussi `Strategy.evaluate`)" -" n'utilisent pas le préfixe `on_`, c'est pourquoi nous le supprimons des " -"quatre méthodes de Stratégie. Pour migrer, renommez les méthodes de " -"`Strategy` suivantes en conséquence :" -#: ../../source/ref-changelog.md:793 -msgid "`on_configure_evaluate` => `configure_evaluate`" -msgstr "`on_configure_evaluate` => `configure_evaluate`" +#: ../../source/ref-api/flwr.server.strategy.FedXgbCyclic.rst:2 +msgid "FedXgbCyclic" +msgstr "" -#: ../../source/ref-changelog.md:794 -msgid "`on_aggregate_evaluate` => `aggregate_evaluate`" -msgstr "`on_aggregate_evaluate` => `aggregate_evaluate`" +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" -#: ../../source/ref-changelog.md:795 -msgid "`on_configure_fit` => `configure_fit`" -msgstr "`on_configure_fit` => `configure_fit`" +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_fit " +"`\\ \\(server\\_round\\," +" results\\, failures\\)" +msgstr "" -#: ../../source/ref-changelog.md:796 -msgid "`on_aggregate_fit` => `aggregate_fit`" -msgstr "`on_aggregate_fit` => `aggregate_fit`" +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" -#: ../../source/ref-changelog.md:800 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of msgid "" -"Deprecated `DefaultStrategy` " -"([#479](https://github.com/adap/flower/pull/479)). To migrate use " -"`FedAvg` instead." +":py:obj:`configure_fit " +"`\\ \\(server\\_round\\," +" parameters\\, ...\\)" msgstr "" -"Déclassé `DefaultStrategy` " -"([#479](https://github.com/adap/flower/pull/479)). Pour migrer, utilisez " -"`FedAvg` à la place." -#: ../../source/ref-changelog.md:801 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of msgid "" -"Simplified examples and baselines " -"([#484](https://github.com/adap/flower/pull/484))." +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" msgstr "" -"Exemples simplifiés et lignes de base " -"([#484](https://github.com/adap/flower/pull/484))." -#: ../../source/ref-changelog.md:802 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of msgid "" -"Removed presently unused `on_conclude_round` from strategy interface " -"([#483](https://github.com/adap/flower/pull/483))." +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" msgstr "" -"Suppression de `on_conclude_round` actuellement inutilisé de l'interface " -"de stratégie ([#483](https://github.com/adap/flower/pull/483))." -#: ../../source/ref-changelog.md:803 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of msgid "" -"Set minimal Python version to 3.6.1 instead of 3.6.9 " -"([#471](https://github.com/adap/flower/pull/471))." +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"Fixe la version minimale de Python à 3.6.1 au lieu de 3.6.9 " -"([#471](https://github.com/adap/flower/pull/471))." -#: ../../source/ref-changelog.md:804 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of msgid "" -"Improved `Strategy` docstrings " -"([#470](https://github.com/adap/flower/pull/470))." +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"Amélioration des docstrings `Stratégie` " -"([#470](https://github.com/adap/flower/pull/470))." -#: ../../source/ref-example-projects.rst:2 +#: ../../source/ref-api/flwr.server.strategy.FedXgbNnAvg.rst:2 #, fuzzy -msgid "Example projects" -msgstr "Exemples de PyTorch" +msgid "FedXgbNnAvg" +msgstr "DP-FedAvg" -#: ../../source/ref-example-projects.rst:4 +#: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg:5 of msgid "" -"Flower comes with a number of usage examples. The examples demonstrate " -"how Flower can be used to federate different kinds of existing machine " -"learning pipelines, usually leveraging popular machine learning " -"frameworks such as `PyTorch `_ or `TensorFlow " -"`_." +"This strategy is deprecated, but a copy of it is available in Flower " +"Baselines: " +"https://github.com/adap/flower/tree/main/baselines/hfedxgboost." msgstr "" -"Flower est livré avec un certain nombre d'exemples d'utilisation, qui " -"montrent comment Flower peut être utilisé pour fédérer différents types " -"de pipelines d'apprentissage automatique existants, qui s'appuient " -"généralement sur des frameworks d'apprentissage automatique populaires " -"tels que `PyTorch `_ ou `TensorFlow " -"`_." -#: ../../source/ref-example-projects.rst:11 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Flower usage examples used to be bundled with Flower in a package called " -"``flwr_example``. We are migrating those examples to standalone projects " -"to make them easier to use. All new examples are based in the directory " -"`examples `_." +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" msgstr "" -"Les exemples d'utilisation de Flower étaient auparavant regroupés avec " -"Flower dans un paquet appelé ``flwr_example``. Nous migrons ces exemples " -"vers des projets autonomes pour les rendre plus faciles à utiliser. Tous " -"les nouveaux exemples sont basés dans le répertoire ``examples " -"`_." - -#: ../../source/ref-example-projects.rst:16 -msgid "The following examples are available as standalone projects." -msgstr "Les exemples suivants sont disponibles sous forme de projets autonomes." - -#: ../../source/ref-example-projects.rst:20 -msgid "Quickstart TensorFlow/Keras" -msgstr "Démarrage rapide de TensorFlow/Keras" -#: ../../source/ref-example-projects.rst:22 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"The TensorFlow/Keras quickstart example shows CIFAR-10 image " -"classification with MobileNetV2:" +":py:obj:`aggregate_fit " +"`\\ \\(server\\_round\\, " +"results\\, failures\\)" msgstr "" -"L'exemple de démarrage rapide TensorFlow/Keras montre la classification " -"d'images CIFAR-10 avec MobileNetV2 :" -#: ../../source/ref-example-projects.rst:25 -#, fuzzy +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"`Quickstart TensorFlow (Code) " -"`_" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" -"`Quickstart TensorFlow (Code) " -"`_" -#: ../../source/ref-example-projects.rst:26 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"`Quickstart TensorFlow (Tutorial) `_" +":py:obj:`configure_fit " +"`\\ \\(server\\_round\\, " +"parameters\\, ...\\)" msgstr "" -"`Quickstart TensorFlow (Tutorial) `_" -#: ../../source/ref-example-projects.rst:27 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"`Quickstart TensorFlow (Blog Post) `_" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" msgstr "" -"`Quickstart TensorFlow (Blog Post) `_" - -#: ../../source/ref-example-projects.rst:31 -#: ../../source/tutorial-quickstart-pytorch.rst:5 -msgid "Quickstart PyTorch" -msgstr "Démarrage rapide de PyTorch" -#: ../../source/ref-example-projects.rst:33 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"The PyTorch quickstart example shows CIFAR-10 image classification with a" -" simple Convolutional Neural Network:" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" msgstr "" -"L'exemple de démarrage rapide PyTorch montre la classification d'images " -"CIFAR-10 avec un simple réseau neuronal convolutif :" -#: ../../source/ref-example-projects.rst:36 -#, fuzzy +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"`Quickstart PyTorch (Code) " -"`_" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"`Quickstart PyTorch (Code) " -"`_" -#: ../../source/ref-example-projects.rst:37 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"`Quickstart PyTorch (Tutorial) `_" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"`Quickstart PyTorch (Tutorial) `_" -#: ../../source/ref-example-projects.rst:41 -msgid "PyTorch: From Centralized To Federated" -msgstr "PyTorch : De la centralisation à la fédération" +#: ../../source/ref-api/flwr.server.strategy.FedYogi.rst:2 +msgid "FedYogi" +msgstr "" -#: ../../source/ref-example-projects.rst:43 -msgid "" -"This example shows how a regular PyTorch project can be federated using " -"Flower:" +#: flwr.server.strategy.fedyogi.FedYogi:32 of +msgid "Server-side learning rate. Defaults to 1e-2." msgstr "" -"Cet exemple montre comment un projet PyTorch ordinaire peut être fédéré à" -" l'aide de Flower :" -#: ../../source/ref-example-projects.rst:45 -#, fuzzy -msgid "" -"`PyTorch: From Centralized To Federated (Code) " -"`_" +#: flwr.server.strategy.fedyogi.FedYogi:34 of +msgid "Client-side learning rate. Defaults to 0.0316." msgstr "" -"`PyTorch : De la centralisation à la fédération (Code) " -"`_" -#: ../../source/ref-example-projects.rst:46 -msgid "" -"`PyTorch: From Centralized To Federated (Tutorial) " -"`_" +#: flwr.server.strategy.fedyogi.FedYogi:40 of +msgid "Controls the algorithm's degree of adaptability. Defaults to 1e-3." msgstr "" -"`PyTorch : De la centralisation à la fédération (Tutoriel) " -"`_" - -#: ../../source/ref-example-projects.rst:50 -msgid "Federated Learning on Raspberry Pi and Nvidia Jetson" -msgstr "Apprentissage fédéré sur Raspberry Pi et Nvidia Jetson" -#: ../../source/ref-example-projects.rst:52 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"This example shows how Flower can be used to build a federated learning " -"system that run across Raspberry Pi and Nvidia Jetson:" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\," +" results\\, ...\\)" msgstr "" -"Cet exemple montre comment Flower peut être utilisé pour construire un " -"système d'apprentissage fédéré qui fonctionne sur Raspberry Pi et Nvidia " -"Jetson :" -#: ../../source/ref-example-projects.rst:54 -#, fuzzy +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"`Federated Learning on Raspberry Pi and Nvidia Jetson (Code) " -"`_" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" msgstr "" -"`L'apprentissage fédéré sur Raspberry Pi et Nvidia Jetson (Code) " -"`_" -#: ../../source/ref-example-projects.rst:55 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"`Federated Learning on Raspberry Pi and Nvidia Jetson (Blog Post) " -"`_" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\," +" parameters\\, ...\\)" msgstr "" -"`L'apprentissage fédéré sur Raspberry Pi et Nvidia Jetson (Blog Post) " -"`_" -#: ../../source/ref-example-projects.rst:60 -msgid "Legacy Examples (`flwr_example`)" -msgstr "Exemples hérités (`flwr_example`)" +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" -#: ../../source/ref-example-projects.rst:63 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"The useage examples in `flwr_example` are deprecated and will be removed " -"in the future. New examples are provided as standalone projects in " -"`examples `_." +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" msgstr "" -"Les exemples d'utilisation dans `flwr_example` sont obsolètes et seront " -"supprimés à l'avenir. De nouveaux exemples sont fournis en tant que " -"projets autonomes dans `examples " -"`_." -#: ../../source/ref-example-projects.rst:69 -msgid "Extra Dependencies" -msgstr "Dépendances supplémentaires" +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" -#: ../../source/ref-example-projects.rst:71 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"The core Flower framework keeps a minimal set of dependencies. The " -"examples demonstrate Flower in the context of different machine learning " -"frameworks, so additional dependencies need to be installed before an " -"example can be run." +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"Le noyau du framework Flower conserve un ensemble minimal de dépendances." -" Les exemples démontrent Flower dans le contexte de différents frameworks" -" d'apprentissage automatique, de sorte que des dépendances " -"supplémentaires doivent être installées avant qu'un exemple puisse être " -"exécuté." -#: ../../source/ref-example-projects.rst:75 -msgid "For PyTorch examples::" -msgstr "Pour les exemples de PyTorch: :" +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" -#: ../../source/ref-example-projects.rst:79 -msgid "For TensorFlow examples::" -msgstr "Pour les exemples de TensorFlow : :" +#: ../../source/ref-api/flwr.server.strategy.Krum.rst:2 +msgid "Krum" +msgstr "" -#: ../../source/ref-example-projects.rst:83 -msgid "For both PyTorch and TensorFlow examples::" -msgstr "Pour les exemples PyTorch et TensorFlow: :" +#: flwr.server.strategy.krum.Krum:3 of +msgid "Implementation based on https://arxiv.org/abs/1703.02757" +msgstr "" -#: ../../source/ref-example-projects.rst:87 +#: flwr.server.strategy.krum.Krum:17 of msgid "" -"Please consult :code:`pyproject.toml` for a full list of possible extras " -"(section :code:`[tool.poetry.extras]`)." +"Number of clients to keep before averaging (MultiKrum). Defaults to 0, in" +" that case classical Krum is applied." msgstr "" -"Tu peux consulter :code:`pyproject.toml` pour une liste complète des " -"extras possibles (section :code:`[tool.poetry.extras]`)." -#: ../../source/ref-example-projects.rst:92 -msgid "PyTorch Examples" -msgstr "Exemples de PyTorch" +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\, " +"results\\, ...\\)" +msgstr "" -#: ../../source/ref-example-projects.rst:94 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"Our PyTorch examples are based on PyTorch 1.7. They should work with " -"other releases as well. So far, we provide the following examples." +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" msgstr "" -"Nos exemples PyTorch sont basés sur PyTorch 1.7. Ils devraient " -"fonctionner avec d'autres versions également. Jusqu'à présent, nous " -"fournissons les exemples suivants." -#: ../../source/ref-example-projects.rst:98 -msgid "CIFAR-10 Image Classification" -msgstr "Classification d'images CIFAR-10" +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.krum.Krum.aggregate_fit:1 of +#, fuzzy +msgid "Aggregate fit results using Krum." +msgstr "Résultats globaux de l'évaluation." -#: ../../source/ref-example-projects.rst:100 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -"`CIFAR-10 and CIFAR-100 `_ " -"are popular RGB image datasets. The Flower CIFAR-10 example uses PyTorch " -"to train a simple CNN classifier in a federated learning setup with two " -"clients." +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\, " +"parameters\\, ...\\)" msgstr "" -"`CIFAR-10 et CIFAR-100 `_ " -"sont des ensembles de données d'images RVB populaires. L'exemple Flower " -"CIFAR-10 utilise PyTorch pour former un classificateur CNN simple dans " -"une configuration d'apprentissage fédéré avec deux clients." -#: ../../source/ref-example-projects.rst:104 -#: ../../source/ref-example-projects.rst:121 -#: ../../source/ref-example-projects.rst:146 -msgid "First, start a Flower server:" -msgstr "Tout d'abord, démarre un serveur Flower :" +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" -#: ../../source/ref-example-projects.rst:106 -msgid "$ ./src/py/flwr_example/pytorch_cifar/run-server.sh" -msgstr "$ ./src/py/flwr_example/pytorch_cifar/run-server.sh" +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" -#: ../../source/ref-example-projects.rst:108 -#: ../../source/ref-example-projects.rst:125 -#: ../../source/ref-example-projects.rst:150 -msgid "Then, start the two clients in a new terminal window:" -msgstr "Ensuite, démarre les deux clients dans une nouvelle fenêtre de terminal :" +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" -#: ../../source/ref-example-projects.rst:110 -msgid "$ ./src/py/flwr_example/pytorch_cifar/run-clients.sh" -msgstr "$ ./src/py/flwr_example/pytorch_cifar/run-clients.sh" +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" -#: ../../source/ref-example-projects.rst:112 -msgid "For more details, see :code:`src/py/flwr_example/pytorch_cifar`." -msgstr "Pour plus de détails, voir :code:`src/py/flwr_example/pytorch_cifar`." +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients `\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" -#: ../../source/ref-example-projects.rst:115 -msgid "ImageNet-2012 Image Classification" -msgstr "ImageNet-2012 Classification des images" +#: ../../source/ref-api/flwr.server.strategy.QFedAvg.rst:2 +#, fuzzy +msgid "QFedAvg" +msgstr "DP-FedAvg" -#: ../../source/ref-example-projects.rst:117 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of msgid "" -"`ImageNet-2012 `_ is one of the major computer" -" vision datasets. The Flower ImageNet example uses PyTorch to train a " -"ResNet-18 classifier in a federated learning setup with ten clients." +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\," +" results\\, ...\\)" msgstr "" -"`ImageNet-2012 `_ est l'un des principaux " -"ensembles de données de vision par ordinateur. L'exemple Flower ImageNet " -"utilise PyTorch pour entraîner un classificateur ResNet-18 dans une " -"configuration d'apprentissage fédéré avec dix clients." -#: ../../source/ref-example-projects.rst:123 -msgid "$ ./src/py/flwr_example/pytorch_imagenet/run-server.sh" -msgstr "$ ./src/py/flwr_example/pytorch_imagenet/run-server.sh" +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" -#: ../../source/ref-example-projects.rst:127 -msgid "$ ./src/py/flwr_example/pytorch_imagenet/run-clients.sh" -msgstr "$ ./src/py/flwr_example/pytorch_imagenet/run-clients.sh" +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\," +" parameters\\, ...\\)" +msgstr "" -#: ../../source/ref-example-projects.rst:129 -msgid "For more details, see :code:`src/py/flwr_example/pytorch_imagenet`." -msgstr "Pour plus de détails, voir :code:`src/py/flwr_example/pytorch_imagenet`." +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" -#: ../../source/ref-example-projects.rst:133 -msgid "TensorFlow Examples" -msgstr "Exemples de TensorFlow" +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" -#: ../../source/ref-example-projects.rst:135 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of msgid "" -"Our TensorFlow examples are based on TensorFlow 2.0 or newer. So far, we " -"provide the following examples." +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" msgstr "" -"Nos exemples TensorFlow sont basés sur TensorFlow 2.0 ou une version plus" -" récente. Jusqu'à présent, nous te proposons les exemples suivants." -#: ../../source/ref-example-projects.rst:139 -msgid "Fashion-MNIST Image Classification" -msgstr "Classification d'images Fashion-MNIST" +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" -#: ../../source/ref-example-projects.rst:141 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of msgid "" -"`Fashion-MNIST `_ is " -"often used as the \"Hello, world!\" of machine learning. We follow this " -"tradition and provide an example which samples random local datasets from" -" Fashion-MNIST and trains a simple image classification model over those " -"partitions." +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" msgstr "" -"nous suivons cette tradition et fournissons un exemple qui échantillonne " -"des ensembles de données locales aléatoires de Fashion-MNIST et entraîne " -"un modèle simple de classification d'images sur ces partitions." -#: ../../source/ref-example-projects.rst:148 -msgid "$ ./src/py/flwr_example/tensorflow_fashion_mnist/run-server.sh" -msgstr "$ ./src/py/flwr_example/tensorflow_fashion_mnist/run-server.sh" +#: ../../source/ref-api/flwr.server.strategy.Strategy.rst:2 +#, fuzzy +msgid "Strategy" +msgstr "stratégie.du.serveur" -#: ../../source/ref-example-projects.rst:152 -msgid "$ ./src/py/flwr_example/tensorflow_fashion_mnist/run-clients.sh" -msgstr "$ ./src/py/flwr_example/tensorflow_fashion_mnist/run-clients.sh" +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" -#: ../../source/ref-example-projects.rst:154 +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1 +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: of +#, fuzzy +msgid "Aggregate evaluation results." +msgstr "Résultats globaux de l'évaluation." + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: of msgid "" -"For more details, see " -":code:`src/py/flwr_example/tensorflow_fashion_mnist`." +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" msgstr "" -"Pour plus de détails, voir " -":code:`src/py/flwr_example/tensorflow_fashion_mnist`." -#: ../../source/ref-faq.rst:4 +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: flwr.server.strategy.strategy.Strategy.aggregate_fit:1 of +#, fuzzy +msgid "Aggregate training results." +msgstr "Résultats globaux de l'évaluation." + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: of msgid "" -"This page collects answers to commonly asked questions about Federated " -"Learning with Flower." +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" -"Cette page rassemble les réponses aux questions les plus fréquemment " -"posées sur l'apprentissage fédéré avec Flower." -#: ../../source/ref-faq.rst -msgid ":fa:`eye,mr-1` Can Flower run on Juptyter Notebooks / Google Colab?" +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" -":fa:`eye,mr-1` Flower peut-il fonctionner sur les ordinateurs portables " -"Juptyter / Google Colab ?" -#: ../../source/ref-faq.rst:8 +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: of msgid "" -"Yes, it can! Flower even comes with a few under-the-hood optimizations to" -" make it work even better on Colab. Here's a quickstart example:" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" msgstr "" -"Oui, c'est possible ! Flower est même livré avec quelques optimisations " -"pour qu'il fonctionne encore mieux sur Colab. Voici un exemple de " -"démarrage rapide :" -#: ../../source/ref-faq.rst:10 +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: flwr.server.strategy.strategy.Strategy.evaluate:1 of #, fuzzy +msgid "Evaluate the current model parameters." +msgstr "``get_parameters`` : renvoie les paramètres du modèle local actuel" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: of msgid "" -"`Flower simulation PyTorch " -"`_" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" msgstr "" -"`Flower Quickstart (TensorFlow/Keras) " -"`_" -#: ../../source/ref-faq.rst:11 +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: flwr.server.strategy.strategy.Strategy.initialize_parameters:1 of #, fuzzy +msgid "Initialize the (global) model parameters." +msgstr "Initialise le modèle global" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:5 of msgid "" -"`Flower simulation TensorFlow/Keras " -"`_" +"Successful updates from the previously selected and configured clients. " +"Each pair of `(ClientProxy, FitRes` constitutes a successful update from " +"one of the previously selected clients. Not that not all previously " +"selected clients are necessarily included in this list: a client might " +"drop out and not submit a result. For each client that did not submit an " +"update, there should be an `Exception` in `failures`." msgstr "" -"`Flower Quickstart (TensorFlow/Keras) " -"`_" -#: ../../source/ref-faq.rst -msgid ":fa:`eye,mr-1` How can I run Federated Learning on a Raspberry Pi?" +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:13 +#: flwr.server.strategy.strategy.Strategy.aggregate_fit:13 of +msgid "Exceptions that occurred while the server was waiting for client updates." msgstr "" -":fa:`eye,mr-1` Comment puis-je faire fonctionner l'apprentissage fédéré " -"sur un Raspberry Pi ?" -#: ../../source/ref-faq.rst:15 -#, fuzzy +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:16 of msgid "" -"Find the `blog post about federated learning on embedded device here " -"`_" -" and the corresponding `GitHub code example " -"`_." +"**aggregation_result** -- The aggregated evaluation result. Aggregation " +"typically uses some variant of a weighted average." msgstr "" -"Trouve le `blog post about federated learning on embedded device ici " -"`_" -" et l'exemple de code GitHub correspondant " -"`_." -#: ../../source/ref-faq.rst -msgid ":fa:`eye,mr-1` Does Flower support federated learning on Android devices?" +#: flwr.server.strategy.strategy.Strategy.aggregate_fit:5 of +msgid "" +"Successful updates from the previously selected and configured clients. " +"Each pair of `(ClientProxy, FitRes)` constitutes a successful update from" +" one of the previously selected clients. Not that not all previously " +"selected clients are necessarily included in this list: a client might " +"drop out and not submit a result. For each client that did not submit an " +"update, there should be an `Exception` in `failures`." msgstr "" -":fa:`eye,mr-1` Est-ce que Flower prend en charge l'apprentissage fédéré " -"sur les appareils Android ?" -#: ../../source/ref-faq.rst:19 -#, fuzzy +#: flwr.server.strategy.strategy.Strategy.aggregate_fit:17 of msgid "" -"Yes, it does. Please take a look at our `blog post " -"`_ or check out the code examples:" +"**parameters** -- If parameters are returned, then the server will treat " +"these as the new global model parameters (i.e., it will replace the " +"previous parameters with the ones returned from this method). If `None` " +"is returned (e.g., because there were only failures and no viable " +"results) then the server will no update the previous model parameters, " +"the updates received in this round are discarded, and the global model " +"parameters remain the same." msgstr "" -"Oui. Jetez un coup d'œil à notre `blog post " -"`_ ou consultez l'`exemple de code Android sur GitHub" -" `_." -#: ../../source/ref-faq.rst:21 +#: flwr.server.strategy.strategy.Strategy.evaluate:3 of msgid "" -"`Android Kotlin example `_" +"This function can be used to perform centralized (i.e., server-side) " +"evaluation of model parameters." msgstr "" -#: ../../source/ref-faq.rst:22 -msgid "`Android Java example `_" +#: flwr.server.strategy.strategy.Strategy.evaluate:11 of +msgid "" +"**evaluation_result** -- The evaluation result, usually a Tuple " +"containing loss and a dictionary containing task-specific metrics (e.g., " +"accuracy)." msgstr "" -#: ../../source/ref-faq.rst -msgid ":fa:`eye,mr-1` Can I combine federated learning with blockchain?" +#: flwr.server.strategy.strategy.Strategy.initialize_parameters:6 of +msgid "" +"**parameters** -- If parameters are returned, then the server will treat " +"these as the initial global model parameters." msgstr "" -":fa:`eye,mr-1` Puis-je combiner l'apprentissage fédéré avec la blockchain" -" ?" -#: ../../source/ref-faq.rst:26 +#: ../../source/ref-api/flwr.simulation.rst:2 +#, fuzzy +msgid "simulation" +msgstr "Simulation de moniteur" + +#: ../../source/ref-api/flwr.simulation.rst:17::1 msgid "" -"Yes, of course. A list of available examples using Flower within a " -"blockchain environment is available here:" +":py:obj:`start_simulation `\\ \\(\\*\\," +" client\\_fn\\[\\, ...\\]\\)" msgstr "" -"Oui, bien sûr, une liste d'exemples disponibles utilisant Flower dans un " -"environnement blockchain est disponible ici :" -#: ../../source/ref-faq.rst:28 +#: ../../source/ref-api/flwr.simulation.rst:17::1 +#: flwr.simulation.app.start_simulation:1 of +#, fuzzy +msgid "Start a Ray-based Flower simulation server." +msgstr "Simulation de moniteur" + +#: ../../source/ref-api/flwr.simulation.start_simulation.rst:2 +#, fuzzy +msgid "start\\_simulation" +msgstr "démarrer_simulation" + +#: flwr.simulation.app.start_simulation:3 of msgid "" -"`Flower meets Nevermined GitHub Repository `_." +"A function creating client instances. The function must take a single " +"`str` argument called `cid`. It should return a single client instance of" +" type Client. Note that the created client instances are ephemeral and " +"will often be destroyed after a single method invocation. Since client " +"instances are not long-lived, they should not attempt to carry state over" +" method invocations. Any state required by the instance (model, dataset, " +"hyperparameters, ...) should be (re-)created in either the call to " +"`client_fn` or the call to any of the client methods (e.g., load " +"evaluation data in the `evaluate` method itself)." msgstr "" -"`Flower meets Nevermined GitHub Repository `_." -#: ../../source/ref-faq.rst:29 +#: flwr.simulation.app.start_simulation:13 of msgid "" -"`Flower meets Nevermined YouTube video " -"`_." +"The total number of clients in this simulation. This must be set if " +"`clients_ids` is not set and vice-versa." msgstr "" -"`Flower rencontre Nevermined vidéo YouTube " -"`_." -#: ../../source/ref-faq.rst:30 +#: flwr.simulation.app.start_simulation:16 of msgid "" -"`Flower meets KOSMoS `_." +"List `client_id`s for each client. This is only required if `num_clients`" +" is not set. Setting both `num_clients` and `clients_ids` with " +"`len(clients_ids)` not equal to `num_clients` generates an error." msgstr "" -"`Flower rencontre KOSMoS `_." -#: ../../source/ref-faq.rst:31 +#: flwr.simulation.app.start_simulation:20 of msgid "" -"`Flower meets Talan blog post `_ ." +"CPU and GPU resources for a single client. Supported keys are `num_cpus` " +"and `num_gpus`. To understand the GPU utilization caused by `num_gpus`, " +"as well as using custom resources, please consult the Ray documentation." msgstr "" -"`Flower meets Talan blog post `_ ." -#: ../../source/ref-faq.rst:32 +#: flwr.simulation.app.start_simulation:25 of msgid "" -"`Flower meets Talan GitHub Repository " -"`_ ." +"An implementation of the abstract base class `flwr.server.Server`. If no " +"instance is provided, then `start_server` will create one." msgstr "" -"`Flower rencontre Talan Dépôt GitHub " -"`_ ." -#: ../../source/ref-telemetry.md:1 -msgid "Telemetry" -msgstr "Télémétrie" +#: flwr.simulation.app.start_simulation:31 of +msgid "" +"An implementation of the abstract base class `flwr.server.Strategy`. If " +"no strategy is provided, then `start_server` will use " +"`flwr.server.strategy.FedAvg`." +msgstr "" -#: ../../source/ref-telemetry.md:3 +#: flwr.simulation.app.start_simulation:35 of msgid "" -"The Flower open-source project collects **anonymous** usage metrics to " -"make well-informed decisions to improve Flower. Doing this enables the " -"Flower team to understand how Flower is used and what challenges users " -"might face." +"An implementation of the abstract base class `flwr.server.ClientManager`." +" If no implementation is provided, then `start_simulation` will use " +"`flwr.server.client_manager.SimpleClientManager`." msgstr "" -"Le projet open-source Flower recueille des mesures d'utilisation " -"**anonymes** afin de prendre des décisions éclairées pour améliorer " -"Flower. Cela permet à l'équipe de Flower de comprendre comment Flower est" -" utilisé et quels sont les défis auxquels les utilisateurs peuvent être " -"confrontés." -#: ../../source/ref-telemetry.md:5 +#: flwr.simulation.app.start_simulation:39 of msgid "" -"**Flower is a friendly framework for collaborative AI and data science.**" -" Staying true to this statement, Flower makes it easy to disable " -"telemetry for users that do not want to share anonymous usage metrics." +"Optional dictionary containing arguments for the call to `ray.init`. If " +"ray_init_args is None (the default), Ray will be initialized with the " +"following default args: { \"ignore_reinit_error\": True, " +"\"include_dashboard\": False } An empty dictionary can be used " +"(ray_init_args={}) to prevent any arguments from being passed to " +"ray.init." msgstr "" -"**Flower est un cadre convivial pour l'IA collaborative et la science des" -" données.** En restant fidèle à cette déclaration, Flower permet de " -"désactiver facilement la télémétrie pour les utilisateurs qui ne " -"souhaitent pas partager des mesures d'utilisation anonymes." -#: ../../source/ref-telemetry.md:7 -msgid "Principles" -msgstr "Principes" +#: flwr.simulation.app.start_simulation:39 of +msgid "" +"Optional dictionary containing arguments for the call to `ray.init`. If " +"ray_init_args is None (the default), Ray will be initialized with the " +"following default args:" +msgstr "" -#: ../../source/ref-telemetry.md:9 -msgid "We follow strong principles guarding anonymous usage metrics collection:" +#: flwr.simulation.app.start_simulation:43 of +msgid "{ \"ignore_reinit_error\": True, \"include_dashboard\": False }" msgstr "" -"Nous suivons des principes stricts concernant la collecte de données " -"anonymes sur l'utilisation :" -#: ../../source/ref-telemetry.md:11 +#: flwr.simulation.app.start_simulation:45 of msgid "" -"**Optional:** You will always be able to disable telemetry; read on to " -"learn “[How to opt-out](#how-to-opt-out)”." +"An empty dictionary can be used (ray_init_args={}) to prevent any " +"arguments from being passed to ray.init." msgstr "" -"**Optionnel:** Tu pourras toujours désactiver la télémétrie ; lis la " -"suite pour apprendre \"[Comment se désengager](#how-to-opt-out)\"." -#: ../../source/ref-telemetry.md:12 +#: flwr.simulation.app.start_simulation:48 of msgid "" -"**Anonymous:** The reported usage metrics are anonymous and do not " -"contain any personally identifiable information (PII). See “[Collected " -"metrics](#collected-metrics)” to understand what metrics are being " -"reported." +"Set to True to prevent `ray.shutdown()` in case " +"`ray.is_initialized()=True`." msgstr "" -"**Anonyme:** Les mesures d'utilisation rapportées sont anonymes et ne " -"contiennent aucune information personnelle identifiable (PII). Voir " -"\"[Collected metrics](#collected-metrics)\" pour comprendre quelles " -"mesures sont rapportées." -#: ../../source/ref-telemetry.md:13 +#: flwr.simulation.app.start_simulation:50 of msgid "" -"**Transparent:** You can easily inspect what anonymous metrics are being " -"reported; see the section “[How to inspect what is being reported](#how-" -"to-inspect-what-is-being-reported)”" +"Optionally specify the type of actor to use. The actor object, which " +"persists throughout the simulation, will be the process in charge of " +"running the clients' jobs (i.e. their `fit()` method)." msgstr "" -"**Transparent:** Tu peux facilement inspecter les métriques anonymes qui " -"sont rapportées ; voir la section \"[Comment inspecter ce qui est " -"rapporté](#how-to-inspect-what-is-being-reported)\"" -#: ../../source/ref-telemetry.md:14 -#, fuzzy +#: flwr.simulation.app.start_simulation:54 of msgid "" -"**Open for feedback:** You can always reach out to us if you have " -"feedback; see the section “[How to contact us](#how-to-contact-us)” for " -"details." +"If you want to create your own Actor classes, you might need to pass some" +" input argument. You can use this dictionary for such purpose." msgstr "" -"**Ouvert pour les commentaires:** Tu peux toujours nous contacter si tu " -"as des commentaires ; voir la section \"[Comment nous contacter ](#how-" -"to-contact-us)\" pour plus de détails." - -#: ../../source/ref-telemetry.md:16 -msgid "How to opt-out" -msgstr "Comment se désinscrire" -#: ../../source/ref-telemetry.md:18 +#: flwr.simulation.app.start_simulation:57 of msgid "" -"When Flower starts, it will check for an environment variable called " -"`FLWR_TELEMETRY_ENABLED`. Telemetry can easily be disabled by setting " -"`FLWR_TELEMETRY_ENABLED=0`. Assuming you are starting a Flower server or " -"client, simply do so by prepending your command as in:" +"(default: \"DEFAULT\") Optional string (\"DEFAULT\" or \"SPREAD\") for " +"the VCE to choose in which node the actor is placed. If you are an " +"advanced user needed more control you can use lower-level scheduling " +"strategies to pin actors to specific compute nodes (e.g. via " +"NodeAffinitySchedulingStrategy). Please note this is an advanced feature." +" For all details, please refer to the Ray documentation: " +"https://docs.ray.io/en/latest/ray-core/scheduling/index.html" msgstr "" -"Lorsque Flower démarre, il vérifie la présence d'une variable " -"d'environnement appelée `FLWR_TELEMETRY_ENABLED`. La télémétrie peut " -"facilement être désactivée en réglant `FLWR_TELEMETRY_ENABLED=0`. En " -"supposant que tu démarres un serveur ou un client Flower, fais-le " -"simplement en faisant précéder ta commande de la façon suivante :" -#: ../../source/ref-telemetry.md:24 -msgid "" -"Alternatively, you can export `FLWR_TELEMETRY_ENABLED=0` in, for example," -" `.bashrc` (or whatever configuration file applies to your environment) " -"to disable Flower telemetry permanently." +#: flwr.simulation.app.start_simulation:66 of +msgid "**hist** -- Object containing metrics from training." msgstr "" -"Tu peux aussi exporter `FLWR_TELEMETRY_ENABLED=0` dans, par exemple, " -"`.bashrc` (ou tout autre fichier de configuration qui s'applique à ton " -"environnement) pour désactiver la télémétrie de la fleur de façon " -"permanente." -#: ../../source/ref-telemetry.md:26 -msgid "Collected metrics" -msgstr "Mesures collectées" +#: ../../source/ref-changelog.md:1 +msgid "Changelog" +msgstr "Changelog" -#: ../../source/ref-telemetry.md:28 -msgid "Flower telemetry collects the following metrics:" -msgstr "La télémétrie des fleurs recueille les métriques suivantes :" +#: ../../source/ref-changelog.md:3 +#, fuzzy +msgid "Unreleased" +msgstr "Inédit" -#: ../../source/ref-telemetry.md:30 +#: ../../source/ref-changelog.md:5 ../../source/ref-changelog.md:17 +#: ../../source/ref-changelog.md:110 ../../source/ref-changelog.md:210 +#: ../../source/ref-changelog.md:294 ../../source/ref-changelog.md:358 +#: ../../source/ref-changelog.md:416 ../../source/ref-changelog.md:485 +#: ../../source/ref-changelog.md:614 ../../source/ref-changelog.md:656 +#: ../../source/ref-changelog.md:723 ../../source/ref-changelog.md:789 +#: ../../source/ref-changelog.md:834 ../../source/ref-changelog.md:873 +#: ../../source/ref-changelog.md:906 ../../source/ref-changelog.md:956 +msgid "What's new?" +msgstr "Quoi de neuf ?" + +#: ../../source/ref-changelog.md:7 ../../source/ref-changelog.md:80 +#: ../../source/ref-changelog.md:192 ../../source/ref-changelog.md:282 +#: ../../source/ref-changelog.md:346 ../../source/ref-changelog.md:404 +#: ../../source/ref-changelog.md:473 ../../source/ref-changelog.md:535 +#: ../../source/ref-changelog.md:554 ../../source/ref-changelog.md:710 +#: ../../source/ref-changelog.md:781 ../../source/ref-changelog.md:818 +#: ../../source/ref-changelog.md:861 +msgid "Incompatible changes" +msgstr "Changements incompatibles" + +#: ../../source/ref-changelog.md:9 +#, fuzzy +msgid "v1.7.0 (2024-02-05)" +msgstr "v1.3.0 (2023-02-06)" + +#: ../../source/ref-changelog.md:11 ../../source/ref-changelog.md:104 +#: ../../source/ref-changelog.md:204 ../../source/ref-changelog.md:288 +#: ../../source/ref-changelog.md:352 ../../source/ref-changelog.md:410 +#: ../../source/ref-changelog.md:479 ../../source/ref-changelog.md:548 +msgid "Thanks to our contributors" +msgstr "Merci à nos contributeurs" + +#: ../../source/ref-changelog.md:13 ../../source/ref-changelog.md:106 +#: ../../source/ref-changelog.md:206 ../../source/ref-changelog.md:290 +#: ../../source/ref-changelog.md:354 ../../source/ref-changelog.md:412 msgid "" -"**Flower version.** Understand which versions of Flower are currently " -"being used. This helps us to decide whether we should invest effort into " -"releasing a patch version for an older version of Flower or instead use " -"the bandwidth to build new features." +"We would like to give our special thanks to all the contributors who made" +" the new version of Flower possible (in `git shortlog` order):" msgstr "" -"**Cela nous aide à décider si nous devons investir des efforts dans la " -"publication d'une version corrective pour une version plus ancienne de " -"Flower ou si nous devons plutôt utiliser la bande passante pour " -"développer de nouvelles fonctionnalités." +"Nous tenons à remercier tout particulièrement tous les contributeurs qui " +"ont rendu possible la nouvelle version de Flower (dans l'ordre `git " +"shortlog`) :" -#: ../../source/ref-telemetry.md:32 +#: ../../source/ref-changelog.md:15 msgid "" -"**Operating system.** Enables us to answer questions such as: *Should we " -"create more guides for Linux, macOS, or Windows?*" +"`Aasheesh Singh`, `Adam Narozniak`, `Aml Hassan Esmil`, `Charles " +"Beauville`, `Daniel J. Beutel`, `Daniel Nata Nugraha`, `Edoardo " +"Gabrielli`, `Gustavo Bertoli`, `HelinLin`, `Heng Pan`, `Javier`, `M S " +"Chaitanya Kumar`, `Mohammad Naseri`, `Nikos Vlachakis`, `Pritam Neog`, " +"`Robert Kuska`, `Robert Steiner`, `Taner Topal`, `Yahia Salaheldin " +"Shaaban`, `Yan Gao`, `Yasar Abbas` " msgstr "" -"**Système d'exploitation.** Nous permet de répondre à des questions " -"telles que : *Faudrait-il créer plus de guides pour Linux, macOS ou " -"Windows ?" -#: ../../source/ref-telemetry.md:34 +#: ../../source/ref-changelog.md:19 +#, fuzzy msgid "" -"**Python version.** Knowing the Python version helps us, for example, to " -"decide whether we should invest effort into supporting old versions of " -"Python or stop supporting them and start taking advantage of new Python " -"features." +"**Introduce stateful clients (experimental)** " +"([#2770](https://github.com/adap/flower/pull/2770), " +"[#2686](https://github.com/adap/flower/pull/2686), " +"[#2696](https://github.com/adap/flower/pull/2696), " +"[#2643](https://github.com/adap/flower/pull/2643), " +"[#2769](https://github.com/adap/flower/pull/2769))" msgstr "" -"**Version de Python.** Connaître la version de Python nous aide, par " -"exemple, à décider si nous devons investir des efforts dans la prise en " -"charge des anciennes versions de Python ou cesser de les prendre en " -"charge et commencer à tirer parti des nouvelles fonctionnalités de " -"Python." +"**([#842](https://github.com/adap/flower/pull/842), " +"[#844](https://github.com/adap/flower/pull/844), " +"[#845](https://github.com/adap/flower/pull/845), " +"[#847](https://github.com/adap/flower/pull/847), " +"[#993](https://github.com/adap/flower/pull/993), " +"[#994](https://github.com/adap/flower/pull/994))" -#: ../../source/ref-telemetry.md:36 +#: ../../source/ref-changelog.md:21 msgid "" -"**Hardware properties.** Understanding the hardware environment that " -"Flower is being used in helps to decide whether we should, for example, " -"put more effort into supporting low-resource environments." +"Subclasses of `Client` and `NumPyClient` can now store local state that " +"remains on the client. Let's start with the highlight first: this new " +"feature is compatible with both simulated clients (via " +"`start_simulation`) and networked clients (via `start_client`). It's also" +" the first preview of new abstractions like `Context` and `RecordSet`. " +"Clients can access state of type `RecordSet` via `state: RecordSet = " +"self.context.state`. Changes to this `RecordSet` are preserved across " +"different rounds of execution to enable stateful computations in a " +"unified way across simulation and deployment." msgstr "" -"**Comprendre l'environnement matériel dans lequel Flower est utilisé " -"permet de décider si nous devrions, par exemple, faire plus d'efforts " -"pour prendre en charge les environnements à faibles ressources." -#: ../../source/ref-telemetry.md:38 +#: ../../source/ref-changelog.md:23 +#, fuzzy msgid "" -"**Execution mode.** Knowing what execution mode Flower starts in enables " -"us to understand how heavily certain features are being used and better " -"prioritize based on that." +"**Improve performance** " +"([#2293](https://github.com/adap/flower/pull/2293))" msgstr "" -"**Mode d'exécution** Connaître le mode d'exécution dans lequel Flower " -"démarre nous permet de comprendre à quel point certaines fonctionnalités " -"sont utilisées et de mieux établir les priorités en fonction de cela." +"**Supprimer les stratégies expérimentales** " +"([#1280](https://github.com/adap/flower/pull/1280))" -#: ../../source/ref-telemetry.md:40 +#: ../../source/ref-changelog.md:25 msgid "" -"**Cluster.** Flower telemetry assigns a random in-memory cluster ID each " -"time a Flower workload starts. This allows us to understand which device " -"types not only start Flower workloads but also successfully complete " -"them." +"Flower is faster than ever. All `FedAvg`-derived strategies now use in-" +"place aggregation to reduce memory consumption. The Flower client " +"serialization/deserialization has been rewritten from the ground up, " +"which results in significant speedups, especially when the client-side " +"training time is short." msgstr "" -"**Cluster.** La télémétrie Flower attribue un ID de cluster en mémoire " -"aléatoire à chaque fois qu'une charge de travail Flower démarre. Cela " -"nous permet de comprendre quels types d'appareils non seulement démarrent" -" les charges de travail Flower, mais aussi les terminent avec succès." -#: ../../source/ref-telemetry.md:42 +#: ../../source/ref-changelog.md:27 +#, fuzzy msgid "" -"**Source.** Flower telemetry tries to store a random source ID in " -"`~/.flwr/source` the first time a telemetry event is generated. The " -"source ID is important to identify whether an issue is recurring or " -"whether an issue is triggered by multiple clusters running concurrently " -"(which often happens in simulation). For example, if a device runs " -"multiple workloads at the same time, and this results in an issue, then, " -"in order to reproduce the issue, multiple workloads must be started at " -"the same time." +"**Support Federated Learning with Apple MLX and Flower** " +"([#2693](https://github.com/adap/flower/pull/2693))" msgstr "" -"**Source.** La télémétrie de Flower essaie de stocker un ID de source " -"aléatoire dans `~/.flwr/source` la première fois qu'un événement de " -"télémétrie est généré. L'ID de source est important pour identifier si un" -" problème est récurrent ou si un problème est déclenché par plusieurs " -"clusters fonctionnant simultanément (ce qui arrive souvent en " -"simulation). Par exemple, si un périphérique exécute plusieurs charges de" -" travail en même temps, et que cela entraîne un problème, alors, afin de " -"reproduire le problème, plusieurs charges de travail doivent être " -"démarrées en même temps." +"**Ajouter un nouvel exemple d'apprentissage fédéré utilisant fastai et " +"Flower** ([#1598](https://github.com/adap/flower/pull/1598))" -#: ../../source/ref-telemetry.md:44 +#: ../../source/ref-changelog.md:29 msgid "" -"You may delete the source ID at any time. If you wish for all events " -"logged under a specific source ID to be deleted, you can send a deletion " -"request mentioning the source ID to `telemetry@flower.dev`. All events " -"related to that source ID will then be permanently deleted." +"Flower has official support for federated learning using [Appple " +"MLX](https://ml-explore.github.io/mlx) via the new `quickstart-mlx` code " +"example." msgstr "" -"Tu peux supprimer l'identifiant de la source à tout moment. Si tu " -"souhaites que tous les événements enregistrés sous un identifiant de " -"source spécifique soient supprimés, tu peux envoyer une demande de " -"suppression mentionnant l'identifiant de source à `telemetry@flower.dev`." -" Tous les événements liés à cet identifiant de source seront alors " -"définitivement supprimés." -#: ../../source/ref-telemetry.md:46 +#: ../../source/ref-changelog.md:31 +#, fuzzy msgid "" -"We will not collect any personally identifiable information. If you think" -" any of the metrics collected could be misused in any way, please [get in" -" touch with us](#how-to-contact-us). We will update this page to reflect " -"any changes to the metrics collected and publish changes in the " -"changelog." +"**Introduce new XGBoost cyclic strategy** " +"([#2666](https://github.com/adap/flower/pull/2666), " +"[#2668](https://github.com/adap/flower/pull/2668))" msgstr "" -"Nous ne collecterons aucune information personnelle identifiable. Si tu " -"penses que l'une des métriques collectées pourrait être utilisée à " -"mauvais escient de quelque manière que ce soit, merci de [nous " -"contacter](#commentnouscontacter). Nous mettrons à jour cette page pour " -"refléter toute modification des métriques collectées et nous publierons " -"les changements dans le journal des modifications (changelog)." +"**Introduction du SDK iOS (aperçu)** " +"([#1621](https://github.com/adap/flower/pull/1621), " +"[#1764](https://github.com/adap/flower/pull/1764))" -#: ../../source/ref-telemetry.md:48 +#: ../../source/ref-changelog.md:33 msgid "" -"If you think other metrics would be helpful for us to better guide our " -"decisions, please let us know! We will carefully review them; if we are " -"confident that they do not compromise user privacy, we may add them." +"A new strategy called `FedXgbCyclic` supports a client-by-client style of" +" training (often called cyclic). The `xgboost-comprehensive` code example" +" shows how to use it in a full project. In addition to that, `xgboost-" +"comprehensive` now also supports simulation mode. With this, Flower " +"offers best-in-class XGBoost support." msgstr "" -"Si tu penses que d'autres mesures nous seraient utiles pour mieux " -"orienter nos décisions, fais-le nous savoir ! Nous les examinerons " -"attentivement ; si nous sommes convaincus qu'elles ne compromettent pas " -"la vie privée des utilisateurs, nous pourrons les ajouter." - -#: ../../source/ref-telemetry.md:50 -msgid "How to inspect what is being reported" -msgstr "Comment inspecter ce qui est rapporté" -#: ../../source/ref-telemetry.md:52 +#: ../../source/ref-changelog.md:35 +#, fuzzy msgid "" -"We wanted to make it very easy for you to inspect what anonymous usage " -"metrics are reported. You can view all the reported telemetry information" -" by setting the environment variable `FLWR_TELEMETRY_LOGGING=1`. Logging " -"is disabled by default. You may use logging independently from " -"`FLWR_TELEMETRY_ENABLED` so that you can inspect the telemetry feature " -"without sending any metrics." +"**Support Python 3.11** " +"([#2394](https://github.com/adap/flower/pull/2394))" msgstr "" -"Nous avons voulu qu'il soit très facile pour toi d'inspecter les mesures " -"d'utilisation anonymes qui sont rapportées. Tu peux voir toutes les " -"informations de télémétrie rapportées en définissant la variable " -"d'environnement `FLWR_TELEMETRY_LOGGING=1`. La journalisation est " -"désactivée par défaut. Tu peux utiliser la journalisation indépendamment " -"de `FLWR_TELEMETRY_ENABLED` afin d'inspecter la fonction de télémétrie " -"sans envoyer de mesures." +"**Support Python 3.10** " +"([#1320](https://github.com/adap/flower/pull/1320))" -#: ../../source/ref-telemetry.md:58 +#: ../../source/ref-changelog.md:37 msgid "" -"The inspect Flower telemetry without sending any anonymous usage metrics," -" use both environment variables:" +"Framework tests now run on Python 3.8, 3.9, 3.10, and 3.11. This will " +"ensure better support for users using more recent Python versions." msgstr "" -"L'inspecteur Flower telemetry sans envoyer de métriques d'utilisation " -"anonymes, utilise les deux variables d'environnement :" - -#: ../../source/ref-telemetry.md:64 -msgid "How to contact us" -msgstr "Comment nous contacter" -#: ../../source/ref-telemetry.md:66 +#: ../../source/ref-changelog.md:39 +#, fuzzy msgid "" -"We want to hear from you. If you have any feedback or ideas on how to " -"improve the way we handle anonymous usage metrics, reach out to us via " -"[Slack](https://flower.dev/join-slack/) (channel `#telemetry`) or email " -"(`telemetry@flower.dev`)." +"**Update gRPC and ProtoBuf dependencies** " +"([#2814](https://github.com/adap/flower/pull/2814))" msgstr "" -"Si tu as des commentaires ou des idées pour améliorer la façon dont nous " -"traitons les mesures d'utilisation anonymes, contacte-nous via " -"[Slack](https://flower.dev/join-slack/) (canal `#telemetry`) ou par " -"courriel (`telemetry@flower.dev`)." +"**Ajouter une nouvelle stratégie `FedProx`** " +"([#1619](https://github.com/adap/flower/pull/1619))" -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:9 -#, fuzzy -msgid "Build a strategy from scratch" -msgstr "Élaborer une stratégie à partir de zéro" +#: ../../source/ref-changelog.md:41 +msgid "" +"The `grpcio` and `protobuf` dependencies were updated to their latest " +"versions for improved security and performance." +msgstr "" -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:11 +#: ../../source/ref-changelog.md:43 #, fuzzy msgid "" -"Welcome to the third part of the Flower federated learning tutorial. In " -"previous parts of this tutorial, we introduced federated learning with " -"PyTorch and Flower (`part 1 `__) and we learned how strategies " -"can be used to customize the execution on both the server and the clients" -" (`part 2 `__)." +"**Introduce Docker image for Flower server** " +"([#2700](https://github.com/adap/flower/pull/2700), " +"[#2688](https://github.com/adap/flower/pull/2688), " +"[#2705](https://github.com/adap/flower/pull/2705), " +"[#2695](https://github.com/adap/flower/pull/2695), " +"[#2747](https://github.com/adap/flower/pull/2747), " +"[#2746](https://github.com/adap/flower/pull/2746), " +"[#2680](https://github.com/adap/flower/pull/2680), " +"[#2682](https://github.com/adap/flower/pull/2682), " +"[#2701](https://github.com/adap/flower/pull/2701))" msgstr "" -"Bienvenue dans la troisième partie du tutoriel sur l'apprentissage fédéré" -" Flower. Dans les parties précédentes de ce tutoriel, nous avons présenté" -" l'apprentissage fédéré avec PyTorch et Flower (`partie 1 " -"`__) " -"et nous avons appris comment les stratégies peuvent être utilisées pour " -"personnaliser l'exécution à la fois sur le serveur et sur les clients " -"(`partie 2 `__)." +"**([#842](https://github.com/adap/flower/pull/842), " +"[#844](https://github.com/adap/flower/pull/844), " +"[#845](https://github.com/adap/flower/pull/845), " +"[#847](https://github.com/adap/flower/pull/847), " +"[#993](https://github.com/adap/flower/pull/993), " +"[#994](https://github.com/adap/flower/pull/994))" -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:13 +#: ../../source/ref-changelog.md:45 msgid "" -"In this notebook, we'll continue to customize the federated learning " -"system we built previously by creating a custom version of FedAvg (again," -" using `Flower `__ and `PyTorch " -"`__)." +"The Flower server can now be run using an official Docker image. A new " +"how-to guide explains [how to run Flower using " +"Docker](https://flower.dev/docs/framework/how-to-run-flower-using-" +"docker.html). An official Flower client Docker image will follow." msgstr "" -"Dans ce carnet, nous allons continuer à personnaliser le système " -"d'apprentissage fédéré que nous avons construit précédemment en créant " -"une version personnalisée de FedAvg (encore une fois, en utilisant " -"`Flower `__ et `PyTorch `__)." -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:15 -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:16 -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:15 -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:15 +#: ../../source/ref-changelog.md:47 +#, fuzzy msgid "" -"`Star Flower on GitHub `__ ⭐️ and join " -"the Flower community on Slack to connect, ask questions, and get help: " -"`Join Slack `__ 🌼 We'd love to hear from " -"you in the ``#introductions`` channel! And if anything is unclear, head " -"over to the ``#questions`` channel." +"**Introduce** `flower-via-docker-compose` **example** " +"([#2626](https://github.com/adap/flower/pull/2626))" msgstr "" -"`Star Flower on GitHub `__ ⭐️ et " -"rejoignez la communauté Flower sur Slack pour vous connecter, poser des " -"questions et obtenir de l'aide : `Join Slack `__ 🌼 Nous serions ravis d'avoir de vos nouvelles dans le canal " -"``#introductions`` ! Et si quelque chose n'est pas clair, rendez-vous sur" -" le canal ``#questions``." - -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:17 -msgid "Let's build a new ``Strategy`` from scratch!" -msgstr "Construisons une nouvelle ``Stratégie`` à partir de zéro !" - -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:29 -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:29 -msgid "Preparation" -msgstr "Préparation" +"**Introduire une nouvelle ligne de base pour les fleurs : FedAvg " +"FEMNIST** ([#1655](https://github.com/adap/flower/pull/1655))" -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:31 -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:32 -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:31 +#: ../../source/ref-changelog.md:49 +#, fuzzy msgid "" -"Before we begin with the actual code, let's make sure that we have " -"everything we need." +"**Introduce** `quickstart-sklearn-tabular` **example** " +"([#2719](https://github.com/adap/flower/pull/2719))" msgstr "" -"Avant de commencer le code proprement dit, assurons-nous que nous " -"disposons de tout ce dont nous avons besoin." - -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:43 -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:44 -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:43 -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:43 -msgid "Installing dependencies" -msgstr "Installation des dépendances" - -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:45 -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:46 -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:45 -msgid "First, we install the necessary packages:" -msgstr "Tout d'abord, nous installons les paquets nécessaires :" +"**Ajouter une nouvelle stratégie `FedProx`** " +"([#1619](https://github.com/adap/flower/pull/1619))" -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:65 -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:66 -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:65 -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:65 +#: ../../source/ref-changelog.md:51 +#, fuzzy msgid "" -"Now that we have all dependencies installed, we can import everything we " -"need for this tutorial:" +"**Introduce** `custom-metrics` **example** " +"([#1958](https://github.com/adap/flower/pull/1958))" msgstr "" -"Maintenant que toutes les dépendances sont installées, nous pouvons " -"importer tout ce dont nous avons besoin pour ce tutoriel :" +"**Ajouter une nouvelle stratégie `FedProx`** " +"([#1619](https://github.com/adap/flower/pull/1619))" -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:101 -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:102 -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:104 -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:101 +#: ../../source/ref-changelog.md:53 +#, fuzzy msgid "" -"It is possible to switch to a runtime that has GPU acceleration enabled " -"(on Google Colab: ``Runtime > Change runtime type > Hardware acclerator: " -"GPU > Save``). Note, however, that Google Colab is not always able to " -"offer GPU acceleration. If you see an error related to GPU availability " -"in one of the following sections, consider switching back to CPU-based " -"execution by setting ``DEVICE = torch.device(\"cpu\")``. If the runtime " -"has GPU acceleration enabled, you should see the output ``Training on " -"cuda``, otherwise it'll say ``Training on cpu``." +"**Update code examples to use Flower Datasets** " +"([#2450](https://github.com/adap/flower/pull/2450), " +"[#2456](https://github.com/adap/flower/pull/2456), " +"[#2318](https://github.com/adap/flower/pull/2318), " +"[#2712](https://github.com/adap/flower/pull/2712))" msgstr "" -"Il est possible de passer à un runtime dont l'accélération GPU est " -"activée (sur Google Colab : ``Runtime > Change runtime type > Hardware " -"acclerator : GPU > Save``). Note cependant que Google Colab n'est pas " -"toujours en mesure de proposer l'accélération GPU. Si tu vois une erreur " -"liée à la disponibilité du GPU dans l'une des sections suivantes, " -"envisage de repasser à une exécution basée sur le CPU en définissant " -"``DEVICE = torch.device(\"cpu\")``. Si le runtime a activé l'accélération" -" GPU, tu devrais voir apparaître le résultat ``Training on cuda``, sinon " -"il dira ``Training on cpu``." - -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:114 -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:115 -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:114 -msgid "Data loading" -msgstr "Chargement des données" +"Mettre à jour les outils de développement " +"([#1231](https://github.com/adap/flower/pull/1231), " +"[#1276](https://github.com/adap/flower/pull/1276), " +"[#1301](https://github.com/adap/flower/pull/1301), " +"[#1310](https://github.com/adap/flower/pull/1310))" -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:116 -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:116 +#: ../../source/ref-changelog.md:55 msgid "" -"Let's now load the CIFAR-10 training and test set, partition them into " -"ten smaller datasets (each split into training and validation set), and " -"wrap everything in their own ``DataLoader``. We introduce a new parameter" -" ``num_clients`` which allows us to call ``load_datasets`` with different" -" numbers of clients." +"Several code examples were updated to use [Flower " +"Datasets](https://flower.dev/docs/datasets/)." msgstr "" -"Chargeons maintenant les ensembles d'entraînement et de test CIFAR-10, " -"divisons-les en dix ensembles de données plus petits (chacun divisé en " -"ensemble d'entraînement et de validation), et enveloppons le tout dans " -"leur propre ``DataLoader``. Nous introduisons un nouveau paramètre " -"``num_clients`` qui nous permet d'appeler ``load_datasets`` avec " -"différents nombres de clients." - -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:167 -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:168 -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:167 -msgid "Model training/evaluation" -msgstr "Formation/évaluation du modèle" -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:169 -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:170 -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:169 +#: ../../source/ref-changelog.md:57 +#, fuzzy msgid "" -"Let's continue with the usual model definition (including " -"``set_parameters`` and ``get_parameters``), training and test functions:" +"**General updates to Flower Examples** " +"([#2381](https://github.com/adap/flower/pull/2381), " +"[#2805](https://github.com/adap/flower/pull/2805), " +"[#2782](https://github.com/adap/flower/pull/2782), " +"[#2806](https://github.com/adap/flower/pull/2806), " +"[#2829](https://github.com/adap/flower/pull/2829), " +"[#2825](https://github.com/adap/flower/pull/2825), " +"[#2816](https://github.com/adap/flower/pull/2816), " +"[#2726](https://github.com/adap/flower/pull/2726), " +"[#2659](https://github.com/adap/flower/pull/2659), " +"[#2655](https://github.com/adap/flower/pull/2655))" msgstr "" -"Continuons avec la définition habituelle du modèle (y compris " -"``set_parameters`` et ``get_parameters``), les fonctions d'entraînement " -"et de test :" - -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:258 -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:258 -msgid "Flower client" -msgstr "Client de Flower" +"**Améliorer l'API (expérimentale) du pilote** " +"([#1663](https://github.com/adap/flower/pull/1663), " +"[#1666](https://github.com/adap/flower/pull/1666), " +"[#1667](https://github.com/adap/flower/pull/1667), " +"[#1664](https://github.com/adap/flower/pull/1664), " +"[#1675](https://github.com/adap/flower/pull/1675), " +"[#1676](https://github.com/adap/flower/pull/1676), " +"[#1693](https://github.com/adap/flower/pull/1693), " +"[#1662](https://github.com/adap/flower/pull/1662), " +"[#1794](https://github.com/adap/flower/pull/1794))" -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:260 -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:260 -msgid "" -"To implement the Flower client, we (again) create a subclass of " -"``flwr.client.NumPyClient`` and implement the three methods " -"``get_parameters``, ``fit``, and ``evaluate``. Here, we also pass the " -"``cid`` to the client and use it log additional details:" +#: ../../source/ref-changelog.md:59 +msgid "Many Flower code examples received substantial updates." msgstr "" -"Pour mettre en œuvre le client Flower, nous créons (à nouveau) une sous-" -"classe de ``flwr.client.NumPyClient`` et mettons en œuvre les trois " -"méthodes ``get_parameters``, ``fit`` et ``evaluate``. Ici, nous " -"transmettons également le ``cid`` au client et l'utilisons pour consigner" -" des détails supplémentaires :" -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:308 -msgid "Let's test what we have so far before we continue:" -msgstr "Testons ce que nous avons jusqu'à présent avant de continuer :" +#: ../../source/ref-changelog.md:61 ../../source/ref-changelog.md:154 +#, fuzzy +msgid "**Update Flower Baselines**" +msgstr "Demande pour une nouvelle Flower Baseline" -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:339 -msgid "Build a Strategy from scratch" -msgstr "Élaborer une stratégie à partir de zéro" - -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:341 +#: ../../source/ref-changelog.md:63 +#, fuzzy msgid "" -"Let’s overwrite the ``configure_fit`` method such that it passes a higher" -" learning rate (potentially also other hyperparameters) to the optimizer " -"of a fraction of the clients. We will keep the sampling of the clients as" -" it is in ``FedAvg`` and then change the configuration dictionary (one of" -" the ``FitIns`` attributes)." +"HFedXGBoost ([#2226](https://github.com/adap/flower/pull/2226), " +"[#2771](https://github.com/adap/flower/pull/2771))" msgstr "" -"Remplaçons la méthode ``configure_fit`` de façon à ce qu'elle transmette " -"un taux d'apprentissage plus élevé (potentiellement aussi d'autres " -"hyperparamètres) à l'optimiseur d'une fraction des clients. Nous " -"garderons l'échantillonnage des clients tel qu'il est dans ``FedAvg`` et " -"changerons ensuite le dictionnaire de configuration (l'un des attributs " -"``FitIns``)." +"**Nouvel exemple de code JAX** " +"([#906](https://github.com/adap/flower/pull/906), " +"[#1143](https://github.com/adap/flower/pull/1143))" -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:507 -msgid "" -"The only thing left is to use the newly created custom Strategy " -"``FedCustom`` when starting the experiment:" +#: ../../source/ref-changelog.md:64 +#, fuzzy +msgid "FedVSSL ([#2412](https://github.com/adap/flower/pull/2412))" msgstr "" -"Il ne reste plus qu'à utiliser la stratégie personnalisée nouvellement " -"créée ``FedCustom`` lors du démarrage de l'expérience :" +"Amélioration de la documentation sur le serveur gRPC " +"([#841](https://github.com/adap/flower/pull/841))" -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:534 -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:932 -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:697 -msgid "Recap" -msgstr "Récapitulation" +#: ../../source/ref-changelog.md:65 +#, fuzzy +msgid "FedNova ([#2179](https://github.com/adap/flower/pull/2179))" +msgstr "" +"**Ajouter une nouvelle stratégie `FedProx`** " +"([#1619](https://github.com/adap/flower/pull/1619))" + +#: ../../source/ref-changelog.md:66 +#, fuzzy +msgid "HeteroFL ([#2439](https://github.com/adap/flower/pull/2439))" +msgstr "Nouvelle référence API ([#554](https://github.com/adap/flower/pull/554))" + +#: ../../source/ref-changelog.md:67 +#, fuzzy +msgid "FedAvgM ([#2246](https://github.com/adap/flower/pull/2246))" +msgstr "Nouvelle référence API ([#554](https://github.com/adap/flower/pull/554))" + +#: ../../source/ref-changelog.md:68 +#, fuzzy +msgid "FedPara ([#2722](https://github.com/adap/flower/pull/2722))" +msgstr "" +"**Renommé stratégie q-FedAvg** " +"([#802](https://github.com/adap/flower/pull/802))" -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:536 +#: ../../source/ref-changelog.md:70 +#, fuzzy msgid "" -"In this notebook, we’ve seen how to implement a custom strategy. A custom" -" strategy enables granular control over client node configuration, result" -" aggregation, and more. To define a custom strategy, you only have to " -"overwrite the abstract methods of the (abstract) base class ``Strategy``." -" To make custom strategies even more powerful, you can pass custom " -"functions to the constructor of your new class (``__init__``) and then " -"call these functions whenever needed." +"**Improve documentation** " +"([#2674](https://github.com/adap/flower/pull/2674), " +"[#2480](https://github.com/adap/flower/pull/2480), " +"[#2826](https://github.com/adap/flower/pull/2826), " +"[#2727](https://github.com/adap/flower/pull/2727), " +"[#2761](https://github.com/adap/flower/pull/2761), " +"[#2900](https://github.com/adap/flower/pull/2900))" msgstr "" -"Dans ce carnet, nous avons vu comment mettre en place une stratégie " -"personnalisée. Une stratégie personnalisée permet un contrôle granulaire " -"sur la configuration des nœuds clients, l'agrégation des résultats, et " -"bien plus encore. Pour définir une stratégie personnalisée, il te suffit " -"d'écraser les méthodes abstraites de la classe de base (abstraite) " -"``Strategy``. Pour rendre les stratégies personnalisées encore plus " -"puissantes, tu peux passer des fonctions personnalisées au constructeur " -"de ta nouvelle classe (``__init__``) et appeler ensuite ces fonctions à " -"chaque fois que c'est nécessaire." +"**Mise à jour de la documentation** " +"([#1629](https://github.com/adap/flower/pull/1629), " +"[#1628](https://github.com/adap/flower/pull/1628), " +"[#1620](https://github.com/adap/flower/pull/1620), " +"[#1618](https://github.com/adap/flower/pull/1618), " +"[#1617](https://github.com/adap/flower/pull/1617), " +"[#1613](https://github.com/adap/flower/pull/1613), " +"[#1614](https://github.com/adap/flower/pull/1614))" -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:550 -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:948 -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:749 -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:715 -#: ../../source/tutorial-what-is-federated-learning.ipynb:369 +#: ../../source/ref-changelog.md:72 +msgid "" +"**Improved testing and development infrastructure** " +"([#2797](https://github.com/adap/flower/pull/2797), " +"[#2676](https://github.com/adap/flower/pull/2676), " +"[#2644](https://github.com/adap/flower/pull/2644), " +"[#2656](https://github.com/adap/flower/pull/2656), " +"[#2848](https://github.com/adap/flower/pull/2848), " +"[#2675](https://github.com/adap/flower/pull/2675), " +"[#2735](https://github.com/adap/flower/pull/2735), " +"[#2767](https://github.com/adap/flower/pull/2767), " +"[#2732](https://github.com/adap/flower/pull/2732), " +"[#2744](https://github.com/adap/flower/pull/2744), " +"[#2681](https://github.com/adap/flower/pull/2681), " +"[#2699](https://github.com/adap/flower/pull/2699), " +"[#2745](https://github.com/adap/flower/pull/2745), " +"[#2734](https://github.com/adap/flower/pull/2734), " +"[#2731](https://github.com/adap/flower/pull/2731), " +"[#2652](https://github.com/adap/flower/pull/2652), " +"[#2720](https://github.com/adap/flower/pull/2720), " +"[#2721](https://github.com/adap/flower/pull/2721), " +"[#2717](https://github.com/adap/flower/pull/2717), " +"[#2864](https://github.com/adap/flower/pull/2864), " +"[#2694](https://github.com/adap/flower/pull/2694), " +"[#2709](https://github.com/adap/flower/pull/2709), " +"[#2658](https://github.com/adap/flower/pull/2658), " +"[#2796](https://github.com/adap/flower/pull/2796), " +"[#2692](https://github.com/adap/flower/pull/2692), " +"[#2657](https://github.com/adap/flower/pull/2657), " +"[#2813](https://github.com/adap/flower/pull/2813), " +"[#2661](https://github.com/adap/flower/pull/2661), " +"[#2398](https://github.com/adap/flower/pull/2398))" +msgstr "" + +#: ../../source/ref-changelog.md:74 +msgid "" +"The Flower testing and development infrastructure has received " +"substantial updates. This makes Flower 1.7 the most tested release ever." +msgstr "" + +#: ../../source/ref-changelog.md:76 +msgid "" +"**Update dependencies** " +"([#2753](https://github.com/adap/flower/pull/2753), " +"[#2651](https://github.com/adap/flower/pull/2651), " +"[#2739](https://github.com/adap/flower/pull/2739), " +"[#2837](https://github.com/adap/flower/pull/2837), " +"[#2788](https://github.com/adap/flower/pull/2788), " +"[#2811](https://github.com/adap/flower/pull/2811), " +"[#2774](https://github.com/adap/flower/pull/2774), " +"[#2790](https://github.com/adap/flower/pull/2790), " +"[#2751](https://github.com/adap/flower/pull/2751), " +"[#2850](https://github.com/adap/flower/pull/2850), " +"[#2812](https://github.com/adap/flower/pull/2812), " +"[#2872](https://github.com/adap/flower/pull/2872), " +"[#2736](https://github.com/adap/flower/pull/2736), " +"[#2756](https://github.com/adap/flower/pull/2756), " +"[#2857](https://github.com/adap/flower/pull/2857), " +"[#2757](https://github.com/adap/flower/pull/2757), " +"[#2810](https://github.com/adap/flower/pull/2810), " +"[#2740](https://github.com/adap/flower/pull/2740), " +"[#2789](https://github.com/adap/flower/pull/2789))" +msgstr "" + +#: ../../source/ref-changelog.md:78 msgid "" -"Before you continue, make sure to join the Flower community on Slack: " -"`Join Slack `__" +"**General improvements** " +"([#2803](https://github.com/adap/flower/pull/2803), " +"[#2847](https://github.com/adap/flower/pull/2847), " +"[#2877](https://github.com/adap/flower/pull/2877), " +"[#2690](https://github.com/adap/flower/pull/2690), " +"[#2889](https://github.com/adap/flower/pull/2889), " +"[#2874](https://github.com/adap/flower/pull/2874), " +"[#2819](https://github.com/adap/flower/pull/2819), " +"[#2689](https://github.com/adap/flower/pull/2689), " +"[#2457](https://github.com/adap/flower/pull/2457), " +"[#2870](https://github.com/adap/flower/pull/2870), " +"[#2669](https://github.com/adap/flower/pull/2669), " +"[#2876](https://github.com/adap/flower/pull/2876), " +"[#2885](https://github.com/adap/flower/pull/2885), " +"[#2858](https://github.com/adap/flower/pull/2858), " +"[#2867](https://github.com/adap/flower/pull/2867), " +"[#2351](https://github.com/adap/flower/pull/2351), " +"[#2886](https://github.com/adap/flower/pull/2886), " +"[#2860](https://github.com/adap/flower/pull/2860), " +"[#2828](https://github.com/adap/flower/pull/2828), " +"[#2869](https://github.com/adap/flower/pull/2869), " +"[#2875](https://github.com/adap/flower/pull/2875), " +"[#2733](https://github.com/adap/flower/pull/2733), " +"[#2488](https://github.com/adap/flower/pull/2488), " +"[#2646](https://github.com/adap/flower/pull/2646), " +"[#2879](https://github.com/adap/flower/pull/2879), " +"[#2821](https://github.com/adap/flower/pull/2821), " +"[#2855](https://github.com/adap/flower/pull/2855), " +"[#2800](https://github.com/adap/flower/pull/2800), " +"[#2807](https://github.com/adap/flower/pull/2807), " +"[#2801](https://github.com/adap/flower/pull/2801), " +"[#2804](https://github.com/adap/flower/pull/2804), " +"[#2851](https://github.com/adap/flower/pull/2851), " +"[#2787](https://github.com/adap/flower/pull/2787), " +"[#2852](https://github.com/adap/flower/pull/2852), " +"[#2672](https://github.com/adap/flower/pull/2672), " +"[#2759](https://github.com/adap/flower/pull/2759))" +msgstr "" + +#: ../../source/ref-changelog.md:82 +#, fuzzy +msgid "" +"**Deprecate** `start_numpy_client` " +"([#2563](https://github.com/adap/flower/pull/2563), " +"[#2718](https://github.com/adap/flower/pull/2718))" msgstr "" -"Avant de continuer, n'oublie pas de rejoindre la communauté Flower sur " -"Slack : `Join Slack `__" +"**Nouvelles stratégies intégrées** " +"([#828](https://github.com/adap/flower/pull/828) " +"[#822](https://github.com/adap/flower/pull/822))" -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:552 -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:950 -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:751 -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:717 -#: ../../source/tutorial-what-is-federated-learning.ipynb:371 +#: ../../source/ref-changelog.md:84 msgid "" -"There's a dedicated ``#questions`` channel if you need help, but we'd " -"also love to hear who you are in ``#introductions``!" +"Until now, clients of type `NumPyClient` needed to be started via " +"`start_numpy_client`. In our efforts to consolidate framework APIs, we " +"have introduced changes, and now all client types should start via " +"`start_client`. To continue using `NumPyClient` clients, you simply need " +"to first call the `.to_client()` method and then pass returned `Client` " +"object to `start_client`. The examples and the documentation have been " +"updated accordingly." msgstr "" -"Il existe un canal dédié aux ``questions`` si vous avez besoin d'aide, " -"mais nous aimerions aussi savoir qui vous êtes dans ``#introductions`` !" -#: ../../source/tutorial-build-a-strategy-from-scratch-pytorch.ipynb:554 +#: ../../source/ref-changelog.md:86 #, fuzzy msgid "" -"The `Flower Federated Learning Tutorial - Part 4 " -"`__ introduces ``Client``, the flexible API underlying " -"``NumPyClient``." +"**Deprecate legacy DP wrappers** " +"([#2749](https://github.com/adap/flower/pull/2749))" +msgstr "" +"**Supprimez KerasClient** " +"([#857](https://github.com/adap/flower/pull/857))" + +#: ../../source/ref-changelog.md:88 +msgid "" +"Legacy DP wrapper classes are deprecated, but still functional. This is " +"in preparation for an all-new pluggable version of differential privacy " +"support in Flower." msgstr "" -"Le `Tutoriel d'apprentissage fédéré Flower - Partie 4 " -"`__ présente ``Client``, l'API flexible qui sous-tend " -"``NumPyClient``." -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:9 +#: ../../source/ref-changelog.md:90 #, fuzzy -msgid "Customize the client" -msgstr "Création du client IMDBC" +msgid "" +"**Make optional arg** `--callable` **in** `flower-client` **a required " +"positional arg** ([#2673](https://github.com/adap/flower/pull/2673))" +msgstr "" +"**Log** `Client` **exceptions dans le moteur de client virtuel** " +"([#1493](https://github.com/adap/flower/pull/1493))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:11 +#: ../../source/ref-changelog.md:92 #, fuzzy msgid "" -"Welcome to the fourth part of the Flower federated learning tutorial. In " -"the previous parts of this tutorial, we introduced federated learning " -"with PyTorch and Flower (`part 1 `__), we learned how " -"strategies can be used to customize the execution on both the server and " -"the clients (`part 2 `__), and we built our own " -"custom strategy from scratch (`part 3 `__)." +"**Rename** `certificates` **to** `root_certificates` **in** `Driver` " +"([#2890](https://github.com/adap/flower/pull/2890))" msgstr "" -"Bienvenue dans la quatrième partie du tutoriel sur l'apprentissage fédéré" -" Flower. Dans les parties précédentes de ce tutoriel, nous avons présenté" -" l'apprentissage fédéré avec PyTorch et Flower (`partie 1 " -"`__)," -" nous avons appris comment les stratégies peuvent être utilisées pour " -"personnaliser l'exécution à la fois sur le serveur et les clients " -"(`partie 2 `__), et nous avons construit notre propre stratégie " -"personnalisée à partir de zéro (`partie 3 - WIP " -"`__)." +"**Rename** `rnd` **to** `server_round` " +"([#1321](https://github.com/adap/flower/pull/1321))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:14 +#: ../../source/ref-changelog.md:94 +#, fuzzy msgid "" -"In this notebook, we revisit ``NumPyClient`` and introduce a new " -"baseclass for building clients, simply named ``Client``. In previous " -"parts of this tutorial, we've based our client on ``NumPyClient``, a " -"convenience class which makes it easy to work with machine learning " -"libraries that have good NumPy interoperability. With ``Client``, we gain" -" a lot of flexibility that we didn't have before, but we'll also have to " -"do a few things the we didn't have to do before." +"**Drop experimental** `Task` **fields** " +"([#2866](https://github.com/adap/flower/pull/2866), " +"[#2865](https://github.com/adap/flower/pull/2865))" msgstr "" -"Dans ce carnet, nous revisitons `NumPyClient`` et introduisons une " -"nouvelle classe de base pour construire des clients, simplement appelée " -"`Client``. Dans les parties précédentes de ce tutoriel, nous avons basé " -"notre client sur ``NumPyClient``, une classe de commodité qui facilite le" -" travail avec les bibliothèques d'apprentissage automatique qui ont une " -"bonne interopérabilité NumPy. Avec ``Client``, nous gagnons beaucoup de " -"flexibilité que nous n'avions pas auparavant, mais nous devrons également" -" faire quelques choses que nous n'avions pas à faire auparavant." +"**Rename** `Weights` **to** `NDArrays` " +"([#1258](https://github.com/adap/flower/pull/1258), " +"[#1259](https://github.com/adap/flower/pull/1259))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:18 +#: ../../source/ref-changelog.md:96 msgid "" -"Let's go deeper and see what it takes to move from ``NumPyClient`` to " -"``Client``!" +"Experimental fields `sa`, `legacy_server_message` and " +"`legacy_client_message` were removed from `Task` message. The removed " +"fields are superseded by the new `RecordSet` abstraction." msgstr "" -"Allons plus loin et voyons ce qu'il faut faire pour passer de " -"``NumPyClient`` à ``Client`` !" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:30 -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:29 -msgid "Step 0: Preparation" -msgstr "Étape 0 : Préparation" +#: ../../source/ref-changelog.md:98 +#, fuzzy +msgid "" +"**Retire MXNet examples** " +"([#2724](https://github.com/adap/flower/pull/2724))" +msgstr "" +"**Nouvel exemple de code scikit-learn** " +"([#748](https://github.com/adap/flower/pull/748))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:117 +#: ../../source/ref-changelog.md:100 msgid "" -"Let's now load the CIFAR-10 training and test set, partition them into " -"ten smaller datasets (each split into training and validation set), and " -"wrap everything in their own ``DataLoader``." +"The development of the MXNet fremework has ended and the project is now " +"[archived on GitHub](https://github.com/apache/mxnet). Existing MXNet " +"examples won't receive updates." msgstr "" -"Chargeons maintenant les ensembles d'entraînement et de test CIFAR-10, " -"divisons-les en dix ensembles de données plus petits (chacun divisé en " -"ensemble d'entraînement et de validation) et enveloppons le tout dans " -"leur propre ``DataLoader``." -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:259 -msgid "Step 1: Revisiting NumPyClient" -msgstr "Étape 1 : Revoir NumPyClient" +#: ../../source/ref-changelog.md:102 +#, fuzzy +msgid "v1.6.0 (2023-11-28)" +msgstr "v1.4.0 (2023-04-21)" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:261 +#: ../../source/ref-changelog.md:108 msgid "" -"So far, we've implemented our client by subclassing " -"``flwr.client.NumPyClient``. The three methods we implemented are " -"``get_parameters``, ``fit``, and ``evaluate``. Finally, we wrap the " -"creation of instances of this class in a function called ``client_fn``:" +"`Aashish Kolluri`, `Adam Narozniak`, `Alessio Mora`, `Barathwaja S`, " +"`Charles Beauville`, `Daniel J. Beutel`, `Daniel Nata Nugraha`, `Gabriel " +"Mota`, `Heng Pan`, `Ivan Agarský`, `JS.KIM`, `Javier`, `Marius Schlegel`," +" `Navin Chandra`, `Nic Lane`, `Peterpan828`, `Qinbin Li`, `Shaz-hash`, " +"`Steve Laskaridis`, `Taner Topal`, `William Lindskog`, `Yan Gao`, " +"`cnxdeveloper`, `k3nfalt` " msgstr "" -"Jusqu'à présent, nous avons implémenté notre client en sous-classant " -"``flwr.client.NumPyClient``. Les trois méthodes que nous avons " -"implémentées sont ``get_parameters``, ``fit`` et ``evaluate``. Enfin, " -"nous enveloppons la création d'instances de cette classe dans une " -"fonction appelée ``client_fn`` :" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:309 +#: ../../source/ref-changelog.md:112 +#, fuzzy msgid "" -"We've seen this before, there's nothing new so far. The only *tiny* " -"difference compared to the previous notebook is naming, we've changed " -"``FlowerClient`` to ``FlowerNumPyClient`` and ``client_fn`` to " -"``numpyclient_fn``. Let's run it to see the output we get:" +"**Add experimental support for Python 3.12** " +"([#2565](https://github.com/adap/flower/pull/2565))" msgstr "" -"Nous avons déjà vu cela auparavant, il n'y a rien de nouveau jusqu'à " -"présent. La seule *petite* différence par rapport au carnet précédent est" -" le nommage, nous avons changé ``FlowerClient`` en ``FlowerNumPyClient`` " -"et ``client_fn`` en ``numpyclient_fn``. Exécutons-le pour voir la sortie " -"que nous obtenons :" +"**Ajouter la prise en charge expérimentale de Python 3.10 et Python " +"3.11** ([#1135](https://github.com/adap/flower/pull/1135))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:339 +#: ../../source/ref-changelog.md:114 +#, fuzzy msgid "" -"This works as expected, two clients are training for three rounds of " -"federated learning." +"**Add new XGBoost examples** " +"([#2612](https://github.com/adap/flower/pull/2612), " +"[#2554](https://github.com/adap/flower/pull/2554), " +"[#2617](https://github.com/adap/flower/pull/2617), " +"[#2618](https://github.com/adap/flower/pull/2618), " +"[#2619](https://github.com/adap/flower/pull/2619), " +"[#2567](https://github.com/adap/flower/pull/2567))" msgstr "" -"Cela fonctionne comme prévu, deux clients s'entraînent pour trois tours " -"d'apprentissage fédéré." +"**([#1520](https://github.com/adap/flower/pull/1520), " +"[#1525](https://github.com/adap/flower/pull/1525), " +"[#1545](https://github.com/adap/flower/pull/1545), " +"[#1546](https://github.com/adap/flower/pull/1546), " +"[#1550](https://github.com/adap/flower/pull/1550), " +"[#1551](https://github.com/adap/flower/pull/1551), " +"[#1567](https://github.com/adap/flower/pull/1567))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:341 +#: ../../source/ref-changelog.md:116 msgid "" -"Let's dive a little bit deeper and discuss how Flower executes this " -"simulation. Whenever a client is selected to do some work, " -"``start_simulation`` calls the function ``numpyclient_fn`` to create an " -"instance of our ``FlowerNumPyClient`` (along with loading the model and " -"the data)." +"We have added a new `xgboost-quickstart` example alongside a new " +"`xgboost-comprehensive` example that goes more in-depth." msgstr "" -"Plongeons un peu plus profondément et discutons de la façon dont Flower " -"exécute cette simulation. Chaque fois qu'un client est sélectionné pour " -"effectuer un travail, ``start_simulation`` appelle la fonction " -"``numpyclient_fn`` pour créer une instance de notre ``FlowerNumPyClient``" -" (en même temps qu'il charge le modèle et les données)." -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:343 +#: ../../source/ref-changelog.md:118 +#, fuzzy msgid "" -"But here's the perhaps surprising part: Flower doesn't actually use the " -"``FlowerNumPyClient`` object directly. Instead, it wraps the object to " -"makes it look like a subclass of ``flwr.client.Client``, not " -"``flwr.client.NumPyClient``. In fact, the Flower core framework doesn't " -"know how to handle ``NumPyClient``'s, it only knows how to handle " -"``Client``'s. ``NumPyClient`` is just a convenience abstraction built on " -"top of ``Client``." +"**Add Vertical FL example** " +"([#2598](https://github.com/adap/flower/pull/2598))" msgstr "" -"Mais voici la partie la plus surprenante : Flower n'utilise pas " -"directement l'objet `FlowerNumPyClient`. Au lieu de cela, il enveloppe " -"l'objet pour le faire ressembler à une sous-classe de " -"`flwr.client.Client`, et non de `flwr.client.NumPyClient`. En fait, le " -"noyau de Flower ne sait pas comment gérer les `NumPyClient`, il sait " -"seulement comment gérer les `Client`. `NumPyClient` est juste une " -"abstraction de commodité construite au dessus de `Client`." +"**Nouvel exemple de code CoreML pour iOS** " +"([#1289](https://github.com/adap/flower/pull/1289))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:345 +#: ../../source/ref-changelog.md:120 msgid "" -"Instead of building on top of ``NumPyClient``, we can directly build on " -"top of ``Client``." +"We had many questions about Vertical Federated Learning using Flower, so " +"we decided to add an simple example for it on the [Titanic " +"dataset](https://www.kaggle.com/competitions/titanic/data) alongside a " +"tutorial (in the README)." msgstr "" -"Au lieu de construire par-dessus `NumPyClient``, nous pouvons construire " -"directement par-dessus `Client``." - -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:357 -msgid "Step 2: Moving from ``NumPyClient`` to ``Client``" -msgstr "Étape 2 : Passer de ``NumPyClient`` à ``Client``" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:359 +#: ../../source/ref-changelog.md:122 +#, fuzzy msgid "" -"Let's try to do the same thing using ``Client`` instead of " -"``NumPyClient``." +"**Support custom** `ClientManager` **in** `start_driver()` " +"([#2292](https://github.com/adap/flower/pull/2292))" msgstr "" -"Essayons de faire la même chose en utilisant ``Client`` au lieu de " -"``NumPyClient``." +"Ajout de la prise en charge d'un `ClientManager` personnalisé comme " +"paramètre de `start_simulation` " +"([#1171](https://github.com/adap/flower/pull/1171))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:465 +#: ../../source/ref-changelog.md:124 +#, fuzzy msgid "" -"Before we discuss the code in more detail, let's try to run it! Gotta " -"make sure our new ``Client``-based client works, right?" +"**Update REST API to support create and delete nodes** " +"([#2283](https://github.com/adap/flower/pull/2283))" msgstr "" -"Avant de discuter du code plus en détail, essayons de l'exécuter ! Nous " -"devons nous assurer que notre nouveau client basé sur le ``Client`` " -"fonctionne, n'est-ce pas ?" +"**Nouvelle stratégie expérimentale TensorBoard** " +"([#789](https://github.com/adap/flower/pull/789))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:490 +#: ../../source/ref-changelog.md:126 +#, fuzzy msgid "" -"That's it, we're now using ``Client``. It probably looks similar to what " -"we've done with ``NumPyClient``. So what's the difference?" +"**Update the Android SDK** " +"([#2187](https://github.com/adap/flower/pull/2187))" msgstr "" -"Voilà, nous utilisons maintenant ``Client``. Cela ressemble probablement " -"à ce que nous avons fait avec ``NumPyClient``. Alors quelle est la " -"différence ?" +"**Introduire une nouvelle ligne de base pour les fleurs : FedAvg " +"FEMNIST** ([#1655](https://github.com/adap/flower/pull/1655))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:492 -msgid "" -"First of all, it's more code. But why? The difference comes from the fact" -" that ``Client`` expects us to take care of parameter serialization and " -"deserialization. For Flower to be able to send parameters over the " -"network, it eventually needs to turn these parameters into ``bytes``. " -"Turning parameters (e.g., NumPy ``ndarray``'s) into raw bytes is called " -"serialization. Turning raw bytes into something more useful (like NumPy " -"``ndarray``'s) is called deserialization. Flower needs to do both: it " -"needs to serialize parameters on the server-side and send them to the " -"client, the client needs to deserialize them to use them for local " -"training, and then serialize the updated parameters again to send them " -"back to the server, which (finally!) deserializes them again in order to " -"aggregate them with the updates received from other clients." +#: ../../source/ref-changelog.md:128 +msgid "Add gRPC request-response capability to the Android SDK." msgstr "" -"First of all, it's more code. But why? The difference comes from the fact" -" that ``Client`` expects us to take care of parameter serialization and " -"deserialization. For Flower to be able to send parameters over the " -"network, it eventually needs to turn these parameters into ``bytes``. " -"Turning parameters (e.g., NumPy ``ndarray``'s) into raw bytes is called " -"serialization. Turning raw bytes into something more useful (like NumPy " -"``ndarray``'s) is called deserialization. Flower needs to do both: it " -"needs to serialize parameters on the server-side and send them to the " -"client, the client needs to deserialize them to use them for local " -"training, and then serialize the updated parameters again to send them " -"back to the server, which (finally!) deserializes them again in order to " -"aggregate them with the updates received from other clients." -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:495 +#: ../../source/ref-changelog.md:130 +#, fuzzy msgid "" -"The only *real* difference between Client and NumPyClient is that " -"NumPyClient takes care of serialization and deserialization for you. It " -"can do so because it expects you to return parameters as NumPy ndarray's," -" and it knows how to handle these. This makes working with machine " -"learning libraries that have good NumPy support (most of them) a breeze." +"**Update the C++ SDK** " +"([#2537](https://github.com/adap/flower/pull/2537), " +"[#2528](https://github.com/adap/flower/pull/2528), " +"[#2523](https://github.com/adap/flower/pull/2523), " +"[#2522](https://github.com/adap/flower/pull/2522))" msgstr "" -"La seule *vraie* différence entre Client et NumPyClient est que " -"NumPyClient s'occupe de la sérialisation et de la désérialisation pour " -"toi. Il peut le faire parce qu'il s'attend à ce que tu renvoies des " -"paramètres sous forme de NumPy ndarray, et il sait comment les gérer. " -"Cela permet de travailler avec des bibliothèques d'apprentissage " -"automatique qui ont une bonne prise en charge de NumPy (la plupart " -"d'entre elles) en un clin d'œil." +"Mettre à jour les outils de développement " +"([#1231](https://github.com/adap/flower/pull/1231), " +"[#1276](https://github.com/adap/flower/pull/1276), " +"[#1301](https://github.com/adap/flower/pull/1301), " +"[#1310](https://github.com/adap/flower/pull/1310))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:497 -msgid "" -"In terms of API, there's one major difference: all methods in Client take" -" exactly one argument (e.g., ``FitIns`` in ``Client.fit``) and return " -"exactly one value (e.g., ``FitRes`` in ``Client.fit``). The methods in " -"``NumPyClient`` on the other hand have multiple arguments (e.g., " -"``parameters`` and ``config`` in ``NumPyClient.fit``) and multiple return" -" values (e.g., ``parameters``, ``num_example``, and ``metrics`` in " -"``NumPyClient.fit``) if there are multiple things to handle. These " -"``*Ins`` and ``*Res`` objects in ``Client`` wrap all the individual " -"values you're used to from ``NumPyClient``." +#: ../../source/ref-changelog.md:132 +msgid "Add gRPC request-response capability to the C++ SDK." msgstr "" -"In terms of API, there's one major difference: all methods in Client take" -" exactly one argument (e.g., ``FitIns`` in ``Client.fit``) and return " -"exactly one value (e.g., ``FitRes`` in ``Client.fit``). The methods in " -"``NumPyClient`` on the other hand have multiple arguments (e.g., " -"``parameters`` and ``config`` in ``NumPyClient.fit``) and multiple return" -" values (e.g., ``parameters``, ``num_example``, and ``metrics`` in " -"``NumPyClient.fit``) if there are multiple things to handle. These " -"``*Ins`` and ``*Res`` objects in ``Client`` wrap all the individual " -"values you're used to from ``NumPyClient``." -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:510 -msgid "Step 3: Custom serialization" -msgstr "Étape 3 : Sérialisation personnalisée" - -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:512 +#: ../../source/ref-changelog.md:134 +#, fuzzy msgid "" -"Here we will explore how to implement custom serialization with a simple " -"example." +"**Make HTTPS the new default** " +"([#2591](https://github.com/adap/flower/pull/2591), " +"[#2636](https://github.com/adap/flower/pull/2636))" msgstr "" -"Nous allons ici explorer comment mettre en œuvre une sérialisation " -"personnalisée à l'aide d'un exemple simple." +"**Exemple de code mis à jour** " +"([#1344](https://github.com/adap/flower/pull/1344), " +"[#1347](https://github.com/adap/flower/pull/1347))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:514 +#: ../../source/ref-changelog.md:136 msgid "" -"But first what is serialization? Serialization is just the process of " -"converting an object into raw bytes, and equally as important, " -"deserialization is the process of converting raw bytes back into an " -"object. This is very useful for network communication. Indeed, without " -"serialization, you could not just a Python object through the internet." +"Flower is moving to HTTPS by default. The new `flower-server` requires " +"passing `--certificates`, but users can enable `--insecure` to use HTTP " +"for prototyping. The same applies to `flower-client`, which can either " +"use user-provided credentials or gRPC-bundled certificates to connect to " +"an HTTPS-enabled server or requires opt-out via passing `--insecure` to " +"enable insecure HTTP connections." msgstr "" -"Mais d'abord, qu'est-ce que la sérialisation ? La sérialisation est " -"simplement le processus de conversion d'un objet en octets bruts, et tout" -" aussi important, la désérialisation est le processus de reconversion des" -" octets bruts en objet. Ceci est très utile pour la communication réseau." -" En effet, sans la sérialisation, tu ne pourrais pas faire passer un " -"objet Python par Internet." -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:516 +#: ../../source/ref-changelog.md:138 msgid "" -"Federated Learning relies heavily on internet communication for training " -"by sending Python objects back and forth between the clients and the " -"server. This means that serialization is an essential part of Federated " -"Learning." +"For backward compatibility, `start_client()` and `start_numpy_client()` " +"will still start in insecure mode by default. In a future release, " +"insecure connections will require user opt-in by passing `insecure=True`." msgstr "" -"L'apprentissage fédéré s'appuie fortement sur la communication Internet " -"pour la formation en envoyant des objets Python dans les deux sens entre " -"les clients et le serveur, ce qui signifie que la sérialisation est un " -"élément essentiel de l'apprentissage fédéré." -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:518 +#: ../../source/ref-changelog.md:140 +#, fuzzy msgid "" -"In the following section, we will write a basic example where instead of " -"sending a serialized version of our ``ndarray``\\ s containing our " -"parameters, we will first convert the ``ndarray`` into sparse matrices, " -"before sending them. This technique can be used to save bandwidth, as in " -"certain cases where the weights of a model are sparse (containing many 0 " -"entries), converting them to a sparse matrix can greatly improve their " -"bytesize." +"**Unify client API** ([#2303](https://github.com/adap/flower/pull/2303), " +"[#2390](https://github.com/adap/flower/pull/2390), " +"[#2493](https://github.com/adap/flower/pull/2493))" msgstr "" -"Dans la section suivante, nous allons écrire un exemple de base où, au " -"lieu d'envoyer une version sérialisée de nos ``ndarray`` contenant nos " -"paramètres, nous allons d'abord convertir les ``ndarray`` en matrices " -"éparses, avant de les envoyer. Cette technique peut être utilisée pour " -"économiser de la bande passante, car dans certains cas où les poids d'un " -"modèle sont épars (contenant de nombreuses entrées 0), les convertir en " -"une matrice éparse peut grandement améliorer leur taille en octets." - -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:521 -msgid "Our custom serialization/deserialization functions" -msgstr "Nos fonctions de sérialisation/désérialisation personnalisées" +"**Mettre à jour les exemples de code** " +"([#1291](https://github.com/adap/flower/pull/1291), " +"[#1286](https://github.com/adap/flower/pull/1286), " +"[#1282](https://github.com/adap/flower/pull/1282))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:523 +#: ../../source/ref-changelog.md:142 msgid "" -"This is where the real serialization/deserialization will happen, " -"especially in ``ndarray_to_sparse_bytes`` for serialization and " -"``sparse_bytes_to_ndarray`` for deserialization." +"Using the `client_fn`, Flower clients can interchangeably run as " +"standalone processes (i.e. via `start_client`) or in simulation (i.e. via" +" `start_simulation`) without requiring changes to how the client class is" +" defined and instantiated. The `to_client()` function is introduced to " +"convert a `NumPyClient` to a `Client`." msgstr "" -"C'est là que la véritable sérialisation/désérialisation se produira, en " -"particulier dans ``ndarray_to_sparse_bytes`` pour la sérialisation et " -"``sparse_bytes_to_ndarray`` pour la désérialisation." -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:525 +#: ../../source/ref-changelog.md:144 +#, fuzzy msgid "" -"Note that we imported the ``scipy.sparse`` library in order to convert " -"our arrays." +"**Add new** `Bulyan` **strategy** " +"([#1817](https://github.com/adap/flower/pull/1817), " +"[#1891](https://github.com/adap/flower/pull/1891))" msgstr "" -"Notez que nous avons importé la bibliothèque ``scipy.sparse`` afin de " -"convertir nos tableaux." - -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:613 -msgid "Client-side" -msgstr "Côté client" +"**Nouvelles stratégies intégrées** " +"([#828](https://github.com/adap/flower/pull/828) " +"[#822](https://github.com/adap/flower/pull/822))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:615 +#: ../../source/ref-changelog.md:146 +#, fuzzy msgid "" -"To be able to able to serialize our ``ndarray``\\ s into sparse " -"parameters, we will just have to call our custom functions in our " -"``flwr.client.Client``." +"The new `Bulyan` strategy implements Bulyan by [El Mhamdi et al., " +"2018](https://arxiv.org/abs/1802.07927)" msgstr "" -"Pour pouvoir sérialiser nos ``ndarray`` en paramètres sparse, il nous " -"suffira d'appeler nos fonctions personnalisées dans notre " -"``flwr.client.Client``." +"La nouvelle stratégie `FedMedian` met en œuvre Federated Median " +"(FedMedian) par [Yin et al., 2018] " +"(https://arxiv.org/pdf/1803.01498v1.pdf)." -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:617 +#: ../../source/ref-changelog.md:148 +#, fuzzy msgid "" -"Indeed, in ``get_parameters`` we need to serialize the parameters we got " -"from our network using our custom ``ndarrays_to_sparse_parameters`` " -"defined above." +"**Add new** `XGB Bagging` **strategy** " +"([#2611](https://github.com/adap/flower/pull/2611))" msgstr "" -"En effet, dans ``get_parameters`` nous devons sérialiser les paramètres " -"que nous avons obtenus de notre réseau en utilisant nos " -"``ndarrays_to_sparse_parameters`` personnalisés définis ci-dessus." +"**Ajouter une nouvelle stratégie `FedProx`** " +"([#1619](https://github.com/adap/flower/pull/1619))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:619 +#: ../../source/ref-changelog.md:150 ../../source/ref-changelog.md:152 +#, fuzzy msgid "" -"In ``fit``, we first need to deserialize the parameters coming from the " -"server using our custom ``sparse_parameters_to_ndarrays`` and then we " -"need to serialize our local results with " -"``ndarrays_to_sparse_parameters``." +"**Introduce `WorkloadState`** " +"([#2564](https://github.com/adap/flower/pull/2564), " +"[#2632](https://github.com/adap/flower/pull/2632))" msgstr "" -"Dans ``fit``, nous devons d'abord désérialiser les paramètres provenant " -"du serveur en utilisant notre ``sparse_parameters_to_ndarrays`` " -"personnalisé, puis nous devons sérialiser nos résultats locaux avec " -"``ndarrays_to_sparse_parameters``." +"**Nouvelles stratégies intégrées** " +"([#828](https://github.com/adap/flower/pull/828) " +"[#822](https://github.com/adap/flower/pull/822))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:621 +#: ../../source/ref-changelog.md:156 +#, fuzzy msgid "" -"In ``evaluate``, we will only need to deserialize the global parameters " -"with our custom function." +"FedProx ([#2210](https://github.com/adap/flower/pull/2210), " +"[#2286](https://github.com/adap/flower/pull/2286), " +"[#2509](https://github.com/adap/flower/pull/2509))" msgstr "" -"Dans ``evaluate``, nous n'aurons besoin que de désérialiser les " -"paramètres globaux avec notre fonction personnalisée." - -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:725 -msgid "Server-side" -msgstr "Côté serveur" +"**Mettre à jour les exemples de code** " +"([#1291](https://github.com/adap/flower/pull/1291), " +"[#1286](https://github.com/adap/flower/pull/1286), " +"[#1282](https://github.com/adap/flower/pull/1282))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:727 +#: ../../source/ref-changelog.md:158 +#, fuzzy msgid "" -"For this example, we will just use ``FedAvg`` as a strategy. To change " -"the serialization and deserialization here, we only need to reimplement " -"the ``evaluate`` and ``aggregate_fit`` functions of ``FedAvg``. The other" -" functions of the strategy will be inherited from the super class " -"``FedAvg``." +"Baselines Docs ([#2290](https://github.com/adap/flower/pull/2290), " +"[#2400](https://github.com/adap/flower/pull/2400))" msgstr "" -"Pour cet exemple, nous utiliserons simplement ``FedAvg`` comme stratégie." -" Pour modifier la sérialisation et la désérialisation ici, il suffit de " -"réimplémenter les fonctions ``evaluate`` et ``aggregate_fit`` de " -"``FedAvg``. Les autres fonctions de la stratégie seront héritées de la " -"super-classe ``FedAvg``." +"**Nouvel exemple de code JAX** " +"([#906](https://github.com/adap/flower/pull/906), " +"[#1143](https://github.com/adap/flower/pull/1143))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:729 -msgid "As you can see only one line as change in ``evaluate``:" -msgstr "Comme tu peux le voir, seule une ligne a été modifiée dans ``evaluate`` :" +#: ../../source/ref-changelog.md:160 +#, fuzzy +msgid "" +"FedMLB ([#2340](https://github.com/adap/flower/pull/2340), " +"[#2507](https://github.com/adap/flower/pull/2507))" +msgstr "" +"**Exemple de code mis à jour** " +"([#1344](https://github.com/adap/flower/pull/1344), " +"[#1347](https://github.com/adap/flower/pull/1347))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:735 +#: ../../source/ref-changelog.md:162 +#, fuzzy msgid "" -"And for ``aggregate_fit``, we will first deserialize every result we " -"received:" +"TAMUNA ([#2254](https://github.com/adap/flower/pull/2254), " +"[#2508](https://github.com/adap/flower/pull/2508))" msgstr "" -"Et pour ``aggregate_fit``, nous allons d'abord désérialiser chaque " -"résultat que nous avons reçu :" +"**Nouvelles stratégies intégrées** " +"([#828](https://github.com/adap/flower/pull/828) " +"[#822](https://github.com/adap/flower/pull/822))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:744 -msgid "And then serialize the aggregated result:" -msgstr "Puis sérialise le résultat agrégé :" +#: ../../source/ref-changelog.md:164 +#, fuzzy +msgid "FedMeta [#2438](https://github.com/adap/flower/pull/2438)" +msgstr "Nouvelle référence API ([#554](https://github.com/adap/flower/pull/554))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:903 -msgid "We can now run our custom serialization example!" +#: ../../source/ref-changelog.md:166 +#, fuzzy +msgid "FjORD [#2431](https://github.com/adap/flower/pull/2431)" msgstr "" -"Nous pouvons maintenant exécuter notre exemple de sérialisation " -"personnalisée !" +"Amélioration de la documentation sur le serveur gRPC " +"([#841](https://github.com/adap/flower/pull/841))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:934 -msgid "" -"In this part of the tutorial, we've seen how we can build clients by " -"subclassing either ``NumPyClient`` or ``Client``. ``NumPyClient`` is a " -"convenience abstraction that makes it easier to work with machine " -"learning libraries that have good NumPy interoperability. ``Client`` is a" -" more flexible abstraction that allows us to do things that are not " -"possible in ``NumPyClient``. In order to do so, it requires us to handle " -"parameter serialization and deserialization ourselves." +#: ../../source/ref-changelog.md:168 +#, fuzzy +msgid "MOON [#2421](https://github.com/adap/flower/pull/2421)" msgstr "" -"Dans cette partie du tutoriel, nous avons vu comment construire des " -"clients en sous-classant soit ``NumPyClient``, soit ``Client``. " -"``NumPyClient`` est une abstraction de commodité qui facilite le travail " -"avec les bibliothèques d'apprentissage automatique qui ont une bonne " -"interopérabilité NumPy. ``Client`` est une abstraction plus flexible qui " -"nous permet de faire des choses qui ne sont pas possibles dans " -"``NumPyClient``. Pour ce faire, elle nous oblige à gérer nous-mêmes la " -"sérialisation et la désérialisation des paramètres." +"**Ajouter une nouvelle stratégie `FedProx`** " +"([#1619](https://github.com/adap/flower/pull/1619))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:952 -msgid "" -"This is the final part of the Flower tutorial (for now!), " -"congratulations! You're now well equipped to understand the rest of the " -"documentation. There are many topics we didn't cover in the tutorial, we " -"recommend the following resources:" +#: ../../source/ref-changelog.md:170 +#, fuzzy +msgid "DepthFL [#2295](https://github.com/adap/flower/pull/2295)" msgstr "" -"C'est la dernière partie du tutoriel Flower (pour l'instant !), " -"félicitations ! Tu es maintenant bien équipé pour comprendre le reste de " -"la documentation. Il y a de nombreux sujets que nous n'avons pas abordés " -"dans le tutoriel, nous te recommandons les ressources suivantes :" +"**Ajouter une nouvelle stratégie `FedProx`** " +"([#1619](https://github.com/adap/flower/pull/1619))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:954 -msgid "`Read Flower Docs `__" -msgstr "`Lire les docs sur les fleurs `__" +#: ../../source/ref-changelog.md:172 +#, fuzzy +msgid "FedPer [#2266](https://github.com/adap/flower/pull/2266)" +msgstr "Nouvelle référence API ([#554](https://github.com/adap/flower/pull/554))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:955 -msgid "" -"`Check out Flower Code Examples " -"`__" -msgstr "" -"`Check out Flower Code Examples " -"`__" +#: ../../source/ref-changelog.md:174 +#, fuzzy +msgid "FedWav2vec [#2551](https://github.com/adap/flower/pull/2551)" +msgstr "Nouvelle référence API ([#554](https://github.com/adap/flower/pull/554))" + +#: ../../source/ref-changelog.md:176 +#, fuzzy +msgid "niid-Bench [#2428](https://github.com/adap/flower/pull/2428)" +msgstr "Nouvelle référence API ([#554](https://github.com/adap/flower/pull/554))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:956 +#: ../../source/ref-changelog.md:178 #, fuzzy msgid "" -"`Use Flower Baselines for your research " -"`__" +"FedBN ([#2608](https://github.com/adap/flower/pull/2608), " +"[#2615](https://github.com/adap/flower/pull/2615))" msgstr "" -"`Utilise les lignes de base des fleurs pour ta recherche " -"`__" +"**Nouvelles stratégies intégrées** " +"([#828](https://github.com/adap/flower/pull/828) " +"[#822](https://github.com/adap/flower/pull/822))" -#: ../../source/tutorial-customize-the-client-pytorch.ipynb:957 +#: ../../source/ref-changelog.md:180 #, fuzzy msgid "" -"`Watch Flower Summit 2023 videos `__" +"**General updates to Flower Examples** " +"([#2384](https://github.com/adap/flower/pull/2384), " +"[#2425](https://github.com/adap/flower/pull/2425), " +"[#2526](https://github.com/adap/flower/pull/2526), " +"[#2302](https://github.com/adap/flower/pull/2302), " +"[#2545](https://github.com/adap/flower/pull/2545))" msgstr "" -"`Regardez les vidéos du Flower Summit 2022 `__" +"Mettre à jour les outils de développement " +"([#1231](https://github.com/adap/flower/pull/1231), " +"[#1276](https://github.com/adap/flower/pull/1276), " +"[#1301](https://github.com/adap/flower/pull/1301), " +"[#1310](https://github.com/adap/flower/pull/1310))" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:9 -msgid "Get started with Flower" +#: ../../source/ref-changelog.md:182 +#, fuzzy +msgid "" +"**General updates to Flower Baselines** " +"([#2301](https://github.com/adap/flower/pull/2301), " +"[#2305](https://github.com/adap/flower/pull/2305), " +"[#2307](https://github.com/adap/flower/pull/2307), " +"[#2327](https://github.com/adap/flower/pull/2327), " +"[#2435](https://github.com/adap/flower/pull/2435), " +"[#2462](https://github.com/adap/flower/pull/2462), " +"[#2463](https://github.com/adap/flower/pull/2463), " +"[#2461](https://github.com/adap/flower/pull/2461), " +"[#2469](https://github.com/adap/flower/pull/2469), " +"[#2466](https://github.com/adap/flower/pull/2466), " +"[#2471](https://github.com/adap/flower/pull/2471), " +"[#2472](https://github.com/adap/flower/pull/2472), " +"[#2470](https://github.com/adap/flower/pull/2470))" msgstr "" +"**Améliorations générales** " +"([#1491](https://github.com/adap/flower/pull/1491), " +"[#1504](https://github.com/adap/flower/pull/1504), " +"[#1506](https://github.com/adap/flower/pull/1506), " +"[#1514](https://github.com/adap/flower/pull/1514), " +"[#1522](https://github.com/adap/flower/pull/1522), " +"[#1523](https://github.com/adap/flower/pull/1523), " +"[#1526](https://github.com/adap/flower/pull/1526), " +"[#1528](https://github.com/adap/flower/pull/1528), " +"[#1547](https://github.com/adap/flower/pull/1547), " +"[#1549](https://github.com/adap/flower/pull/1549), " +"[#1560](https://github.com/adap/flower/pull/1560), " +"[#1564](https://github.com/adap/flower/pull/1564), " +"[#1566](https://github.com/adap/flower/pull/1566))" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:11 -#: ../../source/tutorial-what-is-federated-learning.ipynb:11 -msgid "Welcome to the Flower federated learning tutorial!" -msgstr "Bienvenue au tutoriel sur l'apprentissage fédéré de la fleur !" - -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:13 +#: ../../source/ref-changelog.md:184 +#, fuzzy msgid "" -"In this notebook, we'll build a federated learning system using Flower " -"and PyTorch. In part 1, we use PyTorch for the model training pipeline " -"and data loading. In part 2, we continue to federate the PyTorch-based " -"pipeline using Flower." +"**General updates to the simulation engine** " +"([#2331](https://github.com/adap/flower/pull/2331), " +"[#2447](https://github.com/adap/flower/pull/2447), " +"[#2448](https://github.com/adap/flower/pull/2448), " +"[#2294](https://github.com/adap/flower/pull/2294))" msgstr "" -"Dans ce carnet, nous allons construire un système d'apprentissage fédéré " -"en utilisant Flower et PyTorch. Dans la première partie, nous utilisons " -"PyTorch pour le pipeline d'entraînement des modèles et le chargement des " -"données. Dans la deuxième partie, nous continuons à fédérer le pipeline " -"basé sur PyTorch en utilisant Flower." - -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:17 -#: ../../source/tutorial-what-is-federated-learning.ipynb:19 -msgid "Let's get stated!" -msgstr "Allons-y, déclarons-le !" +"Mettre à jour les outils de développement " +"([#1231](https://github.com/adap/flower/pull/1231), " +"[#1276](https://github.com/adap/flower/pull/1276), " +"[#1301](https://github.com/adap/flower/pull/1301), " +"[#1310](https://github.com/adap/flower/pull/1310))" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:31 +#: ../../source/ref-changelog.md:186 +#, fuzzy msgid "" -"Before we begin with any actual code, let's make sure that we have " -"everything we need." +"**General updates to Flower SDKs** " +"([#2288](https://github.com/adap/flower/pull/2288), " +"[#2429](https://github.com/adap/flower/pull/2429), " +"[#2555](https://github.com/adap/flower/pull/2555), " +"[#2543](https://github.com/adap/flower/pull/2543), " +"[#2544](https://github.com/adap/flower/pull/2544), " +"[#2597](https://github.com/adap/flower/pull/2597), " +"[#2623](https://github.com/adap/flower/pull/2623))" msgstr "" -"Avant de commencer à coder, assurons-nous que nous disposons de tout ce " -"dont nous avons besoin." +"**Tutoriel amélioré** ([#1468](https://github.com/adap/flower/pull/1468)," +" [#1470](https://github.com/adap/flower/pull/1470), " +"[#1472](https://github.com/adap/flower/pull/1472), " +"[#1473](https://github.com/adap/flower/pull/1473), " +"[#1474](https://github.com/adap/flower/pull/1474), " +"[#1475](https://github.com/adap/flower/pull/1475))" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:45 +#: ../../source/ref-changelog.md:188 msgid "" -"Next, we install the necessary packages for PyTorch (``torch`` and " -"``torchvision``) and Flower (``flwr``):" +"**General improvements** " +"([#2309](https://github.com/adap/flower/pull/2309), " +"[#2310](https://github.com/adap/flower/pull/2310), " +"[#2313](https://github.com/adap/flower/pull/2313), " +"[#2316](https://github.com/adap/flower/pull/2316), " +"[#2317](https://github.com/adap/flower/pull/2317), " +"[#2349](https://github.com/adap/flower/pull/2349), " +"[#2360](https://github.com/adap/flower/pull/2360), " +"[#2402](https://github.com/adap/flower/pull/2402), " +"[#2446](https://github.com/adap/flower/pull/2446), " +"[#2561](https://github.com/adap/flower/pull/2561), " +"[#2273](https://github.com/adap/flower/pull/2273), " +"[#2267](https://github.com/adap/flower/pull/2267), " +"[#2274](https://github.com/adap/flower/pull/2274), " +"[#2275](https://github.com/adap/flower/pull/2275), " +"[#2432](https://github.com/adap/flower/pull/2432), " +"[#2251](https://github.com/adap/flower/pull/2251), " +"[#2321](https://github.com/adap/flower/pull/2321), " +"[#1936](https://github.com/adap/flower/pull/1936), " +"[#2408](https://github.com/adap/flower/pull/2408), " +"[#2413](https://github.com/adap/flower/pull/2413), " +"[#2401](https://github.com/adap/flower/pull/2401), " +"[#2531](https://github.com/adap/flower/pull/2531), " +"[#2534](https://github.com/adap/flower/pull/2534), " +"[#2535](https://github.com/adap/flower/pull/2535), " +"[#2521](https://github.com/adap/flower/pull/2521), " +"[#2553](https://github.com/adap/flower/pull/2553), " +"[#2596](https://github.com/adap/flower/pull/2596))" +msgstr "" + +#: ../../source/ref-changelog.md:190 ../../source/ref-changelog.md:280 +#: ../../source/ref-changelog.md:344 ../../source/ref-changelog.md:398 +#: ../../source/ref-changelog.md:465 +msgid "Flower received many improvements under the hood, too many to list here." msgstr "" -"Ensuite, nous installons les paquets nécessaires pour PyTorch (``torch`` " -"et ``torchvision``) et Flower (``flwr``) :" - -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:117 -msgid "Loading the data" -msgstr "Chargement des données" +"Flower a reçu de nombreuses améliorations sous le capot, trop nombreuses " +"pour être énumérées ici." -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:119 +#: ../../source/ref-changelog.md:194 +#, fuzzy msgid "" -"Federated learning can be applied to many different types of tasks across" -" different domains. In this tutorial, we introduce federated learning by " -"training a simple convolutional neural network (CNN) on the popular " -"CIFAR-10 dataset. CIFAR-10 can be used to train image classifiers that " -"distinguish between images from ten different classes:" +"**Remove support for Python 3.7** " +"([#2280](https://github.com/adap/flower/pull/2280), " +"[#2299](https://github.com/adap/flower/pull/2299), " +"[#2304](https://github.com/adap/flower/pull/2304), " +"[#2306](https://github.com/adap/flower/pull/2306), " +"[#2355](https://github.com/adap/flower/pull/2355), " +"[#2356](https://github.com/adap/flower/pull/2356))" msgstr "" -"L'apprentissage fédéré peut être appliqué à de nombreux types de tâches " -"dans différents domaines. Dans ce tutoriel, nous présentons " -"l'apprentissage fédéré en formant un simple réseau neuronal " -"convolutionnel (CNN) sur l'ensemble de données populaire CIFAR-10. " -"CIFAR-10 peut être utilisé pour former des classificateurs d'images qui " -"font la distinction entre les images de dix classes différentes :" +"**Nouvel exemple de code MLCube** " +"([#779](https://github.com/adap/flower/pull/779), " +"[#1034](https://github.com/adap/flower/pull/1034), " +"[#1065](https://github.com/adap/flower/pull/1065), " +"[#1090](https://github.com/adap/flower/pull/1090))" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:150 +#: ../../source/ref-changelog.md:196 msgid "" -"We simulate having multiple datasets from multiple organizations (also " -"called the \"cross-silo\" setting in federated learning) by splitting the" -" original CIFAR-10 dataset into multiple partitions. Each partition will " -"represent the data from a single organization. We're doing this purely " -"for experimentation purposes, in the real world there's no need for data " -"splitting because each organization already has their own data (so the " -"data is naturally partitioned)." +"Python 3.7 support was deprecated in Flower 1.5, and this release removes" +" support. Flower now requires Python 3.8." msgstr "" -"Nous simulons le fait d'avoir plusieurs ensembles de données provenant de" -" plusieurs organisations (également appelé le paramètre \"cross-silo\" " -"dans l'apprentissage fédéré) en divisant l'ensemble de données CIFAR-10 " -"original en plusieurs partitions. Chaque partition représentera les " -"données d'une seule organisation. Nous faisons cela purement à des fins " -"d'expérimentation, dans le monde réel, il n'y a pas besoin de diviser les" -" données parce que chaque organisation a déjà ses propres données (les " -"données sont donc naturellement partitionnées)." -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:152 +#: ../../source/ref-changelog.md:198 +#, fuzzy msgid "" -"Each organization will act as a client in the federated learning system. " -"So having ten organizations participate in a federation means having ten " -"clients connected to the federated learning server:" +"**Remove experimental argument** `rest` **from** `start_client` " +"([#2324](https://github.com/adap/flower/pull/2324))" msgstr "" -"Chaque organisation agira comme un client dans le système d'apprentissage" -" fédéré. Ainsi, le fait que dix organisations participent à une " -"fédération signifie que dix clients sont connectés au serveur " -"d'apprentissage fédéré :" +"**Supprimer les stratégies expérimentales** " +"([#1280](https://github.com/adap/flower/pull/1280))" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:172 +#: ../../source/ref-changelog.md:200 msgid "" -"Let's now load the CIFAR-10 training and test set, partition them into " -"ten smaller datasets (each split into training and validation set), and " -"wrap the resulting partitions by creating a PyTorch ``DataLoader`` for " -"each of them:" +"The (still experimental) argument `rest` was removed from `start_client` " +"and `start_numpy_client`. Use `transport=\"rest\"` to opt into the " +"experimental REST API instead." msgstr "" -"Chargeons maintenant l'ensemble de formation et de test CIFAR-10, " -"partitionnons-les en dix ensembles de données plus petits (chacun divisé " -"en ensemble de formation et de validation), et enveloppons les partitions" -" résultantes en créant un PyTorch ``DataLoader`` pour chacun d'entre eux " -":" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:222 +#: ../../source/ref-changelog.md:202 +#, fuzzy +msgid "v1.5.0 (2023-08-31)" +msgstr "v1.4.0 (2023-04-21)" + +#: ../../source/ref-changelog.md:208 msgid "" -"We now have a list of ten training sets and ten validation sets " -"(``trainloaders`` and ``valloaders``) representing the data of ten " -"different organizations. Each ``trainloader``/``valloader`` pair contains" -" 4500 training examples and 500 validation examples. There's also a " -"single ``testloader`` (we did not split the test set). Again, this is " -"only necessary for building research or educational systems, actual " -"federated learning systems have their data naturally distributed across " -"multiple partitions." +"`Adam Narozniak`, `Anass Anhari`, `Charles Beauville`, `Dana-Farber`, " +"`Daniel J. Beutel`, `Daniel Nata Nugraha`, `Edoardo Gabrielli`, `Gustavo " +"Bertoli`, `Heng Pan`, `Javier`, `Mahdi`, `Steven Hé (Sīchàng)`, `Taner " +"Topal`, `achiverram28`, `danielnugraha`, `eunchung`, `ruthgal` " msgstr "" -"Nous avons maintenant une liste de dix ensembles de formation et dix " -"ensembles de validation (``trainloaders`` et ``valloaders``) représentant" -" les données de dix organisations différentes. Chaque paire " -"``trainloader`/``valloader`` contient 4500 exemples de formation et 500 " -"exemples de validation. Il y a également un seul ``testloader`` (nous " -"n'avons pas divisé l'ensemble de test). Encore une fois, cela n'est " -"nécessaire que pour construire des systèmes de recherche ou d'éducation, " -"les systèmes d'apprentissage fédérés actuels ont leurs données " -"naturellement distribuées à travers plusieurs partitions." -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:225 +#: ../../source/ref-changelog.md:212 +#, fuzzy msgid "" -"Let's take a look at the first batch of images and labels in the first " -"training set (i.e., ``trainloaders[0]``) before we move on:" +"**Introduce new simulation engine** " +"([#1969](https://github.com/adap/flower/pull/1969), " +"[#2221](https://github.com/adap/flower/pull/2221), " +"[#2248](https://github.com/adap/flower/pull/2248))" msgstr "" -"Jetons un coup d'œil au premier lot d'images et d'étiquettes du premier " -"ensemble d'entraînement (c'est-à-dire ``trainloaders[0]``) avant de " -"poursuivre :" +"**Introduire la télémétrie optionnelle** " +"([#1533](https://github.com/adap/flower/pull/1533), " +"[#1544](https://github.com/adap/flower/pull/1544), " +"[#1584](https://github.com/adap/flower/pull/1584))" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:264 +#: ../../source/ref-changelog.md:214 msgid "" -"The output above shows a random batch of images from the first " -"``trainloader`` in our list of ten ``trainloaders``. It also prints the " -"labels associated with each image (i.e., one of the ten possible labels " -"we've seen above). If you run the cell again, you should see another " -"batch of images." +"The new simulation engine has been rewritten from the ground up, yet it " +"remains fully backwards compatible. It offers much improved stability and" +" memory handling, especially when working with GPUs. Simulations " +"transparently adapt to different settings to scale simulation in CPU-" +"only, CPU+GPU, multi-GPU, or multi-node multi-GPU environments." msgstr "" -"La sortie ci-dessus montre un lot aléatoire d'images provenant du premier" -" ``chargeur de formation`` de notre liste de dix ``chargeurs de " -"formation``. Elle imprime également les étiquettes associées à chaque " -"image (c'est-à-dire l'une des dix étiquettes possibles que nous avons " -"vues ci-dessus). Si tu exécutes à nouveau la cellule, tu devrais voir un " -"autre lot d'images." - -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:276 -msgid "Step 1: Centralized Training with PyTorch" -msgstr "Étape 1 : Formation centralisée avec PyTorch" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:287 +#: ../../source/ref-changelog.md:216 msgid "" -"Next, we're going to use PyTorch to define a simple convolutional neural " -"network. This introduction assumes basic familiarity with PyTorch, so it " -"doesn't cover the PyTorch-related aspects in full detail. If you want to " -"dive deeper into PyTorch, we recommend `DEEP LEARNING WITH PYTORCH: A 60 " -"MINUTE BLITZ " -"`__." +"Comprehensive documentation includes a new [how-to run " +"simulations](https://flower.dev/docs/framework/how-to-run-" +"simulations.html) guide, new [simulation-" +"pytorch](https://flower.dev/docs/examples/simulation-pytorch.html) and " +"[simulation-tensorflow](https://flower.dev/docs/examples/simulation-" +"tensorflow.html) notebooks, and a new [YouTube tutorial " +"series](https://www.youtube.com/watch?v=cRebUIGB5RU&list=PLNG4feLHqCWlnj8a_E1A_n5zr2-8pafTB)." msgstr "" -"Ensuite, nous allons utiliser PyTorch pour définir un simple réseau " -"neuronal convolutif. Cette introduction suppose une familiarité de base " -"avec PyTorch, elle ne couvre donc pas en détail les aspects liés à " -"PyTorch. Si tu veux plonger plus profondément dans PyTorch, nous te " -"recommandons `DEEP LEARNING WITH PYTORCH : A 60 MINUTE BLITZ " -"`__." - -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:299 -msgid "Defining the model" -msgstr "Définir le modèle" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:301 +#: ../../source/ref-changelog.md:218 msgid "" -"We use the simple CNN described in the `PyTorch tutorial " -"`__:" +"**Restructure Flower Docs** " +"([#1824](https://github.com/adap/flower/pull/1824), " +"[#1865](https://github.com/adap/flower/pull/1865), " +"[#1884](https://github.com/adap/flower/pull/1884), " +"[#1887](https://github.com/adap/flower/pull/1887), " +"[#1919](https://github.com/adap/flower/pull/1919), " +"[#1922](https://github.com/adap/flower/pull/1922), " +"[#1920](https://github.com/adap/flower/pull/1920), " +"[#1923](https://github.com/adap/flower/pull/1923), " +"[#1924](https://github.com/adap/flower/pull/1924), " +"[#1962](https://github.com/adap/flower/pull/1962), " +"[#2006](https://github.com/adap/flower/pull/2006), " +"[#2133](https://github.com/adap/flower/pull/2133), " +"[#2203](https://github.com/adap/flower/pull/2203), " +"[#2215](https://github.com/adap/flower/pull/2215), " +"[#2122](https://github.com/adap/flower/pull/2122), " +"[#2223](https://github.com/adap/flower/pull/2223), " +"[#2219](https://github.com/adap/flower/pull/2219), " +"[#2232](https://github.com/adap/flower/pull/2232), " +"[#2233](https://github.com/adap/flower/pull/2233), " +"[#2234](https://github.com/adap/flower/pull/2234), " +"[#2235](https://github.com/adap/flower/pull/2235), " +"[#2237](https://github.com/adap/flower/pull/2237), " +"[#2238](https://github.com/adap/flower/pull/2238), " +"[#2242](https://github.com/adap/flower/pull/2242), " +"[#2231](https://github.com/adap/flower/pull/2231), " +"[#2243](https://github.com/adap/flower/pull/2243), " +"[#2227](https://github.com/adap/flower/pull/2227))" msgstr "" -"Nous utilisons le CNN simple décrit dans le tutoriel `PyTorch " -"`__ :" - -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:338 -msgid "Let's continue with the usual training and test functions:" -msgstr "Poursuivons avec les fonctions habituelles de formation et de test :" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:398 -msgid "Training the model" -msgstr "Entraîne le modèle" +#: ../../source/ref-changelog.md:220 +msgid "" +"Much effort went into a completely restructured Flower docs experience. " +"The documentation on [flower.dev/docs](flower.dev/docs) is now divided " +"into Flower Framework, Flower Baselines, Flower Android SDK, Flower iOS " +"SDK, and code example projects." +msgstr "" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:400 +#: ../../source/ref-changelog.md:222 +#, fuzzy msgid "" -"We now have all the basic building blocks we need: a dataset, a model, a " -"training function, and a test function. Let's put them together to train " -"the model on the dataset of one of our organizations " -"(``trainloaders[0]``). This simulates the reality of most machine " -"learning projects today: each organization has their own data and trains " -"models only on this internal data:" +"**Introduce Flower Swift SDK** " +"([#1858](https://github.com/adap/flower/pull/1858), " +"[#1897](https://github.com/adap/flower/pull/1897))" msgstr "" -"Nous avons maintenant tous les éléments de base dont nous avons besoin : " -"un ensemble de données, un modèle, une fonction d'entraînement et une " -"fonction de test. Assemblons-les pour entraîner le modèle sur l'ensemble " -"de données de l'une de nos organisations (``trainloaders[0]``). Cela " -"simule la réalité de la plupart des projets d'apprentissage automatique " -"aujourd'hui : chaque organisation possède ses propres données et entraîne" -" les modèles uniquement sur ces données internes :" +"**Introduction du SDK iOS (aperçu)** " +"([#1621](https://github.com/adap/flower/pull/1621), " +"[#1764](https://github.com/adap/flower/pull/1764))" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:430 +#: ../../source/ref-changelog.md:224 msgid "" -"Training the simple CNN on our CIFAR-10 split for 5 epochs should result " -"in a test set accuracy of about 41%, which is not good, but at the same " -"time, it doesn't really matter for the purposes of this tutorial. The " -"intent was just to show a simplistic centralized training pipeline that " -"sets the stage for what comes next - federated learning!" +"This is the first preview release of the Flower Swift SDK. Flower support" +" on iOS is improving, and alongside the Swift SDK and code example, there" +" is now also an iOS quickstart tutorial." msgstr "" -"L'entraînement du CNN simple sur notre fractionnement CIFAR-10 pendant 5 " -"époques devrait se traduire par une précision de l'ensemble de test " -"d'environ 41 %, ce qui n'est pas bon, mais en même temps, cela n'a pas " -"vraiment d'importance pour les besoins de ce tutoriel. L'intention était " -"juste de montrer un pipeline d'entraînement centralisé simpliste qui " -"prépare le terrain pour ce qui vient ensuite - l'apprentissage fédéré !" - -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:442 -msgid "Step 2: Federated Learning with Flower" -msgstr "Étape 2 : Apprentissage fédéré avec Flower" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:444 +#: ../../source/ref-changelog.md:226 +#, fuzzy msgid "" -"Step 1 demonstrated a simple centralized training pipeline. All data was " -"in one place (i.e., a single ``trainloader`` and a single ``valloader``)." -" Next, we'll simulate a situation where we have multiple datasets in " -"multiple organizations and where we train a model over these " -"organizations using federated learning." +"**Introduce Flower Android SDK** " +"([#2131](https://github.com/adap/flower/pull/2131))" msgstr "" -"L'étape 1 a montré un simple pipeline de formation centralisé. Toutes les" -" données étaient au même endroit (c'est-à-dire un seul ``trainloader`` et" -" un seul ``valloader``). Ensuite, nous allons simuler une situation où " -"nous avons plusieurs ensembles de données dans plusieurs organisations et" -" où nous formons un modèle sur ces organisations à l'aide de " -"l'apprentissage fédéré." - -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:456 -msgid "Updating model parameters" -msgstr "Mise à jour des paramètres du modèle" +"**Introduire une nouvelle ligne de base pour les fleurs : FedAvg " +"FEMNIST** ([#1655](https://github.com/adap/flower/pull/1655))" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:458 +#: ../../source/ref-changelog.md:228 msgid "" -"In federated learning, the server sends the global model parameters to " -"the client, and the client updates the local model with the parameters " -"received from the server. It then trains the model on the local data " -"(which changes the model parameters locally) and sends the " -"updated/changed model parameters back to the server (or, alternatively, " -"it sends just the gradients back to the server, not the full model " -"parameters)." +"This is the first preview release of the Flower Kotlin SDK. Flower " +"support on Android is improving, and alongside the Kotlin SDK and code " +"example, there is now also an Android quickstart tutorial." msgstr "" -"Dans l'apprentissage fédéré, le serveur envoie les paramètres du modèle " -"global au client, et le client met à jour le modèle local avec les " -"paramètres reçus du serveur. Il entraîne ensuite le modèle sur les " -"données locales (ce qui modifie les paramètres du modèle localement) et " -"renvoie les paramètres du modèle mis à jour/changés au serveur (ou, " -"alternativement, il renvoie seulement les gradients au serveur, et non " -"pas les paramètres complets du modèle)." -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:460 +#: ../../source/ref-changelog.md:230 +#, fuzzy msgid "" -"We need two helper functions to update the local model with parameters " -"received from the server and to get the updated model parameters from the" -" local model: ``set_parameters`` and ``get_parameters``. The following " -"two functions do just that for the PyTorch model above." +"**Introduce new end-to-end testing infrastructure** " +"([#1842](https://github.com/adap/flower/pull/1842), " +"[#2071](https://github.com/adap/flower/pull/2071), " +"[#2072](https://github.com/adap/flower/pull/2072), " +"[#2068](https://github.com/adap/flower/pull/2068), " +"[#2067](https://github.com/adap/flower/pull/2067), " +"[#2069](https://github.com/adap/flower/pull/2069), " +"[#2073](https://github.com/adap/flower/pull/2073), " +"[#2070](https://github.com/adap/flower/pull/2070), " +"[#2074](https://github.com/adap/flower/pull/2074), " +"[#2082](https://github.com/adap/flower/pull/2082), " +"[#2084](https://github.com/adap/flower/pull/2084), " +"[#2093](https://github.com/adap/flower/pull/2093), " +"[#2109](https://github.com/adap/flower/pull/2109), " +"[#2095](https://github.com/adap/flower/pull/2095), " +"[#2140](https://github.com/adap/flower/pull/2140), " +"[#2137](https://github.com/adap/flower/pull/2137), " +"[#2165](https://github.com/adap/flower/pull/2165))" msgstr "" -"Nous avons besoin de deux fonctions d'aide pour mettre à jour le modèle " -"local avec les paramètres reçus du serveur et pour obtenir les paramètres" -" mis à jour du modèle local : ``set_parameters`` et ``get_parameters``. " -"Les deux fonctions suivantes font exactement cela pour le modèle PyTorch " -"ci-dessus." +"**Améliorer l'API (expérimentale) du pilote** " +"([#1663](https://github.com/adap/flower/pull/1663), " +"[#1666](https://github.com/adap/flower/pull/1666), " +"[#1667](https://github.com/adap/flower/pull/1667), " +"[#1664](https://github.com/adap/flower/pull/1664), " +"[#1675](https://github.com/adap/flower/pull/1675), " +"[#1676](https://github.com/adap/flower/pull/1676), " +"[#1693](https://github.com/adap/flower/pull/1693), " +"[#1662](https://github.com/adap/flower/pull/1662), " +"[#1794](https://github.com/adap/flower/pull/1794))" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:462 +#: ../../source/ref-changelog.md:232 msgid "" -"The details of how this works are not really important here (feel free to" -" consult the PyTorch documentation if you want to learn more). In " -"essence, we use ``state_dict`` to access PyTorch model parameter tensors." -" The parameter tensors are then converted to/from a list of NumPy " -"ndarray's (which Flower knows how to serialize/deserialize):" +"A new testing infrastructure ensures that new changes stay compatible " +"with existing framework integrations or strategies." msgstr "" -"Les détails de ce fonctionnement ne sont pas vraiment importants ici " -"(n'hésite pas à consulter la documentation PyTorch si tu veux en savoir " -"plus). En substance, nous utilisons ``state_dict`` pour accéder aux " -"tenseurs de paramètres du modèle PyTorch. Les tenseurs de paramètres sont" -" ensuite convertis en/depuis une liste de ndarray NumPy (que Flower sait " -"sérialiser/désérialiser) :" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:490 -msgid "Implementing a Flower client" -msgstr "Mise en place d'un client Flower" +#: ../../source/ref-changelog.md:234 +#, fuzzy +msgid "**Deprecate Python 3.7**" +msgstr "**Créer le PR**" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:492 +#: ../../source/ref-changelog.md:236 msgid "" -"With that out of the way, let's move on to the interesting part. " -"Federated learning systems consist of a server and multiple clients. In " -"Flower, we create clients by implementing subclasses of " -"``flwr.client.Client`` or ``flwr.client.NumPyClient``. We use " -"``NumPyClient`` in this tutorial because it is easier to implement and " -"requires us to write less boilerplate." +"Since Python 3.7 reached its end of life (EOL) on 2023-06-27, support for" +" Python 3.7 is now deprecated and will be removed in an upcoming release." msgstr "" -"Ceci étant dit, passons à la partie intéressante. Les systèmes " -"d'apprentissage fédérés se composent d'un serveur et de plusieurs " -"clients. Dans Flower, nous créons des clients en mettant en œuvre des " -"sous-classes de ``flwr.client.Client`` ou de ``flwr.client.NumPyClient``." -" Nous utilisons ``NumPyClient`` dans ce tutoriel parce qu'il est plus " -"facile à mettre en œuvre et qu'il nous oblige à rédiger moins de modèles " -"de chaudière." -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:494 +#: ../../source/ref-changelog.md:238 +#, fuzzy msgid "" -"To implement the Flower client, we create a subclass of " -"``flwr.client.NumPyClient`` and implement the three methods " -"``get_parameters``, ``fit``, and ``evaluate``:" +"**Add new** `FedTrimmedAvg` **strategy** " +"([#1769](https://github.com/adap/flower/pull/1769), " +"[#1853](https://github.com/adap/flower/pull/1853))" msgstr "" -"Pour mettre en œuvre le client Flower, nous créons une sous-classe de " -"``flwr.client.NumPyClient`` et mettons en œuvre les trois méthodes " -"``get_parameters``, ``fit`` et ``evaluate`` :" +"**Ajouter un nouvel exemple de Federated Analytics avec Pandas** " +"([#1469](https://github.com/adap/flower/pull/1469), " +"[#1535](https://github.com/adap/flower/pull/1535))" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:496 -msgid "``get_parameters``: Return the current local model parameters" -msgstr "``get_parameters`` : renvoie les paramètres du modèle local actuel" +#: ../../source/ref-changelog.md:240 +#, fuzzy +msgid "" +"The new `FedTrimmedAvg` strategy implements Trimmed Mean by [Dong Yin, " +"2018](https://arxiv.org/abs/1803.01498)." +msgstr "" +"La nouvelle stratégie `FedMedian` met en œuvre Federated Median " +"(FedMedian) par [Yin et al., 2018] " +"(https://arxiv.org/pdf/1803.01498v1.pdf)." -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:497 +#: ../../source/ref-changelog.md:242 +#, fuzzy msgid "" -"``fit``: Receive model parameters from the server, train the model " -"parameters on the local data, and return the (updated) model parameters " -"to the server" +"**Introduce start_driver** " +"([#1697](https://github.com/adap/flower/pull/1697))" msgstr "" -"``fit`` : reçoit les paramètres du modèle du serveur, entraîne les " -"paramètres du modèle sur les données locales et renvoie les paramètres du" -" modèle (mis à jour) au serveur" +"**Ajouter une nouvelle stratégie `FedProx`** " +"([#1619](https://github.com/adap/flower/pull/1619))" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:498 +#: ../../source/ref-changelog.md:244 msgid "" -"``evaluate``: Receive model parameters from the server, evaluate the " -"model parameters on the local data, and return the evaluation result to " -"the server" +"In addition to `start_server` and using the raw Driver API, there is a " +"new `start_driver` function that allows for running `start_server` " +"scripts as a Flower driver with only a single-line code change. Check out" +" the `mt-pytorch` code example to see a working example using " +"`start_driver`." msgstr "" -"``evaluate`` : reçoit les paramètres du modèle du serveur, évalue les " -"paramètres du modèle sur les données locales et renvoie le résultat de " -"l'évaluation au serveur" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:500 +#: ../../source/ref-changelog.md:246 +#, fuzzy msgid "" -"We mentioned that our clients will use the previously defined PyTorch " -"components for model training and evaluation. Let's see a simple Flower " -"client implementation that brings everything together:" +"**Add parameter aggregation to** `mt-pytorch` **code example** " +"([#1785](https://github.com/adap/flower/pull/1785))" msgstr "" -"Nous avons mentionné que nos clients utiliseront les composants PyTorch " -"définis précédemment pour la formation et l'évaluation des modèles. " -"Voyons une simple mise en œuvre du client Flower qui réunit tout cela :" +"**Nouvel exemple de code PyTorch avancé** " +"([#1007](https://github.com/adap/flower/pull/1007))" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:537 +#: ../../source/ref-changelog.md:248 msgid "" -"Our class ``FlowerClient`` defines how local training/evaluation will be " -"performed and allows Flower to call the local training/evaluation through" -" ``fit`` and ``evaluate``. Each instance of ``FlowerClient`` represents a" -" *single client* in our federated learning system. Federated learning " -"systems have multiple clients (otherwise, there's not much to federate), " -"so each client will be represented by its own instance of " -"``FlowerClient``. If we have, for example, three clients in our workload," -" then we'd have three instances of ``FlowerClient``. Flower calls " -"``FlowerClient.fit`` on the respective instance when the server selects a" -" particular client for training (and ``FlowerClient.evaluate`` for " -"evaluation)." +"The `mt-pytorch` example shows how to aggregate parameters when writing a" +" driver script. The included `driver.py` and `server.py` have been " +"aligned to demonstrate both the low-level way and the high-level way of " +"building server-side logic." msgstr "" -"Our class ``FlowerClient`` defines how local training/evaluation will be " -"performed and allows Flower to call the local training/evaluation through" -" ``fit`` and ``evaluate``. Each instance of ``FlowerClient`` represents a" -" *single client* in our federated learning system. Federated learning " -"systems have multiple clients (otherwise, there's not much to federate), " -"so each client will be represented by its own instance of " -"``FlowerClient``. If we have, for example, three clients in our workload," -" then we'd have three instances of ``FlowerClient``. Flower calls " -"``FlowerClient.fit`` on the respective instance when the server selects a" -" particular client for training (and ``FlowerClient.evaluate`` for " -"evaluation)." -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:541 -msgid "Using the Virtual Client Engine" -msgstr "Utilisation du moteur du client virtuel" +#: ../../source/ref-changelog.md:250 +#, fuzzy +msgid "" +"**Migrate experimental REST API to Starlette** " +"([2171](https://github.com/adap/flower/pull/2171))" +msgstr "" +"**Nouvelle stratégie expérimentale TensorBoard** " +"([#789](https://github.com/adap/flower/pull/789))" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:543 +#: ../../source/ref-changelog.md:252 msgid "" -"In this notebook, we want to simulate a federated learning system with 10" -" clients on a single machine. This means that the server and all 10 " -"clients will live on a single machine and share resources such as CPU, " -"GPU, and memory. Having 10 clients would mean having 10 instances of " -"``FlowerClient`` in memory. Doing this on a single machine can quickly " -"exhaust the available memory resources, even if only a subset of these " -"clients participates in a single round of federated learning." +"The (experimental) REST API used to be implemented in " +"[FastAPI](https://fastapi.tiangolo.com/), but it has now been migrated to" +" use [Starlette](https://www.starlette.io/) directly." msgstr "" -"Dans ce carnet, nous voulons simuler un système d'apprentissage fédéré " -"avec 10 clients sur une seule machine. Cela signifie que le serveur et " -"les 10 clients vivront sur une seule machine et partageront des " -"ressources telles que le CPU, le GPU et la mémoire. Avoir 10 clients " -"signifierait avoir 10 instances de ``FlowerClient`` en mémoire. Faire " -"cela sur une seule machine peut rapidement épuiser les ressources mémoire" -" disponibles, même si seulement un sous-ensemble de ces clients participe" -" à un seul tour d'apprentissage fédéré." -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:545 +#: ../../source/ref-changelog.md:254 +#, fuzzy msgid "" -"In addition to the regular capabilities where server and clients run on " -"multiple machines, Flower, therefore, provides special simulation " -"capabilities that create ``FlowerClient`` instances only when they are " -"actually necessary for training or evaluation. To enable the Flower " -"framework to create clients when necessary, we need to implement a " -"function called ``client_fn`` that creates a ``FlowerClient`` instance on" -" demand. Flower calls ``client_fn`` whenever it needs an instance of one " -"particular client to call ``fit`` or ``evaluate`` (those instances are " -"usually discarded after use, so they should not keep any local state). " -"Clients are identified by a client ID, or short ``cid``. The ``cid`` can " -"be used, for example, to load different local data partitions for " -"different clients, as can be seen below:" +"Please note: The REST request-response API is still experimental and will" +" likely change significantly over time." msgstr "" -"In addition to the regular capabilities where server and clients run on " -"multiple machines, Flower, therefore, provides special simulation " -"capabilities that create ``FlowerClient`` instances only when they are " -"actually necessary for training or evaluation. To enable the Flower " -"framework to create clients when necessary, we need to implement a " -"function called ``client_fn`` that creates a ``FlowerClient`` instance on" -" demand. Flower calls ``client_fn`` whenever it needs an instance of one " -"particular client to call ``fit`` or ``evaluate`` (those instances are " -"usually discarded after use, so they should not keep any local state). " -"Clients are identified by a client ID, or short ``cid``. The ``cid`` can " -"be used, for example, to load different local data partitions for " -"different clients, as can be seen below:" - -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:580 -msgid "Starting the training" -msgstr "Commencer la formation" +"Remarque : l'API REST est encore expérimentale et est susceptible de " +"changer de manière significative au fil du temps." -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:582 +#: ../../source/ref-changelog.md:256 +#, fuzzy msgid "" -"We now have the class ``FlowerClient`` which defines client-side " -"training/evaluation and ``client_fn`` which allows Flower to create " -"``FlowerClient`` instances whenever it needs to call ``fit`` or " -"``evaluate`` on one particular client. The last step is to start the " -"actual simulation using ``flwr.simulation.start_simulation``." +"**Introduce experimental gRPC request-response API** " +"([#1867](https://github.com/adap/flower/pull/1867), " +"[#1901](https://github.com/adap/flower/pull/1901))" msgstr "" -"Nous avons maintenant la classe ``FlowerClient`` qui définit " -"l'entraînement/évaluation côté client et ``client_fn`` qui permet à " -"Flower de créer des instances de ``FlowerClient`` chaque fois qu'il a " -"besoin d'appeler ``fit`` ou ``evaluate`` sur un client particulier. La " -"dernière étape consiste à démarrer la simulation réelle en utilisant " -"``flwr.simulation.start_simulation``." +"**Introduire les enveloppes de confidentialité différentielle (aperçu)** " +"([#1357](https://github.com/adap/flower/pull/1357), " +"[#1460](https://github.com/adap/flower/pull/1460))" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:584 +#: ../../source/ref-changelog.md:258 msgid "" -"The function ``start_simulation`` accepts a number of arguments, amongst " -"them the ``client_fn`` used to create ``FlowerClient`` instances, the " -"number of clients to simulate (``num_clients``), the number of federated " -"learning rounds (``num_rounds``), and the strategy. The strategy " -"encapsulates the federated learning approach/algorithm, for example, " -"*Federated Averaging* (FedAvg)." +"In addition to the existing gRPC API (based on bidirectional streaming) " +"and the experimental REST API, there is now a new gRPC API that uses a " +"request-response model to communicate with client nodes." msgstr "" -"La fonction ``start_simulation`` accepte un certain nombre d'arguments, " -"parmi lesquels le ``client_fn`` utilisé pour créer les instances " -"``FlowerClient``, le nombre de clients à simuler (``num_clients``), le " -"nombre de tours d'apprentissage fédéré (``num_rounds``), et la stratégie." -" La stratégie encapsule l'approche/algorithme d'apprentissage fédéré, par" -" exemple, *Federated Averaging* (FedAvg)." -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:586 +#: ../../source/ref-changelog.md:260 +#, fuzzy msgid "" -"Flower has a number of built-in strategies, but we can also use our own " -"strategy implementations to customize nearly all aspects of the federated" -" learning approach. For this example, we use the built-in ``FedAvg`` " -"implementation and customize it using a few basic parameters. The last " -"step is the actual call to ``start_simulation`` which - you guessed it - " -"starts the simulation:" -msgstr "" -"Flower dispose d'un certain nombre de stratégies intégrées, mais nous " -"pouvons également utiliser nos propres implémentations de stratégies pour" -" personnaliser presque tous les aspects de l'approche de l'apprentissage " -"fédéré. Pour cet exemple, nous utilisons l'implémentation intégrée " -"``FedAvg`` et nous la personnalisons en utilisant quelques paramètres de " -"base. La dernière étape est l'appel à ``start_simulation`` qui - tu l'as " -"deviné - démarre la simulation :" - -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:628 -msgid "Behind the scenes" -msgstr "Dans les coulisses" - -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:630 -msgid "So how does this work? How does Flower execute this simulation?" +"Please note: The gRPC request-response API is still experimental and will" +" likely change significantly over time." msgstr "" -"Alors, comment cela fonctionne-t-il ? Comment Flower exécute-t-il cette " -"simulation ?" +"Remarque : l'API REST est encore expérimentale et est susceptible de " +"changer de manière significative au fil du temps." -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:632 -#, python-format +#: ../../source/ref-changelog.md:262 +#, fuzzy msgid "" -"When we call ``start_simulation``, we tell Flower that there are 10 " -"clients (``num_clients=10``). Flower then goes ahead an asks the " -"``FedAvg`` strategy to select clients. ``FedAvg`` knows that it should " -"select 100% of the available clients (``fraction_fit=1.0``), so it goes " -"ahead and selects 10 random clients (i.e., 100% of 10)." +"**Replace the experimental** `start_client(rest=True)` **with the new** " +"`start_client(transport=\"rest\")` " +"([#1880](https://github.com/adap/flower/pull/1880))" msgstr "" -"Lorsque nous appelons ``start_simulation``, nous disons à Flower qu'il y " -"a 10 clients (``num_clients=10``). Flower demande alors à la stratégie " -"``FedAvg`` de sélectionner des clients. ``FedAvg` sait qu'il doit " -"sélectionner 100% des clients disponibles (``fraction_fit=1.0``), alors " -"il choisit 10 clients au hasard (c'est à dire 100% de 10)." +"**Initialise** `start_simulation` **avec une liste d'ID de clients** " +"([#860](https://github.com/adap/flower/pull/860))" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:634 +#: ../../source/ref-changelog.md:264 msgid "" -"Flower then asks the selected 10 clients to train the model. When the " -"server receives the model parameter updates from the clients, it hands " -"those updates over to the strategy (*FedAvg*) for aggregation. The " -"strategy aggregates those updates and returns the new global model, which" -" then gets used in the next round of federated learning." +"The (experimental) `start_client` argument `rest` was deprecated in " +"favour of a new argument `transport`. `start_client(transport=\"rest\")` " +"will yield the same behaviour as `start_client(rest=True)` did before. " +"All code should migrate to the new argument `transport`. The deprecated " +"argument `rest` will be removed in a future release." msgstr "" -"Flower demande ensuite aux 10 clients sélectionnés d'entraîner le modèle." -" Lorsque le serveur reçoit les mises à jour des paramètres du modèle de " -"la part des clients, il les transmet à la stratégie (*FedAvg*) pour " -"qu'elle les agrège. La stratégie agrège ces mises à jour et renvoie le " -"nouveau modèle global, qui est ensuite utilisé dans le prochain cycle " -"d'apprentissage fédéré." - -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:646 -msgid "Where's the accuracy?" -msgstr "Où est la précision ?" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:648 +#: ../../source/ref-changelog.md:266 +#, fuzzy msgid "" -"You may have noticed that all metrics except for ``losses_distributed`` " -"are empty. Where did the ``{\"accuracy\": float(accuracy)}`` go?" +"**Add a new gRPC option** " +"([#2197](https://github.com/adap/flower/pull/2197))" msgstr "" -"Tu as peut-être remarqué que toutes les mesures, à l'exception de " -"``pertes_distribuées``, sont vides. Où est passée la ``{\"précision\" : " -"float(précision)}`` ?" +"**Ajouter une nouvelle stratégie `FedProx`** " +"([#1619](https://github.com/adap/flower/pull/1619))" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:650 +#: ../../source/ref-changelog.md:268 msgid "" -"Flower can automatically aggregate losses returned by individual clients," -" but it cannot do the same for metrics in the generic metrics dictionary " -"(the one with the ``accuracy`` key). Metrics dictionaries can contain " -"very different kinds of metrics and even key/value pairs that are not " -"metrics at all, so the framework does not (and can not) know how to " -"handle these automatically." +"We now start a gRPC server with the `grpc.keepalive_permit_without_calls`" +" option set to 0 by default. This prevents the clients from sending " +"keepalive pings when there is no outstanding stream." msgstr "" -"Flower peut automatiquement agréger les pertes renvoyées par les clients " -"individuels, mais il ne peut pas faire la même chose pour les mesures " -"dans le dictionnaire de mesures générique (celui avec la clé " -"``accuracy``). Les dictionnaires de mesures peuvent contenir des types de" -" mesures très différents et même des paires clé/valeur qui ne sont pas " -"des mesures du tout, donc le cadre ne sait pas (et ne peut pas) savoir " -"comment les gérer automatiquement." -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:652 +#: ../../source/ref-changelog.md:270 +#, fuzzy msgid "" -"As users, we need to tell the framework how to handle/aggregate these " -"custom metrics, and we do so by passing metric aggregation functions to " -"the strategy. The strategy will then call these functions whenever it " -"receives fit or evaluate metrics from clients. The two possible functions" -" are ``fit_metrics_aggregation_fn`` and " -"``evaluate_metrics_aggregation_fn``." +"**Improve example notebooks** " +"([#2005](https://github.com/adap/flower/pull/2005))" msgstr "" -"En tant qu'utilisateurs, nous devons indiquer au framework comment " -"gérer/agréger ces métriques personnalisées, et nous le faisons en passant" -" des fonctions d'agrégation de métriques à la stratégie. La stratégie " -"appellera alors ces fonctions chaque fois qu'elle recevra des métriques " -"d'ajustement ou d'évaluation de la part des clients. Les deux fonctions " -"possibles sont ``fit_metrics_aggregation_fn`` et " -"``evaluate_metrics_aggregation_fn``." +"**Supprimer les stratégies expérimentales** " +"([#1280](https://github.com/adap/flower/pull/1280))" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:654 -msgid "" -"Let's create a simple weighted averaging function to aggregate the " -"``accuracy`` metric we return from ``evaluate``:" -msgstr "" -"Créons une simple fonction de calcul de la moyenne pondérée pour agréger " -"la mesure de \"précision\" que nous renvoie ``evaluate`` :" +#: ../../source/ref-changelog.md:272 +#, fuzzy +msgid "There's a new 30min Federated Learning PyTorch tutorial!" +msgstr "Bienvenue au tutoriel sur l'apprentissage fédéré de la fleur !" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:680 +#: ../../source/ref-changelog.md:274 msgid "" -"The only thing left to do is to tell the strategy to call this function " -"whenever it receives evaluation metric dictionaries from the clients:" +"**Example updates** ([#1772](https://github.com/adap/flower/pull/1772), " +"[#1873](https://github.com/adap/flower/pull/1873), " +"[#1981](https://github.com/adap/flower/pull/1981), " +"[#1988](https://github.com/adap/flower/pull/1988), " +"[#1984](https://github.com/adap/flower/pull/1984), " +"[#1982](https://github.com/adap/flower/pull/1982), " +"[#2112](https://github.com/adap/flower/pull/2112), " +"[#2144](https://github.com/adap/flower/pull/2144), " +"[#2174](https://github.com/adap/flower/pull/2174), " +"[#2225](https://github.com/adap/flower/pull/2225), " +"[#2183](https://github.com/adap/flower/pull/2183))" msgstr "" -"La seule chose qui reste à faire est d'indiquer à la stratégie d'appeler " -"cette fonction chaque fois qu'elle reçoit des dictionnaires de métriques " -"d'évaluation de la part des clients :" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:717 +#: ../../source/ref-changelog.md:276 msgid "" -"We now have a full system that performs federated training and federated " -"evaluation. It uses the ``weighted_average`` function to aggregate custom" -" evaluation metrics and calculates a single ``accuracy`` metric across " -"all clients on the server side." +"Many examples have received significant updates, including simplified " +"advanced-tensorflow and advanced-pytorch examples, improved macOS " +"compatibility of TensorFlow examples, and code examples for simulation. A" +" major upgrade is that all code examples now have a `requirements.txt` " +"(in addition to `pyproject.toml`)." msgstr "" -"Nous avons maintenant un système complet qui effectue la formation " -"fédérée et l'évaluation fédérée. Il utilise la fonction ``moyenne " -"pondérée`` pour agréger les mesures d'évaluation personnalisées et " -"calcule une seule mesure de ``précision`` pour tous les clients du côté " -"du serveur." -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:719 +#: ../../source/ref-changelog.md:278 +#, fuzzy msgid "" -"The other two categories of metrics (``losses_centralized`` and " -"``metrics_centralized``) are still empty because they only apply when " -"centralized evaluation is being used. Part two of the Flower tutorial " -"will cover centralized evaluation." +"**General improvements** " +"([#1872](https://github.com/adap/flower/pull/1872), " +"[#1866](https://github.com/adap/flower/pull/1866), " +"[#1884](https://github.com/adap/flower/pull/1884), " +"[#1837](https://github.com/adap/flower/pull/1837), " +"[#1477](https://github.com/adap/flower/pull/1477), " +"[#2171](https://github.com/adap/flower/pull/2171))" msgstr "" -"Les deux autres catégories de mesures (``pertes_centralisées`` et " -"``métriques_centralisées``) sont toujours vides car elles ne s'appliquent" -" que lorsque l'évaluation centralisée est utilisée. La deuxième partie du" -" tutoriel sur les fleurs couvrira l'évaluation centralisée." +"**Mise à jour de la documentation** " +"([#1629](https://github.com/adap/flower/pull/1629), " +"[#1628](https://github.com/adap/flower/pull/1628), " +"[#1620](https://github.com/adap/flower/pull/1620), " +"[#1618](https://github.com/adap/flower/pull/1618), " +"[#1617](https://github.com/adap/flower/pull/1617), " +"[#1613](https://github.com/adap/flower/pull/1613), " +"[#1614](https://github.com/adap/flower/pull/1614))" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:731 -#: ../../source/tutorial-what-is-federated-learning.ipynb:351 -msgid "Final remarks" -msgstr "Remarques finales" +#: ../../source/ref-changelog.md:284 ../../source/ref-changelog.md:348 +#: ../../source/ref-changelog.md:406 ../../source/ref-changelog.md:475 +#: ../../source/ref-changelog.md:537 +msgid "None" +msgstr "Aucun" + +#: ../../source/ref-changelog.md:286 +msgid "v1.4.0 (2023-04-21)" +msgstr "v1.4.0 (2023-04-21)" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:733 +#: ../../source/ref-changelog.md:292 msgid "" -"Congratulations, you just trained a convolutional neural network, " -"federated over 10 clients! With that, you understand the basics of " -"federated learning with Flower. The same approach you've seen can be used" -" with other machine learning frameworks (not just PyTorch) and tasks (not" -" just CIFAR-10 images classification), for example NLP with Hugging Face " -"Transformers or speech with SpeechBrain." -msgstr "" -"Félicitations, tu viens d'entraîner un réseau neuronal convolutif, fédéré" -" sur 10 clients ! Avec ça, tu comprends les bases de l'apprentissage " -"fédéré avec Flower. La même approche que tu as vue peut être utilisée " -"avec d'autres cadres d'apprentissage automatique (pas seulement PyTorch) " -"et d'autres tâches (pas seulement la classification des images CIFAR-10)," -" par exemple le NLP avec Hugging Face Transformers ou la parole avec " -"SpeechBrain." +"`Adam Narozniak`, `Alexander Viala Bellander`, `Charles Beauville`, " +"`Chenyang Ma (Danny)`, `Daniel J. Beutel`, `Edoardo`, `Gautam Jajoo`, " +"`Iacob-Alexandru-Andrei`, `JDRanpariya`, `Jean Charle Yaacoub`, `Kunal " +"Sarkhel`, `L. Jiang`, `Lennart Behme`, `Max Kapsecker`, `Michał`, `Nic " +"Lane`, `Nikolaos Episkopos`, `Ragy`, `Saurav Maheshkar`, `Semo Yang`, " +"`Steve Laskaridis`, `Steven Hé (Sīchàng)`, `Taner Topal`" +msgstr "" +"`Adam Narozniak`, `Alexander Viala Bellander`, `Charles Beauville`, " +"`Chenyang Ma (Danny)`, `Daniel J. Beutel`, `Edoardo`, `Gautam Jajoo`, " +"`Iacob-Alexandru-Andrei`, `JDRanpariya`, `Jean Charle Yaacoub`, `Kunal " +"Sarkhel`, `L. Jiang`, `Lennart Behme`, `Max Kapsecker`, `Michał`, `Nic " +"Lane`, `Nikolaos Episkopos`, `Ragy`, `Saurav Maheshkar`, `Semo Yang`, " +"`Steve Laskaridis`, `Steven Hé (Sīchàng)`, `Taner Topal`" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:735 +#: ../../source/ref-changelog.md:296 msgid "" -"In the next notebook, we're going to cover some more advanced concepts. " -"Want to customize your strategy? Initialize parameters on the server " -"side? Or evaluate the aggregated model on the server side? We'll cover " -"all this and more in the next tutorial." +"**Introduce support for XGBoost (**`FedXgbNnAvg` **strategy and " +"example)** ([#1694](https://github.com/adap/flower/pull/1694), " +"[#1709](https://github.com/adap/flower/pull/1709), " +"[#1715](https://github.com/adap/flower/pull/1715), " +"[#1717](https://github.com/adap/flower/pull/1717), " +"[#1763](https://github.com/adap/flower/pull/1763), " +"[#1795](https://github.com/adap/flower/pull/1795))" msgstr "" -"Dans le prochain cahier, nous allons aborder des concepts plus avancés. " -"Tu veux personnaliser ta stratégie ? Initialiser des paramètres côté " -"serveur ? Ou évaluer le modèle agrégé côté serveur ? Nous aborderons tout" -" cela et bien plus encore dans le prochain tutoriel." +"**Introduire la prise en charge de XGBoost (**`FedXgbNnAvg` **stratégie " +"et exemple)** ([#1694](https://github.com/adap/flower/pull/1694), " +"[#1709](https://github.com/adap/flower/pull/1709), " +"[#1715](https://github.com/adap/flower/pull/1715), " +"[#1717](https://github.com/adap/flower/pull/1717), " +"[#1763](https://github.com/adap/flower/pull/1763), " +"[#1795](https://github.com/adap/flower/pull/1795))" -#: ../../source/tutorial-get-started-with-flower-pytorch.ipynb:753 -#, fuzzy +#: ../../source/ref-changelog.md:298 msgid "" -"The `Flower Federated Learning Tutorial - Part 2 " -"`__ goes into more depth about strategies and all " -"the advanced things you can build with them." +"XGBoost is a tree-based ensemble machine learning algorithm that uses " +"gradient boosting to improve model accuracy. We added a new `FedXgbNnAvg`" +" " +"[strategy](https://github.com/adap/flower/tree/main/src/py/flwr/server/strategy/fedxgb_nn_avg.py)," +" and a [code " +"example](https://github.com/adap/flower/tree/main/examples/quickstart_xgboost_horizontal)" +" that demonstrates the usage of this new strategy in an XGBoost project." msgstr "" -"Le `Tutoriel d'apprentissage fédéré Flower - Partie 2 " -"`__ va plus en profondeur sur les stratégies et toutes les " -"choses avancées que tu peux construire avec elles." - -#: ../../source/tutorial-quickstart-android.rst:5 -#, fuzzy -msgid "Quickstart Android" -msgstr "Démarrage rapide des Pandas" +"Nous avons ajouté une nouvelle [stratégie] `FedXgbNnAvg` " +"(https://github.com/adap/flower/tree/main/src/py/flwr/server/strategy/fedxgb_nn_avg.py)," +" et un [exemple de code] " +"(https://github.com/adap/flower/tree/main/examples/quickstart_xgboost_horizontal)" +" qui démontre l'utilisation de cette nouvelle stratégie dans un projet " +"XGBoost." -#: ../../source/tutorial-quickstart-android.rst:7 -#, fuzzy +#: ../../source/ref-changelog.md:300 msgid "" -"Let's build a federated learning system using TFLite and Flower on " -"Android!" +"**Introduce iOS SDK (preview)** " +"([#1621](https://github.com/adap/flower/pull/1621), " +"[#1764](https://github.com/adap/flower/pull/1764))" msgstr "" -"Construisons un système d'apprentissage fédéré en utilisant fastai et " -"Flower !" +"**Introduction du SDK iOS (aperçu)** " +"([#1621](https://github.com/adap/flower/pull/1621), " +"[#1764](https://github.com/adap/flower/pull/1764))" -#: ../../source/tutorial-quickstart-android.rst:9 -#, fuzzy +#: ../../source/ref-changelog.md:302 msgid "" -"Please refer to the `full code example " -"`_ to learn " -"more." +"This is a major update for anyone wanting to implement Federated Learning" +" on iOS mobile devices. We now have a swift iOS SDK present under " +"[src/swift/flwr](https://github.com/adap/flower/tree/main/src/swift/flwr)" +" that will facilitate greatly the app creating process. To showcase its " +"use, the [iOS " +"example](https://github.com/adap/flower/tree/main/examples/ios) has also " +"been updated!" msgstr "" -"Réfère-toi à l'exemple de code complet " -"`_ " -"pour en savoir plus." - -#: ../../source/tutorial-quickstart-fastai.rst:5 -msgid "Quickstart fastai" -msgstr "Démarrage rapide fastai" +"Il s'agit d'une mise à jour majeure pour tous ceux qui souhaitent mettre " +"en œuvre l'apprentissage fédéré sur les appareils mobiles iOS. Nous " +"disposons désormais d'un SDK swift iOS présent sous " +"[src/swift/flwr](https://github.com/adap/flower/tree/main/src/swift/flwr)" +" qui facilitera grandement le processus de création d'applications. Pour " +"présenter son utilisation, l'[exemple " +"iOS](https://github.com/adap/flower/tree/main/examples/ios) a également " +"été mis à jour !" -#: ../../source/tutorial-quickstart-fastai.rst:7 -msgid "Let's build a federated learning system using fastai and Flower!" +#: ../../source/ref-changelog.md:304 +msgid "" +"**Introduce new \"What is Federated Learning?\" tutorial** " +"([#1657](https://github.com/adap/flower/pull/1657), " +"[#1721](https://github.com/adap/flower/pull/1721))" msgstr "" -"Construisons un système d'apprentissage fédéré en utilisant fastai et " -"Flower !" +"**Introduire un nouveau tutoriel \"Qu'est-ce que l'apprentissage fédéré ?" +" \"** ([#1657](https://github.com/adap/flower/pull/1657), " +"[#1721](https://github.com/adap/flower/pull/1721))" -#: ../../source/tutorial-quickstart-fastai.rst:9 +#: ../../source/ref-changelog.md:306 #, fuzzy msgid "" -"Please refer to the `full code example " -"`_ " -"to learn more." +"A new [entry-level tutorial](https://flower.dev/docs/framework/tutorial-" +"what-is-federated-learning.html) in our documentation explains the basics" +" of Fedetated Learning. It enables anyone who's unfamiliar with Federated" +" Learning to start their journey with Flower. Forward it to anyone who's " +"interested in Federated Learning!" msgstr "" -"Réfère-toi à l'exemple de code complet " -"`_ " -"pour en savoir plus." - -#: ../../source/tutorial-quickstart-huggingface.rst:5 -msgid "Quickstart 🤗 Transformers" -msgstr "Démarrage rapide 🤗 Transformateurs" +"Un nouveau [tutoriel d'entrée de gamme] " +"(https://flower.dev/docs/tutorial/Flower-0-What-is-FL.html) dans notre " +"documentation explique les bases de l'apprentissage fédéré. Il permet à " +"tous ceux qui ne connaissent pas l'apprentissage fédéré de commencer leur" +" voyage avec Flower. Fais-le suivre à tous ceux qui s'intéressent à " +"l'apprentissage fédéré !" -#: ../../source/tutorial-quickstart-huggingface.rst:7 +#: ../../source/ref-changelog.md:308 msgid "" -"Let's build a federated learning system using Hugging Face Transformers " -"and Flower!" +"**Introduce new Flower Baseline: FedProx MNIST** " +"([#1513](https://github.com/adap/flower/pull/1513), " +"[#1680](https://github.com/adap/flower/pull/1680), " +"[#1681](https://github.com/adap/flower/pull/1681), " +"[#1679](https://github.com/adap/flower/pull/1679))" msgstr "" -"Construisons un système d'apprentissage fédéré à l'aide des " -"transformateurs Hugging Face et de Flower !" +"**Introduire une nouvelle fleur Référence : FedProx MNIST** " +"([#1513](https://github.com/adap/flower/pull/1513), " +"[#1680](https://github.com/adap/flower/pull/1680), " +"[#1681](https://github.com/adap/flower/pull/1681), " +"[#1679](https://github.com/adap/flower/pull/1679))" -#: ../../source/tutorial-quickstart-huggingface.rst:9 +#: ../../source/ref-changelog.md:310 msgid "" -"We will leverage Hugging Face to federate the training of language models" -" over multiple clients using Flower. More specifically, we will fine-tune" -" a pre-trained Transformer model (distilBERT) for sequence classification" -" over a dataset of IMDB ratings. The end goal is to detect if a movie " -"rating is positive or negative." +"This new baseline replicates the MNIST+CNN task from the paper [Federated" +" Optimization in Heterogeneous Networks (Li et al., " +"2018)](https://arxiv.org/abs/1812.06127). It uses the `FedProx` strategy," +" which aims at making convergence more robust in heterogenous settings." msgstr "" -"Nous nous appuierons sur Hugging Face pour fédérer l'entraînement de " -"modèles de langage sur plusieurs clients à l'aide de Flower. Plus " -"précisément, nous mettrons au point un modèle Transformer pré-entraîné " -"(distilBERT) pour la classification de séquences sur un ensemble de " -"données d'évaluations IMDB. L'objectif final est de détecter si " -"l'évaluation d'un film est positive ou négative." - -#: ../../source/tutorial-quickstart-huggingface.rst:15 -msgid "Dependencies" -msgstr "Dépendances" +"Cette nouvelle ligne de base reproduit la tâche MNIST+CNN de l'article " +"[Federated Optimization in Heterogeneous Networks (Li et al., 2018)] " +"(https://arxiv.org/abs/1812.06127). Elle utilise la stratégie `FedProx`, " +"qui vise à rendre la convergence plus robuste dans des contextes " +"hétérogènes." -#: ../../source/tutorial-quickstart-huggingface.rst:17 +#: ../../source/ref-changelog.md:312 msgid "" -"To follow along this tutorial you will need to install the following " -"packages: :code:`datasets`, :code:`evaluate`, :code:`flwr`, " -":code:`torch`, and :code:`transformers`. This can be done using " -":code:`pip`:" +"**Introduce new Flower Baseline: FedAvg FEMNIST** " +"([#1655](https://github.com/adap/flower/pull/1655))" msgstr "" -"Pour suivre ce tutoriel, tu devras installer les paquets suivants : " -":code:`datasets`, :code:`evaluate`, :code:`flwr`, :code:`torch`, et " -":code:`transformers`. Cela peut être fait en utilisant :code:`pip` :" - -#: ../../source/tutorial-quickstart-huggingface.rst:27 -msgid "Standard Hugging Face workflow" -msgstr "Flux de travail standard pour le visage" - -#: ../../source/tutorial-quickstart-huggingface.rst:30 -msgid "Handling the data" -msgstr "Traitement des données" +"**Introduire une nouvelle ligne de base pour les fleurs : FedAvg " +"FEMNIST** ([#1655](https://github.com/adap/flower/pull/1655))" -#: ../../source/tutorial-quickstart-huggingface.rst:32 +#: ../../source/ref-changelog.md:314 msgid "" -"To fetch the IMDB dataset, we will use Hugging Face's :code:`datasets` " -"library. We then need to tokenize the data and create :code:`PyTorch` " -"dataloaders, this is all done in the :code:`load_data` function:" +"This new baseline replicates an experiment evaluating the performance of " +"the FedAvg algorithm on the FEMNIST dataset from the paper [LEAF: A " +"Benchmark for Federated Settings (Caldas et al., " +"2018)](https://arxiv.org/abs/1812.01097)." msgstr "" -"Pour récupérer le jeu de données IMDB, nous utiliserons la bibliothèque " -":code:`datasets` de Hugging Face. Nous devons ensuite tokeniser les " -"données et créer des :code:`PyTorch` dataloaders, ce qui est fait dans la" -" fonction :code:`load_data` :" - -#: ../../source/tutorial-quickstart-huggingface.rst:78 -msgid "Training and testing the model" -msgstr "Former et tester le modèle" +"Cette nouvelle ligne de base reproduit une expérience évaluant les " +"performances de l'algorithme FedAvg sur le jeu de données FEMNIST tiré de" +" l'article [LEAF : A Benchmark for Federated Settings (Caldas et al., " +"2018)] (https://arxiv.org/abs/1812.01097)." -#: ../../source/tutorial-quickstart-huggingface.rst:80 +#: ../../source/ref-changelog.md:316 msgid "" -"Once we have a way of creating our trainloader and testloader, we can " -"take care of the training and testing. This is very similar to any " -":code:`PyTorch` training or testing loop:" +"**Introduce (experimental) REST API** " +"([#1594](https://github.com/adap/flower/pull/1594), " +"[#1690](https://github.com/adap/flower/pull/1690), " +"[#1695](https://github.com/adap/flower/pull/1695), " +"[#1712](https://github.com/adap/flower/pull/1712), " +"[#1802](https://github.com/adap/flower/pull/1802), " +"[#1770](https://github.com/adap/flower/pull/1770), " +"[#1733](https://github.com/adap/flower/pull/1733))" msgstr "" -"Une fois que nous avons trouvé un moyen de créer notre trainloader et " -"notre testloader, nous pouvons nous occuper de l'entraînement et du test." -" C'est très similaire à n'importe quelle boucle d'entraînement ou de test" -" :code:`PyTorch` :" - -#: ../../source/tutorial-quickstart-huggingface.rst:118 -msgid "Creating the model itself" -msgstr "Créer le modèle lui-même" +"**Introduire l'API REST (expérimentale)** " +"([#1594](https://github.com/adap/flower/pull/1594), " +"[#1690](https://github.com/adap/flower/pull/1690), " +"[#1695](https://github.com/adap/flower/pull/1695), " +"[#1712](https://github.com/adap/flower/pull/1712), " +"[#1802](https://github.com/adap/flower/pull/1802), " +"[#1770](https://github.com/adap/flower/pull/1770), " +"[#1733](https://github.com/adap/flower/pull/1733))" -#: ../../source/tutorial-quickstart-huggingface.rst:120 +#: ../../source/ref-changelog.md:318 msgid "" -"To create the model itself, we will just load the pre-trained distillBERT" -" model using Hugging Face’s :code:`AutoModelForSequenceClassification` :" +"A new REST API has been introduced as an alternative to the gRPC-based " +"communication stack. In this initial version, the REST API only supports " +"anonymous clients." msgstr "" -"Pour créer le modèle lui-même, nous allons simplement charger le modèle " -"distillBERT pré-entraîné en utilisant le " -":code:`AutoModelForSequenceClassification` de Hugging Face :" +"Une nouvelle API REST a été introduite comme alternative à la pile de " +"communication basée sur gRPC. Dans cette version initiale, l'API REST ne " +"prend en charge que les clients anonymes." -#: ../../source/tutorial-quickstart-huggingface.rst:133 -msgid "Federating the example" -msgstr "Fédérer l'exemple" - -#: ../../source/tutorial-quickstart-huggingface.rst:136 -msgid "Creating the IMDBClient" -msgstr "Création du client IMDBC" - -#: ../../source/tutorial-quickstart-huggingface.rst:138 -msgid "" -"To federate our example to multiple clients, we first need to write our " -"Flower client class (inheriting from :code:`flwr.client.NumPyClient`). " -"This is very easy, as our model is a standard :code:`PyTorch` model:" -msgstr "" -"Pour fédérer notre exemple à plusieurs clients, nous devons d'abord " -"écrire notre classe de client Flower (héritant de " -":code:`flwr.client.NumPyClient`). C'est très facile, car notre modèle est" -" un modèle :code:`PyTorch` standard :" - -#: ../../source/tutorial-quickstart-huggingface.rst:166 -msgid "" -"The :code:`get_parameters` function lets the server get the client's " -"parameters. Inversely, the :code:`set_parameters` function allows the " -"server to send its parameters to the client. Finally, the :code:`fit` " -"function trains the model locally for the client, and the " -":code:`evaluate` function tests the model locally and returns the " -"relevant metrics." -msgstr "" -"La fonction :code:`get_parameters` permet au serveur d'obtenir les " -"paramètres du client. Inversement, la fonction :code:`set_parameters` " -"permet au serveur d'envoyer ses paramètres au client. Enfin, la fonction " -":code:`fit` forme le modèle localement pour le client, et la fonction " -":code:`evaluate` teste le modèle localement et renvoie les mesures " -"correspondantes." - -#: ../../source/tutorial-quickstart-huggingface.rst:172 -msgid "Starting the server" -msgstr "Démarrer le serveur" - -#: ../../source/tutorial-quickstart-huggingface.rst:174 -msgid "" -"Now that we have a way to instantiate clients, we need to create our " -"server in order to aggregate the results. Using Flower, this can be done " -"very easily by first choosing a strategy (here, we are using " -":code:`FedAvg`, which will define the global weights as the average of " -"all the clients' weights at each round) and then using the " -":code:`flwr.server.start_server` function:" -msgstr "" -"Maintenant que nous avons un moyen d'instancier les clients, nous devons " -"créer notre serveur afin d'agréger les résultats. Avec Flower, cela peut " -"être fait très facilement en choisissant d'abord une stratégie (ici, nous" -" utilisons :code:`FedAvg`, qui définira les poids globaux comme la " -"moyenne des poids de tous les clients à chaque tour) et en utilisant " -"ensuite la fonction :code:`flwr.server.start_server` :" - -#: ../../source/tutorial-quickstart-huggingface.rst:202 -msgid "" -"The :code:`weighted_average` function is there to provide a way to " -"aggregate the metrics distributed amongst the clients (basically this " -"allows us to display a nice average accuracy and loss for every round)." -msgstr "" -"La fonction :code:`weighted_average` est là pour fournir un moyen " -"d'agréger les mesures réparties entre les clients (en gros, cela nous " -"permet d'afficher une belle moyenne de précision et de perte pour chaque " -"tour)." - -#: ../../source/tutorial-quickstart-huggingface.rst:206 -msgid "Putting everything together" -msgstr "Tout assembler" - -#: ../../source/tutorial-quickstart-huggingface.rst:208 -msgid "We can now start client instances using:" -msgstr "Nous pouvons maintenant démarrer des instances de clients en utilisant :" - -#: ../../source/tutorial-quickstart-huggingface.rst:218 -msgid "" -"And they will be able to connect to the server and start the federated " -"training." -msgstr "Et ils pourront se connecter au serveur et démarrer la formation fédérée." - -#: ../../source/tutorial-quickstart-huggingface.rst:220 -#, fuzzy +#: ../../source/ref-changelog.md:320 msgid "" -"If you want to check out everything put together, you should check out " -"the full code example: [https://github.com/adap/flower/tree/main/examples" -"/quickstart-" -"huggingface](https://github.com/adap/flower/tree/main/examples" -"/quickstart-huggingface)." +"Please note: The REST API is still experimental and will likely change " +"significantly over time." msgstr "" -"Si tu veux voir tout ce qui est mis ensemble, tu devrais consulter " -"l'exemple de code complet : " -"[https://github.com/adap/flower/tree/main/examples/quickstart-" -"huggingface](https://github.com/adap/flower/tree/main/examples" -"/quickstart-huggingface)." +"Remarque : l'API REST est encore expérimentale et est susceptible de " +"changer de manière significative au fil du temps." -#: ../../source/tutorial-quickstart-huggingface.rst:224 +#: ../../source/ref-changelog.md:322 msgid "" -"Of course, this is a very basic example, and a lot can be added or " -"modified, it was just to showcase how simply we could federate a Hugging " -"Face workflow using Flower." +"**Improve the (experimental) Driver API** " +"([#1663](https://github.com/adap/flower/pull/1663), " +"[#1666](https://github.com/adap/flower/pull/1666), " +"[#1667](https://github.com/adap/flower/pull/1667), " +"[#1664](https://github.com/adap/flower/pull/1664), " +"[#1675](https://github.com/adap/flower/pull/1675), " +"[#1676](https://github.com/adap/flower/pull/1676), " +"[#1693](https://github.com/adap/flower/pull/1693), " +"[#1662](https://github.com/adap/flower/pull/1662), " +"[#1794](https://github.com/adap/flower/pull/1794))" msgstr "" -"Bien sûr, c'est un exemple très basique, et beaucoup de choses peuvent " -"être ajoutées ou modifiées, il s'agissait juste de montrer avec quelle " -"simplicité on pouvait fédérer un flux de travail Hugging Face à l'aide de" -" Flower." +"**Améliorer l'API (expérimentale) du pilote** " +"([#1663](https://github.com/adap/flower/pull/1663), " +"[#1666](https://github.com/adap/flower/pull/1666), " +"[#1667](https://github.com/adap/flower/pull/1667), " +"[#1664](https://github.com/adap/flower/pull/1664), " +"[#1675](https://github.com/adap/flower/pull/1675), " +"[#1676](https://github.com/adap/flower/pull/1676), " +"[#1693](https://github.com/adap/flower/pull/1693), " +"[#1662](https://github.com/adap/flower/pull/1662), " +"[#1794](https://github.com/adap/flower/pull/1794))" -#: ../../source/tutorial-quickstart-huggingface.rst:227 +#: ../../source/ref-changelog.md:324 msgid "" -"Note that in this example we used :code:`PyTorch`, but we could have very" -" well used :code:`TensorFlow`." +"The Driver API is still an experimental feature, but this release " +"introduces some major upgrades. One of the main improvements is the " +"introduction of an SQLite database to store server state on disk (instead" +" of in-memory). Another improvement is that tasks (instructions or " +"results) that have been delivered will now be deleted. This greatly " +"improves the memory efficiency of a long-running Flower server." msgstr "" -"Notez que dans cet exemple, nous avons utilisé :code:`PyTorch`, mais nous" -" aurions très bien pu utiliser :code:`TensorFlow`." - -#: ../../source/tutorial-quickstart-ios.rst:5 -#, fuzzy -msgid "Quickstart iOS" -msgstr "Démarrage rapide XGBoost" +"L'API du pilote est encore une fonction expérimentale, mais cette version" +" introduit quelques améliorations majeures. L'une des principales " +"améliorations est l'introduction d'une base de données SQLite pour " +"stocker l'état du serveur sur le disque (au lieu de la mémoire). Une " +"autre amélioration est que les tâches (instructions ou résultats) qui ont" +" été livrées seront désormais supprimées, ce qui améliore " +"considérablement l'efficacité de la mémoire d'un serveur Flower " +"fonctionnant depuis longtemps." -#: ../../source/tutorial-quickstart-ios.rst:7 -#, fuzzy +#: ../../source/ref-changelog.md:326 msgid "" -"In this tutorial we will learn how to train a Neural Network on MNIST " -"using Flower and CoreML on iOS devices." +"**Fix spilling issues related to Ray during simulations** " +"([#1698](https://github.com/adap/flower/pull/1698))" msgstr "" -"Dans ce tutoriel, nous allons apprendre, comment former un réseau " -"neuronal convolutif sur MNIST en utilisant Flower et PyTorch." +"**Répare les problèmes de déversement liés à Ray pendant les " +"simulations** ([#1698](https://github.com/adap/flower/pull/1698))" -#: ../../source/tutorial-quickstart-ios.rst:9 +#: ../../source/ref-changelog.md:328 #, fuzzy msgid "" -"First of all, for running the Flower Python server, it is recommended to " -"create a virtual environment and run everything within a `virtualenv " -"`_. For the Flower " -"client implementation in iOS, it is recommended to use Xcode as our IDE." +"While running long simulations, `ray` was sometimes spilling huge amounts" +" of data that would make the training unable to continue. This is now " +"fixed! 🎉" msgstr "" -"Tout d'abord, il est recommandé de créer un environnement virtuel et de " -"tout exécuter au sein d'un `virtualenv `_." +"Lors de l'exécution de longues simulations, `ray` déversait parfois " +"d'énormes quantités de données qui rendaient l'entraînement incapable de " +"continuer. ce problème est maintenant corrigé ! 🎉" -#: ../../source/tutorial-quickstart-ios.rst:12 -#, fuzzy +#: ../../source/ref-changelog.md:330 msgid "" -"Our example consists of one Python *server* and two iPhone *clients* that" -" all have the same model." +"**Add new example using** `TabNet` **and Flower** " +"([#1725](https://github.com/adap/flower/pull/1725))" msgstr "" -"Notre exemple consiste en un *serveur* et deux *clients* ayant tous le " -"même modèle." +"**Ajouter un nouvel exemple utilisant** `TabNet` **et Flower** " +"([#1725](https://github.com/adap/flower/pull/1725))" -#: ../../source/tutorial-quickstart-ios.rst:14 -#, fuzzy +#: ../../source/ref-changelog.md:332 msgid "" -"*Clients* are responsible for generating individual weight updates for " -"the model based on their local datasets. These updates are then sent to " -"the *server* which will aggregate them to produce a better model. " -"Finally, the *server* sends this improved version of the model back to " -"each *client*. A complete cycle of weight updates is called a *round*." +"TabNet is a powerful and flexible framework for training machine learning" +" models on tabular data. We now have a federated example using Flower: " +"[https://github.com/adap/flower/tree/main/examples/tabnet](https://github.com/adap/flower/tree/main/examples/quickstart_tabnet)." msgstr "" -"*Les clients* sont chargés de générer des mises à jour de poids " -"individuelles pour le modèle en fonction de leurs ensembles de données " -"locales. Ces mises à jour sont ensuite envoyées au *serveur* qui les " -"agrège pour produire un meilleur modèle. Enfin, le *serveur* renvoie " -"cette version améliorée du modèle à chaque *client*. Un cycle complet de " -"mises à jour de poids s'appelle un *round*." +"TabNet est un cadre puissant et flexible pour former des modèles " +"d'apprentissage automatique sur des données tabulaires. Nous avons " +"maintenant un exemple fédéré utilisant Flower : " +"[https://github.com/adap/flower/tree/main/examples/tabnet](https://github.com/adap/flower/tree/main/examples/quickstart_tabnet)." -#: ../../source/tutorial-quickstart-ios.rst:18 -#, fuzzy +#: ../../source/ref-changelog.md:334 msgid "" -"Now that we have a rough idea of what is going on, let's get started to " -"setup our Flower server environment. We first need to install Flower. You" -" can do this by using pip:" -msgstr "" -"Maintenant que nous avons une idée générale de ce qui se passe, " -"commençons. Nous devons d'abord installer Flower. Tu peux le faire en " -"exécutant :" - -#: ../../source/tutorial-quickstart-ios.rst:24 -msgid "Or Poetry:" +"**Add new how-to guide for monitoring simulations** " +"([#1649](https://github.com/adap/flower/pull/1649))" msgstr "" +"**Ajouter un nouveau guide pratique pour le suivi des simulations** " +"([#1649](https://github.com/adap/flower/pull/1649))" -#: ../../source/tutorial-quickstart-ios.rst:33 +#: ../../source/ref-changelog.md:336 msgid "" -"Now that we have all our dependencies installed, let's run a simple " -"distributed training using CoreML as our local training pipeline and " -"MNIST as our dataset. For simplicity reasons we will use the complete " -"Flower client with CoreML, that has been implemented and stored inside " -"the Swift SDK. The client implementation can be seen below:" +"We now have a documentation guide to help users monitor their performance" +" during simulations." msgstr "" +"Nous avons maintenant un guide de documentation pour aider les " +"utilisateurs à surveiller leurs performances pendant les simulations." -#: ../../source/tutorial-quickstart-ios.rst:69 +#: ../../source/ref-changelog.md:338 msgid "" -"Let's create a new application project in Xcode and add :code:`flwr` as a" -" dependency in your project. For our application, we will store the logic" -" of our app in :code:`FLiOSModel.swift` and the UI elements in " -":code:`ContentView.swift`. We will focus more on :code:`FLiOSModel.swift`" -" in this quickstart. Please refer to the `full code example " -"`_ to learn more " -"about the app." -msgstr "" - -#: ../../source/tutorial-quickstart-ios.rst:72 -msgid "Import Flower and CoreML related packages in :code:`FLiOSModel.swift`:" +"**Add training metrics to** `History` **object during simulations** " +"([#1696](https://github.com/adap/flower/pull/1696))" msgstr "" +"**Ajouter des mesures de formation à** `History` **objet pendant les " +"simulations** ([#1696](https://github.com/adap/flower/pull/1696))" -#: ../../source/tutorial-quickstart-ios.rst:80 +#: ../../source/ref-changelog.md:340 msgid "" -"Then add the mlmodel to the project simply by drag-and-drop, the mlmodel " -"will be bundled inside the application during deployment to your iOS " -"device. We need to pass the url to access mlmodel and run CoreML machine " -"learning processes, it can be retrieved by calling the function " -":code:`Bundle.main.url`. For the MNIST dataset, we need to preprocess it " -"into :code:`MLBatchProvider` object. The preprocessing is done inside " -":code:`DataLoader.swift`." +"The `fit_metrics_aggregation_fn` can be used to aggregate training " +"metrics, but previous releases did not save the results in the `History` " +"object. This is now the case!" msgstr "" +"La fonction `fit_metrics_aggregation_fn` peut être utilisée pour agréger " +"les mesures d'entraînement, mais les versions précédentes " +"n'enregistraient pas les résultats dans l'objet `History`. c'est " +"désormais le cas !" -#: ../../source/tutorial-quickstart-ios.rst:96 +#: ../../source/ref-changelog.md:342 msgid "" -"Since CoreML does not allow the model parameters to be seen before " -"training, and accessing the model parameters during or after the training" -" can only be done by specifying the layer name, we need to know this " -"informations beforehand, through looking at the model specification, " -"which are written as proto files. The implementation can be seen in " -":code:`MLModelInspect`." +"**General improvements** " +"([#1659](https://github.com/adap/flower/pull/1659), " +"[#1646](https://github.com/adap/flower/pull/1646), " +"[#1647](https://github.com/adap/flower/pull/1647), " +"[#1471](https://github.com/adap/flower/pull/1471), " +"[#1648](https://github.com/adap/flower/pull/1648), " +"[#1651](https://github.com/adap/flower/pull/1651), " +"[#1652](https://github.com/adap/flower/pull/1652), " +"[#1653](https://github.com/adap/flower/pull/1653), " +"[#1659](https://github.com/adap/flower/pull/1659), " +"[#1665](https://github.com/adap/flower/pull/1665), " +"[#1670](https://github.com/adap/flower/pull/1670), " +"[#1672](https://github.com/adap/flower/pull/1672), " +"[#1677](https://github.com/adap/flower/pull/1677), " +"[#1684](https://github.com/adap/flower/pull/1684), " +"[#1683](https://github.com/adap/flower/pull/1683), " +"[#1686](https://github.com/adap/flower/pull/1686), " +"[#1682](https://github.com/adap/flower/pull/1682), " +"[#1685](https://github.com/adap/flower/pull/1685), " +"[#1692](https://github.com/adap/flower/pull/1692), " +"[#1705](https://github.com/adap/flower/pull/1705), " +"[#1708](https://github.com/adap/flower/pull/1708), " +"[#1711](https://github.com/adap/flower/pull/1711), " +"[#1713](https://github.com/adap/flower/pull/1713), " +"[#1714](https://github.com/adap/flower/pull/1714), " +"[#1718](https://github.com/adap/flower/pull/1718), " +"[#1716](https://github.com/adap/flower/pull/1716), " +"[#1723](https://github.com/adap/flower/pull/1723), " +"[#1735](https://github.com/adap/flower/pull/1735), " +"[#1678](https://github.com/adap/flower/pull/1678), " +"[#1750](https://github.com/adap/flower/pull/1750), " +"[#1753](https://github.com/adap/flower/pull/1753), " +"[#1736](https://github.com/adap/flower/pull/1736), " +"[#1766](https://github.com/adap/flower/pull/1766), " +"[#1760](https://github.com/adap/flower/pull/1760), " +"[#1775](https://github.com/adap/flower/pull/1775), " +"[#1776](https://github.com/adap/flower/pull/1776), " +"[#1777](https://github.com/adap/flower/pull/1777), " +"[#1779](https://github.com/adap/flower/pull/1779), " +"[#1784](https://github.com/adap/flower/pull/1784), " +"[#1773](https://github.com/adap/flower/pull/1773), " +"[#1755](https://github.com/adap/flower/pull/1755), " +"[#1789](https://github.com/adap/flower/pull/1789), " +"[#1788](https://github.com/adap/flower/pull/1788), " +"[#1798](https://github.com/adap/flower/pull/1798), " +"[#1799](https://github.com/adap/flower/pull/1799), " +"[#1739](https://github.com/adap/flower/pull/1739), " +"[#1800](https://github.com/adap/flower/pull/1800), " +"[#1804](https://github.com/adap/flower/pull/1804), " +"[#1805](https://github.com/adap/flower/pull/1805))" msgstr "" +"**General improvements** " +"([#1659](https://github.com/adap/flower/pull/1659), " +"[#1646](https://github.com/adap/flower/pull/1646), " +"[#1647](https://github.com/adap/flower/pull/1647), " +"[#1471](https://github.com/adap/flower/pull/1471), " +"[#1648](https://github.com/adap/flower/pull/1648), " +"[#1651](https://github.com/adap/flower/pull/1651), " +"[#1652](https://github.com/adap/flower/pull/1652), " +"[#1653](https://github.com/adap/flower/pull/1653), " +"[#1659](https://github.com/adap/flower/pull/1659), " +"[#1665](https://github.com/adap/flower/pull/1665), " +"[#1670](https://github.com/adap/flower/pull/1670), " +"[#1672](https://github.com/adap/flower/pull/1672), " +"[#1677](https://github.com/adap/flower/pull/1677), " +"[#1684](https://github.com/adap/flower/pull/1684), " +"[#1683](https://github.com/adap/flower/pull/1683), " +"[#1686](https://github.com/adap/flower/pull/1686), " +"[#1682](https://github.com/adap/flower/pull/1682), " +"[#1685](https://github.com/adap/flower/pull/1685), " +"[#1692](https://github.com/adap/flower/pull/1692), " +"[#1705](https://github.com/ada" -#: ../../source/tutorial-quickstart-ios.rst:99 -msgid "" -"After we have all of the necessary informations, let's create our Flower " -"client." -msgstr "" +#: ../../source/ref-changelog.md:350 +msgid "v1.3.0 (2023-02-06)" +msgstr "v1.3.0 (2023-02-06)" -#: ../../source/tutorial-quickstart-ios.rst:114 +#: ../../source/ref-changelog.md:356 msgid "" -"Then start the Flower gRPC client and start communicating to the server " -"by passing our Flower client to the function :code:`startFlwrGRPC`." +"`Adam Narozniak`, `Alexander Viala Bellander`, `Charles Beauville`, " +"`Daniel J. Beutel`, `JDRanpariya`, `Lennart Behme`, `Taner Topal`" msgstr "" +"`Adam Narozniak`, `Alexander Viala Bellander`, `Charles Beauville`, " +"`Daniel J. Beutel`, `JDRanpariya`, `Lennart Behme`, `Taner Topal`" -#: ../../source/tutorial-quickstart-ios.rst:121 +#: ../../source/ref-changelog.md:360 msgid "" -"That's it for the client. We only have to implement :code:`Client` or " -"call the provided :code:`MLFlwrClient` and call :code:`startFlwrGRPC()`. " -"The attribute :code:`hostname` and :code:`port` tells the client which " -"server to connect to. This can be done by entering the hostname and port " -"in the application before clicking the start button to start the " -"federated learning process." +"**Add support for** `workload_id` **and** `group_id` **in Driver API** " +"([#1595](https://github.com/adap/flower/pull/1595))" msgstr "" +"**Ajouter la prise en charge de** `workload_id` **et** `group_id` **dans " +"l'API du pilote** ([#1595](https://github.com/adap/flower/pull/1595))" -#: ../../source/tutorial-quickstart-ios.rst:128 -#: ../../source/tutorial-quickstart-mxnet.rst:223 -#: ../../source/tutorial-quickstart-pytorch.rst:202 -#: ../../source/tutorial-quickstart-tensorflow.rst:97 +#: ../../source/ref-changelog.md:362 msgid "" -"For simple workloads we can start a Flower server and leave all the " -"configuration possibilities at their default values. In a file named " -":code:`server.py`, import Flower and start the server:" +"The (experimental) Driver API now supports a `workload_id` that can be " +"used to identify which workload a task belongs to. It also supports a new" +" `group_id` that can be used, for example, to indicate the current " +"training round. Both the `workload_id` and `group_id` enable client nodes" +" to decide whether they want to handle a task or not." msgstr "" -"Pour les charges de travail simples, nous pouvons démarrer un serveur " -"Flower et laisser toutes les possibilités de configuration à leurs " -"valeurs par défaut. Dans un fichier nommé :code:`server.py`, importe " -"Flower et démarre le serveur :" - -#: ../../source/tutorial-quickstart-ios.rst:139 -#: ../../source/tutorial-quickstart-mxnet.rst:234 -#: ../../source/tutorial-quickstart-pytorch.rst:213 -#: ../../source/tutorial-quickstart-scikitlearn.rst:212 -#: ../../source/tutorial-quickstart-tensorflow.rst:109 -msgid "Train the model, federated!" -msgstr "Entraîne le modèle, fédéré !" +"L'API (expérimentale) Driver prend désormais en charge un `workload_id` " +"qui peut être utilisé pour identifier la charge de travail à laquelle une" +" tâche appartient. Elle prend également en charge un nouveau `group_id` " +"qui peut être utilisé, par exemple, pour indiquer le cycle de formation " +"en cours. Le `workload_id` et le `group_id` permettent tous deux aux " +"nœuds clients de décider s'ils veulent traiter une tâche ou non." -#: ../../source/tutorial-quickstart-ios.rst:141 -#: ../../source/tutorial-quickstart-pytorch.rst:215 -#: ../../source/tutorial-quickstart-tensorflow.rst:111 +#: ../../source/ref-changelog.md:364 msgid "" -"With both client and server ready, we can now run everything and see " -"federated learning in action. FL systems usually have a server and " -"multiple clients. We therefore have to start the server first:" +"**Make Driver API and Fleet API address configurable** " +"([#1637](https://github.com/adap/flower/pull/1637))" msgstr "" -"Le client et le serveur étant prêts, nous pouvons maintenant tout " -"exécuter et voir l'apprentissage fédéré en action. Les systèmes FL ont " -"généralement un serveur et plusieurs clients. Nous devons donc commencer " -"par démarrer le serveur :" +"**Faire en sorte que l'adresse de l'API du conducteur et de l'API de la " +"flotte soit configurable** " +"([#1637](https://github.com/adap/flower/pull/1637))" -#: ../../source/tutorial-quickstart-ios.rst:149 +#: ../../source/ref-changelog.md:366 msgid "" -"Once the server is running we can start the clients in different " -"terminals. Build and run the client through your Xcode, one through Xcode" -" Simulator and the other by deploying it to your iPhone. To see more " -"about how to deploy your app to iPhone or Simulator visit `here " -"`_." +"The (experimental) long-running Flower server (Driver API and Fleet API) " +"can now configure the server address of both Driver API (via `--driver-" +"api-address`) and Fleet API (via `--fleet-api-address`) when starting:" msgstr "" +"Le serveur Flower (expérimental) de longue durée (Driver API et Fleet " +"API) peut maintenant configurer l'adresse du serveur de Driver API (via " +"`--driver-api-address`) et de Fleet API (via `--fleet-api-address`) lors " +"de son démarrage :" -#: ../../source/tutorial-quickstart-ios.rst:153 +#: ../../source/ref-changelog.md:368 #, fuzzy msgid "" -"Congratulations! You've successfully built and run your first federated " -"learning system in your ios device. The full `source code " -"`_ for this " -"example can be found in :code:`examples/ios`." +"`flower-server --driver-api-address \"0.0.0.0:8081\" --fleet-api-address " +"\"0.0.0.0:8086\"`" msgstr "" -"Félicitations ! Tu as réussi à construire et à faire fonctionner ton " -"premier système d'apprentissage fédéré. Le code source complet " -"`_ de cet exemple se trouve dans :code:`examples" -"/quickstart-mxnet`." - -#: ../../source/tutorial-quickstart-jax.rst:5 -msgid "Quickstart JAX" -msgstr "Démarrage rapide de JAX" +"``flower-superlink --driver-api-address \"0.0.0.0:8081\" --fleet-api-" +"address \"0.0.0.0:8086\" ``" -#: ../../source/tutorial-quickstart-mxnet.rst:5 -msgid "Quickstart MXNet" -msgstr "Démarrage rapide de MXNet" +#: ../../source/ref-changelog.md:370 +msgid "Both IPv4 and IPv6 addresses are supported." +msgstr "Les adresses IPv4 et IPv6 sont toutes deux prises en charge." -#: ../../source/tutorial-quickstart-mxnet.rst:7 +#: ../../source/ref-changelog.md:372 msgid "" -"In this tutorial, we will learn how to train a :code:`Sequential` model " -"on MNIST using Flower and MXNet." +"**Add new example of Federated Learning using fastai and Flower** " +"([#1598](https://github.com/adap/flower/pull/1598))" msgstr "" -"Dans ce tutoriel, nous allons apprendre à former un modèle " -":code:`Sequential` sur MNIST à l'aide de Flower et de MXNet." +"**Ajouter un nouvel exemple d'apprentissage fédéré utilisant fastai et " +"Flower** ([#1598](https://github.com/adap/flower/pull/1598))" -#: ../../source/tutorial-quickstart-mxnet.rst:9 -#: ../../source/tutorial-quickstart-scikitlearn.rst:9 +#: ../../source/ref-changelog.md:374 msgid "" -"It is recommended to create a virtual environment and run everything " -"within this `virtualenv `_." +"A new code example (`quickstart_fastai`) demonstrates federated learning " +"with [fastai](https://www.fast.ai/) and Flower. You can find it here: " +"[quickstart_fastai](https://github.com/adap/flower/tree/main/examples/quickstart_fastai)." msgstr "" -"Il est recommandé de créer un environnement virtuel et de tout exécuter " -"dans ce `virtualenv `_." +"Un nouvel exemple de code (`quickstart_fastai`) démontre l'apprentissage " +"fédéré avec [fastai](https://www.fast.ai/) et Flower. Tu peux le trouver " +"ici : " +"[quickstart_fastai](https://github.com/adap/flower/tree/main/examples/quickstart_fastai)." -#: ../../source/tutorial-quickstart-mxnet.rst:13 -#: ../../source/tutorial-quickstart-scikitlearn.rst:13 +#: ../../source/ref-changelog.md:376 msgid "" -"*Clients* are responsible for generating individual model parameter " -"updates for the model based on their local datasets. These updates are " -"then sent to the *server* which will aggregate them to produce an updated" -" global model. Finally, the *server* sends this improved version of the " -"model back to each *client*. A complete cycle of parameters updates is " -"called a *round*." +"**Make Android example compatible with** `flwr >= 1.0.0` **and the latest" +" versions of Android** " +"([#1603](https://github.com/adap/flower/pull/1603))" msgstr "" -"*Les clients* sont chargés de générer des mises à jour individuelles des " -"paramètres du modèle en fonction de leurs ensembles de données locales. " -"Ces mises à jour sont ensuite envoyées au *serveur* qui les agrège pour " -"produire un modèle global mis à jour. Enfin, le *serveur* renvoie cette " -"version améliorée du modèle à chaque *client*. Un cycle complet de mises " -"à jour des paramètres s'appelle un *round*." +"**Rendre l'exemple Android compatible avec** `flwr >= 1.0.0` **et les " +"dernières versions d'Android** " +"([#1603](https://github.com/adap/flower/pull/1603))" -#: ../../source/tutorial-quickstart-mxnet.rst:17 -#: ../../source/tutorial-quickstart-scikitlearn.rst:17 +#: ../../source/ref-changelog.md:378 +#, fuzzy msgid "" -"Now that we have a rough idea of what is going on, let's get started. We " -"first need to install Flower. You can do this by running:" +"The Android code example has received a substantial update: the project " +"is compatible with Flower 1.0 (and later), the UI received a full " +"refresh, and the project is updated to be compatible with newer Android " +"tooling." msgstr "" -"Maintenant que nous avons une idée approximative de ce qui se passe, " -"commençons. Nous devons d'abord installer Flower. Tu peux le faire en " -"lançant :" - -#: ../../source/tutorial-quickstart-mxnet.rst:23 -msgid "Since we want to use MXNet, let's go ahead and install it:" -msgstr "Puisque nous voulons utiliser MXNet, allons-y et installons-le :" +"L'exemple de code Android a reçu une mise à jour substantielle : le " +"projet est compatible avec Flower 1.0 et les versions ultérieures, " +"l'interface utilisateur a reçu un rafraîchissement complet, et le projet " +"est mis à jour pour être compatible avec les outils Android les plus " +"récents." -#: ../../source/tutorial-quickstart-mxnet.rst:33 +#: ../../source/ref-changelog.md:380 msgid "" -"Now that we have all our dependencies installed, let's run a simple " -"distributed training with two clients and one server. Our training " -"procedure and network architecture are based on MXNet´s `Hand-written " -"Digit Recognition tutorial " -"`_." +"**Add new `FedProx` strategy** " +"([#1619](https://github.com/adap/flower/pull/1619))" msgstr "" -"Maintenant que toutes nos dépendances sont installées, lançons une " -"formation distribuée simple avec deux clients et un serveur. Notre " -"procédure de formation et l'architecture du réseau sont basées sur le " -"tutoriel de reconnaissance de chiffres écrits à la main du MXNet " -"`_." +"**Ajouter une nouvelle stratégie `FedProx`** " +"([#1619](https://github.com/adap/flower/pull/1619))" -#: ../../source/tutorial-quickstart-mxnet.rst:35 +#: ../../source/ref-changelog.md:382 msgid "" -"In a file called :code:`client.py`, import Flower and MXNet related " -"packages:" +"This " +"[strategy](https://github.com/adap/flower/blob/main/src/py/flwr/server/strategy/fedprox.py)" +" is almost identical to " +"[`FedAvg`](https://github.com/adap/flower/blob/main/src/py/flwr/server/strategy/fedavg.py)," +" but helps users replicate what is described in this " +"[paper](https://arxiv.org/abs/1812.06127). It essentially adds a " +"parameter called `proximal_mu` to regularize the local models with " +"respect to the global models." msgstr "" -"Dans un fichier appelé :code:`client.py`, importe Flower et les paquets " -"liés au MXNet :" +"Cette " +"[stratégie](https://github.com/adap/flower/blob/main/src/py/flwr/server/strategy/fedprox.py)" +" est presque identique à " +"[`FedAvg`](https://github.com/adap/flower/blob/main/src/py/flwr/server/strategy/fedavg.py)," +" mais aide les utilisateurs à reproduire ce qui est décrit dans cet " +"[article](https://arxiv.org/abs/1812.06127). Elle ajoute essentiellement " +"un paramètre appelé `proximal_mu` pour régulariser les modèles locaux par" +" rapport aux modèles globaux." -#: ../../source/tutorial-quickstart-mxnet.rst:50 -msgid "In addition, define the device allocation in MXNet with:" -msgstr "En outre, définis l'attribution de l'appareil dans MXNet avec :" - -#: ../../source/tutorial-quickstart-mxnet.rst:56 +#: ../../source/ref-changelog.md:384 msgid "" -"We use MXNet to load MNIST, a popular image classification dataset of " -"handwritten digits for machine learning. The MXNet utility " -":code:`mx.test_utils.get_mnist()` downloads the training and test data." +"**Add new metrics to telemetry events** " +"([#1640](https://github.com/adap/flower/pull/1640))" msgstr "" -"Nous utilisons MXNet pour charger MNIST, un ensemble de données de " -"classification d'images populaire de chiffres manuscrits pour " -"l'apprentissage automatique. L'utilitaire MXNet " -":code:`mx.test_utils.get_mnist()` télécharge les données d'entraînement " -"et de test." +"**Ajouter de nouvelles métriques aux événements de télémétrie** " +"([#1640](https://github.com/adap/flower/pull/1640))" -#: ../../source/tutorial-quickstart-mxnet.rst:70 +#: ../../source/ref-changelog.md:386 msgid "" -"Define the training and loss with MXNet. We train the model by looping " -"over the dataset, measure the corresponding loss, and optimize it." +"An updated event structure allows, for example, the clustering of events " +"within the same workload." msgstr "" -"Définis l'entraînement et la perte avec MXNet. Nous entraînons le modèle " -"en parcourant en boucle l'ensemble des données, nous mesurons la perte " -"correspondante et nous l'optimisons." +"Une structure d'événements mise à jour permet, par exemple, de regrouper " +"des événements au sein d'une même charge de travail." -#: ../../source/tutorial-quickstart-mxnet.rst:108 +#: ../../source/ref-changelog.md:388 msgid "" -"Next, we define the validation of our machine learning model. We loop " -"over the test set and measure both loss and accuracy on the test set." +"**Add new custom strategy tutorial section** " +"[#1623](https://github.com/adap/flower/pull/1623)" msgstr "" -"Ensuite, nous définissons la validation de notre modèle d'apprentissage " -"automatique. Nous effectuons une boucle sur l'ensemble de test et " -"mesurons à la fois la perte et la précision sur l'ensemble de test." +"**Ajouter une nouvelle section de tutoriel sur les stratégies " +"personnalisées** [#1623](https://github.com/adap/flower/pull/1623)" -#: ../../source/tutorial-quickstart-mxnet.rst:132 +#: ../../source/ref-changelog.md:390 +#, fuzzy msgid "" -"After defining the training and testing of a MXNet machine learning " -"model, we use these functions to implement a Flower client." +"The Flower tutorial now has a new section that covers implementing a " +"custom strategy from scratch: [Open in " +"Colab](https://colab.research.google.com/github/adap/flower/blob/main/doc/source" +"/tutorial-build-a-strategy-from-scratch-pytorch.ipynb)" msgstr "" -"Après avoir défini la formation et le test d'un modèle d'apprentissage " -"automatique MXNet, nous utilisons ces fonctions pour mettre en œuvre un " -"client Flower." - -#: ../../source/tutorial-quickstart-mxnet.rst:134 -msgid "Our Flower clients will use a simple :code:`Sequential` model:" -msgstr "Nos clients Flower utiliseront un modèle simple :code:`Sequential` :" +"Le tutoriel sur les fleurs comporte désormais une nouvelle section qui " +"traite de la mise en œuvre d'une stratégie personnalisée à partir de zéro" +" : [Ouvrir dans " +"Colab](https://colab.research.google.com/github/adap/flower/blob/main/doc/source/tutorial/Flower-3-Building-a" +"-Strategy-PyTorch.ipynb)" -#: ../../source/tutorial-quickstart-mxnet.rst:153 +#: ../../source/ref-changelog.md:392 msgid "" -"After loading the dataset with :code:`load_data()` we perform one forward" -" propagation to initialize the model and model parameters with " -":code:`model(init)`. Next, we implement a Flower client." +"**Add new custom serialization tutorial section** " +"([#1622](https://github.com/adap/flower/pull/1622))" msgstr "" -"Après avoir chargé l'ensemble de données avec :code:`load_data()`, nous " -"effectuons une propagation vers l'avant pour initialiser le modèle et les" -" paramètres du modèle avec :code:`model(init)`. Ensuite, nous " -"implémentons un client Flower." +"**Ajouter une nouvelle section de tutoriel sur la sérialisation " +"personnalisée** ([#1622](https://github.com/adap/flower/pull/1622))" -#: ../../source/tutorial-quickstart-mxnet.rst:155 -#: ../../source/tutorial-quickstart-pytorch.rst:141 -#: ../../source/tutorial-quickstart-tensorflow.rst:51 +#: ../../source/ref-changelog.md:394 +#, fuzzy msgid "" -"The Flower server interacts with clients through an interface called " -":code:`Client`. When the server selects a particular client for training," -" it sends training instructions over the network. The client receives " -"those instructions and calls one of the :code:`Client` methods to run " -"your code (i.e., to train the neural network we defined earlier)." +"The Flower tutorial now has a new section that covers custom " +"serialization: [Open in " +"Colab](https://colab.research.google.com/github/adap/flower/blob/main/doc/source" +"/tutorial-customize-the-client-pytorch.ipynb)" msgstr "" -"Le serveur Flower interagit avec les clients par le biais d'une interface" -" appelée :code:`Client`. Lorsque le serveur sélectionne un client " -"particulier pour la formation, il envoie des instructions de formation " -"sur le réseau. Le client reçoit ces instructions et appelle l'une des " -"méthodes :code:`Client` pour exécuter ton code (c'est-à-dire pour former " -"le réseau neuronal que nous avons défini plus tôt)." +"Le tutoriel sur les fleurs comporte désormais une nouvelle section qui " +"traite de la sérialisation personnalisée : [Ouvrir dans " +"Colab](https://colab.research.google.com/github/adap/flower/blob/main/doc/source/tutorial/Flower-4" +"-Client-and-NumPyClient-PyTorch.ipynb)" -#: ../../source/tutorial-quickstart-mxnet.rst:161 +#: ../../source/ref-changelog.md:396 msgid "" -"Flower provides a convenience class called :code:`NumPyClient` which " -"makes it easier to implement the :code:`Client` interface when your " -"workload uses MXNet. Implementing :code:`NumPyClient` usually means " -"defining the following methods (:code:`set_parameters` is optional " -"though):" +"**General improvements** " +"([#1638](https://github.com/adap/flower/pull/1638), " +"[#1634](https://github.com/adap/flower/pull/1634), " +"[#1636](https://github.com/adap/flower/pull/1636), " +"[#1635](https://github.com/adap/flower/pull/1635), " +"[#1633](https://github.com/adap/flower/pull/1633), " +"[#1632](https://github.com/adap/flower/pull/1632), " +"[#1631](https://github.com/adap/flower/pull/1631), " +"[#1630](https://github.com/adap/flower/pull/1630), " +"[#1627](https://github.com/adap/flower/pull/1627), " +"[#1593](https://github.com/adap/flower/pull/1593), " +"[#1616](https://github.com/adap/flower/pull/1616), " +"[#1615](https://github.com/adap/flower/pull/1615), " +"[#1607](https://github.com/adap/flower/pull/1607), " +"[#1609](https://github.com/adap/flower/pull/1609), " +"[#1608](https://github.com/adap/flower/pull/1608), " +"[#1603](https://github.com/adap/flower/pull/1603), " +"[#1590](https://github.com/adap/flower/pull/1590), " +"[#1580](https://github.com/adap/flower/pull/1580), " +"[#1599](https://github.com/adap/flower/pull/1599), " +"[#1600](https://github.com/adap/flower/pull/1600), " +"[#1601](https://github.com/adap/flower/pull/1601), " +"[#1597](https://github.com/adap/flower/pull/1597), " +"[#1595](https://github.com/adap/flower/pull/1595), " +"[#1591](https://github.com/adap/flower/pull/1591), " +"[#1588](https://github.com/adap/flower/pull/1588), " +"[#1589](https://github.com/adap/flower/pull/1589), " +"[#1587](https://github.com/adap/flower/pull/1587), " +"[#1573](https://github.com/adap/flower/pull/1573), " +"[#1581](https://github.com/adap/flower/pull/1581), " +"[#1578](https://github.com/adap/flower/pull/1578), " +"[#1574](https://github.com/adap/flower/pull/1574), " +"[#1572](https://github.com/adap/flower/pull/1572), " +"[#1586](https://github.com/adap/flower/pull/1586))" msgstr "" -"Flower fournit une classe de commodité appelée :code:`NumPyClient` qui " -"facilite l'implémentation de l'interface :code:`Client` lorsque ta charge" -" de travail utilise MXNet. L'implémentation de :code:`NumPyClient` " -"signifie généralement la définition des méthodes suivantes " -"(:code:`set_parameters` est cependant facultatif) :" - -#: ../../source/tutorial-quickstart-mxnet.rst:167 -#: ../../source/tutorial-quickstart-pytorch.rst:153 -#: ../../source/tutorial-quickstart-scikitlearn.rst:106 -msgid "return the model weight as a list of NumPy ndarrays" -msgstr "renvoie le poids du modèle sous la forme d'une liste de ndarrays NumPy" - -#: ../../source/tutorial-quickstart-mxnet.rst:168 -#: ../../source/tutorial-quickstart-pytorch.rst:154 -#: ../../source/tutorial-quickstart-scikitlearn.rst:108 -msgid ":code:`set_parameters` (optional)" -msgstr ":code:`set_parameters` (optionnel)" +"**General improvements** " +"([#1638](https://github.com/adap/flower/pull/1638), " +"[#1634](https://github.com/adap/flower/pull/1634), " +"[#1636](https://github.com/adap/flower/pull/1636), " +"[#1635](https://github.com/adap/flower/pull/1635), " +"[#1633](https://github.com/adap/flower/pull/1633), " +"[#1632](https://github.com/adap/flower/pull/1632), " +"[#1631](https://github.com/adap/flower/pull/1631), " +"[#1630](https://github.com/adap/flower/pull/1630), " +"[#1627](https://github.com/adap/flower/pull/1627), " +"[#1593](https://github.com/adap/flower/pull/1593), " +"[#1616](https://github.com/adap/flower/pull/1616), " +"[#1615](https://github.com/adap/flower/pull/1615), " +"[#1607](https://github.com/adap/flower/pull/1607), " +"[#1609](https://github.com/adap/flower/pull/1609), " +"[#1608](https://github.com/adap/flower/pull/1608), " +"[#1603](https://github.com/adap/flower/pull/1603), " +"[#1590](https://github.com/adap/flower/pull/1590), " +"[#1580](https://github.com/adap/flower/pull/1580), " +"[#1599](https://github.com/adap/flower/pull/1599), " +"[#1600](https://github.com/ada" -#: ../../source/tutorial-quickstart-mxnet.rst:169 -#: ../../source/tutorial-quickstart-pytorch.rst:155 -#: ../../source/tutorial-quickstart-scikitlearn.rst:108 +#: ../../source/ref-changelog.md:400 msgid "" -"update the local model weights with the parameters received from the " -"server" +"**Updated documentation** " +"([#1629](https://github.com/adap/flower/pull/1629), " +"[#1628](https://github.com/adap/flower/pull/1628), " +"[#1620](https://github.com/adap/flower/pull/1620), " +"[#1618](https://github.com/adap/flower/pull/1618), " +"[#1617](https://github.com/adap/flower/pull/1617), " +"[#1613](https://github.com/adap/flower/pull/1613), " +"[#1614](https://github.com/adap/flower/pull/1614))" msgstr "" -"mettre à jour les poids du modèle local avec les paramètres reçus du " -"serveur" - -#: ../../source/tutorial-quickstart-mxnet.rst:171 -#: ../../source/tutorial-quickstart-pytorch.rst:157 -#: ../../source/tutorial-quickstart-scikitlearn.rst:111 -msgid "set the local model weights" -msgstr "fixe les poids du modèle local" - -#: ../../source/tutorial-quickstart-mxnet.rst:172 -#: ../../source/tutorial-quickstart-pytorch.rst:158 -#: ../../source/tutorial-quickstart-scikitlearn.rst:112 -msgid "train the local model" -msgstr "entraîne le modèle local" - -#: ../../source/tutorial-quickstart-mxnet.rst:173 -#: ../../source/tutorial-quickstart-pytorch.rst:159 -#: ../../source/tutorial-quickstart-scikitlearn.rst:113 -msgid "receive the updated local model weights" -msgstr "recevoir les poids du modèle local mis à jour" +"**Mise à jour de la documentation** " +"([#1629](https://github.com/adap/flower/pull/1629), " +"[#1628](https://github.com/adap/flower/pull/1628), " +"[#1620](https://github.com/adap/flower/pull/1620), " +"[#1618](https://github.com/adap/flower/pull/1618), " +"[#1617](https://github.com/adap/flower/pull/1617), " +"[#1613](https://github.com/adap/flower/pull/1613), " +"[#1614](https://github.com/adap/flower/pull/1614))" -#: ../../source/tutorial-quickstart-mxnet.rst:175 -#: ../../source/tutorial-quickstart-pytorch.rst:161 -#: ../../source/tutorial-quickstart-scikitlearn.rst:115 -msgid "test the local model" -msgstr "teste le modèle local" +#: ../../source/ref-changelog.md:402 ../../source/ref-changelog.md:469 +msgid "" +"As usual, the documentation has improved quite a bit. It is another step " +"in our effort to make the Flower documentation the best documentation of " +"any project. Stay tuned and as always, feel free to provide feedback!" +msgstr "" +"Comme d'habitude, la documentation s'est beaucoup améliorée. C'est une " +"autre étape dans notre effort pour faire de la documentation de Flower la" +" meilleure documentation de tout projet. Reste à l'écoute et comme " +"toujours, n'hésite pas à nous faire part de tes commentaires !" -#: ../../source/tutorial-quickstart-mxnet.rst:177 -msgid "They can be implemented in the following way:" -msgstr "Ils peuvent être mis en œuvre de la manière suivante :" +#: ../../source/ref-changelog.md:408 +msgid "v1.2.0 (2023-01-13)" +msgstr "v1.2.0 (2023-01-13)" -#: ../../source/tutorial-quickstart-mxnet.rst:207 +#: ../../source/ref-changelog.md:414 msgid "" -"We can now create an instance of our class :code:`MNISTClient` and add " -"one line to actually run this client:" +"`Adam Narozniak`, `Charles Beauville`, `Daniel J. Beutel`, `Edoardo`, `L." +" Jiang`, `Ragy`, `Taner Topal`, `dannymcy`" msgstr "" -"Nous pouvons maintenant créer une instance de notre classe " -":code:`MNISTClient` et ajouter une ligne pour exécuter ce client :" +"adam Narozniak`, `Charles Beauville`, `Daniel J. Beutel`, `Edoardo`, `L. " +"Jiang`, `Ragy`, `Taner Topal`, `dannymcy`" -#: ../../source/tutorial-quickstart-mxnet.rst:214 -#: ../../source/tutorial-quickstart-scikitlearn.rst:147 +#: ../../source/ref-changelog.md:418 msgid "" -"That's it for the client. We only have to implement :code:`Client` or " -":code:`NumPyClient` and call :code:`fl.client.start_client()`. The string " -":code:`\"0.0.0.0:8080\"` tells the client which server to connect to. In " -"our case we can run the server and the client on the same machine, " -"therefore we use :code:`\"0.0.0.0:8080\"`. If we run a truly federated " -"workload with the server and clients running on different machines, all " -"that needs to change is the :code:`server_address` we pass to the client." +"**Introduce new Flower Baseline: FedAvg MNIST** " +"([#1497](https://github.com/adap/flower/pull/1497), " +"[#1552](https://github.com/adap/flower/pull/1552))" msgstr "" -"C'est tout pour le client. Il nous suffit d'implémenter :code:`Client` ou" -" :code:`NumPyClient` et d'appeler :code:`fl.client.start_client()`. La chaîne :code:`\"0.0.0:8080\"` " -"indique au client à quel serveur se connecter. Dans notre cas, nous " -"pouvons exécuter le serveur et le client sur la même machine, c'est " -"pourquoi nous utilisons :code:`\"0.0.0:8080\"`. Si nous exécutons une " -"charge de travail véritablement fédérée avec le serveur et les clients " -"s'exécutant sur des machines différentes, tout ce qui doit changer est " -":code:`server_address` que nous transmettons au client." +"**Introduire une nouvelle fleur Référence : FedAvg MNIST** " +"([#1497](https://github.com/adap/flower/pull/1497), " +"[#1552](https://github.com/adap/flower/pull/1552))" -#: ../../source/tutorial-quickstart-mxnet.rst:236 +#: ../../source/ref-changelog.md:420 msgid "" -"With both client and server ready, we can now run everything and see " -"federated learning in action. Federated learning systems usually have a " -"server and multiple clients. We therefore have to start the server first:" +"Over the coming weeks, we will be releasing a number of new reference " +"implementations useful especially to FL newcomers. They will typically " +"revisit well known papers from the literature, and be suitable for " +"integration in your own application or for experimentation, in order to " +"deepen your knowledge of FL in general. Today's release is the first in " +"this series. [Read more.](https://flower.dev/blog/2023-01-12-fl-starter-" +"pack-fedavg-mnist-cnn/)" msgstr "" -"Le client et le serveur étant prêts, nous pouvons maintenant tout " -"exécuter et voir l'apprentissage fédéré en action. Les systèmes " -"d'apprentissage fédéré ont généralement un serveur et plusieurs clients. " -"Nous devons donc commencer par démarrer le serveur :" +"Au cours des prochaines semaines, nous publierons un certain nombre de " +"nouvelles implémentations de référence utiles en particulier pour les " +"nouveaux venus en FL. Elles revisiteront généralement des articles bien " +"connus de la littérature, et seront adaptées à l'intégration dans votre " +"propre application ou à l'expérimentation, afin d'approfondir votre " +"connaissance de FL en général. La publication d'aujourd'hui est la " +"première de cette série. [Lire la " +"suite.](https://flower.dev/blog/2023-01-12-fl-starter-pack-fedavg-mnist-" +"cnn/)" -#: ../../source/tutorial-quickstart-mxnet.rst:244 -#: ../../source/tutorial-quickstart-pytorch.rst:223 -#: ../../source/tutorial-quickstart-scikitlearn.rst:221 -#: ../../source/tutorial-quickstart-tensorflow.rst:119 +#: ../../source/ref-changelog.md:422 msgid "" -"Once the server is running we can start the clients in different " -"terminals. Open a new terminal and start the first client:" -msgstr "" -"Une fois que le serveur fonctionne, nous pouvons démarrer les clients " -"dans différents terminaux. Ouvre un nouveau terminal et démarre le " -"premier client :" - -#: ../../source/tutorial-quickstart-mxnet.rst:251 -#: ../../source/tutorial-quickstart-pytorch.rst:230 -#: ../../source/tutorial-quickstart-scikitlearn.rst:228 -#: ../../source/tutorial-quickstart-tensorflow.rst:126 -msgid "Open another terminal and start the second client:" -msgstr "Ouvre un autre terminal et démarre le deuxième client :" +"**Improve GPU support in simulations** " +"([#1555](https://github.com/adap/flower/pull/1555))" +msgstr "" +"**Améliorer la prise en charge des GPU dans les simulations** " +"([#1555](https://github.com/adap/flower/pull/1555))" -#: ../../source/tutorial-quickstart-mxnet.rst:257 -#: ../../source/tutorial-quickstart-pytorch.rst:236 -#: ../../source/tutorial-quickstart-scikitlearn.rst:234 +#: ../../source/ref-changelog.md:424 msgid "" -"Each client will have its own dataset. You should now see how the " -"training does in the very first terminal (the one that started the " -"server):" +"The Ray-based Virtual Client Engine (`start_simulation`) has been updated" +" to improve GPU support. The update includes some of the hard-earned " +"lessons from scaling simulations in GPU cluster environments. New " +"defaults make running GPU-based simulations substantially more robust." msgstr "" -"Chaque client aura son propre ensemble de données. Tu devrais maintenant " -"voir comment la formation se déroule dans le tout premier terminal (celui" -" qui a démarré le serveur) :" +"Le moteur client virtuel basé sur Ray (`start_simulation`) a été mis à " +"jour pour améliorer la prise en charge des GPU. La mise à jour inclut " +"certaines des leçons durement apprises lors de la mise à l'échelle des " +"simulations dans des environnements de grappes de GPU. De nouveaux " +"paramètres par défaut rendent l'exécution des simulations basées sur les " +"GPU beaucoup plus robuste." -#: ../../source/tutorial-quickstart-mxnet.rst:289 -#, fuzzy +#: ../../source/ref-changelog.md:426 msgid "" -"Congratulations! You've successfully built and run your first federated " -"learning system. The full `source code " -"`_ for this example can be found in :code:`examples" -"/quickstart-mxnet`." +"**Improve GPU support in Jupyter Notebook tutorials** " +"([#1527](https://github.com/adap/flower/pull/1527), " +"[#1558](https://github.com/adap/flower/pull/1558))" msgstr "" -"Félicitations ! Tu as réussi à construire et à faire fonctionner ton " -"premier système d'apprentissage fédéré. Le code source complet " -"`_ de cet exemple se trouve dans :code:`examples" -"/quickstart-mxnet`." - -#: ../../source/tutorial-quickstart-pandas.rst:5 -msgid "Quickstart Pandas" -msgstr "Démarrage rapide des Pandas" - -#: ../../source/tutorial-quickstart-pandas.rst:7 -msgid "Let's build a federated analytics system using Pandas and Flower!" -msgstr "Construisons un système d'analyse fédéré à l'aide de Pandas et de Flower !" +"**Améliorer la prise en charge du GPU dans les tutoriels Jupyter " +"Notebook** ([#1527](https://github.com/adap/flower/pull/1527), " +"[#1558](https://github.com/adap/flower/pull/1558))" -#: ../../source/tutorial-quickstart-pandas.rst:9 -#, fuzzy +#: ../../source/ref-changelog.md:428 msgid "" -"Please refer to the `full code example " -"`_ " -"to learn more." +"Some users reported that Jupyter Notebooks have not always been easy to " +"use on GPU instances. We listened and made improvements to all of our " +"Jupyter notebooks! Check out the updated notebooks here:" msgstr "" -"Réfère-toi à l'exemple de code complet " -"`_ " -"pour en savoir plus." +"Certains utilisateurs ont signalé que les carnets Jupyter n'ont pas " +"toujours été faciles à utiliser sur les instances GPU. Nous les avons " +"écoutés et avons apporté des améliorations à tous nos carnets Jupyter ! " +"Découvre les carnets mis à jour ici :" -#: ../../source/tutorial-quickstart-pytorch.rst:10 +#: ../../source/ref-changelog.md:430 +#, fuzzy msgid "" -"In this tutorial we will learn how to train a Convolutional Neural " -"Network on CIFAR10 using Flower and PyTorch." +"[An Introduction to Federated Learning](https://flower.dev/docs/framework" +"/tutorial-get-started-with-flower-pytorch.html)" msgstr "" -"Dans ce tutoriel, nous allons apprendre à entraîner un réseau neuronal " -"convolutif sur CIFAR10 à l'aide de Flower et PyTorch." +"[Une introduction à l'apprentissage fédéré] " +"(https://flower.dev/docs/tutorial/Flower-1-Intro-to-FL-PyTorch.html)" -#: ../../source/tutorial-quickstart-pytorch.rst:12 +#: ../../source/ref-changelog.md:431 +#, fuzzy msgid "" -"First of all, it is recommended to create a virtual environment and run " -"everything within a `virtualenv `_." +"[Strategies in Federated Learning](https://flower.dev/docs/framework" +"/tutorial-use-a-federated-learning-strategy-pytorch.html)" msgstr "" -"Tout d'abord, il est recommandé de créer un environnement virtuel et de " -"tout exécuter au sein d'un `virtualenv `_." +"[Stratégies d'apprentissage fédéré] " +"(https://flower.dev/docs/tutorial/Flower-2-Strategies-in-FL-PyTorch.html)" -#: ../../source/tutorial-quickstart-pytorch.rst:26 +#: ../../source/ref-changelog.md:432 +#, fuzzy msgid "" -"Since we want to use PyTorch to solve a computer vision task, let's go " -"ahead and install PyTorch and the **torchvision** library:" +"[Building a Strategy](https://flower.dev/docs/framework/tutorial-build-a" +"-strategy-from-scratch-pytorch.html)" msgstr "" -"Puisque nous voulons utiliser PyTorch pour résoudre une tâche de vision " -"par ordinateur, allons-y et installons PyTorch et la bibliothèque " -"**torchvision** :" +"[Construire une stratégie] " +"(https://flower.dev/docs/tutorial/Flower-3-Building-a-Strategy-" +"PyTorch.html)" -#: ../../source/tutorial-quickstart-pytorch.rst:36 +#: ../../source/ref-changelog.md:433 +#, fuzzy msgid "" -"Now that we have all our dependencies installed, let's run a simple " -"distributed training with two clients and one server. Our training " -"procedure and network architecture are based on PyTorch's `Deep Learning " -"with PyTorch " -"`_." +"[Client and NumPyClient](https://flower.dev/docs/framework/tutorial-" +"customize-the-client-pytorch.html)" msgstr "" -"Maintenant que nous avons installé toutes nos dépendances, lançons une " -"formation distribuée simple avec deux clients et un serveur. Notre " -"procédure de formation et l'architecture de notre réseau sont basées sur " -"`Deep Learning with PyTorch " -"`_ de" -" PyTorch." +"[Client et NumPyClient] (https://flower.dev/docs/tutorial/Flower-4" +"-Client-and-NumPyClient-PyTorch.html)" -#: ../../source/tutorial-quickstart-pytorch.rst:38 +#: ../../source/ref-changelog.md:435 msgid "" -"In a file called :code:`client.py`, import Flower and PyTorch related " -"packages:" +"**Introduce optional telemetry** " +"([#1533](https://github.com/adap/flower/pull/1533), " +"[#1544](https://github.com/adap/flower/pull/1544), " +"[#1584](https://github.com/adap/flower/pull/1584))" msgstr "" -"Dans un fichier appelé :code:`client.py`, importe Flower et les paquets " -"liés à PyTorch :" - -#: ../../source/tutorial-quickstart-pytorch.rst:53 -msgid "In addition, we define the device allocation in PyTorch with:" -msgstr "En outre, nous définissons l'attribution des appareils dans PyTorch avec :" +"**Introduire la télémétrie optionnelle** " +"([#1533](https://github.com/adap/flower/pull/1533), " +"[#1544](https://github.com/adap/flower/pull/1544), " +"[#1584](https://github.com/adap/flower/pull/1584))" -#: ../../source/tutorial-quickstart-pytorch.rst:59 +#: ../../source/ref-changelog.md:437 msgid "" -"We use PyTorch to load CIFAR10, a popular colored image classification " -"dataset for machine learning. The PyTorch :code:`DataLoader()` downloads " -"the training and test data that are then normalized." +"After a [request for " +"feedback](https://github.com/adap/flower/issues/1534) from the community," +" the Flower open-source project introduces optional collection of " +"*anonymous* usage metrics to make well-informed decisions to improve " +"Flower. Doing this enables the Flower team to understand how Flower is " +"used and what challenges users might face." msgstr "" -"Nous utilisons PyTorch pour charger CIFAR10, un ensemble de données de " -"classification d'images colorées populaire pour l'apprentissage " -"automatique. Le :code:`DataLoader()` de PyTorch télécharge les données " -"d'entraînement et de test qui sont ensuite normalisées." +"À la suite d'une [demande de commentaires] " +"(https://github.com/adap/flower/issues/1534) de la part de la communauté," +" le projet open-source Flower introduit la collecte optionnelle de " +"mesures d'utilisation *anonymes* afin de prendre des décisions éclairées " +"pour améliorer Flower. Cela permet à l'équipe de Flower de comprendre " +"comment Flower est utilisé et quels sont les défis auxquels les " +"utilisateurs peuvent être confrontés." -#: ../../source/tutorial-quickstart-pytorch.rst:75 +#: ../../source/ref-changelog.md:439 +#, fuzzy msgid "" -"Define the loss and optimizer with PyTorch. The training of the dataset " -"is done by looping over the dataset, measure the corresponding loss and " -"optimize it." +"**Flower is a friendly framework for collaborative AI and data science.**" +" Staying true to this statement, Flower makes it easy to disable " +"telemetry for users who do not want to share anonymous usage metrics. " +"[Read more.](https://flower.dev/docs/telemetry.html)." msgstr "" -"Définis la perte et l'optimiseur avec PyTorch L'entraînement de " -"l'ensemble de données se fait en bouclant sur l'ensemble de données, en " -"mesurant la perte correspondante et en l'optimisant." +"**Flower est un cadre convivial pour l'IA collaborative et la science des" +" données.** Restant fidèle à cette déclaration, Flower permet de " +"désactiver facilement la télémétrie pour les utilisateurs qui ne " +"souhaitent pas partager des métriques d'utilisation anonymes.[Lire la " +"suite.](https://flower.dev/docs/telemetry.html)." -#: ../../source/tutorial-quickstart-pytorch.rst:91 +#: ../../source/ref-changelog.md:441 msgid "" -"Define then the validation of the machine learning network. We loop over" -" the test set and measure the loss and accuracy of the test set." +"**Introduce (experimental) Driver API** " +"([#1520](https://github.com/adap/flower/pull/1520), " +"[#1525](https://github.com/adap/flower/pull/1525), " +"[#1545](https://github.com/adap/flower/pull/1545), " +"[#1546](https://github.com/adap/flower/pull/1546), " +"[#1550](https://github.com/adap/flower/pull/1550), " +"[#1551](https://github.com/adap/flower/pull/1551), " +"[#1567](https://github.com/adap/flower/pull/1567))" msgstr "" -"Définis ensuite la validation du réseau d'apprentissage automatique. Nous" -" passons en boucle sur l'ensemble de test et mesurons la perte et la " -"précision de l'ensemble de test." +"**([#1520](https://github.com/adap/flower/pull/1520), " +"[#1525](https://github.com/adap/flower/pull/1525), " +"[#1545](https://github.com/adap/flower/pull/1545), " +"[#1546](https://github.com/adap/flower/pull/1546), " +"[#1550](https://github.com/adap/flower/pull/1550), " +"[#1551](https://github.com/adap/flower/pull/1551), " +"[#1567](https://github.com/adap/flower/pull/1567))" -#: ../../source/tutorial-quickstart-pytorch.rst:110 +#: ../../source/ref-changelog.md:443 msgid "" -"After defining the training and testing of a PyTorch machine learning " -"model, we use the functions for the Flower clients." +"Flower now has a new (experimental) Driver API which will enable fully " +"programmable, async, and multi-tenant Federated Learning and Federated " +"Analytics applications. Phew, that's a lot! Going forward, the Driver API" +" will be the abstraction that many upcoming features will be built on - " +"and you can start building those things now, too." msgstr "" -"Après avoir défini l'entraînement et le test d'un modèle d'apprentissage " -"automatique PyTorch, nous utilisons les fonctions pour les clients " -"Flower." +"Flower dispose désormais d'une nouvelle API de pilote (expérimentale) qui" +" permettra de créer des applications Federated Learning et Federated " +"Analytics entièrement programmables, asynchrones et multi-tenant. Ouf, " +"c'est beaucoup ! À l'avenir, l'API de pilote sera l'abstraction sur " +"laquelle de nombreuses fonctionnalités à venir seront construites - et tu" +" peux commencer à construire ces choses dès maintenant, aussi." -#: ../../source/tutorial-quickstart-pytorch.rst:112 +#: ../../source/ref-changelog.md:445 msgid "" -"The Flower clients will use a simple CNN adapted from 'PyTorch: A 60 " -"Minute Blitz':" +"The Driver API also enables a new execution mode in which the server runs" +" indefinitely. Multiple individual workloads can run concurrently and " +"start and stop their execution independent of the server. This is " +"especially useful for users who want to deploy Flower in production." msgstr "" -"Les clients de Flower utiliseront un CNN simple adapté de \"PyTorch : A " -"60 Minute Blitz\" :" +"L'API du pilote permet également un nouveau mode d'exécution dans lequel " +"le serveur s'exécute indéfiniment. Plusieurs charges de travail " +"individuelles peuvent s'exécuter simultanément et démarrer et arrêter " +"leur exécution indépendamment du serveur. Ceci est particulièrement utile" +" pour les utilisateurs qui souhaitent déployer Flower en production." -#: ../../source/tutorial-quickstart-pytorch.rst:139 +#: ../../source/ref-changelog.md:447 msgid "" -"After loading the data set with :code:`load_data()` we define the Flower " -"interface." +"To learn more, check out the `mt-pytorch` code example. We look forward " +"to you feedback!" msgstr "" -"Après avoir chargé l'ensemble des données avec :code:`load_data()`, nous " -"définissons l'interface Flower." +"Pour en savoir plus, consulte l'exemple de code `mt-pytorch`. Nous " +"attendons tes commentaires avec impatience !" -#: ../../source/tutorial-quickstart-pytorch.rst:147 +#: ../../source/ref-changelog.md:449 msgid "" -"Flower provides a convenience class called :code:`NumPyClient` which " -"makes it easier to implement the :code:`Client` interface when your " -"workload uses PyTorch. Implementing :code:`NumPyClient` usually means " -"defining the following methods (:code:`set_parameters` is optional " -"though):" +"Please note: *The Driver API is still experimental and will likely change" +" significantly over time.*" msgstr "" -"Flower fournit une classe de commodité appelée :code:`NumPyClient` qui " -"facilite la mise en œuvre de l'interface :code:`Client` lorsque ta charge" -" de travail utilise PyTorch. Mettre en œuvre :code:`NumPyClient` signifie" -" généralement définir les méthodes suivantes (:code:`set_parameters` est " -"cependant facultatif) :" - -#: ../../source/tutorial-quickstart-pytorch.rst:163 -msgid "which can be implemented in the following way:" -msgstr "qui peut être mis en œuvre de la manière suivante :" +"Remarque : *L'API du pilote est encore expérimentale et est susceptible " +"de changer de manière significative au fil du temps.*" -#: ../../source/tutorial-quickstart-pytorch.rst:186 -#: ../../source/tutorial-quickstart-tensorflow.rst:79 +#: ../../source/ref-changelog.md:451 msgid "" -"We can now create an instance of our class :code:`CifarClient` and add " -"one line to actually run this client:" +"**Add new Federated Analytics with Pandas example** " +"([#1469](https://github.com/adap/flower/pull/1469), " +"[#1535](https://github.com/adap/flower/pull/1535))" msgstr "" -"Nous pouvons maintenant créer une instance de notre classe " -":code:`CifarClient` et ajouter une ligne pour exécuter ce client :" +"**Ajouter un nouvel exemple de Federated Analytics avec Pandas** " +"([#1469](https://github.com/adap/flower/pull/1469), " +"[#1535](https://github.com/adap/flower/pull/1535))" -#: ../../source/tutorial-quickstart-pytorch.rst:193 -#: ../../source/tutorial-quickstart-tensorflow.rst:87 +#: ../../source/ref-changelog.md:453 +msgid "" +"A new code example (`quickstart_pandas`) demonstrates federated analytics" +" with Pandas and Flower. You can find it here: " +"[quickstart_pandas](https://github.com/adap/flower/tree/main/examples/quickstart_pandas)." +msgstr "" +"Un nouvel exemple de code (`quickstart_pandas`) démontre l'analyse " +"fédérée avec Pandas et Flower. Tu peux le trouver ici : " +"[quickstart_pandas](https://github.com/adap/flower/tree/main/examples/quickstart_pandas)." + +#: ../../source/ref-changelog.md:455 +msgid "" +"**Add new strategies: Krum and MultiKrum** " +"([#1481](https://github.com/adap/flower/pull/1481))" +msgstr "" +"**Ajouter de nouvelles stratégies : Krum et MultiKrum** " +"([#1481](https://github.com/adap/flower/pull/1481))" + +#: ../../source/ref-changelog.md:457 +msgid "" +"Edoardo, a computer science student at the Sapienza University of Rome, " +"contributed a new `Krum` strategy that enables users to easily use Krum " +"and MultiKrum in their workloads." +msgstr "" +"Edoardo, étudiant en informatique à l'Université Sapienza de Rome, a " +"contribué à une nouvelle stratégie `Krum` qui permet aux utilisateurs " +"d'utiliser facilement Krum et MultiKrum dans leurs charges de travail." + +#: ../../source/ref-changelog.md:459 +msgid "" +"**Update C++ example to be compatible with Flower v1.2.0** " +"([#1495](https://github.com/adap/flower/pull/1495))" +msgstr "" +"**Mettre à jour l'exemple C++ pour qu'il soit compatible avec Flower " +"v1.2.0** ([#1495](https://github.com/adap/flower/pull/1495))" + +#: ../../source/ref-changelog.md:461 +msgid "" +"The C++ code example has received a substantial update to make it " +"compatible with the latest version of Flower." +msgstr "" +"L'exemple de code C++ a reçu une mise à jour substantielle pour le rendre" +" compatible avec la dernière version de Flower." + +#: ../../source/ref-changelog.md:463 +msgid "" +"**General improvements** " +"([#1491](https://github.com/adap/flower/pull/1491), " +"[#1504](https://github.com/adap/flower/pull/1504), " +"[#1506](https://github.com/adap/flower/pull/1506), " +"[#1514](https://github.com/adap/flower/pull/1514), " +"[#1522](https://github.com/adap/flower/pull/1522), " +"[#1523](https://github.com/adap/flower/pull/1523), " +"[#1526](https://github.com/adap/flower/pull/1526), " +"[#1528](https://github.com/adap/flower/pull/1528), " +"[#1547](https://github.com/adap/flower/pull/1547), " +"[#1549](https://github.com/adap/flower/pull/1549), " +"[#1560](https://github.com/adap/flower/pull/1560), " +"[#1564](https://github.com/adap/flower/pull/1564), " +"[#1566](https://github.com/adap/flower/pull/1566))" +msgstr "" +"**Améliorations générales** " +"([#1491](https://github.com/adap/flower/pull/1491), " +"[#1504](https://github.com/adap/flower/pull/1504), " +"[#1506](https://github.com/adap/flower/pull/1506), " +"[#1514](https://github.com/adap/flower/pull/1514), " +"[#1522](https://github.com/adap/flower/pull/1522), " +"[#1523](https://github.com/adap/flower/pull/1523), " +"[#1526](https://github.com/adap/flower/pull/1526), " +"[#1528](https://github.com/adap/flower/pull/1528), " +"[#1547](https://github.com/adap/flower/pull/1547), " +"[#1549](https://github.com/adap/flower/pull/1549), " +"[#1560](https://github.com/adap/flower/pull/1560), " +"[#1564](https://github.com/adap/flower/pull/1564), " +"[#1566](https://github.com/adap/flower/pull/1566))" + +#: ../../source/ref-changelog.md:467 +msgid "" +"**Updated documentation** " +"([#1494](https://github.com/adap/flower/pull/1494), " +"[#1496](https://github.com/adap/flower/pull/1496), " +"[#1500](https://github.com/adap/flower/pull/1500), " +"[#1503](https://github.com/adap/flower/pull/1503), " +"[#1505](https://github.com/adap/flower/pull/1505), " +"[#1524](https://github.com/adap/flower/pull/1524), " +"[#1518](https://github.com/adap/flower/pull/1518), " +"[#1519](https://github.com/adap/flower/pull/1519), " +"[#1515](https://github.com/adap/flower/pull/1515))" +msgstr "" +"**Documentation mise à jour** " +"([#1494](https://github.com/adap/flower/pull/1494), " +"[#1496](https://github.com/adap/flower/pull/1496), " +"[#1500](https://github.com/adap/flower/pull/1500), " +"[#1503](https://github.com/adap/flower/pull/1503), " +"[#1505](https://github.com/adap/flower/pull/1505), " +"[#1524](https://github.com/adap/flower/pull/1524), " +"[#1518](https://github.com/adap/flower/pull/1518), " +"[#1519](https://github.com/adap/flower/pull/1519), " +"[#1515](https://github.com/adap/flower/pull/1515))" + +#: ../../source/ref-changelog.md:471 +msgid "" +"One highlight is the new [first time contributor " +"guide](https://flower.dev/docs/first-time-contributors.html): if you've " +"never contributed on GitHub before, this is the perfect place to start!" +msgstr "" +"L'un des points forts est le nouveau [guide du premier contributeur] " +"(https://flower.dev/docs/first-time-contributors.html) : si tu n'as " +"jamais contribué sur GitHub auparavant, c'est l'endroit idéal pour " +"commencer !" + +#: ../../source/ref-changelog.md:477 +msgid "v1.1.0 (2022-10-31)" +msgstr "v1.1.0 (2022-10-31)" + +#: ../../source/ref-changelog.md:481 +msgid "" +"We would like to give our **special thanks** to all the contributors who " +"made the new version of Flower possible (in `git shortlog` order):" +msgstr "" +"Nous aimerions **remercier tout particulièrement** tous les contributeurs" +" qui ont rendu possible la nouvelle version de Flower (dans l'ordre `git " +"shortlog`) :" + +#: ../../source/ref-changelog.md:483 +msgid "" +"`Akis Linardos`, `Christopher S`, `Daniel J. Beutel`, `George`, `Jan " +"Schlicht`, `Mohammad Fares`, `Pedro Porto Buarque de Gusmão`, `Philipp " +"Wiesner`, `Rob Luke`, `Taner Topal`, `VasundharaAgarwal`, " +"`danielnugraha`, `edogab33`" +msgstr "" +"`Akis Linardos`, `Christopher S`, `Daniel J. Beutel`, `George`, `Jan " +"Schlicht`, `Mohammad Fares`, `Pedro Porto Buarque de Gusmão`, `Philipp " +"Wiesner`, `Rob Luke`, `Taner Topal`, `VasundharaAgarwal`, " +"`danielnugraha`, `edogab33`" + +#: ../../source/ref-changelog.md:487 +msgid "" +"**Introduce Differential Privacy wrappers (preview)** " +"([#1357](https://github.com/adap/flower/pull/1357), " +"[#1460](https://github.com/adap/flower/pull/1460))" +msgstr "" +"**Introduire les enveloppes de confidentialité différentielle (aperçu)** " +"([#1357](https://github.com/adap/flower/pull/1357), " +"[#1460](https://github.com/adap/flower/pull/1460))" + +#: ../../source/ref-changelog.md:489 +msgid "" +"The first (experimental) preview of pluggable Differential Privacy " +"wrappers enables easy configuration and usage of differential privacy " +"(DP). The pluggable DP wrappers enable framework-agnostic **and** " +"strategy-agnostic usage of both client-side DP and server-side DP. Head " +"over to the Flower docs, a new explainer goes into more detail." +msgstr "" +"Le premier aperçu (expérimental) des wrappers enfichables de " +"confidentialité différentielle permet de configurer et d'utiliser " +"facilement la confidentialité différentielle (DP). Les wrappers DP " +"enfichables permettent une utilisation agnostique du cadre **et** de la " +"stratégie à la fois de la DP côté client et de la DP côté serveur. Va " +"voir les documents de Flower, un nouvel explicatif va plus loin dans les " +"détails." + +#: ../../source/ref-changelog.md:491 +msgid "" +"**New iOS CoreML code example** " +"([#1289](https://github.com/adap/flower/pull/1289))" +msgstr "" +"**Nouvel exemple de code CoreML pour iOS** " +"([#1289](https://github.com/adap/flower/pull/1289))" + +#: ../../source/ref-changelog.md:493 +msgid "" +"Flower goes iOS! A massive new code example shows how Flower clients can " +"be built for iOS. The code example contains both Flower iOS SDK " +"components that can be used for many tasks, and one task example running " +"on CoreML." +msgstr "" +"Flower passe à iOS ! Un nouvel exemple de code massif montre comment les " +"clients Flower peuvent être construits pour iOS. L'exemple de code " +"contient à la fois des composants Flower iOS SDK qui peuvent être " +"utilisés pour de nombreuses tâches, et un exemple de tâche fonctionnant " +"sur CoreML." + +#: ../../source/ref-changelog.md:495 +msgid "" +"**New FedMedian strategy** " +"([#1461](https://github.com/adap/flower/pull/1461))" +msgstr "" +"**Nouvelle stratégie de FedMedian** " +"([#1461](https://github.com/adap/flower/pull/1461))" + +#: ../../source/ref-changelog.md:497 +msgid "" +"The new `FedMedian` strategy implements Federated Median (FedMedian) by " +"[Yin et al., 2018](https://arxiv.org/pdf/1803.01498v1.pdf)." +msgstr "" +"La nouvelle stratégie `FedMedian` met en œuvre Federated Median " +"(FedMedian) par [Yin et al., 2018] " +"(https://arxiv.org/pdf/1803.01498v1.pdf)." + +#: ../../source/ref-changelog.md:499 +msgid "" +"**Log** `Client` **exceptions in Virtual Client Engine** " +"([#1493](https://github.com/adap/flower/pull/1493))" +msgstr "" +"**Log** `Client` **exceptions dans le moteur de client virtuel** " +"([#1493](https://github.com/adap/flower/pull/1493))" + +#: ../../source/ref-changelog.md:501 +msgid "" +"All `Client` exceptions happening in the VCE are now logged by default " +"and not just exposed to the configured `Strategy` (via the `failures` " +"argument)." +msgstr "" +"Toutes les exceptions `Client` qui se produisent dans le VCE sont " +"maintenant enregistrées par défaut et ne sont pas seulement exposées à la" +" `Stratégie` configurée (via l'argument `failures`)." + +#: ../../source/ref-changelog.md:503 +msgid "" +"**Improve Virtual Client Engine internals** " +"([#1401](https://github.com/adap/flower/pull/1401), " +"[#1453](https://github.com/adap/flower/pull/1453))" +msgstr "" +"**Améliorer le moteur du client virtuel** " +"([#1401](https://github.com/adap/flower/pull/1401), " +"[#1453](https://github.com/adap/flower/pull/1453))" + +#: ../../source/ref-changelog.md:505 +msgid "" +"Some internals of the Virtual Client Engine have been revamped. The VCE " +"now uses Ray 2.0 under the hood, the value type of the `client_resources`" +" dictionary changed to `float` to allow fractions of resources to be " +"allocated." +msgstr "" +"Le VCE utilise maintenant Ray 2.0 sous le capot, le type de valeur du " +"dictionnaire `client_resources` a été remplacé par `float` pour permettre" +" l'allocation de fractions de ressources." + +#: ../../source/ref-changelog.md:507 +msgid "" +"**Support optional** `Client`**/**`NumPyClient` **methods in Virtual " +"Client Engine**" +msgstr "" +"**Support optional** `Client`**/**`NumPyClient` **methods in Virtual " +"Client Engine**" + +#: ../../source/ref-changelog.md:509 +msgid "" +"The Virtual Client Engine now has full support for optional `Client` (and" +" `NumPyClient`) methods." +msgstr "" +"Le moteur de client virtuel prend désormais en charge les méthodes " +"optionnelles `Client` (et `NumPyClient`)." + +#: ../../source/ref-changelog.md:511 +msgid "" +"**Provide type information to packages using** `flwr` " +"([#1377](https://github.com/adap/flower/pull/1377))" +msgstr "" +"**Fournir des informations de type aux paquets en utilisant** `flwr` " +"([#1377](https://github.com/adap/flower/pull/1377))" + +#: ../../source/ref-changelog.md:513 +msgid "" +"The package `flwr` is now bundled with a `py.typed` file indicating that " +"the package is typed. This enables typing support for projects or " +"packages that use `flwr` by enabling them to improve their code using " +"static type checkers like `mypy`." +msgstr "" +"Le paquet `flwr` est maintenant accompagné d'un fichier `py.typed` " +"indiquant que le paquet est typé. Cela permet de prendre en charge le " +"typage pour les projets ou les paquets qui utilisent `flwr` en leur " +"permettant d'améliorer leur code à l'aide de vérificateurs de types " +"statiques comme `mypy`." + +#: ../../source/ref-changelog.md:515 +msgid "" +"**Updated code example** " +"([#1344](https://github.com/adap/flower/pull/1344), " +"[#1347](https://github.com/adap/flower/pull/1347))" +msgstr "" +"**Exemple de code mis à jour** " +"([#1344](https://github.com/adap/flower/pull/1344), " +"[#1347](https://github.com/adap/flower/pull/1347))" + +#: ../../source/ref-changelog.md:517 +msgid "" +"The code examples covering scikit-learn and PyTorch Lightning have been " +"updated to work with the latest version of Flower." +msgstr "" +"Les exemples de code couvrant scikit-learn et PyTorch Lightning ont été " +"mis à jour pour fonctionner avec la dernière version de Flower." + +#: ../../source/ref-changelog.md:519 +msgid "" +"**Updated documentation** " +"([#1355](https://github.com/adap/flower/pull/1355), " +"[#1558](https://github.com/adap/flower/pull/1558), " +"[#1379](https://github.com/adap/flower/pull/1379), " +"[#1380](https://github.com/adap/flower/pull/1380), " +"[#1381](https://github.com/adap/flower/pull/1381), " +"[#1332](https://github.com/adap/flower/pull/1332), " +"[#1391](https://github.com/adap/flower/pull/1391), " +"[#1403](https://github.com/adap/flower/pull/1403), " +"[#1364](https://github.com/adap/flower/pull/1364), " +"[#1409](https://github.com/adap/flower/pull/1409), " +"[#1419](https://github.com/adap/flower/pull/1419), " +"[#1444](https://github.com/adap/flower/pull/1444), " +"[#1448](https://github.com/adap/flower/pull/1448), " +"[#1417](https://github.com/adap/flower/pull/1417), " +"[#1449](https://github.com/adap/flower/pull/1449), " +"[#1465](https://github.com/adap/flower/pull/1465), " +"[#1467](https://github.com/adap/flower/pull/1467))" +msgstr "" +"**Documentation mise à jour** " +"([#1355](https://github.com/adap/flower/pull/1355), " +"[#1558](https://github.com/adap/flower/pull/1558), " +"[#1379](https://github.com/adap/flower/pull/1379), " +"[#1380](https://github.com/adap/flower/pull/1380), " +"[#1381](https://github.com/adap/flower/pull/1381), " +"[#1332](https://github.com/adap/flower/pull/1332), " +"[#1391](https://github.com/adap/flower/pull/1391), " +"[#1403](https://github.com/adap/flower/pull/1403), " +"[#1364](https://github.com/adap/flower/pull/1364), " +"[#1409](https://github.com/adap/flower/pull/1409), " +"[#1419](https://github.com/adap/flower/pull/1419), " +"[#1444](https://github.com/adap/flower/pull/1444), " +"[#1448](https://github.com/adap/flower/pull/1448), " +"[#1417](https://github.com/adap/flower/pull/1417), " +"[#1449](https://github.com/adap/flower/pull/1449), " +"[#1465](https://github.com/adap/flower/pull/1465), " +"[#1467](https://github.com/adap/flower/pull/1467))" + +#: ../../source/ref-changelog.md:521 +msgid "" +"There have been so many documentation updates that it doesn't even make " +"sense to list them individually." +msgstr "" +"Il y a eu tellement de mises à jour de la documentation que cela n'a même" +" pas de sens de les énumérer individuellement." + +#: ../../source/ref-changelog.md:523 +msgid "" +"**Restructured documentation** " +"([#1387](https://github.com/adap/flower/pull/1387))" +msgstr "" +"**Documentation restructurée** " +"([#1387](https://github.com/adap/flower/pull/1387))" + +#: ../../source/ref-changelog.md:525 +msgid "" +"The documentation has been restructured to make it easier to navigate. " +"This is just the first step in a larger effort to make the Flower " +"documentation the best documentation of any project ever. Stay tuned!" +msgstr "" +"La documentation a été restructurée pour faciliter la navigation. Ce " +"n'est que la première étape d'un effort plus important visant à faire de " +"la documentation de Flower la meilleure documentation de tous les projets" + +#: ../../source/ref-changelog.md:527 +msgid "" +"**Open in Colab button** " +"([#1389](https://github.com/adap/flower/pull/1389))" +msgstr "" +"**Ouvrir dans le bouton Colab** " +"([#1389](https://github.com/adap/flower/pull/1389))" + +#: ../../source/ref-changelog.md:529 +msgid "" +"The four parts of the Flower Federated Learning Tutorial now come with a " +"new `Open in Colab` button. No need to install anything on your local " +"machine, you can now use and learn about Flower in your browser, it's " +"only a single click away." +msgstr "" +"Les quatre parties du didacticiel d'apprentissage fédéré Flower sont " +"maintenant accompagnées d'un nouveau bouton \"Ouvrir dans Colab\". Pas " +"besoin d'installer quoi que ce soit sur ta machine locale, tu peux " +"maintenant utiliser et apprendre à connaître Flower dans ton navigateur, " +"il te suffit d'un simple clic." + +#: ../../source/ref-changelog.md:531 +msgid "" +"**Improved tutorial** ([#1468](https://github.com/adap/flower/pull/1468)," +" [#1470](https://github.com/adap/flower/pull/1470), " +"[#1472](https://github.com/adap/flower/pull/1472), " +"[#1473](https://github.com/adap/flower/pull/1473), " +"[#1474](https://github.com/adap/flower/pull/1474), " +"[#1475](https://github.com/adap/flower/pull/1475))" +msgstr "" +"**Tutoriel amélioré** ([#1468](https://github.com/adap/flower/pull/1468)," +" [#1470](https://github.com/adap/flower/pull/1470), " +"[#1472](https://github.com/adap/flower/pull/1472), " +"[#1473](https://github.com/adap/flower/pull/1473), " +"[#1474](https://github.com/adap/flower/pull/1474), " +"[#1475](https://github.com/adap/flower/pull/1475))" + +#: ../../source/ref-changelog.md:533 +msgid "" +"The Flower Federated Learning Tutorial has two brand-new parts covering " +"custom strategies (still WIP) and the distinction between `Client` and " +"`NumPyClient`. The existing parts one and two have also been improved " +"(many small changes and fixes)." +msgstr "" +"Le tutoriel sur l'apprentissage fédéré des fleurs a deux toutes nouvelles" +" parties couvrant les stratégies personnalisées (encore WIP) et la " +"distinction entre `Client` et `NumPyClient`. Les parties un et deux " +"existantes ont également été améliorées (beaucoup de petits changements " +"et de corrections)." + +#: ../../source/ref-changelog.md:539 +msgid "v1.0.0 (2022-07-28)" +msgstr "v1.0.0 (2022-07-28)" + +#: ../../source/ref-changelog.md:541 +msgid "Highlights" +msgstr "Points forts" + +#: ../../source/ref-changelog.md:543 +msgid "Stable **Virtual Client Engine** (accessible via `start_simulation`)" +msgstr "Moteur de client virtuel stable** (accessible via `start_simulation`)" + +#: ../../source/ref-changelog.md:544 +msgid "All `Client`/`NumPyClient` methods are now optional" +msgstr "Toutes les méthodes `Client`/`NumPyClient` sont maintenant optionnelles" + +#: ../../source/ref-changelog.md:545 +msgid "Configurable `get_parameters`" +msgstr "`get_parameters` configurable" + +#: ../../source/ref-changelog.md:546 +msgid "" +"Tons of small API cleanups resulting in a more coherent developer " +"experience" +msgstr "" +"Des tonnes de petits nettoyages d'API résultant en une expérience plus " +"cohérente pour les développeurs" + +#: ../../source/ref-changelog.md:550 +msgid "" +"We would like to give our **special thanks** to all the contributors who " +"made Flower 1.0 possible (in reverse [GitHub " +"Contributors](https://github.com/adap/flower/graphs/contributors) order):" +msgstr "" +"Nous tenons à remercier **particulièrement** tous les contributeurs qui " +"ont rendu Flower 1.0 possible (dans l'ordre inverse de [GitHub " +"Contributors](https://github.com/adap/flower/graphs/contributors)) :" + +#: ../../source/ref-changelog.md:552 +msgid "" +"[@rtaiello](https://github.com/rtaiello), " +"[@g-pichler](https://github.com/g-pichler), [@rob-" +"luke](https://github.com/rob-luke), [@andreea-zaharia](https://github.com" +"/andreea-zaharia), [@kinshukdua](https://github.com/kinshukdua), " +"[@nfnt](https://github.com/nfnt), " +"[@tatiana-s](https://github.com/tatiana-s), " +"[@TParcollet](https://github.com/TParcollet), " +"[@vballoli](https://github.com/vballoli), " +"[@negedng](https://github.com/negedng), " +"[@RISHIKESHAVAN](https://github.com/RISHIKESHAVAN), " +"[@hei411](https://github.com/hei411), " +"[@SebastianSpeitel](https://github.com/SebastianSpeitel), " +"[@AmitChaulwar](https://github.com/AmitChaulwar), " +"[@Rubiel1](https://github.com/Rubiel1), [@FANTOME-PAN](https://github.com" +"/FANTOME-PAN), [@Rono-BC](https://github.com/Rono-BC), " +"[@lbhm](https://github.com/lbhm), " +"[@sishtiaq](https://github.com/sishtiaq), " +"[@remde](https://github.com/remde), [@Jueun-Park](https://github.com" +"/Jueun-Park), [@architjen](https://github.com/architjen), " +"[@PratikGarai](https://github.com/PratikGarai), " +"[@mrinaald](https://github.com/mrinaald), " +"[@zliel](https://github.com/zliel), " +"[@MeiruiJiang](https://github.com/MeiruiJiang), " +"[@sandracl72](https://github.com/sandracl72), " +"[@gubertoli](https://github.com/gubertoli), " +"[@Vingt100](https://github.com/Vingt100), " +"[@MakGulati](https://github.com/MakGulati), " +"[@cozek](https://github.com/cozek), " +"[@jafermarq](https://github.com/jafermarq), " +"[@sisco0](https://github.com/sisco0), " +"[@akhilmathurs](https://github.com/akhilmathurs), " +"[@CanTuerk](https://github.com/CanTuerk), " +"[@mariaboerner1987](https://github.com/mariaboerner1987), " +"[@pedropgusmao](https://github.com/pedropgusmao), " +"[@tanertopal](https://github.com/tanertopal), " +"[@danieljanes](https://github.com/danieljanes)." +msgstr "" +"[@rtaiello](https://github.com/rtaiello), " +"[@g-pichler](https://github.com/g-pichler), [@rob-" +"luke](https://github.com/rob-luke), [@andreea-zaharia](https://github.com" +"/andreea-zaharia), [@kinshukdua](https://github.com/kinshukdua), " +"[@nfnt](https://github.com/nfnt), " +"[@tatiana-s](https://github.com/tatiana-s), " +"[@TParcollet](https://github.com/TParcollet), " +"[@vballoli](https://github.com/vballoli), " +"[@negedng](https://github.com/negedng), " +"[@RISHIKESHAVAN](https://github.com/RISHIKESHAVAN), " +"[@hei411](https://github.com/hei411), " +"[@SebastianSpeitel](https://github.com/SebastianSpeitel), " +"[@AmitChaulwar](https://github.com/AmitChaulwar), " +"[@Rubiel1](https://github.com/Rubiel1), [@FANTOME-PAN](https://github.com" +"/FANTOME-PAN), [@Rono-BC](https://github.com/Rono-BC), " +"[@lbhm](https://github.com/lbhm), " +"[@sishtiaq](https://github.com/sishtiaq), " +"[@remde](https://github.com/remde), [@Jueun-Park](https://github.com" +"/Jueun-Park), [@architjen](https://github.com/architjen), " +"[@PratikGarai](https://github.com/PratikGarai), [@mrinaald](" + +#: ../../source/ref-changelog.md:556 +msgid "" +"**All arguments must be passed as keyword arguments** " +"([#1338](https://github.com/adap/flower/pull/1338))" +msgstr "" +"**Tous les arguments doivent être passés comme des arguments de mot-clé**" +" ([#1338](https://github.com/adap/flower/pull/1338))" + +#: ../../source/ref-changelog.md:558 +#, fuzzy +msgid "" +"Pass all arguments as keyword arguments, positional arguments are not " +"longer supported. Code that uses positional arguments (e.g., " +"`start_client(\"127.0.0.1:8080\", FlowerClient())`) must add the keyword " +"for each positional argument (e.g., " +"`start_client(server_address=\"127.0.0.1:8080\", " +"client=FlowerClient())`)." +msgstr "" +"Le code qui utilise des arguments positionnels (par exemple, " +"``start_client(\"127.0.0.1:8080\", FlowerClient())`) doit ajouter le mot-" +"clé pour chaque argument positionnel (par exemple, " +"``start_client(server_address=\"127.0.0.1:8080\", " +"client=FlowerClient())`)." + +#: ../../source/ref-changelog.md:560 +msgid "" +"**Introduce configuration object** `ServerConfig` **in** `start_server` " +"**and** `start_simulation` " +"([#1317](https://github.com/adap/flower/pull/1317))" +msgstr "" +"**Introduire l'objet de configuration** `ServerConfig` **dans** " +"`start_server` **et** `start_simulation` " +"([#1317](https://github.com/adap/flower/pull/1317))" + +#: ../../source/ref-changelog.md:562 +msgid "" +"Instead of a config dictionary `{\"num_rounds\": 3, \"round_timeout\": " +"600.0}`, `start_server` and `start_simulation` now expect a configuration" +" object of type `flwr.server.ServerConfig`. `ServerConfig` takes the same" +" arguments that as the previous config dict, but it makes writing type-" +"safe code easier and the default parameters values more transparent." +msgstr "" +"Au lieu d'un dictionnaire de configuration `{\"num_rounds\" : 3, " +"\"round_timeout\" : 600.0}`, `start_server` et `start_simulation` " +"attendent maintenant un objet de configuration de type " +"`flwr.server.ServerConfig`. `ServerConfig` prend les mêmes arguments que " +"le dict de configuration précédent, mais il rend l'écriture de code " +"sécurisé plus facile et les valeurs des paramètres par défaut plus " +"transparentes." + +#: ../../source/ref-changelog.md:564 +msgid "" +"**Rename built-in strategy parameters for clarity** " +"([#1334](https://github.com/adap/flower/pull/1334))" +msgstr "" +"**Renommer les paramètres de la stratégie intégrée pour plus de clarté** " +"([#1334](https://github.com/adap/flower/pull/1334))" + +#: ../../source/ref-changelog.md:566 +msgid "" +"The following built-in strategy parameters were renamed to improve " +"readability and consistency with other API's:" +msgstr "" +"Les paramètres de stratégie intégrés suivants ont été renommés pour " +"améliorer la lisibilité et la cohérence avec d'autres API :" + +#: ../../source/ref-changelog.md:568 +msgid "`fraction_eval` --> `fraction_evaluate`" +msgstr "`fraction_eval` --> `fraction_evaluate`" + +#: ../../source/ref-changelog.md:569 +msgid "`min_eval_clients` --> `min_evaluate_clients`" +msgstr "`min_eval_clients` --> `min_evaluate_clients`" + +#: ../../source/ref-changelog.md:570 +msgid "`eval_fn` --> `evaluate_fn`" +msgstr "`eval_fn` --> `evaluate_fn`" + +#: ../../source/ref-changelog.md:572 +msgid "" +"**Update default arguments of built-in strategies** " +"([#1278](https://github.com/adap/flower/pull/1278))" +msgstr "" +"**Mettre à jour les arguments par défaut des stratégies intégrées** " +"([#1278](https://github.com/adap/flower/pull/1278))" + +#: ../../source/ref-changelog.md:574 +msgid "" +"All built-in strategies now use `fraction_fit=1.0` and " +"`fraction_evaluate=1.0`, which means they select *all* currently " +"available clients for training and evaluation. Projects that relied on " +"the previous default values can get the previous behaviour by " +"initializing the strategy in the following way:" +msgstr "" +"Toutes les stratégies intégrées utilisent désormais `fraction_fit=1.0` et" +" `fraction_evaluate=1.0`, ce qui signifie qu'elles sélectionnent *tous* " +"les clients actuellement disponibles pour l'entraînement et l'évaluation." +" Les projets qui s'appuyaient sur les valeurs par défaut précédentes " +"peuvent retrouver le comportement antérieur en initialisant la stratégie " +"de la manière suivante :" + +#: ../../source/ref-changelog.md:576 +msgid "`strategy = FedAvg(fraction_fit=0.1, fraction_evaluate=0.1)`" +msgstr "`stratégie = FedAvg(fraction_fit=0.1, fraction_evaluate=0.1)`" + +#: ../../source/ref-changelog.md:578 +msgid "" +"**Add** `server_round` **to** `Strategy.evaluate` " +"([#1334](https://github.com/adap/flower/pull/1334))" +msgstr "" +"**Ajouter** `server_round` **à** `Strategy.evaluate` " +"([#1334](https://github.com/adap/flower/pull/1334))" + +#: ../../source/ref-changelog.md:580 +msgid "" +"The `Strategy` method `evaluate` now receives the current round of " +"federated learning/evaluation as the first parameter." +msgstr "" +"La méthode `Stratégie` `évaluer` reçoit maintenant le cycle actuel " +"d'apprentissage/évaluation fédéré comme premier paramètre." + +#: ../../source/ref-changelog.md:582 +msgid "" +"**Add** `server_round` **and** `config` **parameters to** `evaluate_fn` " +"([#1334](https://github.com/adap/flower/pull/1334))" +msgstr "" +"**Ajouter** `server_round` **et** `config` **paramètres à** `evaluate_fn`" +" ([#1334](https://github.com/adap/flower/pull/1334))" + +#: ../../source/ref-changelog.md:584 +msgid "" +"The `evaluate_fn` passed to built-in strategies like `FedAvg` now takes " +"three parameters: (1) The current round of federated learning/evaluation " +"(`server_round`), (2) the model parameters to evaluate (`parameters`), " +"and (3) a config dictionary (`config`)." +msgstr "" +"Le `evaluate_fn` passé aux stratégies intégrées comme `FedAvg` prend " +"maintenant trois paramètres : (1) le cycle actuel " +"d'apprentissage/évaluation fédéré (`server_round`), (2) les paramètres du" +" modèle à évaluer (`parameters`), et (3) un dictionnaire de configuration" +" (`config`)." + +#: ../../source/ref-changelog.md:586 +msgid "" +"**Rename** `rnd` **to** `server_round` " +"([#1321](https://github.com/adap/flower/pull/1321))" +msgstr "" +"**Rename** `rnd` **to** `server_round` " +"([#1321](https://github.com/adap/flower/pull/1321))" + +#: ../../source/ref-changelog.md:588 +msgid "" +"Several Flower methods and functions (`evaluate_fn`, `configure_fit`, " +"`aggregate_fit`, `configure_evaluate`, `aggregate_evaluate`) receive the " +"current round of federated learning/evaluation as their first parameter. " +"To improve reaability and avoid confusion with *random*, this parameter " +"has been renamed from `rnd` to `server_round`." +msgstr "" +"Plusieurs méthodes et fonctions de Flower (`evaluate_fn`, " +"`configure_fit`, `aggregate_fit`, `configure_evaluate`, " +"`aggregate_evaluate`) reçoivent le cycle actuel " +"d'apprentissage/évaluation fédéré comme premier paramètre. Pour améliorer" +" la fiabilité et éviter la confusion avec *random*, ce paramètre a été " +"renommé de `rnd` à `server_round`." + +#: ../../source/ref-changelog.md:590 +msgid "" +"**Move** `flwr.dataset` **to** `flwr_baselines` " +"([#1273](https://github.com/adap/flower/pull/1273))" +msgstr "" +"**Déplacer** `flwr.dataset` **vers** `flwr_baselines` " +"([#1273](https://github.com/adap/flower/pull/1273))" + +#: ../../source/ref-changelog.md:592 +msgid "The experimental package `flwr.dataset` was migrated to Flower Baselines." +msgstr "Le paquet expérimental `flwr.dataset` a été migré vers Flower Baselines." + +#: ../../source/ref-changelog.md:594 +msgid "" +"**Remove experimental strategies** " +"([#1280](https://github.com/adap/flower/pull/1280))" +msgstr "" +"**Supprimer les stratégies expérimentales** " +"([#1280](https://github.com/adap/flower/pull/1280))" + +#: ../../source/ref-changelog.md:596 +msgid "" +"Remove unmaintained experimental strategies (`FastAndSlow`, `FedFSv0`, " +"`FedFSv1`)." +msgstr "" +"Supprimer les stratégies expérimentales non maintenues (`FastAndSlow`, " +"`FedFSv0`, `FedFSv1`)." + +#: ../../source/ref-changelog.md:598 +msgid "" +"**Rename** `Weights` **to** `NDArrays` " +"([#1258](https://github.com/adap/flower/pull/1258), " +"[#1259](https://github.com/adap/flower/pull/1259))" +msgstr "" +"**Rename** `Weights` **to** `NDArrays` " +"([#1258](https://github.com/adap/flower/pull/1258), " +"[#1259](https://github.com/adap/flower/pull/1259))" + +#: ../../source/ref-changelog.md:600 +msgid "" +"`flwr.common.Weights` was renamed to `flwr.common.NDArrays` to better " +"capture what this type is all about." +msgstr "" +"`flwr.common.Weights` a été renommé en `flwr.common.NDArys` pour mieux " +"rendre compte de la nature de ce type." + +#: ../../source/ref-changelog.md:602 +msgid "" +"**Remove antiquated** `force_final_distributed_eval` **from** " +"`start_server` ([#1258](https://github.com/adap/flower/pull/1258), " +"[#1259](https://github.com/adap/flower/pull/1259))" +msgstr "" +"**Supprimez l'ancien** `force_final_distributed_eval` **de** " +"`start_server` ([#1258](https://github.com/adap/flower/pull/1258), " +"[#1259](https://github.com/adap/flower/pull/1259))" + +#: ../../source/ref-changelog.md:604 +msgid "" +"The `start_server` parameter `force_final_distributed_eval` has long been" +" a historic artefact, in this release it is finally gone for good." +msgstr "" +"Le paramètre `start_server` `force_final_distributed_eval` a longtemps " +"été un artefact historique, dans cette version il a finalement disparu " +"pour de bon." + +#: ../../source/ref-changelog.md:606 +msgid "" +"**Make** `get_parameters` **configurable** " +"([#1242](https://github.com/adap/flower/pull/1242))" +msgstr "" +"**Make** `get_parameters` **configurable** " +"([#1242](https://github.com/adap/flower/pull/1242))" + +#: ../../source/ref-changelog.md:608 +msgid "" +"The `get_parameters` method now accepts a configuration dictionary, just " +"like `get_properties`, `fit`, and `evaluate`." +msgstr "" +"La méthode `get_parameters` accepte maintenant un dictionnaire de " +"configuration, tout comme `get_properties`, `fit`, et `evaluate`." + +#: ../../source/ref-changelog.md:610 +msgid "" +"**Replace** `num_rounds` **in** `start_simulation` **with new** `config` " +"**parameter** ([#1281](https://github.com/adap/flower/pull/1281))" +msgstr "" +"**Remplace** `num_rounds` **dans** `start_simulation` **avec le nouveau**" +" `config` **paramètre** " +"([#1281](https://github.com/adap/flower/pull/1281))" + +#: ../../source/ref-changelog.md:612 +msgid "" +"The `start_simulation` function now accepts a configuration dictionary " +"`config` instead of the `num_rounds` integer. This improves the " +"consistency between `start_simulation` and `start_server` and makes " +"transitioning between the two easier." +msgstr "" +"La fonction `start_simulation` accepte maintenant un dictionnaire de " +"configuration `config` au lieu de l'entier `num_rounds`. Cela améliore la" +" cohérence entre `start_simulation` et `start_server` et facilite la " +"transition entre les deux." + +#: ../../source/ref-changelog.md:616 +msgid "" +"**Support Python 3.10** " +"([#1320](https://github.com/adap/flower/pull/1320))" +msgstr "" +"**Support Python 3.10** " +"([#1320](https://github.com/adap/flower/pull/1320))" + +#: ../../source/ref-changelog.md:618 +msgid "" +"The previous Flower release introduced experimental support for Python " +"3.10, this release declares Python 3.10 support as stable." +msgstr "" +"La version précédente de Flower a introduit la prise en charge " +"expérimentale de Python 3.10, cette version déclare la prise en charge de" +" Python 3.10 comme stable." + +#: ../../source/ref-changelog.md:620 +msgid "" +"**Make all** `Client` **and** `NumPyClient` **methods optional** " +"([#1260](https://github.com/adap/flower/pull/1260), " +"[#1277](https://github.com/adap/flower/pull/1277))" +msgstr "" +"**Rendre toutes les **méthodes `Client` **et** `NumPyClient` " +"**facultatives** ([#1260](https://github.com/adap/flower/pull/1260), " +"[#1277](https://github.com/adap/flower/pull/1277))" + +#: ../../source/ref-changelog.md:622 +msgid "" +"The `Client`/`NumPyClient` methods `get_properties`, `get_parameters`, " +"`fit`, and `evaluate` are all optional. This enables writing clients that" +" implement, for example, only `fit`, but no other method. No need to " +"implement `evaluate` when using centralized evaluation!" +msgstr "" +"Les méthodes `Client`/`NumPyClient` `get_properties`, `get_parameters`, " +"`fit`, et `evaluate` sont toutes optionnelles. Cela permet d'écrire des " +"clients qui n'implémentent, par exemple, que `fit`, mais aucune autre " +"méthode. Pas besoin d'implémenter `evaluate` quand on utilise " +"l'évaluation centralisée !" + +#: ../../source/ref-changelog.md:624 +msgid "" +"**Enable passing a** `Server` **instance to** `start_simulation` " +"([#1281](https://github.com/adap/flower/pull/1281))" +msgstr "" +"**Autoriser le passage d'une **instance `Server` à** `start_simulation` " +"([#1281](https://github.com/adap/flower/pull/1281))" + +#: ../../source/ref-changelog.md:626 +msgid "" +"Similar to `start_server`, `start_simulation` now accepts a full `Server`" +" instance. This enables users to heavily customize the execution of " +"eperiments and opens the door to running, for example, async FL using the" +" Virtual Client Engine." +msgstr "" +"Comme pour `start_server`, `start_simulation` accepte maintenant une " +"instance complète de `Server`. Cela permet aux utilisateurs de " +"personnaliser fortement l'exécution des expériences et ouvre la porte à " +"l'exécution, par exemple, de FL asynchrones à l'aide du moteur de client " +"virtuel." + +#: ../../source/ref-changelog.md:628 +msgid "" +"**Update code examples** " +"([#1291](https://github.com/adap/flower/pull/1291), " +"[#1286](https://github.com/adap/flower/pull/1286), " +"[#1282](https://github.com/adap/flower/pull/1282))" +msgstr "" +"**Mettre à jour les exemples de code** " +"([#1291](https://github.com/adap/flower/pull/1291), " +"[#1286](https://github.com/adap/flower/pull/1286), " +"[#1282](https://github.com/adap/flower/pull/1282))" + +#: ../../source/ref-changelog.md:630 +msgid "" +"Many code examples received small or even large maintenance updates, " +"among them are" +msgstr "" +"De nombreux exemples de code ont reçu de petites ou même de grandes mises" +" à jour de maintenance" + +#: ../../source/ref-changelog.md:632 +msgid "`scikit-learn`" +msgstr "`scikit-learn`" + +#: ../../source/ref-changelog.md:633 +msgid "`simulation_pytorch`" +msgstr "`simulation_pytorch`" + +#: ../../source/ref-changelog.md:634 +msgid "`quickstart_pytorch`" +msgstr "`quickstart_pytorch` (démarrage rapide)" + +#: ../../source/ref-changelog.md:635 +msgid "`quickstart_simulation`" +msgstr "`quickstart_simulation`" + +#: ../../source/ref-changelog.md:636 +msgid "`quickstart_tensorflow`" +msgstr "`quickstart_tensorflow`" + +#: ../../source/ref-changelog.md:637 +msgid "`advanced_tensorflow`" +msgstr "`advanced_tensorflow` (en anglais)" + +#: ../../source/ref-changelog.md:639 +msgid "" +"**Remove the obsolete simulation example** " +"([#1328](https://github.com/adap/flower/pull/1328))" +msgstr "" +"**Supprime l'exemple de simulation obsolète** " +"([#1328](https://github.com/adap/flower/pull/1328))" + +#: ../../source/ref-changelog.md:641 +msgid "" +"Removes the obsolete `simulation` example and renames " +"`quickstart_simulation` to `simulation_tensorflow` so it fits withs the " +"naming of `simulation_pytorch`" +msgstr "" +"Supprime l'exemple obsolète `simulation` et renomme " +"`quickstart_simulation` en `simulation_tensorflow` pour qu'il corresponde" +" au nom de `simulation_pytorch`" + +#: ../../source/ref-changelog.md:643 +msgid "" +"**Update documentation** " +"([#1223](https://github.com/adap/flower/pull/1223), " +"[#1209](https://github.com/adap/flower/pull/1209), " +"[#1251](https://github.com/adap/flower/pull/1251), " +"[#1257](https://github.com/adap/flower/pull/1257), " +"[#1267](https://github.com/adap/flower/pull/1267), " +"[#1268](https://github.com/adap/flower/pull/1268), " +"[#1300](https://github.com/adap/flower/pull/1300), " +"[#1304](https://github.com/adap/flower/pull/1304), " +"[#1305](https://github.com/adap/flower/pull/1305), " +"[#1307](https://github.com/adap/flower/pull/1307))" +msgstr "" +"**Mise à jour de la documentation** " +"([#1223](https://github.com/adap/flower/pull/1223), " +"[#1209](https://github.com/adap/flower/pull/1209), " +"[#1251](https://github.com/adap/flower/pull/1251), " +"[#1257](https://github.com/adap/flower/pull/1257), " +"[#1267](https://github.com/adap/flower/pull/1267), " +"[#1268](https://github.com/adap/flower/pull/1268), " +"[#1300](https://github.com/adap/flower/pull/1300), " +"[#1304](https://github.com/adap/flower/pull/1304), " +"[#1305](https://github.com/adap/flower/pull/1305), " +"[#1307](https://github.com/adap/flower/pull/1307))" + +#: ../../source/ref-changelog.md:645 +msgid "" +"One substantial documentation update fixes multiple smaller rendering " +"issues, makes titles more succinct to improve navigation, removes a " +"deprecated library, updates documentation dependencies, includes the " +"`flwr.common` module in the API reference, includes support for markdown-" +"based documentation, migrates the changelog from `.rst` to `.md`, and " +"fixes a number of smaller details!" +msgstr "" +"Une mise à jour substantielle de la documentation corrige plusieurs " +"petits problèmes de rendu, rend les titres plus succincts pour améliorer " +"la navigation, supprime une bibliothèque obsolète, met à jour les " +"dépendances de la documentation, inclut le module `flwr.common` dans la " +"référence de l'API, inclut le support de la documentation basée sur le " +"markdown, migre le changelog de `.rst` vers `.md`, et corrige un certain " +"nombre de détails plus petits !" + +#: ../../source/ref-changelog.md:647 ../../source/ref-changelog.md:702 +#: ../../source/ref-changelog.md:771 ../../source/ref-changelog.md:810 +msgid "**Minor updates**" +msgstr "**Mises à jour mineures**" + +#: ../../source/ref-changelog.md:649 +msgid "" +"Add round number to fit and evaluate log messages " +"([#1266](https://github.com/adap/flower/pull/1266))" +msgstr "" +"Ajoute un chiffre rond pour ajuster et évaluer les messages du journal " +"([#1266](https://github.com/adap/flower/pull/1266))" + +#: ../../source/ref-changelog.md:650 +msgid "" +"Add secure gRPC connection to the `advanced_tensorflow` code example " +"([#847](https://github.com/adap/flower/pull/847))" +msgstr "" +"Ajouter une connexion gRPC sécurisée à l'exemple de code " +"`advanced_tensorflow` ([#847](https://github.com/adap/flower/pull/847))" + +#: ../../source/ref-changelog.md:651 +msgid "" +"Update developer tooling " +"([#1231](https://github.com/adap/flower/pull/1231), " +"[#1276](https://github.com/adap/flower/pull/1276), " +"[#1301](https://github.com/adap/flower/pull/1301), " +"[#1310](https://github.com/adap/flower/pull/1310))" +msgstr "" +"Mettre à jour les outils de développement " +"([#1231](https://github.com/adap/flower/pull/1231), " +"[#1276](https://github.com/adap/flower/pull/1276), " +"[#1301](https://github.com/adap/flower/pull/1301), " +"[#1310](https://github.com/adap/flower/pull/1310))" + +#: ../../source/ref-changelog.md:652 +msgid "" +"Rename ProtoBuf messages to improve consistency " +"([#1214](https://github.com/adap/flower/pull/1214), " +"[#1258](https://github.com/adap/flower/pull/1258), " +"[#1259](https://github.com/adap/flower/pull/1259))" +msgstr "" +"Renomme les messages ProtoBuf pour améliorer la cohérence " +"([#1214](https://github.com/adap/flower/pull/1214), " +"[#1258](https://github.com/adap/flower/pull/1258), " +"[#1259](https://github.com/adap/flower/pull/1259))" + +#: ../../source/ref-changelog.md:654 +msgid "v0.19.0 (2022-05-18)" +msgstr "v0.19.0 (2022-05-18)" + +#: ../../source/ref-changelog.md:658 +msgid "" +"**Flower Baselines (preview): FedOpt, FedBN, FedAvgM** " +"([#919](https://github.com/adap/flower/pull/919), " +"[#1127](https://github.com/adap/flower/pull/1127), " +"[#914](https://github.com/adap/flower/pull/914))" +msgstr "" +"**Flower Baselines (preview) : FedOpt, FedBN, FedAvgM** " +"([#919](https://github.com/adap/flower/pull/919), " +"[#1127](https://github.com/adap/flower/pull/1127), " +"[#914](https://github.com/adap/flower/pull/914))" + +#: ../../source/ref-changelog.md:660 +msgid "" +"The first preview release of Flower Baselines has arrived! We're " +"kickstarting Flower Baselines with implementations of FedOpt (FedYogi, " +"FedAdam, FedAdagrad), FedBN, and FedAvgM. Check the documentation on how " +"to use [Flower Baselines](https://flower.dev/docs/using-baselines.html). " +"With this first preview release we're also inviting the community to " +"[contribute their own baselines](https://flower.dev/docs/contributing-" +"baselines.html)." +msgstr "" +"La première version préliminaire de Flower Baselines est arrivée ! Nous " +"démarrons Flower Baselines avec des implémentations de FedOpt (FedYogi, " +"FedAdam, FedAdagrad), FedBN, et FedAvgM. Consultez la documentation sur " +"l'utilisation de [Flower Baselines](https://flower.dev/docs/using-" +"baselines.html). Avec cette première version préliminaire, nous invitons " +"également la communauté à [contribuer à leurs propres lignes de " +"base](https://flower.dev/docs/contributing-baselines.html)." + +#: ../../source/ref-changelog.md:662 +msgid "" +"**C++ client SDK (preview) and code example** " +"([#1111](https://github.com/adap/flower/pull/1111))" +msgstr "" +"**SDK client C++ (aperçu) et exemple de code** " +"([#1111](https://github.com/adap/flower/pull/1111))" + +#: ../../source/ref-changelog.md:664 +msgid "" +"Preview support for Flower clients written in C++. The C++ preview " +"includes a Flower client SDK and a quickstart code example that " +"demonstrates a simple C++ client using the SDK." +msgstr "" +"L'aperçu C++ comprend un SDK pour les clients Flower et un exemple de " +"code de démarrage rapide qui démontre un client C++ simple utilisant le " +"SDK." + +#: ../../source/ref-changelog.md:666 +msgid "" +"**Add experimental support for Python 3.10 and Python 3.11** " +"([#1135](https://github.com/adap/flower/pull/1135))" +msgstr "" +"**Ajouter la prise en charge expérimentale de Python 3.10 et Python " +"3.11** ([#1135](https://github.com/adap/flower/pull/1135))" + +#: ../../source/ref-changelog.md:668 +msgid "" +"Python 3.10 is the latest stable release of Python and Python 3.11 is due" +" to be released in October. This Flower release adds experimental support" +" for both Python versions." +msgstr "" +"Python 3.10 est la dernière version stable de Python et Python 3.11 " +"devrait sortir en octobre. Cette version de Flower ajoute une prise en " +"charge expérimentale pour les deux versions de Python." + +#: ../../source/ref-changelog.md:670 +msgid "" +"**Aggregate custom metrics through user-provided functions** " +"([#1144](https://github.com/adap/flower/pull/1144))" +msgstr "" +"**Agréger des mesures personnalisées grâce à des fonctions fournies par " +"l'utilisateur** ([#1144](https://github.com/adap/flower/pull/1144))" + +#: ../../source/ref-changelog.md:672 +msgid "" +"Custom metrics (e.g., `accuracy`) can now be aggregated without having to" +" customize the strategy. Built-in strategies support two new arguments, " +"`fit_metrics_aggregation_fn` and `evaluate_metrics_aggregation_fn`, that " +"allow passing custom metric aggregation functions." +msgstr "" +"Les stratégies intégrées prennent en charge deux nouveaux arguments, " +"`fit_metrics_aggregation_fn` et `evaluate_metrics_aggregation_fn`, qui " +"permettent de passer des fonctions d'agrégation de métriques " +"personnalisées." + +#: ../../source/ref-changelog.md:674 +msgid "" +"**User-configurable round timeout** " +"([#1162](https://github.com/adap/flower/pull/1162))" +msgstr "" +"**Temps d'attente configurable par l'utilisateur** " +"([#1162](https://github.com/adap/flower/pull/1162))" + +#: ../../source/ref-changelog.md:676 +msgid "" +"A new configuration value allows the round timeout to be set for " +"`start_server` and `start_simulation`. If the `config` dictionary " +"contains a `round_timeout` key (with a `float` value in seconds), the " +"server will wait *at least* `round_timeout` seconds before it closes the " +"connection." +msgstr "" +"Si le dictionnaire `config` contient une clé `round_timeout` (avec une " +"valeur `float` en secondes), le serveur attendra *au moins* " +"`round_timeout` secondes avant de fermer la connexion." + +#: ../../source/ref-changelog.md:678 +msgid "" +"**Enable both federated evaluation and centralized evaluation to be used " +"at the same time in all built-in strategies** " +"([#1091](https://github.com/adap/flower/pull/1091))" +msgstr "" +"**Permettre l'utilisation simultanée de l'évaluation fédérée et de " +"l'évaluation centralisée dans toutes les stratégies intégrées** " +"([#1091](https://github.com/adap/flower/pull/1091))" + +#: ../../source/ref-changelog.md:680 +msgid "" +"Built-in strategies can now perform both federated evaluation (i.e., " +"client-side) and centralized evaluation (i.e., server-side) in the same " +"round. Federated evaluation can be disabled by setting `fraction_eval` to" +" `0.0`." +msgstr "" +"Les stratégies intégrées peuvent maintenant effectuer une évaluation " +"fédérée (c'est-à-dire côté client) et une évaluation centralisée " +"(c'est-à-dire côté serveur) dans le même tour. L'évaluation fédérée peut " +"être désactivée en réglant `fraction_eval` sur `0.0`." + +#: ../../source/ref-changelog.md:682 +msgid "" +"**Two new Jupyter Notebook tutorials** " +"([#1141](https://github.com/adap/flower/pull/1141))" +msgstr "" +"**Deux nouveaux tutoriels Jupyter Notebook** " +"([#1141](https://github.com/adap/flower/pull/1141))" + +#: ../../source/ref-changelog.md:684 +msgid "" +"Two Jupyter Notebook tutorials (compatible with Google Colab) explain " +"basic and intermediate Flower features:" +msgstr "" +"Deux tutoriels Jupyter Notebook (compatibles avec Google Colab) " +"expliquent les fonctionnalités de base et intermédiaires de Flower :" + +#: ../../source/ref-changelog.md:686 +msgid "" +"*An Introduction to Federated Learning*: [Open in " +"Colab](https://colab.research.google.com/github/adap/flower/blob/main/tutorials/Flower-1" +"-Intro-to-FL-PyTorch.ipynb)" +msgstr "" +"*Introduction à l'apprentissage fédéré* : [Open in " +"Colab](https://colab.research.google.com/github/adap/flower/blob/main/tutorials/Flower-1" +"-Intro-to-FL-PyTorch.ipynb)" + +#: ../../source/ref-changelog.md:688 +msgid "" +"*Using Strategies in Federated Learning*: [Open in " +"Colab](https://colab.research.google.com/github/adap/flower/blob/main/tutorials/Flower-2" +"-Strategies-in-FL-PyTorch.ipynb)" +msgstr "" +"*Utiliser des stratégies dans l'apprentissage fédéré* : [Open in " +"Colab](https://colab.research.google.com/github/adap/flower/blob/main/tutorials/Flower-2" +"-Strategies-in-FL-PyTorch.ipynb)" + +#: ../../source/ref-changelog.md:690 +msgid "" +"**New FedAvgM strategy (Federated Averaging with Server Momentum)** " +"([#1076](https://github.com/adap/flower/pull/1076))" +msgstr "" +"**Nouvelle stratégie FedAvgM (Federated Averaging with Server Momentum)**" +" ([#1076](https://github.com/adap/flower/pull/1076))" + +#: ../../source/ref-changelog.md:692 +#, fuzzy +msgid "" +"The new `FedAvgM` strategy implements Federated Averaging with Server " +"Momentum \\[Hsu et al., 2019\\]." +msgstr "" +"La nouvelle stratégie `FedAvgM` met en œuvre la moyenne fédérée avec le " +"momentum du serveur [Hsu et al., 2019]." + +#: ../../source/ref-changelog.md:694 +msgid "" +"**New advanced PyTorch code example** " +"([#1007](https://github.com/adap/flower/pull/1007))" +msgstr "" +"**Nouvel exemple de code PyTorch avancé** " +"([#1007](https://github.com/adap/flower/pull/1007))" + +#: ../../source/ref-changelog.md:696 +msgid "" +"A new code example (`advanced_pytorch`) demonstrates advanced Flower " +"concepts with PyTorch." +msgstr "" +"Un nouvel exemple de code (`advanced_pytorch`) démontre des concepts de " +"fleur avancés avec PyTorch." + +#: ../../source/ref-changelog.md:698 +msgid "" +"**New JAX code example** " +"([#906](https://github.com/adap/flower/pull/906), " +"[#1143](https://github.com/adap/flower/pull/1143))" +msgstr "" +"**Nouvel exemple de code JAX** " +"([#906](https://github.com/adap/flower/pull/906), " +"[#1143](https://github.com/adap/flower/pull/1143))" + +#: ../../source/ref-changelog.md:700 +msgid "" +"A new code example (`jax_from_centralized_to_federated`) shows federated " +"learning with JAX and Flower." +msgstr "" +"Un nouvel exemple de code (`jax_from_centralized_to_federated`) montre " +"l'apprentissage fédéré avec JAX et Flower." + +#: ../../source/ref-changelog.md:704 +msgid "" +"New option to keep Ray running if Ray was already initialized in " +"`start_simulation` ([#1177](https://github.com/adap/flower/pull/1177))" +msgstr "" +"Nouvelle option pour continuer à faire fonctionner Ray si Ray a déjà été " +"initialisé dans `start_simulation` " +"([#1177](https://github.com/adap/flower/pull/1177))" + +#: ../../source/ref-changelog.md:705 +msgid "" +"Add support for custom `ClientManager` as a `start_simulation` parameter " +"([#1171](https://github.com/adap/flower/pull/1171))" +msgstr "" +"Ajout de la prise en charge d'un `ClientManager` personnalisé comme " +"paramètre de `start_simulation` " +"([#1171](https://github.com/adap/flower/pull/1171))" + +#: ../../source/ref-changelog.md:706 +#, fuzzy +msgid "" +"New documentation for [implementing " +"strategies](https://flower.dev/docs/framework/how-to-implement-" +"strategies.html) ([#1097](https://github.com/adap/flower/pull/1097), " +"[#1175](https://github.com/adap/flower/pull/1175))" +msgstr "" +"Nouvelle documentation pour [mettre en œuvre des " +"stratégies](https://flower.dev/docs/framework/how-to-implement-" +"strategies.html) ([#1097](https://github.com/adap/flower/pull/1097), " +"[#1175](https://github.com/adap/flower/pull/1175))" + +#: ../../source/ref-changelog.md:707 +msgid "" +"New mobile-friendly documentation theme " +"([#1174](https://github.com/adap/flower/pull/1174))" +msgstr "" +"Nouveau thème de documentation adapté aux mobiles " +"([#1174](https://github.com/adap/flower/pull/1174))" + +#: ../../source/ref-changelog.md:708 +msgid "" +"Limit version range for (optional) `ray` dependency to include only " +"compatible releases (`>=1.9.2,<1.12.0`) " +"([#1205](https://github.com/adap/flower/pull/1205))" +msgstr "" +"Limite la plage de versions pour la dépendance (optionnelle) `ray` pour " +"n'inclure que les versions compatibles (`>=1.9.2,<1.12.0`) " +"([#1205](https://github.com/adap/flower/pull/1205))" + +#: ../../source/ref-changelog.md:712 +msgid "" +"**Remove deprecated support for Python 3.6** " +"([#871](https://github.com/adap/flower/pull/871))" +msgstr "" +"**Supprime la prise en charge obsolète de Python 3.6** " +"([#871](https://github.com/adap/flower/pull/871))" + +#: ../../source/ref-changelog.md:713 +msgid "" +"**Remove deprecated KerasClient** " +"([#857](https://github.com/adap/flower/pull/857))" +msgstr "" +"**Supprimez KerasClient** " +"([#857](https://github.com/adap/flower/pull/857))" + +#: ../../source/ref-changelog.md:714 +msgid "" +"**Remove deprecated no-op extra installs** " +"([#973](https://github.com/adap/flower/pull/973))" +msgstr "" +"**Supprimer les installations supplémentaires no-op dépréciées** " +"([#973](https://github.com/adap/flower/pull/973))" + +#: ../../source/ref-changelog.md:715 +msgid "" +"**Remove deprecated proto fields from** `FitRes` **and** `EvaluateRes` " +"([#869](https://github.com/adap/flower/pull/869))" +msgstr "" +"**Supprimez les champs proto obsolètes de** `FitRes` **et** `EvaluateRes`" +" ([#869](https://github.com/adap/flower/pull/869))" + +#: ../../source/ref-changelog.md:716 +msgid "" +"**Remove deprecated QffedAvg strategy (replaced by QFedAvg)** " +"([#1107](https://github.com/adap/flower/pull/1107))" +msgstr "" +"**Supprime la stratégie QffedAvg (remplacée par QFedAvg)** " +"([#1107](https://github.com/adap/flower/pull/1107))" + +#: ../../source/ref-changelog.md:717 +msgid "" +"**Remove deprecated DefaultStrategy strategy** " +"([#1142](https://github.com/adap/flower/pull/1142))" +msgstr "" +"**Supprime la stratégie DefaultStrategy qui est obsolète** " +"([#1142](https://github.com/adap/flower/pull/1142))" + +#: ../../source/ref-changelog.md:718 +msgid "" +"**Remove deprecated support for eval_fn accuracy return value** " +"([#1142](https://github.com/adap/flower/pull/1142))" +msgstr "" +"**Supprimer la prise en charge obsolète de la valeur de retour de la " +"précision eval_fn** ([#1142](https://github.com/adap/flower/pull/1142))" + +#: ../../source/ref-changelog.md:719 +msgid "" +"**Remove deprecated support for passing initial parameters as NumPy " +"ndarrays** ([#1142](https://github.com/adap/flower/pull/1142))" +msgstr "" +"**Supprime la prise en charge obsolète du passage des paramètres initiaux" +" en tant que ndarrays NumPy** " +"([#1142](https://github.com/adap/flower/pull/1142))" + +#: ../../source/ref-changelog.md:721 +msgid "v0.18.0 (2022-02-28)" +msgstr "v0.18.0 (2022-02-28)" + +#: ../../source/ref-changelog.md:725 +msgid "" +"**Improved Virtual Client Engine compatibility with Jupyter Notebook / " +"Google Colab** ([#866](https://github.com/adap/flower/pull/866), " +"[#872](https://github.com/adap/flower/pull/872), " +"[#833](https://github.com/adap/flower/pull/833), " +"[#1036](https://github.com/adap/flower/pull/1036))" +msgstr "" +"**Amélioration de la compatibilité du moteur de client virtuel avec " +"Jupyter Notebook / Google Colab** " +"([#866](https://github.com/adap/flower/pull/866), " +"[#872](https://github.com/adap/flower/pull/872), " +"[#833](https://github.com/adap/flower/pull/833), " +"[#1036](https://github.com/adap/flower/pull/1036))" + +#: ../../source/ref-changelog.md:727 +msgid "" +"Simulations (using the Virtual Client Engine through `start_simulation`) " +"now work more smoothly on Jupyter Notebooks (incl. Google Colab) after " +"installing Flower with the `simulation` extra (`pip install " +"flwr[simulation]`)." +msgstr "" +"Les simulations (utilisant le moteur de client virtuel via " +"`start_simulation`) fonctionnent maintenant plus facilement sur les " +"Notebooks Jupyter (y compris Google Colab) après avoir installé Flower " +"avec l'option `simulation` (`pip install flwr[simulation]`)." + +#: ../../source/ref-changelog.md:729 +msgid "" +"**New Jupyter Notebook code example** " +"([#833](https://github.com/adap/flower/pull/833))" +msgstr "" +"**Nouvel exemple de code Jupyter Notebook** " +"([#833](https://github.com/adap/flower/pull/833))" + +#: ../../source/ref-changelog.md:731 +msgid "" +"A new code example (`quickstart_simulation`) demonstrates Flower " +"simulations using the Virtual Client Engine through Jupyter Notebook " +"(incl. Google Colab)." +msgstr "" +"Un nouvel exemple de code (`quickstart_simulation`) démontre des " +"simulations de Flower en utilisant le moteur de client virtuel via " +"Jupyter Notebook (y compris Google Colab)." + +#: ../../source/ref-changelog.md:733 +msgid "" +"**Client properties (feature preview)** " +"([#795](https://github.com/adap/flower/pull/795))" +msgstr "" +"**Propriétés du client (aperçu des fonctionnalités)** " +"([#795](https://github.com/adap/flower/pull/795))" + +#: ../../source/ref-changelog.md:735 +msgid "" +"Clients can implement a new method `get_properties` to enable server-side" +" strategies to query client properties." +msgstr "" +"Les clients peuvent implémenter une nouvelle méthode `get_properties` " +"pour permettre aux stratégies côté serveur d'interroger les propriétés du" +" client." + +#: ../../source/ref-changelog.md:737 +msgid "" +"**Experimental Android support with TFLite** " +"([#865](https://github.com/adap/flower/pull/865))" +msgstr "" +"**Support expérimental d'Android avec TFLite** " +"([#865](https://github.com/adap/flower/pull/865))" + +#: ../../source/ref-changelog.md:739 +msgid "" +"Android support has finally arrived in `main`! Flower is both client-" +"agnostic and framework-agnostic by design. One can integrate arbitrary " +"client platforms and with this release, using Flower on Android has " +"become a lot easier." +msgstr "" +"La prise en charge d'Android est enfin arrivée dans `main` ! Flower est à" +" la fois agnostique au niveau du client et du cadre de travail. On peut " +"intégrer des plates-formes client arbitraires et avec cette version, " +"l'utilisation de Flower sur Android est devenue beaucoup plus facile." + +#: ../../source/ref-changelog.md:741 +msgid "" +"The example uses TFLite on the client side, along with a new " +"`FedAvgAndroid` strategy. The Android client and `FedAvgAndroid` are " +"still experimental, but they are a first step towards a fully-fledged " +"Android SDK and a unified `FedAvg` implementation that integrated the new" +" functionality from `FedAvgAndroid`." +msgstr "" +"L'exemple utilise TFLite du côté client, ainsi qu'une nouvelle stratégie " +"`FedAvgAndroid`. Le client Android et `FedAvgAndroid` sont encore " +"expérimentaux, mais ils constituent un premier pas vers un SDK Android à " +"part entière et une implémentation unifiée de `FedAvg` intégrant la " +"nouvelle fonctionnalité de `FedAvgAndroid`." + +#: ../../source/ref-changelog.md:743 +msgid "" +"**Make gRPC keepalive time user-configurable and decrease default " +"keepalive time** ([#1069](https://github.com/adap/flower/pull/1069))" +msgstr "" +"**Rendre le temps de garde gRPC configurable par l'utilisateur et " +"diminuer le temps de garde par défaut** " +"([#1069](https://github.com/adap/flower/pull/1069))" + +#: ../../source/ref-changelog.md:745 +msgid "" +"The default gRPC keepalive time has been reduced to increase the " +"compatibility of Flower with more cloud environments (for example, " +"Microsoft Azure). Users can configure the keepalive time to customize the" +" gRPC stack based on specific requirements." +msgstr "" +"Le temps de keepalive gRPC par défaut a été réduit pour augmenter la " +"compatibilité de Flower avec davantage d'environnements cloud (par " +"exemple, Microsoft Azure). Les utilisateurs peuvent configurer le temps " +"de keepalive pour personnaliser la pile gRPC en fonction d'exigences " +"spécifiques." + +#: ../../source/ref-changelog.md:747 +msgid "" +"**New differential privacy example using Opacus and PyTorch** " +"([#805](https://github.com/adap/flower/pull/805))" +msgstr "" +"**Nouvel exemple de confidentialité différentielle utilisant Opacus et " +"PyTorch** ([#805](https://github.com/adap/flower/pull/805))" + +#: ../../source/ref-changelog.md:749 +msgid "" +"A new code example (`opacus`) demonstrates differentially-private " +"federated learning with Opacus, PyTorch, and Flower." +msgstr "" +"Un nouvel exemple de code (`opacus`) démontre l'apprentissage fédéré " +"différentiellement privé avec Opacus, PyTorch et Flower." + +#: ../../source/ref-changelog.md:751 +msgid "" +"**New Hugging Face Transformers code example** " +"([#863](https://github.com/adap/flower/pull/863))" +msgstr "" +"**Nouvel exemple de code pour les Transformers à visage embrassant** " +"([#863](https://github.com/adap/flower/pull/863))" + +#: ../../source/ref-changelog.md:753 +msgid "" +"A new code example (`quickstart_huggingface`) demonstrates usage of " +"Hugging Face Transformers with Flower." +msgstr "" +"Un nouvel exemple de code (`quickstart_huggingface`) démontre " +"l'utilisation des transformateurs Hugging Face avec Flower." + +#: ../../source/ref-changelog.md:755 +msgid "" +"**New MLCube code example** " +"([#779](https://github.com/adap/flower/pull/779), " +"[#1034](https://github.com/adap/flower/pull/1034), " +"[#1065](https://github.com/adap/flower/pull/1065), " +"[#1090](https://github.com/adap/flower/pull/1090))" +msgstr "" +"**Nouvel exemple de code MLCube** " +"([#779](https://github.com/adap/flower/pull/779), " +"[#1034](https://github.com/adap/flower/pull/1034), " +"[#1065](https://github.com/adap/flower/pull/1065), " +"[#1090](https://github.com/adap/flower/pull/1090))" + +#: ../../source/ref-changelog.md:757 +msgid "" +"A new code example (`quickstart_mlcube`) demonstrates usage of MLCube " +"with Flower." +msgstr "" +"Un nouvel exemple de code (`quickstart_mlcube`) démontre l'utilisation de" +" MLCube avec Flower." + +#: ../../source/ref-changelog.md:759 +msgid "" +"**SSL-enabled server and client** " +"([#842](https://github.com/adap/flower/pull/842), " +"[#844](https://github.com/adap/flower/pull/844), " +"[#845](https://github.com/adap/flower/pull/845), " +"[#847](https://github.com/adap/flower/pull/847), " +"[#993](https://github.com/adap/flower/pull/993), " +"[#994](https://github.com/adap/flower/pull/994))" +msgstr "" +"**([#842](https://github.com/adap/flower/pull/842), " +"[#844](https://github.com/adap/flower/pull/844), " +"[#845](https://github.com/adap/flower/pull/845), " +"[#847](https://github.com/adap/flower/pull/847), " +"[#993](https://github.com/adap/flower/pull/993), " +"[#994](https://github.com/adap/flower/pull/994))" + +#: ../../source/ref-changelog.md:761 +msgid "" +"SSL enables secure encrypted connections between clients and servers. " +"This release open-sources the Flower secure gRPC implementation to make " +"encrypted communication channels accessible to all Flower users." +msgstr "" +"SSL permet d'établir des connexions cryptées et sécurisées entre les " +"clients et les serveurs. Cette version met en open-source " +"l'implémentation gRPC sécurisée de Flower afin de rendre les canaux de " +"communication cryptés accessibles à tous les utilisateurs de Flower." + +#: ../../source/ref-changelog.md:763 +msgid "" +"**Updated** `FedAdam` **and** `FedYogi` **strategies** " +"([#885](https://github.com/adap/flower/pull/885), " +"[#895](https://github.com/adap/flower/pull/895))" +msgstr "" +"**Mise à jour** `FedAdam` **et** `FedYogi` **stratégies** " +"([#885](https://github.com/adap/flower/pull/885), " +"[#895](https://github.com/adap/flower/pull/895))" + +#: ../../source/ref-changelog.md:765 +msgid "" +"`FedAdam` and `FedAdam` match the latest version of the Adaptive " +"Federated Optimization paper." +msgstr "" +"`FedAdam` et `FedAdam` correspondent à la dernière version de l'article " +"sur l'optimisation fédérée adaptative." + +#: ../../source/ref-changelog.md:767 +msgid "" +"**Initialize** `start_simulation` **with a list of client IDs** " +"([#860](https://github.com/adap/flower/pull/860))" +msgstr "" +"**Initialise** `start_simulation` **avec une liste d'ID de clients** " +"([#860](https://github.com/adap/flower/pull/860))" + +#: ../../source/ref-changelog.md:769 +msgid "" +"`start_simulation` can now be called with a list of client IDs " +"(`clients_ids`, type: `List[str]`). Those IDs will be passed to the " +"`client_fn` whenever a client needs to be initialized, which can make it " +"easier to load data partitions that are not accessible through `int` " +"identifiers." +msgstr "" +"`start_simulation` peut maintenant être appelé avec une liste " +"d'identifiants de clients (`clients_ids`, type : `List[str]`). Ces " +"identifiants seront passés à `client_fn` chaque fois qu'un client doit " +"être initialisé, ce qui peut faciliter le chargement de partitions de " +"données qui ne sont pas accessibles par des identifiants `int`." + +#: ../../source/ref-changelog.md:773 +msgid "" +"Update `num_examples` calculation in PyTorch code examples in " +"([#909](https://github.com/adap/flower/pull/909))" +msgstr "" +"Mettre à jour le calcul de `num_examples` dans les exemples de code " +"PyTorch dans ([#909](https://github.com/adap/flower/pull/909))" + +#: ../../source/ref-changelog.md:774 +msgid "" +"Expose Flower version through `flwr.__version__` " +"([#952](https://github.com/adap/flower/pull/952))" +msgstr "" +"Exposer la version de Flower à travers `flwr.__version__` " +"([#952](https://github.com/adap/flower/pull/952))" + +#: ../../source/ref-changelog.md:775 +msgid "" +"`start_server` in `app.py` now returns a `History` object containing " +"metrics from training ([#974](https://github.com/adap/flower/pull/974))" +msgstr "" +"`start_server` dans `app.py` renvoie maintenant un objet `History` " +"contenant les métriques de l'entraînement " +"([#974](https://github.com/adap/flower/pull/974))" + +#: ../../source/ref-changelog.md:776 +msgid "" +"Make `max_workers` (used by `ThreadPoolExecutor`) configurable " +"([#978](https://github.com/adap/flower/pull/978))" +msgstr "" +"Rendre `max_workers` (utilisé par `ThreadPoolExecutor`) configurable " +"([#978](https://github.com/adap/flower/pull/978))" + +#: ../../source/ref-changelog.md:777 +msgid "" +"Increase sleep time after server start to three seconds in all code " +"examples ([#1086](https://github.com/adap/flower/pull/1086))" +msgstr "" +"Augmente le temps de sommeil après le démarrage du serveur à trois " +"secondes dans tous les exemples de code " +"([#1086](https://github.com/adap/flower/pull/1086))" + +#: ../../source/ref-changelog.md:778 +msgid "" +"Added a new FAQ section to the documentation " +"([#948](https://github.com/adap/flower/pull/948))" +msgstr "" +"Ajout d'une nouvelle section FAQ à la documentation " +"([#948](https://github.com/adap/flower/pull/948))" + +#: ../../source/ref-changelog.md:779 +msgid "" +"And many more under-the-hood changes, library updates, documentation " +"changes, and tooling improvements!" +msgstr "" +"Et bien d'autres changements sous le capot, des mises à jour de la " +"bibliothèque, des modifications de la documentation et des améliorations " +"de l'outillage !" + +#: ../../source/ref-changelog.md:783 +msgid "" +"**Removed** `flwr_example` **and** `flwr_experimental` **from release " +"build** ([#869](https://github.com/adap/flower/pull/869))" +msgstr "" +"**Supprimé** `flwr_example` **et** `flwr_experimental` **de la version " +"release build** ([#869](https://github.com/adap/flower/pull/869))" + +#: ../../source/ref-changelog.md:785 +msgid "" +"The packages `flwr_example` and `flwr_experimental` have been deprecated " +"since Flower 0.12.0 and they are not longer included in Flower release " +"builds. The associated extras (`baseline`, `examples-pytorch`, `examples-" +"tensorflow`, `http-logger`, `ops`) are now no-op and will be removed in " +"an upcoming release." +msgstr "" +"Les paquets `flwr_example` et `flwr_experimental` ont été dépréciés " +"depuis Flower 0.12.0 et ils ne sont plus inclus dans les builds de " +"Flower. Les extras associés (`baseline`, `examples-pytorch`, `examples-" +"tensorflow`, `http-logger`, `ops`) sont maintenant no-op et seront " +"supprimés dans une prochaine version." + +#: ../../source/ref-changelog.md:787 +msgid "v0.17.0 (2021-09-24)" +msgstr "v0.17.0 (2021-09-24)" + +#: ../../source/ref-changelog.md:791 +msgid "" +"**Experimental virtual client engine** " +"([#781](https://github.com/adap/flower/pull/781) " +"[#790](https://github.com/adap/flower/pull/790) " +"[#791](https://github.com/adap/flower/pull/791))" +msgstr "" +"**Moteur expérimental de client virtuel** " +"([#781](https://github.com/adap/flower/pull/781) " +"[#790](https://github.com/adap/flower/pull/790) " +"[#791](https://github.com/adap/flower/pull/791))" + +#: ../../source/ref-changelog.md:793 +msgid "" +"One of Flower's goals is to enable research at scale. This release " +"enables a first (experimental) peek at a major new feature, codenamed the" +" virtual client engine. Virtual clients enable simulations that scale to " +"a (very) large number of clients on a single machine or compute cluster. " +"The easiest way to test the new functionality is to look at the two new " +"code examples called `quickstart_simulation` and `simulation_pytorch`." +msgstr "" +"L'un des objectifs de Flower est de permettre la recherche à grande " +"échelle. Cette version donne un premier aperçu (expérimental) d'une " +"nouvelle fonctionnalité majeure, connue sous le nom de code de moteur de " +"client virtuel. Les clients virtuels permettent des simulations qui " +"s'étendent à un (très) grand nombre de clients sur une seule machine ou " +"une grappe de calcul. La façon la plus simple de tester la nouvelle " +"fonctionnalité est de regarder les deux nouveaux exemples de code appelés" +" `quickstart_simulation` et `simulation_pytorch`." + +#: ../../source/ref-changelog.md:795 +msgid "" +"The feature is still experimental, so there's no stability guarantee for " +"the API. It's also not quite ready for prime time and comes with a few " +"known caveats. However, those who are curious are encouraged to try it " +"out and share their thoughts." +msgstr "" +"La fonction est encore expérimentale, il n'y a donc aucune garantie de " +"stabilité pour l'API. Elle n'est pas non plus tout à fait prête pour le " +"prime time et s'accompagne de quelques mises en garde connues. Cependant," +" les personnes curieuses sont encouragées à l'essayer et à faire part de " +"leurs réflexions." + +#: ../../source/ref-changelog.md:797 +msgid "" +"**New built-in strategies** " +"([#828](https://github.com/adap/flower/pull/828) " +"[#822](https://github.com/adap/flower/pull/822))" +msgstr "" +"**Nouvelles stratégies intégrées** " +"([#828](https://github.com/adap/flower/pull/828) " +"[#822](https://github.com/adap/flower/pull/822))" + +#: ../../source/ref-changelog.md:799 +msgid "" +"FedYogi - Federated learning strategy using Yogi on server-side. " +"Implementation based on https://arxiv.org/abs/2003.00295" +msgstr "" +"FedYogi - Stratégie d'apprentissage fédéré utilisant Yogi côté serveur. " +"Mise en oeuvre basée sur https://arxiv.org/abs/2003.00295" + +#: ../../source/ref-changelog.md:800 +msgid "" +"FedAdam - Federated learning strategy using Adam on server-side. " +"Implementation based on https://arxiv.org/abs/2003.00295" +msgstr "" +"FedAdam - Stratégie d'apprentissage fédéré utilisant Adam côté serveur. " +"Mise en œuvre basée sur https://arxiv.org/abs/2003.00295" + +#: ../../source/ref-changelog.md:802 +msgid "" +"**New PyTorch Lightning code example** " +"([#617](https://github.com/adap/flower/pull/617))" +msgstr "" +"**Nouvel exemple de code PyTorch Lightning** " +"([#617](https://github.com/adap/flower/pull/617))" + +#: ../../source/ref-changelog.md:804 +msgid "" +"**New Variational Auto-Encoder code example** " +"([#752](https://github.com/adap/flower/pull/752))" +msgstr "" +"**Nouvel exemple de code d'autocodage variationnel** " +"([#752](https://github.com/adap/flower/pull/752))" + +#: ../../source/ref-changelog.md:806 +msgid "" +"**New scikit-learn code example** " +"([#748](https://github.com/adap/flower/pull/748))" +msgstr "" +"**Nouvel exemple de code scikit-learn** " +"([#748](https://github.com/adap/flower/pull/748))" + +#: ../../source/ref-changelog.md:808 +msgid "" +"**New experimental TensorBoard strategy** " +"([#789](https://github.com/adap/flower/pull/789))" +msgstr "" +"**Nouvelle stratégie expérimentale TensorBoard** " +"([#789](https://github.com/adap/flower/pull/789))" + +#: ../../source/ref-changelog.md:812 +msgid "" +"Improved advanced TensorFlow code example " +"([#769](https://github.com/adap/flower/pull/769))" +msgstr "" +"Amélioration de l'exemple de code TensorFlow avancé " +"([#769](https://github.com/adap/flower/pull/769))" + +#: ../../source/ref-changelog.md:813 +msgid "" +"Warning when `min_available_clients` is misconfigured " +"([#830](https://github.com/adap/flower/pull/830))" +msgstr "" +"Avertissement lorsque `min_available_clients` est mal configuré " +"([#830](https://github.com/adap/flower/pull/830))" + +#: ../../source/ref-changelog.md:814 +msgid "" +"Improved gRPC server docs " +"([#841](https://github.com/adap/flower/pull/841))" +msgstr "" +"Amélioration de la documentation sur le serveur gRPC " +"([#841](https://github.com/adap/flower/pull/841))" + +#: ../../source/ref-changelog.md:815 +msgid "" +"Improved error message in `NumPyClient` " +"([#851](https://github.com/adap/flower/pull/851))" +msgstr "" +"Amélioration du message d'erreur dans `NumPyClient` " +"([#851](https://github.com/adap/flower/pull/851))" + +#: ../../source/ref-changelog.md:816 +msgid "" +"Improved PyTorch quickstart code example " +"([#852](https://github.com/adap/flower/pull/852))" +msgstr "" +"Exemple de code de démarrage rapide PyTorch amélioré " +"([#852](https://github.com/adap/flower/pull/852))" + +#: ../../source/ref-changelog.md:820 +msgid "" +"**Disabled final distributed evaluation** " +"([#800](https://github.com/adap/flower/pull/800))" +msgstr "" +"**Désactivé l'évaluation finale distribuée** " +"([#800](https://github.com/adap/flower/pull/800))" + +#: ../../source/ref-changelog.md:822 +msgid "" +"Prior behaviour was to perform a final round of distributed evaluation on" +" all connected clients, which is often not required (e.g., when using " +"server-side evaluation). The prior behaviour can be enabled by passing " +"`force_final_distributed_eval=True` to `start_server`." +msgstr "" +"Le comportement précédent consistait à effectuer un dernier tour " +"d'évaluation distribuée sur tous les clients connectés, ce qui n'est " +"souvent pas nécessaire (par exemple, lors de l'utilisation de " +"l'évaluation côté serveur). Le comportement précédent peut être activé en" +" passant `force_final_distributed_eval=True` à `start_server`." + +#: ../../source/ref-changelog.md:824 +msgid "" +"**Renamed q-FedAvg strategy** " +"([#802](https://github.com/adap/flower/pull/802))" +msgstr "" +"**Renommé stratégie q-FedAvg** " +"([#802](https://github.com/adap/flower/pull/802))" + +#: ../../source/ref-changelog.md:826 +msgid "" +"The strategy named `QffedAvg` was renamed to `QFedAvg` to better reflect " +"the notation given in the original paper (q-FFL is the optimization " +"objective, q-FedAvg is the proposed solver). Note the the original (now " +"deprecated) `QffedAvg` class is still available for compatibility reasons" +" (it will be removed in a future release)." +msgstr "" +"La stratégie nommée `QffedAvg` a été renommée en `QFedAvg` pour mieux " +"refléter la notation donnée dans l'article original (q-FFL est l'objectif" +" d'optimisation, q-FedAvg est le solveur proposé). Notez que la classe " +"`QffedAvg` originale (maintenant obsolète) est toujours disponible pour " +"des raisons de compatibilité (elle sera supprimée dans une prochaine " +"version)." + +#: ../../source/ref-changelog.md:828 +msgid "" +"**Deprecated and renamed code example** `simulation_pytorch` **to** " +"`simulation_pytorch_legacy` " +"([#791](https://github.com/adap/flower/pull/791))" +msgstr "" +"**Exemple de code déprécié et renommé** `simulation_pytorch` **en** " +"`simulation_pytorch_legacy` " +"([#791](https://github.com/adap/flower/pull/791))" + +#: ../../source/ref-changelog.md:830 +msgid "" +"This example has been replaced by a new example. The new example is based" +" on the experimental virtual client engine, which will become the new " +"default way of doing most types of large-scale simulations in Flower. The" +" existing example was kept for reference purposes, but it might be " +"removed in the future." +msgstr "" +"Cet exemple a été remplacé par un nouvel exemple. Le nouvel exemple est " +"basé sur le moteur expérimental du client virtuel, qui deviendra la " +"nouvelle méthode par défaut pour effectuer la plupart des types de " +"simulations à grande échelle dans Flower. L'exemple existant a été " +"conservé à des fins de référence, mais il pourrait être supprimé à " +"l'avenir." + +#: ../../source/ref-changelog.md:832 +msgid "v0.16.0 (2021-05-11)" +msgstr "v0.16.0 (2021-05-11)" + +#: ../../source/ref-changelog.md:836 +msgid "" +"**New built-in strategies** " +"([#549](https://github.com/adap/flower/pull/549))" +msgstr "" +"**Nouvelles stratégies intégrées** " +"([#549](https://github.com/adap/flower/pull/549))" + +#: ../../source/ref-changelog.md:838 +msgid "(abstract) FedOpt" +msgstr "(résumé) FedOpt" + +#: ../../source/ref-changelog.md:841 +msgid "" +"**Custom metrics for server and strategies** " +"([#717](https://github.com/adap/flower/pull/717))" +msgstr "" +"**Métriques personnalisées pour le serveur et les stratégies** " +"([#717](https://github.com/adap/flower/pull/717))" + +#: ../../source/ref-changelog.md:843 +msgid "" +"The Flower server is now fully task-agnostic, all remaining instances of " +"task-specific metrics (such as `accuracy`) have been replaced by custom " +"metrics dictionaries. Flower 0.15 introduced the capability to pass a " +"dictionary containing custom metrics from client to server. As of this " +"release, custom metrics replace task-specific metrics on the server." +msgstr "" +"Le serveur Flower est maintenant totalement agnostique, toutes les " +"instances restantes de métriques spécifiques à une tâche (telles que " +"`accuracy`) ont été remplacées par des dictionnaires de métriques " +"personnalisées. Flower 0.15 a introduit la possibilité de passer un " +"dictionnaire contenant des métriques personnalisées du client au serveur." +" À partir de cette version, les métriques personnalisées remplacent les " +"métriques spécifiques à une tâche sur le serveur." + +#: ../../source/ref-changelog.md:845 +msgid "" +"Custom metric dictionaries are now used in two user-facing APIs: they are" +" returned from Strategy methods `aggregate_fit`/`aggregate_evaluate` and " +"they enable evaluation functions passed to build-in strategies (via " +"`eval_fn`) to return more than two evaluation metrics. Strategies can " +"even return *aggregated* metrics dictionaries for the server to keep " +"track of." +msgstr "" +"Les dictionnaires de métriques personnalisés sont maintenant utilisés " +"dans deux API orientées vers l'utilisateur : ils sont renvoyés par les " +"méthodes de stratégie `aggregate_fit`/`aggregate_evaluate` et ils " +"permettent aux fonctions d'évaluation passées aux stratégies intégrées " +"(via `eval_fn`) de renvoyer plus de deux métriques d'évaluation. Les " +"stratégies peuvent même renvoyer des dictionnaires de métriques " +"*agrégées* pour que le serveur puisse en garder la trace." + +#: ../../source/ref-changelog.md:847 +msgid "" +"Stratey implementations should migrate their `aggregate_fit` and " +"`aggregate_evaluate` methods to the new return type (e.g., by simply " +"returning an empty `{}`), server-side evaluation functions should migrate" +" from `return loss, accuracy` to `return loss, {\"accuracy\": accuracy}`." +msgstr "" +"Les implémentations de Stratey doivent migrer leurs méthodes " +"`aggregate_fit` et `aggregate_evaluate` vers le nouveau type de retour " +"(par exemple, en renvoyant simplement un `{}` vide), les fonctions " +"d'évaluation côté serveur doivent migrer de `return loss, accuracy` à " +"`return loss, {\"accuracy\" : accuracy}`." + +#: ../../source/ref-changelog.md:849 +msgid "" +"Flower 0.15-style return types are deprecated (but still supported), " +"compatibility will be removed in a future release." +msgstr "" +"Les types de retour du style Flower 0.15 sont dépréciés (mais toujours " +"pris en charge), la compatibilité sera supprimée dans une prochaine " +"version." + +#: ../../source/ref-changelog.md:851 +msgid "" +"**Migration warnings for deprecated functionality** " +"([#690](https://github.com/adap/flower/pull/690))" +msgstr "" +"**Avertissements de migration pour les fonctionnalités obsolètes** " +"([#690](https://github.com/adap/flower/pull/690))" + +#: ../../source/ref-changelog.md:853 +msgid "" +"Earlier versions of Flower were often migrated to new APIs, while " +"maintaining compatibility with legacy APIs. This release introduces " +"detailed warning messages if usage of deprecated APIs is detected. The " +"new warning messages often provide details on how to migrate to more " +"recent APIs, thus easing the transition from one release to another." +msgstr "" +"Les versions antérieures de Flower ont souvent été migrées vers de " +"nouvelles API, tout en maintenant la compatibilité avec les anciennes " +"API. Cette version introduit des messages d'avertissement détaillés si " +"l'utilisation d'API obsolètes est détectée. Les nouveaux messages " +"d'avertissement fournissent souvent des détails sur la façon de migrer " +"vers des API plus récentes, facilitant ainsi la transition d'une version " +"à l'autre." + +#: ../../source/ref-changelog.md:855 +msgid "" +"Improved docs and docstrings " +"([#691](https://github.com/adap/flower/pull/691) " +"[#692](https://github.com/adap/flower/pull/692) " +"[#713](https://github.com/adap/flower/pull/713))" +msgstr "" +"Amélioration des docs et des docstrings " +"([#691](https://github.com/adap/flower/pull/691) " +"[#692](https://github.com/adap/flower/pull/692) " +"[#713](https://github.com/adap/flower/pull/713))" + +#: ../../source/ref-changelog.md:857 +msgid "MXNet example and documentation" +msgstr "Exemple et documentation MXNet" + +#: ../../source/ref-changelog.md:859 +msgid "" +"FedBN implementation in example PyTorch: From Centralized To Federated " +"([#696](https://github.com/adap/flower/pull/696) " +"[#702](https://github.com/adap/flower/pull/702) " +"[#705](https://github.com/adap/flower/pull/705))" +msgstr "" +"Mise en œuvre de FedBN dans l'exemple PyTorch : De la centralisation à la" +" fédération ([#696](https://github.com/adap/flower/pull/696) " +"[#702](https://github.com/adap/flower/pull/702) " +"[#705](https://github.com/adap/flower/pull/705))" + +#: ../../source/ref-changelog.md:863 +msgid "" +"**Serialization-agnostic server** " +"([#721](https://github.com/adap/flower/pull/721))" +msgstr "" +"**Serveur agnostique de sérialisation** " +"([#721](https://github.com/adap/flower/pull/721))" + +#: ../../source/ref-changelog.md:865 +msgid "" +"The Flower server is now fully serialization-agnostic. Prior usage of " +"class `Weights` (which represents parameters as deserialized NumPy " +"ndarrays) was replaced by class `Parameters` (e.g., in `Strategy`). " +"`Parameters` objects are fully serialization-agnostic and represents " +"parameters as byte arrays, the `tensor_type` attributes indicates how " +"these byte arrays should be interpreted (e.g., for " +"serialization/deserialization)." +msgstr "" +"Le serveur Flower est désormais totalement agnostique en matière de " +"sérialisation. L'utilisation antérieure de la classe `Weights` (qui " +"représente les paramètres sous forme de tableaux NumPy désérialisés) a " +"été remplacée par la classe `Parameters` (par exemple, dans `Strategy`). " +"Les objets `Parameters` sont totalement agnostiques en matière de " +"sérialisation et représentent les paramètres sous forme de tableaux " +"d'octets, les attributs `tensor_type` indiquent comment ces tableaux " +"d'octets doivent être interprétés (par exemple, pour la " +"sérialisation/désérialisation)." + +#: ../../source/ref-changelog.md:867 +msgid "" +"Built-in strategies implement this approach by handling serialization and" +" deserialization to/from `Weights` internally. Custom/3rd-party Strategy " +"implementations should update to the slighly changed Strategy method " +"definitions. Strategy authors can consult PR " +"[#721](https://github.com/adap/flower/pull/721) to see how strategies can" +" easily migrate to the new format." +msgstr "" +"Les stratégies intégrées mettent en œuvre cette approche en gérant en " +"interne la sérialisation et la désérialisation de `Weights`. Les " +"implémentations de stratégies personnalisées ou tierces doivent être " +"mises à jour avec les définitions de méthodes de stratégie légèrement " +"modifiées. Les auteurs de stratégies peuvent consulter le PR " +"[#721](https://github.com/adap/flower/pull/721) pour voir comment les " +"stratégies peuvent facilement migrer vers le nouveau format." + +#: ../../source/ref-changelog.md:869 +msgid "" +"Deprecated `flwr.server.Server.evaluate`, use " +"`flwr.server.Server.evaluate_round` instead " +"([#717](https://github.com/adap/flower/pull/717))" +msgstr "" +"Déclassé `flwr.server.Server.evaluate`, utiliser " +"`flwr.server.Server.evaluate_round` à la place " +"([#717](https://github.com/adap/flower/pull/717))" + +#: ../../source/ref-changelog.md:871 +msgid "v0.15.0 (2021-03-12)" +msgstr "v0.15.0 (2021-03-12)" + +#: ../../source/ref-changelog.md:875 +msgid "" +"**Server-side parameter initialization** " +"([#658](https://github.com/adap/flower/pull/658))" +msgstr "" +"**Initialisation des paramètres côté serveur** " +"([#658](https://github.com/adap/flower/pull/658))" + +#: ../../source/ref-changelog.md:877 +msgid "" +"Model parameters can now be initialized on the server-side. Server-side " +"parameter initialization works via a new `Strategy` method called " +"`initialize_parameters`." +msgstr "" +"Les paramètres du modèle peuvent maintenant être initialisés côté " +"serveur. L'initialisation des paramètres côté serveur fonctionne via une " +"nouvelle méthode `Strategy` appelée `initialize_parameters`." + +#: ../../source/ref-changelog.md:879 +msgid "" +"Built-in strategies support a new constructor argument called " +"`initial_parameters` to set the initial parameters. Built-in strategies " +"will provide these initial parameters to the server on startup and then " +"delete them to free the memory afterwards." +msgstr "" +"Les stratégies intégrées prennent en charge un nouvel argument du " +"constructeur appelé `initial_parameters` pour définir les paramètres " +"initiaux. Les stratégies intégrées fourniront ces paramètres initiaux au " +"serveur au démarrage et les supprimeront ensuite pour libérer la mémoire." + +#: ../../source/ref-changelog.md:898 +msgid "" +"If no initial parameters are provided to the strategy, the server will " +"continue to use the current behaviour (namely, it will ask one of the " +"connected clients for its parameters and use these as the initial global " +"parameters)." +msgstr "" +"Si aucun paramètre initial n'est fourni à la stratégie, le serveur " +"continuera à utiliser le comportement actuel (à savoir qu'il demandera à " +"l'un des clients connectés ses paramètres et les utilisera comme " +"paramètres globaux initiaux)." + +#: ../../source/ref-changelog.md:900 +msgid "Deprecations" +msgstr "Dépréciations" + +#: ../../source/ref-changelog.md:902 +msgid "" +"Deprecate `flwr.server.strategy.DefaultStrategy` (migrate to " +"`flwr.server.strategy.FedAvg`, which is equivalent)" +msgstr "" +"Déclasser `flwr.server.strategy.DefaultStrategy` (migrer vers " +"`flwr.server.strategy.FedAvg`, qui est équivalent)" + +#: ../../source/ref-changelog.md:904 +msgid "v0.14.0 (2021-02-18)" +msgstr "v0.14.0 (2021-02-18)" + +#: ../../source/ref-changelog.md:908 +msgid "" +"**Generalized** `Client.fit` **and** `Client.evaluate` **return values** " +"([#610](https://github.com/adap/flower/pull/610) " +"[#572](https://github.com/adap/flower/pull/572) " +"[#633](https://github.com/adap/flower/pull/633))" +msgstr "" +"**Généralisé** `Client.fit` **et** `Client.evaluate` **valeurs de " +"retour** ([#610](https://github.com/adap/flower/pull/610) " +"[#572](https://github.com/adap/flower/pull/572) " +"[#633](https://github.com/adap/flower/pull/633))" + +#: ../../source/ref-changelog.md:910 +msgid "" +"Clients can now return an additional dictionary mapping `str` keys to " +"values of the following types: `bool`, `bytes`, `float`, `int`, `str`. " +"This means one can return almost arbitrary values from `fit`/`evaluate` " +"and make use of them on the server side!" +msgstr "" +"Les clients peuvent maintenant renvoyer un dictionnaire supplémentaire " +"associant les clés `str` aux valeurs des types suivants : `bool`, " +"`bytes`, `float`, `int`, `str`. Cela signifie que l'on peut renvoyer des " +"valeurs presque arbitraires de `fit`/`evaluate` et les utiliser du côté " +"du serveur !" + +#: ../../source/ref-changelog.md:912 +msgid "" +"This improvement also allowed for more consistent return types between " +"`fit` and `evaluate`: `evaluate` should now return a tuple `(float, int, " +"dict)` representing the loss, number of examples, and a dictionary " +"holding arbitrary problem-specific values like accuracy." +msgstr "" +"Cette amélioration a également permis de rendre plus cohérents les types " +"de retour entre `fit` et `evaluate` : `evaluate` devrait maintenant " +"retourner un tuple `(float, int, dict)` représentant la perte, le nombre " +"d'exemples, et un dictionnaire contenant des valeurs arbitraires " +"spécifiques au problème comme la précision." + +#: ../../source/ref-changelog.md:914 +msgid "" +"In case you wondered: this feature is compatible with existing projects, " +"the additional dictionary return value is optional. New code should " +"however migrate to the new return types to be compatible with upcoming " +"Flower releases (`fit`: `List[np.ndarray], int, Dict[str, Scalar]`, " +"`evaluate`: `float, int, Dict[str, Scalar]`). See the example below for " +"details." +msgstr "" +"Au cas où tu te poserais la question : cette fonctionnalité est " +"compatible avec les projets existants, la valeur de retour supplémentaire" +" du dictionnaire est facultative. Le nouveau code doit cependant migrer " +"vers les nouveaux types de retour pour être compatible avec les " +"prochaines versions de Flower (`fit` : `List[np.ndarray], int, Dict[str, " +"Scalar]`, `evaluate` : `float, int, Dict[str, Scalar]`). Voir l'exemple " +"ci-dessous pour plus de détails." + +#: ../../source/ref-changelog.md:916 +msgid "" +"*Code example:* note the additional dictionary return values in both " +"`FlwrClient.fit` and `FlwrClient.evaluate`:" +msgstr "" +"*Exemple de code:* note les valeurs de retour du dictionnaire " +"supplémentaires dans `FlwrClient.fit` et `FlwrClient.evaluate` :" + +#: ../../source/ref-changelog.md:931 +msgid "" +"**Generalized** `config` **argument in** `Client.fit` **and** " +"`Client.evaluate` ([#595](https://github.com/adap/flower/pull/595))" +msgstr "" +"**Généralisé** `config` **argument dans** `Client.fit` **et** " +"`Client.evaluate` ([#595](https://github.com/adap/flower/pull/595))" + +#: ../../source/ref-changelog.md:933 +msgid "" +"The `config` argument used to be of type `Dict[str, str]`, which means " +"that dictionary values were expected to be strings. The new release " +"generalizes this to enable values of the following types: `bool`, " +"`bytes`, `float`, `int`, `str`." +msgstr "" +"L'argument `config` était auparavant de type `Dict[str, str]`, ce qui " +"signifie que les valeurs du dictionnaire devaient être des chaînes. La " +"nouvelle version généralise cela pour permettre les valeurs des types " +"suivants : `bool`, `bytes`, `float`, `int`, `str`." + +#: ../../source/ref-changelog.md:935 +msgid "" +"This means one can now pass almost arbitrary values to `fit`/`evaluate` " +"using the `config` dictionary. Yay, no more `str(epochs)` on the server-" +"side and `int(config[\"epochs\"])` on the client side!" +msgstr "" +"Cela signifie que l'on peut maintenant passer des valeurs presque " +"arbitraires à `fit`/`evaluate` en utilisant le dictionnaire `config`. " +"Yay, plus de `str(epochs)` du côté serveur et `int(config[\"epochs\"])` " +"du côté client !" + +#: ../../source/ref-changelog.md:937 +msgid "" +"*Code example:* note that the `config` dictionary now contains non-`str` " +"values in both `Client.fit` and `Client.evaluate`:" +msgstr "" +"*Exemple de code:* Notez que le dictionnaire `config` contient maintenant" +" des valeurs autres que `str` dans `Client.fit` et `Client.evaluate` :" + +#: ../../source/ref-changelog.md:954 +msgid "v0.13.0 (2021-01-08)" +msgstr "v0.13.0 (2021-01-08)" + +#: ../../source/ref-changelog.md:958 +msgid "" +"New example: PyTorch From Centralized To Federated " +"([#549](https://github.com/adap/flower/pull/549))" +msgstr "" +"Nouvel exemple : PyTorch de centralisé à fédéré " +"([#549](https://github.com/adap/flower/pull/549))" + +#: ../../source/ref-changelog.md:959 +msgid "Improved documentation" +msgstr "Amélioration de la documentation" + +#: ../../source/ref-changelog.md:960 +msgid "New documentation theme ([#551](https://github.com/adap/flower/pull/551))" +msgstr "" +"Nouveau thème de documentation " +"([#551](https://github.com/adap/flower/pull/551))" + +#: ../../source/ref-changelog.md:961 +msgid "New API reference ([#554](https://github.com/adap/flower/pull/554))" +msgstr "Nouvelle référence API ([#554](https://github.com/adap/flower/pull/554))" + +#: ../../source/ref-changelog.md:962 +msgid "" +"Updated examples documentation " +"([#549](https://github.com/adap/flower/pull/549))" +msgstr "" +"Mise à jour de la documentation des exemples " +"([#549](https://github.com/adap/flower/pull/549))" + +#: ../../source/ref-changelog.md:963 +msgid "" +"Removed obsolete documentation " +"([#548](https://github.com/adap/flower/pull/548))" +msgstr "" +"Suppression de la documentation obsolète " +"([#548](https://github.com/adap/flower/pull/548))" + +#: ../../source/ref-changelog.md:965 +msgid "Bugfix:" +msgstr "Correction de bogues :" + +#: ../../source/ref-changelog.md:967 +msgid "" +"`Server.fit` does not disconnect clients when finished, disconnecting the" +" clients is now handled in `flwr.server.start_server` " +"([#553](https://github.com/adap/flower/pull/553) " +"[#540](https://github.com/adap/flower/issues/540))." +msgstr "" +"`Server.fit` ne déconnecte pas les clients lorsqu'il est terminé, la " +"déconnexion des clients est maintenant gérée dans " +"`flwr.server.start_server` " +"([#553](https://github.com/adap/flower/pull/553) " +"[#540](https://github.com/adap/flower/issues/540))." + +#: ../../source/ref-changelog.md:969 +msgid "v0.12.0 (2020-12-07)" +msgstr "v0.12.0 (2020-12-07)" + +#: ../../source/ref-changelog.md:971 ../../source/ref-changelog.md:987 +msgid "Important changes:" +msgstr "Changements importants :" + +#: ../../source/ref-changelog.md:973 +msgid "" +"Added an example for embedded devices " +"([#507](https://github.com/adap/flower/pull/507))" +msgstr "" +"Ajout d'un exemple pour les périphériques embarqués " +"([#507](https://github.com/adap/flower/pull/507))" + +#: ../../source/ref-changelog.md:974 +msgid "" +"Added a new NumPyClient (in addition to the existing KerasClient) " +"([#504](https://github.com/adap/flower/pull/504) " +"[#508](https://github.com/adap/flower/pull/508))" +msgstr "" +"Ajout d'un nouveau NumPyClient (en plus du KerasClient existant) " +"([#504](https://github.com/adap/flower/pull/504) " +"[#508](https://github.com/adap/flower/pull/508))" + +#: ../../source/ref-changelog.md:975 +msgid "" +"Deprecated `flwr_example` package and started to migrate examples into " +"the top-level `examples` directory " +"([#494](https://github.com/adap/flower/pull/494) " +"[#512](https://github.com/adap/flower/pull/512))" +msgstr "" +"Déclassement du paquet `flwr_example` et migration des exemples dans le " +"répertoire de premier niveau `examples` " +"([#494](https://github.com/adap/flower/pull/494) " +"[#512](https://github.com/adap/flower/pull/512))" + +#: ../../source/ref-changelog.md:977 +msgid "v0.11.0 (2020-11-30)" +msgstr "v0.11.0 (2020-11-30)" + +#: ../../source/ref-changelog.md:979 +msgid "Incompatible changes:" +msgstr "Changements incompatibles :" + +#: ../../source/ref-changelog.md:981 +msgid "" +"Renamed strategy methods " +"([#486](https://github.com/adap/flower/pull/486)) to unify the naming of " +"Flower's public APIs. Other public methods/functions (e.g., every method " +"in `Client`, but also `Strategy.evaluate`) do not use the `on_` prefix, " +"which is why we're removing it from the four methods in Strategy. To " +"migrate rename the following `Strategy` methods accordingly:" +msgstr "" +"Renommé les méthodes de stratégie " +"([#486](https://github.com/adap/flower/pull/486)) pour unifier le nommage" +" des API publiques de Flower. D'autres méthodes/fonctions publiques (par " +"exemple, toutes les méthodes de `Client`, mais aussi `Strategy.evaluate`)" +" n'utilisent pas le préfixe `on_`, c'est pourquoi nous le supprimons des " +"quatre méthodes de Stratégie. Pour migrer, renommez les méthodes de " +"`Strategy` suivantes en conséquence :" + +#: ../../source/ref-changelog.md:982 +msgid "`on_configure_evaluate` => `configure_evaluate`" +msgstr "`on_configure_evaluate` => `configure_evaluate`" + +#: ../../source/ref-changelog.md:983 +msgid "`on_aggregate_evaluate` => `aggregate_evaluate`" +msgstr "`on_aggregate_evaluate` => `aggregate_evaluate`" + +#: ../../source/ref-changelog.md:984 +msgid "`on_configure_fit` => `configure_fit`" +msgstr "`on_configure_fit` => `configure_fit`" + +#: ../../source/ref-changelog.md:985 +msgid "`on_aggregate_fit` => `aggregate_fit`" +msgstr "`on_aggregate_fit` => `aggregate_fit`" + +#: ../../source/ref-changelog.md:989 +msgid "" +"Deprecated `DefaultStrategy` " +"([#479](https://github.com/adap/flower/pull/479)). To migrate use " +"`FedAvg` instead." +msgstr "" +"Déclassé `DefaultStrategy` " +"([#479](https://github.com/adap/flower/pull/479)). Pour migrer, utilisez " +"`FedAvg` à la place." + +#: ../../source/ref-changelog.md:990 +msgid "" +"Simplified examples and baselines " +"([#484](https://github.com/adap/flower/pull/484))." +msgstr "" +"Exemples simplifiés et lignes de base " +"([#484](https://github.com/adap/flower/pull/484))." + +#: ../../source/ref-changelog.md:991 +msgid "" +"Removed presently unused `on_conclude_round` from strategy interface " +"([#483](https://github.com/adap/flower/pull/483))." +msgstr "" +"Suppression de `on_conclude_round` actuellement inutilisé de l'interface " +"de stratégie ([#483](https://github.com/adap/flower/pull/483))." + +#: ../../source/ref-changelog.md:992 +msgid "" +"Set minimal Python version to 3.6.1 instead of 3.6.9 " +"([#471](https://github.com/adap/flower/pull/471))." +msgstr "" +"Fixe la version minimale de Python à 3.6.1 au lieu de 3.6.9 " +"([#471](https://github.com/adap/flower/pull/471))." + +#: ../../source/ref-changelog.md:993 +msgid "" +"Improved `Strategy` docstrings " +"([#470](https://github.com/adap/flower/pull/470))." +msgstr "" +"Amélioration des docstrings `Stratégie` " +"([#470](https://github.com/adap/flower/pull/470))." + +#: ../../source/ref-example-projects.rst:2 +#, fuzzy +msgid "Example projects" +msgstr "Exemples de PyTorch" + +#: ../../source/ref-example-projects.rst:4 +msgid "" +"Flower comes with a number of usage examples. The examples demonstrate " +"how Flower can be used to federate different kinds of existing machine " +"learning pipelines, usually leveraging popular machine learning " +"frameworks such as `PyTorch `_ or `TensorFlow " +"`_." +msgstr "" +"Flower est livré avec un certain nombre d'exemples d'utilisation, qui " +"montrent comment Flower peut être utilisé pour fédérer différents types " +"de pipelines d'apprentissage automatique existants, qui s'appuient " +"généralement sur des frameworks d'apprentissage automatique populaires " +"tels que `PyTorch `_ ou `TensorFlow " +"`_." + +#: ../../source/ref-example-projects.rst:11 +msgid "" +"Flower usage examples used to be bundled with Flower in a package called " +"``flwr_example``. We are migrating those examples to standalone projects " +"to make them easier to use. All new examples are based in the directory " +"`examples `_." +msgstr "" +"Les exemples d'utilisation de Flower étaient auparavant regroupés avec " +"Flower dans un paquet appelé ``flwr_example``. Nous migrons ces exemples " +"vers des projets autonomes pour les rendre plus faciles à utiliser. Tous " +"les nouveaux exemples sont basés dans le répertoire ``examples " +"`_." + +#: ../../source/ref-example-projects.rst:16 +msgid "The following examples are available as standalone projects." +msgstr "Les exemples suivants sont disponibles sous forme de projets autonomes." + +#: ../../source/ref-example-projects.rst:20 +msgid "Quickstart TensorFlow/Keras" +msgstr "Démarrage rapide de TensorFlow/Keras" + +#: ../../source/ref-example-projects.rst:22 +msgid "" +"The TensorFlow/Keras quickstart example shows CIFAR-10 image " +"classification with MobileNetV2:" +msgstr "" +"L'exemple de démarrage rapide TensorFlow/Keras montre la classification " +"d'images CIFAR-10 avec MobileNetV2 :" + +#: ../../source/ref-example-projects.rst:25 +#, fuzzy +msgid "" +"`Quickstart TensorFlow (Code) " +"`_" +msgstr "" +"`Quickstart TensorFlow (Code) " +"`_" + +#: ../../source/ref-example-projects.rst:26 +#, fuzzy +msgid "" +"`Quickstart TensorFlow (Tutorial) `_" +msgstr "" +"`Quickstart TensorFlow (Tutorial) `_" + +#: ../../source/ref-example-projects.rst:27 +msgid "" +"`Quickstart TensorFlow (Blog Post) `_" +msgstr "" +"`Quickstart TensorFlow (Blog Post) `_" + +#: ../../source/ref-example-projects.rst:31 +#: ../../source/tutorial-quickstart-pytorch.rst:5 +msgid "Quickstart PyTorch" +msgstr "Démarrage rapide de PyTorch" + +#: ../../source/ref-example-projects.rst:33 +msgid "" +"The PyTorch quickstart example shows CIFAR-10 image classification with a" +" simple Convolutional Neural Network:" +msgstr "" +"L'exemple de démarrage rapide PyTorch montre la classification d'images " +"CIFAR-10 avec un simple réseau neuronal convolutif :" + +#: ../../source/ref-example-projects.rst:36 +#, fuzzy +msgid "" +"`Quickstart PyTorch (Code) " +"`_" +msgstr "" +"`Quickstart PyTorch (Code) " +"`_" + +#: ../../source/ref-example-projects.rst:37 +#, fuzzy +msgid "" +"`Quickstart PyTorch (Tutorial) `_" +msgstr "" +"`Quickstart PyTorch (Tutorial) `_" + +#: ../../source/ref-example-projects.rst:41 +msgid "PyTorch: From Centralized To Federated" +msgstr "PyTorch : De la centralisation à la fédération" + +#: ../../source/ref-example-projects.rst:43 +msgid "" +"This example shows how a regular PyTorch project can be federated using " +"Flower:" +msgstr "" +"Cet exemple montre comment un projet PyTorch ordinaire peut être fédéré à" +" l'aide de Flower :" + +#: ../../source/ref-example-projects.rst:45 +#, fuzzy +msgid "" +"`PyTorch: From Centralized To Federated (Code) " +"`_" +msgstr "" +"`PyTorch : De la centralisation à la fédération (Code) " +"`_" + +#: ../../source/ref-example-projects.rst:46 +#, fuzzy +msgid "" +"`PyTorch: From Centralized To Federated (Tutorial) " +"`_" +msgstr "" +"`PyTorch : De la centralisation à la fédération (Tutoriel) " +"`_" + +#: ../../source/ref-example-projects.rst:50 +msgid "Federated Learning on Raspberry Pi and Nvidia Jetson" +msgstr "Apprentissage fédéré sur Raspberry Pi et Nvidia Jetson" + +#: ../../source/ref-example-projects.rst:52 +msgid "" +"This example shows how Flower can be used to build a federated learning " +"system that run across Raspberry Pi and Nvidia Jetson:" +msgstr "" +"Cet exemple montre comment Flower peut être utilisé pour construire un " +"système d'apprentissage fédéré qui fonctionne sur Raspberry Pi et Nvidia " +"Jetson :" + +#: ../../source/ref-example-projects.rst:54 +#, fuzzy +msgid "" +"`Federated Learning on Raspberry Pi and Nvidia Jetson (Code) " +"`_" +msgstr "" +"`L'apprentissage fédéré sur Raspberry Pi et Nvidia Jetson (Code) " +"`_" + +#: ../../source/ref-example-projects.rst:55 +msgid "" +"`Federated Learning on Raspberry Pi and Nvidia Jetson (Blog Post) " +"`_" +msgstr "" +"`L'apprentissage fédéré sur Raspberry Pi et Nvidia Jetson (Blog Post) " +"`_" + +#: ../../source/ref-example-projects.rst:60 +msgid "Legacy Examples (`flwr_example`)" +msgstr "Exemples hérités (`flwr_example`)" + +#: ../../source/ref-example-projects.rst:63 +msgid "" +"The useage examples in `flwr_example` are deprecated and will be removed " +"in the future. New examples are provided as standalone projects in " +"`examples `_." +msgstr "" +"Les exemples d'utilisation dans `flwr_example` sont obsolètes et seront " +"supprimés à l'avenir. De nouveaux exemples sont fournis en tant que " +"projets autonomes dans `examples " +"`_." + +#: ../../source/ref-example-projects.rst:69 +msgid "Extra Dependencies" +msgstr "Dépendances supplémentaires" + +#: ../../source/ref-example-projects.rst:71 +msgid "" +"The core Flower framework keeps a minimal set of dependencies. The " +"examples demonstrate Flower in the context of different machine learning " +"frameworks, so additional dependencies need to be installed before an " +"example can be run." +msgstr "" +"Le noyau du framework Flower conserve un ensemble minimal de dépendances." +" Les exemples démontrent Flower dans le contexte de différents frameworks" +" d'apprentissage automatique, de sorte que des dépendances " +"supplémentaires doivent être installées avant qu'un exemple puisse être " +"exécuté." + +#: ../../source/ref-example-projects.rst:75 +msgid "For PyTorch examples::" +msgstr "Pour les exemples de PyTorch: :" + +#: ../../source/ref-example-projects.rst:79 +msgid "For TensorFlow examples::" +msgstr "Pour les exemples de TensorFlow : :" + +#: ../../source/ref-example-projects.rst:83 +msgid "For both PyTorch and TensorFlow examples::" +msgstr "Pour les exemples PyTorch et TensorFlow: :" + +#: ../../source/ref-example-projects.rst:87 +msgid "" +"Please consult :code:`pyproject.toml` for a full list of possible extras " +"(section :code:`[tool.poetry.extras]`)." +msgstr "" +"Tu peux consulter :code:`pyproject.toml` pour une liste complète des " +"extras possibles (section :code:`[tool.poetry.extras]`)." + +#: ../../source/ref-example-projects.rst:92 +msgid "PyTorch Examples" +msgstr "Exemples de PyTorch" + +#: ../../source/ref-example-projects.rst:94 +msgid "" +"Our PyTorch examples are based on PyTorch 1.7. They should work with " +"other releases as well. So far, we provide the following examples." +msgstr "" +"Nos exemples PyTorch sont basés sur PyTorch 1.7. Ils devraient " +"fonctionner avec d'autres versions également. Jusqu'à présent, nous " +"fournissons les exemples suivants." + +#: ../../source/ref-example-projects.rst:98 +msgid "CIFAR-10 Image Classification" +msgstr "Classification d'images CIFAR-10" + +#: ../../source/ref-example-projects.rst:100 +msgid "" +"`CIFAR-10 and CIFAR-100 `_ " +"are popular RGB image datasets. The Flower CIFAR-10 example uses PyTorch " +"to train a simple CNN classifier in a federated learning setup with two " +"clients." +msgstr "" +"`CIFAR-10 et CIFAR-100 `_ " +"sont des ensembles de données d'images RVB populaires. L'exemple Flower " +"CIFAR-10 utilise PyTorch pour former un classificateur CNN simple dans " +"une configuration d'apprentissage fédéré avec deux clients." + +#: ../../source/ref-example-projects.rst:104 +#: ../../source/ref-example-projects.rst:121 +#: ../../source/ref-example-projects.rst:146 +msgid "First, start a Flower server:" +msgstr "Tout d'abord, démarre un serveur Flower :" + +#: ../../source/ref-example-projects.rst:106 +msgid "$ ./src/py/flwr_example/pytorch_cifar/run-server.sh" +msgstr "$ ./src/py/flwr_example/pytorch_cifar/run-server.sh" + +#: ../../source/ref-example-projects.rst:108 +#: ../../source/ref-example-projects.rst:125 +#: ../../source/ref-example-projects.rst:150 +msgid "Then, start the two clients in a new terminal window:" +msgstr "Ensuite, démarre les deux clients dans une nouvelle fenêtre de terminal :" + +#: ../../source/ref-example-projects.rst:110 +msgid "$ ./src/py/flwr_example/pytorch_cifar/run-clients.sh" +msgstr "$ ./src/py/flwr_example/pytorch_cifar/run-clients.sh" + +#: ../../source/ref-example-projects.rst:112 +msgid "For more details, see :code:`src/py/flwr_example/pytorch_cifar`." +msgstr "Pour plus de détails, voir :code:`src/py/flwr_example/pytorch_cifar`." + +#: ../../source/ref-example-projects.rst:115 +msgid "ImageNet-2012 Image Classification" +msgstr "ImageNet-2012 Classification des images" + +#: ../../source/ref-example-projects.rst:117 +msgid "" +"`ImageNet-2012 `_ is one of the major computer" +" vision datasets. The Flower ImageNet example uses PyTorch to train a " +"ResNet-18 classifier in a federated learning setup with ten clients." +msgstr "" +"`ImageNet-2012 `_ est l'un des principaux " +"ensembles de données de vision par ordinateur. L'exemple Flower ImageNet " +"utilise PyTorch pour entraîner un classificateur ResNet-18 dans une " +"configuration d'apprentissage fédéré avec dix clients." + +#: ../../source/ref-example-projects.rst:123 +msgid "$ ./src/py/flwr_example/pytorch_imagenet/run-server.sh" +msgstr "$ ./src/py/flwr_example/pytorch_imagenet/run-server.sh" + +#: ../../source/ref-example-projects.rst:127 +msgid "$ ./src/py/flwr_example/pytorch_imagenet/run-clients.sh" +msgstr "$ ./src/py/flwr_example/pytorch_imagenet/run-clients.sh" + +#: ../../source/ref-example-projects.rst:129 +msgid "For more details, see :code:`src/py/flwr_example/pytorch_imagenet`." +msgstr "Pour plus de détails, voir :code:`src/py/flwr_example/pytorch_imagenet`." + +#: ../../source/ref-example-projects.rst:133 +msgid "TensorFlow Examples" +msgstr "Exemples de TensorFlow" + +#: ../../source/ref-example-projects.rst:135 +msgid "" +"Our TensorFlow examples are based on TensorFlow 2.0 or newer. So far, we " +"provide the following examples." +msgstr "" +"Nos exemples TensorFlow sont basés sur TensorFlow 2.0 ou une version plus" +" récente. Jusqu'à présent, nous te proposons les exemples suivants." + +#: ../../source/ref-example-projects.rst:139 +msgid "Fashion-MNIST Image Classification" +msgstr "Classification d'images Fashion-MNIST" + +#: ../../source/ref-example-projects.rst:141 +msgid "" +"`Fashion-MNIST `_ is " +"often used as the \"Hello, world!\" of machine learning. We follow this " +"tradition and provide an example which samples random local datasets from" +" Fashion-MNIST and trains a simple image classification model over those " +"partitions." +msgstr "" +"nous suivons cette tradition et fournissons un exemple qui échantillonne " +"des ensembles de données locales aléatoires de Fashion-MNIST et entraîne " +"un modèle simple de classification d'images sur ces partitions." + +#: ../../source/ref-example-projects.rst:148 +msgid "$ ./src/py/flwr_example/tensorflow_fashion_mnist/run-server.sh" +msgstr "$ ./src/py/flwr_example/tensorflow_fashion_mnist/run-server.sh" + +#: ../../source/ref-example-projects.rst:152 +msgid "$ ./src/py/flwr_example/tensorflow_fashion_mnist/run-clients.sh" +msgstr "$ ./src/py/flwr_example/tensorflow_fashion_mnist/run-clients.sh" + +#: ../../source/ref-example-projects.rst:154 +msgid "" +"For more details, see " +":code:`src/py/flwr_example/tensorflow_fashion_mnist`." +msgstr "" +"Pour plus de détails, voir " +":code:`src/py/flwr_example/tensorflow_fashion_mnist`." + +#: ../../source/ref-faq.rst:4 +msgid "" +"This page collects answers to commonly asked questions about Federated " +"Learning with Flower." +msgstr "" +"Cette page rassemble les réponses aux questions les plus fréquemment " +"posées sur l'apprentissage fédéré avec Flower." + +#: ../../source/ref-faq.rst +msgid ":fa:`eye,mr-1` Can Flower run on Juptyter Notebooks / Google Colab?" +msgstr "" +":fa:`eye,mr-1` Flower peut-il fonctionner sur les ordinateurs portables " +"Juptyter / Google Colab ?" + +#: ../../source/ref-faq.rst:8 +msgid "" +"Yes, it can! Flower even comes with a few under-the-hood optimizations to" +" make it work even better on Colab. Here's a quickstart example:" +msgstr "" +"Oui, c'est possible ! Flower est même livré avec quelques optimisations " +"pour qu'il fonctionne encore mieux sur Colab. Voici un exemple de " +"démarrage rapide :" + +#: ../../source/ref-faq.rst:10 +#, fuzzy +msgid "" +"`Flower simulation PyTorch " +"`_" +msgstr "" +"`Flower Quickstart (TensorFlow/Keras) " +"`_" + +#: ../../source/ref-faq.rst:11 +#, fuzzy +msgid "" +"`Flower simulation TensorFlow/Keras " +"`_" +msgstr "" +"`Flower Quickstart (TensorFlow/Keras) " +"`_" + +#: ../../source/ref-faq.rst +msgid ":fa:`eye,mr-1` How can I run Federated Learning on a Raspberry Pi?" +msgstr "" +":fa:`eye,mr-1` Comment puis-je faire fonctionner l'apprentissage fédéré " +"sur un Raspberry Pi ?" + +#: ../../source/ref-faq.rst:15 +#, fuzzy +msgid "" +"Find the `blog post about federated learning on embedded device here " +"`_" +" and the corresponding `GitHub code example " +"`_." +msgstr "" +"Trouve le `blog post about federated learning on embedded device ici " +"`_" +" et l'exemple de code GitHub correspondant " +"`_." + +#: ../../source/ref-faq.rst +msgid ":fa:`eye,mr-1` Does Flower support federated learning on Android devices?" +msgstr "" +":fa:`eye,mr-1` Est-ce que Flower prend en charge l'apprentissage fédéré " +"sur les appareils Android ?" + +#: ../../source/ref-faq.rst:19 +#, fuzzy +msgid "" +"Yes, it does. Please take a look at our `blog post " +"`_ or check out the code examples:" +msgstr "" +"Oui. Jetez un coup d'œil à notre `blog post " +"`_ ou consultez l'`exemple de code Android sur GitHub" +" `_." + +#: ../../source/ref-faq.rst:21 +msgid "" +"`Android Kotlin example `_" +msgstr "" + +#: ../../source/ref-faq.rst:22 +msgid "`Android Java example `_" +msgstr "" + +#: ../../source/ref-faq.rst +msgid ":fa:`eye,mr-1` Can I combine federated learning with blockchain?" +msgstr "" +":fa:`eye,mr-1` Puis-je combiner l'apprentissage fédéré avec la blockchain" +" ?" + +#: ../../source/ref-faq.rst:26 +msgid "" +"Yes, of course. A list of available examples using Flower within a " +"blockchain environment is available here:" +msgstr "" +"Oui, bien sûr, une liste d'exemples disponibles utilisant Flower dans un " +"environnement blockchain est disponible ici :" + +#: ../../source/ref-faq.rst:28 +msgid "" +"`Flower meets Nevermined GitHub Repository `_." +msgstr "" +"`Flower meets Nevermined GitHub Repository `_." + +#: ../../source/ref-faq.rst:29 +msgid "" +"`Flower meets Nevermined YouTube video " +"`_." +msgstr "" +"`Flower rencontre Nevermined vidéo YouTube " +"`_." + +#: ../../source/ref-faq.rst:30 +msgid "" +"`Flower meets KOSMoS `_." +msgstr "" +"`Flower rencontre KOSMoS `_." + +#: ../../source/ref-faq.rst:31 +msgid "" +"`Flower meets Talan blog post `_ ." +msgstr "" +"`Flower meets Talan blog post `_ ." + +#: ../../source/ref-faq.rst:32 +msgid "" +"`Flower meets Talan GitHub Repository " +"`_ ." +msgstr "" +"`Flower rencontre Talan Dépôt GitHub " +"`_ ." + +#: ../../source/ref-telemetry.md:1 +msgid "Telemetry" +msgstr "Télémétrie" + +#: ../../source/ref-telemetry.md:3 +msgid "" +"The Flower open-source project collects **anonymous** usage metrics to " +"make well-informed decisions to improve Flower. Doing this enables the " +"Flower team to understand how Flower is used and what challenges users " +"might face." +msgstr "" +"Le projet open-source Flower recueille des mesures d'utilisation " +"**anonymes** afin de prendre des décisions éclairées pour améliorer " +"Flower. Cela permet à l'équipe de Flower de comprendre comment Flower est" +" utilisé et quels sont les défis auxquels les utilisateurs peuvent être " +"confrontés." + +#: ../../source/ref-telemetry.md:5 +msgid "" +"**Flower is a friendly framework for collaborative AI and data science.**" +" Staying true to this statement, Flower makes it easy to disable " +"telemetry for users that do not want to share anonymous usage metrics." +msgstr "" +"**Flower est un cadre convivial pour l'IA collaborative et la science des" +" données.** En restant fidèle à cette déclaration, Flower permet de " +"désactiver facilement la télémétrie pour les utilisateurs qui ne " +"souhaitent pas partager des mesures d'utilisation anonymes." + +#: ../../source/ref-telemetry.md:7 +msgid "Principles" +msgstr "Principes" + +#: ../../source/ref-telemetry.md:9 +msgid "We follow strong principles guarding anonymous usage metrics collection:" +msgstr "" +"Nous suivons des principes stricts concernant la collecte de données " +"anonymes sur l'utilisation :" + +#: ../../source/ref-telemetry.md:11 +msgid "" +"**Optional:** You will always be able to disable telemetry; read on to " +"learn “[How to opt-out](#how-to-opt-out)”." +msgstr "" +"**Optionnel:** Tu pourras toujours désactiver la télémétrie ; lis la " +"suite pour apprendre \"[Comment se désengager](#how-to-opt-out)\"." + +#: ../../source/ref-telemetry.md:12 +msgid "" +"**Anonymous:** The reported usage metrics are anonymous and do not " +"contain any personally identifiable information (PII). See “[Collected " +"metrics](#collected-metrics)” to understand what metrics are being " +"reported." +msgstr "" +"**Anonyme:** Les mesures d'utilisation rapportées sont anonymes et ne " +"contiennent aucune information personnelle identifiable (PII). Voir " +"\"[Collected metrics](#collected-metrics)\" pour comprendre quelles " +"mesures sont rapportées." + +#: ../../source/ref-telemetry.md:13 +msgid "" +"**Transparent:** You can easily inspect what anonymous metrics are being " +"reported; see the section “[How to inspect what is being reported](#how-" +"to-inspect-what-is-being-reported)”" +msgstr "" +"**Transparent:** Tu peux facilement inspecter les métriques anonymes qui " +"sont rapportées ; voir la section \"[Comment inspecter ce qui est " +"rapporté](#how-to-inspect-what-is-being-reported)\"" + +#: ../../source/ref-telemetry.md:14 +#, fuzzy +msgid "" +"**Open for feedback:** You can always reach out to us if you have " +"feedback; see the section “[How to contact us](#how-to-contact-us)” for " +"details." +msgstr "" +"**Ouvert pour les commentaires:** Tu peux toujours nous contacter si tu " +"as des commentaires ; voir la section \"[Comment nous contacter ](#how-" +"to-contact-us)\" pour plus de détails." + +#: ../../source/ref-telemetry.md:16 +msgid "How to opt-out" +msgstr "Comment se désinscrire" + +#: ../../source/ref-telemetry.md:18 +msgid "" +"When Flower starts, it will check for an environment variable called " +"`FLWR_TELEMETRY_ENABLED`. Telemetry can easily be disabled by setting " +"`FLWR_TELEMETRY_ENABLED=0`. Assuming you are starting a Flower server or " +"client, simply do so by prepending your command as in:" +msgstr "" +"Lorsque Flower démarre, il vérifie la présence d'une variable " +"d'environnement appelée `FLWR_TELEMETRY_ENABLED`. La télémétrie peut " +"facilement être désactivée en réglant `FLWR_TELEMETRY_ENABLED=0`. En " +"supposant que tu démarres un serveur ou un client Flower, fais-le " +"simplement en faisant précéder ta commande de la façon suivante :" + +#: ../../source/ref-telemetry.md:24 +msgid "" +"Alternatively, you can export `FLWR_TELEMETRY_ENABLED=0` in, for example," +" `.bashrc` (or whatever configuration file applies to your environment) " +"to disable Flower telemetry permanently." +msgstr "" +"Tu peux aussi exporter `FLWR_TELEMETRY_ENABLED=0` dans, par exemple, " +"`.bashrc` (ou tout autre fichier de configuration qui s'applique à ton " +"environnement) pour désactiver la télémétrie de la fleur de façon " +"permanente." + +#: ../../source/ref-telemetry.md:26 +msgid "Collected metrics" +msgstr "Mesures collectées" + +#: ../../source/ref-telemetry.md:28 +msgid "Flower telemetry collects the following metrics:" +msgstr "La télémétrie des fleurs recueille les métriques suivantes :" + +#: ../../source/ref-telemetry.md:30 +msgid "" +"**Flower version.** Understand which versions of Flower are currently " +"being used. This helps us to decide whether we should invest effort into " +"releasing a patch version for an older version of Flower or instead use " +"the bandwidth to build new features." +msgstr "" +"**Cela nous aide à décider si nous devons investir des efforts dans la " +"publication d'une version corrective pour une version plus ancienne de " +"Flower ou si nous devons plutôt utiliser la bande passante pour " +"développer de nouvelles fonctionnalités." + +#: ../../source/ref-telemetry.md:32 +msgid "" +"**Operating system.** Enables us to answer questions such as: *Should we " +"create more guides for Linux, macOS, or Windows?*" +msgstr "" +"**Système d'exploitation.** Nous permet de répondre à des questions " +"telles que : *Faudrait-il créer plus de guides pour Linux, macOS ou " +"Windows ?" + +#: ../../source/ref-telemetry.md:34 +msgid "" +"**Python version.** Knowing the Python version helps us, for example, to " +"decide whether we should invest effort into supporting old versions of " +"Python or stop supporting them and start taking advantage of new Python " +"features." +msgstr "" +"**Version de Python.** Connaître la version de Python nous aide, par " +"exemple, à décider si nous devons investir des efforts dans la prise en " +"charge des anciennes versions de Python ou cesser de les prendre en " +"charge et commencer à tirer parti des nouvelles fonctionnalités de " +"Python." + +#: ../../source/ref-telemetry.md:36 +msgid "" +"**Hardware properties.** Understanding the hardware environment that " +"Flower is being used in helps to decide whether we should, for example, " +"put more effort into supporting low-resource environments." +msgstr "" +"**Comprendre l'environnement matériel dans lequel Flower est utilisé " +"permet de décider si nous devrions, par exemple, faire plus d'efforts " +"pour prendre en charge les environnements à faibles ressources." + +#: ../../source/ref-telemetry.md:38 +msgid "" +"**Execution mode.** Knowing what execution mode Flower starts in enables " +"us to understand how heavily certain features are being used and better " +"prioritize based on that." +msgstr "" +"**Mode d'exécution** Connaître le mode d'exécution dans lequel Flower " +"démarre nous permet de comprendre à quel point certaines fonctionnalités " +"sont utilisées et de mieux établir les priorités en fonction de cela." + +#: ../../source/ref-telemetry.md:40 +msgid "" +"**Cluster.** Flower telemetry assigns a random in-memory cluster ID each " +"time a Flower workload starts. This allows us to understand which device " +"types not only start Flower workloads but also successfully complete " +"them." +msgstr "" +"**Cluster.** La télémétrie Flower attribue un ID de cluster en mémoire " +"aléatoire à chaque fois qu'une charge de travail Flower démarre. Cela " +"nous permet de comprendre quels types d'appareils non seulement démarrent" +" les charges de travail Flower, mais aussi les terminent avec succès." + +#: ../../source/ref-telemetry.md:42 +msgid "" +"**Source.** Flower telemetry tries to store a random source ID in " +"`~/.flwr/source` the first time a telemetry event is generated. The " +"source ID is important to identify whether an issue is recurring or " +"whether an issue is triggered by multiple clusters running concurrently " +"(which often happens in simulation). For example, if a device runs " +"multiple workloads at the same time, and this results in an issue, then, " +"in order to reproduce the issue, multiple workloads must be started at " +"the same time." +msgstr "" +"**Source.** La télémétrie de Flower essaie de stocker un ID de source " +"aléatoire dans `~/.flwr/source` la première fois qu'un événement de " +"télémétrie est généré. L'ID de source est important pour identifier si un" +" problème est récurrent ou si un problème est déclenché par plusieurs " +"clusters fonctionnant simultanément (ce qui arrive souvent en " +"simulation). Par exemple, si un périphérique exécute plusieurs charges de" +" travail en même temps, et que cela entraîne un problème, alors, afin de " +"reproduire le problème, plusieurs charges de travail doivent être " +"démarrées en même temps." + +#: ../../source/ref-telemetry.md:44 +msgid "" +"You may delete the source ID at any time. If you wish for all events " +"logged under a specific source ID to be deleted, you can send a deletion " +"request mentioning the source ID to `telemetry@flower.dev`. All events " +"related to that source ID will then be permanently deleted." +msgstr "" +"Tu peux supprimer l'identifiant de la source à tout moment. Si tu " +"souhaites que tous les événements enregistrés sous un identifiant de " +"source spécifique soient supprimés, tu peux envoyer une demande de " +"suppression mentionnant l'identifiant de source à `telemetry@flower.dev`." +" Tous les événements liés à cet identifiant de source seront alors " +"définitivement supprimés." + +#: ../../source/ref-telemetry.md:46 +msgid "" +"We will not collect any personally identifiable information. If you think" +" any of the metrics collected could be misused in any way, please [get in" +" touch with us](#how-to-contact-us). We will update this page to reflect " +"any changes to the metrics collected and publish changes in the " +"changelog." +msgstr "" +"Nous ne collecterons aucune information personnelle identifiable. Si tu " +"penses que l'une des métriques collectées pourrait être utilisée à " +"mauvais escient de quelque manière que ce soit, merci de [nous " +"contacter](#commentnouscontacter). Nous mettrons à jour cette page pour " +"refléter toute modification des métriques collectées et nous publierons " +"les changements dans le journal des modifications (changelog)." + +#: ../../source/ref-telemetry.md:48 +msgid "" +"If you think other metrics would be helpful for us to better guide our " +"decisions, please let us know! We will carefully review them; if we are " +"confident that they do not compromise user privacy, we may add them." +msgstr "" +"Si tu penses que d'autres mesures nous seraient utiles pour mieux " +"orienter nos décisions, fais-le nous savoir ! Nous les examinerons " +"attentivement ; si nous sommes convaincus qu'elles ne compromettent pas " +"la vie privée des utilisateurs, nous pourrons les ajouter." + +#: ../../source/ref-telemetry.md:50 +msgid "How to inspect what is being reported" +msgstr "Comment inspecter ce qui est rapporté" + +#: ../../source/ref-telemetry.md:52 +msgid "" +"We wanted to make it very easy for you to inspect what anonymous usage " +"metrics are reported. You can view all the reported telemetry information" +" by setting the environment variable `FLWR_TELEMETRY_LOGGING=1`. Logging " +"is disabled by default. You may use logging independently from " +"`FLWR_TELEMETRY_ENABLED` so that you can inspect the telemetry feature " +"without sending any metrics." +msgstr "" +"Nous avons voulu qu'il soit très facile pour toi d'inspecter les mesures " +"d'utilisation anonymes qui sont rapportées. Tu peux voir toutes les " +"informations de télémétrie rapportées en définissant la variable " +"d'environnement `FLWR_TELEMETRY_LOGGING=1`. La journalisation est " +"désactivée par défaut. Tu peux utiliser la journalisation indépendamment " +"de `FLWR_TELEMETRY_ENABLED` afin d'inspecter la fonction de télémétrie " +"sans envoyer de mesures." + +#: ../../source/ref-telemetry.md:58 +msgid "" +"The inspect Flower telemetry without sending any anonymous usage metrics," +" use both environment variables:" +msgstr "" +"L'inspecteur Flower telemetry sans envoyer de métriques d'utilisation " +"anonymes, utilise les deux variables d'environnement :" + +#: ../../source/ref-telemetry.md:64 +msgid "How to contact us" +msgstr "Comment nous contacter" + +#: ../../source/ref-telemetry.md:66 +msgid "" +"We want to hear from you. If you have any feedback or ideas on how to " +"improve the way we handle anonymous usage metrics, reach out to us via " +"[Slack](https://flower.dev/join-slack/) (channel `#telemetry`) or email " +"(`telemetry@flower.dev`)." +msgstr "" +"Si tu as des commentaires ou des idées pour améliorer la façon dont nous " +"traitons les mesures d'utilisation anonymes, contacte-nous via " +"[Slack](https://flower.dev/join-slack/) (canal `#telemetry`) ou par " +"courriel (`telemetry@flower.dev`)." + +#: ../../source/tutorial-quickstart-android.rst:-1 +msgid "" +"Read this Federated Learning quickstart tutorial for creating an Android " +"app using Flower." +msgstr "" + +#: ../../source/tutorial-quickstart-android.rst:5 +#, fuzzy +msgid "Quickstart Android" +msgstr "Démarrage rapide des Pandas" + +#: ../../source/tutorial-quickstart-android.rst:10 +#, fuzzy +msgid "" +"Let's build a federated learning system using TFLite and Flower on " +"Android!" +msgstr "" +"Construisons un système d'apprentissage fédéré en utilisant fastai et " +"Flower !" + +#: ../../source/tutorial-quickstart-android.rst:12 +#, fuzzy +msgid "" +"Please refer to the `full code example " +"`_ to learn " +"more." +msgstr "" +"Réfère-toi à l'exemple de code complet " +"`_ " +"pour en savoir plus." + +#: ../../source/tutorial-quickstart-fastai.rst:-1 +msgid "" +"Check out this Federated Learning quickstart tutorial for using Flower " +"with FastAI to train a vision model on CIFAR-10." +msgstr "" + +#: ../../source/tutorial-quickstart-fastai.rst:5 +msgid "Quickstart fastai" +msgstr "Démarrage rapide fastai" + +#: ../../source/tutorial-quickstart-fastai.rst:10 +msgid "Let's build a federated learning system using fastai and Flower!" +msgstr "" +"Construisons un système d'apprentissage fédéré en utilisant fastai et " +"Flower !" + +#: ../../source/tutorial-quickstart-fastai.rst:12 +#, fuzzy +msgid "" +"Please refer to the `full code example " +"`_ " +"to learn more." +msgstr "" +"Réfère-toi à l'exemple de code complet " +"`_ " +"pour en savoir plus." + +#: ../../source/tutorial-quickstart-huggingface.rst:-1 +msgid "" +"Check out this Federating Learning quickstart tutorial for using Flower " +"with HuggingFace Transformers in order to fine-tune an LLM." +msgstr "" + +#: ../../source/tutorial-quickstart-huggingface.rst:5 +msgid "Quickstart 🤗 Transformers" +msgstr "Démarrage rapide 🤗 Transformateurs" + +#: ../../source/tutorial-quickstart-huggingface.rst:10 +msgid "" +"Let's build a federated learning system using Hugging Face Transformers " +"and Flower!" +msgstr "" +"Construisons un système d'apprentissage fédéré à l'aide des " +"transformateurs Hugging Face et de Flower !" + +#: ../../source/tutorial-quickstart-huggingface.rst:12 +msgid "" +"We will leverage Hugging Face to federate the training of language models" +" over multiple clients using Flower. More specifically, we will fine-tune" +" a pre-trained Transformer model (distilBERT) for sequence classification" +" over a dataset of IMDB ratings. The end goal is to detect if a movie " +"rating is positive or negative." +msgstr "" +"Nous nous appuierons sur Hugging Face pour fédérer l'entraînement de " +"modèles de langage sur plusieurs clients à l'aide de Flower. Plus " +"précisément, nous mettrons au point un modèle Transformer pré-entraîné " +"(distilBERT) pour la classification de séquences sur un ensemble de " +"données d'évaluations IMDB. L'objectif final est de détecter si " +"l'évaluation d'un film est positive ou négative." + +#: ../../source/tutorial-quickstart-huggingface.rst:18 +msgid "Dependencies" +msgstr "Dépendances" + +#: ../../source/tutorial-quickstart-huggingface.rst:20 +msgid "" +"To follow along this tutorial you will need to install the following " +"packages: :code:`datasets`, :code:`evaluate`, :code:`flwr`, " +":code:`torch`, and :code:`transformers`. This can be done using " +":code:`pip`:" +msgstr "" +"Pour suivre ce tutoriel, tu devras installer les paquets suivants : " +":code:`datasets`, :code:`evaluate`, :code:`flwr`, :code:`torch`, et " +":code:`transformers`. Cela peut être fait en utilisant :code:`pip` :" + +#: ../../source/tutorial-quickstart-huggingface.rst:30 +msgid "Standard Hugging Face workflow" +msgstr "Flux de travail standard pour le visage" + +#: ../../source/tutorial-quickstart-huggingface.rst:33 +msgid "Handling the data" +msgstr "Traitement des données" + +#: ../../source/tutorial-quickstart-huggingface.rst:35 +msgid "" +"To fetch the IMDB dataset, we will use Hugging Face's :code:`datasets` " +"library. We then need to tokenize the data and create :code:`PyTorch` " +"dataloaders, this is all done in the :code:`load_data` function:" +msgstr "" +"Pour récupérer le jeu de données IMDB, nous utiliserons la bibliothèque " +":code:`datasets` de Hugging Face. Nous devons ensuite tokeniser les " +"données et créer des :code:`PyTorch` dataloaders, ce qui est fait dans la" +" fonction :code:`load_data` :" + +#: ../../source/tutorial-quickstart-huggingface.rst:81 +msgid "Training and testing the model" +msgstr "Former et tester le modèle" + +#: ../../source/tutorial-quickstart-huggingface.rst:83 +msgid "" +"Once we have a way of creating our trainloader and testloader, we can " +"take care of the training and testing. This is very similar to any " +":code:`PyTorch` training or testing loop:" +msgstr "" +"Une fois que nous avons trouvé un moyen de créer notre trainloader et " +"notre testloader, nous pouvons nous occuper de l'entraînement et du test." +" C'est très similaire à n'importe quelle boucle d'entraînement ou de test" +" :code:`PyTorch` :" + +#: ../../source/tutorial-quickstart-huggingface.rst:121 +msgid "Creating the model itself" +msgstr "Créer le modèle lui-même" + +#: ../../source/tutorial-quickstart-huggingface.rst:123 +msgid "" +"To create the model itself, we will just load the pre-trained distillBERT" +" model using Hugging Face’s :code:`AutoModelForSequenceClassification` :" +msgstr "" +"Pour créer le modèle lui-même, nous allons simplement charger le modèle " +"distillBERT pré-entraîné en utilisant le " +":code:`AutoModelForSequenceClassification` de Hugging Face :" + +#: ../../source/tutorial-quickstart-huggingface.rst:136 +msgid "Federating the example" +msgstr "Fédérer l'exemple" + +#: ../../source/tutorial-quickstart-huggingface.rst:139 +msgid "Creating the IMDBClient" +msgstr "Création du client IMDBC" + +#: ../../source/tutorial-quickstart-huggingface.rst:141 +msgid "" +"To federate our example to multiple clients, we first need to write our " +"Flower client class (inheriting from :code:`flwr.client.NumPyClient`). " +"This is very easy, as our model is a standard :code:`PyTorch` model:" +msgstr "" +"Pour fédérer notre exemple à plusieurs clients, nous devons d'abord " +"écrire notre classe de client Flower (héritant de " +":code:`flwr.client.NumPyClient`). C'est très facile, car notre modèle est" +" un modèle :code:`PyTorch` standard :" + +#: ../../source/tutorial-quickstart-huggingface.rst:169 +msgid "" +"The :code:`get_parameters` function lets the server get the client's " +"parameters. Inversely, the :code:`set_parameters` function allows the " +"server to send its parameters to the client. Finally, the :code:`fit` " +"function trains the model locally for the client, and the " +":code:`evaluate` function tests the model locally and returns the " +"relevant metrics." +msgstr "" +"La fonction :code:`get_parameters` permet au serveur d'obtenir les " +"paramètres du client. Inversement, la fonction :code:`set_parameters` " +"permet au serveur d'envoyer ses paramètres au client. Enfin, la fonction " +":code:`fit` forme le modèle localement pour le client, et la fonction " +":code:`evaluate` teste le modèle localement et renvoie les mesures " +"correspondantes." + +#: ../../source/tutorial-quickstart-huggingface.rst:175 +msgid "Starting the server" +msgstr "Démarrer le serveur" + +#: ../../source/tutorial-quickstart-huggingface.rst:177 +msgid "" +"Now that we have a way to instantiate clients, we need to create our " +"server in order to aggregate the results. Using Flower, this can be done " +"very easily by first choosing a strategy (here, we are using " +":code:`FedAvg`, which will define the global weights as the average of " +"all the clients' weights at each round) and then using the " +":code:`flwr.server.start_server` function:" +msgstr "" +"Maintenant que nous avons un moyen d'instancier les clients, nous devons " +"créer notre serveur afin d'agréger les résultats. Avec Flower, cela peut " +"être fait très facilement en choisissant d'abord une stratégie (ici, nous" +" utilisons :code:`FedAvg`, qui définira les poids globaux comme la " +"moyenne des poids de tous les clients à chaque tour) et en utilisant " +"ensuite la fonction :code:`flwr.server.start_server` :" + +#: ../../source/tutorial-quickstart-huggingface.rst:205 +msgid "" +"The :code:`weighted_average` function is there to provide a way to " +"aggregate the metrics distributed amongst the clients (basically this " +"allows us to display a nice average accuracy and loss for every round)." +msgstr "" +"La fonction :code:`weighted_average` est là pour fournir un moyen " +"d'agréger les mesures réparties entre les clients (en gros, cela nous " +"permet d'afficher une belle moyenne de précision et de perte pour chaque " +"tour)." + +#: ../../source/tutorial-quickstart-huggingface.rst:209 +msgid "Putting everything together" +msgstr "Tout assembler" + +#: ../../source/tutorial-quickstart-huggingface.rst:211 +msgid "We can now start client instances using:" +msgstr "Nous pouvons maintenant démarrer des instances de clients en utilisant :" + +#: ../../source/tutorial-quickstart-huggingface.rst:221 +msgid "" +"And they will be able to connect to the server and start the federated " +"training." +msgstr "Et ils pourront se connecter au serveur et démarrer la formation fédérée." + +#: ../../source/tutorial-quickstart-huggingface.rst:223 +#, fuzzy +msgid "" +"If you want to check out everything put together, you should check out " +"the full code example: [https://github.com/adap/flower/tree/main/examples" +"/quickstart-" +"huggingface](https://github.com/adap/flower/tree/main/examples" +"/quickstart-huggingface)." +msgstr "" +"Si tu veux voir tout ce qui est mis ensemble, tu devrais consulter " +"l'exemple de code complet : " +"[https://github.com/adap/flower/tree/main/examples/quickstart-" +"huggingface](https://github.com/adap/flower/tree/main/examples" +"/quickstart-huggingface)." + +#: ../../source/tutorial-quickstart-huggingface.rst:227 +msgid "" +"Of course, this is a very basic example, and a lot can be added or " +"modified, it was just to showcase how simply we could federate a Hugging " +"Face workflow using Flower." +msgstr "" +"Bien sûr, c'est un exemple très basique, et beaucoup de choses peuvent " +"être ajoutées ou modifiées, il s'agissait juste de montrer avec quelle " +"simplicité on pouvait fédérer un flux de travail Hugging Face à l'aide de" +" Flower." + +#: ../../source/tutorial-quickstart-huggingface.rst:230 +msgid "" +"Note that in this example we used :code:`PyTorch`, but we could have very" +" well used :code:`TensorFlow`." +msgstr "" +"Notez que dans cet exemple, nous avons utilisé :code:`PyTorch`, mais nous" +" aurions très bien pu utiliser :code:`TensorFlow`." + +#: ../../source/tutorial-quickstart-ios.rst:-1 +msgid "" +"Read this Federated Learning quickstart tutorial for creating an iOS app " +"using Flower to train a neural network on MNIST." +msgstr "" + +#: ../../source/tutorial-quickstart-ios.rst:5 +#, fuzzy +msgid "Quickstart iOS" +msgstr "Démarrage rapide XGBoost" + +#: ../../source/tutorial-quickstart-ios.rst:10 +#, fuzzy +msgid "" +"In this tutorial we will learn how to train a Neural Network on MNIST " +"using Flower and CoreML on iOS devices." +msgstr "" +"Dans ce tutoriel, nous allons apprendre, comment former un réseau " +"neuronal convolutif sur MNIST en utilisant Flower et PyTorch." + +#: ../../source/tutorial-quickstart-ios.rst:12 +#, fuzzy +msgid "" +"First of all, for running the Flower Python server, it is recommended to " +"create a virtual environment and run everything within a `virtualenv " +"`_. For the Flower " +"client implementation in iOS, it is recommended to use Xcode as our IDE." +msgstr "" +"Tout d'abord, il est recommandé de créer un environnement virtuel et de " +"tout exécuter au sein d'un `virtualenv `_." + +#: ../../source/tutorial-quickstart-ios.rst:15 +#, fuzzy +msgid "" +"Our example consists of one Python *server* and two iPhone *clients* that" +" all have the same model." +msgstr "" +"Notre exemple consiste en un *serveur* et deux *clients* ayant tous le " +"même modèle." + +#: ../../source/tutorial-quickstart-ios.rst:17 +#, fuzzy +msgid "" +"*Clients* are responsible for generating individual weight updates for " +"the model based on their local datasets. These updates are then sent to " +"the *server* which will aggregate them to produce a better model. " +"Finally, the *server* sends this improved version of the model back to " +"each *client*. A complete cycle of weight updates is called a *round*." +msgstr "" +"*Les clients* sont chargés de générer des mises à jour de poids " +"individuelles pour le modèle en fonction de leurs ensembles de données " +"locales. Ces mises à jour sont ensuite envoyées au *serveur* qui les " +"agrège pour produire un meilleur modèle. Enfin, le *serveur* renvoie " +"cette version améliorée du modèle à chaque *client*. Un cycle complet de " +"mises à jour de poids s'appelle un *round*." + +#: ../../source/tutorial-quickstart-ios.rst:21 +#, fuzzy +msgid "" +"Now that we have a rough idea of what is going on, let's get started to " +"setup our Flower server environment. We first need to install Flower. You" +" can do this by using pip:" +msgstr "" +"Maintenant que nous avons une idée générale de ce qui se passe, " +"commençons. Nous devons d'abord installer Flower. Tu peux le faire en " +"exécutant :" + +#: ../../source/tutorial-quickstart-ios.rst:27 +msgid "Or Poetry:" +msgstr "" + +#: ../../source/tutorial-quickstart-ios.rst:36 +msgid "" +"Now that we have all our dependencies installed, let's run a simple " +"distributed training using CoreML as our local training pipeline and " +"MNIST as our dataset. For simplicity reasons we will use the complete " +"Flower client with CoreML, that has been implemented and stored inside " +"the Swift SDK. The client implementation can be seen below:" +msgstr "" + +#: ../../source/tutorial-quickstart-ios.rst:72 +msgid "" +"Let's create a new application project in Xcode and add :code:`flwr` as a" +" dependency in your project. For our application, we will store the logic" +" of our app in :code:`FLiOSModel.swift` and the UI elements in " +":code:`ContentView.swift`. We will focus more on :code:`FLiOSModel.swift`" +" in this quickstart. Please refer to the `full code example " +"`_ to learn more " +"about the app." +msgstr "" + +#: ../../source/tutorial-quickstart-ios.rst:75 +msgid "Import Flower and CoreML related packages in :code:`FLiOSModel.swift`:" +msgstr "" + +#: ../../source/tutorial-quickstart-ios.rst:83 +msgid "" +"Then add the mlmodel to the project simply by drag-and-drop, the mlmodel " +"will be bundled inside the application during deployment to your iOS " +"device. We need to pass the url to access mlmodel and run CoreML machine " +"learning processes, it can be retrieved by calling the function " +":code:`Bundle.main.url`. For the MNIST dataset, we need to preprocess it " +"into :code:`MLBatchProvider` object. The preprocessing is done inside " +":code:`DataLoader.swift`." +msgstr "" + +#: ../../source/tutorial-quickstart-ios.rst:99 +msgid "" +"Since CoreML does not allow the model parameters to be seen before " +"training, and accessing the model parameters during or after the training" +" can only be done by specifying the layer name, we need to know this " +"informations beforehand, through looking at the model specification, " +"which are written as proto files. The implementation can be seen in " +":code:`MLModelInspect`." +msgstr "" + +#: ../../source/tutorial-quickstart-ios.rst:102 +msgid "" +"After we have all of the necessary informations, let's create our Flower " +"client." +msgstr "" + +#: ../../source/tutorial-quickstart-ios.rst:117 +msgid "" +"Then start the Flower gRPC client and start communicating to the server " +"by passing our Flower client to the function :code:`startFlwrGRPC`." +msgstr "" + +#: ../../source/tutorial-quickstart-ios.rst:124 +msgid "" +"That's it for the client. We only have to implement :code:`Client` or " +"call the provided :code:`MLFlwrClient` and call :code:`startFlwrGRPC()`. " +"The attribute :code:`hostname` and :code:`port` tells the client which " +"server to connect to. This can be done by entering the hostname and port " +"in the application before clicking the start button to start the " +"federated learning process." +msgstr "" + +#: ../../source/tutorial-quickstart-ios.rst:131 +#: ../../source/tutorial-quickstart-mxnet.rst:228 +#: ../../source/tutorial-quickstart-pytorch.rst:205 +#: ../../source/tutorial-quickstart-tensorflow.rst:100 +msgid "" +"For simple workloads we can start a Flower server and leave all the " +"configuration possibilities at their default values. In a file named " +":code:`server.py`, import Flower and start the server:" +msgstr "" +"Pour les charges de travail simples, nous pouvons démarrer un serveur " +"Flower et laisser toutes les possibilités de configuration à leurs " +"valeurs par défaut. Dans un fichier nommé :code:`server.py`, importe " +"Flower et démarre le serveur :" + +#: ../../source/tutorial-quickstart-ios.rst:142 +#: ../../source/tutorial-quickstart-mxnet.rst:239 +#: ../../source/tutorial-quickstart-pytorch.rst:216 +#: ../../source/tutorial-quickstart-scikitlearn.rst:215 +#: ../../source/tutorial-quickstart-tensorflow.rst:112 +msgid "Train the model, federated!" +msgstr "Entraîne le modèle, fédéré !" + +#: ../../source/tutorial-quickstart-ios.rst:144 +#: ../../source/tutorial-quickstart-pytorch.rst:218 +#: ../../source/tutorial-quickstart-tensorflow.rst:114 +#: ../../source/tutorial-quickstart-xgboost.rst:525 +msgid "" +"With both client and server ready, we can now run everything and see " +"federated learning in action. FL systems usually have a server and " +"multiple clients. We therefore have to start the server first:" +msgstr "" +"Le client et le serveur étant prêts, nous pouvons maintenant tout " +"exécuter et voir l'apprentissage fédéré en action. Les systèmes FL ont " +"généralement un serveur et plusieurs clients. Nous devons donc commencer " +"par démarrer le serveur :" + +#: ../../source/tutorial-quickstart-ios.rst:152 +msgid "" +"Once the server is running we can start the clients in different " +"terminals. Build and run the client through your Xcode, one through Xcode" +" Simulator and the other by deploying it to your iPhone. To see more " +"about how to deploy your app to iPhone or Simulator visit `here " +"`_." +msgstr "" + +#: ../../source/tutorial-quickstart-ios.rst:156 +#, fuzzy +msgid "" +"Congratulations! You've successfully built and run your first federated " +"learning system in your ios device. The full `source code " +"`_ for this " +"example can be found in :code:`examples/ios`." +msgstr "" +"Félicitations ! Tu as réussi à construire et à faire fonctionner ton " +"premier système d'apprentissage fédéré. Le code source complet " +"`_ de cet exemple se trouve dans :code:`examples" +"/quickstart-mxnet`." + +#: ../../source/tutorial-quickstart-jax.rst:-1 +msgid "" +"Check out this Federated Learning quickstart tutorial for using Flower " +"with Jax to train a linear regression model on a scikit-learn dataset." +msgstr "" + +#: ../../source/tutorial-quickstart-jax.rst:5 +msgid "Quickstart JAX" +msgstr "Démarrage rapide de JAX" + +#: ../../source/tutorial-quickstart-mxnet.rst:-1 +msgid "" +"Check out this Federated Learning quickstart tutorial for using Flower " +"with MXNet to train a Sequential model on MNIST." +msgstr "" + +#: ../../source/tutorial-quickstart-mxnet.rst:5 +msgid "Quickstart MXNet" +msgstr "Démarrage rapide de MXNet" + +#: ../../source/tutorial-quickstart-mxnet.rst:7 +msgid "" +"MXNet is no longer maintained and has been moved into `Attic " +"`_. As a result, we would " +"encourage you to use other ML frameworks alongise Flower, for example, " +"PyTorch. This tutorial might be removed in future versions of Flower." +msgstr "" + +#: ../../source/tutorial-quickstart-mxnet.rst:12 +msgid "" +"In this tutorial, we will learn how to train a :code:`Sequential` model " +"on MNIST using Flower and MXNet." +msgstr "" +"Dans ce tutoriel, nous allons apprendre à former un modèle " +":code:`Sequential` sur MNIST à l'aide de Flower et de MXNet." + +#: ../../source/tutorial-quickstart-mxnet.rst:14 +#: ../../source/tutorial-quickstart-scikitlearn.rst:12 +msgid "" +"It is recommended to create a virtual environment and run everything " +"within this `virtualenv `_." +msgstr "" +"Il est recommandé de créer un environnement virtuel et de tout exécuter " +"dans ce `virtualenv `_." + +#: ../../source/tutorial-quickstart-mxnet.rst:18 +#: ../../source/tutorial-quickstart-scikitlearn.rst:16 +msgid "" +"*Clients* are responsible for generating individual model parameter " +"updates for the model based on their local datasets. These updates are " +"then sent to the *server* which will aggregate them to produce an updated" +" global model. Finally, the *server* sends this improved version of the " +"model back to each *client*. A complete cycle of parameters updates is " +"called a *round*." +msgstr "" +"*Les clients* sont chargés de générer des mises à jour individuelles des " +"paramètres du modèle en fonction de leurs ensembles de données locales. " +"Ces mises à jour sont ensuite envoyées au *serveur* qui les agrège pour " +"produire un modèle global mis à jour. Enfin, le *serveur* renvoie cette " +"version améliorée du modèle à chaque *client*. Un cycle complet de mises " +"à jour des paramètres s'appelle un *round*." + +#: ../../source/tutorial-quickstart-mxnet.rst:22 +#: ../../source/tutorial-quickstart-scikitlearn.rst:20 +msgid "" +"Now that we have a rough idea of what is going on, let's get started. We " +"first need to install Flower. You can do this by running:" +msgstr "" +"Maintenant que nous avons une idée approximative de ce qui se passe, " +"commençons. Nous devons d'abord installer Flower. Tu peux le faire en " +"lançant :" + +#: ../../source/tutorial-quickstart-mxnet.rst:28 +msgid "Since we want to use MXNet, let's go ahead and install it:" +msgstr "Puisque nous voulons utiliser MXNet, allons-y et installons-le :" + +#: ../../source/tutorial-quickstart-mxnet.rst:38 +msgid "" +"Now that we have all our dependencies installed, let's run a simple " +"distributed training with two clients and one server. Our training " +"procedure and network architecture are based on MXNet´s `Hand-written " +"Digit Recognition tutorial " +"`_." +msgstr "" +"Maintenant que toutes nos dépendances sont installées, lançons une " +"formation distribuée simple avec deux clients et un serveur. Notre " +"procédure de formation et l'architecture du réseau sont basées sur le " +"tutoriel de reconnaissance de chiffres écrits à la main du MXNet " +"`_." + +#: ../../source/tutorial-quickstart-mxnet.rst:40 +msgid "" +"In a file called :code:`client.py`, import Flower and MXNet related " +"packages:" +msgstr "" +"Dans un fichier appelé :code:`client.py`, importe Flower et les paquets " +"liés au MXNet :" + +#: ../../source/tutorial-quickstart-mxnet.rst:55 +msgid "In addition, define the device allocation in MXNet with:" +msgstr "En outre, définis l'attribution de l'appareil dans MXNet avec :" + +#: ../../source/tutorial-quickstart-mxnet.rst:61 +msgid "" +"We use MXNet to load MNIST, a popular image classification dataset of " +"handwritten digits for machine learning. The MXNet utility " +":code:`mx.test_utils.get_mnist()` downloads the training and test data." +msgstr "" +"Nous utilisons MXNet pour charger MNIST, un ensemble de données de " +"classification d'images populaire de chiffres manuscrits pour " +"l'apprentissage automatique. L'utilitaire MXNet " +":code:`mx.test_utils.get_mnist()` télécharge les données d'entraînement " +"et de test." + +#: ../../source/tutorial-quickstart-mxnet.rst:75 +msgid "" +"Define the training and loss with MXNet. We train the model by looping " +"over the dataset, measure the corresponding loss, and optimize it." +msgstr "" +"Définis l'entraînement et la perte avec MXNet. Nous entraînons le modèle " +"en parcourant en boucle l'ensemble des données, nous mesurons la perte " +"correspondante et nous l'optimisons." + +#: ../../source/tutorial-quickstart-mxnet.rst:113 +msgid "" +"Next, we define the validation of our machine learning model. We loop " +"over the test set and measure both loss and accuracy on the test set." +msgstr "" +"Ensuite, nous définissons la validation de notre modèle d'apprentissage " +"automatique. Nous effectuons une boucle sur l'ensemble de test et " +"mesurons à la fois la perte et la précision sur l'ensemble de test." + +#: ../../source/tutorial-quickstart-mxnet.rst:137 +msgid "" +"After defining the training and testing of a MXNet machine learning " +"model, we use these functions to implement a Flower client." +msgstr "" +"Après avoir défini la formation et le test d'un modèle d'apprentissage " +"automatique MXNet, nous utilisons ces fonctions pour mettre en œuvre un " +"client Flower." + +#: ../../source/tutorial-quickstart-mxnet.rst:139 +msgid "Our Flower clients will use a simple :code:`Sequential` model:" +msgstr "Nos clients Flower utiliseront un modèle simple :code:`Sequential` :" + +#: ../../source/tutorial-quickstart-mxnet.rst:158 +msgid "" +"After loading the dataset with :code:`load_data()` we perform one forward" +" propagation to initialize the model and model parameters with " +":code:`model(init)`. Next, we implement a Flower client." +msgstr "" +"Après avoir chargé l'ensemble de données avec :code:`load_data()`, nous " +"effectuons une propagation vers l'avant pour initialiser le modèle et les" +" paramètres du modèle avec :code:`model(init)`. Ensuite, nous " +"implémentons un client Flower." + +#: ../../source/tutorial-quickstart-mxnet.rst:160 +#: ../../source/tutorial-quickstart-pytorch.rst:144 +#: ../../source/tutorial-quickstart-tensorflow.rst:54 +msgid "" +"The Flower server interacts with clients through an interface called " +":code:`Client`. When the server selects a particular client for training," +" it sends training instructions over the network. The client receives " +"those instructions and calls one of the :code:`Client` methods to run " +"your code (i.e., to train the neural network we defined earlier)." +msgstr "" +"Le serveur Flower interagit avec les clients par le biais d'une interface" +" appelée :code:`Client`. Lorsque le serveur sélectionne un client " +"particulier pour la formation, il envoie des instructions de formation " +"sur le réseau. Le client reçoit ces instructions et appelle l'une des " +"méthodes :code:`Client` pour exécuter ton code (c'est-à-dire pour former " +"le réseau neuronal que nous avons défini plus tôt)." + +#: ../../source/tutorial-quickstart-mxnet.rst:166 +msgid "" +"Flower provides a convenience class called :code:`NumPyClient` which " +"makes it easier to implement the :code:`Client` interface when your " +"workload uses MXNet. Implementing :code:`NumPyClient` usually means " +"defining the following methods (:code:`set_parameters` is optional " +"though):" +msgstr "" +"Flower fournit une classe de commodité appelée :code:`NumPyClient` qui " +"facilite l'implémentation de l'interface :code:`Client` lorsque ta charge" +" de travail utilise MXNet. L'implémentation de :code:`NumPyClient` " +"signifie généralement la définition des méthodes suivantes " +"(:code:`set_parameters` est cependant facultatif) :" + +#: ../../source/tutorial-quickstart-mxnet.rst:172 +#: ../../source/tutorial-quickstart-pytorch.rst:156 +#: ../../source/tutorial-quickstart-scikitlearn.rst:109 +msgid "return the model weight as a list of NumPy ndarrays" +msgstr "renvoie le poids du modèle sous la forme d'une liste de ndarrays NumPy" + +#: ../../source/tutorial-quickstart-mxnet.rst:173 +#: ../../source/tutorial-quickstart-pytorch.rst:157 +#: ../../source/tutorial-quickstart-scikitlearn.rst:111 +msgid ":code:`set_parameters` (optional)" +msgstr ":code:`set_parameters` (optionnel)" + +#: ../../source/tutorial-quickstart-mxnet.rst:174 +#: ../../source/tutorial-quickstart-pytorch.rst:158 +#: ../../source/tutorial-quickstart-scikitlearn.rst:111 +msgid "" +"update the local model weights with the parameters received from the " +"server" +msgstr "" +"mettre à jour les poids du modèle local avec les paramètres reçus du " +"serveur" + +#: ../../source/tutorial-quickstart-mxnet.rst:176 +#: ../../source/tutorial-quickstart-pytorch.rst:160 +#: ../../source/tutorial-quickstart-scikitlearn.rst:114 +msgid "set the local model weights" +msgstr "fixe les poids du modèle local" + +#: ../../source/tutorial-quickstart-mxnet.rst:177 +#: ../../source/tutorial-quickstart-pytorch.rst:161 +#: ../../source/tutorial-quickstart-scikitlearn.rst:115 +msgid "train the local model" +msgstr "entraîne le modèle local" + +#: ../../source/tutorial-quickstart-mxnet.rst:178 +#: ../../source/tutorial-quickstart-pytorch.rst:162 +#: ../../source/tutorial-quickstart-scikitlearn.rst:116 +msgid "receive the updated local model weights" +msgstr "recevoir les poids du modèle local mis à jour" + +#: ../../source/tutorial-quickstart-mxnet.rst:180 +#: ../../source/tutorial-quickstart-pytorch.rst:164 +#: ../../source/tutorial-quickstart-scikitlearn.rst:118 +msgid "test the local model" +msgstr "teste le modèle local" + +#: ../../source/tutorial-quickstart-mxnet.rst:182 +msgid "They can be implemented in the following way:" +msgstr "Ils peuvent être mis en œuvre de la manière suivante :" + +#: ../../source/tutorial-quickstart-mxnet.rst:212 +msgid "" +"We can now create an instance of our class :code:`MNISTClient` and add " +"one line to actually run this client:" +msgstr "" +"Nous pouvons maintenant créer une instance de notre classe " +":code:`MNISTClient` et ajouter une ligne pour exécuter ce client :" + +#: ../../source/tutorial-quickstart-mxnet.rst:219 +#, fuzzy +msgid "" +"That's it for the client. We only have to implement :code:`Client` or " +":code:`NumPyClient` and call :code:`fl.client.start_client()` or " +":code:`fl.client.start_numpy_client()`. The string " +":code:`\"0.0.0.0:8080\"` tells the client which server to connect to. In " +"our case we can run the server and the client on the same machine, " +"therefore we use :code:`\"0.0.0.0:8080\"`. If we run a truly federated " +"workload with the server and clients running on different machines, all " +"that needs to change is the :code:`server_address` we pass to the client." +msgstr "" +"C'est tout pour le client. Il nous suffit d'implémenter :code:`Client` ou" +" :code:`NumPyClient` et d'appeler :code:`fl.client.start_client()`. La " +"chaîne :code:`\"0.0.0:8080\"` indique au client à quel serveur se " +"connecter. Dans notre cas, nous pouvons exécuter le serveur et le client " +"sur la même machine, c'est pourquoi nous utilisons " +":code:`\"0.0.0:8080\"`. Si nous exécutons une charge de travail " +"véritablement fédérée avec le serveur et les clients s'exécutant sur des " +"machines différentes, tout ce qui doit changer est :code:`server_address`" +" que nous transmettons au client." + +#: ../../source/tutorial-quickstart-mxnet.rst:241 +msgid "" +"With both client and server ready, we can now run everything and see " +"federated learning in action. Federated learning systems usually have a " +"server and multiple clients. We therefore have to start the server first:" +msgstr "" +"Le client et le serveur étant prêts, nous pouvons maintenant tout " +"exécuter et voir l'apprentissage fédéré en action. Les systèmes " +"d'apprentissage fédéré ont généralement un serveur et plusieurs clients. " +"Nous devons donc commencer par démarrer le serveur :" + +#: ../../source/tutorial-quickstart-mxnet.rst:249 +#: ../../source/tutorial-quickstart-pytorch.rst:226 +#: ../../source/tutorial-quickstart-scikitlearn.rst:224 +#: ../../source/tutorial-quickstart-tensorflow.rst:122 +#: ../../source/tutorial-quickstart-xgboost.rst:533 +msgid "" +"Once the server is running we can start the clients in different " +"terminals. Open a new terminal and start the first client:" +msgstr "" +"Une fois que le serveur fonctionne, nous pouvons démarrer les clients " +"dans différents terminaux. Ouvre un nouveau terminal et démarre le " +"premier client :" + +#: ../../source/tutorial-quickstart-mxnet.rst:256 +#: ../../source/tutorial-quickstart-pytorch.rst:233 +#: ../../source/tutorial-quickstart-scikitlearn.rst:231 +#: ../../source/tutorial-quickstart-tensorflow.rst:129 +#: ../../source/tutorial-quickstart-xgboost.rst:540 +msgid "Open another terminal and start the second client:" +msgstr "Ouvre un autre terminal et démarre le deuxième client :" + +#: ../../source/tutorial-quickstart-mxnet.rst:262 +#: ../../source/tutorial-quickstart-pytorch.rst:239 +#: ../../source/tutorial-quickstart-scikitlearn.rst:237 +#: ../../source/tutorial-quickstart-xgboost.rst:546 +msgid "" +"Each client will have its own dataset. You should now see how the " +"training does in the very first terminal (the one that started the " +"server):" +msgstr "" +"Chaque client aura son propre ensemble de données. Tu devrais maintenant " +"voir comment la formation se déroule dans le tout premier terminal (celui" +" qui a démarré le serveur) :" + +#: ../../source/tutorial-quickstart-mxnet.rst:294 +#, fuzzy +msgid "" +"Congratulations! You've successfully built and run your first federated " +"learning system. The full `source code " +"`_ for this example can be found in :code:`examples" +"/quickstart-mxnet`." +msgstr "" +"Félicitations ! Tu as réussi à construire et à faire fonctionner ton " +"premier système d'apprentissage fédéré. Le code source complet " +"`_ de cet exemple se trouve dans :code:`examples" +"/quickstart-mxnet`." + +#: ../../source/tutorial-quickstart-pandas.rst:-1 +msgid "" +"Check out this Federated Learning quickstart tutorial for using Flower " +"with Pandas to perform Federated Analytics." +msgstr "" + +#: ../../source/tutorial-quickstart-pandas.rst:5 +msgid "Quickstart Pandas" +msgstr "Démarrage rapide des Pandas" + +#: ../../source/tutorial-quickstart-pandas.rst:10 +msgid "Let's build a federated analytics system using Pandas and Flower!" +msgstr "Construisons un système d'analyse fédéré à l'aide de Pandas et de Flower !" + +#: ../../source/tutorial-quickstart-pandas.rst:12 +#, fuzzy +msgid "" +"Please refer to the `full code example " +"`_ " +"to learn more." +msgstr "" +"Réfère-toi à l'exemple de code complet " +"`_ " +"pour en savoir plus." + +#: ../../source/tutorial-quickstart-pytorch.rst:-1 +msgid "" +"Check out this Federated Learning quickstart tutorial for using Flower " +"with PyTorch to train a CNN model on MNIST." +msgstr "" + +#: ../../source/tutorial-quickstart-pytorch.rst:13 +msgid "" +"In this tutorial we will learn how to train a Convolutional Neural " +"Network on CIFAR10 using Flower and PyTorch." +msgstr "" +"Dans ce tutoriel, nous allons apprendre à entraîner un réseau neuronal " +"convolutif sur CIFAR10 à l'aide de Flower et PyTorch." + +#: ../../source/tutorial-quickstart-pytorch.rst:15 +#: ../../source/tutorial-quickstart-xgboost.rst:39 +msgid "" +"First of all, it is recommended to create a virtual environment and run " +"everything within a `virtualenv `_." +msgstr "" +"Tout d'abord, il est recommandé de créer un environnement virtuel et de " +"tout exécuter au sein d'un `virtualenv `_." + +#: ../../source/tutorial-quickstart-pytorch.rst:29 +msgid "" +"Since we want to use PyTorch to solve a computer vision task, let's go " +"ahead and install PyTorch and the **torchvision** library:" +msgstr "" +"Puisque nous voulons utiliser PyTorch pour résoudre une tâche de vision " +"par ordinateur, allons-y et installons PyTorch et la bibliothèque " +"**torchvision** :" + +#: ../../source/tutorial-quickstart-pytorch.rst:39 +msgid "" +"Now that we have all our dependencies installed, let's run a simple " +"distributed training with two clients and one server. Our training " +"procedure and network architecture are based on PyTorch's `Deep Learning " +"with PyTorch " +"`_." +msgstr "" +"Maintenant que nous avons installé toutes nos dépendances, lançons une " +"formation distribuée simple avec deux clients et un serveur. Notre " +"procédure de formation et l'architecture de notre réseau sont basées sur " +"`Deep Learning with PyTorch " +"`_ de" +" PyTorch." + +#: ../../source/tutorial-quickstart-pytorch.rst:41 +msgid "" +"In a file called :code:`client.py`, import Flower and PyTorch related " +"packages:" +msgstr "" +"Dans un fichier appelé :code:`client.py`, importe Flower et les paquets " +"liés à PyTorch :" + +#: ../../source/tutorial-quickstart-pytorch.rst:56 +msgid "In addition, we define the device allocation in PyTorch with:" +msgstr "En outre, nous définissons l'attribution des appareils dans PyTorch avec :" + +#: ../../source/tutorial-quickstart-pytorch.rst:62 +msgid "" +"We use PyTorch to load CIFAR10, a popular colored image classification " +"dataset for machine learning. The PyTorch :code:`DataLoader()` downloads " +"the training and test data that are then normalized." +msgstr "" +"Nous utilisons PyTorch pour charger CIFAR10, un ensemble de données de " +"classification d'images colorées populaire pour l'apprentissage " +"automatique. Le :code:`DataLoader()` de PyTorch télécharge les données " +"d'entraînement et de test qui sont ensuite normalisées." + +#: ../../source/tutorial-quickstart-pytorch.rst:78 +msgid "" +"Define the loss and optimizer with PyTorch. The training of the dataset " +"is done by looping over the dataset, measure the corresponding loss and " +"optimize it." +msgstr "" +"Définis la perte et l'optimiseur avec PyTorch L'entraînement de " +"l'ensemble de données se fait en bouclant sur l'ensemble de données, en " +"mesurant la perte correspondante et en l'optimisant." + +#: ../../source/tutorial-quickstart-pytorch.rst:94 +msgid "" +"Define then the validation of the machine learning network. We loop over" +" the test set and measure the loss and accuracy of the test set." +msgstr "" +"Définis ensuite la validation du réseau d'apprentissage automatique. Nous" +" passons en boucle sur l'ensemble de test et mesurons la perte et la " +"précision de l'ensemble de test." + +#: ../../source/tutorial-quickstart-pytorch.rst:113 +msgid "" +"After defining the training and testing of a PyTorch machine learning " +"model, we use the functions for the Flower clients." +msgstr "" +"Après avoir défini l'entraînement et le test d'un modèle d'apprentissage " +"automatique PyTorch, nous utilisons les fonctions pour les clients " +"Flower." + +#: ../../source/tutorial-quickstart-pytorch.rst:115 +msgid "" +"The Flower clients will use a simple CNN adapted from 'PyTorch: A 60 " +"Minute Blitz':" +msgstr "" +"Les clients de Flower utiliseront un CNN simple adapté de \"PyTorch : A " +"60 Minute Blitz\" :" + +#: ../../source/tutorial-quickstart-pytorch.rst:142 +msgid "" +"After loading the data set with :code:`load_data()` we define the Flower " +"interface." +msgstr "" +"Après avoir chargé l'ensemble des données avec :code:`load_data()`, nous " +"définissons l'interface Flower." + +#: ../../source/tutorial-quickstart-pytorch.rst:150 +msgid "" +"Flower provides a convenience class called :code:`NumPyClient` which " +"makes it easier to implement the :code:`Client` interface when your " +"workload uses PyTorch. Implementing :code:`NumPyClient` usually means " +"defining the following methods (:code:`set_parameters` is optional " +"though):" +msgstr "" +"Flower fournit une classe de commodité appelée :code:`NumPyClient` qui " +"facilite la mise en œuvre de l'interface :code:`Client` lorsque ta charge" +" de travail utilise PyTorch. Mettre en œuvre :code:`NumPyClient` signifie" +" généralement définir les méthodes suivantes (:code:`set_parameters` est " +"cependant facultatif) :" + +#: ../../source/tutorial-quickstart-pytorch.rst:166 +msgid "which can be implemented in the following way:" +msgstr "qui peut être mis en œuvre de la manière suivante :" + +#: ../../source/tutorial-quickstart-pytorch.rst:189 +#: ../../source/tutorial-quickstart-tensorflow.rst:82 +msgid "" +"We can now create an instance of our class :code:`CifarClient` and add " +"one line to actually run this client:" +msgstr "" +"Nous pouvons maintenant créer une instance de notre classe " +":code:`CifarClient` et ajouter une ligne pour exécuter ce client :" + +#: ../../source/tutorial-quickstart-pytorch.rst:196 +#: ../../source/tutorial-quickstart-tensorflow.rst:90 +#, fuzzy +msgid "" +"That's it for the client. We only have to implement :code:`Client` or " +":code:`NumPyClient` and call :code:`fl.client.start_client()`. If you " +"implement a client of type :code:`NumPyClient` you'll need to first call " +"its :code:`to_client()` method. The string :code:`\"[::]:8080\"` tells " +"the client which server to connect to. In our case we can run the server " +"and the client on the same machine, therefore we use " +":code:`\"[::]:8080\"`. If we run a truly federated workload with the " +"server and clients running on different machines, all that needs to " +"change is the :code:`server_address` we point the client at." +msgstr "" +"C'est tout pour le client. Il nous suffit d'implémenter :code:`Client` ou" +" :code:`NumPyClient` et d'appeler :code:`fl.client.start_client()`. La " +"chaîne :code:`\"[: :]:8080\"` indique au client à quel serveur se " +"connecter. Dans notre cas, nous pouvons exécuter le serveur et le client " +"sur la même machine, c'est pourquoi nous utilisons :code:`\"[: " +":]:8080\"`. Si nous exécutons une charge de travail véritablement fédérée" +" avec le serveur et les clients fonctionnant sur des machines " +"différentes, tout ce qui doit changer est l'adresse " +":code:`server_address` vers laquelle nous dirigeons le client." + +#: ../../source/tutorial-quickstart-pytorch.rst:271 +#, fuzzy +msgid "" +"Congratulations! You've successfully built and run your first federated " +"learning system. The full `source code " +"`_ for this example can be found in :code:`examples" +"/quickstart-pytorch`." +msgstr "" +"Félicitations ! Tu as réussi à construire et à faire fonctionner ton " +"premier système d'apprentissage fédéré. Le code source complet " +"`_ de cet exemple se trouve dans :code:`examples" +"/quickstart-pytorch`." + +#: ../../source/tutorial-quickstart-pytorch-lightning.rst:-1 +msgid "" +"Check out this Federated Learning quickstart tutorial for using Flower " +"with PyTorch Lightning to train an Auto Encoder model on MNIST." +msgstr "" + +#: ../../source/tutorial-quickstart-pytorch-lightning.rst:5 +msgid "Quickstart PyTorch Lightning" +msgstr "Démarrage rapide de PyTorch Lightning" + +#: ../../source/tutorial-quickstart-pytorch-lightning.rst:10 +#, fuzzy +msgid "" +"Let's build a horizontal federated learning system using PyTorch " +"Lightning and Flower!" +msgstr "" +"Construisons un système d'apprentissage fédéré en utilisant PyTorch " +"Lightning et Flower !" + +#: ../../source/tutorial-quickstart-pytorch-lightning.rst:12 +#, fuzzy +msgid "" +"Please refer to the `full code example " +"`_ to learn more." +msgstr "" +"Réfère-toi à l'exemple de code complet " +"`_ pour en savoir plus." + +#: ../../source/tutorial-quickstart-scikitlearn.rst:-1 +msgid "" +"Check out this Federated Learning quickstart tutorial for using Flower " +"with scikit-learn to train a linear regression model." +msgstr "" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:5 +msgid "Quickstart scikit-learn" +msgstr "Démarrage rapide de scikit-learn" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:10 +msgid "" +"In this tutorial, we will learn how to train a :code:`Logistic " +"Regression` model on MNIST using Flower and scikit-learn." +msgstr "" +"Dans ce tutoriel, nous allons apprendre à former un :code:`modèle de " +"régression logistique` sur MNIST en utilisant Flower et scikit-learn." + +#: ../../source/tutorial-quickstart-scikitlearn.rst:26 +msgid "Since we want to use scikt-learn, let's go ahead and install it:" +msgstr "Puisque nous voulons utiliser scikt-learn, allons-y et installons-le :" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:32 +msgid "Or simply install all dependencies using Poetry:" +msgstr "Ou installe simplement toutes les dépendances à l'aide de Poetry :" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:42 +msgid "" +"Now that we have all our dependencies installed, let's run a simple " +"distributed training with two clients and one server. However, before " +"setting up the client and server, we will define all functionalities that" +" we need for our federated learning setup within :code:`utils.py`. The " +":code:`utils.py` contains different functions defining all the machine " +"learning basics:" +msgstr "" +"Maintenant que toutes nos dépendances sont installées, exécutons une " +"formation distribuée simple avec deux clients et un serveur. Cependant, " +"avant de configurer le client et le serveur, nous allons définir toutes " +"les fonctionnalités dont nous avons besoin pour notre configuration " +"d'apprentissage fédéré dans :code:`utils.py`. Le :code:`utils.py` " +"contient différentes fonctions définissant toutes les bases de " +"l'apprentissage automatique :" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:45 +msgid ":code:`get_model_parameters()`" +msgstr ":code:`get_model_parameters()`" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:46 +msgid "Returns the paramters of a :code:`sklearn` LogisticRegression model" +msgstr "" +"Renvoie les paramètres d'un modèle de régression logistique " +":code:`sklearn`" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:47 +msgid ":code:`set_model_params()`" +msgstr ":code:`set_model_params()`" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:48 +msgid "Sets the parameters of a :code:`sklean` LogisticRegression model" +msgstr "Définit les paramètres d'un modèle de régression logistique :code:`sklean`" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:49 +msgid ":code:`set_initial_params()`" +msgstr ":code:`set_initial_params()`" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:50 +msgid "Initializes the model parameters that the Flower server will ask for" +msgstr "Initialise les paramètres du modèle que le serveur de Flower demandera" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:51 +msgid ":code:`load_mnist()`" +msgstr ":code:`load_mnist()`" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:52 +msgid "Loads the MNIST dataset using OpenML" +msgstr "Charge l'ensemble de données MNIST à l'aide d'OpenML" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:53 +msgid ":code:`shuffle()`" +msgstr ":code:`shuffle()`" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:54 +msgid "Shuffles data and its label" +msgstr "Mélange les données et leur étiquette" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:56 +msgid ":code:`partition()`" +msgstr ":code:`partition()`" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:56 +msgid "Splits datasets into a number of partitions" +msgstr "Divise les ensembles de données en un certain nombre de partitions" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:58 +msgid "" +"Please check out :code:`utils.py` `here " +"`_ for more details. The pre-defined functions are used in" +" the :code:`client.py` and imported. The :code:`client.py` also requires " +"to import several packages such as Flower and scikit-learn:" +msgstr "" +"Tu peux consulter :code:`utils.py` `ici " +"`_ pour plus de détails. Les fonctions prédéfinies sont " +"utilisées dans :code:`client.py` et importées. :code:`client.py` " +"nécessite également d'importer plusieurs paquets tels que Flower et " +"scikit-learn :" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:73 +msgid "" +"We load the MNIST dataset from `OpenML `_, " +"a popular image classification dataset of handwritten digits for machine " +"learning. The utility :code:`utils.load_mnist()` downloads the training " +"and test data. The training set is split afterwards into 10 partitions " +"with :code:`utils.partition()`." +msgstr "" +"Nous chargeons l'ensemble de données MNIST de `OpenML " +"`_, un ensemble de données de " +"classification d'images populaires de chiffres manuscrits pour " +"l'apprentissage automatique. L'utilitaire :code:`utils.load_mnist()` " +"télécharge les données d'entraînement et de test. L'ensemble " +"d'entraînement est ensuite divisé en 10 partitions avec " +":code:`utils.partition()`." + +#: ../../source/tutorial-quickstart-scikitlearn.rst:85 +msgid "" +"Next, the logistic regression model is defined and initialized with " +":code:`utils.set_initial_params()`." +msgstr "" +"Ensuite, le modèle de régression logistique est défini et initialisé avec" +" :code:`utils.set_initial_params()`." + +#: ../../source/tutorial-quickstart-scikitlearn.rst:97 +msgid "" +"The Flower server interacts with clients through an interface called " +":code:`Client`. When the server selects a particular client for training," +" it sends training instructions over the network. The client receives " +"those instructions and calls one of the :code:`Client` methods to run " +"your code (i.e., to fit the logistic regression we defined earlier)." +msgstr "" +"Le serveur Flower interagit avec les clients par le biais d'une interface" +" appelée :code:`Client`. Lorsque le serveur sélectionne un client " +"particulier pour la formation, il envoie des instructions de formation " +"sur le réseau. Le client reçoit ces instructions et appelle l'une des " +"méthodes :code:`Client` pour exécuter ton code (c'est-à-dire pour ajuster" +" la régression logistique que nous avons définie plus tôt)." + +#: ../../source/tutorial-quickstart-scikitlearn.rst:103 +msgid "" +"Flower provides a convenience class called :code:`NumPyClient` which " +"makes it easier to implement the :code:`Client` interface when your " +"workload uses scikit-learn. Implementing :code:`NumPyClient` usually " +"means defining the following methods (:code:`set_parameters` is optional " +"though):" +msgstr "" +"Flower fournit une classe de commodité appelée :code:`NumPyClient` qui " +"facilite la mise en œuvre de l'interface :code:`Client` lorsque ta charge" +" de travail utilise scikit-learn. Mettre en œuvre :code:`NumPyClient` " +"signifie généralement définir les méthodes suivantes " +"(:code:`set_parameters` est cependant facultatif) :" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:112 +msgid "is directly imported with :code:`utils.set_model_params()`" +msgstr "est directement importé avec :code:`utils.set_model_params()`" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:120 +msgid "The methods can be implemented in the following way:" +msgstr "Les méthodes peuvent être mises en œuvre de la manière suivante :" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:143 +msgid "" +"We can now create an instance of our class :code:`MnistClient` and add " +"one line to actually run this client:" +msgstr "" +"Nous pouvons maintenant créer une instance de notre classe " +":code:`MnistClient` et ajouter une ligne pour exécuter ce client :" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:150 +#, fuzzy msgid "" "That's it for the client. We only have to implement :code:`Client` or " -":code:`NumPyClient` and call :code:`fl.client.start_client()`. The string :code:`\"[::]:8080\"` " +":code:`NumPyClient` and call :code:`fl.client.start_client()`. If you " +"implement a client of type :code:`NumPyClient` you'll need to first call " +"its :code:`to_client()` method. The string :code:`\"0.0.0.0:8080\"` tells" +" the client which server to connect to. In our case we can run the server" +" and the client on the same machine, therefore we use " +":code:`\"0.0.0.0:8080\"`. If we run a truly federated workload with the " +"server and clients running on different machines, all that needs to " +"change is the :code:`server_address` we pass to the client." +msgstr "" +"C'est tout pour le client. Il nous suffit d'implémenter :code:`Client` ou" +" :code:`NumPyClient` et d'appeler :code:`fl.client.start_client()`. La " +"chaîne :code:`\"0.0.0:8080\"` indique au client à quel serveur se " +"connecter. Dans notre cas, nous pouvons exécuter le serveur et le client " +"sur la même machine, c'est pourquoi nous utilisons " +":code:`\"0.0.0:8080\"`. Si nous exécutons une charge de travail " +"véritablement fédérée avec le serveur et les clients s'exécutant sur des " +"machines différentes, tout ce qui doit changer est :code:`server_address`" +" que nous transmettons au client." + +#: ../../source/tutorial-quickstart-scikitlearn.rst:159 +msgid "" +"The following Flower server is a little bit more advanced and returns an " +"evaluation function for the server-side evaluation. First, we import " +"again all required libraries such as Flower and scikit-learn." +msgstr "" +"Le serveur Flower suivant est un peu plus avancé et renvoie une fonction " +"d'évaluation pour l'évaluation côté serveur. Tout d'abord, nous importons" +" à nouveau toutes les bibliothèques requises telles que Flower et scikit-" +"learn." + +#: ../../source/tutorial-quickstart-scikitlearn.rst:162 +msgid ":code:`server.py`, import Flower and start the server:" +msgstr ":code:`server.py`, importe Flower et démarre le serveur :" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:173 +msgid "" +"The number of federated learning rounds is set in :code:`fit_round()` and" +" the evaluation is defined in :code:`get_evaluate_fn()`. The evaluation " +"function is called after each federated learning round and gives you " +"information about loss and accuracy." +msgstr "" +"Le nombre de tours d'apprentissage fédéré est défini dans " +":code:`fit_round()` et l'évaluation est définie dans " +":code:`get_evaluate_fn()`. La fonction d'évaluation est appelée après " +"chaque tour d'apprentissage fédéré et te donne des informations sur la " +"perte et la précision." + +#: ../../source/tutorial-quickstart-scikitlearn.rst:198 +msgid "" +"The :code:`main` contains the server-side parameter initialization " +":code:`utils.set_initial_params()` as well as the aggregation strategy " +":code:`fl.server.strategy:FedAvg()`. The strategy is the default one, " +"federated averaging (or FedAvg), with two clients and evaluation after " +"each federated learning round. The server can be started with the command" +" :code:`fl.server.start_server(server_address=\"0.0.0.0:8080\", " +"strategy=strategy, config=fl.server.ServerConfig(num_rounds=3))`." +msgstr "" +"Le :code:`main` contient l'initialisation des paramètres côté serveur " +":code:`utils.set_initial_params()` ainsi que la stratégie d'agrégation " +":code:`fl.server.strategy:FedAvg()`. La stratégie est celle par défaut, " +"la moyenne fédérée (ou FedAvg), avec deux clients et une évaluation après" +" chaque tour d'apprentissage fédéré. Le serveur peut être démarré avec la" +" commande :code:`fl.server.start_server(server_address=\"0.0.0.0:8080\", " +"strategy=strategy, config=fl.server.ServerConfig(num_rounds=3))`." + +#: ../../source/tutorial-quickstart-scikitlearn.rst:217 +msgid "" +"With both client and server ready, we can now run everything and see " +"federated learning in action. Federated learning systems usually have a " +"server and multiple clients. We, therefore, have to start the server " +"first:" +msgstr "" +"Le client et le serveur étant prêts, nous pouvons maintenant tout lancer " +"et voir l'apprentissage fédéré en action. Les systèmes d'apprentissage " +"fédéré ont généralement un serveur et plusieurs clients. Nous devons donc" +" commencer par lancer le serveur :" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:271 +msgid "" +"Congratulations! You've successfully built and run your first federated " +"learning system. The full `source code " +"`_ for this example can be found in :code:`examples/sklearn-logreg-" +"mnist`." +msgstr "" +"Félicitations ! Tu as réussi à construire et à faire fonctionner ton " +"premier système d'apprentissage fédéré. Le code source complet " +"`_ de cet exemple se trouve dans :code:`examples/sklearn-logreg-" +"mnist`." + +#: ../../source/tutorial-quickstart-tensorflow.rst:-1 +msgid "" +"Check out this Federated Learning quickstart tutorial for using Flower " +"with TensorFlow to train a MobilNetV2 model on CIFAR-10." +msgstr "" + +#: ../../source/tutorial-quickstart-tensorflow.rst:5 +msgid "Quickstart TensorFlow" +msgstr "Démarrage rapide de TensorFlow" + +#: ../../source/tutorial-quickstart-tensorflow.rst:13 +msgid "Let's build a federated learning system in less than 20 lines of code!" +msgstr "" +"Construisons un système d'apprentissage fédéré en moins de 20 lignes de " +"code !" + +#: ../../source/tutorial-quickstart-tensorflow.rst:15 +msgid "Before Flower can be imported we have to install it:" +msgstr "Avant de pouvoir importer une fleur, nous devons l'installer :" + +#: ../../source/tutorial-quickstart-tensorflow.rst:21 +msgid "" +"Since we want to use the Keras API of TensorFlow (TF), we have to install" +" TF as well:" +msgstr "" +"Comme nous voulons utiliser l'API Keras de TensorFlow (TF), nous devons " +"également installer TF :" + +#: ../../source/tutorial-quickstart-tensorflow.rst:31 +msgid "Next, in a file called :code:`client.py`, import Flower and TensorFlow:" +msgstr "" +"Ensuite, dans un fichier appelé :code:`client.py`, importe Flower et " +"TensorFlow :" + +#: ../../source/tutorial-quickstart-tensorflow.rst:38 +msgid "" +"We use the Keras utilities of TF to load CIFAR10, a popular colored image" +" classification dataset for machine learning. The call to " +":code:`tf.keras.datasets.cifar10.load_data()` downloads CIFAR10, caches " +"it locally, and then returns the entire training and test set as NumPy " +"ndarrays." +msgstr "" +"Nous utilisons les utilitaires Keras de TF pour charger CIFAR10, un " +"ensemble de données de classification d'images colorées populaire pour " +"l'apprentissage automatique. L'appel à " +":code:`tf.keras.datasets.cifar10.load_data()` télécharge CIFAR10, le met " +"en cache localement, puis renvoie l'ensemble d'entraînement et de test " +"sous forme de NumPy ndarrays." + +#: ../../source/tutorial-quickstart-tensorflow.rst:47 +msgid "" +"Next, we need a model. For the purpose of this tutorial, we use " +"MobilNetV2 with 10 output classes:" +msgstr "" +"Ensuite, nous avons besoin d'un modèle. Pour les besoins de ce tutoriel, " +"nous utilisons MobilNetV2 avec 10 classes de sortie :" + +#: ../../source/tutorial-quickstart-tensorflow.rst:60 +msgid "" +"Flower provides a convenience class called :code:`NumPyClient` which " +"makes it easier to implement the :code:`Client` interface when your " +"workload uses Keras. The :code:`NumPyClient` interface defines three " +"methods which can be implemented in the following way:" +msgstr "" +"Flower fournit une classe de commodité appelée :code:`NumPyClient` qui " +"facilite la mise en œuvre de l'interface :code:`Client` lorsque ta charge" +" de travail utilise Keras. L'interface :code:`NumPyClient` définit trois " +"méthodes qui peuvent être mises en œuvre de la manière suivante :" + +#: ../../source/tutorial-quickstart-tensorflow.rst:135 +msgid "Each client will have its own dataset." +msgstr "Chaque client aura son propre ensemble de données." + +#: ../../source/tutorial-quickstart-tensorflow.rst:137 +msgid "" +"You should now see how the training does in the very first terminal (the " +"one that started the server):" +msgstr "" +"Tu devrais maintenant voir comment la formation se déroule dans le tout " +"premier terminal (celui qui a démarré le serveur) :" + +#: ../../source/tutorial-quickstart-tensorflow.rst:169 +#, fuzzy +msgid "" +"Congratulations! You've successfully built and run your first federated " +"learning system. The full `source code " +"`_ for this can be found in :code:`examples" +"/quickstart-tensorflow/client.py`." +msgstr "" +"Félicitations ! Tu as réussi à construire et à faire fonctionner ton " +"premier système d'apprentissage fédéré. Le `code source complet " +"`_ pour cela se trouve dans :code:`examples" +"/quickstart-tensorflow/client.py`." + +#: ../../source/tutorial-quickstart-xgboost.rst:-1 +msgid "" +"Check out this Federated Learning quickstart tutorial for using Flower " +"with XGBoost to train classification models on trees." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:5 +msgid "Quickstart XGBoost" +msgstr "Démarrage rapide XGBoost" + +#: ../../source/tutorial-quickstart-xgboost.rst:14 +#, fuzzy +msgid "Federated XGBoost" +msgstr "Formation fédérée" + +#: ../../source/tutorial-quickstart-xgboost.rst:16 +msgid "" +"EXtreme Gradient Boosting (**XGBoost**) is a robust and efficient " +"implementation of gradient-boosted decision tree (**GBDT**), that " +"maximises the computational boundaries for boosted tree methods. It's " +"primarily designed to enhance both the performance and computational " +"speed of machine learning models. In XGBoost, trees are constructed " +"concurrently, unlike the sequential approach taken by GBDT." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:20 +msgid "" +"Often, for tabular data on medium-sized datasets with fewer than 10k " +"training examples, XGBoost surpasses the results of deep learning " +"techniques." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:23 +#, fuzzy +msgid "Why federated XGBoost?" +msgstr "Qu'est-ce que l'apprentissage fédéré ?" + +#: ../../source/tutorial-quickstart-xgboost.rst:25 +msgid "" +"Indeed, as the demand for data privacy and decentralized learning grows, " +"there's an increasing requirement to implement federated XGBoost systems " +"for specialised applications, like survival analysis and financial fraud " +"detection." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:27 +msgid "" +"Federated learning ensures that raw data remains on the local device, " +"making it an attractive approach for sensitive domains where data " +"security and privacy are paramount. Given the robustness and efficiency " +"of XGBoost, combining it with federated learning offers a promising " +"solution for these specific challenges." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:30 +msgid "" +"In this tutorial we will learn how to train a federated XGBoost model on " +"HIGGS dataset using Flower and :code:`xgboost` package. We use a simple " +"example (`full code xgboost-quickstart " +"`_)" +" with two *clients* and one *server* to demonstrate how federated XGBoost" +" works, and then we dive into a more complex example (`full code xgboost-" +"comprehensive `_) to run various experiments." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:37 +msgid "Environment Setup" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:41 +msgid "" +"We first need to install Flower and Flower Datasets. You can do this by " +"running :" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:47 +#, fuzzy +msgid "" +"Since we want to use :code:`xgboost` package to build up XGBoost trees, " +"let's go ahead and install :code:`xgboost`:" +msgstr "Puisque nous voulons utiliser scikt-learn, allons-y et installons-le :" + +#: ../../source/tutorial-quickstart-xgboost.rst:57 +msgid "" +"*Clients* are responsible for generating individual weight-updates for " +"the model based on their local datasets. Now that we have all our " +"dependencies installed, let's run a simple distributed training with two " +"clients and one server." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:60 +#, fuzzy +msgid "" +"In a file called :code:`client.py`, import xgboost, Flower, Flower " +"Datasets and other related functions:" +msgstr "" +"Dans un fichier appelé :code:`client.py`, importe Flower et les paquets " +"liés à PyTorch :" + +#: ../../source/tutorial-quickstart-xgboost.rst:87 +msgid "Dataset partition and hyper-parameter selection" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:89 +msgid "" +"Prior to local training, we require loading the HIGGS dataset from Flower" +" Datasets and conduct data partitioning for FL:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:102 +msgid "" +"In this example, we split the dataset into two partitions with uniform " +"distribution (:code:`IidPartitioner(num_partitions=2)`). Then, we load " +"the partition for the given client based on :code:`node_id`:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:121 +msgid "" +"After that, we do train/test splitting on the given partition (client's " +"local data), and transform data format for :code:`xgboost` package." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:134 +msgid "" +"The functions of :code:`train_test_split` and " +":code:`transform_dataset_to_dmatrix` are defined as below:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:158 +msgid "Finally, we define the hyper-parameters used for XGBoost training." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:174 +msgid "" +"The :code:`num_local_round` represents the number of iterations for local" +" tree boost. We use CPU for the training in default. One can shift it to " +"GPU by setting :code:`tree_method` to :code:`gpu_hist`. We use AUC as " +"evaluation metric." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:181 +msgid "Flower client definition for XGBoost" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:183 +msgid "" +"After loading the dataset we define the Flower client. We follow the " +"general rule to define :code:`XgbClient` class inherited from " +":code:`fl.client.Client`." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:193 +msgid "" +"The :code:`self.bst` is used to keep the Booster objects that remain " +"consistent across rounds, allowing them to store predictions from trees " +"integrated in earlier rounds and maintain other essential data structures" +" for training." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:196 +msgid "" +"Then, we override :code:`get_parameters`, :code:`fit` and " +":code:`evaluate` methods insides :code:`XgbClient` class as follows." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:210 +msgid "" +"Unlike neural network training, XGBoost trees are not started from a " +"specified random weights. In this case, we do not use " +":code:`get_parameters` and :code:`set_parameters` to initialise model " +"parameters for XGBoost. As a result, let's return an empty tensor in " +":code:`get_parameters` when it is called by the server at the first " +"round." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:251 +msgid "" +"In :code:`fit`, at the first round, we call :code:`xgb.train()` to build " +"up the first set of trees. the returned Booster object and config are " +"stored in :code:`self.bst` and :code:`self.config`, respectively. From " +"the second round, we load the global model sent from server to " +":code:`self.bst`, and then update model weights on local training data " +"with function :code:`local_boost` as follows:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:269 +msgid "" +"Given :code:`num_local_round`, we update trees by calling " +":code:`self.bst.update` method. After training, the last " +":code:`N=num_local_round` trees will be extracted to send to the server." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:291 +msgid "" +"In :code:`evaluate`, we call :code:`self.bst.eval_set` function to " +"conduct evaluation on valid set. The AUC value will be returned." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:294 +#, fuzzy +msgid "" +"Now, we can create an instance of our class :code:`XgbClient` and add one" +" line to actually run this client:" +msgstr "" +"Nous pouvons maintenant créer une instance de notre classe " +":code:`MnistClient` et ajouter une ligne pour exécuter ce client :" + +#: ../../source/tutorial-quickstart-xgboost.rst:300 +#, fuzzy +msgid "" +"That's it for the client. We only have to implement :code:`Client`and " +"call :code:`fl.client.start_client()`. The string :code:`\"[::]:8080\"` " "tells the client which server to connect to. In our case we can run the " "server and the client on the same machine, therefore we use " ":code:`\"[::]:8080\"`. If we run a truly federated workload with the " "server and clients running on different machines, all that needs to " "change is the :code:`server_address` we point the client at." msgstr "" -"C'est tout pour le client. Il nous suffit d'implémenter :code:`Client` ou" -" :code:`NumPyClient` et d'appeler :code:`fl.client.start_client()`. La chaîne :code:`\"[: :]:8080\"` " -"indique au client à quel serveur se connecter. Dans notre cas, nous " -"pouvons exécuter le serveur et le client sur la même machine, c'est " -"pourquoi nous utilisons :code:`\"[: :]:8080\"`. Si nous exécutons une " -"charge de travail véritablement fédérée avec le serveur et les clients " -"fonctionnant sur des machines différentes, tout ce qui doit changer est " -"l'adresse :code:`server_address` vers laquelle nous dirigeons le client." +"C'est tout pour le client. Il nous suffit d'implémenter :code:`Client` ou" +" :code:`NumPyClient` et d'appeler :code:`fl.client.start_client()`. La " +"chaîne :code:`\"[: :]:8080\"` indique au client à quel serveur se " +"connecter. Dans notre cas, nous pouvons exécuter le serveur et le client " +"sur la même machine, c'est pourquoi nous utilisons :code:`\"[: " +":]:8080\"`. Si nous exécutons une charge de travail véritablement fédérée" +" avec le serveur et les clients fonctionnant sur des machines " +"différentes, tout ce qui doit changer est l'adresse " +":code:`server_address` vers laquelle nous dirigeons le client." + +#: ../../source/tutorial-quickstart-xgboost.rst:311 +#, fuzzy +msgid "" +"These updates are then sent to the *server* which will aggregate them to " +"produce a better model. Finally, the *server* sends this improved version" +" of the model back to each *client* to finish a complete FL round." +msgstr "" +"*Les clients* sont chargés de générer des mises à jour de poids " +"individuelles pour le modèle en fonction de leurs ensembles de données " +"locales. Ces mises à jour sont ensuite envoyées au *serveur* qui les " +"agrège pour produire un meilleur modèle. Enfin, le *serveur* renvoie " +"cette version améliorée du modèle à chaque *client*. Un cycle complet de " +"mises à jour de poids s'appelle un *round*." + +#: ../../source/tutorial-quickstart-xgboost.rst:314 +#, fuzzy +msgid "" +"In a file named :code:`server.py`, import Flower and FedXgbBagging from " +":code:`flwr.server.strategy`." +msgstr "" +"Dans un fichier appelé :code:`client.py`, importe Flower et les paquets " +"liés au MXNet :" + +#: ../../source/tutorial-quickstart-xgboost.rst:316 +msgid "We first define a strategy for XGBoost bagging aggregation." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:339 +msgid "" +"We use two clients for this example. An " +":code:`evaluate_metrics_aggregation` function is defined to collect and " +"wighted average the AUC values from clients." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:342 +#, fuzzy +msgid "Then, we start the server:" +msgstr "Démarrer le serveur" + +#: ../../source/tutorial-quickstart-xgboost.rst:354 +msgid "Tree-based bagging aggregation" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:356 +msgid "" +"You must be curious about how bagging aggregation works. Let's look into " +"the details." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:358 +msgid "" +"In file :code:`flwr.server.strategy.fedxgb_bagging.py`, we define " +":code:`FedXgbBagging` inherited from :code:`flwr.server.strategy.FedAvg`." +" Then, we override the :code:`aggregate_fit`, :code:`aggregate_evaluate` " +"and :code:`evaluate` methods as follows:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:454 +msgid "" +"In :code:`aggregate_fit`, we sequentially aggregate the clients' XGBoost " +"trees by calling :code:`aggregate()` function:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:513 +msgid "" +"In this function, we first fetch the number of trees and the number of " +"parallel trees for the current and previous model by calling " +":code:`_get_tree_nums`. Then, the fetched information will be aggregated." +" After that, the trees (containing model weights) are aggregated to " +"generate a new tree model." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:518 +msgid "" +"After traversal of all clients' models, a new global model is generated, " +"followed by the serialisation, and sending back to each client." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:523 +msgid "Launch Federated XGBoost!" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:585 +msgid "" +"Congratulations! You've successfully built and run your first federated " +"XGBoost system. The AUC values can be checked in " +":code:`metrics_distributed`. One can see that the average AUC increases " +"over FL rounds." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:590 +#, fuzzy +msgid "" +"The full `source code `_ for this example can be found in :code:`examples" +"/xgboost-quickstart`." +msgstr "" +"Félicitations ! Tu as réussi à construire et à faire fonctionner ton " +"premier système d'apprentissage fédéré. Le code source complet " +"`_ de cet exemple se trouve dans :code:`examples" +"/quickstart-mxnet`." + +#: ../../source/tutorial-quickstart-xgboost.rst:594 +msgid "Comprehensive Federated XGBoost" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:596 +msgid "" +"Now that you have known how federated XGBoost work with Flower, it's time" +" to run some more comprehensive experiments by customising the " +"experimental settings. In the xgboost-comprehensive example (`full code " +"`_), we provide more options to define various experimental" +" setups, including aggregation strategies, data partitioning and " +"centralised/distributed evaluation. We also support `Flower simulation " +"`_ making " +"it easy to simulate large client cohorts in a resource-aware manner. " +"Let's take a look!" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:603 +#, fuzzy +msgid "Cyclic training" +msgstr "Formation centralisée" + +#: ../../source/tutorial-quickstart-xgboost.rst:605 +msgid "" +"In addition to bagging aggregation, we offer a cyclic training scheme, " +"which performs FL in a client-by-client fashion. Instead of aggregating " +"multiple clients, there is only one single client participating in the " +"training per round in the cyclic training scenario. The trained local " +"XGBoost trees will be passed to the next client as an initialised model " +"for next round's boosting." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:609 +msgid "" +"To do this, we first customise a :code:`ClientManager` in " +":code:`server_utils.py`:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:649 +msgid "" +"The customised :code:`ClientManager` samples all available clients in " +"each FL round based on the order of connection to the server. Then, we " +"define a new strategy :code:`FedXgbCyclic` in " +":code:`flwr.server.strategy.fedxgb_cyclic.py`, in order to sequentially " +"select only one client in given round and pass the received model to next" +" client." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:690 +msgid "" +"Unlike the original :code:`FedAvg`, we don't perform aggregation here. " +"Instead, we just make a copy of the received client model as global model" +" by overriding :code:`aggregate_fit`." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:693 +msgid "" +"Also, the customised :code:`configure_fit` and :code:`configure_evaluate`" +" methods ensure the clients to be sequentially selected given FL round:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:757 +msgid "Customised data partitioning" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:759 +msgid "" +"In :code:`dataset.py`, we have a function :code:`instantiate_partitioner`" +" to instantiate the data partitioner based on the given " +":code:`num_partitions` and :code:`partitioner_type`. Currently, we " +"provide four supported partitioner type to simulate the uniformity/non-" +"uniformity in data quantity (uniform, linear, square, exponential)." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:790 +#, fuzzy +msgid "Customised centralised/distributed evaluation" +msgstr "Évaluation centralisée" + +#: ../../source/tutorial-quickstart-xgboost.rst:792 +msgid "" +"To facilitate centralised evaluation, we define a function in " +":code:`server_utils.py`:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:824 +msgid "" +"This function returns a evaluation function which instantiates a " +":code:`Booster` object and loads the global model weights to it. The " +"evaluation is conducted by calling :code:`eval_set()` method, and the " +"tested AUC value is reported." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:827 +msgid "" +"As for distributed evaluation on the clients, it's same as the quick-" +"start example by overriding the :code:`evaluate()` method insides the " +":code:`XgbClient` class in :code:`client_utils.py`." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:831 +#, fuzzy +msgid "Flower simulation" +msgstr "Simulation de moniteur" + +#: ../../source/tutorial-quickstart-xgboost.rst:832 +msgid "" +"We also provide an example code (:code:`sim.py`) to use the simulation " +"capabilities of Flower to simulate federated XGBoost training on either a" +" single machine or a cluster of machines." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:866 +msgid "" +"After importing all required packages, we define a :code:`main()` " +"function to perform the simulation process:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:921 +msgid "" +"We first load the dataset and perform data partitioning, and the pre-" +"processed data is stored in a :code:`list`. After the simulation begins, " +"the clients won't need to pre-process their partitions again." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:924 +msgid "Then, we define the strategies and other hyper-parameters:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:975 +msgid "" +"After that, we start the simulation by calling " +":code:`fl.simulation.start_simulation`:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:995 +msgid "" +"One of key parameters for :code:`start_simulation` is :code:`client_fn` " +"which returns a function to construct a client. We define it as follows:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1038 +msgid "Arguments parser" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1040 +msgid "" +"In :code:`utils.py`, we define the arguments parsers for clients, server " +"and simulation, allowing users to specify different experimental " +"settings. Let's first see the sever side:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1086 +msgid "" +"This allows user to specify training strategies / the number of total " +"clients / FL rounds / participating clients / clients for evaluation, and" +" evaluation fashion. Note that with :code:`--centralised-eval`, the sever" +" will do centralised evaluation and all functionalities for client " +"evaluation will be disabled." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1090 +msgid "Then, the argument parser on client side:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1144 +msgid "" +"This defines various options for client data partitioning. Besides, " +"clients also have an option to conduct evaluation on centralised test set" +" by setting :code:`--centralised-eval`, as well as an option to perform " +"scaled learning rate based on the number of clients by setting :code" +":`--scaled-lr`." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1148 +msgid "We also have an argument parser for simulation:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1226 +msgid "This integrates all arguments for both client and server sides." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1229 +#, fuzzy +msgid "Example commands" +msgstr "Exemples de PyTorch" + +#: ../../source/tutorial-quickstart-xgboost.rst:1231 +msgid "" +"To run a centralised evaluated experiment with bagging strategy on 5 " +"clients with exponential distribution for 50 rounds, we first start the " +"server as below:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1238 +#, fuzzy +msgid "Then, on each client terminal, we start the clients:" +msgstr "Ouvre un autre terminal et démarre le deuxième client :" + +#: ../../source/tutorial-quickstart-xgboost.rst:1244 +msgid "To run the same experiment with Flower simulation:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1250 +#, fuzzy +msgid "" +"The full `code `_ for this comprehensive example can be found in" +" :code:`examples/xgboost-comprehensive`." +msgstr "" +"Félicitations ! Tu as réussi à construire et à faire fonctionner ton " +"premier système d'apprentissage fédéré. Le code source complet " +"`_ de cet exemple se trouve dans :code:`examples" +"/quickstart-mxnet`." + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:9 +#, fuzzy +msgid "Build a strategy from scratch" +msgstr "Élaborer une stratégie à partir de zéro" + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:11 +#, fuzzy +msgid "" +"Welcome to the third part of the Flower federated learning tutorial. In " +"previous parts of this tutorial, we introduced federated learning with " +"PyTorch and Flower (`part 1 `__) and we learned how strategies " +"can be used to customize the execution on both the server and the clients" +" (`part 2 `__)." +msgstr "" +"Bienvenue dans la troisième partie du tutoriel sur l'apprentissage fédéré" +" Flower. Dans les parties précédentes de ce tutoriel, nous avons présenté" +" l'apprentissage fédéré avec PyTorch et Flower (`partie 1 " +"`__) " +"et nous avons appris comment les stratégies peuvent être utilisées pour " +"personnaliser l'exécution à la fois sur le serveur et sur les clients " +"(`partie 2 `__)." + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:13 +msgid "" +"In this notebook, we'll continue to customize the federated learning " +"system we built previously by creating a custom version of FedAvg (again," +" using `Flower `__ and `PyTorch " +"`__)." +msgstr "" +"Dans ce carnet, nous allons continuer à personnaliser le système " +"d'apprentissage fédéré que nous avons construit précédemment en créant " +"une version personnalisée de FedAvg (encore une fois, en utilisant " +"`Flower `__ et `PyTorch `__)." + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:15 +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:16 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:15 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:15 +msgid "" +"`Star Flower on GitHub `__ ⭐️ and join " +"the Flower community on Slack to connect, ask questions, and get help: " +"`Join Slack `__ 🌼 We'd love to hear from " +"you in the ``#introductions`` channel! And if anything is unclear, head " +"over to the ``#questions`` channel." +msgstr "" +"`Star Flower on GitHub `__ ⭐️ et " +"rejoignez la communauté Flower sur Slack pour vous connecter, poser des " +"questions et obtenir de l'aide : `Join Slack `__ 🌼 Nous serions ravis d'avoir de vos nouvelles dans le canal " +"``#introductions`` ! Et si quelque chose n'est pas clair, rendez-vous sur" +" le canal ``#questions``." + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:17 +msgid "Let's build a new ``Strategy`` from scratch!" +msgstr "Construisons une nouvelle ``Stratégie`` à partir de zéro !" + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:29 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:29 +msgid "Preparation" +msgstr "Préparation" + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:31 +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:32 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:31 +msgid "" +"Before we begin with the actual code, let's make sure that we have " +"everything we need." +msgstr "" +"Avant de commencer le code proprement dit, assurons-nous que nous " +"disposons de tout ce dont nous avons besoin." + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:43 +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:44 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:43 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:43 +msgid "Installing dependencies" +msgstr "Installation des dépendances" + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:45 +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:46 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:45 +msgid "First, we install the necessary packages:" +msgstr "Tout d'abord, nous installons les paquets nécessaires :" + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:65 +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:66 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:65 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:65 +msgid "" +"Now that we have all dependencies installed, we can import everything we " +"need for this tutorial:" +msgstr "" +"Maintenant que toutes les dépendances sont installées, nous pouvons " +"importer tout ce dont nous avons besoin pour ce tutoriel :" + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:101 +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:102 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:101 +msgid "" +"It is possible to switch to a runtime that has GPU acceleration enabled " +"(on Google Colab: ``Runtime > Change runtime type > Hardware acclerator: " +"GPU > Save``). Note, however, that Google Colab is not always able to " +"offer GPU acceleration. If you see an error related to GPU availability " +"in one of the following sections, consider switching back to CPU-based " +"execution by setting ``DEVICE = torch.device(\"cpu\")``. If the runtime " +"has GPU acceleration enabled, you should see the output ``Training on " +"cuda``, otherwise it'll say ``Training on cpu``." +msgstr "" +"Il est possible de passer à un runtime dont l'accélération GPU est " +"activée (sur Google Colab : ``Runtime > Change runtime type > Hardware " +"acclerator : GPU > Save``). Note cependant que Google Colab n'est pas " +"toujours en mesure de proposer l'accélération GPU. Si tu vois une erreur " +"liée à la disponibilité du GPU dans l'une des sections suivantes, " +"envisage de repasser à une exécution basée sur le CPU en définissant " +"``DEVICE = torch.device(\"cpu\")``. Si le runtime a activé l'accélération" +" GPU, tu devrais voir apparaître le résultat ``Training on cuda``, sinon " +"il dira ``Training on cpu``." + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:114 +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:115 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:114 +msgid "Data loading" +msgstr "Chargement des données" + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:116 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:116 +msgid "" +"Let's now load the CIFAR-10 training and test set, partition them into " +"ten smaller datasets (each split into training and validation set), and " +"wrap everything in their own ``DataLoader``. We introduce a new parameter" +" ``num_clients`` which allows us to call ``load_datasets`` with different" +" numbers of clients." +msgstr "" +"Chargeons maintenant les ensembles d'entraînement et de test CIFAR-10, " +"divisons-les en dix ensembles de données plus petits (chacun divisé en " +"ensemble d'entraînement et de validation), et enveloppons le tout dans " +"leur propre ``DataLoader``. Nous introduisons un nouveau paramètre " +"``num_clients`` qui nous permet d'appeler ``load_datasets`` avec " +"différents nombres de clients." + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:167 +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:168 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:167 +msgid "Model training/evaluation" +msgstr "Formation/évaluation du modèle" + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:169 +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:170 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:169 +msgid "" +"Let's continue with the usual model definition (including " +"``set_parameters`` and ``get_parameters``), training and test functions:" +msgstr "" +"Continuons avec la définition habituelle du modèle (y compris " +"``set_parameters`` et ``get_parameters``), les fonctions d'entraînement " +"et de test :" + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:258 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:258 +msgid "Flower client" +msgstr "Client de Flower" + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:260 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:260 +msgid "" +"To implement the Flower client, we (again) create a subclass of " +"``flwr.client.NumPyClient`` and implement the three methods " +"``get_parameters``, ``fit``, and ``evaluate``. Here, we also pass the " +"``cid`` to the client and use it log additional details:" +msgstr "" +"Pour mettre en œuvre le client Flower, nous créons (à nouveau) une sous-" +"classe de ``flwr.client.NumPyClient`` et mettons en œuvre les trois " +"méthodes ``get_parameters``, ``fit`` et ``evaluate``. Ici, nous " +"transmettons également le ``cid`` au client et l'utilisons pour consigner" +" des détails supplémentaires :" + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:308 +msgid "Let's test what we have so far before we continue:" +msgstr "Testons ce que nous avons jusqu'à présent avant de continuer :" + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:339 +msgid "Build a Strategy from scratch" +msgstr "Élaborer une stratégie à partir de zéro" + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:341 +msgid "" +"Let’s overwrite the ``configure_fit`` method such that it passes a higher" +" learning rate (potentially also other hyperparameters) to the optimizer " +"of a fraction of the clients. We will keep the sampling of the clients as" +" it is in ``FedAvg`` and then change the configuration dictionary (one of" +" the ``FitIns`` attributes)." +msgstr "" +"Remplaçons la méthode ``configure_fit`` de façon à ce qu'elle transmette " +"un taux d'apprentissage plus élevé (potentiellement aussi d'autres " +"hyperparamètres) à l'optimiseur d'une fraction des clients. Nous " +"garderons l'échantillonnage des clients tel qu'il est dans ``FedAvg`` et " +"changerons ensuite le dictionnaire de configuration (l'un des attributs " +"``FitIns``)." + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:507 +msgid "" +"The only thing left is to use the newly created custom Strategy " +"``FedCustom`` when starting the experiment:" +msgstr "" +"Il ne reste plus qu'à utiliser la stratégie personnalisée nouvellement " +"créée ``FedCustom`` lors du démarrage de l'expérience :" + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:534 +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:932 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:697 +msgid "Recap" +msgstr "Récapitulation" + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:536 +msgid "" +"In this notebook, we’ve seen how to implement a custom strategy. A custom" +" strategy enables granular control over client node configuration, result" +" aggregation, and more. To define a custom strategy, you only have to " +"overwrite the abstract methods of the (abstract) base class ``Strategy``." +" To make custom strategies even more powerful, you can pass custom " +"functions to the constructor of your new class (``__init__``) and then " +"call these functions whenever needed." +msgstr "" +"Dans ce carnet, nous avons vu comment mettre en place une stratégie " +"personnalisée. Une stratégie personnalisée permet un contrôle granulaire " +"sur la configuration des nœuds clients, l'agrégation des résultats, et " +"bien plus encore. Pour définir une stratégie personnalisée, il te suffit " +"d'écraser les méthodes abstraites de la classe de base (abstraite) " +"``Strategy``. Pour rendre les stratégies personnalisées encore plus " +"puissantes, tu peux passer des fonctions personnalisées au constructeur " +"de ta nouvelle classe (``__init__``) et appeler ensuite ces fonctions à " +"chaque fois que c'est nécessaire." + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:550 +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:948 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:729 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:715 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:369 +msgid "" +"Before you continue, make sure to join the Flower community on Slack: " +"`Join Slack `__" +msgstr "" +"Avant de continuer, n'oublie pas de rejoindre la communauté Flower sur " +"Slack : `Join Slack `__" + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:552 +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:950 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:731 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:717 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:371 +msgid "" +"There's a dedicated ``#questions`` channel if you need help, but we'd " +"also love to hear who you are in ``#introductions``!" +msgstr "" +"Il existe un canal dédié aux ``questions`` si vous avez besoin d'aide, " +"mais nous aimerions aussi savoir qui vous êtes dans ``#introductions`` !" + +#: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:554 +#, fuzzy +msgid "" +"The `Flower Federated Learning Tutorial - Part 4 " +"`__ introduces ``Client``, the flexible API underlying " +"``NumPyClient``." +msgstr "" +"Le `Tutoriel d'apprentissage fédéré Flower - Partie 4 " +"`__ présente ``Client``, l'API flexible qui sous-tend " +"``NumPyClient``." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:9 +#, fuzzy +msgid "Customize the client" +msgstr "Création du client IMDBC" + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:11 +#, fuzzy +msgid "" +"Welcome to the fourth part of the Flower federated learning tutorial. In " +"the previous parts of this tutorial, we introduced federated learning " +"with PyTorch and Flower (`part 1 `__), we learned how " +"strategies can be used to customize the execution on both the server and " +"the clients (`part 2 `__), and we built our own " +"custom strategy from scratch (`part 3 `__)." +msgstr "" +"Bienvenue dans la quatrième partie du tutoriel sur l'apprentissage fédéré" +" Flower. Dans les parties précédentes de ce tutoriel, nous avons présenté" +" l'apprentissage fédéré avec PyTorch et Flower (`partie 1 " +"`__)," +" nous avons appris comment les stratégies peuvent être utilisées pour " +"personnaliser l'exécution à la fois sur le serveur et les clients " +"(`partie 2 `__), et nous avons construit notre propre stratégie " +"personnalisée à partir de zéro (`partie 3 - WIP " +"`__)." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:14 +msgid "" +"In this notebook, we revisit ``NumPyClient`` and introduce a new " +"baseclass for building clients, simply named ``Client``. In previous " +"parts of this tutorial, we've based our client on ``NumPyClient``, a " +"convenience class which makes it easy to work with machine learning " +"libraries that have good NumPy interoperability. With ``Client``, we gain" +" a lot of flexibility that we didn't have before, but we'll also have to " +"do a few things the we didn't have to do before." +msgstr "" +"Dans ce carnet, nous revisitons `NumPyClient`` et introduisons une " +"nouvelle classe de base pour construire des clients, simplement appelée " +"`Client``. Dans les parties précédentes de ce tutoriel, nous avons basé " +"notre client sur ``NumPyClient``, une classe de commodité qui facilite le" +" travail avec les bibliothèques d'apprentissage automatique qui ont une " +"bonne interopérabilité NumPy. Avec ``Client``, nous gagnons beaucoup de " +"flexibilité que nous n'avions pas auparavant, mais nous devrons également" +" faire quelques choses que nous n'avions pas à faire auparavant." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:18 +msgid "" +"Let's go deeper and see what it takes to move from ``NumPyClient`` to " +"``Client``!" +msgstr "" +"Allons plus loin et voyons ce qu'il faut faire pour passer de " +"``NumPyClient`` à ``Client`` !" + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:30 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:29 +msgid "Step 0: Preparation" +msgstr "Étape 0 : Préparation" + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:117 +msgid "" +"Let's now load the CIFAR-10 training and test set, partition them into " +"ten smaller datasets (each split into training and validation set), and " +"wrap everything in their own ``DataLoader``." +msgstr "" +"Chargeons maintenant les ensembles d'entraînement et de test CIFAR-10, " +"divisons-les en dix ensembles de données plus petits (chacun divisé en " +"ensemble d'entraînement et de validation) et enveloppons le tout dans " +"leur propre ``DataLoader``." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:259 +msgid "Step 1: Revisiting NumPyClient" +msgstr "Étape 1 : Revoir NumPyClient" + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:261 +msgid "" +"So far, we've implemented our client by subclassing " +"``flwr.client.NumPyClient``. The three methods we implemented are " +"``get_parameters``, ``fit``, and ``evaluate``. Finally, we wrap the " +"creation of instances of this class in a function called ``client_fn``:" +msgstr "" +"Jusqu'à présent, nous avons implémenté notre client en sous-classant " +"``flwr.client.NumPyClient``. Les trois méthodes que nous avons " +"implémentées sont ``get_parameters``, ``fit`` et ``evaluate``. Enfin, " +"nous enveloppons la création d'instances de cette classe dans une " +"fonction appelée ``client_fn`` :" + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:309 +msgid "" +"We've seen this before, there's nothing new so far. The only *tiny* " +"difference compared to the previous notebook is naming, we've changed " +"``FlowerClient`` to ``FlowerNumPyClient`` and ``client_fn`` to " +"``numpyclient_fn``. Let's run it to see the output we get:" +msgstr "" +"Nous avons déjà vu cela auparavant, il n'y a rien de nouveau jusqu'à " +"présent. La seule *petite* différence par rapport au carnet précédent est" +" le nommage, nous avons changé ``FlowerClient`` en ``FlowerNumPyClient`` " +"et ``client_fn`` en ``numpyclient_fn``. Exécutons-le pour voir la sortie " +"que nous obtenons :" + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:339 +msgid "" +"This works as expected, two clients are training for three rounds of " +"federated learning." +msgstr "" +"Cela fonctionne comme prévu, deux clients s'entraînent pour trois tours " +"d'apprentissage fédéré." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:341 +msgid "" +"Let's dive a little bit deeper and discuss how Flower executes this " +"simulation. Whenever a client is selected to do some work, " +"``start_simulation`` calls the function ``numpyclient_fn`` to create an " +"instance of our ``FlowerNumPyClient`` (along with loading the model and " +"the data)." +msgstr "" +"Plongeons un peu plus profondément et discutons de la façon dont Flower " +"exécute cette simulation. Chaque fois qu'un client est sélectionné pour " +"effectuer un travail, ``start_simulation`` appelle la fonction " +"``numpyclient_fn`` pour créer une instance de notre ``FlowerNumPyClient``" +" (en même temps qu'il charge le modèle et les données)." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:343 +msgid "" +"But here's the perhaps surprising part: Flower doesn't actually use the " +"``FlowerNumPyClient`` object directly. Instead, it wraps the object to " +"makes it look like a subclass of ``flwr.client.Client``, not " +"``flwr.client.NumPyClient``. In fact, the Flower core framework doesn't " +"know how to handle ``NumPyClient``'s, it only knows how to handle " +"``Client``'s. ``NumPyClient`` is just a convenience abstraction built on " +"top of ``Client``." +msgstr "" +"Mais voici la partie la plus surprenante : Flower n'utilise pas " +"directement l'objet `FlowerNumPyClient`. Au lieu de cela, il enveloppe " +"l'objet pour le faire ressembler à une sous-classe de " +"`flwr.client.Client`, et non de `flwr.client.NumPyClient`. En fait, le " +"noyau de Flower ne sait pas comment gérer les `NumPyClient`, il sait " +"seulement comment gérer les `Client`. `NumPyClient` est juste une " +"abstraction de commodité construite au dessus de `Client`." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:345 +msgid "" +"Instead of building on top of ``NumPyClient``, we can directly build on " +"top of ``Client``." +msgstr "" +"Au lieu de construire par-dessus `NumPyClient``, nous pouvons construire " +"directement par-dessus `Client``." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:357 +msgid "Step 2: Moving from ``NumPyClient`` to ``Client``" +msgstr "Étape 2 : Passer de ``NumPyClient`` à ``Client``" + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:359 +msgid "" +"Let's try to do the same thing using ``Client`` instead of " +"``NumPyClient``." +msgstr "" +"Essayons de faire la même chose en utilisant ``Client`` au lieu de " +"``NumPyClient``." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:465 +msgid "" +"Before we discuss the code in more detail, let's try to run it! Gotta " +"make sure our new ``Client``-based client works, right?" +msgstr "" +"Avant de discuter du code plus en détail, essayons de l'exécuter ! Nous " +"devons nous assurer que notre nouveau client basé sur le ``Client`` " +"fonctionne, n'est-ce pas ?" + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:490 +msgid "" +"That's it, we're now using ``Client``. It probably looks similar to what " +"we've done with ``NumPyClient``. So what's the difference?" +msgstr "" +"Voilà, nous utilisons maintenant ``Client``. Cela ressemble probablement " +"à ce que nous avons fait avec ``NumPyClient``. Alors quelle est la " +"différence ?" + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:492 +msgid "" +"First of all, it's more code. But why? The difference comes from the fact" +" that ``Client`` expects us to take care of parameter serialization and " +"deserialization. For Flower to be able to send parameters over the " +"network, it eventually needs to turn these parameters into ``bytes``. " +"Turning parameters (e.g., NumPy ``ndarray``'s) into raw bytes is called " +"serialization. Turning raw bytes into something more useful (like NumPy " +"``ndarray``'s) is called deserialization. Flower needs to do both: it " +"needs to serialize parameters on the server-side and send them to the " +"client, the client needs to deserialize them to use them for local " +"training, and then serialize the updated parameters again to send them " +"back to the server, which (finally!) deserializes them again in order to " +"aggregate them with the updates received from other clients." +msgstr "" +"First of all, it's more code. But why? The difference comes from the fact" +" that ``Client`` expects us to take care of parameter serialization and " +"deserialization. For Flower to be able to send parameters over the " +"network, it eventually needs to turn these parameters into ``bytes``. " +"Turning parameters (e.g., NumPy ``ndarray``'s) into raw bytes is called " +"serialization. Turning raw bytes into something more useful (like NumPy " +"``ndarray``'s) is called deserialization. Flower needs to do both: it " +"needs to serialize parameters on the server-side and send them to the " +"client, the client needs to deserialize them to use them for local " +"training, and then serialize the updated parameters again to send them " +"back to the server, which (finally!) deserializes them again in order to " +"aggregate them with the updates received from other clients." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:495 +msgid "" +"The only *real* difference between Client and NumPyClient is that " +"NumPyClient takes care of serialization and deserialization for you. It " +"can do so because it expects you to return parameters as NumPy ndarray's," +" and it knows how to handle these. This makes working with machine " +"learning libraries that have good NumPy support (most of them) a breeze." +msgstr "" +"La seule *vraie* différence entre Client et NumPyClient est que " +"NumPyClient s'occupe de la sérialisation et de la désérialisation pour " +"toi. Il peut le faire parce qu'il s'attend à ce que tu renvoies des " +"paramètres sous forme de NumPy ndarray, et il sait comment les gérer. " +"Cela permet de travailler avec des bibliothèques d'apprentissage " +"automatique qui ont une bonne prise en charge de NumPy (la plupart " +"d'entre elles) en un clin d'œil." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:497 +msgid "" +"In terms of API, there's one major difference: all methods in Client take" +" exactly one argument (e.g., ``FitIns`` in ``Client.fit``) and return " +"exactly one value (e.g., ``FitRes`` in ``Client.fit``). The methods in " +"``NumPyClient`` on the other hand have multiple arguments (e.g., " +"``parameters`` and ``config`` in ``NumPyClient.fit``) and multiple return" +" values (e.g., ``parameters``, ``num_example``, and ``metrics`` in " +"``NumPyClient.fit``) if there are multiple things to handle. These " +"``*Ins`` and ``*Res`` objects in ``Client`` wrap all the individual " +"values you're used to from ``NumPyClient``." +msgstr "" +"In terms of API, there's one major difference: all methods in Client take" +" exactly one argument (e.g., ``FitIns`` in ``Client.fit``) and return " +"exactly one value (e.g., ``FitRes`` in ``Client.fit``). The methods in " +"``NumPyClient`` on the other hand have multiple arguments (e.g., " +"``parameters`` and ``config`` in ``NumPyClient.fit``) and multiple return" +" values (e.g., ``parameters``, ``num_example``, and ``metrics`` in " +"``NumPyClient.fit``) if there are multiple things to handle. These " +"``*Ins`` and ``*Res`` objects in ``Client`` wrap all the individual " +"values you're used to from ``NumPyClient``." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:510 +msgid "Step 3: Custom serialization" +msgstr "Étape 3 : Sérialisation personnalisée" + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:512 +msgid "" +"Here we will explore how to implement custom serialization with a simple " +"example." +msgstr "" +"Nous allons ici explorer comment mettre en œuvre une sérialisation " +"personnalisée à l'aide d'un exemple simple." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:514 +msgid "" +"But first what is serialization? Serialization is just the process of " +"converting an object into raw bytes, and equally as important, " +"deserialization is the process of converting raw bytes back into an " +"object. This is very useful for network communication. Indeed, without " +"serialization, you could not just a Python object through the internet." +msgstr "" +"Mais d'abord, qu'est-ce que la sérialisation ? La sérialisation est " +"simplement le processus de conversion d'un objet en octets bruts, et tout" +" aussi important, la désérialisation est le processus de reconversion des" +" octets bruts en objet. Ceci est très utile pour la communication réseau." +" En effet, sans la sérialisation, tu ne pourrais pas faire passer un " +"objet Python par Internet." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:516 +msgid "" +"Federated Learning relies heavily on internet communication for training " +"by sending Python objects back and forth between the clients and the " +"server. This means that serialization is an essential part of Federated " +"Learning." +msgstr "" +"L'apprentissage fédéré s'appuie fortement sur la communication Internet " +"pour la formation en envoyant des objets Python dans les deux sens entre " +"les clients et le serveur, ce qui signifie que la sérialisation est un " +"élément essentiel de l'apprentissage fédéré." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:518 +msgid "" +"In the following section, we will write a basic example where instead of " +"sending a serialized version of our ``ndarray``\\ s containing our " +"parameters, we will first convert the ``ndarray`` into sparse matrices, " +"before sending them. This technique can be used to save bandwidth, as in " +"certain cases where the weights of a model are sparse (containing many 0 " +"entries), converting them to a sparse matrix can greatly improve their " +"bytesize." +msgstr "" +"Dans la section suivante, nous allons écrire un exemple de base où, au " +"lieu d'envoyer une version sérialisée de nos ``ndarray`` contenant nos " +"paramètres, nous allons d'abord convertir les ``ndarray`` en matrices " +"éparses, avant de les envoyer. Cette technique peut être utilisée pour " +"économiser de la bande passante, car dans certains cas où les poids d'un " +"modèle sont épars (contenant de nombreuses entrées 0), les convertir en " +"une matrice éparse peut grandement améliorer leur taille en octets." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:521 +msgid "Our custom serialization/deserialization functions" +msgstr "Nos fonctions de sérialisation/désérialisation personnalisées" + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:523 +msgid "" +"This is where the real serialization/deserialization will happen, " +"especially in ``ndarray_to_sparse_bytes`` for serialization and " +"``sparse_bytes_to_ndarray`` for deserialization." +msgstr "" +"C'est là que la véritable sérialisation/désérialisation se produira, en " +"particulier dans ``ndarray_to_sparse_bytes`` pour la sérialisation et " +"``sparse_bytes_to_ndarray`` pour la désérialisation." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:525 +msgid "" +"Note that we imported the ``scipy.sparse`` library in order to convert " +"our arrays." +msgstr "" +"Notez que nous avons importé la bibliothèque ``scipy.sparse`` afin de " +"convertir nos tableaux." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:613 +msgid "Client-side" +msgstr "Côté client" + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:615 +msgid "" +"To be able to able to serialize our ``ndarray``\\ s into sparse " +"parameters, we will just have to call our custom functions in our " +"``flwr.client.Client``." +msgstr "" +"Pour pouvoir sérialiser nos ``ndarray`` en paramètres sparse, il nous " +"suffira d'appeler nos fonctions personnalisées dans notre " +"``flwr.client.Client``." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:617 +msgid "" +"Indeed, in ``get_parameters`` we need to serialize the parameters we got " +"from our network using our custom ``ndarrays_to_sparse_parameters`` " +"defined above." +msgstr "" +"En effet, dans ``get_parameters`` nous devons sérialiser les paramètres " +"que nous avons obtenus de notre réseau en utilisant nos " +"``ndarrays_to_sparse_parameters`` personnalisés définis ci-dessus." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:619 +msgid "" +"In ``fit``, we first need to deserialize the parameters coming from the " +"server using our custom ``sparse_parameters_to_ndarrays`` and then we " +"need to serialize our local results with " +"``ndarrays_to_sparse_parameters``." +msgstr "" +"Dans ``fit``, nous devons d'abord désérialiser les paramètres provenant " +"du serveur en utilisant notre ``sparse_parameters_to_ndarrays`` " +"personnalisé, puis nous devons sérialiser nos résultats locaux avec " +"``ndarrays_to_sparse_parameters``." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:621 +msgid "" +"In ``evaluate``, we will only need to deserialize the global parameters " +"with our custom function." +msgstr "" +"Dans ``evaluate``, nous n'aurons besoin que de désérialiser les " +"paramètres globaux avec notre fonction personnalisée." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:725 +msgid "Server-side" +msgstr "Côté serveur" + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:727 +msgid "" +"For this example, we will just use ``FedAvg`` as a strategy. To change " +"the serialization and deserialization here, we only need to reimplement " +"the ``evaluate`` and ``aggregate_fit`` functions of ``FedAvg``. The other" +" functions of the strategy will be inherited from the super class " +"``FedAvg``." +msgstr "" +"Pour cet exemple, nous utiliserons simplement ``FedAvg`` comme stratégie." +" Pour modifier la sérialisation et la désérialisation ici, il suffit de " +"réimplémenter les fonctions ``evaluate`` et ``aggregate_fit`` de " +"``FedAvg``. Les autres fonctions de la stratégie seront héritées de la " +"super-classe ``FedAvg``." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:729 +msgid "As you can see only one line as change in ``evaluate``:" +msgstr "Comme tu peux le voir, seule une ligne a été modifiée dans ``evaluate`` :" + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:735 +msgid "" +"And for ``aggregate_fit``, we will first deserialize every result we " +"received:" +msgstr "" +"Et pour ``aggregate_fit``, nous allons d'abord désérialiser chaque " +"résultat que nous avons reçu :" + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:744 +msgid "And then serialize the aggregated result:" +msgstr "Puis sérialise le résultat agrégé :" + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:903 +msgid "We can now run our custom serialization example!" +msgstr "" +"Nous pouvons maintenant exécuter notre exemple de sérialisation " +"personnalisée !" + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:934 +msgid "" +"In this part of the tutorial, we've seen how we can build clients by " +"subclassing either ``NumPyClient`` or ``Client``. ``NumPyClient`` is a " +"convenience abstraction that makes it easier to work with machine " +"learning libraries that have good NumPy interoperability. ``Client`` is a" +" more flexible abstraction that allows us to do things that are not " +"possible in ``NumPyClient``. In order to do so, it requires us to handle " +"parameter serialization and deserialization ourselves." +msgstr "" +"Dans cette partie du tutoriel, nous avons vu comment construire des " +"clients en sous-classant soit ``NumPyClient``, soit ``Client``. " +"``NumPyClient`` est une abstraction de commodité qui facilite le travail " +"avec les bibliothèques d'apprentissage automatique qui ont une bonne " +"interopérabilité NumPy. ``Client`` est une abstraction plus flexible qui " +"nous permet de faire des choses qui ne sont pas possibles dans " +"``NumPyClient``. Pour ce faire, elle nous oblige à gérer nous-mêmes la " +"sérialisation et la désérialisation des paramètres." + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:952 +msgid "" +"This is the final part of the Flower tutorial (for now!), " +"congratulations! You're now well equipped to understand the rest of the " +"documentation. There are many topics we didn't cover in the tutorial, we " +"recommend the following resources:" +msgstr "" +"C'est la dernière partie du tutoriel Flower (pour l'instant !), " +"félicitations ! Tu es maintenant bien équipé pour comprendre le reste de " +"la documentation. Il y a de nombreux sujets que nous n'avons pas abordés " +"dans le tutoriel, nous te recommandons les ressources suivantes :" + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:954 +msgid "`Read Flower Docs `__" +msgstr "`Lire les docs sur les fleurs `__" + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:955 +msgid "" +"`Check out Flower Code Examples " +"`__" +msgstr "" +"`Check out Flower Code Examples " +"`__" + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:956 +#, fuzzy +msgid "" +"`Use Flower Baselines for your research " +"`__" +msgstr "" +"`Utilise les lignes de base des fleurs pour ta recherche " +"`__" + +#: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:957 +#, fuzzy +msgid "" +"`Watch Flower Summit 2023 videos `__" +msgstr "" +"`Regardez les vidéos du Flower Summit 2022 `__" + +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:9 +msgid "Get started with Flower" +msgstr "" + +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:11 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:11 +msgid "Welcome to the Flower federated learning tutorial!" +msgstr "Bienvenue au tutoriel sur l'apprentissage fédéré de la fleur !" + +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:13 +#, fuzzy +msgid "" +"In this notebook, we'll build a federated learning system using Flower, " +"`Flower Datasets `__ and PyTorch. In " +"part 1, we use PyTorch for the model training pipeline and data loading. " +"In part 2, we continue to federate the PyTorch-based pipeline using " +"Flower." +msgstr "" +"Dans ce carnet, nous allons construire un système d'apprentissage fédéré " +"en utilisant Flower et PyTorch. Dans la première partie, nous utilisons " +"PyTorch pour le pipeline d'entraînement des modèles et le chargement des " +"données. Dans la deuxième partie, nous continuons à fédérer le pipeline " +"basé sur PyTorch en utilisant Flower." + +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:17 +msgid "Let's get stated!" +msgstr "Allons-y, déclarons-le !" + +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:31 +msgid "" +"Before we begin with any actual code, let's make sure that we have " +"everything we need." +msgstr "" +"Avant de commencer à coder, assurons-nous que nous disposons de tout ce " +"dont nous avons besoin." + +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:45 +#, fuzzy +msgid "" +"Next, we install the necessary packages for PyTorch (``torch`` and " +"``torchvision``), Flower Datasets (``flwr-datasets``) and Flower " +"(``flwr``):" +msgstr "" +"Ensuite, nous installons les paquets nécessaires pour PyTorch (``torch`` " +"et ``torchvision``) et Flower (``flwr``) :" + +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:105 +#, fuzzy +msgid "" +"It is possible to switch to a runtime that has GPU acceleration enabled " +"(on Google Colab: ``Runtime > Change runtime type > Hardware accelerator:" +" GPU > Save``). Note, however, that Google Colab is not always able to " +"offer GPU acceleration. If you see an error related to GPU availability " +"in one of the following sections, consider switching back to CPU-based " +"execution by setting ``DEVICE = torch.device(\"cpu\")``. If the runtime " +"has GPU acceleration enabled, you should see the output ``Training on " +"cuda``, otherwise it'll say ``Training on cpu``." +msgstr "" +"Il est possible de passer à un runtime dont l'accélération GPU est " +"activée (sur Google Colab : ``Runtime > Change runtime type > Hardware " +"acclerator : GPU > Save``). Note cependant que Google Colab n'est pas " +"toujours en mesure de proposer l'accélération GPU. Si tu vois une erreur " +"liée à la disponibilité du GPU dans l'une des sections suivantes, " +"envisage de repasser à une exécution basée sur le CPU en définissant " +"``DEVICE = torch.device(\"cpu\")``. Si le runtime a activé l'accélération" +" GPU, tu devrais voir apparaître le résultat ``Training on cuda``, sinon " +"il dira ``Training on cpu``." + +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:118 +msgid "Loading the data" +msgstr "Chargement des données" + +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:120 +#, fuzzy +msgid "" +"Federated learning can be applied to many different types of tasks across" +" different domains. In this tutorial, we introduce federated learning by " +"training a simple convolutional neural network (CNN) on the popular " +"CIFAR-10 dataset. CIFAR-10 can be used to train image classifiers that " +"distinguish between images from ten different classes: 'airplane', " +"'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', and " +"'truck'." +msgstr "" +"L'apprentissage fédéré peut être appliqué à de nombreux types de tâches " +"dans différents domaines. Dans ce tutoriel, nous présentons " +"l'apprentissage fédéré en formant un simple réseau neuronal " +"convolutionnel (CNN) sur l'ensemble de données populaire CIFAR-10. " +"CIFAR-10 peut être utilisé pour former des classificateurs d'images qui " +"font la distinction entre les images de dix classes différentes :" + +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:131 +msgid "" +"We simulate having multiple datasets from multiple organizations (also " +"called the \"cross-silo\" setting in federated learning) by splitting the" +" original CIFAR-10 dataset into multiple partitions. Each partition will " +"represent the data from a single organization. We're doing this purely " +"for experimentation purposes, in the real world there's no need for data " +"splitting because each organization already has their own data (so the " +"data is naturally partitioned)." +msgstr "" +"Nous simulons le fait d'avoir plusieurs ensembles de données provenant de" +" plusieurs organisations (également appelé le paramètre \"cross-silo\" " +"dans l'apprentissage fédéré) en divisant l'ensemble de données CIFAR-10 " +"original en plusieurs partitions. Chaque partition représentera les " +"données d'une seule organisation. Nous faisons cela purement à des fins " +"d'expérimentation, dans le monde réel, il n'y a pas besoin de diviser les" +" données parce que chaque organisation a déjà ses propres données (les " +"données sont donc naturellement partitionnées)." -#: ../../source/tutorial-quickstart-pytorch.rst:268 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:133 #, fuzzy msgid "" -"Congratulations! You've successfully built and run your first federated " -"learning system. The full `source code " -"`_ for this example can be found in :code:`examples" -"/quickstart-pytorch`." +"Each organization will act as a client in the federated learning system. " +"So having ten organizations participate in a federation means having ten " +"clients connected to the federated learning server." msgstr "" -"Félicitations ! Tu as réussi à construire et à faire fonctionner ton " -"premier système d'apprentissage fédéré. Le code source complet " -"`_ de cet exemple se trouve dans :code:`examples" -"/quickstart-pytorch`." - -#: ../../source/tutorial-quickstart-pytorch-lightning.rst:5 -msgid "Quickstart PyTorch Lightning" -msgstr "Démarrage rapide de PyTorch Lightning" +"Chaque organisation agira comme un client dans le système d'apprentissage" +" fédéré. Ainsi, le fait que dix organisations participent à une " +"fédération signifie que dix clients sont connectés au serveur " +"d'apprentissage fédéré :" -#: ../../source/tutorial-quickstart-pytorch-lightning.rst:7 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:144 msgid "" -"Let's build a federated learning system using PyTorch Lightning and " -"Flower!" +"Let's now create the Federated Dataset abstraction that from ``flwr-" +"datasets`` that partitions the CIFAR-10. We will create small training " +"and test set for each edge device and wrap each of them into a PyTorch " +"``DataLoader``:" msgstr "" -"Construisons un système d'apprentissage fédéré en utilisant PyTorch " -"Lightning et Flower !" -#: ../../source/tutorial-quickstart-pytorch-lightning.rst:9 -#, fuzzy +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:198 msgid "" -"Please refer to the `full code example " -"`_ to learn more." +"We now have a list of ten training sets and ten validation sets " +"(``trainloaders`` and ``valloaders``) representing the data of ten " +"different organizations. Each ``trainloader``/``valloader`` pair contains" +" 4500 training examples and 500 validation examples. There's also a " +"single ``testloader`` (we did not split the test set). Again, this is " +"only necessary for building research or educational systems, actual " +"federated learning systems have their data naturally distributed across " +"multiple partitions." msgstr "" -"Réfère-toi à l'exemple de code complet " -"`_ pour en savoir plus." - -#: ../../source/tutorial-quickstart-scikitlearn.rst:5 -msgid "Quickstart scikit-learn" -msgstr "Démarrage rapide de scikit-learn" +"Nous avons maintenant une liste de dix ensembles de formation et dix " +"ensembles de validation (``trainloaders`` et ``valloaders``) représentant" +" les données de dix organisations différentes. Chaque paire " +"``trainloader`/``valloader`` contient 4500 exemples de formation et 500 " +"exemples de validation. Il y a également un seul ``testloader`` (nous " +"n'avons pas divisé l'ensemble de test). Encore une fois, cela n'est " +"nécessaire que pour construire des systèmes de recherche ou d'éducation, " +"les systèmes d'apprentissage fédérés actuels ont leurs données " +"naturellement distribuées à travers plusieurs partitions." -#: ../../source/tutorial-quickstart-scikitlearn.rst:7 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:201 msgid "" -"In this tutorial, we will learn how to train a :code:`Logistic " -"Regression` model on MNIST using Flower and scikit-learn." +"Let's take a look at the first batch of images and labels in the first " +"training set (i.e., ``trainloaders[0]``) before we move on:" msgstr "" -"Dans ce tutoriel, nous allons apprendre à former un :code:`modèle de " -"régression logistique` sur MNIST en utilisant Flower et scikit-learn." +"Jetons un coup d'œil au premier lot d'images et d'étiquettes du premier " +"ensemble d'entraînement (c'est-à-dire ``trainloaders[0]``) avant de " +"poursuivre :" -#: ../../source/tutorial-quickstart-scikitlearn.rst:23 -msgid "Since we want to use scikt-learn, let's go ahead and install it:" -msgstr "Puisque nous voulons utiliser scikt-learn, allons-y et installons-le :" +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:240 +msgid "" +"The output above shows a random batch of images from the first " +"``trainloader`` in our list of ten ``trainloaders``. It also prints the " +"labels associated with each image (i.e., one of the ten possible labels " +"we've seen above). If you run the cell again, you should see another " +"batch of images." +msgstr "" +"La sortie ci-dessus montre un lot aléatoire d'images provenant du premier" +" ``chargeur de formation`` de notre liste de dix ``chargeurs de " +"formation``. Elle imprime également les étiquettes associées à chaque " +"image (c'est-à-dire l'une des dix étiquettes possibles que nous avons " +"vues ci-dessus). Si tu exécutes à nouveau la cellule, tu devrais voir un " +"autre lot d'images." -#: ../../source/tutorial-quickstart-scikitlearn.rst:29 -msgid "Or simply install all dependencies using Poetry:" -msgstr "Ou installe simplement toutes les dépendances à l'aide de Poetry :" +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:252 +msgid "Step 1: Centralized Training with PyTorch" +msgstr "Étape 1 : Formation centralisée avec PyTorch" -#: ../../source/tutorial-quickstart-scikitlearn.rst:39 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:263 msgid "" -"Now that we have all our dependencies installed, let's run a simple " -"distributed training with two clients and one server. However, before " -"setting up the client and server, we will define all functionalities that" -" we need for our federated learning setup within :code:`utils.py`. The " -":code:`utils.py` contains different functions defining all the machine " -"learning basics:" +"Next, we're going to use PyTorch to define a simple convolutional neural " +"network. This introduction assumes basic familiarity with PyTorch, so it " +"doesn't cover the PyTorch-related aspects in full detail. If you want to " +"dive deeper into PyTorch, we recommend `DEEP LEARNING WITH PYTORCH: A 60 " +"MINUTE BLITZ " +"`__." msgstr "" -"Maintenant que toutes nos dépendances sont installées, exécutons une " -"formation distribuée simple avec deux clients et un serveur. Cependant, " -"avant de configurer le client et le serveur, nous allons définir toutes " -"les fonctionnalités dont nous avons besoin pour notre configuration " -"d'apprentissage fédéré dans :code:`utils.py`. Le :code:`utils.py` " -"contient différentes fonctions définissant toutes les bases de " -"l'apprentissage automatique :" +"Ensuite, nous allons utiliser PyTorch pour définir un simple réseau " +"neuronal convolutif. Cette introduction suppose une familiarité de base " +"avec PyTorch, elle ne couvre donc pas en détail les aspects liés à " +"PyTorch. Si tu veux plonger plus profondément dans PyTorch, nous te " +"recommandons `DEEP LEARNING WITH PYTORCH : A 60 MINUTE BLITZ " +"`__." -#: ../../source/tutorial-quickstart-scikitlearn.rst:42 -msgid ":code:`get_model_parameters()`" -msgstr ":code:`get_model_parameters()`" +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:275 +msgid "Defining the model" +msgstr "Définir le modèle" -#: ../../source/tutorial-quickstart-scikitlearn.rst:43 -msgid "Returns the paramters of a :code:`sklearn` LogisticRegression model" +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:277 +msgid "" +"We use the simple CNN described in the `PyTorch tutorial " +"`__:" msgstr "" -"Renvoie les paramètres d'un modèle de régression logistique " -":code:`sklearn`" +"Nous utilisons le CNN simple décrit dans le tutoriel `PyTorch " +"`__ :" -#: ../../source/tutorial-quickstart-scikitlearn.rst:44 -msgid ":code:`set_model_params()`" -msgstr ":code:`set_model_params()`" +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:314 +msgid "Let's continue with the usual training and test functions:" +msgstr "Poursuivons avec les fonctions habituelles de formation et de test :" -#: ../../source/tutorial-quickstart-scikitlearn.rst:45 -msgid "Sets the parameters of a :code:`sklean` LogisticRegression model" -msgstr "Définit les paramètres d'un modèle de régression logistique :code:`sklean`" +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:374 +msgid "Training the model" +msgstr "Entraîne le modèle" -#: ../../source/tutorial-quickstart-scikitlearn.rst:46 -msgid ":code:`set_initial_params()`" -msgstr ":code:`set_initial_params()`" +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:376 +msgid "" +"We now have all the basic building blocks we need: a dataset, a model, a " +"training function, and a test function. Let's put them together to train " +"the model on the dataset of one of our organizations " +"(``trainloaders[0]``). This simulates the reality of most machine " +"learning projects today: each organization has their own data and trains " +"models only on this internal data:" +msgstr "" +"Nous avons maintenant tous les éléments de base dont nous avons besoin : " +"un ensemble de données, un modèle, une fonction d'entraînement et une " +"fonction de test. Assemblons-les pour entraîner le modèle sur l'ensemble " +"de données de l'une de nos organisations (``trainloaders[0]``). Cela " +"simule la réalité de la plupart des projets d'apprentissage automatique " +"aujourd'hui : chaque organisation possède ses propres données et entraîne" +" les modèles uniquement sur ces données internes :" -#: ../../source/tutorial-quickstart-scikitlearn.rst:47 -msgid "Initializes the model parameters that the Flower server will ask for" -msgstr "Initialise les paramètres du modèle que le serveur de Flower demandera" +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:406 +msgid "" +"Training the simple CNN on our CIFAR-10 split for 5 epochs should result " +"in a test set accuracy of about 41%, which is not good, but at the same " +"time, it doesn't really matter for the purposes of this tutorial. The " +"intent was just to show a simplistic centralized training pipeline that " +"sets the stage for what comes next - federated learning!" +msgstr "" +"L'entraînement du CNN simple sur notre fractionnement CIFAR-10 pendant 5 " +"époques devrait se traduire par une précision de l'ensemble de test " +"d'environ 41 %, ce qui n'est pas bon, mais en même temps, cela n'a pas " +"vraiment d'importance pour les besoins de ce tutoriel. L'intention était " +"juste de montrer un pipeline d'entraînement centralisé simpliste qui " +"prépare le terrain pour ce qui vient ensuite - l'apprentissage fédéré !" -#: ../../source/tutorial-quickstart-scikitlearn.rst:48 -msgid ":code:`load_mnist()`" -msgstr ":code:`load_mnist()`" +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:418 +msgid "Step 2: Federated Learning with Flower" +msgstr "Étape 2 : Apprentissage fédéré avec Flower" -#: ../../source/tutorial-quickstart-scikitlearn.rst:49 -msgid "Loads the MNIST dataset using OpenML" -msgstr "Charge l'ensemble de données MNIST à l'aide d'OpenML" +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:420 +msgid "" +"Step 1 demonstrated a simple centralized training pipeline. All data was " +"in one place (i.e., a single ``trainloader`` and a single ``valloader``)." +" Next, we'll simulate a situation where we have multiple datasets in " +"multiple organizations and where we train a model over these " +"organizations using federated learning." +msgstr "" +"L'étape 1 a montré un simple pipeline de formation centralisé. Toutes les" +" données étaient au même endroit (c'est-à-dire un seul ``trainloader`` et" +" un seul ``valloader``). Ensuite, nous allons simuler une situation où " +"nous avons plusieurs ensembles de données dans plusieurs organisations et" +" où nous formons un modèle sur ces organisations à l'aide de " +"l'apprentissage fédéré." -#: ../../source/tutorial-quickstart-scikitlearn.rst:50 -msgid ":code:`shuffle()`" -msgstr ":code:`shuffle()`" +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:432 +msgid "Updating model parameters" +msgstr "Mise à jour des paramètres du modèle" -#: ../../source/tutorial-quickstart-scikitlearn.rst:51 -msgid "Shuffles data and its label" -msgstr "Mélange les données et leur étiquette" +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:434 +msgid "" +"In federated learning, the server sends the global model parameters to " +"the client, and the client updates the local model with the parameters " +"received from the server. It then trains the model on the local data " +"(which changes the model parameters locally) and sends the " +"updated/changed model parameters back to the server (or, alternatively, " +"it sends just the gradients back to the server, not the full model " +"parameters)." +msgstr "" +"Dans l'apprentissage fédéré, le serveur envoie les paramètres du modèle " +"global au client, et le client met à jour le modèle local avec les " +"paramètres reçus du serveur. Il entraîne ensuite le modèle sur les " +"données locales (ce qui modifie les paramètres du modèle localement) et " +"renvoie les paramètres du modèle mis à jour/changés au serveur (ou, " +"alternativement, il renvoie seulement les gradients au serveur, et non " +"pas les paramètres complets du modèle)." -#: ../../source/tutorial-quickstart-scikitlearn.rst:53 -msgid ":code:`partition()`" -msgstr ":code:`partition()`" +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:436 +msgid "" +"We need two helper functions to update the local model with parameters " +"received from the server and to get the updated model parameters from the" +" local model: ``set_parameters`` and ``get_parameters``. The following " +"two functions do just that for the PyTorch model above." +msgstr "" +"Nous avons besoin de deux fonctions d'aide pour mettre à jour le modèle " +"local avec les paramètres reçus du serveur et pour obtenir les paramètres" +" mis à jour du modèle local : ``set_parameters`` et ``get_parameters``. " +"Les deux fonctions suivantes font exactement cela pour le modèle PyTorch " +"ci-dessus." + +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:438 +msgid "" +"The details of how this works are not really important here (feel free to" +" consult the PyTorch documentation if you want to learn more). In " +"essence, we use ``state_dict`` to access PyTorch model parameter tensors." +" The parameter tensors are then converted to/from a list of NumPy " +"ndarray's (which Flower knows how to serialize/deserialize):" +msgstr "" +"Les détails de ce fonctionnement ne sont pas vraiment importants ici " +"(n'hésite pas à consulter la documentation PyTorch si tu veux en savoir " +"plus). En substance, nous utilisons ``state_dict`` pour accéder aux " +"tenseurs de paramètres du modèle PyTorch. Les tenseurs de paramètres sont" +" ensuite convertis en/depuis une liste de ndarray NumPy (que Flower sait " +"sérialiser/désérialiser) :" -#: ../../source/tutorial-quickstart-scikitlearn.rst:53 -msgid "Splits datasets into a number of partitions" -msgstr "Divise les ensembles de données en un certain nombre de partitions" +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:466 +msgid "Implementing a Flower client" +msgstr "Mise en place d'un client Flower" -#: ../../source/tutorial-quickstart-scikitlearn.rst:55 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:468 msgid "" -"Please check out :code:`utils.py` `here " -"`_ for more details. The pre-defined functions are used in" -" the :code:`client.py` and imported. The :code:`client.py` also requires " -"to import several packages such as Flower and scikit-learn:" +"With that out of the way, let's move on to the interesting part. " +"Federated learning systems consist of a server and multiple clients. In " +"Flower, we create clients by implementing subclasses of " +"``flwr.client.Client`` or ``flwr.client.NumPyClient``. We use " +"``NumPyClient`` in this tutorial because it is easier to implement and " +"requires us to write less boilerplate." msgstr "" -"Tu peux consulter :code:`utils.py` `ici " -"`_ pour plus de détails. Les fonctions prédéfinies sont " -"utilisées dans :code:`client.py` et importées. :code:`client.py` " -"nécessite également d'importer plusieurs paquets tels que Flower et " -"scikit-learn :" +"Ceci étant dit, passons à la partie intéressante. Les systèmes " +"d'apprentissage fédérés se composent d'un serveur et de plusieurs " +"clients. Dans Flower, nous créons des clients en mettant en œuvre des " +"sous-classes de ``flwr.client.Client`` ou de ``flwr.client.NumPyClient``." +" Nous utilisons ``NumPyClient`` dans ce tutoriel parce qu'il est plus " +"facile à mettre en œuvre et qu'il nous oblige à rédiger moins de modèles " +"de chaudière." -#: ../../source/tutorial-quickstart-scikitlearn.rst:70 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:470 msgid "" -"We load the MNIST dataset from `OpenML `_, " -"a popular image classification dataset of handwritten digits for machine " -"learning. The utility :code:`utils.load_mnist()` downloads the training " -"and test data. The training set is split afterwards into 10 partitions " -"with :code:`utils.partition()`." +"To implement the Flower client, we create a subclass of " +"``flwr.client.NumPyClient`` and implement the three methods " +"``get_parameters``, ``fit``, and ``evaluate``:" msgstr "" -"Nous chargeons l'ensemble de données MNIST de `OpenML " -"`_, un ensemble de données de " -"classification d'images populaires de chiffres manuscrits pour " -"l'apprentissage automatique. L'utilitaire :code:`utils.load_mnist()` " -"télécharge les données d'entraînement et de test. L'ensemble " -"d'entraînement est ensuite divisé en 10 partitions avec " -":code:`utils.partition()`." +"Pour mettre en œuvre le client Flower, nous créons une sous-classe de " +"``flwr.client.NumPyClient`` et mettons en œuvre les trois méthodes " +"``get_parameters``, ``fit`` et ``evaluate`` :" + +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:472 +msgid "``get_parameters``: Return the current local model parameters" +msgstr "``get_parameters`` : renvoie les paramètres du modèle local actuel" -#: ../../source/tutorial-quickstart-scikitlearn.rst:82 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:473 msgid "" -"Next, the logistic regression model is defined and initialized with " -":code:`utils.set_initial_params()`." +"``fit``: Receive model parameters from the server, train the model " +"parameters on the local data, and return the (updated) model parameters " +"to the server" msgstr "" -"Ensuite, le modèle de régression logistique est défini et initialisé avec" -" :code:`utils.set_initial_params()`." +"``fit`` : reçoit les paramètres du modèle du serveur, entraîne les " +"paramètres du modèle sur les données locales et renvoie les paramètres du" +" modèle (mis à jour) au serveur" -#: ../../source/tutorial-quickstart-scikitlearn.rst:94 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:474 msgid "" -"The Flower server interacts with clients through an interface called " -":code:`Client`. When the server selects a particular client for training," -" it sends training instructions over the network. The client receives " -"those instructions and calls one of the :code:`Client` methods to run " -"your code (i.e., to fit the logistic regression we defined earlier)." +"``evaluate``: Receive model parameters from the server, evaluate the " +"model parameters on the local data, and return the evaluation result to " +"the server" msgstr "" -"Le serveur Flower interagit avec les clients par le biais d'une interface" -" appelée :code:`Client`. Lorsque le serveur sélectionne un client " -"particulier pour la formation, il envoie des instructions de formation " -"sur le réseau. Le client reçoit ces instructions et appelle l'une des " -"méthodes :code:`Client` pour exécuter ton code (c'est-à-dire pour ajuster" -" la régression logistique que nous avons définie plus tôt)." +"``evaluate`` : reçoit les paramètres du modèle du serveur, évalue les " +"paramètres du modèle sur les données locales et renvoie le résultat de " +"l'évaluation au serveur" -#: ../../source/tutorial-quickstart-scikitlearn.rst:100 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:476 msgid "" -"Flower provides a convenience class called :code:`NumPyClient` which " -"makes it easier to implement the :code:`Client` interface when your " -"workload uses scikit-learn. Implementing :code:`NumPyClient` usually " -"means defining the following methods (:code:`set_parameters` is optional " -"though):" +"We mentioned that our clients will use the previously defined PyTorch " +"components for model training and evaluation. Let's see a simple Flower " +"client implementation that brings everything together:" msgstr "" -"Flower fournit une classe de commodité appelée :code:`NumPyClient` qui " -"facilite la mise en œuvre de l'interface :code:`Client` lorsque ta charge" -" de travail utilise scikit-learn. Mettre en œuvre :code:`NumPyClient` " -"signifie généralement définir les méthodes suivantes " -"(:code:`set_parameters` est cependant facultatif) :" +"Nous avons mentionné que nos clients utiliseront les composants PyTorch " +"définis précédemment pour la formation et l'évaluation des modèles. " +"Voyons une simple mise en œuvre du client Flower qui réunit tout cela :" -#: ../../source/tutorial-quickstart-scikitlearn.rst:109 -msgid "is directly imported with :code:`utils.set_model_params()`" -msgstr "est directement importé avec :code:`utils.set_model_params()`" +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:513 +msgid "" +"Our class ``FlowerClient`` defines how local training/evaluation will be " +"performed and allows Flower to call the local training/evaluation through" +" ``fit`` and ``evaluate``. Each instance of ``FlowerClient`` represents a" +" *single client* in our federated learning system. Federated learning " +"systems have multiple clients (otherwise, there's not much to federate), " +"so each client will be represented by its own instance of " +"``FlowerClient``. If we have, for example, three clients in our workload," +" then we'd have three instances of ``FlowerClient``. Flower calls " +"``FlowerClient.fit`` on the respective instance when the server selects a" +" particular client for training (and ``FlowerClient.evaluate`` for " +"evaluation)." +msgstr "" +"Our class ``FlowerClient`` defines how local training/evaluation will be " +"performed and allows Flower to call the local training/evaluation through" +" ``fit`` and ``evaluate``. Each instance of ``FlowerClient`` represents a" +" *single client* in our federated learning system. Federated learning " +"systems have multiple clients (otherwise, there's not much to federate), " +"so each client will be represented by its own instance of " +"``FlowerClient``. If we have, for example, three clients in our workload," +" then we'd have three instances of ``FlowerClient``. Flower calls " +"``FlowerClient.fit`` on the respective instance when the server selects a" +" particular client for training (and ``FlowerClient.evaluate`` for " +"evaluation)." -#: ../../source/tutorial-quickstart-scikitlearn.rst:117 -msgid "The methods can be implemented in the following way:" -msgstr "Les méthodes peuvent être mises en œuvre de la manière suivante :" +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:517 +msgid "Using the Virtual Client Engine" +msgstr "Utilisation du moteur du client virtuel" -#: ../../source/tutorial-quickstart-scikitlearn.rst:140 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:519 msgid "" -"We can now create an instance of our class :code:`MnistClient` and add " -"one line to actually run this client:" +"In this notebook, we want to simulate a federated learning system with 10" +" clients on a single machine. This means that the server and all 10 " +"clients will live on a single machine and share resources such as CPU, " +"GPU, and memory. Having 10 clients would mean having 10 instances of " +"``FlowerClient`` in memory. Doing this on a single machine can quickly " +"exhaust the available memory resources, even if only a subset of these " +"clients participates in a single round of federated learning." msgstr "" -"Nous pouvons maintenant créer une instance de notre classe " -":code:`MnistClient` et ajouter une ligne pour exécuter ce client :" +"Dans ce carnet, nous voulons simuler un système d'apprentissage fédéré " +"avec 10 clients sur une seule machine. Cela signifie que le serveur et " +"les 10 clients vivront sur une seule machine et partageront des " +"ressources telles que le CPU, le GPU et la mémoire. Avoir 10 clients " +"signifierait avoir 10 instances de ``FlowerClient`` en mémoire. Faire " +"cela sur une seule machine peut rapidement épuiser les ressources mémoire" +" disponibles, même si seulement un sous-ensemble de ces clients participe" +" à un seul tour d'apprentissage fédéré." -#: ../../source/tutorial-quickstart-scikitlearn.rst:156 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:521 msgid "" -"The following Flower server is a little bit more advanced and returns an " -"evaluation function for the server-side evaluation. First, we import " -"again all required libraries such as Flower and scikit-learn." +"In addition to the regular capabilities where server and clients run on " +"multiple machines, Flower, therefore, provides special simulation " +"capabilities that create ``FlowerClient`` instances only when they are " +"actually necessary for training or evaluation. To enable the Flower " +"framework to create clients when necessary, we need to implement a " +"function called ``client_fn`` that creates a ``FlowerClient`` instance on" +" demand. Flower calls ``client_fn`` whenever it needs an instance of one " +"particular client to call ``fit`` or ``evaluate`` (those instances are " +"usually discarded after use, so they should not keep any local state). " +"Clients are identified by a client ID, or short ``cid``. The ``cid`` can " +"be used, for example, to load different local data partitions for " +"different clients, as can be seen below:" msgstr "" -"Le serveur Flower suivant est un peu plus avancé et renvoie une fonction " -"d'évaluation pour l'évaluation côté serveur. Tout d'abord, nous importons" -" à nouveau toutes les bibliothèques requises telles que Flower et scikit-" -"learn." +"In addition to the regular capabilities where server and clients run on " +"multiple machines, Flower, therefore, provides special simulation " +"capabilities that create ``FlowerClient`` instances only when they are " +"actually necessary for training or evaluation. To enable the Flower " +"framework to create clients when necessary, we need to implement a " +"function called ``client_fn`` that creates a ``FlowerClient`` instance on" +" demand. Flower calls ``client_fn`` whenever it needs an instance of one " +"particular client to call ``fit`` or ``evaluate`` (those instances are " +"usually discarded after use, so they should not keep any local state). " +"Clients are identified by a client ID, or short ``cid``. The ``cid`` can " +"be used, for example, to load different local data partitions for " +"different clients, as can be seen below:" -#: ../../source/tutorial-quickstart-scikitlearn.rst:159 -msgid ":code:`server.py`, import Flower and start the server:" -msgstr ":code:`server.py`, importe Flower et démarre le serveur :" +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:556 +msgid "Starting the training" +msgstr "Commencer la formation" -#: ../../source/tutorial-quickstart-scikitlearn.rst:170 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:558 msgid "" -"The number of federated learning rounds is set in :code:`fit_round()` and" -" the evaluation is defined in :code:`get_evaluate_fn()`. The evaluation " -"function is called after each federated learning round and gives you " -"information about loss and accuracy." +"We now have the class ``FlowerClient`` which defines client-side " +"training/evaluation and ``client_fn`` which allows Flower to create " +"``FlowerClient`` instances whenever it needs to call ``fit`` or " +"``evaluate`` on one particular client. The last step is to start the " +"actual simulation using ``flwr.simulation.start_simulation``." msgstr "" -"Le nombre de tours d'apprentissage fédéré est défini dans " -":code:`fit_round()` et l'évaluation est définie dans " -":code:`get_evaluate_fn()`. La fonction d'évaluation est appelée après " -"chaque tour d'apprentissage fédéré et te donne des informations sur la " -"perte et la précision." +"Nous avons maintenant la classe ``FlowerClient`` qui définit " +"l'entraînement/évaluation côté client et ``client_fn`` qui permet à " +"Flower de créer des instances de ``FlowerClient`` chaque fois qu'il a " +"besoin d'appeler ``fit`` ou ``evaluate`` sur un client particulier. La " +"dernière étape consiste à démarrer la simulation réelle en utilisant " +"``flwr.simulation.start_simulation``." -#: ../../source/tutorial-quickstart-scikitlearn.rst:195 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:560 msgid "" -"The :code:`main` contains the server-side parameter initialization " -":code:`utils.set_initial_params()` as well as the aggregation strategy " -":code:`fl.server.strategy:FedAvg()`. The strategy is the default one, " -"federated averaging (or FedAvg), with two clients and evaluation after " -"each federated learning round. The server can be started with the command" -" :code:`fl.server.start_server(server_address=\"0.0.0.0:8080\", " -"strategy=strategy, config=fl.server.ServerConfig(num_rounds=3))`." +"The function ``start_simulation`` accepts a number of arguments, amongst " +"them the ``client_fn`` used to create ``FlowerClient`` instances, the " +"number of clients to simulate (``num_clients``), the number of federated " +"learning rounds (``num_rounds``), and the strategy. The strategy " +"encapsulates the federated learning approach/algorithm, for example, " +"*Federated Averaging* (FedAvg)." msgstr "" -"Le :code:`main` contient l'initialisation des paramètres côté serveur " -":code:`utils.set_initial_params()` ainsi que la stratégie d'agrégation " -":code:`fl.server.strategy:FedAvg()`. La stratégie est celle par défaut, " -"la moyenne fédérée (ou FedAvg), avec deux clients et une évaluation après" -" chaque tour d'apprentissage fédéré. Le serveur peut être démarré avec la" -" commande :code:`fl.server.start_server(server_address=\"0.0.0.0:8080\", " -"strategy=strategy, config=fl.server.ServerConfig(num_rounds=3))`." +"La fonction ``start_simulation`` accepte un certain nombre d'arguments, " +"parmi lesquels le ``client_fn`` utilisé pour créer les instances " +"``FlowerClient``, le nombre de clients à simuler (``num_clients``), le " +"nombre de tours d'apprentissage fédéré (``num_rounds``), et la stratégie." +" La stratégie encapsule l'approche/algorithme d'apprentissage fédéré, par" +" exemple, *Federated Averaging* (FedAvg)." -#: ../../source/tutorial-quickstart-scikitlearn.rst:214 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:562 msgid "" -"With both client and server ready, we can now run everything and see " -"federated learning in action. Federated learning systems usually have a " -"server and multiple clients. We, therefore, have to start the server " -"first:" +"Flower has a number of built-in strategies, but we can also use our own " +"strategy implementations to customize nearly all aspects of the federated" +" learning approach. For this example, we use the built-in ``FedAvg`` " +"implementation and customize it using a few basic parameters. The last " +"step is the actual call to ``start_simulation`` which - you guessed it - " +"starts the simulation:" msgstr "" -"Le client et le serveur étant prêts, nous pouvons maintenant tout lancer " -"et voir l'apprentissage fédéré en action. Les systèmes d'apprentissage " -"fédéré ont généralement un serveur et plusieurs clients. Nous devons donc" -" commencer par lancer le serveur :" +"Flower dispose d'un certain nombre de stratégies intégrées, mais nous " +"pouvons également utiliser nos propres implémentations de stratégies pour" +" personnaliser presque tous les aspects de l'approche de l'apprentissage " +"fédéré. Pour cet exemple, nous utilisons l'implémentation intégrée " +"``FedAvg`` et nous la personnalisons en utilisant quelques paramètres de " +"base. La dernière étape est l'appel à ``start_simulation`` qui - tu l'as " +"deviné - démarre la simulation :" + +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:608 +msgid "Behind the scenes" +msgstr "Dans les coulisses" + +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:610 +msgid "So how does this work? How does Flower execute this simulation?" +msgstr "" +"Alors, comment cela fonctionne-t-il ? Comment Flower exécute-t-il cette " +"simulation ?" -#: ../../source/tutorial-quickstart-scikitlearn.rst:268 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:612 +#, python-format msgid "" -"Congratulations! You've successfully built and run your first federated " -"learning system. The full `source code " -"`_ for this example can be found in :code:`examples/sklearn-logreg-" -"mnist`." +"When we call ``start_simulation``, we tell Flower that there are 10 " +"clients (``num_clients=10``). Flower then goes ahead an asks the " +"``FedAvg`` strategy to select clients. ``FedAvg`` knows that it should " +"select 100% of the available clients (``fraction_fit=1.0``), so it goes " +"ahead and selects 10 random clients (i.e., 100% of 10)." msgstr "" -"Félicitations ! Tu as réussi à construire et à faire fonctionner ton " -"premier système d'apprentissage fédéré. Le code source complet " -"`_ de cet exemple se trouve dans :code:`examples/sklearn-logreg-" -"mnist`." - -#: ../../source/tutorial-quickstart-tensorflow.rst:5 -msgid "Quickstart TensorFlow" -msgstr "Démarrage rapide de TensorFlow" +"Lorsque nous appelons ``start_simulation``, nous disons à Flower qu'il y " +"a 10 clients (``num_clients=10``). Flower demande alors à la stratégie " +"``FedAvg`` de sélectionner des clients. ``FedAvg` sait qu'il doit " +"sélectionner 100% des clients disponibles (``fraction_fit=1.0``), alors " +"il choisit 10 clients au hasard (c'est à dire 100% de 10)." -#: ../../source/tutorial-quickstart-tensorflow.rst:10 -msgid "Let's build a federated learning system in less than 20 lines of code!" +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:614 +msgid "" +"Flower then asks the selected 10 clients to train the model. When the " +"server receives the model parameter updates from the clients, it hands " +"those updates over to the strategy (*FedAvg*) for aggregation. The " +"strategy aggregates those updates and returns the new global model, which" +" then gets used in the next round of federated learning." msgstr "" -"Construisons un système d'apprentissage fédéré en moins de 20 lignes de " -"code !" +"Flower demande ensuite aux 10 clients sélectionnés d'entraîner le modèle." +" Lorsque le serveur reçoit les mises à jour des paramètres du modèle de " +"la part des clients, il les transmet à la stratégie (*FedAvg*) pour " +"qu'elle les agrège. La stratégie agrège ces mises à jour et renvoie le " +"nouveau modèle global, qui est ensuite utilisé dans le prochain cycle " +"d'apprentissage fédéré." -#: ../../source/tutorial-quickstart-tensorflow.rst:12 -msgid "Before Flower can be imported we have to install it:" -msgstr "Avant de pouvoir importer une fleur, nous devons l'installer :" +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:626 +msgid "Where's the accuracy?" +msgstr "Où est la précision ?" -#: ../../source/tutorial-quickstart-tensorflow.rst:18 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:628 msgid "" -"Since we want to use the Keras API of TensorFlow (TF), we have to install" -" TF as well:" +"You may have noticed that all metrics except for ``losses_distributed`` " +"are empty. Where did the ``{\"accuracy\": float(accuracy)}`` go?" msgstr "" -"Comme nous voulons utiliser l'API Keras de TensorFlow (TF), nous devons " -"également installer TF :" +"Tu as peut-être remarqué que toutes les mesures, à l'exception de " +"``pertes_distribuées``, sont vides. Où est passée la ``{\"précision\" : " +"float(précision)}`` ?" -#: ../../source/tutorial-quickstart-tensorflow.rst:28 -msgid "Next, in a file called :code:`client.py`, import Flower and TensorFlow:" +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:630 +msgid "" +"Flower can automatically aggregate losses returned by individual clients," +" but it cannot do the same for metrics in the generic metrics dictionary " +"(the one with the ``accuracy`` key). Metrics dictionaries can contain " +"very different kinds of metrics and even key/value pairs that are not " +"metrics at all, so the framework does not (and can not) know how to " +"handle these automatically." msgstr "" -"Ensuite, dans un fichier appelé :code:`client.py`, importe Flower et " -"TensorFlow :" +"Flower peut automatiquement agréger les pertes renvoyées par les clients " +"individuels, mais il ne peut pas faire la même chose pour les mesures " +"dans le dictionnaire de mesures générique (celui avec la clé " +"``accuracy``). Les dictionnaires de mesures peuvent contenir des types de" +" mesures très différents et même des paires clé/valeur qui ne sont pas " +"des mesures du tout, donc le cadre ne sait pas (et ne peut pas) savoir " +"comment les gérer automatiquement." -#: ../../source/tutorial-quickstart-tensorflow.rst:35 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:632 msgid "" -"We use the Keras utilities of TF to load CIFAR10, a popular colored image" -" classification dataset for machine learning. The call to " -":code:`tf.keras.datasets.cifar10.load_data()` downloads CIFAR10, caches " -"it locally, and then returns the entire training and test set as NumPy " -"ndarrays." +"As users, we need to tell the framework how to handle/aggregate these " +"custom metrics, and we do so by passing metric aggregation functions to " +"the strategy. The strategy will then call these functions whenever it " +"receives fit or evaluate metrics from clients. The two possible functions" +" are ``fit_metrics_aggregation_fn`` and " +"``evaluate_metrics_aggregation_fn``." msgstr "" -"Nous utilisons les utilitaires Keras de TF pour charger CIFAR10, un " -"ensemble de données de classification d'images colorées populaire pour " -"l'apprentissage automatique. L'appel à " -":code:`tf.keras.datasets.cifar10.load_data()` télécharge CIFAR10, le met " -"en cache localement, puis renvoie l'ensemble d'entraînement et de test " -"sous forme de NumPy ndarrays." +"En tant qu'utilisateurs, nous devons indiquer au framework comment " +"gérer/agréger ces métriques personnalisées, et nous le faisons en passant" +" des fonctions d'agrégation de métriques à la stratégie. La stratégie " +"appellera alors ces fonctions chaque fois qu'elle recevra des métriques " +"d'ajustement ou d'évaluation de la part des clients. Les deux fonctions " +"possibles sont ``fit_metrics_aggregation_fn`` et " +"``evaluate_metrics_aggregation_fn``." -#: ../../source/tutorial-quickstart-tensorflow.rst:44 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:634 msgid "" -"Next, we need a model. For the purpose of this tutorial, we use " -"MobilNetV2 with 10 output classes:" +"Let's create a simple weighted averaging function to aggregate the " +"``accuracy`` metric we return from ``evaluate``:" msgstr "" -"Ensuite, nous avons besoin d'un modèle. Pour les besoins de ce tutoriel, " -"nous utilisons MobilNetV2 avec 10 classes de sortie :" +"Créons une simple fonction de calcul de la moyenne pondérée pour agréger " +"la mesure de \"précision\" que nous renvoie ``evaluate`` :" -#: ../../source/tutorial-quickstart-tensorflow.rst:57 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:660 msgid "" -"Flower provides a convenience class called :code:`NumPyClient` which " -"makes it easier to implement the :code:`Client` interface when your " -"workload uses Keras. The :code:`NumPyClient` interface defines three " -"methods which can be implemented in the following way:" +"The only thing left to do is to tell the strategy to call this function " +"whenever it receives evaluation metric dictionaries from the clients:" msgstr "" -"Flower fournit une classe de commodité appelée :code:`NumPyClient` qui " -"facilite la mise en œuvre de l'interface :code:`Client` lorsque ta charge" -" de travail utilise Keras. L'interface :code:`NumPyClient` définit trois " -"méthodes qui peuvent être mises en œuvre de la manière suivante :" - -#: ../../source/tutorial-quickstart-tensorflow.rst:132 -msgid "Each client will have its own dataset." -msgstr "Chaque client aura son propre ensemble de données." +"La seule chose qui reste à faire est d'indiquer à la stratégie d'appeler " +"cette fonction chaque fois qu'elle reçoit des dictionnaires de métriques " +"d'évaluation de la part des clients :" -#: ../../source/tutorial-quickstart-tensorflow.rst:134 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:697 msgid "" -"You should now see how the training does in the very first terminal (the " -"one that started the server):" +"We now have a full system that performs federated training and federated " +"evaluation. It uses the ``weighted_average`` function to aggregate custom" +" evaluation metrics and calculates a single ``accuracy`` metric across " +"all clients on the server side." msgstr "" -"Tu devrais maintenant voir comment la formation se déroule dans le tout " -"premier terminal (celui qui a démarré le serveur) :" +"Nous avons maintenant un système complet qui effectue la formation " +"fédérée et l'évaluation fédérée. Il utilise la fonction ``moyenne " +"pondérée`` pour agréger les mesures d'évaluation personnalisées et " +"calcule une seule mesure de ``précision`` pour tous les clients du côté " +"du serveur." -#: ../../source/tutorial-quickstart-tensorflow.rst:166 -#, fuzzy +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:699 msgid "" -"Congratulations! You've successfully built and run your first federated " -"learning system. The full `source code " -"`_ for this can be found in :code:`examples" -"/quickstart-tensorflow/client.py`." +"The other two categories of metrics (``losses_centralized`` and " +"``metrics_centralized``) are still empty because they only apply when " +"centralized evaluation is being used. Part two of the Flower tutorial " +"will cover centralized evaluation." msgstr "" -"Félicitations ! Tu as réussi à construire et à faire fonctionner ton " -"premier système d'apprentissage fédéré. Le `code source complet " -"`_ pour cela se trouve dans :code:`examples" -"/quickstart-tensorflow/client.py`." +"Les deux autres catégories de mesures (``pertes_centralisées`` et " +"``métriques_centralisées``) sont toujours vides car elles ne s'appliquent" +" que lorsque l'évaluation centralisée est utilisée. La deuxième partie du" +" tutoriel sur les fleurs couvrira l'évaluation centralisée." -#: ../../source/tutorial-quickstart-xgboost.rst:5 -msgid "Quickstart XGBoost" -msgstr "Démarrage rapide XGBoost" +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:711 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:351 +msgid "Final remarks" +msgstr "Remarques finales" + +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:713 +msgid "" +"Congratulations, you just trained a convolutional neural network, " +"federated over 10 clients! With that, you understand the basics of " +"federated learning with Flower. The same approach you've seen can be used" +" with other machine learning frameworks (not just PyTorch) and tasks (not" +" just CIFAR-10 images classification), for example NLP with Hugging Face " +"Transformers or speech with SpeechBrain." +msgstr "" +"Félicitations, tu viens d'entraîner un réseau neuronal convolutif, fédéré" +" sur 10 clients ! Avec ça, tu comprends les bases de l'apprentissage " +"fédéré avec Flower. La même approche que tu as vue peut être utilisée " +"avec d'autres cadres d'apprentissage automatique (pas seulement PyTorch) " +"et d'autres tâches (pas seulement la classification des images CIFAR-10)," +" par exemple le NLP avec Hugging Face Transformers ou la parole avec " +"SpeechBrain." -#: ../../source/tutorial-quickstart-xgboost.rst:7 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:715 msgid "" -"Let's build a horizontal federated learning system using XGBoost and " -"Flower!" +"In the next notebook, we're going to cover some more advanced concepts. " +"Want to customize your strategy? Initialize parameters on the server " +"side? Or evaluate the aggregated model on the server side? We'll cover " +"all this and more in the next tutorial." msgstr "" -"Construisons un système d'apprentissage fédéré horizontal en utilisant " -"XGBoost et Flower !" +"Dans le prochain cahier, nous allons aborder des concepts plus avancés. " +"Tu veux personnaliser ta stratégie ? Initialiser des paramètres côté " +"serveur ? Ou évaluer le modèle agrégé côté serveur ? Nous aborderons tout" +" cela et bien plus encore dans le prochain tutoriel." -#: ../../source/tutorial-quickstart-xgboost.rst:9 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:733 #, fuzzy msgid "" -"Please refer to the `full code example " -"`_ to learn more." +"The `Flower Federated Learning Tutorial - Part 2 " +"`__ goes into more depth about strategies and all " +"the advanced things you can build with them." msgstr "" -"Réfère-toi à l'exemple de code complet " -"`_ pour en savoir plus." +"Le `Tutoriel d'apprentissage fédéré Flower - Partie 2 " +"`__ va plus en profondeur sur les stratégies et toutes les " +"choses avancées que tu peux construire avec elles." -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:9 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:9 #, fuzzy msgid "Use a federated learning strategy" msgstr "Stratégie de moyenne fédérée." -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:11 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:11 #, fuzzy msgid "" "Welcome to the next part of the federated learning tutorial. In previous " @@ -14751,7 +21411,7 @@ msgstr "" "l'apprentissage fédéré avec PyTorch et Flower (`partie 1 " "`__)." -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:13 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:13 msgid "" "In this notebook, we'll begin to customize the federated learning system " "we built in the introductory notebook (again, using `Flower " @@ -14762,16 +21422,16 @@ msgstr "" "d'introduction (toujours en utilisant `Flower `__ et" " `PyTorch `__)." -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:17 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:17 #, fuzzy msgid "Let's move beyond FedAvg with Flower strategies!" msgstr "Dépassons FedAvg avec les stratégies florales !" -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:309 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:309 msgid "Strategy customization" msgstr "Personnalisation de la stratégie" -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:311 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:311 msgid "" "So far, everything should look familiar if you've worked through the " "introductory notebook. With that, we're ready to introduce a number of " @@ -14781,11 +21441,11 @@ msgstr "" "le cahier d'introduction. Avec cela, nous sommes prêts à présenter un " "certain nombre de nouvelles fonctionnalités." -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:323 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:323 msgid "Server-side parameter **initialization**" msgstr "Paramètres côté serveur **initialisation**" -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:325 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:325 msgid "" "Flower, by default, initializes the global model by asking one random " "client for the initial parameters. In many cases, we want more control " @@ -14798,7 +21458,7 @@ msgstr "" "Flower te permet donc de passer directement les paramètres initiaux à la " "Stratégie :" -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:370 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:370 msgid "" "Passing ``initial_parameters`` to the ``FedAvg`` strategy prevents Flower" " from asking one of the clients for the initial parameters. If we look " @@ -14810,11 +21470,11 @@ msgstr "" " nous regardons de près, nous pouvons voir que les journaux ne montrent " "aucun appel à la méthode ``FlowerClient.get_parameters``." -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:382 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:382 msgid "Starting with a customized strategy" msgstr "Commencer par une stratégie personnalisée" -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:384 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:384 msgid "" "We've seen the function ``start_simulation`` before. It accepts a number " "of arguments, amongst them the ``client_fn`` used to create " @@ -14826,7 +21486,7 @@ msgstr "" "nombre de clients à simuler ``num_clients``, le nombre de rounds " "``num_rounds``, et la stratégie." -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:386 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:386 msgid "" "The strategy encapsulates the federated learning approach/algorithm, for " "example, ``FedAvg`` or ``FedAdagrad``. Let's try to use a different " @@ -14836,11 +21496,11 @@ msgstr "" "exemple, ``FedAvg`` ou ``FedAdagrad``. Essayons d'utiliser une stratégie " "différente cette fois-ci :" -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:424 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:424 msgid "Server-side parameter **evaluation**" msgstr "Paramètre côté serveur **évaluation**" -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:426 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:426 msgid "" "Flower can evaluate the aggregated model on the server-side or on the " "client-side. Client-side and server-side evaluation are similar in some " @@ -14850,7 +21510,7 @@ msgstr "" "évaluations côté client et côté serveur sont similaires à certains " "égards, mais différentes à d'autres." -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:428 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:428 msgid "" "**Centralized Evaluation** (or *server-side evaluation*) is conceptually " "simple: it works the same way that evaluation in centralized machine " @@ -14869,7 +21529,7 @@ msgstr "" "le modèle aux clients. Nous avons également la chance que l'ensemble de " "notre ensemble de données d'évaluation soit disponible à tout moment." -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:430 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:430 msgid "" "**Federated Evaluation** (or *client-side evaluation*) is more complex, " "but also more powerful: it doesn't require a centralized dataset and " @@ -14900,7 +21560,7 @@ msgstr "" "le modèle, nous verrions nos résultats d'évaluation fluctuer au cours des" " cycles consécutifs." -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:433 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:433 msgid "" "We've seen how federated evaluation works on the client side (i.e., by " "implementing the ``evaluate`` method in ``FlowerClient``). Now let's see " @@ -14911,11 +21571,11 @@ msgstr "" "``FlowerClient``). Voyons maintenant comment nous pouvons évaluer les " "paramètres du modèle agrégé du côté serveur :" -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:490 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:490 msgid "Sending/receiving arbitrary values to/from clients" msgstr "Envoi/réception de valeurs arbitraires vers/depuis les clients" -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:492 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:492 #, fuzzy msgid "" "In some situations, we want to configure client-side execution (training," @@ -14942,7 +21602,7 @@ msgstr "" " it reads ``server_round`` and ``local_epochs`` and uses those values to " "improve the logging and configure the number of local training epochs:" -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:546 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:546 msgid "" "So how can we send this config dictionary from server to clients? The " "built-in Flower Strategies provide way to do this, and it works similarly" @@ -14957,7 +21617,7 @@ msgstr "" "stratégie appelle cette fonction pour chaque cycle d'apprentissage fédéré" " :" -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:576 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:576 msgid "" "Next, we'll just pass this function to the FedAvg strategy before " "starting the simulation:" @@ -14965,7 +21625,7 @@ msgstr "" "Ensuite, nous allons simplement passer cette fonction à la stratégie " "FedAvg avant de commencer la simulation :" -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:613 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:613 msgid "" "As we can see, the client logs now include the current round of federated" " learning (which they read from the ``config`` dictionary). We can also " @@ -14980,7 +21640,7 @@ msgstr "" " premier et du deuxième cycle d'apprentissage fédéré, puis pendant deux " "époques au cours du troisième cycle." -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:615 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:615 msgid "" "Clients can also return arbitrary values to the server. To do so, they " "return a dictionary from ``fit`` and/or ``evaluate``. We have seen and " @@ -14995,11 +21655,11 @@ msgstr "" "renvoie un dictionnaire contenant une paire clé/valeur personnalisée en " "tant que troisième valeur de retour dans ``evaluate``." -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:627 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:627 msgid "Scaling federated learning" msgstr "Mise à l'échelle de l'apprentissage fédéré" -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:629 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:629 msgid "" "As a last step in this notebook, let's see how we can use Flower to " "experiment with a large number of clients." @@ -15007,7 +21667,7 @@ msgstr "" "Comme dernière étape de ce carnet, voyons comment nous pouvons utiliser " "Flower pour expérimenter avec un grand nombre de clients." -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:651 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:651 #, python-format msgid "" "We now have 1000 partitions, each holding 45 training and 5 validation " @@ -15032,7 +21692,7 @@ msgstr "" " disponibles (donc 50 clients) seront sélectionnés pour l'entraînement à " "chaque tour :" -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:699 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:699 msgid "" "In this notebook, we've seen how we can gradually enhance our system by " "customizing the strategy, initializing parameters on the server side, " @@ -15045,7 +21705,7 @@ msgstr "" "en évaluant les modèles côté serveur. C'est une sacrée flexibilité avec " "si peu de code, n'est-ce pas ?" -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:701 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:701 msgid "" "In the later sections, we've seen how we can communicate arbitrary values" " between server and clients to fully customize client-side execution. " @@ -15061,7 +21721,7 @@ msgstr "" "avons mené une expérience impliquant 1000 clients dans la même charge de " "travail - le tout dans un carnet Jupyter !" -#: ../../source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb:719 +#: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:719 #, fuzzy msgid "" "The `Flower Federated Learning Tutorial - Part 3 " @@ -15074,11 +21734,11 @@ msgstr "" "PyTorch.html>`__ montre comment construire une ``Stratégie`` entièrement " "personnalisée à partir de zéro." -#: ../../source/tutorial-what-is-federated-learning.ipynb:9 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:9 msgid "What is Federated Learning?" msgstr "Qu'est-ce que l'apprentissage fédéré ?" -#: ../../source/tutorial-what-is-federated-learning.ipynb:13 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:13 #, fuzzy msgid "" "In this tutorial, you will learn what federated learning is, build your " @@ -15092,7 +21752,7 @@ msgstr "" "seras capable de construire des systèmes d'apprentissage fédéré avancés " "qui se rapprochent de l'état actuel de l'art dans le domaine." -#: ../../source/tutorial-what-is-federated-learning.ipynb:15 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:15 msgid "" "🧑‍🏫 This tutorial starts at zero and expects no familiarity with " "federated learning. Only a basic understanding of data science and Python" @@ -15102,7 +21762,7 @@ msgstr "" "l'apprentissage fédéré. Seule une compréhension de base de la science des" " données et de la programmation Python est supposée." -#: ../../source/tutorial-what-is-federated-learning.ipynb:17 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:17 #, fuzzy msgid "" "`Star Flower on GitHub `__ ⭐️ and join " @@ -15118,11 +21778,16 @@ msgstr "" "``#introductions`` ! Et si quelque chose n'est pas clair, rendez-vous sur" " le canal ``#questions``." -#: ../../source/tutorial-what-is-federated-learning.ipynb:31 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:19 +#, fuzzy +msgid "Let's get started!" +msgstr "Allons-y, déclarons-le !" + +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:31 msgid "Classic machine learning" msgstr "Apprentissage automatique classique" -#: ../../source/tutorial-what-is-federated-learning.ipynb:33 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:33 msgid "" "Before we begin to discuss federated learning, let us quickly recap how " "most machine learning works today." @@ -15131,7 +21796,7 @@ msgstr "" "rapidement la façon dont la plupart des apprentissages automatiques " "fonctionnent aujourd'hui." -#: ../../source/tutorial-what-is-federated-learning.ipynb:35 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:35 msgid "" "In machine learning, we have a model, and we have data. The model could " "be a neural network (as depicted here), or something else, like classical" @@ -15141,15 +21806,15 @@ msgstr "" " modèle peut être un réseau neuronal (comme illustré ici), ou quelque " "chose d'autre, comme la régression linéaire classique." -#: ../../source/tutorial-what-is-federated-learning.ipynb:41 -msgid "|3ff4c820a01d4a5abb022617de537c54|" +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:41 +msgid "|31e4b1afa87c4b968327bbeafbf184d4|" msgstr "" -#: ../../source/tutorial-what-is-federated-learning.ipynb:109 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:109 msgid "Model and data" msgstr "Modèle et données" -#: ../../source/tutorial-what-is-federated-learning.ipynb:47 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:47 msgid "" "We train the model using the data to perform a useful task. A task could " "be to detect objects in images, transcribe an audio recording, or play a " @@ -15160,15 +21825,15 @@ msgstr "" "images, à transcrire un enregistrement audio ou à jouer à un jeu comme le" " Go." -#: ../../source/tutorial-what-is-federated-learning.ipynb:53 -msgid "|7f1889391ad448e2a65920165f0d798c|" +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:53 +msgid "|c9d935b4284e4c389a33d86b33e07c0a|" msgstr "" -#: ../../source/tutorial-what-is-federated-learning.ipynb:111 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:111 msgid "Train model using data" msgstr "Entraîne le modèle à l'aide des données" -#: ../../source/tutorial-what-is-federated-learning.ipynb:59 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:59 #, fuzzy msgid "" "Now, in practice, the training data we work with doesn't originate on the" @@ -15178,7 +21843,7 @@ msgstr "" "travaillons ne proviennent pas de la machine sur laquelle nous entraînons" " le modèle. Elles sont créées ailleurs." -#: ../../source/tutorial-what-is-federated-learning.ipynb:61 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:61 #, fuzzy msgid "" "It originates on a smartphone by the user interacting with an app, a car " @@ -15191,15 +21856,15 @@ msgstr "" "parleur intelligent qui écoute quelqu'un qui essaie de chanter une " "chanson." -#: ../../source/tutorial-what-is-federated-learning.ipynb:67 -msgid "|a171dc4a0d044e70b5d585cc10ace0e0|" +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:67 +msgid "|00727b5faffb468f84dd1b03ded88638|" msgstr "" -#: ../../source/tutorial-what-is-federated-learning.ipynb:113 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:113 msgid "Data on a phone" msgstr "Données sur un téléphone" -#: ../../source/tutorial-what-is-federated-learning.ipynb:73 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:73 msgid "" "What's also important to mention, this \"somewhere else\" is usually not " "just one place, it's many places. It could be several devices all running" @@ -15212,15 +21877,15 @@ msgstr "" "peut également s'agir de plusieurs organisations, qui génèrent toutes des" " données pour la même tâche." -#: ../../source/tutorial-what-is-federated-learning.ipynb:79 -msgid "|fe518aa0d86341f7b2fc87bd6e3bbf0c|" +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:79 +msgid "|daf0cf0ff4c24fd29439af78416cf47b|" msgstr "" -#: ../../source/tutorial-what-is-federated-learning.ipynb:115 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:115 msgid "Data is on many devices" msgstr "Les données se trouvent sur de nombreux appareils" -#: ../../source/tutorial-what-is-federated-learning.ipynb:85 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:85 msgid "" "So to use machine learning, or any kind of data analysis, the approach " "that has been used in the past was to collect all data on a central " @@ -15233,15 +21898,15 @@ msgstr "" "trouver quelque part dans un centre de données, ou quelque part dans le " "cloud." -#: ../../source/tutorial-what-is-federated-learning.ipynb:91 -msgid "|6abfdf0dade44469ae9f08c8dc7d148c|" +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:91 +msgid "|9f093007080d471d94ca90d3e9fde9b6|" msgstr "" -#: ../../source/tutorial-what-is-federated-learning.ipynb:117 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:117 msgid "Central data collection" msgstr "Collecte centralisée des données" -#: ../../source/tutorial-what-is-federated-learning.ipynb:97 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:97 #, fuzzy msgid "" "Once all the data is collected in one place, we can finally use machine " @@ -15254,19 +21919,19 @@ msgstr "" "automatique sur laquelle nous nous sommes fondamentalement toujours " "appuyés." -#: ../../source/tutorial-what-is-federated-learning.ipynb:103 -msgid "|b4f147db24bb4da9a786e1d6676a1c2d|" +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:103 +msgid "|46a26e6150e0479fbd3dfd655f36eb13|" msgstr "" -#: ../../source/tutorial-what-is-federated-learning.ipynb:119 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:119 msgid "Central model training" msgstr "Formation au modèle central" -#: ../../source/tutorial-what-is-federated-learning.ipynb:130 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:130 msgid "Challenges of classical machine learning" msgstr "Les défis de l'apprentissage automatique classique" -#: ../../source/tutorial-what-is-federated-learning.ipynb:132 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:132 msgid "" "The classic machine learning approach we've just seen can be used in some" " cases. Great examples include categorizing holiday photos, or analyzing " @@ -15279,15 +21944,15 @@ msgstr "" "trafic web. Des cas, où toutes les données sont naturellement disponibles" " sur un serveur centralisé." -#: ../../source/tutorial-what-is-federated-learning.ipynb:138 -msgid "|5c62032f589a457bb37b5fee5b2adbde|" +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:138 +msgid "|3daba297595c4c7fb845d90404a6179a|" msgstr "" -#: ../../source/tutorial-what-is-federated-learning.ipynb:173 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:173 msgid "Centralized possible" msgstr "Possibilité de centralisation" -#: ../../source/tutorial-what-is-federated-learning.ipynb:144 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:144 msgid "" "But the approach can not be used in many other cases. Cases, where the " "data is not available on a centralized server, or cases where the data " @@ -15298,15 +21963,15 @@ msgstr "" " ou lorsque les données disponibles sur un serveur ne sont pas " "suffisantes pour former un bon modèle." -#: ../../source/tutorial-what-is-federated-learning.ipynb:150 -msgid "|f154df1846dd44f79a94f1dc3ae8b088|" +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:150 +msgid "|5769874fa9c4455b80b2efda850d39d7|" msgstr "" -#: ../../source/tutorial-what-is-federated-learning.ipynb:175 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:175 msgid "Centralized impossible" msgstr "Impossible de centraliser" -#: ../../source/tutorial-what-is-federated-learning.ipynb:156 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:156 #, fuzzy msgid "" "There are many reasons why the classic centralized machine learning " @@ -15318,7 +21983,7 @@ msgstr "" "grand nombre de cas d'utilisation très importants dans le monde réel, " "notamment :" -#: ../../source/tutorial-what-is-federated-learning.ipynb:158 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:158 #, fuzzy msgid "" "**Regulations**: GDPR (Europe), CCPA (California), PIPEDA (Canada), LGPD " @@ -15343,7 +22008,7 @@ msgstr "" "régies par des réglementations différentes en matière de protection des " "données." -#: ../../source/tutorial-what-is-federated-learning.ipynb:160 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:160 msgid "" "**User preference**: In addition to regulation, there are use cases where" " users just expect that no data leaves their device, ever. If you type " @@ -15361,7 +22026,7 @@ msgstr "" "'est-ce pas ? En fait, ce cas d'utilisation est la raison pour laquelle " "l'apprentissage fédéré a été inventé en premier lieu." -#: ../../source/tutorial-what-is-federated-learning.ipynb:161 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:161 #, fuzzy msgid "" "**Data volume**: Some sensors, like cameras, produce such a high data " @@ -15384,13 +22049,13 @@ msgstr "" "excessivement coûteuse pour les traiter et les stocker. Et la plupart de " "ces données ne sont même pas utiles." -#: ../../source/tutorial-what-is-federated-learning.ipynb:164 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:164 msgid "Examples where centralized machine learning does not work include:" msgstr "" "Voici quelques exemples où l'apprentissage automatique centralisé ne " "fonctionne pas :" -#: ../../source/tutorial-what-is-federated-learning.ipynb:166 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:166 #, fuzzy msgid "" "Sensitive healthcare records from multiple hospitals to train cancer " @@ -15399,7 +22064,7 @@ msgstr "" "Des dossiers médicaux sensibles provenant de plusieurs hôpitaux pour " "former des modèles de détection du cancer" -#: ../../source/tutorial-what-is-federated-learning.ipynb:167 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:167 msgid "" "Financial information from different organizations to detect financial " "fraud" @@ -15407,19 +22072,19 @@ msgstr "" "Informations financières provenant de différentes organisations pour " "détecter les fraudes financières" -#: ../../source/tutorial-what-is-federated-learning.ipynb:168 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:168 msgid "Location data from your electric car to make better range prediction" msgstr "" "Les données de localisation de ta voiture électrique pour mieux prédire " "l'autonomie" -#: ../../source/tutorial-what-is-federated-learning.ipynb:169 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:169 msgid "End-to-end encrypted messages to train better auto-complete models" msgstr "" "Messages cryptés de bout en bout pour former de meilleurs modèles " "d'autocomplétion" -#: ../../source/tutorial-what-is-federated-learning.ipynb:171 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:171 #, fuzzy msgid "" "The popularity of privacy-enhancing systems like the `Brave " @@ -15441,11 +22106,11 @@ msgstr "" "qui bénéficieraient de manière significative des récentes avancées en " "matière d'IA." -#: ../../source/tutorial-what-is-federated-learning.ipynb:186 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:186 msgid "Federated learning" msgstr "Apprentissage fédéré" -#: ../../source/tutorial-what-is-federated-learning.ipynb:188 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:188 msgid "" "Federated learning simply reverses this approach. It enables machine " "learning on distributed data by moving the training to the data, instead " @@ -15457,15 +22122,15 @@ msgstr "" "formation vers les données, au lieu de déplacer les données vers la " "formation. Voici l'explication en une seule phrase :" -#: ../../source/tutorial-what-is-federated-learning.ipynb:190 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:190 msgid "Central machine learning: move the data to the computation" msgstr "Apprentissage automatique central : déplace les données vers le calcul" -#: ../../source/tutorial-what-is-federated-learning.ipynb:191 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:191 msgid "Federated (machine) learning: move the computation to the data" msgstr "Apprentissage (machine) fédéré : déplacer le calcul vers les données" -#: ../../source/tutorial-what-is-federated-learning.ipynb:193 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:193 msgid "" "By doing so, it enables us to use machine learning (and other data " "science approaches) in areas where it wasn't possible before. We can now " @@ -15493,7 +22158,7 @@ msgstr "" " réinventés parce qu'ils ont maintenant accès à de vastes quantités de " "données auparavant inaccessibles." -#: ../../source/tutorial-what-is-federated-learning.ipynb:196 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:196 msgid "" "So how does federated learning work, exactly? Let's start with an " "intuitive explanation." @@ -15501,15 +22166,15 @@ msgstr "" "Comment fonctionne l'apprentissage fédéré ? Commençons par une " "explication intuitive." -#: ../../source/tutorial-what-is-federated-learning.ipynb:199 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:199 msgid "Federated learning in five steps" msgstr "L'apprentissage fédéré en cinq étapes" -#: ../../source/tutorial-what-is-federated-learning.ipynb:202 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:202 msgid "Step 0: Initialize global model" msgstr "Étape 0 : Initialisation du modèle global" -#: ../../source/tutorial-what-is-federated-learning.ipynb:204 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:204 msgid "" "We start by initializing the model on the server. This is exactly the " "same in classic centralized learning: we initialize the model parameters," @@ -15520,15 +22185,15 @@ msgstr "" " initialisons les paramètres du modèle, soit de façon aléatoire, soit à " "partir d'un point de contrôle précédemment sauvegardé." -#: ../../source/tutorial-what-is-federated-learning.ipynb:210 -msgid "|9d20be8160f7451fb0f33b194506503f|" +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:210 +msgid "|ba47ffb421814b0f8f9fa5719093d839|" msgstr "" -#: ../../source/tutorial-what-is-federated-learning.ipynb:307 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:307 msgid "Initialize global model" msgstr "Initialise le modèle global" -#: ../../source/tutorial-what-is-federated-learning.ipynb:217 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:217 msgid "" "Step 1: Send model to a number of connected organizations/devices (client" " nodes)" @@ -15536,7 +22201,7 @@ msgstr "" "Étape 1 : envoyer le modèle à un certain nombre d'organisations/appareils" " connectés (nœuds clients)" -#: ../../source/tutorial-what-is-federated-learning.ipynb:219 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:219 #, fuzzy msgid "" "Next, we send the parameters of the global model to the connected client " @@ -15555,15 +22220,15 @@ msgstr "" "est que la sélection d'un nombre croissant de nœuds clients a des " "rendements décroissants." -#: ../../source/tutorial-what-is-federated-learning.ipynb:225 -msgid "|3d949f76988443c59990d2e64f05c386|" +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:225 +msgid "|aeac5bf79cbf497082e979834717e01b|" msgstr "" -#: ../../source/tutorial-what-is-federated-learning.ipynb:309 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:309 msgid "Send global model" msgstr "Envoyer le modèle global" -#: ../../source/tutorial-what-is-federated-learning.ipynb:232 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:232 msgid "" "Step 2: Train model locally on the data of each organization/device " "(client node)" @@ -15571,7 +22236,7 @@ msgstr "" "Étape 2 : Entraîne le modèle localement sur les données de chaque " "organisation/appareil (nœud client)" -#: ../../source/tutorial-what-is-federated-learning.ipynb:234 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:234 msgid "" "Now that all (selected) client nodes have the latest version of the " "global model parameters, they start the local training. They use their " @@ -15588,19 +22253,19 @@ msgstr "" "pendant un petit moment. Il peut s'agir d'une seule époque sur les " "données locales, ou même de quelques étapes (mini-batchs)." -#: ../../source/tutorial-what-is-federated-learning.ipynb:240 -msgid "|526c6d9140f6404f8a226d9056327b3b|" +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:240 +msgid "|ce27ed4bbe95459dba016afc42486ba2|" msgstr "" -#: ../../source/tutorial-what-is-federated-learning.ipynb:311 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:311 msgid "Train on local data" msgstr "Forme-toi aux données locales" -#: ../../source/tutorial-what-is-federated-learning.ipynb:247 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:247 msgid "Step 3: Return model updates back to the server" msgstr "Étape 3 : Renvoyer les mises à jour du modèle au serveur" -#: ../../source/tutorial-what-is-federated-learning.ipynb:249 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:249 msgid "" "After local training, each client node has a slightly different version " "of the model parameters they originally received. The parameters are all " @@ -15619,21 +22284,21 @@ msgstr "" "du modèle, soit seulement les gradients qui ont été accumulés au cours de" " l'entraînement local." -#: ../../source/tutorial-what-is-federated-learning.ipynb:255 -msgid "|a5f6af14cd7c4550929b17f83b4f63c7|" +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:255 +msgid "|ae94a7f71dda443cbec2385751427d41|" msgstr "" -#: ../../source/tutorial-what-is-federated-learning.ipynb:313 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:313 msgid "Send model updates" msgstr "Envoyer les mises à jour du modèle" -#: ../../source/tutorial-what-is-federated-learning.ipynb:262 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:262 msgid "Step 4: Aggregate model updates into a new global model" msgstr "" "Étape 4 : Agréger les mises à jour des modèles dans un nouveau modèle " "global" -#: ../../source/tutorial-what-is-federated-learning.ipynb:264 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:264 msgid "" "The server receives model updates from the selected client nodes. If it " "selected 100 client nodes, it now has 100 slightly different versions of " @@ -15648,7 +22313,7 @@ msgstr "" "voulions-nous pas avoir un seul modèle qui contienne les apprentissages " "des données de l'ensemble des 100 nœuds clients ?" -#: ../../source/tutorial-what-is-federated-learning.ipynb:266 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:266 msgid "" "In order to get one single model, we have to combine all the model " "updates we received from the client nodes. This process is called " @@ -15678,19 +22343,19 @@ msgstr "" "weighting - each of the 10 examples would influence the global model ten " "times as much as each of the 100 examples." -#: ../../source/tutorial-what-is-federated-learning.ipynb:273 -msgid "|bcd571c4f4ee4803a54f71b5c20448cb|" +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:273 +msgid "|e61fce4d43d243e7bb08bdde97d81ce6|" msgstr "" -#: ../../source/tutorial-what-is-federated-learning.ipynb:315 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:315 msgid "Aggregate model updates" msgstr "Mises à jour globales du modèle" -#: ../../source/tutorial-what-is-federated-learning.ipynb:280 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:280 msgid "Step 5: Repeat steps 1 to 4 until the model converges" msgstr "Étape 5 : répète les étapes 1 à 4 jusqu'à ce que le modèle converge" -#: ../../source/tutorial-what-is-federated-learning.ipynb:282 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:282 msgid "" "Steps 1 to 4 are what we call a single round of federated learning. The " "global model parameters get sent to the participating client nodes (step " @@ -15705,7 +22370,7 @@ msgstr "" " serveur (étape 3), et le serveur agrège ensuite les mises à jour du " "modèle pour obtenir une nouvelle version du modèle global (étape 4)." -#: ../../source/tutorial-what-is-federated-learning.ipynb:284 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:284 #, fuzzy msgid "" "During a single round, each client node that participates in that " @@ -15725,7 +22390,7 @@ msgstr "" "modèle entièrement entraîné qui fonctionne bien sur l'ensemble des " "données de tous les nœuds clients." -#: ../../source/tutorial-what-is-federated-learning.ipynb:289 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:289 msgid "" "Congratulations, you now understand the basics of federated learning. " "There's a lot more to discuss, of course, but that was federated learning" @@ -15744,7 +22409,7 @@ msgstr "" "meilleure façon d'agréger les mises à jour du modèle ? Comment pouvons-" "nous gérer les nœuds clients qui échouent (stragglers) ?" -#: ../../source/tutorial-what-is-federated-learning.ipynb:294 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:294 #, fuzzy msgid "" "Just like we can train a model on the decentralized data of different " @@ -15760,11 +22425,11 @@ msgstr "" "fédérée fait partie intégrante de la plupart des systèmes d'apprentissage" " fédéré." -#: ../../source/tutorial-what-is-federated-learning.ipynb:297 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:297 msgid "Federated analytics" msgstr "Analyses fédérées" -#: ../../source/tutorial-what-is-federated-learning.ipynb:299 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:299 msgid "" "In many cases, machine learning isn't necessary to derive value from " "data. Data analysis can yield valuable insights, but again, there's often" @@ -15786,12 +22451,12 @@ msgstr "" "empêcher le serveur de voir les résultats soumis par les nœuds clients " "individuels." -#: ../../source/tutorial-what-is-federated-learning.ipynb:303 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:303 #, fuzzy msgid "Differential Privacy" msgstr "Confidentialité différentielle" -#: ../../source/tutorial-what-is-federated-learning.ipynb:305 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:305 msgid "" "Differential privacy (DP) is often mentioned in the context of Federated " "Learning. It is a privacy-preserving method used when analyzing and " @@ -15802,11 +22467,11 @@ msgid "" "optimization that provides a quantifiable privacy protection measure." msgstr "" -#: ../../source/tutorial-what-is-federated-learning.ipynb:326 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:326 msgid "Flower" msgstr "Fleur" -#: ../../source/tutorial-what-is-federated-learning.ipynb:328 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:328 msgid "" "Federated learning, federated evaluation, and federated analytics require" " infrastructure to move machine learning models back and forth, train and" @@ -15826,11 +22491,11 @@ msgstr "" "l'utilisateur de fédérer n'importe quelle charge de travail, n'importe " "quel cadre de ML et n'importe quel langage de programmation." -#: ../../source/tutorial-what-is-federated-learning.ipynb:334 -msgid "|c76452ae1ed84965be7ef23c72b95845|" +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:334 +msgid "|08cb60859b07461588fe44e55810b050|" msgstr "" -#: ../../source/tutorial-what-is-federated-learning.ipynb:340 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:340 msgid "" "Flower federated learning server and client nodes (car, scooter, personal" " computer, roomba, and phone)" @@ -15838,7 +22503,7 @@ msgstr "" "Serveur d'apprentissage fédéré de Flower et nœuds clients (voiture, " "scooter, ordinateur personnel, roomba et téléphone)" -#: ../../source/tutorial-what-is-federated-learning.ipynb:353 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:353 msgid "" "Congratulations, you just learned the basics of federated learning and " "how it relates to the classic (centralized) machine learning!" @@ -15846,7 +22511,7 @@ msgstr "" "Félicitations, tu viens d'apprendre les bases de l'apprentissage fédéré " "et son rapport avec l'apprentissage automatique classique (centralisé) !" -#: ../../source/tutorial-what-is-federated-learning.ipynb:355 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:355 msgid "" "In the next part of this tutorial, we are going to build a first " "federated learning system with Flower." @@ -15854,7 +22519,7 @@ msgstr "" "Dans la prochaine partie de ce tutoriel, nous allons construire un " "premier système d'apprentissage fédéré avec Flower." -#: ../../source/tutorial-what-is-federated-learning.ipynb:373 +#: ../../source/tutorial-series-what-is-federated-learning.ipynb:373 #, fuzzy msgid "" "The `Flower Federated Learning Tutorial - Part 1 " @@ -17221,14 +23886,13 @@ msgstr "" #~ " and manages `virtual` clients. These " #~ "clients are identical to `non-virtual`" #~ " clients (i.e. the ones you launch" -#~ " via the command `flwr.client.start_client" -#~ " `_)" -#~ " in the sense that they can be" -#~ " configure by creating a class " -#~ "inheriting, for example, from " -#~ "`flwr.client.NumPyClient `_ and therefore " -#~ "behave in an identical way. In " +#~ " via the command `flwr.client.start_client " +#~ "`_) in the" +#~ " sense that they can be configure " +#~ "by creating a class inheriting, for " +#~ "example, from `flwr.client.NumPyClient `_ and therefore" +#~ " behave in an identical way. In " #~ "addition to that, clients managed by " #~ "the :code:`VirtualClientEngine` are:" #~ msgstr "" @@ -17705,7 +24369,7 @@ msgstr "" #~ msgstr "Documentation de Flower" #~ msgid "PyTorch" -#~ msgstr "PyTorch" +#~ msgstr "Exemples de PyTorch" #~ msgid "TensorFlow" #~ msgstr "TensorFlow" @@ -17714,7 +24378,7 @@ msgstr "" #~ msgstr "Client de Flower" #~ msgid "flwr (Python API reference)" -#~ msgstr "flwr (paquet Python)" +#~ msgstr "Référence pour l'API" #~ msgid "Unreleased" #~ msgstr "Inédit" @@ -18909,3 +25573,228 @@ msgstr "" #~ msgid "|025f0a6f7a6145cba4bf8fa0e2495851|" #~ msgstr "" +#~ msgid "Before the release" +#~ msgstr "Avant la sortie" + +#~ msgid "" +#~ "Update the changelog (``changelog.md``) with" +#~ " all relevant changes that happened " +#~ "after the last release. If the " +#~ "last release was tagged ``v1.2.0``, you" +#~ " can use the following URL to " +#~ "see all commits that got merged " +#~ "into ``main`` since then:" +#~ msgstr "" +#~ "Mettez à jour le journal des " +#~ "modifications (``changelog.md``) avec tous les" +#~ " changements pertinents qui se sont " +#~ "produits après la dernière version. Si" +#~ " la dernière version a été étiquetée" +#~ " ``v1.2.0``, vous pouvez utiliser l'URL " +#~ "suivante pour voir tous les commits " +#~ "qui ont été fusionnés dans ``main`` " +#~ "depuis lors :" + +#~ msgid "" +#~ "`GitHub: Compare v1.2.0...main " +#~ "`_" +#~ msgstr "" +#~ "`GitHub : Compare v1.2.0...main " +#~ "`_" + +#~ msgid "" +#~ "Thank the authors who contributed since" +#~ " the last release. This command helps" +#~ " extract them: ``git log --format='%aN' " +#~ "v1.1.0..HEAD | sort -u``. The command" +#~ " has the same order as ``git " +#~ "shortlog``." +#~ msgstr "" +#~ "Remerciez les auteurs qui ont contribué" +#~ " depuis la dernière version. Cette " +#~ "commande permet de les extraire : " +#~ "``git log --format='%aN' v1.1.0..HEAD | " +#~ "sort -u``. La commande a le même" +#~ " ordre que ``git shortlog``." + +#~ msgid "" +#~ "Update the ``changelog.md`` section header " +#~ "``Unreleased`` to contain the version " +#~ "number and date for the release " +#~ "you are building. Create a pull " +#~ "request with the change." +#~ msgstr "" +#~ "Mettez à jour l'en-tête de section" +#~ " ``changelog.md`` ``Unreleased`` pour qu'il " +#~ "contienne le numéro de version et " +#~ "la date de la version que vous " +#~ "construisez. Créez une demande de " +#~ "traction avec le changement." + +#~ msgid "" +#~ "Tag the release commit with the " +#~ "version number as soon as the PR" +#~ " is merged: ``git tag v0.12.3``, then" +#~ " ``git push --tags``" +#~ msgstr "" +#~ "Marquez le commit de la version " +#~ "avec le numéro de version dès que" +#~ " le PR est fusionné : ``git tag" +#~ " v0.12.3``, puis ``git push --tags``" + +#~ msgid "" +#~ "Build the release with ``./dev/build.sh``, " +#~ "then publish it with ``./dev/publish.sh``" +#~ msgstr "" +#~ "Construisez la version avec " +#~ "``./dev/build.sh``, puis publiez-la avec " +#~ "``./dev/publish.sh``" + +#~ msgid "" +#~ "Create an entry in GitHub releases " +#~ "with the release notes for the " +#~ "previously tagged commit and attach the" +#~ " build artifacts (:code:`.whl` and " +#~ ":code:`.tar.gz`)." +#~ msgstr "" +#~ "Crée une entrée dans GitHub releases " +#~ "avec les notes de version pour le" +#~ " commit précédemment étiqueté et attache" +#~ " les artefacts de construction " +#~ "(:code:`.whl` et :code:`.tar.gz`)." + +#~ msgid "" +#~ "Second, create a virtual environment " +#~ "(and activate it). If you chose to" +#~ " use :code:`pyenv` (with the :code" +#~ ":`pyenv-virtualenv` plugin) and already " +#~ "have it installed , you can use" +#~ " the following convenience script (by " +#~ "default it will use :code:`Python " +#~ "3.8.17`, but you can change it by" +#~ " providing a specific :code:``)::" +#~ msgstr "" +#~ "Deuxièmement, créer un environnement virtuel" +#~ " (et l'activer). Si vous choisissez " +#~ "d'utiliser :code:`pyenv` (avec le plugin " +#~ ":code:`pyenv-virtualenv`) et que vous " +#~ "l'avez déjà installé, vous pouvez " +#~ "utiliser le script suivant (par défaut" +#~ " il utilisera :code:`Python 3.8.17`, mais" +#~ " vous pouvez le changer en " +#~ "fournissant une :code:`` spécifique)::" + +#~ msgid "server.strategy.FedAvg" +#~ msgstr "serveur.stratégie.FedAvg" + +#~ msgid "server.strategy.FedAvgM" +#~ msgstr "stratégie.serveur.FedAvgM" + +#~ msgid "server.strategy.QFedAvg" +#~ msgstr "server.strategy.QFedAvg" + +#~ msgid "server.strategy.FedOpt" +#~ msgstr "serveur.stratégie.FedOpt" + +#~ msgid "server.strategy.FedProx" +#~ msgstr "serveur.stratégie.FedProx" + +#~ msgid "server.strategy.FedAdagrad" +#~ msgstr "serveur.stratégie.FedAdagrad" + +#~ msgid "server.strategy.FedAdam" +#~ msgstr "serveur.stratégie.FedAdam" + +#~ msgid "server.strategy.FedYogi" +#~ msgstr "serveur.stratégie.FedYogi" + +#~ msgid "" +#~ "`achiverram28`, `Adam Narozniak`, `Anass " +#~ "Anhari`, `Charles Beauville`, `Dana-Farber`," +#~ " `Daniel J. Beutel`, `Daniel Nata " +#~ "Nugraha`, `Edoardo Gabrielli`, `eunchung`, " +#~ "`Gustavo Bertoli`, `Heng Pan`, `Javier`, " +#~ "`Mahdi`, `Ruth Galindo`, `Steven Hé " +#~ "(Sīchàng)`, `Taner Topal`" +#~ msgstr "" + +#~ msgid "" +#~ "Let's now load the CIFAR-10 training " +#~ "and test set, partition them into " +#~ "ten smaller datasets (each split into" +#~ " training and validation set), and " +#~ "wrap the resulting partitions by " +#~ "creating a PyTorch ``DataLoader`` for " +#~ "each of them:" +#~ msgstr "" +#~ "Chargeons maintenant l'ensemble de formation" +#~ " et de test CIFAR-10, partitionnons-" +#~ "les en dix ensembles de données " +#~ "plus petits (chacun divisé en ensemble" +#~ " de formation et de validation), et" +#~ " enveloppons les partitions résultantes en" +#~ " créant un PyTorch ``DataLoader`` pour " +#~ "chacun d'entre eux :" + +#~ msgid "" +#~ "Let's build a horizontal federated " +#~ "learning system using XGBoost and " +#~ "Flower!" +#~ msgstr "" +#~ "Construisons un système d'apprentissage fédéré" +#~ " horizontal en utilisant XGBoost et " +#~ "Flower !" + +#~ msgid "" +#~ "Please refer to the `full code " +#~ "example `_ to learn " +#~ "more." +#~ msgstr "" +#~ "Réfère-toi à l'exemple de code " +#~ "complet `_ pour en " +#~ "savoir plus." + +#~ msgid "|3ff4c820a01d4a5abb022617de537c54|" +#~ msgstr "" + +#~ msgid "|7f1889391ad448e2a65920165f0d798c|" +#~ msgstr "" + +#~ msgid "|a171dc4a0d044e70b5d585cc10ace0e0|" +#~ msgstr "" + +#~ msgid "|fe518aa0d86341f7b2fc87bd6e3bbf0c|" +#~ msgstr "" + +#~ msgid "|6abfdf0dade44469ae9f08c8dc7d148c|" +#~ msgstr "" + +#~ msgid "|b4f147db24bb4da9a786e1d6676a1c2d|" +#~ msgstr "" + +#~ msgid "|5c62032f589a457bb37b5fee5b2adbde|" +#~ msgstr "" + +#~ msgid "|f154df1846dd44f79a94f1dc3ae8b088|" +#~ msgstr "" + +#~ msgid "|9d20be8160f7451fb0f33b194506503f|" +#~ msgstr "" + +#~ msgid "|3d949f76988443c59990d2e64f05c386|" +#~ msgstr "" + +#~ msgid "|526c6d9140f6404f8a226d9056327b3b|" +#~ msgstr "" + +#~ msgid "|a5f6af14cd7c4550929b17f83b4f63c7|" +#~ msgstr "" + +#~ msgid "|bcd571c4f4ee4803a54f71b5c20448cb|" +#~ msgstr "" + +#~ msgid "|c76452ae1ed84965be7ef23c72b95845|" +#~ msgstr "" + diff --git a/doc/locales/pt_BR/LC_MESSAGES/framework-docs.po b/doc/locales/pt_BR/LC_MESSAGES/framework-docs.po index 22c28a05caa4..5314e0041a99 100644 --- a/doc/locales/pt_BR/LC_MESSAGES/framework-docs.po +++ b/doc/locales/pt_BR/LC_MESSAGES/framework-docs.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Flower main\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-10-19 07:55+0200\n" +"POT-Creation-Date: 2024-02-13 11:23+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language: pt_BR\n" @@ -17,7 +17,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.12.1\n" +"Generated-By: Babel 2.13.1\n" #: ../../source/contributor-explanation-architecture.rst:2 msgid "Flower Architecture" @@ -53,117 +53,225 @@ msgid "" "Virtual Client Engine and Edge Client Engine" msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:2 -msgid "Creating New Messages" +#: ../../source/contributor-how-to-build-docker-images.rst:2 +msgid "How to build Docker Flower images locally" msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:4 +#: ../../source/contributor-how-to-build-docker-images.rst:4 msgid "" -"This is a simple guide for creating a new type of message between the " -"server and clients in Flower." +"Flower provides pre-made docker images on `Docker Hub " +"`_ that include all necessary " +"dependencies for running the server. You can also build your own custom " +"docker images from scratch with a different version of Python or Ubuntu " +"if that is what you need. In this guide, we will explain what images " +"exist and how to build them locally." msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:6 +#: ../../source/contributor-how-to-build-docker-images.rst:9 msgid "" -"Let's suppose we have the following example functions in " -":code:`server.py` and :code:`numpy_client.py`..." +"Before we can start, we need to meet a few prerequisites in our local " +"development environment." msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:8 -msgid "Server's side:" +#: ../../source/contributor-how-to-build-docker-images.rst:11 +msgid "Clone the flower repository." msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:17 -msgid "Client's side:" +#: ../../source/contributor-how-to-build-docker-images.rst:17 +msgid "Verify the Docker daemon is running." msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:26 +#: ../../source/contributor-how-to-build-docker-images.rst:19 msgid "" -"Let's now see what we need to implement in order to get this simple " -"function between the server and client to work!" +"Please follow the first section on `Run Flower using Docker " +"`_ " +"which covers this step in more detail." msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:30 -msgid "Message Types for Protocol Buffers" +#: ../../source/contributor-how-to-build-docker-images.rst:23 +msgid "" +"Currently, Flower provides two images, a base image and a server image. " +"There will also be a client image soon. The base image, as the name " +"suggests, contains basic dependencies that both the server and the client" +" need. This includes system dependencies, Python and Python tools. The " +"server image is based on the base image, but it additionally installs the" +" Flower server using ``pip``." msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:32 +#: ../../source/contributor-how-to-build-docker-images.rst:28 msgid "" -"The first thing we need to do is to define a message type for the RPC " -"system in :code:`transport.proto`. Note that we have to do it for both " -"the request and response messages. For more details on the syntax of " -"proto3, please see the `official documentation " -"`_." +"The build instructions that assemble the images are located in the " +"respective Dockerfiles. You can find them in the subdirectories of " +"``src/docker``." msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:35 -msgid "Within the :code:`ServerMessage` block:" +#: ../../source/contributor-how-to-build-docker-images.rst:31 +msgid "" +"Both, base and server image are configured via build arguments. Through " +"build arguments, we can make our build more flexible. For example, in the" +" base image, we can specify the version of Python to install using the " +"``PYTHON_VERSION`` build argument. Some of the build arguments have " +"default values, others must be specified when building the image. All " +"available build arguments for each image are listed in one of the tables " +"below." msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:52 -msgid "Within the ClientMessage block:" +#: ../../source/contributor-how-to-build-docker-images.rst:38 +msgid "Building the base image" msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:70 -msgid "" -"Make sure to also add a field of the newly created message type in " -":code:`oneof msg`." +#: ../../source/contributor-how-to-build-docker-images.rst:44 +#: ../../source/contributor-how-to-build-docker-images.rst:86 +msgid "Build argument" msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:72 -msgid "Once that is done, we will compile the file with:" +#: ../../source/contributor-how-to-build-docker-images.rst:45 +#: ../../source/contributor-how-to-build-docker-images.rst:87 +msgid "Description" msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:78 -msgid "If it compiles succesfully, you should see the following message:" +#: ../../source/contributor-how-to-build-docker-images.rst:46 +#: ../../source/contributor-how-to-build-docker-images.rst:88 +msgid "Required" msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:87 -msgid "Serialization and Deserialization Functions" +#: ../../source/contributor-how-to-build-docker-images.rst:47 +#: ../../source/contributor-how-to-build-docker-images.rst:89 +msgid "Example" msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:89 -msgid "" -"Our next step is to add functions to serialize and deserialize Python " -"datatypes to or from our defined RPC message types. You should add these " -"functions in :code:`serde.py`." +#: ../../source/contributor-how-to-build-docker-images.rst:48 +msgid "``PYTHON_VERSION``" msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:91 -msgid "The four functions:" +#: ../../source/contributor-how-to-build-docker-images.rst:49 +msgid "Version of ``python`` to be installed." msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:112 -msgid "Sending the Message from the Server" +#: ../../source/contributor-how-to-build-docker-images.rst:50 +#: ../../source/contributor-how-to-build-docker-images.rst:54 +#: ../../source/contributor-how-to-build-docker-images.rst:58 +#: ../../source/contributor-how-to-build-docker-images.rst:100 +msgid "Yes" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:51 +msgid "``3.11``" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:52 +msgid "``PIP_VERSION``" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:53 +msgid "Version of ``pip`` to be installed." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:55 +msgid "``23.0.1``" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:56 +msgid "``SETUPTOOLS_VERSION``" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:57 +msgid "Version of ``setuptools`` to be installed." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:59 +msgid "``69.0.2``" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:60 +msgid "``UBUNTU_VERSION``" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:61 +msgid "Version of the official Ubuntu Docker image." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:62 +msgid "Defaults to ``22.04``." msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:114 +#: ../../source/contributor-how-to-build-docker-images.rst:65 msgid "" -"Now write the request function in your Client Proxy class (e.g., " -":code:`grpc_client_proxy.py`) using the serde functions you just created:" +"The following example creates a base image with Python 3.11.0, pip 23.0.1" +" and setuptools 69.0.2:" msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:128 -msgid "Receiving the Message by the Client" +#: ../../source/contributor-how-to-build-docker-images.rst:76 +msgid "" +"The name of image is ``flwr_base`` and the tag ``0.1.0``. Remember that " +"the build arguments as well as the name and tag can be adapted to your " +"needs. These values serve as examples only." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:80 +msgid "Building the server image" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:90 +msgid "``BASE_REPOSITORY``" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:91 +msgid "The repository name of the base image." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:92 +msgid "Defaults to ``flwr/server``." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:94 +msgid "``BASE_IMAGE_TAG``" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:95 +msgid "The image tag of the base image." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:96 +msgid "Defaults to ``py3.11-ubuntu22.04``." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:98 +msgid "``FLWR_VERSION``" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:99 +msgid "Version of Flower to be installed." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:101 +msgid "``1.7.0``" msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:130 +#: ../../source/contributor-how-to-build-docker-images.rst:103 msgid "" -"Last step! Modify the code in :code:`message_handler.py` to check the " -"field of your message and call the :code:`example_response` function. " -"Remember to use the serde functions!" +"The following example creates a server image with the official Flower " +"base image py3.11-ubuntu22.04 and Flower 1.7.0:" msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:132 -msgid "Within the handle function:" +#: ../../source/contributor-how-to-build-docker-images.rst:114 +msgid "" +"The name of image is ``flwr_server`` and the tag ``0.1.0``. Remember that" +" the build arguments as well as the name and tag can be adapted to your " +"needs. These values serve as examples only." msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:139 -msgid "And add a new function:" +#: ../../source/contributor-how-to-build-docker-images.rst:117 +msgid "" +"If you want to use your own base image instead of the official Flower " +"base image, all you need to do is set the ``BASE_REPOSITORY`` and " +"``BASE_IMAGE_TAG`` build arguments. The value of ``BASE_REPOSITORY`` must" +" match the name of your image and the value of ``BASE_IMAGE_TAG`` must " +"match the tag of your image." msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:149 -msgid "Hopefully, when you run your program you will get the intended result!" +#: ../../source/contributor-how-to-build-docker-images.rst:131 +msgid "After creating the image, we can test whether the image is working:" msgstr "" #: ../../source/contributor-how-to-contribute-translations.rst:2 @@ -272,6 +380,119 @@ msgid "" "issue on our `GitHub repo `_." msgstr "" +#: ../../source/contributor-how-to-create-new-messages.rst:2 +msgid "Creating New Messages" +msgstr "" + +#: ../../source/contributor-how-to-create-new-messages.rst:4 +msgid "" +"This is a simple guide for creating a new type of message between the " +"server and clients in Flower." +msgstr "" + +#: ../../source/contributor-how-to-create-new-messages.rst:6 +msgid "" +"Let's suppose we have the following example functions in " +":code:`server.py` and :code:`numpy_client.py`..." +msgstr "" + +#: ../../source/contributor-how-to-create-new-messages.rst:8 +msgid "Server's side:" +msgstr "" + +#: ../../source/contributor-how-to-create-new-messages.rst:17 +msgid "Client's side:" +msgstr "" + +#: ../../source/contributor-how-to-create-new-messages.rst:26 +msgid "" +"Let's now see what we need to implement in order to get this simple " +"function between the server and client to work!" +msgstr "" + +#: ../../source/contributor-how-to-create-new-messages.rst:30 +msgid "Message Types for Protocol Buffers" +msgstr "" + +#: ../../source/contributor-how-to-create-new-messages.rst:32 +msgid "" +"The first thing we need to do is to define a message type for the RPC " +"system in :code:`transport.proto`. Note that we have to do it for both " +"the request and response messages. For more details on the syntax of " +"proto3, please see the `official documentation " +"`_." +msgstr "" + +#: ../../source/contributor-how-to-create-new-messages.rst:35 +msgid "Within the :code:`ServerMessage` block:" +msgstr "" + +#: ../../source/contributor-how-to-create-new-messages.rst:52 +msgid "Within the ClientMessage block:" +msgstr "" + +#: ../../source/contributor-how-to-create-new-messages.rst:70 +msgid "" +"Make sure to also add a field of the newly created message type in " +":code:`oneof msg`." +msgstr "" + +#: ../../source/contributor-how-to-create-new-messages.rst:72 +msgid "Once that is done, we will compile the file with:" +msgstr "" + +#: ../../source/contributor-how-to-create-new-messages.rst:78 +msgid "If it compiles succesfully, you should see the following message:" +msgstr "" + +#: ../../source/contributor-how-to-create-new-messages.rst:87 +msgid "Serialization and Deserialization Functions" +msgstr "" + +#: ../../source/contributor-how-to-create-new-messages.rst:89 +msgid "" +"Our next step is to add functions to serialize and deserialize Python " +"datatypes to or from our defined RPC message types. You should add these " +"functions in :code:`serde.py`." +msgstr "" + +#: ../../source/contributor-how-to-create-new-messages.rst:91 +msgid "The four functions:" +msgstr "" + +#: ../../source/contributor-how-to-create-new-messages.rst:112 +msgid "Sending the Message from the Server" +msgstr "" + +#: ../../source/contributor-how-to-create-new-messages.rst:114 +msgid "" +"Now write the request function in your Client Proxy class (e.g., " +":code:`grpc_client_proxy.py`) using the serde functions you just created:" +msgstr "" + +#: ../../source/contributor-how-to-create-new-messages.rst:128 +msgid "Receiving the Message by the Client" +msgstr "" + +#: ../../source/contributor-how-to-create-new-messages.rst:130 +msgid "" +"Last step! Modify the code in :code:`message_handler.py` to check the " +"field of your message and call the :code:`example_response` function. " +"Remember to use the serde functions!" +msgstr "" + +#: ../../source/contributor-how-to-create-new-messages.rst:132 +msgid "Within the handle function:" +msgstr "" + +#: ../../source/contributor-how-to-create-new-messages.rst:139 +msgid "And add a new function:" +msgstr "" + +#: ../../source/contributor-how-to-create-new-messages.rst:149 +msgid "Hopefully, when you run your program you will get the intended result!" +msgstr "" + #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:2 msgid "Develop in VSCode Dev Containers" msgstr "" @@ -320,10 +541,11 @@ msgstr "" msgid "" "Configuring and setting up the :code:`Dockerfile` as well the " "configuration for the devcontainer can be a bit more involved. The good " -"thing is you want have to do it. Usually it should be enough to install " -"Docker on your system and ensure its available on your command line. " -"Additionally, install the `VSCode Containers Extension `_." +"thing is you don't have to do it. Usually it should be enough to install " +"`Docker `_ on your system and " +"ensure its available on your command line. Additionally, install the " +"`VSCode Containers Extension `_." msgstr "" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:19 @@ -408,13 +630,13 @@ msgstr "" #: ../../source/contributor-how-to-install-development-versions.rst:22 msgid "" -"``flwr = { path = \"../../dist/flwr-1.0.0-py3-none-any.whl\" }`` (without" +"``flwr = { path = \"../../dist/flwr-1.8.0-py3-none-any.whl\" }`` (without" " extras)" msgstr "" #: ../../source/contributor-how-to-install-development-versions.rst:23 msgid "" -"``flwr = { path = \"../../dist/flwr-1.0.0-py3-none-any.whl\", extras = " +"``flwr = { path = \"../../dist/flwr-1.8.0-py3-none-any.whl\", extras = " "[\"simulation\"] }`` (with extras)" msgstr "" @@ -518,13 +740,13 @@ msgid "" msgstr "" #: ../../source/contributor-how-to-install-development-versions.rst:62 -msgid "Upload the whl (e.g., ``flwr-1.7.0-py3-none-any.whl``)" +msgid "Upload the whl (e.g., ``flwr-1.8.0-py3-none-any.whl``)" msgstr "" #: ../../source/contributor-how-to-install-development-versions.rst:63 msgid "" "Change ``!pip install -q 'flwr[simulation]' torch torchvision " -"matplotlib`` to ``!pip install -q 'flwr-1.7.0-py3-none-" +"matplotlib`` to ``!pip install -q 'flwr-1.8.0-py3-none-" "any.whl[simulation]' torch torchvision matplotlib``" msgstr "" @@ -539,151 +761,136 @@ msgid "" msgstr "" #: ../../source/contributor-how-to-release-flower.rst:7 -msgid "Before the release" +msgid "During the release" msgstr "" #: ../../source/contributor-how-to-release-flower.rst:9 msgid "" -"Update the changelog (``changelog.md``) with all relevant changes that " -"happened after the last release. If the last release was tagged " -"``v1.2.0``, you can use the following URL to see all commits that got " -"merged into ``main`` since then:" +"The version number of a release is stated in ``pyproject.toml``. To " +"release a new version of Flower, the following things need to happen (in " +"that order):" msgstr "" #: ../../source/contributor-how-to-release-flower.rst:11 msgid "" -"`GitHub: Compare v1.2.0...main " -"`_" -msgstr "" - -#: ../../source/contributor-how-to-release-flower.rst:13 -msgid "" -"Thank the authors who contributed since the last release. This can be " -"done by running the ``./dev/add-shortlog.sh`` convenience script (it can " -"be ran multiple times and will update the names in the list if new " -"contributors were added in the meantime)." -msgstr "" - -#: ../../source/contributor-how-to-release-flower.rst:16 -msgid "During the release" -msgstr "" - -#: ../../source/contributor-how-to-release-flower.rst:18 -msgid "" -"The version number of a release is stated in ``pyproject.toml``. To " -"release a new version of Flower, the following things need to happen (in " -"that order):" +"Run ``python3 src/py/flwr_tool/update_changelog.py `` in " +"order to add every new change to the changelog (feel free to make manual " +"changes to the changelog afterwards until it looks good)." msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:20 +#: ../../source/contributor-how-to-release-flower.rst:12 msgid "" -"Update the ``changelog.md`` section header ``Unreleased`` to contain the " -"version number and date for the release you are building. Create a pull " -"request with the change." +"Once the changelog has been updated with all the changes, run ``./dev" +"/prepare-release-changelog.sh v``, where ```` " +"is the version stated in ``pyproject.toml`` (notice the ``v`` added " +"before it). This will replace the ``Unreleased`` header of the changelog " +"by the version and current date, and it will add a thanking message for " +"the contributors. Open a pull request with those changes." msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:21 +#: ../../source/contributor-how-to-release-flower.rst:13 msgid "" -"Tag the release commit with the version number as soon as the PR is " -"merged: ``git tag v0.12.3``, then ``git push --tags``. This will create a" -" draft release on GitHub containing the correct artifacts and the " -"relevant part of the changelog." +"Once the pull request is merged, tag the release commit with the version " +"number as soon as the PR is merged: ``git tag v`` (notice " +"the ``v`` added before the version number), then ``git push --tags``. " +"This will create a draft release on GitHub containing the correct " +"artifacts and the relevant part of the changelog." msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:22 +#: ../../source/contributor-how-to-release-flower.rst:14 msgid "Check the draft release on GitHub, and if everything is good, publish it." msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:25 +#: ../../source/contributor-how-to-release-flower.rst:17 msgid "After the release" msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:27 +#: ../../source/contributor-how-to-release-flower.rst:19 msgid "Create a pull request which contains the following changes:" msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:29 +#: ../../source/contributor-how-to-release-flower.rst:21 msgid "Increase the minor version in ``pyproject.toml`` by one." msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:30 +#: ../../source/contributor-how-to-release-flower.rst:22 msgid "Update all files which contain the current version number if necessary." msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:31 +#: ../../source/contributor-how-to-release-flower.rst:23 msgid "Add a new ``Unreleased`` section in ``changelog.md``." msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:33 +#: ../../source/contributor-how-to-release-flower.rst:25 msgid "" "Merge the pull request on the same day (i.e., before a new nighly release" " gets published to PyPI)." msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:36 +#: ../../source/contributor-how-to-release-flower.rst:28 msgid "Publishing a pre-release" msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:39 +#: ../../source/contributor-how-to-release-flower.rst:31 msgid "Pre-release naming" msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:41 +#: ../../source/contributor-how-to-release-flower.rst:33 msgid "" "PyPI supports pre-releases (alpha, beta, release candiate). Pre-releases " "MUST use one of the following naming patterns:" msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:43 +#: ../../source/contributor-how-to-release-flower.rst:35 msgid "Alpha: ``MAJOR.MINOR.PATCHaN``" msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:44 +#: ../../source/contributor-how-to-release-flower.rst:36 msgid "Beta: ``MAJOR.MINOR.PATCHbN``" msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:45 +#: ../../source/contributor-how-to-release-flower.rst:37 msgid "Release candiate (RC): ``MAJOR.MINOR.PATCHrcN``" msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:47 +#: ../../source/contributor-how-to-release-flower.rst:39 msgid "Examples include:" msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:49 +#: ../../source/contributor-how-to-release-flower.rst:41 msgid "``1.0.0a0``" msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:50 +#: ../../source/contributor-how-to-release-flower.rst:42 msgid "``1.0.0b0``" msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:51 +#: ../../source/contributor-how-to-release-flower.rst:43 msgid "``1.0.0rc0``" msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:52 +#: ../../source/contributor-how-to-release-flower.rst:44 msgid "``1.0.0rc1``" msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:54 +#: ../../source/contributor-how-to-release-flower.rst:46 msgid "" "This is in line with PEP-440 and the recommendations from the Python " "Packaging Authority (PyPA):" msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:57 +#: ../../source/contributor-how-to-release-flower.rst:49 msgid "`PEP-440 `_" msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:58 +#: ../../source/contributor-how-to-release-flower.rst:50 msgid "" "`PyPA Choosing a versioning scheme " "`_" msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:60 +#: ../../source/contributor-how-to-release-flower.rst:52 msgid "" "Note that the approach defined by PyPA is not compatible with SemVer " "2.0.0 spec, for details consult the `Semantic Versioning Specification " @@ -691,26 +898,26 @@ msgid "" "11 on precedence)." msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:63 +#: ../../source/contributor-how-to-release-flower.rst:55 msgid "Pre-release classification" msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:65 +#: ../../source/contributor-how-to-release-flower.rst:57 msgid "Should the next pre-release be called alpha, beta, or release candidate?" msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:67 +#: ../../source/contributor-how-to-release-flower.rst:59 msgid "" "RC: feature complete, no known issues (apart from issues that are " "classified as \"won't fix\" for the next stable release) - if no issues " "surface this will become the next stable release" msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:68 +#: ../../source/contributor-how-to-release-flower.rst:60 msgid "Beta: feature complete, allowed to have known issues" msgstr "" -#: ../../source/contributor-how-to-release-flower.rst:69 +#: ../../source/contributor-how-to-release-flower.rst:61 msgid "Alpha: not feature complete, allowed to have known issues" msgstr "" @@ -823,11 +1030,11 @@ msgid "" msgstr "" #: ../../source/contributor-how-to-write-documentation.rst:10 -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:119 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:142 msgid "" "Note that, in order to build the documentation locally (with ``poetry run" " make html``, like described below), `Pandoc " -"_` needs to be installed on the " +"`_ needs to be installed on the " "system." msgstr "" @@ -1002,20 +1209,19 @@ msgstr "" msgid "" "If you're familiar with how contributing on GitHub works, you can " "directly checkout our `getting started guide for contributors " -"`_ and " -"examples of `good first contributions `_." +"`_." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:12 +#: ../../source/contributor-tutorial-contribute-on-github.rst:11 msgid "Setting up the repository" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:23 +#: ../../source/contributor-tutorial-contribute-on-github.rst:22 msgid "**Create a GitHub account and setup Git**" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:15 +#: ../../source/contributor-tutorial-contribute-on-github.rst:14 msgid "" "Git is a distributed version control tool. This allows for an entire " "codebase's history to be stored and every developer's machine. It is a " @@ -1024,20 +1230,20 @@ msgid "" "/set-up-git>`_ to set it up." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:18 +#: ../../source/contributor-tutorial-contribute-on-github.rst:17 msgid "" "GitHub, itself, is a code hosting platform for version control and " "collaboration. It allows for everyone to collaborate and work from " "anywhere on remote repositories." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:20 +#: ../../source/contributor-tutorial-contribute-on-github.rst:19 msgid "" "If you haven't already, you will need to create an account on `GitHub " "`_." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:22 +#: ../../source/contributor-tutorial-contribute-on-github.rst:21 msgid "" "The idea behind the generic Git and GitHub workflow boils down to this: " "you download code from a remote repository on GitHub, make changes " @@ -1045,11 +1251,11 @@ msgid "" "history back to GitHub." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:34 +#: ../../source/contributor-tutorial-contribute-on-github.rst:33 msgid "**Forking the Flower repository**" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:26 +#: ../../source/contributor-tutorial-contribute-on-github.rst:25 msgid "" "A fork is a personal copy of a GitHub repository. To create one for " "Flower, you must navigate to https://github.com/adap/flower (while " @@ -1057,7 +1263,7 @@ msgid "" "on the top right of the page." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:31 +#: ../../source/contributor-tutorial-contribute-on-github.rst:30 msgid "" "You can change the name if you want, but this is not necessary as this " "version of Flower will be yours and will sit inside your own account " @@ -1065,11 +1271,11 @@ msgid "" " the top left corner that you are looking at your own version of Flower." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:49 +#: ../../source/contributor-tutorial-contribute-on-github.rst:48 msgid "**Cloning your forked repository**" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:37 +#: ../../source/contributor-tutorial-contribute-on-github.rst:36 msgid "" "The next step is to download the forked repository on your machine to be " "able to make changes to it. On your forked repository page, you should " @@ -1077,27 +1283,27 @@ msgid "" "ability to copy the HTTPS link of the repository." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:43 +#: ../../source/contributor-tutorial-contribute-on-github.rst:42 msgid "" "Once you copied the \\, you can open a terminal on your machine, " "navigate to the place you want to download the repository to and type:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:49 +#: ../../source/contributor-tutorial-contribute-on-github.rst:48 msgid "" -"This will create a `flower/` (or the name of your fork if you renamed it)" -" folder in the current working directory." +"This will create a ``flower/`` (or the name of your fork if you renamed " +"it) folder in the current working directory." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:68 +#: ../../source/contributor-tutorial-contribute-on-github.rst:67 msgid "**Add origin**" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:52 +#: ../../source/contributor-tutorial-contribute-on-github.rst:51 msgid "You can then go into the repository folder:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:58 +#: ../../source/contributor-tutorial-contribute-on-github.rst:57 msgid "" "And here we will need to add an origin to our repository. The origin is " "the \\ of the remote fork repository. To obtain it, we can do as " @@ -1105,27 +1311,27 @@ msgid "" "account and copying the link." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:63 +#: ../../source/contributor-tutorial-contribute-on-github.rst:62 msgid "" "Once the \\ is copied, we can type the following command in our " "terminal:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:92 +#: ../../source/contributor-tutorial-contribute-on-github.rst:91 msgid "**Add upstream**" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:71 +#: ../../source/contributor-tutorial-contribute-on-github.rst:70 msgid "" "Now we will add an upstream address to our repository. Still in the same " "directroy, we must run the following command:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:78 +#: ../../source/contributor-tutorial-contribute-on-github.rst:77 msgid "The following diagram visually explains what we did in the previous steps:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:82 +#: ../../source/contributor-tutorial-contribute-on-github.rst:81 msgid "" "The upstream is the GitHub remote address of the parent repository (in " "this case Flower), i.e. the one we eventually want to contribute to and " @@ -1134,17 +1340,17 @@ msgid "" "in our own account." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:86 +#: ../../source/contributor-tutorial-contribute-on-github.rst:85 msgid "" "To make sure our local version of the fork is up-to-date with the latest " "changes from the Flower repository, we can execute the following command:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:95 +#: ../../source/contributor-tutorial-contribute-on-github.rst:94 msgid "Setting up the coding environment" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:97 +#: ../../source/contributor-tutorial-contribute-on-github.rst:96 msgid "" "This can be achieved by following this `getting started guide for " "contributors`_ (note that you won't need to clone the repository). Once " @@ -1152,151 +1358,151 @@ msgid "" "changes!" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:102 +#: ../../source/contributor-tutorial-contribute-on-github.rst:101 msgid "Making changes" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:104 +#: ../../source/contributor-tutorial-contribute-on-github.rst:103 msgid "" "Before making any changes make sure you are up-to-date with your " "repository:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:110 +#: ../../source/contributor-tutorial-contribute-on-github.rst:109 msgid "And with Flower's repository:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:124 +#: ../../source/contributor-tutorial-contribute-on-github.rst:123 msgid "**Create a new branch**" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:117 +#: ../../source/contributor-tutorial-contribute-on-github.rst:116 msgid "" "To make the history cleaner and easier to work with, it is good practice " "to create a new branch for each feature/project that needs to be " "implemented." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:120 +#: ../../source/contributor-tutorial-contribute-on-github.rst:119 msgid "" "To do so, just run the following command inside the repository's " "directory:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:127 +#: ../../source/contributor-tutorial-contribute-on-github.rst:126 msgid "**Make changes**" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:127 +#: ../../source/contributor-tutorial-contribute-on-github.rst:126 msgid "Write great code and create wonderful changes using your favorite editor!" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:140 +#: ../../source/contributor-tutorial-contribute-on-github.rst:139 msgid "**Test and format your code**" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:130 +#: ../../source/contributor-tutorial-contribute-on-github.rst:129 msgid "" "Don't forget to test and format your code! Otherwise your code won't be " "able to be merged into the Flower repository. This is done so the " "codebase stays consistent and easy to understand." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:133 +#: ../../source/contributor-tutorial-contribute-on-github.rst:132 msgid "To do so, we have written a few scripts that you can execute:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:152 +#: ../../source/contributor-tutorial-contribute-on-github.rst:151 msgid "**Stage changes**" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:143 +#: ../../source/contributor-tutorial-contribute-on-github.rst:142 msgid "" "Before creating a commit that will update your history, you must specify " "to Git which files it needs to take into account." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:145 +#: ../../source/contributor-tutorial-contribute-on-github.rst:144 msgid "This can be done with:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:151 +#: ../../source/contributor-tutorial-contribute-on-github.rst:150 msgid "" "To check which files have been modified compared to the last version " "(last commit) and to see which files are staged for commit, you can use " "the :code:`git status` command." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:162 +#: ../../source/contributor-tutorial-contribute-on-github.rst:161 msgid "**Commit changes**" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:155 +#: ../../source/contributor-tutorial-contribute-on-github.rst:154 msgid "" "Once you have added all the files you wanted to commit using :code:`git " "add`, you can finally create your commit using this command:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:161 +#: ../../source/contributor-tutorial-contribute-on-github.rst:160 msgid "" "The \\ is there to explain to others what the commit " "does. It should be written in an imperative style and be concise. An " "example would be :code:`git commit -m \"Add images to README\"`." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:173 +#: ../../source/contributor-tutorial-contribute-on-github.rst:172 msgid "**Push the changes to the fork**" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:165 +#: ../../source/contributor-tutorial-contribute-on-github.rst:164 msgid "" "Once we have committed our changes, we have effectively updated our local" " history, but GitHub has no way of knowing this unless we push our " "changes to our origin's remote address:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:172 +#: ../../source/contributor-tutorial-contribute-on-github.rst:171 msgid "" "Once this is done, you will see on the GitHub that your forked repo was " "updated with the changes you have made." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:176 +#: ../../source/contributor-tutorial-contribute-on-github.rst:175 msgid "Creating and merging a pull request (PR)" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:203 +#: ../../source/contributor-tutorial-contribute-on-github.rst:206 msgid "**Create the PR**" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:179 +#: ../../source/contributor-tutorial-contribute-on-github.rst:178 msgid "" "Once you have pushed changes, on the GitHub webpage of your repository " "you should see the following message:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:183 -msgid "Otherwise you can always find this option in the `Branches` page." +#: ../../source/contributor-tutorial-contribute-on-github.rst:182 +msgid "Otherwise you can always find this option in the ``Branches`` page." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:185 +#: ../../source/contributor-tutorial-contribute-on-github.rst:184 msgid "" -"Once you click the `Compare & pull request` button, you should see " +"Once you click the ``Compare & pull request`` button, you should see " "something similar to this:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:189 +#: ../../source/contributor-tutorial-contribute-on-github.rst:188 msgid "At the top you have an explanation of which branch will be merged where:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:193 +#: ../../source/contributor-tutorial-contribute-on-github.rst:192 msgid "" "In this example you can see that the request is to merge the branch " "``doc-fixes`` from my forked repository to branch ``main`` from the " "Flower repository." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:195 +#: ../../source/contributor-tutorial-contribute-on-github.rst:194 msgid "" "The input box in the middle is there for you to describe what your PR " "does and to link it to existing issues. We have placed comments (that " @@ -1304,163 +1510,172 @@ msgid "" "process." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:198 +#: ../../source/contributor-tutorial-contribute-on-github.rst:197 +msgid "" +"It is important to follow the instructions described in comments. For " +"instance, in order to not break how our changelog system works, you " +"should read the information above the ``Changelog entry`` section " +"carefully. You can also checkout some examples and details in the " +":ref:`changelogentry` appendix." +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:201 msgid "" "At the bottom you will find the button to open the PR. This will notify " "reviewers that a new PR has been opened and that they should look over it" " to merge or to request changes." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:201 +#: ../../source/contributor-tutorial-contribute-on-github.rst:204 msgid "" "If your PR is not yet ready for review, and you don't want to notify " "anyone, you have the option to create a draft pull request:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:206 +#: ../../source/contributor-tutorial-contribute-on-github.rst:209 msgid "**Making new changes**" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:206 +#: ../../source/contributor-tutorial-contribute-on-github.rst:209 msgid "" "Once the PR has been opened (as draft or not), you can still push new " "commits to it the same way we did before, by making changes to the branch" " associated with the PR." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:228 +#: ../../source/contributor-tutorial-contribute-on-github.rst:231 msgid "**Review the PR**" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:209 +#: ../../source/contributor-tutorial-contribute-on-github.rst:212 msgid "" "Once the PR has been opened or once the draft PR has been marked as " "ready, a review from code owners will be automatically requested:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:213 +#: ../../source/contributor-tutorial-contribute-on-github.rst:216 msgid "" "Code owners will then look into the code, ask questions, request changes " "or validate the PR." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:215 +#: ../../source/contributor-tutorial-contribute-on-github.rst:218 msgid "Merging will be blocked if there are ongoing requested changes." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:219 +#: ../../source/contributor-tutorial-contribute-on-github.rst:222 msgid "" "To resolve them, just push the necessary changes to the branch associated" " with the PR:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:223 +#: ../../source/contributor-tutorial-contribute-on-github.rst:226 msgid "And resolve the conversation:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:227 +#: ../../source/contributor-tutorial-contribute-on-github.rst:230 msgid "" "Once all the conversations have been resolved, you can re-request a " "review." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:248 +#: ../../source/contributor-tutorial-contribute-on-github.rst:251 msgid "**Once the PR is merged**" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:231 +#: ../../source/contributor-tutorial-contribute-on-github.rst:234 msgid "" "If all the automatic tests have passed and reviewers have no more changes" " to request, they can approve the PR and merge it." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:235 +#: ../../source/contributor-tutorial-contribute-on-github.rst:238 msgid "" "Once it is merged, you can delete the branch on GitHub (a button should " "appear to do so) and also delete it locally by doing:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:242 +#: ../../source/contributor-tutorial-contribute-on-github.rst:245 msgid "Then you should update your forked repository by doing:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:251 +#: ../../source/contributor-tutorial-contribute-on-github.rst:254 msgid "Example of first contribution" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:254 +#: ../../source/contributor-tutorial-contribute-on-github.rst:257 msgid "Problem" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:256 +#: ../../source/contributor-tutorial-contribute-on-github.rst:259 msgid "" "For our documentation, we’ve started to use the `Diàtaxis framework " "`_." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:258 +#: ../../source/contributor-tutorial-contribute-on-github.rst:261 msgid "" "Our “How to” guides should have titles that continue the sencence “How to" " …”, for example, “How to upgrade to Flower 1.0”." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:260 +#: ../../source/contributor-tutorial-contribute-on-github.rst:263 msgid "" "Most of our guides do not follow this new format yet, and changing their " "title is (unfortunately) more involved than one might think." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:262 +#: ../../source/contributor-tutorial-contribute-on-github.rst:265 msgid "" "This issue is about changing the title of a doc from present continious " "to present simple." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:264 +#: ../../source/contributor-tutorial-contribute-on-github.rst:267 msgid "" "Let's take the example of “Saving Progress” which we changed to “Save " "Progress”. Does this pass our check?" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:266 +#: ../../source/contributor-tutorial-contribute-on-github.rst:269 msgid "Before: ”How to saving progress” ❌" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:268 +#: ../../source/contributor-tutorial-contribute-on-github.rst:271 msgid "After: ”How to save progress” ✅" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:271 +#: ../../source/contributor-tutorial-contribute-on-github.rst:274 msgid "Solution" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:273 +#: ../../source/contributor-tutorial-contribute-on-github.rst:276 msgid "" "This is a tiny change, but it’ll allow us to test your end-to-end setup. " "After cloning and setting up the Flower repo, here’s what you should do:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:275 -msgid "Find the source file in `doc/source`" +#: ../../source/contributor-tutorial-contribute-on-github.rst:278 +msgid "Find the source file in ``doc/source``" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:276 +#: ../../source/contributor-tutorial-contribute-on-github.rst:279 msgid "" -"Make the change in the `.rst` file (beware, the dashes under the title " +"Make the change in the ``.rst`` file (beware, the dashes under the title " "should be the same length as the title itself)" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:277 +#: ../../source/contributor-tutorial-contribute-on-github.rst:280 msgid "" "Build the docs and check the result: ``_" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:280 +#: ../../source/contributor-tutorial-contribute-on-github.rst:283 msgid "Rename file" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:282 +#: ../../source/contributor-tutorial-contribute-on-github.rst:285 msgid "" "You might have noticed that the file name still reflects the old wording." " If we just change the file, then we break all existing links to it - it " @@ -1468,77 +1683,77 @@ msgid "" "engine ranking." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:285 +#: ../../source/contributor-tutorial-contribute-on-github.rst:288 msgid "Here’s how to change the file name:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:287 -msgid "Change the file name to `save-progress.rst`" +#: ../../source/contributor-tutorial-contribute-on-github.rst:290 +msgid "Change the file name to ``save-progress.rst``" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:288 -msgid "Add a redirect rule to `doc/source/conf.py`" +#: ../../source/contributor-tutorial-contribute-on-github.rst:291 +msgid "Add a redirect rule to ``doc/source/conf.py``" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:290 +#: ../../source/contributor-tutorial-contribute-on-github.rst:293 msgid "" -"This will cause a redirect from `saving-progress.html` to `save-" -"progress.html`, old links will continue to work." +"This will cause a redirect from ``saving-progress.html`` to ``save-" +"progress.html``, old links will continue to work." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:293 +#: ../../source/contributor-tutorial-contribute-on-github.rst:296 msgid "Apply changes in the index file" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:295 +#: ../../source/contributor-tutorial-contribute-on-github.rst:298 msgid "" "For the lateral navigation bar to work properly, it is very important to " -"update the `index.rst` file as well. This is where we define the whole " +"update the ``index.rst`` file as well. This is where we define the whole " "arborescence of the navbar." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:298 -msgid "Find and modify the file name in `index.rst`" +#: ../../source/contributor-tutorial-contribute-on-github.rst:301 +msgid "Find and modify the file name in ``index.rst``" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:301 +#: ../../source/contributor-tutorial-contribute-on-github.rst:304 msgid "Open PR" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:303 +#: ../../source/contributor-tutorial-contribute-on-github.rst:306 msgid "" "Commit the changes (commit messages are always imperative: “Do " "something”, in this case “Change …”)" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:304 +#: ../../source/contributor-tutorial-contribute-on-github.rst:307 msgid "Push the changes to your fork" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:305 +#: ../../source/contributor-tutorial-contribute-on-github.rst:308 msgid "Open a PR (as shown above)" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:306 +#: ../../source/contributor-tutorial-contribute-on-github.rst:309 msgid "Wait for it to be approved!" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:307 +#: ../../source/contributor-tutorial-contribute-on-github.rst:310 msgid "Congrats! 🥳 You're now officially a Flower contributor!" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:311 +#: ../../source/contributor-tutorial-contribute-on-github.rst:314 msgid "How to write a good PR title" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:313 +#: ../../source/contributor-tutorial-contribute-on-github.rst:316 msgid "" "A well-crafted PR title helps team members quickly understand the purpose" " and scope of the changes being proposed. Here's a guide to help you " "write a good GitHub PR title:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:315 +#: ../../source/contributor-tutorial-contribute-on-github.rst:318 msgid "" "1. Be Clear and Concise: Provide a clear summary of the changes in a " "concise manner. 1. Use Actionable Verbs: Start with verbs like \"Add,\" " @@ -1548,83 +1763,219 @@ msgid "" "Capitalization and Punctuation: Follow grammar rules for clarity." msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:321 +#: ../../source/contributor-tutorial-contribute-on-github.rst:324 msgid "" "Let's start with a few examples for titles that should be avoided because" " they do not provide meaningful information:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:323 +#: ../../source/contributor-tutorial-contribute-on-github.rst:326 msgid "Implement Algorithm" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:324 +#: ../../source/contributor-tutorial-contribute-on-github.rst:327 msgid "Database" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:325 +#: ../../source/contributor-tutorial-contribute-on-github.rst:328 msgid "Add my_new_file.py to codebase" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:326 +#: ../../source/contributor-tutorial-contribute-on-github.rst:329 msgid "Improve code in module" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:327 +#: ../../source/contributor-tutorial-contribute-on-github.rst:330 msgid "Change SomeModule" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:329 +#: ../../source/contributor-tutorial-contribute-on-github.rst:332 msgid "" "Here are a few positive examples which provide helpful information " "without repeating how they do it, as that is already visible in the " "\"Files changed\" section of the PR:" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:331 +#: ../../source/contributor-tutorial-contribute-on-github.rst:334 msgid "Update docs banner to mention Flower Summit 2023" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:332 +#: ../../source/contributor-tutorial-contribute-on-github.rst:335 msgid "Remove unnecessary XGBoost dependency" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:333 +#: ../../source/contributor-tutorial-contribute-on-github.rst:336 msgid "Remove redundant attributes in strategies subclassing FedAvg" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:334 -msgid "Add CI job to deploy the staging system when the `main` branch changes" +#: ../../source/contributor-tutorial-contribute-on-github.rst:337 +msgid "Add CI job to deploy the staging system when the ``main`` branch changes" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:335 +#: ../../source/contributor-tutorial-contribute-on-github.rst:338 msgid "" "Add new amazing library which will be used to improve the simulation " "engine" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:339 +#: ../../source/contributor-tutorial-contribute-on-github.rst:342 #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:548 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:946 -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:747 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:727 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:713 #: ../../source/tutorial-series-what-is-federated-learning.ipynb:367 msgid "Next steps" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:341 +#: ../../source/contributor-tutorial-contribute-on-github.rst:344 msgid "" "Once you have made your first PR, and want to contribute more, be sure to" " check out the following :" msgstr "" -#: ../../source/contributor-tutorial-contribute-on-github.rst:343 +#: ../../source/contributor-tutorial-contribute-on-github.rst:346 msgid "" "`Good first contributions `_, where you should particularly look " "into the :code:`baselines` contributions." msgstr "" +#: ../../source/contributor-tutorial-contribute-on-github.rst:350 +#: ../../source/fed/0000-20200102-fed-template.md:60 +msgid "Appendix" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:355 +msgid "Changelog entry" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:357 +msgid "" +"When opening a new PR, inside its description, there should be a " +"``Changelog entry`` header." +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:359 +msgid "" +"Above this header you should see the following comment that explains how " +"to write your changelog entry:" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:361 +msgid "" +"Inside the following 'Changelog entry' section, you should put the " +"description of your changes that will be added to the changelog alongside" +" your PR title." +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:364 +msgid "" +"If the section is completely empty (without any token) or non-existant, " +"the changelog will just contain the title of the PR for the changelog " +"entry, without any description." +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:367 +msgid "" +"If the section contains some text other than tokens, it will use it to " +"add a description to the change." +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:369 +msgid "" +"If the section contains one of the following tokens it will ignore any " +"other text and put the PR under the corresponding section of the " +"changelog:" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:371 +msgid " is for classifying a PR as a general improvement." +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:373 +msgid " is to not add the PR to the changelog" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:375 +msgid " is to add a general baselines change to the PR" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:377 +msgid " is to add a general examples change to the PR" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:379 +msgid " is to add a general sdk change to the PR" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:381 +msgid " is to add a general simulations change to the PR" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:383 +msgid "Note that only one token should be used." +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:385 +msgid "" +"Its content must have a specific format. We will break down what each " +"possibility does:" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:387 +msgid "" +"If the ``### Changelog entry`` section contains nothing or doesn't exist," +" the following text will be added to the changelog::" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:391 +msgid "" +"If the ``### Changelog entry`` section contains a description (and no " +"token), the following text will be added to the changelog::" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:397 +msgid "" +"If the ``### Changelog entry`` section contains ````, nothing will " +"change in the changelog." +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:399 +msgid "" +"If the ``### Changelog entry`` section contains ````, the " +"following text will be added to the changelog::" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:403 +msgid "" +"If the ``### Changelog entry`` section contains ````, the " +"following text will be added to the changelog::" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:407 +msgid "" +"If the ``### Changelog entry`` section contains ````, the " +"following text will be added to the changelog::" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:411 +msgid "" +"If the ``### Changelog entry`` section contains ````, the following " +"text will be added to the changelog::" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:415 +msgid "" +"If the ``### Changelog entry`` section contains ````, the " +"following text will be added to the changelog::" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:419 +msgid "" +"Note that only one token must be provided, otherwise, only the first " +"action (in the order listed above), will be performed." +msgstr "" + #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:2 msgid "Get started as a contributor" msgstr "" @@ -1634,7 +1985,7 @@ msgid "Prerequisites" msgstr "" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:7 -msgid "`Python 3.7 `_ or above" +msgid "`Python 3.8 `_ or above" msgstr "" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:8 @@ -1660,39 +2011,84 @@ msgstr "" msgid "Developer Machine Setup" msgstr "" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:20 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:21 +msgid "Preliminarities" +msgstr "" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:22 +msgid "Some system-wide dependencies are needed." +msgstr "" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:25 +msgid "For macOS" +msgstr "" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:27 +msgid "" +"Install `homebrew `_. Don't forget the post-" +"installation actions to add `brew` to your PATH." +msgstr "" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:28 +msgid "" +"Install `xz` (to install different Python versions) and `pandoc` to build" +" the docs::" +msgstr "" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:34 +msgid "For Ubuntu" +msgstr "" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:35 +msgid "" +"Ensure you system (Ubuntu 22.04+) is up-to-date, and you have all " +"necessary packages::" +msgstr "" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:44 +msgid "Create Flower Dev Environment" +msgstr "" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:46 msgid "" -"First, clone the `Flower repository `_ " -"from GitHub::" +"1. Clone the `Flower repository `_ from " +"GitHub::" msgstr "" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:26 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:52 +msgid "" +"Let's create the Python environment for all-things Flower. If you wish to" +" use :code:`pyenv`, we provide two convenience scripts that you can use. " +"If you prefer using something else than :code:`pyenv`, create a new " +"environment, activate and skip to the last point where all packages are " +"installed." +msgstr "" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:54 msgid "" -"Second, create a virtual environment (and activate it). If you chose to " -"use :code:`pyenv` (with the :code:`pyenv-virtualenv` plugin) and already " -"have it installed , you can use the following convenience script (by " -"default it will use :code:`Python 3.8.17`, but you can change it by " -"providing a specific :code:``)::" +"If you don't have :code:`pyenv` installed, the following script that will" +" install it, set it up, and create the virtual environment (with " +":code:`Python 3.8.17` by default)::" msgstr "" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:33 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:58 msgid "" -"If you don't have :code:`pyenv` installed, you can use the following " -"script that will install pyenv, set it up and create the virtual " -"environment (with :code:`Python 3.8.17` by default)::" +"If you already have :code:`pyenv` installed (along with the :code:`pyenv-" +"virtualenv` plugin), you can use the following convenience script (with " +":code:`Python 3.8.17` by default)::" msgstr "" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:39 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:62 msgid "" -"Third, install the Flower package in development mode (think :code:`pip " +"3. Install the Flower package in development mode (think :code:`pip " "install -e`) along with all necessary dependencies::" msgstr "" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:46 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:69 msgid "Convenience Scripts" msgstr "" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:48 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:71 msgid "" "The Flower repository contains a number of convenience scripts to make " "recurring development tasks easier and less error-prone. See the " @@ -1700,68 +2096,68 @@ msgid "" "amonst the most important ones:" msgstr "" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:54 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:77 msgid "Create/Delete Virtual Environment" msgstr "" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:62 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:85 msgid "Compile ProtoBuf Definitions" msgstr "" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:69 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:92 msgid "Auto-Format Code" msgstr "" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:76 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:99 msgid "Run Linters and Tests" msgstr "" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:83 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:106 msgid "Run Github Actions (CI) locally" msgstr "" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:85 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:108 msgid "" "Developers could run the full set of Github Actions workflows under their" -" local environment by using `Act _`. " +" local environment by using `Act `_. " "Please refer to the installation instructions under the linked repository" " and run the next command under Flower main cloned repository folder::" msgstr "" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:92 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:115 msgid "" "The Flower default workflow would run by setting up the required Docker " "machines underneath." msgstr "" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:97 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:120 msgid "Build Release" msgstr "" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:99 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:122 msgid "" "Flower uses Poetry to build releases. The necessary command is wrapped in" " a simple script::" msgstr "" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:104 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:127 msgid "" "The resulting :code:`.whl` and :code:`.tar.gz` releases will be stored in" " the :code:`/dist` subdirectory." msgstr "" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:109 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:132 msgid "Build Documentation" msgstr "" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:111 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:134 msgid "" "Flower's documentation uses `Sphinx `_. " "There's no convenience script to re-build the documentation yet, but it's" " pretty easy::" msgstr "" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:117 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:140 msgid "This will generate HTML documentation in ``doc/build/html``." msgstr "" @@ -2073,7 +2469,7 @@ msgstr "" #: ../../source/example-mxnet-walk-through.rst:244 #: ../../source/example-pytorch-from-centralized-to-federated.rst:221 #: ../../source/tutorial-quickstart-jax.rst:169 -#: ../../source/tutorial-quickstart-mxnet.rst:169 +#: ../../source/tutorial-quickstart-mxnet.rst:171 #: ../../source/tutorial-quickstart-pytorch.rst:155 #: ../../source/tutorial-quickstart-scikitlearn.rst:108 msgid ":code:`get_parameters`" @@ -2092,7 +2488,7 @@ msgstr "" #: ../../source/example-mxnet-walk-through.rst:248 #: ../../source/example-pytorch-from-centralized-to-federated.rst:225 #: ../../source/tutorial-quickstart-jax.rst:173 -#: ../../source/tutorial-quickstart-mxnet.rst:175 +#: ../../source/tutorial-quickstart-mxnet.rst:177 #: ../../source/tutorial-quickstart-pytorch.rst:161 #: ../../source/tutorial-quickstart-scikitlearn.rst:115 msgid ":code:`fit`" @@ -2127,7 +2523,7 @@ msgstr "" #: ../../source/example-mxnet-walk-through.rst:253 #: ../../source/example-pytorch-from-centralized-to-federated.rst:230 #: ../../source/tutorial-quickstart-jax.rst:178 -#: ../../source/tutorial-quickstart-mxnet.rst:178 +#: ../../source/tutorial-quickstart-mxnet.rst:180 #: ../../source/tutorial-quickstart-pytorch.rst:164 #: ../../source/tutorial-quickstart-scikitlearn.rst:118 msgid ":code:`evaluate`" @@ -2544,8 +2940,8 @@ msgid "" "All that's left to do it to define a function that loads both model and " "data, creates a :code:`CifarClient`, and starts this client. You load " "your data and model by using :code:`cifar.py`. Start :code:`CifarClient` " -"with the function :code:`fl.client.start_client()` by pointing it " -"at the same IP adress we used in :code:`server.py`:" +"with the function :code:`fl.client.start_client()` by pointing it at the " +"same IP adress we used in :code:`server.py`:" msgstr "" #: ../../source/example-pytorch-from-centralized-to-federated.rst:307 @@ -2577,7 +2973,7 @@ msgid "" msgstr "" #: ../../source/example-walkthrough-pytorch-mnist.rst:6 -#: ../../source/tutorial-quickstart-mxnet.rst:14 +#: ../../source/tutorial-quickstart-mxnet.rst:16 #: ../../source/tutorial-quickstart-pytorch.rst:17 #: ../../source/tutorial-quickstart-scikitlearn.rst:14 msgid "" @@ -2646,10 +3042,11 @@ msgstr "" #: ../../source/example-walkthrough-pytorch-mnist.rst:69 #: ../../source/tutorial-quickstart-ios.rst:129 -#: ../../source/tutorial-quickstart-mxnet.rst:224 +#: ../../source/tutorial-quickstart-mxnet.rst:226 #: ../../source/tutorial-quickstart-pytorch.rst:203 #: ../../source/tutorial-quickstart-scikitlearn.rst:157 #: ../../source/tutorial-quickstart-tensorflow.rst:98 +#: ../../source/tutorial-quickstart-xgboost.rst:309 msgid "Flower Server" msgstr "" @@ -2671,10 +3068,11 @@ msgstr "" #: ../../source/example-walkthrough-pytorch-mnist.rst:89 #: ../../source/tutorial-quickstart-ios.rst:34 -#: ../../source/tutorial-quickstart-mxnet.rst:34 +#: ../../source/tutorial-quickstart-mxnet.rst:36 #: ../../source/tutorial-quickstart-pytorch.rst:37 #: ../../source/tutorial-quickstart-scikitlearn.rst:40 #: ../../source/tutorial-quickstart-tensorflow.rst:29 +#: ../../source/tutorial-quickstart-xgboost.rst:55 msgid "Flower Client" msgstr "" @@ -2829,7 +3227,7 @@ msgstr "" #: ../../source/explanation-differential-privacy.rst:7 msgid "" -"Please note that these components are still experimental, the correct " +"Please note that these components are still experimental; the correct " "configuration of DP for a specific task is still an unsolved problem." msgstr "" @@ -2867,9 +3265,11 @@ msgstr "" #: ../../source/explanation-differential-privacy.rst:20 msgid "" "The distribution of the update norm has been shown to vary from task-to-" -"task and to evolve as training progresses. Therefore, we use an adaptive " -"approach [andrew]_ that continuously adjusts the clipping threshold to " -"track a prespecified quantile of the update norm distribution." +"task and to evolve as training progresses. This variability is crucial in" +" understanding its impact on differential privacy guarantees, emphasizing" +" the need for an adaptive approach [andrew]_ that continuously adjusts " +"the clipping threshold to track a prespecified quantile of the update " +"norm distribution." msgstr "" #: ../../source/explanation-differential-privacy.rst:23 @@ -2879,7 +3279,7 @@ msgstr "" #: ../../source/explanation-differential-privacy.rst:25 msgid "" "We make (and attempt to enforce) a number of assumptions that must be " -"satisfied to ensure that the training process actually realises the " +"satisfied to ensure that the training process actually realizes the " ":math:`(\\epsilon, \\delta)` guarantees the user has in mind when " "configuring the setup." msgstr "" @@ -2908,8 +3308,8 @@ msgstr "" #: ../../source/explanation-differential-privacy.rst:31 msgid "" "The first two are useful for eliminating a multitude of complications " -"associated with calibrating the noise to the clipping threshold while the" -" third one is required to comply with the assumptions of the privacy " +"associated with calibrating the noise to the clipping threshold, while " +"the third one is required to comply with the assumptions of the privacy " "analysis." msgstr "" @@ -2969,7 +3369,7 @@ msgstr "" #: ../../source/explanation-differential-privacy.rst:51 msgid "" "The first version of our solution was to define a decorator whose " -"constructor accepted, among other things, a boolean valued variable " +"constructor accepted, among other things, a boolean-valued variable " "indicating whether adaptive clipping was to be enabled or not. We quickly" " realized that this would clutter its :code:`__init__()` function with " "variables corresponding to hyperparameters of adaptive clipping that " @@ -2982,6 +3382,7 @@ msgid "" msgstr "" #: ../../source/explanation-differential-privacy.rst:54 +#: ../../source/ref-api/flwr.server.strategy.DPFedAvgFixed.rst:2 msgid "DPFedAvgFixed" msgstr "" @@ -3016,7 +3417,7 @@ msgid "" ":code:`parameters` field of :code:`FitRes` for each received update and " "setting it to 1. Furthermore, if :code:`server_side_noising=true`, each " "update is perturbed with an amount of noise equal to what it would have " -"been subjected to had client-side noising being enabled. This entails " +"been subjected to had client-side noising being enabled. This entails " "*pre*-processing of the arguments to this method before passing them on " "to the wrappee's implementation of :code:`aggregate_fit()`." msgstr "" @@ -3042,6 +3443,7 @@ msgid "" msgstr "" #: ../../source/explanation-differential-privacy.rst:67 +#: ../../source/ref-api/flwr.server.strategy.DPFedAvgAdaptive.rst:2 msgid "DPFedAvgAdaptive" msgstr "" @@ -3113,15 +3515,16 @@ msgstr "" #: ../../source/explanation-differential-privacy.rst:98 msgid "" -"McMahan, H. Brendan, et al. \"Learning differentially private recurrent " -"language models.\" arXiv preprint arXiv:1710.06963 (2017)." +"McMahan et al. \"Learning Differentially Private Recurrent Language " +"Models.\" International Conference on Learning Representations (ICLR), " +"2017." msgstr "" #: ../../source/explanation-differential-privacy.rst:100 msgid "" -"Andrew, Galen, et al. \"Differentially private learning with adaptive " -"clipping.\" Advances in Neural Information Processing Systems 34 (2021): " -"17455-17466." +"Andrew, Galen, et al. \"Differentially Private Learning with Adaptive " +"Clipping.\" Advances in Neural Information Processing Systems (NeurIPS), " +"2021." msgstr "" #: ../../source/explanation-federated-evaluation.rst:2 @@ -3371,10 +3774,6 @@ msgstr "" msgid "\\[Alternative 2\\]" msgstr "" -#: ../../source/fed/0000-20200102-fed-template.md:60 -msgid "Appendix" -msgstr "" - #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:10 msgid "Flower Enhancement Doc" msgstr "" @@ -4011,6 +4410,7 @@ msgid "" msgstr "" #: ../../source/how-to-enable-ssl-connections.rst:41 +#: ../../source/ref-api/flwr.server.Server.rst:2 msgid "Server" msgstr "" @@ -4030,7 +4430,7 @@ msgstr "" #: ../../source/how-to-enable-ssl-connections.rst:65 #: ../../source/how-to-upgrade-to-flower-1.0.rst:37 -#: ../../source/ref-api-flwr.rst:15 +#: ../../source/ref-api/flwr.client.Client.rst:2 msgid "Client" msgstr "" @@ -4048,6 +4448,7 @@ msgid "" msgstr "" #: ../../source/how-to-enable-ssl-connections.rst:89 +#: ../../source/how-to-use-built-in-mods.rst:85 #: ../../source/tutorial-series-what-is-federated-learning.ipynb:287 msgid "Conclusion" msgstr "" @@ -4344,61 +4745,99 @@ msgstr "" msgid "Install stable release" msgstr "" -#: ../../source/how-to-install-flower.rst:14 +#: ../../source/how-to-install-flower.rst:15 +msgid "Using pip" +msgstr "" + +#: ../../source/how-to-install-flower.rst:17 msgid "" "Stable releases are available on `PyPI " "`_::" msgstr "" -#: ../../source/how-to-install-flower.rst:18 +#: ../../source/how-to-install-flower.rst:21 msgid "" "For simulations that use the Virtual Client Engine, ``flwr`` should be " "installed with the ``simulation`` extra::" msgstr "" -#: ../../source/how-to-install-flower.rst:24 +#: ../../source/how-to-install-flower.rst:27 +msgid "Using conda (or mamba)" +msgstr "" + +#: ../../source/how-to-install-flower.rst:29 +msgid "Flower can also be installed from the ``conda-forge`` channel." +msgstr "" + +#: ../../source/how-to-install-flower.rst:31 +msgid "" +"If you have not added ``conda-forge`` to your channels, you will first " +"need to run the following::" +msgstr "" + +#: ../../source/how-to-install-flower.rst:36 +msgid "" +"Once the ``conda-forge`` channel has been enabled, ``flwr`` can be " +"installed with ``conda``::" +msgstr "" + +#: ../../source/how-to-install-flower.rst:40 +msgid "or with ``mamba``::" +msgstr "" + +#: ../../source/how-to-install-flower.rst:46 msgid "Verify installation" msgstr "" -#: ../../source/how-to-install-flower.rst:26 +#: ../../source/how-to-install-flower.rst:48 msgid "" -"The following command can be used to verfiy if Flower was successfully " +"The following command can be used to verify if Flower was successfully " "installed. If everything worked, it should print the version of Flower to" " the command line::" msgstr "" -#: ../../source/how-to-install-flower.rst:33 +#: ../../source/how-to-install-flower.rst:55 msgid "Advanced installation options" msgstr "" -#: ../../source/how-to-install-flower.rst:36 +#: ../../source/how-to-install-flower.rst:58 +msgid "Install via Docker" +msgstr "" + +#: ../../source/how-to-install-flower.rst:60 +msgid "" +"`How to run Flower using Docker `_" +msgstr "" + +#: ../../source/how-to-install-flower.rst:63 msgid "Install pre-release" msgstr "" -#: ../../source/how-to-install-flower.rst:38 +#: ../../source/how-to-install-flower.rst:65 msgid "" "New (possibly unstable) versions of Flower are sometimes available as " "pre-release versions (alpha, beta, release candidate) before the stable " "release happens::" msgstr "" -#: ../../source/how-to-install-flower.rst:42 +#: ../../source/how-to-install-flower.rst:69 msgid "" "For simulations that use the Virtual Client Engine, ``flwr`` pre-releases" " should be installed with the ``simulation`` extra::" msgstr "" -#: ../../source/how-to-install-flower.rst:47 +#: ../../source/how-to-install-flower.rst:74 msgid "Install nightly release" msgstr "" -#: ../../source/how-to-install-flower.rst:49 +#: ../../source/how-to-install-flower.rst:76 msgid "" "The latest (potentially unstable) changes in Flower are available as " "nightly releases::" msgstr "" -#: ../../source/how-to-install-flower.rst:53 +#: ../../source/how-to-install-flower.rst:80 msgid "" "For simulations that use the Virtual Client Engine, ``flwr-nightly`` " "should be installed with the ``simulation`` extra::" @@ -4640,6 +5079,185 @@ msgid "" "metrics.html>`_" msgstr "" +#: ../../source/how-to-run-flower-using-docker.rst:2 +msgid "Run Flower using Docker" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:4 +msgid "" +"The simplest way to get started with Flower is by using the pre-made " +"Docker images, which you can find on `Docker Hub " +"`_." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:7 +msgid "Before you start, make sure that the Docker daemon is running:" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:14 +msgid "" +"If you do not see the version of Docker but instead get an error saying " +"that the command was not found, you will need to install Docker first. " +"You can find installation instruction `here `_." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:20 +msgid "" +"On Linux, Docker commands require ``sudo`` privilege. If you want to " +"avoid using ``sudo``, you can follow the `Post-installation steps " +"`_ on the " +"official Docker website." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:25 +msgid "Flower server" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:28 +msgid "Quickstart" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:30 +msgid "If you're looking to try out Flower, you can use the following command:" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:37 +msgid "" +"The command will pull the Docker image with the tag " +"``1.7.0-py3.11-ubuntu22.04`` from Docker Hub. The tag contains the " +"information which Flower, Python and Ubuntu is used. In this case, it " +"uses Flower 1.7.0, Python 3.11 and Ubuntu 22.04. The ``--rm`` flag tells " +"Docker to remove the container after it exits." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:44 +msgid "" +"By default, the Flower server keeps state in-memory. When using the " +"Docker flag ``--rm``, the state is not persisted between container " +"starts. We will show below how to save the state in a file on your host " +"system." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:48 +msgid "" +"The ``-p :`` flag tells Docker to map the ports " +"``9091``/``9092`` of the host to ``9091``/``9092`` of the container, " +"allowing you to access the Driver API on ``http://localhost:9091`` and " +"the Fleet API on ``http://localhost:9092``. Lastly, any flag that comes " +"after the tag is passed to the Flower server. Here, we are passing the " +"flag ``--insecure``." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:55 +msgid "" +"The ``--insecure`` flag enables insecure communication (using HTTP, not " +"HTTPS) and should only be used for testing purposes. We strongly " +"recommend enabling `SSL `_ when " +"deploying to a production environment." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:60 +msgid "" +"You can use ``--help`` to view all available flags that the server " +"supports:" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:67 +msgid "Mounting a volume to store the state on the host system" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:69 +msgid "" +"If you want to persist the state of the server on your host system, all " +"you need to do is specify a path where you want to save the file on your " +"host system and a name for the database file. In the example below, we " +"tell Docker via the flag ``-v`` to mount the user's home directory " +"(``~/`` on your host) into the ``/app/`` directory of the container. " +"Furthermore, we use the flag ``--database`` to specify the name of the " +"database file." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:82 +msgid "" +"As soon as the server starts, the file ``state.db`` is created in the " +"user's home directory on your host system. If the file already exists, " +"the server tries to restore the state from the file. To start the server " +"with an empty database, simply remove the ``state.db`` file." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:87 +msgid "Enabling SSL for secure connections" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:89 +msgid "" +"To enable SSL, you will need a CA certificate, a server certificate and a" +" server private key." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:92 +msgid "" +"For testing purposes, you can generate your own self-signed certificates." +" The `Enable SSL connections `_ page contains a section that " +"will guide you through the process." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:96 +msgid "" +"Assuming all files we need are in the local ``certificates`` directory, " +"we can use the flag ``-v`` to mount the local directory into the " +"``/app/`` directory of the container. This allows the server to access " +"the files within the container. Finally, we pass the names of the " +"certificates to the server with the ``--certificates`` flag." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:108 +msgid "Using a different Flower or Python version" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:110 +msgid "" +"If you want to use a different version of Flower or Python, you can do so" +" by changing the tag. All versions we provide are available on `Docker " +"Hub `_." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:114 +msgid "Pinning a Docker image to a specific version" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:116 +msgid "" +"It may happen that we update the images behind the tags. Such updates " +"usually include security updates of system dependencies that should not " +"change the functionality of Flower. However, if you want to ensure that " +"you always use the same image, you can specify the hash of the image " +"instead of the tag." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:121 +msgid "" +"The following command returns the current image hash referenced by the " +"``server:1.7.0-py3.11-ubuntu22.04`` tag:" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:128 +msgid "Next, we can pin the hash when running a new server container:" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:137 +msgid "Setting environment variables" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:139 +msgid "" +"To set a variable inside a Docker container, you can use the ``-e " +"=`` flag." +msgstr "" + #: ../../source/how-to-run-simulations.rst:2 msgid "Run simulations" msgstr "" @@ -4665,11 +5283,11 @@ msgid "" "The :code:`VirtualClientEngine` schedules, launches and manages `virtual`" " clients. These clients are identical to `non-virtual` clients (i.e. the " "ones you launch via the command `flwr.client.start_client `_) in the sense that they can be configure " -"by creating a class inheriting, for example, from " -"`flwr.client.NumPyClient `_ " -"and therefore behave in an identical way. In addition to that, clients " -"managed by the :code:`VirtualClientEngine` are:" +"flwr.html#start-client>`_) in the sense that they can be configure by " +"creating a class inheriting, for example, from `flwr.client.NumPyClient " +"`_ and therefore behave in an " +"identical way. In addition to that, clients managed by the " +":code:`VirtualClientEngine` are:" msgstr "" #: ../../source/how-to-run-simulations.rst:12 @@ -5088,6 +5706,12 @@ msgid "" " latest one:" msgstr "" +#: ../../source/how-to-save-and-load-model-checkpoints.rst:97 +msgid "" +"Return/use this object of type ``Parameters`` wherever necessary, such as" +" in the ``initial_parameters`` when defining a ``Strategy``." +msgstr "" + #: ../../source/how-to-upgrade-to-flower-1.0.rst:2 msgid "Upgrade to Flower 1.0" msgstr "" @@ -5353,30 +5977,149 @@ msgid "" "`_ and use the channgel ``#questions``." msgstr "" -#: ../../source/how-to-use-strategies.rst:2 -msgid "Use strategies" +#: ../../source/how-to-use-built-in-mods.rst:2 +msgid "Use Built-in Mods" msgstr "" -#: ../../source/how-to-use-strategies.rst:4 +#: ../../source/how-to-use-built-in-mods.rst:4 msgid "" -"Flower allows full customization of the learning process through the " -":code:`Strategy` abstraction. A number of built-in strategies are " -"provided in the core framework." +"**Note: This tutorial covers experimental features. The functionality and" +" interfaces may change in future versions.**" msgstr "" -#: ../../source/how-to-use-strategies.rst:6 +#: ../../source/how-to-use-built-in-mods.rst:6 msgid "" -"There are three ways to customize the way Flower orchestrates the " -"learning process on the server side:" +"In this tutorial, we will learn how to utilize built-in mods to augment " +"the behavior of a ``ClientApp``. Mods (sometimes also called Modifiers) " +"allow us to perform operations before and after a task is processed in " +"the ``ClientApp``." msgstr "" -#: ../../source/how-to-use-strategies.rst:8 -msgid "Use an existing strategy, for example, :code:`FedAvg`" +#: ../../source/how-to-use-built-in-mods.rst:9 +msgid "What are Mods?" msgstr "" -#: ../../source/how-to-use-strategies.rst:9 -#: ../../source/how-to-use-strategies.rst:40 -msgid "Customize an existing strategy with callback functions" +#: ../../source/how-to-use-built-in-mods.rst:11 +msgid "" +"A Mod is a callable that wraps around a ``ClientApp``. It can manipulate " +"or inspect the incoming ``Message`` and the resulting outgoing " +"``Message``. The signature for a ``Mod`` is as follows:" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:18 +msgid "A typical mod function might look something like this:" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:31 +msgid "Using Mods" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:33 +msgid "To use mods in your ``ClientApp``, you can follow these steps:" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:36 +msgid "1. Import the required mods" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:38 +msgid "First, import the built-in mod you intend to use:" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:46 +msgid "2. Define your client function" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:48 +msgid "" +"Define your client function (``client_fn``) that will be wrapped by the " +"mod(s):" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:57 +msgid "3. Create the ``ClientApp`` with mods" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:59 +msgid "" +"Create your ``ClientApp`` and pass the mods as a list to the ``mods`` " +"argument. The order in which you provide the mods matters:" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:72 +msgid "Order of execution" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:74 +msgid "" +"When the ``ClientApp`` runs, the mods are executed in the order they are " +"provided in the list:" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:76 +msgid "``example_mod_1`` (outermost mod)" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:77 +msgid "``example_mod_2`` (next mod)" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:78 +msgid "" +"Message handler (core function that handles the incoming ``Message`` and " +"returns the outgoing ``Message``)" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:79 +msgid "``example_mod_2`` (on the way back)" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:80 +msgid "``example_mod_1`` (outermost mod on the way back)" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:82 +msgid "" +"Each mod has a chance to inspect and modify the incoming ``Message`` " +"before passing it to the next mod, and likewise with the outgoing " +"``Message`` before returning it up the stack." +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:87 +msgid "" +"By following this guide, you have learned how to effectively use mods to " +"enhance your ``ClientApp``'s functionality. Remember that the order of " +"mods is crucial and affects how the input and output are processed." +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:89 +msgid "Enjoy building more robust and flexible ``ClientApp``s with mods!" +msgstr "" + +#: ../../source/how-to-use-strategies.rst:2 +msgid "Use strategies" +msgstr "" + +#: ../../source/how-to-use-strategies.rst:4 +msgid "" +"Flower allows full customization of the learning process through the " +":code:`Strategy` abstraction. A number of built-in strategies are " +"provided in the core framework." +msgstr "" + +#: ../../source/how-to-use-strategies.rst:6 +msgid "" +"There are three ways to customize the way Flower orchestrates the " +"learning process on the server side:" +msgstr "" + +#: ../../source/how-to-use-strategies.rst:8 +msgid "Use an existing strategy, for example, :code:`FedAvg`" +msgstr "" + +#: ../../source/how-to-use-strategies.rst:9 +#: ../../source/how-to-use-strategies.rst:40 +msgid "Customize an existing strategy with callback functions" msgstr "" #: ../../source/how-to-use-strategies.rst:10 @@ -5468,35 +6211,35 @@ msgstr "" msgid "How-to guides" msgstr "" -#: ../../source/index.rst:95 +#: ../../source/index.rst:97 msgid "Legacy example guides" msgstr "" -#: ../../source/index.rst:106 ../../source/index.rst:110 +#: ../../source/index.rst:108 ../../source/index.rst:112 msgid "Explanations" msgstr "" -#: ../../source/index.rst:122 +#: None:-1 msgid "API reference" msgstr "" -#: ../../source/index.rst:129 +#: ../../source/index.rst:137 msgid "Reference docs" msgstr "" -#: ../../source/index.rst:145 +#: ../../source/index.rst:153 msgid "Contributor tutorials" msgstr "" -#: ../../source/index.rst:152 +#: ../../source/index.rst:160 msgid "Contributor how-to guides" msgstr "" -#: ../../source/index.rst:164 +#: ../../source/index.rst:173 msgid "Contributor explanations" msgstr "" -#: ../../source/index.rst:170 +#: ../../source/index.rst:179 msgid "Contributor references" msgstr "" @@ -5580,25 +6323,33 @@ msgid "" "specific goal." msgstr "" -#: ../../source/index.rst:108 +#: ../../source/index.rst:110 msgid "" "Understanding-oriented concept guides explain and discuss key topics and " "underlying ideas behind Flower and collaborative AI." msgstr "" -#: ../../source/index.rst:118 +#: ../../source/index.rst:120 msgid "References" msgstr "" -#: ../../source/index.rst:120 +#: ../../source/index.rst:122 msgid "Information-oriented API reference and other reference material." msgstr "" -#: ../../source/index.rst:140 +#: ../../source/index.rst:131::1 +msgid ":py:obj:`flwr `\\" +msgstr "" + +#: ../../source/index.rst:131::1 flwr:1 of +msgid "Flower main package." +msgstr "" + +#: ../../source/index.rst:148 msgid "Contributor docs" msgstr "" -#: ../../source/index.rst:142 +#: ../../source/index.rst:150 msgid "" "The Flower community welcomes contributions. The following docs are " "intended to help along the way." @@ -5620,363 +6371,4978 @@ msgstr "" msgid "flower-fleet-api" msgstr "" -#: ../../source/ref-api-flwr.rst:2 -msgid "flwr (Python API reference)" +#: ../../source/ref-api/flwr.rst:2 +msgid "flwr" +msgstr "" + +#: ../../source/ref-api/flwr.rst:25 ../../source/ref-api/flwr.server.rst:48 +msgid "Modules" +msgstr "" + +#: ../../source/ref-api/flwr.rst:35::1 +msgid ":py:obj:`flwr.client `\\" +msgstr "" + +#: ../../source/ref-api/flwr.rst:35::1 flwr.client:1 of +msgid "Flower client." +msgstr "" + +#: ../../source/ref-api/flwr.rst:35::1 +msgid ":py:obj:`flwr.common `\\" +msgstr "" + +#: ../../source/ref-api/flwr.rst:35::1 flwr.common:1 of +msgid "Common components shared between server and client." +msgstr "" + +#: ../../source/ref-api/flwr.rst:35::1 +msgid ":py:obj:`flwr.server `\\" +msgstr "" + +#: ../../source/ref-api/flwr.rst:35::1 +#: ../../source/ref-api/flwr.server.rst:37::1 flwr.server:1 +#: flwr.server.server.Server:1 of +msgid "Flower server." +msgstr "" + +#: ../../source/ref-api/flwr.rst:35::1 +msgid ":py:obj:`flwr.simulation `\\" +msgstr "" + +#: ../../source/ref-api/flwr.rst:35::1 flwr.simulation:1 of +msgid "Flower simulation." msgstr "" -#: ../../source/ref-api-flwr.rst:8 +#: ../../source/ref-api/flwr.client.rst:2 msgid "client" msgstr "" -#: ../../source/ref-api-flwr.rst:24 -msgid "start_client" +#: ../../source/ref-api/flwr.client.rst:13 +#: ../../source/ref-api/flwr.common.rst:13 +#: ../../source/ref-api/flwr.server.driver.rst:13 +#: ../../source/ref-api/flwr.server.rst:13 +#: ../../source/ref-api/flwr.simulation.rst:13 +msgid "Functions" +msgstr "" + +#: ../../source/ref-api/flwr.client.rst:24::1 +msgid ":py:obj:`run_client_app `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.rst:24::1 +#: flwr.client.app.run_client_app:1 of +msgid "Run Flower client app." +msgstr "" + +#: ../../source/ref-api/flwr.client.rst:24::1 +msgid "" +":py:obj:`start_client `\\ \\(\\*\\, " +"server\\_address\\[\\, client\\_fn\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.rst:24::1 +#: flwr.client.app.start_client:1 of +msgid "Start a Flower client node which connects to a Flower server." +msgstr "" + +#: ../../source/ref-api/flwr.client.rst:24::1 +msgid "" +":py:obj:`start_numpy_client `\\ \\(\\*\\," +" server\\_address\\, client\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.rst:24::1 +#: flwr.client.app.start_numpy_client:1 of +msgid "Start a Flower NumPyClient which connects to a gRPC server." +msgstr "" + +#: ../../source/ref-api/flwr.client.rst:26 +#: ../../source/ref-api/flwr.common.rst:31 +#: ../../source/ref-api/flwr.server.driver.rst:24 +#: ../../source/ref-api/flwr.server.rst:28 +#: ../../source/ref-api/flwr.server.strategy.rst:17 +msgid "Classes" +msgstr "" + +#: ../../source/ref-api/flwr.client.rst:33::1 +msgid ":py:obj:`Client `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.rst:33::1 +#: flwr.client.client.Client:1 of +msgid "Abstract base class for Flower clients." +msgstr "" + +#: ../../source/ref-api/flwr.client.rst:33::1 +msgid "" +":py:obj:`ClientApp `\\ \\(client\\_fn\\[\\, " +"mods\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.rst:33::1 +#: flwr.client.clientapp.ClientApp:1 of +msgid "Flower ClientApp." +msgstr "" + +#: ../../source/ref-api/flwr.client.rst:33::1 +msgid ":py:obj:`NumPyClient `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.rst:33::1 +#: flwr.client.numpy_client.NumPyClient:1 of +msgid "Abstract base class for Flower clients using NumPy." +msgstr "" + +#: flwr.client.client.Client:1 flwr.client.numpy_client.NumPyClient:1 +#: flwr.server.client_manager.ClientManager:1 +#: flwr.server.strategy.strategy.Strategy:1 of +msgid "Bases: :py:class:`~abc.ABC`" msgstr "" -#: ../../source/ref-api-flwr.rst:32 +#: ../../source/ref-api/flwr.client.Client.rst:15 +#: ../../source/ref-api/flwr.client.ClientApp.rst:15 +#: ../../source/ref-api/flwr.client.NumPyClient.rst:15 +#: ../../source/ref-api/flwr.common.ClientMessage.rst:15 +#: ../../source/ref-api/flwr.common.DisconnectRes.rst:15 +#: ../../source/ref-api/flwr.common.EvaluateIns.rst:15 +#: ../../source/ref-api/flwr.common.EvaluateRes.rst:15 +#: ../../source/ref-api/flwr.common.FitIns.rst:15 +#: ../../source/ref-api/flwr.common.FitRes.rst:15 +#: ../../source/ref-api/flwr.common.GetParametersIns.rst:15 +#: ../../source/ref-api/flwr.common.GetParametersRes.rst:15 +#: ../../source/ref-api/flwr.common.GetPropertiesIns.rst:15 +#: ../../source/ref-api/flwr.common.GetPropertiesRes.rst:15 +#: ../../source/ref-api/flwr.common.Parameters.rst:15 +#: ../../source/ref-api/flwr.common.ReconnectIns.rst:15 +#: ../../source/ref-api/flwr.common.ServerMessage.rst:15 +#: ../../source/ref-api/flwr.common.Status.rst:15 +#: ../../source/ref-api/flwr.server.ClientManager.rst:15 +#: ../../source/ref-api/flwr.server.History.rst:15 +#: ../../source/ref-api/flwr.server.Server.rst:15 +#: ../../source/ref-api/flwr.server.ServerConfig.rst:15 +#: ../../source/ref-api/flwr.server.SimpleClientManager.rst:15 +#: ../../source/ref-api/flwr.server.driver.Driver.rst:15 +#: ../../source/ref-api/flwr.server.driver.GrpcDriver.rst:15 +#: ../../source/ref-api/flwr.server.strategy.Bulyan.rst:15 +#: ../../source/ref-api/flwr.server.strategy.DPFedAvgAdaptive.rst:15 +#: ../../source/ref-api/flwr.server.strategy.DPFedAvgFixed.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FaultTolerantFedAvg.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedAdagrad.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedAdam.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedAvg.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedAvgAndroid.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedAvgM.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedMedian.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedOpt.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedProx.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedTrimmedAvg.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedXgbBagging.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedXgbCyclic.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedXgbNnAvg.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedYogi.rst:15 +#: ../../source/ref-api/flwr.server.strategy.Krum.rst:15 +#: ../../source/ref-api/flwr.server.strategy.QFedAvg.rst:15 +#: ../../source/ref-api/flwr.server.strategy.Strategy.rst:15 +msgid "Methods" +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +msgid ":py:obj:`evaluate `\\ \\(ins\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +#: flwr.client.client.Client.evaluate:1 +#: flwr.client.numpy_client.NumPyClient.evaluate:1 of +msgid "Evaluate the provided parameters using the locally held dataset." +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +msgid ":py:obj:`fit `\\ \\(ins\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +#: flwr.client.client.Client.fit:1 of +msgid "Refine the provided parameters using the locally held dataset." +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +msgid ":py:obj:`get_context `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +#: flwr.client.client.Client.get_context:1 +#: flwr.client.numpy_client.NumPyClient.get_context:1 of +msgid "Get the run context from this client." +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +msgid ":py:obj:`get_parameters `\\ \\(ins\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +#: flwr.client.client.Client.get_parameters:1 +#: flwr.client.numpy_client.NumPyClient.get_parameters:1 of +msgid "Return the current local model parameters." +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +msgid ":py:obj:`get_properties `\\ \\(ins\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +#: flwr.client.client.Client.get_properties:1 of +msgid "Return set of client's properties." +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +msgid ":py:obj:`set_context `\\ \\(context\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +#: flwr.client.client.Client.set_context:1 +#: flwr.client.numpy_client.NumPyClient.set_context:1 of +msgid "Apply a run context to this client." +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +msgid ":py:obj:`to_client `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +#: flwr.client.client.Client.to_client:1 of +msgid "Return client (itself)." +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:46 +#: ../../source/ref-api/flwr.client.NumPyClient.rst:46 +#: ../../source/ref-api/flwr.common.ClientMessage.rst:25 +#: ../../source/ref-api/flwr.common.Code.rst:19 +#: ../../source/ref-api/flwr.common.DisconnectRes.rst:25 +#: ../../source/ref-api/flwr.common.EvaluateIns.rst:25 +#: ../../source/ref-api/flwr.common.EvaluateRes.rst:25 +#: ../../source/ref-api/flwr.common.EventType.rst:19 +#: ../../source/ref-api/flwr.common.FitIns.rst:25 +#: ../../source/ref-api/flwr.common.FitRes.rst:25 +#: ../../source/ref-api/flwr.common.GetParametersIns.rst:25 +#: ../../source/ref-api/flwr.common.GetParametersRes.rst:25 +#: ../../source/ref-api/flwr.common.GetPropertiesIns.rst:25 +#: ../../source/ref-api/flwr.common.GetPropertiesRes.rst:25 +#: ../../source/ref-api/flwr.common.Parameters.rst:25 +#: ../../source/ref-api/flwr.common.ReconnectIns.rst:25 +#: ../../source/ref-api/flwr.common.ServerMessage.rst:25 +#: ../../source/ref-api/flwr.common.Status.rst:25 +#: ../../source/ref-api/flwr.server.ServerConfig.rst:25 +msgid "Attributes" +msgstr "" + +#: flwr.client.client.Client.evaluate:1::1 of +msgid ":py:obj:`context `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.Parameters.rst:2 +#: flwr.client.app.start_client flwr.client.app.start_numpy_client +#: flwr.client.client.Client.evaluate flwr.client.client.Client.fit +#: flwr.client.client.Client.get_parameters +#: flwr.client.client.Client.get_properties +#: flwr.client.numpy_client.NumPyClient.evaluate +#: flwr.client.numpy_client.NumPyClient.fit +#: flwr.client.numpy_client.NumPyClient.get_parameters +#: flwr.client.numpy_client.NumPyClient.get_properties +#: flwr.server.app.start_server +#: flwr.server.client_manager.ClientManager.register +#: flwr.server.client_manager.ClientManager.unregister +#: flwr.server.client_manager.SimpleClientManager.register +#: flwr.server.client_manager.SimpleClientManager.unregister +#: flwr.server.client_manager.SimpleClientManager.wait_for +#: flwr.server.driver.app.start_driver flwr.server.driver.driver.Driver +#: flwr.server.strategy.bulyan.Bulyan +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit +#: flwr.server.strategy.fedadagrad.FedAdagrad +#: flwr.server.strategy.fedadam.FedAdam flwr.server.strategy.fedavg.FedAvg +#: flwr.server.strategy.fedavg_android.FedAvgAndroid +#: flwr.server.strategy.fedavgm.FedAvgM flwr.server.strategy.fedopt.FedOpt +#: flwr.server.strategy.fedprox.FedProx +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg +#: flwr.server.strategy.fedyogi.FedYogi flwr.server.strategy.krum.Krum +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate +#: flwr.server.strategy.strategy.Strategy.aggregate_fit +#: flwr.server.strategy.strategy.Strategy.configure_evaluate +#: flwr.server.strategy.strategy.Strategy.configure_fit +#: flwr.server.strategy.strategy.Strategy.evaluate +#: flwr.server.strategy.strategy.Strategy.initialize_parameters +#: flwr.simulation.app.start_simulation of +msgid "Parameters" +msgstr "" + +#: flwr.client.client.Client.evaluate:3 of +msgid "" +"The evaluation instructions containing (global) model parameters received" +" from the server and a dictionary of configuration values used to " +"customize the local evaluation process." +msgstr "" + +#: flwr.client.client.Client.evaluate flwr.client.client.Client.fit +#: flwr.client.client.Client.get_parameters +#: flwr.client.client.Client.get_properties +#: flwr.client.numpy_client.NumPyClient.evaluate +#: flwr.client.numpy_client.NumPyClient.fit +#: flwr.client.numpy_client.NumPyClient.get_parameters +#: flwr.client.numpy_client.NumPyClient.get_properties +#: flwr.server.app.start_server +#: flwr.server.client_manager.ClientManager.num_available +#: flwr.server.client_manager.ClientManager.register +#: flwr.server.client_manager.SimpleClientManager.num_available +#: flwr.server.client_manager.SimpleClientManager.register +#: flwr.server.client_manager.SimpleClientManager.wait_for +#: flwr.server.driver.app.start_driver +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate +#: flwr.server.strategy.strategy.Strategy.aggregate_fit +#: flwr.server.strategy.strategy.Strategy.configure_evaluate +#: flwr.server.strategy.strategy.Strategy.configure_fit +#: flwr.server.strategy.strategy.Strategy.evaluate +#: flwr.server.strategy.strategy.Strategy.initialize_parameters +#: flwr.simulation.app.start_simulation of +msgid "Returns" +msgstr "" + +#: flwr.client.client.Client.evaluate:8 of +msgid "" +"The evaluation result containing the loss on the local dataset and other " +"details such as the number of local data examples used for evaluation." +msgstr "" + +#: flwr.client.client.Client.evaluate flwr.client.client.Client.fit +#: flwr.client.client.Client.get_parameters +#: flwr.client.client.Client.get_properties +#: flwr.client.numpy_client.NumPyClient.get_parameters +#: flwr.client.numpy_client.NumPyClient.get_properties +#: flwr.server.app.start_server +#: flwr.server.client_manager.ClientManager.num_available +#: flwr.server.client_manager.ClientManager.register +#: flwr.server.client_manager.SimpleClientManager.num_available +#: flwr.server.client_manager.SimpleClientManager.register +#: flwr.server.client_manager.SimpleClientManager.wait_for +#: flwr.server.driver.app.start_driver +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate +#: flwr.server.strategy.strategy.Strategy.aggregate_fit +#: flwr.server.strategy.strategy.Strategy.configure_evaluate +#: flwr.server.strategy.strategy.Strategy.configure_fit +#: flwr.server.strategy.strategy.Strategy.evaluate +#: flwr.server.strategy.strategy.Strategy.initialize_parameters +#: flwr.simulation.app.start_simulation of +msgid "Return type" +msgstr "" + +#: flwr.client.client.Client.fit:3 of +msgid "" +"The training instructions containing (global) model parameters received " +"from the server and a dictionary of configuration values used to " +"customize the local training process." +msgstr "" + +#: flwr.client.client.Client.fit:8 of +msgid "" +"The training result containing updated parameters and other details such " +"as the number of local training examples used for training." +msgstr "" + +#: flwr.client.client.Client.get_parameters:3 of +msgid "" +"The get parameters instructions received from the server containing a " +"dictionary of configuration values." +msgstr "" + +#: flwr.client.client.Client.get_parameters:7 of +msgid "The current local model parameters." +msgstr "" + +#: flwr.client.client.Client.get_properties:3 of +msgid "" +"The get properties instructions received from the server containing a " +"dictionary of configuration values." +msgstr "" + +#: flwr.client.client.Client.get_properties:7 of +msgid "The current client properties." +msgstr "" + +#: ../../source/ref-api/flwr.client.ClientApp.rst:2 +msgid "ClientApp" +msgstr "" + +#: flwr.client.clientapp.ClientApp:1 flwr.common.typing.ClientMessage:1 +#: flwr.common.typing.DisconnectRes:1 flwr.common.typing.EvaluateIns:1 +#: flwr.common.typing.EvaluateRes:1 flwr.common.typing.FitIns:1 +#: flwr.common.typing.FitRes:1 flwr.common.typing.GetParametersIns:1 +#: flwr.common.typing.GetParametersRes:1 flwr.common.typing.GetPropertiesIns:1 +#: flwr.common.typing.GetPropertiesRes:1 flwr.common.typing.Parameters:1 +#: flwr.common.typing.ReconnectIns:1 flwr.common.typing.ServerMessage:1 +#: flwr.common.typing.Status:1 flwr.server.app.ServerConfig:1 +#: flwr.server.driver.driver.Driver:1 +#: flwr.server.driver.grpc_driver.GrpcDriver:1 flwr.server.history.History:1 +#: flwr.server.server.Server:1 of +msgid "Bases: :py:class:`object`" +msgstr "" + +#: flwr.client.app.start_client:33 flwr.client.app.start_numpy_client:36 +#: flwr.client.clientapp.ClientApp:4 flwr.server.app.start_server:41 +#: flwr.server.driver.app.start_driver:30 of +msgid "Examples" +msgstr "" + +#: flwr.client.clientapp.ClientApp:5 of +msgid "" +"Assuming a typical `Client` implementation named `FlowerClient`, you can " +"wrap it in a `ClientApp` as follows:" +msgstr "" + +#: flwr.client.clientapp.ClientApp:16 of +msgid "" +"If the above code is in a Python module called `client`, it can be " +"started as follows:" +msgstr "" + +#: flwr.client.clientapp.ClientApp:21 of +msgid "" +"In this `client:app` example, `client` refers to the Python module " +"`client.py` in which the previous code lives in and `app` refers to the " +"global attribute `app` that points to an object of type `ClientApp`." +msgstr "" + +#: ../../source/ref-api/flwr.client.NumPyClient.rst:2 msgid "NumPyClient" msgstr "" -#: ../../source/ref-api-flwr.rst:41 -msgid "start_numpy_client" +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +msgid "" +":py:obj:`evaluate `\\ \\(parameters\\, " +"config\\)" msgstr "" -#: ../../source/ref-api-flwr.rst:49 -msgid "start_simulation" +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +msgid ":py:obj:`fit `\\ \\(parameters\\, config\\)" msgstr "" -#: ../../source/ref-api-flwr.rst:57 -msgid "server" +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +#: flwr.client.numpy_client.NumPyClient.fit:1 of +msgid "Train the provided parameters using the locally held dataset." +msgstr "" + +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +msgid ":py:obj:`get_context `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +msgid "" +":py:obj:`get_parameters `\\ " +"\\(config\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +msgid "" +":py:obj:`get_properties `\\ " +"\\(config\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +#: flwr.client.numpy_client.NumPyClient.get_properties:1 of +msgid "Return a client's set of properties." +msgstr "" + +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +msgid "" +":py:obj:`set_context `\\ " +"\\(context\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +msgid ":py:obj:`to_client `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +#: flwr.client.numpy_client.NumPyClient.to_client:1 of +msgid "Convert to object to Client type and return it." +msgstr "" + +#: flwr.client.numpy_client.NumPyClient.evaluate:1::1 of +msgid ":py:obj:`context `\\" +msgstr "" + +#: flwr.client.numpy_client.NumPyClient.evaluate:3 +#: flwr.client.numpy_client.NumPyClient.fit:3 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate:5 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:8 +#: flwr.server.strategy.strategy.Strategy.configure_evaluate:5 +#: flwr.server.strategy.strategy.Strategy.configure_fit:5 +#: flwr.server.strategy.strategy.Strategy.evaluate:8 of +msgid "The current (global) model parameters." msgstr "" -#: ../../source/ref-api-flwr.rst:65 -msgid "server.start_server" +#: flwr.client.numpy_client.NumPyClient.evaluate:5 of +msgid "" +"Configuration parameters which allow the server to influence evaluation " +"on the client. It can be used to communicate arbitrary values from the " +"server to the client, for example, to influence the number of examples " +"used for evaluation." +msgstr "" + +#: flwr.client.numpy_client.NumPyClient.evaluate:11 of +msgid "" +"* **loss** (*float*) -- The evaluation loss of the model on the local " +"dataset. * **num_examples** (*int*) -- The number of examples used for " +"evaluation. * **metrics** (*Dict[str, Scalar]*) -- A dictionary mapping " +"arbitrary string keys to values of type bool, bytes, float, int, or " +"str. It can be used to communicate arbitrary values back to the server." +msgstr "" + +#: flwr.client.numpy_client.NumPyClient.evaluate:11 of +msgid "" +"**loss** (*float*) -- The evaluation loss of the model on the local " +"dataset." +msgstr "" + +#: flwr.client.numpy_client.NumPyClient.evaluate:12 of +msgid "**num_examples** (*int*) -- The number of examples used for evaluation." +msgstr "" + +#: flwr.client.numpy_client.NumPyClient.evaluate:13 +#: flwr.client.numpy_client.NumPyClient.fit:13 of +msgid "" +"**metrics** (*Dict[str, Scalar]*) -- A dictionary mapping arbitrary " +"string keys to values of type bool, bytes, float, int, or str. It can be " +"used to communicate arbitrary values back to the server." +msgstr "" + +#: flwr.client.numpy_client.NumPyClient.evaluate:19 of +msgid "" +"The previous return type format (int, float, float) and the extended " +"format (int, float, float, Dict[str, Scalar]) have been deprecated and " +"removed since Flower 0.19." +msgstr "" + +#: flwr.client.numpy_client.NumPyClient.fit:5 of +msgid "" +"Configuration parameters which allow the server to influence training on " +"the client. It can be used to communicate arbitrary values from the " +"server to the client, for example, to set the number of (local) training " +"epochs." +msgstr "" + +#: flwr.client.numpy_client.NumPyClient.fit:11 of +msgid "" +"* **parameters** (*NDArrays*) -- The locally updated model parameters. * " +"**num_examples** (*int*) -- The number of examples used for training. * " +"**metrics** (*Dict[str, Scalar]*) -- A dictionary mapping arbitrary " +"string keys to values of type bool, bytes, float, int, or str. It can " +"be used to communicate arbitrary values back to the server." +msgstr "" + +#: flwr.client.numpy_client.NumPyClient.fit:11 of +msgid "**parameters** (*NDArrays*) -- The locally updated model parameters." +msgstr "" + +#: flwr.client.numpy_client.NumPyClient.fit:12 of +msgid "**num_examples** (*int*) -- The number of examples used for training." +msgstr "" + +#: flwr.client.numpy_client.NumPyClient.get_parameters:3 of +msgid "" +"Configuration parameters requested by the server. This can be used to " +"tell the client which parameters are needed along with some Scalar " +"attributes." +msgstr "" + +#: flwr.client.numpy_client.NumPyClient.get_parameters:8 of +msgid "**parameters** -- The local model parameters as a list of NumPy ndarrays." +msgstr "" + +#: flwr.client.numpy_client.NumPyClient.get_properties:3 of +msgid "" +"Configuration parameters requested by the server. This can be used to " +"tell the client which properties are needed along with some Scalar " +"attributes." +msgstr "" + +#: flwr.client.numpy_client.NumPyClient.get_properties:8 of +msgid "" +"**properties** -- A dictionary mapping arbitrary string keys to values of" +" type bool, bytes, float, int, or str. It can be used to communicate " +"arbitrary property values back to the server." +msgstr "" + +#: ../../source/ref-api/flwr.client.run_client_app.rst:2 +msgid "run\\_client\\_app" +msgstr "" + +#: ../../source/ref-api/flwr.client.start_client.rst:2 +msgid "start\\_client" +msgstr "" + +#: flwr.client.app.start_client:3 flwr.client.app.start_numpy_client:9 of +msgid "" +"The IPv4 or IPv6 address of the server. If the Flower server runs on the " +"same machine on port 8080, then `server_address` would be " +"`\"[::]:8080\"`." +msgstr "" + +#: flwr.client.app.start_client:7 of +msgid "A callable that instantiates a Client. (default: None)" +msgstr "" + +#: flwr.client.app.start_client:9 of +msgid "" +"An implementation of the abstract base class `flwr.client.Client` " +"(default: None)" msgstr "" -#: ../../source/ref-api-flwr.rst:73 -msgid "server.strategy" +#: flwr.client.app.start_client:12 flwr.client.app.start_numpy_client:15 of +msgid "" +"The maximum length of gRPC messages that can be exchanged with the Flower" +" server. The default should be sufficient for most models. Users who " +"train very large models might need to increase this value. Note that the " +"Flower server needs to be started with the same value (see " +"`flwr.server.start_server`), otherwise it will not know about the " +"increased limit and block larger messages." +msgstr "" + +#: flwr.client.app.start_client:19 flwr.client.app.start_numpy_client:22 +#: flwr.server.driver.app.start_driver:21 of +msgid "" +"The PEM-encoded root certificates as a byte string or a path string. If " +"provided, a secure connection using the certificates will be established " +"to an SSL-enabled Flower server." +msgstr "" + +#: flwr.client.app.start_client:23 flwr.client.app.start_numpy_client:26 of +msgid "" +"Starts an insecure gRPC connection when True. Enables HTTPS connection " +"when False, using system certificates if `root_certificates` is None." +msgstr "" + +#: flwr.client.app.start_client:26 flwr.client.app.start_numpy_client:29 of +msgid "" +"Configure the transport layer. Allowed values: - 'grpc-bidi': gRPC, " +"bidirectional streaming - 'grpc-rere': gRPC, request-response " +"(experimental) - 'rest': HTTP (experimental)" +msgstr "" + +#: flwr.client.app.start_client:34 flwr.client.app.start_numpy_client:37 of +msgid "Starting a gRPC client with an insecure server connection:" msgstr "" -#: ../../source/ref-api-flwr.rst:81 -msgid "server.strategy.Strategy" +#: flwr.client.app.start_client:41 flwr.client.app.start_numpy_client:44 of +msgid "Starting an SSL-enabled gRPC client using system certificates:" msgstr "" -#: ../../source/ref-api-flwr.rst:90 -msgid "server.strategy.FedAvg" +#: flwr.client.app.start_client:52 flwr.client.app.start_numpy_client:52 of +msgid "Starting an SSL-enabled gRPC client using provided certificates:" msgstr "" -#: ../../source/ref-api-flwr.rst:101 -msgid "server.strategy.FedAvgM" +#: ../../source/ref-api/flwr.client.start_numpy_client.rst:2 +msgid "start\\_numpy\\_client" msgstr "" -#: ../../source/ref-api-flwr.rst:112 -msgid "server.strategy.FedMedian" +#: flwr.client.app.start_numpy_client:5 of +msgid "" +"This function is deprecated since 1.7.0. Use " +":code:`flwr.client.start_client` instead and first convert your " +":code:`NumPyClient` to type :code:`flwr.client.Client` by executing its " +":code:`to_client()` method." +msgstr "" + +#: flwr.client.app.start_numpy_client:13 of +msgid "An implementation of the abstract base class `flwr.client.NumPyClient`." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:2 +msgid "common" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:29::1 +msgid ":py:obj:`bytes_to_ndarray `\\ \\(tensor\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:29::1 +#: flwr.common.parameter.bytes_to_ndarray:1 of +msgid "Deserialize NumPy ndarray from bytes." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:29::1 +msgid "" +":py:obj:`configure `\\ \\(identifier\\[\\, " +"filename\\, host\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:29::1 +#: flwr.common.logger.configure:1 of +msgid "Configure logging to file and/or remote log server." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:29::1 +msgid "" +":py:obj:`event `\\ \\(event\\_type\\[\\, " +"event\\_details\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:29::1 +#: flwr.common.telemetry.event:1 of +msgid "Submit create_event to ThreadPoolExecutor to avoid blocking." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:29::1 +msgid "" +":py:obj:`log `\\ \\(level\\, msg\\, \\*args\\, " +"\\*\\*kwargs\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:29::1 logging.Logger.log:1 +#: of +msgid "Log 'msg % args' with the integer severity 'level'." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:29::1 +msgid ":py:obj:`ndarray_to_bytes `\\ \\(ndarray\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:29::1 +#: flwr.common.parameter.ndarray_to_bytes:1 of +msgid "Serialize NumPy ndarray to bytes." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:29::1 +msgid ":py:obj:`now `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:29::1 +#: flwr.common.date.now:1 of +msgid "Construct a datetime from time.time() with time zone set to UTC." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:29::1 +msgid "" +":py:obj:`ndarrays_to_parameters `\\ " +"\\(ndarrays\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:29::1 +#: flwr.common.parameter.ndarrays_to_parameters:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.ndarrays_to_parameters:1 +#: of +msgid "Convert NumPy ndarrays to parameters object." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:29::1 +msgid "" +":py:obj:`parameters_to_ndarrays `\\ " +"\\(parameters\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:29::1 +#: flwr.common.parameter.parameters_to_ndarrays:1 of +msgid "Convert parameters object to NumPy ndarrays." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid "" +":py:obj:`ClientMessage `\\ " +"\\(\\[get\\_properties\\_res\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.ClientMessage:1 of +msgid "ClientMessage is a container used to hold one result message." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`Code `\\ \\(value\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.Code:1 of +msgid "Client status codes." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`DisconnectRes `\\ \\(reason\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.DisconnectRes:1 of +msgid "DisconnectRes message from client to server." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid "" +":py:obj:`EvaluateIns `\\ \\(parameters\\, " +"config\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.EvaluateIns:1 of +msgid "Evaluate instructions for a client." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid "" +":py:obj:`EvaluateRes `\\ \\(status\\, loss\\, " +"num\\_examples\\, metrics\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.EvaluateRes:1 of +msgid "Evaluate response from a client." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`EventType `\\ \\(value\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.telemetry.EventType:1 of +msgid "Types of telemetry events." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`FitIns `\\ \\(parameters\\, config\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.FitIns:1 of +msgid "Fit instructions for a client." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid "" +":py:obj:`FitRes `\\ \\(status\\, parameters\\, " +"num\\_examples\\, metrics\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.FitRes:1 of +msgid "Fit response from a client." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`GetParametersIns `\\ \\(config\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.GetParametersIns:1 of +msgid "Parameters request for a client." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid "" +":py:obj:`GetParametersRes `\\ \\(status\\, " +"parameters\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.GetParametersRes:1 of +msgid "Response when asked to return parameters." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`GetPropertiesIns `\\ \\(config\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.GetPropertiesIns:1 of +msgid "Properties request for a client." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid "" +":py:obj:`GetPropertiesRes `\\ \\(status\\, " +"properties\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.GetPropertiesRes:1 of +msgid "Properties response from a client." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`NDArray `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid "" +"alias of :py:class:`~numpy.ndarray`\\ [:py:obj:`~typing.Any`, " +":py:class:`~numpy.dtype`\\ [:py:obj:`~typing.Any`]]" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid "" +":py:obj:`Parameters `\\ \\(tensors\\, " +"tensor\\_type\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.Parameters:1 of +msgid "Model parameters." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`ReconnectIns `\\ \\(seconds\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.ReconnectIns:1 of +msgid "ReconnectIns message from server to client." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid "" +":py:obj:`ServerMessage `\\ " +"\\(\\[get\\_properties\\_ins\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.ServerMessage:1 of +msgid "ServerMessage is a container used to hold one instruction message." +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`Status `\\ \\(code\\, message\\)" +msgstr "" + +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.Status:1 of +msgid "Client status." +msgstr "" + +#: ../../source/ref-api/flwr.common.ClientMessage.rst:2 +msgid "ClientMessage" +msgstr "" + +#: ../../source/ref-api/flwr.common.ClientMessage.rst:31::1 +msgid ":py:obj:`evaluate_res `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.ClientMessage.rst:31::1 +msgid ":py:obj:`fit_res `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.ClientMessage.rst:31::1 +msgid "" +":py:obj:`get_parameters_res " +"`\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.ClientMessage.rst:31::1 +msgid "" +":py:obj:`get_properties_res " +"`\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.Code.rst:2 +msgid "Code" +msgstr "" + +#: flwr.common.typing.Code:1 of +msgid "Bases: :py:class:`~enum.Enum`" +msgstr "" + +#: ../../source/ref-api/flwr.common.Code.rst:26::1 +msgid ":py:obj:`OK `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.Code.rst:26::1 +msgid "" +":py:obj:`GET_PROPERTIES_NOT_IMPLEMENTED " +"`\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.Code.rst:26::1 +msgid "" +":py:obj:`GET_PARAMETERS_NOT_IMPLEMENTED " +"`\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.Code.rst:26::1 +msgid ":py:obj:`FIT_NOT_IMPLEMENTED `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.Code.rst:26::1 +msgid "" +":py:obj:`EVALUATE_NOT_IMPLEMENTED " +"`\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.DisconnectRes.rst:2 +msgid "DisconnectRes" +msgstr "" + +#: ../../source/ref-api/flwr.common.DisconnectRes.rst:28::1 +msgid ":py:obj:`reason `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EvaluateIns.rst:2 +msgid "EvaluateIns" +msgstr "" + +#: ../../source/ref-api/flwr.common.EvaluateIns.rst:29::1 +msgid ":py:obj:`parameters `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EvaluateIns.rst:29::1 +msgid ":py:obj:`config `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EvaluateRes.rst:2 +msgid "EvaluateRes" +msgstr "" + +#: ../../source/ref-api/flwr.common.EvaluateRes.rst:31::1 +msgid ":py:obj:`status `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EvaluateRes.rst:31::1 +msgid ":py:obj:`loss `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EvaluateRes.rst:31::1 +msgid ":py:obj:`num_examples `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EvaluateRes.rst:31::1 +msgid ":py:obj:`metrics `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:2 +msgid "EventType" +msgstr "" + +#: flwr.common.telemetry.EventType:1 of +msgid "Bases: :py:class:`str`, :py:class:`~enum.Enum`" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`PING `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`START_CLIENT_ENTER `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`START_CLIENT_LEAVE `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`START_SERVER_ENTER `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`START_SERVER_LEAVE `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid "" +":py:obj:`RUN_DRIVER_API_ENTER " +"`\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid "" +":py:obj:`RUN_DRIVER_API_LEAVE " +"`\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid "" +":py:obj:`RUN_FLEET_API_ENTER " +"`\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid "" +":py:obj:`RUN_FLEET_API_LEAVE " +"`\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid "" +":py:obj:`RUN_SUPERLINK_ENTER " +"`\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid "" +":py:obj:`RUN_SUPERLINK_LEAVE " +"`\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid "" +":py:obj:`START_SIMULATION_ENTER " +"`\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid "" +":py:obj:`START_SIMULATION_LEAVE " +"`\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`DRIVER_CONNECT `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`DRIVER_DISCONNECT `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`START_DRIVER_ENTER `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`START_DRIVER_LEAVE `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid "" +":py:obj:`RUN_CLIENT_APP_ENTER " +"`\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid "" +":py:obj:`RUN_CLIENT_APP_LEAVE " +"`\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid "" +":py:obj:`RUN_SERVER_APP_ENTER " +"`\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid "" +":py:obj:`RUN_SERVER_APP_LEAVE " +"`\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.FitIns.rst:2 +msgid "FitIns" +msgstr "" + +#: ../../source/ref-api/flwr.common.FitIns.rst:29::1 +msgid ":py:obj:`parameters `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.FitIns.rst:29::1 +msgid ":py:obj:`config `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.FitRes.rst:2 +msgid "FitRes" +msgstr "" + +#: ../../source/ref-api/flwr.common.FitRes.rst:31::1 +msgid ":py:obj:`status `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.FitRes.rst:31::1 +msgid ":py:obj:`parameters `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.FitRes.rst:31::1 +msgid ":py:obj:`num_examples `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.FitRes.rst:31::1 +msgid ":py:obj:`metrics `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.GetParametersIns.rst:2 +msgid "GetParametersIns" +msgstr "" + +#: ../../source/ref-api/flwr.common.GetParametersIns.rst:28::1 +msgid ":py:obj:`config `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.GetParametersRes.rst:2 +msgid "GetParametersRes" +msgstr "" + +#: ../../source/ref-api/flwr.common.GetParametersRes.rst:29::1 +msgid ":py:obj:`status `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.GetParametersRes.rst:29::1 +msgid ":py:obj:`parameters `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.GetPropertiesIns.rst:2 +msgid "GetPropertiesIns" +msgstr "" + +#: ../../source/ref-api/flwr.common.GetPropertiesIns.rst:28::1 +msgid ":py:obj:`config `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.GetPropertiesRes.rst:2 +msgid "GetPropertiesRes" +msgstr "" + +#: ../../source/ref-api/flwr.common.GetPropertiesRes.rst:29::1 +msgid ":py:obj:`status `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.GetPropertiesRes.rst:29::1 +msgid ":py:obj:`properties `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.NDArray.rst:2 +msgid "NDArray" +msgstr "" + +#: ../../source/ref-api/flwr.common.Parameters.rst:29::1 +msgid ":py:obj:`tensors `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.Parameters.rst:29::1 +msgid ":py:obj:`tensor_type `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.ReconnectIns.rst:2 +msgid "ReconnectIns" +msgstr "" + +#: ../../source/ref-api/flwr.common.ReconnectIns.rst:28::1 +msgid ":py:obj:`seconds `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.ServerMessage.rst:2 +msgid "ServerMessage" +msgstr "" + +#: ../../source/ref-api/flwr.common.ServerMessage.rst:31::1 +msgid ":py:obj:`evaluate_ins `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.ServerMessage.rst:31::1 +msgid ":py:obj:`fit_ins `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.ServerMessage.rst:31::1 +msgid "" +":py:obj:`get_parameters_ins " +"`\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.ServerMessage.rst:31::1 +msgid "" +":py:obj:`get_properties_ins " +"`\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.Status.rst:2 +msgid "Status" +msgstr "" + +#: ../../source/ref-api/flwr.common.Status.rst:29::1 +msgid ":py:obj:`code `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.Status.rst:29::1 +msgid ":py:obj:`message `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.bytes_to_ndarray.rst:2 +msgid "bytes\\_to\\_ndarray" +msgstr "" + +#: ../../source/ref-api/flwr.common.configure.rst:2 +msgid "configure" +msgstr "" + +#: ../../source/ref-api/flwr.common.event.rst:2 +msgid "event" +msgstr "" + +#: ../../source/ref-api/flwr.common.log.rst:2 +msgid "log" +msgstr "" + +#: logging.Logger.log:3 of +msgid "" +"To pass exception information, use the keyword argument exc_info with a " +"true value, e.g." +msgstr "" + +#: logging.Logger.log:6 of +#, python-format +msgid "logger.log(level, \"We have a %s\", \"mysterious problem\", exc_info=1)" +msgstr "" + +#: ../../source/ref-api/flwr.common.ndarray_to_bytes.rst:2 +msgid "ndarray\\_to\\_bytes" +msgstr "" + +#: ../../source/ref-api/flwr.common.ndarrays_to_parameters.rst:2 +msgid "ndarrays\\_to\\_parameters" +msgstr "" + +#: ../../source/ref-api/flwr.common.now.rst:2 +msgid "now" +msgstr "" + +#: ../../source/ref-api/flwr.common.parameters_to_ndarrays.rst:2 +msgid "parameters\\_to\\_ndarrays" +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:2 +msgid "server" +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:26::1 +msgid ":py:obj:`run_driver_api `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:26::1 +#: flwr.server.app.run_driver_api:1 of +msgid "Run Flower server (Driver API)." +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:26::1 +msgid ":py:obj:`run_fleet_api `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:26::1 +#: flwr.server.app.run_fleet_api:1 of +msgid "Run Flower server (Fleet API)." +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:26::1 +msgid ":py:obj:`run_server_app `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:26::1 +#: flwr.server.app.run_server_app:1 of +msgid "Run Flower server app." +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:26::1 +msgid ":py:obj:`run_superlink `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:26::1 +#: flwr.server.app.run_superlink:1 of +msgid "Run Flower server (Driver API and Fleet API)." +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:26::1 +msgid "" +":py:obj:`start_server `\\ \\(\\*\\[\\, " +"server\\_address\\, server\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:26::1 +#: flwr.server.app.start_server:1 of +msgid "Start a Flower server using the gRPC transport layer." +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:37::1 +msgid ":py:obj:`ClientManager `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:37::1 +#: flwr.server.client_manager.ClientManager:1 of +msgid "Abstract base class for managing Flower clients." +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:37::1 +msgid ":py:obj:`History `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:37::1 +#: flwr.server.history.History:1 of +msgid "History class for training and/or evaluation metrics collection." +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:37::1 +msgid "" +":py:obj:`Server `\\ \\(\\*\\, client\\_manager\\[\\, " +"strategy\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:37::1 +msgid "" +":py:obj:`ServerConfig `\\ \\(\\[num\\_rounds\\," +" round\\_timeout\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:37::1 +#: flwr.server.app.ServerConfig:1 of +msgid "Flower server config." +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:37::1 +msgid ":py:obj:`SimpleClientManager `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:37::1 +#: flwr.server.client_manager.SimpleClientManager:1 of +msgid "Provides a pool of available clients." +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:56::1 +msgid ":py:obj:`flwr.server.driver `\\" +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:56::1 flwr.server.driver:1 +#: of +msgid "Flower driver SDK." +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:56::1 +msgid ":py:obj:`flwr.server.strategy `\\" +msgstr "" + +#: ../../source/ref-api/flwr.server.rst:56::1 +#: flwr.server.strategy:1 of +msgid "Contains the strategy abstraction and different implementations." +msgstr "" + +#: ../../source/ref-api/flwr.server.ClientManager.rst:2 +msgid "ClientManager" +msgstr "" + +#: flwr.server.client_manager.ClientManager.all:1::1 of +msgid ":py:obj:`all `\\ \\(\\)" +msgstr "" + +#: flwr.server.client_manager.ClientManager.all:1 +#: flwr.server.client_manager.ClientManager.all:1::1 +#: flwr.server.client_manager.SimpleClientManager.all:1 +#: flwr.server.client_manager.SimpleClientManager.all:1::1 of +msgid "Return all available clients." +msgstr "" + +#: flwr.server.client_manager.ClientManager.all:1::1 of +msgid ":py:obj:`num_available `\\ \\(\\)" +msgstr "" + +#: flwr.server.client_manager.ClientManager.all:1::1 +#: flwr.server.client_manager.ClientManager.num_available:1 +#: flwr.server.client_manager.SimpleClientManager.all:1::1 +#: flwr.server.client_manager.SimpleClientManager.num_available:1 of +msgid "Return the number of available clients." +msgstr "" + +#: flwr.server.client_manager.ClientManager.all:1::1 of +msgid ":py:obj:`register `\\ \\(client\\)" +msgstr "" + +#: flwr.server.client_manager.ClientManager.all:1::1 +#: flwr.server.client_manager.ClientManager.register:1 +#: flwr.server.client_manager.SimpleClientManager.all:1::1 +#: flwr.server.client_manager.SimpleClientManager.register:1 of +msgid "Register Flower ClientProxy instance." +msgstr "" + +#: flwr.server.client_manager.ClientManager.all:1::1 of +msgid "" +":py:obj:`sample `\\ " +"\\(num\\_clients\\[\\, min\\_num\\_clients\\, criterion\\]\\)" +msgstr "" + +#: flwr.server.client_manager.ClientManager.all:1::1 +#: flwr.server.client_manager.ClientManager.sample:1 +#: flwr.server.client_manager.SimpleClientManager.all:1::1 +#: flwr.server.client_manager.SimpleClientManager.sample:1 of +msgid "Sample a number of Flower ClientProxy instances." +msgstr "" + +#: flwr.server.client_manager.ClientManager.all:1::1 of +msgid ":py:obj:`unregister `\\ \\(client\\)" +msgstr "" + +#: flwr.server.client_manager.ClientManager.all:1::1 +#: flwr.server.client_manager.ClientManager.unregister:1 +#: flwr.server.client_manager.SimpleClientManager.all:1::1 +#: flwr.server.client_manager.SimpleClientManager.unregister:1 of +msgid "Unregister Flower ClientProxy instance." +msgstr "" + +#: flwr.server.client_manager.ClientManager.all:1::1 of +msgid "" +":py:obj:`wait_for `\\ " +"\\(num\\_clients\\, timeout\\)" +msgstr "" + +#: flwr.server.client_manager.ClientManager.all:1::1 +#: flwr.server.client_manager.ClientManager.wait_for:1 +#: flwr.server.client_manager.SimpleClientManager.all:1::1 +#: flwr.server.client_manager.SimpleClientManager.wait_for:1 of +msgid "Wait until at least `num_clients` are available." +msgstr "" + +#: flwr.server.client_manager.ClientManager.num_available:3 +#: flwr.server.client_manager.SimpleClientManager.num_available:3 of +msgid "**num_available** -- The number of currently available clients." +msgstr "" + +#: flwr.server.client_manager.ClientManager.register:6 +#: flwr.server.client_manager.SimpleClientManager.register:6 of +msgid "" +"**success** -- Indicating if registration was successful. False if " +"ClientProxy is already registered or can not be registered for any " +"reason." +msgstr "" + +#: flwr.server.client_manager.ClientManager.unregister:3 +#: flwr.server.client_manager.SimpleClientManager.unregister:3 of +msgid "This method is idempotent." +msgstr "" + +#: ../../source/ref-api/flwr.server.History.rst:2 +msgid "History" +msgstr "" + +#: flwr.server.history.History.add_loss_centralized:1::1 of +msgid "" +":py:obj:`add_loss_centralized " +"`\\ \\(server\\_round\\, " +"loss\\)" +msgstr "" + +#: flwr.server.history.History.add_loss_centralized:1 +#: flwr.server.history.History.add_loss_centralized:1::1 of +msgid "Add one loss entry (from centralized evaluation)." +msgstr "" + +#: flwr.server.history.History.add_loss_centralized:1::1 of +msgid "" +":py:obj:`add_loss_distributed " +"`\\ \\(server\\_round\\, " +"loss\\)" +msgstr "" + +#: flwr.server.history.History.add_loss_centralized:1::1 +#: flwr.server.history.History.add_loss_distributed:1 of +msgid "Add one loss entry (from distributed evaluation)." +msgstr "" + +#: flwr.server.history.History.add_loss_centralized:1::1 of +msgid "" +":py:obj:`add_metrics_centralized " +"`\\ \\(server\\_round\\, " +"metrics\\)" +msgstr "" + +#: flwr.server.history.History.add_loss_centralized:1::1 +#: flwr.server.history.History.add_metrics_centralized:1 of +msgid "Add metrics entries (from centralized evaluation)." +msgstr "" + +#: flwr.server.history.History.add_loss_centralized:1::1 of +msgid "" +":py:obj:`add_metrics_distributed " +"`\\ \\(server\\_round\\, " +"metrics\\)" +msgstr "" + +#: flwr.server.history.History.add_loss_centralized:1::1 +#: flwr.server.history.History.add_metrics_distributed:1 of +msgid "Add metrics entries (from distributed evaluation)." +msgstr "" + +#: flwr.server.history.History.add_loss_centralized:1::1 of +msgid "" +":py:obj:`add_metrics_distributed_fit " +"`\\ \\(server\\_round\\," +" ...\\)" +msgstr "" + +#: flwr.server.history.History.add_loss_centralized:1::1 +#: flwr.server.history.History.add_metrics_distributed_fit:1 of +msgid "Add metrics entries (from distributed fit)." +msgstr "" + +#: flwr.server.server.Server.client_manager:1::1 of +msgid ":py:obj:`client_manager `\\ \\(\\)" +msgstr "" + +#: flwr.server.server.Server.client_manager:1 +#: flwr.server.server.Server.client_manager:1::1 of +msgid "Return ClientManager." +msgstr "" + +#: flwr.server.server.Server.client_manager:1::1 of +msgid "" +":py:obj:`disconnect_all_clients " +"`\\ \\(timeout\\)" +msgstr "" + +#: flwr.server.server.Server.client_manager:1::1 +#: flwr.server.server.Server.disconnect_all_clients:1 of +msgid "Send shutdown signal to all clients." +msgstr "" + +#: flwr.server.server.Server.client_manager:1::1 of +msgid "" +":py:obj:`evaluate_round `\\ " +"\\(server\\_round\\, timeout\\)" +msgstr "" + +#: flwr.server.server.Server.client_manager:1::1 +#: flwr.server.server.Server.evaluate_round:1 of +msgid "Validate current global model on a number of clients." +msgstr "" + +#: flwr.server.server.Server.client_manager:1::1 of +msgid ":py:obj:`fit `\\ \\(num\\_rounds\\, timeout\\)" +msgstr "" + +#: flwr.server.server.Server.client_manager:1::1 +#: flwr.server.server.Server.fit:1 of +msgid "Run federated averaging for a number of rounds." +msgstr "" + +#: flwr.server.server.Server.client_manager:1::1 of +msgid "" +":py:obj:`fit_round `\\ \\(server\\_round\\," +" timeout\\)" +msgstr "" + +#: flwr.server.server.Server.client_manager:1::1 +#: flwr.server.server.Server.fit_round:1 of +msgid "Perform a single round of federated averaging." +msgstr "" + +#: flwr.server.server.Server.client_manager:1::1 of +msgid "" +":py:obj:`set_max_workers `\\ " +"\\(max\\_workers\\)" +msgstr "" + +#: flwr.server.server.Server.client_manager:1::1 +#: flwr.server.server.Server.set_max_workers:1 of +msgid "Set the max_workers used by ThreadPoolExecutor." +msgstr "" + +#: flwr.server.server.Server.client_manager:1::1 of +msgid ":py:obj:`set_strategy `\\ \\(strategy\\)" +msgstr "" + +#: flwr.server.server.Server.client_manager:1::1 +#: flwr.server.server.Server.set_strategy:1 of +msgid "Replace server strategy." +msgstr "" + +#: ../../source/ref-api/flwr.server.ServerConfig.rst:2 +msgid "ServerConfig" +msgstr "" + +#: flwr.server.app.ServerConfig:3 of +msgid "" +"All attributes have default values which allows users to configure just " +"the ones they care about." +msgstr "" + +#: ../../source/ref-api/flwr.server.ServerConfig.rst:29::1 +msgid ":py:obj:`num_rounds `\\" +msgstr "" + +#: ../../source/ref-api/flwr.server.ServerConfig.rst:29::1 +msgid ":py:obj:`round_timeout `\\" +msgstr "" + +#: ../../source/ref-api/flwr.server.SimpleClientManager.rst:2 +msgid "SimpleClientManager" +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager:1 of +msgid "Bases: :py:class:`~flwr.server.client_manager.ClientManager`" +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager.all:1::1 of +msgid ":py:obj:`all `\\ \\(\\)" +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager.all:1::1 of +msgid "" +":py:obj:`num_available `\\" +" \\(\\)" +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager.all:1::1 of +msgid "" +":py:obj:`register `\\ " +"\\(client\\)" +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager.all:1::1 of +msgid "" +":py:obj:`sample `\\ " +"\\(num\\_clients\\[\\, min\\_num\\_clients\\, criterion\\]\\)" +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager.all:1::1 of +msgid "" +":py:obj:`unregister `\\ " +"\\(client\\)" +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager.all:1::1 of +msgid "" +":py:obj:`wait_for `\\ " +"\\(num\\_clients\\[\\, timeout\\]\\)" +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager.wait_for:3 of +msgid "" +"Blocks until the requested number of clients is available or until a " +"timeout is reached. Current timeout default: 1 day." +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager.wait_for:6 of +msgid "The number of clients to wait for." +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager.wait_for:8 of +msgid "The time in seconds to wait for, defaults to 86400 (24h)." +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager.wait_for:11 of +msgid "**success**" +msgstr "" + +#: ../../source/ref-api/flwr.server.driver.rst:2 +msgid "driver" +msgstr "" + +#: ../../source/ref-api/flwr.server.driver.rst:22::1 +msgid "" +":py:obj:`start_driver `\\ \\(\\*\\[\\, " +"server\\_address\\, server\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.driver.rst:22::1 +#: flwr.server.driver.app.start_driver:1 of +msgid "Start a Flower Driver API server." +msgstr "" + +#: ../../source/ref-api/flwr.server.driver.rst:30::1 +msgid "" +":py:obj:`Driver `\\ " +"\\(\\[driver\\_service\\_address\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.driver.rst:30::1 +#: flwr.server.driver.driver.Driver:1 of +msgid "`Driver` class provides an interface to the Driver API." +msgstr "" + +#: ../../source/ref-api/flwr.server.driver.rst:30::1 +msgid "" +":py:obj:`GrpcDriver `\\ " +"\\(\\[driver\\_service\\_address\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.driver.rst:30::1 +#: flwr.server.driver.grpc_driver.GrpcDriver:1 of +msgid "`GrpcDriver` provides access to the gRPC Driver API/service." +msgstr "" + +#: ../../source/ref-api/flwr.server.driver.Driver.rst:2 +msgid "Driver" +msgstr "" + +#: flwr.server.driver.driver.Driver:3 of +msgid "" +"The IPv4 or IPv6 address of the Driver API server. Defaults to " +"`\"[::]:9091\"`." +msgstr "" + +#: flwr.server.app.start_server:28 flwr.server.driver.driver.Driver:6 of +msgid "" +"Tuple containing root certificate, server certificate, and private key to" +" start a secure SSL-enabled server. The tuple is expected to have three " +"bytes elements in the following order: * CA certificate. * " +"server certificate. * server private key." +msgstr "" + +#: flwr.server.app.start_server:28 flwr.server.driver.driver.Driver:6 of +msgid "" +"Tuple containing root certificate, server certificate, and private key to" +" start a secure SSL-enabled server. The tuple is expected to have three " +"bytes elements in the following order:" +msgstr "" + +#: flwr.server.app.start_server:32 flwr.server.driver.driver.Driver:10 of +msgid "CA certificate." +msgstr "" + +#: flwr.server.app.start_server:33 flwr.server.driver.driver.Driver:11 of +msgid "server certificate." +msgstr "" + +#: flwr.server.app.start_server:34 flwr.server.driver.driver.Driver:12 of +msgid "server private key." +msgstr "" + +#: flwr.server.driver.driver.Driver.get_nodes:1::1 of +msgid ":py:obj:`get_nodes `\\ \\(\\)" +msgstr "" + +#: flwr.server.driver.driver.Driver.get_nodes:1 +#: flwr.server.driver.driver.Driver.get_nodes:1::1 of +msgid "Get node IDs." +msgstr "" + +#: flwr.server.driver.driver.Driver.get_nodes:1::1 of +msgid "" +":py:obj:`pull_task_res `\\ " +"\\(task\\_ids\\)" +msgstr "" + +#: flwr.server.driver.driver.Driver.get_nodes:1::1 +#: flwr.server.driver.driver.Driver.pull_task_res:1 +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 +#: flwr.server.driver.grpc_driver.GrpcDriver.pull_task_res:1 of +msgid "Get task results." +msgstr "" + +#: flwr.server.driver.driver.Driver.get_nodes:1::1 of +msgid "" +":py:obj:`push_task_ins `\\ " +"\\(task\\_ins\\_list\\)" +msgstr "" + +#: flwr.server.driver.driver.Driver.get_nodes:1::1 +#: flwr.server.driver.driver.Driver.push_task_ins:1 +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 +#: flwr.server.driver.grpc_driver.GrpcDriver.push_task_ins:1 of +msgid "Schedule tasks." +msgstr "" + +#: ../../source/ref-api/flwr.server.driver.GrpcDriver.rst:2 +msgid "GrpcDriver" +msgstr "" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 of +msgid ":py:obj:`connect `\\ \\(\\)" +msgstr "" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1 +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 of +msgid "Connect to the Driver API." +msgstr "" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 of +msgid "" +":py:obj:`create_run `\\ " +"\\(req\\)" +msgstr "" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 +#: flwr.server.driver.grpc_driver.GrpcDriver.create_run:1 of +msgid "Request for run ID." +msgstr "" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 of +msgid ":py:obj:`disconnect `\\ \\(\\)" +msgstr "" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 +#: flwr.server.driver.grpc_driver.GrpcDriver.disconnect:1 of +msgid "Disconnect from the Driver API." +msgstr "" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 of +msgid ":py:obj:`get_nodes `\\ \\(req\\)" +msgstr "" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 +#: flwr.server.driver.grpc_driver.GrpcDriver.get_nodes:1 of +msgid "Get client IDs." +msgstr "" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 of +msgid "" +":py:obj:`pull_task_res `\\ " +"\\(req\\)" +msgstr "" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 of +msgid "" +":py:obj:`push_task_ins `\\ " +"\\(req\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.driver.start_driver.rst:2 +msgid "start\\_driver" +msgstr "" + +#: flwr.server.driver.app.start_driver:3 of +msgid "" +"The IPv4 or IPv6 address of the Driver API server. Defaults to " +"`\"[::]:8080\"`." +msgstr "" + +#: flwr.server.driver.app.start_driver:6 of +msgid "" +"A server implementation, either `flwr.server.Server` or a subclass " +"thereof. If no instance is provided, then `start_driver` will create one." +msgstr "" + +#: flwr.server.app.start_server:9 flwr.server.driver.app.start_driver:10 +#: flwr.simulation.app.start_simulation:28 of +msgid "" +"Currently supported values are `num_rounds` (int, default: 1) and " +"`round_timeout` in seconds (float, default: None)." +msgstr "" + +#: flwr.server.app.start_server:12 flwr.server.driver.app.start_driver:13 of +msgid "" +"An implementation of the abstract base class " +"`flwr.server.strategy.Strategy`. If no strategy is provided, then " +"`start_server` will use `flwr.server.strategy.FedAvg`." +msgstr "" + +#: flwr.server.driver.app.start_driver:17 of +msgid "" +"An implementation of the class `flwr.server.ClientManager`. If no " +"implementation is provided, then `start_driver` will use " +"`flwr.server.SimpleClientManager`." +msgstr "" + +#: flwr.server.app.start_server:37 flwr.server.driver.app.start_driver:26 of +msgid "**hist** -- Object containing training and evaluation metrics." +msgstr "" + +#: flwr.server.driver.app.start_driver:31 of +msgid "Starting a driver that connects to an insecure server:" +msgstr "" + +#: flwr.server.driver.app.start_driver:35 of +msgid "Starting a driver that connects to an SSL-enabled server:" +msgstr "" + +#: ../../source/ref-api/flwr.server.run_driver_api.rst:2 +msgid "run\\_driver\\_api" +msgstr "" + +#: ../../source/ref-api/flwr.server.run_fleet_api.rst:2 +msgid "run\\_fleet\\_api" +msgstr "" + +#: ../../source/ref-api/flwr.server.run_server_app.rst:2 +msgid "run\\_server\\_app" +msgstr "" + +#: ../../source/ref-api/flwr.server.run_superlink.rst:2 +msgid "run\\_superlink" +msgstr "" + +#: ../../source/ref-api/flwr.server.start_server.rst:2 +msgid "start\\_server" +msgstr "" + +#: flwr.server.app.start_server:3 of +msgid "The IPv4 or IPv6 address of the server. Defaults to `\"[::]:8080\"`." +msgstr "" + +#: flwr.server.app.start_server:5 of +msgid "" +"A server implementation, either `flwr.server.Server` or a subclass " +"thereof. If no instance is provided, then `start_server` will create one." +msgstr "" + +#: flwr.server.app.start_server:16 of +msgid "" +"An implementation of the abstract base class `flwr.server.ClientManager`." +" If no implementation is provided, then `start_server` will use " +"`flwr.server.client_manager.SimpleClientManager`." +msgstr "" + +#: flwr.server.app.start_server:21 of +msgid "" +"The maximum length of gRPC messages that can be exchanged with the Flower" +" clients. The default should be sufficient for most models. Users who " +"train very large models might need to increase this value. Note that the " +"Flower clients need to be started with the same value (see " +"`flwr.client.start_client`), otherwise clients will not know about the " +"increased limit and block larger messages." +msgstr "" + +#: flwr.server.app.start_server:42 of +msgid "Starting an insecure server:" +msgstr "" + +#: flwr.server.app.start_server:46 of +msgid "Starting an SSL-enabled server:" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:2 +msgid "strategy" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FaultTolerantFedAvg " +"`\\ \\(\\*\\[\\, " +"fraction\\_fit\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg:1 of +msgid "Configurable fault-tolerant FedAvg strategy implementation." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedAdagrad `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedadagrad.FedAdagrad:1 of +msgid "FedAdagrad strategy - Adaptive Federated Optimization using Adagrad." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedAdam `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedadam.FedAdam:1 of +msgid "FedAdam - Adaptive Federated Optimization using Adam." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedAvg `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, fraction\\_evaluate\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedavg.FedAvg:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:1 of +msgid "Federated Averaging strategy." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedXgbNnAvg `\\ \\(\\*args\\, " +"\\*\\*kwargs\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg:1 of +msgid "Configurable FedXgbNnAvg strategy implementation." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedXgbBagging `\\ " +"\\(\\[evaluate\\_function\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging:1 of +msgid "Configurable FedXgbBagging strategy implementation." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedXgbCyclic `\\ " +"\\(\\*\\*kwargs\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic:1 of +msgid "Configurable FedXgbCyclic strategy implementation." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedAvgAndroid `\\ " +"\\(\\*\\[\\, fraction\\_fit\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedAvgM `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedavgm.FedAvgM:1 of +msgid "Federated Averaging with Momentum strategy." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedOpt `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, fraction\\_evaluate\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedopt.FedOpt:1 of +msgid "Federated Optim strategy." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedProx `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedprox.FedProx:1 of +msgid "Federated Optimization strategy." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedYogi `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedyogi.FedYogi:1 of +msgid "FedYogi [Reddi et al., 2020] strategy." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`QFedAvg `\\ \\(\\*\\[\\, " +"q\\_param\\, qffl\\_learning\\_rate\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.qfedavg.QFedAvg:1 of +msgid "Configurable QFedAvg strategy implementation." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedMedian `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedmedian.FedMedian:1 of +msgid "Configurable FedMedian strategy implementation." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedTrimmedAvg `\\ " +"\\(\\*\\[\\, fraction\\_fit\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:1 of +msgid "Federated Averaging with Trimmed Mean [Dong Yin, et al., 2021]." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`Krum `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, fraction\\_evaluate\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.krum.Krum:1 of +msgid "Krum [Blanchard et al., 2017] strategy." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`Bulyan `\\ \\(\\*\\, " +"fraction\\_fit\\, fraction\\_evaluate\\, ...\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.bulyan.Bulyan:1 of +msgid "Bulyan strategy." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`DPFedAvgAdaptive `\\ " +"\\(strategy\\, num\\_sampled\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.dpfedavg_adaptive.DPFedAvgAdaptive:1 of +msgid "Wrapper for configuring a Strategy for DP with Adaptive Clipping." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`DPFedAvgFixed `\\ " +"\\(strategy\\, num\\_sampled\\_clients\\, ...\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed:1 of +msgid "Wrapper for configuring a Strategy for DP with Fixed Clipping." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid ":py:obj:`Strategy `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.strategy.Strategy:1 of +msgid "Abstract base class for server strategy implementations." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.Bulyan.rst:2 +msgid "Bulyan" +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:1 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg:1 +#: flwr.server.strategy.fedavgm.FedAvgM:1 +#: flwr.server.strategy.fedmedian.FedMedian:1 +#: flwr.server.strategy.fedopt.FedOpt:1 flwr.server.strategy.fedprox.FedProx:1 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging:1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic:1 +#: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg:1 +#: flwr.server.strategy.krum.Krum:1 flwr.server.strategy.qfedavg.QFedAvg:1 of +msgid "Bases: :py:class:`~flwr.server.strategy.fedavg.FedAvg`" +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:3 of +msgid "Implementation based on https://arxiv.org/abs/1802.07927." +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:5 +#: flwr.server.strategy.fedadagrad.FedAdagrad:5 +#: flwr.server.strategy.fedadam.FedAdam:5 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:5 +#: flwr.server.strategy.fedavgm.FedAvgM:5 flwr.server.strategy.fedopt.FedOpt:5 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:5 +#: flwr.server.strategy.fedyogi.FedYogi:5 flwr.server.strategy.krum.Krum:5 of +msgid "Fraction of clients used during training. Defaults to 1.0." +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:7 +#: flwr.server.strategy.fedadagrad.FedAdagrad:7 +#: flwr.server.strategy.fedadam.FedAdam:7 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:7 +#: flwr.server.strategy.fedavgm.FedAvgM:7 flwr.server.strategy.fedopt.FedOpt:7 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:7 +#: flwr.server.strategy.fedyogi.FedYogi:7 flwr.server.strategy.krum.Krum:7 of +msgid "Fraction of clients used during validation. Defaults to 1.0." +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:9 +#: flwr.server.strategy.fedadagrad.FedAdagrad:9 +#: flwr.server.strategy.fedadam.FedAdam:9 flwr.server.strategy.fedavg.FedAvg:13 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:9 +#: flwr.server.strategy.fedavgm.FedAvgM:9 flwr.server.strategy.fedopt.FedOpt:9 +#: flwr.server.strategy.fedprox.FedProx:45 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:9 +#: flwr.server.strategy.fedyogi.FedYogi:9 flwr.server.strategy.krum.Krum:9 of +msgid "Minimum number of clients used during training. Defaults to 2." +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:11 +#: flwr.server.strategy.fedadagrad.FedAdagrad:11 +#: flwr.server.strategy.fedadam.FedAdam:11 +#: flwr.server.strategy.fedavg.FedAvg:15 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:11 +#: flwr.server.strategy.fedavgm.FedAvgM:11 +#: flwr.server.strategy.fedopt.FedOpt:11 +#: flwr.server.strategy.fedprox.FedProx:47 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:11 +#: flwr.server.strategy.fedyogi.FedYogi:11 flwr.server.strategy.krum.Krum:11 of +msgid "Minimum number of clients used during validation. Defaults to 2." +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:13 +#: flwr.server.strategy.fedadagrad.FedAdagrad:13 +#: flwr.server.strategy.fedadam.FedAdam:13 +#: flwr.server.strategy.fedavg.FedAvg:17 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:13 +#: flwr.server.strategy.fedavgm.FedAvgM:13 +#: flwr.server.strategy.fedopt.FedOpt:13 +#: flwr.server.strategy.fedprox.FedProx:49 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:13 +#: flwr.server.strategy.fedyogi.FedYogi:13 flwr.server.strategy.krum.Krum:13 of +msgid "Minimum number of total clients in the system. Defaults to 2." +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:15 flwr.server.strategy.krum.Krum:15 of +msgid "Number of malicious clients in the system. Defaults to 0." +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:17 +#: flwr.server.strategy.fedadagrad.FedAdagrad:15 +#: flwr.server.strategy.fedadam.FedAdam:15 +#: flwr.server.strategy.fedavg.FedAvg:19 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:15 +#: flwr.server.strategy.fedavgm.FedAvgM:15 +#: flwr.server.strategy.fedopt.FedOpt:15 +#: flwr.server.strategy.fedprox.FedProx:51 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:15 +#: flwr.server.strategy.fedyogi.FedYogi:17 +#: flwr.server.strategy.fedyogi.FedYogi:18 +#: flwr.server.strategy.fedyogi.FedYogi:19 flwr.server.strategy.krum.Krum:20 of +msgid "Optional function used for validation. Defaults to None." +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:19 +#: flwr.server.strategy.fedadagrad.FedAdagrad:17 +#: flwr.server.strategy.fedadam.FedAdam:17 +#: flwr.server.strategy.fedavg.FedAvg:21 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:17 +#: flwr.server.strategy.fedavgm.FedAvgM:17 +#: flwr.server.strategy.fedopt.FedOpt:17 +#: flwr.server.strategy.fedprox.FedProx:53 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:17 +#: flwr.server.strategy.fedyogi.FedYogi:20 flwr.server.strategy.krum.Krum:22 of +msgid "Function used to configure training. Defaults to None." +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:21 +#: flwr.server.strategy.fedadagrad.FedAdagrad:19 +#: flwr.server.strategy.fedadam.FedAdam:19 +#: flwr.server.strategy.fedavg.FedAvg:23 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:19 +#: flwr.server.strategy.fedavgm.FedAvgM:19 +#: flwr.server.strategy.fedopt.FedOpt:19 +#: flwr.server.strategy.fedprox.FedProx:55 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:19 +#: flwr.server.strategy.fedyogi.FedYogi:22 flwr.server.strategy.krum.Krum:24 of +msgid "Function used to configure validation. Defaults to None." +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:23 +#: flwr.server.strategy.fedadagrad.FedAdagrad:25 +#: flwr.server.strategy.fedadam.FedAdam:21 +#: flwr.server.strategy.fedavg.FedAvg:25 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:21 +#: flwr.server.strategy.fedavgm.FedAvgM:21 +#: flwr.server.strategy.fedopt.FedOpt:21 +#: flwr.server.strategy.fedprox.FedProx:57 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:21 +#: flwr.server.strategy.fedyogi.FedYogi:24 flwr.server.strategy.krum.Krum:26 of +msgid "Whether or not accept rounds containing failures. Defaults to True." +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:25 +#: flwr.server.strategy.fedadagrad.FedAdagrad:27 +#: flwr.server.strategy.fedadam.FedAdam:23 +#: flwr.server.strategy.fedavg.FedAvg:27 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:24 +#: flwr.server.strategy.fedavgm.FedAvgM:23 +#: flwr.server.strategy.fedopt.FedOpt:23 +#: flwr.server.strategy.fedprox.FedProx:59 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:23 +#: flwr.server.strategy.fedyogi.FedYogi:26 flwr.server.strategy.krum.Krum:28 of +msgid "Initial global model parameters." +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:27 of +msgid "" +"Byzantine resilient aggregation rule that is used as the first step of " +"the Bulyan (e.g., Krum)" +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:29 of +msgid "arguments to the first_aggregation rule" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\, " +"results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "Aggregate evaluation losses using weighted average." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan.aggregate_fit:1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "Aggregate fit results using Bulyan." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\, " +"parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.configure_evaluate:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.configure_evaluate:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.configure_evaluate:1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.configure_evaluate:1 +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: flwr.server.strategy.strategy.Strategy.configure_evaluate:1 of +msgid "Configure the next round of evaluation." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_adaptive.DPFedAvgAdaptive.configure_fit:1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.configure_fit:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.configure_fit:1 +#: flwr.server.strategy.fedprox.FedProx.configure_fit:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.configure_fit:1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.configure_fit:1 +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: flwr.server.strategy.strategy.Strategy.configure_fit:1 of +msgid "Configure the next round of training." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.evaluate:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.evaluate:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.evaluate:1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg.evaluate:1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "Evaluate model parameters using an evaluation function." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.initialize_parameters:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.initialize_parameters:1 +#: flwr.server.strategy.fedavgm.FedAvgM.initialize_parameters:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "Initialize global model parameters." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.num_evaluation_clients:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.num_evaluation_clients:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.num_evaluation_clients:1 of +msgid "Use a fraction of available clients for evaluation." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients `\\" +" \\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.num_fit_clients:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.num_fit_clients:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.num_fit_clients:1 of +msgid "Return the sample size and the required number of available clients." +msgstr "" + +#: flwr.server.strategy.dpfedavg_adaptive.DPFedAvgAdaptive:1 of +msgid "Bases: :py:class:`~flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed`" +msgstr "" + +#: flwr.server.strategy.dpfedavg_adaptive.DPFedAvgAdaptive:3 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed:3 of +msgid "This class is deprecated and will be removed in a future release." +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "Aggregate evaluation losses using the given strategy." +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_fit " +"`\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_adaptive.DPFedAvgAdaptive.aggregate_fit:1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "Aggregate training results as in DPFedAvgFixed and update clip norms." +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate:1 of +msgid "Configure the next round of evaluation using the specified strategy." +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_fit " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.evaluate:1 of +msgid "Evaluate model parameters using an evaluation function from the strategy." +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.initialize_parameters:1 of +msgid "Initialize global model parameters using given strategy." +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate:3 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:6 +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:3 +#: flwr.server.strategy.strategy.Strategy.aggregate_fit:3 +#: flwr.server.strategy.strategy.Strategy.configure_evaluate:3 +#: flwr.server.strategy.strategy.Strategy.configure_fit:3 +#: flwr.server.strategy.strategy.Strategy.evaluate:6 of +msgid "The current round of federated learning." +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate:7 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:10 +#: flwr.server.strategy.strategy.Strategy.configure_evaluate:7 +#: flwr.server.strategy.strategy.Strategy.configure_fit:7 +#: flwr.server.strategy.strategy.Strategy.initialize_parameters:3 of +msgid "The client manager which holds all currently connected clients." +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate:10 +#: flwr.server.strategy.strategy.Strategy.configure_evaluate:10 of +msgid "" +"**evaluate_configuration** -- A list of tuples. Each tuple in the list " +"identifies a `ClientProxy` and the `EvaluateIns` for this particular " +"`ClientProxy`. If a particular `ClientProxy` is not included in this " +"list, it means that this `ClientProxy` will not participate in the next " +"round of federated evaluation." +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed:1 +#: flwr.server.strategy.fedavg.FedAvg:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:1 of +msgid "Bases: :py:class:`~flwr.server.strategy.strategy.Strategy`" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_fit " +"`\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_fit:1 of +msgid "Aggregate training results using unweighted aggregation." +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_fit " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:1 of +msgid "" +"Configure the next round of training incorporating Differential Privacy " +"(DP)." +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:3 of +msgid "" +"Configuration of the next training round includes information related to " +"DP, such as clip norm and noise stddev." +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:13 +#: flwr.server.strategy.strategy.Strategy.configure_fit:10 of +msgid "" +"**fit_configuration** -- A list of tuples. Each tuple in the list " +"identifies a `ClientProxy` and the `FitIns` for this particular " +"`ClientProxy`. If a particular `ClientProxy` is not included in this " +"list, it means that this `ClientProxy` will not participate in the next " +"round of federated learning." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FaultTolerantFedAvg.rst:2 +msgid "FaultTolerantFedAvg" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_fit " +"`\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_fit:1 +#: flwr.server.strategy.fedadagrad.FedAdagrad.aggregate_fit:1 +#: flwr.server.strategy.fedadam.FedAdam.aggregate_fit:1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_fit:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_fit:1 +#: flwr.server.strategy.fedavgm.FedAvgM.aggregate_fit:1 +#: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg.aggregate_fit:1 +#: flwr.server.strategy.fedyogi.FedYogi.aggregate_fit:1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_fit:1 of +msgid "Aggregate fit results using weighted average." +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_fit " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedAdagrad.rst:2 +#: ../../source/ref-changelog.md:839 +msgid "FedAdagrad" +msgstr "" + +#: flwr.server.strategy.fedadagrad.FedAdagrad:1 +#: flwr.server.strategy.fedadam.FedAdam:1 +#: flwr.server.strategy.fedyogi.FedYogi:1 of +msgid "Bases: :py:class:`~flwr.server.strategy.fedopt.FedOpt`" +msgstr "" + +#: flwr.server.strategy.fedadagrad.FedAdagrad:3 +#: flwr.server.strategy.fedadam.FedAdam:3 flwr.server.strategy.fedopt.FedOpt:3 +#: flwr.server.strategy.fedyogi.FedYogi:3 of +msgid "Implementation based on https://arxiv.org/abs/2003.00295v5" +msgstr "" + +#: flwr.server.strategy.fedadagrad.FedAdagrad:21 +#: flwr.server.strategy.fedadagrad.FedAdagrad:23 +#: flwr.server.strategy.fedadam.FedAdam:25 +#: flwr.server.strategy.fedadam.FedAdam:27 +#: flwr.server.strategy.fedavg.FedAvg:29 flwr.server.strategy.fedavg.FedAvg:31 +#: flwr.server.strategy.fedopt.FedOpt:25 flwr.server.strategy.fedopt.FedOpt:27 +#: flwr.server.strategy.fedprox.FedProx:61 +#: flwr.server.strategy.fedprox.FedProx:63 +#: flwr.server.strategy.fedyogi.FedYogi:28 +#: flwr.server.strategy.fedyogi.FedYogi:30 of +msgid "Metrics aggregation function, optional." +msgstr "" + +#: flwr.server.strategy.fedadagrad.FedAdagrad:29 +#: flwr.server.strategy.fedadam.FedAdam:29 +#: flwr.server.strategy.fedopt.FedOpt:29 of +msgid "Server-side learning rate. Defaults to 1e-1." +msgstr "" + +#: flwr.server.strategy.fedadagrad.FedAdagrad:31 +#: flwr.server.strategy.fedadam.FedAdam:31 +#: flwr.server.strategy.fedopt.FedOpt:31 of +msgid "Client-side learning rate. Defaults to 1e-1." +msgstr "" + +#: flwr.server.strategy.fedadagrad.FedAdagrad:33 +#: flwr.server.strategy.fedadam.FedAdam:37 +#: flwr.server.strategy.fedopt.FedOpt:37 of +msgid "Controls the algorithm's degree of adaptability. Defaults to 1e-9." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit `\\" +" \\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\" +" \\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedAdam.rst:2 +msgid "FedAdam" +msgstr "" + +#: flwr.server.strategy.fedadam.FedAdam:33 +#: flwr.server.strategy.fedyogi.FedYogi:36 of +msgid "Momentum parameter. Defaults to 0.9." +msgstr "" + +#: flwr.server.strategy.fedadam.FedAdam:35 +#: flwr.server.strategy.fedyogi.FedYogi:38 of +msgid "Second moment parameter. Defaults to 0.99." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\," +" results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\," +" parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedAvg.rst:2 +msgid "FedAvg" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg:3 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:3 of +msgid "Implementation based on https://arxiv.org/abs/1602.05629" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg:5 flwr.server.strategy.fedprox.FedProx:37 +#: of +msgid "" +"Fraction of clients used during training. In case `min_fit_clients` is " +"larger than `fraction_fit * available_clients`, `min_fit_clients` will " +"still be sampled. Defaults to 1.0." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg:9 flwr.server.strategy.fedprox.FedProx:41 +#: of +msgid "" +"Fraction of clients used during validation. In case " +"`min_evaluate_clients` is larger than `fraction_evaluate * " +"available_clients`, `min_evaluate_clients` will still be sampled. " +"Defaults to 1.0." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\, " +"results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\, " +"parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients `\\" +" \\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedAvgAndroid.rst:2 +msgid "FedAvgAndroid" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_fit " +"`\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`bytes_to_ndarray " +"`\\ \\(tensor\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.bytes_to_ndarray:1 of +msgid "Deserialize NumPy array from bytes." +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_fit " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`ndarray_to_bytes " +"`\\ \\(ndarray\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.ndarray_to_bytes:1 of +msgid "Serialize NumPy array to bytes." +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`ndarrays_to_parameters " +"`\\ " +"\\(ndarrays\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`parameters_to_ndarrays " +"`\\ " +"\\(parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.parameters_to_ndarrays:1 +#: of +msgid "Convert parameters object to NumPy weights." +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedAvgM.rst:2 +msgid "FedAvgM" +msgstr "" + +#: flwr.server.strategy.fedavgm.FedAvgM:3 of +msgid "Implementation based on https://arxiv.org/abs/1909.06335" +msgstr "" + +#: flwr.server.strategy.fedavgm.FedAvgM:25 of +msgid "" +"Server-side learning rate used in server-side optimization. Defaults to " +"1.0." +msgstr "" + +#: flwr.server.strategy.fedavgm.FedAvgM:28 of +msgid "Server-side momentum factor used for FedAvgM. Defaults to 0.0." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\," +" results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\," +" parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedMedian.rst:2 +msgid "FedMedian" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedmedian.FedMedian.aggregate_fit:1 of +msgid "Aggregate fit results using median." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedOpt.rst:2 +msgid "FedOpt" +msgstr "" + +#: flwr.server.strategy.fedopt.FedOpt:33 of +msgid "Momentum parameter. Defaults to 0.0." +msgstr "" + +#: flwr.server.strategy.fedopt.FedOpt:35 of +msgid "Second moment parameter. Defaults to 0.0." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\, " +"results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\, " +"parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients `\\" +" \\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedProx.rst:2 +msgid "FedProx" +msgstr "" + +#: flwr.server.strategy.fedprox.FedProx:3 of +msgid "Implementation based on https://arxiv.org/abs/1812.06127" +msgstr "" + +#: flwr.server.strategy.fedprox.FedProx:5 of +msgid "" +"The strategy in itself will not be different than FedAvg, the client " +"needs to be adjusted. A proximal term needs to be added to the loss " +"function during the training:" +msgstr "" + +#: flwr.server.strategy.fedprox.FedProx:9 of +msgid "" +"\\\\frac{\\\\mu}{2} || w - w^t ||^2\n" +"\n" +msgstr "" + +#: flwr.server.strategy.fedprox.FedProx:12 of +msgid "" +"Where $w^t$ are the global parameters and $w$ are the local weights the " +"function will be optimized with." +msgstr "" + +#: flwr.server.strategy.fedprox.FedProx:15 of +msgid "In PyTorch, for example, the loss would go from:" +msgstr "" + +#: flwr.server.strategy.fedprox.FedProx:21 of +msgid "To:" +msgstr "" + +#: flwr.server.strategy.fedprox.FedProx:30 of +msgid "" +"With `global_params` being a copy of the parameters before the training " +"takes place." +msgstr "" + +#: flwr.server.strategy.fedprox.FedProx:65 of +msgid "" +"The weight of the proximal term used in the optimization. 0.0 makes this " +"strategy equivalent to FedAvg, and the higher the coefficient, the more " +"regularization will be used (that is, the client parameters will need to " +"be closer to the server parameters during training)." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\," +" results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\," +" parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedprox.FedProx.configure_fit:3 of +msgid "Sends the proximal factor mu to the clients" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedTrimmedAvg.rst:2 +msgid "FedTrimmedAvg" +msgstr "" + +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:3 of +msgid "Implemented based on: https://arxiv.org/abs/1803.01498" +msgstr "" + +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:25 of +msgid "Fraction to cut off of both tails of the distribution. Defaults to 0.2." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit " +"`\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg.aggregate_fit:1 of +msgid "Aggregate fit results using trimmed average." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedXgbBagging.rst:2 +msgid "FedXgbBagging" +msgstr "" + +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of +msgid "Aggregate evaluation metrics using average." +msgstr "" + +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_fit " +"`\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_fit:1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_fit:1 of +msgid "Aggregate fit results using bagging." +msgstr "" + +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_fit " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedXgbCyclic.rst:2 +msgid "FedXgbCyclic" +msgstr "" + +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_fit " +"`\\ \\(server\\_round\\," +" results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_fit " +"`\\ \\(server\\_round\\," +" parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedXgbNnAvg.rst:2 +msgid "FedXgbNnAvg" +msgstr "" + +#: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg:5 of +msgid "" +"This strategy is deprecated, but a copy of it is available in Flower " +"Baselines: " +"https://github.com/adap/flower/tree/main/baselines/hfedxgboost." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit " +"`\\ \\(server\\_round\\, " +"results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit " +"`\\ \\(server\\_round\\, " +"parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedYogi.rst:2 +msgid "FedYogi" +msgstr "" + +#: flwr.server.strategy.fedyogi.FedYogi:32 of +msgid "Server-side learning rate. Defaults to 1e-2." +msgstr "" + +#: flwr.server.strategy.fedyogi.FedYogi:34 of +msgid "Client-side learning rate. Defaults to 0.0316." +msgstr "" + +#: flwr.server.strategy.fedyogi.FedYogi:40 of +msgid "Controls the algorithm's degree of adaptability. Defaults to 1e-3." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\," +" results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\," +" parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.Krum.rst:2 +msgid "Krum" +msgstr "" + +#: flwr.server.strategy.krum.Krum:3 of +msgid "Implementation based on https://arxiv.org/abs/1703.02757" +msgstr "" + +#: flwr.server.strategy.krum.Krum:17 of +msgid "" +"Number of clients to keep before averaging (MultiKrum). Defaults to 0, in" +" that case classical Krum is applied." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\, " +"results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.krum.Krum.aggregate_fit:1 of +msgid "Aggregate fit results using Krum." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\, " +"parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients `\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.QFedAvg.rst:2 +msgid "QFedAvg" +msgstr "" + +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\," +" results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\," +" parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.Strategy.rst:2 +msgid "Strategy" +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1 +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: of +msgid "Aggregate evaluation results." +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: flwr.server.strategy.strategy.Strategy.aggregate_fit:1 of +msgid "Aggregate training results." +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: flwr.server.strategy.strategy.Strategy.evaluate:1 of +msgid "Evaluate the current model parameters." +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: flwr.server.strategy.strategy.Strategy.initialize_parameters:1 of +msgid "Initialize the (global) model parameters." +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:5 of +msgid "" +"Successful updates from the previously selected and configured clients. " +"Each pair of `(ClientProxy, FitRes` constitutes a successful update from " +"one of the previously selected clients. Not that not all previously " +"selected clients are necessarily included in this list: a client might " +"drop out and not submit a result. For each client that did not submit an " +"update, there should be an `Exception` in `failures`." +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:13 +#: flwr.server.strategy.strategy.Strategy.aggregate_fit:13 of +msgid "Exceptions that occurred while the server was waiting for client updates." +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:16 of +msgid "" +"**aggregation_result** -- The aggregated evaluation result. Aggregation " +"typically uses some variant of a weighted average." +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.aggregate_fit:5 of +msgid "" +"Successful updates from the previously selected and configured clients. " +"Each pair of `(ClientProxy, FitRes)` constitutes a successful update from" +" one of the previously selected clients. Not that not all previously " +"selected clients are necessarily included in this list: a client might " +"drop out and not submit a result. For each client that did not submit an " +"update, there should be an `Exception` in `failures`." +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.aggregate_fit:17 of +msgid "" +"**parameters** -- If parameters are returned, then the server will treat " +"these as the new global model parameters (i.e., it will replace the " +"previous parameters with the ones returned from this method). If `None` " +"is returned (e.g., because there were only failures and no viable " +"results) then the server will no update the previous model parameters, " +"the updates received in this round are discarded, and the global model " +"parameters remain the same." +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.evaluate:3 of +msgid "" +"This function can be used to perform centralized (i.e., server-side) " +"evaluation of model parameters." +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.evaluate:11 of +msgid "" +"**evaluation_result** -- The evaluation result, usually a Tuple " +"containing loss and a dictionary containing task-specific metrics (e.g., " +"accuracy)." +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.initialize_parameters:6 of +msgid "" +"**parameters** -- If parameters are returned, then the server will treat " +"these as the initial global model parameters." +msgstr "" + +#: ../../source/ref-api/flwr.simulation.rst:2 +msgid "simulation" +msgstr "" + +#: ../../source/ref-api/flwr.simulation.rst:17::1 +msgid "" +":py:obj:`start_simulation `\\ \\(\\*\\," +" client\\_fn\\[\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.simulation.rst:17::1 +#: flwr.simulation.app.start_simulation:1 of +msgid "Start a Ray-based Flower simulation server." +msgstr "" + +#: ../../source/ref-api/flwr.simulation.start_simulation.rst:2 +msgid "start\\_simulation" +msgstr "" + +#: flwr.simulation.app.start_simulation:3 of +msgid "" +"A function creating client instances. The function must take a single " +"`str` argument called `cid`. It should return a single client instance of" +" type Client. Note that the created client instances are ephemeral and " +"will often be destroyed after a single method invocation. Since client " +"instances are not long-lived, they should not attempt to carry state over" +" method invocations. Any state required by the instance (model, dataset, " +"hyperparameters, ...) should be (re-)created in either the call to " +"`client_fn` or the call to any of the client methods (e.g., load " +"evaluation data in the `evaluate` method itself)." +msgstr "" + +#: flwr.simulation.app.start_simulation:13 of +msgid "" +"The total number of clients in this simulation. This must be set if " +"`clients_ids` is not set and vice-versa." +msgstr "" + +#: flwr.simulation.app.start_simulation:16 of +msgid "" +"List `client_id`s for each client. This is only required if `num_clients`" +" is not set. Setting both `num_clients` and `clients_ids` with " +"`len(clients_ids)` not equal to `num_clients` generates an error." +msgstr "" + +#: flwr.simulation.app.start_simulation:20 of +msgid "" +"CPU and GPU resources for a single client. Supported keys are `num_cpus` " +"and `num_gpus`. To understand the GPU utilization caused by `num_gpus`, " +"as well as using custom resources, please consult the Ray documentation." +msgstr "" + +#: flwr.simulation.app.start_simulation:25 of +msgid "" +"An implementation of the abstract base class `flwr.server.Server`. If no " +"instance is provided, then `start_server` will create one." +msgstr "" + +#: flwr.simulation.app.start_simulation:31 of +msgid "" +"An implementation of the abstract base class `flwr.server.Strategy`. If " +"no strategy is provided, then `start_server` will use " +"`flwr.server.strategy.FedAvg`." +msgstr "" + +#: flwr.simulation.app.start_simulation:35 of +msgid "" +"An implementation of the abstract base class `flwr.server.ClientManager`." +" If no implementation is provided, then `start_simulation` will use " +"`flwr.server.client_manager.SimpleClientManager`." +msgstr "" + +#: flwr.simulation.app.start_simulation:39 of +msgid "" +"Optional dictionary containing arguments for the call to `ray.init`. If " +"ray_init_args is None (the default), Ray will be initialized with the " +"following default args: { \"ignore_reinit_error\": True, " +"\"include_dashboard\": False } An empty dictionary can be used " +"(ray_init_args={}) to prevent any arguments from being passed to " +"ray.init." +msgstr "" + +#: flwr.simulation.app.start_simulation:39 of +msgid "" +"Optional dictionary containing arguments for the call to `ray.init`. If " +"ray_init_args is None (the default), Ray will be initialized with the " +"following default args:" +msgstr "" + +#: flwr.simulation.app.start_simulation:43 of +msgid "{ \"ignore_reinit_error\": True, \"include_dashboard\": False }" +msgstr "" + +#: flwr.simulation.app.start_simulation:45 of +msgid "" +"An empty dictionary can be used (ray_init_args={}) to prevent any " +"arguments from being passed to ray.init." +msgstr "" + +#: flwr.simulation.app.start_simulation:48 of +msgid "" +"Set to True to prevent `ray.shutdown()` in case " +"`ray.is_initialized()=True`." +msgstr "" + +#: flwr.simulation.app.start_simulation:50 of +msgid "" +"Optionally specify the type of actor to use. The actor object, which " +"persists throughout the simulation, will be the process in charge of " +"running the clients' jobs (i.e. their `fit()` method)." +msgstr "" + +#: flwr.simulation.app.start_simulation:54 of +msgid "" +"If you want to create your own Actor classes, you might need to pass some" +" input argument. You can use this dictionary for such purpose." +msgstr "" + +#: flwr.simulation.app.start_simulation:57 of +msgid "" +"(default: \"DEFAULT\") Optional string (\"DEFAULT\" or \"SPREAD\") for " +"the VCE to choose in which node the actor is placed. If you are an " +"advanced user needed more control you can use lower-level scheduling " +"strategies to pin actors to specific compute nodes (e.g. via " +"NodeAffinitySchedulingStrategy). Please note this is an advanced feature." +" For all details, please refer to the Ray documentation: " +"https://docs.ray.io/en/latest/ray-core/scheduling/index.html" +msgstr "" + +#: flwr.simulation.app.start_simulation:66 of +msgid "**hist** -- Object containing metrics from training." +msgstr "" + +#: ../../source/ref-changelog.md:1 +msgid "Changelog" +msgstr "" + +#: ../../source/ref-changelog.md:3 +msgid "Unreleased" +msgstr "" + +#: ../../source/ref-changelog.md:5 ../../source/ref-changelog.md:17 +#: ../../source/ref-changelog.md:110 ../../source/ref-changelog.md:210 +#: ../../source/ref-changelog.md:294 ../../source/ref-changelog.md:358 +#: ../../source/ref-changelog.md:416 ../../source/ref-changelog.md:485 +#: ../../source/ref-changelog.md:614 ../../source/ref-changelog.md:656 +#: ../../source/ref-changelog.md:723 ../../source/ref-changelog.md:789 +#: ../../source/ref-changelog.md:834 ../../source/ref-changelog.md:873 +#: ../../source/ref-changelog.md:906 ../../source/ref-changelog.md:956 +msgid "What's new?" +msgstr "" + +#: ../../source/ref-changelog.md:7 ../../source/ref-changelog.md:80 +#: ../../source/ref-changelog.md:192 ../../source/ref-changelog.md:282 +#: ../../source/ref-changelog.md:346 ../../source/ref-changelog.md:404 +#: ../../source/ref-changelog.md:473 ../../source/ref-changelog.md:535 +#: ../../source/ref-changelog.md:554 ../../source/ref-changelog.md:710 +#: ../../source/ref-changelog.md:781 ../../source/ref-changelog.md:818 +#: ../../source/ref-changelog.md:861 +msgid "Incompatible changes" +msgstr "" + +#: ../../source/ref-changelog.md:9 +msgid "v1.7.0 (2024-02-05)" +msgstr "" + +#: ../../source/ref-changelog.md:11 ../../source/ref-changelog.md:104 +#: ../../source/ref-changelog.md:204 ../../source/ref-changelog.md:288 +#: ../../source/ref-changelog.md:352 ../../source/ref-changelog.md:410 +#: ../../source/ref-changelog.md:479 ../../source/ref-changelog.md:548 +msgid "Thanks to our contributors" +msgstr "" + +#: ../../source/ref-changelog.md:13 ../../source/ref-changelog.md:106 +#: ../../source/ref-changelog.md:206 ../../source/ref-changelog.md:290 +#: ../../source/ref-changelog.md:354 ../../source/ref-changelog.md:412 +msgid "" +"We would like to give our special thanks to all the contributors who made" +" the new version of Flower possible (in `git shortlog` order):" +msgstr "" + +#: ../../source/ref-changelog.md:15 +msgid "" +"`Aasheesh Singh`, `Adam Narozniak`, `Aml Hassan Esmil`, `Charles " +"Beauville`, `Daniel J. Beutel`, `Daniel Nata Nugraha`, `Edoardo " +"Gabrielli`, `Gustavo Bertoli`, `HelinLin`, `Heng Pan`, `Javier`, `M S " +"Chaitanya Kumar`, `Mohammad Naseri`, `Nikos Vlachakis`, `Pritam Neog`, " +"`Robert Kuska`, `Robert Steiner`, `Taner Topal`, `Yahia Salaheldin " +"Shaaban`, `Yan Gao`, `Yasar Abbas` " +msgstr "" + +#: ../../source/ref-changelog.md:19 +msgid "" +"**Introduce stateful clients (experimental)** " +"([#2770](https://github.com/adap/flower/pull/2770), " +"[#2686](https://github.com/adap/flower/pull/2686), " +"[#2696](https://github.com/adap/flower/pull/2696), " +"[#2643](https://github.com/adap/flower/pull/2643), " +"[#2769](https://github.com/adap/flower/pull/2769))" +msgstr "" + +#: ../../source/ref-changelog.md:21 +msgid "" +"Subclasses of `Client` and `NumPyClient` can now store local state that " +"remains on the client. Let's start with the highlight first: this new " +"feature is compatible with both simulated clients (via " +"`start_simulation`) and networked clients (via `start_client`). It's also" +" the first preview of new abstractions like `Context` and `RecordSet`. " +"Clients can access state of type `RecordSet` via `state: RecordSet = " +"self.context.state`. Changes to this `RecordSet` are preserved across " +"different rounds of execution to enable stateful computations in a " +"unified way across simulation and deployment." +msgstr "" + +#: ../../source/ref-changelog.md:23 +msgid "" +"**Improve performance** " +"([#2293](https://github.com/adap/flower/pull/2293))" +msgstr "" + +#: ../../source/ref-changelog.md:25 +msgid "" +"Flower is faster than ever. All `FedAvg`-derived strategies now use in-" +"place aggregation to reduce memory consumption. The Flower client " +"serialization/deserialization has been rewritten from the ground up, " +"which results in significant speedups, especially when the client-side " +"training time is short." +msgstr "" + +#: ../../source/ref-changelog.md:27 +msgid "" +"**Support Federated Learning with Apple MLX and Flower** " +"([#2693](https://github.com/adap/flower/pull/2693))" +msgstr "" + +#: ../../source/ref-changelog.md:29 +msgid "" +"Flower has official support for federated learning using [Appple " +"MLX](https://ml-explore.github.io/mlx) via the new `quickstart-mlx` code " +"example." +msgstr "" + +#: ../../source/ref-changelog.md:31 +msgid "" +"**Introduce new XGBoost cyclic strategy** " +"([#2666](https://github.com/adap/flower/pull/2666), " +"[#2668](https://github.com/adap/flower/pull/2668))" msgstr "" -#: ../../source/ref-api-flwr.rst:122 -msgid "server.strategy.QFedAvg" +#: ../../source/ref-changelog.md:33 +msgid "" +"A new strategy called `FedXgbCyclic` supports a client-by-client style of" +" training (often called cyclic). The `xgboost-comprehensive` code example" +" shows how to use it in a full project. In addition to that, `xgboost-" +"comprehensive` now also supports simulation mode. With this, Flower " +"offers best-in-class XGBoost support." msgstr "" -#: ../../source/ref-api-flwr.rst:133 -msgid "server.strategy.FaultTolerantFedAvg" +#: ../../source/ref-changelog.md:35 +msgid "" +"**Support Python 3.11** " +"([#2394](https://github.com/adap/flower/pull/2394))" msgstr "" -#: ../../source/ref-api-flwr.rst:144 -msgid "server.strategy.FedOpt" +#: ../../source/ref-changelog.md:37 +msgid "" +"Framework tests now run on Python 3.8, 3.9, 3.10, and 3.11. This will " +"ensure better support for users using more recent Python versions." msgstr "" -#: ../../source/ref-api-flwr.rst:155 -msgid "server.strategy.FedProx" +#: ../../source/ref-changelog.md:39 +msgid "" +"**Update gRPC and ProtoBuf dependencies** " +"([#2814](https://github.com/adap/flower/pull/2814))" msgstr "" -#: ../../source/ref-api-flwr.rst:166 -msgid "server.strategy.FedAdagrad" +#: ../../source/ref-changelog.md:41 +msgid "" +"The `grpcio` and `protobuf` dependencies were updated to their latest " +"versions for improved security and performance." msgstr "" -#: ../../source/ref-api-flwr.rst:177 -msgid "server.strategy.FedAdam" +#: ../../source/ref-changelog.md:43 +msgid "" +"**Introduce Docker image for Flower server** " +"([#2700](https://github.com/adap/flower/pull/2700), " +"[#2688](https://github.com/adap/flower/pull/2688), " +"[#2705](https://github.com/adap/flower/pull/2705), " +"[#2695](https://github.com/adap/flower/pull/2695), " +"[#2747](https://github.com/adap/flower/pull/2747), " +"[#2746](https://github.com/adap/flower/pull/2746), " +"[#2680](https://github.com/adap/flower/pull/2680), " +"[#2682](https://github.com/adap/flower/pull/2682), " +"[#2701](https://github.com/adap/flower/pull/2701))" msgstr "" -#: ../../source/ref-api-flwr.rst:188 -msgid "server.strategy.FedYogi" +#: ../../source/ref-changelog.md:45 +msgid "" +"The Flower server can now be run using an official Docker image. A new " +"how-to guide explains [how to run Flower using " +"Docker](https://flower.dev/docs/framework/how-to-run-flower-using-" +"docker.html). An official Flower client Docker image will follow." msgstr "" -#: ../../source/ref-api-flwr.rst:199 -msgid "server.strategy.FedTrimmedAvg" +#: ../../source/ref-changelog.md:47 +msgid "" +"**Introduce** `flower-via-docker-compose` **example** " +"([#2626](https://github.com/adap/flower/pull/2626))" msgstr "" -#: ../../source/ref-api-flwr.rst:210 -msgid "server.strategy.Krum" +#: ../../source/ref-changelog.md:49 +msgid "" +"**Introduce** `quickstart-sklearn-tabular` **example** " +"([#2719](https://github.com/adap/flower/pull/2719))" msgstr "" -#: ../../source/ref-api-flwr.rst:221 -msgid "server.strategy.FedXgbNnAvg" +#: ../../source/ref-changelog.md:51 +msgid "" +"**Introduce** `custom-metrics` **example** " +"([#1958](https://github.com/adap/flower/pull/1958))" msgstr "" -#: ../../source/ref-api-flwr.rst:232 -msgid "server.strategy.DPFedAvgAdaptive" +#: ../../source/ref-changelog.md:53 +msgid "" +"**Update code examples to use Flower Datasets** " +"([#2450](https://github.com/adap/flower/pull/2450), " +"[#2456](https://github.com/adap/flower/pull/2456), " +"[#2318](https://github.com/adap/flower/pull/2318), " +"[#2712](https://github.com/adap/flower/pull/2712))" msgstr "" -#: ../../source/ref-api-flwr.rst:243 -msgid "server.strategy.DPFedAvgFixed" +#: ../../source/ref-changelog.md:55 +msgid "" +"Several code examples were updated to use [Flower " +"Datasets](https://flower.dev/docs/datasets/)." msgstr "" -#: ../../source/ref-api-flwr.rst:251 -msgid "common" +#: ../../source/ref-changelog.md:57 +msgid "" +"**General updates to Flower Examples** " +"([#2381](https://github.com/adap/flower/pull/2381), " +"[#2805](https://github.com/adap/flower/pull/2805), " +"[#2782](https://github.com/adap/flower/pull/2782), " +"[#2806](https://github.com/adap/flower/pull/2806), " +"[#2829](https://github.com/adap/flower/pull/2829), " +"[#2825](https://github.com/adap/flower/pull/2825), " +"[#2816](https://github.com/adap/flower/pull/2816), " +"[#2726](https://github.com/adap/flower/pull/2726), " +"[#2659](https://github.com/adap/flower/pull/2659), " +"[#2655](https://github.com/adap/flower/pull/2655))" msgstr "" -#: flwr.common:1 of -msgid "Common components shared between server and client." +#: ../../source/ref-changelog.md:59 +msgid "Many Flower code examples received substantial updates." msgstr "" -#: flwr.common.typing.ClientMessage:1 of -msgid "ClientMessage is a container used to hold one result message." +#: ../../source/ref-changelog.md:61 ../../source/ref-changelog.md:154 +msgid "**Update Flower Baselines**" msgstr "" -#: flwr.common.typing.Code:1 of -msgid "Client status codes." +#: ../../source/ref-changelog.md:63 +msgid "" +"HFedXGBoost ([#2226](https://github.com/adap/flower/pull/2226), " +"[#2771](https://github.com/adap/flower/pull/2771))" msgstr "" -#: flwr.common.typing.DisconnectRes:1 of -msgid "DisconnectRes message from client to server." +#: ../../source/ref-changelog.md:64 +msgid "FedVSSL ([#2412](https://github.com/adap/flower/pull/2412))" msgstr "" -#: flwr.common.typing.EvaluateIns:1 of -msgid "Evaluate instructions for a client." +#: ../../source/ref-changelog.md:65 +msgid "FedNova ([#2179](https://github.com/adap/flower/pull/2179))" msgstr "" -#: flwr.common.typing.EvaluateRes:1 of -msgid "Evaluate response from a client." +#: ../../source/ref-changelog.md:66 +msgid "HeteroFL ([#2439](https://github.com/adap/flower/pull/2439))" msgstr "" -#: flwr.common.telemetry.EventType:1 of -msgid "Types of telemetry events." +#: ../../source/ref-changelog.md:67 +msgid "FedAvgM ([#2246](https://github.com/adap/flower/pull/2246))" +msgstr "" + +#: ../../source/ref-changelog.md:68 +msgid "FedPara ([#2722](https://github.com/adap/flower/pull/2722))" +msgstr "" + +#: ../../source/ref-changelog.md:70 +msgid "" +"**Improve documentation** " +"([#2674](https://github.com/adap/flower/pull/2674), " +"[#2480](https://github.com/adap/flower/pull/2480), " +"[#2826](https://github.com/adap/flower/pull/2826), " +"[#2727](https://github.com/adap/flower/pull/2727), " +"[#2761](https://github.com/adap/flower/pull/2761), " +"[#2900](https://github.com/adap/flower/pull/2900))" +msgstr "" + +#: ../../source/ref-changelog.md:72 +msgid "" +"**Improved testing and development infrastructure** " +"([#2797](https://github.com/adap/flower/pull/2797), " +"[#2676](https://github.com/adap/flower/pull/2676), " +"[#2644](https://github.com/adap/flower/pull/2644), " +"[#2656](https://github.com/adap/flower/pull/2656), " +"[#2848](https://github.com/adap/flower/pull/2848), " +"[#2675](https://github.com/adap/flower/pull/2675), " +"[#2735](https://github.com/adap/flower/pull/2735), " +"[#2767](https://github.com/adap/flower/pull/2767), " +"[#2732](https://github.com/adap/flower/pull/2732), " +"[#2744](https://github.com/adap/flower/pull/2744), " +"[#2681](https://github.com/adap/flower/pull/2681), " +"[#2699](https://github.com/adap/flower/pull/2699), " +"[#2745](https://github.com/adap/flower/pull/2745), " +"[#2734](https://github.com/adap/flower/pull/2734), " +"[#2731](https://github.com/adap/flower/pull/2731), " +"[#2652](https://github.com/adap/flower/pull/2652), " +"[#2720](https://github.com/adap/flower/pull/2720), " +"[#2721](https://github.com/adap/flower/pull/2721), " +"[#2717](https://github.com/adap/flower/pull/2717), " +"[#2864](https://github.com/adap/flower/pull/2864), " +"[#2694](https://github.com/adap/flower/pull/2694), " +"[#2709](https://github.com/adap/flower/pull/2709), " +"[#2658](https://github.com/adap/flower/pull/2658), " +"[#2796](https://github.com/adap/flower/pull/2796), " +"[#2692](https://github.com/adap/flower/pull/2692), " +"[#2657](https://github.com/adap/flower/pull/2657), " +"[#2813](https://github.com/adap/flower/pull/2813), " +"[#2661](https://github.com/adap/flower/pull/2661), " +"[#2398](https://github.com/adap/flower/pull/2398))" +msgstr "" + +#: ../../source/ref-changelog.md:74 +msgid "" +"The Flower testing and development infrastructure has received " +"substantial updates. This makes Flower 1.7 the most tested release ever." +msgstr "" + +#: ../../source/ref-changelog.md:76 +msgid "" +"**Update dependencies** " +"([#2753](https://github.com/adap/flower/pull/2753), " +"[#2651](https://github.com/adap/flower/pull/2651), " +"[#2739](https://github.com/adap/flower/pull/2739), " +"[#2837](https://github.com/adap/flower/pull/2837), " +"[#2788](https://github.com/adap/flower/pull/2788), " +"[#2811](https://github.com/adap/flower/pull/2811), " +"[#2774](https://github.com/adap/flower/pull/2774), " +"[#2790](https://github.com/adap/flower/pull/2790), " +"[#2751](https://github.com/adap/flower/pull/2751), " +"[#2850](https://github.com/adap/flower/pull/2850), " +"[#2812](https://github.com/adap/flower/pull/2812), " +"[#2872](https://github.com/adap/flower/pull/2872), " +"[#2736](https://github.com/adap/flower/pull/2736), " +"[#2756](https://github.com/adap/flower/pull/2756), " +"[#2857](https://github.com/adap/flower/pull/2857), " +"[#2757](https://github.com/adap/flower/pull/2757), " +"[#2810](https://github.com/adap/flower/pull/2810), " +"[#2740](https://github.com/adap/flower/pull/2740), " +"[#2789](https://github.com/adap/flower/pull/2789))" +msgstr "" + +#: ../../source/ref-changelog.md:78 +msgid "" +"**General improvements** " +"([#2803](https://github.com/adap/flower/pull/2803), " +"[#2847](https://github.com/adap/flower/pull/2847), " +"[#2877](https://github.com/adap/flower/pull/2877), " +"[#2690](https://github.com/adap/flower/pull/2690), " +"[#2889](https://github.com/adap/flower/pull/2889), " +"[#2874](https://github.com/adap/flower/pull/2874), " +"[#2819](https://github.com/adap/flower/pull/2819), " +"[#2689](https://github.com/adap/flower/pull/2689), " +"[#2457](https://github.com/adap/flower/pull/2457), " +"[#2870](https://github.com/adap/flower/pull/2870), " +"[#2669](https://github.com/adap/flower/pull/2669), " +"[#2876](https://github.com/adap/flower/pull/2876), " +"[#2885](https://github.com/adap/flower/pull/2885), " +"[#2858](https://github.com/adap/flower/pull/2858), " +"[#2867](https://github.com/adap/flower/pull/2867), " +"[#2351](https://github.com/adap/flower/pull/2351), " +"[#2886](https://github.com/adap/flower/pull/2886), " +"[#2860](https://github.com/adap/flower/pull/2860), " +"[#2828](https://github.com/adap/flower/pull/2828), " +"[#2869](https://github.com/adap/flower/pull/2869), " +"[#2875](https://github.com/adap/flower/pull/2875), " +"[#2733](https://github.com/adap/flower/pull/2733), " +"[#2488](https://github.com/adap/flower/pull/2488), " +"[#2646](https://github.com/adap/flower/pull/2646), " +"[#2879](https://github.com/adap/flower/pull/2879), " +"[#2821](https://github.com/adap/flower/pull/2821), " +"[#2855](https://github.com/adap/flower/pull/2855), " +"[#2800](https://github.com/adap/flower/pull/2800), " +"[#2807](https://github.com/adap/flower/pull/2807), " +"[#2801](https://github.com/adap/flower/pull/2801), " +"[#2804](https://github.com/adap/flower/pull/2804), " +"[#2851](https://github.com/adap/flower/pull/2851), " +"[#2787](https://github.com/adap/flower/pull/2787), " +"[#2852](https://github.com/adap/flower/pull/2852), " +"[#2672](https://github.com/adap/flower/pull/2672), " +"[#2759](https://github.com/adap/flower/pull/2759))" msgstr "" -#: flwr.common.typing.FitIns:1 of -msgid "Fit instructions for a client." +#: ../../source/ref-changelog.md:82 +msgid "" +"**Deprecate** `start_numpy_client` " +"([#2563](https://github.com/adap/flower/pull/2563), " +"[#2718](https://github.com/adap/flower/pull/2718))" msgstr "" -#: flwr.common.typing.FitRes:1 of -msgid "Fit response from a client." +#: ../../source/ref-changelog.md:84 +msgid "" +"Until now, clients of type `NumPyClient` needed to be started via " +"`start_numpy_client`. In our efforts to consolidate framework APIs, we " +"have introduced changes, and now all client types should start via " +"`start_client`. To continue using `NumPyClient` clients, you simply need " +"to first call the `.to_client()` method and then pass returned `Client` " +"object to `start_client`. The examples and the documentation have been " +"updated accordingly." msgstr "" -#: flwr.common.typing.GetParametersIns:1 of -msgid "Parameters request for a client." +#: ../../source/ref-changelog.md:86 +msgid "" +"**Deprecate legacy DP wrappers** " +"([#2749](https://github.com/adap/flower/pull/2749))" msgstr "" -#: flwr.common.typing.GetParametersRes:1 of -msgid "Response when asked to return parameters." +#: ../../source/ref-changelog.md:88 +msgid "" +"Legacy DP wrapper classes are deprecated, but still functional. This is " +"in preparation for an all-new pluggable version of differential privacy " +"support in Flower." msgstr "" -#: flwr.common.typing.GetPropertiesIns:1 of -msgid "Properties request for a client." +#: ../../source/ref-changelog.md:90 +msgid "" +"**Make optional arg** `--callable` **in** `flower-client` **a required " +"positional arg** ([#2673](https://github.com/adap/flower/pull/2673))" msgstr "" -#: flwr.common.typing.GetPropertiesRes:1 of -msgid "Properties response from a client." +#: ../../source/ref-changelog.md:92 +msgid "" +"**Rename** `certificates` **to** `root_certificates` **in** `Driver` " +"([#2890](https://github.com/adap/flower/pull/2890))" msgstr "" -#: flwr.common.typing.Parameters:1 of -msgid "Model parameters." +#: ../../source/ref-changelog.md:94 +msgid "" +"**Drop experimental** `Task` **fields** " +"([#2866](https://github.com/adap/flower/pull/2866), " +"[#2865](https://github.com/adap/flower/pull/2865))" msgstr "" -#: flwr.common.typing.ReconnectIns:1 of -msgid "ReconnectIns message from server to client." +#: ../../source/ref-changelog.md:96 +msgid "" +"Experimental fields `sa`, `legacy_server_message` and " +"`legacy_client_message` were removed from `Task` message. The removed " +"fields are superseded by the new `RecordSet` abstraction." msgstr "" -#: flwr.common.typing.ServerMessage:1 of -msgid "ServerMessage is a container used to hold one instruction message." +#: ../../source/ref-changelog.md:98 +msgid "" +"**Retire MXNet examples** " +"([#2724](https://github.com/adap/flower/pull/2724))" msgstr "" -#: flwr.common.typing.Status:1 of -msgid "Client status." +#: ../../source/ref-changelog.md:100 +msgid "" +"The development of the MXNet fremework has ended and the project is now " +"[archived on GitHub](https://github.com/apache/mxnet). Existing MXNet " +"examples won't receive updates." msgstr "" -#: flwr.common.parameter.bytes_to_ndarray:1 of -msgid "Deserialize NumPy ndarray from bytes." +#: ../../source/ref-changelog.md:102 +msgid "v1.6.0 (2023-11-28)" msgstr "" -#: flwr.common.logger.configure:1 of -msgid "Configure logging to file and/or remote log server." +#: ../../source/ref-changelog.md:108 +msgid "" +"`Aashish Kolluri`, `Adam Narozniak`, `Alessio Mora`, `Barathwaja S`, " +"`Charles Beauville`, `Daniel J. Beutel`, `Daniel Nata Nugraha`, `Gabriel " +"Mota`, `Heng Pan`, `Ivan Agarský`, `JS.KIM`, `Javier`, `Marius Schlegel`," +" `Navin Chandra`, `Nic Lane`, `Peterpan828`, `Qinbin Li`, `Shaz-hash`, " +"`Steve Laskaridis`, `Taner Topal`, `William Lindskog`, `Yan Gao`, " +"`cnxdeveloper`, `k3nfalt` " msgstr "" -#: logging.Logger.log:1 of -msgid "Log 'msg % args' with the integer severity 'level'." +#: ../../source/ref-changelog.md:112 +msgid "" +"**Add experimental support for Python 3.12** " +"([#2565](https://github.com/adap/flower/pull/2565))" msgstr "" -#: logging.Logger.log:3 of +#: ../../source/ref-changelog.md:114 msgid "" -"To pass exception information, use the keyword argument exc_info with a " -"true value, e.g." +"**Add new XGBoost examples** " +"([#2612](https://github.com/adap/flower/pull/2612), " +"[#2554](https://github.com/adap/flower/pull/2554), " +"[#2617](https://github.com/adap/flower/pull/2617), " +"[#2618](https://github.com/adap/flower/pull/2618), " +"[#2619](https://github.com/adap/flower/pull/2619), " +"[#2567](https://github.com/adap/flower/pull/2567))" msgstr "" -#: logging.Logger.log:6 of -#, python-format -msgid "logger.log(level, \"We have a %s\", \"mysterious problem\", exc_info=1)" +#: ../../source/ref-changelog.md:116 +msgid "" +"We have added a new `xgboost-quickstart` example alongside a new " +"`xgboost-comprehensive` example that goes more in-depth." msgstr "" -#: flwr.common.parameter.ndarray_to_bytes:1 of -msgid "Serialize NumPy ndarray to bytes." +#: ../../source/ref-changelog.md:118 +msgid "" +"**Add Vertical FL example** " +"([#2598](https://github.com/adap/flower/pull/2598))" msgstr "" -#: flwr.common.parameter.ndarrays_to_parameters:1 of -msgid "Convert NumPy ndarrays to parameters object." +#: ../../source/ref-changelog.md:120 +msgid "" +"We had many questions about Vertical Federated Learning using Flower, so " +"we decided to add an simple example for it on the [Titanic " +"dataset](https://www.kaggle.com/competitions/titanic/data) alongside a " +"tutorial (in the README)." msgstr "" -#: flwr.common.date.now:1 of -msgid "Construct a datetime from time.time() with time zone set to UTC." +#: ../../source/ref-changelog.md:122 +msgid "" +"**Support custom** `ClientManager` **in** `start_driver()` " +"([#2292](https://github.com/adap/flower/pull/2292))" msgstr "" -#: flwr.common.parameter.parameters_to_ndarrays:1 of -msgid "Convert parameters object to NumPy ndarrays." +#: ../../source/ref-changelog.md:124 +msgid "" +"**Update REST API to support create and delete nodes** " +"([#2283](https://github.com/adap/flower/pull/2283))" msgstr "" -#: ../../source/ref-changelog.md:1 -msgid "Changelog" +#: ../../source/ref-changelog.md:126 +msgid "" +"**Update the Android SDK** " +"([#2187](https://github.com/adap/flower/pull/2187))" msgstr "" -#: ../../source/ref-changelog.md:3 -msgid "Unreleased" +#: ../../source/ref-changelog.md:128 +msgid "Add gRPC request-response capability to the Android SDK." msgstr "" -#: ../../source/ref-changelog.md:5 +#: ../../source/ref-changelog.md:130 msgid "" -"**Support custom** `ClientManager` **in** `start_driver()` " -"([#2292](https://github.com/adap/flower/pull/2292))" +"**Update the C++ SDK** " +"([#2537](https://github.com/adap/flower/pull/2537), " +"[#2528](https://github.com/adap/flower/pull/2528), " +"[#2523](https://github.com/adap/flower/pull/2523), " +"[#2522](https://github.com/adap/flower/pull/2522))" msgstr "" -#: ../../source/ref-changelog.md:7 -msgid "" -"**Update REST API to support create and delete nodes** " -"([#2283](https://github.com/adap/flower/pull/2283))" +#: ../../source/ref-changelog.md:132 +msgid "Add gRPC request-response capability to the C++ SDK." msgstr "" -#: ../../source/ref-changelog.md:9 ../../source/ref-changelog.md:59 -#: ../../source/ref-changelog.md:143 ../../source/ref-changelog.md:207 -#: ../../source/ref-changelog.md:265 ../../source/ref-changelog.md:334 -#: ../../source/ref-changelog.md:463 ../../source/ref-changelog.md:505 -#: ../../source/ref-changelog.md:572 ../../source/ref-changelog.md:638 -#: ../../source/ref-changelog.md:683 ../../source/ref-changelog.md:722 -#: ../../source/ref-changelog.md:755 ../../source/ref-changelog.md:805 -msgid "What's new?" +#: ../../source/ref-changelog.md:134 +msgid "" +"**Make HTTPS the new default** " +"([#2591](https://github.com/adap/flower/pull/2591), " +"[#2636](https://github.com/adap/flower/pull/2636))" msgstr "" -#: ../../source/ref-changelog.md:11 +#: ../../source/ref-changelog.md:136 msgid "" -"**Fix the incorrect return types of Strategy** " -"([#2432](https://github.com/adap/flower/pull/2432/files))" +"Flower is moving to HTTPS by default. The new `flower-server` requires " +"passing `--certificates`, but users can enable `--insecure` to use HTTP " +"for prototyping. The same applies to `flower-client`, which can either " +"use user-provided credentials or gRPC-bundled certificates to connect to " +"an HTTPS-enabled server or requires opt-out via passing `--insecure` to " +"enable insecure HTTP connections." msgstr "" -#: ../../source/ref-changelog.md:13 +#: ../../source/ref-changelog.md:138 msgid "" -"The types of the return values in the docstrings in two methods " -"(`aggregate_fit` and `aggregate_evaluate`) now match the hint types in " -"the code." +"For backward compatibility, `start_client()` and `start_numpy_client()` " +"will still start in insecure mode by default. In a future release, " +"insecure connections will require user opt-in by passing `insecure=True`." msgstr "" -#: ../../source/ref-changelog.md:15 +#: ../../source/ref-changelog.md:140 msgid "" "**Unify client API** ([#2303](https://github.com/adap/flower/pull/2303), " "[#2390](https://github.com/adap/flower/pull/2390), " "[#2493](https://github.com/adap/flower/pull/2493))" msgstr "" -#: ../../source/ref-changelog.md:17 +#: ../../source/ref-changelog.md:142 msgid "" "Using the `client_fn`, Flower clients can interchangeably run as " "standalone processes (i.e. via `start_client`) or in simulation (i.e. via" " `start_simulation`) without requiring changes to how the client class is" -" defined and instantiated. Calling `start_numpy_client` is now " -"deprecated." +" defined and instantiated. The `to_client()` function is introduced to " +"convert a `NumPyClient` to a `Client`." msgstr "" -#: ../../source/ref-changelog.md:19 -msgid "**Update Flower Baselines**" +#: ../../source/ref-changelog.md:144 +msgid "" +"**Add new** `Bulyan` **strategy** " +"([#1817](https://github.com/adap/flower/pull/1817), " +"[#1891](https://github.com/adap/flower/pull/1891))" msgstr "" -#: ../../source/ref-changelog.md:21 +#: ../../source/ref-changelog.md:146 +msgid "" +"The new `Bulyan` strategy implements Bulyan by [El Mhamdi et al., " +"2018](https://arxiv.org/abs/1802.07927)" +msgstr "" + +#: ../../source/ref-changelog.md:148 +msgid "" +"**Add new** `XGB Bagging` **strategy** " +"([#2611](https://github.com/adap/flower/pull/2611))" +msgstr "" + +#: ../../source/ref-changelog.md:150 ../../source/ref-changelog.md:152 +msgid "" +"**Introduce `WorkloadState`** " +"([#2564](https://github.com/adap/flower/pull/2564), " +"[#2632](https://github.com/adap/flower/pull/2632))" +msgstr "" + +#: ../../source/ref-changelog.md:156 msgid "" "FedProx ([#2210](https://github.com/adap/flower/pull/2210), " "[#2286](https://github.com/adap/flower/pull/2286), " "[#2509](https://github.com/adap/flower/pull/2509))" msgstr "" -#: ../../source/ref-changelog.md:23 +#: ../../source/ref-changelog.md:158 msgid "" "Baselines Docs ([#2290](https://github.com/adap/flower/pull/2290), " "[#2400](https://github.com/adap/flower/pull/2400))" msgstr "" -#: ../../source/ref-changelog.md:25 +#: ../../source/ref-changelog.md:160 msgid "" "FedMLB ([#2340](https://github.com/adap/flower/pull/2340), " "[#2507](https://github.com/adap/flower/pull/2507))" msgstr "" -#: ../../source/ref-changelog.md:27 +#: ../../source/ref-changelog.md:162 msgid "" "TAMUNA ([#2254](https://github.com/adap/flower/pull/2254), " "[#2508](https://github.com/adap/flower/pull/2508))" msgstr "" -#: ../../source/ref-changelog.md:29 +#: ../../source/ref-changelog.md:164 msgid "FedMeta [#2438](https://github.com/adap/flower/pull/2438)" msgstr "" -#: ../../source/ref-changelog.md:31 +#: ../../source/ref-changelog.md:166 +msgid "FjORD [#2431](https://github.com/adap/flower/pull/2431)" +msgstr "" + +#: ../../source/ref-changelog.md:168 +msgid "MOON [#2421](https://github.com/adap/flower/pull/2421)" +msgstr "" + +#: ../../source/ref-changelog.md:170 +msgid "DepthFL [#2295](https://github.com/adap/flower/pull/2295)" +msgstr "" + +#: ../../source/ref-changelog.md:172 +msgid "FedPer [#2266](https://github.com/adap/flower/pull/2266)" +msgstr "" + +#: ../../source/ref-changelog.md:174 +msgid "FedWav2vec [#2551](https://github.com/adap/flower/pull/2551)" +msgstr "" + +#: ../../source/ref-changelog.md:176 +msgid "niid-Bench [#2428](https://github.com/adap/flower/pull/2428)" +msgstr "" + +#: ../../source/ref-changelog.md:178 msgid "" -"**Update Flower Examples** " -"([#2384](https://github.com/adap/flower/pull/2384)), " -"([#2425](https://github.com/adap/flower/pull/2425))" +"FedBN ([#2608](https://github.com/adap/flower/pull/2608), " +"[#2615](https://github.com/adap/flower/pull/2615))" msgstr "" -#: ../../source/ref-changelog.md:33 +#: ../../source/ref-changelog.md:180 +msgid "" +"**General updates to Flower Examples** " +"([#2384](https://github.com/adap/flower/pull/2384), " +"[#2425](https://github.com/adap/flower/pull/2425), " +"[#2526](https://github.com/adap/flower/pull/2526), " +"[#2302](https://github.com/adap/flower/pull/2302), " +"[#2545](https://github.com/adap/flower/pull/2545))" +msgstr "" + +#: ../../source/ref-changelog.md:182 msgid "" -"**General updates to baselines** " +"**General updates to Flower Baselines** " "([#2301](https://github.com/adap/flower/pull/2301), " "[#2305](https://github.com/adap/flower/pull/2305), " "[#2307](https://github.com/adap/flower/pull/2307), " "[#2327](https://github.com/adap/flower/pull/2327), " -"[#2435](https://github.com/adap/flower/pull/2435))" +"[#2435](https://github.com/adap/flower/pull/2435), " +"[#2462](https://github.com/adap/flower/pull/2462), " +"[#2463](https://github.com/adap/flower/pull/2463), " +"[#2461](https://github.com/adap/flower/pull/2461), " +"[#2469](https://github.com/adap/flower/pull/2469), " +"[#2466](https://github.com/adap/flower/pull/2466), " +"[#2471](https://github.com/adap/flower/pull/2471), " +"[#2472](https://github.com/adap/flower/pull/2472), " +"[#2470](https://github.com/adap/flower/pull/2470))" msgstr "" -#: ../../source/ref-changelog.md:35 +#: ../../source/ref-changelog.md:184 msgid "" "**General updates to the simulation engine** " "([#2331](https://github.com/adap/flower/pull/2331), " "[#2447](https://github.com/adap/flower/pull/2447), " -"[#2448](https://github.com/adap/flower/pull/2448))" +"[#2448](https://github.com/adap/flower/pull/2448), " +"[#2294](https://github.com/adap/flower/pull/2294))" msgstr "" -#: ../../source/ref-changelog.md:37 +#: ../../source/ref-changelog.md:186 +msgid "" +"**General updates to Flower SDKs** " +"([#2288](https://github.com/adap/flower/pull/2288), " +"[#2429](https://github.com/adap/flower/pull/2429), " +"[#2555](https://github.com/adap/flower/pull/2555), " +"[#2543](https://github.com/adap/flower/pull/2543), " +"[#2544](https://github.com/adap/flower/pull/2544), " +"[#2597](https://github.com/adap/flower/pull/2597), " +"[#2623](https://github.com/adap/flower/pull/2623))" +msgstr "" + +#: ../../source/ref-changelog.md:188 msgid "" "**General improvements** " "([#2309](https://github.com/adap/flower/pull/2309), " "[#2310](https://github.com/adap/flower/pull/2310), " -"[2313](https://github.com/adap/flower/pull/2313), " +"[#2313](https://github.com/adap/flower/pull/2313), " "[#2316](https://github.com/adap/flower/pull/2316), " -"[2317](https://github.com/adap/flower/pull/2317),[#2349](https://github.com/adap/flower/pull/2349)," -" [#2360](https://github.com/adap/flower/pull/2360), " +"[#2317](https://github.com/adap/flower/pull/2317), " +"[#2349](https://github.com/adap/flower/pull/2349), " +"[#2360](https://github.com/adap/flower/pull/2360), " "[#2402](https://github.com/adap/flower/pull/2402), " -"[#2446](https://github.com/adap/flower/pull/2446))" -msgstr "" - -#: ../../source/ref-changelog.md:39 ../../source/ref-changelog.md:129 -#: ../../source/ref-changelog.md:193 ../../source/ref-changelog.md:247 -#: ../../source/ref-changelog.md:314 +"[#2446](https://github.com/adap/flower/pull/2446), " +"[#2561](https://github.com/adap/flower/pull/2561), " +"[#2273](https://github.com/adap/flower/pull/2273), " +"[#2267](https://github.com/adap/flower/pull/2267), " +"[#2274](https://github.com/adap/flower/pull/2274), " +"[#2275](https://github.com/adap/flower/pull/2275), " +"[#2432](https://github.com/adap/flower/pull/2432), " +"[#2251](https://github.com/adap/flower/pull/2251), " +"[#2321](https://github.com/adap/flower/pull/2321), " +"[#1936](https://github.com/adap/flower/pull/1936), " +"[#2408](https://github.com/adap/flower/pull/2408), " +"[#2413](https://github.com/adap/flower/pull/2413), " +"[#2401](https://github.com/adap/flower/pull/2401), " +"[#2531](https://github.com/adap/flower/pull/2531), " +"[#2534](https://github.com/adap/flower/pull/2534), " +"[#2535](https://github.com/adap/flower/pull/2535), " +"[#2521](https://github.com/adap/flower/pull/2521), " +"[#2553](https://github.com/adap/flower/pull/2553), " +"[#2596](https://github.com/adap/flower/pull/2596))" +msgstr "" + +#: ../../source/ref-changelog.md:190 ../../source/ref-changelog.md:280 +#: ../../source/ref-changelog.md:344 ../../source/ref-changelog.md:398 +#: ../../source/ref-changelog.md:465 msgid "Flower received many improvements under the hood, too many to list here." msgstr "" -#: ../../source/ref-changelog.md:41 ../../source/ref-changelog.md:131 -#: ../../source/ref-changelog.md:195 ../../source/ref-changelog.md:253 -#: ../../source/ref-changelog.md:322 ../../source/ref-changelog.md:384 -#: ../../source/ref-changelog.md:403 ../../source/ref-changelog.md:559 -#: ../../source/ref-changelog.md:630 ../../source/ref-changelog.md:667 -#: ../../source/ref-changelog.md:710 -msgid "Incompatible changes" -msgstr "" - -#: ../../source/ref-changelog.md:43 +#: ../../source/ref-changelog.md:194 msgid "" "**Remove support for Python 3.7** " "([#2280](https://github.com/adap/flower/pull/2280), " @@ -5987,43 +11353,30 @@ msgid "" "[#2356](https://github.com/adap/flower/pull/2356))" msgstr "" -#: ../../source/ref-changelog.md:45 +#: ../../source/ref-changelog.md:196 msgid "" "Python 3.7 support was deprecated in Flower 1.5, and this release removes" " support. Flower now requires Python 3.8." msgstr "" -#: ../../source/ref-changelog.md:47 +#: ../../source/ref-changelog.md:198 msgid "" "**Remove experimental argument** `rest` **from** `start_client` " "([#2324](https://github.com/adap/flower/pull/2324))" msgstr "" -#: ../../source/ref-changelog.md:49 +#: ../../source/ref-changelog.md:200 msgid "" "The (still experimental) argument `rest` was removed from `start_client` " "and `start_numpy_client`. Use `transport=\"rest\"` to opt into the " "experimental REST API instead." msgstr "" -#: ../../source/ref-changelog.md:51 +#: ../../source/ref-changelog.md:202 msgid "v1.5.0 (2023-08-31)" msgstr "" -#: ../../source/ref-changelog.md:53 ../../source/ref-changelog.md:137 -#: ../../source/ref-changelog.md:201 ../../source/ref-changelog.md:259 -#: ../../source/ref-changelog.md:328 ../../source/ref-changelog.md:397 -msgid "Thanks to our contributors" -msgstr "" - -#: ../../source/ref-changelog.md:55 ../../source/ref-changelog.md:139 -#: ../../source/ref-changelog.md:203 ../../source/ref-changelog.md:261 -msgid "" -"We would like to give our special thanks to all the contributors who made" -" the new version of Flower possible (in `git shortlog` order):" -msgstr "" - -#: ../../source/ref-changelog.md:57 +#: ../../source/ref-changelog.md:208 msgid "" "`Adam Narozniak`, `Anass Anhari`, `Charles Beauville`, `Dana-Farber`, " "`Daniel J. Beutel`, `Daniel Nata Nugraha`, `Edoardo Gabrielli`, `Gustavo " @@ -6032,7 +11385,7 @@ msgid "" "TOKEN_v1.5.0-->" msgstr "" -#: ../../source/ref-changelog.md:61 +#: ../../source/ref-changelog.md:212 msgid "" "**Introduce new simulation engine** " "([#1969](https://github.com/adap/flower/pull/1969), " @@ -6040,7 +11393,7 @@ msgid "" "[#2248](https://github.com/adap/flower/pull/2248))" msgstr "" -#: ../../source/ref-changelog.md:63 +#: ../../source/ref-changelog.md:214 msgid "" "The new simulation engine has been rewritten from the ground up, yet it " "remains fully backwards compatible. It offers much improved stability and" @@ -6049,7 +11402,7 @@ msgid "" "only, CPU+GPU, multi-GPU, or multi-node multi-GPU environments." msgstr "" -#: ../../source/ref-changelog.md:65 +#: ../../source/ref-changelog.md:216 msgid "" "Comprehensive documentation includes a new [how-to run " "simulations](https://flower.dev/docs/framework/how-to-run-" @@ -6060,7 +11413,7 @@ msgid "" "series](https://www.youtube.com/watch?v=cRebUIGB5RU&list=PLNG4feLHqCWlnj8a_E1A_n5zr2-8pafTB)." msgstr "" -#: ../../source/ref-changelog.md:67 +#: ../../source/ref-changelog.md:218 msgid "" "**Restructure Flower Docs** " "([#1824](https://github.com/adap/flower/pull/1824), " @@ -6092,7 +11445,7 @@ msgid "" "[#2227](https://github.com/adap/flower/pull/2227))" msgstr "" -#: ../../source/ref-changelog.md:69 +#: ../../source/ref-changelog.md:220 msgid "" "Much effort went into a completely restructured Flower docs experience. " "The documentation on [flower.dev/docs](flower.dev/docs) is now divided " @@ -6100,34 +11453,34 @@ msgid "" "SDK, and code example projects." msgstr "" -#: ../../source/ref-changelog.md:71 +#: ../../source/ref-changelog.md:222 msgid "" "**Introduce Flower Swift SDK** " "([#1858](https://github.com/adap/flower/pull/1858), " "[#1897](https://github.com/adap/flower/pull/1897))" msgstr "" -#: ../../source/ref-changelog.md:73 +#: ../../source/ref-changelog.md:224 msgid "" "This is the first preview release of the Flower Swift SDK. Flower support" " on iOS is improving, and alongside the Swift SDK and code example, there" " is now also an iOS quickstart tutorial." msgstr "" -#: ../../source/ref-changelog.md:75 +#: ../../source/ref-changelog.md:226 msgid "" "**Introduce Flower Android SDK** " "([#2131](https://github.com/adap/flower/pull/2131))" msgstr "" -#: ../../source/ref-changelog.md:77 +#: ../../source/ref-changelog.md:228 msgid "" "This is the first preview release of the Flower Kotlin SDK. Flower " "support on Android is improving, and alongside the Kotlin SDK and code " "example, there is now also an Android quickstart tutorial." msgstr "" -#: ../../source/ref-changelog.md:79 +#: ../../source/ref-changelog.md:230 msgid "" "**Introduce new end-to-end testing infrastructure** " "([#1842](https://github.com/adap/flower/pull/1842), " @@ -6149,42 +11502,42 @@ msgid "" "[#2165](https://github.com/adap/flower/pull/2165))" msgstr "" -#: ../../source/ref-changelog.md:81 +#: ../../source/ref-changelog.md:232 msgid "" "A new testing infrastructure ensures that new changes stay compatible " "with existing framework integrations or strategies." msgstr "" -#: ../../source/ref-changelog.md:83 +#: ../../source/ref-changelog.md:234 msgid "**Deprecate Python 3.7**" msgstr "" -#: ../../source/ref-changelog.md:85 +#: ../../source/ref-changelog.md:236 msgid "" "Since Python 3.7 reached its end of life (EOL) on 2023-06-27, support for" " Python 3.7 is now deprecated and will be removed in an upcoming release." msgstr "" -#: ../../source/ref-changelog.md:87 +#: ../../source/ref-changelog.md:238 msgid "" "**Add new** `FedTrimmedAvg` **strategy** " "([#1769](https://github.com/adap/flower/pull/1769), " "[#1853](https://github.com/adap/flower/pull/1853))" msgstr "" -#: ../../source/ref-changelog.md:89 +#: ../../source/ref-changelog.md:240 msgid "" "The new `FedTrimmedAvg` strategy implements Trimmed Mean by [Dong Yin, " "2018](https://arxiv.org/abs/1803.01498)." msgstr "" -#: ../../source/ref-changelog.md:91 +#: ../../source/ref-changelog.md:242 msgid "" "**Introduce start_driver** " "([#1697](https://github.com/adap/flower/pull/1697))" msgstr "" -#: ../../source/ref-changelog.md:93 +#: ../../source/ref-changelog.md:244 msgid "" "In addition to `start_server` and using the raw Driver API, there is a " "new `start_driver` function that allows for running `start_server` " @@ -6193,13 +11546,13 @@ msgid "" "`start_driver`." msgstr "" -#: ../../source/ref-changelog.md:95 +#: ../../source/ref-changelog.md:246 msgid "" "**Add parameter aggregation to** `mt-pytorch` **code example** " "([#1785](https://github.com/adap/flower/pull/1785))" msgstr "" -#: ../../source/ref-changelog.md:97 +#: ../../source/ref-changelog.md:248 msgid "" "The `mt-pytorch` example shows how to aggregate parameters when writing a" " driver script. The included `driver.py` and `server.py` have been " @@ -6207,53 +11560,53 @@ msgid "" "building server-side logic." msgstr "" -#: ../../source/ref-changelog.md:99 +#: ../../source/ref-changelog.md:250 msgid "" "**Migrate experimental REST API to Starlette** " "([2171](https://github.com/adap/flower/pull/2171))" msgstr "" -#: ../../source/ref-changelog.md:101 +#: ../../source/ref-changelog.md:252 msgid "" "The (experimental) REST API used to be implemented in " "[FastAPI](https://fastapi.tiangolo.com/), but it has now been migrated to" " use [Starlette](https://www.starlette.io/) directly." msgstr "" -#: ../../source/ref-changelog.md:103 +#: ../../source/ref-changelog.md:254 msgid "" "Please note: The REST request-response API is still experimental and will" " likely change significantly over time." msgstr "" -#: ../../source/ref-changelog.md:105 +#: ../../source/ref-changelog.md:256 msgid "" "**Introduce experimental gRPC request-response API** " "([#1867](https://github.com/adap/flower/pull/1867), " "[#1901](https://github.com/adap/flower/pull/1901))" msgstr "" -#: ../../source/ref-changelog.md:107 +#: ../../source/ref-changelog.md:258 msgid "" "In addition to the existing gRPC API (based on bidirectional streaming) " "and the experimental REST API, there is now a new gRPC API that uses a " "request-response model to communicate with client nodes." msgstr "" -#: ../../source/ref-changelog.md:109 +#: ../../source/ref-changelog.md:260 msgid "" "Please note: The gRPC request-response API is still experimental and will" " likely change significantly over time." msgstr "" -#: ../../source/ref-changelog.md:111 +#: ../../source/ref-changelog.md:262 msgid "" "**Replace the experimental** `start_client(rest=True)` **with the new** " "`start_client(transport=\"rest\")` " "([#1880](https://github.com/adap/flower/pull/1880))" msgstr "" -#: ../../source/ref-changelog.md:113 +#: ../../source/ref-changelog.md:264 msgid "" "The (experimental) `start_client` argument `rest` was deprecated in " "favour of a new argument `transport`. `start_client(transport=\"rest\")` " @@ -6262,30 +11615,30 @@ msgid "" "argument `rest` will be removed in a future release." msgstr "" -#: ../../source/ref-changelog.md:115 +#: ../../source/ref-changelog.md:266 msgid "" "**Add a new gRPC option** " "([#2197](https://github.com/adap/flower/pull/2197))" msgstr "" -#: ../../source/ref-changelog.md:117 +#: ../../source/ref-changelog.md:268 msgid "" "We now start a gRPC server with the `grpc.keepalive_permit_without_calls`" " option set to 0 by default. This prevents the clients from sending " "keepalive pings when there is no outstanding stream." msgstr "" -#: ../../source/ref-changelog.md:119 +#: ../../source/ref-changelog.md:270 msgid "" "**Improve example notebooks** " "([#2005](https://github.com/adap/flower/pull/2005))" msgstr "" -#: ../../source/ref-changelog.md:121 +#: ../../source/ref-changelog.md:272 msgid "There's a new 30min Federated Learning PyTorch tutorial!" msgstr "" -#: ../../source/ref-changelog.md:123 +#: ../../source/ref-changelog.md:274 msgid "" "**Example updates** ([#1772](https://github.com/adap/flower/pull/1772), " "[#1873](https://github.com/adap/flower/pull/1873), " @@ -6300,7 +11653,7 @@ msgid "" "[#2183](https://github.com/adap/flower/pull/2183))" msgstr "" -#: ../../source/ref-changelog.md:125 +#: ../../source/ref-changelog.md:276 msgid "" "Many examples have received significant updates, including simplified " "advanced-tensorflow and advanced-pytorch examples, improved macOS " @@ -6309,7 +11662,7 @@ msgid "" "(in addition to `pyproject.toml`)." msgstr "" -#: ../../source/ref-changelog.md:127 +#: ../../source/ref-changelog.md:278 msgid "" "**General improvements** " "([#1872](https://github.com/adap/flower/pull/1872), " @@ -6320,17 +11673,17 @@ msgid "" "[#2171](https://github.com/adap/flower/pull/2171))" msgstr "" -#: ../../source/ref-changelog.md:133 ../../source/ref-changelog.md:197 -#: ../../source/ref-changelog.md:255 ../../source/ref-changelog.md:324 -#: ../../source/ref-changelog.md:386 +#: ../../source/ref-changelog.md:284 ../../source/ref-changelog.md:348 +#: ../../source/ref-changelog.md:406 ../../source/ref-changelog.md:475 +#: ../../source/ref-changelog.md:537 msgid "None" msgstr "" -#: ../../source/ref-changelog.md:135 +#: ../../source/ref-changelog.md:286 msgid "v1.4.0 (2023-04-21)" msgstr "" -#: ../../source/ref-changelog.md:141 +#: ../../source/ref-changelog.md:292 msgid "" "`Adam Narozniak`, `Alexander Viala Bellander`, `Charles Beauville`, " "`Chenyang Ma (Danny)`, `Daniel J. Beutel`, `Edoardo`, `Gautam Jajoo`, " @@ -6340,7 +11693,7 @@ msgid "" "`Steve Laskaridis`, `Steven Hé (Sīchàng)`, `Taner Topal`" msgstr "" -#: ../../source/ref-changelog.md:145 +#: ../../source/ref-changelog.md:296 msgid "" "**Introduce support for XGBoost (**`FedXgbNnAvg` **strategy and " "example)** ([#1694](https://github.com/adap/flower/pull/1694), " @@ -6351,7 +11704,7 @@ msgid "" "[#1795](https://github.com/adap/flower/pull/1795))" msgstr "" -#: ../../source/ref-changelog.md:147 +#: ../../source/ref-changelog.md:298 msgid "" "XGBoost is a tree-based ensemble machine learning algorithm that uses " "gradient boosting to improve model accuracy. We added a new `FedXgbNnAvg`" @@ -6362,14 +11715,14 @@ msgid "" " that demonstrates the usage of this new strategy in an XGBoost project." msgstr "" -#: ../../source/ref-changelog.md:149 +#: ../../source/ref-changelog.md:300 msgid "" "**Introduce iOS SDK (preview)** " "([#1621](https://github.com/adap/flower/pull/1621), " "[#1764](https://github.com/adap/flower/pull/1764))" msgstr "" -#: ../../source/ref-changelog.md:151 +#: ../../source/ref-changelog.md:302 msgid "" "This is a major update for anyone wanting to implement Federated Learning" " on iOS mobile devices. We now have a swift iOS SDK present under " @@ -6380,14 +11733,14 @@ msgid "" "been updated!" msgstr "" -#: ../../source/ref-changelog.md:153 +#: ../../source/ref-changelog.md:304 msgid "" "**Introduce new \"What is Federated Learning?\" tutorial** " "([#1657](https://github.com/adap/flower/pull/1657), " "[#1721](https://github.com/adap/flower/pull/1721))" msgstr "" -#: ../../source/ref-changelog.md:155 +#: ../../source/ref-changelog.md:306 msgid "" "A new [entry-level tutorial](https://flower.dev/docs/framework/tutorial-" "what-is-federated-learning.html) in our documentation explains the basics" @@ -6396,7 +11749,7 @@ msgid "" "interested in Federated Learning!" msgstr "" -#: ../../source/ref-changelog.md:157 +#: ../../source/ref-changelog.md:308 msgid "" "**Introduce new Flower Baseline: FedProx MNIST** " "([#1513](https://github.com/adap/flower/pull/1513), " @@ -6405,7 +11758,7 @@ msgid "" "[#1679](https://github.com/adap/flower/pull/1679))" msgstr "" -#: ../../source/ref-changelog.md:159 +#: ../../source/ref-changelog.md:310 msgid "" "This new baseline replicates the MNIST+CNN task from the paper [Federated" " Optimization in Heterogeneous Networks (Li et al., " @@ -6413,13 +11766,13 @@ msgid "" " which aims at making convergence more robust in heterogenous settings." msgstr "" -#: ../../source/ref-changelog.md:161 +#: ../../source/ref-changelog.md:312 msgid "" "**Introduce new Flower Baseline: FedAvg FEMNIST** " "([#1655](https://github.com/adap/flower/pull/1655))" msgstr "" -#: ../../source/ref-changelog.md:163 +#: ../../source/ref-changelog.md:314 msgid "" "This new baseline replicates an experiment evaluating the performance of " "the FedAvg algorithm on the FEMNIST dataset from the paper [LEAF: A " @@ -6427,7 +11780,7 @@ msgid "" "2018)](https://arxiv.org/abs/1812.01097)." msgstr "" -#: ../../source/ref-changelog.md:165 +#: ../../source/ref-changelog.md:316 msgid "" "**Introduce (experimental) REST API** " "([#1594](https://github.com/adap/flower/pull/1594), " @@ -6439,20 +11792,20 @@ msgid "" "[#1733](https://github.com/adap/flower/pull/1733))" msgstr "" -#: ../../source/ref-changelog.md:167 +#: ../../source/ref-changelog.md:318 msgid "" "A new REST API has been introduced as an alternative to the gRPC-based " "communication stack. In this initial version, the REST API only supports " "anonymous clients." msgstr "" -#: ../../source/ref-changelog.md:169 +#: ../../source/ref-changelog.md:320 msgid "" "Please note: The REST API is still experimental and will likely change " "significantly over time." msgstr "" -#: ../../source/ref-changelog.md:171 +#: ../../source/ref-changelog.md:322 msgid "" "**Improve the (experimental) Driver API** " "([#1663](https://github.com/adap/flower/pull/1663), " @@ -6466,7 +11819,7 @@ msgid "" "[#1794](https://github.com/adap/flower/pull/1794))" msgstr "" -#: ../../source/ref-changelog.md:173 +#: ../../source/ref-changelog.md:324 msgid "" "The Driver API is still an experimental feature, but this release " "introduces some major upgrades. One of the main improvements is the " @@ -6476,58 +11829,58 @@ msgid "" "improves the memory efficiency of a long-running Flower server." msgstr "" -#: ../../source/ref-changelog.md:175 +#: ../../source/ref-changelog.md:326 msgid "" "**Fix spilling issues related to Ray during simulations** " "([#1698](https://github.com/adap/flower/pull/1698))" msgstr "" -#: ../../source/ref-changelog.md:177 +#: ../../source/ref-changelog.md:328 msgid "" "While running long simulations, `ray` was sometimes spilling huge amounts" " of data that would make the training unable to continue. This is now " "fixed! 🎉" msgstr "" -#: ../../source/ref-changelog.md:179 +#: ../../source/ref-changelog.md:330 msgid "" "**Add new example using** `TabNet` **and Flower** " "([#1725](https://github.com/adap/flower/pull/1725))" msgstr "" -#: ../../source/ref-changelog.md:181 +#: ../../source/ref-changelog.md:332 msgid "" "TabNet is a powerful and flexible framework for training machine learning" " models on tabular data. We now have a federated example using Flower: " "[https://github.com/adap/flower/tree/main/examples/tabnet](https://github.com/adap/flower/tree/main/examples/quickstart_tabnet)." msgstr "" -#: ../../source/ref-changelog.md:183 +#: ../../source/ref-changelog.md:334 msgid "" "**Add new how-to guide for monitoring simulations** " "([#1649](https://github.com/adap/flower/pull/1649))" msgstr "" -#: ../../source/ref-changelog.md:185 +#: ../../source/ref-changelog.md:336 msgid "" "We now have a documentation guide to help users monitor their performance" " during simulations." msgstr "" -#: ../../source/ref-changelog.md:187 +#: ../../source/ref-changelog.md:338 msgid "" "**Add training metrics to** `History` **object during simulations** " "([#1696](https://github.com/adap/flower/pull/1696))" msgstr "" -#: ../../source/ref-changelog.md:189 +#: ../../source/ref-changelog.md:340 msgid "" "The `fit_metrics_aggregation_fn` can be used to aggregate training " "metrics, but previous releases did not save the results in the `History` " "object. This is now the case!" msgstr "" -#: ../../source/ref-changelog.md:191 +#: ../../source/ref-changelog.md:342 msgid "" "**General improvements** " "([#1659](https://github.com/adap/flower/pull/1659), " @@ -6581,23 +11934,23 @@ msgid "" "[#1805](https://github.com/adap/flower/pull/1805))" msgstr "" -#: ../../source/ref-changelog.md:199 +#: ../../source/ref-changelog.md:350 msgid "v1.3.0 (2023-02-06)" msgstr "" -#: ../../source/ref-changelog.md:205 +#: ../../source/ref-changelog.md:356 msgid "" "`Adam Narozniak`, `Alexander Viala Bellander`, `Charles Beauville`, " "`Daniel J. Beutel`, `JDRanpariya`, `Lennart Behme`, `Taner Topal`" msgstr "" -#: ../../source/ref-changelog.md:209 +#: ../../source/ref-changelog.md:360 msgid "" "**Add support for** `workload_id` **and** `group_id` **in Driver API** " "([#1595](https://github.com/adap/flower/pull/1595))" msgstr "" -#: ../../source/ref-changelog.md:211 +#: ../../source/ref-changelog.md:362 msgid "" "The (experimental) Driver API now supports a `workload_id` that can be " "used to identify which workload a task belongs to. It also supports a new" @@ -6606,50 +11959,50 @@ msgid "" " to decide whether they want to handle a task or not." msgstr "" -#: ../../source/ref-changelog.md:213 +#: ../../source/ref-changelog.md:364 msgid "" "**Make Driver API and Fleet API address configurable** " "([#1637](https://github.com/adap/flower/pull/1637))" msgstr "" -#: ../../source/ref-changelog.md:215 +#: ../../source/ref-changelog.md:366 msgid "" "The (experimental) long-running Flower server (Driver API and Fleet API) " "can now configure the server address of both Driver API (via `--driver-" "api-address`) and Fleet API (via `--fleet-api-address`) when starting:" msgstr "" -#: ../../source/ref-changelog.md:217 +#: ../../source/ref-changelog.md:368 msgid "" -"`flower-superlink --driver-api-address \"0.0.0.0:8081\" --fleet-api-address " +"`flower-server --driver-api-address \"0.0.0.0:8081\" --fleet-api-address " "\"0.0.0.0:8086\"`" msgstr "" -#: ../../source/ref-changelog.md:219 +#: ../../source/ref-changelog.md:370 msgid "Both IPv4 and IPv6 addresses are supported." msgstr "" -#: ../../source/ref-changelog.md:221 +#: ../../source/ref-changelog.md:372 msgid "" "**Add new example of Federated Learning using fastai and Flower** " "([#1598](https://github.com/adap/flower/pull/1598))" msgstr "" -#: ../../source/ref-changelog.md:223 +#: ../../source/ref-changelog.md:374 msgid "" "A new code example (`quickstart_fastai`) demonstrates federated learning " "with [fastai](https://www.fast.ai/) and Flower. You can find it here: " "[quickstart_fastai](https://github.com/adap/flower/tree/main/examples/quickstart_fastai)." msgstr "" -#: ../../source/ref-changelog.md:225 +#: ../../source/ref-changelog.md:376 msgid "" "**Make Android example compatible with** `flwr >= 1.0.0` **and the latest" " versions of Android** " "([#1603](https://github.com/adap/flower/pull/1603))" msgstr "" -#: ../../source/ref-changelog.md:227 +#: ../../source/ref-changelog.md:378 msgid "" "The Android code example has received a substantial update: the project " "is compatible with Flower 1.0 (and later), the UI received a full " @@ -6657,13 +12010,13 @@ msgid "" "tooling." msgstr "" -#: ../../source/ref-changelog.md:229 +#: ../../source/ref-changelog.md:380 msgid "" "**Add new `FedProx` strategy** " "([#1619](https://github.com/adap/flower/pull/1619))" msgstr "" -#: ../../source/ref-changelog.md:231 +#: ../../source/ref-changelog.md:382 msgid "" "This " "[strategy](https://github.com/adap/flower/blob/main/src/py/flwr/server/strategy/fedprox.py)" @@ -6675,25 +12028,25 @@ msgid "" "respect to the global models." msgstr "" -#: ../../source/ref-changelog.md:233 +#: ../../source/ref-changelog.md:384 msgid "" "**Add new metrics to telemetry events** " "([#1640](https://github.com/adap/flower/pull/1640))" msgstr "" -#: ../../source/ref-changelog.md:235 +#: ../../source/ref-changelog.md:386 msgid "" "An updated event structure allows, for example, the clustering of events " "within the same workload." msgstr "" -#: ../../source/ref-changelog.md:237 +#: ../../source/ref-changelog.md:388 msgid "" "**Add new custom strategy tutorial section** " "[#1623](https://github.com/adap/flower/pull/1623)" msgstr "" -#: ../../source/ref-changelog.md:239 +#: ../../source/ref-changelog.md:390 msgid "" "The Flower tutorial now has a new section that covers implementing a " "custom strategy from scratch: [Open in " @@ -6701,13 +12054,13 @@ msgid "" "/tutorial-build-a-strategy-from-scratch-pytorch.ipynb)" msgstr "" -#: ../../source/ref-changelog.md:241 +#: ../../source/ref-changelog.md:392 msgid "" "**Add new custom serialization tutorial section** " "([#1622](https://github.com/adap/flower/pull/1622))" msgstr "" -#: ../../source/ref-changelog.md:243 +#: ../../source/ref-changelog.md:394 msgid "" "The Flower tutorial now has a new section that covers custom " "serialization: [Open in " @@ -6715,7 +12068,7 @@ msgid "" "/tutorial-customize-the-client-pytorch.ipynb)" msgstr "" -#: ../../source/ref-changelog.md:245 +#: ../../source/ref-changelog.md:396 msgid "" "**General improvements** " "([#1638](https://github.com/adap/flower/pull/1638), " @@ -6753,7 +12106,7 @@ msgid "" "[#1586](https://github.com/adap/flower/pull/1586))" msgstr "" -#: ../../source/ref-changelog.md:249 +#: ../../source/ref-changelog.md:400 msgid "" "**Updated documentation** " "([#1629](https://github.com/adap/flower/pull/1629), " @@ -6765,31 +12118,31 @@ msgid "" "[#1614](https://github.com/adap/flower/pull/1614))" msgstr "" -#: ../../source/ref-changelog.md:251 ../../source/ref-changelog.md:318 +#: ../../source/ref-changelog.md:402 ../../source/ref-changelog.md:469 msgid "" "As usual, the documentation has improved quite a bit. It is another step " "in our effort to make the Flower documentation the best documentation of " "any project. Stay tuned and as always, feel free to provide feedback!" msgstr "" -#: ../../source/ref-changelog.md:257 +#: ../../source/ref-changelog.md:408 msgid "v1.2.0 (2023-01-13)" msgstr "" -#: ../../source/ref-changelog.md:263 +#: ../../source/ref-changelog.md:414 msgid "" "`Adam Narozniak`, `Charles Beauville`, `Daniel J. Beutel`, `Edoardo`, `L." " Jiang`, `Ragy`, `Taner Topal`, `dannymcy`" msgstr "" -#: ../../source/ref-changelog.md:267 +#: ../../source/ref-changelog.md:418 msgid "" "**Introduce new Flower Baseline: FedAvg MNIST** " "([#1497](https://github.com/adap/flower/pull/1497), " "[#1552](https://github.com/adap/flower/pull/1552))" msgstr "" -#: ../../source/ref-changelog.md:269 +#: ../../source/ref-changelog.md:420 msgid "" "Over the coming weeks, we will be releasing a number of new reference " "implementations useful especially to FL newcomers. They will typically " @@ -6800,13 +12153,13 @@ msgid "" "pack-fedavg-mnist-cnn/)" msgstr "" -#: ../../source/ref-changelog.md:271 +#: ../../source/ref-changelog.md:422 msgid "" "**Improve GPU support in simulations** " "([#1555](https://github.com/adap/flower/pull/1555))" msgstr "" -#: ../../source/ref-changelog.md:273 +#: ../../source/ref-changelog.md:424 msgid "" "The Ray-based Virtual Client Engine (`start_simulation`) has been updated" " to improve GPU support. The update includes some of the hard-earned " @@ -6814,45 +12167,45 @@ msgid "" "defaults make running GPU-based simulations substantially more robust." msgstr "" -#: ../../source/ref-changelog.md:275 +#: ../../source/ref-changelog.md:426 msgid "" "**Improve GPU support in Jupyter Notebook tutorials** " "([#1527](https://github.com/adap/flower/pull/1527), " "[#1558](https://github.com/adap/flower/pull/1558))" msgstr "" -#: ../../source/ref-changelog.md:277 +#: ../../source/ref-changelog.md:428 msgid "" "Some users reported that Jupyter Notebooks have not always been easy to " "use on GPU instances. We listened and made improvements to all of our " "Jupyter notebooks! Check out the updated notebooks here:" msgstr "" -#: ../../source/ref-changelog.md:279 +#: ../../source/ref-changelog.md:430 msgid "" "[An Introduction to Federated Learning](https://flower.dev/docs/framework" "/tutorial-get-started-with-flower-pytorch.html)" msgstr "" -#: ../../source/ref-changelog.md:280 +#: ../../source/ref-changelog.md:431 msgid "" "[Strategies in Federated Learning](https://flower.dev/docs/framework" "/tutorial-use-a-federated-learning-strategy-pytorch.html)" msgstr "" -#: ../../source/ref-changelog.md:281 +#: ../../source/ref-changelog.md:432 msgid "" "[Building a Strategy](https://flower.dev/docs/framework/tutorial-build-a" "-strategy-from-scratch-pytorch.html)" msgstr "" -#: ../../source/ref-changelog.md:282 +#: ../../source/ref-changelog.md:433 msgid "" "[Client and NumPyClient](https://flower.dev/docs/framework/tutorial-" "customize-the-client-pytorch.html)" msgstr "" -#: ../../source/ref-changelog.md:284 +#: ../../source/ref-changelog.md:435 msgid "" "**Introduce optional telemetry** " "([#1533](https://github.com/adap/flower/pull/1533), " @@ -6860,7 +12213,7 @@ msgid "" "[#1584](https://github.com/adap/flower/pull/1584))" msgstr "" -#: ../../source/ref-changelog.md:286 +#: ../../source/ref-changelog.md:437 msgid "" "After a [request for " "feedback](https://github.com/adap/flower/issues/1534) from the community," @@ -6870,7 +12223,7 @@ msgid "" "used and what challenges users might face." msgstr "" -#: ../../source/ref-changelog.md:288 +#: ../../source/ref-changelog.md:439 msgid "" "**Flower is a friendly framework for collaborative AI and data science.**" " Staying true to this statement, Flower makes it easy to disable " @@ -6878,7 +12231,7 @@ msgid "" "[Read more.](https://flower.dev/docs/telemetry.html)." msgstr "" -#: ../../source/ref-changelog.md:290 +#: ../../source/ref-changelog.md:441 msgid "" "**Introduce (experimental) Driver API** " "([#1520](https://github.com/adap/flower/pull/1520), " @@ -6890,7 +12243,7 @@ msgid "" "[#1567](https://github.com/adap/flower/pull/1567))" msgstr "" -#: ../../source/ref-changelog.md:292 +#: ../../source/ref-changelog.md:443 msgid "" "Flower now has a new (experimental) Driver API which will enable fully " "programmable, async, and multi-tenant Federated Learning and Federated " @@ -6899,7 +12252,7 @@ msgid "" "and you can start building those things now, too." msgstr "" -#: ../../source/ref-changelog.md:294 +#: ../../source/ref-changelog.md:445 msgid "" "The Driver API also enables a new execution mode in which the server runs" " indefinitely. Multiple individual workloads can run concurrently and " @@ -6907,58 +12260,58 @@ msgid "" "especially useful for users who want to deploy Flower in production." msgstr "" -#: ../../source/ref-changelog.md:296 +#: ../../source/ref-changelog.md:447 msgid "" "To learn more, check out the `mt-pytorch` code example. We look forward " "to you feedback!" msgstr "" -#: ../../source/ref-changelog.md:298 +#: ../../source/ref-changelog.md:449 msgid "" "Please note: *The Driver API is still experimental and will likely change" " significantly over time.*" msgstr "" -#: ../../source/ref-changelog.md:300 +#: ../../source/ref-changelog.md:451 msgid "" "**Add new Federated Analytics with Pandas example** " "([#1469](https://github.com/adap/flower/pull/1469), " "[#1535](https://github.com/adap/flower/pull/1535))" msgstr "" -#: ../../source/ref-changelog.md:302 +#: ../../source/ref-changelog.md:453 msgid "" "A new code example (`quickstart_pandas`) demonstrates federated analytics" " with Pandas and Flower. You can find it here: " "[quickstart_pandas](https://github.com/adap/flower/tree/main/examples/quickstart_pandas)." msgstr "" -#: ../../source/ref-changelog.md:304 +#: ../../source/ref-changelog.md:455 msgid "" "**Add new strategies: Krum and MultiKrum** " "([#1481](https://github.com/adap/flower/pull/1481))" msgstr "" -#: ../../source/ref-changelog.md:306 +#: ../../source/ref-changelog.md:457 msgid "" "Edoardo, a computer science student at the Sapienza University of Rome, " "contributed a new `Krum` strategy that enables users to easily use Krum " "and MultiKrum in their workloads." msgstr "" -#: ../../source/ref-changelog.md:308 +#: ../../source/ref-changelog.md:459 msgid "" "**Update C++ example to be compatible with Flower v1.2.0** " "([#1495](https://github.com/adap/flower/pull/1495))" msgstr "" -#: ../../source/ref-changelog.md:310 +#: ../../source/ref-changelog.md:461 msgid "" "The C++ code example has received a substantial update to make it " "compatible with the latest version of Flower." msgstr "" -#: ../../source/ref-changelog.md:312 +#: ../../source/ref-changelog.md:463 msgid "" "**General improvements** " "([#1491](https://github.com/adap/flower/pull/1491), " @@ -6976,7 +12329,7 @@ msgid "" "[#1566](https://github.com/adap/flower/pull/1566))" msgstr "" -#: ../../source/ref-changelog.md:316 +#: ../../source/ref-changelog.md:467 msgid "" "**Updated documentation** " "([#1494](https://github.com/adap/flower/pull/1494), " @@ -6990,24 +12343,24 @@ msgid "" "[#1515](https://github.com/adap/flower/pull/1515))" msgstr "" -#: ../../source/ref-changelog.md:320 +#: ../../source/ref-changelog.md:471 msgid "" "One highlight is the new [first time contributor " "guide](https://flower.dev/docs/first-time-contributors.html): if you've " "never contributed on GitHub before, this is the perfect place to start!" msgstr "" -#: ../../source/ref-changelog.md:326 +#: ../../source/ref-changelog.md:477 msgid "v1.1.0 (2022-10-31)" msgstr "" -#: ../../source/ref-changelog.md:330 +#: ../../source/ref-changelog.md:481 msgid "" "We would like to give our **special thanks** to all the contributors who " "made the new version of Flower possible (in `git shortlog` order):" msgstr "" -#: ../../source/ref-changelog.md:332 +#: ../../source/ref-changelog.md:483 msgid "" "`Akis Linardos`, `Christopher S`, `Daniel J. Beutel`, `George`, `Jan " "Schlicht`, `Mohammad Fares`, `Pedro Porto Buarque de Gusmão`, `Philipp " @@ -7015,14 +12368,14 @@ msgid "" "`danielnugraha`, `edogab33`" msgstr "" -#: ../../source/ref-changelog.md:336 +#: ../../source/ref-changelog.md:487 msgid "" "**Introduce Differential Privacy wrappers (preview)** " "([#1357](https://github.com/adap/flower/pull/1357), " "[#1460](https://github.com/adap/flower/pull/1460))" msgstr "" -#: ../../source/ref-changelog.md:338 +#: ../../source/ref-changelog.md:489 msgid "" "The first (experimental) preview of pluggable Differential Privacy " "wrappers enables easy configuration and usage of differential privacy " @@ -7031,13 +12384,13 @@ msgid "" "over to the Flower docs, a new explainer goes into more detail." msgstr "" -#: ../../source/ref-changelog.md:340 +#: ../../source/ref-changelog.md:491 msgid "" "**New iOS CoreML code example** " "([#1289](https://github.com/adap/flower/pull/1289))" msgstr "" -#: ../../source/ref-changelog.md:342 +#: ../../source/ref-changelog.md:493 msgid "" "Flower goes iOS! A massive new code example shows how Flower clients can " "be built for iOS. The code example contains both Flower iOS SDK " @@ -7045,39 +12398,39 @@ msgid "" "on CoreML." msgstr "" -#: ../../source/ref-changelog.md:344 +#: ../../source/ref-changelog.md:495 msgid "" "**New FedMedian strategy** " "([#1461](https://github.com/adap/flower/pull/1461))" msgstr "" -#: ../../source/ref-changelog.md:346 +#: ../../source/ref-changelog.md:497 msgid "" "The new `FedMedian` strategy implements Federated Median (FedMedian) by " "[Yin et al., 2018](https://arxiv.org/pdf/1803.01498v1.pdf)." msgstr "" -#: ../../source/ref-changelog.md:348 +#: ../../source/ref-changelog.md:499 msgid "" "**Log** `Client` **exceptions in Virtual Client Engine** " "([#1493](https://github.com/adap/flower/pull/1493))" msgstr "" -#: ../../source/ref-changelog.md:350 +#: ../../source/ref-changelog.md:501 msgid "" "All `Client` exceptions happening in the VCE are now logged by default " "and not just exposed to the configured `Strategy` (via the `failures` " "argument)." msgstr "" -#: ../../source/ref-changelog.md:352 +#: ../../source/ref-changelog.md:503 msgid "" "**Improve Virtual Client Engine internals** " "([#1401](https://github.com/adap/flower/pull/1401), " "[#1453](https://github.com/adap/flower/pull/1453))" msgstr "" -#: ../../source/ref-changelog.md:354 +#: ../../source/ref-changelog.md:505 msgid "" "Some internals of the Virtual Client Engine have been revamped. The VCE " "now uses Ray 2.0 under the hood, the value type of the `client_resources`" @@ -7085,25 +12438,25 @@ msgid "" "allocated." msgstr "" -#: ../../source/ref-changelog.md:356 +#: ../../source/ref-changelog.md:507 msgid "" "**Support optional** `Client`**/**`NumPyClient` **methods in Virtual " "Client Engine**" msgstr "" -#: ../../source/ref-changelog.md:358 +#: ../../source/ref-changelog.md:509 msgid "" "The Virtual Client Engine now has full support for optional `Client` (and" " `NumPyClient`) methods." msgstr "" -#: ../../source/ref-changelog.md:360 +#: ../../source/ref-changelog.md:511 msgid "" "**Provide type information to packages using** `flwr` " "([#1377](https://github.com/adap/flower/pull/1377))" msgstr "" -#: ../../source/ref-changelog.md:362 +#: ../../source/ref-changelog.md:513 msgid "" "The package `flwr` is now bundled with a `py.typed` file indicating that " "the package is typed. This enables typing support for projects or " @@ -7111,20 +12464,20 @@ msgid "" "static type checkers like `mypy`." msgstr "" -#: ../../source/ref-changelog.md:364 +#: ../../source/ref-changelog.md:515 msgid "" "**Updated code example** " "([#1344](https://github.com/adap/flower/pull/1344), " "[#1347](https://github.com/adap/flower/pull/1347))" msgstr "" -#: ../../source/ref-changelog.md:366 +#: ../../source/ref-changelog.md:517 msgid "" "The code examples covering scikit-learn and PyTorch Lightning have been " "updated to work with the latest version of Flower." msgstr "" -#: ../../source/ref-changelog.md:368 +#: ../../source/ref-changelog.md:519 msgid "" "**Updated documentation** " "([#1355](https://github.com/adap/flower/pull/1355), " @@ -7146,32 +12499,32 @@ msgid "" "[#1467](https://github.com/adap/flower/pull/1467))" msgstr "" -#: ../../source/ref-changelog.md:370 +#: ../../source/ref-changelog.md:521 msgid "" "There have been so many documentation updates that it doesn't even make " "sense to list them individually." msgstr "" -#: ../../source/ref-changelog.md:372 +#: ../../source/ref-changelog.md:523 msgid "" "**Restructured documentation** " "([#1387](https://github.com/adap/flower/pull/1387))" msgstr "" -#: ../../source/ref-changelog.md:374 +#: ../../source/ref-changelog.md:525 msgid "" "The documentation has been restructured to make it easier to navigate. " "This is just the first step in a larger effort to make the Flower " "documentation the best documentation of any project ever. Stay tuned!" msgstr "" -#: ../../source/ref-changelog.md:376 +#: ../../source/ref-changelog.md:527 msgid "" "**Open in Colab button** " "([#1389](https://github.com/adap/flower/pull/1389))" msgstr "" -#: ../../source/ref-changelog.md:378 +#: ../../source/ref-changelog.md:529 msgid "" "The four parts of the Flower Federated Learning Tutorial now come with a " "new `Open in Colab` button. No need to install anything on your local " @@ -7179,7 +12532,7 @@ msgid "" "only a single click away." msgstr "" -#: ../../source/ref-changelog.md:380 +#: ../../source/ref-changelog.md:531 msgid "" "**Improved tutorial** ([#1468](https://github.com/adap/flower/pull/1468)," " [#1470](https://github.com/adap/flower/pull/1470), " @@ -7189,7 +12542,7 @@ msgid "" "[#1475](https://github.com/adap/flower/pull/1475))" msgstr "" -#: ../../source/ref-changelog.md:382 +#: ../../source/ref-changelog.md:533 msgid "" "The Flower Federated Learning Tutorial has two brand-new parts covering " "custom strategies (still WIP) and the distinction between `Client` and " @@ -7197,40 +12550,40 @@ msgid "" "(many small changes and fixes)." msgstr "" -#: ../../source/ref-changelog.md:388 +#: ../../source/ref-changelog.md:539 msgid "v1.0.0 (2022-07-28)" msgstr "" -#: ../../source/ref-changelog.md:390 +#: ../../source/ref-changelog.md:541 msgid "Highlights" msgstr "" -#: ../../source/ref-changelog.md:392 +#: ../../source/ref-changelog.md:543 msgid "Stable **Virtual Client Engine** (accessible via `start_simulation`)" msgstr "" -#: ../../source/ref-changelog.md:393 +#: ../../source/ref-changelog.md:544 msgid "All `Client`/`NumPyClient` methods are now optional" msgstr "" -#: ../../source/ref-changelog.md:394 +#: ../../source/ref-changelog.md:545 msgid "Configurable `get_parameters`" msgstr "" -#: ../../source/ref-changelog.md:395 +#: ../../source/ref-changelog.md:546 msgid "" "Tons of small API cleanups resulting in a more coherent developer " "experience" msgstr "" -#: ../../source/ref-changelog.md:399 +#: ../../source/ref-changelog.md:550 msgid "" "We would like to give our **special thanks** to all the contributors who " "made Flower 1.0 possible (in reverse [GitHub " "Contributors](https://github.com/adap/flower/graphs/contributors) order):" msgstr "" -#: ../../source/ref-changelog.md:401 +#: ../../source/ref-changelog.md:552 msgid "" "[@rtaiello](https://github.com/rtaiello), " "[@g-pichler](https://github.com/g-pichler), [@rob-" @@ -7270,13 +12623,13 @@ msgid "" "[@danieljanes](https://github.com/danieljanes)." msgstr "" -#: ../../source/ref-changelog.md:405 +#: ../../source/ref-changelog.md:556 msgid "" "**All arguments must be passed as keyword arguments** " "([#1338](https://github.com/adap/flower/pull/1338))" msgstr "" -#: ../../source/ref-changelog.md:407 +#: ../../source/ref-changelog.md:558 msgid "" "Pass all arguments as keyword arguments, positional arguments are not " "longer supported. Code that uses positional arguments (e.g., " @@ -7286,14 +12639,14 @@ msgid "" "client=FlowerClient())`)." msgstr "" -#: ../../source/ref-changelog.md:409 +#: ../../source/ref-changelog.md:560 msgid "" "**Introduce configuration object** `ServerConfig` **in** `start_server` " "**and** `start_simulation` " "([#1317](https://github.com/adap/flower/pull/1317))" msgstr "" -#: ../../source/ref-changelog.md:411 +#: ../../source/ref-changelog.md:562 msgid "" "Instead of a config dictionary `{\"num_rounds\": 3, \"round_timeout\": " "600.0}`, `start_server` and `start_simulation` now expect a configuration" @@ -7302,37 +12655,37 @@ msgid "" "safe code easier and the default parameters values more transparent." msgstr "" -#: ../../source/ref-changelog.md:413 +#: ../../source/ref-changelog.md:564 msgid "" "**Rename built-in strategy parameters for clarity** " "([#1334](https://github.com/adap/flower/pull/1334))" msgstr "" -#: ../../source/ref-changelog.md:415 +#: ../../source/ref-changelog.md:566 msgid "" "The following built-in strategy parameters were renamed to improve " "readability and consistency with other API's:" msgstr "" -#: ../../source/ref-changelog.md:417 +#: ../../source/ref-changelog.md:568 msgid "`fraction_eval` --> `fraction_evaluate`" msgstr "" -#: ../../source/ref-changelog.md:418 +#: ../../source/ref-changelog.md:569 msgid "`min_eval_clients` --> `min_evaluate_clients`" msgstr "" -#: ../../source/ref-changelog.md:419 +#: ../../source/ref-changelog.md:570 msgid "`eval_fn` --> `evaluate_fn`" msgstr "" -#: ../../source/ref-changelog.md:421 +#: ../../source/ref-changelog.md:572 msgid "" "**Update default arguments of built-in strategies** " "([#1278](https://github.com/adap/flower/pull/1278))" msgstr "" -#: ../../source/ref-changelog.md:423 +#: ../../source/ref-changelog.md:574 msgid "" "All built-in strategies now use `fraction_fit=1.0` and " "`fraction_evaluate=1.0`, which means they select *all* currently " @@ -7341,29 +12694,29 @@ msgid "" "initializing the strategy in the following way:" msgstr "" -#: ../../source/ref-changelog.md:425 +#: ../../source/ref-changelog.md:576 msgid "`strategy = FedAvg(fraction_fit=0.1, fraction_evaluate=0.1)`" msgstr "" -#: ../../source/ref-changelog.md:427 +#: ../../source/ref-changelog.md:578 msgid "" "**Add** `server_round` **to** `Strategy.evaluate` " "([#1334](https://github.com/adap/flower/pull/1334))" msgstr "" -#: ../../source/ref-changelog.md:429 +#: ../../source/ref-changelog.md:580 msgid "" "The `Strategy` method `evaluate` now receives the current round of " "federated learning/evaluation as the first parameter." msgstr "" -#: ../../source/ref-changelog.md:431 +#: ../../source/ref-changelog.md:582 msgid "" "**Add** `server_round` **and** `config` **parameters to** `evaluate_fn` " "([#1334](https://github.com/adap/flower/pull/1334))" msgstr "" -#: ../../source/ref-changelog.md:433 +#: ../../source/ref-changelog.md:584 msgid "" "The `evaluate_fn` passed to built-in strategies like `FedAvg` now takes " "three parameters: (1) The current round of federated learning/evaluation " @@ -7371,13 +12724,13 @@ msgid "" "and (3) a config dictionary (`config`)." msgstr "" -#: ../../source/ref-changelog.md:435 +#: ../../source/ref-changelog.md:586 msgid "" "**Rename** `rnd` **to** `server_round` " "([#1321](https://github.com/adap/flower/pull/1321))" msgstr "" -#: ../../source/ref-changelog.md:437 +#: ../../source/ref-changelog.md:588 msgid "" "Several Flower methods and functions (`evaluate_fn`, `configure_fit`, " "`aggregate_fit`, `configure_evaluate`, `aggregate_evaluate`) receive the " @@ -7386,73 +12739,73 @@ msgid "" "has been renamed from `rnd` to `server_round`." msgstr "" -#: ../../source/ref-changelog.md:439 +#: ../../source/ref-changelog.md:590 msgid "" "**Move** `flwr.dataset` **to** `flwr_baselines` " "([#1273](https://github.com/adap/flower/pull/1273))" msgstr "" -#: ../../source/ref-changelog.md:441 +#: ../../source/ref-changelog.md:592 msgid "The experimental package `flwr.dataset` was migrated to Flower Baselines." msgstr "" -#: ../../source/ref-changelog.md:443 +#: ../../source/ref-changelog.md:594 msgid "" "**Remove experimental strategies** " "([#1280](https://github.com/adap/flower/pull/1280))" msgstr "" -#: ../../source/ref-changelog.md:445 +#: ../../source/ref-changelog.md:596 msgid "" "Remove unmaintained experimental strategies (`FastAndSlow`, `FedFSv0`, " "`FedFSv1`)." msgstr "" -#: ../../source/ref-changelog.md:447 +#: ../../source/ref-changelog.md:598 msgid "" "**Rename** `Weights` **to** `NDArrays` " "([#1258](https://github.com/adap/flower/pull/1258), " "[#1259](https://github.com/adap/flower/pull/1259))" msgstr "" -#: ../../source/ref-changelog.md:449 +#: ../../source/ref-changelog.md:600 msgid "" "`flwr.common.Weights` was renamed to `flwr.common.NDArrays` to better " "capture what this type is all about." msgstr "" -#: ../../source/ref-changelog.md:451 +#: ../../source/ref-changelog.md:602 msgid "" "**Remove antiquated** `force_final_distributed_eval` **from** " "`start_server` ([#1258](https://github.com/adap/flower/pull/1258), " "[#1259](https://github.com/adap/flower/pull/1259))" msgstr "" -#: ../../source/ref-changelog.md:453 +#: ../../source/ref-changelog.md:604 msgid "" "The `start_server` parameter `force_final_distributed_eval` has long been" " a historic artefact, in this release it is finally gone for good." msgstr "" -#: ../../source/ref-changelog.md:455 +#: ../../source/ref-changelog.md:606 msgid "" "**Make** `get_parameters` **configurable** " "([#1242](https://github.com/adap/flower/pull/1242))" msgstr "" -#: ../../source/ref-changelog.md:457 +#: ../../source/ref-changelog.md:608 msgid "" "The `get_parameters` method now accepts a configuration dictionary, just " "like `get_properties`, `fit`, and `evaluate`." msgstr "" -#: ../../source/ref-changelog.md:459 +#: ../../source/ref-changelog.md:610 msgid "" "**Replace** `num_rounds` **in** `start_simulation` **with new** `config` " "**parameter** ([#1281](https://github.com/adap/flower/pull/1281))" msgstr "" -#: ../../source/ref-changelog.md:461 +#: ../../source/ref-changelog.md:612 msgid "" "The `start_simulation` function now accepts a configuration dictionary " "`config` instead of the `num_rounds` integer. This improves the " @@ -7460,26 +12813,26 @@ msgid "" "transitioning between the two easier." msgstr "" -#: ../../source/ref-changelog.md:465 +#: ../../source/ref-changelog.md:616 msgid "" "**Support Python 3.10** " "([#1320](https://github.com/adap/flower/pull/1320))" msgstr "" -#: ../../source/ref-changelog.md:467 +#: ../../source/ref-changelog.md:618 msgid "" "The previous Flower release introduced experimental support for Python " "3.10, this release declares Python 3.10 support as stable." msgstr "" -#: ../../source/ref-changelog.md:469 +#: ../../source/ref-changelog.md:620 msgid "" "**Make all** `Client` **and** `NumPyClient` **methods optional** " "([#1260](https://github.com/adap/flower/pull/1260), " "[#1277](https://github.com/adap/flower/pull/1277))" msgstr "" -#: ../../source/ref-changelog.md:471 +#: ../../source/ref-changelog.md:622 msgid "" "The `Client`/`NumPyClient` methods `get_properties`, `get_parameters`, " "`fit`, and `evaluate` are all optional. This enables writing clients that" @@ -7487,13 +12840,13 @@ msgid "" "implement `evaluate` when using centralized evaluation!" msgstr "" -#: ../../source/ref-changelog.md:473 +#: ../../source/ref-changelog.md:624 msgid "" "**Enable passing a** `Server` **instance to** `start_simulation` " "([#1281](https://github.com/adap/flower/pull/1281))" msgstr "" -#: ../../source/ref-changelog.md:475 +#: ../../source/ref-changelog.md:626 msgid "" "Similar to `start_server`, `start_simulation` now accepts a full `Server`" " instance. This enables users to heavily customize the execution of " @@ -7501,7 +12854,7 @@ msgid "" " Virtual Client Engine." msgstr "" -#: ../../source/ref-changelog.md:477 +#: ../../source/ref-changelog.md:628 msgid "" "**Update code examples** " "([#1291](https://github.com/adap/flower/pull/1291), " @@ -7509,50 +12862,50 @@ msgid "" "[#1282](https://github.com/adap/flower/pull/1282))" msgstr "" -#: ../../source/ref-changelog.md:479 +#: ../../source/ref-changelog.md:630 msgid "" "Many code examples received small or even large maintenance updates, " "among them are" msgstr "" -#: ../../source/ref-changelog.md:481 +#: ../../source/ref-changelog.md:632 msgid "`scikit-learn`" msgstr "" -#: ../../source/ref-changelog.md:482 +#: ../../source/ref-changelog.md:633 msgid "`simulation_pytorch`" msgstr "" -#: ../../source/ref-changelog.md:483 +#: ../../source/ref-changelog.md:634 msgid "`quickstart_pytorch`" msgstr "" -#: ../../source/ref-changelog.md:484 +#: ../../source/ref-changelog.md:635 msgid "`quickstart_simulation`" msgstr "" -#: ../../source/ref-changelog.md:485 +#: ../../source/ref-changelog.md:636 msgid "`quickstart_tensorflow`" msgstr "" -#: ../../source/ref-changelog.md:486 +#: ../../source/ref-changelog.md:637 msgid "`advanced_tensorflow`" msgstr "" -#: ../../source/ref-changelog.md:488 +#: ../../source/ref-changelog.md:639 msgid "" "**Remove the obsolete simulation example** " "([#1328](https://github.com/adap/flower/pull/1328))" msgstr "" -#: ../../source/ref-changelog.md:490 +#: ../../source/ref-changelog.md:641 msgid "" "Removes the obsolete `simulation` example and renames " "`quickstart_simulation` to `simulation_tensorflow` so it fits withs the " "naming of `simulation_pytorch`" msgstr "" -#: ../../source/ref-changelog.md:492 +#: ../../source/ref-changelog.md:643 msgid "" "**Update documentation** " "([#1223](https://github.com/adap/flower/pull/1223), " @@ -7567,7 +12920,7 @@ msgid "" "[#1307](https://github.com/adap/flower/pull/1307))" msgstr "" -#: ../../source/ref-changelog.md:494 +#: ../../source/ref-changelog.md:645 msgid "" "One substantial documentation update fixes multiple smaller rendering " "issues, makes titles more succinct to improve navigation, removes a " @@ -7577,24 +12930,24 @@ msgid "" "fixes a number of smaller details!" msgstr "" -#: ../../source/ref-changelog.md:496 ../../source/ref-changelog.md:551 -#: ../../source/ref-changelog.md:620 ../../source/ref-changelog.md:659 +#: ../../source/ref-changelog.md:647 ../../source/ref-changelog.md:702 +#: ../../source/ref-changelog.md:771 ../../source/ref-changelog.md:810 msgid "**Minor updates**" msgstr "" -#: ../../source/ref-changelog.md:498 +#: ../../source/ref-changelog.md:649 msgid "" "Add round number to fit and evaluate log messages " "([#1266](https://github.com/adap/flower/pull/1266))" msgstr "" -#: ../../source/ref-changelog.md:499 +#: ../../source/ref-changelog.md:650 msgid "" "Add secure gRPC connection to the `advanced_tensorflow` code example " "([#847](https://github.com/adap/flower/pull/847))" msgstr "" -#: ../../source/ref-changelog.md:500 +#: ../../source/ref-changelog.md:651 msgid "" "Update developer tooling " "([#1231](https://github.com/adap/flower/pull/1231), " @@ -7603,7 +12956,7 @@ msgid "" "[#1310](https://github.com/adap/flower/pull/1310))" msgstr "" -#: ../../source/ref-changelog.md:501 +#: ../../source/ref-changelog.md:652 msgid "" "Rename ProtoBuf messages to improve consistency " "([#1214](https://github.com/adap/flower/pull/1214), " @@ -7611,11 +12964,11 @@ msgid "" "[#1259](https://github.com/adap/flower/pull/1259))" msgstr "" -#: ../../source/ref-changelog.md:503 +#: ../../source/ref-changelog.md:654 msgid "v0.19.0 (2022-05-18)" msgstr "" -#: ../../source/ref-changelog.md:507 +#: ../../source/ref-changelog.md:658 msgid "" "**Flower Baselines (preview): FedOpt, FedBN, FedAvgM** " "([#919](https://github.com/adap/flower/pull/919), " @@ -7623,7 +12976,7 @@ msgid "" "[#914](https://github.com/adap/flower/pull/914))" msgstr "" -#: ../../source/ref-changelog.md:509 +#: ../../source/ref-changelog.md:660 msgid "" "The first preview release of Flower Baselines has arrived! We're " "kickstarting Flower Baselines with implementations of FedOpt (FedYogi, " @@ -7634,39 +12987,39 @@ msgid "" "baselines.html)." msgstr "" -#: ../../source/ref-changelog.md:511 +#: ../../source/ref-changelog.md:662 msgid "" "**C++ client SDK (preview) and code example** " "([#1111](https://github.com/adap/flower/pull/1111))" msgstr "" -#: ../../source/ref-changelog.md:513 +#: ../../source/ref-changelog.md:664 msgid "" "Preview support for Flower clients written in C++. The C++ preview " "includes a Flower client SDK and a quickstart code example that " "demonstrates a simple C++ client using the SDK." msgstr "" -#: ../../source/ref-changelog.md:515 +#: ../../source/ref-changelog.md:666 msgid "" "**Add experimental support for Python 3.10 and Python 3.11** " "([#1135](https://github.com/adap/flower/pull/1135))" msgstr "" -#: ../../source/ref-changelog.md:517 +#: ../../source/ref-changelog.md:668 msgid "" "Python 3.10 is the latest stable release of Python and Python 3.11 is due" " to be released in October. This Flower release adds experimental support" " for both Python versions." msgstr "" -#: ../../source/ref-changelog.md:519 +#: ../../source/ref-changelog.md:670 msgid "" "**Aggregate custom metrics through user-provided functions** " "([#1144](https://github.com/adap/flower/pull/1144))" msgstr "" -#: ../../source/ref-changelog.md:521 +#: ../../source/ref-changelog.md:672 msgid "" "Custom metrics (e.g., `accuracy`) can now be aggregated without having to" " customize the strategy. Built-in strategies support two new arguments, " @@ -7674,13 +13027,13 @@ msgid "" "allow passing custom metric aggregation functions." msgstr "" -#: ../../source/ref-changelog.md:523 +#: ../../source/ref-changelog.md:674 msgid "" "**User-configurable round timeout** " "([#1162](https://github.com/adap/flower/pull/1162))" msgstr "" -#: ../../source/ref-changelog.md:525 +#: ../../source/ref-changelog.md:676 msgid "" "A new configuration value allows the round timeout to be set for " "`start_server` and `start_simulation`. If the `config` dictionary " @@ -7689,14 +13042,14 @@ msgid "" "connection." msgstr "" -#: ../../source/ref-changelog.md:527 +#: ../../source/ref-changelog.md:678 msgid "" "**Enable both federated evaluation and centralized evaluation to be used " "at the same time in all built-in strategies** " "([#1091](https://github.com/adap/flower/pull/1091))" msgstr "" -#: ../../source/ref-changelog.md:529 +#: ../../source/ref-changelog.md:680 msgid "" "Built-in strategies can now perform both federated evaluation (i.e., " "client-side) and centralized evaluation (i.e., server-side) in the same " @@ -7704,82 +13057,82 @@ msgid "" " `0.0`." msgstr "" -#: ../../source/ref-changelog.md:531 +#: ../../source/ref-changelog.md:682 msgid "" "**Two new Jupyter Notebook tutorials** " "([#1141](https://github.com/adap/flower/pull/1141))" msgstr "" -#: ../../source/ref-changelog.md:533 +#: ../../source/ref-changelog.md:684 msgid "" "Two Jupyter Notebook tutorials (compatible with Google Colab) explain " "basic and intermediate Flower features:" msgstr "" -#: ../../source/ref-changelog.md:535 +#: ../../source/ref-changelog.md:686 msgid "" "*An Introduction to Federated Learning*: [Open in " "Colab](https://colab.research.google.com/github/adap/flower/blob/main/tutorials/Flower-1" "-Intro-to-FL-PyTorch.ipynb)" msgstr "" -#: ../../source/ref-changelog.md:537 +#: ../../source/ref-changelog.md:688 msgid "" "*Using Strategies in Federated Learning*: [Open in " "Colab](https://colab.research.google.com/github/adap/flower/blob/main/tutorials/Flower-2" "-Strategies-in-FL-PyTorch.ipynb)" msgstr "" -#: ../../source/ref-changelog.md:539 +#: ../../source/ref-changelog.md:690 msgid "" "**New FedAvgM strategy (Federated Averaging with Server Momentum)** " "([#1076](https://github.com/adap/flower/pull/1076))" msgstr "" -#: ../../source/ref-changelog.md:541 +#: ../../source/ref-changelog.md:692 msgid "" "The new `FedAvgM` strategy implements Federated Averaging with Server " "Momentum \\[Hsu et al., 2019\\]." msgstr "" -#: ../../source/ref-changelog.md:543 +#: ../../source/ref-changelog.md:694 msgid "" "**New advanced PyTorch code example** " "([#1007](https://github.com/adap/flower/pull/1007))" msgstr "" -#: ../../source/ref-changelog.md:545 +#: ../../source/ref-changelog.md:696 msgid "" "A new code example (`advanced_pytorch`) demonstrates advanced Flower " "concepts with PyTorch." msgstr "" -#: ../../source/ref-changelog.md:547 +#: ../../source/ref-changelog.md:698 msgid "" "**New JAX code example** " "([#906](https://github.com/adap/flower/pull/906), " "[#1143](https://github.com/adap/flower/pull/1143))" msgstr "" -#: ../../source/ref-changelog.md:549 +#: ../../source/ref-changelog.md:700 msgid "" "A new code example (`jax_from_centralized_to_federated`) shows federated " "learning with JAX and Flower." msgstr "" -#: ../../source/ref-changelog.md:553 +#: ../../source/ref-changelog.md:704 msgid "" "New option to keep Ray running if Ray was already initialized in " "`start_simulation` ([#1177](https://github.com/adap/flower/pull/1177))" msgstr "" -#: ../../source/ref-changelog.md:554 +#: ../../source/ref-changelog.md:705 msgid "" "Add support for custom `ClientManager` as a `start_simulation` parameter " "([#1171](https://github.com/adap/flower/pull/1171))" msgstr "" -#: ../../source/ref-changelog.md:555 +#: ../../source/ref-changelog.md:706 msgid "" "New documentation for [implementing " "strategies](https://flower.dev/docs/framework/how-to-implement-" @@ -7787,72 +13140,72 @@ msgid "" "[#1175](https://github.com/adap/flower/pull/1175))" msgstr "" -#: ../../source/ref-changelog.md:556 +#: ../../source/ref-changelog.md:707 msgid "" "New mobile-friendly documentation theme " "([#1174](https://github.com/adap/flower/pull/1174))" msgstr "" -#: ../../source/ref-changelog.md:557 +#: ../../source/ref-changelog.md:708 msgid "" "Limit version range for (optional) `ray` dependency to include only " "compatible releases (`>=1.9.2,<1.12.0`) " "([#1205](https://github.com/adap/flower/pull/1205))" msgstr "" -#: ../../source/ref-changelog.md:561 +#: ../../source/ref-changelog.md:712 msgid "" "**Remove deprecated support for Python 3.6** " "([#871](https://github.com/adap/flower/pull/871))" msgstr "" -#: ../../source/ref-changelog.md:562 +#: ../../source/ref-changelog.md:713 msgid "" "**Remove deprecated KerasClient** " "([#857](https://github.com/adap/flower/pull/857))" msgstr "" -#: ../../source/ref-changelog.md:563 +#: ../../source/ref-changelog.md:714 msgid "" "**Remove deprecated no-op extra installs** " "([#973](https://github.com/adap/flower/pull/973))" msgstr "" -#: ../../source/ref-changelog.md:564 +#: ../../source/ref-changelog.md:715 msgid "" "**Remove deprecated proto fields from** `FitRes` **and** `EvaluateRes` " "([#869](https://github.com/adap/flower/pull/869))" msgstr "" -#: ../../source/ref-changelog.md:565 +#: ../../source/ref-changelog.md:716 msgid "" "**Remove deprecated QffedAvg strategy (replaced by QFedAvg)** " "([#1107](https://github.com/adap/flower/pull/1107))" msgstr "" -#: ../../source/ref-changelog.md:566 +#: ../../source/ref-changelog.md:717 msgid "" "**Remove deprecated DefaultStrategy strategy** " "([#1142](https://github.com/adap/flower/pull/1142))" msgstr "" -#: ../../source/ref-changelog.md:567 +#: ../../source/ref-changelog.md:718 msgid "" "**Remove deprecated support for eval_fn accuracy return value** " "([#1142](https://github.com/adap/flower/pull/1142))" msgstr "" -#: ../../source/ref-changelog.md:568 +#: ../../source/ref-changelog.md:719 msgid "" "**Remove deprecated support for passing initial parameters as NumPy " "ndarrays** ([#1142](https://github.com/adap/flower/pull/1142))" msgstr "" -#: ../../source/ref-changelog.md:570 +#: ../../source/ref-changelog.md:721 msgid "v0.18.0 (2022-02-28)" msgstr "" -#: ../../source/ref-changelog.md:574 +#: ../../source/ref-changelog.md:725 msgid "" "**Improved Virtual Client Engine compatibility with Jupyter Notebook / " "Google Colab** ([#866](https://github.com/adap/flower/pull/866), " @@ -7861,7 +13214,7 @@ msgid "" "[#1036](https://github.com/adap/flower/pull/1036))" msgstr "" -#: ../../source/ref-changelog.md:576 +#: ../../source/ref-changelog.md:727 msgid "" "Simulations (using the Virtual Client Engine through `start_simulation`) " "now work more smoothly on Jupyter Notebooks (incl. Google Colab) after " @@ -7869,38 +13222,38 @@ msgid "" "flwr[simulation]`)." msgstr "" -#: ../../source/ref-changelog.md:578 +#: ../../source/ref-changelog.md:729 msgid "" "**New Jupyter Notebook code example** " "([#833](https://github.com/adap/flower/pull/833))" msgstr "" -#: ../../source/ref-changelog.md:580 +#: ../../source/ref-changelog.md:731 msgid "" "A new code example (`quickstart_simulation`) demonstrates Flower " "simulations using the Virtual Client Engine through Jupyter Notebook " "(incl. Google Colab)." msgstr "" -#: ../../source/ref-changelog.md:582 +#: ../../source/ref-changelog.md:733 msgid "" "**Client properties (feature preview)** " "([#795](https://github.com/adap/flower/pull/795))" msgstr "" -#: ../../source/ref-changelog.md:584 +#: ../../source/ref-changelog.md:735 msgid "" "Clients can implement a new method `get_properties` to enable server-side" " strategies to query client properties." msgstr "" -#: ../../source/ref-changelog.md:586 +#: ../../source/ref-changelog.md:737 msgid "" "**Experimental Android support with TFLite** " "([#865](https://github.com/adap/flower/pull/865))" msgstr "" -#: ../../source/ref-changelog.md:588 +#: ../../source/ref-changelog.md:739 msgid "" "Android support has finally arrived in `main`! Flower is both client-" "agnostic and framework-agnostic by design. One can integrate arbitrary " @@ -7908,7 +13261,7 @@ msgid "" "become a lot easier." msgstr "" -#: ../../source/ref-changelog.md:590 +#: ../../source/ref-changelog.md:741 msgid "" "The example uses TFLite on the client side, along with a new " "`FedAvgAndroid` strategy. The Android client and `FedAvgAndroid` are " @@ -7917,13 +13270,13 @@ msgid "" " functionality from `FedAvgAndroid`." msgstr "" -#: ../../source/ref-changelog.md:592 +#: ../../source/ref-changelog.md:743 msgid "" "**Make gRPC keepalive time user-configurable and decrease default " "keepalive time** ([#1069](https://github.com/adap/flower/pull/1069))" msgstr "" -#: ../../source/ref-changelog.md:594 +#: ../../source/ref-changelog.md:745 msgid "" "The default gRPC keepalive time has been reduced to increase the " "compatibility of Flower with more cloud environments (for example, " @@ -7931,31 +13284,31 @@ msgid "" " gRPC stack based on specific requirements." msgstr "" -#: ../../source/ref-changelog.md:596 +#: ../../source/ref-changelog.md:747 msgid "" "**New differential privacy example using Opacus and PyTorch** " "([#805](https://github.com/adap/flower/pull/805))" msgstr "" -#: ../../source/ref-changelog.md:598 +#: ../../source/ref-changelog.md:749 msgid "" "A new code example (`opacus`) demonstrates differentially-private " "federated learning with Opacus, PyTorch, and Flower." msgstr "" -#: ../../source/ref-changelog.md:600 +#: ../../source/ref-changelog.md:751 msgid "" "**New Hugging Face Transformers code example** " "([#863](https://github.com/adap/flower/pull/863))" msgstr "" -#: ../../source/ref-changelog.md:602 +#: ../../source/ref-changelog.md:753 msgid "" "A new code example (`quickstart_huggingface`) demonstrates usage of " "Hugging Face Transformers with Flower." msgstr "" -#: ../../source/ref-changelog.md:604 +#: ../../source/ref-changelog.md:755 msgid "" "**New MLCube code example** " "([#779](https://github.com/adap/flower/pull/779), " @@ -7964,13 +13317,13 @@ msgid "" "[#1090](https://github.com/adap/flower/pull/1090))" msgstr "" -#: ../../source/ref-changelog.md:606 +#: ../../source/ref-changelog.md:757 msgid "" "A new code example (`quickstart_mlcube`) demonstrates usage of MLCube " "with Flower." msgstr "" -#: ../../source/ref-changelog.md:608 +#: ../../source/ref-changelog.md:759 msgid "" "**SSL-enabled server and client** " "([#842](https://github.com/adap/flower/pull/842), " @@ -7981,33 +13334,33 @@ msgid "" "[#994](https://github.com/adap/flower/pull/994))" msgstr "" -#: ../../source/ref-changelog.md:610 +#: ../../source/ref-changelog.md:761 msgid "" "SSL enables secure encrypted connections between clients and servers. " "This release open-sources the Flower secure gRPC implementation to make " "encrypted communication channels accessible to all Flower users." msgstr "" -#: ../../source/ref-changelog.md:612 +#: ../../source/ref-changelog.md:763 msgid "" "**Updated** `FedAdam` **and** `FedYogi` **strategies** " "([#885](https://github.com/adap/flower/pull/885), " "[#895](https://github.com/adap/flower/pull/895))" msgstr "" -#: ../../source/ref-changelog.md:614 +#: ../../source/ref-changelog.md:765 msgid "" "`FedAdam` and `FedAdam` match the latest version of the Adaptive " "Federated Optimization paper." msgstr "" -#: ../../source/ref-changelog.md:616 +#: ../../source/ref-changelog.md:767 msgid "" "**Initialize** `start_simulation` **with a list of client IDs** " "([#860](https://github.com/adap/flower/pull/860))" msgstr "" -#: ../../source/ref-changelog.md:618 +#: ../../source/ref-changelog.md:769 msgid "" "`start_simulation` can now be called with a list of client IDs " "(`clients_ids`, type: `List[str]`). Those IDs will be passed to the " @@ -8016,55 +13369,55 @@ msgid "" "identifiers." msgstr "" -#: ../../source/ref-changelog.md:622 +#: ../../source/ref-changelog.md:773 msgid "" "Update `num_examples` calculation in PyTorch code examples in " "([#909](https://github.com/adap/flower/pull/909))" msgstr "" -#: ../../source/ref-changelog.md:623 +#: ../../source/ref-changelog.md:774 msgid "" "Expose Flower version through `flwr.__version__` " "([#952](https://github.com/adap/flower/pull/952))" msgstr "" -#: ../../source/ref-changelog.md:624 +#: ../../source/ref-changelog.md:775 msgid "" "`start_server` in `app.py` now returns a `History` object containing " "metrics from training ([#974](https://github.com/adap/flower/pull/974))" msgstr "" -#: ../../source/ref-changelog.md:625 +#: ../../source/ref-changelog.md:776 msgid "" "Make `max_workers` (used by `ThreadPoolExecutor`) configurable " "([#978](https://github.com/adap/flower/pull/978))" msgstr "" -#: ../../source/ref-changelog.md:626 +#: ../../source/ref-changelog.md:777 msgid "" "Increase sleep time after server start to three seconds in all code " "examples ([#1086](https://github.com/adap/flower/pull/1086))" msgstr "" -#: ../../source/ref-changelog.md:627 +#: ../../source/ref-changelog.md:778 msgid "" "Added a new FAQ section to the documentation " "([#948](https://github.com/adap/flower/pull/948))" msgstr "" -#: ../../source/ref-changelog.md:628 +#: ../../source/ref-changelog.md:779 msgid "" "And many more under-the-hood changes, library updates, documentation " "changes, and tooling improvements!" msgstr "" -#: ../../source/ref-changelog.md:632 +#: ../../source/ref-changelog.md:783 msgid "" "**Removed** `flwr_example` **and** `flwr_experimental` **from release " "build** ([#869](https://github.com/adap/flower/pull/869))" msgstr "" -#: ../../source/ref-changelog.md:634 +#: ../../source/ref-changelog.md:785 msgid "" "The packages `flwr_example` and `flwr_experimental` have been deprecated " "since Flower 0.12.0 and they are not longer included in Flower release " @@ -8073,11 +13426,11 @@ msgid "" "an upcoming release." msgstr "" -#: ../../source/ref-changelog.md:636 +#: ../../source/ref-changelog.md:787 msgid "v0.17.0 (2021-09-24)" msgstr "" -#: ../../source/ref-changelog.md:640 +#: ../../source/ref-changelog.md:791 msgid "" "**Experimental virtual client engine** " "([#781](https://github.com/adap/flower/pull/781) " @@ -8085,7 +13438,7 @@ msgid "" "[#791](https://github.com/adap/flower/pull/791))" msgstr "" -#: ../../source/ref-changelog.md:642 +#: ../../source/ref-changelog.md:793 msgid "" "One of Flower's goals is to enable research at scale. This release " "enables a first (experimental) peek at a major new feature, codenamed the" @@ -8095,7 +13448,7 @@ msgid "" "code examples called `quickstart_simulation` and `simulation_pytorch`." msgstr "" -#: ../../source/ref-changelog.md:644 +#: ../../source/ref-changelog.md:795 msgid "" "The feature is still experimental, so there's no stability guarantee for " "the API. It's also not quite ready for prime time and comes with a few " @@ -8103,86 +13456,86 @@ msgid "" "out and share their thoughts." msgstr "" -#: ../../source/ref-changelog.md:646 +#: ../../source/ref-changelog.md:797 msgid "" "**New built-in strategies** " "([#828](https://github.com/adap/flower/pull/828) " "[#822](https://github.com/adap/flower/pull/822))" msgstr "" -#: ../../source/ref-changelog.md:648 +#: ../../source/ref-changelog.md:799 msgid "" "FedYogi - Federated learning strategy using Yogi on server-side. " "Implementation based on https://arxiv.org/abs/2003.00295" msgstr "" -#: ../../source/ref-changelog.md:649 +#: ../../source/ref-changelog.md:800 msgid "" "FedAdam - Federated learning strategy using Adam on server-side. " "Implementation based on https://arxiv.org/abs/2003.00295" msgstr "" -#: ../../source/ref-changelog.md:651 +#: ../../source/ref-changelog.md:802 msgid "" "**New PyTorch Lightning code example** " "([#617](https://github.com/adap/flower/pull/617))" msgstr "" -#: ../../source/ref-changelog.md:653 +#: ../../source/ref-changelog.md:804 msgid "" "**New Variational Auto-Encoder code example** " "([#752](https://github.com/adap/flower/pull/752))" msgstr "" -#: ../../source/ref-changelog.md:655 +#: ../../source/ref-changelog.md:806 msgid "" "**New scikit-learn code example** " "([#748](https://github.com/adap/flower/pull/748))" msgstr "" -#: ../../source/ref-changelog.md:657 +#: ../../source/ref-changelog.md:808 msgid "" "**New experimental TensorBoard strategy** " "([#789](https://github.com/adap/flower/pull/789))" msgstr "" -#: ../../source/ref-changelog.md:661 +#: ../../source/ref-changelog.md:812 msgid "" "Improved advanced TensorFlow code example " "([#769](https://github.com/adap/flower/pull/769))" msgstr "" -#: ../../source/ref-changelog.md:662 +#: ../../source/ref-changelog.md:813 msgid "" "Warning when `min_available_clients` is misconfigured " "([#830](https://github.com/adap/flower/pull/830))" msgstr "" -#: ../../source/ref-changelog.md:663 +#: ../../source/ref-changelog.md:814 msgid "" "Improved gRPC server docs " "([#841](https://github.com/adap/flower/pull/841))" msgstr "" -#: ../../source/ref-changelog.md:664 +#: ../../source/ref-changelog.md:815 msgid "" "Improved error message in `NumPyClient` " "([#851](https://github.com/adap/flower/pull/851))" msgstr "" -#: ../../source/ref-changelog.md:665 +#: ../../source/ref-changelog.md:816 msgid "" "Improved PyTorch quickstart code example " "([#852](https://github.com/adap/flower/pull/852))" msgstr "" -#: ../../source/ref-changelog.md:669 +#: ../../source/ref-changelog.md:820 msgid "" "**Disabled final distributed evaluation** " "([#800](https://github.com/adap/flower/pull/800))" msgstr "" -#: ../../source/ref-changelog.md:671 +#: ../../source/ref-changelog.md:822 msgid "" "Prior behaviour was to perform a final round of distributed evaluation on" " all connected clients, which is often not required (e.g., when using " @@ -8190,13 +13543,13 @@ msgid "" "`force_final_distributed_eval=True` to `start_server`." msgstr "" -#: ../../source/ref-changelog.md:673 +#: ../../source/ref-changelog.md:824 msgid "" "**Renamed q-FedAvg strategy** " "([#802](https://github.com/adap/flower/pull/802))" msgstr "" -#: ../../source/ref-changelog.md:675 +#: ../../source/ref-changelog.md:826 msgid "" "The strategy named `QffedAvg` was renamed to `QFedAvg` to better reflect " "the notation given in the original paper (q-FFL is the optimization " @@ -8205,14 +13558,14 @@ msgid "" " (it will be removed in a future release)." msgstr "" -#: ../../source/ref-changelog.md:677 +#: ../../source/ref-changelog.md:828 msgid "" "**Deprecated and renamed code example** `simulation_pytorch` **to** " "`simulation_pytorch_legacy` " "([#791](https://github.com/adap/flower/pull/791))" msgstr "" -#: ../../source/ref-changelog.md:679 +#: ../../source/ref-changelog.md:830 msgid "" "This example has been replaced by a new example. The new example is based" " on the experimental virtual client engine, which will become the new " @@ -8221,31 +13574,27 @@ msgid "" "removed in the future." msgstr "" -#: ../../source/ref-changelog.md:681 +#: ../../source/ref-changelog.md:832 msgid "v0.16.0 (2021-05-11)" msgstr "" -#: ../../source/ref-changelog.md:685 +#: ../../source/ref-changelog.md:836 msgid "" "**New built-in strategies** " "([#549](https://github.com/adap/flower/pull/549))" msgstr "" -#: ../../source/ref-changelog.md:687 +#: ../../source/ref-changelog.md:838 msgid "(abstract) FedOpt" msgstr "" -#: ../../source/ref-changelog.md:688 -msgid "FedAdagrad" -msgstr "" - -#: ../../source/ref-changelog.md:690 +#: ../../source/ref-changelog.md:841 msgid "" "**Custom metrics for server and strategies** " "([#717](https://github.com/adap/flower/pull/717))" msgstr "" -#: ../../source/ref-changelog.md:692 +#: ../../source/ref-changelog.md:843 msgid "" "The Flower server is now fully task-agnostic, all remaining instances of " "task-specific metrics (such as `accuracy`) have been replaced by custom " @@ -8254,7 +13603,7 @@ msgid "" "release, custom metrics replace task-specific metrics on the server." msgstr "" -#: ../../source/ref-changelog.md:694 +#: ../../source/ref-changelog.md:845 msgid "" "Custom metric dictionaries are now used in two user-facing APIs: they are" " returned from Strategy methods `aggregate_fit`/`aggregate_evaluate` and " @@ -8264,7 +13613,7 @@ msgid "" "track of." msgstr "" -#: ../../source/ref-changelog.md:696 +#: ../../source/ref-changelog.md:847 msgid "" "Stratey implementations should migrate their `aggregate_fit` and " "`aggregate_evaluate` methods to the new return type (e.g., by simply " @@ -8272,19 +13621,19 @@ msgid "" " from `return loss, accuracy` to `return loss, {\"accuracy\": accuracy}`." msgstr "" -#: ../../source/ref-changelog.md:698 +#: ../../source/ref-changelog.md:849 msgid "" "Flower 0.15-style return types are deprecated (but still supported), " "compatibility will be removed in a future release." msgstr "" -#: ../../source/ref-changelog.md:700 +#: ../../source/ref-changelog.md:851 msgid "" "**Migration warnings for deprecated functionality** " "([#690](https://github.com/adap/flower/pull/690))" msgstr "" -#: ../../source/ref-changelog.md:702 +#: ../../source/ref-changelog.md:853 msgid "" "Earlier versions of Flower were often migrated to new APIs, while " "maintaining compatibility with legacy APIs. This release introduces " @@ -8293,7 +13642,7 @@ msgid "" "recent APIs, thus easing the transition from one release to another." msgstr "" -#: ../../source/ref-changelog.md:704 +#: ../../source/ref-changelog.md:855 msgid "" "Improved docs and docstrings " "([#691](https://github.com/adap/flower/pull/691) " @@ -8301,11 +13650,11 @@ msgid "" "[#713](https://github.com/adap/flower/pull/713))" msgstr "" -#: ../../source/ref-changelog.md:706 +#: ../../source/ref-changelog.md:857 msgid "MXNet example and documentation" msgstr "" -#: ../../source/ref-changelog.md:708 +#: ../../source/ref-changelog.md:859 msgid "" "FedBN implementation in example PyTorch: From Centralized To Federated " "([#696](https://github.com/adap/flower/pull/696) " @@ -8313,13 +13662,13 @@ msgid "" "[#705](https://github.com/adap/flower/pull/705))" msgstr "" -#: ../../source/ref-changelog.md:712 +#: ../../source/ref-changelog.md:863 msgid "" "**Serialization-agnostic server** " "([#721](https://github.com/adap/flower/pull/721))" msgstr "" -#: ../../source/ref-changelog.md:714 +#: ../../source/ref-changelog.md:865 msgid "" "The Flower server is now fully serialization-agnostic. Prior usage of " "class `Weights` (which represents parameters as deserialized NumPy " @@ -8330,7 +13679,7 @@ msgid "" "serialization/deserialization)." msgstr "" -#: ../../source/ref-changelog.md:716 +#: ../../source/ref-changelog.md:867 msgid "" "Built-in strategies implement this approach by handling serialization and" " deserialization to/from `Weights` internally. Custom/3rd-party Strategy " @@ -8340,31 +13689,31 @@ msgid "" " easily migrate to the new format." msgstr "" -#: ../../source/ref-changelog.md:718 +#: ../../source/ref-changelog.md:869 msgid "" "Deprecated `flwr.server.Server.evaluate`, use " "`flwr.server.Server.evaluate_round` instead " "([#717](https://github.com/adap/flower/pull/717))" msgstr "" -#: ../../source/ref-changelog.md:720 +#: ../../source/ref-changelog.md:871 msgid "v0.15.0 (2021-03-12)" msgstr "" -#: ../../source/ref-changelog.md:724 +#: ../../source/ref-changelog.md:875 msgid "" "**Server-side parameter initialization** " "([#658](https://github.com/adap/flower/pull/658))" msgstr "" -#: ../../source/ref-changelog.md:726 +#: ../../source/ref-changelog.md:877 msgid "" "Model parameters can now be initialized on the server-side. Server-side " "parameter initialization works via a new `Strategy` method called " "`initialize_parameters`." msgstr "" -#: ../../source/ref-changelog.md:728 +#: ../../source/ref-changelog.md:879 msgid "" "Built-in strategies support a new constructor argument called " "`initial_parameters` to set the initial parameters. Built-in strategies " @@ -8372,7 +13721,7 @@ msgid "" "delete them to free the memory afterwards." msgstr "" -#: ../../source/ref-changelog.md:747 +#: ../../source/ref-changelog.md:898 msgid "" "If no initial parameters are provided to the strategy, the server will " "continue to use the current behaviour (namely, it will ask one of the " @@ -8380,21 +13729,21 @@ msgid "" "parameters)." msgstr "" -#: ../../source/ref-changelog.md:749 +#: ../../source/ref-changelog.md:900 msgid "Deprecations" msgstr "" -#: ../../source/ref-changelog.md:751 +#: ../../source/ref-changelog.md:902 msgid "" "Deprecate `flwr.server.strategy.DefaultStrategy` (migrate to " "`flwr.server.strategy.FedAvg`, which is equivalent)" msgstr "" -#: ../../source/ref-changelog.md:753 +#: ../../source/ref-changelog.md:904 msgid "v0.14.0 (2021-02-18)" msgstr "" -#: ../../source/ref-changelog.md:757 +#: ../../source/ref-changelog.md:908 msgid "" "**Generalized** `Client.fit` **and** `Client.evaluate` **return values** " "([#610](https://github.com/adap/flower/pull/610) " @@ -8402,7 +13751,7 @@ msgid "" "[#633](https://github.com/adap/flower/pull/633))" msgstr "" -#: ../../source/ref-changelog.md:759 +#: ../../source/ref-changelog.md:910 msgid "" "Clients can now return an additional dictionary mapping `str` keys to " "values of the following types: `bool`, `bytes`, `float`, `int`, `str`. " @@ -8410,7 +13759,7 @@ msgid "" "and make use of them on the server side!" msgstr "" -#: ../../source/ref-changelog.md:761 +#: ../../source/ref-changelog.md:912 msgid "" "This improvement also allowed for more consistent return types between " "`fit` and `evaluate`: `evaluate` should now return a tuple `(float, int, " @@ -8418,7 +13767,7 @@ msgid "" "holding arbitrary problem-specific values like accuracy." msgstr "" -#: ../../source/ref-changelog.md:763 +#: ../../source/ref-changelog.md:914 msgid "" "In case you wondered: this feature is compatible with existing projects, " "the additional dictionary return value is optional. New code should " @@ -8428,19 +13777,19 @@ msgid "" "details." msgstr "" -#: ../../source/ref-changelog.md:765 +#: ../../source/ref-changelog.md:916 msgid "" "*Code example:* note the additional dictionary return values in both " "`FlwrClient.fit` and `FlwrClient.evaluate`:" msgstr "" -#: ../../source/ref-changelog.md:780 +#: ../../source/ref-changelog.md:931 msgid "" "**Generalized** `config` **argument in** `Client.fit` **and** " "`Client.evaluate` ([#595](https://github.com/adap/flower/pull/595))" msgstr "" -#: ../../source/ref-changelog.md:782 +#: ../../source/ref-changelog.md:933 msgid "" "The `config` argument used to be of type `Dict[str, str]`, which means " "that dictionary values were expected to be strings. The new release " @@ -8448,58 +13797,58 @@ msgid "" "`bytes`, `float`, `int`, `str`." msgstr "" -#: ../../source/ref-changelog.md:784 +#: ../../source/ref-changelog.md:935 msgid "" "This means one can now pass almost arbitrary values to `fit`/`evaluate` " "using the `config` dictionary. Yay, no more `str(epochs)` on the server-" "side and `int(config[\"epochs\"])` on the client side!" msgstr "" -#: ../../source/ref-changelog.md:786 +#: ../../source/ref-changelog.md:937 msgid "" "*Code example:* note that the `config` dictionary now contains non-`str` " "values in both `Client.fit` and `Client.evaluate`:" msgstr "" -#: ../../source/ref-changelog.md:803 +#: ../../source/ref-changelog.md:954 msgid "v0.13.0 (2021-01-08)" msgstr "" -#: ../../source/ref-changelog.md:807 +#: ../../source/ref-changelog.md:958 msgid "" "New example: PyTorch From Centralized To Federated " "([#549](https://github.com/adap/flower/pull/549))" msgstr "" -#: ../../source/ref-changelog.md:808 +#: ../../source/ref-changelog.md:959 msgid "Improved documentation" msgstr "" -#: ../../source/ref-changelog.md:809 +#: ../../source/ref-changelog.md:960 msgid "New documentation theme ([#551](https://github.com/adap/flower/pull/551))" msgstr "" -#: ../../source/ref-changelog.md:810 +#: ../../source/ref-changelog.md:961 msgid "New API reference ([#554](https://github.com/adap/flower/pull/554))" msgstr "" -#: ../../source/ref-changelog.md:811 +#: ../../source/ref-changelog.md:962 msgid "" "Updated examples documentation " "([#549](https://github.com/adap/flower/pull/549))" msgstr "" -#: ../../source/ref-changelog.md:812 +#: ../../source/ref-changelog.md:963 msgid "" "Removed obsolete documentation " "([#548](https://github.com/adap/flower/pull/548))" msgstr "" -#: ../../source/ref-changelog.md:814 +#: ../../source/ref-changelog.md:965 msgid "Bugfix:" msgstr "" -#: ../../source/ref-changelog.md:816 +#: ../../source/ref-changelog.md:967 msgid "" "`Server.fit` does not disconnect clients when finished, disconnecting the" " clients is now handled in `flwr.server.start_server` " @@ -8507,28 +13856,28 @@ msgid "" "[#540](https://github.com/adap/flower/issues/540))." msgstr "" -#: ../../source/ref-changelog.md:818 +#: ../../source/ref-changelog.md:969 msgid "v0.12.0 (2020-12-07)" msgstr "" -#: ../../source/ref-changelog.md:820 ../../source/ref-changelog.md:836 +#: ../../source/ref-changelog.md:971 ../../source/ref-changelog.md:987 msgid "Important changes:" msgstr "" -#: ../../source/ref-changelog.md:822 +#: ../../source/ref-changelog.md:973 msgid "" "Added an example for embedded devices " "([#507](https://github.com/adap/flower/pull/507))" msgstr "" -#: ../../source/ref-changelog.md:823 +#: ../../source/ref-changelog.md:974 msgid "" "Added a new NumPyClient (in addition to the existing KerasClient) " "([#504](https://github.com/adap/flower/pull/504) " "[#508](https://github.com/adap/flower/pull/508))" msgstr "" -#: ../../source/ref-changelog.md:824 +#: ../../source/ref-changelog.md:975 msgid "" "Deprecated `flwr_example` package and started to migrate examples into " "the top-level `examples` directory " @@ -8536,15 +13885,15 @@ msgid "" "[#512](https://github.com/adap/flower/pull/512))" msgstr "" -#: ../../source/ref-changelog.md:826 +#: ../../source/ref-changelog.md:977 msgid "v0.11.0 (2020-11-30)" msgstr "" -#: ../../source/ref-changelog.md:828 +#: ../../source/ref-changelog.md:979 msgid "Incompatible changes:" msgstr "" -#: ../../source/ref-changelog.md:830 +#: ../../source/ref-changelog.md:981 msgid "" "Renamed strategy methods " "([#486](https://github.com/adap/flower/pull/486)) to unify the naming of " @@ -8554,48 +13903,48 @@ msgid "" "migrate rename the following `Strategy` methods accordingly:" msgstr "" -#: ../../source/ref-changelog.md:831 +#: ../../source/ref-changelog.md:982 msgid "`on_configure_evaluate` => `configure_evaluate`" msgstr "" -#: ../../source/ref-changelog.md:832 +#: ../../source/ref-changelog.md:983 msgid "`on_aggregate_evaluate` => `aggregate_evaluate`" msgstr "" -#: ../../source/ref-changelog.md:833 +#: ../../source/ref-changelog.md:984 msgid "`on_configure_fit` => `configure_fit`" msgstr "" -#: ../../source/ref-changelog.md:834 +#: ../../source/ref-changelog.md:985 msgid "`on_aggregate_fit` => `aggregate_fit`" msgstr "" -#: ../../source/ref-changelog.md:838 +#: ../../source/ref-changelog.md:989 msgid "" "Deprecated `DefaultStrategy` " "([#479](https://github.com/adap/flower/pull/479)). To migrate use " "`FedAvg` instead." msgstr "" -#: ../../source/ref-changelog.md:839 +#: ../../source/ref-changelog.md:990 msgid "" "Simplified examples and baselines " "([#484](https://github.com/adap/flower/pull/484))." msgstr "" -#: ../../source/ref-changelog.md:840 +#: ../../source/ref-changelog.md:991 msgid "" "Removed presently unused `on_conclude_round` from strategy interface " "([#483](https://github.com/adap/flower/pull/483))." msgstr "" -#: ../../source/ref-changelog.md:841 +#: ../../source/ref-changelog.md:992 msgid "" "Set minimal Python version to 3.6.1 instead of 3.6.9 " "([#471](https://github.com/adap/flower/pull/471))." msgstr "" -#: ../../source/ref-changelog.md:842 +#: ../../source/ref-changelog.md:993 msgid "" "Improved `Strategy` docstrings " "([#470](https://github.com/adap/flower/pull/470))." @@ -9486,7 +14835,7 @@ msgid "" msgstr "" #: ../../source/tutorial-quickstart-ios.rst:131 -#: ../../source/tutorial-quickstart-mxnet.rst:226 +#: ../../source/tutorial-quickstart-mxnet.rst:228 #: ../../source/tutorial-quickstart-pytorch.rst:205 #: ../../source/tutorial-quickstart-tensorflow.rst:100 msgid "" @@ -9496,7 +14845,7 @@ msgid "" msgstr "" #: ../../source/tutorial-quickstart-ios.rst:142 -#: ../../source/tutorial-quickstart-mxnet.rst:237 +#: ../../source/tutorial-quickstart-mxnet.rst:239 #: ../../source/tutorial-quickstart-pytorch.rst:216 #: ../../source/tutorial-quickstart-scikitlearn.rst:215 #: ../../source/tutorial-quickstart-tensorflow.rst:112 @@ -9506,6 +14855,7 @@ msgstr "" #: ../../source/tutorial-quickstart-ios.rst:144 #: ../../source/tutorial-quickstart-pytorch.rst:218 #: ../../source/tutorial-quickstart-tensorflow.rst:114 +#: ../../source/tutorial-quickstart-xgboost.rst:525 msgid "" "With both client and server ready, we can now run everything and see " "federated learning in action. FL systems usually have a server and " @@ -9550,13 +14900,21 @@ msgstr "" msgid "Quickstart MXNet" msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:10 +#: ../../source/tutorial-quickstart-mxnet.rst:7 +msgid "" +"MXNet is no longer maintained and has been moved into `Attic " +"`_. As a result, we would " +"encourage you to use other ML frameworks alongise Flower, for example, " +"PyTorch. This tutorial might be removed in future versions of Flower." +msgstr "" + +#: ../../source/tutorial-quickstart-mxnet.rst:12 msgid "" "In this tutorial, we will learn how to train a :code:`Sequential` model " "on MNIST using Flower and MXNet." msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:12 +#: ../../source/tutorial-quickstart-mxnet.rst:14 #: ../../source/tutorial-quickstart-scikitlearn.rst:12 msgid "" "It is recommended to create a virtual environment and run everything " @@ -9564,7 +14922,7 @@ msgid "" "setup.html>`_." msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:16 +#: ../../source/tutorial-quickstart-mxnet.rst:18 #: ../../source/tutorial-quickstart-scikitlearn.rst:16 msgid "" "*Clients* are responsible for generating individual model parameter " @@ -9575,18 +14933,18 @@ msgid "" "called a *round*." msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:20 +#: ../../source/tutorial-quickstart-mxnet.rst:22 #: ../../source/tutorial-quickstart-scikitlearn.rst:20 msgid "" "Now that we have a rough idea of what is going on, let's get started. We " "first need to install Flower. You can do this by running:" msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:26 +#: ../../source/tutorial-quickstart-mxnet.rst:28 msgid "Since we want to use MXNet, let's go ahead and install it:" msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:36 +#: ../../source/tutorial-quickstart-mxnet.rst:38 msgid "" "Now that we have all our dependencies installed, let's run a simple " "distributed training with two clients and one server. Our training " @@ -9595,53 +14953,53 @@ msgid "" "`_." msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:38 +#: ../../source/tutorial-quickstart-mxnet.rst:40 msgid "" "In a file called :code:`client.py`, import Flower and MXNet related " "packages:" msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:53 +#: ../../source/tutorial-quickstart-mxnet.rst:55 msgid "In addition, define the device allocation in MXNet with:" msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:59 +#: ../../source/tutorial-quickstart-mxnet.rst:61 msgid "" "We use MXNet to load MNIST, a popular image classification dataset of " "handwritten digits for machine learning. The MXNet utility " ":code:`mx.test_utils.get_mnist()` downloads the training and test data." msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:73 +#: ../../source/tutorial-quickstart-mxnet.rst:75 msgid "" "Define the training and loss with MXNet. We train the model by looping " "over the dataset, measure the corresponding loss, and optimize it." msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:111 +#: ../../source/tutorial-quickstart-mxnet.rst:113 msgid "" "Next, we define the validation of our machine learning model. We loop " "over the test set and measure both loss and accuracy on the test set." msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:135 +#: ../../source/tutorial-quickstart-mxnet.rst:137 msgid "" "After defining the training and testing of a MXNet machine learning " "model, we use these functions to implement a Flower client." msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:137 +#: ../../source/tutorial-quickstart-mxnet.rst:139 msgid "Our Flower clients will use a simple :code:`Sequential` model:" msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:156 +#: ../../source/tutorial-quickstart-mxnet.rst:158 msgid "" "After loading the dataset with :code:`load_data()` we perform one forward" " propagation to initialize the model and model parameters with " ":code:`model(init)`. Next, we implement a Flower client." msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:158 +#: ../../source/tutorial-quickstart-mxnet.rst:160 #: ../../source/tutorial-quickstart-pytorch.rst:144 #: ../../source/tutorial-quickstart-tensorflow.rst:54 msgid "" @@ -9652,7 +15010,7 @@ msgid "" "your code (i.e., to train the neural network we defined earlier)." msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:164 +#: ../../source/tutorial-quickstart-mxnet.rst:166 msgid "" "Flower provides a convenience class called :code:`NumPyClient` which " "makes it easier to implement the :code:`Client` interface when your " @@ -9661,19 +15019,19 @@ msgid "" "though):" msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:170 +#: ../../source/tutorial-quickstart-mxnet.rst:172 #: ../../source/tutorial-quickstart-pytorch.rst:156 #: ../../source/tutorial-quickstart-scikitlearn.rst:109 msgid "return the model weight as a list of NumPy ndarrays" msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:171 +#: ../../source/tutorial-quickstart-mxnet.rst:173 #: ../../source/tutorial-quickstart-pytorch.rst:157 #: ../../source/tutorial-quickstart-scikitlearn.rst:111 msgid ":code:`set_parameters` (optional)" msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:172 +#: ../../source/tutorial-quickstart-mxnet.rst:174 #: ../../source/tutorial-quickstart-pytorch.rst:158 #: ../../source/tutorial-quickstart-scikitlearn.rst:111 msgid "" @@ -9681,45 +15039,45 @@ msgid "" "server" msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:174 +#: ../../source/tutorial-quickstart-mxnet.rst:176 #: ../../source/tutorial-quickstart-pytorch.rst:160 #: ../../source/tutorial-quickstart-scikitlearn.rst:114 msgid "set the local model weights" msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:175 +#: ../../source/tutorial-quickstart-mxnet.rst:177 #: ../../source/tutorial-quickstart-pytorch.rst:161 #: ../../source/tutorial-quickstart-scikitlearn.rst:115 msgid "train the local model" msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:176 +#: ../../source/tutorial-quickstart-mxnet.rst:178 #: ../../source/tutorial-quickstart-pytorch.rst:162 #: ../../source/tutorial-quickstart-scikitlearn.rst:116 msgid "receive the updated local model weights" msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:178 +#: ../../source/tutorial-quickstart-mxnet.rst:180 #: ../../source/tutorial-quickstart-pytorch.rst:164 #: ../../source/tutorial-quickstart-scikitlearn.rst:118 msgid "test the local model" msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:180 +#: ../../source/tutorial-quickstart-mxnet.rst:182 msgid "They can be implemented in the following way:" msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:210 +#: ../../source/tutorial-quickstart-mxnet.rst:212 msgid "" "We can now create an instance of our class :code:`MNISTClient` and add " "one line to actually run this client:" msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:217 -#: ../../source/tutorial-quickstart-scikitlearn.rst:150 +#: ../../source/tutorial-quickstart-mxnet.rst:219 msgid "" "That's it for the client. We only have to implement :code:`Client` or " -":code:`NumPyClient` and call :code:`fl.client.start_client()`. The string " +":code:`NumPyClient` and call :code:`fl.client.start_client()` or " +":code:`fl.client.start_numpy_client()`. The string " ":code:`\"0.0.0.0:8080\"` tells the client which server to connect to. In " "our case we can run the server and the client on the same machine, " "therefore we use :code:`\"0.0.0.0:8080\"`. If we run a truly federated " @@ -9727,39 +15085,42 @@ msgid "" "that needs to change is the :code:`server_address` we pass to the client." msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:239 +#: ../../source/tutorial-quickstart-mxnet.rst:241 msgid "" "With both client and server ready, we can now run everything and see " "federated learning in action. Federated learning systems usually have a " "server and multiple clients. We therefore have to start the server first:" msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:247 +#: ../../source/tutorial-quickstart-mxnet.rst:249 #: ../../source/tutorial-quickstart-pytorch.rst:226 #: ../../source/tutorial-quickstart-scikitlearn.rst:224 #: ../../source/tutorial-quickstart-tensorflow.rst:122 +#: ../../source/tutorial-quickstart-xgboost.rst:533 msgid "" "Once the server is running we can start the clients in different " "terminals. Open a new terminal and start the first client:" msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:254 +#: ../../source/tutorial-quickstart-mxnet.rst:256 #: ../../source/tutorial-quickstart-pytorch.rst:233 #: ../../source/tutorial-quickstart-scikitlearn.rst:231 #: ../../source/tutorial-quickstart-tensorflow.rst:129 +#: ../../source/tutorial-quickstart-xgboost.rst:540 msgid "Open another terminal and start the second client:" msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:260 +#: ../../source/tutorial-quickstart-mxnet.rst:262 #: ../../source/tutorial-quickstart-pytorch.rst:239 #: ../../source/tutorial-quickstart-scikitlearn.rst:237 +#: ../../source/tutorial-quickstart-xgboost.rst:546 msgid "" "Each client will have its own dataset. You should now see how the " "training does in the very first terminal (the one that started the " "server):" msgstr "" -#: ../../source/tutorial-quickstart-mxnet.rst:292 +#: ../../source/tutorial-quickstart-mxnet.rst:294 msgid "" "Congratulations! You've successfully built and run your first federated " "learning system. The full `source code " @@ -9802,6 +15163,7 @@ msgid "" msgstr "" #: ../../source/tutorial-quickstart-pytorch.rst:15 +#: ../../source/tutorial-quickstart-xgboost.rst:39 msgid "" "First of all, it is recommended to create a virtual environment and run " "everything within a `virtualenv `_ to learn more." +"Often, for tabular data on medium-sized datasets with fewer than 10k " +"training examples, XGBoost surpasses the results of deep learning " +"techniques." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:23 +msgid "Why federated XGBoost?" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:25 +msgid "" +"Indeed, as the demand for data privacy and decentralized learning grows, " +"there's an increasing requirement to implement federated XGBoost systems " +"for specialised applications, like survival analysis and financial fraud " +"detection." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:27 +msgid "" +"Federated learning ensures that raw data remains on the local device, " +"making it an attractive approach for sensitive domains where data " +"security and privacy are paramount. Given the robustness and efficiency " +"of XGBoost, combining it with federated learning offers a promising " +"solution for these specific challenges." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:30 +msgid "" +"In this tutorial we will learn how to train a federated XGBoost model on " +"HIGGS dataset using Flower and :code:`xgboost` package. We use a simple " +"example (`full code xgboost-quickstart " +"`_)" +" with two *clients* and one *server* to demonstrate how federated XGBoost" +" works, and then we dive into a more complex example (`full code xgboost-" +"comprehensive `_) to run various experiments." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:37 +msgid "Environment Setup" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:41 +msgid "" +"We first need to install Flower and Flower Datasets. You can do this by " +"running :" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:47 +msgid "" +"Since we want to use :code:`xgboost` package to build up XGBoost trees, " +"let's go ahead and install :code:`xgboost`:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:57 +msgid "" +"*Clients* are responsible for generating individual weight-updates for " +"the model based on their local datasets. Now that we have all our " +"dependencies installed, let's run a simple distributed training with two " +"clients and one server." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:60 +msgid "" +"In a file called :code:`client.py`, import xgboost, Flower, Flower " +"Datasets and other related functions:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:87 +msgid "Dataset partition and hyper-parameter selection" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:89 +msgid "" +"Prior to local training, we require loading the HIGGS dataset from Flower" +" Datasets and conduct data partitioning for FL:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:102 +msgid "" +"In this example, we split the dataset into two partitions with uniform " +"distribution (:code:`IidPartitioner(num_partitions=2)`). Then, we load " +"the partition for the given client based on :code:`node_id`:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:121 +msgid "" +"After that, we do train/test splitting on the given partition (client's " +"local data), and transform data format for :code:`xgboost` package." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:134 +msgid "" +"The functions of :code:`train_test_split` and " +":code:`transform_dataset_to_dmatrix` are defined as below:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:158 +msgid "Finally, we define the hyper-parameters used for XGBoost training." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:174 +msgid "" +"The :code:`num_local_round` represents the number of iterations for local" +" tree boost. We use CPU for the training in default. One can shift it to " +"GPU by setting :code:`tree_method` to :code:`gpu_hist`. We use AUC as " +"evaluation metric." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:181 +msgid "Flower client definition for XGBoost" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:183 +msgid "" +"After loading the dataset we define the Flower client. We follow the " +"general rule to define :code:`XgbClient` class inherited from " +":code:`fl.client.Client`." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:193 +msgid "" +"The :code:`self.bst` is used to keep the Booster objects that remain " +"consistent across rounds, allowing them to store predictions from trees " +"integrated in earlier rounds and maintain other essential data structures" +" for training." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:196 +msgid "" +"Then, we override :code:`get_parameters`, :code:`fit` and " +":code:`evaluate` methods insides :code:`XgbClient` class as follows." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:210 +msgid "" +"Unlike neural network training, XGBoost trees are not started from a " +"specified random weights. In this case, we do not use " +":code:`get_parameters` and :code:`set_parameters` to initialise model " +"parameters for XGBoost. As a result, let's return an empty tensor in " +":code:`get_parameters` when it is called by the server at the first " +"round." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:251 +msgid "" +"In :code:`fit`, at the first round, we call :code:`xgb.train()` to build " +"up the first set of trees. the returned Booster object and config are " +"stored in :code:`self.bst` and :code:`self.config`, respectively. From " +"the second round, we load the global model sent from server to " +":code:`self.bst`, and then update model weights on local training data " +"with function :code:`local_boost` as follows:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:269 +msgid "" +"Given :code:`num_local_round`, we update trees by calling " +":code:`self.bst.update` method. After training, the last " +":code:`N=num_local_round` trees will be extracted to send to the server." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:291 +msgid "" +"In :code:`evaluate`, we call :code:`self.bst.eval_set` function to " +"conduct evaluation on valid set. The AUC value will be returned." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:294 +msgid "" +"Now, we can create an instance of our class :code:`XgbClient` and add one" +" line to actually run this client:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:300 +msgid "" +"That's it for the client. We only have to implement :code:`Client`and " +"call :code:`fl.client.start_client()`. The string :code:`\"[::]:8080\"` " +"tells the client which server to connect to. In our case we can run the " +"server and the client on the same machine, therefore we use " +":code:`\"[::]:8080\"`. If we run a truly federated workload with the " +"server and clients running on different machines, all that needs to " +"change is the :code:`server_address` we point the client at." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:311 +msgid "" +"These updates are then sent to the *server* which will aggregate them to " +"produce a better model. Finally, the *server* sends this improved version" +" of the model back to each *client* to finish a complete FL round." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:314 +msgid "" +"In a file named :code:`server.py`, import Flower and FedXgbBagging from " +":code:`flwr.server.strategy`." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:316 +msgid "We first define a strategy for XGBoost bagging aggregation." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:339 +msgid "" +"We use two clients for this example. An " +":code:`evaluate_metrics_aggregation` function is defined to collect and " +"wighted average the AUC values from clients." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:342 +msgid "Then, we start the server:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:354 +msgid "Tree-based bagging aggregation" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:356 +msgid "" +"You must be curious about how bagging aggregation works. Let's look into " +"the details." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:358 +msgid "" +"In file :code:`flwr.server.strategy.fedxgb_bagging.py`, we define " +":code:`FedXgbBagging` inherited from :code:`flwr.server.strategy.FedAvg`." +" Then, we override the :code:`aggregate_fit`, :code:`aggregate_evaluate` " +"and :code:`evaluate` methods as follows:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:454 +msgid "" +"In :code:`aggregate_fit`, we sequentially aggregate the clients' XGBoost " +"trees by calling :code:`aggregate()` function:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:513 +msgid "" +"In this function, we first fetch the number of trees and the number of " +"parallel trees for the current and previous model by calling " +":code:`_get_tree_nums`. Then, the fetched information will be aggregated." +" After that, the trees (containing model weights) are aggregated to " +"generate a new tree model." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:518 +msgid "" +"After traversal of all clients' models, a new global model is generated, " +"followed by the serialisation, and sending back to each client." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:523 +msgid "Launch Federated XGBoost!" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:585 +msgid "" +"Congratulations! You've successfully built and run your first federated " +"XGBoost system. The AUC values can be checked in " +":code:`metrics_distributed`. One can see that the average AUC increases " +"over FL rounds." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:590 +msgid "" +"The full `source code `_ for this example can be found in :code:`examples" +"/xgboost-quickstart`." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:594 +msgid "Comprehensive Federated XGBoost" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:596 +msgid "" +"Now that you have known how federated XGBoost work with Flower, it's time" +" to run some more comprehensive experiments by customising the " +"experimental settings. In the xgboost-comprehensive example (`full code " +"`_), we provide more options to define various experimental" +" setups, including aggregation strategies, data partitioning and " +"centralised/distributed evaluation. We also support `Flower simulation " +"`_ making " +"it easy to simulate large client cohorts in a resource-aware manner. " +"Let's take a look!" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:603 +msgid "Cyclic training" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:605 +msgid "" +"In addition to bagging aggregation, we offer a cyclic training scheme, " +"which performs FL in a client-by-client fashion. Instead of aggregating " +"multiple clients, there is only one single client participating in the " +"training per round in the cyclic training scenario. The trained local " +"XGBoost trees will be passed to the next client as an initialised model " +"for next round's boosting." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:609 +msgid "" +"To do this, we first customise a :code:`ClientManager` in " +":code:`server_utils.py`:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:649 +msgid "" +"The customised :code:`ClientManager` samples all available clients in " +"each FL round based on the order of connection to the server. Then, we " +"define a new strategy :code:`FedXgbCyclic` in " +":code:`flwr.server.strategy.fedxgb_cyclic.py`, in order to sequentially " +"select only one client in given round and pass the received model to next" +" client." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:690 +msgid "" +"Unlike the original :code:`FedAvg`, we don't perform aggregation here. " +"Instead, we just make a copy of the received client model as global model" +" by overriding :code:`aggregate_fit`." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:693 +msgid "" +"Also, the customised :code:`configure_fit` and :code:`configure_evaluate`" +" methods ensure the clients to be sequentially selected given FL round:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:757 +msgid "Customised data partitioning" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:759 +msgid "" +"In :code:`dataset.py`, we have a function :code:`instantiate_partitioner`" +" to instantiate the data partitioner based on the given " +":code:`num_partitions` and :code:`partitioner_type`. Currently, we " +"provide four supported partitioner type to simulate the uniformity/non-" +"uniformity in data quantity (uniform, linear, square, exponential)." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:790 +msgid "Customised centralised/distributed evaluation" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:792 +msgid "" +"To facilitate centralised evaluation, we define a function in " +":code:`server_utils.py`:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:824 +msgid "" +"This function returns a evaluation function which instantiates a " +":code:`Booster` object and loads the global model weights to it. The " +"evaluation is conducted by calling :code:`eval_set()` method, and the " +"tested AUC value is reported." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:827 +msgid "" +"As for distributed evaluation on the clients, it's same as the quick-" +"start example by overriding the :code:`evaluate()` method insides the " +":code:`XgbClient` class in :code:`client_utils.py`." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:831 +msgid "Flower simulation" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:832 +msgid "" +"We also provide an example code (:code:`sim.py`) to use the simulation " +"capabilities of Flower to simulate federated XGBoost training on either a" +" single machine or a cluster of machines." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:866 +msgid "" +"After importing all required packages, we define a :code:`main()` " +"function to perform the simulation process:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:921 +msgid "" +"We first load the dataset and perform data partitioning, and the pre-" +"processed data is stored in a :code:`list`. After the simulation begins, " +"the clients won't need to pre-process their partitions again." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:924 +msgid "Then, we define the strategies and other hyper-parameters:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:975 +msgid "" +"After that, we start the simulation by calling " +":code:`fl.simulation.start_simulation`:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:995 +msgid "" +"One of key parameters for :code:`start_simulation` is :code:`client_fn` " +"which returns a function to construct a client. We define it as follows:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1038 +msgid "Arguments parser" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1040 +msgid "" +"In :code:`utils.py`, we define the arguments parsers for clients, server " +"and simulation, allowing users to specify different experimental " +"settings. Let's first see the sever side:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1086 +msgid "" +"This allows user to specify training strategies / the number of total " +"clients / FL rounds / participating clients / clients for evaluation, and" +" evaluation fashion. Note that with :code:`--centralised-eval`, the sever" +" will do centralised evaluation and all functionalities for client " +"evaluation will be disabled." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1090 +msgid "Then, the argument parser on client side:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1144 +msgid "" +"This defines various options for client data partitioning. Besides, " +"clients also have an option to conduct evaluation on centralised test set" +" by setting :code:`--centralised-eval`, as well as an option to perform " +"scaled learning rate based on the number of clients by setting :code" +":`--scaled-lr`." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1148 +msgid "We also have an argument parser for simulation:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1226 +msgid "This integrates all arguments for both client and server sides." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1229 +msgid "Example commands" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1231 +msgid "" +"To run a centralised evaluated experiment with bagging strategy on 5 " +"clients with exponential distribution for 50 rounds, we first start the " +"server as below:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1238 +msgid "Then, on each client terminal, we start the clients:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1244 +msgid "To run the same experiment with Flower simulation:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1250 +msgid "" +"The full `code `_ for this comprehensive example can be found in" +" :code:`examples/xgboost-comprehensive`." msgstr "" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:9 @@ -10289,7 +16145,6 @@ msgstr "" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:101 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:102 -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:104 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:101 msgid "" "It is possible to switch to a runtime that has GPU acceleration enabled " @@ -10388,7 +16243,7 @@ msgstr "" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:550 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:948 -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:749 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:729 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:715 #: ../../source/tutorial-series-what-is-federated-learning.ipynb:369 msgid "" @@ -10398,7 +16253,7 @@ msgstr "" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:552 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:950 -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:751 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:731 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:717 #: ../../source/tutorial-series-what-is-federated-learning.ipynb:371 msgid "" @@ -10742,10 +16597,11 @@ msgstr "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:13 msgid "" -"In this notebook, we'll build a federated learning system using Flower " -"and PyTorch. In part 1, we use PyTorch for the model training pipeline " -"and data loading. In part 2, we continue to federate the PyTorch-based " -"pipeline using Flower." +"In this notebook, we'll build a federated learning system using Flower, " +"`Flower Datasets `__ and PyTorch. In " +"part 1, we use PyTorch for the model training pipeline and data loading. " +"In part 2, we continue to federate the PyTorch-based pipeline using " +"Flower." msgstr "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:17 @@ -10761,23 +16617,38 @@ msgstr "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:45 msgid "" "Next, we install the necessary packages for PyTorch (``torch`` and " -"``torchvision``) and Flower (``flwr``):" +"``torchvision``), Flower Datasets (``flwr-datasets``) and Flower " +"(``flwr``):" +msgstr "" + +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:105 +msgid "" +"It is possible to switch to a runtime that has GPU acceleration enabled " +"(on Google Colab: ``Runtime > Change runtime type > Hardware accelerator:" +" GPU > Save``). Note, however, that Google Colab is not always able to " +"offer GPU acceleration. If you see an error related to GPU availability " +"in one of the following sections, consider switching back to CPU-based " +"execution by setting ``DEVICE = torch.device(\"cpu\")``. If the runtime " +"has GPU acceleration enabled, you should see the output ``Training on " +"cuda``, otherwise it'll say ``Training on cpu``." msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:117 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:118 msgid "Loading the data" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:119 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:120 msgid "" "Federated learning can be applied to many different types of tasks across" " different domains. In this tutorial, we introduce federated learning by " "training a simple convolutional neural network (CNN) on the popular " "CIFAR-10 dataset. CIFAR-10 can be used to train image classifiers that " -"distinguish between images from ten different classes:" +"distinguish between images from ten different classes: 'airplane', " +"'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', and " +"'truck'." msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:150 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:131 msgid "" "We simulate having multiple datasets from multiple organizations (also " "called the \"cross-silo\" setting in federated learning) by splitting the" @@ -10788,22 +16659,22 @@ msgid "" "data is naturally partitioned)." msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:152 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:133 msgid "" "Each organization will act as a client in the federated learning system. " "So having ten organizations participate in a federation means having ten " -"clients connected to the federated learning server:" +"clients connected to the federated learning server." msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:172 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:144 msgid "" -"Let's now load the CIFAR-10 training and test set, partition them into " -"ten smaller datasets (each split into training and validation set), and " -"wrap the resulting partitions by creating a PyTorch ``DataLoader`` for " -"each of them:" +"Let's now create the Federated Dataset abstraction that from ``flwr-" +"datasets`` that partitions the CIFAR-10. We will create small training " +"and test set for each edge device and wrap each of them into a PyTorch " +"``DataLoader``:" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:222 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:198 msgid "" "We now have a list of ten training sets and ten validation sets " "(``trainloaders`` and ``valloaders``) representing the data of ten " @@ -10815,13 +16686,13 @@ msgid "" "multiple partitions." msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:225 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:201 msgid "" "Let's take a look at the first batch of images and labels in the first " "training set (i.e., ``trainloaders[0]``) before we move on:" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:264 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:240 msgid "" "The output above shows a random batch of images from the first " "``trainloader`` in our list of ten ``trainloaders``. It also prints the " @@ -10830,11 +16701,11 @@ msgid "" "batch of images." msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:276 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:252 msgid "Step 1: Centralized Training with PyTorch" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:287 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:263 msgid "" "Next, we're going to use PyTorch to define a simple convolutional neural " "network. This introduction assumes basic familiarity with PyTorch, so it " @@ -10844,26 +16715,26 @@ msgid "" "`__." msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:299 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:275 msgid "Defining the model" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:301 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:277 msgid "" "We use the simple CNN described in the `PyTorch tutorial " "`__:" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:338 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:314 msgid "Let's continue with the usual training and test functions:" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:398 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:374 msgid "Training the model" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:400 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:376 msgid "" "We now have all the basic building blocks we need: a dataset, a model, a " "training function, and a test function. Let's put them together to train " @@ -10873,7 +16744,7 @@ msgid "" "models only on this internal data:" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:430 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:406 msgid "" "Training the simple CNN on our CIFAR-10 split for 5 epochs should result " "in a test set accuracy of about 41%, which is not good, but at the same " @@ -10882,11 +16753,11 @@ msgid "" "sets the stage for what comes next - federated learning!" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:442 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:418 msgid "Step 2: Federated Learning with Flower" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:444 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:420 msgid "" "Step 1 demonstrated a simple centralized training pipeline. All data was " "in one place (i.e., a single ``trainloader`` and a single ``valloader``)." @@ -10895,11 +16766,11 @@ msgid "" "organizations using federated learning." msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:456 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:432 msgid "Updating model parameters" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:458 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:434 msgid "" "In federated learning, the server sends the global model parameters to " "the client, and the client updates the local model with the parameters " @@ -10910,7 +16781,7 @@ msgid "" "parameters)." msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:460 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:436 msgid "" "We need two helper functions to update the local model with parameters " "received from the server and to get the updated model parameters from the" @@ -10918,7 +16789,7 @@ msgid "" "two functions do just that for the PyTorch model above." msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:462 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:438 msgid "" "The details of how this works are not really important here (feel free to" " consult the PyTorch documentation if you want to learn more). In " @@ -10927,11 +16798,11 @@ msgid "" "ndarray's (which Flower knows how to serialize/deserialize):" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:490 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:466 msgid "Implementing a Flower client" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:492 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:468 msgid "" "With that out of the way, let's move on to the interesting part. " "Federated learning systems consist of a server and multiple clients. In " @@ -10941,39 +16812,39 @@ msgid "" "requires us to write less boilerplate." msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:494 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:470 msgid "" "To implement the Flower client, we create a subclass of " "``flwr.client.NumPyClient`` and implement the three methods " "``get_parameters``, ``fit``, and ``evaluate``:" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:496 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:472 msgid "``get_parameters``: Return the current local model parameters" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:497 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:473 msgid "" "``fit``: Receive model parameters from the server, train the model " "parameters on the local data, and return the (updated) model parameters " "to the server" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:498 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:474 msgid "" "``evaluate``: Receive model parameters from the server, evaluate the " "model parameters on the local data, and return the evaluation result to " "the server" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:500 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:476 msgid "" "We mentioned that our clients will use the previously defined PyTorch " "components for model training and evaluation. Let's see a simple Flower " "client implementation that brings everything together:" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:537 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:513 msgid "" "Our class ``FlowerClient`` defines how local training/evaluation will be " "performed and allows Flower to call the local training/evaluation through" @@ -10988,11 +16859,11 @@ msgid "" "evaluation)." msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:541 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:517 msgid "Using the Virtual Client Engine" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:543 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:519 msgid "" "In this notebook, we want to simulate a federated learning system with 10" " clients on a single machine. This means that the server and all 10 " @@ -11003,7 +16874,7 @@ msgid "" "clients participates in a single round of federated learning." msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:545 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:521 msgid "" "In addition to the regular capabilities where server and clients run on " "multiple machines, Flower, therefore, provides special simulation " @@ -11019,11 +16890,11 @@ msgid "" "different clients, as can be seen below:" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:580 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:556 msgid "Starting the training" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:582 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:558 msgid "" "We now have the class ``FlowerClient`` which defines client-side " "training/evaluation and ``client_fn`` which allows Flower to create " @@ -11032,7 +16903,7 @@ msgid "" "actual simulation using ``flwr.simulation.start_simulation``." msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:584 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:560 msgid "" "The function ``start_simulation`` accepts a number of arguments, amongst " "them the ``client_fn`` used to create ``FlowerClient`` instances, the " @@ -11042,7 +16913,7 @@ msgid "" "*Federated Averaging* (FedAvg)." msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:586 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:562 msgid "" "Flower has a number of built-in strategies, but we can also use our own " "strategy implementations to customize nearly all aspects of the federated" @@ -11052,15 +16923,15 @@ msgid "" "starts the simulation:" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:628 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:608 msgid "Behind the scenes" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:630 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:610 msgid "So how does this work? How does Flower execute this simulation?" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:632 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:612 #, python-format msgid "" "When we call ``start_simulation``, we tell Flower that there are 10 " @@ -11070,7 +16941,7 @@ msgid "" "ahead and selects 10 random clients (i.e., 100% of 10)." msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:634 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:614 msgid "" "Flower then asks the selected 10 clients to train the model. When the " "server receives the model parameter updates from the clients, it hands " @@ -11079,17 +16950,17 @@ msgid "" " then gets used in the next round of federated learning." msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:646 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:626 msgid "Where's the accuracy?" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:648 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:628 msgid "" "You may have noticed that all metrics except for ``losses_distributed`` " "are empty. Where did the ``{\"accuracy\": float(accuracy)}`` go?" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:650 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:630 msgid "" "Flower can automatically aggregate losses returned by individual clients," " but it cannot do the same for metrics in the generic metrics dictionary " @@ -11099,7 +16970,7 @@ msgid "" "handle these automatically." msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:652 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:632 msgid "" "As users, we need to tell the framework how to handle/aggregate these " "custom metrics, and we do so by passing metric aggregation functions to " @@ -11109,19 +16980,19 @@ msgid "" "``evaluate_metrics_aggregation_fn``." msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:654 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:634 msgid "" "Let's create a simple weighted averaging function to aggregate the " "``accuracy`` metric we return from ``evaluate``:" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:680 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:660 msgid "" "The only thing left to do is to tell the strategy to call this function " "whenever it receives evaluation metric dictionaries from the clients:" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:717 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:697 msgid "" "We now have a full system that performs federated training and federated " "evaluation. It uses the ``weighted_average`` function to aggregate custom" @@ -11129,7 +17000,7 @@ msgid "" "all clients on the server side." msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:719 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:699 msgid "" "The other two categories of metrics (``losses_centralized`` and " "``metrics_centralized``) are still empty because they only apply when " @@ -11137,12 +17008,12 @@ msgid "" "will cover centralized evaluation." msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:731 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:711 #: ../../source/tutorial-series-what-is-federated-learning.ipynb:351 msgid "Final remarks" msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:733 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:713 msgid "" "Congratulations, you just trained a convolutional neural network, " "federated over 10 clients! With that, you understand the basics of " @@ -11152,7 +17023,7 @@ msgid "" "Transformers or speech with SpeechBrain." msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:735 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:715 msgid "" "In the next notebook, we're going to cover some more advanced concepts. " "Want to customize your strategy? Initialize parameters on the server " @@ -11160,7 +17031,7 @@ msgid "" "all this and more in the next tutorial." msgstr "" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:753 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:733 msgid "" "The `Flower Federated Learning Tutorial - Part 2 " "`_." +#~ msgstr "" + +#~ msgid "" +#~ "``flwr = { path = " +#~ "\"../../dist/flwr-1.0.0-py3-none-any.whl\" }`` " +#~ "(without extras)" +#~ msgstr "" + +#~ msgid "" +#~ "``flwr = { path = " +#~ "\"../../dist/flwr-1.0.0-py3-none-any.whl\", extras =" +#~ " [\"simulation\"] }`` (with extras)" +#~ msgstr "" + +#~ msgid "Upload the whl (e.g., ``flwr-1.7.0-py3-none-any.whl``)" +#~ msgstr "" + +#~ msgid "" +#~ "Change ``!pip install -q 'flwr[simulation]'" +#~ " torch torchvision matplotlib`` to ``!pip" +#~ " install -q 'flwr-1.7.0-py3-none-" +#~ "any.whl[simulation]' torch torchvision matplotlib``" +#~ msgstr "" + +#~ msgid "Before the release" +#~ msgstr "" + +#~ msgid "" +#~ "Update the changelog (``changelog.md``) with" +#~ " all relevant changes that happened " +#~ "after the last release. If the " +#~ "last release was tagged ``v1.2.0``, you" +#~ " can use the following URL to " +#~ "see all commits that got merged " +#~ "into ``main`` since then:" +#~ msgstr "" + +#~ msgid "" +#~ "`GitHub: Compare v1.2.0...main " +#~ "`_" +#~ msgstr "" + +#~ msgid "" +#~ "Thank the authors who contributed since" +#~ " the last release. This can be " +#~ "done by running the ``./dev/add-" +#~ "shortlog.sh`` convenience script (it can " +#~ "be ran multiple times and will " +#~ "update the names in the list if" +#~ " new contributors were added in the" +#~ " meantime)." +#~ msgstr "" + +#~ msgid "" +#~ "Update the ``changelog.md`` section header " +#~ "``Unreleased`` to contain the version " +#~ "number and date for the release " +#~ "you are building. Create a pull " +#~ "request with the change." +#~ msgstr "" + +#~ msgid "" +#~ "Tag the release commit with the " +#~ "version number as soon as the PR" +#~ " is merged: ``git tag v0.12.3``, then" +#~ " ``git push --tags``. This will " +#~ "create a draft release on GitHub " +#~ "containing the correct artifacts and the" +#~ " relevant part of the changelog." +#~ msgstr "" + +#~ msgid "" +#~ "Note that, in order to build the" +#~ " documentation locally (with ``poetry run" +#~ " make html``, like described below), " +#~ "`Pandoc _` needs " +#~ "to be installed on the system." +#~ msgstr "" + +#~ msgid "" +#~ "If you're familiar with how contributing" +#~ " on GitHub works, you can directly" +#~ " checkout our `getting started guide " +#~ "for contributors `_ and examples " +#~ "of `good first contributions " +#~ "`_." +#~ msgstr "" + +#~ msgid "" +#~ "This will create a `flower/` (or " +#~ "the name of your fork if you " +#~ "renamed it) folder in the current " +#~ "working directory." +#~ msgstr "" + +#~ msgid "Otherwise you can always find this option in the `Branches` page." +#~ msgstr "" + +#~ msgid "" +#~ "Once you click the `Compare & pull" +#~ " request` button, you should see " +#~ "something similar to this:" +#~ msgstr "" + +#~ msgid "Find the source file in `doc/source`" +#~ msgstr "" + +#~ msgid "" +#~ "Make the change in the `.rst` file" +#~ " (beware, the dashes under the title" +#~ " should be the same length as " +#~ "the title itself)" +#~ msgstr "" + +#~ msgid "Change the file name to `save-progress.rst`" +#~ msgstr "" + +#~ msgid "Add a redirect rule to `doc/source/conf.py`" +#~ msgstr "" + +#~ msgid "" +#~ "This will cause a redirect from " +#~ "`saving-progress.html` to `save-progress.html`," +#~ " old links will continue to work." +#~ msgstr "" + +#~ msgid "" +#~ "For the lateral navigation bar to " +#~ "work properly, it is very important " +#~ "to update the `index.rst` file as " +#~ "well. This is where we define the" +#~ " whole arborescence of the navbar." +#~ msgstr "" + +#~ msgid "Find and modify the file name in `index.rst`" +#~ msgstr "" + +#~ msgid "Add CI job to deploy the staging system when the `main` branch changes" +#~ msgstr "" + +#~ msgid "`Python 3.7 `_ or above" +#~ msgstr "" + +#~ msgid "" +#~ "First, clone the `Flower repository " +#~ "`_ from GitHub::" +#~ msgstr "" + +#~ msgid "" +#~ "Second, create a virtual environment " +#~ "(and activate it). If you chose to" +#~ " use :code:`pyenv` (with the :code" +#~ ":`pyenv-virtualenv` plugin) and already " +#~ "have it installed , you can use" +#~ " the following convenience script (by " +#~ "default it will use :code:`Python " +#~ "3.8.17`, but you can change it by" +#~ " providing a specific :code:``)::" +#~ msgstr "" + +#~ msgid "" +#~ "If you don't have :code:`pyenv` " +#~ "installed, you can use the following " +#~ "script that will install pyenv, set " +#~ "it up and create the virtual " +#~ "environment (with :code:`Python 3.8.17` by " +#~ "default)::" +#~ msgstr "" + +#~ msgid "" +#~ "Third, install the Flower package in " +#~ "development mode (think :code:`pip install " +#~ "-e`) along with all necessary " +#~ "dependencies::" +#~ msgstr "" + +#~ msgid "" +#~ "Developers could run the full set " +#~ "of Github Actions workflows under their" +#~ " local environment by using `Act " +#~ "_`. Please refer to" +#~ " the installation instructions under the" +#~ " linked repository and run the next" +#~ " command under Flower main cloned " +#~ "repository folder::" +#~ msgstr "" + +#~ msgid "" +#~ "Please note that these components are" +#~ " still experimental, the correct " +#~ "configuration of DP for a specific " +#~ "task is still an unsolved problem." +#~ msgstr "" + +#~ msgid "" +#~ "The distribution of the update norm " +#~ "has been shown to vary from " +#~ "task-to-task and to evolve as " +#~ "training progresses. Therefore, we use " +#~ "an adaptive approach [andrew]_ that " +#~ "continuously adjusts the clipping threshold" +#~ " to track a prespecified quantile of" +#~ " the update norm distribution." +#~ msgstr "" + +#~ msgid "" +#~ "We make (and attempt to enforce) a" +#~ " number of assumptions that must be" +#~ " satisfied to ensure that the " +#~ "training process actually realises the " +#~ ":math:`(\\epsilon, \\delta)` guarantees the " +#~ "user has in mind when configuring " +#~ "the setup." +#~ msgstr "" + +#~ msgid "" +#~ "The first two are useful for " +#~ "eliminating a multitude of complications " +#~ "associated with calibrating the noise to" +#~ " the clipping threshold while the " +#~ "third one is required to comply " +#~ "with the assumptions of the privacy " +#~ "analysis." +#~ msgstr "" + +#~ msgid "" +#~ "The first version of our solution " +#~ "was to define a decorator whose " +#~ "constructor accepted, among other things, " +#~ "a boolean valued variable indicating " +#~ "whether adaptive clipping was to be " +#~ "enabled or not. We quickly realized " +#~ "that this would clutter its " +#~ ":code:`__init__()` function with variables " +#~ "corresponding to hyperparameters of adaptive" +#~ " clipping that would remain unused " +#~ "when it was disabled. A cleaner " +#~ "implementation could be achieved by " +#~ "splitting the functionality into two " +#~ "decorators, :code:`DPFedAvgFixed` and " +#~ ":code:`DPFedAvgAdaptive`, with the latter sub-" +#~ " classing the former. The constructors " +#~ "for both classes accept a boolean " +#~ "parameter :code:`server_side_noising`, which, as " +#~ "the name suggests, determines where " +#~ "noising is to be performed." +#~ msgstr "" + +#~ msgid "" +#~ ":code:`aggregate_fit()`: We check whether any" +#~ " of the sampled clients dropped out" +#~ " or failed to upload an update " +#~ "before the round timed out. In " +#~ "that case, we need to abort the" +#~ " current round, discarding any successful" +#~ " updates that were received, and move" +#~ " on to the next one. On the " +#~ "other hand, if all clients responded " +#~ "successfully, we must force the " +#~ "averaging of the updates to happen " +#~ "in an unweighted manner by intercepting" +#~ " the :code:`parameters` field of " +#~ ":code:`FitRes` for each received update " +#~ "and setting it to 1. Furthermore, " +#~ "if :code:`server_side_noising=true`, each update " +#~ "is perturbed with an amount of " +#~ "noise equal to what it would have" +#~ " been subjected to had client-side" +#~ " noising being enabled. This entails " +#~ "*pre*-processing of the arguments to " +#~ "this method before passing them on " +#~ "to the wrappee's implementation of " +#~ ":code:`aggregate_fit()`." +#~ msgstr "" + +#~ msgid "" +#~ "McMahan, H. Brendan, et al. \"Learning" +#~ " differentially private recurrent language " +#~ "models.\" arXiv preprint arXiv:1710.06963 " +#~ "(2017)." +#~ msgstr "" + +#~ msgid "" +#~ "Andrew, Galen, et al. \"Differentially " +#~ "private learning with adaptive clipping.\" " +#~ "Advances in Neural Information Processing " +#~ "Systems 34 (2021): 17455-17466." +#~ msgstr "" + +#~ msgid "" +#~ "The following command can be used " +#~ "to verfiy if Flower was successfully " +#~ "installed. If everything worked, it " +#~ "should print the version of Flower " +#~ "to the command line::" +#~ msgstr "" + +#~ msgid "flwr (Python API reference)" +#~ msgstr "" + +#~ msgid "start_client" +#~ msgstr "" + +#~ msgid "start_numpy_client" +#~ msgstr "" + +#~ msgid "start_simulation" +#~ msgstr "" + +#~ msgid "server.start_server" +#~ msgstr "" + +#~ msgid "server.strategy" +#~ msgstr "" + +#~ msgid "server.strategy.Strategy" +#~ msgstr "" + +#~ msgid "server.strategy.FedAvg" +#~ msgstr "" + +#~ msgid "server.strategy.FedAvgM" +#~ msgstr "" + +#~ msgid "server.strategy.FedMedian" +#~ msgstr "" + +#~ msgid "server.strategy.QFedAvg" +#~ msgstr "" + +#~ msgid "server.strategy.FaultTolerantFedAvg" +#~ msgstr "" + +#~ msgid "server.strategy.FedOpt" +#~ msgstr "" + +#~ msgid "server.strategy.FedProx" +#~ msgstr "" + +#~ msgid "server.strategy.FedAdagrad" +#~ msgstr "" + +#~ msgid "server.strategy.FedAdam" +#~ msgstr "" + +#~ msgid "server.strategy.FedYogi" +#~ msgstr "" + +#~ msgid "server.strategy.FedTrimmedAvg" +#~ msgstr "" + +#~ msgid "server.strategy.Krum" +#~ msgstr "" + +#~ msgid "server.strategy.FedXgbNnAvg" +#~ msgstr "" + +#~ msgid "server.strategy.DPFedAvgAdaptive" +#~ msgstr "" + +#~ msgid "server.strategy.DPFedAvgFixed" +#~ msgstr "" + +#~ msgid "" +#~ "**Fix the incorrect return types of " +#~ "Strategy** " +#~ "([#2432](https://github.com/adap/flower/pull/2432/files))" +#~ msgstr "" + +#~ msgid "" +#~ "The types of the return values in" +#~ " the docstrings in two methods " +#~ "(`aggregate_fit` and `aggregate_evaluate`) now " +#~ "match the hint types in the code." +#~ msgstr "" + +#~ msgid "" +#~ "Using the `client_fn`, Flower clients " +#~ "can interchangeably run as standalone " +#~ "processes (i.e. via `start_client`) or " +#~ "in simulation (i.e. via `start_simulation`)" +#~ " without requiring changes to how the" +#~ " client class is defined and " +#~ "instantiated. Calling `start_numpy_client` is " +#~ "now deprecated." +#~ msgstr "" + +#~ msgid "" +#~ "**Update Flower Examples** " +#~ "([#2384](https://github.com/adap/flower/pull/2384)), " +#~ "([#2425](https://github.com/adap/flower/pull/2425))" +#~ msgstr "" + +#~ msgid "" +#~ "**General updates to baselines** " +#~ "([#2301](https://github.com/adap/flower/pull/2301), " +#~ "[#2305](https://github.com/adap/flower/pull/2305), " +#~ "[#2307](https://github.com/adap/flower/pull/2307), " +#~ "[#2327](https://github.com/adap/flower/pull/2327), " +#~ "[#2435](https://github.com/adap/flower/pull/2435))" +#~ msgstr "" + +#~ msgid "" +#~ "**General updates to the simulation " +#~ "engine** ([#2331](https://github.com/adap/flower/pull/2331), " +#~ "[#2447](https://github.com/adap/flower/pull/2447), " +#~ "[#2448](https://github.com/adap/flower/pull/2448))" +#~ msgstr "" + +#~ msgid "" +#~ "**General improvements** " +#~ "([#2309](https://github.com/adap/flower/pull/2309), " +#~ "[#2310](https://github.com/adap/flower/pull/2310), " +#~ "[2313](https://github.com/adap/flower/pull/2313), " +#~ "[#2316](https://github.com/adap/flower/pull/2316), " +#~ "[2317](https://github.com/adap/flower/pull/2317),[#2349](https://github.com/adap/flower/pull/2349)," +#~ " [#2360](https://github.com/adap/flower/pull/2360), " +#~ "[#2402](https://github.com/adap/flower/pull/2402), " +#~ "[#2446](https://github.com/adap/flower/pull/2446))" +#~ msgstr "" + +#~ msgid "" +#~ "`flower-superlink --driver-api-address " +#~ "\"0.0.0.0:8081\" --fleet-api-address " +#~ "\"0.0.0.0:8086\"`" +#~ msgstr "" + +#~ msgid "" +#~ "That's it for the client. We only" +#~ " have to implement :code:`Client` or " +#~ ":code:`NumPyClient` and call " +#~ ":code:`fl.client.start_client()`. The string " +#~ ":code:`\"0.0.0.0:8080\"` tells the client " +#~ "which server to connect to. In our" +#~ " case we can run the server and" +#~ " the client on the same machine, " +#~ "therefore we use :code:`\"0.0.0.0:8080\"`. If" +#~ " we run a truly federated workload" +#~ " with the server and clients running" +#~ " on different machines, all that " +#~ "needs to change is the " +#~ ":code:`server_address` we pass to the " +#~ "client." +#~ msgstr "" + +#~ msgid "" +#~ "That's it for the client. We only" +#~ " have to implement :code:`Client` or " +#~ ":code:`NumPyClient` and call " +#~ ":code:`fl.client.start_client()`. The string " +#~ ":code:`\"[::]:8080\"` tells the client which" +#~ " server to connect to. In our " +#~ "case we can run the server and " +#~ "the client on the same machine, " +#~ "therefore we use :code:`\"[::]:8080\"`. If " +#~ "we run a truly federated workload " +#~ "with the server and clients running " +#~ "on different machines, all that needs" +#~ " to change is the :code:`server_address`" +#~ " we point the client at." +#~ msgstr "" + +#~ msgid "" +#~ "Let's build a horizontal federated " +#~ "learning system using XGBoost and " +#~ "Flower!" +#~ msgstr "" + +#~ msgid "" +#~ "Please refer to the `full code " +#~ "example `_ to learn " +#~ "more." +#~ msgstr "" + +#~ msgid "" +#~ "In this notebook, we'll build a " +#~ "federated learning system using Flower " +#~ "and PyTorch. In part 1, we use " +#~ "PyTorch for the model training pipeline" +#~ " and data loading. In part 2, " +#~ "we continue to federate the PyTorch-" +#~ "based pipeline using Flower." +#~ msgstr "" + +#~ msgid "" +#~ "Next, we install the necessary packages" +#~ " for PyTorch (``torch`` and " +#~ "``torchvision``) and Flower (``flwr``):" +#~ msgstr "" + +#~ msgid "" +#~ "Federated learning can be applied to " +#~ "many different types of tasks across " +#~ "different domains. In this tutorial, we" +#~ " introduce federated learning by training" +#~ " a simple convolutional neural network " +#~ "(CNN) on the popular CIFAR-10 dataset." +#~ " CIFAR-10 can be used to train " +#~ "image classifiers that distinguish between " +#~ "images from ten different classes:" +#~ msgstr "" + +#~ msgid "" +#~ "Each organization will act as a " +#~ "client in the federated learning system." +#~ " So having ten organizations participate" +#~ " in a federation means having ten " +#~ "clients connected to the federated " +#~ "learning server:" +#~ msgstr "" + +#~ msgid "" +#~ "Let's now load the CIFAR-10 training " +#~ "and test set, partition them into " +#~ "ten smaller datasets (each split into" +#~ " training and validation set), and " +#~ "wrap the resulting partitions by " +#~ "creating a PyTorch ``DataLoader`` for " +#~ "each of them:" +#~ msgstr "" + +#~ msgid "|ed6498a023f2477a9ccd57ee4514bda4|" +#~ msgstr "" + +#~ msgid "|5a4f742489ac4f819afefdd4dc9ab272|" +#~ msgstr "" + +#~ msgid "|3331c80cd05045f6a56524d8e3e76d0c|" +#~ msgstr "" + +#~ msgid "|4987b26884ec4b2c8f06c1264bcebe60|" +#~ msgstr "" + +#~ msgid "|ec8ae2d778aa493a986eb2fa29c220e5|" +#~ msgstr "" + +#~ msgid "|b8949d0669fe4f8eadc9a4932f4e9c57|" +#~ msgstr "" + +#~ msgid "|94ff30bdcd09443e8488b5f29932a541|" +#~ msgstr "" + +#~ msgid "|48dccf1d6d0544bba8917d2783a47719|" +#~ msgstr "" + +#~ msgid "|0366618db96b4f329f0d4372d1150fde|" +#~ msgstr "" + +#~ msgid "|ac80eddc76e6478081b1ca35eed029c0|" +#~ msgstr "" + +#~ msgid "|1ac94140c317450e89678db133c7f3c2|" +#~ msgstr "" + +#~ msgid "|f8850c6e96fc4430b55e53bba237a7c0|" +#~ msgstr "" + +#~ msgid "|4a368fdd3fc34adabd20a46752a68582|" +#~ msgstr "" + +#~ msgid "|40f69c17bb444652a7c8dfe577cd120e|" +#~ msgstr "" + diff --git a/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po b/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po index 4d63193f8e9e..a627c41c9277 100644 --- a/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po +++ b/doc/locales/zh_Hans/LC_MESSAGES/framework-docs.po @@ -7,17 +7,16 @@ msgid "" msgstr "" "Project-Id-Version: Flower main\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-11-23 18:31+0100\n" +"POT-Creation-Date: 2024-02-13 11:23+0100\n" "PO-Revision-Date: 2024-02-10 11:56+0000\n" "Last-Translator: Yan Gao \n" -"Language-Team: Chinese (Simplified) \n" "Language: zh_Hans\n" +"Language-Team: Chinese (Simplified) \n" +"Plural-Forms: nplurals=1; plural=0;\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 5.4-dev\n" "Generated-By: Babel 2.13.1\n" #: ../../source/contributor-explanation-architecture.rst:2 @@ -30,8 +29,8 @@ msgstr "边缘客户端引擎" #: ../../source/contributor-explanation-architecture.rst:7 msgid "" -"`Flower `_ core framework architecture with Edge Client " -"Engine" +"`Flower `_ core framework architecture with Edge " +"Client Engine" msgstr "具有边缘客户端引擎的`Flower `核心架构" #: ../../source/contributor-explanation-architecture.rst:13 @@ -50,136 +49,243 @@ msgstr "可同步进行的虚拟客户端引擎和边缘客户端引擎" #: ../../source/contributor-explanation-architecture.rst:23 msgid "" -"`Flower `_ core framework architecture with both Virtual " -"Client Engine and Edge Client Engine" -msgstr "" -"具有虚拟客户端引擎和边缘客户端引擎的`Flower `核心架构" +"`Flower `_ core framework architecture with both " +"Virtual Client Engine and Edge Client Engine" +msgstr "具有虚拟客户端引擎和边缘客户端引擎的`Flower `核心架构" -#: ../../source/contributor-how-create-new-messages.rst:2 -msgid "Creating New Messages" -msgstr "创建新信息" +#: ../../source/contributor-how-to-build-docker-images.rst:2 +msgid "How to build Docker Flower images locally" +msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:4 +#: ../../source/contributor-how-to-build-docker-images.rst:4 msgid "" -"This is a simple guide for creating a new type of message between the server " -"and clients in Flower." -msgstr "这是一个如何用Flower在服务器和客户端之间创建新类型的信息的简要指导。" +"Flower provides pre-made docker images on `Docker Hub " +"`_ that include all necessary " +"dependencies for running the server. You can also build your own custom " +"docker images from scratch with a different version of Python or Ubuntu " +"if that is what you need. In this guide, we will explain what images " +"exist and how to build them locally." +msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:6 +#: ../../source/contributor-how-to-build-docker-images.rst:9 msgid "" -"Let's suppose we have the following example functions in :code:`server.py` " -"and :code:`numpy_client.py`..." +"Before we can start, we need to meet a few prerequisites in our local " +"development environment." msgstr "" -"假设我们在脚本code:`server.py`和code:`numpy_client.py`中有以下的示例函数..." -#: ../../source/contributor-how-create-new-messages.rst:8 -msgid "Server's side:" -msgstr "在服务器端:" +#: ../../source/contributor-how-to-build-docker-images.rst:11 +#, fuzzy +msgid "Clone the flower repository." +msgstr "**叉花仓库**" -#: ../../source/contributor-how-create-new-messages.rst:17 -msgid "Client's side:" -msgstr "在客户端:" +#: ../../source/contributor-how-to-build-docker-images.rst:17 +msgid "Verify the Docker daemon is running." +msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:26 +#: ../../source/contributor-how-to-build-docker-images.rst:19 msgid "" -"Let's now see what we need to implement in order to get this simple function " -"between the server and client to work!" +"Please follow the first section on `Run Flower using Docker " +"`_ " +"which covers this step in more detail." msgstr "" -"现在让我们来看看,为了让服务器和客户端之间的这个简单的函数正常工作,我们需要" -"实现哪些功能!" -#: ../../source/contributor-how-create-new-messages.rst:30 -msgid "Message Types for Protocol Buffers" -msgstr "协议缓冲区的信息类型" +#: ../../source/contributor-how-to-build-docker-images.rst:23 +msgid "" +"Currently, Flower provides two images, a base image and a server image. " +"There will also be a client image soon. The base image, as the name " +"suggests, contains basic dependencies that both the server and the client" +" need. This includes system dependencies, Python and Python tools. The " +"server image is based on the base image, but it additionally installs the" +" Flower server using ``pip``." +msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:32 +#: ../../source/contributor-how-to-build-docker-images.rst:28 msgid "" -"The first thing we need to do is to define a message type for the RPC system " -"in :code:`transport.proto`. Note that we have to do it for both the request " -"and response messages. For more details on the syntax of proto3, please see " -"the `official documentation `_." +"The build instructions that assemble the images are located in the " +"respective Dockerfiles. You can find them in the subdirectories of " +"``src/docker``." msgstr "" -"我们需要做的第一件事是在脚本code:`transport.proto`中定义 RPC 系统的消息类型。" -"请注意,我们必须对请求信息和响应信息都这样做。有关 proto3 语法的更多详情,请" -"参阅官方文档 `_。" -#: ../../source/contributor-how-create-new-messages.rst:35 -msgid "Within the :code:`ServerMessage` block:" -msgstr "在 :code:`ServerMessage` 代码块中:" +#: ../../source/contributor-how-to-build-docker-images.rst:31 +msgid "" +"Both, base and server image are configured via build arguments. Through " +"build arguments, we can make our build more flexible. For example, in the" +" base image, we can specify the version of Python to install using the " +"``PYTHON_VERSION`` build argument. Some of the build arguments have " +"default values, others must be specified when building the image. All " +"available build arguments for each image are listed in one of the tables " +"below." +msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:52 -msgid "Within the ClientMessage block:" -msgstr "在 ClientMessage 代码块中:" +#: ../../source/contributor-how-to-build-docker-images.rst:38 +#, fuzzy +msgid "Building the base image" +msgstr "加载数据" -#: ../../source/contributor-how-create-new-messages.rst:70 -msgid "" -"Make sure to also add a field of the newly created message type in :code:" -"`oneof msg`." -msgstr "确保在 :code:`oneof msg` 中也添加一个新创建的消息类型字段。" +#: ../../source/contributor-how-to-build-docker-images.rst:44 +#: ../../source/contributor-how-to-build-docker-images.rst:86 +#, fuzzy +msgid "Build argument" +msgstr "构建文档" -#: ../../source/contributor-how-create-new-messages.rst:72 -msgid "Once that is done, we will compile the file with:" -msgstr "完成后,我们将使用:" +#: ../../source/contributor-how-to-build-docker-images.rst:45 +#: ../../source/contributor-how-to-build-docker-images.rst:87 +#, fuzzy +msgid "Description" +msgstr "停用" -#: ../../source/contributor-how-create-new-messages.rst:78 -msgid "If it compiles succesfully, you should see the following message:" -msgstr "如果编译成功,你应该会看到以下信息:" +#: ../../source/contributor-how-to-build-docker-images.rst:46 +#: ../../source/contributor-how-to-build-docker-images.rst:88 +#, fuzzy +msgid "Required" +msgstr "所需变更" -#: ../../source/contributor-how-create-new-messages.rst:87 -msgid "Serialization and Deserialization Functions" -msgstr "序列化和反序列化函数" +#: ../../source/contributor-how-to-build-docker-images.rst:47 +#: ../../source/contributor-how-to-build-docker-images.rst:89 +#, fuzzy +msgid "Example" +msgstr "实例" -#: ../../source/contributor-how-create-new-messages.rst:89 -msgid "" -"Our next step is to add functions to serialize and deserialize Python " -"datatypes to or from our defined RPC message types. You should add these " -"functions in :code:`serde.py`." +#: ../../source/contributor-how-to-build-docker-images.rst:48 +#, fuzzy +msgid "``PYTHON_VERSION``" +msgstr "Python 版本" + +#: ../../source/contributor-how-to-build-docker-images.rst:49 +msgid "Version of ``python`` to be installed." msgstr "" -"下一步是添加函数,以便将 Python 数据类型序列化和反序列化为我们定义的 RPC 消息" -"类型或从我们定义的 RPC 消息类型反序列化和反序列化 Python 数据类型。您应该在 :" -"code:`serde.py` 中添加这些函数。" -#: ../../source/contributor-how-create-new-messages.rst:91 -msgid "The four functions:" -msgstr "四种函数:" +#: ../../source/contributor-how-to-build-docker-images.rst:50 +#: ../../source/contributor-how-to-build-docker-images.rst:54 +#: ../../source/contributor-how-to-build-docker-images.rst:58 +#: ../../source/contributor-how-to-build-docker-images.rst:100 +#, fuzzy +msgid "Yes" +msgstr "类型" -#: ../../source/contributor-how-create-new-messages.rst:112 -msgid "Sending the Message from the Server" -msgstr "从服务器发送信息" +#: ../../source/contributor-how-to-build-docker-images.rst:51 +#, fuzzy +msgid "``3.11``" +msgstr "``1.0.0rc1``" + +#: ../../source/contributor-how-to-build-docker-images.rst:52 +msgid "``PIP_VERSION``" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:53 +msgid "Version of ``pip`` to be installed." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:55 +#, fuzzy +msgid "``23.0.1``" +msgstr "``1.0.0rc1``" + +#: ../../source/contributor-how-to-build-docker-images.rst:56 +msgid "``SETUPTOOLS_VERSION``" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:57 +msgid "Version of ``setuptools`` to be installed." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:59 +#, fuzzy +msgid "``69.0.2``" +msgstr "``1.0.0b0``" + +#: ../../source/contributor-how-to-build-docker-images.rst:60 +msgid "``UBUNTU_VERSION``" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:61 +msgid "Version of the official Ubuntu Docker image." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:62 +msgid "Defaults to ``22.04``." +msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:114 +#: ../../source/contributor-how-to-build-docker-images.rst:65 msgid "" -"Now write the request function in your Client Proxy class (e.g., :code:" -"`grpc_client_proxy.py`) using the serde functions you just created:" +"The following example creates a base image with Python 3.11.0, pip 23.0.1" +" and setuptools 69.0.2:" msgstr "" -"现在,在客户端代理类(例如 :code:`grpc_client_proxy.py`)中使用刚才创建的 " -"serde 函数编写请求函数:" -#: ../../source/contributor-how-create-new-messages.rst:128 -msgid "Receiving the Message by the Client" -msgstr "由客户端接收信息" +#: ../../source/contributor-how-to-build-docker-images.rst:76 +msgid "" +"The name of image is ``flwr_base`` and the tag ``0.1.0``. Remember that " +"the build arguments as well as the name and tag can be adapted to your " +"needs. These values serve as examples only." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:80 +#, fuzzy +msgid "Building the server image" +msgstr "启动服务器" + +#: ../../source/contributor-how-to-build-docker-images.rst:90 +msgid "``BASE_REPOSITORY``" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:91 +msgid "The repository name of the base image." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:92 +msgid "Defaults to ``flwr/server``." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:94 +msgid "``BASE_IMAGE_TAG``" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:95 +msgid "The image tag of the base image." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:96 +msgid "Defaults to ``py3.11-ubuntu22.04``." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:98 +msgid "``FLWR_VERSION``" +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:99 +msgid "Version of Flower to be installed." +msgstr "" + +#: ../../source/contributor-how-to-build-docker-images.rst:101 +#, fuzzy +msgid "``1.7.0``" +msgstr "``1.0.0b0``" -#: ../../source/contributor-how-create-new-messages.rst:130 +#: ../../source/contributor-how-to-build-docker-images.rst:103 msgid "" -"Last step! Modify the code in :code:`message_handler.py` to check the field " -"of your message and call the :code:`example_response` function. Remember to " -"use the serde functions!" +"The following example creates a server image with the official Flower " +"base image py3.11-ubuntu22.04 and Flower 1.7.0:" msgstr "" -"最后一步 修改 :code:`message_handler.py` 中的代码,检查信息的字段并调用 :" -"code:`example_response` 函数。记住使用 serde 函数!" -#: ../../source/contributor-how-create-new-messages.rst:132 -msgid "Within the handle function:" -msgstr "在句柄函数内:" +#: ../../source/contributor-how-to-build-docker-images.rst:114 +msgid "" +"The name of image is ``flwr_server`` and the tag ``0.1.0``. Remember that" +" the build arguments as well as the name and tag can be adapted to your " +"needs. These values serve as examples only." +msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:139 -msgid "And add a new function:" -msgstr "并增加一个新函数:" +#: ../../source/contributor-how-to-build-docker-images.rst:117 +msgid "" +"If you want to use your own base image instead of the official Flower " +"base image, all you need to do is set the ``BASE_REPOSITORY`` and " +"``BASE_IMAGE_TAG`` build arguments. The value of ``BASE_REPOSITORY`` must" +" match the name of your image and the value of ``BASE_IMAGE_TAG`` must " +"match the tag of your image." +msgstr "" -#: ../../source/contributor-how-create-new-messages.rst:149 -msgid "Hopefully, when you run your program you will get the intended result!" -msgstr "希望您在运行程序时能得到预期的结果!" +#: ../../source/contributor-how-to-build-docker-images.rst:131 +msgid "After creating the image, we can test whether the image is working:" +msgstr "" #: ../../source/contributor-how-to-contribute-translations.rst:2 msgid "Contribute translations" @@ -187,26 +293,25 @@ msgstr "贡献译文" #: ../../source/contributor-how-to-contribute-translations.rst:4 msgid "" -"Since `Flower 1.5 `_ we have introduced translations to our doc pages, " -"but, as you might have noticed, the translations are often imperfect. If you " -"speak languages other than English, you might be able to help us in our " -"effort to make Federated Learning accessible to as many people as possible " -"by contributing to those translations! This might also be a great " -"opportunity for those wanting to become open source contributors with little " -"prerequistes." -msgstr "" -"从 `Flower 1.5 `_ 开始,我们在文档页面中引入了翻译,但正如你可能已经" -"注意到的,这些翻译往往并不完美。如果您会说英语以外的语言,也许您可以帮助我们" -"翻译这些文档,让更多的人了解 Federated Learning!对于那些想成为开源贡献者的人" -"来说,这也是一个很好的机会。" +"Since `Flower 1.5 `_ we have introduced translations to " +"our doc pages, but, as you might have noticed, the translations are often" +" imperfect. If you speak languages other than English, you might be able " +"to help us in our effort to make Federated Learning accessible to as many" +" people as possible by contributing to those translations! This might " +"also be a great opportunity for those wanting to become open source " +"contributors with little prerequistes." +msgstr "" +"从 `Flower 1.5 `_ " +"开始,我们在文档页面中引入了翻译,但正如你可能已经注意到的,这些翻译往往并不完美。如果您会说英语以外的语言,也许您可以帮助我们翻译这些文档,让更多的人了解" +" Federated Learning!对于那些想成为开源贡献者的人来说,这也是一个很好的机会。" #: ../../source/contributor-how-to-contribute-translations.rst:13 msgid "" -"Our translation project is publicly available over on `Weblate `_, this where most of " -"the work will happen." +"Our translation project is publicly available over on `Weblate " +"`_, this " +"where most of the work will happen." msgstr "" "我们的翻译项目已在 \"Weblate `_\"上公开,大部分工作都将在这里进行。" @@ -217,41 +322,39 @@ msgstr "为现有语言作出贡献" #: ../../source/contributor-how-to-contribute-translations.rst:23 msgid "" -"The first thing you will need to do in order to contribute is to create a " -"free Weblate account on this `page `_. More information about profile settings can be found `here " +"The first thing you will need to do in order to contribute is to create a" +" free Weblate account on this `page " +"`_. More information about" +" profile settings can be found `here " "`_." msgstr "" -"您需要做的第一件事就是在本`网页`_上创建一个免费的Weblate帐户。有关个人资料设置的更多信息,请参阅`这里 " -"`_。" +"您需要做的第一件事就是在本`网页`_上创建一个免费的Weblate帐户。有关个人资料设置的更多信息,请参阅`这里" +" `_。" #: ../../source/contributor-how-to-contribute-translations.rst:29 msgid "" -"Once you are signed in to Weblate, you can navigate to the `Flower Framework " -"project `_. " -"Here, you should see the different existing languages that can be found on " -"the website." +"Once you are signed in to Weblate, you can navigate to the `Flower " +"Framework project `_. Here, you should see the different existing languages" +" that can be found on the website." msgstr "" -"登录到Weblate后,您可以导航到 \"Flower Framework \"项目`_。在这里,您可以看到网站上现有" -"的各种语言。" +"登录到Weblate后,您可以导航到 \"Flower Framework " +"\"项目`_。在这里,您可以看到网站上现有的各种语言。" #: ../../source/contributor-how-to-contribute-translations.rst:34 msgid "" -"Once you have selected the language you want to contribute to, you should " -"see a similar interface to this:" +"Once you have selected the language you want to contribute to, you should" +" see a similar interface to this:" msgstr "选择您要贡献的语言后,您应该会看到与此类似的界面:" #: ../../source/contributor-how-to-contribute-translations.rst:39 msgid "" "The most straight forward option here is to click on the ``Translate`` " -"button on the top right (in the ``Translation status`` section). This will " -"automatically bring you to the translation interface for untranslated " -"strings." -msgstr "" -"最简单的方法是点击右上角(\"翻译状态 \"部分)的 \"翻译 \"按钮。这将自动带您进" -"入未翻译字符串的翻译界面。" +"button on the top right (in the ``Translation status`` section). This " +"will automatically bring you to the translation interface for " +"untranslated strings." +msgstr "最简单的方法是点击右上角(\"翻译状态 \"部分)的 \"翻译 \"按钮。这将自动带您进入未翻译字符串的翻译界面。" #: ../../source/contributor-how-to-contribute-translations.rst:43 msgid "This is what the interface looks like:" @@ -259,46 +362,43 @@ msgstr "这就是界面的样子:" #: ../../source/contributor-how-to-contribute-translations.rst:47 msgid "" -"You input your translation in the textbox at the top and then, once you are " -"happy with it, you either press ``Save and continue`` (to save the " -"translation and go to the next untranslated string), ``Save and stay`` (to " -"save the translation and stay on the same page), ``Suggest`` (to add your " -"translation to suggestions for other users to view), or ``Skip`` (to go to " -"the next untranslated string without saving anything)." +"You input your translation in the textbox at the top and then, once you " +"are happy with it, you either press ``Save and continue`` (to save the " +"translation and go to the next untranslated string), ``Save and stay`` " +"(to save the translation and stay on the same page), ``Suggest`` (to add " +"your translation to suggestions for other users to view), or ``Skip`` (to" +" go to the next untranslated string without saving anything)." msgstr "" -"您可以在顶部的文本框中输入翻译内容,满意后按 \"保存并继续\"(保存翻译内容并转" -"到下一个未翻译的字符串)、\"保存并停留\"(保存翻译内容并停留在同一页" -"面)、\"建议\"(将您的翻译添加到建议中供其他用户查看)或 \"跳过\"(转到下一个" -"未翻译的字符串而不保存任何内容)。" +"您可以在顶部的文本框中输入翻译内容,满意后按 " +"\"保存并继续\"(保存翻译内容并转到下一个未翻译的字符串)、\"保存并停留\"(保存翻译内容并停留在同一页面)、\"建议\"(将您的翻译添加到建议中供其他用户查看)或" +" \"跳过\"(转到下一个未翻译的字符串而不保存任何内容)。" #: ../../source/contributor-how-to-contribute-translations.rst:54 msgid "" "In order to help with the translations, you can see on the bottom the " "``Nearby strings``, the ``Comments`` (from other contributors), the " "``Automatic suggestions`` (from machine translation engines), the " -"translations in ``Other languages``, and the ``History`` of translations for " -"this string." +"translations in ``Other languages``, and the ``History`` of translations " +"for this string." msgstr "" -"为了帮助翻译,您可以在底部看到 \"邻近字符串\"、\"评论\"(来自其他贡献" -"者)、\"自动建议\"(来自机器翻译引擎)、\"其他语言 \"中的翻译以及该字符串的 " -"\"历史翻译\"。" +"为了帮助翻译,您可以在底部看到 \"邻近字符串\"、\"评论\"(来自其他贡献者)、\"自动建议\"(来自机器翻译引擎)、\"其他语言 " +"\"中的翻译以及该字符串的 \"历史翻译\"。" #: ../../source/contributor-how-to-contribute-translations.rst:59 msgid "" -"On the right, under the ``String information`` section, you can also click " -"the link under ``Source string location`` in order to view the source of the " -"doc file containing the string." -msgstr "" -"在右侧的 \"字符串信息 \"部分,您还可以单击 \"源字符串位置 \"下的链接,以查看" -"包含字符串的 doc 文件的源文件。" +"On the right, under the ``String information`` section, you can also " +"click the link under ``Source string location`` in order to view the " +"source of the doc file containing the string." +msgstr "在右侧的 \"字符串信息 \"部分,您还可以单击 \"源字符串位置 \"下的链接,以查看包含字符串的 doc 文件的源文件。" #: ../../source/contributor-how-to-contribute-translations.rst:63 msgid "" -"For more information about translating using Weblate, you can check out this " -"`in-depth guide `_." +"For more information about translating using Weblate, you can check out " +"this `in-depth guide " +"`_." msgstr "" -"有关使用 Weblate 进行翻译的更多信息,您可以查看本 \"深入指南 `_\"。" +"有关使用 Weblate 进行翻译的更多信息,您可以查看本 \"深入指南 " +"`_\"。" #: ../../source/contributor-how-to-contribute-translations.rst:67 msgid "Add new languages" @@ -306,13 +406,132 @@ msgstr "添加新语言" #: ../../source/contributor-how-to-contribute-translations.rst:69 msgid "" -"If you want to add a new language, you will first have to contact us, either " -"on `Slack `_, or by opening an issue on our " -"`GitHub repo `_." +"If you want to add a new language, you will first have to contact us, " +"either on `Slack `_, or by opening an " +"issue on our `GitHub repo `_." +msgstr "" +"如果您想添加新语言,请先联系我们,可以在 `Slack `_ 上联系,也可以在我们的" +" `GitHub repo `_ 上提交问题。" + +#: ../../source/contributor-how-to-create-new-messages.rst:2 +msgid "Creating New Messages" +msgstr "创建新信息" + +#: ../../source/contributor-how-to-create-new-messages.rst:4 +msgid "" +"This is a simple guide for creating a new type of message between the " +"server and clients in Flower." +msgstr "这是一个如何用Flower在服务器和客户端之间创建新类型的信息的简要指导。" + +#: ../../source/contributor-how-to-create-new-messages.rst:6 +msgid "" +"Let's suppose we have the following example functions in " +":code:`server.py` and :code:`numpy_client.py`..." +msgstr "假设我们在脚本code:`server.py`和code:`numpy_client.py`中有以下的示例函数..." + +#: ../../source/contributor-how-to-create-new-messages.rst:8 +msgid "Server's side:" +msgstr "在服务器端:" + +#: ../../source/contributor-how-to-create-new-messages.rst:17 +msgid "Client's side:" +msgstr "在客户端:" + +#: ../../source/contributor-how-to-create-new-messages.rst:26 +msgid "" +"Let's now see what we need to implement in order to get this simple " +"function between the server and client to work!" +msgstr "现在让我们来看看,为了让服务器和客户端之间的这个简单的函数正常工作,我们需要实现哪些功能!" + +#: ../../source/contributor-how-to-create-new-messages.rst:30 +msgid "Message Types for Protocol Buffers" +msgstr "协议缓冲区的信息类型" + +#: ../../source/contributor-how-to-create-new-messages.rst:32 +msgid "" +"The first thing we need to do is to define a message type for the RPC " +"system in :code:`transport.proto`. Note that we have to do it for both " +"the request and response messages. For more details on the syntax of " +"proto3, please see the `official documentation " +"`_." +msgstr "" +"我们需要做的第一件事是在脚本code:`transport.proto`中定义 RPC " +"系统的消息类型。请注意,我们必须对请求信息和响应信息都这样做。有关 proto3 语法的更多详情,请参阅官方文档 " +"`_。" + +#: ../../source/contributor-how-to-create-new-messages.rst:35 +msgid "Within the :code:`ServerMessage` block:" +msgstr "在 :code:`ServerMessage` 代码块中:" + +#: ../../source/contributor-how-to-create-new-messages.rst:52 +msgid "Within the ClientMessage block:" +msgstr "在 ClientMessage 代码块中:" + +#: ../../source/contributor-how-to-create-new-messages.rst:70 +msgid "" +"Make sure to also add a field of the newly created message type in " +":code:`oneof msg`." +msgstr "确保在 :code:`oneof msg` 中也添加一个新创建的消息类型字段。" + +#: ../../source/contributor-how-to-create-new-messages.rst:72 +msgid "Once that is done, we will compile the file with:" +msgstr "完成后,我们将使用:" + +#: ../../source/contributor-how-to-create-new-messages.rst:78 +msgid "If it compiles succesfully, you should see the following message:" +msgstr "如果编译成功,你应该会看到以下信息:" + +#: ../../source/contributor-how-to-create-new-messages.rst:87 +msgid "Serialization and Deserialization Functions" +msgstr "序列化和反序列化函数" + +#: ../../source/contributor-how-to-create-new-messages.rst:89 +msgid "" +"Our next step is to add functions to serialize and deserialize Python " +"datatypes to or from our defined RPC message types. You should add these " +"functions in :code:`serde.py`." +msgstr "" +"下一步是添加函数,以便将 Python 数据类型序列化和反序列化为我们定义的 RPC 消息类型或从我们定义的 RPC 消息类型反序列化和反序列化 " +"Python 数据类型。您应该在 :code:`serde.py` 中添加这些函数。" + +#: ../../source/contributor-how-to-create-new-messages.rst:91 +msgid "The four functions:" +msgstr "四种函数:" + +#: ../../source/contributor-how-to-create-new-messages.rst:112 +msgid "Sending the Message from the Server" +msgstr "从服务器发送信息" + +#: ../../source/contributor-how-to-create-new-messages.rst:114 +msgid "" +"Now write the request function in your Client Proxy class (e.g., " +":code:`grpc_client_proxy.py`) using the serde functions you just created:" +msgstr "现在,在客户端代理类(例如 :code:`grpc_client_proxy.py`)中使用刚才创建的 serde 函数编写请求函数:" + +#: ../../source/contributor-how-to-create-new-messages.rst:128 +msgid "Receiving the Message by the Client" +msgstr "由客户端接收信息" + +#: ../../source/contributor-how-to-create-new-messages.rst:130 +msgid "" +"Last step! Modify the code in :code:`message_handler.py` to check the " +"field of your message and call the :code:`example_response` function. " +"Remember to use the serde functions!" msgstr "" -"如果您想添加新语言,请先联系我们,可以在 `Slack `_ 上联系,也可以在我们的 `GitHub repo `_ 上提交问题。" +"最后一步 修改 :code:`message_handler.py` 中的代码,检查信息的字段并调用 " +":code:`example_response` 函数。记住使用 serde 函数!" + +#: ../../source/contributor-how-to-create-new-messages.rst:132 +msgid "Within the handle function:" +msgstr "在句柄函数内:" + +#: ../../source/contributor-how-to-create-new-messages.rst:139 +msgid "And add a new function:" +msgstr "并增加一个新函数:" + +#: ../../source/contributor-how-to-create-new-messages.rst:149 +msgid "Hopefully, when you run your program you will get the intended result!" +msgstr "希望您在运行程序时能得到预期的结果!" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:2 msgid "Develop in VSCode Dev Containers" @@ -320,104 +539,97 @@ msgstr "使用 VSCode Dev Containers 进行开发" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:4 msgid "" -"When working on the Flower framework we want to ensure that all contributors " -"use the same developer environment to format code or run tests. For this " -"purpose we are using the VSCode Remote Containers extension. What is it? " -"Read the following quote:" +"When working on the Flower framework we want to ensure that all " +"contributors use the same developer environment to format code or run " +"tests. For this purpose we are using the VSCode Remote Containers " +"extension. What is it? Read the following quote:" msgstr "" -"在开发 Flower 框架时,我们希望确保所有贡献者使用相同的开发环境来格式化代码或" -"运行测试。为此,我们使用了 VSCode 远程容器扩展。这是什么?请阅读下面这段话:" +"在开发 Flower 框架时,我们希望确保所有贡献者使用相同的开发环境来格式化代码或运行测试。为此,我们使用了 VSCode " +"远程容器扩展。这是什么?请阅读下面这段话:" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:7 msgid "" -"The Visual Studio Code Remote - Containers extension lets you use a Docker " -"container as a fully-featured development environment. It allows you to open " -"any folder inside (or mounted into) a container and take advantage of Visual " -"Studio Code's full feature set. A :code:`devcontainer.json` file in your " -"project tells VS Code how to access (or create) a development container with " -"a well-defined tool and runtime stack. This container can be used to run an " -"application or to separate tools, libraries, or runtimes needed for working " -"with a codebase." -msgstr "" -"Visual Studio Code Remote - Containers扩展可让你将Docker容器用作功能齐全的开" -"发环境。它允许你打开容器内(或挂载到容器内)的任何文件夹,并利用 Visual " -"Studio Code 的全部功能集。项目中的 :code:`devcontainer.json` 文件会告诉 VS " -"Code 如何访问(或创建)一个带有定义明确的工具和运行时栈的开发容器。该容器可用" -"于运行应用程序,也可用于分离处理代码库所需的工具、库或运行时。" +"The Visual Studio Code Remote - Containers extension lets you use a " +"Docker container as a fully-featured development environment. It allows " +"you to open any folder inside (or mounted into) a container and take " +"advantage of Visual Studio Code's full feature set. A " +":code:`devcontainer.json` file in your project tells VS Code how to " +"access (or create) a development container with a well-defined tool and " +"runtime stack. This container can be used to run an application or to " +"separate tools, libraries, or runtimes needed for working with a " +"codebase." +msgstr "" +"Visual Studio Code Remote - " +"Containers扩展可让你将Docker容器用作功能齐全的开发环境。它允许你打开容器内(或挂载到容器内)的任何文件夹,并利用 Visual " +"Studio Code 的全部功能集。项目中的 :code:`devcontainer.json` 文件会告诉 VS Code " +"如何访问(或创建)一个带有定义明确的工具和运行时栈的开发容器。该容器可用于运行应用程序,也可用于分离处理代码库所需的工具、库或运行时。" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:9 msgid "" -"Workspace files are mounted from the local file system or copied or cloned " -"into the container. Extensions are installed and run inside the container, " -"where they have full access to the tools, platform, and file system. This " -"means that you can seamlessly switch your entire development environment " -"just by connecting to a different container." -msgstr "" -"工作区文件从本地文件系统加载,或复制或克隆到容器中。扩展在容器内安装和运行," -"在容器内它们可以完全访问工具、平台和文件系统。这意味着,只需连接到不同的容" -"器,就能无缝切换整个开发环境。" +"Workspace files are mounted from the local file system or copied or " +"cloned into the container. Extensions are installed and run inside the " +"container, where they have full access to the tools, platform, and file " +"system. This means that you can seamlessly switch your entire development" +" environment just by connecting to a different container." +msgstr "工作区文件从本地文件系统加载,或复制或克隆到容器中。扩展在容器内安装和运行,在容器内它们可以完全访问工具、平台和文件系统。这意味着,只需连接到不同的容器,就能无缝切换整个开发环境。" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:11 msgid "" -"Source: `Official VSCode documentation `_" -msgstr "" -"来源:`VSCode 官方文档 `_" +"Source: `Official VSCode documentation " +"`_" +msgstr "来源:`VSCode 官方文档 `_" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:15 msgid "Getting started" msgstr "开始" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:17 +#, fuzzy msgid "" -"Configuring and setting up the :code:`Dockerfile` as well the configuration " -"for the devcontainer can be a bit more involved. The good thing is you want " -"have to do it. Usually it should be enough to install Docker on your system " -"and ensure its available on your command line. Additionally, install the " +"Configuring and setting up the :code:`Dockerfile` as well the " +"configuration for the devcontainer can be a bit more involved. The good " +"thing is you don't have to do it. Usually it should be enough to install " +"`Docker `_ on your system and " +"ensure its available on your command line. Additionally, install the " "`VSCode Containers Extension `_." msgstr "" -"配置和设置 :code:`Dockerfile` 以及 devcontainer 的配置可能比较复杂。好在你想" -"做就得做。通常只需在系统中安装 Docker 并确保其在命令行中可用即可。此外,请安" -"装 `VSCode Containers Extension `_。" +"配置和设置 :code:`Dockerfile` 以及 devcontainer 的配置可能比较复杂。好在你想做就得做。通常只需在系统中安装 " +"Docker 并确保其在命令行中可用即可。此外,请安装 `VSCode Containers Extension " +"`_。" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:19 msgid "" -"Now you should be good to go. When starting VSCode, it will ask you to run " -"in the container environment and - if you confirm - automatically build the " -"container and use it. To manually instruct VSCode to use the devcontainer, " -"you can, after installing the extension, click the green area in the bottom " -"left corner of your VSCode window and select the option *(Re)Open Folder in " -"Container*." +"Now you should be good to go. When starting VSCode, it will ask you to " +"run in the container environment and - if you confirm - automatically " +"build the container and use it. To manually instruct VSCode to use the " +"devcontainer, you can, after installing the extension, click the green " +"area in the bottom left corner of your VSCode window and select the " +"option *(Re)Open Folder in Container*." msgstr "" -"现在你应该可以开始了。启动 VSCode 时,它会要求你在容器环境中运行,如果你确" -"认,它会自动构建容器并使用它。要手动指示 VSCode 使用 devcontainer,可以在安装" -"扩展后,点击 VSCode 窗口左下角的绿色区域,然后选择 \"*(重新)在容器中打开文" -"件夹*\"选项。" +"现在你应该可以开始了。启动 VSCode 时,它会要求你在容器环境中运行,如果你确认,它会自动构建容器并使用它。要手动指示 VSCode 使用 " +"devcontainer,可以在安装扩展后,点击 VSCode 窗口左下角的绿色区域,然后选择 \"*(重新)在容器中打开文件夹*\"选项。" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:21 msgid "" -"In some cases your setup might be more involved. For those cases consult the " -"following sources:" +"In some cases your setup might be more involved. For those cases consult " +"the following sources:" msgstr "在某些情况下,您的设置可能更复杂。有关这些情况,请参考以下资料:" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:23 msgid "" -"`Developing inside a Container `_" +"`Developing inside a Container " +"`_" msgstr "" "在容器内开发 `_" #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:24 msgid "" -"`Remote development in Containers `_" -msgstr "" -"容器中的远程开发 `_" +"`Remote development in Containers " +"`_" +msgstr "容器中的远程开发 `_" #: ../../source/contributor-how-to-install-development-versions.rst:2 msgid "Install development versions" @@ -433,21 +645,19 @@ msgstr "使用诗歌(推荐)" #: ../../source/contributor-how-to-install-development-versions.rst:10 msgid "" -"Install a ``flwr`` pre-release from PyPI: update the ``flwr`` dependency in " -"``pyproject.toml`` and then reinstall (don't forget to delete ``poetry." -"lock`` (``rm poetry.lock``) before running ``poetry install``)." +"Install a ``flwr`` pre-release from PyPI: update the ``flwr`` dependency " +"in ``pyproject.toml`` and then reinstall (don't forget to delete " +"``poetry.lock`` (``rm poetry.lock``) before running ``poetry install``)." msgstr "" "安装来自 PyPI 的 ``flwr`` 预发布版本:更新 ``pyproject.toml`` 中的 ``flwr`` " -"依赖关系,然后重新安装(运行 ``poetry install` 前,别忘了删除 ``poetry.lock` " -"(``rm poetry.lock`))。" +"依赖关系,然后重新安装(运行 ``poetry install` 前,别忘了删除 ``poetry.lock` (``rm " +"poetry.lock`))。" #: ../../source/contributor-how-to-install-development-versions.rst:12 msgid "" "``flwr = { version = \"1.0.0a0\", allow-prereleases = true }`` (without " "extras)" -msgstr "" -"``flwr = { version = \"1.0.0a0\", allow-prereleases = true }`` (不含额外内" -"容)" +msgstr "``flwr = { version = \"1.0.0a0\", allow-prereleases = true }`` (不含额外内容)" #: ../../source/contributor-how-to-install-development-versions.rst:13 msgid "" @@ -459,8 +669,8 @@ msgstr "" #: ../../source/contributor-how-to-install-development-versions.rst:15 msgid "" -"Install ``flwr`` from a local copy of the Flower source code via ``pyproject." -"toml``:" +"Install ``flwr`` from a local copy of the Flower source code via " +"``pyproject.toml``:" msgstr "通过 ``pyproject.toml`` 从 Flower 源代码的本地副本安装 ``flwr``:" #: ../../source/contributor-how-to-install-development-versions.rst:17 @@ -469,27 +679,27 @@ msgstr "``flwr = { path = \"../../\", develop = true }`` (不含额外内容 #: ../../source/contributor-how-to-install-development-versions.rst:18 msgid "" -"``flwr = { path = \"../../\", develop = true, extras = [\"simulation\"] }`` " -"(with extras)" +"``flwr = { path = \"../../\", develop = true, extras = [\"simulation\"] " +"}`` (with extras)" msgstr "" -"``flwr = { path = \"../../\", develop = true, extras = [\"simulation\"] }`` " -"(包含额外内容)" +"``flwr = { path = \"../../\", develop = true, extras = [\"simulation\"] " +"}`` (包含额外内容)" #: ../../source/contributor-how-to-install-development-versions.rst:20 msgid "Install ``flwr`` from a local wheel file via ``pyproject.toml``:" msgstr "通过 ``pyproject.toml`` 从本地轮子文件安装 ``flwr``:" #: ../../source/contributor-how-to-install-development-versions.rst:22 +#, fuzzy msgid "" -"``flwr = { path = \"../../dist/flwr-1.0.0-py3-none-any.whl\" }`` (without " -"extras)" -msgstr "" -"``flwr = { path = \"../../dist/flwr-1.0.0-py3-none-any.whl\" }``(无额外内" -"容)" +"``flwr = { path = \"../../dist/flwr-1.8.0-py3-none-any.whl\" }`` (without" +" extras)" +msgstr "``flwr = { path = \"../../dist/flwr-1.0.0-py3-none-any.whl\" }``(无额外内容)" #: ../../source/contributor-how-to-install-development-versions.rst:23 +#, fuzzy msgid "" -"``flwr = { path = \"../../dist/flwr-1.0.0-py3-none-any.whl\", extras = " +"``flwr = { path = \"../../dist/flwr-1.8.0-py3-none-any.whl\", extras = " "[\"simulation\"] }`` (with extras)" msgstr "" "``flwr = { path = \"../../dist/flwr-1.0.0-py3-none-any.whl\", extras = " @@ -501,8 +711,8 @@ msgid "" "Dependency Specification `_" msgstr "" -"有关详细信息,请参阅 Poetry 文档: 诗歌依赖性规范 `_" +"有关详细信息,请参阅 Poetry 文档: 诗歌依赖性规范 `_" #: ../../source/contributor-how-to-install-development-versions.rst:28 msgid "Using pip (recommended on Colab)" @@ -524,8 +734,7 @@ msgstr "`pip install -U -pre flwr[simulation]``(包含额外功能)" msgid "" "Python packages can be installed from git repositories. Use one of the " "following commands to install the Flower directly from GitHub." -msgstr "" -"Python 软件包可以从 git 仓库安装。使用以下命令之一直接从 GitHub 安装 Flower。" +msgstr "Python 软件包可以从 git 仓库安装。使用以下命令之一直接从 GitHub 安装 Flower。" #: ../../source/contributor-how-to-install-development-versions.rst:37 msgid "Install ``flwr`` from the default GitHub branch (``main``):" @@ -533,17 +742,17 @@ msgstr "从 GitHub 的默认分支 (``main`) 安装 ``flwr``:" #: ../../source/contributor-how-to-install-development-versions.rst:39 msgid "" -"``pip install flwr@git+https://github.com/adap/flower.git`` (without extras)" -msgstr "" -"`pip install flwr@git+https://github.com/adap/flower.git`` (不含额外功能)" +"``pip install flwr@git+https://github.com/adap/flower.git`` (without " +"extras)" +msgstr "`pip install flwr@git+https://github.com/adap/flower.git`` (不含额外功能)" #: ../../source/contributor-how-to-install-development-versions.rst:40 msgid "" "``pip install flwr[simulation]@git+https://github.com/adap/flower.git`` " "(with extras)" msgstr "" -"`pip install flwr[simulation]@git+https://github.com/adap/flower.git``(带附" -"加功能)" +"`pip install " +"flwr[simulation]@git+https://github.com/adap/flower.git``(带附加功能)" #: ../../source/contributor-how-to-install-development-versions.rst:42 msgid "Install ``flwr`` from a specific GitHub branch (``branch-name``):" @@ -554,16 +763,14 @@ msgid "" "``pip install flwr@git+https://github.com/adap/flower.git@branch-name`` " "(without extras)" msgstr "" -"`pip install flwr@git+https://github.com/adap/flower.git@branch-name`` (不含" -"附加功能)" +"`pip install flwr@git+https://github.com/adap/flower.git@branch-name`` " +"(不含附加功能)" #: ../../source/contributor-how-to-install-development-versions.rst:45 msgid "" -"``pip install flwr[simulation]@git+https://github.com/adap/flower.git@branch-" -"name`` (with extras)" -msgstr "" -"`pip安装flwr[模拟]@git+https://github.com/adap/flower.git@分支名``(带附加功" -"能)" +"``pip install flwr[simulation]@git+https://github.com/adap/flower.git" +"@branch-name`` (with extras)" +msgstr "`pip安装flwr[模拟]@git+https://github.com/adap/flower.git@分支名``(带附加功能)" #: ../../source/contributor-how-to-install-development-versions.rst:49 msgid "Open Jupyter Notebooks on Google Colab" @@ -571,34 +778,33 @@ msgstr "在谷歌 Colab 上打开 Jupyter 笔记本" #: ../../source/contributor-how-to-install-development-versions.rst:51 msgid "" -"Open the notebook ``doc/source/tutorial-get-started-with-flower-pytorch." -"ipynb``:" -msgstr "" -"打开笔记本 ``doc/source/tutorial-get-started-with-flower-pytorch.ipynb``:" +"Open the notebook ``doc/source/tutorial-get-started-with-flower-" +"pytorch.ipynb``:" +msgstr "打开笔记本 ``doc/source/tutorial-get-started-with-flower-pytorch.ipynb``:" #: ../../source/contributor-how-to-install-development-versions.rst:53 msgid "" -"https://colab.research.google.com/github/adap/flower/blob/main/doc/source/" -"tutorial-get-started-with-flower-pytorch.ipynb" +"https://colab.research.google.com/github/adap/flower/blob/main/doc/source" +"/tutorial-get-started-with-flower-pytorch.ipynb" msgstr "" -"https://colab.research.google.com/github/adap/flower/blob/main/doc/source/" -"tutorial-get-started-with-flower-pytorch.ipynb" +"https://colab.research.google.com/github/adap/flower/blob/main/doc/source" +"/tutorial-get-started-with-flower-pytorch.ipynb" #: ../../source/contributor-how-to-install-development-versions.rst:55 msgid "" -"Open a development version of the same notebook from branch `branch-name` by " -"changing ``main`` to ``branch-name`` (right after ``blob``):" +"Open a development version of the same notebook from branch `branch-name`" +" by changing ``main`` to ``branch-name`` (right after ``blob``):" msgstr "" -"将 ``main`` 改为 ``branch-name``(紧跟在 ``blob``之后),从分支 `branch-" -"name` 打开同一笔记本的开发版本:" +"将 ``main`` 改为 ``branch-name``(紧跟在 ``blob``之后),从分支 `branch-name` " +"打开同一笔记本的开发版本:" #: ../../source/contributor-how-to-install-development-versions.rst:57 msgid "" -"https://colab.research.google.com/github/adap/flower/blob/branch-name/doc/" -"source/tutorial-get-started-with-flower-pytorch.ipynb" +"https://colab.research.google.com/github/adap/flower/blob/branch-" +"name/doc/source/tutorial-get-started-with-flower-pytorch.ipynb" msgstr "" -"https://colab.research.google.com/github/adap/flower/blob/branch-name/doc/" -"source/tutorial-get-started-with-flower-pytorch.ipynb" +"https://colab.research.google.com/github/adap/flower/blob/branch-" +"name/doc/source/tutorial-get-started-with-flower-pytorch.ipynb" #: ../../source/contributor-how-to-install-development-versions.rst:59 msgid "Install a `whl` on Google Colab:" @@ -606,23 +812,25 @@ msgstr "在 Google Colab 上安装 `whl`:" #: ../../source/contributor-how-to-install-development-versions.rst:61 msgid "" -"In the vertical icon grid on the left hand side, select ``Files`` > ``Upload " -"to session storage``" +"In the vertical icon grid on the left hand side, select ``Files`` > " +"``Upload to session storage``" msgstr "在左侧的垂直图标网格中,选择 \"文件\">\"上传到会话存储\"" #: ../../source/contributor-how-to-install-development-versions.rst:62 -msgid "Upload the whl (e.g., ``flwr-1.7.0-py3-none-any.whl``)" +#, fuzzy +msgid "Upload the whl (e.g., ``flwr-1.8.0-py3-none-any.whl``)" msgstr "更新 whl (e.g., ``flwr-1.7.0-py3-none-any.whl``)" #: ../../source/contributor-how-to-install-development-versions.rst:63 +#, fuzzy msgid "" -"Change ``!pip install -q 'flwr[simulation]' torch torchvision matplotlib`` " -"to ``!pip install -q 'flwr-1.7.0-py3-none-any.whl[simulation]' torch " -"torchvision matplotlib``" +"Change ``!pip install -q 'flwr[simulation]' torch torchvision " +"matplotlib`` to ``!pip install -q 'flwr-1.8.0-py3-none-" +"any.whl[simulation]' torch torchvision matplotlib``" msgstr "" -"把``!pip install -q 'flwr[simulation]' torch torchvision matplotlib``变为``" -"!pip install -q 'flwr-1.7.0-py3-none-any.whl[simulation]' torch torchvision " -"matplotlib``" +"把``!pip install -q 'flwr[simulation]' torch torchvision " +"matplotlib``变为``!pip install -q 'flwr-1.7.0-py3-none-any.whl[simulation]'" +" torch torchvision matplotlib``" #: ../../source/contributor-how-to-release-flower.rst:2 msgid "Release Flower" @@ -635,202 +843,171 @@ msgid "" msgstr "本文件描述了当前的发布流程。今后可能会有变化,也可能不会有变化。" #: ../../source/contributor-how-to-release-flower.rst:7 -msgid "Before the release" -msgstr "发布前" +msgid "During the release" +msgstr "在发布期间" #: ../../source/contributor-how-to-release-flower.rst:9 msgid "" -"Update the changelog (``changelog.md``) with all relevant changes that " -"happened after the last release. If the last release was tagged ``v1.2.0``, " -"you can use the following URL to see all commits that got merged into " -"``main`` since then:" -msgstr "" -"更新更新日志 (``changelog.md``),加入上次发布后发生的所有相关变更。如果上次发" -"布的版本被标记为 ``v1.2.0``,则可以使用以下 URL 查看此后合并到 ``main`` 的所" -"有提交:" +"The version number of a release is stated in ``pyproject.toml``. To " +"release a new version of Flower, the following things need to happen (in " +"that order):" +msgstr "版本号在 ``pyproject.toml`` 中说明。要发布 Flower 的新版本,需要完成以下工作(按顺序排列):" #: ../../source/contributor-how-to-release-flower.rst:11 msgid "" -"`GitHub: Compare v1.2.0...main `_" -msgstr "" -"`GitHub: Compare v1.2.0...main `_" - -#: ../../source/contributor-how-to-release-flower.rst:13 -msgid "" -"Thank the authors who contributed since the last release. This can be done " -"by running the ``./dev/add-shortlog.sh`` convenience script (it can be ran " -"multiple times and will update the names in the list if new contributors " -"were added in the meantime)." +"Run ``python3 src/py/flwr_tool/update_changelog.py `` in " +"order to add every new change to the changelog (feel free to make manual " +"changes to the changelog afterwards until it looks good)." msgstr "" -"感谢自上次发布以来做出贡献的作者。可以通过运行 ``./dev/add-shortlog.sh`` 方便" -"脚本来完成(可以多次运行,如果在此期间有新的贡献者加入,则会更新列表中的名" -"字)。" -#: ../../source/contributor-how-to-release-flower.rst:16 -msgid "During the release" -msgstr "在发布期间" - -#: ../../source/contributor-how-to-release-flower.rst:18 -msgid "" -"The version number of a release is stated in ``pyproject.toml``. To release " -"a new version of Flower, the following things need to happen (in that order):" -msgstr "" -"版本号在 ``pyproject.toml`` 中说明。要发布 Flower 的新版本,需要完成以下工作" -"(按顺序排列):" - -#: ../../source/contributor-how-to-release-flower.rst:20 +#: ../../source/contributor-how-to-release-flower.rst:12 msgid "" -"Update the ``changelog.md`` section header ``Unreleased`` to contain the " -"version number and date for the release you are building. Create a pull " -"request with the change." +"Once the changelog has been updated with all the changes, run ``./dev" +"/prepare-release-changelog.sh v``, where ```` " +"is the version stated in ``pyproject.toml`` (notice the ``v`` added " +"before it). This will replace the ``Unreleased`` header of the changelog " +"by the version and current date, and it will add a thanking message for " +"the contributors. Open a pull request with those changes." msgstr "" -"更新 ``changelog.md`` 部分的标题 ``Unreleased`` 以包含你正在构建的版本的版本" -"号和日期。创建一个包含更改的拉取请求。" -#: ../../source/contributor-how-to-release-flower.rst:21 +#: ../../source/contributor-how-to-release-flower.rst:13 +#, fuzzy msgid "" -"Tag the release commit with the version number as soon as the PR is merged: " -"``git tag v0.12.3``, then ``git push --tags``. This will create a draft " -"release on GitHub containing the correct artifacts and the relevant part of " -"the changelog." +"Once the pull request is merged, tag the release commit with the version " +"number as soon as the PR is merged: ``git tag v`` (notice " +"the ``v`` added before the version number), then ``git push --tags``. " +"This will create a draft release on GitHub containing the correct " +"artifacts and the relevant part of the changelog." msgstr "" -"在 PR 合并后立即用版本号标记发布提交:``git tag v0.12.3``,然后``git push --" -"tags``。这将在 GitHub 上创建一个包含正确工件和更新日志相关部分的发布草案。" +"在 PR 合并后立即用版本号标记发布提交:``git tag v0.12.3``,然后``git push --tags``。这将在 GitHub" +" 上创建一个包含正确工件和更新日志相关部分的发布草案。" -#: ../../source/contributor-how-to-release-flower.rst:22 -msgid "" -"Check the draft release on GitHub, and if everything is good, publish it." +#: ../../source/contributor-how-to-release-flower.rst:14 +msgid "Check the draft release on GitHub, and if everything is good, publish it." msgstr "检查 GitHub 上的发布稿,如果一切正常,就发布它。" -#: ../../source/contributor-how-to-release-flower.rst:25 +#: ../../source/contributor-how-to-release-flower.rst:17 msgid "After the release" msgstr "发布后" -#: ../../source/contributor-how-to-release-flower.rst:27 +#: ../../source/contributor-how-to-release-flower.rst:19 msgid "Create a pull request which contains the following changes:" msgstr "创建包含以下更改的拉取请求:" -#: ../../source/contributor-how-to-release-flower.rst:29 +#: ../../source/contributor-how-to-release-flower.rst:21 msgid "Increase the minor version in ``pyproject.toml`` by one." msgstr "将 ``pyproject.toml`` 中的次要版本增加一个。" -#: ../../source/contributor-how-to-release-flower.rst:30 +#: ../../source/contributor-how-to-release-flower.rst:22 msgid "Update all files which contain the current version number if necessary." msgstr "如有必要,更新包含当前版本号的所有文件。" -#: ../../source/contributor-how-to-release-flower.rst:31 +#: ../../source/contributor-how-to-release-flower.rst:23 msgid "Add a new ``Unreleased`` section in ``changelog.md``." msgstr "在 ``changelog.md`` 中添加新的 ``Unreleased`` 部分。" -#: ../../source/contributor-how-to-release-flower.rst:33 +#: ../../source/contributor-how-to-release-flower.rst:25 msgid "" -"Merge the pull request on the same day (i.e., before a new nighly release " -"gets published to PyPI)." +"Merge the pull request on the same day (i.e., before a new nighly release" +" gets published to PyPI)." msgstr "在同一天合并拉取请求(即在新版本发布到 PyPI 之前)。" -#: ../../source/contributor-how-to-release-flower.rst:36 +#: ../../source/contributor-how-to-release-flower.rst:28 msgid "Publishing a pre-release" msgstr "发布预发布版本" -#: ../../source/contributor-how-to-release-flower.rst:39 +#: ../../source/contributor-how-to-release-flower.rst:31 msgid "Pre-release naming" msgstr "释放前命名" -#: ../../source/contributor-how-to-release-flower.rst:41 +#: ../../source/contributor-how-to-release-flower.rst:33 msgid "" "PyPI supports pre-releases (alpha, beta, release candiate). Pre-releases " "MUST use one of the following naming patterns:" -msgstr "" -"PyPI 支持预发布版本(alpha、beta、release candiate)。预发布版本必须使用以下" -"命名模式之一:" +msgstr "PyPI 支持预发布版本(alpha、beta、release candiate)。预发布版本必须使用以下命名模式之一:" -#: ../../source/contributor-how-to-release-flower.rst:43 +#: ../../source/contributor-how-to-release-flower.rst:35 msgid "Alpha: ``MAJOR.MINOR.PATCHaN``" msgstr "阿尔法 ``MAJOR.MINOR.PATCHaN``" -#: ../../source/contributor-how-to-release-flower.rst:44 +#: ../../source/contributor-how-to-release-flower.rst:36 msgid "Beta: ``MAJOR.MINOR.PATCHbN``" msgstr "贝塔: ``MAJOR.MINOR.PATCHbN``" -#: ../../source/contributor-how-to-release-flower.rst:45 +#: ../../source/contributor-how-to-release-flower.rst:37 msgid "Release candiate (RC): ``MAJOR.MINOR.PATCHrcN``" msgstr "版本代号 (RC): ``MAJOR.MINOR.PATCHrcN``" -#: ../../source/contributor-how-to-release-flower.rst:47 +#: ../../source/contributor-how-to-release-flower.rst:39 msgid "Examples include:" msgstr "例子包括:" -#: ../../source/contributor-how-to-release-flower.rst:49 +#: ../../source/contributor-how-to-release-flower.rst:41 msgid "``1.0.0a0``" msgstr "``1.0.0a0``" -#: ../../source/contributor-how-to-release-flower.rst:50 +#: ../../source/contributor-how-to-release-flower.rst:42 msgid "``1.0.0b0``" msgstr "``1.0.0b0``" -#: ../../source/contributor-how-to-release-flower.rst:51 +#: ../../source/contributor-how-to-release-flower.rst:43 msgid "``1.0.0rc0``" msgstr "``1.0.0rc0``" -#: ../../source/contributor-how-to-release-flower.rst:52 +#: ../../source/contributor-how-to-release-flower.rst:44 msgid "``1.0.0rc1``" msgstr "``1.0.0rc1``" -#: ../../source/contributor-how-to-release-flower.rst:54 +#: ../../source/contributor-how-to-release-flower.rst:46 msgid "" "This is in line with PEP-440 and the recommendations from the Python " "Packaging Authority (PyPA):" msgstr "这符合 PEP-440 和 Python 包装管理局 (PyPA) 的建议:" -#: ../../source/contributor-how-to-release-flower.rst:57 +#: ../../source/contributor-how-to-release-flower.rst:49 msgid "`PEP-440 `_" msgstr "`PEP-440 `_" -#: ../../source/contributor-how-to-release-flower.rst:58 +#: ../../source/contributor-how-to-release-flower.rst:50 msgid "" -"`PyPA Choosing a versioning scheme `_" +"`PyPA Choosing a versioning scheme " +"`_" msgstr "" -"`PyPA 选择版本控制方案 `_" +"`PyPA 选择版本控制方案 `_" -#: ../../source/contributor-how-to-release-flower.rst:60 +#: ../../source/contributor-how-to-release-flower.rst:52 msgid "" -"Note that the approach defined by PyPA is not compatible with SemVer 2.0.0 " -"spec, for details consult the `Semantic Versioning Specification `_ (specifically item 11 on " -"precedence)." +"Note that the approach defined by PyPA is not compatible with SemVer " +"2.0.0 spec, for details consult the `Semantic Versioning Specification " +"`_ (specifically item " +"11 on precedence)." msgstr "" -"请注意,PyPA 所定义的方法与 SemVer 2.0.0 规范不兼容,详情请查阅《语义版本规" -"范》`_(特别是关于优先级的" -"第 11 项)。" +"请注意,PyPA 所定义的方法与 SemVer 2.0.0 " +"规范不兼容,详情请查阅《语义版本规范》`_(特别是关于优先级的第 11 项)。" -#: ../../source/contributor-how-to-release-flower.rst:63 +#: ../../source/contributor-how-to-release-flower.rst:55 msgid "Pre-release classification" msgstr "发布前分类" -#: ../../source/contributor-how-to-release-flower.rst:65 -msgid "" -"Should the next pre-release be called alpha, beta, or release candidate?" +#: ../../source/contributor-how-to-release-flower.rst:57 +msgid "Should the next pre-release be called alpha, beta, or release candidate?" msgstr "下一个预发布版应该叫阿尔法版、贝塔版还是候选发布版?" -#: ../../source/contributor-how-to-release-flower.rst:67 +#: ../../source/contributor-how-to-release-flower.rst:59 msgid "" -"RC: feature complete, no known issues (apart from issues that are classified " -"as \"won't fix\" for the next stable release) - if no issues surface this " -"will become the next stable release" -msgstr "" -"RC:功能完整,无已知问题(除了下一个稳定版中被列为 \"不会修复 \"的问题)--如" -"果没有问题出现,这将成为下一个稳定版" +"RC: feature complete, no known issues (apart from issues that are " +"classified as \"won't fix\" for the next stable release) - if no issues " +"surface this will become the next stable release" +msgstr "RC:功能完整,无已知问题(除了下一个稳定版中被列为 \"不会修复 \"的问题)--如果没有问题出现,这将成为下一个稳定版" -#: ../../source/contributor-how-to-release-flower.rst:68 +#: ../../source/contributor-how-to-release-flower.rst:60 msgid "Beta: feature complete, allowed to have known issues" msgstr "贝塔版:功能完整,允许存在已知问题" -#: ../../source/contributor-how-to-release-flower.rst:69 +#: ../../source/contributor-how-to-release-flower.rst:61 msgid "Alpha: not feature complete, allowed to have known issues" msgstr "阿尔法版:功能不完整,允许存在已知问题" @@ -842,12 +1019,11 @@ msgstr "建立虚拟环境" msgid "" "It is recommended to run your Python setup within a virtual environment. " "This guide shows three different examples how to create a virtual " -"environment with pyenv virtualenv, poetry, or Anaconda. You can follow the " -"instructions or choose your preferred setup." +"environment with pyenv virtualenv, poetry, or Anaconda. You can follow " +"the instructions or choose your preferred setup." msgstr "" -"建议在虚拟环境中运行 Python 设置。本指南展示了如何使用 pyenv virtualenv、" -"poes 或 Anaconda 创建虚拟环境的三个不同示例。您可以按照说明或选择您喜欢的设" -"置。" +"建议在虚拟环境中运行 Python 设置。本指南展示了如何使用 pyenv virtualenv、poes 或 Anaconda " +"创建虚拟环境的三个不同示例。您可以按照说明或选择您喜欢的设置。" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:9 msgid "Python Version" @@ -856,11 +1032,12 @@ msgstr "Python 版本" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:11 #: ../../source/how-to-install-flower.rst:8 msgid "" -"Flower requires at least `Python 3.8 `_, but " -"`Python 3.10 `_ or above is recommended." +"Flower requires at least `Python 3.8 `_, " +"but `Python 3.10 `_ or above is " +"recommended." msgstr "" -"Flower 至少需要 `Python 3.8 `_,但建议使用 " -"`Python 3.10 `_或更高版本。" +"Flower 至少需要 `Python 3.8 `_,但建议使用 `Python " +"3.10 `_或更高版本。" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:14 msgid "Virutualenv with Pyenv/Virtualenv" @@ -868,22 +1045,20 @@ msgstr "Virutualenv 和 Pyenv/Virtualenv" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:16 msgid "" -"One of the recommended virtual environment is `pyenv `_/`virtualenv `_. " -"Please see `Flower examples `_ for details." +"One of the recommended virtual environment is `pyenv " +"`_/`virtualenv `_. Please see `Flower examples " +"`_ for details." msgstr "" -"其中一个推荐的虚拟环境是 `pyenv `_/" -"`virtualenv `_。详情请参见 " -"`Flower 示例 `_。" +"其中一个推荐的虚拟环境是 `pyenv `_/`virtualenv " +"`_。详情请参见 `Flower 示例 " +"`_。" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:18 msgid "" "Once Pyenv is set up, you can use it to install `Python Version 3.10 " "`_ or above:" -msgstr "" -"一旦设置好 Pyenv,就可以用它来安装 `Python 3.10 `_ 或更高版本:" +msgstr "一旦设置好 Pyenv,就可以用它来安装 `Python 3.10 `_ 或更高版本:" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:24 msgid "Create the virtualenv with:" @@ -899,17 +1074,17 @@ msgstr "有诗意的 Virtualenv" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:41 msgid "" -"The Flower examples are based on `Poetry `_ " -"to manage dependencies. After installing Poetry you simply create a virtual " -"environment with:" +"The Flower examples are based on `Poetry `_ to manage dependencies. After installing Poetry you " +"simply create a virtual environment with:" msgstr "" -"Flower 示例基于 `Poetry `_ 来管理依赖关系。" -"安装 Poetry 后,只需创建一个虚拟环境即可:" +"Flower 示例基于 `Poetry `_ 来管理依赖关系。安装 Poetry" +" 后,只需创建一个虚拟环境即可:" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:47 msgid "" -"If you open a new terminal you can activate the previously created virtual " -"environment with the following command:" +"If you open a new terminal you can activate the previously created " +"virtual environment with the following command:" msgstr "如果打开一个新终端,可以使用以下命令激活之前创建的虚拟环境:" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:55 @@ -918,14 +1093,14 @@ msgstr "使用 Anaconda 的 Virtualenv" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:57 msgid "" -"If you prefer to use Anaconda for your virtual environment then install and " -"setup the `conda `_ package. After setting it up you can create a virtual " -"environment with:" +"If you prefer to use Anaconda for your virtual environment then install " +"and setup the `conda `_ package. After setting it up you can " +"create a virtual environment with:" msgstr "" -"如果你更喜欢在虚拟环境中使用 Anaconda,那么请安装并设置 `conda `_ 软件包。设" -"置完成后,您就可以使用以下工具创建虚拟环境:" +"如果你更喜欢在虚拟环境中使用 Anaconda,那么请安装并设置 `conda " +"`_ 软件包。设置完成后,您就可以使用以下工具创建虚拟环境:" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:63 msgid "and activate the virtual environment with:" @@ -937,11 +1112,11 @@ msgstr "然后呢?" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:73 msgid "" -"As soon as you created your virtual environment you clone one of the `Flower " -"examples `_." +"As soon as you created your virtual environment you clone one of the " +"`Flower examples `_." msgstr "" -"创建虚拟环境后,您可以克隆一个 `Flower 示例 `_。" +"创建虚拟环境后,您可以克隆一个 `Flower 示例 " +"`_。" #: ../../source/contributor-how-to-write-documentation.rst:2 msgid "Write documentation" @@ -953,22 +1128,24 @@ msgstr "项目布局" #: ../../source/contributor-how-to-write-documentation.rst:8 msgid "" -"The Flower documentation lives in the ``doc`` directory. The Sphinx-based " -"documentation system supports both reStructuredText (``.rst`` files) and " -"Markdown (``.md`` files)." +"The Flower documentation lives in the ``doc`` directory. The Sphinx-based" +" documentation system supports both reStructuredText (``.rst`` files) and" +" Markdown (``.md`` files)." msgstr "" -"Flower 文档位于 ``doc`` 目录中。基于 Sphinx 的文档系统支持 reStructuredText" -"(``.rst`` 文件)和 Markdown(``.md`` 文件)。" +"Flower 文档位于 ``doc`` 目录中。基于 Sphinx 的文档系统支持 reStructuredText(``.rst`` 文件)和 " +"Markdown(``.md`` 文件)。" #: ../../source/contributor-how-to-write-documentation.rst:10 -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:119 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:142 +#, fuzzy msgid "" -"Note that, in order to build the documentation locally (with ``poetry run " -"make html``, like described below), `Pandoc _` needs to be installed on the system." +"Note that, in order to build the documentation locally (with ``poetry run" +" make html``, like described below), `Pandoc " +"`_ needs to be installed on the " +"system." msgstr "" -"请注意,要在本地构建文档(使用 ``poetry run make html``,如下所述),系统上必" -"须安装 ``Pandoc _`。" +"请注意,要在本地构建文档(使用 ``poetry run make html``,如下所述),系统上必须安装 ``Pandoc " +"_`。" #: ../../source/contributor-how-to-write-documentation.rst:14 msgid "Edit an existing page" @@ -1010,13 +1187,13 @@ msgstr "良好的首批捐款" #: ../../source/contributor-ref-good-first-contributions.rst:4 msgid "" -"We welcome contributions to Flower! However, it is not always easy to know " -"where to start. We therefore put together a few recommendations on where to " -"start to increase your chances of getting your PR accepted into the Flower " -"codebase." +"We welcome contributions to Flower! However, it is not always easy to " +"know where to start. We therefore put together a few recommendations on " +"where to start to increase your chances of getting your PR accepted into " +"the Flower codebase." msgstr "" -"我们欢迎为《鲜花》投稿!然而,要知道从哪里开始并非易事。因此,我们提出了一些" -"建议,告诉您从哪里开始,以增加您的 PR 被 Flower 代码库接受的机会。" +"我们欢迎为《鲜花》投稿!然而,要知道从哪里开始并非易事。因此,我们提出了一些建议,告诉您从哪里开始,以增加您的 PR 被 Flower " +"代码库接受的机会。" #: ../../source/contributor-ref-good-first-contributions.rst:11 msgid "Where to start" @@ -1024,12 +1201,10 @@ msgstr "从哪里开始" #: ../../source/contributor-ref-good-first-contributions.rst:13 msgid "" -"Until the Flower core library matures it will be easier to get PR's accepted " -"if they only touch non-core areas of the codebase. Good candidates to get " -"started are:" -msgstr "" -"在 Flower 核心库成熟之前,如果 PR 只涉及代码库中的非核心区域,则会更容易被接" -"受。可以从以下方面入手:" +"Until the Flower core library matures it will be easier to get PR's " +"accepted if they only touch non-core areas of the codebase. Good " +"candidates to get started are:" +msgstr "在 Flower 核心库成熟之前,如果 PR 只涉及代码库中的非核心区域,则会更容易被接受。可以从以下方面入手:" #: ../../source/contributor-ref-good-first-contributions.rst:17 msgid "Documentation: What's missing? What could be expressed more clearly?" @@ -1049,30 +1224,30 @@ msgstr "Flower 基线申请" #: ../../source/contributor-ref-good-first-contributions.rst:25 msgid "" -"If you are not familiar with Flower Baselines, you should probably check-out " -"our `contributing guide for baselines `_." +"If you are not familiar with Flower Baselines, you should probably check-" +"out our `contributing guide for baselines `_." msgstr "" -"如果您对 Flower Baselines 还不熟悉,也许应该看看我们的 \"基线贡献指南 " -"`_\"。" +"如果您对 Flower Baselines 还不熟悉,也许应该看看我们的 \"基线贡献指南 `_\"。" #: ../../source/contributor-ref-good-first-contributions.rst:27 msgid "" -"You should then check out the open `issues `_ for baseline " -"requests. If you find a baseline that you'd like to work on and that has no " -"assignes, feel free to assign it to yourself and start working on it!" +"You should then check out the open `issues " +"`_" +" for baseline requests. If you find a baseline that you'd like to work on" +" and that has no assignes, feel free to assign it to yourself and start " +"working on it!" msgstr "" -"然后,您应该查看开放的 `issues `_ 基线请求。如果您发现了自" -"己想做的基线,而它还没有被分配,请随时把它分配给自己,然后开始工作!" +"然后,您应该查看开放的 `issues " +"`_" +" 基线请求。如果您发现了自己想做的基线,而它还没有被分配,请随时把它分配给自己,然后开始工作!" #: ../../source/contributor-ref-good-first-contributions.rst:31 msgid "" -"Otherwise, if you don't find a baseline you'd like to work on, be sure to " -"open a new issue with the baseline request template!" -msgstr "" -"否则,如果您没有找到想要处理的基线,请务必使用基线请求模板打开一个新问题!" +"Otherwise, if you don't find a baseline you'd like to work on, be sure to" +" open a new issue with the baseline request template!" +msgstr "否则,如果您没有找到想要处理的基线,请务必使用基线请求模板打开一个新问题!" #: ../../source/contributor-ref-good-first-contributions.rst:34 msgid "Request for examples" @@ -1081,11 +1256,9 @@ msgstr "要求提供范例" #: ../../source/contributor-ref-good-first-contributions.rst:36 msgid "" "We wish we had more time to write usage examples because we believe they " -"help users to get started with building what they want to build. Here are a " -"few ideas where we'd be happy to accept a PR:" -msgstr "" -"我们希望有更多的时间来撰写使用示例,因为我们相信这些示例可以帮助用户开始构建" -"他们想要构建的东西。以下是我们乐意接受 PR 的几个想法:" +"help users to get started with building what they want to build. Here are" +" a few ideas where we'd be happy to accept a PR:" +msgstr "我们希望有更多的时间来撰写使用示例,因为我们相信这些示例可以帮助用户开始构建他们想要构建的东西。以下是我们乐意接受 PR 的几个想法:" #: ../../source/contributor-ref-good-first-contributions.rst:40 msgid "Llama 2 fine-tuning, with Hugging Face Transformers and PyTorch" @@ -1105,13 +1278,13 @@ msgstr "安全聚合协议" #: ../../source/contributor-ref-secure-aggregation-protocols.rst:4 msgid "" -"Include SecAgg, SecAgg+, and LightSecAgg protocol. The LightSecAgg protocol " -"has not been implemented yet, so its diagram and abstraction may not be " -"accurate in practice. The SecAgg protocol can be considered as a special " -"case of the SecAgg+ protocol." +"Include SecAgg, SecAgg+, and LightSecAgg protocol. The LightSecAgg " +"protocol has not been implemented yet, so its diagram and abstraction may" +" not be accurate in practice. The SecAgg protocol can be considered as a " +"special case of the SecAgg+ protocol." msgstr "" -"包括 SecAgg、SecAgg+ 和 LightSecAgg 协议。LightSecAgg 协议尚未实施,因此其图" -"表和抽象在实践中可能并不准确。SecAgg 协议可视为 SecAgg+ 协议的特例。" +"包括 SecAgg、SecAgg+ 和 LightSecAgg 协议。LightSecAgg " +"协议尚未实施,因此其图表和抽象在实践中可能并不准确。SecAgg 协议可视为 SecAgg+ 协议的特例。" #: ../../source/contributor-ref-secure-aggregation-protocols.rst:8 msgid "The :code:`SecAgg+` abstraction" @@ -1121,17 +1294,17 @@ msgstr "代码:`SecAgg+` 抽象" #: ../../source/contributor-ref-secure-aggregation-protocols.rst:161 msgid "" "In this implementation, each client will be assigned with a unique index " -"(int) for secure aggregation, and thus many python dictionaries used have " -"keys of int type rather than ClientProxy type." +"(int) for secure aggregation, and thus many python dictionaries used have" +" keys of int type rather than ClientProxy type." msgstr "" -"在此实现中,将为每个客户端分配一个唯一索引(int),以确保聚合的安全性,因此使" -"用的许多 python 字典的键都是 int 类型,而不是 ClientProxy 类型。" +"在此实现中,将为每个客户端分配一个唯一索引(int),以确保聚合的安全性,因此使用的许多 python 字典的键都是 int 类型,而不是 " +"ClientProxy 类型。" #: ../../source/contributor-ref-secure-aggregation-protocols.rst:65 #: ../../source/contributor-ref-secure-aggregation-protocols.rst:198 msgid "" -"The Flower server will execute and process received results in the following " -"order:" +"The Flower server will execute and process received results in the " +"following order:" msgstr "Flower 服务器将按以下顺序执行和处理收到的结果:" #: ../../source/contributor-ref-secure-aggregation-protocols.rst:159 @@ -1148,719 +1321,822 @@ msgstr "在 GitHub 上投稿" #: ../../source/contributor-tutorial-contribute-on-github.rst:4 msgid "" -"This guide is for people who want to get involved with Flower, but who are " -"not used to contributing to GitHub projects." +"This guide is for people who want to get involved with Flower, but who " +"are not used to contributing to GitHub projects." msgstr "本指南适用于想参与 Flower,但不习惯为 GitHub 项目贡献的人。" #: ../../source/contributor-tutorial-contribute-on-github.rst:6 +#, fuzzy msgid "" -"If you're familiar with how contributing on GitHub works, you can directly " -"checkout our `getting started guide for contributors `_ and examples of `good first " -"contributions `_." +"If you're familiar with how contributing on GitHub works, you can " +"directly checkout our `getting started guide for contributors " +"`_." msgstr "" -"如果您熟悉如何在 GitHub 上贡献,可以直接查看我们的 \"贡献者入门指南\" " -"`_ 和 \"优秀的" -"首次贡献示例\" `_。" +"如果您熟悉如何在 GitHub 上贡献,可以直接查看我们的 \"贡献者入门指南\" `_ 和 \"优秀的首次贡献示例\" " +"`_。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:12 +#: ../../source/contributor-tutorial-contribute-on-github.rst:11 msgid "Setting up the repository" msgstr "建立资源库" -#: ../../source/contributor-tutorial-contribute-on-github.rst:23 +#: ../../source/contributor-tutorial-contribute-on-github.rst:22 msgid "**Create a GitHub account and setup Git**" msgstr "**创建 GitHub 账户并设置 Git**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:15 +#: ../../source/contributor-tutorial-contribute-on-github.rst:14 msgid "" "Git is a distributed version control tool. This allows for an entire " "codebase's history to be stored and every developer's machine. It is a " "software that will need to be installed on your local machine, you can " -"follow this `guide `_ to set it up." +"follow this `guide `_ to set it up." msgstr "" -"Git 是一种分布式版本控制工具。它可以将整个代码库的历史记录保存在每个开发人员" -"的机器上。您需要在本地计算机上安装该软件,可以按照本指南 `_ 进行设置。" +"Git 是一种分布式版本控制工具。它可以将整个代码库的历史记录保存在每个开发人员的机器上。您需要在本地计算机上安装该软件,可以按照本指南 " +"`_ 进行设置。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:18 +#: ../../source/contributor-tutorial-contribute-on-github.rst:17 msgid "" "GitHub, itself, is a code hosting platform for version control and " -"collaboration. It allows for everyone to collaborate and work from anywhere " -"on remote repositories." -msgstr "" -"GitHub 本身是一个用于版本控制和协作的代码托管平台。它允许每个人在任何地方对远" -"程仓库进行协作和工作。" +"collaboration. It allows for everyone to collaborate and work from " +"anywhere on remote repositories." +msgstr "GitHub 本身是一个用于版本控制和协作的代码托管平台。它允许每个人在任何地方对远程仓库进行协作和工作。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:20 +#: ../../source/contributor-tutorial-contribute-on-github.rst:19 msgid "" "If you haven't already, you will need to create an account on `GitHub " "`_." -msgstr "" -"如果还没有,您需要在 `GitHub `_ 上创建一个账户。" +msgstr "如果还没有,您需要在 `GitHub `_ 上创建一个账户。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:22 +#: ../../source/contributor-tutorial-contribute-on-github.rst:21 msgid "" -"The idea behind the generic Git and GitHub workflow boils down to this: you " -"download code from a remote repository on GitHub, make changes locally and " -"keep track of them using Git and then you upload your new history back to " -"GitHub." +"The idea behind the generic Git and GitHub workflow boils down to this: " +"you download code from a remote repository on GitHub, make changes " +"locally and keep track of them using Git and then you upload your new " +"history back to GitHub." msgstr "" -"通用的 Git 和 GitHub 工作流程背后的理念可以归结为:从 GitHub 上的远程仓库下载" -"代码,在本地进行修改并使用 Git 进行跟踪,然后将新的历史记录上传回 GitHub。" +"通用的 Git 和 GitHub 工作流程背后的理念可以归结为:从 GitHub 上的远程仓库下载代码,在本地进行修改并使用 Git " +"进行跟踪,然后将新的历史记录上传回 GitHub。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:34 +#: ../../source/contributor-tutorial-contribute-on-github.rst:33 msgid "**Forking the Flower repository**" msgstr "**叉花仓库**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:26 +#: ../../source/contributor-tutorial-contribute-on-github.rst:25 msgid "" -"A fork is a personal copy of a GitHub repository. To create one for Flower, " -"you must navigate to https://github.com/adap/flower (while connected to your " -"GitHub account) and click the ``Fork`` button situated on the top right of " -"the page." +"A fork is a personal copy of a GitHub repository. To create one for " +"Flower, you must navigate to https://github.com/adap/flower (while " +"connected to your GitHub account) and click the ``Fork`` button situated " +"on the top right of the page." msgstr "" "fork 是 GitHub 仓库的个人副本。要为 Flower 创建一个 fork,您必须导航到 " -"https://github.com/adap/flower(同时连接到您的 GitHub 账户),然后点击页面右" -"上方的 ``Fork`` 按钮。" +"https://github.com/adap/flower(同时连接到您的 GitHub 账户),然后点击页面右上方的 ``Fork`` 按钮。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:31 +#: ../../source/contributor-tutorial-contribute-on-github.rst:30 msgid "" "You can change the name if you want, but this is not necessary as this " -"version of Flower will be yours and will sit inside your own account (i.e., " -"in your own list of repositories). Once created, you should see on the top " -"left corner that you are looking at your own version of Flower." +"version of Flower will be yours and will sit inside your own account " +"(i.e., in your own list of repositories). Once created, you should see on" +" the top left corner that you are looking at your own version of Flower." msgstr "" -"您可以更改名称,但没有必要,因为这个版本的 Flower 将是您自己的,并位于您自己" -"的账户中(即,在您自己的版本库列表中)。创建完成后,您会在左上角看到自己的 " -"Flower 版本。" +"您可以更改名称,但没有必要,因为这个版本的 Flower " +"将是您自己的,并位于您自己的账户中(即,在您自己的版本库列表中)。创建完成后,您会在左上角看到自己的 Flower 版本。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:49 +#: ../../source/contributor-tutorial-contribute-on-github.rst:48 msgid "**Cloning your forked repository**" msgstr "**克隆你的分叉仓库**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:37 +#: ../../source/contributor-tutorial-contribute-on-github.rst:36 msgid "" "The next step is to download the forked repository on your machine to be " -"able to make changes to it. On your forked repository page, you should first " -"click on the ``Code`` button on the right, this will give you the ability to " -"copy the HTTPS link of the repository." +"able to make changes to it. On your forked repository page, you should " +"first click on the ``Code`` button on the right, this will give you the " +"ability to copy the HTTPS link of the repository." msgstr "" -"下一步是在你的机器上下载分叉版本库,以便对其进行修改。在分叉版本库页面上,首" -"先点击右侧的 \"代码 \"按钮,这样就能复制版本库的 HTTPS 链接。" +"下一步是在你的机器上下载分叉版本库,以便对其进行修改。在分叉版本库页面上,首先点击右侧的 \"代码 \"按钮,这样就能复制版本库的 HTTPS " +"链接。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:43 +#: ../../source/contributor-tutorial-contribute-on-github.rst:42 msgid "" "Once you copied the \\, you can open a terminal on your machine, " "navigate to the place you want to download the repository to and type:" -msgstr "" -"一旦复制了 (),你就可以在你的机器上打开一个终端,导航到你想下载软件" -"源的地方,然后键入:" +msgstr "一旦复制了 (),你就可以在你的机器上打开一个终端,导航到你想下载软件源的地方,然后键入:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:49 +#: ../../source/contributor-tutorial-contribute-on-github.rst:48 +#, fuzzy msgid "" -"This will create a `flower/` (or the name of your fork if you renamed it) " -"folder in the current working directory." -msgstr "" -"这将在当前工作目录下创建一个 `flower/`(如果重命名了,则使用 fork 的名称)文" -"件夹。" +"This will create a ``flower/`` (or the name of your fork if you renamed " +"it) folder in the current working directory." +msgstr "这将在当前工作目录下创建一个 `flower/`(如果重命名了,则使用 fork 的名称)文件夹。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:68 +#: ../../source/contributor-tutorial-contribute-on-github.rst:67 msgid "**Add origin**" msgstr "**添加原产地**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:52 +#: ../../source/contributor-tutorial-contribute-on-github.rst:51 msgid "You can then go into the repository folder:" msgstr "然后,您就可以进入存储库文件夹:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:58 +#: ../../source/contributor-tutorial-contribute-on-github.rst:57 msgid "" -"And here we will need to add an origin to our repository. The origin is the " -"\\ of the remote fork repository. To obtain it, we can do as " -"previously mentioned by going to our fork repository on our GitHub account " -"and copying the link." +"And here we will need to add an origin to our repository. The origin is " +"the \\ of the remote fork repository. To obtain it, we can do as " +"previously mentioned by going to our fork repository on our GitHub " +"account and copying the link." msgstr "" "在这里,我们需要为我们的版本库添加一个 origin。origin 是远程 fork 仓库的 " -"\\。要获得它,我们可以像前面提到的那样,访问 GitHub 账户上的分叉仓库并" -"复制链接。" +"\\。要获得它,我们可以像前面提到的那样,访问 GitHub 账户上的分叉仓库并复制链接。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:63 +#: ../../source/contributor-tutorial-contribute-on-github.rst:62 msgid "" "Once the \\ is copied, we can type the following command in our " "terminal:" msgstr "一旦复制了 \\ ,我们就可以在终端中键入以下命令:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:92 +#: ../../source/contributor-tutorial-contribute-on-github.rst:91 msgid "**Add upstream**" msgstr "**增加上游**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:71 +#: ../../source/contributor-tutorial-contribute-on-github.rst:70 msgid "" "Now we will add an upstream address to our repository. Still in the same " "directroy, we must run the following command:" -msgstr "" -"现在,我们要为版本库添加一个上游地址。还是在同一目录下,我们必须运行以下命" -"令:" +msgstr "现在,我们要为版本库添加一个上游地址。还是在同一目录下,我们必须运行以下命令:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:78 -msgid "" -"The following diagram visually explains what we did in the previous steps:" +#: ../../source/contributor-tutorial-contribute-on-github.rst:77 +msgid "The following diagram visually explains what we did in the previous steps:" msgstr "下图直观地解释了我们在前面步骤中的操作:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:82 +#: ../../source/contributor-tutorial-contribute-on-github.rst:81 msgid "" -"The upstream is the GitHub remote address of the parent repository (in this " -"case Flower), i.e. the one we eventually want to contribute to and therefore " -"need an up-to-date history of. The origin is just the GitHub remote address " -"of the forked repository we created, i.e. the copy (fork) in our own account." +"The upstream is the GitHub remote address of the parent repository (in " +"this case Flower), i.e. the one we eventually want to contribute to and " +"therefore need an up-to-date history of. The origin is just the GitHub " +"remote address of the forked repository we created, i.e. the copy (fork) " +"in our own account." msgstr "" -"上游是父版本库(这里是 Flower)的 GitHub 远程地址,即我们最终要贡献的版本库," -"因此需要最新的历史记录。origin 只是我们创建的分叉仓库的 GitHub 远程地址,即我" -"们自己账户中的副本(分叉)。" +"上游是父版本库(这里是 Flower)的 GitHub 远程地址,即我们最终要贡献的版本库,因此需要最新的历史记录。origin " +"只是我们创建的分叉仓库的 GitHub 远程地址,即我们自己账户中的副本(分叉)。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:86 +#: ../../source/contributor-tutorial-contribute-on-github.rst:85 msgid "" "To make sure our local version of the fork is up-to-date with the latest " "changes from the Flower repository, we can execute the following command:" -msgstr "" -"为了确保本地版本的分叉程序与 Flower 代码库的最新更改保持一致,我们可以执行以" -"下命令:" +msgstr "为了确保本地版本的分叉程序与 Flower 代码库的最新更改保持一致,我们可以执行以下命令:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:95 +#: ../../source/contributor-tutorial-contribute-on-github.rst:94 msgid "Setting up the coding environment" msgstr "设置编码环境" -#: ../../source/contributor-tutorial-contribute-on-github.rst:97 +#: ../../source/contributor-tutorial-contribute-on-github.rst:96 msgid "" "This can be achieved by following this `getting started guide for " -"contributors`_ (note that you won't need to clone the repository). Once you " -"are able to write code and test it, you can finally start making changes!" -msgstr "" -"您可以按照这份 \"贡献者入门指南\"__(注意,您不需要克隆版本库)来实现这一点。" -"一旦您能够编写代码并进行测试,您就可以开始修改了!" +"contributors`_ (note that you won't need to clone the repository). Once " +"you are able to write code and test it, you can finally start making " +"changes!" +msgstr "您可以按照这份 \"贡献者入门指南\"__(注意,您不需要克隆版本库)来实现这一点。一旦您能够编写代码并进行测试,您就可以开始修改了!" -#: ../../source/contributor-tutorial-contribute-on-github.rst:102 +#: ../../source/contributor-tutorial-contribute-on-github.rst:101 msgid "Making changes" msgstr "做出改变" -#: ../../source/contributor-tutorial-contribute-on-github.rst:104 +#: ../../source/contributor-tutorial-contribute-on-github.rst:103 msgid "" -"Before making any changes make sure you are up-to-date with your repository:" +"Before making any changes make sure you are up-to-date with your " +"repository:" msgstr "在进行任何更改之前,请确保您的版本库是最新的:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:110 +#: ../../source/contributor-tutorial-contribute-on-github.rst:109 msgid "And with Flower's repository:" msgstr "还有Flower的存储库:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:124 +#: ../../source/contributor-tutorial-contribute-on-github.rst:123 msgid "**Create a new branch**" msgstr "**创建一个新分支**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:117 +#: ../../source/contributor-tutorial-contribute-on-github.rst:116 msgid "" -"To make the history cleaner and easier to work with, it is good practice to " -"create a new branch for each feature/project that needs to be implemented." -msgstr "" -"为了使历史记录更简洁、更易于操作,为每个需要实现的功能/项目创建一个新分支是个" -"不错的做法。" +"To make the history cleaner and easier to work with, it is good practice " +"to create a new branch for each feature/project that needs to be " +"implemented." +msgstr "为了使历史记录更简洁、更易于操作,为每个需要实现的功能/项目创建一个新分支是个不错的做法。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:120 +#: ../../source/contributor-tutorial-contribute-on-github.rst:119 msgid "" -"To do so, just run the following command inside the repository's directory:" +"To do so, just run the following command inside the repository's " +"directory:" msgstr "为此,只需在版本库目录下运行以下命令即可:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:127 +#: ../../source/contributor-tutorial-contribute-on-github.rst:126 msgid "**Make changes**" msgstr "**进行修改**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:127 -msgid "" -"Write great code and create wonderful changes using your favorite editor!" +#: ../../source/contributor-tutorial-contribute-on-github.rst:126 +msgid "Write great code and create wonderful changes using your favorite editor!" msgstr "使用您最喜欢的编辑器编写优秀的代码并创建精彩的更改!" -#: ../../source/contributor-tutorial-contribute-on-github.rst:140 +#: ../../source/contributor-tutorial-contribute-on-github.rst:139 msgid "**Test and format your code**" msgstr "**测试并格式化您的代码**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:130 +#: ../../source/contributor-tutorial-contribute-on-github.rst:129 msgid "" -"Don't forget to test and format your code! Otherwise your code won't be able " -"to be merged into the Flower repository. This is done so the codebase stays " -"consistent and easy to understand." -msgstr "" -"不要忘记测试和格式化您的代码!否则您的代码将无法并入 Flower 代码库。这样做是" -"为了使代码库保持一致并易于理解。" +"Don't forget to test and format your code! Otherwise your code won't be " +"able to be merged into the Flower repository. This is done so the " +"codebase stays consistent and easy to understand." +msgstr "不要忘记测试和格式化您的代码!否则您的代码将无法并入 Flower 代码库。这样做是为了使代码库保持一致并易于理解。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:133 +#: ../../source/contributor-tutorial-contribute-on-github.rst:132 msgid "To do so, we have written a few scripts that you can execute:" msgstr "为此,我们编写了一些脚本供您执行:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:152 +#: ../../source/contributor-tutorial-contribute-on-github.rst:151 msgid "**Stage changes**" msgstr "**舞台变化**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:143 +#: ../../source/contributor-tutorial-contribute-on-github.rst:142 msgid "" -"Before creating a commit that will update your history, you must specify to " -"Git which files it needs to take into account." +"Before creating a commit that will update your history, you must specify " +"to Git which files it needs to take into account." msgstr "在创建更新历史记录的提交之前,必须向 Git 说明需要考虑哪些文件。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:145 +#: ../../source/contributor-tutorial-contribute-on-github.rst:144 msgid "This can be done with:" msgstr "这可以通过:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:151 +#: ../../source/contributor-tutorial-contribute-on-github.rst:150 msgid "" -"To check which files have been modified compared to the last version (last " -"commit) and to see which files are staged for commit, you can use the :code:" -"`git status` command." -msgstr "" -"要查看与上一版本(上次提交)相比哪些文件已被修改,以及哪些文件处于提交阶段," -"可以使用 :code:`git status` 命令。" +"To check which files have been modified compared to the last version " +"(last commit) and to see which files are staged for commit, you can use " +"the :code:`git status` command." +msgstr "要查看与上一版本(上次提交)相比哪些文件已被修改,以及哪些文件处于提交阶段,可以使用 :code:`git status` 命令。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:162 +#: ../../source/contributor-tutorial-contribute-on-github.rst:161 msgid "**Commit changes**" msgstr "**提交更改**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:155 +#: ../../source/contributor-tutorial-contribute-on-github.rst:154 msgid "" "Once you have added all the files you wanted to commit using :code:`git " "add`, you can finally create your commit using this command:" -msgstr "" -"使用 :code:`git add` 添加完所有要提交的文件后,就可以使用此命令创建提交了:" +msgstr "使用 :code:`git add` 添加完所有要提交的文件后,就可以使用此命令创建提交了:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:161 +#: ../../source/contributor-tutorial-contribute-on-github.rst:160 msgid "" -"The \\ is there to explain to others what the commit does. " -"It should be written in an imperative style and be concise. An example would " -"be :code:`git commit -m \"Add images to README\"`." +"The \\ is there to explain to others what the commit " +"does. It should be written in an imperative style and be concise. An " +"example would be :code:`git commit -m \"Add images to README\"`." msgstr "" -" 用于向他人解释提交的作用。它应该以命令式风格书写,并且简明" -"扼要。例如 :code:`git commit -m \"Add images to README\"`。" +" 用于向他人解释提交的作用。它应该以命令式风格书写,并且简明扼要。例如 :code:`git commit " +"-m \"Add images to README\"`。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:173 +#: ../../source/contributor-tutorial-contribute-on-github.rst:172 msgid "**Push the changes to the fork**" msgstr "**将更改推送到分叉**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:165 +#: ../../source/contributor-tutorial-contribute-on-github.rst:164 msgid "" -"Once we have committed our changes, we have effectively updated our local " -"history, but GitHub has no way of knowing this unless we push our changes to " -"our origin's remote address:" -msgstr "" -"一旦提交了修改,我们就有效地更新了本地历史记录,但除非我们将修改推送到原点的" -"远程地址,否则 GitHub 无法得知:" +"Once we have committed our changes, we have effectively updated our local" +" history, but GitHub has no way of knowing this unless we push our " +"changes to our origin's remote address:" +msgstr "一旦提交了修改,我们就有效地更新了本地历史记录,但除非我们将修改推送到原点的远程地址,否则 GitHub 无法得知:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:172 +#: ../../source/contributor-tutorial-contribute-on-github.rst:171 msgid "" "Once this is done, you will see on the GitHub that your forked repo was " "updated with the changes you have made." -msgstr "" -"完成此操作后,您将在 GitHub 上看到您的分叉仓库已根据您所做的更改进行了更新。" +msgstr "完成此操作后,您将在 GitHub 上看到您的分叉仓库已根据您所做的更改进行了更新。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:176 +#: ../../source/contributor-tutorial-contribute-on-github.rst:175 msgid "Creating and merging a pull request (PR)" msgstr "创建和合并拉取请求 (PR)" -#: ../../source/contributor-tutorial-contribute-on-github.rst:203 +#: ../../source/contributor-tutorial-contribute-on-github.rst:206 msgid "**Create the PR**" msgstr "**创建 PR**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:179 +#: ../../source/contributor-tutorial-contribute-on-github.rst:178 msgid "" -"Once you have pushed changes, on the GitHub webpage of your repository you " -"should see the following message:" +"Once you have pushed changes, on the GitHub webpage of your repository " +"you should see the following message:" msgstr "推送更改后,在仓库的 GitHub 网页上应该会看到以下信息:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:183 -msgid "Otherwise you can always find this option in the `Branches` page." +#: ../../source/contributor-tutorial-contribute-on-github.rst:182 +#, fuzzy +msgid "Otherwise you can always find this option in the ``Branches`` page." msgstr "否则,您可以在 \"分支 \"页面找到该选项。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:185 +#: ../../source/contributor-tutorial-contribute-on-github.rst:184 +#, fuzzy msgid "" -"Once you click the `Compare & pull request` button, you should see something " -"similar to this:" +"Once you click the ``Compare & pull request`` button, you should see " +"something similar to this:" msgstr "点击 \"比较和拉取请求 \"按钮后,您应该会看到类似下面的内容:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:189 -msgid "" -"At the top you have an explanation of which branch will be merged where:" +#: ../../source/contributor-tutorial-contribute-on-github.rst:188 +msgid "At the top you have an explanation of which branch will be merged where:" msgstr "在顶部,你可以看到关于哪个分支将被合并的说明:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:193 +#: ../../source/contributor-tutorial-contribute-on-github.rst:192 msgid "" -"In this example you can see that the request is to merge the branch ``doc-" -"fixes`` from my forked repository to branch ``main`` from the Flower " -"repository." -msgstr "" -"在这个例子中,你可以看到请求将我分叉的版本库中的分支 ``doc-fixes`` 合并到 " -"Flower 版本库中的分支 ``main``。" +"In this example you can see that the request is to merge the branch " +"``doc-fixes`` from my forked repository to branch ``main`` from the " +"Flower repository." +msgstr "在这个例子中,你可以看到请求将我分叉的版本库中的分支 ``doc-fixes`` 合并到 Flower 版本库中的分支 ``main``。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:195 +#: ../../source/contributor-tutorial-contribute-on-github.rst:194 msgid "" -"The input box in the middle is there for you to describe what your PR does " -"and to link it to existing issues. We have placed comments (that won't be " -"rendered once the PR is opened) to guide you through the process." -msgstr "" -"中间的输入框供您描述 PR 的作用,并将其与现有问题联系起来。我们在此放置了注释" -"(一旦 PR 打开,注释将不会显示),以指导您完成整个过程。" +"The input box in the middle is there for you to describe what your PR " +"does and to link it to existing issues. We have placed comments (that " +"won't be rendered once the PR is opened) to guide you through the " +"process." +msgstr "中间的输入框供您描述 PR 的作用,并将其与现有问题联系起来。我们在此放置了注释(一旦 PR 打开,注释将不会显示),以指导您完成整个过程。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:198 +#: ../../source/contributor-tutorial-contribute-on-github.rst:197 msgid "" -"At the bottom you will find the button to open the PR. This will notify " -"reviewers that a new PR has been opened and that they should look over it to " -"merge or to request changes." +"It is important to follow the instructions described in comments. For " +"instance, in order to not break how our changelog system works, you " +"should read the information above the ``Changelog entry`` section " +"carefully. You can also checkout some examples and details in the " +":ref:`changelogentry` appendix." msgstr "" -"在底部,您可以找到打开 PR 的按钮。这将通知审核人员新的 PR 已经打开,他们应该" -"查看该 PR 以进行合并或要求修改。" #: ../../source/contributor-tutorial-contribute-on-github.rst:201 msgid "" -"If your PR is not yet ready for review, and you don't want to notify anyone, " -"you have the option to create a draft pull request:" -msgstr "" -"如果您的 PR 尚未准备好接受审核,而且您不想通知任何人,您可以选择创建一个草案" -"拉取请求:" +"At the bottom you will find the button to open the PR. This will notify " +"reviewers that a new PR has been opened and that they should look over it" +" to merge or to request changes." +msgstr "在底部,您可以找到打开 PR 的按钮。这将通知审核人员新的 PR 已经打开,他们应该查看该 PR 以进行合并或要求修改。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:206 +#: ../../source/contributor-tutorial-contribute-on-github.rst:204 +msgid "" +"If your PR is not yet ready for review, and you don't want to notify " +"anyone, you have the option to create a draft pull request:" +msgstr "如果您的 PR 尚未准备好接受审核,而且您不想通知任何人,您可以选择创建一个草案拉取请求:" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:209 msgid "**Making new changes**" msgstr "**作出新的改变**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:206 +#: ../../source/contributor-tutorial-contribute-on-github.rst:209 msgid "" "Once the PR has been opened (as draft or not), you can still push new " -"commits to it the same way we did before, by making changes to the branch " -"associated with the PR." -msgstr "" -"一旦 PR 被打开(无论是否作为草案),你仍然可以像以前一样,通过修改与 PR 关联" -"的分支来推送新的提交。" +"commits to it the same way we did before, by making changes to the branch" +" associated with the PR." +msgstr "一旦 PR 被打开(无论是否作为草案),你仍然可以像以前一样,通过修改与 PR 关联的分支来推送新的提交。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:228 +#: ../../source/contributor-tutorial-contribute-on-github.rst:231 msgid "**Review the PR**" msgstr "**审查 PR**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:209 +#: ../../source/contributor-tutorial-contribute-on-github.rst:212 msgid "" -"Once the PR has been opened or once the draft PR has been marked as ready, a " -"review from code owners will be automatically requested:" +"Once the PR has been opened or once the draft PR has been marked as " +"ready, a review from code owners will be automatically requested:" msgstr "一旦 PR 被打开或 PR 草案被标记为就绪,就会自动要求代码所有者进行审核:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:213 +#: ../../source/contributor-tutorial-contribute-on-github.rst:216 msgid "" -"Code owners will then look into the code, ask questions, request changes or " -"validate the PR." +"Code owners will then look into the code, ask questions, request changes " +"or validate the PR." msgstr "然后,代码所有者会查看代码、提出问题、要求修改或验证 PR。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:215 +#: ../../source/contributor-tutorial-contribute-on-github.rst:218 msgid "Merging will be blocked if there are ongoing requested changes." msgstr "如果有正在进行的更改请求,合并将被阻止。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:219 +#: ../../source/contributor-tutorial-contribute-on-github.rst:222 msgid "" -"To resolve them, just push the necessary changes to the branch associated " -"with the PR:" +"To resolve them, just push the necessary changes to the branch associated" +" with the PR:" msgstr "要解决这些问题,只需将必要的更改推送到与 PR 关联的分支即可:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:223 +#: ../../source/contributor-tutorial-contribute-on-github.rst:226 msgid "And resolve the conversation:" msgstr "并解决对话:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:227 +#: ../../source/contributor-tutorial-contribute-on-github.rst:230 msgid "" -"Once all the conversations have been resolved, you can re-request a review." +"Once all the conversations have been resolved, you can re-request a " +"review." msgstr "一旦所有对话都得到解决,您就可以重新申请审核。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:248 +#: ../../source/contributor-tutorial-contribute-on-github.rst:251 msgid "**Once the PR is merged**" msgstr "**一旦 PR 被合并**" -#: ../../source/contributor-tutorial-contribute-on-github.rst:231 +#: ../../source/contributor-tutorial-contribute-on-github.rst:234 msgid "" -"If all the automatic tests have passed and reviewers have no more changes to " -"request, they can approve the PR and merge it." -msgstr "" -"如果所有自动测试都已通过,且审核员不再需要修改,他们就可以批准 PR 并将其合" -"并。" +"If all the automatic tests have passed and reviewers have no more changes" +" to request, they can approve the PR and merge it." +msgstr "如果所有自动测试都已通过,且审核员不再需要修改,他们就可以批准 PR 并将其合并。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:235 +#: ../../source/contributor-tutorial-contribute-on-github.rst:238 msgid "" "Once it is merged, you can delete the branch on GitHub (a button should " "appear to do so) and also delete it locally by doing:" -msgstr "" -"合并后,您可以在 GitHub 上删除该分支(会出现一个删除按钮),也可以在本地删除" -"该分支:" +msgstr "合并后,您可以在 GitHub 上删除该分支(会出现一个删除按钮),也可以在本地删除该分支:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:242 +#: ../../source/contributor-tutorial-contribute-on-github.rst:245 msgid "Then you should update your forked repository by doing:" msgstr "然后,你应该更新你的分叉仓库:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:251 +#: ../../source/contributor-tutorial-contribute-on-github.rst:254 msgid "Example of first contribution" msgstr "首次捐款实例" -#: ../../source/contributor-tutorial-contribute-on-github.rst:254 +#: ../../source/contributor-tutorial-contribute-on-github.rst:257 msgid "Problem" msgstr "问题" -#: ../../source/contributor-tutorial-contribute-on-github.rst:256 +#: ../../source/contributor-tutorial-contribute-on-github.rst:259 msgid "" -"For our documentation, we’ve started to use the `Diàtaxis framework `_." -msgstr "" -"对于我们的文档,我们已经开始使用 \"Diàtaxis 框架 `_\"。" +"For our documentation, we’ve started to use the `Diàtaxis framework " +"`_." +msgstr "对于我们的文档,我们已经开始使用 \"Diàtaxis 框架 `_\"。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:258 +#: ../../source/contributor-tutorial-contribute-on-github.rst:261 msgid "" -"Our “How to” guides should have titles that continue the sencence “How to " -"…”, for example, “How to upgrade to Flower 1.0”." -msgstr "" -"我们的 \"如何 \"指南的标题应延续 \"如何...... \"的句式,例如 \"如何升级到 " -"Flower 1.0\"。" +"Our “How to” guides should have titles that continue the sencence “How to" +" …”, for example, “How to upgrade to Flower 1.0”." +msgstr "我们的 \"如何 \"指南的标题应延续 \"如何...... \"的句式,例如 \"如何升级到 Flower 1.0\"。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:260 +#: ../../source/contributor-tutorial-contribute-on-github.rst:263 msgid "" "Most of our guides do not follow this new format yet, and changing their " "title is (unfortunately) more involved than one might think." -msgstr "" -"我们的大多数指南还没有采用这种新格式,而更改其标题(不幸的是)比人们想象的要" -"复杂得多。" +msgstr "我们的大多数指南还没有采用这种新格式,而更改其标题(不幸的是)比人们想象的要复杂得多。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:262 +#: ../../source/contributor-tutorial-contribute-on-github.rst:265 msgid "" -"This issue is about changing the title of a doc from present continious to " -"present simple." +"This issue is about changing the title of a doc from present continious " +"to present simple." msgstr "这个问题是关于将文档标题从现在进行时改为现在进行时。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:264 +#: ../../source/contributor-tutorial-contribute-on-github.rst:267 msgid "" "Let's take the example of “Saving Progress” which we changed to “Save " "Progress”. Does this pass our check?" -msgstr "" -"以 \"保存进度 \"为例,我们将其改为 \"保存进度\"。这是否通过了我们的检查?" +msgstr "以 \"保存进度 \"为例,我们将其改为 \"保存进度\"。这是否通过了我们的检查?" -#: ../../source/contributor-tutorial-contribute-on-github.rst:266 +#: ../../source/contributor-tutorial-contribute-on-github.rst:269 msgid "Before: ”How to saving progress” ❌" msgstr "之前: \"如何保存进度\" ❌" -#: ../../source/contributor-tutorial-contribute-on-github.rst:268 +#: ../../source/contributor-tutorial-contribute-on-github.rst:271 msgid "After: ”How to save progress” ✅" msgstr "之后: \"如何保存进度\"✅" -#: ../../source/contributor-tutorial-contribute-on-github.rst:271 +#: ../../source/contributor-tutorial-contribute-on-github.rst:274 msgid "Solution" msgstr "解决方案" -#: ../../source/contributor-tutorial-contribute-on-github.rst:273 +#: ../../source/contributor-tutorial-contribute-on-github.rst:276 msgid "" "This is a tiny change, but it’ll allow us to test your end-to-end setup. " "After cloning and setting up the Flower repo, here’s what you should do:" -msgstr "" -"这只是一个很小的改动,但可以让我们测试你的端到端设置。克隆并设置好 Flower " -"repo 后,你应该这样做:" +msgstr "这只是一个很小的改动,但可以让我们测试你的端到端设置。克隆并设置好 Flower repo 后,你应该这样做:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:275 -msgid "Find the source file in `doc/source`" +#: ../../source/contributor-tutorial-contribute-on-github.rst:278 +#, fuzzy +msgid "Find the source file in ``doc/source``" msgstr "在 `doc/source` 中查找源文件" -#: ../../source/contributor-tutorial-contribute-on-github.rst:276 +#: ../../source/contributor-tutorial-contribute-on-github.rst:279 +#, fuzzy msgid "" -"Make the change in the `.rst` file (beware, the dashes under the title " +"Make the change in the ``.rst`` file (beware, the dashes under the title " "should be the same length as the title itself)" msgstr "在 `.rst` 文件中进行修改(注意,标题下的破折号应与标题本身的长度相同)" -#: ../../source/contributor-tutorial-contribute-on-github.rst:277 +#: ../../source/contributor-tutorial-contribute-on-github.rst:280 msgid "" "Build the docs and check the result: ``_" msgstr "" -"构建文档并检查结果: ``_" +"构建文档并检查结果: ``_" -#: ../../source/contributor-tutorial-contribute-on-github.rst:280 +#: ../../source/contributor-tutorial-contribute-on-github.rst:283 msgid "Rename file" msgstr "重命名文件" -#: ../../source/contributor-tutorial-contribute-on-github.rst:282 +#: ../../source/contributor-tutorial-contribute-on-github.rst:285 msgid "" -"You might have noticed that the file name still reflects the old wording. If " -"we just change the file, then we break all existing links to it - it is " -"**very important** to avoid that, breaking links can harm our search engine " -"ranking." +"You might have noticed that the file name still reflects the old wording." +" If we just change the file, then we break all existing links to it - it " +"is **very important** to avoid that, breaking links can harm our search " +"engine ranking." msgstr "" -"您可能已经注意到,文件名仍然反映了旧的措辞。如果我们只是更改文件,那么就会破" -"坏与该文件的所有现有链接--避免这种情况是***重要的,破坏链接会损害我们的搜索引" -"擎排名。" +"您可能已经注意到,文件名仍然反映了旧的措辞。如果我们只是更改文件,那么就会破坏与该文件的所有现有链接--" +"避免这种情况是***重要的,破坏链接会损害我们的搜索引擎排名。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:285 +#: ../../source/contributor-tutorial-contribute-on-github.rst:288 msgid "Here’s how to change the file name:" msgstr "下面是更改文件名的方法:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:287 -msgid "Change the file name to `save-progress.rst`" +#: ../../source/contributor-tutorial-contribute-on-github.rst:290 +#, fuzzy +msgid "Change the file name to ``save-progress.rst``" msgstr "将文件名改为`save-progress.rst`" -#: ../../source/contributor-tutorial-contribute-on-github.rst:288 -msgid "Add a redirect rule to `doc/source/conf.py`" +#: ../../source/contributor-tutorial-contribute-on-github.rst:291 +#, fuzzy +msgid "Add a redirect rule to ``doc/source/conf.py``" msgstr "在 `doc/source/conf.py` 中添加重定向规则" -#: ../../source/contributor-tutorial-contribute-on-github.rst:290 +#: ../../source/contributor-tutorial-contribute-on-github.rst:293 +#, fuzzy msgid "" -"This will cause a redirect from `saving-progress.html` to `save-progress." -"html`, old links will continue to work." -msgstr "" -"这将导致从 `saving-progress.html` 重定向到 `save-progress.html`,旧链接将继续" -"工作。" +"This will cause a redirect from ``saving-progress.html`` to ``save-" +"progress.html``, old links will continue to work." +msgstr "这将导致从 `saving-progress.html` 重定向到 `save-progress.html`,旧链接将继续工作。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:293 +#: ../../source/contributor-tutorial-contribute-on-github.rst:296 msgid "Apply changes in the index file" msgstr "应用索引文件中的更改" -#: ../../source/contributor-tutorial-contribute-on-github.rst:295 +#: ../../source/contributor-tutorial-contribute-on-github.rst:298 +#, fuzzy msgid "" "For the lateral navigation bar to work properly, it is very important to " -"update the `index.rst` file as well. This is where we define the whole " +"update the ``index.rst`` file as well. This is where we define the whole " "arborescence of the navbar." -msgstr "" -"要使横向导航栏正常工作,更新 `index.rst` 文件也非常重要。我们就是在这里定义整" -"个导航栏的结构。" +msgstr "要使横向导航栏正常工作,更新 `index.rst` 文件也非常重要。我们就是在这里定义整个导航栏的结构。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:298 -msgid "Find and modify the file name in `index.rst`" +#: ../../source/contributor-tutorial-contribute-on-github.rst:301 +#, fuzzy +msgid "Find and modify the file name in ``index.rst``" msgstr "查找并修改 `index.rst` 中的文件名" -#: ../../source/contributor-tutorial-contribute-on-github.rst:301 +#: ../../source/contributor-tutorial-contribute-on-github.rst:304 msgid "Open PR" msgstr "开放式 PR" -#: ../../source/contributor-tutorial-contribute-on-github.rst:303 +#: ../../source/contributor-tutorial-contribute-on-github.rst:306 msgid "" -"Commit the changes (commit messages are always imperative: “Do something”, " -"in this case “Change …”)" +"Commit the changes (commit messages are always imperative: “Do " +"something”, in this case “Change …”)" msgstr "提交更改(提交信息总是命令式的:\"做某事\",这里是 \"更改......\")" -#: ../../source/contributor-tutorial-contribute-on-github.rst:304 +#: ../../source/contributor-tutorial-contribute-on-github.rst:307 msgid "Push the changes to your fork" msgstr "将更改推送到分叉" -#: ../../source/contributor-tutorial-contribute-on-github.rst:305 +#: ../../source/contributor-tutorial-contribute-on-github.rst:308 msgid "Open a PR (as shown above)" msgstr "打开 PR(如上图所示)" -#: ../../source/contributor-tutorial-contribute-on-github.rst:306 +#: ../../source/contributor-tutorial-contribute-on-github.rst:309 msgid "Wait for it to be approved!" msgstr "等待审批!" -#: ../../source/contributor-tutorial-contribute-on-github.rst:307 +#: ../../source/contributor-tutorial-contribute-on-github.rst:310 msgid "Congrats! 🥳 You're now officially a Flower contributor!" msgstr "祝贺你 🥳 您现在正式成为 \"Flower \"贡献者!" -#: ../../source/contributor-tutorial-contribute-on-github.rst:311 +#: ../../source/contributor-tutorial-contribute-on-github.rst:314 msgid "How to write a good PR title" msgstr "如何撰写好的公关标题" -#: ../../source/contributor-tutorial-contribute-on-github.rst:313 +#: ../../source/contributor-tutorial-contribute-on-github.rst:316 msgid "" -"A well-crafted PR title helps team members quickly understand the purpose " -"and scope of the changes being proposed. Here's a guide to help you write a " -"good GitHub PR title:" -msgstr "" -"一个精心撰写的公关标题能帮助团队成员迅速了解所提修改的目的和范围。以下指南可" -"帮助您撰写一个好的 GitHub PR 标题:" +"A well-crafted PR title helps team members quickly understand the purpose" +" and scope of the changes being proposed. Here's a guide to help you " +"write a good GitHub PR title:" +msgstr "一个精心撰写的公关标题能帮助团队成员迅速了解所提修改的目的和范围。以下指南可帮助您撰写一个好的 GitHub PR 标题:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:315 +#: ../../source/contributor-tutorial-contribute-on-github.rst:318 msgid "" -"1. Be Clear and Concise: Provide a clear summary of the changes in a concise " -"manner. 1. Use Actionable Verbs: Start with verbs like \"Add,\" \"Update,\" " -"or \"Fix\" to indicate the purpose. 1. Include Relevant Information: Mention " -"the affected feature or module for context. 1. Keep it Short: Avoid lengthy " -"titles for easy readability. 1. Use Proper Capitalization and Punctuation: " -"Follow grammar rules for clarity." +"1. Be Clear and Concise: Provide a clear summary of the changes in a " +"concise manner. 1. Use Actionable Verbs: Start with verbs like \"Add,\" " +"\"Update,\" or \"Fix\" to indicate the purpose. 1. Include Relevant " +"Information: Mention the affected feature or module for context. 1. Keep " +"it Short: Avoid lengthy titles for easy readability. 1. Use Proper " +"Capitalization and Punctuation: Follow grammar rules for clarity." msgstr "" -"1. 简明扼要: 以简明扼要的方式清楚地概述变化。1. 使用可操作的动词: 使用 \"添" -"加\"、\"更新 \"或 \"修复 \"等动词来表明目的。1. 包含相关信息: 提及受影响的功" -"能或模块以了解上下文。1. 简短:避免冗长的标题,以方便阅读。1. 使用正确的大小" -"写和标点符号: 遵守语法规则,以确保清晰。" +"1. 简明扼要: 以简明扼要的方式清楚地概述变化。1. 使用可操作的动词: 使用 \"添加\"、\"更新 \"或 \"修复 " +"\"等动词来表明目的。1. 包含相关信息: 提及受影响的功能或模块以了解上下文。1. 简短:避免冗长的标题,以方便阅读。1. " +"使用正确的大小写和标点符号: 遵守语法规则,以确保清晰。" -#: ../../source/contributor-tutorial-contribute-on-github.rst:321 +#: ../../source/contributor-tutorial-contribute-on-github.rst:324 msgid "" -"Let's start with a few examples for titles that should be avoided because " -"they do not provide meaningful information:" +"Let's start with a few examples for titles that should be avoided because" +" they do not provide meaningful information:" msgstr "让我们先举例说明几个应该避免使用的标题,因为它们不能提供有意义的信息:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:323 +#: ../../source/contributor-tutorial-contribute-on-github.rst:326 msgid "Implement Algorithm" msgstr "执行算法" -#: ../../source/contributor-tutorial-contribute-on-github.rst:324 +#: ../../source/contributor-tutorial-contribute-on-github.rst:327 msgid "Database" msgstr "数据库" -#: ../../source/contributor-tutorial-contribute-on-github.rst:325 +#: ../../source/contributor-tutorial-contribute-on-github.rst:328 msgid "Add my_new_file.py to codebase" msgstr "在代码库中添加 my_new_file.py" -#: ../../source/contributor-tutorial-contribute-on-github.rst:326 +#: ../../source/contributor-tutorial-contribute-on-github.rst:329 msgid "Improve code in module" msgstr "改进模块中的代码" -#: ../../source/contributor-tutorial-contribute-on-github.rst:327 +#: ../../source/contributor-tutorial-contribute-on-github.rst:330 msgid "Change SomeModule" msgstr "更改 SomeModule" -#: ../../source/contributor-tutorial-contribute-on-github.rst:329 +#: ../../source/contributor-tutorial-contribute-on-github.rst:332 msgid "" -"Here are a few positive examples which provide helpful information without " -"repeating how they do it, as that is already visible in the \"Files " -"changed\" section of the PR:" -msgstr "" -"这里有几个正面的例子,提供了有用的信息,但没有重复他们是如何做的,因为在 PR " -"的 \"已更改文件 \"部分已经可以看到:" +"Here are a few positive examples which provide helpful information " +"without repeating how they do it, as that is already visible in the " +"\"Files changed\" section of the PR:" +msgstr "这里有几个正面的例子,提供了有用的信息,但没有重复他们是如何做的,因为在 PR 的 \"已更改文件 \"部分已经可以看到:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:331 +#: ../../source/contributor-tutorial-contribute-on-github.rst:334 msgid "Update docs banner to mention Flower Summit 2023" msgstr "更新文件横幅,提及 2023 年 Flower 峰会" -#: ../../source/contributor-tutorial-contribute-on-github.rst:332 +#: ../../source/contributor-tutorial-contribute-on-github.rst:335 msgid "Remove unnecessary XGBoost dependency" msgstr "移除不必要的 XGBoost 依赖性" -#: ../../source/contributor-tutorial-contribute-on-github.rst:333 +#: ../../source/contributor-tutorial-contribute-on-github.rst:336 msgid "Remove redundant attributes in strategies subclassing FedAvg" msgstr "删除 FedAvg 子类化策略中的多余属性" -#: ../../source/contributor-tutorial-contribute-on-github.rst:334 -msgid "Add CI job to deploy the staging system when the `main` branch changes" +#: ../../source/contributor-tutorial-contribute-on-github.rst:337 +#, fuzzy +msgid "Add CI job to deploy the staging system when the ``main`` branch changes" msgstr "添加 CI 作业,以便在 \"主 \"分支发生变化时部署暂存系统" -#: ../../source/contributor-tutorial-contribute-on-github.rst:335 +#: ../../source/contributor-tutorial-contribute-on-github.rst:338 msgid "" -"Add new amazing library which will be used to improve the simulation engine" +"Add new amazing library which will be used to improve the simulation " +"engine" msgstr "添加新的惊人库,用于改进模拟引擎" -#: ../../source/contributor-tutorial-contribute-on-github.rst:339 +#: ../../source/contributor-tutorial-contribute-on-github.rst:342 #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:548 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:946 -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:747 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:727 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:713 #: ../../source/tutorial-series-what-is-federated-learning.ipynb:367 msgid "Next steps" msgstr "接下来的步骤" -#: ../../source/contributor-tutorial-contribute-on-github.rst:341 +#: ../../source/contributor-tutorial-contribute-on-github.rst:344 msgid "" -"Once you have made your first PR, and want to contribute more, be sure to " -"check out the following :" +"Once you have made your first PR, and want to contribute more, be sure to" +" check out the following :" msgstr "一旦您完成了第一份 PR,并希望做出更多贡献,请务必查看以下内容:" -#: ../../source/contributor-tutorial-contribute-on-github.rst:343 +#: ../../source/contributor-tutorial-contribute-on-github.rst:346 msgid "" -"`Good first contributions `_, where you should particularly look into " -"the :code:`baselines` contributions." +"`Good first contributions `_, where you should particularly look " +"into the :code:`baselines` contributions." msgstr "" "好的第一批贡献 `_,在这里你应该特别看看 :code:`baselines` 的贡献。" +#: ../../source/contributor-tutorial-contribute-on-github.rst:350 +#: ../../source/fed/0000-20200102-fed-template.md:60 +msgid "Appendix" +msgstr "附录" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:355 +#, fuzzy +msgid "Changelog entry" +msgstr "更新日志" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:357 +msgid "" +"When opening a new PR, inside its description, there should be a " +"``Changelog entry`` header." +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:359 +msgid "" +"Above this header you should see the following comment that explains how " +"to write your changelog entry:" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:361 +msgid "" +"Inside the following 'Changelog entry' section, you should put the " +"description of your changes that will be added to the changelog alongside" +" your PR title." +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:364 +msgid "" +"If the section is completely empty (without any token) or non-existant, " +"the changelog will just contain the title of the PR for the changelog " +"entry, without any description." +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:367 +msgid "" +"If the section contains some text other than tokens, it will use it to " +"add a description to the change." +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:369 +msgid "" +"If the section contains one of the following tokens it will ignore any " +"other text and put the PR under the corresponding section of the " +"changelog:" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:371 +msgid " is for classifying a PR as a general improvement." +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:373 +msgid " is to not add the PR to the changelog" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:375 +msgid " is to add a general baselines change to the PR" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:377 +msgid " is to add a general examples change to the PR" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:379 +msgid " is to add a general sdk change to the PR" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:381 +msgid " is to add a general simulations change to the PR" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:383 +msgid "Note that only one token should be used." +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:385 +msgid "" +"Its content must have a specific format. We will break down what each " +"possibility does:" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:387 +msgid "" +"If the ``### Changelog entry`` section contains nothing or doesn't exist," +" the following text will be added to the changelog::" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:391 +msgid "" +"If the ``### Changelog entry`` section contains a description (and no " +"token), the following text will be added to the changelog::" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:397 +msgid "" +"If the ``### Changelog entry`` section contains ````, nothing will " +"change in the changelog." +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:399 +msgid "" +"If the ``### Changelog entry`` section contains ````, the " +"following text will be added to the changelog::" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:403 +msgid "" +"If the ``### Changelog entry`` section contains ````, the " +"following text will be added to the changelog::" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:407 +msgid "" +"If the ``### Changelog entry`` section contains ````, the " +"following text will be added to the changelog::" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:411 +msgid "" +"If the ``### Changelog entry`` section contains ````, the following " +"text will be added to the changelog::" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:415 +msgid "" +"If the ``### Changelog entry`` section contains ````, the " +"following text will be added to the changelog::" +msgstr "" + +#: ../../source/contributor-tutorial-contribute-on-github.rst:419 +msgid "" +"Note that only one token must be provided, otherwise, only the first " +"action (in the order listed above), will be performed." +msgstr "" + #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:2 msgid "Get started as a contributor" msgstr "成为贡献者" @@ -1870,7 +2146,8 @@ msgid "Prerequisites" msgstr "先决条件" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:7 -msgid "`Python 3.7 `_ or above" +#, fuzzy +msgid "`Python 3.8 `_ or above" msgstr "Python 3.7 `_ 或更高版本" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:8 @@ -1882,144 +2159,183 @@ msgid "(Optional) `pyenv `_" msgstr "(可选) `pyenv `_" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:10 -msgid "" -"(Optional) `pyenv-virtualenv `_" -msgstr "" -"(可选) `pyenv-virtualenv `_" +msgid "(Optional) `pyenv-virtualenv `_" +msgstr "(可选) `pyenv-virtualenv `_" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:12 msgid "" "Flower uses :code:`pyproject.toml` to manage dependencies and configure " -"development tools (the ones which support it). Poetry is a build tool which " -"supports `PEP 517 `_." +"development tools (the ones which support it). Poetry is a build tool " +"which supports `PEP 517 `_." msgstr "" -"Flower 使用 :code:`pyproject.toml` 来管理依赖关系和配置开发工具(支持它的)。" -"Poetry 是一种支持 `PEP 517 `_ 的构" -"建工具。" +"Flower 使用 :code:`pyproject.toml` 来管理依赖关系和配置开发工具(支持它的)。Poetry 是一种支持 `PEP " +"517 `_ 的构建工具。" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:18 msgid "Developer Machine Setup" msgstr "开发者机器设置" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:20 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:21 +msgid "Preliminarities" +msgstr "" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:22 +msgid "Some system-wide dependencies are needed." +msgstr "" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:25 +msgid "For macOS" +msgstr "" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:27 +msgid "" +"Install `homebrew `_. Don't forget the post-" +"installation actions to add `brew` to your PATH." +msgstr "" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:28 +msgid "" +"Install `xz` (to install different Python versions) and `pandoc` to build" +" the docs::" +msgstr "" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:34 +msgid "For Ubuntu" +msgstr "" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:35 +msgid "" +"Ensure you system (Ubuntu 22.04+) is up-to-date, and you have all " +"necessary packages::" +msgstr "" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:44 +#, fuzzy +msgid "Create Flower Dev Environment" +msgstr "创建/删除虚拟环境" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:46 +#, fuzzy msgid "" -"First, clone the `Flower repository `_ from " +"1. Clone the `Flower repository `_ from " "GitHub::" +msgstr "首先,从 GitHub 克隆 \"Flower 存储库 `_\":" + +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:52 +msgid "" +"Let's create the Python environment for all-things Flower. If you wish to" +" use :code:`pyenv`, we provide two convenience scripts that you can use. " +"If you prefer using something else than :code:`pyenv`, create a new " +"environment, activate and skip to the last point where all packages are " +"installed." msgstr "" -"首先,从 GitHub 克隆 \"Flower 存储库 `_\":" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:26 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:54 +#, fuzzy msgid "" -"Second, create a virtual environment (and activate it). If you chose to use :" -"code:`pyenv` (with the :code:`pyenv-virtualenv` plugin) and already have it " -"installed , you can use the following convenience script (by default it will " -"use :code:`Python 3.8.17`, but you can change it by providing a specific :" -"code:``)::" +"If you don't have :code:`pyenv` installed, the following script that will" +" install it, set it up, and create the virtual environment (with " +":code:`Python 3.8.17` by default)::" msgstr "" -"其次,创建虚拟环境(并激活它)。如果您选择使用 :code:`pyenv`(使用 :code:" -"`pyenv-virtualenv`插件),并且已经安装了该插件,则可以使用下面的便捷脚本(默" -"认情况下使用 :code:`Python3.8.17`,但您可以通过提供特定的 :code:`<版本>`来更" -"改)::" +"如果没有安装 :code:`pyenv`,可以使用以下脚本安装 pyenv、设置并创建虚拟环境(默认使用 " +":code:`Python3.8.17)::" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:33 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:58 +#, fuzzy msgid "" -"If you don't have :code:`pyenv` installed, you can use the following script " -"that will install pyenv, set it up and create the virtual environment (with :" -"code:`Python 3.8.17` by default)::" +"If you already have :code:`pyenv` installed (along with the :code:`pyenv-" +"virtualenv` plugin), you can use the following convenience script (with " +":code:`Python 3.8.17` by default)::" msgstr "" -"如果没有安装 :code:`pyenv`,可以使用以下脚本安装 pyenv、设置并创建虚拟环境" -"(默认使用 :code:`Python3.8.17)::" +"如果没有安装 :code:`pyenv`,可以使用以下脚本安装 pyenv、设置并创建虚拟环境(默认使用 " +":code:`Python3.8.17)::" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:39 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:62 +#, fuzzy msgid "" -"Third, install the Flower package in development mode (think :code:`pip " +"3. Install the Flower package in development mode (think :code:`pip " "install -e`) along with all necessary dependencies::" -msgstr "" -"第三,在开发模式下安装 Flower 软件包(想想 :code:`pip install -e`)以及所有必" -"要的依赖项::" +msgstr "第三,在开发模式下安装 Flower 软件包(想想 :code:`pip install -e`)以及所有必要的依赖项::" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:46 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:69 msgid "Convenience Scripts" msgstr "便捷脚本" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:48 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:71 msgid "" "The Flower repository contains a number of convenience scripts to make " -"recurring development tasks easier and less error-prone. See the :code:`/" -"dev` subdirectory for a full list. The following scripts are amonst the most " -"important ones:" -msgstr "" -"Flower 软件仓库包含大量便捷脚本,可使重复性开发任务更轻松、更不易出错。完整列" -"表请参见 :code:`/dev` 子目录。以下是最重要的脚本:" +"recurring development tasks easier and less error-prone. See the " +":code:`/dev` subdirectory for a full list. The following scripts are " +"amonst the most important ones:" +msgstr "Flower 软件仓库包含大量便捷脚本,可使重复性开发任务更轻松、更不易出错。完整列表请参见 :code:`/dev` 子目录。以下是最重要的脚本:" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:54 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:77 msgid "Create/Delete Virtual Environment" msgstr "创建/删除虚拟环境" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:62 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:85 msgid "Compile ProtoBuf Definitions" msgstr "编译 ProtoBuf 定义" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:69 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:92 msgid "Auto-Format Code" msgstr "自动格式化代码" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:76 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:99 msgid "Run Linters and Tests" msgstr "运行分类器和测试" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:83 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:106 msgid "Run Github Actions (CI) locally" msgstr "在本地运行 Github 操作 (CI)" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:85 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:108 +#, fuzzy msgid "" -"Developers could run the full set of Github Actions workflows under their " -"local environment by using `Act _`. Please " -"refer to the installation instructions under the linked repository and run " -"the next command under Flower main cloned repository folder::" +"Developers could run the full set of Github Actions workflows under their" +" local environment by using `Act `_. " +"Please refer to the installation instructions under the linked repository" +" and run the next command under Flower main cloned repository folder::" msgstr "" -"开发人员可以使用 `Act _` 在本地环境下运行全套 " -"Github Actions 工作流程。请参考链接仓库下的安装说明,并在 Flower 主克隆仓库文" -"件夹下运行下一条命令::" +"开发人员可以使用 `Act _` 在本地环境下运行全套 Github Actions" +" 工作流程。请参考链接仓库下的安装说明,并在 Flower 主克隆仓库文件夹下运行下一条命令::" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:92 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:115 msgid "" "The Flower default workflow would run by setting up the required Docker " "machines underneath." msgstr "Flower 默认工作流程将通过在下面设置所需的 Docker 机器来运行。" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:97 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:120 msgid "Build Release" msgstr "版本发布" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:99 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:122 msgid "" -"Flower uses Poetry to build releases. The necessary command is wrapped in a " -"simple script::" +"Flower uses Poetry to build releases. The necessary command is wrapped in" +" a simple script::" msgstr "Flower 使用 Poetry 创建发布版本。必要的命令封装在一个简单的脚本中::" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:104 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:127 msgid "" -"The resulting :code:`.whl` and :code:`.tar.gz` releases will be stored in " -"the :code:`/dist` subdirectory." -msgstr "" -"生成的 :code:`.whl` 和 :code:`.tar.gz` 版本将存储在 :code:`/dist` 子目录中。" +"The resulting :code:`.whl` and :code:`.tar.gz` releases will be stored in" +" the :code:`/dist` subdirectory." +msgstr "生成的 :code:`.whl` 和 :code:`.tar.gz` 版本将存储在 :code:`/dist` 子目录中。" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:109 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:132 msgid "Build Documentation" msgstr "构建文档" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:111 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:134 msgid "" -"Flower's documentation uses `Sphinx `_. There's " -"no convenience script to re-build the documentation yet, but it's pretty " -"easy::" +"Flower's documentation uses `Sphinx `_. " +"There's no convenience script to re-build the documentation yet, but it's" +" pretty easy::" msgstr "" -"Flower 的文档使用 `Sphinx `_。目前还没有很方便的" -"脚本来重新构建文档,不过这很容易::" +"Flower 的文档使用 `Sphinx `_。目前还没有很方便的脚本来重新构建文档,不过这很容易::" -#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:117 +#: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:140 msgid "This will generate HTML documentation in ``doc/build/html``." msgstr "这将在 ``doc/build/html`` 中生成 HTML 文档。" @@ -2029,20 +2345,19 @@ msgstr "示例: PyTorch 中的 FedBN - 从集中式到联邦式" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:4 msgid "" -"This tutorial will show you how to use Flower to build a federated version " -"of an existing machine learning workload with `FedBN `_, a federated training strategy designed for non-iid data. We " -"are using PyTorch to train a Convolutional Neural Network(with Batch " -"Normalization layers) on the CIFAR-10 dataset. When applying FedBN, only few " -"changes needed compared to `Example: PyTorch - From Centralized To Federated " -"`_." -msgstr "" -"本教程将向您展示如何使用 Flower 为现有的机器学习框架构建一个联邦学习的版本," -"并使用 \"FedBN `_\"(一种针对非 iid 数据设" -"计的联邦训练策略)。我们使用 PyTorch 在 CIFAR-10 数据集上训练一个卷积神经网络" -"(带有Batch Normalization层)。在应用 FedBN 时,只需对 `示例: PyTorch - 从集" -"中式到联邦式 `_, a federated training strategy " +"designed for non-iid data. We are using PyTorch to train a Convolutional " +"Neural Network(with Batch Normalization layers) on the CIFAR-10 dataset. " +"When applying FedBN, only few changes needed compared to `Example: " +"PyTorch - From Centralized To Federated `_." +msgstr "" +"本教程将向您展示如何使用 Flower 为现有的机器学习框架构建一个联邦学习的版本,并使用 \"FedBN `_\"(一种针对非 iid 数据设计的联邦训练策略)。我们使用 PyTorch 在 CIFAR-10 " +"数据集上训练一个卷积神经网络(带有Batch Normalization层)。在应用 FedBN 时,只需对 `示例: PyTorch - " +"从集中式到联邦式 `_ 做少量改动。" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:9 @@ -2054,12 +2369,12 @@ msgstr "集中式训练" msgid "" "All files are revised based on `Example: PyTorch - From Centralized To " "Federated `_. The only thing to do is modifying the file called :code:" -"`cifar.py`, revised part is shown below:" +"federated.html>`_. The only thing to do is modifying the file called " +":code:`cifar.py`, revised part is shown below:" msgstr "" -"所有文件均根据 `示例: PyTorch -从集中式到联邦式 `_。唯一要做的就是修改名" -"为 :code:`cifar.py` 的文件,修改部分如下所示:" +"所有文件均根据 `示例: PyTorch -从集中式到联邦式 `_。唯一要做的就是修改名为 :code:`cifar.py` " +"的文件,修改部分如下所示:" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:13 msgid "" @@ -2074,14 +2389,13 @@ msgstr "现在,您可以运行您的机器学习工作了:" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:47 msgid "" -"So far this should all look fairly familiar if you've used PyTorch before. " -"Let's take the next step and use what we've built to create a federated " -"learning system within FedBN, the sytstem consists of one server and two " -"clients." +"So far this should all look fairly familiar if you've used PyTorch " +"before. Let's take the next step and use what we've built to create a " +"federated learning system within FedBN, the sytstem consists of one " +"server and two clients." msgstr "" -"到目前为止,如果您以前使用过 PyTorch,这一切看起来应该相当熟悉。让我们进行下" -"一步,使用我们所构建的内容在 FedBN 中创建一个联邦学习系统,该系统由一个服务器" -"和两个客户端组成。" +"到目前为止,如果您以前使用过 PyTorch,这一切看起来应该相当熟悉。让我们进行下一步,使用我们所构建的内容在 FedBN " +"中创建一个联邦学习系统,该系统由一个服务器和两个客户端组成。" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:51 #: ../../source/example-pytorch-from-centralized-to-federated.rst:167 @@ -2090,39 +2404,36 @@ msgstr "联邦培训" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:53 msgid "" -"If you have read `Example: PyTorch - From Centralized To Federated `_, the " -"following parts are easy to follow, onyl :code:`get_parameters` and :code:" -"`set_parameters` function in :code:`client.py` needed to revise. If not, " -"please read the `Example: PyTorch - From Centralized To Federated `_. " -"first." -msgstr "" -"如果你读过 `示例: PyTorch - 从集中式到联邦式 `_,下面的部分就很容易理" -"解了,只需要修改 :code:`get_parameters` 和 :code:`set_parameters` 中的 :code:" -"`client.py` 函数。如果没有,请阅读 `示例: PyTorch - 从集中式到联邦式 " -"`_。" +"If you have read `Example: PyTorch - From Centralized To Federated " +"`_, the following parts are easy to follow, onyl " +":code:`get_parameters` and :code:`set_parameters` function in " +":code:`client.py` needed to revise. If not, please read the `Example: " +"PyTorch - From Centralized To Federated `_. first." +msgstr "" +"如果你读过 `示例: PyTorch - 从集中式到联邦式 `_,下面的部分就很容易理解了,只需要修改 " +":code:`get_parameters` 和 :code:`set_parameters` 中的 :code:`client.py` " +"函数。如果没有,请阅读 `示例: PyTorch - 从集中式到联邦式 `_。" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:56 msgid "" -"Our example consists of one *server* and two *clients*. In FedBN, :code:" -"`server.py` keeps unchanged, we can start the server directly." -msgstr "" -"我们的示例包括一个*服务器*和两个*客户端*。在 FedBN 中,:code:`server.py` 保持" -"不变,我们可以直接启动服务器。" +"Our example consists of one *server* and two *clients*. In FedBN, " +":code:`server.py` keeps unchanged, we can start the server directly." +msgstr "我们的示例包括一个*服务器*和两个*客户端*。在 FedBN 中,:code:`server.py` 保持不变,我们可以直接启动服务器。" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:62 msgid "" -"Finally, we will revise our *client* logic by changing :code:" -"`get_parameters` and :code:`set_parameters` in :code:`client.py`, we will " -"exclude batch normalization parameters from model parameter list when " -"sending to or receiving from the server." +"Finally, we will revise our *client* logic by changing " +":code:`get_parameters` and :code:`set_parameters` in :code:`client.py`, " +"we will exclude batch normalization parameters from model parameter list " +"when sending to or receiving from the server." msgstr "" -"最后,我们将修改 *client* 的逻辑,修改 :code:`client.py` 中的 :code:" -"`get_parameters` 和 :code:`set_parameters`,在向服务器发送或从服务器接收时," -"我们将从模型参数列表中排除batch normalization层的参数。" +"最后,我们将修改 *client* 的逻辑,修改 :code:`client.py` 中的 :code:`get_parameters` 和 " +":code:`set_parameters`,在向服务器发送或从服务器接收时,我们将从模型参数列表中排除batch " +"normalization层的参数。" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:85 msgid "Now, you can now open two additional terminal windows and run" @@ -2130,12 +2441,10 @@ msgstr "现在,您可以打开另外两个终端窗口并运行程序" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:91 msgid "" -"in each window (make sure that the server is still running before you do so) " -"and see your (previously centralized) PyTorch project run federated learning " -"with FedBN strategy across two clients. Congratulations!" -msgstr "" -"确保服务器仍在运行后,然后您就能看到您的 PyTorch 项目(之前是集中式的)通过 " -"FedBN 策略在两个客户端上运行联合学习。祝贺!" +"in each window (make sure that the server is still running before you do " +"so) and see your (previously centralized) PyTorch project run federated " +"learning with FedBN strategy across two clients. Congratulations!" +msgstr "确保服务器仍在运行后,然后您就能看到您的 PyTorch 项目(之前是集中式的)通过 FedBN 策略在两个客户端上运行联合学习。祝贺!" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:94 #: ../../source/example-jax-from-centralized-to-federated.rst:277 @@ -2147,17 +2456,18 @@ msgstr "下一步工作" #: ../../source/example-fedbn-pytorch-from-centralized-to-federated.rst:96 msgid "" -"The full source code for this example can be found `here `_. Our " -"example is of course somewhat over-simplified because both clients load the " -"exact same dataset, which isn't realistic. You're now prepared to explore " -"this topic further. How about using different subsets of CIFAR-10 on each " -"client? How about adding more clients?" +"The full source code for this example can be found `here " +"`_. Our example is of course somewhat over-" +"simplified because both clients load the exact same dataset, which isn't " +"realistic. You're now prepared to explore this topic further. How about " +"using different subsets of CIFAR-10 on each client? How about adding more" +" clients?" msgstr "" -"本示例的完整源代码可在 `_ 找到。当然,我们的示例有些过于简单," -"因为两个客户端都加载了完全相同的数据集,这并不真实。让我们准备好进一步探讨这" -"一主题。如在每个客户端使用不同的 CIFAR-10 子集,或者增加客户端的数量。" +"本示例的完整源代码可在 `_ " +"找到。当然,我们的示例有些过于简单,因为两个客户端都加载了完全相同的数据集,这并不真实。让我们准备好进一步探讨这一主题。如在每个客户端使用不同的 " +"CIFAR-10 子集,或者增加客户端的数量。" #: ../../source/example-jax-from-centralized-to-federated.rst:2 msgid "Example: JAX - Run JAX Federated" @@ -2166,32 +2476,32 @@ msgstr "示例: JAX - 运行联邦式 JAX" #: ../../source/example-jax-from-centralized-to-federated.rst:4 #: ../../source/tutorial-quickstart-jax.rst:10 msgid "" -"This tutorial will show you how to use Flower to build a federated version " -"of an existing JAX workload. We are using JAX to train a linear regression " -"model on a scikit-learn dataset. We will structure the example similar to " -"our `PyTorch - From Centralized To Federated `_ walkthrough. " -"First, we build a centralized training approach based on the `Linear " -"Regression with JAX `_ tutorial`. Then, we build upon the centralized " -"training code to run the training in a federated fashion." -msgstr "" -"本教程将向您展示如何使用 Flower 构建现有 JAX 的联邦学习版本。我们将使用 JAX " -"在 scikit-learn 数据集上训练线性回归模型。我们将采用与 `PyTorch - 从集中式到" -"联邦式 `_ 教程中类似的示例结构。首先,我们根据 `JAX 的线性" -"回归 `_ 教程构建集中式训练方法。然后,我们在集中式训练代码的基础上以联邦方式" -"运行训练。" +"This tutorial will show you how to use Flower to build a federated " +"version of an existing JAX workload. We are using JAX to train a linear " +"regression model on a scikit-learn dataset. We will structure the example" +" similar to our `PyTorch - From Centralized To Federated " +"`_ walkthrough. First, we build a centralized " +"training approach based on the `Linear Regression with JAX " +"`_" +" tutorial`. Then, we build upon the centralized training code to run the " +"training in a federated fashion." +msgstr "" +"本教程将向您展示如何使用 Flower 构建现有 JAX 的联邦学习版本。我们将使用 JAX 在 scikit-learn " +"数据集上训练线性回归模型。我们将采用与 `PyTorch - 从集中式到联邦式 " +"`_ 教程中类似的示例结构。首先,我们根据 `JAX 的线性回归 " +"`_" +" 教程构建集中式训练方法。然后,我们在集中式训练代码的基础上以联邦方式运行训练。" #: ../../source/example-jax-from-centralized-to-federated.rst:10 #: ../../source/tutorial-quickstart-jax.rst:16 msgid "" -"Before we start building our JAX example, we need install the packages :code:" -"`jax`, :code:`jaxlib`, :code:`scikit-learn`, and :code:`flwr`:" +"Before we start building our JAX example, we need install the packages " +":code:`jax`, :code:`jaxlib`, :code:`scikit-learn`, and :code:`flwr`:" msgstr "" -"在开始构建 JAX 示例之前,我们需要安装软件包 :code:`jax`、:code:`jaxlib`、:" -"code:`scikit-learn` 和 :code:`flwr`:" +"在开始构建 JAX 示例之前,我们需要安装软件包 :code:`jax`、:code:`jaxlib`、:code:`scikit-learn` " +"和 :code:`flwr`:" #: ../../source/example-jax-from-centralized-to-federated.rst:18 #: ../../source/tutorial-quickstart-jax.rst:24 @@ -2201,83 +2511,77 @@ msgstr "使用 JAX 进行线性回归" #: ../../source/example-jax-from-centralized-to-federated.rst:20 #: ../../source/tutorial-quickstart-jax.rst:26 msgid "" -"We begin with a brief description of the centralized training code based on " -"a :code:`Linear Regression` model. If you want a more in-depth explanation " -"of what's going on then have a look at the official `JAX documentation " -"`_." +"We begin with a brief description of the centralized training code based " +"on a :code:`Linear Regression` model. If you want a more in-depth " +"explanation of what's going on then have a look at the official `JAX " +"documentation `_." msgstr "" -"首先,我们将简要介绍基于 :code:`Linear Regression` 模型的集中式训练代码。如果" -"您想获得更深入的解释,请参阅官方的 `JAX 文档 `_。" +"首先,我们将简要介绍基于 :code:`Linear Regression` 模型的集中式训练代码。如果您想获得更深入的解释,请参阅官方的 " +"`JAX 文档 `_。" #: ../../source/example-jax-from-centralized-to-federated.rst:23 #: ../../source/tutorial-quickstart-jax.rst:29 msgid "" "Let's create a new file called :code:`jax_training.py` with all the " "components required for a traditional (centralized) linear regression " -"training. First, the JAX packages :code:`jax` and :code:`jaxlib` need to be " -"imported. In addition, we need to import :code:`sklearn` since we use :code:" -"`make_regression` for the dataset and :code:`train_test_split` to split the " -"dataset into a training and test set. You can see that we do not yet import " -"the :code:`flwr` package for federated learning. This will be done later." -msgstr "" -"让我们创建一个名为 :code:`jax_training.py` 的新文件,其中包含传统(集中式)线" -"性回归训练所需的所有组件。首先,需要导入 JAX 包 :code:`jax` 和 :code:" -"`jaxlib`。此外,我们还需要导入 :code:`sklearn`,因为我们使用 :code:" -"`make_regression` 创建数据集,并使用 :code:`train_test_split` 将数据集拆分成" -"训练集和测试集。您可以看到,我们还没有导入用于联邦学习的 :code:`flwr` 软件" -"包,这将在稍后完成。" +"training. First, the JAX packages :code:`jax` and :code:`jaxlib` need to " +"be imported. In addition, we need to import :code:`sklearn` since we use " +":code:`make_regression` for the dataset and :code:`train_test_split` to " +"split the dataset into a training and test set. You can see that we do " +"not yet import the :code:`flwr` package for federated learning. This will" +" be done later." +msgstr "" +"让我们创建一个名为 :code:`jax_training.py` 的新文件,其中包含传统(集中式)线性回归训练所需的所有组件。首先,需要导入 " +"JAX 包 :code:`jax` 和 :code:`jaxlib`。此外,我们还需要导入 :code:`sklearn`,因为我们使用 " +":code:`make_regression` 创建数据集,并使用 :code:`train_test_split` " +"将数据集拆分成训练集和测试集。您可以看到,我们还没有导入用于联邦学习的 :code:`flwr` 软件包,这将在稍后完成。" #: ../../source/example-jax-from-centralized-to-federated.rst:37 #: ../../source/tutorial-quickstart-jax.rst:43 msgid "" -"The :code:`load_data()` function loads the mentioned training and test sets." +"The :code:`load_data()` function loads the mentioned training and test " +"sets." msgstr ":code:`load_data()` 函数会加载上述训练集和测试集。" #: ../../source/example-jax-from-centralized-to-federated.rst:47 #: ../../source/tutorial-quickstart-jax.rst:53 msgid "" -"The model architecture (a very simple :code:`Linear Regression` model) is " -"defined in :code:`load_model()`." -msgstr "" -"模型结构(一个非常简单的 :code:`Linear Regression` 线性回归模型)在 :code:" -"`load_model()` 中定义。" +"The model architecture (a very simple :code:`Linear Regression` model) is" +" defined in :code:`load_model()`." +msgstr "模型结构(一个非常简单的 :code:`Linear Regression` 线性回归模型)在 :code:`load_model()` 中定义。" #: ../../source/example-jax-from-centralized-to-federated.rst:59 #: ../../source/tutorial-quickstart-jax.rst:65 msgid "" -"We now need to define the training (function :code:`train()`), which loops " -"over the training set and measures the loss (function :code:`loss_fn()`) for " -"each batch of training examples. The loss function is separate since JAX " -"takes derivatives with a :code:`grad()` function (defined in the :code:" -"`main()` function and called in :code:`train()`)." +"We now need to define the training (function :code:`train()`), which " +"loops over the training set and measures the loss (function " +":code:`loss_fn()`) for each batch of training examples. The loss function" +" is separate since JAX takes derivatives with a :code:`grad()` function " +"(defined in the :code:`main()` function and called in :code:`train()`)." msgstr "" -"现在,我们需要定义训练函数( :code:`train()`)。它循环遍历训练集,并计算每批" -"训练数据的损失值(函数 :code:`loss_fn()`)。由于 JAX 使用 :code:`grad()` 函数" -"提取导数(在 :code:`main()` 函数中定义,并在 :code:`train()` 中调用),因此损" -"失函数是独立的。" +"现在,我们需要定义训练函数( :code:`train()`)。它循环遍历训练集,并计算每批训练数据的损失值(函数 " +":code:`loss_fn()`)。由于 JAX 使用 :code:`grad()` 函数提取导数(在 :code:`main()` " +"函数中定义,并在 :code:`train()` 中调用),因此损失函数是独立的。" #: ../../source/example-jax-from-centralized-to-federated.rst:77 #: ../../source/tutorial-quickstart-jax.rst:83 msgid "" -"The evaluation of the model is defined in the function :code:`evaluation()`. " -"The function takes all test examples and measures the loss of the linear " -"regression model." -msgstr "" -"模型的评估在函数 :code:`evaluation()` 中定义。该函数获取所有测试数据,并计算" -"线性回归模型的损失值。" +"The evaluation of the model is defined in the function " +":code:`evaluation()`. The function takes all test examples and measures " +"the loss of the linear regression model." +msgstr "模型的评估在函数 :code:`evaluation()` 中定义。该函数获取所有测试数据,并计算线性回归模型的损失值。" #: ../../source/example-jax-from-centralized-to-federated.rst:88 #: ../../source/tutorial-quickstart-jax.rst:94 msgid "" "Having defined the data loading, model architecture, training, and " -"evaluation we can put everything together and train our model using JAX. As " -"already mentioned, the :code:`jax.grad()` function is defined in :code:" -"`main()` and passed to :code:`train()`." +"evaluation we can put everything together and train our model using JAX. " +"As already mentioned, the :code:`jax.grad()` function is defined in " +":code:`main()` and passed to :code:`train()`." msgstr "" -"在定义了数据加载、模型架构、训练和评估之后,我们就可以把这些放在一起,使用 " -"JAX 训练我们的模型了。如前所述,:code:`jax.grad()` 函数在 :code:`main()` 中定" -"义,并传递给 :code:`train()`。" +"在定义了数据加载、模型架构、训练和评估之后,我们就可以把这些放在一起,使用 JAX " +"训练我们的模型了。如前所述,:code:`jax.grad()` 函数在 :code:`main()` 中定义,并传递给 " +":code:`train()`。" #: ../../source/example-jax-from-centralized-to-federated.rst:105 #: ../../source/tutorial-quickstart-jax.rst:111 @@ -2287,12 +2591,10 @@ msgstr "现在您可以运行(集中式)JAX 线性回归工作了:" #: ../../source/example-jax-from-centralized-to-federated.rst:111 #: ../../source/tutorial-quickstart-jax.rst:117 msgid "" -"So far this should all look fairly familiar if you've used JAX before. Let's " -"take the next step and use what we've built to create a simple federated " -"learning system consisting of one server and two clients." -msgstr "" -"到目前为止,如果你以前使用过 JAX,就会对这一切感到很熟悉。下一步,让我们利用" -"已构建的代码创建一个简单的联邦学习系统(一个服务器和两个客户端)。" +"So far this should all look fairly familiar if you've used JAX before. " +"Let's take the next step and use what we've built to create a simple " +"federated learning system consisting of one server and two clients." +msgstr "到目前为止,如果你以前使用过 JAX,就会对这一切感到很熟悉。下一步,让我们利用已构建的代码创建一个简单的联邦学习系统(一个服务器和两个客户端)。" #: ../../source/example-jax-from-centralized-to-federated.rst:115 #: ../../source/tutorial-quickstart-jax.rst:121 @@ -2302,34 +2604,30 @@ msgstr "JAX 结合 Flower" #: ../../source/example-jax-from-centralized-to-federated.rst:117 #: ../../source/tutorial-quickstart-jax.rst:123 msgid "" -"The concept of federating an existing workload is always the same and easy " -"to understand. We have to start a *server* and then use the code in :code:" -"`jax_training.py` for the *clients* that are connected to the *server*. The " -"*server* sends model parameters to the clients. The *clients* run the " -"training and update the parameters. The updated parameters are sent back to " -"the *server*, which averages all received parameter updates. This describes " -"one round of the federated learning process, and we repeat this for multiple " -"rounds." -msgstr "" -"把现有工作联邦化的概念始终是相同的,也很容易理解。我们要启动一个*服务器*,然" -"后对连接到*服务器*的*客户端*运行 :code:`jax_training.py`中的代码。*服务器*向" -"客户端发送模型参数,*客户端*运行训练并更新参数。更新后的参数被发回*服务器*," -"然后服务器对所有收到的参数进行平均聚合。以上的描述构成了一轮联邦学习,我们将" -"重复进行多轮学习。" +"The concept of federating an existing workload is always the same and " +"easy to understand. We have to start a *server* and then use the code in " +":code:`jax_training.py` for the *clients* that are connected to the " +"*server*. The *server* sends model parameters to the clients. The " +"*clients* run the training and update the parameters. The updated " +"parameters are sent back to the *server*, which averages all received " +"parameter updates. This describes one round of the federated learning " +"process, and we repeat this for multiple rounds." +msgstr "" +"把现有工作联邦化的概念始终是相同的,也很容易理解。我们要启动一个*服务器*,然后对连接到*服务器*的*客户端*运行 " +":code:`jax_training.py`中的代码。*服务器*向客户端发送模型参数,*客户端*运行训练并更新参数。更新后的参数被发回*服务器*,然后服务器对所有收到的参数进行平均聚合。以上的描述构成了一轮联邦学习,我们将重复进行多轮学习。" #: ../../source/example-jax-from-centralized-to-federated.rst:123 #: ../../source/example-mxnet-walk-through.rst:204 #: ../../source/example-pytorch-from-centralized-to-federated.rst:181 #: ../../source/tutorial-quickstart-jax.rst:129 msgid "" -"Our example consists of one *server* and two *clients*. Let's set up :code:" -"`server.py` first. The *server* needs to import the Flower package :code:" -"`flwr`. Next, we use the :code:`start_server` function to start a server and " -"tell it to perform three rounds of federated learning." +"Our example consists of one *server* and two *clients*. Let's set up " +":code:`server.py` first. The *server* needs to import the Flower package " +":code:`flwr`. Next, we use the :code:`start_server` function to start a " +"server and tell it to perform three rounds of federated learning." msgstr "" -"我们的示例包括一个*服务器*和两个*客户端*。让我们先设置 :code:`server.py`。*服" -"务器*需要导入 Flower 软件包 :code:`flwr`。接下来,我们使用 :code:" -"`start_server` 函数启动服务器,并让它执行三轮联邦学习。" +"我们的示例包括一个*服务器*和两个*客户端*。让我们先设置 :code:`server.py`。*服务器*需要导入 Flower 软件包 " +":code:`flwr`。接下来,我们使用 :code:`start_server` 函数启动服务器,并让它执行三轮联邦学习。" #: ../../source/example-jax-from-centralized-to-federated.rst:133 #: ../../source/example-mxnet-walk-through.rst:214 @@ -2341,34 +2639,35 @@ msgstr "我们已经可以启动*服务器*了:" #: ../../source/example-jax-from-centralized-to-federated.rst:139 #: ../../source/tutorial-quickstart-jax.rst:145 msgid "" -"Finally, we will define our *client* logic in :code:`client.py` and build " -"upon the previously defined JAX training in :code:`jax_training.py`. Our " -"*client* needs to import :code:`flwr`, but also :code:`jax` and :code:" -"`jaxlib` to update the parameters on our JAX model:" +"Finally, we will define our *client* logic in :code:`client.py` and build" +" upon the previously defined JAX training in :code:`jax_training.py`. Our" +" *client* needs to import :code:`flwr`, but also :code:`jax` and " +":code:`jaxlib` to update the parameters on our JAX model:" msgstr "" -"最后,我们将在 :code:`client.py` 中定义我们的 *client* 逻辑,并以之前在 :" -"code:`jax_training.py` 中定义的 JAX 训练为基础。我们的 *client* 需要导入 :" -"code:`flwr`,还需要导入 :code:`jax` 和 :code:`jaxlib` 以更新 JAX 模型的参数:" +"最后,我们将在 :code:`client.py` 中定义我们的 *client* 逻辑,并以之前在 " +":code:`jax_training.py` 中定义的 JAX 训练为基础。我们的 *client* 需要导入 " +":code:`flwr`,还需要导入 :code:`jax` 和 :code:`jaxlib` 以更新 JAX 模型的参数:" #: ../../source/example-jax-from-centralized-to-federated.rst:154 #: ../../source/tutorial-quickstart-jax.rst:160 msgid "" -"Implementing a Flower *client* basically means implementing a subclass of " -"either :code:`flwr.client.Client` or :code:`flwr.client.NumPyClient`. Our " -"implementation will be based on :code:`flwr.client.NumPyClient` and we'll " -"call it :code:`FlowerClient`. :code:`NumPyClient` is slightly easier to " -"implement than :code:`Client` if you use a framework with good NumPy " -"interoperability (like JAX) because it avoids some of the boilerplate that " -"would otherwise be necessary. :code:`FlowerClient` needs to implement four " -"methods, two methods for getting/setting model parameters, one method for " -"training the model, and one method for testing the model:" -msgstr "" -"实现一个 Flower *client*基本上意味着去实现一个 :code:`flwr.client.Client` " -"或 :code:`flwr.client.NumPyClient` 的子类。我们的代码实现将基于 :code:`flwr." -"client.NumPyClient`,并将其命名为 :code:`FlowerClient`。如果使用具有良好 " -"NumPy 互操作性的框架(如 JAX),:code:`NumPyClient` 比 :code:`Client`更容易实" -"现,因为它避免了一些不必要的操作。:code:`FlowerClient` 需要实现四个方法,两个" -"用于获取/设置模型参数,一个用于训练模型,一个用于测试模型:" +"Implementing a Flower *client* basically means implementing a subclass of" +" either :code:`flwr.client.Client` or :code:`flwr.client.NumPyClient`. " +"Our implementation will be based on :code:`flwr.client.NumPyClient` and " +"we'll call it :code:`FlowerClient`. :code:`NumPyClient` is slightly " +"easier to implement than :code:`Client` if you use a framework with good " +"NumPy interoperability (like JAX) because it avoids some of the " +"boilerplate that would otherwise be necessary. :code:`FlowerClient` needs" +" to implement four methods, two methods for getting/setting model " +"parameters, one method for training the model, and one method for testing" +" the model:" +msgstr "" +"实现一个 Flower *client*基本上意味着去实现一个 :code:`flwr.client.Client` 或 " +":code:`flwr.client.NumPyClient` 的子类。我们的代码实现将基于 " +":code:`flwr.client.NumPyClient`,并将其命名为 :code:`FlowerClient`。如果使用具有良好 " +"NumPy 互操作性的框架(如 JAX),:code:`NumPyClient` 比 " +":code:`Client`更容易实现,因为它避免了一些不必要的操作。:code:`FlowerClient` " +"需要实现四个方法,两个用于获取/设置模型参数,一个用于训练模型,一个用于测试模型:" #: ../../source/example-jax-from-centralized-to-federated.rst:161 #: ../../source/example-mxnet-walk-through.rst:242 @@ -2381,7 +2680,8 @@ msgstr ":code:`set_parameters (可选)`" #: ../../source/example-pytorch-from-centralized-to-federated.rst:219 #: ../../source/tutorial-quickstart-jax.rst:166 msgid "" -"set the model parameters on the local model that are received from the server" +"set the model parameters on the local model that are received from the " +"server" msgstr "在本地模型上设置从服务器接收的模型参数" #: ../../source/example-jax-from-centralized-to-federated.rst:161 @@ -2394,17 +2694,15 @@ msgstr "将参数转换为 NumPy :code:`ndarray`格式" #: ../../source/example-pytorch-from-centralized-to-federated.rst:220 #: ../../source/tutorial-quickstart-jax.rst:168 msgid "" -"loop over the list of model parameters received as NumPy :code:`ndarray`'s " -"(think list of neural network layers)" -msgstr "" -"循环遍历以 NumPy :code:`ndarray` 形式接收的模型参数列表(可以看作神经网络的列" -"表)" +"loop over the list of model parameters received as NumPy " +":code:`ndarray`'s (think list of neural network layers)" +msgstr "循环遍历以 NumPy :code:`ndarray` 形式接收的模型参数列表(可以看作神经网络的列表)" #: ../../source/example-jax-from-centralized-to-federated.rst:163 #: ../../source/example-mxnet-walk-through.rst:244 #: ../../source/example-pytorch-from-centralized-to-federated.rst:221 #: ../../source/tutorial-quickstart-jax.rst:169 -#: ../../source/tutorial-quickstart-mxnet.rst:169 +#: ../../source/tutorial-quickstart-mxnet.rst:171 #: ../../source/tutorial-quickstart-pytorch.rst:155 #: ../../source/tutorial-quickstart-scikitlearn.rst:108 msgid ":code:`get_parameters`" @@ -2415,17 +2713,17 @@ msgstr ":code:`get_parameters`" #: ../../source/example-pytorch-from-centralized-to-federated.rst:222 #: ../../source/tutorial-quickstart-jax.rst:170 msgid "" -"get the model parameters and return them as a list of NumPy :code:" -"`ndarray`'s (which is what :code:`flwr.client.NumPyClient` expects)" +"get the model parameters and return them as a list of NumPy " +":code:`ndarray`'s (which is what :code:`flwr.client.NumPyClient` expects)" msgstr "" -"获取模型参数,并以 NumPy :code:`ndarray`的列表形式返回(这正是 :code:`flwr." -"client.NumPyClient`所匹配的格式)" +"获取模型参数,并以 NumPy :code:`ndarray`的列表形式返回(这正是 " +":code:`flwr.client.NumPyClient`所匹配的格式)" #: ../../source/example-jax-from-centralized-to-federated.rst:167 #: ../../source/example-mxnet-walk-through.rst:248 #: ../../source/example-pytorch-from-centralized-to-federated.rst:225 #: ../../source/tutorial-quickstart-jax.rst:173 -#: ../../source/tutorial-quickstart-mxnet.rst:175 +#: ../../source/tutorial-quickstart-mxnet.rst:177 #: ../../source/tutorial-quickstart-pytorch.rst:161 #: ../../source/tutorial-quickstart-scikitlearn.rst:115 msgid ":code:`fit`" @@ -2440,8 +2738,8 @@ msgstr ":code:`fit`" #: ../../source/tutorial-quickstart-jax.rst:172 #: ../../source/tutorial-quickstart-jax.rst:176 msgid "" -"update the parameters of the local model with the parameters received from " -"the server" +"update the parameters of the local model with the parameters received " +"from the server" msgstr "用从服务器接收到的参数更新本地模型的参数" #: ../../source/example-jax-from-centralized-to-federated.rst:167 @@ -2460,7 +2758,7 @@ msgstr "获取更新后的本地模型参数并返回服务器" #: ../../source/example-mxnet-walk-through.rst:253 #: ../../source/example-pytorch-from-centralized-to-federated.rst:230 #: ../../source/tutorial-quickstart-jax.rst:178 -#: ../../source/tutorial-quickstart-mxnet.rst:178 +#: ../../source/tutorial-quickstart-mxnet.rst:180 #: ../../source/tutorial-quickstart-pytorch.rst:164 #: ../../source/tutorial-quickstart-scikitlearn.rst:118 msgid ":code:`evaluate`" @@ -2481,28 +2779,28 @@ msgstr "向服务器返回本地损失值" #: ../../source/example-jax-from-centralized-to-federated.rst:174 #: ../../source/tutorial-quickstart-jax.rst:180 msgid "" -"The challenging part is to transform the JAX model parameters from :code:" -"`DeviceArray` to :code:`NumPy ndarray` to make them compatible with " -"`NumPyClient`." +"The challenging part is to transform the JAX model parameters from " +":code:`DeviceArray` to :code:`NumPy ndarray` to make them compatible with" +" `NumPyClient`." msgstr "" -"具有挑战性的部分是将 JAX 模型参数从 :code:`DeviceArray` 转换为 :code:`NumPy " -"ndarray`,使其与 `NumPyClient` 兼容。" +"具有挑战性的部分是将 JAX 模型参数从 :code:`DeviceArray` 转换为 :code:`NumPy ndarray`,使其与 " +"`NumPyClient` 兼容。" #: ../../source/example-jax-from-centralized-to-federated.rst:176 #: ../../source/tutorial-quickstart-jax.rst:182 msgid "" -"The two :code:`NumPyClient` methods :code:`fit` and :code:`evaluate` make " -"use of the functions :code:`train()` and :code:`evaluate()` previously " +"The two :code:`NumPyClient` methods :code:`fit` and :code:`evaluate` make" +" use of the functions :code:`train()` and :code:`evaluate()` previously " "defined in :code:`jax_training.py`. So what we really do here is we tell " -"Flower through our :code:`NumPyClient` subclass which of our already defined " -"functions to call for training and evaluation. We included type annotations " -"to give you a better understanding of the data types that get passed around." +"Flower through our :code:`NumPyClient` subclass which of our already " +"defined functions to call for training and evaluation. We included type " +"annotations to give you a better understanding of the data types that get" +" passed around." msgstr "" -"这两个 :code:`NumPyClient` 方法 :code:`fit` 和 :code:`evaluate` 使用了之前" -"在 :code:`jax_training.py` 中定义的函数 :code:`train()` 和 :code:" -"`evaluate()`。因此,我们在这里要做的就是通过 :code:`NumPyClient` 子类告知 " -"Flower 在训练和评估时要调用哪些已定义的函数。我们加入了类型注解,以便让您更好" -"地理解传递的数据类型。" +"这两个 :code:`NumPyClient` 方法 :code:`fit` 和 :code:`evaluate` 使用了之前在 " +":code:`jax_training.py` 中定义的函数 :code:`train()` 和 " +":code:`evaluate()`。因此,我们在这里要做的就是通过 :code:`NumPyClient` 子类告知 Flower " +"在训练和评估时要调用哪些已定义的函数。我们加入了类型注解,以便让您更好地理解传递的数据类型。" #: ../../source/example-jax-from-centralized-to-federated.rst:245 #: ../../source/tutorial-quickstart-jax.rst:251 @@ -2519,34 +2817,30 @@ msgstr "就是这样,现在你可以打开另外两个终端窗口,然后运 #: ../../source/example-jax-from-centralized-to-federated.rst:274 #: ../../source/tutorial-quickstart-jax.rst:280 msgid "" -"in each window (make sure that the server is still running before you do so) " -"and see your JAX project run federated learning across two clients. " +"in each window (make sure that the server is still running before you do " +"so) and see your JAX project run federated learning across two clients. " "Congratulations!" -msgstr "" -"确保服务器仍在运行,然后在每个客户端窗口就能看到你的 JAX 项目在两个客户端上运" -"行联邦学习了。祝贺!" +msgstr "确保服务器仍在运行,然后在每个客户端窗口就能看到你的 JAX 项目在两个客户端上运行联邦学习了。祝贺!" #: ../../source/example-jax-from-centralized-to-federated.rst:279 #: ../../source/tutorial-quickstart-jax.rst:285 msgid "" "The source code of this example was improved over time and can be found " -"here: `Quickstart JAX `_. Our example is somewhat over-simplified because both " +"here: `Quickstart JAX `_. Our example is somewhat over-simplified because both " "clients load the same dataset." msgstr "" -"此示例的源代码经过长期改进,可在此处找到: `Quickstart JAX `_。我们的示例有些过于简" -"单,因为两个客户端都加载了相同的数据集。" +"此示例的源代码经过长期改进,可在此处找到: `Quickstart JAX " +"`_。我们的示例有些过于简单,因为两个客户端都加载了相同的数据集。" #: ../../source/example-jax-from-centralized-to-federated.rst:282 #: ../../source/tutorial-quickstart-jax.rst:288 msgid "" -"You're now prepared to explore this topic further. How about using a more " -"sophisticated model or using a different dataset? How about adding more " +"You're now prepared to explore this topic further. How about using a more" +" sophisticated model or using a different dataset? How about adding more " "clients?" -msgstr "" -"现在,您已准备好进行更深一步探索了。例如使用更复杂的模型或使用不同的数据集会" -"如何?增加更多客户端会如何?" +msgstr "现在,您已准备好进行更深一步探索了。例如使用更复杂的模型或使用不同的数据集会如何?增加更多客户端会如何?" #: ../../source/example-mxnet-walk-through.rst:2 msgid "Example: MXNet - Run MXNet Federated" @@ -2554,36 +2848,35 @@ msgstr "示例: MXNet - 运行联邦式 MXNet" #: ../../source/example-mxnet-walk-through.rst:4 msgid "" -"This tutorial will show you how to use Flower to build a federated version " -"of an existing MXNet workload. We are using MXNet to train a Sequential " -"model on the MNIST dataset. We will structure the example similar to our " -"`PyTorch - From Centralized To Federated `_ walkthrough. " -"MXNet and PyTorch are very similar and a very good comparison between MXNet " -"and PyTorch is given `here `_. First, we " -"build a centralized training approach based on the `Handwritten Digit " -"Recognition `_ tutorial. Then, we build upon " -"the centralized training code to run the training in a federated fashion." -msgstr "" -"本教程将向您展示如何使用 Flower 构建现有 MXNet 的联学习版本。我们将使用 " -"MXNet 在 MNIST 数据集上训练一个序列模型。另外,我们将采用与我们的 `PyTorch - " -"从集中式到联邦式 `_ 教程类似的示例结构。MXNet 和 PyTorch 非常相" -"似,参考 `此处 `_对 MXNet 和 PyTorch 进行了" -"详细的比较。首先,我们根据 `手写数字识别 ` 教" -"程 建立了集中式训练方法。然后,我们在集中式训练代码的基础上,以联邦方式运行训" -"练。" +"This tutorial will show you how to use Flower to build a federated " +"version of an existing MXNet workload. We are using MXNet to train a " +"Sequential model on the MNIST dataset. We will structure the example " +"similar to our `PyTorch - From Centralized To Federated " +"`_ walkthrough. MXNet and PyTorch are very " +"similar and a very good comparison between MXNet and PyTorch is given " +"`here `_. First, we build a centralized " +"training approach based on the `Handwritten Digit Recognition " +"`_" +" tutorial. Then, we build upon the centralized training code to run the " +"training in a federated fashion." +msgstr "" +"本教程将向您展示如何使用 Flower 构建现有 MXNet 的联学习版本。我们将使用 MXNet 在 MNIST " +"数据集上训练一个序列模型。另外,我们将采用与我们的 `PyTorch - 从集中式到联邦式 " +"`_ 教程类似的示例结构。MXNet 和 PyTorch 非常相似,参考 `此处 " +"`_对 MXNet 和 PyTorch " +"进行了详细的比较。首先,我们根据 `手写数字识别 " +"`" +" 教程 建立了集中式训练方法。然后,我们在集中式训练代码的基础上,以联邦方式运行训练。" #: ../../source/example-mxnet-walk-through.rst:10 msgid "" -"Before we start setting up our MXNet example, we install the :code:`mxnet` " -"and :code:`flwr` packages:" -msgstr "" -"在开始设置 MXNet 示例之前,我们先安装 :code:`mxnet` 和 :code:`flwr` 软件包:" +"Before we start setting up our MXNet example, we install the " +":code:`mxnet` and :code:`flwr` packages:" +msgstr "在开始设置 MXNet 示例之前,我们先安装 :code:`mxnet` 和 :code:`flwr` 软件包:" #: ../../source/example-mxnet-walk-through.rst:19 msgid "MNIST Training with MXNet" @@ -2591,67 +2884,61 @@ msgstr "使用 MXNet 进行 MNIST 训练" #: ../../source/example-mxnet-walk-through.rst:21 msgid "" -"We begin with a brief description of the centralized training code based on " -"a :code:`Sequential` model. If you want a more in-depth explanation of " -"what's going on then have a look at the official `MXNet tutorial `_." +"We begin with a brief description of the centralized training code based " +"on a :code:`Sequential` model. If you want a more in-depth explanation of" +" what's going on then have a look at the official `MXNet tutorial " +"`_." msgstr "" -"首先,我们将简要介绍基于 :code:`Sequential` 模型的集中式训练代码。如果您想获" -"得更深入的解释,请参阅官方的 `MXNet教程 `_。" +"首先,我们将简要介绍基于 :code:`Sequential` 模型的集中式训练代码。如果您想获得更深入的解释,请参阅官方的 `MXNet教程 " +"`_。" #: ../../source/example-mxnet-walk-through.rst:24 msgid "" -"Let's create a new file called:code:`mxnet_mnist.py` with all the components " -"required for a traditional (centralized) MNIST training. First, the MXNet " -"package :code:`mxnet` needs to be imported. You can see that we do not yet " -"import the :code:`flwr` package for federated learning. This will be done " -"later." +"Let's create a new file called:code:`mxnet_mnist.py` with all the " +"components required for a traditional (centralized) MNIST training. " +"First, the MXNet package :code:`mxnet` needs to be imported. You can see " +"that we do not yet import the :code:`flwr` package for federated " +"learning. This will be done later." msgstr "" -"让我们创建一个名为:code:`mxnet_mnist.py`的新文件,其中包含传统(集中式)" -"MNIST 训练所需的所有组件。首先,需要导入 MXNet 包 :code:`mxnet`。您可以看到," -"我们尚未导入用于联合学习的 :code:`flwr` 包,这将在稍后完成。" +"让我们创建一个名为:code:`mxnet_mnist.py`的新文件,其中包含传统(集中式)MNIST 训练所需的所有组件。首先,需要导入 " +"MXNet 包 :code:`mxnet`。您可以看到,我们尚未导入用于联合学习的 :code:`flwr` 包,这将在稍后完成。" #: ../../source/example-mxnet-walk-through.rst:42 -msgid "" -"The :code:`load_data()` function loads the MNIST training and test sets." +msgid "The :code:`load_data()` function loads the MNIST training and test sets." msgstr ":code:`load_data()` 函数加载 MNIST 训练集和测试集。" #: ../../source/example-mxnet-walk-through.rst:57 msgid "" "As already mentioned, we will use the MNIST dataset for this machine " -"learning workload. The model architecture (a very simple :code:`Sequential` " -"model) is defined in :code:`model()`." +"learning workload. The model architecture (a very simple " +":code:`Sequential` model) is defined in :code:`model()`." msgstr "" -"如前所述,我们将使用 MNIST 数据集进行机器学习。模型架构(一个非常简单的 :" -"code:`Sequential` 模型)在 :code:`model()` 中定义。" +"如前所述,我们将使用 MNIST 数据集进行机器学习。模型架构(一个非常简单的 :code:`Sequential` 模型)在 " +":code:`model()` 中定义。" #: ../../source/example-mxnet-walk-through.rst:70 msgid "" -"We now need to define the training (function :code:`train()`) which loops " -"over the training set and measures the loss for each batch of training " +"We now need to define the training (function :code:`train()`) which loops" +" over the training set and measures the loss for each batch of training " "examples." -msgstr "现在,我们需要定义训练函数( " -":code:`train()`),该函数在训练集上循环训练,并计算每批训练示例的损失值。" +msgstr "现在,我们需要定义训练函数( :code:`train()`),该函数在训练集上循环训练,并计算每批训练示例的损失值。" #: ../../source/example-mxnet-walk-through.rst:123 msgid "" "The evaluation of the model is defined in function :code:`test()`. The " -"function loops over all test samples and measures the loss and accuracy of " -"the model based on the test dataset." -msgstr "模型的评估在函数 :code:`test()` 中定义。该函数循环遍历所有测试样本,并根据测" -"试数据集计算模型的损失值和准确度。" +"function loops over all test samples and measures the loss and accuracy " +"of the model based on the test dataset." +msgstr "模型的评估在函数 :code:`test()` 中定义。该函数循环遍历所有测试样本,并根据测试数据集计算模型的损失值和准确度。" #: ../../source/example-mxnet-walk-through.rst:158 msgid "" "Having defined the data loading, model architecture, training, and " -"evaluation we can put everything together and train our model on MNIST. Note " -"that the GPU/CPU device for the training and testing is defined within the :" -"code:`ctx` (context)." +"evaluation we can put everything together and train our model on MNIST. " +"Note that the GPU/CPU device for the training and testing is defined " +"within the :code:`ctx` (context)." msgstr "" -"在定义了数据加载、模型架构、训练和评估之后,我们就可以把所有放在一起,在 " -"MNIST 上训练我们的模型了。请注意,用于训练和测试的 GPU/CPU 设备是在 " -":code:`ctx`中定义的。" +"在定义了数据加载、模型架构、训练和评估之后,我们就可以把所有放在一起,在 MNIST 上训练我们的模型了。请注意,用于训练和测试的 GPU/CPU" +" 设备是在 :code:`ctx`中定义的。" #: ../../source/example-mxnet-walk-through.rst:184 msgid "You can now run your (centralized) MXNet machine learning workload:" @@ -2659,13 +2946,13 @@ msgstr "现在,您可以运行(集中式)MXNet 机器学习工作:" #: ../../source/example-mxnet-walk-through.rst:190 msgid "" -"So far this should all look fairly familiar if you've used MXNet (or even " -"PyTorch) before. Let's take the next step and use what we've built to create " -"a simple federated learning system consisting of one server and two clients." +"So far this should all look fairly familiar if you've used MXNet (or even" +" PyTorch) before. Let's take the next step and use what we've built to " +"create a simple federated learning system consisting of one server and " +"two clients." msgstr "" -"到目前为止,如果你以前使用过 MXNet(甚至 PyTorch),这一切看起来应该相当熟悉" -"。下一步,让我们利用已构建的内容创建一个简单联邦学习系统(由一个服务器和两个" -"客户端组成)。" +"到目前为止,如果你以前使用过 MXNet(甚至 " +"PyTorch),这一切看起来应该相当熟悉。下一步,让我们利用已构建的内容创建一个简单联邦学习系统(由一个服务器和两个客户端组成)。" #: ../../source/example-mxnet-walk-through.rst:194 msgid "MXNet meets Flower" @@ -2674,62 +2961,59 @@ msgstr "MXNet 结合 Flower" #: ../../source/example-mxnet-walk-through.rst:196 msgid "" "So far, it was not easily possible to use MXNet workloads for federated " -"learning because federated learning is not supported in MXNet. Since Flower " -"is fully agnostic towards the underlying machine learning framework, it can " -"be used to federated arbitrary machine learning workloads. This section will " -"show you how Flower can be used to federate our centralized MXNet workload." +"learning because federated learning is not supported in MXNet. Since " +"Flower is fully agnostic towards the underlying machine learning " +"framework, it can be used to federated arbitrary machine learning " +"workloads. This section will show you how Flower can be used to federate " +"our centralized MXNet workload." msgstr "" -"由于 MXNet 目前不支持联邦学习,因此无法轻松地直接将 MXNet 用于联邦学习之中。" -"Flower 与底层机器学习框架完全无关,因此它可用于任意联邦式机器学习工作。" -"本节将向你展示如何使用 Flower 将我们的集中式 MXNet 改为联邦式训练。" +"由于 MXNet 目前不支持联邦学习,因此无法轻松地直接将 MXNet 用于联邦学习之中。Flower " +"与底层机器学习框架完全无关,因此它可用于任意联邦式机器学习工作。本节将向你展示如何使用 Flower 将我们的集中式 MXNet 改为联邦式训练。" #: ../../source/example-mxnet-walk-through.rst:198 msgid "" -"The concept to federate an existing workload is always the same and easy to " -"understand. We have to start a *server* and then use the code in :code:" -"`mxnet_mnist.py` for the *clients* that are connected to the *server*. The " -"*server* sends model parameters to the clients. The *clients* run the " -"training and update the parameters. The updated parameters are sent back to " -"the *server* which averages all received parameter updates. This describes " -"one round of the federated learning process and we repeat this for multiple " -"rounds." -msgstr "" -"将现有模型框架联邦化的概念始终是相同的,也很容易理解。我们必须启动一个*服务器" -"*,然后对连接到*服务器*的*客户端*使用 :code:`mxnet_mnist.py`中的代码。*服务器" -"*向客户端发送模型参数,然后*客户端*运行训练并更新参数。更新后的参数被发回*服" -"务器*,然后会对所有收到的参数更新进行平均聚合。以上描述的是一轮联邦学习过程," -"我们将重复进行多轮学习。" +"The concept to federate an existing workload is always the same and easy " +"to understand. We have to start a *server* and then use the code in " +":code:`mxnet_mnist.py` for the *clients* that are connected to the " +"*server*. The *server* sends model parameters to the clients. The " +"*clients* run the training and update the parameters. The updated " +"parameters are sent back to the *server* which averages all received " +"parameter updates. This describes one round of the federated learning " +"process and we repeat this for multiple rounds." +msgstr "" +"将现有模型框架联邦化的概念始终是相同的,也很容易理解。我们必须启动一个*服务器*,然后对连接到*服务器*的*客户端*使用 " +":code:`mxnet_mnist.py`中的代码。*服务器*向客户端发送模型参数,然后*客户端*运行训练并更新参数。更新后的参数被发回*服务器*,然后会对所有收到的参数更新进行平均聚合。以上描述的是一轮联邦学习过程,我们将重复进行多轮学习。" #: ../../source/example-mxnet-walk-through.rst:220 msgid "" -"Finally, we will define our *client* logic in :code:`client.py` and build " -"upon the previously defined MXNet training in :code:`mxnet_mnist.py`. Our " -"*client* needs to import :code:`flwr`, but also :code:`mxnet` to update the " -"parameters on our MXNet model:" +"Finally, we will define our *client* logic in :code:`client.py` and build" +" upon the previously defined MXNet training in :code:`mxnet_mnist.py`. " +"Our *client* needs to import :code:`flwr`, but also :code:`mxnet` to " +"update the parameters on our MXNet model:" msgstr "" -"最后,我们将在 :code:`client.py` 中定义我们的 *client* 逻辑,并以之前在 :" -"code:`mxnet_mnist.py` 中定义的 MXNet 训练为基础。我们的 *client* 不仅需要导" -"入 :code:`flwr`,还需要导入 :code:`mxnet`,以更新 MXNet 模型的参数:" +"最后,我们将在 :code:`client.py` 中定义我们的 *client* 逻辑,并以之前在 :code:`mxnet_mnist.py`" +" 中定义的 MXNet 训练为基础。我们的 *client* 不仅需要导入 :code:`flwr`,还需要导入 " +":code:`mxnet`,以更新 MXNet 模型的参数:" #: ../../source/example-mxnet-walk-through.rst:235 msgid "" -"Implementing a Flower *client* basically means implementing a subclass of " -"either :code:`flwr.client.Client` or :code:`flwr.client.NumPyClient`. Our " -"implementation will be based on :code:`flwr.client.NumPyClient` and we'll " -"call it :code:`MNISTClient`. :code:`NumPyClient` is slighly easier to " -"implement than :code:`Client` if you use a framework with good NumPy " +"Implementing a Flower *client* basically means implementing a subclass of" +" either :code:`flwr.client.Client` or :code:`flwr.client.NumPyClient`. " +"Our implementation will be based on :code:`flwr.client.NumPyClient` and " +"we'll call it :code:`MNISTClient`. :code:`NumPyClient` is slighly easier " +"to implement than :code:`Client` if you use a framework with good NumPy " "interoperability (like PyTorch or MXNet) because it avoids some of the " -"boilerplate that would otherwise be necessary. :code:`MNISTClient` needs to " -"implement four methods, two methods for getting/setting model parameters, " -"one method for training the model, and one method for testing the model:" +"boilerplate that would otherwise be necessary. :code:`MNISTClient` needs " +"to implement four methods, two methods for getting/setting model " +"parameters, one method for training the model, and one method for testing" +" the model:" msgstr "" "实现 Flower *client*基本上意味着要实现 :code:`flwr.client.Client` 或 " -":code:`flwr.client.NumPyClient` 的子类。我们的代码实现将基于 :code:`flwr." -"client.NumPyClient`,并将其命名为 :code:`MNISTClient`。如果使用具有良好 " -"NumPy 互操作性的框架(如 PyTorch 或 MXNet),:code:`NumPyClient` 比 " +":code:`flwr.client.NumPyClient` 的子类。我们的代码实现将基于 " +":code:`flwr.client.NumPyClient`,并将其命名为 :code:`MNISTClient`。如果使用具有良好 NumPy" +" 互操作性的框架(如 PyTorch 或 MXNet),:code:`NumPyClient` 比 " ":code:`Client`更容易实现,因为它避免了一些不必要的操作。:code:`MNISTClient` " -"需要实现四个方法,两个用于获取/设置模型参数,一个用于训练模型,一个用于测试模" -"型:" +"需要实现四个方法,两个用于获取/设置模型参数,一个用于训练模型,一个用于测试模型:" #: ../../source/example-mxnet-walk-through.rst:242 msgid "transform MXNet :code:`NDArray`'s to NumPy :code:`ndarray`'s" @@ -2747,56 +3031,58 @@ msgstr "向服务器返回本地损失值和精确度" #: ../../source/example-mxnet-walk-through.rst:255 msgid "" -"The challenging part is to transform the MXNet parameters from :code:" -"`NDArray` to :code:`NumPy Arrays` to make it readable for Flower." +"The challenging part is to transform the MXNet parameters from " +":code:`NDArray` to :code:`NumPy Arrays` to make it readable for Flower." msgstr "" -"具有挑战性的部分是将 MXNet 参数从 :code:`NDArray` 转换为 :code:`NumPy " -"Arrays` 以便 Flower 可以读取。" +"具有挑战性的部分是将 MXNet 参数从 :code:`NDArray` 转换为 :code:`NumPy Arrays` 以便 Flower " +"可以读取。" #: ../../source/example-mxnet-walk-through.rst:257 msgid "" -"The two :code:`NumPyClient` methods :code:`fit` and :code:`evaluate` make " -"use of the functions :code:`train()` and :code:`test()` previously defined " -"in :code:`mxnet_mnist.py`. So what we really do here is we tell Flower " -"through our :code:`NumPyClient` subclass which of our already defined " -"functions to call for training and evaluation. We included type annotations " -"to give you a better understanding of the data types that get passed around." +"The two :code:`NumPyClient` methods :code:`fit` and :code:`evaluate` make" +" use of the functions :code:`train()` and :code:`test()` previously " +"defined in :code:`mxnet_mnist.py`. So what we really do here is we tell " +"Flower through our :code:`NumPyClient` subclass which of our already " +"defined functions to call for training and evaluation. We included type " +"annotations to give you a better understanding of the data types that get" +" passed around." msgstr "" "这两个 :code:`NumPyClient` 方法 :code:`fit` 和 :code:`evaluate` 使用了之前在 " -":code:`mxnet_mnist.py` 中定义的函数 :code:`train()` 和 :code:`test()`。因此," -"我们要做的就是通过 :code:`NumPyClient` 子类告知 Flower 在训练和评估时要调用哪" -"些已定义的函数。我们加入了类型注解,以便让您更好地理解传递的数据类型。" +":code:`mxnet_mnist.py` 中定义的函数 :code:`train()` 和 " +":code:`test()`。因此,我们要做的就是通过 :code:`NumPyClient` 子类告知 Flower " +"在训练和评估时要调用哪些已定义的函数。我们加入了类型注解,以便让您更好地理解传递的数据类型。" #: ../../source/example-mxnet-walk-through.rst:319 msgid "" -"Having defined data loading, model architecture, training, and evaluation we " -"can put everything together and train our :code:`Sequential` model on MNIST." +"Having defined data loading, model architecture, training, and evaluation" +" we can put everything together and train our :code:`Sequential` model on" +" MNIST." msgstr "" -"在定义了数据加载、模型架构、训练和评估之后,我们就可以将所有内容整合在一起," -"在 MNIST 上训练我们的 :code:`Sequential` 模型。" +"在定义了数据加载、模型架构、训练和评估之后,我们就可以将所有内容整合在一起,在 MNIST 上训练我们的 :code:`Sequential` " +"模型。" #: ../../source/example-mxnet-walk-through.rst:353 msgid "" -"in each window (make sure that the server is still running before you do so) " -"and see your MXNet project run federated learning across two clients. " -"Congratulations!" -msgstr "确保服务器仍在运行后,然后就能在每个窗口中看到 MXNet " -"项目在两个客户端上运行联邦学习了。祝贺!" +"in each window (make sure that the server is still running before you do " +"so) and see your MXNet project run federated learning across two clients." +" Congratulations!" +msgstr "确保服务器仍在运行后,然后就能在每个窗口中看到 MXNet 项目在两个客户端上运行联邦学习了。祝贺!" #: ../../source/example-mxnet-walk-through.rst:358 msgid "" -"The full source code for this example: `MXNet: From Centralized To Federated " -"(Code) `_. Our example is of course somewhat over-" -"simplified because both clients load the exact same dataset, which isn't " -"realistic. You're now prepared to explore this topic further. How about " -"using a CNN or using a different dataset? How about adding more clients?" +"The full source code for this example: `MXNet: From Centralized To " +"Federated (Code) `_. Our example is of course " +"somewhat over-simplified because both clients load the exact same " +"dataset, which isn't realistic. You're now prepared to explore this topic" +" further. How about using a CNN or using a different dataset? How about " +"adding more clients?" msgstr "" "此示例的完整源代码在:\"MXNet: From Centralized To Federated (Code) " -"`_。当然,我们的示例有些过于简单,因为两个客户端都加载了完全相同的" -"数据集,这并不真实。现在您已经准备好进一步探讨了。使用 CNN " -"或使用不同的数据集会如何?添加更多客户端会如何?" +"`_。当然,我们的示例有些过于简单,因为两个客户端都加载了完全相同的数据集,这并不真实。现在您已经准备好进一步探讨了。使用 " +"CNN 或使用不同的数据集会如何?添加更多客户端会如何?" #: ../../source/example-pytorch-from-centralized-to-federated.rst:2 msgid "Example: PyTorch - From Centralized To Federated" @@ -2804,44 +3090,41 @@ msgstr "实例: PyTorch - 从集中式到联邦式" #: ../../source/example-pytorch-from-centralized-to-federated.rst:4 msgid "" -"This tutorial will show you how to use Flower to build a federated version " -"of an existing machine learning workload. We are using PyTorch to train a " -"Convolutional Neural Network on the CIFAR-10 dataset. First, we introduce " -"this machine learning task with a centralized training approach based on the " -"`Deep Learning with PyTorch `_ tutorial. Then, we build upon the centralized " -"training code to run the training in a federated fashion." +"This tutorial will show you how to use Flower to build a federated " +"version of an existing machine learning workload. We are using PyTorch to" +" train a Convolutional Neural Network on the CIFAR-10 dataset. First, we " +"introduce this machine learning task with a centralized training approach" +" based on the `Deep Learning with PyTorch " +"`_ " +"tutorial. Then, we build upon the centralized training code to run the " +"training in a federated fashion." msgstr "" -"本教程将向您展示如何使用 Flower 构建现有机器学习工作的联邦版本。我们使用 " -"PyTorch 在 CIFAR-10 数据集上训练一个卷积神经网络。首先,我们基于 \"Deep " -"Learning with PyTorch `_\"教程,采用集中式训练方法介绍了这项机器学习任务。然" -"后,我们在集中式训练代码的基础上以联邦方式运行训练。" +"本教程将向您展示如何使用 Flower 构建现有机器学习工作的联邦版本。我们使用 PyTorch 在 CIFAR-10 " +"数据集上训练一个卷积神经网络。首先,我们基于 \"Deep Learning with PyTorch " +"`_\"教程,采用集中式训练方法介绍了这项机器学习任务。然后,我们在集中式训练代码的基础上以联邦方式运行训练。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:12 msgid "" -"We begin with a brief description of the centralized CNN training code. If " -"you want a more in-depth explanation of what's going on then have a look at " -"the official `PyTorch tutorial `_." +"We begin with a brief description of the centralized CNN training code. " +"If you want a more in-depth explanation of what's going on then have a " +"look at the official `PyTorch tutorial " +"`_." msgstr "" -"我们首先简要介绍一下集中式 CNN 训练代码。如果您想获得更深入的解释,请参阅 " -"PyTorch 官方教程`PyTorch tutorial `_。" +"我们首先简要介绍一下集中式 CNN 训练代码。如果您想获得更深入的解释,请参阅 PyTorch 官方教程`PyTorch tutorial " +"`_。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:15 msgid "" "Let's create a new file called :code:`cifar.py` with all the components " -"required for a traditional (centralized) training on CIFAR-10. First, all " -"required packages (such as :code:`torch` and :code:`torchvision`) need to be " -"imported. You can see that we do not import any package for federated " -"learning. You can keep all these imports as they are even when we add the " -"federated learning components at a later point." +"required for a traditional (centralized) training on CIFAR-10. First, all" +" required packages (such as :code:`torch` and :code:`torchvision`) need " +"to be imported. You can see that we do not import any package for " +"federated learning. You can keep all these imports as they are even when " +"we add the federated learning components at a later point." msgstr "" "让我们创建一个名为 :code:`cifar.py` 的新文件,其中包含 CIFAR-10 " -"传统(集中)培训所需的所有组件。首先,需要导入所有必需的软件包(如 " -":code:`torch` 和 :code:`torchvision`)。您可以看到,我们没有导入任何用于联邦" -"学习的软件包。即使在以后添加联邦学习组件时,也可以保留所有这些导入。" +"传统(集中)培训所需的所有组件。首先,需要导入所有必需的软件包(如 :code:`torch` 和 " +":code:`torchvision`)。您可以看到,我们没有导入任何用于联邦学习的软件包。即使在以后添加联邦学习组件时,也可以保留所有这些导入。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:32 msgid "" @@ -2849,120 +3132,107 @@ msgid "" "learning workload. The model architecture (a very simple Convolutional " "Neural Network) is defined in :code:`class Net()`." msgstr "" -"如前所述,我们将使用 CIFAR-10 数据集进行机器学习。模型架构(一个非常简单的卷" -"积神经网络)在 :code:`class Net()` 中定义。" +"如前所述,我们将使用 CIFAR-10 数据集进行机器学习。模型架构(一个非常简单的卷积神经网络)在 :code:`class Net()` " +"中定义。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:56 msgid "" -"The :code:`load_data()` function loads the CIFAR-10 training and test sets. " -"The :code:`transform` normalized the data after loading." +"The :code:`load_data()` function loads the CIFAR-10 training and test " +"sets. The :code:`transform` normalized the data after loading." msgstr "" -":code:`load_data()` 函数加载 CIFAR-10 训练集和测试集。加载数据后,:code:" -"`transform`函数对数据进行了归一化处理。" +":code:`load_data()` 函数加载 CIFAR-10 " +"训练集和测试集。加载数据后,:code:`transform`函数对数据进行了归一化处理。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:74 msgid "" -"We now need to define the training (function :code:`train()`) which loops " -"over the training set, measures the loss, backpropagates it, and then takes " -"one optimizer step for each batch of training examples." -msgstr "" -"现在,我们需要定义训练函数(:code:`train()`),该函数在训练集上循环训练,计算" -"损失值并反向传播,然后为每批训练数据在优化器上执行一个优化步骤。" +"We now need to define the training (function :code:`train()`) which loops" +" over the training set, measures the loss, backpropagates it, and then " +"takes one optimizer step for each batch of training examples." +msgstr "现在,我们需要定义训练函数(:code:`train()`),该函数在训练集上循环训练,计算损失值并反向传播,然后为每批训练数据在优化器上执行一个优化步骤。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:76 msgid "" -"The evaluation of the model is defined in the function :code:`test()`. The " -"function loops over all test samples and measures the loss of the model " -"based on the test dataset." -msgstr "模型的评估在函数 :code:`test()` " -"中定义。该函数循环遍历所有测试样本,并计算测试数据集的模型损失值。" +"The evaluation of the model is defined in the function :code:`test()`. " +"The function loops over all test samples and measures the loss of the " +"model based on the test dataset." +msgstr "模型的评估在函数 :code:`test()` 中定义。该函数循环遍历所有测试样本,并计算测试数据集的模型损失值。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:136 msgid "" "Having defined the data loading, model architecture, training, and " "evaluation we can put everything together and train our CNN on CIFAR-10." -msgstr "在确定了数据加载、模型架构、训练和评估之后,我们就可以将所有整合在一起,在 " -"CIFAR-10 上训练我们的 CNN。" +msgstr "在确定了数据加载、模型架构、训练和评估之后,我们就可以将所有整合在一起,在 CIFAR-10 上训练我们的 CNN。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:163 msgid "" -"So far, this should all look fairly familiar if you've used PyTorch before. " -"Let's take the next step and use what we've built to create a simple " -"federated learning system consisting of one server and two clients." +"So far, this should all look fairly familiar if you've used PyTorch " +"before. Let's take the next step and use what we've built to create a " +"simple federated learning system consisting of one server and two " +"clients." msgstr "" -"到目前为止,如果你以前用过 PyTorch,这一切看起来应该相当熟悉。让我们进行下一" -"步,利用我们所构建的内容创建一个简单联邦学习系统(由一个服务器和两个客户端组" -"成)。" +"到目前为止,如果你以前用过 " +"PyTorch,这一切看起来应该相当熟悉。让我们进行下一步,利用我们所构建的内容创建一个简单联邦学习系统(由一个服务器和两个客户端组成)。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:169 msgid "" -"The simple machine learning project discussed in the previous section trains " -"the model on a single dataset (CIFAR-10), we call this centralized learning. " -"This concept of centralized learning, as shown in the previous section, is " -"probably known to most of you, and many of you have used it previously. " -"Normally, if you'd want to run machine learning workloads in a federated " -"fashion, then you'd have to change most of your code and set everything up " -"from scratch. This can be a considerable effort." -msgstr "" -"上一节讨论的简单机器学习项目在单一数据集(CIFAR-10)上训练模型,我们称之为集" -"中学习。如上一节所示,集中学习的概念可能为大多数人所熟知,而且很多人以前都使" -"用过。通常情况下,如果要以联邦方式运行机器学习工作,就必须更改大部分代码,并" -"从头开始设置一切。这可能是一个相当大的工作量。" +"The simple machine learning project discussed in the previous section " +"trains the model on a single dataset (CIFAR-10), we call this centralized" +" learning. This concept of centralized learning, as shown in the previous" +" section, is probably known to most of you, and many of you have used it " +"previously. Normally, if you'd want to run machine learning workloads in " +"a federated fashion, then you'd have to change most of your code and set " +"everything up from scratch. This can be a considerable effort." +msgstr "上一节讨论的简单机器学习项目在单一数据集(CIFAR-10)上训练模型,我们称之为集中学习。如上一节所示,集中学习的概念可能为大多数人所熟知,而且很多人以前都使用过。通常情况下,如果要以联邦方式运行机器学习工作,就必须更改大部分代码,并从头开始设置一切。这可能是一个相当大的工作量。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:173 msgid "" -"However, with Flower you can evolve your pre-existing code into a federated " -"learning setup without the need for a major rewrite." -msgstr "不过,有了 " -"Flower,您可以轻松地将已有的代码转变成联邦学习的模式,无需进行大量重写。" +"However, with Flower you can evolve your pre-existing code into a " +"federated learning setup without the need for a major rewrite." +msgstr "不过,有了 Flower,您可以轻松地将已有的代码转变成联邦学习的模式,无需进行大量重写。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:175 msgid "" -"The concept is easy to understand. We have to start a *server* and then use " -"the code in :code:`cifar.py` for the *clients* that are connected to the " -"*server*. The *server* sends model parameters to the clients. The *clients* " -"run the training and update the paramters. The updated parameters are sent " -"back to the *server* which averages all received parameter updates. This " -"describes one round of the federated learning process and we repeat this for " -"multiple rounds." +"The concept is easy to understand. We have to start a *server* and then " +"use the code in :code:`cifar.py` for the *clients* that are connected to " +"the *server*. The *server* sends model parameters to the clients. The " +"*clients* run the training and update the paramters. The updated " +"parameters are sent back to the *server* which averages all received " +"parameter updates. This describes one round of the federated learning " +"process and we repeat this for multiple rounds." msgstr "" -"这个概念很容易理解。我们必须启动一个*服务器*,然后对连接到*服务器*的*客户端*" -"使用 :code:`cifar.py`中的代码。*服务器*向客户端发送模型参数,*客户端*运行训练" -"并更新参数。更新后的参数被发回*服务器*,然后会对所有收到的参数更新进行平均聚" -"合。以上描述的是一轮联邦学习过程,我们将重复进行多轮学习。" +"这个概念很容易理解。我们必须启动一个*服务器*,然后对连接到*服务器*的*客户端*使用 " +":code:`cifar.py`中的代码。*服务器*向客户端发送模型参数,*客户端*运行训练并更新参数。更新后的参数被发回*服务器*,然后会对所有收到的参数更新进行平均聚合。以上描述的是一轮联邦学习过程,我们将重复进行多轮学习。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:197 msgid "" -"Finally, we will define our *client* logic in :code:`client.py` and build " -"upon the previously defined centralized training in :code:`cifar.py`. Our " -"*client* needs to import :code:`flwr`, but also :code:`torch` to update the " -"paramters on our PyTorch model:" +"Finally, we will define our *client* logic in :code:`client.py` and build" +" upon the previously defined centralized training in :code:`cifar.py`. " +"Our *client* needs to import :code:`flwr`, but also :code:`torch` to " +"update the paramters on our PyTorch model:" msgstr "" -"最后,我们将在 :code:`client.py` 中定义我们的 *client* 逻辑,并以之前在 :" -"code:`cifar.py` 中定义的集中式训练为基础。我们的 *client* 不仅需要导入 :code:" -"`flwr`,还需要导入 :code:`torch`,以更新 PyTorch 模型的参数:" +"最后,我们将在 :code:`client.py` 中定义我们的 *client* 逻辑,并以之前在 :code:`cifar.py` " +"中定义的集中式训练为基础。我们的 *client* 不仅需要导入 :code:`flwr`,还需要导入 :code:`torch`,以更新 " +"PyTorch 模型的参数:" #: ../../source/example-pytorch-from-centralized-to-federated.rst:213 msgid "" -"Implementing a Flower *client* basically means implementing a subclass of " -"either :code:`flwr.client.Client` or :code:`flwr.client.NumPyClient`. Our " -"implementation will be based on :code:`flwr.client.NumPyClient` and we'll " -"call it :code:`CifarClient`. :code:`NumPyClient` is slighly easier to " -"implement than :code:`Client` if you use a framework with good NumPy " -"interoperability (like PyTorch or TensorFlow/Keras) because it avoids some " -"of the boilerplate that would otherwise be necessary. :code:`CifarClient` " -"needs to implement four methods, two methods for getting/setting model " -"parameters, one method for training the model, and one method for testing " -"the model:" +"Implementing a Flower *client* basically means implementing a subclass of" +" either :code:`flwr.client.Client` or :code:`flwr.client.NumPyClient`. " +"Our implementation will be based on :code:`flwr.client.NumPyClient` and " +"we'll call it :code:`CifarClient`. :code:`NumPyClient` is slighly easier " +"to implement than :code:`Client` if you use a framework with good NumPy " +"interoperability (like PyTorch or TensorFlow/Keras) because it avoids " +"some of the boilerplate that would otherwise be necessary. " +":code:`CifarClient` needs to implement four methods, two methods for " +"getting/setting model parameters, one method for training the model, and " +"one method for testing the model:" msgstr "" "实现 Flower *client*基本上意味着实现 :code:`flwr.client.Client` 或 " -":code:`flwr.client.NumPyClient` 的子类。我们的代码实现将基于 :code:`flwr." -"client.NumPyClient`,并将其命名为 :code:`CifarClient`。如果使用具有良好 " -"NumPy 互操作性的框架(如 PyTorch 或 TensorFlow/Keras),:code:`NumPyClient`" -"的实现比 " -":code:`Client`略微容易一些,因为它避免了一些不必要的操作。:code:`CifarClient`" -" 需要实现四个方法,两个用于获取/设置模型参数,一个用于训练模型,一个用于测试" -"模型:" +":code:`flwr.client.NumPyClient` 的子类。我们的代码实现将基于 " +":code:`flwr.client.NumPyClient`,并将其命名为 :code:`CifarClient`。如果使用具有良好 NumPy" +" 互操作性的框架(如 PyTorch 或 TensorFlow/Keras),:code:`NumPyClient`的实现比 " +":code:`Client`略微容易一些,因为它避免了一些不必要的操作。:code:`CifarClient` " +"需要实现四个方法,两个用于获取/设置模型参数,一个用于训练模型,一个用于测试模型:" #: ../../source/example-pytorch-from-centralized-to-federated.rst:219 msgid ":code:`set_parameters`" @@ -2970,55 +3240,50 @@ msgstr ":code:`set_parameters`" #: ../../source/example-pytorch-from-centralized-to-federated.rst:232 msgid "" -"The two :code:`NumPyClient` methods :code:`fit` and :code:`evaluate` make " -"use of the functions :code:`train()` and :code:`test()` previously defined " -"in :code:`cifar.py`. So what we really do here is we tell Flower through " -"our :code:`NumPyClient` subclass which of our already defined functions to " -"call for training and evaluation. We included type annotations to give you a " -"better understanding of the data types that get passed around." +"The two :code:`NumPyClient` methods :code:`fit` and :code:`evaluate` make" +" use of the functions :code:`train()` and :code:`test()` previously " +"defined in :code:`cifar.py`. So what we really do here is we tell Flower " +"through our :code:`NumPyClient` subclass which of our already defined " +"functions to call for training and evaluation. We included type " +"annotations to give you a better understanding of the data types that get" +" passed around." msgstr "" -"这两个 :code:`NumPyClient` 中的方法 :code:`fit` 和 :code:`evaluate` " -"使用了之前在 :code:`cifar.py` 中定义的函数 :code:`train()` 和 " -":code:`test()`。因此,我们在这里要做的就是通过 :code:`NumPyClient` 子类告知 " -"Flower 在训练和评估时要调用哪些已定义的函数。我们加入了类型注解,以便让你更好" -"地理解传递的数据类型。" +"这两个 :code:`NumPyClient` 中的方法 :code:`fit` 和 :code:`evaluate` 使用了之前在 " +":code:`cifar.py` 中定义的函数 :code:`train()` 和 :code:`test()`。因此,我们在这里要做的就是通过 " +":code:`NumPyClient` 子类告知 Flower " +"在训练和评估时要调用哪些已定义的函数。我们加入了类型注解,以便让你更好地理解传递的数据类型。" #: ../../source/example-pytorch-from-centralized-to-federated.rst:280 msgid "" "All that's left to do it to define a function that loads both model and " -"data, creates a :code:`CifarClient`, and starts this client. You load your " -"data and model by using :code:`cifar.py`. Start :code:`CifarClient` with the " -"function :code:`fl.client.start_client()` by pointing it at the same IP " -"adress we used in :code:`server.py`:" -msgstr "" -"剩下的就是定义模型和数据加载函数了。创建一个:code:`CifarClient`类,并运行这个" -"客服端。您将通过:code:`cifar.py`加载数据和模型。另外,通过:code:`fl.client.st" -"art_client()`函数来运行客户端:code:`CifarClient`,需要保证IP地址和:code:`serv" -"er.py`中所使用的一致:" +"data, creates a :code:`CifarClient`, and starts this client. You load " +"your data and model by using :code:`cifar.py`. Start :code:`CifarClient` " +"with the function :code:`fl.client.start_client()` by pointing it at the " +"same IP adress we used in :code:`server.py`:" +msgstr "剩下的就是定义模型和数据加载函数了。创建一个:code:`CifarClient`类,并运行这个客服端。您将通过:code:`cifar.py`加载数据和模型。另外,通过:code:`fl.client.start_client()`函数来运行客户端:code:`CifarClient`,需要保证IP地址和:code:`server.py`中所使用的一致:" #: ../../source/example-pytorch-from-centralized-to-federated.rst:307 msgid "" -"in each window (make sure that the server is running before you do so) and " -"see your (previously centralized) PyTorch project run federated learning " -"across two clients. Congratulations!" -msgstr "确保服务器正在运行后,您就能看到您的 PyTorch " -"项目(之前是集中式的)在两个客户端上运行联邦学习了。祝贺!" +"in each window (make sure that the server is running before you do so) " +"and see your (previously centralized) PyTorch project run federated " +"learning across two clients. Congratulations!" +msgstr "确保服务器正在运行后,您就能看到您的 PyTorch 项目(之前是集中式的)在两个客户端上运行联邦学习了。祝贺!" #: ../../source/example-pytorch-from-centralized-to-federated.rst:312 msgid "" "The full source code for this example: `PyTorch: From Centralized To " -"Federated (Code) `_. Our example is, of course, somewhat over-" -"simplified because both clients load the exact same dataset, which isn't " -"realistic. You're now prepared to explore this topic further. How about " -"using different subsets of CIFAR-10 on each client? How about adding more " -"clients?" -msgstr "" -"本示例的完整源代码为:`PyTorch: 从集中式到联合式 `_。当然,我" -"们的示例有些过于简单,因为两个客户端都加载了完全相同的数据集,这并不真实。现" -"在,您已经准备好进一步探讨这一主题了。比如在每个客户端使用不同的 CIFAR-10 " -"子集会如何?增加更多客户端会如何?" +"Federated (Code) `_. Our example is, of course, " +"somewhat over-simplified because both clients load the exact same " +"dataset, which isn't realistic. You're now prepared to explore this topic" +" further. How about using different subsets of CIFAR-10 on each client? " +"How about adding more clients?" +msgstr "" +"本示例的完整源代码为:`PyTorch: 从集中式到联合式 " +"`_。当然,我们的示例有些过于简单,因为两个客户端都加载了完全相同的数据集,这并不真实。现在,您已经准备好进一步探讨这一主题了。比如在每个客户端使用不同的" +" CIFAR-10 子集会如何?增加更多客户端会如何?" #: ../../source/example-walkthrough-pytorch-mnist.rst:2 msgid "Example: Walk-Through PyTorch & MNIST" @@ -3026,48 +3291,41 @@ msgstr "实例: PyTorch 和 MNIST 的演练" #: ../../source/example-walkthrough-pytorch-mnist.rst:4 msgid "" -"In this tutorial we will learn, how to train a Convolutional Neural Network " -"on MNIST using Flower and PyTorch." -msgstr "" -"在本教程中,我们将学习如何使用 Flower 和 PyTorch 在 MNIST 上训练卷积神经网" -"络。" +"In this tutorial we will learn, how to train a Convolutional Neural " +"Network on MNIST using Flower and PyTorch." +msgstr "在本教程中,我们将学习如何使用 Flower 和 PyTorch 在 MNIST 上训练卷积神经网络。" #: ../../source/example-walkthrough-pytorch-mnist.rst:6 -#: ../../source/tutorial-quickstart-mxnet.rst:14 +#: ../../source/tutorial-quickstart-mxnet.rst:16 #: ../../source/tutorial-quickstart-pytorch.rst:17 #: ../../source/tutorial-quickstart-scikitlearn.rst:14 msgid "" -"Our example consists of one *server* and two *clients* all having the same " -"model." +"Our example consists of one *server* and two *clients* all having the " +"same model." msgstr "我们的例子包括一个*服务器*和两个*客户端*,它们都有相同的模型。" #: ../../source/example-walkthrough-pytorch-mnist.rst:8 #: ../../source/tutorial-quickstart-pytorch.rst:19 msgid "" -"*Clients* are responsible for generating individual weight-updates for the " -"model based on their local datasets. These updates are then sent to the " -"*server* which will aggregate them to produce a better model. Finally, the " -"*server* sends this improved version of the model back to each *client*. A " -"complete cycle of weight updates is called a *round*." -msgstr "" -"*客户端*负责在其本地数据集上更新模型参数。然后,这些参数会被发送到*服务器*," -"由*服务器*聚合后生成一个更好的模型。最后,*服务器*将改进后的模型发送回每个*客" -"户端*。一个完整的模型参数更新周期称为一*轮*。" +"*Clients* are responsible for generating individual weight-updates for " +"the model based on their local datasets. These updates are then sent to " +"the *server* which will aggregate them to produce a better model. " +"Finally, the *server* sends this improved version of the model back to " +"each *client*. A complete cycle of weight updates is called a *round*." +msgstr "*客户端*负责在其本地数据集上更新模型参数。然后,这些参数会被发送到*服务器*,由*服务器*聚合后生成一个更好的模型。最后,*服务器*将改进后的模型发送回每个*客户端*。一个完整的模型参数更新周期称为一*轮*。" #: ../../source/example-walkthrough-pytorch-mnist.rst:12 #: ../../source/tutorial-quickstart-pytorch.rst:23 msgid "" "Now that we have a rough idea of what is going on, let's get started. We " "first need to install Flower. You can do this by running :" -msgstr "现在,我们已经有了一个大致的概念了,那就让我们开始吧。首先,我们需要安装 " -"Flower。可以通过运行 :" +msgstr "现在,我们已经有了一个大致的概念了,那就让我们开始吧。首先,我们需要安装 Flower。可以通过运行 :" #: ../../source/example-walkthrough-pytorch-mnist.rst:18 msgid "" -"Since we want to use PyTorch to solve a computer vision task, let's go ahead " -"an install PyTorch and the **torchvision** library:" -msgstr "我们想用 PyTorch 来做计算机视觉任务,需要先安装 PyTorch 和 **torchvision** " -"库:" +"Since we want to use PyTorch to solve a computer vision task, let's go " +"ahead an install PyTorch and the **torchvision** library:" +msgstr "我们想用 PyTorch 来做计算机视觉任务,需要先安装 PyTorch 和 **torchvision** 库:" #: ../../source/example-walkthrough-pytorch-mnist.rst:26 msgid "Ready... Set... Train!" @@ -3076,19 +3334,19 @@ msgstr "准备...设置...训练!" #: ../../source/example-walkthrough-pytorch-mnist.rst:28 msgid "" "Now that we have all our dependencies installed, let's run a simple " -"distributed training with two clients and one server. Our training procedure " -"and network architecture are based on PyTorch's `Basic MNIST Example " -"`_. This will allow " -"you see how easy it is to wrap your code with Flower and begin training in a " -"federated way. We provide you with two helper scripts, namely *run-server." -"sh*, and *run-clients.sh*. Don't be afraid to look inside, they are simple " -"enough =)." -msgstr "" -"现在我们已经安装了所有的依赖包,让我们用两个客户端和一个服务器来运行一个简单" -"的分布式训练。我们的训练过程和网络架构基于 PyTorch 的 `Basic MNIST Example " +"distributed training with two clients and one server. Our training " +"procedure and network architecture are based on PyTorch's `Basic MNIST " +"Example `_. This " +"will allow you see how easy it is to wrap your code with Flower and begin" +" training in a federated way. We provide you with two helper scripts, " +"namely *run-server.sh*, and *run-clients.sh*. Don't be afraid to look " +"inside, they are simple enough =)." +msgstr "" +"现在我们已经安装了所有的依赖包,让我们用两个客户端和一个服务器来运行一个简单的分布式训练。我们的训练过程和网络架构基于 PyTorch 的 " +"`Basic MNIST Example " "`_。您会发现用 Flower " -"来封装您的代码并进行联邦学习训练是多么容易。我们为您提供了两个辅助脚本,即 " -"*run-server.sh* 和 *run-clients.sh*。别害怕,它们很简单 =)。" +"来封装您的代码并进行联邦学习训练是多么容易。我们为您提供了两个辅助脚本,即 *run-server.sh* 和 *run-" +"clients.sh*。别害怕,它们很简单 =)。" #: ../../source/example-walkthrough-pytorch-mnist.rst:31 msgid "" @@ -3104,8 +3362,7 @@ msgstr "现在服务器已经启动并运行,请继续启动客户端。" msgid "" "Et voilà! You should be seeing the training procedure and, after a few " "iterations, the test accuracy for each client." -msgstr "然后就可以了!您应该能看到训练过程,以及经过几次反复后,每个客户端的测试准确" -"率。" +msgstr "然后就可以了!您应该能看到训练过程,以及经过几次反复后,每个客户端的测试准确率。" #: ../../source/example-walkthrough-pytorch-mnist.rst:66 msgid "Now, let's see what is really happening inside." @@ -3113,57 +3370,53 @@ msgstr "现在,让我们看看里面到底发生了什么。" #: ../../source/example-walkthrough-pytorch-mnist.rst:69 #: ../../source/tutorial-quickstart-ios.rst:129 -#: ../../source/tutorial-quickstart-mxnet.rst:224 +#: ../../source/tutorial-quickstart-mxnet.rst:226 #: ../../source/tutorial-quickstart-pytorch.rst:203 #: ../../source/tutorial-quickstart-scikitlearn.rst:157 #: ../../source/tutorial-quickstart-tensorflow.rst:98 -#: ../../source/tutorial-quickstart-xgboost.rst:306 +#: ../../source/tutorial-quickstart-xgboost.rst:309 msgid "Flower Server" msgstr "Flower 服务器" #: ../../source/example-walkthrough-pytorch-mnist.rst:71 msgid "" -"Inside the server helper script *run-server.sh* you will find the following " -"code that basically runs the :code:`server.py`" -msgstr "" -"在服务器辅助脚本 *run-server.sh* 中,你可以找到以下代码,这些代码基本上都是运" -"行 :code:`server.py` 的代码" +"Inside the server helper script *run-server.sh* you will find the " +"following code that basically runs the :code:`server.py`" +msgstr "在服务器辅助脚本 *run-server.sh* 中,你可以找到以下代码,这些代码基本上都是运行 :code:`server.py` 的代码" #: ../../source/example-walkthrough-pytorch-mnist.rst:78 msgid "" "We can go a bit deeper and see that :code:`server.py` simply launches a " "server that will coordinate three rounds of training. Flower Servers are " "very customizable, but for simple workloads, we can start a server using " -"the :ref:`start_server ` function and leave " -"all the configuration possibilities at their default values, as seen below." +"the :ref:`start_server ` function and " +"leave all the configuration possibilities at their default values, as " +"seen below." msgstr "" -"我们可以再深入一点,:code:`server.py` " -"只是启动了一个服务器,该服务器将协调三轮训练。Flower " -"服务器是非常容易修改的,但对于简单的工作,我们可以使用 :ref:`start_server " -"`函数启动服务器,并将所有可能的配置保留为默认值,如下所示。" #: ../../source/example-walkthrough-pytorch-mnist.rst:89 #: ../../source/tutorial-quickstart-ios.rst:34 -#: ../../source/tutorial-quickstart-mxnet.rst:34 +#: ../../source/tutorial-quickstart-mxnet.rst:36 #: ../../source/tutorial-quickstart-pytorch.rst:37 #: ../../source/tutorial-quickstart-scikitlearn.rst:40 #: ../../source/tutorial-quickstart-tensorflow.rst:29 -#: ../../source/tutorial-quickstart-xgboost.rst:52 +#: ../../source/tutorial-quickstart-xgboost.rst:55 msgid "Flower Client" msgstr "Flower 客户端" #: ../../source/example-walkthrough-pytorch-mnist.rst:91 msgid "" -"Next, let's take a look at the *run-clients.sh* file. You will see that it " -"contains the main loop that starts a set of *clients*." -msgstr "接下来,让我们看看 *run-clients.sh* 文件。您会看到它包含了用来启动多个 " -"*客户端* 的代码。" +"Next, let's take a look at the *run-clients.sh* file. You will see that " +"it contains the main loop that starts a set of *clients*." +msgstr "接下来,让我们看看 *run-clients.sh* 文件。您会看到它包含了用来启动多个 *客户端* 的代码。" #: ../../source/example-walkthrough-pytorch-mnist.rst:100 msgid "" -"**cid**: is the client ID. It is an integer that uniquely identifies client " -"identifier." +"**cid**: is the client ID. It is an integer that uniquely identifies " +"client identifier." msgstr "**cid**:是客户 ID。它是一个整数,可唯一标识客户标识符。" #: ../../source/example-walkthrough-pytorch-mnist.rst:101 @@ -3172,39 +3425,38 @@ msgstr "**sever_address**: 标识服务器 IP 和端口的字符串。" #: ../../source/example-walkthrough-pytorch-mnist.rst:102 msgid "" -"**nb_clients**: This defines the number of clients being created. This piece " -"of information is not required by the client, but it helps us partition the " -"original MNIST dataset to make sure that every client is working on unique " -"subsets of both *training* and *test* sets." +"**nb_clients**: This defines the number of clients being created. This " +"piece of information is not required by the client, but it helps us " +"partition the original MNIST dataset to make sure that every client is " +"working on unique subsets of both *training* and *test* sets." msgstr "" -"**nb_clients**: 这定义了正在创建的客户端数量。客户端并不需要这一信息," -"但它有助于我们对原始 MNIST 数据集进行划分,以确保每个客户端都在 *training* " -"和 *test* 数据集上有独立的数据。" +"**nb_clients**: 这定义了正在创建的客户端数量。客户端并不需要这一信息,但它有助于我们对原始 MNIST " +"数据集进行划分,以确保每个客户端都在 *training* 和 *test* 数据集上有独立的数据。" #: ../../source/example-walkthrough-pytorch-mnist.rst:104 msgid "" "Again, we can go deeper and look inside :code:`flwr_example/quickstart-" "pytorch/client.py`. After going through the argument parsing code at the " -"beginning of our :code:`main` function, you will find a call to :code:`mnist." -"load_data`. This function is responsible for partitioning the original MNIST " -"datasets (*training* and *test*) and returning a :code:`torch.utils.data." -"DataLoader` s for each of them. We then instantiate a :code:" -"`PytorchMNISTClient` object with our client ID, our DataLoaders, the number " -"of epochs in each round, and which device we want to use for training (CPU " -"or GPU)." +"beginning of our :code:`main` function, you will find a call to " +":code:`mnist.load_data`. This function is responsible for partitioning " +"the original MNIST datasets (*training* and *test*) and returning a " +":code:`torch.utils.data.DataLoader` s for each of them. We then " +"instantiate a :code:`PytorchMNISTClient` object with our client ID, our " +"DataLoaders, the number of epochs in each round, and which device we want" +" to use for training (CPU or GPU)." msgstr "" "我们可以深入看一下 :code:`flwr_example/quickstart-pytorch/client.py`。查看 " -":code:`main` 函数开头的参数解析代码后,你会发现一个对 :code:`mnist.load_data`" -" 的调用。该函数负责分割原始 MNIST 数据集(*training* 和 *test*)," -"并为每个数据集返回一个 :code:`torch.utils.data.DataLoader` 。然后," -"我们实例化一个 :code:`PytorchMNISTClient` 对象,其中包含我们的客户端 ID、 " +":code:`main` 函数开头的参数解析代码后,你会发现一个对 :code:`mnist.load_data` 的调用。该函数负责分割原始 " +"MNIST 数据集(*training* 和 *test*),并为每个数据集返回一个 " +":code:`torch.utils.data.DataLoader` 。然后,我们实例化一个 " +":code:`PytorchMNISTClient` 对象,其中包含我们的客户端 ID、 " "DataLoader、每一轮中的遍历数,以及我们希望用于训练的设备(CPU 或 GPU)。" #: ../../source/example-walkthrough-pytorch-mnist.rst:119 msgid "" -"The :code:`PytorchMNISTClient` object when finally passed to :code:`fl." -"client.start_client` along with the server's address as the training process " -"begins." +"The :code:`PytorchMNISTClient` object when finally passed to " +":code:`fl.client.start_client` along with the server's address as the " +"training process begins." msgstr "" "当训练过程开始时,:code:`PytorchMNISTClient` 对象会连同服务器地址一起传递给 " ":code:`fl.client.start_client`。" @@ -3215,67 +3467,63 @@ msgstr "仔细看一下" #: ../../source/example-walkthrough-pytorch-mnist.rst:125 msgid "" -"Now, let's look closely into the :code:`PytorchMNISTClient` inside :code:" -"`flwr_example.quickstart-pytorch.mnist` and see what it is doing:" +"Now, let's look closely into the :code:`PytorchMNISTClient` inside " +":code:`flwr_example.quickstart-pytorch.mnist` and see what it is doing:" msgstr "" -"现在,让我们仔细研究一下 :code:`flwr_example.quickstart-pytorch.mnist` 中的 :" -"code:`PytorchMNISTClient`,看看它在做什么:" +"现在,让我们仔细研究一下 :code:`flwr_example.quickstart-pytorch.mnist` 中的 " +":code:`PytorchMNISTClient`,看看它在做什么:" #: ../../source/example-walkthrough-pytorch-mnist.rst:226 msgid "" -"The first thing to notice is that :code:`PytorchMNISTClient` instantiates a " -"CNN model inside its constructor" -msgstr "" -"首先要注意的是 :code:`PytorchMNISTClient` 在其构造函数中实例化了一个 CNN 模型" +"The first thing to notice is that :code:`PytorchMNISTClient` instantiates" +" a CNN model inside its constructor" +msgstr "首先要注意的是 :code:`PytorchMNISTClient` 在其构造函数中实例化了一个 CNN 模型" #: ../../source/example-walkthrough-pytorch-mnist.rst:244 msgid "" -"The code for the CNN is available under :code:`quickstart-pytorch.mnist` and " -"it is reproduced below. It is the same network found in `Basic MNIST Example " -"`_." +"The code for the CNN is available under :code:`quickstart-pytorch.mnist` " +"and it is reproduced below. It is the same network found in `Basic MNIST " +"Example `_." msgstr "" -"CNN 的代码可在 :code:`quickstart-pytorch.mnist` 下找到,现复制如下。它与 `" -"Basic MNIST Example `_中的网络相同。" +"CNN 的代码可在 :code:`quickstart-pytorch.mnist` 下找到,现复制如下。它与 `Basic MNIST " +"Example `_中的网络相同。" #: ../../source/example-walkthrough-pytorch-mnist.rst:290 msgid "" -"The second thing to notice is that :code:`PytorchMNISTClient` class inherits " -"from the :code:`fl.client.Client`, and hence it must implement the following " -"methods:" +"The second thing to notice is that :code:`PytorchMNISTClient` class " +"inherits from the :code:`fl.client.Client`, and hence it must implement " +"the following methods:" msgstr "" -"第二件要注意的事是 :code:`PytorchMNISTClient` 类继承自 :code:`fl.client." -"Client`,因此它必须实现以下方法:" +"第二件要注意的事是 :code:`PytorchMNISTClient` 类继承自 " +":code:`fl.client.Client`,因此它必须实现以下方法:" #: ../../source/example-walkthrough-pytorch-mnist.rst:315 msgid "" -"When comparing the abstract class to its derived class :code:" -"`PytorchMNISTClient` you will notice that :code:`fit` calls a :code:`train` " -"function and that :code:`evaluate` calls a :code:`test`: function." +"When comparing the abstract class to its derived class " +":code:`PytorchMNISTClient` you will notice that :code:`fit` calls a " +":code:`train` function and that :code:`evaluate` calls a :code:`test`: " +"function." msgstr "" -"将抽象类与其派生类 :code:`PytorchMNISTClient` 进行比较时,您会发现 :code:" -"`fit` 调用了一个 :code:`train` 函数,而 :code:`evaluate` 则调用了一个 :code:" -"`test`: 函数。" +"将抽象类与其派生类 :code:`PytorchMNISTClient` 进行比较时,您会发现 :code:`fit` 调用了一个 " +":code:`train` 函数,而 :code:`evaluate` 则调用了一个 :code:`test`: 函数。" #: ../../source/example-walkthrough-pytorch-mnist.rst:317 msgid "" -"These functions can both be found inside the same :code:`quickstart-pytorch." -"mnist` module:" +"These functions can both be found inside the same :code:`quickstart-" +"pytorch.mnist` module:" msgstr "这些函数都可以在同一个 :code:`quickstart-pytorch.mnist` 模块中找到:" #: ../../source/example-walkthrough-pytorch-mnist.rst:437 msgid "" -"Observe that these functions encapsulate regular training and test loops and " -"provide :code:`fit` and :code:`evaluate` with final statistics for each " -"round. You could substitute them with your custom train and test loops and " -"change the network architecture, and the entire example would still work " -"flawlessly. As a matter of fact, why not try and modify the code to an " -"example of your liking?" +"Observe that these functions encapsulate regular training and test loops " +"and provide :code:`fit` and :code:`evaluate` with final statistics for " +"each round. You could substitute them with your custom train and test " +"loops and change the network architecture, and the entire example would " +"still work flawlessly. As a matter of fact, why not try and modify the " +"code to an example of your liking?" msgstr "" -"请注意,这些函数封装了常规的训练和测试循环,并为 :code:`fit` 和 :code:" -"`evaluate` 提供了每轮的最终统计数据。您可以用自定义的训练和测试循环来替代它" -"们,并改变网络结构,整个示例仍然可以完美运行。事实上,为什么不按照自己的喜好" -"修改代码呢?" +"请注意,这些函数封装了常规的训练和测试循环,并为 :code:`fit` 和 :code:`evaluate` " +"提供了每轮的最终统计数据。您可以用自定义的训练和测试循环来替代它们,并改变网络结构,整个示例仍然可以完美运行。事实上,为什么不按照自己的喜好修改代码呢?" #: ../../source/example-walkthrough-pytorch-mnist.rst:444 msgid "Give It a Try" @@ -3283,14 +3531,15 @@ msgstr "试试看" #: ../../source/example-walkthrough-pytorch-mnist.rst:445 msgid "" -"Looking through the quickstart code description above will have given a good " -"understanding of how *clients* and *servers* work in Flower, how to run a " -"simple experiment, and the internals of a client wrapper. Here are a few " -"things you could try on your own and get more experience with Flower:" +"Looking through the quickstart code description above will have given a " +"good understanding of how *clients* and *servers* work in Flower, how to " +"run a simple experiment, and the internals of a client wrapper. Here are " +"a few things you could try on your own and get more experience with " +"Flower:" msgstr "" -"通过上面的快速入门代码描述,你将对 Flower 中*客户端*和*服务器*的工作方式、如" -"何运行一个简单的实验以及客户端封装器的内部结构有一个很好的了解。您可以自己尝" -"试以下内容,以获得更多使用 Flower 的经验:" +"通过上面的快速入门代码描述,你将对 Flower " +"中*客户端*和*服务器*的工作方式、如何运行一个简单的实验以及客户端封装器的内部结构有一个很好的了解。您可以自己尝试以下内容,以获得更多使用 " +"Flower 的经验:" #: ../../source/example-walkthrough-pytorch-mnist.rst:448 msgid "" @@ -3299,23 +3548,20 @@ msgid "" msgstr "尝试修改 :code:`PytorchMNISTClient`,使其可以接受不同的架构。" #: ../../source/example-walkthrough-pytorch-mnist.rst:449 -msgid "" -"Modify the :code:`train` function so that it accepts different optimizers" +msgid "Modify the :code:`train` function so that it accepts different optimizers" msgstr "修改 :code:`train` 函数,使其接受不同的优化器" #: ../../source/example-walkthrough-pytorch-mnist.rst:450 msgid "" "Modify the :code:`test` function so that it proves not only the top-1 " "(regular accuracy) but also the top-5 accuracy?" -msgstr "修改 :code:`test` 函数,使其不仅能输出前 1 名(常规精确度),还能证明前 5 " -"名的精确度?" +msgstr "修改 :code:`test` 函数,使其不仅能输出前 1 名(常规精确度),还能证明前 5 名的精确度?" #: ../../source/example-walkthrough-pytorch-mnist.rst:451 msgid "" -"Go larger! Try to adapt the code to larger images and datasets. Why not try " -"training on ImageNet with a ResNet-50?" -msgstr "让我们尝试让代码适应更大的图像和数据集。为什么不尝试使用 ResNet-50 在 " -"ImageNet 上进行训练呢?" +"Go larger! Try to adapt the code to larger images and datasets. Why not " +"try training on ImageNet with a ResNet-50?" +msgstr "让我们尝试让代码适应更大的图像和数据集。为什么不尝试使用 ResNet-50 在 ImageNet 上进行训练呢?" #: ../../source/example-walkthrough-pytorch-mnist.rst:453 msgid "You are ready now. Enjoy learning in a federated way!" @@ -3328,29 +3574,26 @@ msgstr "差别隐私" #: ../../source/explanation-differential-privacy.rst:4 msgid "" "Flower provides differential privacy (DP) wrapper classes for the easy " -"integration of the central DP guarantees provided by DP-FedAvg into training " -"pipelines defined in any of the various ML frameworks that Flower is " -"compatible with." +"integration of the central DP guarantees provided by DP-FedAvg into " +"training pipelines defined in any of the various ML frameworks that " +"Flower is compatible with." msgstr "" -"Flower 提供了差分隐私 (DP) 封装类,可将 DP-FedAvg 提供的核心 DP 轻松集成到 " -"Flower 兼容的各种 ML 框架中定义的训练模式中。" +"Flower 提供了差分隐私 (DP) 封装类,可将 DP-FedAvg 提供的核心 DP 轻松集成到 Flower 兼容的各种 ML " +"框架中定义的训练模式中。" #: ../../source/explanation-differential-privacy.rst:7 +#, fuzzy msgid "" -"Please note that these components are still experimental, the correct " +"Please note that these components are still experimental; the correct " "configuration of DP for a specific task is still an unsolved problem." -msgstr "" -"请注意,这些组件仍处于试验阶段,如何为特定任务正确配置 DP 仍是一个尚未解决的" -"问题。" +msgstr "请注意,这些组件仍处于试验阶段,如何为特定任务正确配置 DP 仍是一个尚未解决的问题。" #: ../../source/explanation-differential-privacy.rst:10 msgid "" -"The name DP-FedAvg is misleading since it can be applied on top of any FL " -"algorithm that conforms to the general structure prescribed by the FedOpt " -"family of algorithms." -msgstr "" -"DP-FedAvg 这个名称容易引起误解,因为它可以应用于任何符合 FedOpt 系列算法规定" -"的一般结构的 FL 算法之上。" +"The name DP-FedAvg is misleading since it can be applied on top of any FL" +" algorithm that conforms to the general structure prescribed by the " +"FedOpt family of algorithms." +msgstr "DP-FedAvg 这个名称容易引起误解,因为它可以应用于任何符合 FedOpt 系列算法规定的一般结构的 FL 算法之上。" #: ../../source/explanation-differential-privacy.rst:13 msgid "DP-FedAvg" @@ -3358,83 +3601,79 @@ msgstr "DP-FedAvg" #: ../../source/explanation-differential-privacy.rst:15 msgid "" -"DP-FedAvg, originally proposed by McMahan et al. [mcmahan]_ and extended by " -"Andrew et al. [andrew]_, is essentially FedAvg with the following " +"DP-FedAvg, originally proposed by McMahan et al. [mcmahan]_ and extended " +"by Andrew et al. [andrew]_, is essentially FedAvg with the following " "modifications." msgstr "DP-FedAvg 最初由McMahan等人提出,并由Andrew等人加以扩展。" #: ../../source/explanation-differential-privacy.rst:17 msgid "" -"**Clipping** : The influence of each client's update is bounded by clipping " -"it. This is achieved by enforcing a cap on the L2 norm of the update, " -"scaling it down if needed." -msgstr "**裁剪** : 裁剪会影响到每个客户端的模型参数。具体做法是对参数的 L2 " -"准则设置上限,必要时将其缩减。" +"**Clipping** : The influence of each client's update is bounded by " +"clipping it. This is achieved by enforcing a cap on the L2 norm of the " +"update, scaling it down if needed." +msgstr "**裁剪** : 裁剪会影响到每个客户端的模型参数。具体做法是对参数的 L2 准则设置上限,必要时将其缩减。" #: ../../source/explanation-differential-privacy.rst:18 msgid "" "**Noising** : Gaussian noise, calibrated to the clipping threshold, is " "added to the average computed at the server." -msgstr "**噪声** : " -"在服务器计算出的平均值中加入高斯噪声,该噪声根据剪切阈值进行校准。" +msgstr "**噪声** : 在服务器计算出的平均值中加入高斯噪声,该噪声根据剪切阈值进行校准。" #: ../../source/explanation-differential-privacy.rst:20 +#, fuzzy msgid "" -"The distribution of the update norm has been shown to vary from task-to-task " -"and to evolve as training progresses. Therefore, we use an adaptive approach " -"[andrew]_ that continuously adjusts the clipping threshold to track a " -"prespecified quantile of the update norm distribution." -msgstr "" -"事实证明,参数更新准则的分布会随着任务的不同而变化,并随着训练的进展而演变。" -"因此,我们采用了一种自适应方法,该方法会不断调整剪切阈值,以跟踪参数更新准则" -"分布的预设量化值。" +"The distribution of the update norm has been shown to vary from task-to-" +"task and to evolve as training progresses. This variability is crucial in" +" understanding its impact on differential privacy guarantees, emphasizing" +" the need for an adaptive approach [andrew]_ that continuously adjusts " +"the clipping threshold to track a prespecified quantile of the update " +"norm distribution." +msgstr "事实证明,参数更新准则的分布会随着任务的不同而变化,并随着训练的进展而演变。因此,我们采用了一种自适应方法,该方法会不断调整剪切阈值,以跟踪参数更新准则分布的预设量化值。" #: ../../source/explanation-differential-privacy.rst:23 msgid "Simplifying Assumptions" msgstr "简化假设" #: ../../source/explanation-differential-privacy.rst:25 +#, fuzzy msgid "" "We make (and attempt to enforce) a number of assumptions that must be " -"satisfied to ensure that the training process actually realises the :math:" -"`(\\epsilon, \\delta)` guarantees the user has in mind when configuring the " -"setup." +"satisfied to ensure that the training process actually realizes the " +":math:`(\\epsilon, \\delta)` guarantees the user has in mind when " +"configuring the setup." msgstr "" -"我们提出(并试图执行)了一系列必须满足的假设," -"以确保训练过程真正实现用户在配置设置时所定的 :math:`(\\epsilon,\\delta)` 。" +"我们提出(并试图执行)了一系列必须满足的假设,以确保训练过程真正实现用户在配置设置时所定的 :math:`(\\epsilon,\\delta)`" +" 。" #: ../../source/explanation-differential-privacy.rst:27 msgid "" "**Fixed-size subsampling** :Fixed-size subsamples of the clients must be " "taken at each round, as opposed to variable-sized Poisson subsamples." -msgstr "** 固定大小的子样本** " -":与可变大小的泊松分布子样本相比,每轮必须抽取固定大小的客户端子样本。" +msgstr "** 固定大小的子样本** :与可变大小的泊松分布子样本相比,每轮必须抽取固定大小的客户端子样本。" #: ../../source/explanation-differential-privacy.rst:28 msgid "" "**Unweighted averaging** : The contributions from all the clients must " "weighted equally in the aggregate to eliminate the requirement for the " -"server to know in advance the sum of the weights of all clients available " -"for selection." -msgstr "**非加权平均**: " -"所有客户端的贡献必须加权相等,这样服务器就不需要事先知道所有客户的权重总和。" +"server to know in advance the sum of the weights of all clients available" +" for selection." +msgstr "**非加权平均**: 所有客户端的贡献必须加权相等,这样服务器就不需要事先知道所有客户的权重总和。" #: ../../source/explanation-differential-privacy.rst:29 msgid "" "**No client failures** : The set of available clients must stay constant " -"across all rounds of training. In other words, clients cannot drop out or " -"fail." -msgstr "**没有失败的客户端** : " -"在各轮训练中,可用客户端的数量必须保持不变。换句话说,客户端不能退出或失败。" +"across all rounds of training. In other words, clients cannot drop out or" +" fail." +msgstr "**没有失败的客户端** : 在各轮训练中,可用客户端的数量必须保持不变。换句话说,客户端不能退出或失败。" #: ../../source/explanation-differential-privacy.rst:31 +#, fuzzy msgid "" "The first two are useful for eliminating a multitude of complications " -"associated with calibrating the noise to the clipping threshold while the " -"third one is required to comply with the assumptions of the privacy analysis." -msgstr "" -"前两种方法有助于消除将噪声校准为削波阈值所带来的诸多复杂问题,而第三种方法则" -"需要符合隐私分析的假设。" +"associated with calibrating the noise to the clipping threshold, while " +"the third one is required to comply with the assumptions of the privacy " +"analysis." +msgstr "前两种方法有助于消除将噪声校准为削波阈值所带来的诸多复杂问题,而第三种方法则需要符合隐私分析的假设。" #: ../../source/explanation-differential-privacy.rst:34 msgid "" @@ -3449,29 +3688,25 @@ msgstr "可定制的噪声注入" #: ../../source/explanation-differential-privacy.rst:38 msgid "" "In contrast to other implementations where the addition of noise is " -"performed at the server, you can configure the site of noise injection to " -"better match your threat model. We provide users with the flexibility to set " -"up the training such that each client independently adds a small amount of " -"noise to the clipped update, with the result that simply aggregating the " -"noisy updates is equivalent to the explicit addition of noise to the non-" -"noisy aggregate at the server." -msgstr "" -"与其他在服务器上添加噪声的实现方法不同,您可以配置噪声注入的位置,以便更好地" -"匹配您的威胁模型。我们为用户提供了设置训练的灵活性,使每个客户端都能独立地为" -"剪切参数更新添加少量噪声,这样,只需聚合噪声更新,就相当于在服务器上为非噪声" -"聚合添加噪声了。" +"performed at the server, you can configure the site of noise injection to" +" better match your threat model. We provide users with the flexibility to" +" set up the training such that each client independently adds a small " +"amount of noise to the clipped update, with the result that simply " +"aggregating the noisy updates is equivalent to the explicit addition of " +"noise to the non-noisy aggregate at the server." +msgstr "与其他在服务器上添加噪声的实现方法不同,您可以配置噪声注入的位置,以便更好地匹配您的威胁模型。我们为用户提供了设置训练的灵活性,使每个客户端都能独立地为剪切参数更新添加少量噪声,这样,只需聚合噪声更新,就相当于在服务器上为非噪声聚合添加噪声了。" #: ../../source/explanation-differential-privacy.rst:41 msgid "" "To be precise, if we let :math:`m` be the number of clients sampled each " -"round and :math:`\\sigma_\\Delta` be the scale of the total Gaussian noise " -"that needs to be added to the sum of the model updates, we can use simple " -"maths to show that this is equivalent to each client adding noise with " -"scale :math:`\\sigma_\\Delta/\\sqrt{m}`." +"round and :math:`\\sigma_\\Delta` be the scale of the total Gaussian " +"noise that needs to be added to the sum of the model updates, we can use " +"simple maths to show that this is equivalent to each client adding noise " +"with scale :math:`\\sigma_\\Delta/\\sqrt{m}`." msgstr "" -"准确地说,我们假设每轮采样的客户端数量为:math:`m`,:math:`\\sigma_\\Delta` 为" -"需要添加到模型更新总和中的总高斯噪声的规模,我们就可以用简单的数学方法证明了" -",这相当于每个客户端都添加了规模为 :math:`\\sigma_\\Delta/\\sqrt{m}` 的噪声。" +"准确地说,我们假设每轮采样的客户端数量为:math:`m`,:math:`\\sigma_\\Delta` " +"为需要添加到模型更新总和中的总高斯噪声的规模,我们就可以用简单的数学方法证明了,这相当于每个客户端都添加了规模为 " +":math:`\\sigma_\\Delta/\\sqrt{m}` 的噪声。" #: ../../source/explanation-differential-privacy.rst:44 msgid "Wrapper-based approach" @@ -3479,169 +3714,160 @@ msgstr "基于封装的方法" #: ../../source/explanation-differential-privacy.rst:46 msgid "" -"Introducing DP to an existing workload can be thought of as adding an extra " -"layer of security around it. This inspired us to provide the additional " -"server and client-side logic needed to make the training process " -"differentially private as wrappers for instances of the :code:`Strategy` " -"and :code:`NumPyClient` abstract classes respectively. This wrapper-based " -"approach has the advantage of being easily composable with other wrappers " -"that someone might contribute to the Flower library in the future, e.g., for " -"secure aggregation. Using Inheritance instead can be tedious because that " -"would require the creation of new sub- classes every time a new class " -"implementing :code:`Strategy` or :code:`NumPyClient` is defined." -msgstr "" -"在现有工作负载中引入 DP 可以被认为是在其周围增加了一层额外的安全性。受此启发" -",我们提供了额外的服务器端和客户端逻辑,分别作为 :code:`Strategy` 和 " -":code:`NumPyClient` 抽象类实例的封装器,使训练过程具有不同的隐私性。" -"这种基于封装器的方法的优点是可以很容易地与将来有人贡献给 Flower " -"的其他封装器(例如用于安全聚合的封装器)进行组合。使用继承可能会比较繁琐," -"因为每次定义实现 :code:`Strategy` 或 :code:`NumPyClient` " -"的新类时,都需要创建新的子类。" +"Introducing DP to an existing workload can be thought of as adding an " +"extra layer of security around it. This inspired us to provide the " +"additional server and client-side logic needed to make the training " +"process differentially private as wrappers for instances of the " +":code:`Strategy` and :code:`NumPyClient` abstract classes respectively. " +"This wrapper-based approach has the advantage of being easily composable " +"with other wrappers that someone might contribute to the Flower library " +"in the future, e.g., for secure aggregation. Using Inheritance instead " +"can be tedious because that would require the creation of new sub- " +"classes every time a new class implementing :code:`Strategy` or " +":code:`NumPyClient` is defined." +msgstr "" +"在现有工作负载中引入 DP 可以被认为是在其周围增加了一层额外的安全性。受此启发,我们提供了额外的服务器端和客户端逻辑,分别作为 " +":code:`Strategy` 和 :code:`NumPyClient` " +"抽象类实例的封装器,使训练过程具有不同的隐私性。这种基于封装器的方法的优点是可以很容易地与将来有人贡献给 Flower " +"的其他封装器(例如用于安全聚合的封装器)进行组合。使用继承可能会比较繁琐,因为每次定义实现 :code:`Strategy` 或 " +":code:`NumPyClient` 的新类时,都需要创建新的子类。" #: ../../source/explanation-differential-privacy.rst:49 msgid "Server-side logic" msgstr "服务器端逻辑" #: ../../source/explanation-differential-privacy.rst:51 +#, fuzzy msgid "" "The first version of our solution was to define a decorator whose " -"constructor accepted, among other things, a boolean valued variable " -"indicating whether adaptive clipping was to be enabled or not. We quickly " -"realized that this would clutter its :code:`__init__()` function with " -"variables corresponding to hyperparameters of adaptive clipping that would " -"remain unused when it was disabled. A cleaner implementation could be " -"achieved by splitting the functionality into two decorators, :code:" -"`DPFedAvgFixed` and :code:`DPFedAvgAdaptive`, with the latter sub- classing " -"the former. The constructors for both classes accept a boolean parameter :" -"code:`server_side_noising`, which, as the name suggests, determines where " -"noising is to be performed." -msgstr "" -"我们的第一版解决方案是定义一个装饰器,其构造函数接受一个布尔值变量,表示是否" -"启用自适应剪裁。我们很快意识到,这样会使其 :code:`__init__()` 函数中与自适应" -"裁剪超参数相对应的变量变得杂乱无章,而这些变量在自适应裁剪被禁用时将保持未使" -"用状态。要实现更简洁的功能,可以将该功能拆分为两个装饰器,即 " -":code:`DPFedAvgFixed` 和 :code:`DPFedAvgAdaptive`,后者是前者的子类。" -"这两个类的构造函数都接受一个布尔参数 " +"constructor accepted, among other things, a boolean-valued variable " +"indicating whether adaptive clipping was to be enabled or not. We quickly" +" realized that this would clutter its :code:`__init__()` function with " +"variables corresponding to hyperparameters of adaptive clipping that " +"would remain unused when it was disabled. A cleaner implementation could " +"be achieved by splitting the functionality into two decorators, " +":code:`DPFedAvgFixed` and :code:`DPFedAvgAdaptive`, with the latter sub- " +"classing the former. The constructors for both classes accept a boolean " +"parameter :code:`server_side_noising`, which, as the name suggests, " +"determines where noising is to be performed." +msgstr "" +"我们的第一版解决方案是定义一个装饰器,其构造函数接受一个布尔值变量,表示是否启用自适应剪裁。我们很快意识到,这样会使其 " +":code:`__init__()` " +"函数中与自适应裁剪超参数相对应的变量变得杂乱无章,而这些变量在自适应裁剪被禁用时将保持未使用状态。要实现更简洁的功能,可以将该功能拆分为两个装饰器,即" +" :code:`DPFedAvgFixed` 和 " +":code:`DPFedAvgAdaptive`,后者是前者的子类。这两个类的构造函数都接受一个布尔参数 " ":code:`server_side_noising`,顾名思义,它决定了在哪里加噪声。" #: ../../source/explanation-differential-privacy.rst:54 +#: ../../source/ref-api/flwr.server.strategy.DPFedAvgFixed.rst:2 msgid "DPFedAvgFixed" msgstr "DPFedAvgFixed" #: ../../source/explanation-differential-privacy.rst:56 msgid "" -"The server-side capabilities required for the original version of DP-FedAvg, " -"i.e., the one which performed fixed clipping, can be completely captured " -"with the help of wrapper logic for just the following two methods of the :" -"code:`Strategy` abstract class." +"The server-side capabilities required for the original version of DP-" +"FedAvg, i.e., the one which performed fixed clipping, can be completely " +"captured with the help of wrapper logic for just the following two " +"methods of the :code:`Strategy` abstract class." msgstr "" "只需对 :code:`Strategy` 抽象类的以下两个方法进行封装,就能完全捕获 DP-FedAvg " "原始版本(即执行固定剪裁的版本)所需的服务器端功能。" #: ../../source/explanation-differential-privacy.rst:58 msgid "" -":code:`configure_fit()` : The config dictionary being sent by the wrapped :" -"code:`Strategy` to each client needs to be augmented with an additional " -"value equal to the clipping threshold (keyed under :code:" -"`dpfedavg_clip_norm`) and, if :code:`server_side_noising=true`, another one " -"equal to the scale of the Gaussian noise that needs to be added at the " -"client (keyed under :code:`dpfedavg_noise_stddev`). This entails *post*-" -"processing of the results returned by the wrappee's implementation of :code:" -"`configure_fit()`." +":code:`configure_fit()` : The config dictionary being sent by the wrapped" +" :code:`Strategy` to each client needs to be augmented with an additional" +" value equal to the clipping threshold (keyed under " +":code:`dpfedavg_clip_norm`) and, if :code:`server_side_noising=true`, " +"another one equal to the scale of the Gaussian noise that needs to be " +"added at the client (keyed under :code:`dpfedavg_noise_stddev`). This " +"entails *post*-processing of the results returned by the wrappee's " +"implementation of :code:`configure_fit()`." msgstr "" ":code:`configure_fit()` :由封装的 :code:`Strategy` " -"发送到每个客户端的配置字典需要使用等于裁剪阈值的附加值(在 " -":code:`dpfedavg_clip_norm` 下键入)进行扩充。并且,如果 " -"server_side_noising=true,则另一个值等于需要在客户端添加的高斯噪声的大小(在 " -"dpfedavg_noise_stddev 下键入)。这需要对封装后的configure_fit() " -"所返回的结果进行后处理。" +"发送到每个客户端的配置字典需要使用等于裁剪阈值的附加值(在 :code:`dpfedavg_clip_norm` 下键入)进行扩充。并且,如果 " +"server_side_noising=true,则另一个值等于需要在客户端添加的高斯噪声的大小(在 dpfedavg_noise_stddev " +"下键入)。这需要对封装后的configure_fit() 所返回的结果进行后处理。" #: ../../source/explanation-differential-privacy.rst:59 -msgid "" -":code:`aggregate_fit()`: We check whether any of the sampled clients dropped " -"out or failed to upload an update before the round timed out. In that case, " -"we need to abort the current round, discarding any successful updates that " -"were received, and move on to the next one. On the other hand, if all " -"clients responded successfully, we must force the averaging of the updates " -"to happen in an unweighted manner by intercepting the :code:`parameters` " -"field of :code:`FitRes` for each received update and setting it to 1. " -"Furthermore, if :code:`server_side_noising=true`, each update is perturbed " -"with an amount of noise equal to what it would have been subjected to had " -"client-side noising being enabled. This entails *pre*-processing of the " -"arguments to this method before passing them on to the wrappee's " -"implementation of :code:`aggregate_fit()`." -msgstr "" -":code:`aggregate_fit()`: 我们会检查是否有任何客户端在本轮超时前退出或未能上" -"传参数更新。在这种情况下,我们需要中止当前一轮,丢弃已收到的所有参数更新,然" -"后继续下一轮。另一方面,如果所有客户端都成功响应,我们就必须通过拦截 " -":code:`FitRes` 的 :code:`parameters` 字段并将其设置为 " -"1,强制以不加权的方式平均更新。此外,如果 :code:`server_side_noising=true`," -"每次更新都会受到一定量的噪声扰动,其扰动量相当于启用客户端噪声时的扰动量。 " -"这就需要在将本方法的参数传递给封装的 :code:`aggregate_fit()` " -"之前,对参数进行*预*处理。" +#, fuzzy +msgid "" +":code:`aggregate_fit()`: We check whether any of the sampled clients " +"dropped out or failed to upload an update before the round timed out. In " +"that case, we need to abort the current round, discarding any successful " +"updates that were received, and move on to the next one. On the other " +"hand, if all clients responded successfully, we must force the averaging " +"of the updates to happen in an unweighted manner by intercepting the " +":code:`parameters` field of :code:`FitRes` for each received update and " +"setting it to 1. Furthermore, if :code:`server_side_noising=true`, each " +"update is perturbed with an amount of noise equal to what it would have " +"been subjected to had client-side noising being enabled. This entails " +"*pre*-processing of the arguments to this method before passing them on " +"to the wrappee's implementation of :code:`aggregate_fit()`." +msgstr "" +":code:`aggregate_fit()`: " +"我们会检查是否有任何客户端在本轮超时前退出或未能上传参数更新。在这种情况下,我们需要中止当前一轮,丢弃已收到的所有参数更新,然后继续下一轮。另一方面,如果所有客户端都成功响应,我们就必须通过拦截" +" :code:`FitRes` 的 :code:`parameters` 字段并将其设置为 1,强制以不加权的方式平均更新。此外,如果 " +":code:`server_side_noising=true`,每次更新都会受到一定量的噪声扰动,其扰动量相当于启用客户端噪声时的扰动量。 " +"这就需要在将本方法的参数传递给封装的 :code:`aggregate_fit()` 之前,对参数进行*预*处理。" #: ../../source/explanation-differential-privacy.rst:62 msgid "" -"We can't directly change the aggregation function of the wrapped strategy to " -"force it to add noise to the aggregate, hence we simulate client-side " -"noising to implement server-side noising." -msgstr "" -"我们无法直接改变封装策略的聚合函数,迫使它在聚合中添加噪声,因此我们模拟客户" -"端噪声来实现服务器端噪声。" +"We can't directly change the aggregation function of the wrapped strategy" +" to force it to add noise to the aggregate, hence we simulate client-side" +" noising to implement server-side noising." +msgstr "我们无法直接改变封装策略的聚合函数,迫使它在聚合中添加噪声,因此我们模拟客户端噪声来实现服务器端噪声。" #: ../../source/explanation-differential-privacy.rst:64 msgid "" -"These changes have been put together into a class called :code:" -"`DPFedAvgFixed`, whose constructor accepts the strategy being decorated, the " -"clipping threshold and the number of clients sampled every round as " -"compulsory arguments. The user is expected to specify the clipping threshold " -"since the order of magnitude of the update norms is highly dependent on the " -"model being trained and providing a default value would be misleading. The " -"number of clients sampled at every round is required to calculate the amount " -"of noise that must be added to each individual update, either by the server " -"or the clients." -msgstr "" -"这些变化被整合到一个名为 :code:`DPFedAvgFixed` 的类中,其构造函数接受被装饰的" -"策略、剪切阈值和每轮采样的客户数作为必选参数。用户需要指定剪切阈值,因为参数" -"更新规范的数量级在很大程度上取决于正在训练的模型,提供默认值会产生误导。每轮" -"采样的客户端数量是计算服务器或客户在每次参数更新时添加的噪音量所必需的。" +"These changes have been put together into a class called " +":code:`DPFedAvgFixed`, whose constructor accepts the strategy being " +"decorated, the clipping threshold and the number of clients sampled every" +" round as compulsory arguments. The user is expected to specify the " +"clipping threshold since the order of magnitude of the update norms is " +"highly dependent on the model being trained and providing a default value" +" would be misleading. The number of clients sampled at every round is " +"required to calculate the amount of noise that must be added to each " +"individual update, either by the server or the clients." +msgstr "" +"这些变化被整合到一个名为 :code:`DPFedAvgFixed` " +"的类中,其构造函数接受被装饰的策略、剪切阈值和每轮采样的客户数作为必选参数。用户需要指定剪切阈值,因为参数更新规范的数量级在很大程度上取决于正在训练的模型,提供默认值会产生误导。每轮采样的客户端数量是计算服务器或客户在每次参数更新时添加的噪音量所必需的。" #: ../../source/explanation-differential-privacy.rst:67 +#: ../../source/ref-api/flwr.server.strategy.DPFedAvgAdaptive.rst:2 msgid "DPFedAvgAdaptive" msgstr "DPFedAvgAdaptive" #: ../../source/explanation-differential-privacy.rst:69 msgid "" -"The additional functionality required to facilitate adaptive clipping has " -"been provided in :code:`DPFedAvgAdaptive`, a subclass of :code:" -"`DPFedAvgFixed`. It overrides the above-mentioned methods to do the " -"following." +"The additional functionality required to facilitate adaptive clipping has" +" been provided in :code:`DPFedAvgAdaptive`, a subclass of " +":code:`DPFedAvgFixed`. It overrides the above-mentioned methods to do the" +" following." msgstr "" -"自适应剪裁所需的附加功能在 :code:`DPFedAvgAdaptive` 中提供,其是 " -":code:`DPFedAvgFixed` 的子类。它重写了上述方法,以实现以下功能。" +"自适应剪裁所需的附加功能在 :code:`DPFedAvgAdaptive` 中提供,其是 :code:`DPFedAvgFixed` " +"的子类。它重写了上述方法,以实现以下功能。" #: ../../source/explanation-differential-privacy.rst:71 msgid "" -":code:`configure_fit()` : It intercepts the config dict returned by :code:" -"`super.configure_fit()` to add the key-value pair :code:" -"`dpfedavg_adaptive_clip_enabled:True` to it, which the client interprets as " -"an instruction to include an indicator bit (1 if update norm <= clipping " -"threshold, 0 otherwise) in the results returned by it." +":code:`configure_fit()` : It intercepts the config dict returned by " +":code:`super.configure_fit()` to add the key-value pair " +":code:`dpfedavg_adaptive_clip_enabled:True` to it, which the client " +"interprets as an instruction to include an indicator bit (1 if update " +"norm <= clipping threshold, 0 otherwise) in the results returned by it." msgstr "" -":code:`configure_fit()`:它截取由 :code:`super.configure_fit()` 返回的 " -"config 字典,并在其中添加键-值对 :code:`dpfedavg_adaptive_clip_enabled:True\"" -",客户端将其解释为在返回结果中包含一个指示位(如果参数更新范式 <= 剪裁阈值," -"则为 1,否则为 0)的指令。" +":code:`configure_fit()`:它截取由 :code:`super.configure_fit()` 返回的 config " +"字典,并在其中添加键-值对 " +":code:`dpfedavg_adaptive_clip_enabled:True\",客户端将其解释为在返回结果中包含一个指示位(如果参数更新范式" +" <= 剪裁阈值,则为 1,否则为 0)的指令。" #: ../../source/explanation-differential-privacy.rst:73 msgid "" -":code:`aggregate_fit()` : It follows a call to :code:`super.aggregate_fit()` " -"with one to :code:`__update_clip_norm__()`, a procedure which adjusts the " -"clipping threshold on the basis of the indicator bits received from the " -"sampled clients." -msgstr "" -":code:`aggregate_fit()`:在调用:code:`super.aggregate_fit()`后,再调用:code:`" -"__update_clip_norm__()`,该过程根据从采样客户端接收到的指示位调整裁剪阈值。" +":code:`aggregate_fit()` : It follows a call to " +":code:`super.aggregate_fit()` with one to :code:`__update_clip_norm__()`," +" a procedure which adjusts the clipping threshold on the basis of the " +"indicator bits received from the sampled clients." +msgstr ":code:`aggregate_fit()`:在调用:code:`super.aggregate_fit()`后,再调用:code:`__update_clip_norm__()`,该过程根据从采样客户端接收到的指示位调整裁剪阈值。" #: ../../source/explanation-differential-privacy.rst:77 msgid "Client-side logic" @@ -3650,17 +3876,16 @@ msgstr "客户端逻辑" #: ../../source/explanation-differential-privacy.rst:79 msgid "" "The client-side capabilities required can be completely captured through " -"wrapper logic for just the :code:`fit()` method of the :code:`NumPyClient` " -"abstract class. To be precise, we need to *post-process* the update computed " -"by the wrapped client to clip it, if necessary, to the threshold value " -"supplied by the server as part of the config dictionary. In addition to " -"this, it may need to perform some extra work if either (or both) of the " -"following keys are also present in the dict." -msgstr "" -"客户端所需的功能完全可以通过 :code:`NumPyClient` 抽象类的 :code:`fit()` 方法" -"的封装逻辑来实现。准确地说,我们需要对封装客户端计算的参数更新进行处理,以便" -"在必要时将其剪切到服务器作为配置字典的一部分提供的阈值。除此之外,如果配置字" -"典中还存在以下任一(或两个)键,客户端可能还需要执行一些额外的工作。" +"wrapper logic for just the :code:`fit()` method of the " +":code:`NumPyClient` abstract class. To be precise, we need to *post-" +"process* the update computed by the wrapped client to clip it, if " +"necessary, to the threshold value supplied by the server as part of the " +"config dictionary. In addition to this, it may need to perform some extra" +" work if either (or both) of the following keys are also present in the " +"dict." +msgstr "" +"客户端所需的功能完全可以通过 :code:`NumPyClient` 抽象类的 :code:`fit()` " +"方法的封装逻辑来实现。准确地说,我们需要对封装客户端计算的参数更新进行处理,以便在必要时将其剪切到服务器作为配置字典的一部分提供的阈值。除此之外,如果配置字典中还存在以下任一(或两个)键,客户端可能还需要执行一些额外的工作。" #: ../../source/explanation-differential-privacy.rst:81 msgid "" @@ -3670,9 +3895,9 @@ msgstr "code:`dpfedavg_noise_stddev`:生成并在剪切参数更新中添加 #: ../../source/explanation-differential-privacy.rst:82 msgid "" -":code:`dpfedavg_adaptive_clip_enabled` : Augment the metrics dict in the :" -"code:`FitRes` object being returned to the server with an indicator bit, " -"calculated as described earlier." +":code:`dpfedavg_adaptive_clip_enabled` : Augment the metrics dict in the " +":code:`FitRes` object being returned to the server with an indicator bit," +" calculated as described earlier." msgstr "" ":code:`dpfedavg_adaptive_clip_enabled`:在返回给服务器的 :code:`FitRes` " "对象中的度量值字典中增加一个指标位,计算方法如前所述。" @@ -3683,30 +3908,34 @@ msgstr "进行 :math:`(epsilon, \\delta)` 分析" #: ../../source/explanation-differential-privacy.rst:88 msgid "" -"Assume you have trained for :math:`n` rounds with sampling fraction :math:" -"`q` and noise multiplier :math:`z`. In order to calculate the :math:" -"`\\epsilon` value this would result in for a particular :math:`\\delta`, the " -"following script may be used." +"Assume you have trained for :math:`n` rounds with sampling fraction " +":math:`q` and noise multiplier :math:`z`. In order to calculate the " +":math:`\\epsilon` value this would result in for a particular " +":math:`\\delta`, the following script may be used." msgstr "" -"假设您已经训练了 :math:`n` 轮,采样比例为 :math:`q`,噪声乘数为 :math:`z`。" -"为了计算特定 :math:`\\delta` 的 :math:`epsilon` 值,可以使用下面的脚本。" +"假设您已经训练了 :math:`n` 轮,采样比例为 :math:`q`,噪声乘数为 :math:`z`。为了计算特定 " +":math:`\\delta` 的 :math:`epsilon` 值,可以使用下面的脚本。" #: ../../source/explanation-differential-privacy.rst:98 +#, fuzzy msgid "" -"McMahan, H. Brendan, et al. \"Learning differentially private recurrent " -"language models.\" arXiv preprint arXiv:1710.06963 (2017)." +"McMahan et al. \"Learning Differentially Private Recurrent Language " +"Models.\" International Conference on Learning Representations (ICLR), " +"2017." msgstr "" -"McMahan, H. Brendan等. \"Learning differentially private recurrent language " -"models.\" arXiv preprint arXiv:1710.06963 (2017)." +"McMahan, H. Brendan等. \"Learning differentially private recurrent " +"language models.\" arXiv preprint arXiv:1710.06963 (2017)." #: ../../source/explanation-differential-privacy.rst:100 +#, fuzzy msgid "" -"Andrew, Galen, et al. \"Differentially private learning with adaptive " +"Andrew, Galen, et al. \"Differentially Private Learning with Adaptive " +"Clipping.\" Advances in Neural Information Processing Systems (NeurIPS), " +"2021." +msgstr "" +"Andrew, Galen等. \"Differentially private learning with adaptive " "clipping.\" Advances in Neural Information Processing Systems 34 (2021): " "17455-17466." -msgstr "" -"Andrew, Galen等. \"Differentially private learning with adaptive clipping.\" " -"Advances in Neural Information Processing Systems 34 (2021): 17455-17466." #: ../../source/explanation-federated-evaluation.rst:2 #: ../../source/tutorial-series-what-is-federated-learning.ipynb:292 @@ -3716,10 +3945,9 @@ msgstr "联邦学习评估" #: ../../source/explanation-federated-evaluation.rst:4 msgid "" "There are two main approaches to evaluating models in federated learning " -"systems: centralized (or server-side) evaluation and federated (or client-" -"side) evaluation." -msgstr "评估联合学习系统中的模型主要有两种方法:集中(或服务器端)评估和联邦(或客户" -"端)评估。" +"systems: centralized (or server-side) evaluation and federated (or " +"client-side) evaluation." +msgstr "评估联合学习系统中的模型主要有两种方法:集中(或服务器端)评估和联邦(或客户端)评估。" #: ../../source/explanation-federated-evaluation.rst:8 msgid "Centralized Evaluation" @@ -3735,9 +3963,7 @@ msgid "" "evaluation function during initialization. An evaluation function is any " "function that can take the current global model parameters as input and " "return evaluation results:" -msgstr "" -"所有内置策略都通过在初始化过程中提供一个评估函数来支持集中评估。评估函数是任" -"何可以将当前全局模型参数作为输入并返回评估结果的函数:" +msgstr "所有内置策略都通过在初始化过程中提供一个评估函数来支持集中评估。评估函数是任何可以将当前全局模型参数作为输入并返回评估结果的函数:" #: ../../source/explanation-federated-evaluation.rst:58 msgid "Custom Strategies" @@ -3745,14 +3971,14 @@ msgstr "定制策略" #: ../../source/explanation-federated-evaluation.rst:60 msgid "" -"The :code:`Strategy` abstraction provides a method called :code:`evaluate` " -"that can directly be used to evaluate the current global model parameters. " -"The current server implementation calls :code:`evaluate` after parameter " -"aggregation and before federated evaluation (see next paragraph)." +"The :code:`Strategy` abstraction provides a method called " +":code:`evaluate` that can directly be used to evaluate the current global" +" model parameters. The current server implementation calls " +":code:`evaluate` after parameter aggregation and before federated " +"evaluation (see next paragraph)." msgstr "" ":code:`Strategy` 抽象提供了一个名为 :code:`evaluate` " -"的方法,可直接用于评估当前的全局模型参数。" -"服务器会在参数聚合后和联邦评估前调用 :code:`evaluate`(见下段)。" +"的方法,可直接用于评估当前的全局模型参数。服务器会在参数聚合后和联邦评估前调用 :code:`evaluate`(见下段)。" #: ../../source/explanation-federated-evaluation.rst:65 msgid "Federated Evaluation" @@ -3764,10 +3990,9 @@ msgstr "实现联邦评估" #: ../../source/explanation-federated-evaluation.rst:70 msgid "" -"Client-side evaluation happens in the :code:`Client.evaluate` method and can " -"be configured from the server side." -msgstr "" -"客户端评估在 :code:`Client.evaluate` 方法中进行,并可从服务器端进行配置。" +"Client-side evaluation happens in the :code:`Client.evaluate` method and " +"can be configured from the server side." +msgstr "客户端评估在 :code:`Client.evaluate` 方法中进行,并可从服务器端进行配置。" #: ../../source/explanation-federated-evaluation.rst:101 msgid "Configuring Federated Evaluation" @@ -3781,56 +4006,51 @@ msgstr "联邦评估可从服务器端进行配置。内置策略支持以下参 #: ../../source/explanation-federated-evaluation.rst:105 msgid "" -":code:`fraction_evaluate`: a :code:`float` defining the fraction of clients " -"that will be selected for evaluation. If :code:`fraction_evaluate` is set " -"to :code:`0.1` and :code:`100` clients are connected to the server, then :" -"code:`10` will be randomly selected for evaluation. If :code:" -"`fraction_evaluate` is set to :code:`0.0`, federated evaluation will be " -"disabled." +":code:`fraction_evaluate`: a :code:`float` defining the fraction of " +"clients that will be selected for evaluation. If " +":code:`fraction_evaluate` is set to :code:`0.1` and :code:`100` clients " +"are connected to the server, then :code:`10` will be randomly selected " +"for evaluation. If :code:`fraction_evaluate` is set to :code:`0.0`, " +"federated evaluation will be disabled." msgstr "" -":code:`fraction_evaluate`: " -":code:`float`,定义了被选中进行评估的客户端的比例。如果 " -":code:`fraction_evaluate` 设置为 :code:`0.1`,并且 :code:`100` " -"个客户端连接到服务器,那么 :code:`10` 个客户端将被随机选中进行评估。如果 " -":code:`fraction_evaluate` 设置为 :code:`0.0`,联邦评估将被禁用。" +":code:`fraction_evaluate`: :code:`float`,定义了被选中进行评估的客户端的比例。如果 " +":code:`fraction_evaluate` 设置为 :code:`0.1`,并且 :code:`100` 个客户端连接到服务器,那么 " +":code:`10` 个客户端将被随机选中进行评估。如果 :code:`fraction_evaluate` 设置为 " +":code:`0.0`,联邦评估将被禁用。" #: ../../source/explanation-federated-evaluation.rst:106 msgid "" -":code:`min_evaluate_clients`: an :code:`int`: the minimum number of clients " -"to be selected for evaluation. If :code:`fraction_evaluate` is set to :code:" -"`0.1`, :code:`min_evaluate_clients` is set to 20, and :code:`100` clients " -"are connected to the server, then :code:`20` clients will be selected for " -"evaluation." +":code:`min_evaluate_clients`: an :code:`int`: the minimum number of " +"clients to be selected for evaluation. If :code:`fraction_evaluate` is " +"set to :code:`0.1`, :code:`min_evaluate_clients` is set to 20, and " +":code:`100` clients are connected to the server, then :code:`20` clients " +"will be selected for evaluation." msgstr "" -":code:`min_evaluate_clients`:一个 :code:`int`,需要评估的客户的最小数量。" -"如果 :code:`fraction_evaluate` 设置为 :code:`0." -"1`,:code:`min_evaluate_clients` 设置为 20,并且有 :code:`100` " -"个客户端已连接到服务器,那么 :code:`20` 个客户端将被选中进行评估。" +":code:`min_evaluate_clients`:一个 :code:`int`,需要评估的客户的最小数量。如果 " +":code:`fraction_evaluate` 设置为 :code:`0.1`,:code:`min_evaluate_clients` " +"设置为 20,并且有 :code:`100` 个客户端已连接到服务器,那么 :code:`20` 个客户端将被选中进行评估。" #: ../../source/explanation-federated-evaluation.rst:107 msgid "" ":code:`min_available_clients`: an :code:`int` that defines the minimum " -"number of clients which need to be connected to the server before a round of " -"federated evaluation can start. If fewer than :code:`min_available_clients` " -"are connected to the server, the server will wait until more clients are " -"connected before it continues to sample clients for evaluation." +"number of clients which need to be connected to the server before a round" +" of federated evaluation can start. If fewer than " +":code:`min_available_clients` are connected to the server, the server " +"will wait until more clients are connected before it continues to sample " +"clients for evaluation." msgstr "" ":code:`min_available_clients`: " -":code:`int`,定义了在一轮联邦评估开始之前,需要连接到服务器的最小客户端数量。" -"如果连接到服务器的客户端数量少于 :code:`min_available_clients`,服务器将等待" -"更多客户端连接后,才继续采样客户端进行评估。" +":code:`int`,定义了在一轮联邦评估开始之前,需要连接到服务器的最小客户端数量。如果连接到服务器的客户端数量少于 " +":code:`min_available_clients`,服务器将等待更多客户端连接后,才继续采样客户端进行评估。" #: ../../source/explanation-federated-evaluation.rst:108 msgid "" ":code:`on_evaluate_config_fn`: a function that returns a configuration " -"dictionary which will be sent to the selected clients. The function will be " -"called during each round and provides a convenient way to customize client-" -"side evaluation from the server side, for example, to configure the number " -"of validation steps performed." -msgstr "" -"code:`on_evaluate_config_fn`:返回配置字典的函数,该字典将发送给选定的客户" -"端。该函数将在每一轮中被调用,并提供了一种方便的方法来从服务器端自定义客户端" -"评估,例如,配置执行的验证步骤数。" +"dictionary which will be sent to the selected clients. The function will " +"be called during each round and provides a convenient way to customize " +"client-side evaluation from the server side, for example, to configure " +"the number of validation steps performed." +msgstr "code:`on_evaluate_config_fn`:返回配置字典的函数,该字典将发送给选定的客户端。该函数将在每一轮中被调用,并提供了一种方便的方法来从服务器端自定义客户端评估,例如,配置执行的验证步骤数。" #: ../../source/explanation-federated-evaluation.rst:135 msgid "Evaluating Local Model Updates During Training" @@ -3838,11 +4058,10 @@ msgstr "评估训练期间的本地模型更新" #: ../../source/explanation-federated-evaluation.rst:137 msgid "" -"Model parameters can also be evaluated during training. :code:`Client.fit` " -"can return arbitrary evaluation results as a dictionary:" -msgstr "" -"模型参数也可在训练过程中进行评估。 :code:`Client.fit`可以字典形式返回任意评估" -"结果:" +"Model parameters can also be evaluated during training. " +":code:`Client.fit` can return arbitrary evaluation results as a " +"dictionary:" +msgstr "模型参数也可在训练过程中进行评估。 :code:`Client.fit`可以字典形式返回任意评估结果:" #: ../../source/explanation-federated-evaluation.rst:177 msgid "Full Code Example" @@ -3850,14 +4069,14 @@ msgstr "完整代码示例" #: ../../source/explanation-federated-evaluation.rst:179 msgid "" -"For a full code example that uses both centralized and federated evaluation, " -"see the *Advanced TensorFlow Example* (the same approach can be applied to " -"workloads implemented in any other framework): https://github.com/adap/" -"flower/tree/main/examples/advanced-tensorflow" +"For a full code example that uses both centralized and federated " +"evaluation, see the *Advanced TensorFlow Example* (the same approach can " +"be applied to workloads implemented in any other framework): " +"https://github.com/adap/flower/tree/main/examples/advanced-tensorflow" msgstr "" "有关同时使用集中评估和联邦评估的完整代码示例,请参阅 *Advanced TensorFlow " -"Example*(同样的方法也可应用于任何其他框架中): https://github.com/adap/" -"flower/tree/main/examples/advanced-tensorflow" +"Example*(同样的方法也可应用于任何其他框架中): " +"https://github.com/adap/flower/tree/main/examples/advanced-tensorflow" #: ../../source/fed/0000-20200102-fed-template.md:10 msgid "FED Template" @@ -3980,10 +4199,6 @@ msgstr "\\[备选 1\\]" msgid "\\[Alternative 2\\]" msgstr "\\[备选 2\\]" -#: ../../source/fed/0000-20200102-fed-template.md:60 -msgid "Appendix" -msgstr "附录" - #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:10 msgid "Flower Enhancement Doc" msgstr "Flower 改善文档" @@ -4034,11 +4249,10 @@ msgstr "保留 GitHub 问题,用于跟踪进行中的工作" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:37 msgid "" -"ensure community participants can successfully drive changes to completion " -"across one or more releases while stakeholders are adequately represented " -"throughout the process" -msgstr "确保社区参与者能够成功推动改动,完成一个或多个版本,同时利益相关者在整个过程" -"中得到充分展现" +"ensure community participants can successfully drive changes to " +"completion across one or more releases while stakeholders are adequately " +"represented throughout the process" +msgstr "确保社区参与者能够成功推动改动,完成一个或多个版本,同时利益相关者在整个过程中得到充分展现" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:39 msgid "Hence, an Enhancement Doc combines aspects of" @@ -4065,69 +4279,61 @@ msgstr "该文件是与社区合作逐步创建的。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:49 msgid "" "For far-fetching changes or features proposed to Flower, an abstraction " -"beyond a single GitHub issue or pull request is required to understand and " -"communicate upcoming changes to the project." +"beyond a single GitHub issue or pull request is required to understand " +"and communicate upcoming changes to the project." msgstr "" -"对于向 Flower 提出的远期变更或功能,需要一个超越单个 GitHub 问题或拉取请求(" -"pull request)的抽象概念,以了解和沟通项目即将发生的变更。" +"对于向 Flower 提出的远期变更或功能,需要一个超越单个 GitHub 问题或拉取请求(pull " +"request)的抽象概念,以了解和沟通项目即将发生的变更。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:51 msgid "" -"The purpose of this process is to reduce the amount of \"tribal knowledge\" " -"in our community. By moving decisions from Slack threads, video calls, and " -"hallway conversations into a well-tracked artifact, this process aims to " -"enhance communication and discoverability." +"The purpose of this process is to reduce the amount of \"tribal " +"knowledge\" in our community. By moving decisions from Slack threads, " +"video calls, and hallway conversations into a well-tracked artifact, this" +" process aims to enhance communication and discoverability." msgstr "" -"这一流程的目的是减少我们社区中 \"部落知识 \"的数量。通过将决策从 Slack 线程、" -"视频通话和走廊对话转移到一个跟踪良好的工作环境中,该流程旨在加强沟通和可发现" -"性。" +"这一流程的目的是减少我们社区中 \"部落知识 \"的数量。通过将决策从 Slack " +"线程、视频通话和走廊对话转移到一个跟踪良好的工作环境中,该流程旨在加强沟通和可发现性。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:55 msgid "" -"Roughly any larger, user-facing enhancement should follow the Enhancement " -"process. If an enhancement would be described in either written or verbal " -"communication to anyone besides the author or developer, then consider " -"creating an Enhancement Doc." -msgstr "任何较大的、面向用户的增强都应遵循增强流程。如果要以书面或口头形式向作者或开" -"发人员以外的任何人描述增强功能,则应考虑创建改善文档。" +"Roughly any larger, user-facing enhancement should follow the Enhancement" +" process. If an enhancement would be described in either written or " +"verbal communication to anyone besides the author or developer, then " +"consider creating an Enhancement Doc." +msgstr "任何较大的、面向用户的增强都应遵循增强流程。如果要以书面或口头形式向作者或开发人员以外的任何人描述增强功能,则应考虑创建改善文档。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:57 msgid "" -"Similarly, any technical effort (refactoring, major architectural change) " -"that will impact a large section of the development community should also be " -"communicated widely. The Enhancement process is suited for this even if it " -"will have zero impact on the typical user or operator." -msgstr "" -"同样,任何会对开发社区的大部分人产生影响的技术工作(重构、重大架构变更)也应" -"广泛传播。即使对典型用户或操作员的影响为零,改进流程也适用于这种情况。" +"Similarly, any technical effort (refactoring, major architectural change)" +" that will impact a large section of the development community should " +"also be communicated widely. The Enhancement process is suited for this " +"even if it will have zero impact on the typical user or operator." +msgstr "同样,任何会对开发社区的大部分人产生影响的技术工作(重构、重大架构变更)也应广泛传播。即使对典型用户或操作员的影响为零,改进流程也适用于这种情况。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:61 msgid "" -"For small changes and additions, going through the Enhancement process would " -"be time-consuming and unnecessary. This includes, for example, adding new " -"Federated Learning algorithms, as these only add features without changing " -"how Flower works or is used." +"For small changes and additions, going through the Enhancement process " +"would be time-consuming and unnecessary. This includes, for example, " +"adding new Federated Learning algorithms, as these only add features " +"without changing how Flower works or is used." msgstr "" -"对于小的改动和添加,通过 \"改善\"程序既耗时又没有必要" -"。例如,这包括添加新的联邦学习算法,因为这只会增加功能,而不会改变 \"Flower " +"对于小的改动和添加,通过 \"改善\"程序既耗时又没有必要。例如,这包括添加新的联邦学习算法,因为这只会增加功能,而不会改变 \"Flower " "\"的工作或使用方式。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:63 msgid "" "Enhancements are different from feature requests, as they are already " -"providing a laid-out path for implementation and are championed by members " -"of the community." -msgstr "" -"增强功能与功能请求不同,因为它们已经提供了实施路径,并得到了社区成员的支持。" +"providing a laid-out path for implementation and are championed by " +"members of the community." +msgstr "增强功能与功能请求不同,因为它们已经提供了实施路径,并得到了社区成员的支持。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:67 msgid "" "An Enhancement is captured in a Markdown file that follows a defined " -"template and a workflow to review and store enhancement docs for reference " -"— the Enhancement Doc." -msgstr "" -"增强功能被记录在一个 Markdown 文件中,该文件遵循已定义的模板和工作流程,用于" -"审查和存储增强功能文档(即增强功能文档)以供参考。" +"template and a workflow to review and store enhancement docs for " +"reference — the Enhancement Doc." +msgstr "增强功能被记录在一个 Markdown 文件中,该文件遵循已定义的模板和工作流程,用于审查和存储增强功能文档(即增强功能文档)以供参考。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:69 msgid "Enhancement Doc Template" @@ -4177,10 +4383,9 @@ msgstr "描述数据" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:92 msgid "" -"**fed-number** (Required) The `fed-number` of the last Flower Enhancement " -"Doc + 1. With this number, it becomes easy to reference other proposals." -msgstr "**fed-number**(必填)上一个Flower增强文件的 \"fed-number \"" -"+1。有了这个编号,就很容易参考其他提案。" +"**fed-number** (Required) The `fed-number` of the last Flower Enhancement" +" Doc + 1. With this number, it becomes easy to reference other proposals." +msgstr "**fed-number**(必填)上一个Flower增强文件的 \"fed-number \"+1。有了这个编号,就很容易参考其他提案。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:94 msgid "**title** (Required) The title of the proposal in plain language." @@ -4188,22 +4393,20 @@ msgstr "**标题** (必填)用简明语言写出提案的标题。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:96 msgid "" -"**status** (Required) The current status of the proposal. See [workflow]" -"(#workflow) for the possible states." -msgstr "" -"**status** (必填)提案的当前状态。有关可能的状态,请参阅 [工作流程]" -"(#workflow)。" +"**status** (Required) The current status of the proposal. See " +"[workflow](#workflow) for the possible states." +msgstr "**status** (必填)提案的当前状态。有关可能的状态,请参阅 [工作流程](#workflow)。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:98 msgid "" -"**authors** (Required) A list of authors of the proposal. This is simply the " -"GitHub ID." +"**authors** (Required) A list of authors of the proposal. This is simply " +"the GitHub ID." msgstr "**作者**(必填) 提案的作者列表。这只是 GitHub ID。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:100 msgid "" -"**creation-date** (Required) The date that the proposal was first submitted " -"in a PR." +"**creation-date** (Required) The date that the proposal was first " +"submitted in a PR." msgstr "**创建日期**(必填) 建议书在 PR 中首次提交的日期。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:102 @@ -4214,8 +4417,8 @@ msgstr "**最后更新** (可选)提案最后一次重大修改的日期。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:104 msgid "" -"**see-also** (Optional) A list of other proposals that are relevant to this " -"one." +"**see-also** (Optional) A list of other proposals that are relevant to " +"this one." msgstr "**另见** (可选)与本提案相关的其他提案清单。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:106 @@ -4223,8 +4426,7 @@ msgid "**replaces** (Optional) A list of proposals that this one replaces." msgstr "**取代**(可选) 这份提案所取代的提案列表。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:108 -msgid "" -"**superseded-by** (Optional) A list of proposals that this one supersedes." +msgid "**superseded-by** (Optional) A list of proposals that this one supersedes." msgstr "**被取代者** (可选) 此提案取代的提案列表。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:111 @@ -4234,51 +4436,46 @@ msgstr "工作流程" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:113 msgid "" "The idea forming the enhancement should already have been discussed or " -"pitched in the community. As such, it needs a champion, usually the author, " -"who shepherds the enhancement. This person also has to find committers to " -"Flower willing to review the proposal." -msgstr "" -"形成增强功能的想法应该已经在社区中讨论过或提出过。因此,它需要一个支持者(通" -"常是作者)来引导增强。这个人还必须找到愿意审核提案的提交者。" +"pitched in the community. As such, it needs a champion, usually the " +"author, who shepherds the enhancement. This person also has to find " +"committers to Flower willing to review the proposal." +msgstr "形成增强功能的想法应该已经在社区中讨论过或提出过。因此,它需要一个支持者(通常是作者)来引导增强。这个人还必须找到愿意审核提案的提交者。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:115 msgid "" "New enhancements are checked in with a file name in the form of `NNNN-" -"YYYYMMDD-enhancement-title.md`, with `NNNN` being the Flower Enhancement Doc " -"number, to `enhancements`. All enhancements start in `provisional` state as " -"part of a pull request. Discussions are done as part of the pull request " -"review." +"YYYYMMDD-enhancement-title.md`, with `NNNN` being the Flower Enhancement " +"Doc number, to `enhancements`. All enhancements start in `provisional` " +"state as part of a pull request. Discussions are done as part of the pull" +" request review." msgstr "" -"新的增强功能以 `NNNN-YYYYMMDD-enhancement-title.md` 的文件名签入,其中 `NNNN`" -" 是花朵增强文档的编号,并将其转入 `enhancements`。作为拉取请求(pull " -"request)的一部分,所有增强功能都从 `provisional` " -"状态开始。讨论是作为拉取请求审查的一部分进行的。" +"新的增强功能以 `NNNN-YYYYMMDD-enhancement-title.md` 的文件名签入,其中 `NNNN` " +"是花朵增强文档的编号,并将其转入 `enhancements`。作为拉取请求(pull request)的一部分,所有增强功能都从 " +"`provisional` 状态开始。讨论是作为拉取请求审查的一部分进行的。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:117 msgid "" -"Once an enhancement has been reviewed and approved, its status is changed to " -"`implementable`. The actual implementation is then done in separate pull " -"requests. These pull requests should mention the respective enhancement as " -"part of their description. After the implementation is done, the proposal " -"status is changed to `implemented`." +"Once an enhancement has been reviewed and approved, its status is changed" +" to `implementable`. The actual implementation is then done in separate " +"pull requests. These pull requests should mention the respective " +"enhancement as part of their description. After the implementation is " +"done, the proposal status is changed to `implemented`." msgstr "" -"一旦增强功能通过审核和批准,其状态就会变为 `可实施`。实际的实施工作将在单独的" -"拉取请求中完成。这些拉取请求应在其描述中提及相应的增强功能。实施完成后," -"提案状态将更改为 `已实施`。" +"一旦增强功能通过审核和批准,其状态就会变为 " +"`可实施`。实际的实施工作将在单独的拉取请求中完成。这些拉取请求应在其描述中提及相应的增强功能。实施完成后,提案状态将更改为 `已实施`。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:119 msgid "" -"Under certain conditions, other states are possible. An Enhancement has the " -"following states:" +"Under certain conditions, other states are possible. An Enhancement has " +"the following states:" msgstr "在某些条件下,还可能出现其他状态。增强提案具有以下状态:" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:121 msgid "" "`provisional`: The enhancement has been proposed and is actively being " -"defined. This is the starting state while the proposal is being fleshed out " -"and actively defined and discussed." -msgstr "`暂定`: 已提出改进建议并正在积极定义。这是在提案得到充实、积极定义和讨论时的" -"起始状态。" +"defined. This is the starting state while the proposal is being fleshed " +"out and actively defined and discussed." +msgstr "`暂定`: 已提出改进建议并正在积极定义。这是在提案得到充实、积极定义和讨论时的起始状态。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:122 msgid "`implementable`: The enhancement has been reviewed and approved." @@ -4291,14 +4488,13 @@ msgid "" msgstr "`已实施`: 增强功能已实施,不再主动更改。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:124 -msgid "" -"`deferred`: The enhancement is proposed but not actively being worked on." +msgid "`deferred`: The enhancement is proposed but not actively being worked on." msgstr "`推迟`: 已提出改进建议,但尚未积极开展工作。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:125 msgid "" -"`rejected`: The authors and reviewers have decided that this enhancement is " -"not moving forward." +"`rejected`: The authors and reviewers have decided that this enhancement " +"is not moving forward." msgstr "`拒绝`: 作者和审稿人已决定不再推进该增强功能。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:126 @@ -4311,21 +4507,17 @@ msgstr "`已替换`: 增强功能已被新的增强功能取代。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:131 msgid "" -"Adding an additional process to the ones already provided by GitHub (Issues " -"and Pull Requests) adds more complexity and can be a barrier for potential " -"first-time contributors." -msgstr "" -"在 GitHub 已提供的流程(问题和拉取请求)之外再增加一个流程,会增加复杂性,并" -"可能成为潜在首次贡献者的障碍。" +"Adding an additional process to the ones already provided by GitHub " +"(Issues and Pull Requests) adds more complexity and can be a barrier for " +"potential first-time contributors." +msgstr "在 GitHub 已提供的流程(问题和拉取请求)之外再增加一个流程,会增加复杂性,并可能成为潜在首次贡献者的障碍。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:133 msgid "" "Expanding the proposal template beyond the single-sentence description " -"currently required in the features issue template may be a heavy burden for " -"non-native English speakers." -msgstr "" -"对于英语非母语者来说,将提案模板扩展到目前要求的单句描述之外可能是一个沉重的" -"负担。" +"currently required in the features issue template may be a heavy burden " +"for non-native English speakers." +msgstr "对于英语非母语者来说,将提案模板扩展到目前要求的单句描述之外可能是一个沉重的负担。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:137 msgid "GitHub Issues" @@ -4334,17 +4526,16 @@ msgstr "GitHub 问题" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:139 msgid "" "Using GitHub Issues for these kinds of enhancements is doable. One could " -"use, for example, tags, to differentiate and filter them from other issues. " -"The main issue is in discussing and reviewing an enhancement: GitHub issues " -"only have a single thread for comments. Enhancements usually have multiple " -"threads of discussion at the same time for various parts of the doc. " -"Managing these multiple discussions can be confusing when using GitHub " -"Issues." -msgstr "" -"使用 GitHub Issues 进行此类改进是可行的。例如,我们可以使用标签来区分和过滤这" -"些问题。主要的问题在于讨论和审查增强功能: GitHub 问题只有一个评论线程。而增" -"强功能通常会同时有多个讨论线程,针对文档的不同部分。在使用 GitHub 问题时,管" -"理这些多重讨论会很混乱。" +"use, for example, tags, to differentiate and filter them from other " +"issues. The main issue is in discussing and reviewing an enhancement: " +"GitHub issues only have a single thread for comments. Enhancements " +"usually have multiple threads of discussion at the same time for various " +"parts of the doc. Managing these multiple discussions can be confusing " +"when using GitHub Issues." +msgstr "" +"使用 GitHub Issues 进行此类改进是可行的。例如,我们可以使用标签来区分和过滤这些问题。主要的问题在于讨论和审查增强功能: " +"GitHub 问题只有一个评论线程。而增强功能通常会同时有多个讨论线程,针对文档的不同部分。在使用 GitHub " +"问题时,管理这些多重讨论会很混乱。" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:141 msgid "Google Docs" @@ -4352,15 +4543,15 @@ msgstr "谷歌文档" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:143 msgid "" -"Google Docs allow for multiple threads of discussions. But as Google Docs " -"are hosted outside the project, their discoverability by the community needs " -"to be taken care of. A list of links to all proposals has to be managed and " -"made available for the community. Compared to shipping proposals as part of " -"Flower's repository, the potential for missing links is much higher." +"Google Docs allow for multiple threads of discussions. But as Google Docs" +" are hosted outside the project, their discoverability by the community " +"needs to be taken care of. A list of links to all proposals has to be " +"managed and made available for the community. Compared to shipping " +"proposals as part of Flower's repository, the potential for missing links" +" is much higher." msgstr "" -"谷歌文档允许多线程讨论。但是,由于谷歌文档是在项目之外托管的,因此需要注意它" -"们是否能被社区发现。我们必须管理所有提案的链接列表,并提供给社区使用。与作为 " -"Flower 资源库一部分的提案相比,丢失链接的可能性要大得多。" +"谷歌文档允许多线程讨论。但是,由于谷歌文档是在项目之外托管的,因此需要注意它们是否能被社区发现。我们必须管理所有提案的链接列表,并提供给社区使用。与作为" +" Flower 资源库一部分的提案相比,丢失链接的可能性要大得多。" #: ../../source/fed/index.md:1 msgid "FED - Flower Enhancement Doc" @@ -4372,8 +4563,8 @@ msgstr "整合评估结果" #: ../../source/how-to-aggregate-evaluation-results.rst:4 msgid "" -"The Flower server does not prescribe a way to aggregate evaluation results, " -"but it enables the user to fully customize result aggregation." +"The Flower server does not prescribe a way to aggregate evaluation " +"results, but it enables the user to fully customize result aggregation." msgstr "Flower 服务器没有规定整合评估结果的方法,但用户可以完全自定义如何整合。" #: ../../source/how-to-aggregate-evaluation-results.rst:8 @@ -4382,12 +4573,10 @@ msgstr "自定义整合评估结果" #: ../../source/how-to-aggregate-evaluation-results.rst:10 msgid "" -"The same :code:`Strategy`-customization approach can be used to aggregate " -"custom evaluation results coming from individual clients. Clients can return " -"custom metrics to the server by returning a dictionary:" -msgstr "" -"同样的 :code:`Strategy` 定制方法也可用于汇总来自单个客户端的自定义评估结果。" -"客户端可以通过返回字典的方式向服务器返回自定义指标:" +"The same :code:`Strategy`-customization approach can be used to aggregate" +" custom evaluation results coming from individual clients. Clients can " +"return custom metrics to the server by returning a dictionary:" +msgstr "同样的 :code:`Strategy` 定制方法也可用于汇总来自单个客户端的自定义评估结果。客户端可以通过返回字典的方式向服务器返回自定义指标:" #: ../../source/how-to-aggregate-evaluation-results.rst:36 msgid "" @@ -4402,11 +4591,10 @@ msgstr "配置客户端" #: ../../source/how-to-configure-clients.rst:4 msgid "" "Along with model parameters, Flower can send configuration values to " -"clients. Configuration values can be used for various purposes. They are, " -"for example, a popular way to control client-side hyperparameters from the " -"server." -msgstr "除了模型参数,Flower 还可以向客户端发送配置值。配置值有多种用途。它们是一种从" -"服务器控制客户端超参数的常用方法。" +"clients. Configuration values can be used for various purposes. They are," +" for example, a popular way to control client-side hyperparameters from " +"the server." +msgstr "除了模型参数,Flower 还可以向客户端发送配置值。配置值有多种用途。它们是一种从服务器控制客户端超参数的常用方法。" #: ../../source/how-to-configure-clients.rst:7 msgid "Configuration values" @@ -4414,45 +4602,41 @@ msgstr "配置值" #: ../../source/how-to-configure-clients.rst:9 msgid "" -"Configuration values are represented as a dictionary with ``str`` keys and " -"values of type ``bool``, ``bytes``, ``double`` (64-bit precision float), " -"``int``, or ``str`` (or equivalent types in different languages). Here is an " -"example of a configuration dictionary in Python:" +"Configuration values are represented as a dictionary with ``str`` keys " +"and values of type ``bool``, ``bytes``, ``double`` (64-bit precision " +"float), ``int``, or ``str`` (or equivalent types in different languages)." +" Here is an example of a configuration dictionary in Python:" msgstr "" -"配置值以字典的形式表示,字典的键为 ``str``,值的类型为 ``bool``、``bytes``、" -"``double``(64 位精度浮点型)、``int``或 ``str`(或不同语言中的等效类型)。下" -"面是一个 Python 配置字典的示例:" +"配置值以字典的形式表示,字典的键为 ``str``,值的类型为 ``bool``、``bytes``、``double``(64 " +"位精度浮点型)、``int``或 ``str`(或不同语言中的等效类型)。下面是一个 Python 配置字典的示例:" #: ../../source/how-to-configure-clients.rst:20 msgid "" "Flower serializes these configuration dictionaries (or *config dict* for " -"short) to their ProtoBuf representation, transports them to the client using " -"gRPC, and then deserializes them back to Python dictionaries." +"short) to their ProtoBuf representation, transports them to the client " +"using gRPC, and then deserializes them back to Python dictionaries." msgstr "" -"Flower 将这些配置字典(简称 *config dict*)序列化为 ProtoBuf 表示形式,使用 " -"gRPC 将其传输到客户端,然后再反序列化为 Python 字典。" +"Flower 将这些配置字典(简称 *config dict*)序列化为 ProtoBuf 表示形式,使用 gRPC " +"将其传输到客户端,然后再反序列化为 Python 字典。" #: ../../source/how-to-configure-clients.rst:24 msgid "" -"Currently, there is no support for directly sending collection types (e.g., " -"``Set``, ``List``, ``Map``) as values in configuration dictionaries. There " -"are several workarounds to send collections as values by converting them to " -"one of the supported value types (and converting them back on the client-" -"side)." +"Currently, there is no support for directly sending collection types " +"(e.g., ``Set``, ``List``, ``Map``) as values in configuration " +"dictionaries. There are several workarounds to send collections as values" +" by converting them to one of the supported value types (and converting " +"them back on the client-side)." msgstr "" -"目前,还不支持在配置字典中直接发送作为值的集合类型(例如,`Set``, `List`, `Ma" -"p``)。有几种变通方法可将集合转换为支持的值类型之一(并在客户端将其转换回)," -"从而将集合作为值发送。" +"目前,还不支持在配置字典中直接发送作为值的集合类型(例如,`Set``, `List`, " +"`Map``)。有几种变通方法可将集合转换为支持的值类型之一(并在客户端将其转换回),从而将集合作为值发送。" #: ../../source/how-to-configure-clients.rst:26 msgid "" "One can, for example, convert a list of floating-point numbers to a JSON " -"string, then send the JSON string using the configuration dictionary, and " -"then convert the JSON string back to a list of floating-point numbers on the " -"client." -msgstr "" -"例如,可以将浮点数列表转换为 JSON 字符串,然后使用配置字典发送 JSON 字符串," -"再在客户端将 JSON 字符串转换回浮点数列表。" +"string, then send the JSON string using the configuration dictionary, and" +" then convert the JSON string back to a list of floating-point numbers on" +" the client." +msgstr "例如,可以将浮点数列表转换为 JSON 字符串,然后使用配置字典发送 JSON 字符串,再在客户端将 JSON 字符串转换回浮点数列表。" #: ../../source/how-to-configure-clients.rst:30 msgid "Configuration through built-in strategies" @@ -4460,65 +4644,57 @@ msgstr "通过内置策略进行配置" #: ../../source/how-to-configure-clients.rst:32 msgid "" -"The easiest way to send configuration values to clients is to use a built-in " -"strategy like :code:`FedAvg`. Built-in strategies support so-called " -"configuration functions. A configuration function is a function that the " -"built-in strategy calls to get the configuration dictionary for the current " -"round. It then forwards the configuration dictionary to all the clients " -"selected during that round." +"The easiest way to send configuration values to clients is to use a " +"built-in strategy like :code:`FedAvg`. Built-in strategies support so-" +"called configuration functions. A configuration function is a function " +"that the built-in strategy calls to get the configuration dictionary for " +"the current round. It then forwards the configuration dictionary to all " +"the clients selected during that round." msgstr "" -"向客户端发送配置值的最简单方法是使用内置策略,如 :code:`FedAvg`。内置策略支持" -"所谓的配置函数。配置函数是内置策略调用的函数,用于获取当前轮的配置字典。然后" -",它会将配置字典转发给该轮中选择的所有客户端。" +"向客户端发送配置值的最简单方法是使用内置策略,如 " +":code:`FedAvg`。内置策略支持所谓的配置函数。配置函数是内置策略调用的函数,用于获取当前轮的配置字典。然后,它会将配置字典转发给该轮中选择的所有客户端。" #: ../../source/how-to-configure-clients.rst:34 msgid "" "Let's start with a simple example. Imagine we want to send (a) the batch " -"size that the client should use, (b) the current global round of federated " -"learning, and (c) the number of epochs to train on the client-side. Our " -"configuration function could look like this:" -msgstr "" -"让我们从一个简单的例子开始。想象一下,我们想要发送给客户端(a)应该使用的批次" -"大小,(b)当前联邦学习的全局轮次,以及(c)客户端训练的遍历数。我们的配置函" -"数可以是这样的:" +"size that the client should use, (b) the current global round of " +"federated learning, and (c) the number of epochs to train on the client-" +"side. Our configuration function could look like this:" +msgstr "让我们从一个简单的例子开始。想象一下,我们想要发送给客户端(a)应该使用的批次大小,(b)当前联邦学习的全局轮次,以及(c)客户端训练的遍历数。我们的配置函数可以是这样的:" #: ../../source/how-to-configure-clients.rst:47 msgid "" "To make the built-in strategies use this function, we can pass it to " -"``FedAvg`` during initialization using the parameter :code:" -"`on_fit_config_fn`:" -msgstr "" -"为了让内置策略使用这个函数,我们可以在初始化时使用参数 :code:" -"`on_fit_config_fn` 将它传递给 ``FedAvg`` :" +"``FedAvg`` during initialization using the parameter " +":code:`on_fit_config_fn`:" +msgstr "为了让内置策略使用这个函数,我们可以在初始化时使用参数 :code:`on_fit_config_fn` 将它传递给 ``FedAvg`` :" #: ../../source/how-to-configure-clients.rst:56 -msgid "" -"One the client side, we receive the configuration dictionary in ``fit``:" +msgid "One the client side, we receive the configuration dictionary in ``fit``:" msgstr "在客户端,我们在 ``fit`` 中接收配置字典:" #: ../../source/how-to-configure-clients.rst:67 msgid "" "There is also an `on_evaluate_config_fn` to configure evaluation, which " -"works the same way. They are separate functions because one might want to " -"send different configuration values to `evaluate` (for example, to use a " -"different batch size)." +"works the same way. They are separate functions because one might want to" +" send different configuration values to `evaluate` (for example, to use a" +" different batch size)." msgstr "" -"还有一个 `on_evaluate_config_fn` 用于配置评估,其工作方式相同。它们是不同的函" -"数,因为可能需要向 `evaluate` 发送不同的配置值(例如,使用不同的批量大小)。" +"还有一个 `on_evaluate_config_fn` 用于配置评估,其工作方式相同。它们是不同的函数,因为可能需要向 `evaluate` " +"发送不同的配置值(例如,使用不同的批量大小)。" #: ../../source/how-to-configure-clients.rst:69 msgid "" -"The built-in strategies call this function every round (that is, every time " -"`Strategy.configure_fit` or `Strategy.configure_evaluate` runs). Calling " -"`on_evaluate_config_fn` every round allows us to vary/change the config dict " -"over consecutive rounds. If we wanted to implement a hyperparameter " -"schedule, for example, to increase the number of local epochs during later " -"rounds, we could do the following:" +"The built-in strategies call this function every round (that is, every " +"time `Strategy.configure_fit` or `Strategy.configure_evaluate` runs). " +"Calling `on_evaluate_config_fn` every round allows us to vary/change the " +"config dict over consecutive rounds. If we wanted to implement a " +"hyperparameter schedule, for example, to increase the number of local " +"epochs during later rounds, we could do the following:" msgstr "" -"内置策略每轮都会调用此函数(即每次运行 `Strategy.configure_fit` 或 `Strategy." -"configure_evaluate` 时)。每轮调用 `on_evaluate_config_fn` 允许我们在连续几轮" -"中改变配置指令。例如,如果我们想实现一个超参数时间表,以增加后几轮的本地遍历" -"次数,我们可以这样做:" +"内置策略每轮都会调用此函数(即每次运行 `Strategy.configure_fit` 或 " +"`Strategy.configure_evaluate` 时)。每轮调用 `on_evaluate_config_fn` " +"允许我们在连续几轮中改变配置指令。例如,如果我们想实现一个超参数时间表,以增加后几轮的本地遍历次数,我们可以这样做:" #: ../../source/how-to-configure-clients.rst:82 msgid "The :code:`FedAvg` strategy will call this function *every round*." @@ -4536,20 +4712,20 @@ msgstr "在某些情况下,有必要向不同的客户端发送不同的配置 #: ../../source/how-to-configure-clients.rst:89 msgid "" -"This can be achieved by customizing an existing strategy or by `implementing " -"a custom strategy from scratch `_. Here's a nonsensical example that customizes :" -"code:`FedAvg` by adding a custom ``\"hello\": \"world\"`` configuration key/" -"value pair to the config dict of a *single client* (only the first client in " -"the list, the other clients in this round to not receive this \"special\" " -"config value):" -msgstr "" -"这可以通过定制现有策略或 `从头开始实施一个定制策略 `_来实现。下面是一个无厘头的例子,`FedAvg`通过在*单个客户端*的配置指令(" -"config dict)中添加自定义的``\"hello\": \"world\"``配置键/" -"值对添加到此的配置 dict 中(仅列表中的第一个客户端," -"本轮中的其他客户端不会收到此 \"特殊 \"配置值):" +"This can be achieved by customizing an existing strategy or by " +"`implementing a custom strategy from scratch " +"`_. " +"Here's a nonsensical example that customizes :code:`FedAvg` by adding a " +"custom ``\"hello\": \"world\"`` configuration key/value pair to the " +"config dict of a *single client* (only the first client in the list, the " +"other clients in this round to not receive this \"special\" config " +"value):" +msgstr "" +"这可以通过定制现有策略或 `从头开始实施一个定制策略 `_来实现。下面是一个无厘头的例子,`FedAvg`通过在*单个客户端*的配置指令(config " +"dict)中添加自定义的``\"hello\": \"world\"``配置键/值对添加到此的配置 dict " +"中(仅列表中的第一个客户端,本轮中的其他客户端不会收到此 \"特殊 \"配置值):" #: ../../source/how-to-configure-logging.rst:2 msgid "Configure logging" @@ -4558,20 +4734,19 @@ msgstr "配置日志记录" #: ../../source/how-to-configure-logging.rst:4 msgid "" "The Flower logger keeps track of all core events that take place in " -"federated learning workloads. It presents information by default following a " -"standard message format:" -msgstr "Flower 日志记录器会跟踪联邦学习工作负载中发生的所有核心事件。它默认按照标准信" -"息格式提供信息:" +"federated learning workloads. It presents information by default " +"following a standard message format:" +msgstr "Flower 日志记录器会跟踪联邦学习工作负载中发生的所有核心事件。它默认按照标准信息格式提供信息:" #: ../../source/how-to-configure-logging.rst:13 msgid "" -"containing relevant information including: log message level (e.g. :code:" -"`INFO`, :code:`DEBUG`), a timestamp, the line where the logging took place " -"from, as well as the log message itself. In this way, the logger would " -"typically display information on your terminal as follows:" +"containing relevant information including: log message level (e.g. " +":code:`INFO`, :code:`DEBUG`), a timestamp, the line where the logging " +"took place from, as well as the log message itself. In this way, the " +"logger would typically display information on your terminal as follows:" msgstr "" -"相关信息包括:日志信息级别(例如 :code:`INFO`、:code:`DEBUG`)、时间戳、日志" -"记录的行以及日志信息本身。这样,日志记录器通常会在终端上显示如下信息:" +"相关信息包括:日志信息级别(例如 " +":code:`INFO`、:code:`DEBUG`)、时间戳、日志记录的行以及日志信息本身。这样,日志记录器通常会在终端上显示如下信息:" #: ../../source/how-to-configure-logging.rst:34 msgid "Saving log to file" @@ -4581,30 +4756,31 @@ msgstr "将日志保存到文件" msgid "" "By default, the Flower log is outputted to the terminal where you launch " "your Federated Learning workload from. This applies for both gRPC-based " -"federation (i.e. when you do :code:`fl.server.start_server`) and when using " -"the :code:`VirtualClientEngine` (i.e. when you do :code:`fl.simulation." -"start_simulation`). In some situations you might want to save this log to " -"disk. You can do so by calling the `fl.common.logger.configure() `_ function. " -"For example:" -msgstr "" -"默认情况下,Flower 日志会输出到启动联邦学习工作负载的终端。这既适用于基于 " -"gRPC 的联邦学习(即执行 :code:`fl.server.start_server` 时),也适用于使用 " -":code:`VirtualClientEngine` 时(即执行 :code:`fl.simulation.start_simulation`" -" 时)。在某些情况下,您可能希望将此日志保存到磁盘。为此,您可以调用 `fl." -"common.logger.configure() `_ 函数。例如:" +"federation (i.e. when you do :code:`fl.server.start_server`) and when " +"using the :code:`VirtualClientEngine` (i.e. when you do " +":code:`fl.simulation.start_simulation`). In some situations you might " +"want to save this log to disk. You can do so by calling the " +"`fl.common.logger.configure() " +"`_" +" function. For example:" +msgstr "" +"默认情况下,Flower 日志会输出到启动联邦学习工作负载的终端。这既适用于基于 gRPC 的联邦学习(即执行 " +":code:`fl.server.start_server` 时),也适用于使用 :code:`VirtualClientEngine` " +"时(即执行 :code:`fl.simulation.start_simulation` " +"时)。在某些情况下,您可能希望将此日志保存到磁盘。为此,您可以调用 `fl.common.logger.configure() " +"`_" +" 函数。例如:" #: ../../source/how-to-configure-logging.rst:53 msgid "" -"With the above, Flower will record the log you see on your terminal to :code:" -"`log.txt`. This file will be created in the same directory as were you are " -"running the code from. If we inspect we see the log above is also recorded " -"but prefixing with :code:`identifier` each line:" +"With the above, Flower will record the log you see on your terminal to " +":code:`log.txt`. This file will be created in the same directory as were " +"you are running the code from. If we inspect we see the log above is also" +" recorded but prefixing with :code:`identifier` each line:" msgstr "" -"通过上述操作,Flower 会将您在终端上看到的日志记录到 :code:`log.txt`。该文件将" -"创建在运行代码的同一目录下。如果我们检查一下,就会发现上面的日志也被记录了下" -"来,但每一行都以 :code:`identifier` 作为前缀:" +"通过上述操作,Flower 会将您在终端上看到的日志记录到 " +":code:`log.txt`。该文件将创建在运行代码的同一目录下。如果我们检查一下,就会发现上面的日志也被记录了下来,但每一行都以 " +":code:`identifier` 作为前缀:" #: ../../source/how-to-configure-logging.rst:74 msgid "Log your own messages" @@ -4612,19 +4788,16 @@ msgstr "记录自己的信息" #: ../../source/how-to-configure-logging.rst:76 msgid "" -"You might expand the information shown by default with the Flower logger by " -"adding more messages relevant to your application. You can achieve this " -"easily as follows." -msgstr "" -"您可以通过添加更多与应用程序相关的信息来扩展 Flower 日志记录器默认显示的信" -"息。您可以通过以下方法轻松实现这一目标。" +"You might expand the information shown by default with the Flower logger " +"by adding more messages relevant to your application. You can achieve " +"this easily as follows." +msgstr "您可以通过添加更多与应用程序相关的信息来扩展 Flower 日志记录器默认显示的信息。您可以通过以下方法轻松实现这一目标。" #: ../../source/how-to-configure-logging.rst:102 msgid "" -"In this way your logger will show, in addition to the default messages, the " -"ones introduced by the clients as specified above." -msgstr "" -"这样,除默认信息外,您的日志记录器还将显示由客户引入的信息,如上文所述。" +"In this way your logger will show, in addition to the default messages, " +"the ones introduced by the clients as specified above." +msgstr "这样,除默认信息外,您的日志记录器还将显示由客户引入的信息,如上文所述。" #: ../../source/how-to-configure-logging.rst:128 msgid "Log to a remote service" @@ -4632,21 +4805,20 @@ msgstr "登录远程服务" #: ../../source/how-to-configure-logging.rst:130 msgid "" -"The :code:`fl.common.logger.configure` function, also allows specifying a " -"host to which logs can be pushed (via :code:`POST`) through a native Python :" -"code:`logging.handler.HTTPHandler`. This is a particularly useful feature " -"in :code:`gRPC`-based Federated Learning workloads where otherwise gathering " -"logs from all entities (i.e. the server and the clients) might be " -"cumbersome. Note that in Flower simulation, the server automatically " -"displays all logs. You can still specify a :code:`HTTPHandler` should you " -"whish to backup or analyze the logs somewhere else." +"The :code:`fl.common.logger.configure` function, also allows specifying a" +" host to which logs can be pushed (via :code:`POST`) through a native " +"Python :code:`logging.handler.HTTPHandler`. This is a particularly useful" +" feature in :code:`gRPC`-based Federated Learning workloads where " +"otherwise gathering logs from all entities (i.e. the server and the " +"clients) might be cumbersome. Note that in Flower simulation, the server " +"automatically displays all logs. You can still specify a " +":code:`HTTPHandler` should you whish to backup or analyze the logs " +"somewhere else." msgstr "" "此外,:code:`fl.common.logger.configure`函数还允许指定主机,通过本地 Python " -":code:`logging.handler.HTTPHandler`,向该主机推送日志(通过 :code:`POST`)。" -"在基于 :code:`gRPC` 的联邦学习工作负载中,这是一个特别有用的功能,否则从所有" -"实体(即服务器和客户端)收集日志可能会很麻烦。请注意,在 Flower " -"模拟器中,服务器会自动显示所有日志。如果希望在其他地方备份或分析日志," -"仍可指定 :code:`HTTPHandler`。" +":code:`logging.handler.HTTPHandler`,向该主机推送日志(通过 :code:`POST`)。在基于 " +":code:`gRPC` 的联邦学习工作负载中,这是一个特别有用的功能,否则从所有实体(即服务器和客户端)收集日志可能会很麻烦。请注意,在 " +"Flower 模拟器中,服务器会自动显示所有日志。如果希望在其他地方备份或分析日志,仍可指定 :code:`HTTPHandler`。" #: ../../source/how-to-enable-ssl-connections.rst:2 msgid "Enable SSL connections" @@ -4656,26 +4828,24 @@ msgstr "启用 SSL 连接" msgid "" "This guide describes how to a SSL-enabled secure Flower server can be " "started and how a Flower client can establish a secure connections to it." -msgstr "" -"本指南介绍如何启动启用 SSL 的安全 Flower 服务器,以及 Flower 客户端如何与其建" -"立安全连接。" +msgstr "本指南介绍如何启动启用 SSL 的安全 Flower 服务器,以及 Flower 客户端如何与其建立安全连接。" #: ../../source/how-to-enable-ssl-connections.rst:7 msgid "" -"A complete code example demonstrating a secure connection can be found `here " -"`_." +"A complete code example demonstrating a secure connection can be found " +"`here `_." msgstr "" -"有关安全连接的完整代码示例,请参见 `_ 。" +"有关安全连接的完整代码示例,请参见 `_ 。" #: ../../source/how-to-enable-ssl-connections.rst:10 msgid "" -"The code example comes with a README.md file which will explain how to start " -"it. Although it is already SSL-enabled, it might be less descriptive on how. " -"Stick to this guide for a deeper introduction to the topic." -msgstr "" -"代码示例附带的 README.md 文件将解释如何启动它。虽然它已经启用了 SSL,但对如何" -"启用可能描述较少。请参考本指南,了解更深入的相关介绍。" +"The code example comes with a README.md file which will explain how to " +"start it. Although it is already SSL-enabled, it might be less " +"descriptive on how. Stick to this guide for a deeper introduction to the " +"topic." +msgstr "代码示例附带的 README.md 文件将解释如何启动它。虽然它已经启用了 SSL,但对如何启用可能描述较少。请参考本指南,了解更深入的相关介绍。" #: ../../source/how-to-enable-ssl-connections.rst:16 msgid "Certificates" @@ -4684,14 +4854,13 @@ msgstr "证书" #: ../../source/how-to-enable-ssl-connections.rst:18 msgid "" "Using SSL-enabled connections requires certificates to be passed to the " -"server and client. For the purpose of this guide we are going to generate " -"self-signed certificates. As this can become quite complex we are going to " -"ask you to run the script in :code:`examples/advanced-tensorflow/" -"certificates/generate.sh`" +"server and client. For the purpose of this guide we are going to generate" +" self-signed certificates. As this can become quite complex we are going " +"to ask you to run the script in :code:`examples/advanced-" +"tensorflow/certificates/generate.sh`" msgstr "" -"使用支持 SSL 的连接需要向服务器和客户端传递证书。在本指南中,我们将生成自签名" -"证书。由于这可能会变得相当复杂,我们将要求你运行 :code:`examples/advanced-" -"tensorflow/certificates/generate.sh` 中的脚本" +"使用支持 SSL 的连接需要向服务器和客户端传递证书。在本指南中,我们将生成自签名证书。由于这可能会变得相当复杂,我们将要求你运行 " +":code:`examples/advanced-tensorflow/certificates/generate.sh` 中的脚本" #: ../../source/how-to-enable-ssl-connections.rst:23 msgid "with the following command sequence:" @@ -4699,10 +4868,9 @@ msgstr "使用以下命令序列:" #: ../../source/how-to-enable-ssl-connections.rst:30 msgid "" -"This will generate the certificates in :code:`examples/advanced-tensorflow/." -"cache/certificates`." -msgstr "" -"这将在 :code:`examples/advanced-tensorflow/.cache/certificates` 中生成证书。" +"This will generate the certificates in :code:`examples/advanced-" +"tensorflow/.cache/certificates`." +msgstr "这将在 :code:`examples/advanced-tensorflow/.cache/certificates` 中生成证书。" #: ../../source/how-to-enable-ssl-connections.rst:32 msgid "" @@ -4711,16 +4879,16 @@ msgid "" "complete for production environments. Please refer to other sources " "regarding the issue of correctly generating certificates for production " "environments." -msgstr "本示例中生成 SSL 证书的方法可作为启发和起点,但不应被视为生产环境的完整方法。" -"有关在生产环境中正确生成证书的问题,请参考其他资料。" +msgstr "本示例中生成 SSL 证书的方法可作为启发和起点,但不应被视为生产环境的完整方法。有关在生产环境中正确生成证书的问题,请参考其他资料。" #: ../../source/how-to-enable-ssl-connections.rst:36 msgid "" -"In case you are a researcher you might be just fine using the self-signed " -"certificates generated using the scripts which are part of this guide." +"In case you are a researcher you might be just fine using the self-signed" +" certificates generated using the scripts which are part of this guide." msgstr "如果你是一名研究人员,使用本指南中的脚本生成的自签名证书就可以了。" #: ../../source/how-to-enable-ssl-connections.rst:41 +#: ../../source/ref-api/flwr.server.Server.rst:2 msgid "Server" msgstr "服务器" @@ -4733,16 +4901,16 @@ msgstr "现在,我们将展示如何编写一个使用先前生成的脚本的 #: ../../source/how-to-enable-ssl-connections.rst:61 msgid "" "When providing certificates, the server expects a tuple of three " -"certificates. :code:`Path` can be used to easily read the contents of those " -"files into byte strings, which is the data type :code:`start_server` expects." +"certificates. :code:`Path` can be used to easily read the contents of " +"those files into byte strings, which is the data type " +":code:`start_server` expects." msgstr "" -"在提供证书时,服务器希望得到由三个证书组成的元组。 :code:`Path` 可用于轻松地" -"将这些文件的内容读取为字节字符串,这就是 :code:`start_server` 期望的数据类" -"型。" +"在提供证书时,服务器希望得到由三个证书组成的元组。 :code:`Path` 可用于轻松地将这些文件的内容读取为字节字符串,这就是 " +":code:`start_server` 期望的数据类型。" #: ../../source/how-to-enable-ssl-connections.rst:65 #: ../../source/how-to-upgrade-to-flower-1.0.rst:37 -#: ../../source/ref-api-flwr.rst:15 +#: ../../source/ref-api/flwr.client.Client.rst:2 msgid "Client" msgstr "客户端" @@ -4754,26 +4922,25 @@ msgstr "现在我们将演示如何编写一个客户端,使用之前生成的 #: ../../source/how-to-enable-ssl-connections.rst:84 msgid "" -"When setting :code:`root_certificates`, the client expects the PEM-encoded " -"root certificates as a byte string. We are again using :code:`Path` to " -"simplify reading those as byte strings." +"When setting :code:`root_certificates`, the client expects the PEM-" +"encoded root certificates as a byte string. We are again using " +":code:`Path` to simplify reading those as byte strings." msgstr "" -"当设置 :code:`root_certificates` 时,客户端希望 PEM 编码的根证书是字节字符" -"串。我们再次使用 :code:`Path` 来简化以字节字符串形式读取证书的过程。" +"当设置 :code:`root_certificates` 时,客户端希望 PEM 编码的根证书是字节字符串。我们再次使用 " +":code:`Path` 来简化以字节字符串形式读取证书的过程。" #: ../../source/how-to-enable-ssl-connections.rst:89 +#: ../../source/how-to-use-built-in-mods.rst:85 #: ../../source/tutorial-series-what-is-federated-learning.ipynb:287 msgid "Conclusion" msgstr "总结" #: ../../source/how-to-enable-ssl-connections.rst:91 msgid "" -"You should now have learned how to generate self-signed certificates using " -"the given script, start a SSL-enabled server, and have a client establish a " -"secure connection to it." -msgstr "" -"现在,你应该已经学会了如何使用给定的脚本生成自签名证书、启动启用 SSL 的服务器" -"并让客户端与其建立安全连接。" +"You should now have learned how to generate self-signed certificates " +"using the given script, start a SSL-enabled server, and have a client " +"establish a secure connection to it." +msgstr "现在,你应该已经学会了如何使用给定的脚本生成自签名证书、启动启用 SSL 的服务器并让客户端与其建立安全连接。" #: ../../source/how-to-enable-ssl-connections.rst:96 msgid "Additional resources" @@ -4781,8 +4948,8 @@ msgstr "补充资源" #: ../../source/how-to-enable-ssl-connections.rst:98 msgid "" -"These additional sources might be relevant if you would like to dive deeper " -"into the topic of certificates:" +"These additional sources might be relevant if you would like to dive " +"deeper into the topic of certificates:" msgstr "如果您想更深入地了解证书主题,这些额外的资料来源可能有帮助:" #: ../../source/how-to-enable-ssl-connections.rst:100 @@ -4799,16 +4966,15 @@ msgstr "实施策略" #: ../../source/how-to-implement-strategies.rst:4 msgid "" -"The strategy abstraction enables implementation of fully custom strategies. " -"A strategy is basically the federated learning algorithm that runs on the " -"server. Strategies decide how to sample clients, how to configure clients " -"for training, how to aggregate updates, and how to evaluate models. Flower " -"provides a few built-in strategies which are based on the same API described " -"below." +"The strategy abstraction enables implementation of fully custom " +"strategies. A strategy is basically the federated learning algorithm that" +" runs on the server. Strategies decide how to sample clients, how to " +"configure clients for training, how to aggregate updates, and how to " +"evaluate models. Flower provides a few built-in strategies which are " +"based on the same API described below." msgstr "" -"策略抽象类可以实现完全定制的策略。策略基本上就是在服务器上运行的联邦学习算法" -"。策略决定如何对客户端进行采样、如何配置客户端进行训练、如何聚合参数更新以及" -"如何评估模型。Flower 提供了一些内置策略,这些策略基于下文所述的相同 API。" +"策略抽象类可以实现完全定制的策略。策略基本上就是在服务器上运行的联邦学习算法。策略决定如何对客户端进行采样、如何配置客户端进行训练、如何聚合参数更新以及如何评估模型。Flower" +" 提供了一些内置策略,这些策略基于下文所述的相同 API。" #: ../../source/how-to-implement-strategies.rst:11 msgid "The :code:`Strategy` abstraction" @@ -4816,13 +4982,14 @@ msgstr ":code:`策略 ` 抽象类" #: ../../source/how-to-implement-strategies.rst:13 msgid "" -"All strategy implementation are derived from the abstract base class :code:" -"`flwr.server.strategy.Strategy`, both built-in implementations and third " -"party implementations. This means that custom strategy implementations have " -"the exact same capabilities at their disposal as built-in ones." +"All strategy implementation are derived from the abstract base class " +":code:`flwr.server.strategy.Strategy`, both built-in implementations and " +"third party implementations. This means that custom strategy " +"implementations have the exact same capabilities at their disposal as " +"built-in ones." msgstr "" -"所有策略实现均源自抽象基类 :code:`flwr.server.strategy.Strategy`,包括内置实" -"现和第三方实现。这意味着自定义策略实现与内置实现具有完全相同的功能。" +"所有策略实现均源自抽象基类 " +":code:`flwr.server.strategy.Strategy`,包括内置实现和第三方实现。这意味着自定义策略实现与内置实现具有完全相同的功能。" #: ../../source/how-to-implement-strategies.rst:18 msgid "" @@ -4832,12 +4999,10 @@ msgstr "策略抽象定义了一些需要实现的抽象方法:" #: ../../source/how-to-implement-strategies.rst:75 msgid "" -"Creating a new strategy means implementing a new :code:`class` (derived from " -"the abstract base class :code:`Strategy`) that implements for the previously " -"shown abstract methods:" -msgstr "" -"创建一个新策略意味着要实现一个新的 :code:`class`(从抽象基类 :code:" -"`Strategy` 派生),该类要实现前面显示的抽象方法:" +"Creating a new strategy means implementing a new :code:`class` (derived " +"from the abstract base class :code:`Strategy`) that implements for the " +"previously shown abstract methods:" +msgstr "创建一个新策略意味着要实现一个新的 :code:`class`(从抽象基类 :code:`Strategy` 派生),该类要实现前面显示的抽象方法:" #: ../../source/how-to-implement-strategies.rst:100 msgid "The Flower server calls these methods in the following order:" @@ -4853,48 +5018,44 @@ msgstr ":code:`初始化参数` 方法" #: ../../source/how-to-implement-strategies.rst:182 msgid "" -":code:`initialize_parameters` is called only once, at the very beginning of " -"an execution. It is responsible for providing the initial global model " -"parameters in a serialized form (i.e., as a :code:`Parameters` object)." +":code:`initialize_parameters` is called only once, at the very beginning " +"of an execution. It is responsible for providing the initial global model" +" parameters in a serialized form (i.e., as a :code:`Parameters` object)." msgstr "" -":code:`initialize_parameters` 只调用一次,即在执行开始时。它负责以序列化形式" -"(即 :code:`Parameters` 对象)提供初始全局模型参数。" +":code:`initialize_parameters` 只调用一次,即在执行开始时。它负责以序列化形式(即 " +":code:`Parameters` 对象)提供初始全局模型参数。" #: ../../source/how-to-implement-strategies.rst:184 msgid "" -"Built-in strategies return user-provided initial parameters. The following " -"example shows how initial parameters can be passed to :code:`FedAvg`:" -msgstr "" -"内置策略会返回用户提供的初始参数。下面的示例展示了如何将初始参数传递给 :code:" -"`FedAvg`:" +"Built-in strategies return user-provided initial parameters. The " +"following example shows how initial parameters can be passed to " +":code:`FedAvg`:" +msgstr "内置策略会返回用户提供的初始参数。下面的示例展示了如何将初始参数传递给 :code:`FedAvg`:" #: ../../source/how-to-implement-strategies.rst:209 msgid "" "The Flower server will call :code:`initialize_parameters`, which either " -"returns the parameters that were passed to :code:`initial_parameters`, or :" -"code:`None`. If no parameters are returned from :code:" -"`initialize_parameters` (i.e., :code:`None`), the server will randomly " -"select one client and ask it to provide its parameters. This is a " -"convenience feature and not recommended in practice, but it can be useful " -"for prototyping. In practice, it is recommended to always use server-side " -"parameter initialization." +"returns the parameters that were passed to :code:`initial_parameters`, or" +" :code:`None`. If no parameters are returned from " +":code:`initialize_parameters` (i.e., :code:`None`), the server will " +"randomly select one client and ask it to provide its parameters. This is " +"a convenience feature and not recommended in practice, but it can be " +"useful for prototyping. In practice, it is recommended to always use " +"server-side parameter initialization." msgstr "" "Flower 服务器将调用 :code:`initialize_parameters`,返回传给 " ":code:`initial_parameters` 的参数或 :code:`None`。如果 " -":code:`initialize_parameters` 没有返回任何参数(即 :code:`None`),服务器将随" -"机选择一个客户端并要求其提供参数。这只是一个便捷的功能,在实际应用中并不推荐" -"使用,但在原型开发中可能很有用。在实践中,建议始终使用服务器端参数初始化。" +":code:`initialize_parameters` 没有返回任何参数(即 " +":code:`None`),服务器将随机选择一个客户端并要求其提供参数。这只是一个便捷的功能,在实际应用中并不推荐使用,但在原型开发中可能很有用。在实践中,建议始终使用服务器端参数初始化。" #: ../../source/how-to-implement-strategies.rst:213 msgid "" "Server-side parameter initialization is a powerful mechanism. It can be " -"used, for example, to resume training from a previously saved checkpoint. It " -"is also the fundamental capability needed to implement hybrid approaches, " -"for example, to fine-tune a pre-trained model using federated learning." -msgstr "" -"服务器端参数初始化是一种强大的机制。例如,它可以用来从先前保存的检查点恢复训" -"练。它也是实现混合方法所需的基本能力,例如,使用联邦学习对预先训练好的模型进" -"行微调。" +"used, for example, to resume training from a previously saved checkpoint." +" It is also the fundamental capability needed to implement hybrid " +"approaches, for example, to fine-tune a pre-trained model using federated" +" learning." +msgstr "服务器端参数初始化是一种强大的机制。例如,它可以用来从先前保存的检查点恢复训练。它也是实现混合方法所需的基本能力,例如,使用联邦学习对预先训练好的模型进行微调。" #: ../../source/how-to-implement-strategies.rst:216 msgid "The :code:`configure_fit` method" @@ -4902,23 +5063,21 @@ msgstr ":code:`configure_fit`方法" #: ../../source/how-to-implement-strategies.rst:218 msgid "" -":code:`configure_fit` is responsible for configuring the upcoming round of " -"training. What does *configure* mean in this context? Configuring a round " -"means selecting clients and deciding what instructions to send to these " -"clients. The signature of :code:`configure_fit` makes this clear:" +":code:`configure_fit` is responsible for configuring the upcoming round " +"of training. What does *configure* mean in this context? Configuring a " +"round means selecting clients and deciding what instructions to send to " +"these clients. The signature of :code:`configure_fit` makes this clear:" msgstr "" -":code:`configure_fit` 负责配置即将开始的一轮训练。*配置*在这里是什么意思?配" -"置一轮训练意味着选择客户并决定向这些客户发送什么指令。:code:`configure_fit` " -"说明了这一点:" +":code:`configure_fit` " +"负责配置即将开始的一轮训练。*配置*在这里是什么意思?配置一轮训练意味着选择客户并决定向这些客户发送什么指令。:code:`configure_fit`" +" 说明了这一点:" #: ../../source/how-to-implement-strategies.rst:231 msgid "" "The return value is a list of tuples, each representing the instructions " -"that will be sent to a particular client. Strategy implementations usually " -"perform the following steps in :code:`configure_fit`:" -msgstr "" -"返回值是一个元组列表,每个元组代表将发送到特定客户端的指令。策略实现通常在 :" -"code:`configure_fit` 中执行以下步骤:" +"that will be sent to a particular client. Strategy implementations " +"usually perform the following steps in :code:`configure_fit`:" +msgstr "返回值是一个元组列表,每个元组代表将发送到特定客户端的指令。策略实现通常在 :code:`configure_fit` 中执行以下步骤:" #: ../../source/how-to-implement-strategies.rst:233 #: ../../source/how-to-implement-strategies.rst:280 @@ -4926,39 +5085,38 @@ msgid "" "Use the :code:`client_manager` to randomly sample all (or a subset of) " "available clients (each represented as a :code:`ClientProxy` object)" msgstr "" -"使用 :code:`client_manager` 随机抽样所有(或部分)可用客户端(每个客户端都表" -"示为 :code:`ClientProxy` 对象)" +"使用 :code:`client_manager` 随机抽样所有(或部分)可用客户端(每个客户端都表示为 :code:`ClientProxy` " +"对象)" #: ../../source/how-to-implement-strategies.rst:234 msgid "" "Pair each :code:`ClientProxy` with the same :code:`FitIns` holding the " "current global model :code:`parameters` and :code:`config` dict" msgstr "" -"将每个 :code:`ClientProxy` 与持有当前全局模型 :code:`parameters` 和 :code:" -"`config` dict 的 :code:`FitIns` 配对" +"将每个 :code:`ClientProxy` 与持有当前全局模型 :code:`parameters` 和 :code:`config` " +"dict 的 :code:`FitIns` 配对" #: ../../source/how-to-implement-strategies.rst:236 msgid "" "More sophisticated implementations can use :code:`configure_fit` to " -"implement custom client selection logic. A client will only participate in a " -"round if the corresponding :code:`ClientProxy` is included in the the list " -"returned from :code:`configure_fit`." +"implement custom client selection logic. A client will only participate " +"in a round if the corresponding :code:`ClientProxy` is included in the " +"the list returned from :code:`configure_fit`." msgstr "" -"更复杂的实现可以使用 :code:`configure_fit` 来实现自定义的客户端选择逻辑。" -"只有当相应的 :code:`ClientProxy` 包含在 :code:`configure_fit` " -"返回的列表中时,客户端才会参与进来。" +"更复杂的实现可以使用 :code:`configure_fit` 来实现自定义的客户端选择逻辑。只有当相应的 " +":code:`ClientProxy` 包含在 :code:`configure_fit` 返回的列表中时,客户端才会参与进来。" #: ../../source/how-to-implement-strategies.rst:240 msgid "" "The structure of this return value provides a lot of flexibility to the " "user. Since instructions are defined on a per-client basis, different " -"instructions can be sent to each client. This enables custom strategies to " -"train, for example, different models on different clients, or use different " -"hyperparameters on different clients (via the :code:`config` dict)." +"instructions can be sent to each client. This enables custom strategies " +"to train, for example, different models on different clients, or use " +"different hyperparameters on different clients (via the :code:`config` " +"dict)." msgstr "" -"该返回值的结构为用户提供了很大的灵活性。由于指令是按客户端定义的,因此可以向" -"每个客户端发送不同的指令。这使得自定义策略成为可能,例如在不同的客户端上训练" -"不同的模型,或在不同的客户端上使用不同的超参数(通过 :code:`config` dict)。" +"该返回值的结构为用户提供了很大的灵活性。由于指令是按客户端定义的,因此可以向每个客户端发送不同的指令。这使得自定义策略成为可能,例如在不同的客户端上训练不同的模型,或在不同的客户端上使用不同的超参数(通过" +" :code:`config` dict)。" #: ../../source/how-to-implement-strategies.rst:243 msgid "The :code:`aggregate_fit` method" @@ -4966,33 +5124,31 @@ msgstr ":code:`aggregate_fit` 方法" #: ../../source/how-to-implement-strategies.rst:245 msgid "" -":code:`aggregate_fit` is responsible for aggregating the results returned by " -"the clients that were selected and asked to train in :code:`configure_fit`." -msgstr "" -":code:`aggregate_fit` 负责汇总在 :code:`configure_fit` 中选择并要求训练的客户" -"端所返回的结果。" +":code:`aggregate_fit` is responsible for aggregating the results returned" +" by the clients that were selected and asked to train in " +":code:`configure_fit`." +msgstr ":code:`aggregate_fit` 负责汇总在 :code:`configure_fit` 中选择并要求训练的客户端所返回的结果。" #: ../../source/how-to-implement-strategies.rst:258 msgid "" "Of course, failures can happen, so there is no guarantee that the server " -"will get results from all the clients it sent instructions to (via :code:" -"`configure_fit`). :code:`aggregate_fit` therefore receives a list of :code:" -"`results`, but also a list of :code:`failures`." +"will get results from all the clients it sent instructions to (via " +":code:`configure_fit`). :code:`aggregate_fit` therefore receives a list " +"of :code:`results`, but also a list of :code:`failures`." msgstr "" -"当然,失败是有可能发生的,因此无法保证服务器会从它发送指令(通过 :code:" -"`configure_fit`)的所有客户端获得结果。因此 :code:`aggregate_fit` 会收到 :" -"code:`results` 的列表,但也会收到 :code:`failures` 的列表。" +"当然,失败是有可能发生的,因此无法保证服务器会从它发送指令(通过 :code:`configure_fit`)的所有客户端获得结果。因此 " +":code:`aggregate_fit` 会收到 :code:`results` 的列表,但也会收到 :code:`failures` 的列表。" #: ../../source/how-to-implement-strategies.rst:260 msgid "" -":code:`aggregate_fit` returns an optional :code:`Parameters` object and a " -"dictionary of aggregated metrics. The :code:`Parameters` return value is " -"optional because :code:`aggregate_fit` might decide that the results " +":code:`aggregate_fit` returns an optional :code:`Parameters` object and a" +" dictionary of aggregated metrics. The :code:`Parameters` return value is" +" optional because :code:`aggregate_fit` might decide that the results " "provided are not sufficient for aggregation (e.g., too many failures)." msgstr "" -":code:`aggregate_fit` 返回一个可选的 :code:`Parameters` 对象和一个聚合度量的" -"字典。:code:`Parameters` 返回值是可选的,因为 :code:`aggregate_fit` 可能会认" -"为所提供的结果不足以进行聚合(例如,失败次数过多)。" +":code:`aggregate_fit` 返回一个可选的 :code:`Parameters` " +"对象和一个聚合度量的字典。:code:`Parameters` 返回值是可选的,因为 :code:`aggregate_fit` " +"可能会认为所提供的结果不足以进行聚合(例如,失败次数过多)。" #: ../../source/how-to-implement-strategies.rst:263 msgid "The :code:`configure_evaluate` method" @@ -5000,54 +5156,52 @@ msgstr ":code:`configure_evaluate`方法" #: ../../source/how-to-implement-strategies.rst:265 msgid "" -":code:`configure_evaluate` is responsible for configuring the upcoming round " -"of evaluation. What does *configure* mean in this context? Configuring a " -"round means selecting clients and deciding what instructions to send to " -"these clients. The signature of :code:`configure_evaluate` makes this clear:" +":code:`configure_evaluate` is responsible for configuring the upcoming " +"round of evaluation. What does *configure* mean in this context? " +"Configuring a round means selecting clients and deciding what " +"instructions to send to these clients. The signature of " +":code:`configure_evaluate` makes this clear:" msgstr "" -":code:`configure_evaluate` 负责配置下一轮评估。*配置*在这里是什么意思?配置一" -"轮评估意味着选择客户端并决定向这些客户端发送什么指令。:code:`configure_evalua" -"te` 说明了这一点:" +":code:`configure_evaluate` " +"负责配置下一轮评估。*配置*在这里是什么意思?配置一轮评估意味着选择客户端并决定向这些客户端发送什么指令。:code:`configure_evaluate`" +" 说明了这一点:" #: ../../source/how-to-implement-strategies.rst:278 msgid "" "The return value is a list of tuples, each representing the instructions " -"that will be sent to a particular client. Strategy implementations usually " -"perform the following steps in :code:`configure_evaluate`:" -msgstr "" -"返回值是一个元组列表,每个元组代表将发送到特定客户端的指令。策略实现通常在 :" -"code:`configure_evaluate` 中执行以下步骤:" +"that will be sent to a particular client. Strategy implementations " +"usually perform the following steps in :code:`configure_evaluate`:" +msgstr "返回值是一个元组列表,每个元组代表将发送到特定客户端的指令。策略实现通常在 :code:`configure_evaluate` 中执行以下步骤:" #: ../../source/how-to-implement-strategies.rst:281 msgid "" -"Pair each :code:`ClientProxy` with the same :code:`EvaluateIns` holding the " -"current global model :code:`parameters` and :code:`config` dict" +"Pair each :code:`ClientProxy` with the same :code:`EvaluateIns` holding " +"the current global model :code:`parameters` and :code:`config` dict" msgstr "" -"将每个 :code:`ClientProxy` 与持有当前全局模型 :code:`parameters` 和 :code:" -"`config` dict 的 :code:`EvaluateIns` 配对" +"将每个 :code:`ClientProxy` 与持有当前全局模型 :code:`parameters` 和 :code:`config` " +"dict 的 :code:`EvaluateIns` 配对" #: ../../source/how-to-implement-strategies.rst:283 msgid "" "More sophisticated implementations can use :code:`configure_evaluate` to " -"implement custom client selection logic. A client will only participate in a " -"round if the corresponding :code:`ClientProxy` is included in the the list " -"returned from :code:`configure_evaluate`." +"implement custom client selection logic. A client will only participate " +"in a round if the corresponding :code:`ClientProxy` is included in the " +"the list returned from :code:`configure_evaluate`." msgstr "" -"更复杂的实现可以使用 :code:`configure_evaluate` " -"来实现自定义的客户端选择逻辑。只有当相应的 :code:`ClientProxy` 包含在 " -":code:`configure_evaluate` 返回的列表中时,客户端才会参与进来。" +"更复杂的实现可以使用 :code:`configure_evaluate` 来实现自定义的客户端选择逻辑。只有当相应的 " +":code:`ClientProxy` 包含在 :code:`configure_evaluate` 返回的列表中时,客户端才会参与进来。" #: ../../source/how-to-implement-strategies.rst:287 msgid "" "The structure of this return value provides a lot of flexibility to the " "user. Since instructions are defined on a per-client basis, different " -"instructions can be sent to each client. This enables custom strategies to " -"evaluate, for example, different models on different clients, or use " -"different hyperparameters on different clients (via the :code:`config` dict)." +"instructions can be sent to each client. This enables custom strategies " +"to evaluate, for example, different models on different clients, or use " +"different hyperparameters on different clients (via the :code:`config` " +"dict)." msgstr "" -"该返回值的结构为用户提供了很大的灵活性。由于指令是按客户端定义的,因此可以向" -"每个客户端发送不同的指令。这使得自定义策略可以在不同客户端上评估不同的模型," -"或在不同客户端上使用不同的超参数(通过 :code:`config` dict)。" +"该返回值的结构为用户提供了很大的灵活性。由于指令是按客户端定义的,因此可以向每个客户端发送不同的指令。这使得自定义策略可以在不同客户端上评估不同的模型,或在不同客户端上使用不同的超参数(通过" +" :code:`config` dict)。" #: ../../source/how-to-implement-strategies.rst:291 msgid "The :code:`aggregate_evaluate` method" @@ -5056,35 +5210,33 @@ msgstr ":code:`aggregate_evaluate` 方法" #: ../../source/how-to-implement-strategies.rst:293 msgid "" ":code:`aggregate_evaluate` is responsible for aggregating the results " -"returned by the clients that were selected and asked to evaluate in :code:" -"`configure_evaluate`." +"returned by the clients that were selected and asked to evaluate in " +":code:`configure_evaluate`." msgstr "" -":code:`aggregate_evaluate` 负责汇总在 :code:`configure_evaluate` 中选择并要求" -"评估的客户端返回的结果。" +":code:`aggregate_evaluate` 负责汇总在 :code:`configure_evaluate` " +"中选择并要求评估的客户端返回的结果。" #: ../../source/how-to-implement-strategies.rst:306 msgid "" "Of course, failures can happen, so there is no guarantee that the server " -"will get results from all the clients it sent instructions to (via :code:" -"`configure_evaluate`). :code:`aggregate_evaluate` therefore receives a list " -"of :code:`results`, but also a list of :code:`failures`." +"will get results from all the clients it sent instructions to (via " +":code:`configure_evaluate`). :code:`aggregate_evaluate` therefore " +"receives a list of :code:`results`, but also a list of :code:`failures`." msgstr "" -"当然,失败是有可能发生的,因此无法保证服务器会从它发送指令(通过 :code:" -"`configure_evaluate`)的所有客户端获得结果。因此, :code:" -"`aggregate_evaluate` 会接收 :code:`results` 的列表,但也会接收 :code:" -"`failures` 的列表。" +"当然,失败是有可能发生的,因此无法保证服务器会从它发送指令(通过 " +":code:`configure_evaluate`)的所有客户端获得结果。因此, :code:`aggregate_evaluate` 会接收 " +":code:`results` 的列表,但也会接收 :code:`failures` 的列表。" #: ../../source/how-to-implement-strategies.rst:308 msgid "" -":code:`aggregate_evaluate` returns an optional :code:`float` (loss) and a " -"dictionary of aggregated metrics. The :code:`float` return value is optional " -"because :code:`aggregate_evaluate` might decide that the results provided " -"are not sufficient for aggregation (e.g., too many failures)." +":code:`aggregate_evaluate` returns an optional :code:`float` (loss) and a" +" dictionary of aggregated metrics. The :code:`float` return value is " +"optional because :code:`aggregate_evaluate` might decide that the results" +" provided are not sufficient for aggregation (e.g., too many failures)." msgstr "" ":code:`aggregate_evaluate` 返回一个可选的 " -":code:`float`(损失值)和一个聚合指标字典。:code:`float` 返回值是可选的," -"因为 :code:`aggregate_evaluate` " -"可能会认为所提供的结果不足以进行聚合(例如,失败次数过多)。" +":code:`float`(损失值)和一个聚合指标字典。:code:`float` 返回值是可选的,因为 " +":code:`aggregate_evaluate` 可能会认为所提供的结果不足以进行聚合(例如,失败次数过多)。" #: ../../source/how-to-implement-strategies.rst:311 msgid "The :code:`evaluate` method" @@ -5093,24 +5245,23 @@ msgstr ":code:`evaluate`方法" #: ../../source/how-to-implement-strategies.rst:313 msgid "" ":code:`evaluate` is responsible for evaluating model parameters on the " -"server-side. Having :code:`evaluate` in addition to :code:" -"`configure_evaluate`/:code:`aggregate_evaluate` enables strategies to " -"perform both servers-side and client-side (federated) evaluation." +"server-side. Having :code:`evaluate` in addition to " +":code:`configure_evaluate`/:code:`aggregate_evaluate` enables strategies " +"to perform both servers-side and client-side (federated) evaluation." msgstr "" ":code:`evaluate` 负责在服务器端评估模型参数。除了 " -":code:`configure_evaluate`/:code:`aggregate_evaluate` 之外,:code:`evaluate` " -"可以使策略同时执行服务器端和客户端(联邦)评估。" +":code:`configure_evaluate`/:code:`aggregate_evaluate` 之外,:code:`evaluate`" +" 可以使策略同时执行服务器端和客户端(联邦)评估。" #: ../../source/how-to-implement-strategies.rst:323 msgid "" -"The return value is again optional because the strategy might not need to " -"implement server-side evaluation or because the user-defined :code:" -"`evaluate` method might not complete successfully (e.g., it might fail to " -"load the server-side evaluation data)." +"The return value is again optional because the strategy might not need to" +" implement server-side evaluation or because the user-defined " +":code:`evaluate` method might not complete successfully (e.g., it might " +"fail to load the server-side evaluation data)." msgstr "" -"返回值也是可选的,因为策略可能不需要执行服务器端评估,或者因为用户定义的 :" -"code:`evaluate` 方法可能无法成功完成(例如,它可能无法加载服务器端评估数" -"据)。" +"返回值也是可选的,因为策略可能不需要执行服务器端评估,或者因为用户定义的 :code:`evaluate` " +"方法可能无法成功完成(例如,它可能无法加载服务器端评估数据)。" #: ../../source/how-to-install-flower.rst:2 msgid "Install Flower" @@ -5124,67 +5275,107 @@ msgstr "Python 版本" msgid "Install stable release" msgstr "安装稳定版" -#: ../../source/how-to-install-flower.rst:14 +#: ../../source/how-to-install-flower.rst:15 +msgid "Using pip" +msgstr "" + +#: ../../source/how-to-install-flower.rst:17 msgid "" -"Stable releases are available on `PyPI `_::" +"Stable releases are available on `PyPI " +"`_::" msgstr "稳定版本可在 `PyPI `_::" -#: ../../source/how-to-install-flower.rst:18 +#: ../../source/how-to-install-flower.rst:21 msgid "" "For simulations that use the Virtual Client Engine, ``flwr`` should be " "installed with the ``simulation`` extra::" msgstr "对于使用虚拟客户端引擎的模拟,`flwr`` 应与`simulation`` 一起安装:" -#: ../../source/how-to-install-flower.rst:24 +#: ../../source/how-to-install-flower.rst:27 +msgid "Using conda (or mamba)" +msgstr "" + +#: ../../source/how-to-install-flower.rst:29 +msgid "Flower can also be installed from the ``conda-forge`` channel." +msgstr "" + +#: ../../source/how-to-install-flower.rst:31 +msgid "" +"If you have not added ``conda-forge`` to your channels, you will first " +"need to run the following::" +msgstr "" + +#: ../../source/how-to-install-flower.rst:36 +msgid "" +"Once the ``conda-forge`` channel has been enabled, ``flwr`` can be " +"installed with ``conda``::" +msgstr "" + +#: ../../source/how-to-install-flower.rst:40 +msgid "or with ``mamba``::" +msgstr "" + +#: ../../source/how-to-install-flower.rst:46 msgid "Verify installation" msgstr "验证安装" -#: ../../source/how-to-install-flower.rst:26 +#: ../../source/how-to-install-flower.rst:48 +#, fuzzy msgid "" -"The following command can be used to verfiy if Flower was successfully " -"installed. If everything worked, it should print the version of Flower to " -"the command line::" -msgstr "" -"可以使用以下命令来验证 Flower 是否安装成功。如果一切正常,它将在命令行中打印 " -"Flower 的版本::" +"The following command can be used to verify if Flower was successfully " +"installed. If everything worked, it should print the version of Flower to" +" the command line::" +msgstr "可以使用以下命令来验证 Flower 是否安装成功。如果一切正常,它将在命令行中打印 Flower 的版本::" -#: ../../source/how-to-install-flower.rst:33 +#: ../../source/how-to-install-flower.rst:55 msgid "Advanced installation options" msgstr "高级安装选项" -#: ../../source/how-to-install-flower.rst:36 +#: ../../source/how-to-install-flower.rst:58 +#, fuzzy +msgid "Install via Docker" +msgstr "安装Flower" + +#: ../../source/how-to-install-flower.rst:60 +#, fuzzy +msgid "" +"`How to run Flower using Docker `_" +msgstr "" +"`TensorFlow快速入门 (教程) `_" + +#: ../../source/how-to-install-flower.rst:63 msgid "Install pre-release" msgstr "安装预发布版本" -#: ../../source/how-to-install-flower.rst:38 +#: ../../source/how-to-install-flower.rst:65 msgid "" -"New (possibly unstable) versions of Flower are sometimes available as pre-" -"release versions (alpha, beta, release candidate) before the stable release " -"happens::" -msgstr "" -"在稳定版发布之前,Flower 的新版本(可能是不稳定版)有时会作为预发布版本" -"(alpha、beta、候选发布版本)提供::" +"New (possibly unstable) versions of Flower are sometimes available as " +"pre-release versions (alpha, beta, release candidate) before the stable " +"release happens::" +msgstr "在稳定版发布之前,Flower 的新版本(可能是不稳定版)有时会作为预发布版本(alpha、beta、候选发布版本)提供::" -#: ../../source/how-to-install-flower.rst:42 +#: ../../source/how-to-install-flower.rst:69 msgid "" -"For simulations that use the Virtual Client Engine, ``flwr`` pre-releases " -"should be installed with the ``simulation`` extra::" +"For simulations that use the Virtual Client Engine, ``flwr`` pre-releases" +" should be installed with the ``simulation`` extra::" msgstr "对于使用虚拟客户端引擎的模拟,`flwr``预发行版应与`simulation``一起安装:" -#: ../../source/how-to-install-flower.rst:47 +#: ../../source/how-to-install-flower.rst:74 msgid "Install nightly release" msgstr "安装隔夜版本" -#: ../../source/how-to-install-flower.rst:49 +#: ../../source/how-to-install-flower.rst:76 msgid "" -"The latest (potentially unstable) changes in Flower are available as nightly " -"releases::" +"The latest (potentially unstable) changes in Flower are available as " +"nightly releases::" msgstr "Flower 中最新(可能不稳定)的更改以隔夜发布的形式提供::" -#: ../../source/how-to-install-flower.rst:53 +#: ../../source/how-to-install-flower.rst:80 msgid "" -"For simulations that use the Virtual Client Engine, ``flwr-nightly`` should " -"be installed with the ``simulation`` extra::" +"For simulations that use the Virtual Client Engine, ``flwr-nightly`` " +"should be installed with the ``simulation`` extra::" msgstr "对于使用虚拟客户端引擎的模拟,`flwr-nightly`应与`simulation`一起安装:" #: ../../source/how-to-monitor-simulation.rst:2 @@ -5193,23 +5384,20 @@ msgstr "监控模拟" #: ../../source/how-to-monitor-simulation.rst:4 msgid "" -"Flower allows you to monitor system resources while running your simulation. " -"Moreover, the Flower simulation engine is powerful and enables you to decide " -"how to allocate resources per client manner and constrain the total usage. " -"Insights from resource consumption can help you make smarter decisions and " -"speed up the execution time." +"Flower allows you to monitor system resources while running your " +"simulation. Moreover, the Flower simulation engine is powerful and " +"enables you to decide how to allocate resources per client manner and " +"constrain the total usage. Insights from resource consumption can help " +"you make smarter decisions and speed up the execution time." msgstr "" -"Flower 允许您在运行模拟时监控系统资源。此外,Flower 仿真引擎功能强大,能让您" -"决定如何按客户端方式分配资源并限制总使用量。从资源消耗中获得的观察可以帮助您" -"做出更明智的决策,并加快执行时间。" +"Flower 允许您在运行模拟时监控系统资源。此外,Flower " +"仿真引擎功能强大,能让您决定如何按客户端方式分配资源并限制总使用量。从资源消耗中获得的观察可以帮助您做出更明智的决策,并加快执行时间。" #: ../../source/how-to-monitor-simulation.rst:6 msgid "" -"The specific instructions assume you are using macOS and have the `Homebrew " -"`_ package manager installed." -msgstr "" -"具体说明假定你使用的是 macOS,并且安装了 `Homebrew `_ 软件" -"包管理器。" +"The specific instructions assume you are using macOS and have the " +"`Homebrew `_ package manager installed." +msgstr "具体说明假定你使用的是 macOS,并且安装了 `Homebrew `_ 软件包管理器。" #: ../../source/how-to-monitor-simulation.rst:10 msgid "Downloads" @@ -5217,14 +5405,14 @@ msgstr "下载" #: ../../source/how-to-monitor-simulation.rst:16 msgid "" -"`Prometheus `_ is used for data collection, while " -"`Grafana `_ will enable you to visualize the collected " -"data. They are both well integrated with `Ray `_ which " -"Flower uses under the hood." +"`Prometheus `_ is used for data collection, while" +" `Grafana `_ will enable you to visualize the " +"collected data. They are both well integrated with `Ray " +"`_ which Flower uses under the hood." msgstr "" "`Prometheus `_ 用于收集数据,而 `Grafana " -"`_ 则能让你将收集到的数据可视化。它们都与 Flower " -"在引擎下使用的 `Ray `_ 紧密集成。" +"`_ 则能让你将收集到的数据可视化。它们都与 Flower 在引擎下使用的 `Ray " +"`_ 紧密集成。" #: ../../source/how-to-monitor-simulation.rst:18 msgid "" @@ -5242,26 +5430,23 @@ msgstr "在上一代英特尔 Mac 设备上,应该是这样:" #: ../../source/how-to-monitor-simulation.rst:34 msgid "" -"Open the respective configuration files and change them. Depending on your " -"device, use one of the two following commands:" +"Open the respective configuration files and change them. Depending on " +"your device, use one of the two following commands:" msgstr "打开相应的配置文件并修改它们。根据设备情况,使用以下两个命令之一:" #: ../../source/how-to-monitor-simulation.rst:44 msgid "" -"and then delete all the text in the file and paste a new Prometheus config " -"you see below. You may adjust the time intervals to your requirements:" -msgstr "" -"然后删除文件中的所有文本,粘贴一个新的 Prometheus 配置文件,如下所示。您可以" -"根据需要调整时间间隔:" +"and then delete all the text in the file and paste a new Prometheus " +"config you see below. You may adjust the time intervals to your " +"requirements:" +msgstr "然后删除文件中的所有文本,粘贴一个新的 Prometheus 配置文件,如下所示。您可以根据需要调整时间间隔:" #: ../../source/how-to-monitor-simulation.rst:59 msgid "" -"Now after you have edited the Prometheus configuration, do the same with the " -"Grafana configuration files. Open those using one of the following commands " -"as before:" -msgstr "" -"编辑完 Prometheus 配置后,请对 Grafana 配置文件执行同样的操作。与之前一样,使" -"用以下命令之一打开这些文件:" +"Now after you have edited the Prometheus configuration, do the same with " +"the Grafana configuration files. Open those using one of the following " +"commands as before:" +msgstr "编辑完 Prometheus 配置后,请对 Grafana 配置文件执行同样的操作。与之前一样,使用以下命令之一打开这些文件:" #: ../../source/how-to-monitor-simulation.rst:69 msgid "" @@ -5271,8 +5456,8 @@ msgstr "您的终端编辑器应该会打开,并允许您像之前一样应用 #: ../../source/how-to-monitor-simulation.rst:84 msgid "" -"Congratulations, you just downloaded all the necessary software needed for " -"metrics tracking. Now, let’s start it." +"Congratulations, you just downloaded all the necessary software needed " +"for metrics tracking. Now, let’s start it." msgstr "恭喜您,您刚刚下载了指标跟踪所需的所有软件。现在,让我们开始吧。" #: ../../source/how-to-monitor-simulation.rst:88 @@ -5287,8 +5472,8 @@ msgstr "在运行 Flower 模拟之前,您必须启动刚刚安装和配置的 #: ../../source/how-to-monitor-simulation.rst:97 msgid "" -"Please include the following argument in your Python code when starting a " -"simulation." +"Please include the following argument in your Python code when starting a" +" simulation." msgstr "开始模拟时,请在 Python 代码中加入以下参数。" #: ../../source/how-to-monitor-simulation.rst:108 @@ -5297,8 +5482,8 @@ msgstr "现在,您可以开始工作了。" #: ../../source/how-to-monitor-simulation.rst:110 msgid "" -"Shortly after the simulation starts, you should see the following logs in " -"your terminal:" +"Shortly after the simulation starts, you should see the following logs in" +" your terminal:" msgstr "模拟启动后不久,您就会在终端中看到以下日志:" #: ../../source/how-to-monitor-simulation.rst:117 @@ -5307,31 +5492,28 @@ msgstr "您可以在 ``_ 查看所有内容。" #: ../../source/how-to-monitor-simulation.rst:119 msgid "" -"It's a Ray Dashboard. You can navigate to Metrics (on the left panel, the " -"lowest option)." -msgstr "" -"这是一个 Ray Dashboard。您可以导航到 \"度量标准\"(左侧面板,最低选项)。" +"It's a Ray Dashboard. You can navigate to Metrics (on the left panel, the" +" lowest option)." +msgstr "这是一个 Ray Dashboard。您可以导航到 \"度量标准\"(左侧面板,最低选项)。" #: ../../source/how-to-monitor-simulation.rst:121 msgid "" -"Or alternatively, you can just see them in Grafana by clicking on the right-" -"up corner, “View in Grafana”. Please note that the Ray dashboard is only " -"accessible during the simulation. After the simulation ends, you can only " -"use Grafana to explore the metrics. You can start Grafana by going to " -"``http://localhost:3000/``." +"Or alternatively, you can just see them in Grafana by clicking on the " +"right-up corner, “View in Grafana”. Please note that the Ray dashboard is" +" only accessible during the simulation. After the simulation ends, you " +"can only use Grafana to explore the metrics. You can start Grafana by " +"going to ``http://localhost:3000/``." msgstr "" -"或者,您也可以点击右上角的 \"在 Grafana 中查看\",在 Grafana 中查看它们。请注" -"意,Ray 仪表盘只能在模拟期间访问。模拟结束后,您只能使用 Grafana 浏览指标。您" -"可以访问 ``http://localhost:3000/``启动 Grafana。" +"或者,您也可以点击右上角的 \"在 Grafana 中查看\",在 Grafana 中查看它们。请注意,Ray " +"仪表盘只能在模拟期间访问。模拟结束后,您只能使用 Grafana 浏览指标。您可以访问 ``http://localhost:3000/``启动 " +"Grafana。" #: ../../source/how-to-monitor-simulation.rst:123 msgid "" "After you finish the visualization, stop Prometheus and Grafana. This is " "important as they will otherwise block, for example port :code:`3000` on " "your machine as long as they are running." -msgstr "" -"完成可视化后,请停止 Prometheus 和 Grafana。这一点很重要,否则只要它们在运" -"行,就会阻塞机器上的端口 :code:`3000`。" +msgstr "完成可视化后,请停止 Prometheus 和 Grafana。这一点很重要,否则只要它们在运行,就会阻塞机器上的端口 :code:`3000`。" #: ../../source/how-to-monitor-simulation.rst:132 msgid "Resource allocation" @@ -5339,24 +5521,21 @@ msgstr "资源分配" #: ../../source/how-to-monitor-simulation.rst:134 msgid "" -"You must understand how the Ray library works to efficiently allocate system " -"resources to simulation clients on your own." -msgstr "" -"您必须了解 Ray 库是如何工作的,才能有效地为自己的仿真客户端分配系统资源。" +"You must understand how the Ray library works to efficiently allocate " +"system resources to simulation clients on your own." +msgstr "您必须了解 Ray 库是如何工作的,才能有效地为自己的仿真客户端分配系统资源。" #: ../../source/how-to-monitor-simulation.rst:136 msgid "" "Initially, the simulation (which Ray handles under the hood) starts by " "default with all the available resources on the system, which it shares " -"among the clients. It doesn't mean it divides it equally among all of them, " -"nor that the model training happens at all of them simultaneously. You will " -"learn more about that in the later part of this blog. You can check the " -"system resources by running the following:" +"among the clients. It doesn't mean it divides it equally among all of " +"them, nor that the model training happens at all of them simultaneously. " +"You will learn more about that in the later part of this blog. You can " +"check the system resources by running the following:" msgstr "" -"最初,模拟(由 Ray 在引擎下处理)默认使用系统上的所有可用资源启动,并在客户端" -"之间共享。但这并不意味着它会将资源平均分配给所有客户端,也不意味着模型训练会" -"在所有客户端同时进行。您将在本博客的后半部分了解到更多相关信息。您可以运行以" -"下命令检查系统资源:" +"最初,模拟(由 Ray " +"在引擎下处理)默认使用系统上的所有可用资源启动,并在客户端之间共享。但这并不意味着它会将资源平均分配给所有客户端,也不意味着模型训练会在所有客户端同时进行。您将在本博客的后半部分了解到更多相关信息。您可以运行以下命令检查系统资源:" #: ../../source/how-to-monitor-simulation.rst:143 msgid "In Google Colab, the result you see might be similar to this:" @@ -5364,8 +5543,8 @@ msgstr "在 Google Colab 中,您看到的结果可能与此类似:" #: ../../source/how-to-monitor-simulation.rst:155 msgid "" -"However, you can overwrite the defaults. When starting a simulation, do the " -"following (you don't need to overwrite all of them):" +"However, you can overwrite the defaults. When starting a simulation, do " +"the following (you don't need to overwrite all of them):" msgstr "不过,您可以覆盖默认值。开始模拟时,请执行以下操作(不必全部覆盖):" #: ../../source/how-to-monitor-simulation.rst:175 @@ -5374,26 +5553,23 @@ msgstr "我们还可以为单个客户指定资源。" #: ../../source/how-to-monitor-simulation.rst:205 msgid "" -"Now comes the crucial part. Ray will start a new client only when it has all " -"the required resources (such that they run in parallel) when the resources " -"allow." -msgstr "" -"现在到了关键部分。只有在资源允许的情况下,Ray 才会在拥有所有所需资源(如并行" -"运行)时启动新客户端。" +"Now comes the crucial part. Ray will start a new client only when it has " +"all the required resources (such that they run in parallel) when the " +"resources allow." +msgstr "现在到了关键部分。只有在资源允许的情况下,Ray 才会在拥有所有所需资源(如并行运行)时启动新客户端。" #: ../../source/how-to-monitor-simulation.rst:207 msgid "" -"In the example above, only one client will be run, so your clients won't run " -"concurrently. Setting :code:`client_num_gpus = 0.5` would allow running two " -"clients and therefore enable them to run concurrently. Be careful not to " -"require more resources than available. If you specified :code:" -"`client_num_gpus = 2`, the simulation wouldn't start (even if you had 2 GPUs " -"but decided to set 1 in :code:`ray_init_args`)." +"In the example above, only one client will be run, so your clients won't " +"run concurrently. Setting :code:`client_num_gpus = 0.5` would allow " +"running two clients and therefore enable them to run concurrently. Be " +"careful not to require more resources than available. If you specified " +":code:`client_num_gpus = 2`, the simulation wouldn't start (even if you " +"had 2 GPUs but decided to set 1 in :code:`ray_init_args`)." msgstr "" -"在上面的示例中,将只运行一个客户端,因此您的客户端不会并发运行。设置 :code:" -"`client_num_gpus = 0.5` 将允许运行两个客户端,从而使它们能够并发运行。请注" -"意,所需的资源不要超过可用资源。如果您指定 :code:`client_num_gpus = 2`,模拟" -"将无法启动(即使您有 2 个 GPU,但决定在 :code:`ray_init_args` 中设置为 1)。" +"在上面的示例中,将只运行一个客户端,因此您的客户端不会并发运行。设置 :code:`client_num_gpus = 0.5` " +"将允许运行两个客户端,从而使它们能够并发运行。请注意,所需的资源不要超过可用资源。如果您指定 :code:`client_num_gpus = " +"2`,模拟将无法启动(即使您有 2 个 GPU,但决定在 :code:`ray_init_args` 中设置为 1)。" #: ../../source/how-to-monitor-simulation.rst:212 ../../source/ref-faq.rst:2 msgid "FAQ" @@ -5405,25 +5581,22 @@ msgstr "问:我没有看到任何指标记录。" #: ../../source/how-to-monitor-simulation.rst:216 msgid "" -"A: The timeframe might not be properly set. The setting is in the top right " -"corner (\"Last 30 minutes\" by default). Please change the timeframe to " -"reflect the period when the simulation was running." -msgstr "" -"答:时间范围可能没有正确设置。设置在右上角(默认为 \"最后 30 分钟\")。请更改" -"时间框架,以反映模拟运行的时间段。" +"A: The timeframe might not be properly set. The setting is in the top " +"right corner (\"Last 30 minutes\" by default). Please change the " +"timeframe to reflect the period when the simulation was running." +msgstr "答:时间范围可能没有正确设置。设置在右上角(默认为 \"最后 30 分钟\")。请更改时间框架,以反映模拟运行的时间段。" #: ../../source/how-to-monitor-simulation.rst:218 msgid "" -"Q: I see “Grafana server not detected. Please make sure the Grafana server " -"is running and refresh this page” after going to the Metrics tab in Ray " -"Dashboard." -msgstr "" -"问:我看到 \"未检测到 Grafana 服务器。请确保 Grafana 服务器正在运行并刷新此页" -"面\"。" +"Q: I see “Grafana server not detected. Please make sure the Grafana " +"server is running and refresh this page” after going to the Metrics tab " +"in Ray Dashboard." +msgstr "问:我看到 \"未检测到 Grafana 服务器。请确保 Grafana 服务器正在运行并刷新此页面\"。" #: ../../source/how-to-monitor-simulation.rst:220 msgid "" -"A: You probably don't have Grafana running. Please check the running services" +"A: You probably don't have Grafana running. Please check the running " +"services" msgstr "答:您可能没有运行 Grafana。请检查正在运行的服务" #: ../../source/how-to-monitor-simulation.rst:226 @@ -5434,8 +5607,8 @@ msgstr "问:在访问 ``_时,我看到 \"无法访问 #: ../../source/how-to-monitor-simulation.rst:228 msgid "" -"A: Either the simulation has already finished, or you still need to start " -"Prometheus." +"A: Either the simulation has already finished, or you still need to start" +" Prometheus." msgstr "答:要么模拟已经完成,要么您还需要启动Prometheus。" #: ../../source/how-to-monitor-simulation.rst:232 @@ -5444,16 +5617,200 @@ msgstr "资源" #: ../../source/how-to-monitor-simulation.rst:234 msgid "" -"Ray Dashboard: ``_" +"Ray Dashboard: ``_" msgstr "Ray 仪表盘: ``_" #: ../../source/how-to-monitor-simulation.rst:236 msgid "" -"Ray Metrics: ``_" +"Ray Metrics: ``_" +msgstr "" +"Ray 指标: ``_" + +#: ../../source/how-to-run-flower-using-docker.rst:2 +msgid "Run Flower using Docker" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:4 +msgid "" +"The simplest way to get started with Flower is by using the pre-made " +"Docker images, which you can find on `Docker Hub " +"`_." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:7 +msgid "Before you start, make sure that the Docker daemon is running:" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:14 +msgid "" +"If you do not see the version of Docker but instead get an error saying " +"that the command was not found, you will need to install Docker first. " +"You can find installation instruction `here `_." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:20 +msgid "" +"On Linux, Docker commands require ``sudo`` privilege. If you want to " +"avoid using ``sudo``, you can follow the `Post-installation steps " +"`_ on the " +"official Docker website." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:25 +#, fuzzy +msgid "Flower server" +msgstr "Flower 服务器" + +#: ../../source/how-to-run-flower-using-docker.rst:28 +#, fuzzy +msgid "Quickstart" +msgstr "快速入门 JAX" + +#: ../../source/how-to-run-flower-using-docker.rst:30 +msgid "If you're looking to try out Flower, you can use the following command:" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:37 +msgid "" +"The command will pull the Docker image with the tag " +"``1.7.0-py3.11-ubuntu22.04`` from Docker Hub. The tag contains the " +"information which Flower, Python and Ubuntu is used. In this case, it " +"uses Flower 1.7.0, Python 3.11 and Ubuntu 22.04. The ``--rm`` flag tells " +"Docker to remove the container after it exits." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:44 +msgid "" +"By default, the Flower server keeps state in-memory. When using the " +"Docker flag ``--rm``, the state is not persisted between container " +"starts. We will show below how to save the state in a file on your host " +"system." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:48 +msgid "" +"The ``-p :`` flag tells Docker to map the ports " +"``9091``/``9092`` of the host to ``9091``/``9092`` of the container, " +"allowing you to access the Driver API on ``http://localhost:9091`` and " +"the Fleet API on ``http://localhost:9092``. Lastly, any flag that comes " +"after the tag is passed to the Flower server. Here, we are passing the " +"flag ``--insecure``." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:55 +msgid "" +"The ``--insecure`` flag enables insecure communication (using HTTP, not " +"HTTPS) and should only be used for testing purposes. We strongly " +"recommend enabling `SSL `_ when " +"deploying to a production environment." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:60 +msgid "" +"You can use ``--help`` to view all available flags that the server " +"supports:" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:67 +msgid "Mounting a volume to store the state on the host system" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:69 +msgid "" +"If you want to persist the state of the server on your host system, all " +"you need to do is specify a path where you want to save the file on your " +"host system and a name for the database file. In the example below, we " +"tell Docker via the flag ``-v`` to mount the user's home directory " +"(``~/`` on your host) into the ``/app/`` directory of the container. " +"Furthermore, we use the flag ``--database`` to specify the name of the " +"database file." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:82 +msgid "" +"As soon as the server starts, the file ``state.db`` is created in the " +"user's home directory on your host system. If the file already exists, " +"the server tries to restore the state from the file. To start the server " +"with an empty database, simply remove the ``state.db`` file." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:87 +#, fuzzy +msgid "Enabling SSL for secure connections" +msgstr "启用 SSL 连接" + +#: ../../source/how-to-run-flower-using-docker.rst:89 +msgid "" +"To enable SSL, you will need a CA certificate, a server certificate and a" +" server private key." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:92 +msgid "" +"For testing purposes, you can generate your own self-signed certificates." +" The `Enable SSL connections `_ page contains a section that " +"will guide you through the process." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:96 +msgid "" +"Assuming all files we need are in the local ``certificates`` directory, " +"we can use the flag ``-v`` to mount the local directory into the " +"``/app/`` directory of the container. This allows the server to access " +"the files within the container. Finally, we pass the names of the " +"certificates to the server with the ``--certificates`` flag." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:108 +msgid "Using a different Flower or Python version" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:110 +msgid "" +"If you want to use a different version of Flower or Python, you can do so" +" by changing the tag. All versions we provide are available on `Docker " +"Hub `_." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:114 +msgid "Pinning a Docker image to a specific version" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:116 +msgid "" +"It may happen that we update the images behind the tags. Such updates " +"usually include security updates of system dependencies that should not " +"change the functionality of Flower. However, if you want to ensure that " +"you always use the same image, you can specify the hash of the image " +"instead of the tag." +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:121 +msgid "" +"The following command returns the current image hash referenced by the " +"``server:1.7.0-py3.11-ubuntu22.04`` tag:" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:128 +msgid "Next, we can pin the hash when running a new server container:" +msgstr "" + +#: ../../source/how-to-run-flower-using-docker.rst:137 +#, fuzzy +msgid "Setting environment variables" +msgstr "设置编码环境" + +#: ../../source/how-to-run-flower-using-docker.rst:139 +msgid "" +"To set a variable inside a Docker container, you can use the ``-e " +"=`` flag." msgstr "" -"Ray 指标: ``_" #: ../../source/how-to-run-simulations.rst:2 msgid "Run simulations" @@ -5462,85 +5819,81 @@ msgstr "运行模拟" #: ../../source/how-to-run-simulations.rst:8 msgid "" "Simulating Federated Learning workloads is useful for a multitude of use-" -"cases: you might want to run your workload on a large cohort of clients but " -"without having to source, configure and mange a large number of physical " -"devices; you might want to run your FL workloads as fast as possible on the " -"compute systems you have access to without having to go through a complex " -"setup process; you might want to validate your algorithm on different " -"scenarios at varying levels of data and system heterogeneity, client " -"availability, privacy budgets, etc. These are among some of the use-cases " -"where simulating FL workloads makes sense. Flower can accommodate these " -"scenarios by means of its `VirtualClientEngine `_ or VCE." -msgstr "" -"模拟联邦学习工作负载可用于多种案例:您可能希望在大量客户端上运行您的工作负载" -",但无需采购、配置和管理大量物理设备;" -"您可能希望在您可以访问的计算系统上尽可能快地运行您的 FL 工作负载,而无需经过" -"复杂的设置过程;您可能希望在不同数据和系统异构性、客户端可用性、隐私预算等不" -"同水平的场景中验证您的算法。这些都是模拟 FL 工作负载的一些案例。Flower " -"可以通过其 \"虚拟客户端引擎\"(VirtualClientEngine)_或 VCE 来匹配这些情况。" +"cases: you might want to run your workload on a large cohort of clients " +"but without having to source, configure and mange a large number of " +"physical devices; you might want to run your FL workloads as fast as " +"possible on the compute systems you have access to without having to go " +"through a complex setup process; you might want to validate your " +"algorithm on different scenarios at varying levels of data and system " +"heterogeneity, client availability, privacy budgets, etc. These are among" +" some of the use-cases where simulating FL workloads makes sense. Flower " +"can accommodate these scenarios by means of its `VirtualClientEngine " +"`_ or " +"VCE." +msgstr "" +"模拟联邦学习工作负载可用于多种案例:您可能希望在大量客户端上运行您的工作负载,但无需采购、配置和管理大量物理设备;您可能希望在您可以访问的计算系统上尽可能快地运行您的" +" FL 工作负载,而无需经过复杂的设置过程;您可能希望在不同数据和系统异构性、客户端可用性、隐私预算等不同水平的场景中验证您的算法。这些都是模拟 " +"FL 工作负载的一些案例。Flower 可以通过其 \"虚拟客户端引擎\"(VirtualClientEngine)_或 VCE 来匹配这些情况。" #: ../../source/how-to-run-simulations.rst:10 msgid "" -"The :code:`VirtualClientEngine` schedules, launches and manages `virtual` " -"clients. These clients are identical to `non-virtual` clients (i.e. the ones " -"you launch via the command `flwr.client.start_client `_) in the sense that they can be configure by creating a " -"class inheriting, for example, from `flwr.client.NumPyClient `_ and therefore behave in an identical way. In " -"addition to that, clients managed by the :code:`VirtualClientEngine` are:" -msgstr "" -":code:`VirtualClientEngine`用来规划,启动和管理`虚拟`客户端。这些客户端跟`非" -"虚拟`客户端是一样的(即为您通过`flwr.client.start_client `_启动的客户端),因为它们可以通过创建一个继承自 `" -"flwr.client.NumPyClient `_ " -"的类进行配置,因此其行为方式相同。另外,由 `VirtualClientEngine` " -"管理的客户端有:" +"The :code:`VirtualClientEngine` schedules, launches and manages `virtual`" +" clients. These clients are identical to `non-virtual` clients (i.e. the " +"ones you launch via the command `flwr.client.start_client `_) in the sense that they can be configure by " +"creating a class inheriting, for example, from `flwr.client.NumPyClient " +"`_ and therefore behave in an " +"identical way. In addition to that, clients managed by the " +":code:`VirtualClientEngine` are:" +msgstr "" +":code:`VirtualClientEngine`用来规划,启动和管理`虚拟`客户端。这些客户端跟`非虚拟`客户端是一样的(即为您通过`flwr.client.start_client" +" `_启动的客户端),因为它们可以通过创建一个继承自 " +"`flwr.client.NumPyClient `_ " +"的类进行配置,因此其行为方式相同。另外,由 `VirtualClientEngine` 管理的客户端有:" #: ../../source/how-to-run-simulations.rst:12 msgid "" -"resource-aware: this means that each client gets assigned a portion of the " -"compute and memory on your system. You as a user can control this at the " -"beginning of the simulation and allows you to control the degree of " +"resource-aware: this means that each client gets assigned a portion of " +"the compute and memory on your system. You as a user can control this at " +"the beginning of the simulation and allows you to control the degree of " "parallelism of your Flower FL simulation. The fewer the resources per " "client, the more clients can run concurrently on the same hardware." msgstr "" -"资源感知:这意味着每个客户端都会分配到系统中的一部分计算和内存。作为用户,您" -"可以在模拟开始时对其进行控制,从而控制 Flower FL 模拟的并行程度。每个客户端的" -"资源越少,在同一硬件上并发运行的客户端就越多。" +"资源感知:这意味着每个客户端都会分配到系统中的一部分计算和内存。作为用户,您可以在模拟开始时对其进行控制,从而控制 Flower FL " +"模拟的并行程度。每个客户端的资源越少,在同一硬件上并发运行的客户端就越多。" #: ../../source/how-to-run-simulations.rst:13 msgid "" -"self-managed: this means that you as a user do not need to launch clients " -"manually, instead this gets delegated to :code:`VirtualClientEngine`'s " +"self-managed: this means that you as a user do not need to launch clients" +" manually, instead this gets delegated to :code:`VirtualClientEngine`'s " "internals." -msgstr "自管理:这意味着用户无需手动启动客户端,而是由 :code:`VirtualClientEngine` " -"负责。" +msgstr "自管理:这意味着用户无需手动启动客户端,而是由 :code:`VirtualClientEngine` 负责。" #: ../../source/how-to-run-simulations.rst:14 msgid "" -"ephemeral: this means that a client is only materialized when it is required " -"in the FL process (e.g. to do `fit() `_). The object is destroyed afterwards, releasing the resources it was " -"assigned and allowing in this way other clients to participate." +"ephemeral: this means that a client is only materialized when it is " +"required in the FL process (e.g. to do `fit() `_). The object is destroyed afterwards," +" releasing the resources it was assigned and allowing in this way other " +"clients to participate." msgstr "" -"即时性:这意味着客户端只有在 FL 进程中需要它时才会被实体化(例如执行 `fit() " -"`_ " +"即时性:这意味着客户端只有在 FL 进程中需要它时才会被实体化(例如执行 `fit() `_ " ")。之后该对象将被销毁,释放分配给它的资源,并允许其他客户端以这种方式参与。" #: ../../source/how-to-run-simulations.rst:16 msgid "" "The :code:`VirtualClientEngine` implements `virtual` clients using `Ray " "`_, an open-source framework for scalable Python " -"workloads. In particular, Flower's :code:`VirtualClientEngine` makes use of " -"`Actors `_ to spawn " -"`virtual` clients and run their workload." +"workloads. In particular, Flower's :code:`VirtualClientEngine` makes use " +"of `Actors `_ to " +"spawn `virtual` clients and run their workload." msgstr "" -":code:`VirtualClientEngine`使用`Ray `_来实现`虚拟`客户端,这是一个用于可扩展 Python 工作负载的开源框架。特别地," -"Flower 的 :code:`VirtualClientEngine` 使用 `Actors `_ 来生成 `virtual` 客户端并运行它们的工作负载。" +":code:`VirtualClientEngine`使用`Ray " +"`_来实现`虚拟`客户端,这是一个用于可扩展 Python 工作负载的开源框架。特别地,Flower 的" +" :code:`VirtualClientEngine` 使用 `Actors `_ 来生成 `virtual` 客户端并运行它们的工作负载。" #: ../../source/how-to-run-simulations.rst:20 msgid "Launch your Flower simulation" @@ -5548,16 +5901,16 @@ msgstr "启动 Flower 模拟" #: ../../source/how-to-run-simulations.rst:22 msgid "" -"Running Flower simulations still require you to define your client class, a " -"strategy, and utility functions to download and load (and potentially " -"partition) your dataset. With that out of the way, launching your simulation " -"is done with `start_simulation `_ and a minimal example looks as follows:" +"Running Flower simulations still require you to define your client class," +" a strategy, and utility functions to download and load (and potentially " +"partition) your dataset. With that out of the way, launching your " +"simulation is done with `start_simulation `_ and a minimal example looks" +" as follows:" msgstr "" -"运行 Flower 模拟器仍然需要定义客户端类、策略以及下载和加载(可能还需要分割)" -"数据集的实用程序。在完成这些工作后,就可以使用 \"start_simulation `_\" " -"来启动模拟了,一个最简单的示例如下:" +"运行 Flower 模拟器仍然需要定义客户端类、策略以及下载和加载(可能还需要分割)数据集的实用程序。在完成这些工作后,就可以使用 " +"\"start_simulation `_\" 来启动模拟了,一个最简单的示例如下:" #: ../../source/how-to-run-simulations.rst:44 msgid "VirtualClientEngine resources" @@ -5565,25 +5918,23 @@ msgstr "虚拟客户端引擎资源" #: ../../source/how-to-run-simulations.rst:45 msgid "" -"By default the VCE has access to all system resources (i.e. all CPUs, all " -"GPUs, etc) since that is also the default behavior when starting Ray. " -"However, in some settings you might want to limit how many of your system " -"resources are used for simulation. You can do this via the :code:" -"`ray_init_args` input argument to :code:`start_simulation` which the VCE " -"internally passes to Ray's :code:`ray.init` command. For a complete list of " -"settings you can configure check the `ray.init `_ documentation. Do not set :" -"code:`ray_init_args` if you want the VCE to use all your system's CPUs and " -"GPUs." -msgstr "" -"默认情况下,VCE 可以访问所有系统资源(即所有 CPU、所有 GPU 等)," -"因为这也是启动 Ray " -"时的默认行为。不过,在某些设置中,您可能希望限制有多少系统资源用于模拟。" -"您可以通过 :code:`ray_init_args` 输入到 :code:`start_simulation` " -"的参数来做到这一点,VCE 会在内部将该参数传递给 Ray 的 :code:`ray.init` " -"命令。有关您可以配置的设置的完整列表,请查看 `ray.init `_ 文档。如果希望 VCE " -"使用系统中所有的 CPU 和 GPU,请不要设置 :code:`ray_init_args`。" +"By default the VCE has access to all system resources (i.e. all CPUs, all" +" GPUs, etc) since that is also the default behavior when starting Ray. " +"However, in some settings you might want to limit how many of your system" +" resources are used for simulation. You can do this via the " +":code:`ray_init_args` input argument to :code:`start_simulation` which " +"the VCE internally passes to Ray's :code:`ray.init` command. For a " +"complete list of settings you can configure check the `ray.init " +"`_" +" documentation. Do not set :code:`ray_init_args` if you want the VCE to " +"use all your system's CPUs and GPUs." +msgstr "" +"默认情况下,VCE 可以访问所有系统资源(即所有 CPU、所有 GPU 等),因为这也是启动 Ray " +"时的默认行为。不过,在某些设置中,您可能希望限制有多少系统资源用于模拟。您可以通过 :code:`ray_init_args` 输入到 " +":code:`start_simulation` 的参数来做到这一点,VCE 会在内部将该参数传递给 Ray 的 :code:`ray.init`" +" 命令。有关您可以配置的设置的完整列表,请查看 `ray.init `_ 文档。如果希望 VCE 使用系统中所有的 CPU 和 " +"GPU,请不要设置 :code:`ray_init_args`。" #: ../../source/how-to-run-simulations.rst:62 msgid "Assigning client resources" @@ -5591,27 +5942,26 @@ msgstr "分配客户端资源" #: ../../source/how-to-run-simulations.rst:63 msgid "" -"By default the :code:`VirtualClientEngine` assigns a single CPU core (and " -"nothing else) to each virtual client. This means that if your system has 10 " -"cores, that many virtual clients can be concurrently running." +"By default the :code:`VirtualClientEngine` assigns a single CPU core (and" +" nothing else) to each virtual client. This means that if your system has" +" 10 cores, that many virtual clients can be concurrently running." msgstr "" -"默认情况下,:code:`VirtualClientEngine` 会为每个虚拟客户端分配一个 CPU 内核" -"(不分配其他任何内核)。这意味着,如果系统有 10 个内核,那么可以同时运行这么" -"多虚拟客户端。" +"默认情况下,:code:`VirtualClientEngine` 会为每个虚拟客户端分配一个 CPU " +"内核(不分配其他任何内核)。这意味着,如果系统有 10 个内核,那么可以同时运行这么多虚拟客户端。" #: ../../source/how-to-run-simulations.rst:65 msgid "" -"More often than not, you would probably like to adjust the resources your " -"clients get assigned based on the complexity (i.e. compute and memory " -"footprint) of your FL workload. You can do so when starting your simulation " -"by setting the argument `client_resources` to `start_simulation `_. Two keys are internally used " -"by Ray to schedule and spawn workloads (in our case Flower clients):" -msgstr "" -"通常情况下,您可能希望根据 FL " -"工作负载的复杂性(即计算和内存占用)来调整分配给客户端的资源。" -"您可以在启动模拟时将参数 `client_resources` 设置为 `start_simulation `_ 。Ray " +"More often than not, you would probably like to adjust the resources your" +" clients get assigned based on the complexity (i.e. compute and memory " +"footprint) of your FL workload. You can do so when starting your " +"simulation by setting the argument `client_resources` to " +"`start_simulation `_." +" Two keys are internally used by Ray to schedule and spawn workloads (in " +"our case Flower clients):" +msgstr "" +"通常情况下,您可能希望根据 FL 工作负载的复杂性(即计算和内存占用)来调整分配给客户端的资源。您可以在启动模拟时将参数 " +"`client_resources` 设置为 `start_simulation `_ 。Ray " "内部使用两个键来调度和生成工作负载(在我们的例子中是 Flower 客户端):" #: ../../source/how-to-run-simulations.rst:67 @@ -5632,31 +5982,29 @@ msgstr "让我们来看几个例子:" msgid "" "While the :code:`client_resources` can be used to control the degree of " "concurrency in your FL simulation, this does not stop you from running " -"dozens, hundreds or even thousands of clients in the same round and having " -"orders of magnitude more `dormant` (i.e. not participating in a round) " -"clients. Let's say you want to have 100 clients per round but your system " -"can only accommodate 8 clients concurrently. The :code:`VirtualClientEngine` " -"will schedule 100 jobs to run (each simulating a client sampled by the " -"strategy) and then will execute them in a resource-aware manner in batches " -"of 8." -msgstr "" -"虽然 :code:`client_resources` 可用来控制 FL 模拟的并发程度,但这并不能阻止您" -"在同一轮模拟中运行几十、几百甚至上千个客户端,并拥有数量级更多的 \"休眠\"" -"(即不参与一轮模拟)客户端。比方说,您希望每轮有 100 个客户端," -"但您的系统只能同时容纳 8 个客户端。:code:`VirtualClientEngine` 将安排运行 " -"100 " +"dozens, hundreds or even thousands of clients in the same round and " +"having orders of magnitude more `dormant` (i.e. not participating in a " +"round) clients. Let's say you want to have 100 clients per round but your" +" system can only accommodate 8 clients concurrently. The " +":code:`VirtualClientEngine` will schedule 100 jobs to run (each " +"simulating a client sampled by the strategy) and then will execute them " +"in a resource-aware manner in batches of 8." +msgstr "" +"虽然 :code:`client_resources` 可用来控制 FL " +"模拟的并发程度,但这并不能阻止您在同一轮模拟中运行几十、几百甚至上千个客户端,并拥有数量级更多的 " +"\"休眠\"(即不参与一轮模拟)客户端。比方说,您希望每轮有 100 个客户端,但您的系统只能同时容纳 8 " +"个客户端。:code:`VirtualClientEngine` 将安排运行 100 " "个工作(每个工作模拟策略采样的一个客户端),然后以资源感知的方式分批执行。" #: ../../source/how-to-run-simulations.rst:91 msgid "" "To understand all the intricate details on how resources are used to " -"schedule FL clients and how to define custom resources, please take a look " -"at the `Ray documentation `_." +"schedule FL clients and how to define custom resources, please take a " +"look at the `Ray documentation `_." msgstr "" -"要了解资源如何用于调度 FL 客户端以及如何定义自定义资源的所有复杂细节,请查看 " -"`Ray 文档 `_。" +"要了解资源如何用于调度 FL 客户端以及如何定义自定义资源的所有复杂细节,请查看 `Ray 文档 " +"`_。" #: ../../source/how-to-run-simulations.rst:94 msgid "Simulation examples" @@ -5664,27 +6012,26 @@ msgstr "模拟示例" #: ../../source/how-to-run-simulations.rst:96 msgid "" -"A few ready-to-run complete examples for Flower simulation in Tensorflow/" -"Keras and PyTorch are provided in the `Flower repository `_. You can run them on Google Colab too:" +"A few ready-to-run complete examples for Flower simulation in " +"Tensorflow/Keras and PyTorch are provided in the `Flower repository " +"`_. You can run them on Google Colab too:" msgstr "" -"在 Tensorflow/Keras 和 PyTorch 中进行 Flower " -"模拟的几个可随时运行的完整示例已在 `Flower 库 `_ 中提供。您也可以在 Google Colab 上运行它们:" +"在 Tensorflow/Keras 和 PyTorch 中进行 Flower 模拟的几个可随时运行的完整示例已在 `Flower 库 " +"`_ 中提供。您也可以在 Google Colab 上运行它们:" #: ../../source/how-to-run-simulations.rst:98 msgid "" -"`Tensorflow/Keras Simulation `_: 100 clients collaboratively train a MLP " -"model on MNIST." +"`Tensorflow/Keras Simulation " +"`_: 100 clients collaboratively train a MLP model on MNIST." msgstr "" -"Tensorflow/Keras模拟 `_:100个客户端在MNIST上协作训练一个MLP模型。" +"Tensorflow/Keras模拟 `_:100个客户端在MNIST上协作训练一个MLP模型。" #: ../../source/how-to-run-simulations.rst:99 msgid "" -"`PyTorch Simulation `_: 100 clients collaboratively train a CNN model on " +"`PyTorch Simulation `_: 100 clients collaboratively train a CNN model on " "MNIST." msgstr "" "PyTorch 模拟 `)" -msgstr "" -"在所有节点中都有一份数据集副本(更多相关信息请参阅 :ref:`模拟注意事项" -"`)" +"Have a copy of your dataset in all nodes (more about this in " +":ref:`simulation considerations `)" +msgstr "在所有节点中都有一份数据集副本(更多相关信息请参阅 :ref:`模拟注意事项`)" #: ../../source/how-to-run-simulations.rst:111 msgid "" -"Pass :code:`ray_init_args={\"address\"=\"auto\"}` to `start_simulation `_ so the :code:" -"`VirtualClientEngine` attaches to a running Ray instance." +"Pass :code:`ray_init_args={\"address\"=\"auto\"}` to `start_simulation " +"`_ so the " +":code:`VirtualClientEngine` attaches to a running Ray instance." msgstr "" "将 :code:`ray_init_args={\"address\"=\"auto\"}`传递给 `start_simulation `_ ,这样 :code:" -"`VirtualClientEngine`就会连接到正在运行的 Ray 实例。" +"api-flwr.html#flwr.simulation.start_simulation>`_ ,这样 " +":code:`VirtualClientEngine`就会连接到正在运行的 Ray 实例。" #: ../../source/how-to-run-simulations.rst:112 msgid "" -"Start Ray on you head node: on the terminal type :code:`ray start --head`. " -"This command will print a few lines, one of which indicates how to attach " -"other nodes to the head node." +"Start Ray on you head node: on the terminal type :code:`ray start " +"--head`. This command will print a few lines, one of which indicates how " +"to attach other nodes to the head node." msgstr "" "在头部节点上启动 Ray:在终端上输入 :code:`raystart--" "head`。该命令将打印几行输出,其中一行说明如何将其他节点连接到头部节点。" #: ../../source/how-to-run-simulations.rst:113 msgid "" -"Attach other nodes to the head node: copy the command shown after starting " -"the head and execute it on terminal of a new node: for example :code:`ray " -"start --address='192.168.1.132:6379'`" +"Attach other nodes to the head node: copy the command shown after " +"starting the head and execute it on terminal of a new node: for example " +":code:`ray start --address='192.168.1.132:6379'`" msgstr "" -"将其他节点附加到头部节点:复制启动头部后显示的命令,并在新节点的终端上执行:" -"例如 :code:`ray start --address='192.168.1.132:6379'`" +"将其他节点附加到头部节点:复制启动头部后显示的命令,并在新节点的终端上执行:例如 :code:`ray start " +"--address='192.168.1.132:6379'`" #: ../../source/how-to-run-simulations.rst:115 msgid "" "With all the above done, you can run your code from the head node as you " "would if the simulation was running on a single node." -msgstr "" -"完成上述所有操作后,您就可以在头部节点上运行代码了,就像在单个节点上运行模拟" -"一样。" +msgstr "完成上述所有操作后,您就可以在头部节点上运行代码了,就像在单个节点上运行模拟一样。" #: ../../source/how-to-run-simulations.rst:117 msgid "" -"Once your simulation is finished, if you'd like to dismantle your cluster " -"you simply need to run the command :code:`ray stop` in each node's terminal " -"(including the head node)." -msgstr "" -"模拟结束后,如果要拆除集群,只需在每个节点(包括头部节点)的终端运行 :code:" -"`ray stop` 命令即可。" +"Once your simulation is finished, if you'd like to dismantle your cluster" +" you simply need to run the command :code:`ray stop` in each node's " +"terminal (including the head node)." +msgstr "模拟结束后,如果要拆除集群,只需在每个节点(包括头部节点)的终端运行 :code:`ray stop` 命令即可。" #: ../../source/how-to-run-simulations.rst:120 msgid "Multi-node simulation good-to-know" @@ -5776,27 +6115,28 @@ msgstr "在此,我们列举了运行多节点 FL 模拟时的一些有趣功 #: ../../source/how-to-run-simulations.rst:124 msgid "" -"User :code:`ray status` to check all nodes connected to your head node as " -"well as the total resources available to the :code:`VirtualClientEngine`." +"User :code:`ray status` to check all nodes connected to your head node as" +" well as the total resources available to the " +":code:`VirtualClientEngine`." msgstr "" -"使用 :code:`ray status` 查看连接到头部节点的所有节点,以及 :code:" -"`VirtualClientEngine` 可用的总资源。" +"使用 :code:`ray status` 查看连接到头部节点的所有节点,以及 :code:`VirtualClientEngine` " +"可用的总资源。" #: ../../source/how-to-run-simulations.rst:126 msgid "" -"When attaching a new node to the head, all its resources (i.e. all CPUs, all " -"GPUs) will be visible by the head node. This means that the :code:" -"`VirtualClientEngine` can schedule as many `virtual` clients as that node " -"can possible run. In some settings you might want to exclude certain " -"resources from the simulation. You can do this by appending `--num-" -"cpus=` and/or `--num-gpus=` in any :" -"code:`ray start` command (including when starting the head)" +"When attaching a new node to the head, all its resources (i.e. all CPUs, " +"all GPUs) will be visible by the head node. This means that the " +":code:`VirtualClientEngine` can schedule as many `virtual` clients as " +"that node can possible run. In some settings you might want to exclude " +"certain resources from the simulation. You can do this by appending " +"`--num-cpus=` and/or `--num-" +"gpus=` in any :code:`ray start` command (including " +"when starting the head)" msgstr "" -"将新节点附加到头部节点时,头部节点将可见其所有资源(即所有 CPU 和 GPU)。这意" -"味着 :code:`VirtualClientEngine` 可以调度尽可能多的 \"虚拟 \"客户端来运行该节" -"点。在某些设置中,您可能希望将某些资源排除在模拟之外。为此,您可以在任何 :" -"code:`ray start` 命令(包括启动头部时)中添加 `--num-" -"cpus=`和/或 `--num-gpus=`" +"将新节点附加到头部节点时,头部节点将可见其所有资源(即所有 CPU 和 GPU)。这意味着 :code:`VirtualClientEngine`" +" 可以调度尽可能多的 \"虚拟 \"客户端来运行该节点。在某些设置中,您可能希望将某些资源排除在模拟之外。为此,您可以在任何 :code:`ray" +" start` 命令(包括启动头部时)中添加 `--num-cpus=`和/或 `--num-" +"gpus=`" #: ../../source/how-to-run-simulations.rst:132 msgid "Considerations for simulations" @@ -5804,24 +6144,22 @@ msgstr "模拟的注意事项" #: ../../source/how-to-run-simulations.rst:135 msgid "" -"We are actively working on these fronts so to make it trivial to run any FL " -"workload with Flower simulation." -msgstr "我们正在积极开展这些方面的工作,以便使 FL 工作负载与 Flower " -"模拟的运行变得轻而易举。" +"We are actively working on these fronts so to make it trivial to run any " +"FL workload with Flower simulation." +msgstr "我们正在积极开展这些方面的工作,以便使 FL 工作负载与 Flower 模拟的运行变得轻而易举。" #: ../../source/how-to-run-simulations.rst:138 msgid "" -"The current VCE allows you to run Federated Learning workloads in simulation " -"mode whether you are prototyping simple scenarios on your personal laptop or " -"you want to train a complex FL pipeline across multiple high-performance GPU " -"nodes. While we add more capabilities to the VCE, the points below highlight " -"some of the considerations to keep in mind when designing your FL pipeline " -"with Flower. We also highlight a couple of current limitations in our " -"implementation." -msgstr "" -"当前的 VCE 允许您在模拟模式下运行联邦学习工作负载,无论您是在个人笔记本电脑上" -"建立简单的场景原型,还是要在多个高性能 GPU 节点上训练复杂的 FL情景。" -"虽然我们为 VCE 增加了更多的功能,但以下几点强调了在使用 Flower 设计 FL " +"The current VCE allows you to run Federated Learning workloads in " +"simulation mode whether you are prototyping simple scenarios on your " +"personal laptop or you want to train a complex FL pipeline across " +"multiple high-performance GPU nodes. While we add more capabilities to " +"the VCE, the points below highlight some of the considerations to keep in" +" mind when designing your FL pipeline with Flower. We also highlight a " +"couple of current limitations in our implementation." +msgstr "" +"当前的 VCE 允许您在模拟模式下运行联邦学习工作负载,无论您是在个人笔记本电脑上建立简单的场景原型,还是要在多个高性能 GPU 节点上训练复杂的" +" FL情景。虽然我们为 VCE 增加了更多的功能,但以下几点强调了在使用 Flower 设计 FL " "时需要注意的一些事项。我们还强调了我们的实现中目前存在的一些局限性。" #: ../../source/how-to-run-simulations.rst:141 @@ -5830,29 +6168,28 @@ msgstr "GPU 资源" #: ../../source/how-to-run-simulations.rst:143 msgid "" -"The VCE assigns a share of GPU memory to a client that specifies the key :" -"code:`num_gpus` in :code:`client_resources`. This being said, Ray (used " +"The VCE assigns a share of GPU memory to a client that specifies the key " +":code:`num_gpus` in :code:`client_resources`. This being said, Ray (used " "internally by the VCE) is by default:" msgstr "" -"VCE 会为指定 :code:`client_resources` 中 :code:`num_gpus` 关键字的客户端分配 " -"GPU 内存份额。也就是说,Ray(VCE 内部使用)是默认的:" +"VCE 会为指定 :code:`client_resources` 中 :code:`num_gpus` 关键字的客户端分配 GPU " +"内存份额。也就是说,Ray(VCE 内部使用)是默认的:" #: ../../source/how-to-run-simulations.rst:146 msgid "" -"not aware of the total VRAM available on the GPUs. This means that if you " -"set :code:`num_gpus=0.5` and you have two GPUs in your system with different " -"(e.g. 32GB and 8GB) VRAM amounts, they both would run 2 clients concurrently." +"not aware of the total VRAM available on the GPUs. This means that if you" +" set :code:`num_gpus=0.5` and you have two GPUs in your system with " +"different (e.g. 32GB and 8GB) VRAM amounts, they both would run 2 clients" +" concurrently." msgstr "" -"不知道 GPU 上可用的总 VRAM。这意味着,如果您设置 :code:`num_gpus=0.5`,而系统" -"中有两个不同(如 32GB 和 8GB)VRAM 的 GPU,它们都将同时运行 2 个客户端。" +"不知道 GPU 上可用的总 VRAM。这意味着,如果您设置 :code:`num_gpus=0.5`,而系统中有两个不同(如 32GB 和 " +"8GB)VRAM 的 GPU,它们都将同时运行 2 个客户端。" #: ../../source/how-to-run-simulations.rst:147 msgid "" "not aware of other unrelated (i.e. not created by the VCE) workloads are " "running on the GPU. Two takeaways from this are:" -msgstr "" -"不知道 GPU 上正在运行其他无关(即不是由 VCE 创建)的工作负载。从中可以得到以" -"下两点启示:" +msgstr "不知道 GPU 上正在运行其他无关(即不是由 VCE 创建)的工作负载。从中可以得到以下两点启示:" #: ../../source/how-to-run-simulations.rst:149 msgid "" @@ -5860,27 +6197,28 @@ msgid "" "aggregation (by instance when making use of the `evaluate method `_)" msgstr "" -"您的 Flower 服务器可能需要 GPU 来评估聚合后的 \"全局模型\"(例如在使用 \"评估" -"方法\"`_时)" +"您的 Flower 服务器可能需要 GPU 来评估聚合后的 \"全局模型\"(例如在使用 \"评估方法\"`_时)" #: ../../source/how-to-run-simulations.rst:150 msgid "" "If you want to run several independent Flower simulations on the same " -"machine you need to mask-out your GPUs with :code:" -"`CUDA_VISIBLE_DEVICES=\"\"` when launching your experiment." +"machine you need to mask-out your GPUs with " +":code:`CUDA_VISIBLE_DEVICES=\"\"` when launching your " +"experiment." msgstr "" "如果您想在同一台机器上运行多个独立的 Flower 模拟,则需要在启动实验时使用 " ":code:`CUDA_VISIBLE_DEVICES=\"\"` 屏蔽 GPU。" #: ../../source/how-to-run-simulations.rst:153 msgid "" -"In addition, the GPU resource limits passed to :code:`client_resources` are " -"not `enforced` (i.e. they can be exceeded) which can result in the situation " -"of client using more VRAM than the ratio specified when starting the " -"simulation." +"In addition, the GPU resource limits passed to :code:`client_resources` " +"are not `enforced` (i.e. they can be exceeded) which can result in the " +"situation of client using more VRAM than the ratio specified when " +"starting the simulation." msgstr "" -"此外,传递给 :code:`client_resources` 的 GPU 资源限制并不是 \"强制 \"的(即可" -"以超出),这可能导致客户端使用的 VRAM 超过启动模拟时指定的比例。" +"此外,传递给 :code:`client_resources` 的 GPU 资源限制并不是 \"强制 \"的(即可以超出),这可能导致客户端使用的" +" VRAM 超过启动模拟时指定的比例。" #: ../../source/how-to-run-simulations.rst:156 msgid "TensorFlow with GPUs" @@ -5888,42 +6226,42 @@ msgstr "使用 GPU 的 TensorFlow" #: ../../source/how-to-run-simulations.rst:158 msgid "" -"When `using a GPU with TensorFlow `_ " -"nearly your entire GPU memory of all your GPUs visible to the process will " -"be mapped. This is done by TensorFlow for optimization purposes. However, in " -"settings such as FL simulations where we want to split the GPU into multiple " -"`virtual` clients, this is not a desirable mechanism. Luckily we can disable " -"this default behavior by `enabling memory growth `_." -msgstr "" -"在 TensorFlow `_ 中使用 GPU 时," -"几乎所有进程可见的 GPU 内存都将被映射。TensorFlow " -"这样做是出于优化目的。然而,在 FL 模拟等设置中,我们希望将 GPU 分割成多个 " -"\"虚拟 \"客户端,这并不是一个理想的机制。幸运的是,我们可以通过 `" -"启用内存增长 `_来禁用这一默认行为。" +"When `using a GPU with TensorFlow " +"`_ nearly your entire GPU memory of" +" all your GPUs visible to the process will be mapped. This is done by " +"TensorFlow for optimization purposes. However, in settings such as FL " +"simulations where we want to split the GPU into multiple `virtual` " +"clients, this is not a desirable mechanism. Luckily we can disable this " +"default behavior by `enabling memory growth " +"`_." +msgstr "" +"在 TensorFlow `_ 中使用 GPU 时,几乎所有进程可见的" +" GPU 内存都将被映射。TensorFlow 这样做是出于优化目的。然而,在 FL 模拟等设置中,我们希望将 GPU 分割成多个 \"虚拟 " +"\"客户端,这并不是一个理想的机制。幸运的是,我们可以通过 `启用内存增长 " +"`_来禁用这一默认行为。" #: ../../source/how-to-run-simulations.rst:160 msgid "" -"This would need to be done in the main process (which is where the server " -"would run) and in each Actor created by the VCE. By means of :code:" -"`actor_kwargs` we can pass the reserved key `\"on_actor_init_fn\"` in order " -"to specify a function to be executed upon actor initialization. In this " -"case, to enable GPU growth for TF workloads. It would look as follows:" +"This would need to be done in the main process (which is where the server" +" would run) and in each Actor created by the VCE. By means of " +":code:`actor_kwargs` we can pass the reserved key `\"on_actor_init_fn\"` " +"in order to specify a function to be executed upon actor initialization. " +"In this case, to enable GPU growth for TF workloads. It would look as " +"follows:" msgstr "" "这需要在主进程(也就是服务器运行的地方)和 VCE 创建的每个角色中完成。通过 " -":code:`actor_kwargs`,我们可以传递保留关键字`\"on_actor_init_fn\"" -"`,以指定在角色初始化时执行的函数。在本例中,为了使 TF 工作负载的 GPU " -"增长,它看起来如下:" +":code:`actor_kwargs`,我们可以传递保留关键字`\"on_actor_init_fn\"`,以指定在角色初始化时执行的函数。在本例中,为了使" +" TF 工作负载的 GPU 增长,它看起来如下:" #: ../../source/how-to-run-simulations.rst:179 msgid "" "This is precisely the mechanism used in `Tensorflow/Keras Simulation " -"`_ " -"example." +"`_ example." msgstr "" -"这正是 \"Tensorflow/Keras 模拟 `_\"示例中使用的机制。" +"这正是 \"Tensorflow/Keras 模拟 " +"`_\"示例中使用的机制。" #: ../../source/how-to-run-simulations.rst:183 msgid "Multi-node setups" @@ -5931,35 +6269,35 @@ msgstr "多节点设置" #: ../../source/how-to-run-simulations.rst:185 msgid "" -"The VCE does not currently offer a way to control on which node a particular " -"`virtual` client is executed. In other words, if more than a single node " -"have the resources needed by a client to run, then any of those nodes could " -"get the client workload scheduled onto. Later in the FL process (i.e. in a " -"different round) the same client could be executed by a different node. " -"Depending on how your clients access their datasets, this might require " -"either having a copy of all dataset partitions on all nodes or a dataset " -"serving mechanism (e.g. using nfs, a database) to circumvent data " -"duplication." -msgstr "" -"VCE 目前不提供控制特定 \"虚拟 \"客户端在哪个节点上执行的方法。换句话说,如果" -"不止一个节点拥有客户端运行所需的资源,那么这些节点中的任何一个都可能被调度到" -"客户端工作负载上。在 FL 进程的稍后阶段(即在另一轮中),同一客户端可以由不同" -"的节点执行。根据客户访问数据集的方式,这可能需要在所有节点上复制所有数据集分" -"区,或采用数据集服务机制(如使用 nfs 或数据库)来避免数据重复。" +"The VCE does not currently offer a way to control on which node a " +"particular `virtual` client is executed. In other words, if more than a " +"single node have the resources needed by a client to run, then any of " +"those nodes could get the client workload scheduled onto. Later in the FL" +" process (i.e. in a different round) the same client could be executed by" +" a different node. Depending on how your clients access their datasets, " +"this might require either having a copy of all dataset partitions on all " +"nodes or a dataset serving mechanism (e.g. using nfs, a database) to " +"circumvent data duplication." +msgstr "" +"VCE 目前不提供控制特定 \"虚拟 " +"\"客户端在哪个节点上执行的方法。换句话说,如果不止一个节点拥有客户端运行所需的资源,那么这些节点中的任何一个都可能被调度到客户端工作负载上。在 " +"FL " +"进程的稍后阶段(即在另一轮中),同一客户端可以由不同的节点执行。根据客户访问数据集的方式,这可能需要在所有节点上复制所有数据集分区,或采用数据集服务机制(如使用" +" nfs 或数据库)来避免数据重复。" #: ../../source/how-to-run-simulations.rst:187 msgid "" -"By definition virtual clients are `stateless` due to their ephemeral nature. " -"A client state can be implemented as part of the Flower client class but " -"users need to ensure this saved to persistent storage (e.g. a database, " -"disk) and that can be retrieve later by the same client regardless on which " -"node it is running from. This is related to the point above also since, in " -"some way, the client's dataset could be seen as a type of `state`." +"By definition virtual clients are `stateless` due to their ephemeral " +"nature. A client state can be implemented as part of the Flower client " +"class but users need to ensure this saved to persistent storage (e.g. a " +"database, disk) and that can be retrieve later by the same client " +"regardless on which node it is running from. This is related to the point" +" above also since, in some way, the client's dataset could be seen as a " +"type of `state`." msgstr "" -"根据定义,虚拟客户端是 \"无状态 \"的,因为它们具有即时性。客户机状态可以作为 " -"Flower 客户机类的一部分来实现,但用户需要确保将其保存到持久存储(如数据库、磁" -"盘)中,而且无论客户机在哪个节点上运行,都能在以后检索到。这也与上述观点有关" -",因为在某种程度上,客户端的数据集可以被视为一种 \"状态\"。" +"根据定义,虚拟客户端是 \"无状态 \"的,因为它们具有即时性。客户机状态可以作为 Flower " +"客户机类的一部分来实现,但用户需要确保将其保存到持久存储(如数据库、磁盘)中,而且无论客户机在哪个节点上运行,都能在以后检索到。这也与上述观点有关,因为在某种程度上,客户端的数据集可以被视为一种" +" \"状态\"。" #: ../../source/how-to-save-and-load-model-checkpoints.rst:2 msgid "Save and load model checkpoints" @@ -5967,12 +6305,10 @@ msgstr "保存和加载模型检查点" #: ../../source/how-to-save-and-load-model-checkpoints.rst:4 msgid "" -"Flower does not automatically save model updates on the server-side. This " -"how-to guide describes the steps to save (and load) model checkpoints in " -"Flower." -msgstr "" -"Flower 不会在服务器端自动保存模型更新。本指南将介绍在 Flower 中保存(和加载)" -"模型检查点的步骤。" +"Flower does not automatically save model updates on the server-side. This" +" how-to guide describes the steps to save (and load) model checkpoints in" +" Flower." +msgstr "Flower 不会在服务器端自动保存模型更新。本指南将介绍在 Flower 中保存(和加载)模型检查点的步骤。" #: ../../source/how-to-save-and-load-model-checkpoints.rst:8 msgid "Model checkpointing" @@ -5980,22 +6316,22 @@ msgstr "模型检查点" #: ../../source/how-to-save-and-load-model-checkpoints.rst:10 msgid "" -"Model updates can be persisted on the server-side by customizing :code:" -"`Strategy` methods. Implementing custom strategies is always an option, but " -"for many cases it may be more convenient to simply customize an existing " -"strategy. The following code example defines a new :code:`SaveModelStrategy` " -"which customized the existing built-in :code:`FedAvg` strategy. In " -"particular, it customizes :code:`aggregate_fit` by calling :code:" -"`aggregate_fit` in the base class (:code:`FedAvg`). It then continues to " -"save returned (aggregated) weights before it returns those aggregated " -"weights to the caller (i.e., the server):" -msgstr "" -"模型更新可通过自定义 :code:`Strategy` 方法在服务器端持久化。实现自定义策略始" -"终是一种选择,但在许多情况下,简单地自定义现有策略可能更方便。" -"下面的代码示例定义了一个新的 :code:`SaveModelStrategy`,它自定义了现有的内置 " -":code:`FedAvg` 策略。特别是,它通过调用基类(:code:`FedAvg`)中的 " -":code:`aggregate_fit` 来定制 :code:`aggregate_fit`。然后继续保存返回的(聚合" -")参数,然后再将这些聚合参数返回给调用者(即服务器):" +"Model updates can be persisted on the server-side by customizing " +":code:`Strategy` methods. Implementing custom strategies is always an " +"option, but for many cases it may be more convenient to simply customize " +"an existing strategy. The following code example defines a new " +":code:`SaveModelStrategy` which customized the existing built-in " +":code:`FedAvg` strategy. In particular, it customizes " +":code:`aggregate_fit` by calling :code:`aggregate_fit` in the base class " +"(:code:`FedAvg`). It then continues to save returned (aggregated) weights" +" before it returns those aggregated weights to the caller (i.e., the " +"server):" +msgstr "" +"模型更新可通过自定义 :code:`Strategy` " +"方法在服务器端持久化。实现自定义策略始终是一种选择,但在许多情况下,简单地自定义现有策略可能更方便。下面的代码示例定义了一个新的 " +":code:`SaveModelStrategy`,它自定义了现有的内置 :code:`FedAvg` " +"策略。特别是,它通过调用基类(:code:`FedAvg`)中的 :code:`aggregate_fit` 来定制 " +":code:`aggregate_fit`。然后继续保存返回的(聚合)参数,然后再将这些聚合参数返回给调用者(即服务器):" #: ../../source/how-to-save-and-load-model-checkpoints.rst:47 msgid "Save and load PyTorch checkpoints" @@ -6003,26 +6339,29 @@ msgstr "保存和加载 PyTorch 检查点" #: ../../source/how-to-save-and-load-model-checkpoints.rst:49 msgid "" -"Similar to the previous example but with a few extra steps, we'll show how " -"to store a PyTorch checkpoint we'll use the ``torch.save`` function. " -"Firstly, ``aggregate_fit`` returns a ``Parameters`` object that has to be " -"transformed into a list of NumPy ``ndarray``'s, then those are transformed " -"into the PyTorch ``state_dict`` following the ``OrderedDict`` class " -"structure." +"Similar to the previous example but with a few extra steps, we'll show " +"how to store a PyTorch checkpoint we'll use the ``torch.save`` function. " +"Firstly, ``aggregate_fit`` returns a ``Parameters`` object that has to be" +" transformed into a list of NumPy ``ndarray``'s, then those are " +"transformed into the PyTorch ``state_dict`` following the ``OrderedDict``" +" class structure." msgstr "" -"与前面的例子类似,但多了几个步骤,我们将展示如何存储一个 PyTorch 检查点,我们" -"将使用 ``torch.save`` 函数。首先,``aggregate_fit`` 返回一个 ``Parameters`` " -"对象,它必须被转换成一个 NumPy ``ndarray`` 的列表,然后这些对象按照 " -"``OrderedDict`` 类结构被转换成 PyTorch `state_dict` 对象。" +"与前面的例子类似,但多了几个步骤,我们将展示如何存储一个 PyTorch 检查点,我们将使用 ``torch.save`` " +"函数。首先,``aggregate_fit`` 返回一个 ``Parameters`` 对象,它必须被转换成一个 NumPy " +"``ndarray`` 的列表,然后这些对象按照 ``OrderedDict`` 类结构被转换成 PyTorch `state_dict` 对象。" #: ../../source/how-to-save-and-load-model-checkpoints.rst:85 msgid "" -"To load your progress, you simply append the following lines to your code. " -"Note that this will iterate over all saved checkpoints and load the latest " -"one:" +"To load your progress, you simply append the following lines to your " +"code. Note that this will iterate over all saved checkpoints and load the" +" latest one:" +msgstr "要加载进度,只需在代码中添加以下几行。请注意,这将遍历所有已保存的检查点,并加载最新的检查点:" + +#: ../../source/how-to-save-and-load-model-checkpoints.rst:97 +msgid "" +"Return/use this object of type ``Parameters`` wherever necessary, such as" +" in the ``initial_parameters`` when defining a ``Strategy``." msgstr "" -"要加载进度,只需在代码中添加以下几行。请注意,这将遍历所有已保存的检查点,并" -"加载最新的检查点:" #: ../../source/how-to-upgrade-to-flower-1.0.rst:2 msgid "Upgrade to Flower 1.0" @@ -6030,14 +6369,13 @@ msgstr "升级至 Flower 1.0" #: ../../source/how-to-upgrade-to-flower-1.0.rst:4 msgid "" -"Flower 1.0 is here. Along with new features, Flower 1.0 provides a stable " -"foundation for future growth. Compared to Flower 0.19 (and other 0.x series " -"releases), there are a few breaking changes that make it necessary to change " -"the code of existing 0.x-series projects." +"Flower 1.0 is here. Along with new features, Flower 1.0 provides a stable" +" foundation for future growth. Compared to Flower 0.19 (and other 0.x " +"series releases), there are a few breaking changes that make it necessary" +" to change the code of existing 0.x-series projects." msgstr "" -"Flower 1.0 正式发布。除了新功能,Flower 1.0 还为未来的发展奠定了稳定的基础。" -"与 Flower 0.19(以及其他 0.x 系列版本)相比,有一些破坏性改动需要修改现有 0." -"x 系列项目的代码。" +"Flower 1.0 正式发布。除了新功能,Flower 1.0 还为未来的发展奠定了稳定的基础。与 Flower 0.19(以及其他 0.x " +"系列版本)相比,有一些破坏性改动需要修改现有 0.x 系列项目的代码。" #: ../../source/how-to-upgrade-to-flower-1.0.rst:8 msgid "Install update" @@ -6045,8 +6383,8 @@ msgstr "安装更新" #: ../../source/how-to-upgrade-to-flower-1.0.rst:10 msgid "" -"Here's how to update an existing installation to Flower 1.0 using either pip " -"or Poetry:" +"Here's how to update an existing installation to Flower 1.0 using either " +"pip or Poetry:" msgstr "下面介绍如何使用 pip 或 Poetry 将现有安装更新到 Flower 1.0:" #: ../../source/how-to-upgrade-to-flower-1.0.rst:12 @@ -6057,15 +6395,13 @@ msgstr "pip: 安装时添加 ``-U``." msgid "" "``python -m pip install -U flwr`` (when using ``start_server`` and " "``start_client``)" -msgstr "" -"`python -m pip install -U flwr``(当使用`start_server`和`start_client`时)" +msgstr "`python -m pip install -U flwr``(当使用`start_server`和`start_client`时)" #: ../../source/how-to-upgrade-to-flower-1.0.rst:15 msgid "" "``python -m pip install -U flwr[simulation]`` (when using " "``start_simulation``)" -msgstr "" -"`python -m pip install -U flwr[simulation]``(当使用`start_simulation``时)" +msgstr "`python -m pip install -U flwr[simulation]``(当使用`start_simulation``时)" #: ../../source/how-to-upgrade-to-flower-1.0.rst:17 msgid "" @@ -6073,21 +6409,20 @@ msgid "" "reinstall (don't forget to delete ``poetry.lock`` via ``rm poetry.lock`` " "before running ``poetry install``)." msgstr "" -"Poetry:更新 ``pyproject.toml`` 中的 ``flwr`` 依赖包,然后重新安装(运行 ``" -"poetry install`` 前,别忘了通过 ``rm poetry.lock` 删除 ``poetry.lock`)。" +"Poetry:更新 ``pyproject.toml`` 中的 ``flwr`` 依赖包,然后重新安装(运行 ``poetry install``" +" 前,别忘了通过 ``rm poetry.lock` 删除 ``poetry.lock`)。" #: ../../source/how-to-upgrade-to-flower-1.0.rst:19 -msgid "" -"``flwr = \"^1.0.0\"`` (when using ``start_server`` and ``start_client``)" +msgid "``flwr = \"^1.0.0\"`` (when using ``start_server`` and ``start_client``)" msgstr "``flwr = \"^1.0.0\"`` (当使用 ``start_server` 和 ``start_client` 时)" #: ../../source/how-to-upgrade-to-flower-1.0.rst:20 msgid "" -"``flwr = { version = \"^1.0.0\", extras = [\"simulation\"] }`` (when using " -"``start_simulation``)" +"``flwr = { version = \"^1.0.0\", extras = [\"simulation\"] }`` (when " +"using ``start_simulation``)" msgstr "" -"``flwr = { version = \"^1.0.0\", extras = [\"simulation\"] }``(当使用" -"``start_simulation``时)" +"``flwr = { version = \"^1.0.0\", extras = [\"simulation\"] " +"}``(当使用``start_simulation``时)" #: ../../source/how-to-upgrade-to-flower-1.0.rst:24 msgid "Required changes" @@ -6111,13 +6446,13 @@ msgstr "将所有参数作为关键字参数传递(而不是位置参数)。 msgid "" "Flower 0.19 (positional arguments): ``start_client(\"127.0.0.1:8080\", " "FlowerClient())``" -msgstr "" -"Flower 0.19 (位置参数): ``start_client(\"127.0.0.1:8080\", FlowerClient())``" +msgstr "Flower 0.19 (位置参数): ``start_client(\"127.0.0.1:8080\", FlowerClient())``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:34 msgid "" "Flower 1.0 (keyword arguments): " -"``start_client(server_address=\"127.0.0.1:8080\", client=FlowerClient())``" +"``start_client(server_address=\"127.0.0.1:8080\", " +"client=FlowerClient())``" msgstr "" "Flower 1.0(关键字参数): ``start_client(server_address=\"127.0.0.1:8080\", " "client=FlowerClient())``" @@ -6135,8 +6470,8 @@ msgid "" "Subclasses of ``Client``: change ``def get_parameters(self):``` to ``def " "get_parameters(self, ins: GetParametersIns):``" msgstr "" -"客户端 \"的子类:将 \"get_parameters(self): \"改为 \"get_parameters(self, " -"ins: GetParametersIns):\"" +"客户端 \"的子类:将 \"get_parameters(self): \"改为 \"get_parameters(self, ins: " +"GetParametersIns):\"" #: ../../source/how-to-upgrade-to-flower-1.0.rst:43 msgid "Strategies / ``start_server`` / ``start_simulation``" @@ -6160,30 +6495,29 @@ msgstr "" #: ../../source/how-to-upgrade-to-flower-1.0.rst:48 msgid "" -"Flower 1.0: ``start_server(..., config=flwr.server." -"ServerConfig(num_rounds=3, round_timeout=600.0), ...)``" +"Flower 1.0: ``start_server(..., " +"config=flwr.server.ServerConfig(num_rounds=3, round_timeout=600.0), " +"...)``" msgstr "" -"Flower 1.0: ``start_server(..., config=flwr.server.ServerConfig(" -"num_rounds=3, round_timeout=600.0), ...)``" +"Flower 1.0: ``start_server(..., " +"config=flwr.server.ServerConfig(num_rounds=3, round_timeout=600.0), " +"...)``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:50 msgid "" "Replace ``num_rounds=1`` in ``start_simulation`` with the new " "``config=ServerConfig(...)`` (see previous item)" -msgstr "" -"将`start_simulation``中的`num_rounds=1``替换为新的`config=ServerConfig(...)`" -"(参见前一项)" +msgstr "将`start_simulation``中的`num_rounds=1``替换为新的`config=ServerConfig(...)`(参见前一项)" #: ../../source/how-to-upgrade-to-flower-1.0.rst:51 msgid "" "Remove ``force_final_distributed_eval`` parameter from calls to " -"``start_server``. Distributed evaluation on all clients can be enabled by " -"configuring the strategy to sample all clients for evaluation after the last " -"round of training." +"``start_server``. Distributed evaluation on all clients can be enabled by" +" configuring the strategy to sample all clients for evaluation after the " +"last round of training." msgstr "" -"删除调用 ``start_server`` 时的 ``force_final_distributed_eval` 参数。可以通过" -"配置策略,在最后一轮训练后对所有客户端进行抽样评估,从而启用对所有客户端的分" -"布式评估。" +"删除调用 ``start_server`` 时的 ``force_final_distributed_eval` " +"参数。可以通过配置策略,在最后一轮训练后对所有客户端进行抽样评估,从而启用对所有客户端的分布式评估。" #: ../../source/how-to-upgrade-to-flower-1.0.rst:52 msgid "Rename parameter/ndarray conversion functions:" @@ -6199,18 +6533,17 @@ msgstr "``weights_to_parameters`` --> ``ndarrays_to_parameters``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:57 msgid "" -"Strategy initialization: if the strategy relies on the default values for " -"``fraction_fit`` and ``fraction_evaluate``, set ``fraction_fit`` and " +"Strategy initialization: if the strategy relies on the default values for" +" ``fraction_fit`` and ``fraction_evaluate``, set ``fraction_fit`` and " "``fraction_evaluate`` manually to ``0.1``. Projects that do not manually " "create a strategy (by calling ``start_server`` or ``start_simulation`` " -"without passing a strategy instance) should now manually initialize FedAvg " -"with ``fraction_fit`` and ``fraction_evaluate`` set to ``0.1``." +"without passing a strategy instance) should now manually initialize " +"FedAvg with ``fraction_fit`` and ``fraction_evaluate`` set to ``0.1``." msgstr "" -"策略初始化:如果策略依赖于 ``fraction_fit`` 和 ``fraction_evaluate`` 的默认" -"值,请手动将 ``fraction_fit`` 和 ``fraction_evaluate`` 设置为 ``0.1``。未手动" -"创建策略的项目(调用 ``start_server` 或 ``start_simulation` 时未传递策略实" -"例)现在应手动初始化 FedAvg,并将 `fraction_fit` 和 `fraction_evaluate` 设为 " -"`0.1``。" +"策略初始化:如果策略依赖于 ``fraction_fit`` 和 ``fraction_evaluate`` 的默认值,请手动将 " +"``fraction_fit`` 和 ``fraction_evaluate`` 设置为 ``0.1``。未手动创建策略的项目(调用 " +"``start_server` 或 ``start_simulation` 时未传递策略实例)现在应手动初始化 FedAvg,并将 " +"`fraction_fit` 和 `fraction_evaluate` 设为 `0.1``。" #: ../../source/how-to-upgrade-to-flower-1.0.rst:58 msgid "Rename built-in strategy parameters (e.g., ``FedAvg``):" @@ -6235,8 +6568,8 @@ msgid "" "``configure_evaluate``, ``aggregate_evaluate``, and ``evaluate_fn``." msgstr "" "将 `rnd` 更名为 `server_round`。这会影响多个方法和函数,例如 " -"``configure_fit``、``aggregate_fit``、``configure_evaluate``、" -"`aggregate_evaluate`` 和 ``evaluate_fn``。" +"``configure_fit``、``aggregate_fit``、``configure_evaluate``、`aggregate_evaluate``" +" 和 ``evaluate_fn``。" #: ../../source/how-to-upgrade-to-flower-1.0.rst:65 msgid "Add ``server_round`` and ``config`` to ``evaluate_fn``:" @@ -6244,19 +6577,21 @@ msgstr "在 ``evaluate_fn` 中添加 ``server_round` 和 ``config`:" #: ../../source/how-to-upgrade-to-flower-1.0.rst:67 msgid "" -"Flower 0.19: ``def evaluate(parameters: NDArrays) -> Optional[Tuple[float, " -"Dict[str, Scalar]]]:``" +"Flower 0.19: ``def evaluate(parameters: NDArrays) -> " +"Optional[Tuple[float, Dict[str, Scalar]]]:``" msgstr "" -"Flower 0.19: ``def evaluate(parameters: NDArrays) -> Optional[Tuple[float, " -"Dict[str, Scalar]]]:``" +"Flower 0.19: ``def evaluate(parameters: NDArrays) -> " +"Optional[Tuple[float, Dict[str, Scalar]]]:``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:68 msgid "" -"Flower 1.0: ``def evaluate(server_round: int, parameters: NDArrays, config: " -"Dict[str, Scalar]) -> Optional[Tuple[float, Dict[str, Scalar]]]:``" +"Flower 1.0: ``def evaluate(server_round: int, parameters: NDArrays, " +"config: Dict[str, Scalar]) -> Optional[Tuple[float, Dict[str, " +"Scalar]]]:``" msgstr "" -"Flower 1.0: ``def evaluate(server_round: int, parameters: NDArrays, config: " -"Dict[str, Scalar]) -> Optional[Tuple[float, Dict[str, Scalar]]]:``" +"Flower 1.0: ``def evaluate(server_round: int, parameters: NDArrays, " +"config: Dict[str, Scalar]) -> Optional[Tuple[float, Dict[str, " +"Scalar]]]:``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:71 msgid "Custom strategies" @@ -6264,38 +6599,38 @@ msgstr "定制策略" #: ../../source/how-to-upgrade-to-flower-1.0.rst:73 msgid "" -"The type of parameter ``failures`` has changed from ``List[BaseException]`` " -"to ``List[Union[Tuple[ClientProxy, FitRes], BaseException]]`` (in " -"``aggregate_fit``) and ``List[Union[Tuple[ClientProxy, EvaluateRes], " -"BaseException]]`` (in ``aggregate_evaluate``)" +"The type of parameter ``failures`` has changed from " +"``List[BaseException]`` to ``List[Union[Tuple[ClientProxy, FitRes], " +"BaseException]]`` (in ``aggregate_fit``) and " +"``List[Union[Tuple[ClientProxy, EvaluateRes], BaseException]]`` (in " +"``aggregate_evaluate``)" msgstr "" -"参数``failures``的类型已从``List[BaseException]``变为" -"``List[Union[Tuple[ClientProxy, FitRes], BaseException]]``(在" -"``agregate_fit``中)和``List[Union[Tuple[ClientProxy, EvaluateRes], " -"BaseException]]``(在``agregate_evaluate``中)" +"参数``failures``的类型已从``List[BaseException]``变为``List[Union[Tuple[ClientProxy," +" FitRes], " +"BaseException]]``(在``agregate_fit``中)和``List[Union[Tuple[ClientProxy, " +"EvaluateRes], BaseException]]``(在``agregate_evaluate``中)" #: ../../source/how-to-upgrade-to-flower-1.0.rst:74 msgid "" "The ``Strategy`` method ``evaluate`` now receives the current round of " "federated learning/evaluation as the first parameter:" -msgstr "``Strategy``方法 " -"的``evaluate``现在会接收当前一轮联邦学习/评估作为第一个参数:" +msgstr "``Strategy``方法 的``evaluate``现在会接收当前一轮联邦学习/评估作为第一个参数:" #: ../../source/how-to-upgrade-to-flower-1.0.rst:76 msgid "" "Flower 0.19: ``def evaluate(self, parameters: Parameters) -> " "Optional[Tuple[float, Dict[str, Scalar]]]:``" msgstr "" -"Flower 0.19: ``def evaluate(self, parameters: Parameters) -> Optional[Tuple[" -"float, Dict[str, Scalar]]]:```" +"Flower 0.19: ``def evaluate(self, parameters: Parameters) -> " +"Optional[Tuple[float, Dict[str, Scalar]]]:```" #: ../../source/how-to-upgrade-to-flower-1.0.rst:77 msgid "" -"Flower 1.0: ``def evaluate(self, server_round: int, parameters: Parameters) -" -"> Optional[Tuple[float, Dict[str, Scalar]]]:``" +"Flower 1.0: ``def evaluate(self, server_round: int, parameters: " +"Parameters) -> Optional[Tuple[float, Dict[str, Scalar]]]:``" msgstr "" -"Flower 1.0: ``def evaluate(self, server_round: int, parameters: Parameters) -" -"> Optional[Tuple[float, Dict[str, Scalar]]]:``" +"Flower 1.0: ``def evaluate(self, server_round: int, parameters: " +"Parameters) -> Optional[Tuple[float, Dict[str, Scalar]]]:``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:80 msgid "Optional improvements" @@ -6310,12 +6645,11 @@ msgstr "除了上述必要的改动之外,还有一些潜在的改进措施: #: ../../source/how-to-upgrade-to-flower-1.0.rst:84 msgid "" "Remove \"placeholder\" methods from subclasses of ``Client`` or " -"``NumPyClient``. If you, for example, use server-side evaluation, then empy " -"placeholder implementations of ``evaluate`` are no longer necessary." +"``NumPyClient``. If you, for example, use server-side evaluation, then " +"empy placeholder implementations of ``evaluate`` are no longer necessary." msgstr "" -"删除 ``Client`` 或 ``NumPyClient`` 子类中的 \"占位符 \"方法" -"。例如,如果你使用服务器端评估,那么就不再需要``evaluate``的 \"空占位符 " -"\"实现。" +"删除 ``Client`` 或 ``NumPyClient`` 子类中的 \"占位符 " +"\"方法。例如,如果你使用服务器端评估,那么就不再需要``evaluate``的 \"空占位符 \"实现。" #: ../../source/how-to-upgrade-to-flower-1.0.rst:85 msgid "" @@ -6323,8 +6657,9 @@ msgid "" "``start_simulation(..., config=flwr.server.ServerConfig(num_rounds=3, " "round_timeout=600.0), ...)``" msgstr "" -"通过 ``start_simulation`` 配置循环超时: ``start_simulation(..., config=flwr." -"server.ServerConfig(num_rounds=3, round_timeout=600.0), ...)``" +"通过 ``start_simulation`` 配置循环超时: ``start_simulation(..., " +"config=flwr.server.ServerConfig(num_rounds=3, round_timeout=600.0), " +"...)``" #: ../../source/how-to-upgrade-to-flower-1.0.rst:89 msgid "Further help" @@ -6332,16 +6667,135 @@ msgstr "更多帮助" #: ../../source/how-to-upgrade-to-flower-1.0.rst:91 msgid "" -"Most official `Flower code examples `_ are already updated to Flower 1.0, they can serve as a " -"reference for using the Flower 1.0 API. If there are further questionsm, " -"`join the Flower Slack `_ and use the " -"channgel ``#questions``." +"Most official `Flower code examples " +"`_ are already updated" +" to Flower 1.0, they can serve as a reference for using the Flower 1.0 " +"API. If there are further questionsm, `join the Flower Slack " +"`_ and use the channgel ``#questions``." +msgstr "" +"大多数官方的 `Flower 代码示例 `_" +" 已经更新到 Flower 1.0,它们可以作为使用 Flower 1.0 API 的参考。如果还有其他问题,请加入 Flower Slack " +"`_ 并使用 \"#questions``\"。" + +#: ../../source/how-to-use-built-in-mods.rst:2 +msgid "Use Built-in Mods" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:4 +msgid "" +"**Note: This tutorial covers experimental features. The functionality and" +" interfaces may change in future versions.**" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:6 +msgid "" +"In this tutorial, we will learn how to utilize built-in mods to augment " +"the behavior of a ``ClientApp``. Mods (sometimes also called Modifiers) " +"allow us to perform operations before and after a task is processed in " +"the ``ClientApp``." +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:9 +msgid "What are Mods?" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:11 +msgid "" +"A Mod is a callable that wraps around a ``ClientApp``. It can manipulate " +"or inspect the incoming ``Message`` and the resulting outgoing " +"``Message``. The signature for a ``Mod`` is as follows:" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:18 +msgid "A typical mod function might look something like this:" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:31 +msgid "Using Mods" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:33 +msgid "To use mods in your ``ClientApp``, you can follow these steps:" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:36 +msgid "1. Import the required mods" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:38 +msgid "First, import the built-in mod you intend to use:" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:46 +msgid "2. Define your client function" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:48 +msgid "" +"Define your client function (``client_fn``) that will be wrapped by the " +"mod(s):" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:57 +msgid "3. Create the ``ClientApp`` with mods" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:59 +msgid "" +"Create your ``ClientApp`` and pass the mods as a list to the ``mods`` " +"argument. The order in which you provide the mods matters:" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:72 +#, fuzzy +msgid "Order of execution" +msgstr "停用" + +#: ../../source/how-to-use-built-in-mods.rst:74 +msgid "" +"When the ``ClientApp`` runs, the mods are executed in the order they are " +"provided in the list:" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:76 +msgid "``example_mod_1`` (outermost mod)" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:77 +msgid "``example_mod_2`` (next mod)" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:78 +msgid "" +"Message handler (core function that handles the incoming ``Message`` and " +"returns the outgoing ``Message``)" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:79 +msgid "``example_mod_2`` (on the way back)" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:80 +msgid "``example_mod_1`` (outermost mod on the way back)" +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:82 +msgid "" +"Each mod has a chance to inspect and modify the incoming ``Message`` " +"before passing it to the next mod, and likewise with the outgoing " +"``Message`` before returning it up the stack." +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:87 +msgid "" +"By following this guide, you have learned how to effectively use mods to " +"enhance your ``ClientApp``'s functionality. Remember that the order of " +"mods is crucial and affects how the input and output are processed." +msgstr "" + +#: ../../source/how-to-use-built-in-mods.rst:89 +msgid "Enjoy building more robust and flexible ``ClientApp``s with mods!" msgstr "" -"大多数官方的 `Flower 代码示例 `_ 已经更新到 Flower 1.0,它们可以作为使用 Flower 1.0 API " -"的参考。如果还有其他问题,请加入 Flower Slack `_ 并使用 \"#questions``\"。" #: ../../source/how-to-use-strategies.rst:2 msgid "Use strategies" @@ -6349,16 +6803,15 @@ msgstr "使用策略" #: ../../source/how-to-use-strategies.rst:4 msgid "" -"Flower allows full customization of the learning process through the :code:" -"`Strategy` abstraction. A number of built-in strategies are provided in the " -"core framework." -msgstr "Flower 允许通过 :code:`Strategy` " -"抽象类对学习过程进行完全定制。核心框架中提供了许多内置策略。" +"Flower allows full customization of the learning process through the " +":code:`Strategy` abstraction. A number of built-in strategies are " +"provided in the core framework." +msgstr "Flower 允许通过 :code:`Strategy` 抽象类对学习过程进行完全定制。核心框架中提供了许多内置策略。" #: ../../source/how-to-use-strategies.rst:6 msgid "" -"There are three ways to customize the way Flower orchestrates the learning " -"process on the server side:" +"There are three ways to customize the way Flower orchestrates the " +"learning process on the server side:" msgstr "有三种方法可以自定义 Flower 在服务器端协调学习过程的方式:" #: ../../source/how-to-use-strategies.rst:8 @@ -6381,27 +6834,23 @@ msgstr "使用现有策略" #: ../../source/how-to-use-strategies.rst:16 msgid "" -"Flower comes with a number of popular federated learning strategies built-" -"in. A built-in strategy can be instantiated as follows:" +"Flower comes with a number of popular federated learning strategies " +"built-in. A built-in strategy can be instantiated as follows:" msgstr "Flower 内置了许多流行的联邦学习策略。内置策略的实例化方法如下:" #: ../../source/how-to-use-strategies.rst:25 msgid "" -"This creates a strategy with all parameters left at their default values and " -"passes it to the :code:`start_server` function. It is usually recommended to " -"adjust a few parameters during instantiation:" -msgstr "" -"这会创建一个所有参数都保持默认值的策略,并将其传递给 :code:`start_server` 函" -"数。通常建议在实例化过程中调整一些参数:" +"This creates a strategy with all parameters left at their default values " +"and passes it to the :code:`start_server` function. It is usually " +"recommended to adjust a few parameters during instantiation:" +msgstr "这会创建一个所有参数都保持默认值的策略,并将其传递给 :code:`start_server` 函数。通常建议在实例化过程中调整一些参数:" #: ../../source/how-to-use-strategies.rst:42 msgid "" "Existing strategies provide several ways to customize their behaviour. " "Callback functions allow strategies to call user-provided code during " "execution." -msgstr "" -"现有的策略提供了多种自定义行为的方法。回调函数允许策略在执行过程中调用用户提" -"供的代码。" +msgstr "现有的策略提供了多种自定义行为的方法。回调函数允许策略在执行过程中调用用户提供的代码。" #: ../../source/how-to-use-strategies.rst:45 msgid "Configuring client fit and client evaluate" @@ -6410,37 +6859,36 @@ msgstr "配置客户匹配和客户评估" #: ../../source/how-to-use-strategies.rst:47 msgid "" "The server can pass new configuration values to the client each round by " -"providing a function to :code:`on_fit_config_fn`. The provided function will " -"be called by the strategy and must return a dictionary of configuration key " -"values pairs that will be sent to the client. It must return a dictionary of " -"arbitraty configuration values :code:`client.fit` and :code:`client." -"evaluate` functions during each round of federated learning." +"providing a function to :code:`on_fit_config_fn`. The provided function " +"will be called by the strategy and must return a dictionary of " +"configuration key values pairs that will be sent to the client. It must " +"return a dictionary of arbitraty configuration values :code:`client.fit`" +" and :code:`client.evaluate` functions during each round of federated " +"learning." msgstr "" -"服务器可以通过向 :code:`on_fit_config_fn` 提供一个函数,在每一轮向客户端传递" -"新的配置值。提供的函数将被策略调用,并且必须返回一个配置键值对的字典,该字典" -"将被发送到客户端。在每一轮联邦学习期间,它必须返回一个任意配置值 dictionary " -":code:`client.fit`和 :code:`client.evaluate`函数。" +"服务器可以通过向 :code:`on_fit_config_fn` " +"提供一个函数,在每一轮向客户端传递新的配置值。提供的函数将被策略调用,并且必须返回一个配置键值对的字典,该字典将被发送到客户端。在每一轮联邦学习期间,它必须返回一个任意配置值" +" dictionary :code:`client.fit`和 :code:`client.evaluate`函数。" #: ../../source/how-to-use-strategies.rst:75 msgid "" "The :code:`on_fit_config_fn` can be used to pass arbitrary configuration " "values from server to client, and poetentially change these values each " -"round, for example, to adjust the learning rate. The client will receive the " -"dictionary returned by the :code:`on_fit_config_fn` in its own :code:`client." -"fit()` function." +"round, for example, to adjust the learning rate. The client will receive " +"the dictionary returned by the :code:`on_fit_config_fn` in its own " +":code:`client.fit()` function." msgstr "" -":code:`on_fit_config_fn`可用于将任意配置值从服务器传递到客户端,并在每一轮改" -"变这些值,例如,调整学习率。客户端将在自己的 :code:`client.fit()` 函数中接收 " -":code:`on_fit_config_fn` 返回的字典。" +":code:`on_fit_config_fn`可用于将任意配置值从服务器传递到客户端,并在每一轮改变这些值,例如,调整学习率。客户端将在自己的 " +":code:`client.fit()` 函数中接收 :code:`on_fit_config_fn` 返回的字典。" #: ../../source/how-to-use-strategies.rst:78 msgid "" -"Similar to :code:`on_fit_config_fn`, there is also :code:" -"`on_evaluate_config_fn` to customize the configuration sent to :code:`client." -"evaluate()`" +"Similar to :code:`on_fit_config_fn`, there is also " +":code:`on_evaluate_config_fn` to customize the configuration sent to " +":code:`client.evaluate()`" msgstr "" -"与 :code:`on_fit_config_fn` 类似,还有 :code:`on_evaluate_config_fn` 用于定制" -"发送到 :code:`client.evaluate()` 的配置" +"与 :code:`on_fit_config_fn` 类似,还有 :code:`on_evaluate_config_fn` 用于定制发送到 " +":code:`client.evaluate()` 的配置" #: ../../source/how-to-use-strategies.rst:81 msgid "Configuring server-side evaluation" @@ -6448,18 +6896,18 @@ msgstr "配置服务器端评估" #: ../../source/how-to-use-strategies.rst:83 msgid "" -"Server-side evaluation can be enabled by passing an evaluation function to :" -"code:`evaluate_fn`." +"Server-side evaluation can be enabled by passing an evaluation function " +"to :code:`evaluate_fn`." msgstr "服务器端评估可通过向 :code:`evaluate_fn` 传递评估函数来启用。" #: ../../source/how-to-use-strategies.rst:89 msgid "" -"Writing a fully custom strategy is a bit more involved, but it provides the " -"most flexibility. Read the `Implementing Strategies `_ guide to learn more." +"Writing a fully custom strategy is a bit more involved, but it provides " +"the most flexibility. Read the `Implementing Strategies `_ guide to learn more." msgstr "" -"编写完全自定义的策略涉及的内容较多,但灵活性最高。阅读 `实施策略 _ 指南,了解更多信息。" +"编写完全自定义的策略涉及的内容较多,但灵活性最高。阅读 `实施策略 _ " +"指南,了解更多信息。" #: ../../source/index.rst:34 msgid "Tutorial" @@ -6473,35 +6921,35 @@ msgstr "快速入门教程" msgid "How-to guides" msgstr "操作指南" -#: ../../source/index.rst:95 +#: ../../source/index.rst:97 msgid "Legacy example guides" msgstr "旧版指南范例" -#: ../../source/index.rst:106 ../../source/index.rst:110 +#: ../../source/index.rst:108 ../../source/index.rst:112 msgid "Explanations" msgstr "说明" -#: ../../source/index.rst:122 +#: None:-1 msgid "API reference" msgstr "应用程序接口参考" -#: ../../source/index.rst:129 +#: ../../source/index.rst:137 msgid "Reference docs" msgstr "参考文档" -#: ../../source/index.rst:145 +#: ../../source/index.rst:153 msgid "Contributor tutorials" msgstr "贡献者教程" -#: ../../source/index.rst:152 +#: ../../source/index.rst:160 msgid "Contributor how-to guides" msgstr "投稿指南" -#: ../../source/index.rst:164 +#: ../../source/index.rst:173 msgid "Contributor explanations" msgstr "贡献者解释" -#: ../../source/index.rst:170 +#: ../../source/index.rst:179 msgid "Contributor references" msgstr "贡献者参考资料" @@ -6519,8 +6967,7 @@ msgstr "Flower 框架文档" msgid "" "Welcome to Flower's documentation. `Flower `_ is a " "friendly federated learning framework." -msgstr "欢迎访问 Flower 文档。`Flower `_ " -"是一个友好的联邦学习框架。" +msgstr "欢迎访问 Flower 文档。`Flower `_ 是一个友好的联邦学习框架。" #: ../../source/index.rst:11 msgid "Join the Flower Community" @@ -6531,9 +6978,7 @@ msgid "" "The Flower Community is growing quickly - we're a friendly group of " "researchers, engineers, students, professionals, academics, and other " "enthusiasts." -msgstr "" -"Flower 社区发展迅速--我们是一个由研究人员、工程师、学生、专业人士、学者和其他" -"爱好者组成的友好团体。" +msgstr "Flower 社区发展迅速--我们是一个由研究人员、工程师、学生、专业人士、学者和其他爱好者组成的友好团体。" #: ../../source/index.rst:15 msgid "Join us on Slack" @@ -6547,11 +6992,10 @@ msgstr "Flower 框架" msgid "" "The user guide is targeted at researchers and developers who want to use " "Flower to bring existing machine learning workloads into a federated " -"setting. One of Flower's design goals was to make this simple. Read on to " -"learn more." +"setting. One of Flower's design goals was to make this simple. Read on to" +" learn more." msgstr "" -"该用户指南面向希望使用 Flower " -"将现有机器学习工作负载引入联邦环境的研究人员和开发人员。Flower " +"该用户指南面向希望使用 Flower 将现有机器学习工作负载引入联邦环境的研究人员和开发人员。Flower " "的设计目标之一就是让这一切变得简单。请继续阅读,了解更多信息。" #: ../../source/index.rst:30 @@ -6560,31 +7004,31 @@ msgstr "教程" #: ../../source/index.rst:32 msgid "" -"A learning-oriented series of federated learning tutorials, the best place " -"to start." +"A learning-oriented series of federated learning tutorials, the best " +"place to start." msgstr "以学习为导向的联邦学习教程系列,最好的起点。" #: ../../source/index.rst:62 msgid "" -"QUICKSTART TUTORIALS: :doc:`PyTorch ` | :doc:" -"`TensorFlow ` | :doc:`🤗 Transformers " -"` | :doc:`JAX ` | :" -"doc:`Pandas ` | :doc:`fastai ` | :doc:`PyTorch Lightning ` | :doc:`MXNet ` | :doc:`scikit-learn " -"` | :doc:`XGBoost ` | :doc:`Android ` | :doc:`iOS " -"`" -msgstr "" -"快速入门教程: :doc:`PyTorch ` | :doc:`" -"TensorFlow ` | :doc:`🤗 Transformers " -"` | :doc:`JAX ` | " +"QUICKSTART TUTORIALS: :doc:`PyTorch ` | " +":doc:`TensorFlow ` | :doc:`🤗 Transformers" +" ` | :doc:`JAX ` | :doc:`Pandas ` | :doc:`fastai " +"` | :doc:`PyTorch Lightning ` | :doc:`MXNet `" +" | :doc:`scikit-learn ` | :doc:`XGBoost " +"` | :doc:`Android ` | :doc:`iOS `" +msgstr "" +"快速入门教程: :doc:`PyTorch ` | :doc:`TensorFlow " +"` | :doc:`🤗 Transformers ` | :doc:`JAX ` | " ":doc:`Pandas ` | :doc:`fastai ` | :doc:`PyTorch Lightning ` | :doc:`MXNet ` | :doc:`scikit-learn " -"` | :doc:`XGBoost ` | :doc:`Android ` | :doc:`iOS " -"`" +"quickstart-fastai>` | :doc:`PyTorch Lightning ` | :doc:`MXNet ` | :doc" +":`scikit-learn ` | :doc:`XGBoost " +"` | :doc:`Android ` | :doc:`iOS `" #: ../../source/index.rst:64 msgid "We also made video tutorials for PyTorch:" @@ -6596,33 +7040,40 @@ msgstr "还有 TensorFlow:" #: ../../source/index.rst:77 msgid "" -"Problem-oriented how-to guides show step-by-step how to achieve a specific " -"goal." +"Problem-oriented how-to guides show step-by-step how to achieve a " +"specific goal." msgstr "以问题为导向的 \"如何做 \"指南逐步展示如何实现特定目标。" -#: ../../source/index.rst:108 +#: ../../source/index.rst:110 msgid "" "Understanding-oriented concept guides explain and discuss key topics and " "underlying ideas behind Flower and collaborative AI." -msgstr "以理解为导向的概念指南解释并讨论了Flower和协作式人工智能背后的关键主题和基本" -"思想。" +msgstr "以理解为导向的概念指南解释并讨论了Flower和协作式人工智能背后的关键主题和基本思想。" -#: ../../source/index.rst:118 +#: ../../source/index.rst:120 msgid "References" msgstr "参考资料" -#: ../../source/index.rst:120 +#: ../../source/index.rst:122 msgid "Information-oriented API reference and other reference material." msgstr "以信息为导向的 API 参考资料和其他参考资料。" -#: ../../source/index.rst:140 +#: ../../source/index.rst:131::1 +msgid ":py:obj:`flwr `\\" +msgstr "" + +#: ../../source/index.rst:131::1 flwr:1 of +msgid "Flower main package." +msgstr "" + +#: ../../source/index.rst:148 msgid "Contributor docs" msgstr "贡献者文档" -#: ../../source/index.rst:142 +#: ../../source/index.rst:150 msgid "" -"The Flower community welcomes contributions. The following docs are intended " -"to help along the way." +"The Flower community welcomes contributions. The following docs are " +"intended to help along the way." msgstr "Flower 社区欢迎您的贡献。以下文档旨在为您提供帮助。" #: ../../source/ref-api-cli.rst:2 @@ -6641,27 +7092,285 @@ msgstr "flower-driver-api" msgid "flower-fleet-api" msgstr "flower-fleet-api" -#: ../../source/ref-api-flwr.rst:2 -msgid "flwr (Python API reference)" -msgstr "flwr(Python API 参考)" +#: ../../source/ref-api/flwr.rst:2 +#, fuzzy +msgid "flwr" +msgstr "Flower" + +#: ../../source/ref-api/flwr.rst:25 ../../source/ref-api/flwr.server.rst:48 +msgid "Modules" +msgstr "" -#: ../../source/ref-api-flwr.rst:8 -msgid "client" -msgstr "客户端" +#: ../../source/ref-api/flwr.rst:35::1 +msgid ":py:obj:`flwr.client `\\" +msgstr "" -#: flwr.client:1 of +#: ../../source/ref-api/flwr.rst:35::1 flwr.client:1 of msgid "Flower client." msgstr "Flower 客户端。" -#: flwr.client.client.Client:1 of -msgid "Abstract base class for Flower clients." -msgstr "Flower 客户端的抽象基类。" +#: ../../source/ref-api/flwr.rst:35::1 +msgid ":py:obj:`flwr.common `\\" +msgstr "" + +#: ../../source/ref-api/flwr.rst:35::1 flwr.common:1 of +msgid "Common components shared between server and client." +msgstr "服务器和客户端共享的通用组件。" + +#: ../../source/ref-api/flwr.rst:35::1 +msgid ":py:obj:`flwr.server `\\" +msgstr "" + +#: ../../source/ref-api/flwr.rst:35::1 +#: ../../source/ref-api/flwr.server.rst:37::1 flwr.server:1 +#: flwr.server.server.Server:1 of +msgid "Flower server." +msgstr "Flower 服务器。" + +#: ../../source/ref-api/flwr.rst:35::1 +msgid ":py:obj:`flwr.simulation `\\" +msgstr "" + +#: ../../source/ref-api/flwr.rst:35::1 flwr.simulation:1 of +#, fuzzy +msgid "Flower simulation." +msgstr "运行模拟" + +#: ../../source/ref-api/flwr.client.rst:2 +msgid "client" +msgstr "客户端" + +#: ../../source/ref-api/flwr.client.rst:13 +#: ../../source/ref-api/flwr.common.rst:13 +#: ../../source/ref-api/flwr.server.driver.rst:13 +#: ../../source/ref-api/flwr.server.rst:13 +#: ../../source/ref-api/flwr.simulation.rst:13 +#, fuzzy +msgid "Functions" +msgstr "四种函数:" + +#: ../../source/ref-api/flwr.client.rst:24::1 +msgid ":py:obj:`run_client_app `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.rst:24::1 +#: flwr.client.app.run_client_app:1 of +#, fuzzy +msgid "Run Flower client app." +msgstr "Flower 客户端。" + +#: ../../source/ref-api/flwr.client.rst:24::1 +msgid "" +":py:obj:`start_client `\\ \\(\\*\\, " +"server\\_address\\[\\, client\\_fn\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.rst:24::1 +#: flwr.client.app.start_client:1 of +msgid "Start a Flower client node which connects to a Flower server." +msgstr "启动一个 Flower 客户节点,连接到 Flower 服务器。" + +#: ../../source/ref-api/flwr.client.rst:24::1 +msgid "" +":py:obj:`start_numpy_client `\\ \\(\\*\\," +" server\\_address\\, client\\)" +msgstr "" +#: ../../source/ref-api/flwr.client.rst:24::1 +#: flwr.client.app.start_numpy_client:1 of +msgid "Start a Flower NumPyClient which connects to a gRPC server." +msgstr "启动 Flower NumPyClient,连接到 gRPC 服务器。" + +#: ../../source/ref-api/flwr.client.rst:26 +#: ../../source/ref-api/flwr.common.rst:31 +#: ../../source/ref-api/flwr.server.driver.rst:24 +#: ../../source/ref-api/flwr.server.rst:28 +#: ../../source/ref-api/flwr.server.strategy.rst:17 +msgid "Classes" +msgstr "" + +#: ../../source/ref-api/flwr.client.rst:33::1 +msgid ":py:obj:`Client `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.rst:33::1 +#: flwr.client.client.Client:1 of +msgid "Abstract base class for Flower clients." +msgstr "Flower 客户端的抽象基类。" + +#: ../../source/ref-api/flwr.client.rst:33::1 +msgid "" +":py:obj:`ClientApp `\\ \\(client\\_fn\\[\\, " +"mods\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.rst:33::1 +#: flwr.client.clientapp.ClientApp:1 of +#, fuzzy +msgid "Flower ClientApp." +msgstr "Flower 客户端。" + +#: ../../source/ref-api/flwr.client.rst:33::1 +msgid ":py:obj:`NumPyClient `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.rst:33::1 +#: flwr.client.numpy_client.NumPyClient:1 of +msgid "Abstract base class for Flower clients using NumPy." +msgstr "使用 NumPy 的 Flower 客户端的抽象基类。" + +#: flwr.client.client.Client:1 flwr.client.numpy_client.NumPyClient:1 +#: flwr.server.client_manager.ClientManager:1 +#: flwr.server.strategy.strategy.Strategy:1 of +msgid "Bases: :py:class:`~abc.ABC`" +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:15 +#: ../../source/ref-api/flwr.client.ClientApp.rst:15 +#: ../../source/ref-api/flwr.client.NumPyClient.rst:15 +#: ../../source/ref-api/flwr.common.ClientMessage.rst:15 +#: ../../source/ref-api/flwr.common.DisconnectRes.rst:15 +#: ../../source/ref-api/flwr.common.EvaluateIns.rst:15 +#: ../../source/ref-api/flwr.common.EvaluateRes.rst:15 +#: ../../source/ref-api/flwr.common.FitIns.rst:15 +#: ../../source/ref-api/flwr.common.FitRes.rst:15 +#: ../../source/ref-api/flwr.common.GetParametersIns.rst:15 +#: ../../source/ref-api/flwr.common.GetParametersRes.rst:15 +#: ../../source/ref-api/flwr.common.GetPropertiesIns.rst:15 +#: ../../source/ref-api/flwr.common.GetPropertiesRes.rst:15 +#: ../../source/ref-api/flwr.common.Parameters.rst:15 +#: ../../source/ref-api/flwr.common.ReconnectIns.rst:15 +#: ../../source/ref-api/flwr.common.ServerMessage.rst:15 +#: ../../source/ref-api/flwr.common.Status.rst:15 +#: ../../source/ref-api/flwr.server.ClientManager.rst:15 +#: ../../source/ref-api/flwr.server.History.rst:15 +#: ../../source/ref-api/flwr.server.Server.rst:15 +#: ../../source/ref-api/flwr.server.ServerConfig.rst:15 +#: ../../source/ref-api/flwr.server.SimpleClientManager.rst:15 +#: ../../source/ref-api/flwr.server.driver.Driver.rst:15 +#: ../../source/ref-api/flwr.server.driver.GrpcDriver.rst:15 +#: ../../source/ref-api/flwr.server.strategy.Bulyan.rst:15 +#: ../../source/ref-api/flwr.server.strategy.DPFedAvgAdaptive.rst:15 +#: ../../source/ref-api/flwr.server.strategy.DPFedAvgFixed.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FaultTolerantFedAvg.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedAdagrad.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedAdam.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedAvg.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedAvgAndroid.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedAvgM.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedMedian.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedOpt.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedProx.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedTrimmedAvg.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedXgbBagging.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedXgbCyclic.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedXgbNnAvg.rst:15 +#: ../../source/ref-api/flwr.server.strategy.FedYogi.rst:15 +#: ../../source/ref-api/flwr.server.strategy.Krum.rst:15 +#: ../../source/ref-api/flwr.server.strategy.QFedAvg.rst:15 +#: ../../source/ref-api/flwr.server.strategy.Strategy.rst:15 +msgid "Methods" +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +msgid ":py:obj:`evaluate `\\ \\(ins\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 #: flwr.client.client.Client.evaluate:1 #: flwr.client.numpy_client.NumPyClient.evaluate:1 of msgid "Evaluate the provided parameters using the locally held dataset." msgstr "使用本地数据集评估所提供的参数。" +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +msgid ":py:obj:`fit `\\ \\(ins\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +#: flwr.client.client.Client.fit:1 of +msgid "Refine the provided parameters using the locally held dataset." +msgstr "利用本地数据集完善所提供的参数。" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +msgid ":py:obj:`get_context `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +#: flwr.client.client.Client.get_context:1 +#: flwr.client.numpy_client.NumPyClient.get_context:1 of +#, fuzzy +msgid "Get the run context from this client." +msgstr "评估客户端的反应。" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +msgid ":py:obj:`get_parameters `\\ \\(ins\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +#: flwr.client.client.Client.get_parameters:1 +#: flwr.client.numpy_client.NumPyClient.get_parameters:1 of +msgid "Return the current local model parameters." +msgstr "返回当前本地模型参数。" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +msgid ":py:obj:`get_properties `\\ \\(ins\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +#: flwr.client.client.Client.get_properties:1 of +msgid "Return set of client's properties." +msgstr "返回客户端的属性集。" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +msgid ":py:obj:`set_context `\\ \\(context\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +#: flwr.client.client.Client.set_context:1 +#: flwr.client.numpy_client.NumPyClient.set_context:1 of +msgid "Apply a run context to this client." +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +msgid ":py:obj:`to_client `\\ \\(\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.Client.rst:44::1 +#: flwr.client.client.Client.to_client:1 of +msgid "Return client (itself)." +msgstr "返回客户端(本身)。" + +#: ../../source/ref-api/flwr.client.Client.rst:46 +#: ../../source/ref-api/flwr.client.NumPyClient.rst:46 +#: ../../source/ref-api/flwr.common.ClientMessage.rst:25 +#: ../../source/ref-api/flwr.common.Code.rst:19 +#: ../../source/ref-api/flwr.common.DisconnectRes.rst:25 +#: ../../source/ref-api/flwr.common.EvaluateIns.rst:25 +#: ../../source/ref-api/flwr.common.EvaluateRes.rst:25 +#: ../../source/ref-api/flwr.common.EventType.rst:19 +#: ../../source/ref-api/flwr.common.FitIns.rst:25 +#: ../../source/ref-api/flwr.common.FitRes.rst:25 +#: ../../source/ref-api/flwr.common.GetParametersIns.rst:25 +#: ../../source/ref-api/flwr.common.GetParametersRes.rst:25 +#: ../../source/ref-api/flwr.common.GetPropertiesIns.rst:25 +#: ../../source/ref-api/flwr.common.GetPropertiesRes.rst:25 +#: ../../source/ref-api/flwr.common.Parameters.rst:25 +#: ../../source/ref-api/flwr.common.ReconnectIns.rst:25 +#: ../../source/ref-api/flwr.common.ServerMessage.rst:25 +#: ../../source/ref-api/flwr.common.Status.rst:25 +#: ../../source/ref-api/flwr.server.ServerConfig.rst:25 +msgid "Attributes" +msgstr "" + +#: flwr.client.client.Client.evaluate:1::1 of +msgid ":py:obj:`context `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.Parameters.rst:2 #: flwr.client.app.start_client flwr.client.app.start_numpy_client #: flwr.client.client.Client.evaluate flwr.client.client.Client.fit #: flwr.client.client.Client.get_parameters @@ -6670,20 +7379,23 @@ msgstr "使用本地数据集评估所提供的参数。" #: flwr.client.numpy_client.NumPyClient.fit #: flwr.client.numpy_client.NumPyClient.get_parameters #: flwr.client.numpy_client.NumPyClient.get_properties -#: flwr.server.app.start_server flwr.server.strategy.bulyan.Bulyan.__init__ +#: flwr.server.app.start_server +#: flwr.server.client_manager.ClientManager.register +#: flwr.server.client_manager.ClientManager.unregister +#: flwr.server.client_manager.SimpleClientManager.register +#: flwr.server.client_manager.SimpleClientManager.unregister +#: flwr.server.client_manager.SimpleClientManager.wait_for +#: flwr.server.driver.app.start_driver flwr.server.driver.driver.Driver +#: flwr.server.strategy.bulyan.Bulyan #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit -#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__ -#: flwr.server.strategy.fedadagrad.FedAdagrad.__init__ -#: flwr.server.strategy.fedadam.FedAdam.__init__ -#: flwr.server.strategy.fedavg.FedAvg.__init__ -#: flwr.server.strategy.fedavgm.FedAvgM.__init__ -#: flwr.server.strategy.fedopt.FedOpt.__init__ -#: flwr.server.strategy.fedprox.FedProx.__init__ -#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg.__init__ -#: flwr.server.strategy.fedyogi.FedYogi.__init__ -#: flwr.server.strategy.krum.Krum.__init__ -#: flwr.server.strategy.qfedavg.QFedAvg.__init__ +#: flwr.server.strategy.fedadagrad.FedAdagrad +#: flwr.server.strategy.fedadam.FedAdam flwr.server.strategy.fedavg.FedAvg +#: flwr.server.strategy.fedavg_android.FedAvgAndroid +#: flwr.server.strategy.fedavgm.FedAvgM flwr.server.strategy.fedopt.FedOpt +#: flwr.server.strategy.fedprox.FedProx +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg +#: flwr.server.strategy.fedyogi.FedYogi flwr.server.strategy.krum.Krum #: flwr.server.strategy.strategy.Strategy.aggregate_evaluate #: flwr.server.strategy.strategy.Strategy.aggregate_fit #: flwr.server.strategy.strategy.Strategy.configure_evaluate @@ -6696,12 +7408,10 @@ msgstr "参数" #: flwr.client.client.Client.evaluate:3 of msgid "" -"The evaluation instructions containing (global) model parameters received " -"from the server and a dictionary of configuration values used to customize " -"the local evaluation process." -msgstr "" -"评估指令包含从服务器接收的(全局)模型参数,以及用于定制本地评估流程的配置值" -"字典。" +"The evaluation instructions containing (global) model parameters received" +" from the server and a dictionary of configuration values used to " +"customize the local evaluation process." +msgstr "评估指令包含从服务器接收的(全局)模型参数,以及用于定制本地评估流程的配置值字典。" #: flwr.client.client.Client.evaluate flwr.client.client.Client.fit #: flwr.client.client.Client.get_parameters @@ -6711,6 +7421,12 @@ msgstr "" #: flwr.client.numpy_client.NumPyClient.get_parameters #: flwr.client.numpy_client.NumPyClient.get_properties #: flwr.server.app.start_server +#: flwr.server.client_manager.ClientManager.num_available +#: flwr.server.client_manager.ClientManager.register +#: flwr.server.client_manager.SimpleClientManager.num_available +#: flwr.server.client_manager.SimpleClientManager.register +#: flwr.server.client_manager.SimpleClientManager.wait_for +#: flwr.server.driver.app.start_driver #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit #: flwr.server.strategy.strategy.Strategy.aggregate_evaluate @@ -6735,6 +7451,12 @@ msgstr "评估结果包含本地数据集上的损失值和其他详细信息, #: flwr.client.numpy_client.NumPyClient.get_parameters #: flwr.client.numpy_client.NumPyClient.get_properties #: flwr.server.app.start_server +#: flwr.server.client_manager.ClientManager.num_available +#: flwr.server.client_manager.ClientManager.register +#: flwr.server.client_manager.SimpleClientManager.num_available +#: flwr.server.client_manager.SimpleClientManager.register +#: flwr.server.client_manager.SimpleClientManager.wait_for +#: flwr.server.driver.app.start_driver #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit #: flwr.server.strategy.strategy.Strategy.aggregate_evaluate @@ -6747,30 +7469,19 @@ msgstr "评估结果包含本地数据集上的损失值和其他详细信息, msgid "Return type" msgstr "返回类型" -#: flwr.client.client.Client.fit:1 of -msgid "Refine the provided parameters using the locally held dataset." -msgstr "利用本地数据集完善所提供的参数。" - #: flwr.client.client.Client.fit:3 of msgid "" -"The training instructions containing (global) model parameters received from " -"the server and a dictionary of configuration values used to customize the " -"local training process." -msgstr "" -"训练指令,包含从服务器接收的(全局)模型参数,以及用于定制本地训练过程的配置" -"值字典。" +"The training instructions containing (global) model parameters received " +"from the server and a dictionary of configuration values used to " +"customize the local training process." +msgstr "训练指令,包含从服务器接收的(全局)模型参数,以及用于定制本地训练过程的配置值字典。" #: flwr.client.client.Client.fit:8 of msgid "" -"The training result containing updated parameters and other details such as " -"the number of local training examples used for training." +"The training result containing updated parameters and other details such " +"as the number of local training examples used for training." msgstr "训练结果包含更新的参数和其他详细信息,如用于训练的本地训练示例的数量。" -#: flwr.client.client.Client.get_parameters:1 -#: flwr.client.numpy_client.NumPyClient.get_parameters:1 of -msgid "Return the current local model parameters." -msgstr "返回当前本地模型参数。" - #: flwr.client.client.Client.get_parameters:3 of msgid "" "The get parameters instructions received from the server containing a " @@ -6781,10 +7492,6 @@ msgstr "从服务器接收的获取参数指令包含配置值字典。" msgid "The current local model parameters." msgstr "当前的本地模型参数。" -#: flwr.client.client.Client.get_properties:1 of -msgid "Return set of client's properties." -msgstr "返回客户端的属性集。" - #: flwr.client.client.Client.get_properties:3 of msgid "" "The get properties instructions received from the server containing a " @@ -6795,92 +7502,108 @@ msgstr "从服务器接收的获取属性指令包含配置值字典。" msgid "The current client properties." msgstr "当前客户端属性。" -#: flwr.client.client.Client.to_client:1 of -msgid "Return client (itself)." -msgstr "返回客户端(本身)。" +#: ../../source/ref-api/flwr.client.ClientApp.rst:2 +#, fuzzy +msgid "ClientApp" +msgstr "客户端" -#: ../../source/ref-api-flwr.rst:24 -msgid "start_client" -msgstr "启动客户端" +#: flwr.client.clientapp.ClientApp:1 flwr.common.typing.ClientMessage:1 +#: flwr.common.typing.DisconnectRes:1 flwr.common.typing.EvaluateIns:1 +#: flwr.common.typing.EvaluateRes:1 flwr.common.typing.FitIns:1 +#: flwr.common.typing.FitRes:1 flwr.common.typing.GetParametersIns:1 +#: flwr.common.typing.GetParametersRes:1 flwr.common.typing.GetPropertiesIns:1 +#: flwr.common.typing.GetPropertiesRes:1 flwr.common.typing.Parameters:1 +#: flwr.common.typing.ReconnectIns:1 flwr.common.typing.ServerMessage:1 +#: flwr.common.typing.Status:1 flwr.server.app.ServerConfig:1 +#: flwr.server.driver.driver.Driver:1 +#: flwr.server.driver.grpc_driver.GrpcDriver:1 flwr.server.history.History:1 +#: flwr.server.server.Server:1 of +msgid "Bases: :py:class:`object`" +msgstr "" + +#: flwr.client.app.start_client:33 flwr.client.app.start_numpy_client:36 +#: flwr.client.clientapp.ClientApp:4 flwr.server.app.start_server:41 +#: flwr.server.driver.app.start_driver:30 of +msgid "Examples" +msgstr "实例" -#: flwr.client.app.start_client:1 of -msgid "Start a Flower client node which connects to a Flower server." -msgstr "启动一个 Flower 客户节点,连接到 Flower 服务器。" +#: flwr.client.clientapp.ClientApp:5 of +msgid "" +"Assuming a typical `Client` implementation named `FlowerClient`, you can " +"wrap it in a `ClientApp` as follows:" +msgstr "" -#: flwr.client.app.start_client:3 flwr.client.app.start_numpy_client:3 of +#: flwr.client.clientapp.ClientApp:16 of msgid "" -"The IPv4 or IPv6 address of the server. If the Flower server runs on the " -"same machine on port 8080, then `server_address` would be `\"[::]:8080\"`." +"If the above code is in a Python module called `client`, it can be " +"started as follows:" msgstr "" -"服务器的 IPv4 或 IPv6 地址:如果 Flower 服务器在同一台机器上运行,端口为 " -"8080,则`server_address`应为`\"[::]:8080\"`。" -#: flwr.client.app.start_client:7 of -msgid "..." -msgstr "..." +#: flwr.client.clientapp.ClientApp:21 of +msgid "" +"In this `client:app` example, `client` refers to the Python module " +"`client.py` in which the previous code lives in and `app` refers to the " +"global attribute `app` that points to an object of type `ClientApp`." +msgstr "" -#: flwr.client.app.start_client:9 of -msgid "A callable that instantiates a Client. (default: None)" -msgstr "用于实例化客户端的可调用程序。(默认值:无)" +#: ../../source/ref-api/flwr.client.NumPyClient.rst:2 +msgid "NumPyClient" +msgstr "NumPyClient" -#: flwr.client.app.start_client:11 of +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 msgid "" -"An implementation of the abstract base class `flwr.client.Client` (default: " -"None)" -msgstr "抽象基类 `flwr.client.Client` 的实现(默认值:无)" +":py:obj:`evaluate `\\ \\(parameters\\, " +"config\\)" +msgstr "" -#: flwr.client.app.start_client:14 flwr.client.app.start_numpy_client:9 of -msgid "" -"The maximum length of gRPC messages that can be exchanged with the Flower " -"server. The default should be sufficient for most models. Users who train " -"very large models might need to increase this value. Note that the Flower " -"server needs to be started with the same value (see `flwr.server." -"start_server`), otherwise it will not know about the increased limit and " -"block larger messages." +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +msgid ":py:obj:`fit `\\ \\(parameters\\, config\\)" +msgstr "" + +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +#: flwr.client.numpy_client.NumPyClient.fit:1 of +msgid "Train the provided parameters using the locally held dataset." +msgstr "使用本地数据集训练所提供的参数。" + +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +msgid ":py:obj:`get_context `\\ \\(\\)" msgstr "" -"可与 Flower 服务器交换的 gRPC 信息的最大长度:默认值对大多数模型都足够了。训" -"练超大模型的用户可能需要增加该值。请注意,Flower 服务器需要以相同的值启动(" -"请参阅 `flwr.server." -"start_server`),否则它将不知道增加的限制并阻止更大的消息。" -#: flwr.client.app.start_client:21 flwr.client.app.start_numpy_client:16 of +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 msgid "" -"The PEM-encoded root certificates as a byte string or a path string. If " -"provided, a secure connection using the certificates will be established to " -"an SSL-enabled Flower server." +":py:obj:`get_parameters `\\ " +"\\(config\\)" msgstr "" -"字节字符串或路径字符串形式的 PEM 编码根证书。如果提供,将使用这些证书与启用 " -"SSL 的 Flower 服务器建立安全连接。" -#: flwr.client.app.start_client:25 flwr.client.app.start_numpy_client:20 of +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 msgid "" -"Configure the transport layer. Allowed values: - 'grpc-bidi': gRPC, " -"bidirectional streaming - 'grpc-rere': gRPC, request-response (experimental) " -"- 'rest': HTTP (experimental)" +":py:obj:`get_properties `\\ " +"\\(config\\)" msgstr "" -"配置传输层:允许的值包括 - 'grpc-bidi': gRPC,双向流 - 'grpc-rere': " -"gRPC,请求-响应(实验性) - 'rest': HTTP(实验性)" -#: flwr.client.app.start_client:32 flwr.client.app.start_numpy_client:27 -#: flwr.server.app.start_server:41 of -msgid "Examples" -msgstr "实例" +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +#: flwr.client.numpy_client.NumPyClient.get_properties:1 of +msgid "Return a client's set of properties." +msgstr "返回客户端的属性集。" -#: flwr.client.app.start_client:33 of -msgid "Starting a gRPC client with an insecure server connection:" -msgstr "使用不安全的服务器连接启动 gRPC 客户端:" +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +msgid "" +":py:obj:`set_context `\\ " +"\\(context\\)" +msgstr "" -#: flwr.client.app.start_client:43 flwr.client.app.start_numpy_client:35 of -msgid "Starting an SSL-enabled gRPC client:" -msgstr "启动支持 SSL 的 gRPC 客户端:" +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +msgid ":py:obj:`to_client `\\ \\(\\)" +msgstr "" -#: ../../source/ref-api-flwr.rst:32 -msgid "NumPyClient" -msgstr "NumPyClient" +#: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 +#: flwr.client.numpy_client.NumPyClient.to_client:1 of +msgid "Convert to object to Client type and return it." +msgstr "将对象转换为客户类型并返回。" -#: flwr.client.numpy_client.NumPyClient:1 of -msgid "Abstract base class for Flower clients using NumPy." -msgstr "使用 NumPy 的 Flower 客户端的抽象基类。" +#: flwr.client.numpy_client.NumPyClient.evaluate:1::1 of +msgid ":py:obj:`context `\\" +msgstr "" #: flwr.client.numpy_client.NumPyClient.evaluate:3 #: flwr.client.numpy_client.NumPyClient.fit:3 @@ -6894,30 +7617,28 @@ msgstr "当前(全局)模型参数。" #: flwr.client.numpy_client.NumPyClient.evaluate:5 of msgid "" -"Configuration parameters which allow the server to influence evaluation on " -"the client. It can be used to communicate arbitrary values from the server " -"to the client, for example, to influence the number of examples used for " -"evaluation." -msgstr "" -"允许服务器影响客户端评估的配置参数。它可用于将任意值从服务器传送到客户端,例" -"如,影响用于评估的示例数量。" +"Configuration parameters which allow the server to influence evaluation " +"on the client. It can be used to communicate arbitrary values from the " +"server to the client, for example, to influence the number of examples " +"used for evaluation." +msgstr "允许服务器影响客户端评估的配置参数。它可用于将任意值从服务器传送到客户端,例如,影响用于评估的示例数量。" #: flwr.client.numpy_client.NumPyClient.evaluate:11 of msgid "" "* **loss** (*float*) -- The evaluation loss of the model on the local " "dataset. * **num_examples** (*int*) -- The number of examples used for " "evaluation. * **metrics** (*Dict[str, Scalar]*) -- A dictionary mapping " -"arbitrary string keys to values of type bool, bytes, float, int, or str. " -"It can be used to communicate arbitrary values back to the server." +"arbitrary string keys to values of type bool, bytes, float, int, or " +"str. It can be used to communicate arbitrary values back to the server." msgstr "" -"**loss** (*float*) -- 模型在本地数据集上的评估损失值。**num_examples** " -"(*int*) -- 用于评估的示例数量。**metrics** (*Dict[str, Scalar]*) -- " -"将任意字符串键映射到 bool、bytes、float、int 或 str " -"类型值的字典。它可用于将任意值传回服务器。" +"**loss** (*float*) -- 模型在本地数据集上的评估损失值。**num_examples** (*int*) -- " +"用于评估的示例数量。**metrics** (*Dict[str, Scalar]*) -- 将任意字符串键映射到 " +"bool、bytes、float、int 或 str 类型值的字典。它可用于将任意值传回服务器。" #: flwr.client.numpy_client.NumPyClient.evaluate:11 of msgid "" -"**loss** (*float*) -- The evaluation loss of the model on the local dataset." +"**loss** (*float*) -- The evaluation loss of the model on the local " +"dataset." msgstr "**loss** (*float*) -- 模型在本地数据集上的评估损失值。" #: flwr.client.numpy_client.NumPyClient.evaluate:12 of @@ -6927,46 +7648,41 @@ msgstr "**num_examples** (*int*) -- 用于评估的示例数量。" #: flwr.client.numpy_client.NumPyClient.evaluate:13 #: flwr.client.numpy_client.NumPyClient.fit:13 of msgid "" -"**metrics** (*Dict[str, Scalar]*) -- A dictionary mapping arbitrary string " -"keys to values of type bool, bytes, float, int, or str. It can be used to " -"communicate arbitrary values back to the server." +"**metrics** (*Dict[str, Scalar]*) -- A dictionary mapping arbitrary " +"string keys to values of type bool, bytes, float, int, or str. It can be " +"used to communicate arbitrary values back to the server." msgstr "" -"**metrics** (*Dict[str, Scalar]*) -- 将任意字符串键映射到 bool、bytes、" -"float、int 或 str 类型值的字典。它可用于将任意值传回服务器。" +"**metrics** (*Dict[str, Scalar]*) -- 将任意字符串键映射到 bool、bytes、float、int 或 " +"str 类型值的字典。它可用于将任意值传回服务器。" #: flwr.client.numpy_client.NumPyClient.evaluate:19 of msgid "" -"The previous return type format (int, float, float) and the extended format " -"(int, float, float, Dict[str, Scalar]) have been deprecated and removed " -"since Flower 0.19." +"The previous return type format (int, float, float) and the extended " +"format (int, float, float, Dict[str, Scalar]) have been deprecated and " +"removed since Flower 0.19." msgstr "" -"自 Flower 0.19 起,之前的返回类型格式(int、float、float)和扩展格式(int、" -"float、float、Dict[str, Scalar])已被弃用和移除。" - -#: flwr.client.numpy_client.NumPyClient.fit:1 of -msgid "Train the provided parameters using the locally held dataset." -msgstr "使用本地数据集训练所提供的参数。" +"自 Flower 0.19 起,之前的返回类型格式(int、float、float)和扩展格式(int、float、float、Dict[str," +" Scalar])已被弃用和移除。" #: flwr.client.numpy_client.NumPyClient.fit:5 of msgid "" -"Configuration parameters which allow the server to influence training on the " -"client. It can be used to communicate arbitrary values from the server to " -"the client, for example, to set the number of (local) training epochs." -msgstr "允许服务器影响客户端训练的配置参数。它可用于将任意值从服务器传送到客户端,例" -"如设置(本地)训练遍历数。" +"Configuration parameters which allow the server to influence training on " +"the client. It can be used to communicate arbitrary values from the " +"server to the client, for example, to set the number of (local) training " +"epochs." +msgstr "允许服务器影响客户端训练的配置参数。它可用于将任意值从服务器传送到客户端,例如设置(本地)训练遍历数。" #: flwr.client.numpy_client.NumPyClient.fit:11 of msgid "" "* **parameters** (*NDArrays*) -- The locally updated model parameters. * " "**num_examples** (*int*) -- The number of examples used for training. * " -"**metrics** (*Dict[str, Scalar]*) -- A dictionary mapping arbitrary string " -"keys to values of type bool, bytes, float, int, or str. It can be used to " -"communicate arbitrary values back to the server." +"**metrics** (*Dict[str, Scalar]*) -- A dictionary mapping arbitrary " +"string keys to values of type bool, bytes, float, int, or str. It can " +"be used to communicate arbitrary values back to the server." msgstr "" -"**parameters** (*NDArrays*) -- 本地更新的模型参数。**num_examples** (*int*) " -"-- 用于训练的示例数量。**metrics** (*Dict[str, Scalar]*) -- 将任意字符串键映" -"射到 bool、bytes、float、int 或 str 类型值的字典。它可用于将任意值传回服务" -"器。" +"**parameters** (*NDArrays*) -- 本地更新的模型参数。**num_examples** (*int*) -- " +"用于训练的示例数量。**metrics** (*Dict[str, Scalar]*) -- 将任意字符串键映射到 " +"bool、bytes、float、int 或 str 类型值的字典。它可用于将任意值传回服务器。" #: flwr.client.numpy_client.NumPyClient.fit:11 of msgid "**parameters** (*NDArrays*) -- The locally updated model parameters." @@ -6978,1521 +7694,4747 @@ msgstr "**num_examples** (*int*) -- 用于训练的数据数量。" #: flwr.client.numpy_client.NumPyClient.get_parameters:3 of msgid "" -"Configuration parameters requested by the server. This can be used to tell " -"the client which parameters are needed along with some Scalar attributes." -msgstr "" -"服务器请求的配置参数。这可以用来告诉客户端需要哪些参数以及一些标量属性。" +"Configuration parameters requested by the server. This can be used to " +"tell the client which parameters are needed along with some Scalar " +"attributes." +msgstr "服务器请求的配置参数。这可以用来告诉客户端需要哪些参数以及一些标量属性。" #: flwr.client.numpy_client.NumPyClient.get_parameters:8 of -msgid "" -"**parameters** -- The local model parameters as a list of NumPy ndarrays." +msgid "**parameters** -- The local model parameters as a list of NumPy ndarrays." msgstr "**parameters** -- NumPy ndarrays 的本地模型参数列表。" -#: flwr.client.numpy_client.NumPyClient.get_properties:1 of -msgid "Return a client's set of properties." -msgstr "返回客户端的属性集。" - #: flwr.client.numpy_client.NumPyClient.get_properties:3 of msgid "" -"Configuration parameters requested by the server. This can be used to tell " -"the client which properties are needed along with some Scalar attributes." -msgstr "" -"服务器请求的配置参数。这可以用来告诉客户端需要哪些属性以及一些标量属性。" +"Configuration parameters requested by the server. This can be used to " +"tell the client which properties are needed along with some Scalar " +"attributes." +msgstr "服务器请求的配置参数。这可以用来告诉客户端需要哪些属性以及一些标量属性。" #: flwr.client.numpy_client.NumPyClient.get_properties:8 of msgid "" -"**properties** -- A dictionary mapping arbitrary string keys to values of " -"type bool, bytes, float, int, or str. It can be used to communicate " +"**properties** -- A dictionary mapping arbitrary string keys to values of" +" type bool, bytes, float, int, or str. It can be used to communicate " "arbitrary property values back to the server." msgstr "" -"**properties** -- 将任意字符串键映射到 bool、bytes、float、int 或 str 类型值" -"的字典。它可用于将任意属性值传回服务器。" - -#: flwr.client.numpy_client.NumPyClient.to_client:1 of -msgid "Convert to object to Client type and return it." -msgstr "将对象转换为客户类型并返回。" - -#: ../../source/ref-api-flwr.rst:41 -msgid "start_numpy_client" -msgstr "start_numpy_client" +"**properties** -- 将任意字符串键映射到 bool、bytes、float、int 或 str " +"类型值的字典。它可用于将任意属性值传回服务器。" -#: flwr.client.app.start_numpy_client:1 of -msgid "Start a Flower NumPyClient which connects to a gRPC server." -msgstr "启动 Flower NumPyClient,连接到 gRPC 服务器。" +#: ../../source/ref-api/flwr.client.run_client_app.rst:2 +msgid "run\\_client\\_app" +msgstr "" -#: flwr.client.app.start_numpy_client:7 of -msgid "An implementation of the abstract base class `flwr.client.NumPyClient`." -msgstr "抽象基类 `flwr.client.NumPyClient` 的实现。" +#: ../../source/ref-api/flwr.client.start_client.rst:2 +#, fuzzy +msgid "start\\_client" +msgstr "启动客户端" -#: flwr.client.app.start_numpy_client:28 of -msgid "Starting a client with an insecure server connection:" -msgstr "使用不安全的服务器连接启动客户端:" +#: flwr.client.app.start_client:3 flwr.client.app.start_numpy_client:9 of +msgid "" +"The IPv4 or IPv6 address of the server. If the Flower server runs on the " +"same machine on port 8080, then `server_address` would be " +"`\"[::]:8080\"`." +msgstr "" +"服务器的 IPv4 或 IPv6 地址:如果 Flower 服务器在同一台机器上运行,端口为 " +"8080,则`server_address`应为`\"[::]:8080\"`。" -#: ../../source/ref-api-flwr.rst:49 -msgid "start_simulation" -msgstr "start_simulation" +#: flwr.client.app.start_client:7 of +msgid "A callable that instantiates a Client. (default: None)" +msgstr "用于实例化客户端的可调用程序。(默认值:无)" -#: flwr.simulation.app.start_simulation:1 of -msgid "Start a Ray-based Flower simulation server." -msgstr "启动基于 Ray 的Flower模拟服务器。" +#: flwr.client.app.start_client:9 of +msgid "" +"An implementation of the abstract base class `flwr.client.Client` " +"(default: None)" +msgstr "抽象基类 `flwr.client.Client` 的实现(默认值:无)" -#: flwr.simulation.app.start_simulation:3 of +#: flwr.client.app.start_client:12 flwr.client.app.start_numpy_client:15 of msgid "" -"A function creating client instances. The function must take a single `str` " -"argument called `cid`. It should return a single client instance of type " -"Client. Note that the created client instances are ephemeral and will often " -"be destroyed after a single method invocation. Since client instances are " -"not long-lived, they should not attempt to carry state over method " -"invocations. Any state required by the instance (model, dataset, " -"hyperparameters, ...) should be (re-)created in either the call to " -"`client_fn` or the call to any of the client methods (e.g., load evaluation " -"data in the `evaluate` method itself)." +"The maximum length of gRPC messages that can be exchanged with the Flower" +" server. The default should be sufficient for most models. Users who " +"train very large models might need to increase this value. Note that the " +"Flower server needs to be started with the same value (see " +"`flwr.server.start_server`), otherwise it will not know about the " +"increased limit and block larger messages." msgstr "" -"创建客户端实例的函数。该函数必须接受一个名为 `cid` 的 `str` 参数。" -"它应返回一个 Client 类型的客户端实例。请注意,创建的客户端实例是短暂的,通常" -"在调用一个方法后就会被销毁。由于客户机实例不是长期存在的,它们不应试图在方法" -"调用时携带状态数据。实例所需的任何状态数据(模型、数据集、超参数......)" -"都应在调用 `client_fn` 或任何客户端方法(例如,在 `evaluate` " -"方法中加载评估数据)时(重新)创建。" +"可与 Flower 服务器交换的 gRPC 信息的最大长度:默认值对大多数模型都足够了。训练超大模型的用户可能需要增加该值。请注意,Flower " +"服务器需要以相同的值启动(请参阅 `flwr.server.start_server`),否则它将不知道增加的限制并阻止更大的消息。" -#: flwr.simulation.app.start_simulation:13 of +#: flwr.client.app.start_client:19 flwr.client.app.start_numpy_client:22 +#: flwr.server.driver.app.start_driver:21 of msgid "" -"The total number of clients in this simulation. This must be set if " -"`clients_ids` is not set and vice-versa." -msgstr "" -"本次模拟的客户总数。如果未设置 `clients_ids`,则必须设置该参数,反之亦然。" +"The PEM-encoded root certificates as a byte string or a path string. If " +"provided, a secure connection using the certificates will be established " +"to an SSL-enabled Flower server." +msgstr "字节字符串或路径字符串形式的 PEM 编码根证书。如果提供,将使用这些证书与启用 SSL 的 Flower 服务器建立安全连接。" -#: flwr.simulation.app.start_simulation:16 of +#: flwr.client.app.start_client:23 flwr.client.app.start_numpy_client:26 of msgid "" -"List `client_id`s for each client. This is only required if `num_clients` is " -"not set. Setting both `num_clients` and `clients_ids` with " -"`len(clients_ids)` not equal to `num_clients` generates an error." +"Starts an insecure gRPC connection when True. Enables HTTPS connection " +"when False, using system certificates if `root_certificates` is None." msgstr "" -"列出每个客户的 `client_id`。只有在未设置 `num_clients` 时才需要这样做。同时设" -"置`num_clients`和`clients_ids`,且`len(clients_ids)`不等于`num_clients`,会产" -"生错误。" -#: flwr.simulation.app.start_simulation:20 of +#: flwr.client.app.start_client:26 flwr.client.app.start_numpy_client:29 of msgid "" -"\"num_gpus\": 0.0}` CPU and GPU resources for a single client. Supported " -"keys are `num_cpus` and `num_gpus`. To understand the GPU utilization caused " -"by `num_gpus`, as well as using custom resources, please consult the Ray " -"documentation." +"Configure the transport layer. Allowed values: - 'grpc-bidi': gRPC, " +"bidirectional streaming - 'grpc-rere': gRPC, request-response " +"(experimental) - 'rest': HTTP (experimental)" msgstr "" -"\"num_gpus\": 0.0` 单个客户端的 CPU 和 GPU 资源。支持的键值为 `num_cpus` 和 " -"`num_gpus`。要了解 `num_gpus` 所导致的 GPU 利用率,以及使用自定义资源的情况," -"请查阅 Ray 文档。" +"配置传输层:允许的值包括 - 'grpc-bidi': gRPC,双向流 - 'grpc-rere': gRPC,请求-响应(实验性) - " +"'rest': HTTP(实验性)" -#: flwr.simulation.app.start_simulation:25 of +#: flwr.client.app.start_client:34 flwr.client.app.start_numpy_client:37 of +msgid "Starting a gRPC client with an insecure server connection:" +msgstr "使用不安全的服务器连接启动 gRPC 客户端:" + +#: flwr.client.app.start_client:41 flwr.client.app.start_numpy_client:44 of +#, fuzzy +msgid "Starting an SSL-enabled gRPC client using system certificates:" +msgstr "启动支持 SSL 的 gRPC 客户端:" + +#: flwr.client.app.start_client:52 flwr.client.app.start_numpy_client:52 of +#, fuzzy +msgid "Starting an SSL-enabled gRPC client using provided certificates:" +msgstr "启动支持 SSL 的 gRPC 客户端:" + +#: ../../source/ref-api/flwr.client.start_numpy_client.rst:2 +#, fuzzy +msgid "start\\_numpy\\_client" +msgstr "start_numpy_client" + +#: flwr.client.app.start_numpy_client:5 of msgid "" -"An implementation of the abstract base class `flwr.server.Server`. If no " -"instance is provided, then `start_server` will create one." +"This function is deprecated since 1.7.0. Use " +":code:`flwr.client.start_client` instead and first convert your " +":code:`NumPyClient` to type :code:`flwr.client.Client` by executing its " +":code:`to_client()` method." msgstr "" -"抽象基类 `flwr.server.Server`的实现。如果没有提供实例,`start_server` 将创建" -"一个。" -#: flwr.server.app.start_server:9 flwr.simulation.app.start_simulation:28 of -msgid "" -"Currently supported values are `num_rounds` (int, default: 1) and " -"`round_timeout` in seconds (float, default: None)." +#: flwr.client.app.start_numpy_client:13 of +msgid "An implementation of the abstract base class `flwr.client.NumPyClient`." +msgstr "抽象基类 `flwr.client.NumPyClient` 的实现。" + +#: ../../source/ref-api/flwr.common.rst:2 +msgid "common" +msgstr "常见" + +#: ../../source/ref-api/flwr.common.rst:29::1 +msgid ":py:obj:`bytes_to_ndarray `\\ \\(tensor\\)" msgstr "" -"目前支持的值有:`num_rounds`(int,默认值:1)和以秒为单位的`round_timeout`" -"(float,默认值:无)。" -#: flwr.simulation.app.start_simulation:31 of +#: ../../source/ref-api/flwr.common.rst:29::1 +#: flwr.common.parameter.bytes_to_ndarray:1 of +msgid "Deserialize NumPy ndarray from bytes." +msgstr "从字节反序列化 NumPy ndarray。" + +#: ../../source/ref-api/flwr.common.rst:29::1 msgid "" -"An implementation of the abstract base class `flwr.server.Strategy`. If no " -"strategy is provided, then `start_server` will use `flwr.server.strategy." -"FedAvg`." +":py:obj:`configure `\\ \\(identifier\\[\\, " +"filename\\, host\\]\\)" msgstr "" -"抽象基类 `flwr.server.strategy` 的实现。如果没有提供策略,`start_server` 将使" -"用 `flwr.server.strategy.FedAvg`。" -#: flwr.simulation.app.start_simulation:35 of +#: ../../source/ref-api/flwr.common.rst:29::1 +#: flwr.common.logger.configure:1 of +msgid "Configure logging to file and/or remote log server." +msgstr "配置将日志记录到文件和/或远程日志服务器。" + +#: ../../source/ref-api/flwr.common.rst:29::1 msgid "" -"An implementation of the abstract base class `flwr.server.ClientManager`. If " -"no implementation is provided, then `start_simulation` will use `flwr.server." -"client_manager.SimpleClientManager`." +":py:obj:`event `\\ \\(event\\_type\\[\\, " +"event\\_details\\]\\)" msgstr "" -"抽象基类 `flwr.server.ClientManager` 的实现。如果没有提供实现," -"`start_simulation` 将使用 `flwr.server.client_manager.SimpleClientManager`。" -#: flwr.simulation.app.start_simulation:39 of -msgid "" -"Optional dictionary containing arguments for the call to `ray.init`. If " -"ray_init_args is None (the default), Ray will be initialized with the " -"following default args: { \"ignore_reinit_error\": True, " -"\"include_dashboard\": False } An empty dictionary can be used " -"(ray_init_args={}) to prevent any arguments from being passed to ray.init." +#: ../../source/ref-api/flwr.common.rst:29::1 +#: flwr.common.telemetry.event:1 of +msgid "Submit create_event to ThreadPoolExecutor to avoid blocking." msgstr "" -"可选字典,包含调用 `ray.init` 时的参数。如果 ray_init_args 为 None(默认" -"值),则将使用以下默认参数初始化 Ray: { \"ignore_reinit_error\": True, " -"\"include_dashboard\": False } 可以使用空字典(ray_init_args={})来防止向 " -"ray.init 传递任何参数。" -#: flwr.simulation.app.start_simulation:39 of +#: ../../source/ref-api/flwr.common.rst:29::1 msgid "" -"Optional dictionary containing arguments for the call to `ray.init`. If " -"ray_init_args is None (the default), Ray will be initialized with the " -"following default args:" +":py:obj:`log `\\ \\(level\\, msg\\, \\*args\\, " +"\\*\\*kwargs\\)" msgstr "" -"可选字典,包含调用 `ray.init` 时的参数。如果 ray_init_args 为 None(默认" -"值),则将使用以下默认参数初始化 Ray:" -#: flwr.simulation.app.start_simulation:43 of -msgid "{ \"ignore_reinit_error\": True, \"include_dashboard\": False }" -msgstr "{ \"ignore_reinit_error\": True, \"include_dashboard\": False }" +#: ../../source/ref-api/flwr.common.rst:29::1 logging.Logger.log:1 +#: of +msgid "Log 'msg % args' with the integer severity 'level'." +msgstr "以整数严重性 \"级别 \"记录 \"msg % args\"。" -#: flwr.simulation.app.start_simulation:45 of -msgid "" -"An empty dictionary can be used (ray_init_args={}) to prevent any arguments " -"from being passed to ray.init." -msgstr "可以使用空字典 (ray_init_args={}) 来防止向 ray.init 传递任何参数。" +#: ../../source/ref-api/flwr.common.rst:29::1 +msgid ":py:obj:`ndarray_to_bytes `\\ \\(ndarray\\)" +msgstr "" -#: flwr.simulation.app.start_simulation:48 of -msgid "" -"Set to True to prevent `ray.shutdown()` in case `ray.is_initialized()=True`." +#: ../../source/ref-api/flwr.common.rst:29::1 +#: flwr.common.parameter.ndarray_to_bytes:1 of +msgid "Serialize NumPy ndarray to bytes." +msgstr "将 NumPy ndarray 序列化为字节。" + +#: ../../source/ref-api/flwr.common.rst:29::1 +msgid ":py:obj:`now `\\ \\(\\)" msgstr "" -"设为 True 可在 `ray.is_initialized()=True` 情况下阻止 `ray.shutdown()` 。" -#: flwr.simulation.app.start_simulation:50 of -msgid "" -"Optionally specify the type of actor to use. The actor object, which " -"persists throughout the simulation, will be the process in charge of running " -"the clients' jobs (i.e. their `fit()` method)." -msgstr "可选择指定要使用的actor类型。actor对象将在整个模拟过程中持续存在,它将是负责" -"运行客户端作业(即其 `fit()`方法)的进程。" +#: ../../source/ref-api/flwr.common.rst:29::1 +#: flwr.common.date.now:1 of +msgid "Construct a datetime from time.time() with time zone set to UTC." +msgstr "从 time.time() 生成日期时间,时区设置为 UTC。" -#: flwr.simulation.app.start_simulation:54 of +#: ../../source/ref-api/flwr.common.rst:29::1 msgid "" -"If you want to create your own Actor classes, you might need to pass some " -"input argument. You can use this dictionary for such purpose." +":py:obj:`ndarrays_to_parameters `\\ " +"\\(ndarrays\\)" msgstr "" -"如果您想创建自己的 Actor 类,可能需要传递一些输入参数。为此,您可以使用本字" -"典。" -#: flwr.simulation.app.start_simulation:57 of +#: ../../source/ref-api/flwr.common.rst:29::1 +#: flwr.common.parameter.ndarrays_to_parameters:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.ndarrays_to_parameters:1 +#: of +msgid "Convert NumPy ndarrays to parameters object." +msgstr "将 NumPy ndarrays 转换为参数对象。" + +#: ../../source/ref-api/flwr.common.rst:29::1 msgid "" -"(default: \"DEFAULT\") Optional string (\"DEFAULT\" or \"SPREAD\") for the " -"VCE to choose in which node the actor is placed. If you are an advanced user " -"needed more control you can use lower-level scheduling strategies to pin " -"actors to specific compute nodes (e.g. via NodeAffinitySchedulingStrategy). " -"Please note this is an advanced feature. For all details, please refer to " -"the Ray documentation: https://docs.ray.io/en/latest/ray-core/scheduling/" -"index.html" +":py:obj:`parameters_to_ndarrays `\\ " +"\\(parameters\\)" msgstr "" -"(默认:\"DEFAULT\")可选字符串(\"DEFAULT \"或 \"SPREAD\"),供 VCE 选择将行" -"为体放置在哪个节点上。如果你是需要更多控制权的高级用户,可以使用低级调度策略" -"将actor固定到特定计算节点(例如,通过 " -"NodeAffinitySchedulingStrategy)。请注意,这是一项高级功能。有关详细信息," -"请参阅 Ray 文档:https://docs.ray.io/en/latest/ray-core/scheduling/index.html" - -#: flwr.simulation.app.start_simulation:66 of -msgid "**hist** -- Object containing metrics from training." -msgstr "**hist** -- 包含训练指标的对象。" -#: ../../source/ref-api-flwr.rst:57 -msgid "server" -msgstr "服务器" +#: ../../source/ref-api/flwr.common.rst:29::1 +#: flwr.common.parameter.parameters_to_ndarrays:1 of +msgid "Convert parameters object to NumPy ndarrays." +msgstr "将参数对象转换为 NumPy ndarrays。" -#: flwr.server:1 of -msgid "Flower server." -msgstr "Flower 服务器。" +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid "" +":py:obj:`ClientMessage `\\ " +"\\(\\[get\\_properties\\_res\\, ...\\]\\)" +msgstr "" -#: ../../source/ref-api-flwr.rst:65 -msgid "server.start_server" -msgstr "server.start_server" +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.ClientMessage:1 of +msgid "ClientMessage is a container used to hold one result message." +msgstr "ClientMessage 是用于容纳一条结果信息的容器。" -#: flwr.server.app.start_server:1 of -msgid "Start a Flower server using the gRPC transport layer." -msgstr "使用 gRPC 传输层启动 Flower 服务器。" +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`Code `\\ \\(value\\)" +msgstr "" -#: flwr.server.app.start_server:3 of -msgid "The IPv4 or IPv6 address of the server. Defaults to `\"[::]:8080\"`." -msgstr "服务器的 IPv4 或 IPv6 地址。默认为 `\"[::]:8080\"。" +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.Code:1 of +msgid "Client status codes." +msgstr "客户端状态代码。" -#: flwr.server.app.start_server:5 of -msgid "" -"A server implementation, either `flwr.server.Server` or a subclass thereof. " -"If no instance is provided, then `start_server` will create one." +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`DisconnectRes `\\ \\(reason\\)" msgstr "" -"服务器实现,可以是 `flwr.server.Server` 或其子类。如果没有提供实例," -"`start_server` 将创建一个。" -#: flwr.server.app.start_server:12 of -msgid "" -"An implementation of the abstract base class `flwr.server.strategy." -"Strategy`. If no strategy is provided, then `start_server` will use `flwr." -"server.strategy.FedAvg`." -msgstr "" -"抽象基类 `flwr.server.strategy.Strategy` 的实现。如果没有提供策略," -"`start_server` 将使用 `flwr.server.strategy.FedAvg`。" +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.DisconnectRes:1 of +msgid "DisconnectRes message from client to server." +msgstr "客户端向服务器发送 DisconnectRes 信息。" -#: flwr.server.app.start_server:16 of +#: ../../source/ref-api/flwr.common.rst:52::1 msgid "" -"An implementation of the abstract base class `flwr.server.ClientManager`. If " -"no implementation is provided, then `start_server` will use `flwr.server." -"client_manager.SimpleClientManager`." +":py:obj:`EvaluateIns `\\ \\(parameters\\, " +"config\\)" msgstr "" -"抽象基类 `flwr.server.ClientManager` 的实现。如果没有提供实现," -"`start_server` 将使用 `flwr.server.client_manager.SimpleClientManager`。" -#: flwr.server.app.start_server:21 of +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.EvaluateIns:1 of +msgid "Evaluate instructions for a client." +msgstr "评估客户端的指示。" + +#: ../../source/ref-api/flwr.common.rst:52::1 msgid "" -"The maximum length of gRPC messages that can be exchanged with the Flower " -"clients. The default should be sufficient for most models. Users who train " -"very large models might need to increase this value. Note that the Flower " -"clients need to be started with the same value (see `flwr.client." -"start_client`), otherwise clients will not know about the increased limit " -"and block larger messages." +":py:obj:`EvaluateRes `\\ \\(status\\, loss\\, " +"num\\_examples\\, metrics\\)" msgstr "" -"可与 Flower 客户端交换的 gRPC 消息的最大长度:默认值对大多数模型都足够了。训" -"练超大模型的用户可能需要增加该值。请注意,Flower 客户端需要以相同的值启动(" -"请参阅 `flwr.client." -"start_client`),否则客户端将不知道已增加的限制并阻止更大的消息。" -#: flwr.server.app.start_server:28 of -msgid "" -"Tuple containing root certificate, server certificate, and private key to " -"start a secure SSL-enabled server. The tuple is expected to have three bytes " -"elements in the following order: * CA certificate. * server " -"certificate. * server private key." +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.EvaluateRes:1 of +msgid "Evaluate response from a client." +msgstr "评估客户端的反应。" + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`EventType `\\ \\(value\\)" msgstr "" -"包含根证书、服务器证书和私钥的元组,用于启动启用 SSL " -"的安全服务器。元组应按以下顺序包含三个字节元素: * CA 证书,* 服务器证书, * " -"服务器私钥。" -#: flwr.server.app.start_server:28 of -msgid "" -"Tuple containing root certificate, server certificate, and private key to " -"start a secure SSL-enabled server. The tuple is expected to have three bytes " -"elements in the following order:" +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.telemetry.EventType:1 of +msgid "Types of telemetry events." +msgstr "遥测事件类型。" + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`FitIns `\\ \\(parameters\\, config\\)" msgstr "" -"包含根证书、服务器证书和私钥的元组,用于启动启用 SSL 的安全服务器。元组应按以" -"下顺序包含三个字节元素:" -#: flwr.server.app.start_server:32 of -msgid "CA certificate." -msgstr "CA 证书。" +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.FitIns:1 of +msgid "Fit instructions for a client." +msgstr "为客户提供安装说明。" -#: flwr.server.app.start_server:33 of -msgid "server certificate." -msgstr "服务器证书。" +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid "" +":py:obj:`FitRes `\\ \\(status\\, parameters\\, " +"num\\_examples\\, metrics\\)" +msgstr "" -#: flwr.server.app.start_server:34 of -msgid "server private key." -msgstr "服务器私人密钥。" +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.FitRes:1 of +msgid "Fit response from a client." +msgstr "来自客户端的合适回复。" -#: flwr.server.app.start_server:37 of -msgid "**hist** -- Object containing training and evaluation metrics." -msgstr "**hist** -- 包含训练和评估指标的对象。" +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`GetParametersIns `\\ \\(config\\)" +msgstr "" -#: flwr.server.app.start_server:42 of -msgid "Starting an insecure server:" -msgstr "启动不安全的服务器:" +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.GetParametersIns:1 of +msgid "Parameters request for a client." +msgstr "客户端的参数请求。" -#: flwr.server.app.start_server:46 of -msgid "Starting an SSL-enabled server:" -msgstr "启动支持 SSL 的服务器:" +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid "" +":py:obj:`GetParametersRes `\\ \\(status\\, " +"parameters\\)" +msgstr "" -#: ../../source/ref-api-flwr.rst:73 -msgid "server.strategy" -msgstr "server.strategy" +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.GetParametersRes:1 of +msgid "Response when asked to return parameters." +msgstr "要求返回参数时的响应。" -#: flwr.server.strategy:1 of -msgid "Contains the strategy abstraction and different implementations." -msgstr "包含策略抽象和不同的实现方法。" +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`GetPropertiesIns `\\ \\(config\\)" +msgstr "" -#: ../../source/ref-api-flwr.rst:81 -msgid "server.strategy.Strategy" -msgstr "server.strategy.Strategy" +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.GetPropertiesIns:1 of +msgid "Properties request for a client." +msgstr "客户端的属性请求。" -#: flwr.server.strategy.strategy.Strategy:1 of -msgid "Abstract base class for server strategy implementations." -msgstr "服务器策略实现的抽象基类。" +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid "" +":py:obj:`GetPropertiesRes `\\ \\(status\\, " +"properties\\)" +msgstr "" -#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1 of -msgid "Aggregate evaluation results." -msgstr "聚合评估结果。" +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.GetPropertiesRes:1 of +msgid "Properties response from a client." +msgstr "来自客户端的属性响应。" -#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate:3 -#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:6 -#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:3 -#: flwr.server.strategy.strategy.Strategy.aggregate_fit:3 -#: flwr.server.strategy.strategy.Strategy.configure_evaluate:3 -#: flwr.server.strategy.strategy.Strategy.configure_fit:3 -#: flwr.server.strategy.strategy.Strategy.evaluate:6 of -msgid "The current round of federated learning." -msgstr "本轮联邦学习。" +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`NDArray `\\" +msgstr "" -#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:5 of +#: ../../source/ref-api/flwr.common.rst:52::1 msgid "" -"Successful updates from the previously selected and configured clients. Each " -"pair of `(ClientProxy, FitRes` constitutes a successful update from one of " -"the previously selected clients. Not that not all previously selected " -"clients are necessarily included in this list: a client might drop out and " -"not submit a result. For each client that did not submit an update, there " -"should be an `Exception` in `failures`." +"alias of :py:class:`~numpy.ndarray`\\ [:py:obj:`~typing.Any`, " +":py:class:`~numpy.dtype`\\ [:py:obj:`~typing.Any`]]" msgstr "" -"从先前选定和配置的客户端进行的成功更新。每一对`(ClientProxy, FitRes)`都是来自" -"先前选定客户端的一次成功更新。但并非所有先前选定的客户机都一定包含在此列表中" -":客户机可能会退出,不提交结果。对于每个没有提交更新的客户端,`failures`中都" -"应该有一个`Exception`。" -#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:13 -#: flwr.server.strategy.strategy.Strategy.aggregate_fit:13 of +#: ../../source/ref-api/flwr.common.rst:52::1 msgid "" -"Exceptions that occurred while the server was waiting for client updates." -msgstr "服务器等待客户端更新时发生的异常。" +":py:obj:`Parameters `\\ \\(tensors\\, " +"tensor\\_type\\)" +msgstr "" -#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:16 of -msgid "" -"**aggregation_result** -- The aggregated evaluation result. Aggregation " -"typically uses some variant of a weighted average." -msgstr "**aggregation_result** -- 汇总的评估结果。聚合通常使用某种加权平均值。" +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.Parameters:1 of +msgid "Model parameters." +msgstr "模型参数。" -#: flwr.server.strategy.strategy.Strategy.aggregate_fit:1 of -msgid "Aggregate training results." -msgstr "汇总训练结果。" +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`ReconnectIns `\\ \\(seconds\\)" +msgstr "" -#: flwr.server.strategy.strategy.Strategy.aggregate_fit:5 of +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.ReconnectIns:1 of +msgid "ReconnectIns message from server to client." +msgstr "服务器发送给客户端的重新连接信息。" + +#: ../../source/ref-api/flwr.common.rst:52::1 msgid "" -"Successful updates from the previously selected and configured clients. Each " -"pair of `(ClientProxy, FitRes)` constitutes a successful update from one of " -"the previously selected clients. Not that not all previously selected " -"clients are necessarily included in this list: a client might drop out and " -"not submit a result. For each client that did not submit an update, there " -"should be an `Exception` in `failures`." +":py:obj:`ServerMessage `\\ " +"\\(\\[get\\_properties\\_ins\\, ...\\]\\)" msgstr "" -"来自先前选定和配置的客户端的成功更新。每一对`(ClientProxy, FitRes)`都构成先前" -"选定的客户端之一的一次成功更新。但并非所有先前选定的客户机都一定包含在此列表" -"中:客户机可能会退出,不提交结果。对于每个没有提交更新的客户端,\"失败 " -"\"中都应该有一个 \"异常\"。" -#: flwr.server.strategy.strategy.Strategy.aggregate_fit:17 of -msgid "" -"**parameters** -- If parameters are returned, then the server will treat " -"these as the new global model parameters (i.e., it will replace the previous " -"parameters with the ones returned from this method). If `None` is returned " -"(e.g., because there were only failures and no viable results) then the " -"server will no update the previous model parameters, the updates received in " -"this round are discarded, and the global model parameters remain the same." +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.ServerMessage:1 of +msgid "ServerMessage is a container used to hold one instruction message." +msgstr "ServerMessage 是用于容纳一条指令信息的容器。" + +#: ../../source/ref-api/flwr.common.rst:52::1 +msgid ":py:obj:`Status `\\ \\(code\\, message\\)" msgstr "" -"**parameters** -- 如果返回参数,那么服务器将把这些参数作为新的全局模型参数" -"(即用本方法返回的参数替换之前的参数)。如果返回 \"无\"(例如,因为只有失败而" -"没有可行的结果),那么服务器将不再更新之前的模型参数,本轮收到的更新将被丢" -"弃,全局模型参数保持不变。" -#: flwr.server.strategy.fedavg.FedAvg.configure_evaluate:1 -#: flwr.server.strategy.qfedavg.QFedAvg.configure_evaluate:1 -#: flwr.server.strategy.strategy.Strategy.configure_evaluate:1 of -msgid "Configure the next round of evaluation." -msgstr "配置下一轮评估。" +#: ../../source/ref-api/flwr.common.rst:52::1 +#: flwr.common.typing.Status:1 of +msgid "Client status." +msgstr "客户端状态。" -#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate:7 -#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:10 -#: flwr.server.strategy.strategy.Strategy.configure_evaluate:7 -#: flwr.server.strategy.strategy.Strategy.configure_fit:7 -#: flwr.server.strategy.strategy.Strategy.initialize_parameters:3 of -msgid "The client manager which holds all currently connected clients." -msgstr "客户端管理器,用于管理当前连接的所有客户端。" +#: ../../source/ref-api/flwr.common.ClientMessage.rst:2 +#, fuzzy +msgid "ClientMessage" +msgstr "客户端" -#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate:10 -#: flwr.server.strategy.strategy.Strategy.configure_evaluate:10 of -msgid "" -"**evaluate_configuration** -- A list of tuples. Each tuple in the list " -"identifies a `ClientProxy` and the `EvaluateIns` for this particular " -"`ClientProxy`. If a particular `ClientProxy` is not included in this list, " -"it means that this `ClientProxy` will not participate in the next round of " -"federated evaluation." +#: ../../source/ref-api/flwr.common.ClientMessage.rst:31::1 +msgid ":py:obj:`evaluate_res `\\" msgstr "" -"**evaluate_configuration** -- 一个元组列表。列表中的每个元组都标识了一个`Clie" -"ntProxy`和该特定`ClientProxy`的`EvaluateIns`。如果某个特定的 `ClientProxy` " -"未包含在此列表中,则表示该 `ClientProxy` 将不参与下一轮联合评估。" -#: flwr.server.strategy.dpfedavg_adaptive.DPFedAvgAdaptive.configure_fit:1 -#: flwr.server.strategy.fedavg.FedAvg.configure_fit:1 -#: flwr.server.strategy.fedprox.FedProx.configure_fit:1 -#: flwr.server.strategy.qfedavg.QFedAvg.configure_fit:1 -#: flwr.server.strategy.strategy.Strategy.configure_fit:1 of -msgid "Configure the next round of training." -msgstr "配置下一轮训练。" +#: ../../source/ref-api/flwr.common.ClientMessage.rst:31::1 +msgid ":py:obj:`fit_res `\\" +msgstr "" -#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:13 -#: flwr.server.strategy.strategy.Strategy.configure_fit:10 of +#: ../../source/ref-api/flwr.common.ClientMessage.rst:31::1 msgid "" -"**fit_configuration** -- A list of tuples. Each tuple in the list identifies " -"a `ClientProxy` and the `FitIns` for this particular `ClientProxy`. If a " -"particular `ClientProxy` is not included in this list, it means that this " -"`ClientProxy` will not participate in the next round of federated learning." +":py:obj:`get_parameters_res " +"`\\" msgstr "" -"**fit_configuration** -- 一个元组列表。列表中的每个元组都标识了一个`ClientPro" -"xy`和该特定`ClientProxy`的`FitIns'。如果某个特定的`ClientProxy`不在此列表中," -"则表示该`ClientProxy`将不参加下一轮联合学习。" -#: flwr.server.strategy.strategy.Strategy.evaluate:1 of -msgid "Evaluate the current model parameters." -msgstr "评估当前的模型参数。" +#: ../../source/ref-api/flwr.common.ClientMessage.rst:31::1 +msgid "" +":py:obj:`get_properties_res " +"`\\" +msgstr "" -#: flwr.server.strategy.strategy.Strategy.evaluate:3 of +#: ../../source/ref-api/flwr.common.Code.rst:2 +msgid "Code" +msgstr "" + +#: flwr.common.typing.Code:1 of +msgid "Bases: :py:class:`~enum.Enum`" +msgstr "" + +#: ../../source/ref-api/flwr.common.Code.rst:26::1 +msgid ":py:obj:`OK `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.Code.rst:26::1 msgid "" -"This function can be used to perform centralized (i.e., server-side) " -"evaluation of model parameters." -msgstr "该函数可用于对模型参数进行集中(即服务器端)评估。" +":py:obj:`GET_PROPERTIES_NOT_IMPLEMENTED " +"`\\" +msgstr "" -#: flwr.server.strategy.strategy.Strategy.evaluate:11 of +#: ../../source/ref-api/flwr.common.Code.rst:26::1 msgid "" -"**evaluation_result** -- The evaluation result, usually a Tuple containing " -"loss and a dictionary containing task-specific metrics (e.g., accuracy)." -msgstr "**evaluation_result** -- 评估结果,通常是一个元组,包含损失值和一个字典,字典" -"中包含特定任务的指标(如准确率)。" +":py:obj:`GET_PARAMETERS_NOT_IMPLEMENTED " +"`\\" +msgstr "" -#: flwr.server.strategy.strategy.Strategy.initialize_parameters:1 of -msgid "Initialize the (global) model parameters." -msgstr "初始化(全局)模型参数。" +#: ../../source/ref-api/flwr.common.Code.rst:26::1 +msgid ":py:obj:`FIT_NOT_IMPLEMENTED `\\" +msgstr "" -#: flwr.server.strategy.strategy.Strategy.initialize_parameters:6 of +#: ../../source/ref-api/flwr.common.Code.rst:26::1 msgid "" -"**parameters** -- If parameters are returned, then the server will treat " -"these as the initial global model parameters." +":py:obj:`EVALUATE_NOT_IMPLEMENTED " +"`\\" msgstr "" -"**parameters** -- 如果返回参数,服务器将把这些参数视为初始全局模型参数。" -#: ../../source/ref-api-flwr.rst:90 -msgid "server.strategy.FedAvg" -msgstr "server.strategy.FedAvg" +#: ../../source/ref-api/flwr.common.DisconnectRes.rst:2 +msgid "DisconnectRes" +msgstr "" -#: flwr.server.strategy.fedavg.FedAvg:1 of -msgid "Configurable FedAvg strategy implementation." -msgstr "可配置的 FedAvg 策略实施。" +#: ../../source/ref-api/flwr.common.DisconnectRes.rst:28::1 +msgid ":py:obj:`reason `\\" +msgstr "" -#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:1 -#: flwr.server.strategy.fedavg.FedAvg.__init__:1 -#: flwr.server.strategy.qfedavg.QFedAvg.__init__:1 of -msgid "Federated Averaging strategy." -msgstr "联邦平均策略。" +#: ../../source/ref-api/flwr.common.EvaluateIns.rst:2 +#, fuzzy +msgid "EvaluateIns" +msgstr "说明" -#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:3 -#: flwr.server.strategy.fedavg.FedAvg.__init__:3 -#: flwr.server.strategy.qfedavg.QFedAvg.__init__:3 of -msgid "Implementation based on https://arxiv.org/abs/1602.05629" -msgstr "实施基于 https://arxiv.org/abs/1602.05629" +#: ../../source/ref-api/flwr.common.EvaluateIns.rst:29::1 +msgid ":py:obj:`parameters `\\" +msgstr "" -#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:5 -#: flwr.server.strategy.fedavg.FedAvg.__init__:5 -#: flwr.server.strategy.fedprox.FedProx.__init__:37 -#: flwr.server.strategy.qfedavg.QFedAvg.__init__:5 of -msgid "" -"Fraction of clients used during training. In case `min_fit_clients` is " -"larger than `fraction_fit * available_clients`, `min_fit_clients` will still " -"be sampled. Defaults to 1.0." +#: ../../source/ref-api/flwr.common.EvaluateIns.rst:29::1 +msgid ":py:obj:`config `\\" msgstr "" -"训练过程中使用的客户端比例。如果 `min_fit_clients` 大于 `fraction_fit * " -"available_clients`,则仍会对 `min_fit_clients` 进行采样。默认为 1.0。" -#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:9 -#: flwr.server.strategy.fedavg.FedAvg.__init__:9 -#: flwr.server.strategy.fedprox.FedProx.__init__:41 -#: flwr.server.strategy.qfedavg.QFedAvg.__init__:9 of -msgid "" -"Fraction of clients used during validation. In case `min_evaluate_clients` " -"is larger than `fraction_evaluate * available_clients`, " -"`min_evaluate_clients` will still be sampled. Defaults to 1.0." -msgstr "" -"验证过程中使用的客户端的比例。如果 `min_evaluate_clients` 大于 `" -"fraction_evaluate * available_clients`,则仍会对 `min_evaluate_clients` " -"进行采样。默认为 1.0。" - -#: flwr.server.strategy.bulyan.Bulyan.__init__:9 -#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:13 -#: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:9 -#: flwr.server.strategy.fedadam.FedAdam.__init__:9 -#: flwr.server.strategy.fedavg.FedAvg.__init__:13 -#: flwr.server.strategy.fedavgm.FedAvgM.__init__:9 -#: flwr.server.strategy.fedopt.FedOpt.__init__:9 -#: flwr.server.strategy.fedprox.FedProx.__init__:45 -#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg.__init__:7 -#: flwr.server.strategy.fedyogi.FedYogi.__init__:9 -#: flwr.server.strategy.krum.Krum.__init__:7 -#: flwr.server.strategy.qfedavg.QFedAvg.__init__:13 of -msgid "Minimum number of clients used during training. Defaults to 2." -msgstr "训练期间使用的最少客户数。默认为 2。" +#: ../../source/ref-api/flwr.common.EvaluateRes.rst:2 +msgid "EvaluateRes" +msgstr "" -#: flwr.server.strategy.bulyan.Bulyan.__init__:11 -#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:15 -#: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:11 -#: flwr.server.strategy.fedadam.FedAdam.__init__:11 -#: flwr.server.strategy.fedavg.FedAvg.__init__:15 -#: flwr.server.strategy.fedavgm.FedAvgM.__init__:11 -#: flwr.server.strategy.fedopt.FedOpt.__init__:11 -#: flwr.server.strategy.fedprox.FedProx.__init__:47 -#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg.__init__:9 -#: flwr.server.strategy.fedyogi.FedYogi.__init__:11 -#: flwr.server.strategy.krum.Krum.__init__:9 -#: flwr.server.strategy.qfedavg.QFedAvg.__init__:15 of -msgid "Minimum number of clients used during validation. Defaults to 2." -msgstr "验证过程中使用的最少客户端数量。默认为 2。" +#: ../../source/ref-api/flwr.common.EvaluateRes.rst:31::1 +msgid ":py:obj:`status `\\" +msgstr "" -#: flwr.server.strategy.bulyan.Bulyan.__init__:13 -#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:17 -#: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:13 -#: flwr.server.strategy.fedadam.FedAdam.__init__:13 -#: flwr.server.strategy.fedavg.FedAvg.__init__:17 -#: flwr.server.strategy.fedavgm.FedAvgM.__init__:13 -#: flwr.server.strategy.fedopt.FedOpt.__init__:13 -#: flwr.server.strategy.fedprox.FedProx.__init__:49 -#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg.__init__:11 -#: flwr.server.strategy.fedyogi.FedYogi.__init__:13 -#: flwr.server.strategy.krum.Krum.__init__:11 -#: flwr.server.strategy.qfedavg.QFedAvg.__init__:17 of -msgid "Minimum number of total clients in the system. Defaults to 2." -msgstr "系统中客户总数的最小值。默认为 2。" +#: ../../source/ref-api/flwr.common.EvaluateRes.rst:31::1 +msgid ":py:obj:`loss `\\" +msgstr "" -#: flwr.server.strategy.bulyan.Bulyan.__init__:17 -#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:19 -#: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:15 -#: flwr.server.strategy.fedadam.FedAdam.__init__:15 -#: flwr.server.strategy.fedavg.FedAvg.__init__:19 -#: flwr.server.strategy.fedavgm.FedAvgM.__init__:15 -#: flwr.server.strategy.fedopt.FedOpt.__init__:15 -#: flwr.server.strategy.fedprox.FedProx.__init__:51 -#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg.__init__:13 -#: flwr.server.strategy.fedyogi.FedYogi.__init__:15 -#: flwr.server.strategy.krum.Krum.__init__:18 -#: flwr.server.strategy.qfedavg.QFedAvg.__init__:19 of -msgid "Optional function used for validation. Defaults to None." -msgstr "用于验证的可选函数。默认为 \"无\"。" +#: ../../source/ref-api/flwr.common.EvaluateRes.rst:31::1 +msgid ":py:obj:`num_examples `\\" +msgstr "" -#: flwr.server.strategy.bulyan.Bulyan.__init__:19 -#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:21 -#: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:17 -#: flwr.server.strategy.fedadam.FedAdam.__init__:17 -#: flwr.server.strategy.fedavg.FedAvg.__init__:21 -#: flwr.server.strategy.fedavgm.FedAvgM.__init__:17 -#: flwr.server.strategy.fedopt.FedOpt.__init__:17 -#: flwr.server.strategy.fedprox.FedProx.__init__:53 -#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg.__init__:15 -#: flwr.server.strategy.fedyogi.FedYogi.__init__:17 -#: flwr.server.strategy.krum.Krum.__init__:20 -#: flwr.server.strategy.qfedavg.QFedAvg.__init__:21 of -msgid "Function used to configure training. Defaults to None." -msgstr "用于配置训练的功能。默认为 \"无\"。" +#: ../../source/ref-api/flwr.common.EvaluateRes.rst:31::1 +msgid ":py:obj:`metrics `\\" +msgstr "" -#: flwr.server.strategy.bulyan.Bulyan.__init__:21 -#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:23 -#: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:19 -#: flwr.server.strategy.fedadam.FedAdam.__init__:19 -#: flwr.server.strategy.fedavg.FedAvg.__init__:23 -#: flwr.server.strategy.fedavgm.FedAvgM.__init__:19 -#: flwr.server.strategy.fedopt.FedOpt.__init__:19 -#: flwr.server.strategy.fedprox.FedProx.__init__:55 -#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg.__init__:17 -#: flwr.server.strategy.fedyogi.FedYogi.__init__:19 -#: flwr.server.strategy.krum.Krum.__init__:22 -#: flwr.server.strategy.qfedavg.QFedAvg.__init__:23 of -msgid "Function used to configure validation. Defaults to None." -msgstr "用于配置验证的函数。默认为 \"无\"。" +#: ../../source/ref-api/flwr.common.EventType.rst:2 +#, fuzzy +msgid "EventType" +msgstr "返回类型" -#: flwr.server.strategy.bulyan.Bulyan.__init__:23 -#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:25 -#: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:25 -#: flwr.server.strategy.fedadam.FedAdam.__init__:21 -#: flwr.server.strategy.fedavg.FedAvg.__init__:25 -#: flwr.server.strategy.fedavgm.FedAvgM.__init__:21 -#: flwr.server.strategy.fedopt.FedOpt.__init__:21 -#: flwr.server.strategy.fedprox.FedProx.__init__:57 -#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg.__init__:19 -#: flwr.server.strategy.fedyogi.FedYogi.__init__:21 -#: flwr.server.strategy.krum.Krum.__init__:24 -#: flwr.server.strategy.qfedavg.QFedAvg.__init__:25 of -msgid "Whether or not accept rounds containing failures. Defaults to True." -msgstr "是否接受包含失败的轮。默认为 True。" +#: flwr.common.telemetry.EventType:1 of +msgid "Bases: :py:class:`str`, :py:class:`~enum.Enum`" +msgstr "" -#: flwr.server.strategy.bulyan.Bulyan.__init__:25 -#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:27 -#: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:27 -#: flwr.server.strategy.fedadam.FedAdam.__init__:23 -#: flwr.server.strategy.fedavg.FedAvg.__init__:27 -#: flwr.server.strategy.fedavgm.FedAvgM.__init__:23 -#: flwr.server.strategy.fedopt.FedOpt.__init__:23 -#: flwr.server.strategy.fedprox.FedProx.__init__:59 -#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg.__init__:21 -#: flwr.server.strategy.fedyogi.FedYogi.__init__:23 -#: flwr.server.strategy.krum.Krum.__init__:26 -#: flwr.server.strategy.qfedavg.QFedAvg.__init__:27 of -msgid "Initial global model parameters." -msgstr "初始全局模型参数。" +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`PING `\\" +msgstr "" -#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:29 -#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.__init__:31 -#: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:21 -#: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:23 -#: flwr.server.strategy.fedadam.FedAdam.__init__:25 -#: flwr.server.strategy.fedadam.FedAdam.__init__:27 -#: flwr.server.strategy.fedavg.FedAvg.__init__:29 -#: flwr.server.strategy.fedavg.FedAvg.__init__:31 -#: flwr.server.strategy.fedopt.FedOpt.__init__:25 -#: flwr.server.strategy.fedopt.FedOpt.__init__:27 -#: flwr.server.strategy.fedprox.FedProx.__init__:61 -#: flwr.server.strategy.fedprox.FedProx.__init__:63 -#: flwr.server.strategy.fedyogi.FedYogi.__init__:25 -#: flwr.server.strategy.fedyogi.FedYogi.__init__:27 -#: flwr.server.strategy.qfedavg.QFedAvg.__init__:29 -#: flwr.server.strategy.qfedavg.QFedAvg.__init__:31 of -msgid "Metrics aggregation function, optional." -msgstr "指标汇总功能,可选。" +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`START_CLIENT_ENTER `\\" +msgstr "" -#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1 -#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1 -#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1 of -msgid "Aggregate evaluation losses using weighted average." -msgstr "采用加权平均法计算评估损失总额。" +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`START_CLIENT_LEAVE `\\" +msgstr "" -#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_fit:1 -#: flwr.server.strategy.fedadagrad.FedAdagrad.aggregate_fit:1 -#: flwr.server.strategy.fedadam.FedAdam.aggregate_fit:1 -#: flwr.server.strategy.fedavg.FedAvg.aggregate_fit:1 -#: flwr.server.strategy.fedavgm.FedAvgM.aggregate_fit:1 -#: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg.aggregate_fit:1 -#: flwr.server.strategy.fedyogi.FedYogi.aggregate_fit:1 -#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_fit:1 of -msgid "Aggregate fit results using weighted average." -msgstr "使用加权平均法汇总拟合结果。" +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`START_SERVER_ENTER `\\" +msgstr "" -#: flwr.server.strategy.fedavg.FedAvg.evaluate:1 -#: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg.evaluate:1 of -msgid "Evaluate model parameters using an evaluation function." -msgstr "使用评估函数评估模型参数。" +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`START_SERVER_LEAVE `\\" +msgstr "" -#: flwr.server.strategy.fedavg.FedAvg.initialize_parameters:1 -#: flwr.server.strategy.fedavgm.FedAvgM.initialize_parameters:1 of -msgid "Initialize global model parameters." -msgstr "初始化全局模型参数。" +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid "" +":py:obj:`RUN_DRIVER_API_ENTER " +"`\\" +msgstr "" -#: flwr.server.strategy.fedavg.FedAvg.num_evaluation_clients:1 -#: flwr.server.strategy.qfedavg.QFedAvg.num_evaluation_clients:1 of -msgid "Use a fraction of available clients for evaluation." -msgstr "使用部分可用客户进行评估。" +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid "" +":py:obj:`RUN_DRIVER_API_LEAVE " +"`\\" +msgstr "" -#: flwr.server.strategy.fedavg.FedAvg.num_fit_clients:1 -#: flwr.server.strategy.qfedavg.QFedAvg.num_fit_clients:1 of -msgid "Return the sample size and the required number of available clients." -msgstr "返回样本大小和所需的可用客户数量。" +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid "" +":py:obj:`RUN_FLEET_API_ENTER " +"`\\" +msgstr "" -#: ../../source/ref-api-flwr.rst:101 -msgid "server.strategy.FedAvgM" -msgstr "server.strategy.FedAvgM" +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid "" +":py:obj:`RUN_FLEET_API_LEAVE " +"`\\" +msgstr "" -#: flwr.server.strategy.fedavgm.FedAvgM:1 -#: flwr.server.strategy.fedmedian.FedMedian:1 of -msgid "Configurable FedAvg with Momentum strategy implementation." -msgstr "可配置的 FedAvg 动量策略实施。" +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid "" +":py:obj:`RUN_SUPERLINK_ENTER " +"`\\" +msgstr "" -#: flwr.server.strategy.fedavgm.FedAvgM.__init__:1 of -msgid "Federated Averaging with Momentum strategy." -msgstr "联邦平均动量策略。" +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid "" +":py:obj:`RUN_SUPERLINK_LEAVE " +"`\\" +msgstr "" -#: flwr.server.strategy.fedavgm.FedAvgM.__init__:3 of -msgid "Implementation based on https://arxiv.org/pdf/1909.06335.pdf" -msgstr "实施基于 https://arxiv.org/pdf/1909.06335.pdf" +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid "" +":py:obj:`START_SIMULATION_ENTER " +"`\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid "" +":py:obj:`START_SIMULATION_LEAVE " +"`\\" +msgstr "" -#: flwr.server.strategy.fedavgm.FedAvgM.__init__:5 -#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg.__init__:3 -#: flwr.server.strategy.krum.Krum.__init__:3 of -msgid "Fraction of clients used during training. Defaults to 0.1." -msgstr "训练期间使用客户的比例。默认为 0.1。" +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`DRIVER_CONNECT `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`DRIVER_DISCONNECT `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`START_DRIVER_ENTER `\\" +msgstr "" -#: flwr.server.strategy.fedavgm.FedAvgM.__init__:7 -#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg.__init__:5 -#: flwr.server.strategy.krum.Krum.__init__:5 of -msgid "Fraction of clients used during validation. Defaults to 0.1." -msgstr "验证过程中使用的客户端比例。默认为 0.1。" +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid ":py:obj:`START_DRIVER_LEAVE `\\" +msgstr "" -#: flwr.server.strategy.fedavgm.FedAvgM.__init__:25 of +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 msgid "" -"Server-side learning rate used in server-side optimization. Defaults to 1.0." -msgstr "服务器端优化中使用的服务器端学习率。默认为 1.0。" +":py:obj:`RUN_CLIENT_APP_ENTER " +"`\\" +msgstr "" -#: flwr.server.strategy.fedavgm.FedAvgM.__init__:28 of -msgid "Server-side momentum factor used for FedAvgM. Defaults to 0.0." -msgstr "用于 FedAvgM 的服务器端动量因子。默认为 0.0。" +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid "" +":py:obj:`RUN_CLIENT_APP_LEAVE " +"`\\" +msgstr "" -#: ../../source/ref-api-flwr.rst:112 -msgid "server.strategy.FedMedian" -msgstr "server.strategy.FedMedian" +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid "" +":py:obj:`RUN_SERVER_APP_ENTER " +"`\\" +msgstr "" -#: flwr.server.strategy.fedmedian.FedMedian.aggregate_fit:1 of -msgid "Aggregate fit results using median." -msgstr "使用中位数汇总拟合结果。" +#: ../../source/ref-api/flwr.common.EventType.rst:42::1 +msgid "" +":py:obj:`RUN_SERVER_APP_LEAVE " +"`\\" +msgstr "" -#: ../../source/ref-api-flwr.rst:122 -msgid "server.strategy.QFedAvg" -msgstr "server.strategy.QFedAvg" +#: ../../source/ref-api/flwr.common.FitIns.rst:2 +msgid "FitIns" +msgstr "" -#: flwr.server.strategy.qfedavg.QFedAvg:1 of -msgid "Configurable QFedAvg strategy implementation." -msgstr "可配置的 QFedAvg 策略实施。" +#: ../../source/ref-api/flwr.common.FitIns.rst:29::1 +msgid ":py:obj:`parameters `\\" +msgstr "" -#: ../../source/ref-api-flwr.rst:133 -msgid "server.strategy.FaultTolerantFedAvg" -msgstr "server.strategy.FaultTolerantFedAvg" +#: ../../source/ref-api/flwr.common.FitIns.rst:29::1 +msgid ":py:obj:`config `\\" +msgstr "" -#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg:1 of -msgid "Configurable fault-tolerant FedAvg strategy implementation." -msgstr "可配置的容错 FedAvg 策略实施。" +#: ../../source/ref-api/flwr.common.FitRes.rst:2 +msgid "FitRes" +msgstr "" -#: ../../source/ref-api-flwr.rst:144 -msgid "server.strategy.FedOpt" -msgstr "server.strategy.FedOpt" +#: ../../source/ref-api/flwr.common.FitRes.rst:31::1 +msgid ":py:obj:`status `\\" +msgstr "" -#: flwr.server.strategy.fedopt.FedOpt:1 of -msgid "Configurable FedAdagrad strategy implementation." -msgstr "可配置的 FedAdagrad 策略实施。" +#: ../../source/ref-api/flwr.common.FitRes.rst:31::1 +msgid ":py:obj:`parameters `\\" +msgstr "" -#: flwr.server.strategy.fedopt.FedOpt.__init__:1 of -msgid "Federated Optim strategy interface." -msgstr "Federated Optim 策略界面。" +#: ../../source/ref-api/flwr.common.FitRes.rst:31::1 +msgid ":py:obj:`num_examples `\\" +msgstr "" -#: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:3 -#: flwr.server.strategy.fedadam.FedAdam.__init__:3 -#: flwr.server.strategy.fedopt.FedOpt.__init__:3 -#: flwr.server.strategy.fedyogi.FedYogi.__init__:3 of -msgid "Implementation based on https://arxiv.org/abs/2003.00295v5" -msgstr "实施基于 https://arxiv.org/abs/2003.00295v5" +#: ../../source/ref-api/flwr.common.FitRes.rst:31::1 +msgid ":py:obj:`metrics `\\" +msgstr "" -#: flwr.server.strategy.bulyan.Bulyan.__init__:5 -#: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:5 -#: flwr.server.strategy.fedadam.FedAdam.__init__:5 -#: flwr.server.strategy.fedopt.FedOpt.__init__:5 -#: flwr.server.strategy.fedyogi.FedYogi.__init__:5 of -msgid "Fraction of clients used during training. Defaults to 1.0." -msgstr "训练期间使用客户的比例。默认为 1.0。" +#: ../../source/ref-api/flwr.common.GetParametersIns.rst:2 +#, fuzzy +msgid "GetParametersIns" +msgstr "参数" -#: flwr.server.strategy.bulyan.Bulyan.__init__:7 -#: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:7 -#: flwr.server.strategy.fedadam.FedAdam.__init__:7 -#: flwr.server.strategy.fedopt.FedOpt.__init__:7 -#: flwr.server.strategy.fedyogi.FedYogi.__init__:7 of -msgid "Fraction of clients used during validation. Defaults to 1.0." -msgstr "验证过程中使用的客户端比例。默认为 1.0。" +#: ../../source/ref-api/flwr.common.GetParametersIns.rst:28::1 +msgid ":py:obj:`config `\\" +msgstr "" -#: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:29 -#: flwr.server.strategy.fedadam.FedAdam.__init__:29 -#: flwr.server.strategy.fedopt.FedOpt.__init__:29 -#: flwr.server.strategy.fedyogi.FedYogi.__init__:29 of -msgid "Server-side learning rate. Defaults to 1e-1." -msgstr "服务器端学习率。默认为 1e-1。" +#: ../../source/ref-api/flwr.common.GetParametersRes.rst:2 +#, fuzzy +msgid "GetParametersRes" +msgstr "参数" -#: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:31 -#: flwr.server.strategy.fedadam.FedAdam.__init__:31 -#: flwr.server.strategy.fedopt.FedOpt.__init__:31 -#: flwr.server.strategy.fedyogi.FedYogi.__init__:31 of -msgid "Client-side learning rate. Defaults to 1e-1." -msgstr "客户端学习率。默认为 1e-1。" +#: ../../source/ref-api/flwr.common.GetParametersRes.rst:29::1 +msgid ":py:obj:`status `\\" +msgstr "" -#: flwr.server.strategy.fedopt.FedOpt.__init__:33 of -msgid "Momentum parameter. Defaults to 0.0." -msgstr "动量参数。默认为 0.0。" +#: ../../source/ref-api/flwr.common.GetParametersRes.rst:29::1 +msgid ":py:obj:`parameters `\\" +msgstr "" -#: flwr.server.strategy.fedopt.FedOpt.__init__:35 of -msgid "Second moment parameter. Defaults to 0.0." -msgstr "第二动量参数。默认为 0.0。" +#: ../../source/ref-api/flwr.common.GetPropertiesIns.rst:2 +msgid "GetPropertiesIns" +msgstr "" -#: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:33 -#: flwr.server.strategy.fedadam.FedAdam.__init__:37 -#: flwr.server.strategy.fedopt.FedOpt.__init__:37 -#: flwr.server.strategy.fedyogi.FedYogi.__init__:37 of -msgid "Controls the algorithm's degree of adaptability. Defaults to 1e-9." -msgstr "控制算法的适应度。默认为 1e-9。" +#: ../../source/ref-api/flwr.common.GetPropertiesIns.rst:28::1 +msgid ":py:obj:`config `\\" +msgstr "" -#: ../../source/ref-api-flwr.rst:155 -msgid "server.strategy.FedProx" -msgstr "server.strategy.FedProx" +#: ../../source/ref-api/flwr.common.GetPropertiesRes.rst:2 +msgid "GetPropertiesRes" +msgstr "" -#: flwr.server.strategy.fedprox.FedProx:1 of -msgid "Configurable FedProx strategy implementation." -msgstr "可配置的 FedProx 策略实施。" +#: ../../source/ref-api/flwr.common.GetPropertiesRes.rst:29::1 +msgid ":py:obj:`status `\\" +msgstr "" -#: flwr.server.strategy.fedprox.FedProx.__init__:1 of -msgid "Federated Optimization strategy." -msgstr "联邦优化策略。" +#: ../../source/ref-api/flwr.common.GetPropertiesRes.rst:29::1 +msgid ":py:obj:`properties `\\" +msgstr "" -#: flwr.server.strategy.fedprox.FedProx.__init__:3 of -msgid "Implementation based on https://arxiv.org/abs/1812.06127" -msgstr "实施基于 https://arxiv.org/abs/1812.06127" +#: ../../source/ref-api/flwr.common.NDArray.rst:2 +msgid "NDArray" +msgstr "" -#: flwr.server.strategy.fedprox.FedProx.__init__:5 of -msgid "" -"The strategy in itself will not be different than FedAvg, the client needs " -"to be adjusted. A proximal term needs to be added to the loss function " -"during the training:" -msgstr "策略本身与 FedAvg " -"并无不同,客户端需要进行调整。在训练过程中,需要在损失函数中添加一个近端项:" +#: ../../source/ref-api/flwr.common.Parameters.rst:29::1 +msgid ":py:obj:`tensors `\\" +msgstr "" -#: flwr.server.strategy.fedprox.FedProx.__init__:9 of -msgid "" -"\\\\frac{\\\\mu}{2} || w - w^t ||^2\n" -"\n" +#: ../../source/ref-api/flwr.common.Parameters.rst:29::1 +msgid ":py:obj:`tensor_type `\\" msgstr "" -"\\\\frac{\\\\mu}{2} || w - w^t ||^2\n" -"\n" -#: flwr.server.strategy.fedprox.FedProx.__init__:12 of -msgid "" -"Where $w^t$ are the global parameters and $w$ are the local weights the " -"function will be optimized with." -msgstr "其中,$w^t$ 是全局参数,$w$ 是优化函数的局部权重。" +#: ../../source/ref-api/flwr.common.ReconnectIns.rst:2 +#, fuzzy +msgid "ReconnectIns" +msgstr "启用 SSL 连接" -#: flwr.server.strategy.fedprox.FedProx.__init__:15 of -msgid "In PyTorch, for example, the loss would go from:" -msgstr "例如,在 PyTorch 中,损失将从:" +#: ../../source/ref-api/flwr.common.ReconnectIns.rst:28::1 +msgid ":py:obj:`seconds `\\" +msgstr "" -#: flwr.server.strategy.fedprox.FedProx.__init__:21 of -msgid "To:" -msgstr "致:" +#: ../../source/ref-api/flwr.common.ServerMessage.rst:2 +#, fuzzy +msgid "ServerMessage" +msgstr "服务器端" + +#: ../../source/ref-api/flwr.common.ServerMessage.rst:31::1 +msgid ":py:obj:`evaluate_ins `\\" +msgstr "" + +#: ../../source/ref-api/flwr.common.ServerMessage.rst:31::1 +msgid ":py:obj:`fit_ins `\\" +msgstr "" -#: flwr.server.strategy.fedprox.FedProx.__init__:30 of +#: ../../source/ref-api/flwr.common.ServerMessage.rst:31::1 msgid "" -"With `global_params` being a copy of the parameters before the training " -"takes place." -msgstr "其中,\"global_params \"是训练前的参数副本。" +":py:obj:`get_parameters_ins " +"`\\" +msgstr "" -#: flwr.server.strategy.fedprox.FedProx.__init__:65 of +#: ../../source/ref-api/flwr.common.ServerMessage.rst:31::1 msgid "" -"The weight of the proximal term used in the optimization. 0.0 makes this " -"strategy equivalent to FedAvg, and the higher the coefficient, the more " -"regularization will be used (that is, the client parameters will need to be " -"closer to the server parameters during training)." +":py:obj:`get_properties_ins " +"`\\" msgstr "" -"优化中使用的近端项权重。0.0 使该策略等同于 FedAvg,系数越大,使用的正则化就越" -"多(也就是说,在训练过程中,客户端参数需要更接近服务器参数)。" -#: flwr.server.strategy.fedprox.FedProx.configure_fit:3 of -msgid "Sends the proximal factor mu to the clients" -msgstr "向客户发送近端因子mu" +#: ../../source/ref-api/flwr.common.Status.rst:2 +#, fuzzy +msgid "Status" +msgstr "客户端状态。" -#: ../../source/ref-api-flwr.rst:166 -msgid "server.strategy.FedAdagrad" -msgstr "server.strategy.FedAdagrad" +#: ../../source/ref-api/flwr.common.Status.rst:29::1 +msgid ":py:obj:`code `\\" +msgstr "" -#: flwr.server.strategy.fedadagrad.FedAdagrad:1 of -msgid "FedAdagrad strategy - Adaptive Federated Optimization using Adagrad." -msgstr "FedAdagrad 策略 - 使用 Adagrad 进行自适应联合优化。" +#: ../../source/ref-api/flwr.common.Status.rst:29::1 +msgid ":py:obj:`message `\\" +msgstr "" -#: flwr.server.strategy.fedadagrad.FedAdagrad:3 -#: flwr.server.strategy.fedadam.FedAdam:3 -#: flwr.server.strategy.fedyogi.FedYogi:5 of -msgid "Paper: https://arxiv.org/abs/2003.00295" -msgstr "论文: https://arxiv.org/abs/2003.00295" +#: ../../source/ref-api/flwr.common.bytes_to_ndarray.rst:2 +msgid "bytes\\_to\\_ndarray" +msgstr "" -#: flwr.server.strategy.fedadagrad.FedAdagrad.__init__:1 -#: flwr.server.strategy.fedadam.FedAdam.__init__:1 of -msgid "Federated learning strategy using Adagrad on server-side." -msgstr "在服务器端使用 Adagrad 的联邦学习策略。" +#: ../../source/ref-api/flwr.common.configure.rst:2 +#, fuzzy +msgid "configure" +msgstr "配置日志记录" -#: ../../source/ref-api-flwr.rst:177 -msgid "server.strategy.FedAdam" -msgstr "server.strategy.FedAdam" +#: ../../source/ref-api/flwr.common.event.rst:2 +msgid "event" +msgstr "" -#: flwr.server.strategy.fedadam.FedAdam:1 of -msgid "FedAdam - Adaptive Federated Optimization using Adam." -msgstr "FedAdam - 使用 Adam 进行自适应联合优化。" +#: ../../source/ref-api/flwr.common.log.rst:2 +msgid "log" +msgstr "" -#: flwr.server.strategy.fedadam.FedAdam.__init__:33 -#: flwr.server.strategy.fedyogi.FedYogi.__init__:33 of -msgid "Momentum parameter. Defaults to 0.9." -msgstr "动量参数。默认为 0.9。" +#: logging.Logger.log:3 of +msgid "" +"To pass exception information, use the keyword argument exc_info with a " +"true value, e.g." +msgstr "要传递异常信息,请使用带 true 值的关键字参数 exc_info,例如。" -#: flwr.server.strategy.fedadam.FedAdam.__init__:35 -#: flwr.server.strategy.fedyogi.FedYogi.__init__:35 of -msgid "Second moment parameter. Defaults to 0.99." -msgstr "第二动量参数。默认为 0.99。" +#: logging.Logger.log:6 of +#, python-format +msgid "logger.log(level, \"We have a %s\", \"mysterious problem\", exc_info=1)" +msgstr "logger.log(level, \"We have a %s\", \"mysterious problem\", exc_info=1)" -#: ../../source/ref-api-flwr.rst:188 -msgid "server.strategy.FedYogi" -msgstr "server.strategy.FedYogi" +#: ../../source/ref-api/flwr.common.ndarray_to_bytes.rst:2 +msgid "ndarray\\_to\\_bytes" +msgstr "" -#: flwr.server.strategy.fedyogi.FedYogi:1 of -msgid "FedYogi [Reddi et al., 2020] strategy." -msgstr "FedYogi [Reddi 等人,2020] 策略。" +#: ../../source/ref-api/flwr.common.ndarrays_to_parameters.rst:2 +msgid "ndarrays\\_to\\_parameters" +msgstr "" -#: flwr.server.strategy.fedyogi.FedYogi:3 of -msgid "Adaptive Federated Optimization using Yogi." -msgstr "使用 Yogi 的自适应联合优化。" +#: ../../source/ref-api/flwr.common.now.rst:2 +msgid "now" +msgstr "" -#: flwr.server.strategy.fedyogi.FedYogi.__init__:1 of -msgid "Federated learning strategy using Yogi on server-side." -msgstr "在服务器端使用 Yogi 的联邦学习策略。" +#: ../../source/ref-api/flwr.common.parameters_to_ndarrays.rst:2 +msgid "parameters\\_to\\_ndarrays" +msgstr "" -#: ../../source/ref-api-flwr.rst:199 -msgid "server.strategy.FedTrimmedAvg" -msgstr "server.strategy.FedTrimmedAvg" +#: ../../source/ref-api/flwr.server.rst:2 +msgid "server" +msgstr "服务器" -#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:1 -#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg.__init__:1 of -msgid "Federated Averaging with Trimmed Mean [Dong Yin, et al., 2021]." -msgstr "带修剪均值的联邦平均法[Dong Yin 等,2021]。" +#: ../../source/ref-api/flwr.server.rst:26::1 +msgid ":py:obj:`run_driver_api `\\ \\(\\)" +msgstr "" -#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:3 of -msgid "Paper: https://arxiv.org/abs/1803.01498" -msgstr "论文:https://arxiv.org/abs/1803.01498" +#: ../../source/ref-api/flwr.server.rst:26::1 +#: flwr.server.app.run_driver_api:1 of +#, fuzzy +msgid "Run Flower server (Driver API)." +msgstr "flower-driver-api" -#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg.__init__:23 of -msgid "Fraction to cut off of both tails of the distribution. Defaults to 0.2." -msgstr "截取分布两个尾部的分数。默认为 0.2。" +#: ../../source/ref-api/flwr.server.rst:26::1 +msgid ":py:obj:`run_fleet_api `\\ \\(\\)" +msgstr "" -#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg.aggregate_fit:1 of -msgid "Aggregate fit results using trimmed average." -msgstr "使用修剪平均值汇总拟合结果。" +#: ../../source/ref-api/flwr.server.rst:26::1 +#: flwr.server.app.run_fleet_api:1 of +#, fuzzy +msgid "Run Flower server (Fleet API)." +msgstr "Flower 服务器。" -#: ../../source/ref-api-flwr.rst:210 -msgid "server.strategy.Krum" -msgstr "server.strategy.Krum" +#: ../../source/ref-api/flwr.server.rst:26::1 +msgid ":py:obj:`run_server_app `\\ \\(\\)" +msgstr "" -#: flwr.server.strategy.krum.Krum:1 of -msgid "Configurable Krum strategy implementation." -msgstr "可配置的 Krum 策略实施。" +#: ../../source/ref-api/flwr.server.rst:26::1 +#: flwr.server.app.run_server_app:1 of +#, fuzzy +msgid "Run Flower server app." +msgstr "Flower 服务器。" -#: flwr.server.strategy.krum.Krum.__init__:1 of -msgid "Krum strategy." -msgstr "Krum 策略。" +#: ../../source/ref-api/flwr.server.rst:26::1 +msgid ":py:obj:`run_superlink `\\ \\(\\)" +msgstr "" -#: flwr.server.strategy.bulyan.Bulyan.__init__:15 -#: flwr.server.strategy.krum.Krum.__init__:13 of -msgid "Number of malicious clients in the system. Defaults to 0." -msgstr "系统中恶意客户端的数量。默认为 0。" +#: ../../source/ref-api/flwr.server.rst:26::1 +#: flwr.server.app.run_superlink:1 of +msgid "Run Flower server (Driver API and Fleet API)." +msgstr "" -#: flwr.server.strategy.krum.Krum.__init__:15 of +#: ../../source/ref-api/flwr.server.rst:26::1 msgid "" -"Number of clients to keep before averaging (MultiKrum). Defaults to 0, in " -"that case classical Krum is applied." +":py:obj:`start_server `\\ \\(\\*\\[\\, " +"server\\_address\\, server\\, ...\\]\\)" msgstr "" -"求平均值前保留的客户端数量(MultiKrum)。默认值为 0,在这种情况下会应用经典 " -"Krum。" -#: flwr.server.strategy.krum.Krum.aggregate_fit:1 of -msgid "Aggregate fit results using Krum." -msgstr "使用 Krum 汇总拟合结果。" +#: ../../source/ref-api/flwr.server.rst:26::1 +#: flwr.server.app.start_server:1 of +msgid "Start a Flower server using the gRPC transport layer." +msgstr "使用 gRPC 传输层启动 Flower 服务器。" -#: ../../source/ref-api-flwr.rst:220 -msgid "server.strategy.Bulyan" -msgstr "server.strategy.Bulyan" +#: ../../source/ref-api/flwr.server.rst:37::1 +msgid ":py:obj:`ClientManager `\\ \\(\\)" +msgstr "" -#: flwr.server.strategy.bulyan.Bulyan:1 of -msgid "Bulyan strategy implementation." -msgstr "Bulyan策略的实施。" +#: ../../source/ref-api/flwr.server.rst:37::1 +#: flwr.server.client_manager.ClientManager:1 of +#, fuzzy +msgid "Abstract base class for managing Flower clients." +msgstr "Flower 客户端的抽象基类。" -#: flwr.server.strategy.bulyan.Bulyan.__init__:1 of -msgid "Bulyan strategy." -msgstr "Bulyan 策略。" +#: ../../source/ref-api/flwr.server.rst:37::1 +msgid ":py:obj:`History `\\ \\(\\)" +msgstr "" -#: flwr.server.strategy.bulyan.Bulyan.__init__:3 of -msgid "Implementation based on https://arxiv.org/abs/1802.07927." -msgstr "实施基于 https://arxiv.org/abs/1802.07927。" +#: ../../source/ref-api/flwr.server.rst:37::1 +#: flwr.server.history.History:1 of +#, fuzzy +msgid "History class for training and/or evaluation metrics collection." +msgstr "**hist** -- 包含训练和评估指标的对象。" -#: flwr.server.strategy.bulyan.Bulyan.__init__:27 of +#: ../../source/ref-api/flwr.server.rst:37::1 msgid "" -"Byzantine resilient aggregation rule that is used as the first step of the " -"Bulyan (e.g., Krum)" -msgstr "Byzantine弹性聚合规则,用作 Bulyan 的第一步(如 Krum)" +":py:obj:`Server `\\ \\(\\*\\, client\\_manager\\[\\, " +"strategy\\]\\)" +msgstr "" -#: flwr.server.strategy.bulyan.Bulyan.__init__:29 of -msgid "arguments to the first_aggregation rule" -msgstr "第一聚类规则的参数" +#: ../../source/ref-api/flwr.server.rst:37::1 +#, fuzzy +msgid "" +":py:obj:`ServerConfig `\\ \\(\\[num\\_rounds\\," +" round\\_timeout\\]\\)" +msgstr "" +"Flower 1.0: ``start_server(..., " +"config=flwr.server.ServerConfig(num_rounds=3, round_timeout=600.0), " +"...)``" -#: flwr.server.strategy.bulyan.Bulyan.aggregate_fit:1 of -msgid "Aggregate fit results using Bulyan." -msgstr "使用 Bulyan 技术汇总拟合结果。" +#: ../../source/ref-api/flwr.server.rst:37::1 +#: flwr.server.app.ServerConfig:1 of +#, fuzzy +msgid "Flower server config." +msgstr "Flower 服务器。" -#: ../../source/ref-api-flwr.rst:231 -msgid "server.strategy.FedXgbNnAvg" -msgstr "server.strategy.FedXgbNnAvg" +#: ../../source/ref-api/flwr.server.rst:37::1 +msgid ":py:obj:`SimpleClientManager `\\ \\(\\)" +msgstr "" -#: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg:1 of -msgid "Configurable FedXgbNnAvg strategy implementation." -msgstr "可配置的 FedXgbNAvg 策略实施。" +#: ../../source/ref-api/flwr.server.rst:37::1 +#: flwr.server.client_manager.SimpleClientManager:1 of +#, fuzzy +msgid "Provides a pool of available clients." +msgstr "使用部分可用客户进行评估。" -#: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg.__init__:1 of -msgid "Federated XGBoost [Ma et al., 2023] strategy." -msgstr "Federated XGBoost [Ma 等人,2023] 策略。" +#: ../../source/ref-api/flwr.server.rst:56::1 +msgid ":py:obj:`flwr.server.driver `\\" +msgstr "" -#: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg.__init__:3 of -msgid "Implementation based on https://arxiv.org/abs/2304.07537." -msgstr "实施基于 https://arxiv.org/abs/2304.07537。" +#: ../../source/ref-api/flwr.server.rst:56::1 flwr.server.driver:1 +#: of +#, fuzzy +msgid "Flower driver SDK." +msgstr "Flower 服务器。" -#: ../../source/ref-api-flwr.rst:242 -msgid "server.strategy.DPFedAvgAdaptive" -msgstr "server.strategy.DPFedAvgAdaptive" +#: ../../source/ref-api/flwr.server.rst:56::1 +#, fuzzy +msgid ":py:obj:`flwr.server.strategy `\\" +msgstr "server.strategy.Strategy" -#: flwr.server.strategy.dpfedavg_adaptive.DPFedAvgAdaptive:1 of -msgid "Wrapper for configuring a Strategy for DP with Adaptive Clipping." -msgstr "用于配置具有自适应剪切功能的 DP 策略的包装器。" +#: ../../source/ref-api/flwr.server.rst:56::1 +#: flwr.server.strategy:1 of +msgid "Contains the strategy abstraction and different implementations." +msgstr "包含策略抽象和不同的实现方法。" -#: flwr.server.strategy.dpfedavg_adaptive.DPFedAvgAdaptive.aggregate_fit:1 of -msgid "Aggregate training results as in DPFedAvgFixed and update clip norms." -msgstr "汇总 DPFedAvgFixed 中的训练结果并更新片段标准。" +#: ../../source/ref-api/flwr.server.ClientManager.rst:2 +#, fuzzy +msgid "ClientManager" +msgstr "客户端" -#: ../../source/ref-api-flwr.rst:253 -msgid "server.strategy.DPFedAvgFixed" -msgstr "server.strategy.DPFedAvgFixed" +#: flwr.server.client_manager.ClientManager.all:1::1 of +msgid ":py:obj:`all `\\ \\(\\)" +msgstr "" -#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed:1 of +#: flwr.server.client_manager.ClientManager.all:1 +#: flwr.server.client_manager.ClientManager.all:1::1 +#: flwr.server.client_manager.SimpleClientManager.all:1 +#: flwr.server.client_manager.SimpleClientManager.all:1::1 of +msgid "Return all available clients." +msgstr "" + +#: flwr.server.client_manager.ClientManager.all:1::1 of +msgid ":py:obj:`num_available `\\ \\(\\)" +msgstr "" + +#: flwr.server.client_manager.ClientManager.all:1::1 +#: flwr.server.client_manager.ClientManager.num_available:1 +#: flwr.server.client_manager.SimpleClientManager.all:1::1 +#: flwr.server.client_manager.SimpleClientManager.num_available:1 of +#, fuzzy +msgid "Return the number of available clients." +msgstr "返回样本大小和所需的可用客户数量。" + +#: flwr.server.client_manager.ClientManager.all:1::1 of +msgid ":py:obj:`register `\\ \\(client\\)" +msgstr "" + +#: flwr.server.client_manager.ClientManager.all:1::1 +#: flwr.server.client_manager.ClientManager.register:1 +#: flwr.server.client_manager.SimpleClientManager.all:1::1 +#: flwr.server.client_manager.SimpleClientManager.register:1 of +msgid "Register Flower ClientProxy instance." +msgstr "" + +#: flwr.server.client_manager.ClientManager.all:1::1 of +msgid "" +":py:obj:`sample `\\ " +"\\(num\\_clients\\[\\, min\\_num\\_clients\\, criterion\\]\\)" +msgstr "" + +#: flwr.server.client_manager.ClientManager.all:1::1 +#: flwr.server.client_manager.ClientManager.sample:1 +#: flwr.server.client_manager.SimpleClientManager.all:1::1 +#: flwr.server.client_manager.SimpleClientManager.sample:1 of +msgid "Sample a number of Flower ClientProxy instances." +msgstr "" + +#: flwr.server.client_manager.ClientManager.all:1::1 of +msgid ":py:obj:`unregister `\\ \\(client\\)" +msgstr "" + +#: flwr.server.client_manager.ClientManager.all:1::1 +#: flwr.server.client_manager.ClientManager.unregister:1 +#: flwr.server.client_manager.SimpleClientManager.all:1::1 +#: flwr.server.client_manager.SimpleClientManager.unregister:1 of +msgid "Unregister Flower ClientProxy instance." +msgstr "" + +#: flwr.server.client_manager.ClientManager.all:1::1 of +msgid "" +":py:obj:`wait_for `\\ " +"\\(num\\_clients\\, timeout\\)" +msgstr "" + +#: flwr.server.client_manager.ClientManager.all:1::1 +#: flwr.server.client_manager.ClientManager.wait_for:1 +#: flwr.server.client_manager.SimpleClientManager.all:1::1 +#: flwr.server.client_manager.SimpleClientManager.wait_for:1 of +msgid "Wait until at least `num_clients` are available." +msgstr "" + +#: flwr.server.client_manager.ClientManager.num_available:3 +#: flwr.server.client_manager.SimpleClientManager.num_available:3 of +msgid "**num_available** -- The number of currently available clients." +msgstr "" + +#: flwr.server.client_manager.ClientManager.register:6 +#: flwr.server.client_manager.SimpleClientManager.register:6 of +msgid "" +"**success** -- Indicating if registration was successful. False if " +"ClientProxy is already registered or can not be registered for any " +"reason." +msgstr "" + +#: flwr.server.client_manager.ClientManager.unregister:3 +#: flwr.server.client_manager.SimpleClientManager.unregister:3 of +msgid "This method is idempotent." +msgstr "" + +#: ../../source/ref-api/flwr.server.History.rst:2 +msgid "History" +msgstr "" + +#: flwr.server.history.History.add_loss_centralized:1::1 of +msgid "" +":py:obj:`add_loss_centralized " +"`\\ \\(server\\_round\\, " +"loss\\)" +msgstr "" + +#: flwr.server.history.History.add_loss_centralized:1 +#: flwr.server.history.History.add_loss_centralized:1::1 of +#, fuzzy +msgid "Add one loss entry (from centralized evaluation)." +msgstr "集中评估" + +#: flwr.server.history.History.add_loss_centralized:1::1 of +msgid "" +":py:obj:`add_loss_distributed " +"`\\ \\(server\\_round\\, " +"loss\\)" +msgstr "" + +#: flwr.server.history.History.add_loss_centralized:1::1 +#: flwr.server.history.History.add_loss_distributed:1 of +msgid "Add one loss entry (from distributed evaluation)." +msgstr "" + +#: flwr.server.history.History.add_loss_centralized:1::1 of +msgid "" +":py:obj:`add_metrics_centralized " +"`\\ \\(server\\_round\\, " +"metrics\\)" +msgstr "" + +#: flwr.server.history.History.add_loss_centralized:1::1 +#: flwr.server.history.History.add_metrics_centralized:1 of +#, fuzzy +msgid "Add metrics entries (from centralized evaluation)." +msgstr "集中评估" + +#: flwr.server.history.History.add_loss_centralized:1::1 of +msgid "" +":py:obj:`add_metrics_distributed " +"`\\ \\(server\\_round\\, " +"metrics\\)" +msgstr "" + +#: flwr.server.history.History.add_loss_centralized:1::1 +#: flwr.server.history.History.add_metrics_distributed:1 of +#, fuzzy +msgid "Add metrics entries (from distributed evaluation)." +msgstr "定制的集中/分布式评估" + +#: flwr.server.history.History.add_loss_centralized:1::1 of +msgid "" +":py:obj:`add_metrics_distributed_fit " +"`\\ \\(server\\_round\\," +" ...\\)" +msgstr "" + +#: flwr.server.history.History.add_loss_centralized:1::1 +#: flwr.server.history.History.add_metrics_distributed_fit:1 of +msgid "Add metrics entries (from distributed fit)." +msgstr "" + +#: flwr.server.server.Server.client_manager:1::1 of +msgid ":py:obj:`client_manager `\\ \\(\\)" +msgstr "" + +#: flwr.server.server.Server.client_manager:1 +#: flwr.server.server.Server.client_manager:1::1 of +#, fuzzy +msgid "Return ClientManager." +msgstr "返回客户端(本身)。" + +#: flwr.server.server.Server.client_manager:1::1 of +msgid "" +":py:obj:`disconnect_all_clients " +"`\\ \\(timeout\\)" +msgstr "" + +#: flwr.server.server.Server.client_manager:1::1 +#: flwr.server.server.Server.disconnect_all_clients:1 of +msgid "Send shutdown signal to all clients." +msgstr "" + +#: flwr.server.server.Server.client_manager:1::1 of +msgid "" +":py:obj:`evaluate_round `\\ " +"\\(server\\_round\\, timeout\\)" +msgstr "" + +#: flwr.server.server.Server.client_manager:1::1 +#: flwr.server.server.Server.evaluate_round:1 of +#, fuzzy +msgid "Validate current global model on a number of clients." +msgstr "当前(全局)模型参数。" + +#: flwr.server.server.Server.client_manager:1::1 of +msgid ":py:obj:`fit `\\ \\(num\\_rounds\\, timeout\\)" +msgstr "" + +#: flwr.server.server.Server.client_manager:1::1 +#: flwr.server.server.Server.fit:1 of +#, fuzzy +msgid "Run federated averaging for a number of rounds." +msgstr "联邦平均动量策略。" + +#: flwr.server.server.Server.client_manager:1::1 of +msgid "" +":py:obj:`fit_round `\\ \\(server\\_round\\," +" timeout\\)" +msgstr "" + +#: flwr.server.server.Server.client_manager:1::1 +#: flwr.server.server.Server.fit_round:1 of +#, fuzzy +msgid "Perform a single round of federated averaging." +msgstr "本轮联邦学习。" + +#: flwr.server.server.Server.client_manager:1::1 of +msgid "" +":py:obj:`set_max_workers `\\ " +"\\(max\\_workers\\)" +msgstr "" + +#: flwr.server.server.Server.client_manager:1::1 +#: flwr.server.server.Server.set_max_workers:1 of +msgid "Set the max_workers used by ThreadPoolExecutor." +msgstr "" + +#: flwr.server.server.Server.client_manager:1::1 of +msgid ":py:obj:`set_strategy `\\ \\(strategy\\)" +msgstr "" + +#: flwr.server.server.Server.client_manager:1::1 +#: flwr.server.server.Server.set_strategy:1 of +#, fuzzy +msgid "Replace server strategy." +msgstr "server.strategy" + +#: ../../source/ref-api/flwr.server.ServerConfig.rst:2 +#, fuzzy +msgid "ServerConfig" +msgstr "服务器" + +#: flwr.server.app.ServerConfig:3 of +msgid "" +"All attributes have default values which allows users to configure just " +"the ones they care about." +msgstr "" + +#: ../../source/ref-api/flwr.server.ServerConfig.rst:29::1 +msgid ":py:obj:`num_rounds `\\" +msgstr "" + +#: ../../source/ref-api/flwr.server.ServerConfig.rst:29::1 +msgid ":py:obj:`round_timeout `\\" +msgstr "" + +#: ../../source/ref-api/flwr.server.SimpleClientManager.rst:2 +msgid "SimpleClientManager" +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager:1 of +msgid "Bases: :py:class:`~flwr.server.client_manager.ClientManager`" +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager.all:1::1 of +msgid ":py:obj:`all `\\ \\(\\)" +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager.all:1::1 of +msgid "" +":py:obj:`num_available `\\" +" \\(\\)" +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager.all:1::1 of +msgid "" +":py:obj:`register `\\ " +"\\(client\\)" +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager.all:1::1 of +msgid "" +":py:obj:`sample `\\ " +"\\(num\\_clients\\[\\, min\\_num\\_clients\\, criterion\\]\\)" +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager.all:1::1 of +msgid "" +":py:obj:`unregister `\\ " +"\\(client\\)" +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager.all:1::1 of +msgid "" +":py:obj:`wait_for `\\ " +"\\(num\\_clients\\[\\, timeout\\]\\)" +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager.wait_for:3 of +msgid "" +"Blocks until the requested number of clients is available or until a " +"timeout is reached. Current timeout default: 1 day." +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager.wait_for:6 of +msgid "The number of clients to wait for." +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager.wait_for:8 of +msgid "The time in seconds to wait for, defaults to 86400 (24h)." +msgstr "" + +#: flwr.server.client_manager.SimpleClientManager.wait_for:11 of +msgid "**success**" +msgstr "" + +#: ../../source/ref-api/flwr.server.driver.rst:2 +#, fuzzy +msgid "driver" +msgstr "服务器" + +#: ../../source/ref-api/flwr.server.driver.rst:22::1 +msgid "" +":py:obj:`start_driver `\\ \\(\\*\\[\\, " +"server\\_address\\, server\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.driver.rst:22::1 +#: flwr.server.driver.app.start_driver:1 of +#, fuzzy +msgid "Start a Flower Driver API server." +msgstr "启动基于 Ray 的Flower模拟服务器。" + +#: ../../source/ref-api/flwr.server.driver.rst:30::1 +msgid "" +":py:obj:`Driver `\\ " +"\\(\\[driver\\_service\\_address\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.driver.rst:30::1 +#: flwr.server.driver.driver.Driver:1 of +msgid "`Driver` class provides an interface to the Driver API." +msgstr "" + +#: ../../source/ref-api/flwr.server.driver.rst:30::1 +msgid "" +":py:obj:`GrpcDriver `\\ " +"\\(\\[driver\\_service\\_address\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.driver.rst:30::1 +#: flwr.server.driver.grpc_driver.GrpcDriver:1 of +msgid "`GrpcDriver` provides access to the gRPC Driver API/service." +msgstr "" + +#: ../../source/ref-api/flwr.server.driver.Driver.rst:2 +#, fuzzy +msgid "Driver" +msgstr "服务器" + +#: flwr.server.driver.driver.Driver:3 of +#, fuzzy +msgid "" +"The IPv4 or IPv6 address of the Driver API server. Defaults to " +"`\"[::]:9091\"`." +msgstr "服务器的 IPv4 或 IPv6 地址。默认为 `\"[::]:8080\"。" + +#: flwr.server.app.start_server:28 flwr.server.driver.driver.Driver:6 of +msgid "" +"Tuple containing root certificate, server certificate, and private key to" +" start a secure SSL-enabled server. The tuple is expected to have three " +"bytes elements in the following order: * CA certificate. * " +"server certificate. * server private key." +msgstr "" +"包含根证书、服务器证书和私钥的元组,用于启动启用 SSL 的安全服务器。元组应按以下顺序包含三个字节元素: * CA 证书,* 服务器证书, * " +"服务器私钥。" + +#: flwr.server.app.start_server:28 flwr.server.driver.driver.Driver:6 of +msgid "" +"Tuple containing root certificate, server certificate, and private key to" +" start a secure SSL-enabled server. The tuple is expected to have three " +"bytes elements in the following order:" +msgstr "包含根证书、服务器证书和私钥的元组,用于启动启用 SSL 的安全服务器。元组应按以下顺序包含三个字节元素:" + +#: flwr.server.app.start_server:32 flwr.server.driver.driver.Driver:10 of +msgid "CA certificate." +msgstr "CA 证书。" + +#: flwr.server.app.start_server:33 flwr.server.driver.driver.Driver:11 of +msgid "server certificate." +msgstr "服务器证书。" + +#: flwr.server.app.start_server:34 flwr.server.driver.driver.Driver:12 of +msgid "server private key." +msgstr "服务器私人密钥。" + +#: flwr.server.driver.driver.Driver.get_nodes:1::1 of +msgid ":py:obj:`get_nodes `\\ \\(\\)" +msgstr "" + +#: flwr.server.driver.driver.Driver.get_nodes:1 +#: flwr.server.driver.driver.Driver.get_nodes:1::1 of +msgid "Get node IDs." +msgstr "" + +#: flwr.server.driver.driver.Driver.get_nodes:1::1 of +msgid "" +":py:obj:`pull_task_res `\\ " +"\\(task\\_ids\\)" +msgstr "" + +#: flwr.server.driver.driver.Driver.get_nodes:1::1 +#: flwr.server.driver.driver.Driver.pull_task_res:1 +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 +#: flwr.server.driver.grpc_driver.GrpcDriver.pull_task_res:1 of +#, fuzzy +msgid "Get task results." +msgstr "汇总训练结果。" + +#: flwr.server.driver.driver.Driver.get_nodes:1::1 of +msgid "" +":py:obj:`push_task_ins `\\ " +"\\(task\\_ins\\_list\\)" +msgstr "" + +#: flwr.server.driver.driver.Driver.get_nodes:1::1 +#: flwr.server.driver.driver.Driver.push_task_ins:1 +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 +#: flwr.server.driver.grpc_driver.GrpcDriver.push_task_ins:1 of +msgid "Schedule tasks." +msgstr "" + +#: ../../source/ref-api/flwr.server.driver.GrpcDriver.rst:2 +msgid "GrpcDriver" +msgstr "" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 of +msgid ":py:obj:`connect `\\ \\(\\)" +msgstr "" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1 +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 of +msgid "Connect to the Driver API." +msgstr "" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 of +msgid "" +":py:obj:`create_run `\\ " +"\\(req\\)" +msgstr "" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 +#: flwr.server.driver.grpc_driver.GrpcDriver.create_run:1 of +#, fuzzy +msgid "Request for run ID." +msgstr "Flower 基线申请" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 of +msgid ":py:obj:`disconnect `\\ \\(\\)" +msgstr "" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 +#: flwr.server.driver.grpc_driver.GrpcDriver.disconnect:1 of +msgid "Disconnect from the Driver API." +msgstr "" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 of +msgid ":py:obj:`get_nodes `\\ \\(req\\)" +msgstr "" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 +#: flwr.server.driver.grpc_driver.GrpcDriver.get_nodes:1 of +#, fuzzy +msgid "Get client IDs." +msgstr "返回客户端(本身)。" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 of +msgid "" +":py:obj:`pull_task_res `\\ " +"\\(req\\)" +msgstr "" + +#: flwr.server.driver.grpc_driver.GrpcDriver.connect:1::1 of +msgid "" +":py:obj:`push_task_ins `\\ " +"\\(req\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.driver.start_driver.rst:2 +#, fuzzy +msgid "start\\_driver" +msgstr "启动客户端" + +#: flwr.server.driver.app.start_driver:3 of +#, fuzzy +msgid "" +"The IPv4 or IPv6 address of the Driver API server. Defaults to " +"`\"[::]:8080\"`." +msgstr "服务器的 IPv4 或 IPv6 地址。默认为 `\"[::]:8080\"。" + +#: flwr.server.driver.app.start_driver:6 of +#, fuzzy +msgid "" +"A server implementation, either `flwr.server.Server` or a subclass " +"thereof. If no instance is provided, then `start_driver` will create one." +msgstr "服务器实现,可以是 `flwr.server.Server` 或其子类。如果没有提供实例,`start_server` 将创建一个。" + +#: flwr.server.app.start_server:9 flwr.server.driver.app.start_driver:10 +#: flwr.simulation.app.start_simulation:28 of +msgid "" +"Currently supported values are `num_rounds` (int, default: 1) and " +"`round_timeout` in seconds (float, default: None)." +msgstr "目前支持的值有:`num_rounds`(int,默认值:1)和以秒为单位的`round_timeout`(float,默认值:无)。" + +#: flwr.server.app.start_server:12 flwr.server.driver.app.start_driver:13 of +msgid "" +"An implementation of the abstract base class " +"`flwr.server.strategy.Strategy`. If no strategy is provided, then " +"`start_server` will use `flwr.server.strategy.FedAvg`." +msgstr "" +"抽象基类 `flwr.server.strategy.Strategy` 的实现。如果没有提供策略,`start_server` 将使用 " +"`flwr.server.strategy.FedAvg`。" + +#: flwr.server.driver.app.start_driver:17 of +#, fuzzy +msgid "" +"An implementation of the class `flwr.server.ClientManager`. If no " +"implementation is provided, then `start_driver` will use " +"`flwr.server.SimpleClientManager`." +msgstr "" +"抽象基类 `flwr.server.ClientManager` 的实现。如果没有提供实现,`start_server` 将使用 " +"`flwr.server.client_manager.SimpleClientManager`。" + +#: flwr.server.app.start_server:37 flwr.server.driver.app.start_driver:26 of +msgid "**hist** -- Object containing training and evaluation metrics." +msgstr "**hist** -- 包含训练和评估指标的对象。" + +#: flwr.server.driver.app.start_driver:31 of +#, fuzzy +msgid "Starting a driver that connects to an insecure server:" +msgstr "启动不安全的服务器:" + +#: flwr.server.driver.app.start_driver:35 of +#, fuzzy +msgid "Starting a driver that connects to an SSL-enabled server:" +msgstr "启动支持 SSL 的服务器:" + +#: ../../source/ref-api/flwr.server.run_driver_api.rst:2 +#, fuzzy +msgid "run\\_driver\\_api" +msgstr "flower-driver-api" + +#: ../../source/ref-api/flwr.server.run_fleet_api.rst:2 +msgid "run\\_fleet\\_api" +msgstr "" + +#: ../../source/ref-api/flwr.server.run_server_app.rst:2 +msgid "run\\_server\\_app" +msgstr "" + +#: ../../source/ref-api/flwr.server.run_superlink.rst:2 +#, fuzzy +msgid "run\\_superlink" +msgstr "flower-superlink" + +#: ../../source/ref-api/flwr.server.start_server.rst:2 +#, fuzzy +msgid "start\\_server" +msgstr "server.start_server" + +#: flwr.server.app.start_server:3 of +msgid "The IPv4 or IPv6 address of the server. Defaults to `\"[::]:8080\"`." +msgstr "服务器的 IPv4 或 IPv6 地址。默认为 `\"[::]:8080\"。" + +#: flwr.server.app.start_server:5 of +msgid "" +"A server implementation, either `flwr.server.Server` or a subclass " +"thereof. If no instance is provided, then `start_server` will create one." +msgstr "服务器实现,可以是 `flwr.server.Server` 或其子类。如果没有提供实例,`start_server` 将创建一个。" + +#: flwr.server.app.start_server:16 of +msgid "" +"An implementation of the abstract base class `flwr.server.ClientManager`." +" If no implementation is provided, then `start_server` will use " +"`flwr.server.client_manager.SimpleClientManager`." +msgstr "" +"抽象基类 `flwr.server.ClientManager` 的实现。如果没有提供实现,`start_server` 将使用 " +"`flwr.server.client_manager.SimpleClientManager`。" + +#: flwr.server.app.start_server:21 of +msgid "" +"The maximum length of gRPC messages that can be exchanged with the Flower" +" clients. The default should be sufficient for most models. Users who " +"train very large models might need to increase this value. Note that the " +"Flower clients need to be started with the same value (see " +"`flwr.client.start_client`), otherwise clients will not know about the " +"increased limit and block larger messages." +msgstr "" +"可与 Flower 客户端交换的 gRPC 消息的最大长度:默认值对大多数模型都足够了。训练超大模型的用户可能需要增加该值。请注意,Flower " +"客户端需要以相同的值启动(请参阅 `flwr.client.start_client`),否则客户端将不知道已增加的限制并阻止更大的消息。" + +#: flwr.server.app.start_server:42 of +msgid "Starting an insecure server:" +msgstr "启动不安全的服务器:" + +#: flwr.server.app.start_server:46 of +msgid "Starting an SSL-enabled server:" +msgstr "启动支持 SSL 的服务器:" + +#: ../../source/ref-api/flwr.server.strategy.rst:2 +#, fuzzy +msgid "strategy" +msgstr "Krum 策略。" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FaultTolerantFedAvg " +"`\\ \\(\\*\\[\\, " +"fraction\\_fit\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg:1 of +msgid "Configurable fault-tolerant FedAvg strategy implementation." +msgstr "可配置的容错 FedAvg 策略实施。" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedAdagrad `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedadagrad.FedAdagrad:1 of +msgid "FedAdagrad strategy - Adaptive Federated Optimization using Adagrad." +msgstr "FedAdagrad 策略 - 使用 Adagrad 进行自适应联合优化。" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedAdam `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedadam.FedAdam:1 of +msgid "FedAdam - Adaptive Federated Optimization using Adam." +msgstr "FedAdam - 使用 Adam 进行自适应联合优化。" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedAvg `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, fraction\\_evaluate\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedavg.FedAvg:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:1 of +msgid "Federated Averaging strategy." +msgstr "联邦平均策略。" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedXgbNnAvg `\\ \\(\\*args\\, " +"\\*\\*kwargs\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg:1 of +msgid "Configurable FedXgbNnAvg strategy implementation." +msgstr "可配置的 FedXgbNAvg 策略实施。" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedXgbBagging `\\ " +"\\(\\[evaluate\\_function\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging:1 of +#, fuzzy +msgid "Configurable FedXgbBagging strategy implementation." +msgstr "可配置的 FedXgbNAvg 策略实施。" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedXgbCyclic `\\ " +"\\(\\*\\*kwargs\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic:1 of +#, fuzzy +msgid "Configurable FedXgbCyclic strategy implementation." +msgstr "可配置的 FedAvg 策略实施。" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedAvgAndroid `\\ " +"\\(\\*\\[\\, fraction\\_fit\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedAvgM `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedavgm.FedAvgM:1 of +msgid "Federated Averaging with Momentum strategy." +msgstr "联邦平均动量策略。" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedOpt `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, fraction\\_evaluate\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedopt.FedOpt:1 of +#, fuzzy +msgid "Federated Optim strategy." +msgstr "联邦优化策略。" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedProx `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedprox.FedProx:1 of +msgid "Federated Optimization strategy." +msgstr "联邦优化策略。" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedYogi `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedyogi.FedYogi:1 of +msgid "FedYogi [Reddi et al., 2020] strategy." +msgstr "FedYogi [Reddi 等人,2020] 策略。" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`QFedAvg `\\ \\(\\*\\[\\, " +"q\\_param\\, qffl\\_learning\\_rate\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.qfedavg.QFedAvg:1 of +msgid "Configurable QFedAvg strategy implementation." +msgstr "可配置的 QFedAvg 策略实施。" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedMedian `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedmedian.FedMedian:1 of +#, fuzzy +msgid "Configurable FedMedian strategy implementation." +msgstr "可配置的 FedAvg 策略实施。" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`FedTrimmedAvg `\\ " +"\\(\\*\\[\\, fraction\\_fit\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:1 of +msgid "Federated Averaging with Trimmed Mean [Dong Yin, et al., 2021]." +msgstr "带修剪均值的联邦平均法[Dong Yin 等,2021]。" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`Krum `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, fraction\\_evaluate\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.krum.Krum:1 of +#, fuzzy +msgid "Krum [Blanchard et al., 2017] strategy." +msgstr "FedYogi [Reddi 等人,2020] 策略。" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`Bulyan `\\ \\(\\*\\, " +"fraction\\_fit\\, fraction\\_evaluate\\, ...\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.bulyan.Bulyan:1 of +msgid "Bulyan strategy." +msgstr "Bulyan 策略。" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`DPFedAvgAdaptive `\\ " +"\\(strategy\\, num\\_sampled\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.dpfedavg_adaptive.DPFedAvgAdaptive:1 of +msgid "Wrapper for configuring a Strategy for DP with Adaptive Clipping." +msgstr "用于配置具有自适应剪切功能的 DP 策略的包装器。" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +msgid "" +":py:obj:`DPFedAvgFixed `\\ " +"\\(strategy\\, num\\_sampled\\_clients\\, ...\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed:1 of msgid "Wrapper for configuring a Strategy for DP with Fixed Clipping." msgstr "封装器,用于为具有固定剪切功能的 DP 配置策略。" -#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1 of -msgid "Aggregate evaluation losses using the given strategy." -msgstr "使用给定的策略汇总评估损失。" +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#, fuzzy +msgid ":py:obj:`Strategy `\\ \\(\\)" +msgstr "server.strategy.Strategy" + +#: ../../source/ref-api/flwr.server.strategy.rst:41::1 +#: flwr.server.strategy.strategy.Strategy:1 of +msgid "Abstract base class for server strategy implementations." +msgstr "服务器策略实现的抽象基类。" + +#: ../../source/ref-api/flwr.server.strategy.Bulyan.rst:2 +msgid "Bulyan" +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan:1 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg:1 +#: flwr.server.strategy.fedavgm.FedAvgM:1 +#: flwr.server.strategy.fedmedian.FedMedian:1 +#: flwr.server.strategy.fedopt.FedOpt:1 flwr.server.strategy.fedprox.FedProx:1 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging:1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic:1 +#: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg:1 +#: flwr.server.strategy.krum.Krum:1 flwr.server.strategy.qfedavg.QFedAvg:1 of +#, fuzzy +msgid "Bases: :py:class:`~flwr.server.strategy.fedavg.FedAvg`" +msgstr "server.strategy.DPFedAvgFixed" + +#: flwr.server.strategy.bulyan.Bulyan:3 of +msgid "Implementation based on https://arxiv.org/abs/1802.07927." +msgstr "实施基于 https://arxiv.org/abs/1802.07927。" + +#: flwr.server.strategy.bulyan.Bulyan:5 +#: flwr.server.strategy.fedadagrad.FedAdagrad:5 +#: flwr.server.strategy.fedadam.FedAdam:5 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:5 +#: flwr.server.strategy.fedavgm.FedAvgM:5 flwr.server.strategy.fedopt.FedOpt:5 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:5 +#: flwr.server.strategy.fedyogi.FedYogi:5 flwr.server.strategy.krum.Krum:5 of +msgid "Fraction of clients used during training. Defaults to 1.0." +msgstr "训练期间使用客户的比例。默认为 1.0。" + +#: flwr.server.strategy.bulyan.Bulyan:7 +#: flwr.server.strategy.fedadagrad.FedAdagrad:7 +#: flwr.server.strategy.fedadam.FedAdam:7 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:7 +#: flwr.server.strategy.fedavgm.FedAvgM:7 flwr.server.strategy.fedopt.FedOpt:7 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:7 +#: flwr.server.strategy.fedyogi.FedYogi:7 flwr.server.strategy.krum.Krum:7 of +msgid "Fraction of clients used during validation. Defaults to 1.0." +msgstr "验证过程中使用的客户端比例。默认为 1.0。" + +#: flwr.server.strategy.bulyan.Bulyan:9 +#: flwr.server.strategy.fedadagrad.FedAdagrad:9 +#: flwr.server.strategy.fedadam.FedAdam:9 flwr.server.strategy.fedavg.FedAvg:13 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:9 +#: flwr.server.strategy.fedavgm.FedAvgM:9 flwr.server.strategy.fedopt.FedOpt:9 +#: flwr.server.strategy.fedprox.FedProx:45 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:9 +#: flwr.server.strategy.fedyogi.FedYogi:9 flwr.server.strategy.krum.Krum:9 of +msgid "Minimum number of clients used during training. Defaults to 2." +msgstr "训练期间使用的最少客户数。默认为 2。" + +#: flwr.server.strategy.bulyan.Bulyan:11 +#: flwr.server.strategy.fedadagrad.FedAdagrad:11 +#: flwr.server.strategy.fedadam.FedAdam:11 +#: flwr.server.strategy.fedavg.FedAvg:15 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:11 +#: flwr.server.strategy.fedavgm.FedAvgM:11 +#: flwr.server.strategy.fedopt.FedOpt:11 +#: flwr.server.strategy.fedprox.FedProx:47 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:11 +#: flwr.server.strategy.fedyogi.FedYogi:11 flwr.server.strategy.krum.Krum:11 of +msgid "Minimum number of clients used during validation. Defaults to 2." +msgstr "验证过程中使用的最少客户端数量。默认为 2。" + +#: flwr.server.strategy.bulyan.Bulyan:13 +#: flwr.server.strategy.fedadagrad.FedAdagrad:13 +#: flwr.server.strategy.fedadam.FedAdam:13 +#: flwr.server.strategy.fedavg.FedAvg:17 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:13 +#: flwr.server.strategy.fedavgm.FedAvgM:13 +#: flwr.server.strategy.fedopt.FedOpt:13 +#: flwr.server.strategy.fedprox.FedProx:49 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:13 +#: flwr.server.strategy.fedyogi.FedYogi:13 flwr.server.strategy.krum.Krum:13 of +msgid "Minimum number of total clients in the system. Defaults to 2." +msgstr "系统中客户总数的最小值。默认为 2。" + +#: flwr.server.strategy.bulyan.Bulyan:15 flwr.server.strategy.krum.Krum:15 of +msgid "Number of malicious clients in the system. Defaults to 0." +msgstr "系统中恶意客户端的数量。默认为 0。" + +#: flwr.server.strategy.bulyan.Bulyan:17 +#: flwr.server.strategy.fedadagrad.FedAdagrad:15 +#: flwr.server.strategy.fedadam.FedAdam:15 +#: flwr.server.strategy.fedavg.FedAvg:19 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:15 +#: flwr.server.strategy.fedavgm.FedAvgM:15 +#: flwr.server.strategy.fedopt.FedOpt:15 +#: flwr.server.strategy.fedprox.FedProx:51 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:15 +#: flwr.server.strategy.fedyogi.FedYogi:17 +#: flwr.server.strategy.fedyogi.FedYogi:18 +#: flwr.server.strategy.fedyogi.FedYogi:19 flwr.server.strategy.krum.Krum:20 of +msgid "Optional function used for validation. Defaults to None." +msgstr "用于验证的可选函数。默认为 \"无\"。" + +#: flwr.server.strategy.bulyan.Bulyan:19 +#: flwr.server.strategy.fedadagrad.FedAdagrad:17 +#: flwr.server.strategy.fedadam.FedAdam:17 +#: flwr.server.strategy.fedavg.FedAvg:21 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:17 +#: flwr.server.strategy.fedavgm.FedAvgM:17 +#: flwr.server.strategy.fedopt.FedOpt:17 +#: flwr.server.strategy.fedprox.FedProx:53 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:17 +#: flwr.server.strategy.fedyogi.FedYogi:20 flwr.server.strategy.krum.Krum:22 of +msgid "Function used to configure training. Defaults to None." +msgstr "用于配置训练的功能。默认为 \"无\"。" + +#: flwr.server.strategy.bulyan.Bulyan:21 +#: flwr.server.strategy.fedadagrad.FedAdagrad:19 +#: flwr.server.strategy.fedadam.FedAdam:19 +#: flwr.server.strategy.fedavg.FedAvg:23 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:19 +#: flwr.server.strategy.fedavgm.FedAvgM:19 +#: flwr.server.strategy.fedopt.FedOpt:19 +#: flwr.server.strategy.fedprox.FedProx:55 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:19 +#: flwr.server.strategy.fedyogi.FedYogi:22 flwr.server.strategy.krum.Krum:24 of +msgid "Function used to configure validation. Defaults to None." +msgstr "用于配置验证的函数。默认为 \"无\"。" + +#: flwr.server.strategy.bulyan.Bulyan:23 +#: flwr.server.strategy.fedadagrad.FedAdagrad:25 +#: flwr.server.strategy.fedadam.FedAdam:21 +#: flwr.server.strategy.fedavg.FedAvg:25 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:21 +#: flwr.server.strategy.fedavgm.FedAvgM:21 +#: flwr.server.strategy.fedopt.FedOpt:21 +#: flwr.server.strategy.fedprox.FedProx:57 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:21 +#: flwr.server.strategy.fedyogi.FedYogi:24 flwr.server.strategy.krum.Krum:26 of +msgid "Whether or not accept rounds containing failures. Defaults to True." +msgstr "是否接受包含失败的轮。默认为 True。" + +#: flwr.server.strategy.bulyan.Bulyan:25 +#: flwr.server.strategy.fedadagrad.FedAdagrad:27 +#: flwr.server.strategy.fedadam.FedAdam:23 +#: flwr.server.strategy.fedavg.FedAvg:27 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:24 +#: flwr.server.strategy.fedavgm.FedAvgM:23 +#: flwr.server.strategy.fedopt.FedOpt:23 +#: flwr.server.strategy.fedprox.FedProx:59 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:23 +#: flwr.server.strategy.fedyogi.FedYogi:26 flwr.server.strategy.krum.Krum:28 of +msgid "Initial global model parameters." +msgstr "初始全局模型参数。" + +#: flwr.server.strategy.bulyan.Bulyan:27 of +msgid "" +"Byzantine resilient aggregation rule that is used as the first step of " +"the Bulyan (e.g., Krum)" +msgstr "Byzantine弹性聚合规则,用作 Bulyan 的第一步(如 Krum)" + +#: flwr.server.strategy.bulyan.Bulyan:29 of +msgid "arguments to the first_aggregation rule" +msgstr "第一聚类规则的参数" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\, " +"results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "Aggregate evaluation losses using weighted average." +msgstr "采用加权平均法计算评估损失总额。" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.bulyan.Bulyan.aggregate_fit:1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "Aggregate fit results using Bulyan." +msgstr "使用 Bulyan 技术汇总拟合结果。" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\, " +"parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.configure_evaluate:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.configure_evaluate:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.configure_evaluate:1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.configure_evaluate:1 +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: flwr.server.strategy.strategy.Strategy.configure_evaluate:1 of +msgid "Configure the next round of evaluation." +msgstr "配置下一轮评估。" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_adaptive.DPFedAvgAdaptive.configure_fit:1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.configure_fit:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.configure_fit:1 +#: flwr.server.strategy.fedprox.FedProx.configure_fit:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.configure_fit:1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.configure_fit:1 +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: flwr.server.strategy.strategy.Strategy.configure_fit:1 of +msgid "Configure the next round of training." +msgstr "配置下一轮训练。" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.evaluate:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.evaluate:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.evaluate:1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg.evaluate:1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "Evaluate model parameters using an evaluation function." +msgstr "使用评估函数评估模型参数。" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.initialize_parameters:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.initialize_parameters:1 +#: flwr.server.strategy.fedavgm.FedAvgM.initialize_parameters:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "Initialize global model parameters." +msgstr "初始化全局模型参数。" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.num_evaluation_clients:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.num_evaluation_clients:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.num_evaluation_clients:1 of +msgid "Use a fraction of available clients for evaluation." +msgstr "使用部分可用客户进行评估。" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients `\\" +" \\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.num_fit_clients:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.num_fit_clients:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.num_fit_clients:1 of +msgid "Return the sample size and the required number of available clients." +msgstr "返回样本大小和所需的可用客户数量。" + +#: flwr.server.strategy.dpfedavg_adaptive.DPFedAvgAdaptive:1 of +msgid "Bases: :py:class:`~flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed`" +msgstr "" + +#: flwr.server.strategy.dpfedavg_adaptive.DPFedAvgAdaptive:3 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed:3 of +msgid "This class is deprecated and will be removed in a future release." +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "Aggregate evaluation losses using the given strategy." +msgstr "使用给定的策略汇总评估损失。" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_fit " +"`\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_adaptive.DPFedAvgAdaptive.aggregate_fit:1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "Aggregate training results as in DPFedAvgFixed and update clip norms." +msgstr "汇总 DPFedAvgFixed 中的训练结果并更新片段标准。" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate:1 of +msgid "Configure the next round of evaluation using the specified strategy." +msgstr "使用指定策略配置下一轮评估。" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_fit " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.evaluate:1 of +msgid "Evaluate model parameters using an evaluation function from the strategy." +msgstr "使用策略中的评估函数评估模型参数。" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.initialize_parameters:1 of +msgid "Initialize global model parameters using given strategy." +msgstr "使用给定的策略初始化全局模型参数。" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate:3 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:6 +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:3 +#: flwr.server.strategy.strategy.Strategy.aggregate_fit:3 +#: flwr.server.strategy.strategy.Strategy.configure_evaluate:3 +#: flwr.server.strategy.strategy.Strategy.configure_fit:3 +#: flwr.server.strategy.strategy.Strategy.evaluate:6 of +msgid "The current round of federated learning." +msgstr "本轮联邦学习。" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate:7 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:10 +#: flwr.server.strategy.strategy.Strategy.configure_evaluate:7 +#: flwr.server.strategy.strategy.Strategy.configure_fit:7 +#: flwr.server.strategy.strategy.Strategy.initialize_parameters:3 of +msgid "The client manager which holds all currently connected clients." +msgstr "客户端管理器,用于管理当前连接的所有客户端。" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate:10 +#: flwr.server.strategy.strategy.Strategy.configure_evaluate:10 of +msgid "" +"**evaluate_configuration** -- A list of tuples. Each tuple in the list " +"identifies a `ClientProxy` and the `EvaluateIns` for this particular " +"`ClientProxy`. If a particular `ClientProxy` is not included in this " +"list, it means that this `ClientProxy` will not participate in the next " +"round of federated evaluation." +msgstr "" +"**evaluate_configuration** -- " +"一个元组列表。列表中的每个元组都标识了一个`ClientProxy`和该特定`ClientProxy`的`EvaluateIns`。如果某个特定的" +" `ClientProxy` 未包含在此列表中,则表示该 `ClientProxy` 将不参与下一轮联合评估。" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed:1 +#: flwr.server.strategy.fedavg.FedAvg:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:1 of +msgid "Bases: :py:class:`~flwr.server.strategy.strategy.Strategy`" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_fit " +"`\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_fit:1 of +msgid "Aggregate training results using unweighted aggregation." +msgstr "使用非加权汇总法汇总训练结果。" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_fit " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:1 of +msgid "" +"Configure the next round of training incorporating Differential Privacy " +"(DP)." +msgstr "配置包含差分隐私 (DP) 的下一轮训练。" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:3 of +msgid "" +"Configuration of the next training round includes information related to " +"DP, such as clip norm and noise stddev." +msgstr "下一轮训练的配置包括与 DP 相关的信息,如片段规范和噪声 stddev。" + +#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:13 +#: flwr.server.strategy.strategy.Strategy.configure_fit:10 of +msgid "" +"**fit_configuration** -- A list of tuples. Each tuple in the list " +"identifies a `ClientProxy` and the `FitIns` for this particular " +"`ClientProxy`. If a particular `ClientProxy` is not included in this " +"list, it means that this `ClientProxy` will not participate in the next " +"round of federated learning." +msgstr "" +"**fit_configuration** -- " +"一个元组列表。列表中的每个元组都标识了一个`ClientProxy`和该特定`ClientProxy`的`FitIns'。如果某个特定的`ClientProxy`不在此列表中,则表示该`ClientProxy`将不参加下一轮联合学习。" + +#: ../../source/ref-api/flwr.server.strategy.FaultTolerantFedAvg.rst:2 +#, fuzzy +msgid "FaultTolerantFedAvg" +msgstr "server.strategy.FaultTolerantFedAvg" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_fit " +"`\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_fit:1 +#: flwr.server.strategy.fedadagrad.FedAdagrad.aggregate_fit:1 +#: flwr.server.strategy.fedadam.FedAdam.aggregate_fit:1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg.FedAvg.aggregate_fit:1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_fit:1 +#: flwr.server.strategy.fedavgm.FedAvgM.aggregate_fit:1 +#: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg.aggregate_fit:1 +#: flwr.server.strategy.fedyogi.FedYogi.aggregate_fit:1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_fit:1 of +msgid "Aggregate fit results using weighted average." +msgstr "使用加权平均法汇总拟合结果。" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_fit " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedAdagrad.rst:2 +#: ../../source/ref-changelog.md:839 +msgid "FedAdagrad" +msgstr "FedAdagrad" + +#: flwr.server.strategy.fedadagrad.FedAdagrad:1 +#: flwr.server.strategy.fedadam.FedAdam:1 +#: flwr.server.strategy.fedyogi.FedYogi:1 of +msgid "Bases: :py:class:`~flwr.server.strategy.fedopt.FedOpt`" +msgstr "" + +#: flwr.server.strategy.fedadagrad.FedAdagrad:3 +#: flwr.server.strategy.fedadam.FedAdam:3 flwr.server.strategy.fedopt.FedOpt:3 +#: flwr.server.strategy.fedyogi.FedYogi:3 of +msgid "Implementation based on https://arxiv.org/abs/2003.00295v5" +msgstr "实施基于 https://arxiv.org/abs/2003.00295v5" + +#: flwr.server.strategy.fedadagrad.FedAdagrad:21 +#: flwr.server.strategy.fedadagrad.FedAdagrad:23 +#: flwr.server.strategy.fedadam.FedAdam:25 +#: flwr.server.strategy.fedadam.FedAdam:27 +#: flwr.server.strategy.fedavg.FedAvg:29 flwr.server.strategy.fedavg.FedAvg:31 +#: flwr.server.strategy.fedopt.FedOpt:25 flwr.server.strategy.fedopt.FedOpt:27 +#: flwr.server.strategy.fedprox.FedProx:61 +#: flwr.server.strategy.fedprox.FedProx:63 +#: flwr.server.strategy.fedyogi.FedYogi:28 +#: flwr.server.strategy.fedyogi.FedYogi:30 of +msgid "Metrics aggregation function, optional." +msgstr "指标汇总功能,可选。" + +#: flwr.server.strategy.fedadagrad.FedAdagrad:29 +#: flwr.server.strategy.fedadam.FedAdam:29 +#: flwr.server.strategy.fedopt.FedOpt:29 of +msgid "Server-side learning rate. Defaults to 1e-1." +msgstr "服务器端学习率。默认为 1e-1。" + +#: flwr.server.strategy.fedadagrad.FedAdagrad:31 +#: flwr.server.strategy.fedadam.FedAdam:31 +#: flwr.server.strategy.fedopt.FedOpt:31 of +msgid "Client-side learning rate. Defaults to 1e-1." +msgstr "客户端学习率。默认为 1e-1。" + +#: flwr.server.strategy.fedadagrad.FedAdagrad:33 +#: flwr.server.strategy.fedadam.FedAdam:37 +#: flwr.server.strategy.fedopt.FedOpt:37 of +msgid "Controls the algorithm's degree of adaptability. Defaults to 1e-9." +msgstr "控制算法的适应度。默认为 1e-9。" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit `\\" +" \\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\" +" \\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedAdam.rst:2 +#, fuzzy +msgid "FedAdam" +msgstr "FedAdagrad" + +#: flwr.server.strategy.fedadam.FedAdam:33 +#: flwr.server.strategy.fedyogi.FedYogi:36 of +msgid "Momentum parameter. Defaults to 0.9." +msgstr "动量参数。默认为 0.9。" + +#: flwr.server.strategy.fedadam.FedAdam:35 +#: flwr.server.strategy.fedyogi.FedYogi:38 of +msgid "Second moment parameter. Defaults to 0.99." +msgstr "第二动量参数。默认为 0.99。" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\," +" results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\," +" parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedAvg.rst:2 +#, fuzzy +msgid "FedAvg" +msgstr "DP-FedAvg" + +#: flwr.server.strategy.fedavg.FedAvg:3 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid:3 of +msgid "Implementation based on https://arxiv.org/abs/1602.05629" +msgstr "实施基于 https://arxiv.org/abs/1602.05629" + +#: flwr.server.strategy.fedavg.FedAvg:5 flwr.server.strategy.fedprox.FedProx:37 +#: of +msgid "" +"Fraction of clients used during training. In case `min_fit_clients` is " +"larger than `fraction_fit * available_clients`, `min_fit_clients` will " +"still be sampled. Defaults to 1.0." +msgstr "" +"训练过程中使用的客户端比例。如果 `min_fit_clients` 大于 `fraction_fit * " +"available_clients`,则仍会对 `min_fit_clients` 进行采样。默认为 1.0。" + +#: flwr.server.strategy.fedavg.FedAvg:9 flwr.server.strategy.fedprox.FedProx:41 +#: of +msgid "" +"Fraction of clients used during validation. In case " +"`min_evaluate_clients` is larger than `fraction_evaluate * " +"available_clients`, `min_evaluate_clients` will still be sampled. " +"Defaults to 1.0." +msgstr "" +"验证过程中使用的客户端的比例。如果 `min_evaluate_clients` 大于 `fraction_evaluate * " +"available_clients`,则仍会对 `min_evaluate_clients` 进行采样。默认为 1.0。" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\, " +"results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\, " +"parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients `\\" +" \\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedAvgAndroid.rst:2 +#, fuzzy +msgid "FedAvgAndroid" +msgstr "DPFedAvgAdaptive" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_fit " +"`\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`bytes_to_ndarray " +"`\\ \\(tensor\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.bytes_to_ndarray:1 of +#, fuzzy +msgid "Deserialize NumPy array from bytes." +msgstr "从字节反序列化 NumPy ndarray。" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_fit " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`ndarray_to_bytes " +"`\\ \\(ndarray\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.ndarray_to_bytes:1 of +#, fuzzy +msgid "Serialize NumPy array to bytes." +msgstr "将 NumPy ndarray 序列化为字节。" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`ndarrays_to_parameters " +"`\\ " +"\\(ndarrays\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`parameters_to_ndarrays " +"`\\ " +"\\(parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedavg_android.FedAvgAndroid.parameters_to_ndarrays:1 +#: of +#, fuzzy +msgid "Convert parameters object to NumPy weights." +msgstr "将参数对象转换为 NumPy ndarrays。" + +#: ../../source/ref-api/flwr.server.strategy.FedAvgM.rst:2 +#, fuzzy +msgid "FedAvgM" +msgstr "DP-FedAvg" + +#: flwr.server.strategy.fedavgm.FedAvgM:3 of +#, fuzzy +msgid "Implementation based on https://arxiv.org/abs/1909.06335" +msgstr "实施基于 https://arxiv.org/pdf/1909.06335.pdf" + +#: flwr.server.strategy.fedavgm.FedAvgM:25 of +msgid "" +"Server-side learning rate used in server-side optimization. Defaults to " +"1.0." +msgstr "服务器端优化中使用的服务器端学习率。默认为 1.0。" + +#: flwr.server.strategy.fedavgm.FedAvgM:28 of +msgid "Server-side momentum factor used for FedAvgM. Defaults to 0.0." +msgstr "用于 FedAvgM 的服务器端动量因子。默认为 0.0。" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\," +" results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\," +" parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedMedian.rst:2 +msgid "FedMedian" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedmedian.FedMedian.aggregate_fit:1 of +msgid "Aggregate fit results using median." +msgstr "使用中位数汇总拟合结果。" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedOpt.rst:2 +msgid "FedOpt" +msgstr "" + +#: flwr.server.strategy.fedopt.FedOpt:33 of +msgid "Momentum parameter. Defaults to 0.0." +msgstr "动量参数。默认为 0.0。" + +#: flwr.server.strategy.fedopt.FedOpt:35 of +msgid "Second moment parameter. Defaults to 0.0." +msgstr "第二动量参数。默认为 0.0。" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\, " +"results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\, " +"parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients `\\" +" \\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedProx.rst:2 +msgid "FedProx" +msgstr "" + +#: flwr.server.strategy.fedprox.FedProx:3 of +msgid "Implementation based on https://arxiv.org/abs/1812.06127" +msgstr "实施基于 https://arxiv.org/abs/1812.06127" + +#: flwr.server.strategy.fedprox.FedProx:5 of +msgid "" +"The strategy in itself will not be different than FedAvg, the client " +"needs to be adjusted. A proximal term needs to be added to the loss " +"function during the training:" +msgstr "策略本身与 FedAvg 并无不同,客户端需要进行调整。在训练过程中,需要在损失函数中添加一个近端项:" + +#: flwr.server.strategy.fedprox.FedProx:9 of +msgid "" +"\\\\frac{\\\\mu}{2} || w - w^t ||^2\n" +"\n" +msgstr "" +"\\\\frac{\\\\mu}{2} || w - w^t ||^2\n" +"\n" + +#: flwr.server.strategy.fedprox.FedProx:12 of +msgid "" +"Where $w^t$ are the global parameters and $w$ are the local weights the " +"function will be optimized with." +msgstr "其中,$w^t$ 是全局参数,$w$ 是优化函数的局部权重。" + +#: flwr.server.strategy.fedprox.FedProx:15 of +msgid "In PyTorch, for example, the loss would go from:" +msgstr "例如,在 PyTorch 中,损失将从:" + +#: flwr.server.strategy.fedprox.FedProx:21 of +msgid "To:" +msgstr "致:" + +#: flwr.server.strategy.fedprox.FedProx:30 of +msgid "" +"With `global_params` being a copy of the parameters before the training " +"takes place." +msgstr "其中,\"global_params \"是训练前的参数副本。" + +#: flwr.server.strategy.fedprox.FedProx:65 of +msgid "" +"The weight of the proximal term used in the optimization. 0.0 makes this " +"strategy equivalent to FedAvg, and the higher the coefficient, the more " +"regularization will be used (that is, the client parameters will need to " +"be closer to the server parameters during training)." +msgstr "" +"优化中使用的近端项权重。0.0 使该策略等同于 " +"FedAvg,系数越大,使用的正则化就越多(也就是说,在训练过程中,客户端参数需要更接近服务器参数)。" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\," +" results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\," +" parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedprox.FedProx.configure_fit:3 of +msgid "Sends the proximal factor mu to the clients" +msgstr "向客户发送近端因子mu" + +#: ../../source/ref-api/flwr.server.strategy.FedTrimmedAvg.rst:2 +#, fuzzy +msgid "FedTrimmedAvg" +msgstr "server.strategy.FedTrimmedAvg" + +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:3 of +#, fuzzy +msgid "Implemented based on: https://arxiv.org/abs/1803.01498" +msgstr "实施基于 https://arxiv.org/abs/1802.07927。" + +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg:25 of +msgid "Fraction to cut off of both tails of the distribution. Defaults to 0.2." +msgstr "截取分布两个尾部的分数。默认为 0.2。" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit " +"`\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedtrimmedavg.FedTrimmedAvg.aggregate_fit:1 of +msgid "Aggregate fit results using trimmed average." +msgstr "使用修剪平均值汇总拟合结果。" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedXgbBagging.rst:2 +msgid "FedXgbBagging" +msgstr "" + +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of +#, fuzzy +msgid "Aggregate evaluation metrics using average." +msgstr "采用加权平均法计算评估损失总额。" + +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_fit " +"`\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_fit:1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_fit:1 of +#, fuzzy +msgid "Aggregate fit results using bagging." +msgstr "使用 Bulyan 技术汇总拟合结果。" + +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_fit " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedXgbCyclic.rst:2 +msgid "FedXgbCyclic" +msgstr "" + +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_fit " +"`\\ \\(server\\_round\\," +" results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_fit " +"`\\ \\(server\\_round\\," +" parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedXgbNnAvg.rst:2 +#, fuzzy +msgid "FedXgbNnAvg" +msgstr "DP-FedAvg" + +#: flwr.server.strategy.fedxgb_nn_avg.FedXgbNnAvg:5 of +msgid "" +"This strategy is deprecated, but a copy of it is available in Flower " +"Baselines: " +"https://github.com/adap/flower/tree/main/baselines/hfedxgboost." +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit " +"`\\ \\(server\\_round\\, " +"results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit " +"`\\ \\(server\\_round\\, " +"parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.FedYogi.rst:2 +msgid "FedYogi" +msgstr "" + +#: flwr.server.strategy.fedyogi.FedYogi:32 of +#, fuzzy +msgid "Server-side learning rate. Defaults to 1e-2." +msgstr "服务器端学习率。默认为 1e-1。" + +#: flwr.server.strategy.fedyogi.FedYogi:34 of +#, fuzzy +msgid "Client-side learning rate. Defaults to 0.0316." +msgstr "客户端学习率。默认为 1e-1。" + +#: flwr.server.strategy.fedyogi.FedYogi:40 of +#, fuzzy +msgid "Controls the algorithm's degree of adaptability. Defaults to 1e-3." +msgstr "控制算法的适应度。默认为 1e-9。" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\," +" results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\," +" parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.Krum.rst:2 +msgid "Krum" +msgstr "" + +#: flwr.server.strategy.krum.Krum:3 of +#, fuzzy +msgid "Implementation based on https://arxiv.org/abs/1703.02757" +msgstr "实施基于 https://arxiv.org/abs/2304.07537。" + +#: flwr.server.strategy.krum.Krum:17 of +msgid "" +"Number of clients to keep before averaging (MultiKrum). Defaults to 0, in" +" that case classical Krum is applied." +msgstr "求平均值前保留的客户端数量(MultiKrum)。默认值为 0,在这种情况下会应用经典 Krum。" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\, " +"results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 +#: flwr.server.strategy.krum.Krum.aggregate_fit:1 of +msgid "Aggregate fit results using Krum." +msgstr "使用 Krum 汇总拟合结果。" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\, " +"parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients `\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.QFedAvg.rst:2 +#, fuzzy +msgid "QFedAvg" +msgstr "DP-FedAvg" + +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ \\(server\\_round\\," +" results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_evaluate " +"`\\ \\(server\\_round\\," +" parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_evaluation_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of +msgid "" +":py:obj:`num_fit_clients " +"`\\ " +"\\(num\\_available\\_clients\\)" +msgstr "" + +#: ../../source/ref-api/flwr.server.strategy.Strategy.rst:2 +#, fuzzy +msgid "Strategy" +msgstr "Krum 策略。" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_evaluate " +"`\\ " +"\\(server\\_round\\, results\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1 +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: of +msgid "Aggregate evaluation results." +msgstr "聚合评估结果。" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: flwr.server.strategy.strategy.Strategy.aggregate_fit:1 of +msgid "Aggregate training results." +msgstr "汇总训练结果。" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_evaluate " +"`\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: flwr.server.strategy.strategy.Strategy.evaluate:1 of +msgid "Evaluate the current model parameters." +msgstr "评估当前的模型参数。" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: of +msgid "" +":py:obj:`initialize_parameters " +"`\\ " +"\\(client\\_manager\\)" +msgstr "" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 +#: flwr.server.strategy.strategy.Strategy.initialize_parameters:1 of +msgid "Initialize the (global) model parameters." +msgstr "初始化(全局)模型参数。" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:5 of +msgid "" +"Successful updates from the previously selected and configured clients. " +"Each pair of `(ClientProxy, FitRes` constitutes a successful update from " +"one of the previously selected clients. Not that not all previously " +"selected clients are necessarily included in this list: a client might " +"drop out and not submit a result. For each client that did not submit an " +"update, there should be an `Exception` in `failures`." +msgstr "" +"从先前选定和配置的客户端进行的成功更新。每一对`(ClientProxy, " +"FitRes)`都是来自先前选定客户端的一次成功更新。但并非所有先前选定的客户机都一定包含在此列表中:客户机可能会退出,不提交结果。对于每个没有提交更新的客户端,`failures`中都应该有一个`Exception`。" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:13 +#: flwr.server.strategy.strategy.Strategy.aggregate_fit:13 of +msgid "Exceptions that occurred while the server was waiting for client updates." +msgstr "服务器等待客户端更新时发生的异常。" + +#: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:16 of +msgid "" +"**aggregation_result** -- The aggregated evaluation result. Aggregation " +"typically uses some variant of a weighted average." +msgstr "**aggregation_result** -- 汇总的评估结果。聚合通常使用某种加权平均值。" + +#: flwr.server.strategy.strategy.Strategy.aggregate_fit:5 of +msgid "" +"Successful updates from the previously selected and configured clients. " +"Each pair of `(ClientProxy, FitRes)` constitutes a successful update from" +" one of the previously selected clients. Not that not all previously " +"selected clients are necessarily included in this list: a client might " +"drop out and not submit a result. For each client that did not submit an " +"update, there should be an `Exception` in `failures`." +msgstr "" +"来自先前选定和配置的客户端的成功更新。每一对`(ClientProxy, " +"FitRes)`都构成先前选定的客户端之一的一次成功更新。但并非所有先前选定的客户机都一定包含在此列表中:客户机可能会退出,不提交结果。对于每个没有提交更新的客户端,\"失败" +" \"中都应该有一个 \"异常\"。" + +#: flwr.server.strategy.strategy.Strategy.aggregate_fit:17 of +msgid "" +"**parameters** -- If parameters are returned, then the server will treat " +"these as the new global model parameters (i.e., it will replace the " +"previous parameters with the ones returned from this method). If `None` " +"is returned (e.g., because there were only failures and no viable " +"results) then the server will no update the previous model parameters, " +"the updates received in this round are discarded, and the global model " +"parameters remain the same." +msgstr "" +"**parameters** -- 如果返回参数,那么服务器将把这些参数作为新的全局模型参数(即用本方法返回的参数替换之前的参数)。如果返回 " +"\"无\"(例如,因为只有失败而没有可行的结果),那么服务器将不再更新之前的模型参数,本轮收到的更新将被丢弃,全局模型参数保持不变。" + +#: flwr.server.strategy.strategy.Strategy.evaluate:3 of +msgid "" +"This function can be used to perform centralized (i.e., server-side) " +"evaluation of model parameters." +msgstr "该函数可用于对模型参数进行集中(即服务器端)评估。" + +#: flwr.server.strategy.strategy.Strategy.evaluate:11 of +msgid "" +"**evaluation_result** -- The evaluation result, usually a Tuple " +"containing loss and a dictionary containing task-specific metrics (e.g., " +"accuracy)." +msgstr "**evaluation_result** -- 评估结果,通常是一个元组,包含损失值和一个字典,字典中包含特定任务的指标(如准确率)。" + +#: flwr.server.strategy.strategy.Strategy.initialize_parameters:6 of +msgid "" +"**parameters** -- If parameters are returned, then the server will treat " +"these as the initial global model parameters." +msgstr "**parameters** -- 如果返回参数,服务器将把这些参数视为初始全局模型参数。" + +#: ../../source/ref-api/flwr.simulation.rst:2 +#, fuzzy +msgid "simulation" +msgstr "运行模拟" + +#: ../../source/ref-api/flwr.simulation.rst:17::1 +msgid "" +":py:obj:`start_simulation `\\ \\(\\*\\," +" client\\_fn\\[\\, ...\\]\\)" +msgstr "" + +#: ../../source/ref-api/flwr.simulation.rst:17::1 +#: flwr.simulation.app.start_simulation:1 of +msgid "Start a Ray-based Flower simulation server." +msgstr "启动基于 Ray 的Flower模拟服务器。" + +#: ../../source/ref-api/flwr.simulation.start_simulation.rst:2 +#, fuzzy +msgid "start\\_simulation" +msgstr "start_simulation" + +#: flwr.simulation.app.start_simulation:3 of +msgid "" +"A function creating client instances. The function must take a single " +"`str` argument called `cid`. It should return a single client instance of" +" type Client. Note that the created client instances are ephemeral and " +"will often be destroyed after a single method invocation. Since client " +"instances are not long-lived, they should not attempt to carry state over" +" method invocations. Any state required by the instance (model, dataset, " +"hyperparameters, ...) should be (re-)created in either the call to " +"`client_fn` or the call to any of the client methods (e.g., load " +"evaluation data in the `evaluate` method itself)." +msgstr "" +"创建客户端实例的函数。该函数必须接受一个名为 `cid` 的 `str` 参数。它应返回一个 Client " +"类型的客户端实例。请注意,创建的客户端实例是短暂的,通常在调用一个方法后就会被销毁。由于客户机实例不是长期存在的,它们不应试图在方法调用时携带状态数据。实例所需的任何状态数据(模型、数据集、超参数......)都应在调用" +" `client_fn` 或任何客户端方法(例如,在 `evaluate` 方法中加载评估数据)时(重新)创建。" + +#: flwr.simulation.app.start_simulation:13 of +msgid "" +"The total number of clients in this simulation. This must be set if " +"`clients_ids` is not set and vice-versa." +msgstr "本次模拟的客户总数。如果未设置 `clients_ids`,则必须设置该参数,反之亦然。" + +#: flwr.simulation.app.start_simulation:16 of +msgid "" +"List `client_id`s for each client. This is only required if `num_clients`" +" is not set. Setting both `num_clients` and `clients_ids` with " +"`len(clients_ids)` not equal to `num_clients` generates an error." +msgstr "" +"列出每个客户的 `client_id`。只有在未设置 `num_clients` " +"时才需要这样做。同时设置`num_clients`和`clients_ids`,且`len(clients_ids)`不等于`num_clients`,会产生错误。" + +#: flwr.simulation.app.start_simulation:20 of +#, fuzzy +msgid "" +"CPU and GPU resources for a single client. Supported keys are `num_cpus` " +"and `num_gpus`. To understand the GPU utilization caused by `num_gpus`, " +"as well as using custom resources, please consult the Ray documentation." +msgstr "" +"\"num_gpus\": 0.0` 单个客户端的 CPU 和 GPU 资源。支持的键值为 `num_cpus` 和 `num_gpus`。要了解" +" `num_gpus` 所导致的 GPU 利用率,以及使用自定义资源的情况,请查阅 Ray 文档。" + +#: flwr.simulation.app.start_simulation:25 of +msgid "" +"An implementation of the abstract base class `flwr.server.Server`. If no " +"instance is provided, then `start_server` will create one." +msgstr "抽象基类 `flwr.server.Server`的实现。如果没有提供实例,`start_server` 将创建一个。" + +#: flwr.simulation.app.start_simulation:31 of +msgid "" +"An implementation of the abstract base class `flwr.server.Strategy`. If " +"no strategy is provided, then `start_server` will use " +"`flwr.server.strategy.FedAvg`." +msgstr "" +"抽象基类 `flwr.server.strategy` 的实现。如果没有提供策略,`start_server` 将使用 " +"`flwr.server.strategy.FedAvg`。" + +#: flwr.simulation.app.start_simulation:35 of +msgid "" +"An implementation of the abstract base class `flwr.server.ClientManager`." +" If no implementation is provided, then `start_simulation` will use " +"`flwr.server.client_manager.SimpleClientManager`." +msgstr "" +"抽象基类 `flwr.server.ClientManager` 的实现。如果没有提供实现,`start_simulation` 将使用 " +"`flwr.server.client_manager.SimpleClientManager`。" + +#: flwr.simulation.app.start_simulation:39 of +msgid "" +"Optional dictionary containing arguments for the call to `ray.init`. If " +"ray_init_args is None (the default), Ray will be initialized with the " +"following default args: { \"ignore_reinit_error\": True, " +"\"include_dashboard\": False } An empty dictionary can be used " +"(ray_init_args={}) to prevent any arguments from being passed to " +"ray.init." +msgstr "" +"可选字典,包含调用 `ray.init` 时的参数。如果 ray_init_args 为 None(默认值),则将使用以下默认参数初始化 Ray:" +" { \"ignore_reinit_error\": True, \"include_dashboard\": False } " +"可以使用空字典(ray_init_args={})来防止向 ray.init 传递任何参数。" + +#: flwr.simulation.app.start_simulation:39 of +msgid "" +"Optional dictionary containing arguments for the call to `ray.init`. If " +"ray_init_args is None (the default), Ray will be initialized with the " +"following default args:" +msgstr "可选字典,包含调用 `ray.init` 时的参数。如果 ray_init_args 为 None(默认值),则将使用以下默认参数初始化 Ray:" + +#: flwr.simulation.app.start_simulation:43 of +msgid "{ \"ignore_reinit_error\": True, \"include_dashboard\": False }" +msgstr "{ \"ignore_reinit_error\": True, \"include_dashboard\": False }" -#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_fit:1 of -msgid "Aggregate training results using unweighted aggregation." -msgstr "使用非加权汇总法汇总训练结果。" +#: flwr.simulation.app.start_simulation:45 of +msgid "" +"An empty dictionary can be used (ray_init_args={}) to prevent any " +"arguments from being passed to ray.init." +msgstr "可以使用空字典 (ray_init_args={}) 来防止向 ray.init 传递任何参数。" -#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_evaluate:1 of -msgid "Configure the next round of evaluation using the specified strategy." -msgstr "使用指定策略配置下一轮评估。" +#: flwr.simulation.app.start_simulation:48 of +msgid "" +"Set to True to prevent `ray.shutdown()` in case " +"`ray.is_initialized()=True`." +msgstr "设为 True 可在 `ray.is_initialized()=True` 情况下阻止 `ray.shutdown()` 。" -#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:1 of +#: flwr.simulation.app.start_simulation:50 of msgid "" -"Configure the next round of training incorporating Differential Privacy (DP)." -msgstr "配置包含差分隐私 (DP) 的下一轮训练。" +"Optionally specify the type of actor to use. The actor object, which " +"persists throughout the simulation, will be the process in charge of " +"running the clients' jobs (i.e. their `fit()` method)." +msgstr "可选择指定要使用的actor类型。actor对象将在整个模拟过程中持续存在,它将是负责运行客户端作业(即其 `fit()`方法)的进程。" -#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.configure_fit:3 of +#: flwr.simulation.app.start_simulation:54 of msgid "" -"Configuration of the next training round includes information related to DP, " -"such as clip norm and noise stddev." -msgstr "下一轮训练的配置包括与 DP 相关的信息,如片段规范和噪声 stddev。" +"If you want to create your own Actor classes, you might need to pass some" +" input argument. You can use this dictionary for such purpose." +msgstr "如果您想创建自己的 Actor 类,可能需要传递一些输入参数。为此,您可以使用本字典。" -#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.evaluate:1 of +#: flwr.simulation.app.start_simulation:57 of msgid "" -"Evaluate model parameters using an evaluation function from the strategy." -msgstr "使用策略中的评估函数评估模型参数。" +"(default: \"DEFAULT\") Optional string (\"DEFAULT\" or \"SPREAD\") for " +"the VCE to choose in which node the actor is placed. If you are an " +"advanced user needed more control you can use lower-level scheduling " +"strategies to pin actors to specific compute nodes (e.g. via " +"NodeAffinitySchedulingStrategy). Please note this is an advanced feature." +" For all details, please refer to the Ray documentation: " +"https://docs.ray.io/en/latest/ray-core/scheduling/index.html" +msgstr "" +"(默认:\"DEFAULT\")可选字符串(\"DEFAULT \"或 \"SPREAD\"),供 VCE " +"选择将行为体放置在哪个节点上。如果你是需要更多控制权的高级用户,可以使用低级调度策略将actor固定到特定计算节点(例如,通过 " +"NodeAffinitySchedulingStrategy)。请注意,这是一项高级功能。有关详细信息,请参阅 Ray " +"文档:https://docs.ray.io/en/latest/ray-core/scheduling/index.html" -#: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.initialize_parameters:1 of -msgid "Initialize global model parameters using given strategy." -msgstr "使用给定的策略初始化全局模型参数。" +#: flwr.simulation.app.start_simulation:66 of +msgid "**hist** -- Object containing metrics from training." +msgstr "**hist** -- 包含训练指标的对象。" -#: ../../source/ref-api-flwr.rst:261 -msgid "common" -msgstr "常见" +#: ../../source/ref-changelog.md:1 +msgid "Changelog" +msgstr "更新日志" -#: flwr.common:1 of -msgid "Common components shared between server and client." -msgstr "服务器和客户端共享的通用组件。" +#: ../../source/ref-changelog.md:3 +msgid "Unreleased" +msgstr "尚未发布" -#: flwr.common.typing.ClientMessage:1 of -msgid "ClientMessage is a container used to hold one result message." -msgstr "ClientMessage 是用于容纳一条结果信息的容器。" +#: ../../source/ref-changelog.md:5 ../../source/ref-changelog.md:17 +#: ../../source/ref-changelog.md:110 ../../source/ref-changelog.md:210 +#: ../../source/ref-changelog.md:294 ../../source/ref-changelog.md:358 +#: ../../source/ref-changelog.md:416 ../../source/ref-changelog.md:485 +#: ../../source/ref-changelog.md:614 ../../source/ref-changelog.md:656 +#: ../../source/ref-changelog.md:723 ../../source/ref-changelog.md:789 +#: ../../source/ref-changelog.md:834 ../../source/ref-changelog.md:873 +#: ../../source/ref-changelog.md:906 ../../source/ref-changelog.md:956 +msgid "What's new?" +msgstr "有什么新内容?" -#: flwr.common.typing.Code:1 of -msgid "Client status codes." -msgstr "客户端状态代码。" +#: ../../source/ref-changelog.md:7 ../../source/ref-changelog.md:80 +#: ../../source/ref-changelog.md:192 ../../source/ref-changelog.md:282 +#: ../../source/ref-changelog.md:346 ../../source/ref-changelog.md:404 +#: ../../source/ref-changelog.md:473 ../../source/ref-changelog.md:535 +#: ../../source/ref-changelog.md:554 ../../source/ref-changelog.md:710 +#: ../../source/ref-changelog.md:781 ../../source/ref-changelog.md:818 +#: ../../source/ref-changelog.md:861 +msgid "Incompatible changes" +msgstr "不兼容的更改" -#: flwr.common.typing.DisconnectRes:1 of -msgid "DisconnectRes message from client to server." -msgstr "客户端向服务器发送 DisconnectRes 信息。" +#: ../../source/ref-changelog.md:9 +#, fuzzy +msgid "v1.7.0 (2024-02-05)" +msgstr "v1.3.0 (2023-02-06)" -#: flwr.common.typing.EvaluateIns:1 of -msgid "Evaluate instructions for a client." -msgstr "评估客户端的指示。" +#: ../../source/ref-changelog.md:11 ../../source/ref-changelog.md:104 +#: ../../source/ref-changelog.md:204 ../../source/ref-changelog.md:288 +#: ../../source/ref-changelog.md:352 ../../source/ref-changelog.md:410 +#: ../../source/ref-changelog.md:479 ../../source/ref-changelog.md:548 +msgid "Thanks to our contributors" +msgstr "感谢我们的贡献者" -#: flwr.common.typing.EvaluateRes:1 of -msgid "Evaluate response from a client." -msgstr "评估客户端的反应。" +#: ../../source/ref-changelog.md:13 ../../source/ref-changelog.md:106 +#: ../../source/ref-changelog.md:206 ../../source/ref-changelog.md:290 +#: ../../source/ref-changelog.md:354 ../../source/ref-changelog.md:412 +msgid "" +"We would like to give our special thanks to all the contributors who made" +" the new version of Flower possible (in `git shortlog` order):" +msgstr "在此,我们要特别感谢所有为 Flower 的新版本做出贡献的人员(按 `git shortlog` 顺序排列):" -#: flwr.common.telemetry.EventType:1 of -msgid "Types of telemetry events." -msgstr "遥测事件类型。" +#: ../../source/ref-changelog.md:15 +#, fuzzy +msgid "" +"`Aasheesh Singh`, `Adam Narozniak`, `Aml Hassan Esmil`, `Charles " +"Beauville`, `Daniel J. Beutel`, `Daniel Nata Nugraha`, `Edoardo " +"Gabrielli`, `Gustavo Bertoli`, `HelinLin`, `Heng Pan`, `Javier`, `M S " +"Chaitanya Kumar`, `Mohammad Naseri`, `Nikos Vlachakis`, `Pritam Neog`, " +"`Robert Kuska`, `Robert Steiner`, `Taner Topal`, `Yahia Salaheldin " +"Shaaban`, `Yan Gao`, `Yasar Abbas` " +msgstr "" +"`Adam Narozniak`, `Anass Anhari`, `Charles Beauville`, `Dana-Farber`, " +"`Daniel J. Beutel`, `Daniel Nata Nugraha`, `Edoardo Gabrielli`, `Gustavo " +"Bertoli`, `Heng Pan`, `Javier`, `Mahdi`, `Steven Hé (Sīchàng)`, `Taner " +"Topal`, `achiverram28`, `danielnugraha`, `eunchung`, `ruthgal` " -#: flwr.common.typing.FitIns:1 of -msgid "Fit instructions for a client." -msgstr "为客户提供安装说明。" +#: ../../source/ref-changelog.md:19 +#, fuzzy +msgid "" +"**Introduce stateful clients (experimental)** " +"([#2770](https://github.com/adap/flower/pull/2770), " +"[#2686](https://github.com/adap/flower/pull/2686), " +"[#2696](https://github.com/adap/flower/pull/2696), " +"[#2643](https://github.com/adap/flower/pull/2643), " +"[#2769](https://github.com/adap/flower/pull/2769))" +msgstr "" +"** baselines的普通更新** ([#2301](https://github.com/adap/flower/pull/2301), " +"[#2305](https://github.com/adap/flower/pull/2305), " +"[#2307](https://github.com/adap/flower/pull/2307), " +"[#2327](https://github.com/adap/flower/pull/2327), " +"[#2435](https://github.com/adap/flower/pull/2435))" -#: flwr.common.typing.FitRes:1 of -msgid "Fit response from a client." -msgstr "来自客户端的合适回复。" +#: ../../source/ref-changelog.md:21 +msgid "" +"Subclasses of `Client` and `NumPyClient` can now store local state that " +"remains on the client. Let's start with the highlight first: this new " +"feature is compatible with both simulated clients (via " +"`start_simulation`) and networked clients (via `start_client`). It's also" +" the first preview of new abstractions like `Context` and `RecordSet`. " +"Clients can access state of type `RecordSet` via `state: RecordSet = " +"self.context.state`. Changes to this `RecordSet` are preserved across " +"different rounds of execution to enable stateful computations in a " +"unified way across simulation and deployment." +msgstr "" -#: flwr.common.typing.GetParametersIns:1 of -msgid "Parameters request for a client." -msgstr "客户端的参数请求。" +#: ../../source/ref-changelog.md:23 +#, fuzzy +msgid "" +"**Improve performance** " +"([#2293](https://github.com/adap/flower/pull/2293))" +msgstr "**改进示例笔记** ([#2005](https://github.com/adap/flower/pull/2005))" -#: flwr.common.typing.GetParametersRes:1 of -msgid "Response when asked to return parameters." -msgstr "要求返回参数时的响应。" +#: ../../source/ref-changelog.md:25 +msgid "" +"Flower is faster than ever. All `FedAvg`-derived strategies now use in-" +"place aggregation to reduce memory consumption. The Flower client " +"serialization/deserialization has been rewritten from the ground up, " +"which results in significant speedups, especially when the client-side " +"training time is short." +msgstr "" -#: flwr.common.typing.GetPropertiesIns:1 of -msgid "Properties request for a client." -msgstr "客户端的属性请求。" +#: ../../source/ref-changelog.md:27 +#, fuzzy +msgid "" +"**Support Federated Learning with Apple MLX and Flower** " +"([#2693](https://github.com/adap/flower/pull/2693))" +msgstr "" +"** 添加使用 fastai 和 Flower 进行联邦学习的新示例** " +"([#1598](https://github.com/adap/flower/pull/1598))" -#: flwr.common.typing.GetPropertiesRes:1 of -msgid "Properties response from a client." -msgstr "来自客户端的属性响应。" +#: ../../source/ref-changelog.md:29 +msgid "" +"Flower has official support for federated learning using [Appple " +"MLX](https://ml-explore.github.io/mlx) via the new `quickstart-mlx` code " +"example." +msgstr "" -#: flwr.common.typing.Parameters:1 of -msgid "Model parameters." -msgstr "模型参数。" +#: ../../source/ref-changelog.md:31 +#, fuzzy +msgid "" +"**Introduce new XGBoost cyclic strategy** " +"([#2666](https://github.com/adap/flower/pull/2666), " +"[#2668](https://github.com/adap/flower/pull/2668))" +msgstr "" +"**介绍 iOS SDK(预览版)** ([#1621](https://github.com/adap/flower/pull/1621), " +"[#1764](https://github.com/adap/flower/pull/1764))" -#: flwr.common.typing.ReconnectIns:1 of -msgid "ReconnectIns message from server to client." -msgstr "服务器发送给客户端的重新连接信息。" +#: ../../source/ref-changelog.md:33 +msgid "" +"A new strategy called `FedXgbCyclic` supports a client-by-client style of" +" training (often called cyclic). The `xgboost-comprehensive` code example" +" shows how to use it in a full project. In addition to that, `xgboost-" +"comprehensive` now also supports simulation mode. With this, Flower " +"offers best-in-class XGBoost support." +msgstr "" -#: flwr.common.typing.ServerMessage:1 of -msgid "ServerMessage is a container used to hold one instruction message." -msgstr "ServerMessage 是用于容纳一条指令信息的容器。" +#: ../../source/ref-changelog.md:35 +#, fuzzy +msgid "" +"**Support Python 3.11** " +"([#2394](https://github.com/adap/flower/pull/2394))" +msgstr "** 支持 Python 3.10** ([#1320](https://github.com/adap/flower/pull/1320))" -#: flwr.common.typing.Status:1 of -msgid "Client status." -msgstr "客户端状态。" +#: ../../source/ref-changelog.md:37 +msgid "" +"Framework tests now run on Python 3.8, 3.9, 3.10, and 3.11. This will " +"ensure better support for users using more recent Python versions." +msgstr "" -#: flwr.common.parameter.bytes_to_ndarray:1 of -msgid "Deserialize NumPy ndarray from bytes." -msgstr "从字节反序列化 NumPy ndarray。" +#: ../../source/ref-changelog.md:39 +#, fuzzy +msgid "" +"**Update gRPC and ProtoBuf dependencies** " +"([#2814](https://github.com/adap/flower/pull/2814))" +msgstr "" +"**更新 REST API 以支持创建和删除节点** " +"([#2283](https://github.com/adap/flower/pull/2283))" -#: flwr.common.logger.configure:1 of -msgid "Configure logging to file and/or remote log server." -msgstr "配置将日志记录到文件和/或远程日志服务器。" +#: ../../source/ref-changelog.md:41 +msgid "" +"The `grpcio` and `protobuf` dependencies were updated to their latest " +"versions for improved security and performance." +msgstr "" -#: logging.Logger.log:1 of -msgid "Log 'msg % args' with the integer severity 'level'." -msgstr "以整数严重性 \"级别 \"记录 \"msg % args\"。" +#: ../../source/ref-changelog.md:43 +#, fuzzy +msgid "" +"**Introduce Docker image for Flower server** " +"([#2700](https://github.com/adap/flower/pull/2700), " +"[#2688](https://github.com/adap/flower/pull/2688), " +"[#2705](https://github.com/adap/flower/pull/2705), " +"[#2695](https://github.com/adap/flower/pull/2695), " +"[#2747](https://github.com/adap/flower/pull/2747), " +"[#2746](https://github.com/adap/flower/pull/2746), " +"[#2680](https://github.com/adap/flower/pull/2680), " +"[#2682](https://github.com/adap/flower/pull/2682), " +"[#2701](https://github.com/adap/flower/pull/2701))" +msgstr "" +"** 支持 SSL 的服务器和客户端** ([#842](https://github.com/adap/flower/pull/842), " +"[#844](https://github.com/adap/flower/pull/844), " +"[#845](https://github.com/adap/flower/pull/845), " +"[#847](https://github.com/adap/flower/pull/847), " +"[#993](https://github.com/adap/flower/pull/993), " +"[#994](https://github.com/adap/flower/pull/994))" -#: logging.Logger.log:3 of +#: ../../source/ref-changelog.md:45 msgid "" -"To pass exception information, use the keyword argument exc_info with a true " -"value, e.g." -msgstr "要传递异常信息,请使用带 true 值的关键字参数 exc_info,例如。" +"The Flower server can now be run using an official Docker image. A new " +"how-to guide explains [how to run Flower using " +"Docker](https://flower.dev/docs/framework/how-to-run-flower-using-" +"docker.html). An official Flower client Docker image will follow." +msgstr "" -#: logging.Logger.log:6 of -#, python-format -msgid "logger.log(level, \"We have a %s\", \"mysterious problem\", exc_info=1)" -msgstr "logger.log(level, \"We have a %s\", \"mysterious problem\", exc_info=1)" +#: ../../source/ref-changelog.md:47 +#, fuzzy +msgid "" +"**Introduce** `flower-via-docker-compose` **example** " +"([#2626](https://github.com/adap/flower/pull/2626))" +msgstr "" +"**介绍Flower Android SDK** " +"([#2131](https://github.com/adap/flower/pull/2131))" -#: flwr.common.parameter.ndarray_to_bytes:1 of -msgid "Serialize NumPy ndarray to bytes." -msgstr "将 NumPy ndarray 序列化为字节。" +#: ../../source/ref-changelog.md:49 +#, fuzzy +msgid "" +"**Introduce** `quickstart-sklearn-tabular` **example** " +"([#2719](https://github.com/adap/flower/pull/2719))" +msgstr "**引入 start_driver**([#1697](https://github.com/adap/flower/pull/1697))" -#: flwr.common.parameter.ndarrays_to_parameters:1 of -msgid "Convert NumPy ndarrays to parameters object." -msgstr "将 NumPy ndarrays 转换为参数对象。" +#: ../../source/ref-changelog.md:51 +#, fuzzy +msgid "" +"**Introduce** `custom-metrics` **example** " +"([#1958](https://github.com/adap/flower/pull/1958))" +msgstr "**引入 start_driver**([#1697](https://github.com/adap/flower/pull/1697))" -#: flwr.common.date.now:1 of -msgid "Construct a datetime from time.time() with time zone set to UTC." -msgstr "从 time.time() 生成日期时间,时区设置为 UTC。" +#: ../../source/ref-changelog.md:53 +#, fuzzy +msgid "" +"**Update code examples to use Flower Datasets** " +"([#2450](https://github.com/adap/flower/pull/2450), " +"[#2456](https://github.com/adap/flower/pull/2456), " +"[#2318](https://github.com/adap/flower/pull/2318), " +"[#2712](https://github.com/adap/flower/pull/2712))" +msgstr "" +"更新开发人员工具([#1231](https://github.com/adap/flower/pull/1231), " +"[#1276](https://github.com/adap/flower/pull/1276), " +"[#1301](https://github.com/adap/flower/pull/1301), " +"[#1310](https://github.com/adap/flower/pull/1310)" -#: flwr.common.parameter.parameters_to_ndarrays:1 of -msgid "Convert parameters object to NumPy ndarrays." -msgstr "将参数对象转换为 NumPy ndarrays。" +#: ../../source/ref-changelog.md:55 +msgid "" +"Several code examples were updated to use [Flower " +"Datasets](https://flower.dev/docs/datasets/)." +msgstr "" -#: ../../source/ref-changelog.md:1 -msgid "Changelog" -msgstr "更新日志" +#: ../../source/ref-changelog.md:57 +#, fuzzy +msgid "" +"**General updates to Flower Examples** " +"([#2381](https://github.com/adap/flower/pull/2381), " +"[#2805](https://github.com/adap/flower/pull/2805), " +"[#2782](https://github.com/adap/flower/pull/2782), " +"[#2806](https://github.com/adap/flower/pull/2806), " +"[#2829](https://github.com/adap/flower/pull/2829), " +"[#2825](https://github.com/adap/flower/pull/2825), " +"[#2816](https://github.com/adap/flower/pull/2816), " +"[#2726](https://github.com/adap/flower/pull/2726), " +"[#2659](https://github.com/adap/flower/pull/2659), " +"[#2655](https://github.com/adap/flower/pull/2655))" +msgstr "" +"**改进(试验性)驱动程序应用程序接口** ([#1663](https://github.com/adap/flower/pull/1663)," +" [#1666](https://github.com/adap/flower/pull/1666), " +"[#1667](https://github.com/adap/flower/pull/1667), " +"[#1664](https://github.com/adap/flower/pull/1664), " +"[#1675](https://github.com/adap/flower/pull/1675), " +"[#1676](https://github.com/adap/flower/pull/1676), " +"[#1693](https://github.com/adap/flower/pull/1693), " +"[#1662](https://github.com/adap/flower/pull/1662), " +"[#1794](https://github.com/adap/flower/pull/1794))" + +#: ../../source/ref-changelog.md:59 +msgid "Many Flower code examples received substantial updates." +msgstr "" + +#: ../../source/ref-changelog.md:61 ../../source/ref-changelog.md:154 +msgid "**Update Flower Baselines**" +msgstr "**更新 Flower Baselines**" + +#: ../../source/ref-changelog.md:63 +#, fuzzy +msgid "" +"HFedXGBoost ([#2226](https://github.com/adap/flower/pull/2226), " +"[#2771](https://github.com/adap/flower/pull/2771))" +msgstr "" +"FedBN ([#2608](https://github.com/adap/flower/pull/2608), " +"[#2615](https://github.com/adap/flower/pull/2615))" + +#: ../../source/ref-changelog.md:64 +#, fuzzy +msgid "FedVSSL ([#2412](https://github.com/adap/flower/pull/2412))" +msgstr "FjORD [#2431](https://github.com/adap/flower/pull/2431)" + +#: ../../source/ref-changelog.md:65 +#, fuzzy +msgid "FedNova ([#2179](https://github.com/adap/flower/pull/2179))" +msgstr "FjORD [#2431](https://github.com/adap/flower/pull/2431)" + +#: ../../source/ref-changelog.md:66 +#, fuzzy +msgid "HeteroFL ([#2439](https://github.com/adap/flower/pull/2439))" +msgstr "FedMeta [#2438](https://github.com/adap/flower/pull/2438)" + +#: ../../source/ref-changelog.md:67 +#, fuzzy +msgid "FedAvgM ([#2246](https://github.com/adap/flower/pull/2246))" +msgstr "FedPer [#2266](https://github.com/adap/flower/pull/2266)" + +#: ../../source/ref-changelog.md:68 +#, fuzzy +msgid "FedPara ([#2722](https://github.com/adap/flower/pull/2722))" +msgstr "FedPer [#2266](https://github.com/adap/flower/pull/2266)" + +#: ../../source/ref-changelog.md:70 +#, fuzzy +msgid "" +"**Improve documentation** " +"([#2674](https://github.com/adap/flower/pull/2674), " +"[#2480](https://github.com/adap/flower/pull/2480), " +"[#2826](https://github.com/adap/flower/pull/2826), " +"[#2727](https://github.com/adap/flower/pull/2727), " +"[#2761](https://github.com/adap/flower/pull/2761), " +"[#2900](https://github.com/adap/flower/pull/2900))" +msgstr "" +"** 更新文档** ([#1629](https://github.com/adap/flower/pull/1629), " +"[#1628](https://github.com/adap/flower/pull/1628), " +"[#1620](https://github.com/adap/flower/pull/1620), " +"[#1618](https://github.com/adap/flower/pull/1618), " +"[#1617](https://github.com/adap/flower/pull/1617), " +"[#1613](https://github.com/adap/flower/pull/1613), " +"[#1614](https://github.com/adap/flower/pull/1614)))" + +#: ../../source/ref-changelog.md:72 +msgid "" +"**Improved testing and development infrastructure** " +"([#2797](https://github.com/adap/flower/pull/2797), " +"[#2676](https://github.com/adap/flower/pull/2676), " +"[#2644](https://github.com/adap/flower/pull/2644), " +"[#2656](https://github.com/adap/flower/pull/2656), " +"[#2848](https://github.com/adap/flower/pull/2848), " +"[#2675](https://github.com/adap/flower/pull/2675), " +"[#2735](https://github.com/adap/flower/pull/2735), " +"[#2767](https://github.com/adap/flower/pull/2767), " +"[#2732](https://github.com/adap/flower/pull/2732), " +"[#2744](https://github.com/adap/flower/pull/2744), " +"[#2681](https://github.com/adap/flower/pull/2681), " +"[#2699](https://github.com/adap/flower/pull/2699), " +"[#2745](https://github.com/adap/flower/pull/2745), " +"[#2734](https://github.com/adap/flower/pull/2734), " +"[#2731](https://github.com/adap/flower/pull/2731), " +"[#2652](https://github.com/adap/flower/pull/2652), " +"[#2720](https://github.com/adap/flower/pull/2720), " +"[#2721](https://github.com/adap/flower/pull/2721), " +"[#2717](https://github.com/adap/flower/pull/2717), " +"[#2864](https://github.com/adap/flower/pull/2864), " +"[#2694](https://github.com/adap/flower/pull/2694), " +"[#2709](https://github.com/adap/flower/pull/2709), " +"[#2658](https://github.com/adap/flower/pull/2658), " +"[#2796](https://github.com/adap/flower/pull/2796), " +"[#2692](https://github.com/adap/flower/pull/2692), " +"[#2657](https://github.com/adap/flower/pull/2657), " +"[#2813](https://github.com/adap/flower/pull/2813), " +"[#2661](https://github.com/adap/flower/pull/2661), " +"[#2398](https://github.com/adap/flower/pull/2398))" +msgstr "" + +#: ../../source/ref-changelog.md:74 +msgid "" +"The Flower testing and development infrastructure has received " +"substantial updates. This makes Flower 1.7 the most tested release ever." +msgstr "" + +#: ../../source/ref-changelog.md:76 +#, fuzzy +msgid "" +"**Update dependencies** " +"([#2753](https://github.com/adap/flower/pull/2753), " +"[#2651](https://github.com/adap/flower/pull/2651), " +"[#2739](https://github.com/adap/flower/pull/2739), " +"[#2837](https://github.com/adap/flower/pull/2837), " +"[#2788](https://github.com/adap/flower/pull/2788), " +"[#2811](https://github.com/adap/flower/pull/2811), " +"[#2774](https://github.com/adap/flower/pull/2774), " +"[#2790](https://github.com/adap/flower/pull/2790), " +"[#2751](https://github.com/adap/flower/pull/2751), " +"[#2850](https://github.com/adap/flower/pull/2850), " +"[#2812](https://github.com/adap/flower/pull/2812), " +"[#2872](https://github.com/adap/flower/pull/2872), " +"[#2736](https://github.com/adap/flower/pull/2736), " +"[#2756](https://github.com/adap/flower/pull/2756), " +"[#2857](https://github.com/adap/flower/pull/2857), " +"[#2757](https://github.com/adap/flower/pull/2757), " +"[#2810](https://github.com/adap/flower/pull/2810), " +"[#2740](https://github.com/adap/flower/pull/2740), " +"[#2789](https://github.com/adap/flower/pull/2789))" +msgstr "" +"**更新Example** ([#1772](https://github.com/adap/flower/pull/1772), " +"[#1873](https://github.com/adap/flower/pull/1873), " +"[#1981](https://github.com/adap/flower/pull/1981), " +"[#1988](https://github.com/adap/flower/pull/1988), " +"[#1984](https://github.com/adap/flower/pull/1984), " +"[#1982](https://github.com/adap/flower/pull/1982), " +"[#2112](https://github.com/adap/flower/pull/2112), " +"[#2144](https://github.com/adap/flower/pull/2144), " +"[#2174](https://github.com/adap/flower/pull/2174), " +"[#2225](https://github.com/adap/flower/pull/2225), " +"[#2183](https://github.com/adap/flower/pull/2183))" + +#: ../../source/ref-changelog.md:78 +msgid "" +"**General improvements** " +"([#2803](https://github.com/adap/flower/pull/2803), " +"[#2847](https://github.com/adap/flower/pull/2847), " +"[#2877](https://github.com/adap/flower/pull/2877), " +"[#2690](https://github.com/adap/flower/pull/2690), " +"[#2889](https://github.com/adap/flower/pull/2889), " +"[#2874](https://github.com/adap/flower/pull/2874), " +"[#2819](https://github.com/adap/flower/pull/2819), " +"[#2689](https://github.com/adap/flower/pull/2689), " +"[#2457](https://github.com/adap/flower/pull/2457), " +"[#2870](https://github.com/adap/flower/pull/2870), " +"[#2669](https://github.com/adap/flower/pull/2669), " +"[#2876](https://github.com/adap/flower/pull/2876), " +"[#2885](https://github.com/adap/flower/pull/2885), " +"[#2858](https://github.com/adap/flower/pull/2858), " +"[#2867](https://github.com/adap/flower/pull/2867), " +"[#2351](https://github.com/adap/flower/pull/2351), " +"[#2886](https://github.com/adap/flower/pull/2886), " +"[#2860](https://github.com/adap/flower/pull/2860), " +"[#2828](https://github.com/adap/flower/pull/2828), " +"[#2869](https://github.com/adap/flower/pull/2869), " +"[#2875](https://github.com/adap/flower/pull/2875), " +"[#2733](https://github.com/adap/flower/pull/2733), " +"[#2488](https://github.com/adap/flower/pull/2488), " +"[#2646](https://github.com/adap/flower/pull/2646), " +"[#2879](https://github.com/adap/flower/pull/2879), " +"[#2821](https://github.com/adap/flower/pull/2821), " +"[#2855](https://github.com/adap/flower/pull/2855), " +"[#2800](https://github.com/adap/flower/pull/2800), " +"[#2807](https://github.com/adap/flower/pull/2807), " +"[#2801](https://github.com/adap/flower/pull/2801), " +"[#2804](https://github.com/adap/flower/pull/2804), " +"[#2851](https://github.com/adap/flower/pull/2851), " +"[#2787](https://github.com/adap/flower/pull/2787), " +"[#2852](https://github.com/adap/flower/pull/2852), " +"[#2672](https://github.com/adap/flower/pull/2672), " +"[#2759](https://github.com/adap/flower/pull/2759))" +msgstr "" + +#: ../../source/ref-changelog.md:82 +#, fuzzy +msgid "" +"**Deprecate** `start_numpy_client` " +"([#2563](https://github.com/adap/flower/pull/2563), " +"[#2718](https://github.com/adap/flower/pull/2718))" +msgstr "" +"TAMUNA ([#2254](https://github.com/adap/flower/pull/2254), " +"[#2508](https://github.com/adap/flower/pull/2508))" + +#: ../../source/ref-changelog.md:84 +msgid "" +"Until now, clients of type `NumPyClient` needed to be started via " +"`start_numpy_client`. In our efforts to consolidate framework APIs, we " +"have introduced changes, and now all client types should start via " +"`start_client`. To continue using `NumPyClient` clients, you simply need " +"to first call the `.to_client()` method and then pass returned `Client` " +"object to `start_client`. The examples and the documentation have been " +"updated accordingly." +msgstr "" + +#: ../../source/ref-changelog.md:86 +#, fuzzy +msgid "" +"**Deprecate legacy DP wrappers** " +"([#2749](https://github.com/adap/flower/pull/2749))" +msgstr "**移除过时的 KerasClient**([#857](https://github.com/adap/flower/pull/857))" + +#: ../../source/ref-changelog.md:88 +msgid "" +"Legacy DP wrapper classes are deprecated, but still functional. This is " +"in preparation for an all-new pluggable version of differential privacy " +"support in Flower." +msgstr "" + +#: ../../source/ref-changelog.md:90 +#, fuzzy +msgid "" +"**Make optional arg** `--callable` **in** `flower-client` **a required " +"positional arg** ([#2673](https://github.com/adap/flower/pull/2673))" +msgstr "" +"**从** `start_client` 中移除** `rest` **实验参数 " +"([#2324](https://github.com/adap/flower/pull/2324))" + +#: ../../source/ref-changelog.md:92 +#, fuzzy +msgid "" +"**Rename** `certificates` **to** `root_certificates` **in** `Driver` " +"([#2890](https://github.com/adap/flower/pull/2890))" +msgstr "" +"**重新命名** `rnd` ** to** `server_round` " +"([#1321](https://github.com/adap/flower/pull/1321))" + +#: ../../source/ref-changelog.md:94 +#, fuzzy +msgid "" +"**Drop experimental** `Task` **fields** " +"([#2866](https://github.com/adap/flower/pull/2866), " +"[#2865](https://github.com/adap/flower/pull/2865))" +msgstr "" +"FedBN ([#2608](https://github.com/adap/flower/pull/2608), " +"[#2615](https://github.com/adap/flower/pull/2615))" + +#: ../../source/ref-changelog.md:96 +msgid "" +"Experimental fields `sa`, `legacy_server_message` and " +"`legacy_client_message` were removed from `Task` message. The removed " +"fields are superseded by the new `RecordSet` abstraction." +msgstr "" + +#: ../../source/ref-changelog.md:98 +#, fuzzy +msgid "" +"**Retire MXNet examples** " +"([#2724](https://github.com/adap/flower/pull/2724))" +msgstr "**新的 scikit-learn 代码示例** ([#748](https://github.com/adap/flower/pull/748))" + +#: ../../source/ref-changelog.md:100 +msgid "" +"The development of the MXNet fremework has ended and the project is now " +"[archived on GitHub](https://github.com/apache/mxnet). Existing MXNet " +"examples won't receive updates." +msgstr "" + +#: ../../source/ref-changelog.md:102 +#, fuzzy +msgid "v1.6.0 (2023-11-28)" +msgstr "v1.4.0 (2023-04-21)" + +#: ../../source/ref-changelog.md:108 +msgid "" +"`Aashish Kolluri`, `Adam Narozniak`, `Alessio Mora`, `Barathwaja S`, " +"`Charles Beauville`, `Daniel J. Beutel`, `Daniel Nata Nugraha`, `Gabriel " +"Mota`, `Heng Pan`, `Ivan Agarský`, `JS.KIM`, `Javier`, `Marius Schlegel`," +" `Navin Chandra`, `Nic Lane`, `Peterpan828`, `Qinbin Li`, `Shaz-hash`, " +"`Steve Laskaridis`, `Taner Topal`, `William Lindskog`, `Yan Gao`, " +"`cnxdeveloper`, `k3nfalt` " +msgstr "" + +#: ../../source/ref-changelog.md:112 +msgid "" +"**Add experimental support for Python 3.12** " +"([#2565](https://github.com/adap/flower/pull/2565))" +msgstr "" +"** 增加对 Python 3.12 的实验支持** " +"([#2565](https://github.com/adap/flower/pull/2565))" + +#: ../../source/ref-changelog.md:114 +#, fuzzy +msgid "" +"**Add new XGBoost examples** " +"([#2612](https://github.com/adap/flower/pull/2612), " +"[#2554](https://github.com/adap/flower/pull/2554), " +"[#2617](https://github.com/adap/flower/pull/2617), " +"[#2618](https://github.com/adap/flower/pull/2618), " +"[#2619](https://github.com/adap/flower/pull/2619), " +"[#2567](https://github.com/adap/flower/pull/2567))" +msgstr "" +"**引入(试验性)Driver API** ([#1520](https://github.com/adap/flower/pull/1520)," +" [#1525](https://github.com/adap/flower/pull/1525), " +"[#1545](https://github.com/adap/flower/pull/1545), " +"[#1546](https://github.com/adap/flower/pull/1546), " +"[#1550](https://github.com/adap/flower/pull/1550), " +"[#1551](https://github.com/adap/flower/pull/1551), " +"[#1567](https://github.com/adap/flower/pull/1567))" -#: ../../source/ref-changelog.md:3 -msgid "Unreleased" -msgstr "尚未发布" +#: ../../source/ref-changelog.md:116 +msgid "" +"We have added a new `xgboost-quickstart` example alongside a new " +"`xgboost-comprehensive` example that goes more in-depth." +msgstr "" -#: ../../source/ref-changelog.md:5 ../../source/ref-changelog.md:83 -#: ../../source/ref-changelog.md:167 ../../source/ref-changelog.md:231 -#: ../../source/ref-changelog.md:289 ../../source/ref-changelog.md:358 -#: ../../source/ref-changelog.md:487 ../../source/ref-changelog.md:529 -#: ../../source/ref-changelog.md:596 ../../source/ref-changelog.md:662 -#: ../../source/ref-changelog.md:707 ../../source/ref-changelog.md:746 -#: ../../source/ref-changelog.md:779 ../../source/ref-changelog.md:829 -msgid "What's new?" -msgstr "有什么新内容?" +#: ../../source/ref-changelog.md:118 +#, fuzzy +msgid "" +"**Add Vertical FL example** " +"([#2598](https://github.com/adap/flower/pull/2598))" +msgstr "**新的 iOS CoreML 代码示例**([#1289](https://github.com/adap/flower/pull/1289))" -#: ../../source/ref-changelog.md:7 +#: ../../source/ref-changelog.md:120 msgid "" -"**Add experimental support for Python 3.12** ([#2565](https://github.com/" -"adap/flower/pull/2565))" +"We had many questions about Vertical Federated Learning using Flower, so " +"we decided to add an simple example for it on the [Titanic " +"dataset](https://www.kaggle.com/competitions/titanic/data) alongside a " +"tutorial (in the README)." msgstr "" -"** 增加对 Python 3.12 的实验支持** ([#2565](https://github.com/adap/flower/" -"pull/2565))" -#: ../../source/ref-changelog.md:9 +#: ../../source/ref-changelog.md:122 +msgid "" +"**Support custom** `ClientManager` **in** `start_driver()` " +"([#2292](https://github.com/adap/flower/pull/2292))" +msgstr "**在***`start_driver()`中支持自定义***`ClientManager([#2292](https://github.com/adap/flower/pull/2292))" + +#: ../../source/ref-changelog.md:124 msgid "" -"**Support custom** `ClientManager` **in** `start_driver()` ([#2292](https://" -"github.com/adap/flower/pull/2292))" +"**Update REST API to support create and delete nodes** " +"([#2283](https://github.com/adap/flower/pull/2283))" msgstr "" -"**在***`start_driver()`中支持自定义***`ClientManager([#2292](https://github." -"com/adap/flower/pull/2292))" +"**更新 REST API 以支持创建和删除节点** " +"([#2283](https://github.com/adap/flower/pull/2283))" -#: ../../source/ref-changelog.md:11 +#: ../../source/ref-changelog.md:126 +#, fuzzy msgid "" -"**Update REST API to support create and delete nodes** ([#2283](https://" -"github.com/adap/flower/pull/2283))" +"**Update the Android SDK** " +"([#2187](https://github.com/adap/flower/pull/2187))" msgstr "" -"**更新 REST API 以支持创建和删除节点** ([#2283](https://github.com/adap/" -"flower/pull/2283))" +"**介绍Flower Android SDK** " +"([#2131](https://github.com/adap/flower/pull/2131))" + +#: ../../source/ref-changelog.md:128 +#, fuzzy +msgid "Add gRPC request-response capability to the Android SDK." +msgstr "为 C++ SDK 添加 gRPC 请求-响应功能。" -#: ../../source/ref-changelog.md:13 +#: ../../source/ref-changelog.md:130 +#, fuzzy msgid "" -"**Update the C++ SDK** ([#2537](https://github/com/adap/flower/pull/2537), " -"[#2528](https://github/com/adap/flower/pull/2528), [#2523](https://github." -"com/adap/flower/pull/2523), [#2522](https://github.com/adap/flower/" -"pull/2522))" +"**Update the C++ SDK** " +"([#2537](https://github.com/adap/flower/pull/2537), " +"[#2528](https://github.com/adap/flower/pull/2528), " +"[#2523](https://github.com/adap/flower/pull/2523), " +"[#2522](https://github.com/adap/flower/pull/2522))" msgstr "" -"** 更新 C++ SDK** ([#2537](https://github/com/adap/flower/pull/2537), [#2528]" -"(https://github/com/adap/flower/pull/2528), [#2523](https://github.com/adap/" -"flower/pull/2523), [#2522](https://github.com/adap/flower/pull/2522))" +"** 更新 C++ SDK** ([#2537](https://github/com/adap/flower/pull/2537), " +"[#2528](https://github/com/adap/flower/pull/2528), " +"[#2523](https://github.com/adap/flower/pull/2523), " +"[#2522](https://github.com/adap/flower/pull/2522))" -#: ../../source/ref-changelog.md:15 +#: ../../source/ref-changelog.md:132 msgid "Add gRPC request-response capability to the C++ SDK." msgstr "为 C++ SDK 添加 gRPC 请求-响应功能。" -#: ../../source/ref-changelog.md:17 +#: ../../source/ref-changelog.md:134 +#, fuzzy msgid "" -"**Fix the incorrect return types of Strategy** ([#2432](https://github.com/" -"adap/flower/pull/2432/files))" +"**Make HTTPS the new default** " +"([#2591](https://github.com/adap/flower/pull/2591), " +"[#2636](https://github.com/adap/flower/pull/2636))" msgstr "" -"**修复策略的错误返回类型** ([#2432](https://github.com/adap/flower/pull/2432/" -"files))" +"Baselines文档([#2290](https://github.com/adap/flower/pull/2290), " +"[#2400](https://github.com/adap/flower/pull/2400)" -#: ../../source/ref-changelog.md:19 +#: ../../source/ref-changelog.md:136 msgid "" -"The types of the return values in the docstrings in two methods " -"(`aggregate_fit` and `aggregate_evaluate`) now match the hint types in the " -"code." +"Flower is moving to HTTPS by default. The new `flower-server` requires " +"passing `--certificates`, but users can enable `--insecure` to use HTTP " +"for prototyping. The same applies to `flower-client`, which can either " +"use user-provided credentials or gRPC-bundled certificates to connect to " +"an HTTPS-enabled server or requires opt-out via passing `--insecure` to " +"enable insecure HTTP connections." msgstr "" -"两个方法(\"aggregate_fit \"和 \"aggregate_evaluate\")的文档说明中的返回值类" -"型现在与代码中的提示类型一致。" -#: ../../source/ref-changelog.md:21 +#: ../../source/ref-changelog.md:138 +msgid "" +"For backward compatibility, `start_client()` and `start_numpy_client()` " +"will still start in insecure mode by default. In a future release, " +"insecure connections will require user opt-in by passing `insecure=True`." +msgstr "" + +#: ../../source/ref-changelog.md:140 msgid "" "**Unify client API** ([#2303](https://github.com/adap/flower/pull/2303), " -"[#2390](https://github.com/adap/flower/pull/2390), [#2493](https://github." -"com/adap/flower/pull/2493))" +"[#2390](https://github.com/adap/flower/pull/2390), " +"[#2493](https://github.com/adap/flower/pull/2493))" msgstr "" -"** 统一客户端应用程序接口** ([#2303](https://github.com/adap/flower/" -"pull/2303), [#2390](https://github.com/adap/flower/pull/2390), [#2493]" -"(https://github.com/adap/flower/pull/2493))" +"** 统一客户端应用程序接口** ([#2303](https://github.com/adap/flower/pull/2303), " +"[#2390](https://github.com/adap/flower/pull/2390), " +"[#2493](https://github.com/adap/flower/pull/2493))" -#: ../../source/ref-changelog.md:23 +#: ../../source/ref-changelog.md:142 +#, fuzzy msgid "" -"Using the `client_fn`, Flower clients can interchangeably run as standalone " -"processes (i.e. via `start_client`) or in simulation (i.e. via " -"`start_simulation`) without requiring changes to how the client class is " -"defined and instantiated. Calling `start_numpy_client` is now deprecated." +"Using the `client_fn`, Flower clients can interchangeably run as " +"standalone processes (i.e. via `start_client`) or in simulation (i.e. via" +" `start_simulation`) without requiring changes to how the client class is" +" defined and instantiated. The `to_client()` function is introduced to " +"convert a `NumPyClient` to a `Client`." msgstr "" -"使用 `client_fn`,Flower 客户端可以作为独立进程(即通过 `start_client`)或在" -"模拟中(即通过 `start_simulation`)交替运行,而无需更改客户端类的定义和实例化" -"方式。调用 `start_numpy_client` 现已过时。" +"使用 `client_fn`,Flower 客户端可以作为独立进程(即通过 `start_client`)或在模拟中(即通过 " +"`start_simulation`)交替运行,而无需更改客户端类的定义和实例化方式。调用 `start_numpy_client` 现已过时。" -#: ../../source/ref-changelog.md:25 -msgid "**Update Flower Baselines**" -msgstr "**更新 Flower Baselines**" +#: ../../source/ref-changelog.md:144 +msgid "" +"**Add new** `Bulyan` **strategy** " +"([#1817](https://github.com/adap/flower/pull/1817), " +"[#1891](https://github.com/adap/flower/pull/1891))" +msgstr "" +"**添加新**\"Bulyan " +"\"**策略**([#1817](https://github.com/adap/flower/pull/1817), " +"[#1891](https://github.com/adap/flower/pull/1891)" -#: ../../source/ref-changelog.md:27 +#: ../../source/ref-changelog.md:146 +msgid "" +"The new `Bulyan` strategy implements Bulyan by [El Mhamdi et al., " +"2018](https://arxiv.org/abs/1802.07927)" +msgstr "新的 \"Bulyan\"策略通过[El Mhamdi 等人,2018](https://arxiv.org/abs/1802.07927)实现" + +#: ../../source/ref-changelog.md:148 +#, fuzzy msgid "" -"FedProx ([#2210](https://github.com/adap/flower/pull/2210), [#2286](https://" -"github.com/adap/flower/pull/2286), [#2509](https://github.com/adap/flower/" -"pull/2509))" +"**Add new** `XGB Bagging` **strategy** " +"([#2611](https://github.com/adap/flower/pull/2611))" +msgstr "**添加新的`FedProx`策略** ([#1619](https://github.com/adap/flower/pull/1619))" + +#: ../../source/ref-changelog.md:150 ../../source/ref-changelog.md:152 +#, fuzzy +msgid "" +"**Introduce `WorkloadState`** " +"([#2564](https://github.com/adap/flower/pull/2564), " +"[#2632](https://github.com/adap/flower/pull/2632))" +msgstr "" +"**新的内置策略**([#828](https://github.com/adap/flower/pull/828) " +"[#822](https://github.com/adap/flower/pull/822)" + +#: ../../source/ref-changelog.md:156 +msgid "" +"FedProx ([#2210](https://github.com/adap/flower/pull/2210), " +"[#2286](https://github.com/adap/flower/pull/2286), " +"[#2509](https://github.com/adap/flower/pull/2509))" msgstr "" "FedProx ([#2210](https://github.com/adap/flower/pull/2210), " -"[#2286](https://github.com/adap/flower/pull/2286), [#2509](https://github." -"com/adap/flower/pull/2509))" +"[#2286](https://github.com/adap/flower/pull/2286), " +"[#2509](https://github.com/adap/flower/pull/2509))" -#: ../../source/ref-changelog.md:29 +#: ../../source/ref-changelog.md:158 msgid "" -"Baselines Docs ([#2290](https://github.com/adap/flower/pull/2290), [#2400]" -"(https://github.com/adap/flower/pull/2400))" +"Baselines Docs ([#2290](https://github.com/adap/flower/pull/2290), " +"[#2400](https://github.com/adap/flower/pull/2400))" msgstr "" "Baselines文档([#2290](https://github.com/adap/flower/pull/2290), " "[#2400](https://github.com/adap/flower/pull/2400)" -#: ../../source/ref-changelog.md:31 +#: ../../source/ref-changelog.md:160 msgid "" -"FedMLB ([#2340](https://github.com/adap/flower/pull/2340), [#2507](https://" -"github.com/adap/flower/pull/2507))" +"FedMLB ([#2340](https://github.com/adap/flower/pull/2340), " +"[#2507](https://github.com/adap/flower/pull/2507))" msgstr "" "FedMLB ([#2340](https://github.com/adap/flower/pull/2340), " "[#2507](https://github.com/adap/flower/pull/2507))" -#: ../../source/ref-changelog.md:33 +#: ../../source/ref-changelog.md:162 msgid "" -"TAMUNA ([#2254](https://github.com/adap/flower/pull/2254), [#2508](https://" -"github.com/adap/flower/pull/2508))" +"TAMUNA ([#2254](https://github.com/adap/flower/pull/2254), " +"[#2508](https://github.com/adap/flower/pull/2508))" msgstr "" "TAMUNA ([#2254](https://github.com/adap/flower/pull/2254), " "[#2508](https://github.com/adap/flower/pull/2508))" -#: ../../source/ref-changelog.md:35 +#: ../../source/ref-changelog.md:164 msgid "FedMeta [#2438](https://github.com/adap/flower/pull/2438)" msgstr "FedMeta [#2438](https://github.com/adap/flower/pull/2438)" -#: ../../source/ref-changelog.md:37 +#: ../../source/ref-changelog.md:166 msgid "FjORD [#2431](https://github.com/adap/flower/pull/2431)" msgstr "FjORD [#2431](https://github.com/adap/flower/pull/2431)" -#: ../../source/ref-changelog.md:39 +#: ../../source/ref-changelog.md:168 msgid "MOON [#2421](https://github.com/adap/flower/pull/2421)" msgstr "MOON [#2421](https://github.com/adap/flower/pull/2421)" -#: ../../source/ref-changelog.md:41 +#: ../../source/ref-changelog.md:170 msgid "DepthFL [#2295](https://github.com/adap/flower/pull/2295)" msgstr "DepthFL [#2295](https://github.com/adap/flower/pull/2295)" -#: ../../source/ref-changelog.md:43 +#: ../../source/ref-changelog.md:172 msgid "FedPer [#2266](https://github.com/adap/flower/pull/2266)" msgstr "FedPer [#2266](https://github.com/adap/flower/pull/2266)" -#: ../../source/ref-changelog.md:45 +#: ../../source/ref-changelog.md:174 msgid "FedWav2vec [#2551](https://github.com/adap/flower/pull/2551)" msgstr "FedWav2vec [#2551](https://github.com/adap/flower/pull/2551)" -#: ../../source/ref-changelog.md:47 +#: ../../source/ref-changelog.md:176 msgid "niid-Bench [#2428](https://github.com/adap/flower/pull/2428)" msgstr "niid-Bench [#2428](https://github.com/adap/flower/pull/2428)" -#: ../../source/ref-changelog.md:49 +#: ../../source/ref-changelog.md:178 msgid "" -"FedBN ([#2608](https://github.com/adap/flower/pull/2608), [#2615](https://" -"github.com/adap/flower/pull/2615))" -msgstr "" "FedBN ([#2608](https://github.com/adap/flower/pull/2608), " "[#2615](https://github.com/adap/flower/pull/2615))" - -#: ../../source/ref-changelog.md:51 -msgid "" -"**Update Flower Examples** ([#2384](https://github.com/adap/flower/" -"pull/2384),[#2425](https://github.com/adap/flower/pull/2425), [#2526]" -"(https://github.com/adap/flower/pull/2526))" msgstr "" -"** 更新 Flower Examples** ([#2384](https://github.com/adap/flower/pull/" -"2384),[#2425](https://github.com/adap/flower/pull/2425), " -"[#2526](https://github.com/adap/flower/pull/2526))" +"FedBN ([#2608](https://github.com/adap/flower/pull/2608), " +"[#2615](https://github.com/adap/flower/pull/2615))" -#: ../../source/ref-changelog.md:53 -msgid "" -"**General updates to baselines** ([#2301](https://github.com/adap/flower/" -"pull/2301), [#2305](https://github.com/adap/flower/pull/2305), [#2307]" -"(https://github.com/adap/flower/pull/2307), [#2327](https://github.com/adap/" -"flower/pull/2327), [#2435](https://github.com/adap/flower/pull/2435))" +#: ../../source/ref-changelog.md:180 +#, fuzzy +msgid "" +"**General updates to Flower Examples** " +"([#2384](https://github.com/adap/flower/pull/2384), " +"[#2425](https://github.com/adap/flower/pull/2425), " +"[#2526](https://github.com/adap/flower/pull/2526), " +"[#2302](https://github.com/adap/flower/pull/2302), " +"[#2545](https://github.com/adap/flower/pull/2545))" +msgstr "" +"** 更新 C++ SDK** ([#2537](https://github/com/adap/flower/pull/2537), " +"[#2528](https://github/com/adap/flower/pull/2528), " +"[#2523](https://github.com/adap/flower/pull/2523), " +"[#2522](https://github.com/adap/flower/pull/2522))" + +#: ../../source/ref-changelog.md:182 +#, fuzzy +msgid "" +"**General updates to Flower Baselines** " +"([#2301](https://github.com/adap/flower/pull/2301), " +"[#2305](https://github.com/adap/flower/pull/2305), " +"[#2307](https://github.com/adap/flower/pull/2307), " +"[#2327](https://github.com/adap/flower/pull/2327), " +"[#2435](https://github.com/adap/flower/pull/2435), " +"[#2462](https://github.com/adap/flower/pull/2462), " +"[#2463](https://github.com/adap/flower/pull/2463), " +"[#2461](https://github.com/adap/flower/pull/2461), " +"[#2469](https://github.com/adap/flower/pull/2469), " +"[#2466](https://github.com/adap/flower/pull/2466), " +"[#2471](https://github.com/adap/flower/pull/2471), " +"[#2472](https://github.com/adap/flower/pull/2472), " +"[#2470](https://github.com/adap/flower/pull/2470))" msgstr "" -"** baselines的普通更新** ([#2301](https://github.com/adap/flower/pull/2301), " -"[#2305](https://github.com/adap/flower/pull/2305), [#2307](https://github." -"com/adap/flower/pull/2307), [#2327](https://github.com/adap/flower/pull/2327)" -", [#2435](https://github.com/adap/flower/pull/2435))" - -#: ../../source/ref-changelog.md:55 -msgid "" -"**General updates to the simulation engine** ([#2331](https://github.com/" -"adap/flower/pull/2331), [#2447](https://github.com/adap/flower/pull/2447), " -"[#2448](https://github.com/adap/flower/pull/2448))" +"**普通改进**([#2309](https://github.com/adap/flower/pull/2309), " +"[#2310](https://github.com/adap/flower/pull/2310), " +"[2313](https://github.com/adap/flower/pull/2313), " +"[#2316](https://github.com/adap/flower/pull/2316), " +"[2317](https://github.com/adap/flower/pull/2317),[#2349](https://github.com/adap/flower/pull/2349)," +" [#2360](https://github.com/adap/flower/pull/2360), " +"[#2402](https://github.com/adap/flower/pull/2402), " +"[#2446](https://github.com/adap/flower/pull/2446) " +"[#2561](https://github.com/adap/flower/pull/2561))" + +#: ../../source/ref-changelog.md:184 +#, fuzzy +msgid "" +"**General updates to the simulation engine** " +"([#2331](https://github.com/adap/flower/pull/2331), " +"[#2447](https://github.com/adap/flower/pull/2447), " +"[#2448](https://github.com/adap/flower/pull/2448), " +"[#2294](https://github.com/adap/flower/pull/2294))" msgstr "" "**模拟引擎的普通更新** ([#2331](https://github.com/adap/flower/pull/2331), " -"[#2447](https://github.com/adap/flower/pull/2447), [#2448](https://github." -"com/adap/flower/pull/2448))" +"[#2447](https://github.com/adap/flower/pull/2447), " +"[#2448](https://github.com/adap/flower/pull/2448))" -#: ../../source/ref-changelog.md:57 -msgid "" -"**General improvements** ([#2309](https://github.com/adap/flower/pull/2309), " -"[#2310](https://github.com/adap/flower/pull/2310), [2313](https://github.com/" -"adap/flower/pull/2313), [#2316](https://github.com/adap/flower/pull/2316), " -"[2317](https://github.com/adap/flower/pull/2317),[#2349](https://github.com/" -"adap/flower/pull/2349), [#2360](https://github.com/adap/flower/pull/2360), " -"[#2402](https://github.com/adap/flower/pull/2402), [#2446](https://github." -"com/adap/flower/pull/2446) [#2561](https://github.com/adap/flower/pull/2561))" -msgstr "" -"**普通改进**([#2309](https://github.com/adap/flower/pull/2309), " -"[#2310](https://github.com/adap/flower/pull/2310), [2313](https://github.com/" -"adap/flower/pull/2313), [#2316](https://github.com/adap/flower/pull/2316), " -"[2317](https://github.com/adap/flower/pull/2317),[#2349](https://github.com/" -"adap/flower/pull/2349), [#2360](https://github.com/adap/flower/pull/2360), " -"[#2402](https://github.com/adap/flower/pull/2402), [#2446](https://github." -"com/adap/flower/pull/2446) [#2561](https://github.com/adap/flower/pull/2561))" - -#: ../../source/ref-changelog.md:59 ../../source/ref-changelog.md:153 -#: ../../source/ref-changelog.md:217 ../../source/ref-changelog.md:271 -#: ../../source/ref-changelog.md:338 -msgid "" -"Flower received many improvements under the hood, too many to list here." +#: ../../source/ref-changelog.md:186 +#, fuzzy +msgid "" +"**General updates to Flower SDKs** " +"([#2288](https://github.com/adap/flower/pull/2288), " +"[#2429](https://github.com/adap/flower/pull/2429), " +"[#2555](https://github.com/adap/flower/pull/2555), " +"[#2543](https://github.com/adap/flower/pull/2543), " +"[#2544](https://github.com/adap/flower/pull/2544), " +"[#2597](https://github.com/adap/flower/pull/2597), " +"[#2623](https://github.com/adap/flower/pull/2623))" +msgstr "" +"**改进教程** ([#1468](https://github.com/adap/flower/pull/1468), " +"[#1470](https://github.com/adap/flower/pull/1470), " +"[#1472](https://github.com/adap/flower/pull/1472), " +"[#1473](https://github.com/adap/flower/pull/1473), " +"[#1474](https://github.com/adap/flower/pull/1474), " +"[#1475](https://github.com/adap/flower/pull/1475)))" + +#: ../../source/ref-changelog.md:188 +msgid "" +"**General improvements** " +"([#2309](https://github.com/adap/flower/pull/2309), " +"[#2310](https://github.com/adap/flower/pull/2310), " +"[#2313](https://github.com/adap/flower/pull/2313), " +"[#2316](https://github.com/adap/flower/pull/2316), " +"[#2317](https://github.com/adap/flower/pull/2317), " +"[#2349](https://github.com/adap/flower/pull/2349), " +"[#2360](https://github.com/adap/flower/pull/2360), " +"[#2402](https://github.com/adap/flower/pull/2402), " +"[#2446](https://github.com/adap/flower/pull/2446), " +"[#2561](https://github.com/adap/flower/pull/2561), " +"[#2273](https://github.com/adap/flower/pull/2273), " +"[#2267](https://github.com/adap/flower/pull/2267), " +"[#2274](https://github.com/adap/flower/pull/2274), " +"[#2275](https://github.com/adap/flower/pull/2275), " +"[#2432](https://github.com/adap/flower/pull/2432), " +"[#2251](https://github.com/adap/flower/pull/2251), " +"[#2321](https://github.com/adap/flower/pull/2321), " +"[#1936](https://github.com/adap/flower/pull/1936), " +"[#2408](https://github.com/adap/flower/pull/2408), " +"[#2413](https://github.com/adap/flower/pull/2413), " +"[#2401](https://github.com/adap/flower/pull/2401), " +"[#2531](https://github.com/adap/flower/pull/2531), " +"[#2534](https://github.com/adap/flower/pull/2534), " +"[#2535](https://github.com/adap/flower/pull/2535), " +"[#2521](https://github.com/adap/flower/pull/2521), " +"[#2553](https://github.com/adap/flower/pull/2553), " +"[#2596](https://github.com/adap/flower/pull/2596))" +msgstr "" + +#: ../../source/ref-changelog.md:190 ../../source/ref-changelog.md:280 +#: ../../source/ref-changelog.md:344 ../../source/ref-changelog.md:398 +#: ../../source/ref-changelog.md:465 +msgid "Flower received many improvements under the hood, too many to list here." msgstr "Flower 进行了许多改进,这里就不一一列举了。" -#: ../../source/ref-changelog.md:61 -msgid "" -"**Add new** `Bulyan` **strategy** ([#1817](https://github.com/adap/flower/" -"pull/1817), [#1891](https://github.com/adap/flower/pull/1891))" -msgstr "" -"**添加新**\"Bulyan \"**策略**([#1817](https://github.com/adap/flower/" -"pull/1817), [#1891](https://github.com/adap/flower/pull/1891)" - -#: ../../source/ref-changelog.md:63 -msgid "" -"The new `Bulyan` strategy implements Bulyan by [El Mhamdi et al., 2018]" -"(https://arxiv.org/abs/1802.07927)" -msgstr "" -"新的 \"Bulyan\"策略通过[El Mhamdi 等人,2018](https://arxiv.org/" -"abs/1802.07927)实现" - -#: ../../source/ref-changelog.md:65 ../../source/ref-changelog.md:155 -#: ../../source/ref-changelog.md:219 ../../source/ref-changelog.md:277 -#: ../../source/ref-changelog.md:346 ../../source/ref-changelog.md:408 -#: ../../source/ref-changelog.md:427 ../../source/ref-changelog.md:583 -#: ../../source/ref-changelog.md:654 ../../source/ref-changelog.md:691 -#: ../../source/ref-changelog.md:734 -msgid "Incompatible changes" -msgstr "不兼容的更改" - -#: ../../source/ref-changelog.md:67 +#: ../../source/ref-changelog.md:194 msgid "" -"**Remove support for Python 3.7** ([#2280](https://github.com/adap/flower/" -"pull/2280), [#2299](https://github.com/adap/flower/pull/2299), [#2304]" -"(https://github.com/adap/flower/pull/2304), [#2306](https://github.com/adap/" -"flower/pull/2306), [#2355](https://github.com/adap/flower/pull/2355), [#2356]" -"(https://github.com/adap/flower/pull/2356))" +"**Remove support for Python 3.7** " +"([#2280](https://github.com/adap/flower/pull/2280), " +"[#2299](https://github.com/adap/flower/pull/2299), " +"[#2304](https://github.com/adap/flower/pull/2304), " +"[#2306](https://github.com/adap/flower/pull/2306), " +"[#2355](https://github.com/adap/flower/pull/2355), " +"[#2356](https://github.com/adap/flower/pull/2356))" msgstr "" -"**移除对 Python 3.7 的支持** ([#2280](https://github.com/adap/flower/" -"pull/2280), [#2299](https://github.com/adap/flower/pull/2299), [#2304]" -"(https://github.com/adap/flower/pull/2304), [#2306](https://github.com/adap/" -"flower/pull/2306), [#2355](https://github.com/adap/flower/pull/2355), [#2356]" -"(https://github.com/adap/flower/pull/2356))" +"**移除对 Python 3.7 的支持** " +"([#2280](https://github.com/adap/flower/pull/2280), " +"[#2299](https://github.com/adap/flower/pull/2299), " +"[#2304](https://github.com/adap/flower/pull/2304), " +"[#2306](https://github.com/adap/flower/pull/2306), " +"[#2355](https://github.com/adap/flower/pull/2355), " +"[#2356](https://github.com/adap/flower/pull/2356))" -#: ../../source/ref-changelog.md:69 +#: ../../source/ref-changelog.md:196 msgid "" -"Python 3.7 support was deprecated in Flower 1.5, and this release removes " -"support. Flower now requires Python 3.8." -msgstr "" -"在 Flower 1.5 中,Python 3.7 支持已被弃用,本版本将删除该支持。Flower 现在需" -"要 Python 3.8。" +"Python 3.7 support was deprecated in Flower 1.5, and this release removes" +" support. Flower now requires Python 3.8." +msgstr "在 Flower 1.5 中,Python 3.7 支持已被弃用,本版本将删除该支持。Flower 现在需要 Python 3.8。" -#: ../../source/ref-changelog.md:71 +#: ../../source/ref-changelog.md:198 msgid "" -"**Remove experimental argument** `rest` **from** `start_client` ([#2324]" -"(https://github.com/adap/flower/pull/2324))" +"**Remove experimental argument** `rest` **from** `start_client` " +"([#2324](https://github.com/adap/flower/pull/2324))" msgstr "" -"**从** `start_client` 中移除** `rest` **实验参数 ([#2324](https://github.com/" -"adap/flower/pull/2324))" +"**从** `start_client` 中移除** `rest` **实验参数 " +"([#2324](https://github.com/adap/flower/pull/2324))" -#: ../../source/ref-changelog.md:73 +#: ../../source/ref-changelog.md:200 msgid "" -"The (still experimental) argument `rest` was removed from `start_client` and " -"`start_numpy_client`. Use `transport=\"rest\"` to opt into the experimental " -"REST API instead." +"The (still experimental) argument `rest` was removed from `start_client` " +"and `start_numpy_client`. Use `transport=\"rest\"` to opt into the " +"experimental REST API instead." msgstr "" -"删除了 `start_client` 和 `start_numpy_client` 中的参数 `rest`(仍属试验性" -"质)。请使用 `transport=\"rest\"` 来选择使用试验性 REST API。" +"删除了 `start_client` 和 `start_numpy_client` 中的参数 `rest`(仍属试验性质)。请使用 " +"`transport=\"rest\"` 来选择使用试验性 REST API。" -#: ../../source/ref-changelog.md:75 +#: ../../source/ref-changelog.md:202 msgid "v1.5.0 (2023-08-31)" msgstr "v1.5.0 (2023-08-31)" -#: ../../source/ref-changelog.md:77 ../../source/ref-changelog.md:161 -#: ../../source/ref-changelog.md:225 ../../source/ref-changelog.md:283 -#: ../../source/ref-changelog.md:352 ../../source/ref-changelog.md:421 -msgid "Thanks to our contributors" -msgstr "感谢我们的贡献者" - -#: ../../source/ref-changelog.md:79 ../../source/ref-changelog.md:163 -#: ../../source/ref-changelog.md:227 ../../source/ref-changelog.md:285 -msgid "" -"We would like to give our special thanks to all the contributors who made " -"the new version of Flower possible (in `git shortlog` order):" -msgstr "" -"在此,我们要特别感谢所有为 Flower 的新版本做出贡献的人员(按 `git shortlog` " -"顺序排列):" - -#: ../../source/ref-changelog.md:81 +#: ../../source/ref-changelog.md:208 msgid "" "`Adam Narozniak`, `Anass Anhari`, `Charles Beauville`, `Dana-Farber`, " "`Daniel J. Beutel`, `Daniel Nata Nugraha`, `Edoardo Gabrielli`, `Gustavo " @@ -8500,1068 +12442,1150 @@ msgid "" "Topal`, `achiverram28`, `danielnugraha`, `eunchung`, `ruthgal` " msgstr "" -"`Adam Narozniak`, `Anass Anhari`, `Charles Beauville`, `Dana-Farber`, `" -"Daniel J. Beutel`, `Daniel Nata Nugraha`, `Edoardo Gabrielli`, `Gustavo " -"Bertoli`, `Heng Pan`, `Javier`, `Mahdi`, `Steven Hé (Sīchàng)`, `Taner Topal`" -", `achiverram28`, `danielnugraha`, `eunchung`, `ruthgal` " +"`Adam Narozniak`, `Anass Anhari`, `Charles Beauville`, `Dana-Farber`, " +"`Daniel J. Beutel`, `Daniel Nata Nugraha`, `Edoardo Gabrielli`, `Gustavo " +"Bertoli`, `Heng Pan`, `Javier`, `Mahdi`, `Steven Hé (Sīchàng)`, `Taner " +"Topal`, `achiverram28`, `danielnugraha`, `eunchung`, `ruthgal` " -#: ../../source/ref-changelog.md:85 +#: ../../source/ref-changelog.md:212 msgid "" -"**Introduce new simulation engine** ([#1969](https://github.com/adap/flower/" -"pull/1969), [#2221](https://github.com/adap/flower/pull/2221), [#2248]" -"(https://github.com/adap/flower/pull/2248))" +"**Introduce new simulation engine** " +"([#1969](https://github.com/adap/flower/pull/1969), " +"[#2221](https://github.com/adap/flower/pull/2221), " +"[#2248](https://github.com/adap/flower/pull/2248))" msgstr "" "**引入新的模拟引擎** ([#1969](https://github.com/adap/flower/pull/1969), " -"[#2221](https://github.com/adap/flower/pull/2221), [#2248](https://github." -"com/adap/flower/pull/2248))" +"[#2221](https://github.com/adap/flower/pull/2221), " +"[#2248](https://github.com/adap/flower/pull/2248))" -#: ../../source/ref-changelog.md:87 +#: ../../source/ref-changelog.md:214 msgid "" "The new simulation engine has been rewritten from the ground up, yet it " -"remains fully backwards compatible. It offers much improved stability and " -"memory handling, especially when working with GPUs. Simulations " -"transparently adapt to different settings to scale simulation in CPU-only, " -"CPU+GPU, multi-GPU, or multi-node multi-GPU environments." -msgstr "" -"新的模拟引擎从头开始重新编写,但仍完全向后兼容。它的稳定性和内存处理能力大大" -"提高,尤其是在使用 GPU 时。仿真可透明地适应不同的设置,以在仅 CPU、CPU+GPU、" -"多 GPU 或多节点多 GPU 环境中扩展模拟。" - -#: ../../source/ref-changelog.md:89 -msgid "" -"Comprehensive documentation includes a new [how-to run simulations](https://" -"flower.dev/docs/framework/how-to-run-simulations.html) guide, new " -"[simulation-pytorch](https://flower.dev/docs/examples/simulation-pytorch." -"html) and [simulation-tensorflow](https://flower.dev/docs/examples/" -"simulation-tensorflow.html) notebooks, and a new [YouTube tutorial series]" -"(https://www.youtube.com/watch?" -"v=cRebUIGB5RU&list=PLNG4feLHqCWlnj8a_E1A_n5zr2-8pafTB)." -msgstr "" -"综合文档包括新的[how-to run simulations](https://flower.dev/docs/framework/" -"how-to-run-simulations.html) guide, new [simulation-pytorch](https://flower." -"dev/docs/examples/simulation-pytorch.html) and [simulation-" -"tensorflow](https://flower.dev/docs/examples/simulation-tensorflow.html) " -"notebooks, and a new [YouTube tutorial series](https://www.youtube.com/" -"watch?v=cRebUIGB5RU&list=PLNG4feLHqCWlnj8a_E1A_n5zr2-8pafTB)。" - -#: ../../source/ref-changelog.md:91 -msgid "" -"**Restructure Flower Docs** ([#1824](https://github.com/adap/flower/" -"pull/1824), [#1865](https://github.com/adap/flower/pull/1865), [#1884]" -"(https://github.com/adap/flower/pull/1884), [#1887](https://github.com/adap/" -"flower/pull/1887), [#1919](https://github.com/adap/flower/pull/1919), [#1922]" -"(https://github.com/adap/flower/pull/1922), [#1920](https://github.com/adap/" -"flower/pull/1920), [#1923](https://github.com/adap/flower/pull/1923), [#1924]" -"(https://github.com/adap/flower/pull/1924), [#1962](https://github.com/adap/" -"flower/pull/1962), [#2006](https://github.com/adap/flower/pull/2006), [#2133]" -"(https://github.com/adap/flower/pull/2133), [#2203](https://github.com/adap/" -"flower/pull/2203), [#2215](https://github.com/adap/flower/pull/2215), [#2122]" -"(https://github.com/adap/flower/pull/2122), [#2223](https://github.com/adap/" -"flower/pull/2223), [#2219](https://github.com/adap/flower/pull/2219), [#2232]" -"(https://github.com/adap/flower/pull/2232), [#2233](https://github.com/adap/" -"flower/pull/2233), [#2234](https://github.com/adap/flower/pull/2234), [#2235]" -"(https://github.com/adap/flower/pull/2235), [#2237](https://github.com/adap/" -"flower/pull/2237), [#2238](https://github.com/adap/flower/pull/2238), [#2242]" -"(https://github.com/adap/flower/pull/2242), [#2231](https://github.com/adap/" -"flower/pull/2231), [#2243](https://github.com/adap/flower/pull/2243), [#2227]" -"(https://github.com/adap/flower/pull/2227))" +"remains fully backwards compatible. It offers much improved stability and" +" memory handling, especially when working with GPUs. Simulations " +"transparently adapt to different settings to scale simulation in CPU-" +"only, CPU+GPU, multi-GPU, or multi-node multi-GPU environments." +msgstr "" +"新的模拟引擎从头开始重新编写,但仍完全向后兼容。它的稳定性和内存处理能力大大提高,尤其是在使用 GPU 时。仿真可透明地适应不同的设置,以在仅 " +"CPU、CPU+GPU、多 GPU 或多节点多 GPU 环境中扩展模拟。" + +#: ../../source/ref-changelog.md:216 +msgid "" +"Comprehensive documentation includes a new [how-to run " +"simulations](https://flower.dev/docs/framework/how-to-run-" +"simulations.html) guide, new [simulation-" +"pytorch](https://flower.dev/docs/examples/simulation-pytorch.html) and " +"[simulation-tensorflow](https://flower.dev/docs/examples/simulation-" +"tensorflow.html) notebooks, and a new [YouTube tutorial " +"series](https://www.youtube.com/watch?v=cRebUIGB5RU&list=PLNG4feLHqCWlnj8a_E1A_n5zr2-8pafTB)." +msgstr "" +"综合文档包括新的[how-to run simulations](https://flower.dev/docs/framework/how-" +"to-run-simulations.html) guide, new [simulation-" +"pytorch](https://flower.dev/docs/examples/simulation-pytorch.html) and " +"[simulation-tensorflow](https://flower.dev/docs/examples/simulation-" +"tensorflow.html) notebooks, and a new [YouTube tutorial " +"series](https://www.youtube.com/watch?v=cRebUIGB5RU&list=PLNG4feLHqCWlnj8a_E1A_n5zr2-8pafTB)。" + +#: ../../source/ref-changelog.md:218 +msgid "" +"**Restructure Flower Docs** " +"([#1824](https://github.com/adap/flower/pull/1824), " +"[#1865](https://github.com/adap/flower/pull/1865), " +"[#1884](https://github.com/adap/flower/pull/1884), " +"[#1887](https://github.com/adap/flower/pull/1887), " +"[#1919](https://github.com/adap/flower/pull/1919), " +"[#1922](https://github.com/adap/flower/pull/1922), " +"[#1920](https://github.com/adap/flower/pull/1920), " +"[#1923](https://github.com/adap/flower/pull/1923), " +"[#1924](https://github.com/adap/flower/pull/1924), " +"[#1962](https://github.com/adap/flower/pull/1962), " +"[#2006](https://github.com/adap/flower/pull/2006), " +"[#2133](https://github.com/adap/flower/pull/2133), " +"[#2203](https://github.com/adap/flower/pull/2203), " +"[#2215](https://github.com/adap/flower/pull/2215), " +"[#2122](https://github.com/adap/flower/pull/2122), " +"[#2223](https://github.com/adap/flower/pull/2223), " +"[#2219](https://github.com/adap/flower/pull/2219), " +"[#2232](https://github.com/adap/flower/pull/2232), " +"[#2233](https://github.com/adap/flower/pull/2233), " +"[#2234](https://github.com/adap/flower/pull/2234), " +"[#2235](https://github.com/adap/flower/pull/2235), " +"[#2237](https://github.com/adap/flower/pull/2237), " +"[#2238](https://github.com/adap/flower/pull/2238), " +"[#2242](https://github.com/adap/flower/pull/2242), " +"[#2231](https://github.com/adap/flower/pull/2231), " +"[#2243](https://github.com/adap/flower/pull/2243), " +"[#2227](https://github.com/adap/flower/pull/2227))" msgstr "" "**重构 Flower 文档** ([#1824](https://github.com/adap/flower/pull/1824), " -"[#1865](https://github.com/adap/flower/pull/1865), [#1884](https://github." -"com/adap/flower/pull/1884), [#1887](https://github.com/adap/flower/pull/1887)" -", [#1919](https://github.com/adap/flower/pull/1919), [#1922](https://github." -"com/adap/flower/pull/1922), [#1920](https://github.com/adap/flower/pull/1920)" -", [#1923](https://github.com/adap/flower/pull/1923), [#1924](https://github." -"com/adap/flower/pull/1924), [#1962](https://github.com/adap/flower/pull/1962)" -", [#2006](https://github.com/adap/flower/pull/2006), [#2133](https://github." -"com/adap/flower/pull/2133), [#2203](https://github.com/adap/flower/pull/2203)" -", [#2215](https://github.com/adap/flower/pull/2215), [#2122](https://github." -"com/adap/flower/pull/2122), [#2223](https://github.com/adap/flower/pull/2223)" -", [#2219](https://github.com/adap/flower/pull/2219), [#2232](https://github." -"com/adap/flower/pull/2232), [#2233](https://github.com/adap/flower/pull/2233)" -", [#2234](https://github.com/adap/flower/pull/2234), [#2235](https://github." -"com/adap/flower/pull/2235), [#2237](https://github.com/adap/flower/pull/2237)" -", [#2238](https://github.com/adap/flower/pull/2238), [#2242](https://github." -"com/adap/flower/pull/2242), [#2231](https://github.com/adap/flower/pull/2231)" -", [#2243](https://github.com/adap/flower/pull/2243), [#2227](https://github." -"com/adap/flower/pull/2227))" - -#: ../../source/ref-changelog.md:93 -msgid "" -"Much effort went into a completely restructured Flower docs experience. The " -"documentation on [flower.dev/docs](flower.dev/docs) is now divided into " -"Flower Framework, Flower Baselines, Flower Android SDK, Flower iOS SDK, and " -"code example projects." -msgstr "" -"Flower 文档体验的全面重构耗费了大量精力。现在,[flower.dev/docs](flower.dev/" -"docs)上的文档分为 Flower Framework、Flower Baselines、Flower Android SDK、" -"Flower iOS SDK 和代码示例项目。" - -#: ../../source/ref-changelog.md:95 -msgid "" -"**Introduce Flower Swift SDK** ([#1858](https://github.com/adap/flower/" -"pull/1858), [#1897](https://github.com/adap/flower/pull/1897))" -msgstr "" -"**介绍 Flower Swift SDK** ([#1858](https://github.com/adap/flower/pull/1858)" -", [#1897](https://github.com/adap/flower/pull/1897))" - -#: ../../source/ref-changelog.md:97 -msgid "" -"This is the first preview release of the Flower Swift SDK. Flower support on " -"iOS is improving, and alongside the Swift SDK and code example, there is now " -"also an iOS quickstart tutorial." -msgstr "" -"这是 Flower Swift SDK 的首个预览版。Flower 对 iOS 的支持正在不断改进,除了 " -"Swift SDK 和代码示例外,现在还有 iOS 快速入门教程。" - -#: ../../source/ref-changelog.md:99 -msgid "" -"**Introduce Flower Android SDK** ([#2131](https://github.com/adap/flower/" -"pull/2131))" -msgstr "" -"**介绍Flower Android SDK** ([#2131](https://github.com/adap/flower/" -"pull/2131))" - -#: ../../source/ref-changelog.md:101 -msgid "" -"This is the first preview release of the Flower Kotlin SDK. Flower support " -"on Android is improving, and alongside the Kotlin SDK and code example, " -"there is now also an Android quickstart tutorial." -msgstr "" -"这是 Flower Kotlin SDK 的首个预览版。Flower 对 Android 的支持正在不断改进,除" -"了 Kotlin SDK 和代码示例,现在还有 Android 快速入门教程。" - -#: ../../source/ref-changelog.md:103 -msgid "" -"**Introduce new end-to-end testing infrastructure** ([#1842](https://github." -"com/adap/flower/pull/1842), [#2071](https://github.com/adap/flower/" -"pull/2071), [#2072](https://github.com/adap/flower/pull/2072), [#2068]" -"(https://github.com/adap/flower/pull/2068), [#2067](https://github.com/adap/" -"flower/pull/2067), [#2069](https://github.com/adap/flower/pull/2069), [#2073]" -"(https://github.com/adap/flower/pull/2073), [#2070](https://github.com/adap/" -"flower/pull/2070), [#2074](https://github.com/adap/flower/pull/2074), [#2082]" -"(https://github.com/adap/flower/pull/2082), [#2084](https://github.com/adap/" -"flower/pull/2084), [#2093](https://github.com/adap/flower/pull/2093), [#2109]" -"(https://github.com/adap/flower/pull/2109), [#2095](https://github.com/adap/" -"flower/pull/2095), [#2140](https://github.com/adap/flower/pull/2140), [#2137]" -"(https://github.com/adap/flower/pull/2137), [#2165](https://github.com/adap/" -"flower/pull/2165))" +"[#1865](https://github.com/adap/flower/pull/1865), " +"[#1884](https://github.com/adap/flower/pull/1884), " +"[#1887](https://github.com/adap/flower/pull/1887), " +"[#1919](https://github.com/adap/flower/pull/1919), " +"[#1922](https://github.com/adap/flower/pull/1922), " +"[#1920](https://github.com/adap/flower/pull/1920), " +"[#1923](https://github.com/adap/flower/pull/1923), " +"[#1924](https://github.com/adap/flower/pull/1924), " +"[#1962](https://github.com/adap/flower/pull/1962), " +"[#2006](https://github.com/adap/flower/pull/2006), " +"[#2133](https://github.com/adap/flower/pull/2133), " +"[#2203](https://github.com/adap/flower/pull/2203), " +"[#2215](https://github.com/adap/flower/pull/2215), " +"[#2122](https://github.com/adap/flower/pull/2122), " +"[#2223](https://github.com/adap/flower/pull/2223), " +"[#2219](https://github.com/adap/flower/pull/2219), " +"[#2232](https://github.com/adap/flower/pull/2232), " +"[#2233](https://github.com/adap/flower/pull/2233), " +"[#2234](https://github.com/adap/flower/pull/2234), " +"[#2235](https://github.com/adap/flower/pull/2235), " +"[#2237](https://github.com/adap/flower/pull/2237), " +"[#2238](https://github.com/adap/flower/pull/2238), " +"[#2242](https://github.com/adap/flower/pull/2242), " +"[#2231](https://github.com/adap/flower/pull/2231), " +"[#2243](https://github.com/adap/flower/pull/2243), " +"[#2227](https://github.com/adap/flower/pull/2227))" + +#: ../../source/ref-changelog.md:220 +msgid "" +"Much effort went into a completely restructured Flower docs experience. " +"The documentation on [flower.dev/docs](flower.dev/docs) is now divided " +"into Flower Framework, Flower Baselines, Flower Android SDK, Flower iOS " +"SDK, and code example projects." +msgstr "" +"Flower 文档体验的全面重构耗费了大量精力。现在,[flower.dev/docs](flower.dev/docs)上的文档分为 " +"Flower Framework、Flower Baselines、Flower Android SDK、Flower iOS SDK " +"和代码示例项目。" + +#: ../../source/ref-changelog.md:222 +msgid "" +"**Introduce Flower Swift SDK** " +"([#1858](https://github.com/adap/flower/pull/1858), " +"[#1897](https://github.com/adap/flower/pull/1897))" +msgstr "" +"**介绍 Flower Swift SDK** " +"([#1858](https://github.com/adap/flower/pull/1858), " +"[#1897](https://github.com/adap/flower/pull/1897))" + +#: ../../source/ref-changelog.md:224 +msgid "" +"This is the first preview release of the Flower Swift SDK. Flower support" +" on iOS is improving, and alongside the Swift SDK and code example, there" +" is now also an iOS quickstart tutorial." +msgstr "" +"这是 Flower Swift SDK 的首个预览版。Flower 对 iOS 的支持正在不断改进,除了 Swift SDK " +"和代码示例外,现在还有 iOS 快速入门教程。" + +#: ../../source/ref-changelog.md:226 +msgid "" +"**Introduce Flower Android SDK** " +"([#2131](https://github.com/adap/flower/pull/2131))" +msgstr "" +"**介绍Flower Android SDK** " +"([#2131](https://github.com/adap/flower/pull/2131))" + +#: ../../source/ref-changelog.md:228 +msgid "" +"This is the first preview release of the Flower Kotlin SDK. Flower " +"support on Android is improving, and alongside the Kotlin SDK and code " +"example, there is now also an Android quickstart tutorial." +msgstr "" +"这是 Flower Kotlin SDK 的首个预览版。Flower 对 Android 的支持正在不断改进,除了 Kotlin SDK " +"和代码示例,现在还有 Android 快速入门教程。" + +#: ../../source/ref-changelog.md:230 +msgid "" +"**Introduce new end-to-end testing infrastructure** " +"([#1842](https://github.com/adap/flower/pull/1842), " +"[#2071](https://github.com/adap/flower/pull/2071), " +"[#2072](https://github.com/adap/flower/pull/2072), " +"[#2068](https://github.com/adap/flower/pull/2068), " +"[#2067](https://github.com/adap/flower/pull/2067), " +"[#2069](https://github.com/adap/flower/pull/2069), " +"[#2073](https://github.com/adap/flower/pull/2073), " +"[#2070](https://github.com/adap/flower/pull/2070), " +"[#2074](https://github.com/adap/flower/pull/2074), " +"[#2082](https://github.com/adap/flower/pull/2082), " +"[#2084](https://github.com/adap/flower/pull/2084), " +"[#2093](https://github.com/adap/flower/pull/2093), " +"[#2109](https://github.com/adap/flower/pull/2109), " +"[#2095](https://github.com/adap/flower/pull/2095), " +"[#2140](https://github.com/adap/flower/pull/2140), " +"[#2137](https://github.com/adap/flower/pull/2137), " +"[#2165](https://github.com/adap/flower/pull/2165))" msgstr "" "*介绍新的端到端测试** ([#1842](https://github.com/adap/flower/pull/1842), " -"[#2071](https://github.com/adap/flower/pull/2071), [#2072](https://github." -"com/adap/flower/pull/2072), [#2068](https://github.com/adap/flower/pull/2068)" -", [#2067](https://github.com/adap/flower/pull/2067), [#2069](https://github." -"com/adap/flower/pull/2069), [#2073](https://github.com/adap/flower/pull/2073)" -", [#2070](https://github.com/adap/flower/pull/2070), [#2074](https://github." -"com/adap/flower/pull/2074), [#2082](https://github.com/adap/flower/pull/2082)" -", [#2084](https://github.com/adap/flower/pull/2084), [#2093](https://github." -"com/adap/flower/pull/2093), [#2109](https://github.com/adap/flower/pull/2109)" -", [#2095](https://github.com/adap/flower/pull/2095), [#2140](https://github." -"com/adap/flower/pull/2140), [#2137](https://github.com/adap/flower/pull/2137)" -", [#2165](https://github.com/adap/flower/pull/2165))" - -#: ../../source/ref-changelog.md:105 -msgid "" -"A new testing infrastructure ensures that new changes stay compatible with " -"existing framework integrations or strategies." +"[#2071](https://github.com/adap/flower/pull/2071), " +"[#2072](https://github.com/adap/flower/pull/2072), " +"[#2068](https://github.com/adap/flower/pull/2068), " +"[#2067](https://github.com/adap/flower/pull/2067), " +"[#2069](https://github.com/adap/flower/pull/2069), " +"[#2073](https://github.com/adap/flower/pull/2073), " +"[#2070](https://github.com/adap/flower/pull/2070), " +"[#2074](https://github.com/adap/flower/pull/2074), " +"[#2082](https://github.com/adap/flower/pull/2082), " +"[#2084](https://github.com/adap/flower/pull/2084), " +"[#2093](https://github.com/adap/flower/pull/2093), " +"[#2109](https://github.com/adap/flower/pull/2109), " +"[#2095](https://github.com/adap/flower/pull/2095), " +"[#2140](https://github.com/adap/flower/pull/2140), " +"[#2137](https://github.com/adap/flower/pull/2137), " +"[#2165](https://github.com/adap/flower/pull/2165))" + +#: ../../source/ref-changelog.md:232 +msgid "" +"A new testing infrastructure ensures that new changes stay compatible " +"with existing framework integrations or strategies." msgstr "新的测试设施可确保新的变更与现有的框架集成或策略保持兼容。" -#: ../../source/ref-changelog.md:107 +#: ../../source/ref-changelog.md:234 msgid "**Deprecate Python 3.7**" msgstr "** 过时的 Python 3.7**" -#: ../../source/ref-changelog.md:109 +#: ../../source/ref-changelog.md:236 msgid "" -"Since Python 3.7 reached its end of life (EOL) on 2023-06-27, support for " -"Python 3.7 is now deprecated and will be removed in an upcoming release." -msgstr "" -"由于 Python 3.7 已于 2023-06-27 弃用 (EOL),对 Python 3.7 " -"的支持现已废弃,并将在即将发布的版本中移除。" +"Since Python 3.7 reached its end of life (EOL) on 2023-06-27, support for" +" Python 3.7 is now deprecated and will be removed in an upcoming release." +msgstr "由于 Python 3.7 已于 2023-06-27 弃用 (EOL),对 Python 3.7 的支持现已废弃,并将在即将发布的版本中移除。" -#: ../../source/ref-changelog.md:111 +#: ../../source/ref-changelog.md:238 msgid "" -"**Add new** `FedTrimmedAvg` **strategy** ([#1769](https://github.com/adap/" -"flower/pull/1769), [#1853](https://github.com/adap/flower/pull/1853))" +"**Add new** `FedTrimmedAvg` **strategy** " +"([#1769](https://github.com/adap/flower/pull/1769), " +"[#1853](https://github.com/adap/flower/pull/1853))" msgstr "" -"**添加新的**`FedTrimmedAvg`**策略**([#1769](https://github.com/adap/flower/" -"pull/1769), [#1853](https://github.com/adap/flower/pull/1853)" +"**添加新的**`FedTrimmedAvg`**策略**([#1769](https://github.com/adap/flower/pull/1769)," +" [#1853](https://github.com/adap/flower/pull/1853)" -#: ../../source/ref-changelog.md:113 +#: ../../source/ref-changelog.md:240 msgid "" -"The new `FedTrimmedAvg` strategy implements Trimmed Mean by [Dong Yin, 2018]" -"(https://arxiv.org/abs/1803.01498)." +"The new `FedTrimmedAvg` strategy implements Trimmed Mean by [Dong Yin, " +"2018](https://arxiv.org/abs/1803.01498)." msgstr "" -"新的 \"FedTrimmedAvg \"策略实现了[Dong Yin, 2018](https://arxiv.org/" -"abs/1803.01498)的 \"Trimmed Mean\"。" +"新的 \"FedTrimmedAvg \"策略实现了[Dong Yin, " +"2018](https://arxiv.org/abs/1803.01498)的 \"Trimmed Mean\"。" -#: ../../source/ref-changelog.md:115 +#: ../../source/ref-changelog.md:242 msgid "" -"**Introduce start_driver** ([#1697](https://github.com/adap/flower/" -"pull/1697))" -msgstr "" -"**引入 start_driver**([#1697](https://github.com/adap/flower/pull/1697))" +"**Introduce start_driver** " +"([#1697](https://github.com/adap/flower/pull/1697))" +msgstr "**引入 start_driver**([#1697](https://github.com/adap/flower/pull/1697))" -#: ../../source/ref-changelog.md:117 +#: ../../source/ref-changelog.md:244 msgid "" -"In addition to `start_server` and using the raw Driver API, there is a new " -"`start_driver` function that allows for running `start_server` scripts as a " -"Flower driver with only a single-line code change. Check out the `mt-" -"pytorch` code example to see a working example using `start_driver`." +"In addition to `start_server` and using the raw Driver API, there is a " +"new `start_driver` function that allows for running `start_server` " +"scripts as a Flower driver with only a single-line code change. Check out" +" the `mt-pytorch` code example to see a working example using " +"`start_driver`." msgstr "" -"除了 `start_server` 和使用原始驱动 API 之外,还有一个新的 `start_driver` 函" -"数,只需修改一行代码,就能将 `start_server` 脚本作为 Flower 驱动程序运行。请" -"查看 `mt-pytorch` 代码示例,了解使用 `start_driver` 的工作示例。" +"除了 `start_server` 和使用原始驱动 API 之外,还有一个新的 `start_driver` 函数,只需修改一行代码,就能将 " +"`start_server` 脚本作为 Flower 驱动程序运行。请查看 `mt-pytorch` 代码示例,了解使用 " +"`start_driver` 的工作示例。" -#: ../../source/ref-changelog.md:119 +#: ../../source/ref-changelog.md:246 msgid "" -"**Add parameter aggregation to** `mt-pytorch` **code example** ([#1785]" -"(https://github.com/adap/flower/pull/1785))" +"**Add parameter aggregation to** `mt-pytorch` **code example** " +"([#1785](https://github.com/adap/flower/pull/1785))" msgstr "" -"为 `mt-pytorch` **代码示例**添加参数聚合 ([#1785](https://github.com/adap/" -"flower/pull/1785))" +"为 `mt-pytorch` **代码示例**添加参数聚合 " +"([#1785](https://github.com/adap/flower/pull/1785))" -#: ../../source/ref-changelog.md:121 +#: ../../source/ref-changelog.md:248 msgid "" -"The `mt-pytorch` example shows how to aggregate parameters when writing a " -"driver script. The included `driver.py` and `server.py` have been aligned to " -"demonstrate both the low-level way and the high-level way of building server-" -"side logic." +"The `mt-pytorch` example shows how to aggregate parameters when writing a" +" driver script. The included `driver.py` and `server.py` have been " +"aligned to demonstrate both the low-level way and the high-level way of " +"building server-side logic." msgstr "" -"`mt-pytorch`示例展示了如何在编写驱动程序脚本时聚合参数。附带的 `driver.py` " -"和 `server.py` 已经进行了调整,以演示构建服务器端逻辑的低级方法和高级方法。" +"`mt-pytorch`示例展示了如何在编写驱动程序脚本时聚合参数。附带的 `driver.py` 和 `server.py` " +"已经进行了调整,以演示构建服务器端逻辑的低级方法和高级方法。" -#: ../../source/ref-changelog.md:123 +#: ../../source/ref-changelog.md:250 msgid "" -"**Migrate experimental REST API to Starlette** ([2171](https://github.com/" -"adap/flower/pull/2171))" +"**Migrate experimental REST API to Starlette** " +"([2171](https://github.com/adap/flower/pull/2171))" msgstr "" -"**将实验性 REST API 移植到 Starlette** ([2171](https://github.com/adap/" -"flower/pull/2171))" +"**将实验性 REST API 移植到 Starlette** " +"([2171](https://github.com/adap/flower/pull/2171))" -#: ../../source/ref-changelog.md:125 +#: ../../source/ref-changelog.md:252 msgid "" -"The (experimental) REST API used to be implemented in [FastAPI](https://" -"fastapi.tiangolo.com/), but it has now been migrated to use [Starlette]" -"(https://www.starlette.io/) directly." +"The (experimental) REST API used to be implemented in " +"[FastAPI](https://fastapi.tiangolo.com/), but it has now been migrated to" +" use [Starlette](https://www.starlette.io/) directly." msgstr "" -"REST API(试验性)曾在 [FastAPI](https://fastapi.tiangolo.com/) 中实现,但现" -"在已迁移到直接使用 [Starlette](https://www.starlette.io/) 。" +"REST API(试验性)曾在 [FastAPI](https://fastapi.tiangolo.com/) 中实现,但现在已迁移到直接使用 " +"[Starlette](https://www.starlette.io/) 。" -#: ../../source/ref-changelog.md:127 +#: ../../source/ref-changelog.md:254 msgid "" -"Please note: The REST request-response API is still experimental and will " -"likely change significantly over time." -msgstr "" -"请注意:REST 请求-响应 API 仍处于试验阶段,随着时间的推移可能会发生重大变化。" +"Please note: The REST request-response API is still experimental and will" +" likely change significantly over time." +msgstr "请注意:REST 请求-响应 API 仍处于试验阶段,随着时间的推移可能会发生重大变化。" -#: ../../source/ref-changelog.md:129 +#: ../../source/ref-changelog.md:256 msgid "" -"**Introduce experimental gRPC request-response API** ([#1867](https://github." -"com/adap/flower/pull/1867), [#1901](https://github.com/adap/flower/" -"pull/1901))" +"**Introduce experimental gRPC request-response API** " +"([#1867](https://github.com/adap/flower/pull/1867), " +"[#1901](https://github.com/adap/flower/pull/1901))" msgstr "" -"**引入实验性 gRPC 请求-响应 API** ([#1867](https://github.com/adap/flower/" -"pull/1867), [#1901](https://github.com/adap/flower/pull/1901)" +"**引入实验性 gRPC 请求-响应 API** " +"([#1867](https://github.com/adap/flower/pull/1867), " +"[#1901](https://github.com/adap/flower/pull/1901)" -#: ../../source/ref-changelog.md:131 +#: ../../source/ref-changelog.md:258 msgid "" -"In addition to the existing gRPC API (based on bidirectional streaming) and " -"the experimental REST API, there is now a new gRPC API that uses a request-" -"response model to communicate with client nodes." +"In addition to the existing gRPC API (based on bidirectional streaming) " +"and the experimental REST API, there is now a new gRPC API that uses a " +"request-response model to communicate with client nodes." msgstr "" -"除了现有的 gRPC 应用程序接口(基于双向流)和试验性 REST 应用程序接口外,现在" -"还有一个新的 gRPC 应用程序接口,它使用请求-响应模型与客户端节点通信。" +"除了现有的 gRPC 应用程序接口(基于双向流)和试验性 REST 应用程序接口外,现在还有一个新的 gRPC " +"应用程序接口,它使用请求-响应模型与客户端节点通信。" -#: ../../source/ref-changelog.md:133 +#: ../../source/ref-changelog.md:260 msgid "" -"Please note: The gRPC request-response API is still experimental and will " -"likely change significantly over time." -msgstr "" -"请注意:gRPC 请求-响应 API 仍处于试验阶段,随着时间的推移可能会发生重大变化。" +"Please note: The gRPC request-response API is still experimental and will" +" likely change significantly over time." +msgstr "请注意:gRPC 请求-响应 API 仍处于试验阶段,随着时间的推移可能会发生重大变化。" -#: ../../source/ref-changelog.md:135 +#: ../../source/ref-changelog.md:262 msgid "" "**Replace the experimental** `start_client(rest=True)` **with the new** " -"`start_client(transport=\"rest\")` ([#1880](https://github.com/adap/flower/" -"pull/1880))" +"`start_client(transport=\"rest\")` " +"([#1880](https://github.com/adap/flower/pull/1880))" msgstr "" "**用新的** `start_client(transport=\"rest\")` 替换实验性** " -"`start_client(rest=True)` ([#1880](https://github.com/adap/flower/pull/1880))" +"`start_client(rest=True)` " +"([#1880](https://github.com/adap/flower/pull/1880))" -#: ../../source/ref-changelog.md:137 +#: ../../source/ref-changelog.md:264 msgid "" -"The (experimental) `start_client` argument `rest` was deprecated in favour " -"of a new argument `transport`. `start_client(transport=\"rest\")` will yield " -"the same behaviour as `start_client(rest=True)` did before. All code should " -"migrate to the new argument `transport`. The deprecated argument `rest` will " -"be removed in a future release." +"The (experimental) `start_client` argument `rest` was deprecated in " +"favour of a new argument `transport`. `start_client(transport=\"rest\")` " +"will yield the same behaviour as `start_client(rest=True)` did before. " +"All code should migrate to the new argument `transport`. The deprecated " +"argument `rest` will be removed in a future release." msgstr "" -"已废弃(试验性的)`start_client`参数`rest`,改用新参数`transport`。" -"`start_client(transport=\"rest\")`将产生与以前的`start_client(rest=True)`相同" -"的行为。所有代码都应迁移到新参数 `transport`。过时的参数 `rest` 将在今后的版" -"本中删除。" +"已废弃(试验性的)`start_client`参数`rest`,改用新参数`transport`。`start_client(transport=\"rest\")`将产生与以前的`start_client(rest=True)`相同的行为。所有代码都应迁移到新参数" +" `transport`。过时的参数 `rest` 将在今后的版本中删除。" -#: ../../source/ref-changelog.md:139 +#: ../../source/ref-changelog.md:266 msgid "" -"**Add a new gRPC option** ([#2197](https://github.com/adap/flower/pull/2197))" -msgstr "" -"** 添加一个新的 gRPC 选项**([#2197](https://github.com/adap/flower/" -"pull/2197))" +"**Add a new gRPC option** " +"([#2197](https://github.com/adap/flower/pull/2197))" +msgstr "** 添加一个新的 gRPC 选项**([#2197](https://github.com/adap/flower/pull/2197))" -#: ../../source/ref-changelog.md:141 +#: ../../source/ref-changelog.md:268 msgid "" -"We now start a gRPC server with the `grpc.keepalive_permit_without_calls` " -"option set to 0 by default. This prevents the clients from sending keepalive " -"pings when there is no outstanding stream." +"We now start a gRPC server with the `grpc.keepalive_permit_without_calls`" +" option set to 0 by default. This prevents the clients from sending " +"keepalive pings when there is no outstanding stream." msgstr "" -"现在我们启动一个 gRPC 服务器,并将 `grpc.keepalive_permit_without_calls` " -"选项默认设置为 0。这将防止客户端在没有未处理数据流时发送 keepalive pings。" +"现在我们启动一个 gRPC 服务器,并将 `grpc.keepalive_permit_without_calls` 选项默认设置为 " +"0。这将防止客户端在没有未处理数据流时发送 keepalive pings。" -#: ../../source/ref-changelog.md:143 +#: ../../source/ref-changelog.md:270 msgid "" -"**Improve example notebooks** ([#2005](https://github.com/adap/flower/" -"pull/2005))" +"**Improve example notebooks** " +"([#2005](https://github.com/adap/flower/pull/2005))" msgstr "**改进示例笔记** ([#2005](https://github.com/adap/flower/pull/2005))" -#: ../../source/ref-changelog.md:145 +#: ../../source/ref-changelog.md:272 msgid "There's a new 30min Federated Learning PyTorch tutorial!" msgstr "有一个新的 30 分钟的联邦学习 PyTorch 教程!" -#: ../../source/ref-changelog.md:147 +#: ../../source/ref-changelog.md:274 msgid "" "**Example updates** ([#1772](https://github.com/adap/flower/pull/1772), " -"[#1873](https://github.com/adap/flower/pull/1873), [#1981](https://github." -"com/adap/flower/pull/1981), [#1988](https://github.com/adap/flower/" -"pull/1988), [#1984](https://github.com/adap/flower/pull/1984), [#1982]" -"(https://github.com/adap/flower/pull/1982), [#2112](https://github.com/adap/" -"flower/pull/2112), [#2144](https://github.com/adap/flower/pull/2144), [#2174]" -"(https://github.com/adap/flower/pull/2174), [#2225](https://github.com/adap/" -"flower/pull/2225), [#2183](https://github.com/adap/flower/pull/2183))" +"[#1873](https://github.com/adap/flower/pull/1873), " +"[#1981](https://github.com/adap/flower/pull/1981), " +"[#1988](https://github.com/adap/flower/pull/1988), " +"[#1984](https://github.com/adap/flower/pull/1984), " +"[#1982](https://github.com/adap/flower/pull/1982), " +"[#2112](https://github.com/adap/flower/pull/2112), " +"[#2144](https://github.com/adap/flower/pull/2144), " +"[#2174](https://github.com/adap/flower/pull/2174), " +"[#2225](https://github.com/adap/flower/pull/2225), " +"[#2183](https://github.com/adap/flower/pull/2183))" msgstr "" "**更新Example** ([#1772](https://github.com/adap/flower/pull/1772), " -"[#1873](https://github.com/adap/flower/pull/1873), [#1981](https://github." -"com/adap/flower/pull/1981), [#1988](https://github.com/adap/flower/pull/1988)" -", [#1984](https://github.com/adap/flower/pull/1984), [#1982](https://github." -"com/adap/flower/pull/1982), [#2112](https://github.com/adap/flower/pull/2112)" -", [#2144](https://github.com/adap/flower/pull/2144), [#2174](https://github." -"com/adap/flower/pull/2174), [#2225](https://github.com/adap/flower/pull/2225)" -", [#2183](https://github.com/adap/flower/pull/2183))" - -#: ../../source/ref-changelog.md:149 +"[#1873](https://github.com/adap/flower/pull/1873), " +"[#1981](https://github.com/adap/flower/pull/1981), " +"[#1988](https://github.com/adap/flower/pull/1988), " +"[#1984](https://github.com/adap/flower/pull/1984), " +"[#1982](https://github.com/adap/flower/pull/1982), " +"[#2112](https://github.com/adap/flower/pull/2112), " +"[#2144](https://github.com/adap/flower/pull/2144), " +"[#2174](https://github.com/adap/flower/pull/2174), " +"[#2225](https://github.com/adap/flower/pull/2225), " +"[#2183](https://github.com/adap/flower/pull/2183))" + +#: ../../source/ref-changelog.md:276 msgid "" "Many examples have received significant updates, including simplified " "advanced-tensorflow and advanced-pytorch examples, improved macOS " -"compatibility of TensorFlow examples, and code examples for simulation. A " -"major upgrade is that all code examples now have a `requirements.txt` (in " -"addition to `pyproject.toml`)." +"compatibility of TensorFlow examples, and code examples for simulation. A" +" major upgrade is that all code examples now have a `requirements.txt` " +"(in addition to `pyproject.toml`)." msgstr "" -"许多示例都进行了重大更新,包括简化了 advanced-tensorflow 和 advanced-pytorch " -"示例,改进了 TensorFlow 示例的 macOS 兼容性,以及模拟代码示例。" -"一项重大升级是所有代码示例现在都有了 \"requirements.txt\"(除 \"pyproject." -"toml \"外)。" +"许多示例都进行了重大更新,包括简化了 advanced-tensorflow 和 advanced-pytorch 示例,改进了 " +"TensorFlow 示例的 macOS 兼容性,以及模拟代码示例。一项重大升级是所有代码示例现在都有了 " +"\"requirements.txt\"(除 \"pyproject.toml \"外)。" -#: ../../source/ref-changelog.md:151 +#: ../../source/ref-changelog.md:278 msgid "" -"**General improvements** ([#1872](https://github.com/adap/flower/pull/1872), " -"[#1866](https://github.com/adap/flower/pull/1866), [#1884](https://github." -"com/adap/flower/pull/1884), [#1837](https://github.com/adap/flower/" -"pull/1837), [#1477](https://github.com/adap/flower/pull/1477), [#2171]" -"(https://github.com/adap/flower/pull/2171))" +"**General improvements** " +"([#1872](https://github.com/adap/flower/pull/1872), " +"[#1866](https://github.com/adap/flower/pull/1866), " +"[#1884](https://github.com/adap/flower/pull/1884), " +"[#1837](https://github.com/adap/flower/pull/1837), " +"[#1477](https://github.com/adap/flower/pull/1477), " +"[#2171](https://github.com/adap/flower/pull/2171))" msgstr "" "**普通改进**([#1872](https://github.com/adap/flower/pull/1872), " -"[#1866](https://github.com/adap/flower/pull/1866), [#1884](https://github." -"com/adap/flower/pull/1884), [#1837](https://github.com/adap/flower/pull/1837)" -", [#1477](https://github.com/adap/flower/pull/1477), [#2171](https://github." -"com/adap/flower/pull/2171))" - -#: ../../source/ref-changelog.md:157 ../../source/ref-changelog.md:221 -#: ../../source/ref-changelog.md:279 ../../source/ref-changelog.md:348 -#: ../../source/ref-changelog.md:410 +"[#1866](https://github.com/adap/flower/pull/1866), " +"[#1884](https://github.com/adap/flower/pull/1884), " +"[#1837](https://github.com/adap/flower/pull/1837), " +"[#1477](https://github.com/adap/flower/pull/1477), " +"[#2171](https://github.com/adap/flower/pull/2171))" + +#: ../../source/ref-changelog.md:284 ../../source/ref-changelog.md:348 +#: ../../source/ref-changelog.md:406 ../../source/ref-changelog.md:475 +#: ../../source/ref-changelog.md:537 msgid "None" msgstr "无" -#: ../../source/ref-changelog.md:159 +#: ../../source/ref-changelog.md:286 msgid "v1.4.0 (2023-04-21)" msgstr "v1.4.0 (2023-04-21)" -#: ../../source/ref-changelog.md:165 +#: ../../source/ref-changelog.md:292 msgid "" "`Adam Narozniak`, `Alexander Viala Bellander`, `Charles Beauville`, " -"`Chenyang Ma (Danny)`, `Daniel J. Beutel`, `Edoardo`, `Gautam Jajoo`, `Iacob-" -"Alexandru-Andrei`, `JDRanpariya`, `Jean Charle Yaacoub`, `Kunal Sarkhel`, " -"`L. Jiang`, `Lennart Behme`, `Max Kapsecker`, `Michał`, `Nic Lane`, " -"`Nikolaos Episkopos`, `Ragy`, `Saurav Maheshkar`, `Semo Yang`, `Steve " -"Laskaridis`, `Steven Hé (Sīchàng)`, `Taner Topal`" -msgstr "" -"`Adam Narozniak`, `Alexander Viala Bellander`, `Charles Beauville`, `" -"Chenyang Ma (Danny)`, `Daniel J. Beutel`, `Edoardo`, `Gautam Jajoo`, `Iacob-" -"Alexandru-Andrei`, `JDRanpariya`, `Jean Charle Yaacoub`, `Kunal Sarkhel`, `" -"L. Jiang`, `Lennart Behme`, `Max Kapsecker`, `Michał`, `Nic Lane`, `Nikolaos " -"Episkopos`, `Ragy`, `Saurav Maheshkar`, `Semo Yang`, `Steve Laskaridis`, `" -"Steven Hé (Sīchàng)`, `Taner Topal`" - -#: ../../source/ref-changelog.md:169 -msgid "" -"**Introduce support for XGBoost (**`FedXgbNnAvg` **strategy and example)** " -"([#1694](https://github.com/adap/flower/pull/1694), [#1709](https://github." -"com/adap/flower/pull/1709), [#1715](https://github.com/adap/flower/" -"pull/1715), [#1717](https://github.com/adap/flower/pull/1717), [#1763]" -"(https://github.com/adap/flower/pull/1763), [#1795](https://github.com/adap/" -"flower/pull/1795))" -msgstr "" -"**引入对XGBoost的支持(**`FedXgbNnAvg` **策略和示例)** ([#1694](https://" -"github.com/adap/flower/pull/1694), [#1709](https://github.com/adap/flower/" -"pull/1709), [#1715](https://github.com/adap/flower/pull/1715), [#1717]" -"(https://github.com/adap/flower/pull/1717), [#1763](https://github.com/adap/" -"flower/pull/1763), [#1795](https://github.com/adap/flower/pull/1795))" - -#: ../../source/ref-changelog.md:171 +"`Chenyang Ma (Danny)`, `Daniel J. Beutel`, `Edoardo`, `Gautam Jajoo`, " +"`Iacob-Alexandru-Andrei`, `JDRanpariya`, `Jean Charle Yaacoub`, `Kunal " +"Sarkhel`, `L. Jiang`, `Lennart Behme`, `Max Kapsecker`, `Michał`, `Nic " +"Lane`, `Nikolaos Episkopos`, `Ragy`, `Saurav Maheshkar`, `Semo Yang`, " +"`Steve Laskaridis`, `Steven Hé (Sīchàng)`, `Taner Topal`" +msgstr "" +"`Adam Narozniak`, `Alexander Viala Bellander`, `Charles Beauville`, " +"`Chenyang Ma (Danny)`, `Daniel J. Beutel`, `Edoardo`, `Gautam Jajoo`, " +"`Iacob-Alexandru-Andrei`, `JDRanpariya`, `Jean Charle Yaacoub`, `Kunal " +"Sarkhel`, `L. Jiang`, `Lennart Behme`, `Max Kapsecker`, `Michał`, `Nic " +"Lane`, `Nikolaos Episkopos`, `Ragy`, `Saurav Maheshkar`, `Semo Yang`, " +"`Steve Laskaridis`, `Steven Hé (Sīchàng)`, `Taner Topal`" + +#: ../../source/ref-changelog.md:296 +msgid "" +"**Introduce support for XGBoost (**`FedXgbNnAvg` **strategy and " +"example)** ([#1694](https://github.com/adap/flower/pull/1694), " +"[#1709](https://github.com/adap/flower/pull/1709), " +"[#1715](https://github.com/adap/flower/pull/1715), " +"[#1717](https://github.com/adap/flower/pull/1717), " +"[#1763](https://github.com/adap/flower/pull/1763), " +"[#1795](https://github.com/adap/flower/pull/1795))" +msgstr "" +"**引入对XGBoost的支持(**`FedXgbNnAvg` **策略和示例)** " +"([#1694](https://github.com/adap/flower/pull/1694), " +"[#1709](https://github.com/adap/flower/pull/1709), " +"[#1715](https://github.com/adap/flower/pull/1715), " +"[#1717](https://github.com/adap/flower/pull/1717), " +"[#1763](https://github.com/adap/flower/pull/1763), " +"[#1795](https://github.com/adap/flower/pull/1795))" + +#: ../../source/ref-changelog.md:298 msgid "" "XGBoost is a tree-based ensemble machine learning algorithm that uses " -"gradient boosting to improve model accuracy. We added a new `FedXgbNnAvg` " -"[strategy](https://github.com/adap/flower/tree/main/src/py/flwr/server/" -"strategy/fedxgb_nn_avg.py), and a [code example](https://github.com/adap/" -"flower/tree/main/examples/quickstart_xgboost_horizontal) that demonstrates " -"the usage of this new strategy in an XGBoost project." +"gradient boosting to improve model accuracy. We added a new `FedXgbNnAvg`" +" " +"[strategy](https://github.com/adap/flower/tree/main/src/py/flwr/server/strategy/fedxgb_nn_avg.py)," +" and a [code " +"example](https://github.com/adap/flower/tree/main/examples/quickstart_xgboost_horizontal)" +" that demonstrates the usage of this new strategy in an XGBoost project." msgstr "" -"XGBoost 是一种基于树的集合机器学习算法,它使用梯度提升来提高模型的准确性。我" -"们添加了一个新的 \"FedXgbNnAvg\"[策略](https://github.com/adap/flower/tree/" -"main/src/py/flwr/server/strategy/fedxgb_nn_avg.py)和一个[代码示例](https://" -"github.com/adap/flower/tree/main/examples/quickstart_xgboost_horizontal),演" -"示如何在 XGBoost 项目中使用这个新策略。" +"XGBoost 是一种基于树的集合机器学习算法,它使用梯度提升来提高模型的准确性。我们添加了一个新的 " +"\"FedXgbNnAvg\"[策略](https://github.com/adap/flower/tree/main/src/py/flwr/server/strategy/fedxgb_nn_avg.py)和一个[代码示例](https://github.com/adap/flower/tree/main/examples/quickstart_xgboost_horizontal),演示如何在" +" XGBoost 项目中使用这个新策略。" -#: ../../source/ref-changelog.md:173 +#: ../../source/ref-changelog.md:300 msgid "" -"**Introduce iOS SDK (preview)** ([#1621](https://github.com/adap/flower/" -"pull/1621), [#1764](https://github.com/adap/flower/pull/1764))" +"**Introduce iOS SDK (preview)** " +"([#1621](https://github.com/adap/flower/pull/1621), " +"[#1764](https://github.com/adap/flower/pull/1764))" msgstr "" -"**介绍 iOS SDK(预览版)** ([#1621](https://github.com/adap/flower/" -"pull/1621), [#1764](https://github.com/adap/flower/pull/1764))" +"**介绍 iOS SDK(预览版)** ([#1621](https://github.com/adap/flower/pull/1621), " +"[#1764](https://github.com/adap/flower/pull/1764))" -#: ../../source/ref-changelog.md:175 +#: ../../source/ref-changelog.md:302 msgid "" -"This is a major update for anyone wanting to implement Federated Learning on " -"iOS mobile devices. We now have a swift iOS SDK present under [src/swift/" -"flwr](https://github.com/adap/flower/tree/main/src/swift/flwr) that will " -"facilitate greatly the app creating process. To showcase its use, the [iOS " +"This is a major update for anyone wanting to implement Federated Learning" +" on iOS mobile devices. We now have a swift iOS SDK present under " +"[src/swift/flwr](https://github.com/adap/flower/tree/main/src/swift/flwr)" +" that will facilitate greatly the app creating process. To showcase its " +"use, the [iOS " "example](https://github.com/adap/flower/tree/main/examples/ios) has also " "been updated!" msgstr "" -"对于想要在 iOS 移动设备上实施联邦学习的人来说,这是一次重大更新。现在," -"我们在 [src/swift/flwr](https://github.com/adap/flower/tree/main/src/swift/" -"flwr) 下提供了一个迅捷的 iOS " -"SDK,这将大大方便应用程序的创建过程。为了展示其使用情况,我们还更新了 [iOS " +"对于想要在 iOS 移动设备上实施联邦学习的人来说,这是一次重大更新。现在,我们在 " +"[src/swift/flwr](https://github.com/adap/flower/tree/main/src/swift/flwr)" +" 下提供了一个迅捷的 iOS SDK,这将大大方便应用程序的创建过程。为了展示其使用情况,我们还更新了 [iOS " "示例](https://github.com/adap/flower/tree/main/examples/ios)!" -#: ../../source/ref-changelog.md:177 +#: ../../source/ref-changelog.md:304 msgid "" -"**Introduce new \"What is Federated Learning?\" tutorial** ([#1657](https://" -"github.com/adap/flower/pull/1657), [#1721](https://github.com/adap/flower/" -"pull/1721))" +"**Introduce new \"What is Federated Learning?\" tutorial** " +"([#1657](https://github.com/adap/flower/pull/1657), " +"[#1721](https://github.com/adap/flower/pull/1721))" msgstr "" -"**引入新的 \"什么是联邦学习?\"教程**([#1657](https://github.com/adap/" -"flower/pull/1657), [#1721](https://github.com/adap/flower/pull/1721)" +"**引入新的 " +"\"什么是联邦学习?\"教程**([#1657](https://github.com/adap/flower/pull/1657), " +"[#1721](https://github.com/adap/flower/pull/1721)" -#: ../../source/ref-changelog.md:179 +#: ../../source/ref-changelog.md:306 msgid "" -"A new [entry-level tutorial](https://flower.dev/docs/framework/tutorial-what-" -"is-federated-learning.html) in our documentation explains the basics of " -"Fedetated Learning. It enables anyone who's unfamiliar with Federated " -"Learning to start their journey with Flower. Forward it to anyone who's " +"A new [entry-level tutorial](https://flower.dev/docs/framework/tutorial-" +"what-is-federated-learning.html) in our documentation explains the basics" +" of Fedetated Learning. It enables anyone who's unfamiliar with Federated" +" Learning to start their journey with Flower. Forward it to anyone who's " "interested in Federated Learning!" msgstr "" -"我们的文档中新增了一个[入门级教程](https://flower.dev/docs/framework/" -"tutorial-what-is-federated-learning.html),解释了联邦学习的基础知识。" -"它让任何不熟悉联邦学习的人都能开始 Flower " +"我们的文档中新增了一个[入门级教程](https://flower.dev/docs/framework/tutorial-what-is-" +"federated-learning.html),解释了联邦学习的基础知识。它让任何不熟悉联邦学习的人都能开始 Flower " "之旅。请转发给对联邦学习感兴趣的人!" -#: ../../source/ref-changelog.md:181 +#: ../../source/ref-changelog.md:308 msgid "" -"**Introduce new Flower Baseline: FedProx MNIST** ([#1513](https://github.com/" -"adap/flower/pull/1513), [#1680](https://github.com/adap/flower/pull/1680), " -"[#1681](https://github.com/adap/flower/pull/1681), [#1679](https://github." -"com/adap/flower/pull/1679))" +"**Introduce new Flower Baseline: FedProx MNIST** " +"([#1513](https://github.com/adap/flower/pull/1513), " +"[#1680](https://github.com/adap/flower/pull/1680), " +"[#1681](https://github.com/adap/flower/pull/1681), " +"[#1679](https://github.com/adap/flower/pull/1679))" msgstr "" -"**引入新的 Flower Baseline: FedProx MNIST** ([#1513](https://github.com/" -"adap/flower/pull/1513), [#1680](https://github.com/adap/flower/pull/1680), " -"[#1681](https://github.com/adap/flower/pull/1681), [#1679](https://github." -"com/adap/flower/pull/1679)" +"**引入新的 Flower Baseline: FedProx MNIST** " +"([#1513](https://github.com/adap/flower/pull/1513), " +"[#1680](https://github.com/adap/flower/pull/1680), " +"[#1681](https://github.com/adap/flower/pull/1681), " +"[#1679](https://github.com/adap/flower/pull/1679)" -#: ../../source/ref-changelog.md:183 +#: ../../source/ref-changelog.md:310 msgid "" -"This new baseline replicates the MNIST+CNN task from the paper [Federated " -"Optimization in Heterogeneous Networks (Li et al., 2018)](https://arxiv.org/" -"abs/1812.06127). It uses the `FedProx` strategy, which aims at making " -"convergence more robust in heterogenous settings." +"This new baseline replicates the MNIST+CNN task from the paper [Federated" +" Optimization in Heterogeneous Networks (Li et al., " +"2018)](https://arxiv.org/abs/1812.06127). It uses the `FedProx` strategy," +" which aims at making convergence more robust in heterogenous settings." msgstr "" -"这条新Baseline复现了论文[Federated Optimization in Heterogeneous Networks (" -"Li et al., 2018)](https://arxiv.org/abs/1812.06127)中的 MNIST+CNN 任务。" -"它使用 \"FedProx \"策略,旨在使收敛在异构环境中更加稳健。" +"这条新Baseline复现了论文[Federated Optimization in Heterogeneous Networks (Li et " +"al., 2018)](https://arxiv.org/abs/1812.06127)中的 MNIST+CNN 任务。它使用 " +"\"FedProx \"策略,旨在使收敛在异构环境中更加稳健。" -#: ../../source/ref-changelog.md:185 +#: ../../source/ref-changelog.md:312 msgid "" -"**Introduce new Flower Baseline: FedAvg FEMNIST** ([#1655](https://github." -"com/adap/flower/pull/1655))" +"**Introduce new Flower Baseline: FedAvg FEMNIST** " +"([#1655](https://github.com/adap/flower/pull/1655))" msgstr "" -"**引入新的 Flower Baseline: FedAvg FEMNIST** ([#1655](https://github.com/" -"adap/flower/pull/1655))" +"**引入新的 Flower Baseline: FedAvg FEMNIST** " +"([#1655](https://github.com/adap/flower/pull/1655))" -#: ../../source/ref-changelog.md:187 +#: ../../source/ref-changelog.md:314 msgid "" -"This new baseline replicates an experiment evaluating the performance of the " -"FedAvg algorithm on the FEMNIST dataset from the paper [LEAF: A Benchmark " -"for Federated Settings (Caldas et al., 2018)](https://arxiv.org/" -"abs/1812.01097)." +"This new baseline replicates an experiment evaluating the performance of " +"the FedAvg algorithm on the FEMNIST dataset from the paper [LEAF: A " +"Benchmark for Federated Settings (Caldas et al., " +"2018)](https://arxiv.org/abs/1812.01097)." msgstr "" -"这一新Baseline复现了论文[LEAF: A Benchmark for Federated Settings(Caldas " -"等人,2018 年)](https://arxiv.org/abs/1812.01097)中评估 FedAvg 算法在 " -"FEMNIST 数据集上性能的实验。" +"这一新Baseline复现了论文[LEAF: A Benchmark for Federated Settings(Caldas 等人,2018 " +"年)](https://arxiv.org/abs/1812.01097)中评估 FedAvg 算法在 FEMNIST 数据集上性能的实验。" -#: ../../source/ref-changelog.md:189 +#: ../../source/ref-changelog.md:316 msgid "" -"**Introduce (experimental) REST API** ([#1594](https://github.com/adap/" -"flower/pull/1594), [#1690](https://github.com/adap/flower/pull/1690), [#1695]" -"(https://github.com/adap/flower/pull/1695), [#1712](https://github.com/adap/" -"flower/pull/1712), [#1802](https://github.com/adap/flower/pull/1802), [#1770]" -"(https://github.com/adap/flower/pull/1770), [#1733](https://github.com/adap/" -"flower/pull/1733))" -msgstr "" -"**引入(试验性)REST API** ([#1594](https://github.com/adap/flower/" -"pull/1594), [#1690](https://github.com/adap/flower/pull/1690), [#1695]" -"(https://github.com/adap/flower/pull/1695), [#1712](https://github.com/adap/" -"flower/pull/1712), [#1802](https://github.com/adap/flower/pull/1802), [#1770]" -"(https://github.com/adap/flower/pull/1770), [#1733](https://github.com/adap/" -"flower/pull/1733))" +"**Introduce (experimental) REST API** " +"([#1594](https://github.com/adap/flower/pull/1594), " +"[#1690](https://github.com/adap/flower/pull/1690), " +"[#1695](https://github.com/adap/flower/pull/1695), " +"[#1712](https://github.com/adap/flower/pull/1712), " +"[#1802](https://github.com/adap/flower/pull/1802), " +"[#1770](https://github.com/adap/flower/pull/1770), " +"[#1733](https://github.com/adap/flower/pull/1733))" +msgstr "" +"**引入(试验性)REST API** ([#1594](https://github.com/adap/flower/pull/1594), " +"[#1690](https://github.com/adap/flower/pull/1690), " +"[#1695](https://github.com/adap/flower/pull/1695), " +"[#1712](https://github.com/adap/flower/pull/1712), " +"[#1802](https://github.com/adap/flower/pull/1802), " +"[#1770](https://github.com/adap/flower/pull/1770), " +"[#1733](https://github.com/adap/flower/pull/1733))" -#: ../../source/ref-changelog.md:191 +#: ../../source/ref-changelog.md:318 msgid "" "A new REST API has been introduced as an alternative to the gRPC-based " "communication stack. In this initial version, the REST API only supports " "anonymous clients." -msgstr "" -"作为基于 gRPC 的通信栈的替代方案,我们引入了新的 REST API。在初始版本中," -"REST API 仅支持匿名客户端。" +msgstr "作为基于 gRPC 的通信栈的替代方案,我们引入了新的 REST API。在初始版本中,REST API 仅支持匿名客户端。" -#: ../../source/ref-changelog.md:193 +#: ../../source/ref-changelog.md:320 msgid "" "Please note: The REST API is still experimental and will likely change " "significantly over time." msgstr "请注意:REST API 仍处于试验阶段,随着时间的推移可能会发生重大变化。" -#: ../../source/ref-changelog.md:195 +#: ../../source/ref-changelog.md:322 msgid "" -"**Improve the (experimental) Driver API** ([#1663](https://github.com/adap/" -"flower/pull/1663), [#1666](https://github.com/adap/flower/pull/1666), [#1667]" -"(https://github.com/adap/flower/pull/1667), [#1664](https://github.com/adap/" -"flower/pull/1664), [#1675](https://github.com/adap/flower/pull/1675), [#1676]" -"(https://github.com/adap/flower/pull/1676), [#1693](https://github.com/adap/" -"flower/pull/1693), [#1662](https://github.com/adap/flower/pull/1662), [#1794]" -"(https://github.com/adap/flower/pull/1794))" -msgstr "" -"**改进(试验性)驱动程序应用程序接口** ([#1663](https://github.com/adap/" -"flower/pull/1663), [#1666](https://github.com/adap/flower/pull/1666), [#1667]" -"(https://github.com/adap/flower/pull/1667), [#1664](https://github.com/adap/" -"flower/pull/1664), [#1675](https://github.com/adap/flower/pull/1675), [#1676]" -"(https://github.com/adap/flower/pull/1676), [#1693](https://github.com/adap/" -"flower/pull/1693), [#1662](https://github.com/adap/flower/pull/1662), [#1794]" -"(https://github.com/adap/flower/pull/1794))" +"**Improve the (experimental) Driver API** " +"([#1663](https://github.com/adap/flower/pull/1663), " +"[#1666](https://github.com/adap/flower/pull/1666), " +"[#1667](https://github.com/adap/flower/pull/1667), " +"[#1664](https://github.com/adap/flower/pull/1664), " +"[#1675](https://github.com/adap/flower/pull/1675), " +"[#1676](https://github.com/adap/flower/pull/1676), " +"[#1693](https://github.com/adap/flower/pull/1693), " +"[#1662](https://github.com/adap/flower/pull/1662), " +"[#1794](https://github.com/adap/flower/pull/1794))" +msgstr "" +"**改进(试验性)驱动程序应用程序接口** ([#1663](https://github.com/adap/flower/pull/1663)," +" [#1666](https://github.com/adap/flower/pull/1666), " +"[#1667](https://github.com/adap/flower/pull/1667), " +"[#1664](https://github.com/adap/flower/pull/1664), " +"[#1675](https://github.com/adap/flower/pull/1675), " +"[#1676](https://github.com/adap/flower/pull/1676), " +"[#1693](https://github.com/adap/flower/pull/1693), " +"[#1662](https://github.com/adap/flower/pull/1662), " +"[#1794](https://github.com/adap/flower/pull/1794))" -#: ../../source/ref-changelog.md:197 +#: ../../source/ref-changelog.md:324 msgid "" -"The Driver API is still an experimental feature, but this release introduces " -"some major upgrades. One of the main improvements is the introduction of an " -"SQLite database to store server state on disk (instead of in-memory). " -"Another improvement is that tasks (instructions or results) that have been " -"delivered will now be deleted. This greatly improves the memory efficiency " -"of a long-running Flower server." +"The Driver API is still an experimental feature, but this release " +"introduces some major upgrades. One of the main improvements is the " +"introduction of an SQLite database to store server state on disk (instead" +" of in-memory). Another improvement is that tasks (instructions or " +"results) that have been delivered will now be deleted. This greatly " +"improves the memory efficiency of a long-running Flower server." msgstr "" -"驱动程序应用程序接口(Driver API)仍是一项试验性功能,但这一版本引入了一些重" -"大升级。主要改进之一是引入了 SQLite 数据库,将服务器状态存储在磁盘上(而不是" -"内存中)。另一项改进是,已交付的任务(指令或结果)现在将被删除。这大大提高了" -"长期运行的 Flower 服务器的内存效率。" +"驱动程序应用程序接口(Driver API)仍是一项试验性功能,但这一版本引入了一些重大升级。主要改进之一是引入了 SQLite " +"数据库,将服务器状态存储在磁盘上(而不是内存中)。另一项改进是,已交付的任务(指令或结果)现在将被删除。这大大提高了长期运行的 Flower " +"服务器的内存效率。" -#: ../../source/ref-changelog.md:199 +#: ../../source/ref-changelog.md:326 msgid "" -"**Fix spilling issues related to Ray during simulations** ([#1698](https://" -"github.com/adap/flower/pull/1698))" -msgstr "" -"**修复模拟过程中与Ray有关的溢出问题** ([#1698](https://github.com/adap/" -"flower/pull/1698))" +"**Fix spilling issues related to Ray during simulations** " +"([#1698](https://github.com/adap/flower/pull/1698))" +msgstr "**修复模拟过程中与Ray有关的溢出问题** ([#1698](https://github.com/adap/flower/pull/1698))" -#: ../../source/ref-changelog.md:201 +#: ../../source/ref-changelog.md:328 msgid "" -"While running long simulations, `ray` was sometimes spilling huge amounts of " -"data that would make the training unable to continue. This is now fixed! 🎉" -msgstr "" -"在运行长时间模拟时,`ray` 有时会溢出大量数据,导致训练无法继续。现在这个问题" -"已经解决!🎉" +"While running long simulations, `ray` was sometimes spilling huge amounts" +" of data that would make the training unable to continue. This is now " +"fixed! 🎉" +msgstr "在运行长时间模拟时,`ray` 有时会溢出大量数据,导致训练无法继续。现在这个问题已经解决!🎉" -#: ../../source/ref-changelog.md:203 +#: ../../source/ref-changelog.md:330 msgid "" -"**Add new example using** `TabNet` **and Flower** ([#1725](https://github." -"com/adap/flower/pull/1725))" +"**Add new example using** `TabNet` **and Flower** " +"([#1725](https://github.com/adap/flower/pull/1725))" msgstr "" -"** 添加使用** `TabNet` ** 的新示例** ([#1725](https://github.com/adap/flower/" -"pull/1725))" +"** 添加使用** `TabNet` ** 的新示例** " +"([#1725](https://github.com/adap/flower/pull/1725))" -#: ../../source/ref-changelog.md:205 +#: ../../source/ref-changelog.md:332 msgid "" -"TabNet is a powerful and flexible framework for training machine learning " -"models on tabular data. We now have a federated example using Flower: " -"[https://github.com/adap/flower/tree/main/examples/tabnet](https://github." -"com/adap/flower/tree/main/examples/quickstart_tabnet)." +"TabNet is a powerful and flexible framework for training machine learning" +" models on tabular data. We now have a federated example using Flower: " +"[https://github.com/adap/flower/tree/main/examples/tabnet](https://github.com/adap/flower/tree/main/examples/quickstart_tabnet)." msgstr "" -"TabNet 是一个强大而灵活的框架,用于在表格数据上训练机器学习模型。" -"我们现在有一个使用 Flower 的联邦示例:[https://github.com/adap/flower/tree/" -"main/examples/tabnet](https://github.com/adap/flower/tree/main/examples/" -"quickstart_tabnet)。" +"TabNet 是一个强大而灵活的框架,用于在表格数据上训练机器学习模型。我们现在有一个使用 Flower " +"的联邦示例:[https://github.com/adap/flower/tree/main/examples/tabnet](https://github.com/adap/flower/tree/main/examples/quickstart_tabnet)。" -#: ../../source/ref-changelog.md:207 +#: ../../source/ref-changelog.md:334 msgid "" -"**Add new how-to guide for monitoring simulations** ([#1649](https://github." -"com/adap/flower/pull/1649))" -msgstr "" -"** 添加新的模拟监控指南** ([#1649](https://github.com/adap/flower/pull/1649))" +"**Add new how-to guide for monitoring simulations** " +"([#1649](https://github.com/adap/flower/pull/1649))" +msgstr "** 添加新的模拟监控指南** ([#1649](https://github.com/adap/flower/pull/1649))" -#: ../../source/ref-changelog.md:209 +#: ../../source/ref-changelog.md:336 msgid "" -"We now have a documentation guide to help users monitor their performance " -"during simulations." +"We now have a documentation guide to help users monitor their performance" +" during simulations." msgstr "我们现在有一份文档指南,可帮助用户在模拟过程中监控其性能。" -#: ../../source/ref-changelog.md:211 -msgid "" -"**Add training metrics to** `History` **object during simulations** ([#1696]" -"(https://github.com/adap/flower/pull/1696))" -msgstr "" -"**在模拟过程中为***`历史`***对象添加训练指标*** ([#1696](https://github.com/" -"adap/flower/pull/1696))" - -#: ../../source/ref-changelog.md:213 -msgid "" -"The `fit_metrics_aggregation_fn` can be used to aggregate training metrics, " -"but previous releases did not save the results in the `History` object. This " -"is now the case!" -msgstr "" -"`fit_metrics_aggregation_fn`可用于汇总训练指标,但以前的版本不会将结果保存在 " -"\"History \"对象中。现在可以了!" - -#: ../../source/ref-changelog.md:215 -msgid "" -"**General improvements** ([#1659](https://github.com/adap/flower/pull/1659), " -"[#1646](https://github.com/adap/flower/pull/1646), [#1647](https://github." -"com/adap/flower/pull/1647), [#1471](https://github.com/adap/flower/" -"pull/1471), [#1648](https://github.com/adap/flower/pull/1648), [#1651]" -"(https://github.com/adap/flower/pull/1651), [#1652](https://github.com/adap/" -"flower/pull/1652), [#1653](https://github.com/adap/flower/pull/1653), [#1659]" -"(https://github.com/adap/flower/pull/1659), [#1665](https://github.com/adap/" -"flower/pull/1665), [#1670](https://github.com/adap/flower/pull/1670), [#1672]" -"(https://github.com/adap/flower/pull/1672), [#1677](https://github.com/adap/" -"flower/pull/1677), [#1684](https://github.com/adap/flower/pull/1684), [#1683]" -"(https://github.com/adap/flower/pull/1683), [#1686](https://github.com/adap/" -"flower/pull/1686), [#1682](https://github.com/adap/flower/pull/1682), [#1685]" -"(https://github.com/adap/flower/pull/1685), [#1692](https://github.com/adap/" -"flower/pull/1692), [#1705](https://github.com/adap/flower/pull/1705), [#1708]" -"(https://github.com/adap/flower/pull/1708), [#1711](https://github.com/adap/" -"flower/pull/1711), [#1713](https://github.com/adap/flower/pull/1713), [#1714]" -"(https://github.com/adap/flower/pull/1714), [#1718](https://github.com/adap/" -"flower/pull/1718), [#1716](https://github.com/adap/flower/pull/1716), [#1723]" -"(https://github.com/adap/flower/pull/1723), [#1735](https://github.com/adap/" -"flower/pull/1735), [#1678](https://github.com/adap/flower/pull/1678), [#1750]" -"(https://github.com/adap/flower/pull/1750), [#1753](https://github.com/adap/" -"flower/pull/1753), [#1736](https://github.com/adap/flower/pull/1736), [#1766]" -"(https://github.com/adap/flower/pull/1766), [#1760](https://github.com/adap/" -"flower/pull/1760), [#1775](https://github.com/adap/flower/pull/1775), [#1776]" -"(https://github.com/adap/flower/pull/1776), [#1777](https://github.com/adap/" -"flower/pull/1777), [#1779](https://github.com/adap/flower/pull/1779), [#1784]" -"(https://github.com/adap/flower/pull/1784), [#1773](https://github.com/adap/" -"flower/pull/1773), [#1755](https://github.com/adap/flower/pull/1755), [#1789]" -"(https://github.com/adap/flower/pull/1789), [#1788](https://github.com/adap/" -"flower/pull/1788), [#1798](https://github.com/adap/flower/pull/1798), [#1799]" -"(https://github.com/adap/flower/pull/1799), [#1739](https://github.com/adap/" -"flower/pull/1739), [#1800](https://github.com/adap/flower/pull/1800), [#1804]" -"(https://github.com/adap/flower/pull/1804), [#1805](https://github.com/adap/" -"flower/pull/1805))" +#: ../../source/ref-changelog.md:338 +msgid "" +"**Add training metrics to** `History` **object during simulations** " +"([#1696](https://github.com/adap/flower/pull/1696))" +msgstr "" +"**在模拟过程中为***`历史`***对象添加训练指标*** " +"([#1696](https://github.com/adap/flower/pull/1696))" + +#: ../../source/ref-changelog.md:340 +msgid "" +"The `fit_metrics_aggregation_fn` can be used to aggregate training " +"metrics, but previous releases did not save the results in the `History` " +"object. This is now the case!" +msgstr "" +"`fit_metrics_aggregation_fn`可用于汇总训练指标,但以前的版本不会将结果保存在 \"History " +"\"对象中。现在可以了!" + +#: ../../source/ref-changelog.md:342 +msgid "" +"**General improvements** " +"([#1659](https://github.com/adap/flower/pull/1659), " +"[#1646](https://github.com/adap/flower/pull/1646), " +"[#1647](https://github.com/adap/flower/pull/1647), " +"[#1471](https://github.com/adap/flower/pull/1471), " +"[#1648](https://github.com/adap/flower/pull/1648), " +"[#1651](https://github.com/adap/flower/pull/1651), " +"[#1652](https://github.com/adap/flower/pull/1652), " +"[#1653](https://github.com/adap/flower/pull/1653), " +"[#1659](https://github.com/adap/flower/pull/1659), " +"[#1665](https://github.com/adap/flower/pull/1665), " +"[#1670](https://github.com/adap/flower/pull/1670), " +"[#1672](https://github.com/adap/flower/pull/1672), " +"[#1677](https://github.com/adap/flower/pull/1677), " +"[#1684](https://github.com/adap/flower/pull/1684), " +"[#1683](https://github.com/adap/flower/pull/1683), " +"[#1686](https://github.com/adap/flower/pull/1686), " +"[#1682](https://github.com/adap/flower/pull/1682), " +"[#1685](https://github.com/adap/flower/pull/1685), " +"[#1692](https://github.com/adap/flower/pull/1692), " +"[#1705](https://github.com/adap/flower/pull/1705), " +"[#1708](https://github.com/adap/flower/pull/1708), " +"[#1711](https://github.com/adap/flower/pull/1711), " +"[#1713](https://github.com/adap/flower/pull/1713), " +"[#1714](https://github.com/adap/flower/pull/1714), " +"[#1718](https://github.com/adap/flower/pull/1718), " +"[#1716](https://github.com/adap/flower/pull/1716), " +"[#1723](https://github.com/adap/flower/pull/1723), " +"[#1735](https://github.com/adap/flower/pull/1735), " +"[#1678](https://github.com/adap/flower/pull/1678), " +"[#1750](https://github.com/adap/flower/pull/1750), " +"[#1753](https://github.com/adap/flower/pull/1753), " +"[#1736](https://github.com/adap/flower/pull/1736), " +"[#1766](https://github.com/adap/flower/pull/1766), " +"[#1760](https://github.com/adap/flower/pull/1760), " +"[#1775](https://github.com/adap/flower/pull/1775), " +"[#1776](https://github.com/adap/flower/pull/1776), " +"[#1777](https://github.com/adap/flower/pull/1777), " +"[#1779](https://github.com/adap/flower/pull/1779), " +"[#1784](https://github.com/adap/flower/pull/1784), " +"[#1773](https://github.com/adap/flower/pull/1773), " +"[#1755](https://github.com/adap/flower/pull/1755), " +"[#1789](https://github.com/adap/flower/pull/1789), " +"[#1788](https://github.com/adap/flower/pull/1788), " +"[#1798](https://github.com/adap/flower/pull/1798), " +"[#1799](https://github.com/adap/flower/pull/1799), " +"[#1739](https://github.com/adap/flower/pull/1739), " +"[#1800](https://github.com/adap/flower/pull/1800), " +"[#1804](https://github.com/adap/flower/pull/1804), " +"[#1805](https://github.com/adap/flower/pull/1805))" msgstr "" "**普通改进** ([#1659](https://github.com/adap/flower/pull/1659), " -"[#1646](https://github.com/adap/flower/pull/1646), [#1647](https://github." -"com/adap/flower/pull/1647), [#1471](https://github.com/adap/flower/pull/1471)" -", [#1648](https://github.com/adap/flower/pull/1648), [#1651](https://github." -"com/adap/flower/pull/1651), [#1652](https://github.com/adap/flower/pull/1652)" -", [#1653](https://github.com/adap/flower/pull/1653), [#1659](https://github." -"com/adap/flower/pull/1659), [#1665](https://github.com/adap/flower/pull/1665)" -", [#1670](https://github.com/adap/flower/pull/1670), [#1672](https://github." -"com/adap/flower/pull/1672), [#1677](https://github.com/adap/flower/pull/1677)" -", [#1684](https://github.com/adap/flower/pull/1684), [#1683](https://github." -"com/adap/flower/pull/1683), [#1686](https://github.com/adap/flower/pull/1686)" -", [#1682](https://github.com/adap/flower/pull/1682), [#1685](https://github." -"com/adap/flower/pull/1685), [#1692](https://github.com/adap/flower/pull/1692)" -", [#1705](https://github.com/adap/flower/pull/1705), [#1708](https://github." -"com/adap/flower/pull/1708), [#1711](https://github.com/adap/flower/pull/1711)" -", [#1713](https://github.com/adap/flower/pull/1713), [#1714](https://github." -"com/adap/flower/pull/1714), [#1718](https://github.com/adap/flower/pull/1718)" -", [#1716](https://github.com/adap/flower/pull/1716), [#1723](https://github." -"com/adap/flower/pull/1723), [#1735](https://github.com/adap/flower/pull/1735)" -", [#1678](https://github.com/adap/flower/pull/1678), [#1750](https://github." -"com/adap/flower/pull/1750), [#1753](https://github.com/adap/flower/pull/1753)" -", [#1736](https://github.com/adap/flower/pull/1736), [#1766](https://github." -"com/adap/flower/pull/1766), [#1760](https://github.com/adap/flower/pull/1760)" -", [#1775](https://github.com/adap/flower/pull/1775), [#1776](https://github." -"com/adap/flower/pull/1776), [#1777](https://github.com/adap/flower/pull/1777)" -", [#1779](https://github.com/adap/flower/pull/1779), [#1784](https://github." -"com/adap/flower/pull/1784), [#1773](https://github.com/adap/flower/pull/1773)" -", [#1755](https://github.com/adap/flower/pull/1755), [#1789](https://github." -"com/adap/flower/pull/1789), [#1788](https://github.com/adap/flower/pull/1788)" -", [#1798](https://github.com/adap/flower/pull/1798), [#1799](https://github." -"com/adap/flower/pull/1799), [#1739](https://github.com/adap/flower/pull/1739)" -", [#1800](https://github.com/adap/flower/pull/1800), [#1804](https://github." -"com/adap/flower/pull/1804), [#1805](https://github.com/adap/flower/pull/" -"1805))" - -#: ../../source/ref-changelog.md:223 +"[#1646](https://github.com/adap/flower/pull/1646), " +"[#1647](https://github.com/adap/flower/pull/1647), " +"[#1471](https://github.com/adap/flower/pull/1471), " +"[#1648](https://github.com/adap/flower/pull/1648), " +"[#1651](https://github.com/adap/flower/pull/1651), " +"[#1652](https://github.com/adap/flower/pull/1652), " +"[#1653](https://github.com/adap/flower/pull/1653), " +"[#1659](https://github.com/adap/flower/pull/1659), " +"[#1665](https://github.com/adap/flower/pull/1665), " +"[#1670](https://github.com/adap/flower/pull/1670), " +"[#1672](https://github.com/adap/flower/pull/1672), " +"[#1677](https://github.com/adap/flower/pull/1677), " +"[#1684](https://github.com/adap/flower/pull/1684), " +"[#1683](https://github.com/adap/flower/pull/1683), " +"[#1686](https://github.com/adap/flower/pull/1686), " +"[#1682](https://github.com/adap/flower/pull/1682), " +"[#1685](https://github.com/adap/flower/pull/1685), " +"[#1692](https://github.com/adap/flower/pull/1692), " +"[#1705](https://github.com/adap/flower/pull/1705), " +"[#1708](https://github.com/adap/flower/pull/1708), " +"[#1711](https://github.com/adap/flower/pull/1711), " +"[#1713](https://github.com/adap/flower/pull/1713), " +"[#1714](https://github.com/adap/flower/pull/1714), " +"[#1718](https://github.com/adap/flower/pull/1718), " +"[#1716](https://github.com/adap/flower/pull/1716), " +"[#1723](https://github.com/adap/flower/pull/1723), " +"[#1735](https://github.com/adap/flower/pull/1735), " +"[#1678](https://github.com/adap/flower/pull/1678), " +"[#1750](https://github.com/adap/flower/pull/1750), " +"[#1753](https://github.com/adap/flower/pull/1753), " +"[#1736](https://github.com/adap/flower/pull/1736), " +"[#1766](https://github.com/adap/flower/pull/1766), " +"[#1760](https://github.com/adap/flower/pull/1760), " +"[#1775](https://github.com/adap/flower/pull/1775), " +"[#1776](https://github.com/adap/flower/pull/1776), " +"[#1777](https://github.com/adap/flower/pull/1777), " +"[#1779](https://github.com/adap/flower/pull/1779), " +"[#1784](https://github.com/adap/flower/pull/1784), " +"[#1773](https://github.com/adap/flower/pull/1773), " +"[#1755](https://github.com/adap/flower/pull/1755), " +"[#1789](https://github.com/adap/flower/pull/1789), " +"[#1788](https://github.com/adap/flower/pull/1788), " +"[#1798](https://github.com/adap/flower/pull/1798), " +"[#1799](https://github.com/adap/flower/pull/1799), " +"[#1739](https://github.com/adap/flower/pull/1739), " +"[#1800](https://github.com/adap/flower/pull/1800), " +"[#1804](https://github.com/adap/flower/pull/1804), " +"[#1805](https://github.com/adap/flower/pull/1805))" + +#: ../../source/ref-changelog.md:350 msgid "v1.3.0 (2023-02-06)" msgstr "v1.3.0 (2023-02-06)" -#: ../../source/ref-changelog.md:229 +#: ../../source/ref-changelog.md:356 msgid "" -"`Adam Narozniak`, `Alexander Viala Bellander`, `Charles Beauville`, `Daniel " -"J. Beutel`, `JDRanpariya`, `Lennart Behme`, `Taner Topal`" +"`Adam Narozniak`, `Alexander Viala Bellander`, `Charles Beauville`, " +"`Daniel J. Beutel`, `JDRanpariya`, `Lennart Behme`, `Taner Topal`" msgstr "" -"`Adam Narozniak`, `Alexander Viala Bellander`, `Charles Beauville`, `Daniel " -"J. Beutel`, `JDRanpariya`, `Lennart Behme`, `Taner Topal`" +"`Adam Narozniak`, `Alexander Viala Bellander`, `Charles Beauville`, " +"`Daniel J. Beutel`, `JDRanpariya`, `Lennart Behme`, `Taner Topal`" -#: ../../source/ref-changelog.md:233 +#: ../../source/ref-changelog.md:360 msgid "" "**Add support for** `workload_id` **and** `group_id` **in Driver API** " "([#1595](https://github.com/adap/flower/pull/1595))" msgstr "" -"**在驱动程序应用程序接口中添加对** `workload_id` **和** `group_id` **的支持**" -" ([#1595](https://github.com/adap/flower/pull/1595))" +"**在驱动程序应用程序接口中添加对** `workload_id` **和** `group_id` **的支持** " +"([#1595](https://github.com/adap/flower/pull/1595))" -#: ../../source/ref-changelog.md:235 +#: ../../source/ref-changelog.md:362 msgid "" -"The (experimental) Driver API now supports a `workload_id` that can be used " -"to identify which workload a task belongs to. It also supports a new " -"`group_id` that can be used, for example, to indicate the current training " -"round. Both the `workload_id` and `group_id` enable client nodes to decide " -"whether they want to handle a task or not." +"The (experimental) Driver API now supports a `workload_id` that can be " +"used to identify which workload a task belongs to. It also supports a new" +" `group_id` that can be used, for example, to indicate the current " +"training round. Both the `workload_id` and `group_id` enable client nodes" +" to decide whether they want to handle a task or not." msgstr "" -"驱动程序 API(试验性)现在支持 `workload_id`,可用于识别任务所属的工作量。" -"它还支持新的 `group_id`,例如,可用于指示当前的训练轮次。通过 `workload_id` " -"和 `group_id` 客户端节点可以决定是否要处理某个任务。" +"驱动程序 API(试验性)现在支持 `workload_id`,可用于识别任务所属的工作量。它还支持新的 " +"`group_id`,例如,可用于指示当前的训练轮次。通过 `workload_id` 和 `group_id` " +"客户端节点可以决定是否要处理某个任务。" -#: ../../source/ref-changelog.md:237 +#: ../../source/ref-changelog.md:364 msgid "" -"**Make Driver API and Fleet API address configurable** ([#1637](https://" -"github.com/adap/flower/pull/1637))" +"**Make Driver API and Fleet API address configurable** " +"([#1637](https://github.com/adap/flower/pull/1637))" msgstr "" -"**使Driver API 和Fleet API地址可配置**([#1637](https://github.com/adap/" -"flower/pull/1637))" +"**使Driver API 和Fleet " +"API地址可配置**([#1637](https://github.com/adap/flower/pull/1637))" -#: ../../source/ref-changelog.md:239 +#: ../../source/ref-changelog.md:366 msgid "" -"The (experimental) long-running Flower server (Driver API and Fleet API) can " -"now configure the server address of both Driver API (via `--driver-api-" -"address`) and Fleet API (via `--fleet-api-address`) when starting:" +"The (experimental) long-running Flower server (Driver API and Fleet API) " +"can now configure the server address of both Driver API (via `--driver-" +"api-address`) and Fleet API (via `--fleet-api-address`) when starting:" msgstr "" -"长期运行的 Flower 服务器(Driver API 和 Fleet API)现在可以在启动时配置 " -"Driver API(通过 `--driver-api-address`)和 Fleet API(通过 `-fleet-api-" -"address`)的服务器地址:" +"长期运行的 Flower 服务器(Driver API 和 Fleet API)现在可以在启动时配置 Driver API(通过 " +"`--driver-api-address`)和 Fleet API(通过 `-fleet-api-address`)的服务器地址:" -#: ../../source/ref-changelog.md:241 +#: ../../source/ref-changelog.md:368 +#, fuzzy msgid "" -"`flower-superlink --driver-api-address \"0.0.0.0:8081\" --fleet-api-address " +"`flower-server --driver-api-address \"0.0.0.0:8081\" --fleet-api-address " "\"0.0.0.0:8086\"`" msgstr "" -"`flower-server --driver-api-address \"0.0.0.0:8081\" --fleet-api-address \"0." -"0.0.0:8086\"`" +"`flower-server --driver-api-address \"0.0.0.0:8081\" --fleet-api-address " +"\"0.0.0.0:8086\"`" -#: ../../source/ref-changelog.md:243 +#: ../../source/ref-changelog.md:370 msgid "Both IPv4 and IPv6 addresses are supported." msgstr "支持 IPv4 和 IPv6 地址。" -#: ../../source/ref-changelog.md:245 +#: ../../source/ref-changelog.md:372 msgid "" -"**Add new example of Federated Learning using fastai and Flower** ([#1598]" -"(https://github.com/adap/flower/pull/1598))" +"**Add new example of Federated Learning using fastai and Flower** " +"([#1598](https://github.com/adap/flower/pull/1598))" msgstr "" -"** 添加使用 fastai 和 Flower 进行联邦学习的新示例** ([#1598](https://github." -"com/adap/flower/pull/1598))" +"** 添加使用 fastai 和 Flower 进行联邦学习的新示例** " +"([#1598](https://github.com/adap/flower/pull/1598))" -#: ../../source/ref-changelog.md:247 +#: ../../source/ref-changelog.md:374 msgid "" "A new code example (`quickstart_fastai`) demonstrates federated learning " "with [fastai](https://www.fast.ai/) and Flower. You can find it here: " -"[quickstart_fastai](https://github.com/adap/flower/tree/main/examples/" -"quickstart_fastai)." +"[quickstart_fastai](https://github.com/adap/flower/tree/main/examples/quickstart_fastai)." msgstr "" -"一个新的代码示例(`quickstart_fastai`)演示了使用 [fastai](https://www.fast." -"ai/) 和 Flower 的联邦学习。您可以在这里找到它: " -"[quickstart_fastai](https://github.com/adap/flower/tree/main/examples/" -"quickstart_fastai)。" +"一个新的代码示例(`quickstart_fastai`)演示了使用 [fastai](https://www.fast.ai/) 和 " +"Flower 的联邦学习。您可以在这里找到它: " +"[quickstart_fastai](https://github.com/adap/flower/tree/main/examples/quickstart_fastai)。" -#: ../../source/ref-changelog.md:249 +#: ../../source/ref-changelog.md:376 msgid "" -"**Make Android example compatible with** `flwr >= 1.0.0` **and the latest " -"versions of Android** ([#1603](https://github.com/adap/flower/pull/1603))" +"**Make Android example compatible with** `flwr >= 1.0.0` **and the latest" +" versions of Android** " +"([#1603](https://github.com/adap/flower/pull/1603))" msgstr "" -"**使安卓示例兼容** `flwr >= 1.0.0` **和最新版本的安卓** ([#1603](https://" -"github.com/adap/flower/pull/1603))" +"**使安卓示例兼容** `flwr >= 1.0.0` **和最新版本的安卓** " +"([#1603](https://github.com/adap/flower/pull/1603))" -#: ../../source/ref-changelog.md:251 +#: ../../source/ref-changelog.md:378 msgid "" -"The Android code example has received a substantial update: the project is " -"compatible with Flower 1.0 (and later), the UI received a full refresh, and " -"the project is updated to be compatible with newer Android tooling." +"The Android code example has received a substantial update: the project " +"is compatible with Flower 1.0 (and later), the UI received a full " +"refresh, and the project is updated to be compatible with newer Android " +"tooling." msgstr "" -"Android 代码示例已进行了大幅更新:项目兼容 Flower 1.0(及更高版本),用户界面" -"已全面刷新,项目已更新为兼容较新的 Android 工具。" +"Android 代码示例已进行了大幅更新:项目兼容 Flower 1.0(及更高版本),用户界面已全面刷新,项目已更新为兼容较新的 Android" +" 工具。" -#: ../../source/ref-changelog.md:253 +#: ../../source/ref-changelog.md:380 msgid "" -"**Add new `FedProx` strategy** ([#1619](https://github.com/adap/flower/" -"pull/1619))" -msgstr "**添加新的`FedProx`策略** ([#1619](https://github.com/adap/flower/pull/" -"1619))" +"**Add new `FedProx` strategy** " +"([#1619](https://github.com/adap/flower/pull/1619))" +msgstr "**添加新的`FedProx`策略** ([#1619](https://github.com/adap/flower/pull/1619))" -#: ../../source/ref-changelog.md:255 +#: ../../source/ref-changelog.md:382 msgid "" -"This [strategy](https://github.com/adap/flower/blob/main/src/py/flwr/server/" -"strategy/fedprox.py) is almost identical to [`FedAvg`](https://github.com/" -"adap/flower/blob/main/src/py/flwr/server/strategy/fedavg.py), but helps " -"users replicate what is described in this [paper](https://arxiv.org/" -"abs/1812.06127). It essentially adds a parameter called `proximal_mu` to " -"regularize the local models with respect to the global models." +"This " +"[strategy](https://github.com/adap/flower/blob/main/src/py/flwr/server/strategy/fedprox.py)" +" is almost identical to " +"[`FedAvg`](https://github.com/adap/flower/blob/main/src/py/flwr/server/strategy/fedavg.py)," +" but helps users replicate what is described in this " +"[paper](https://arxiv.org/abs/1812.06127). It essentially adds a " +"parameter called `proximal_mu` to regularize the local models with " +"respect to the global models." msgstr "" -"该[策略](https://github.com/adap/flower/blob/main/src/py/flwr/server/" -"strategy/fedprox.py)与[`FedAvg`](https://github.com/adap/flower/blob/main/" -"src/py/flwr/server/strategy/fedavg." -"py)几乎相同,但可以帮助用户复现本[论文](https://arxiv.org/abs/1812." -"06127)中的描述。它的本质是添加一个名为 " -"`proximal_mu`的参数,使局部模型与全局模型正则化。" +"该[策略](https://github.com/adap/flower/blob/main/src/py/flwr/server/strategy/fedprox.py)与[`FedAvg`](https://github.com/adap/flower/blob/main/src/py/flwr/server/strategy/fedavg.py)几乎相同,但可以帮助用户复现本[论文](https://arxiv.org/abs/1812.06127)中的描述。它的本质是添加一个名为" +" `proximal_mu`的参数,使局部模型与全局模型正则化。" -#: ../../source/ref-changelog.md:257 +#: ../../source/ref-changelog.md:384 msgid "" -"**Add new metrics to telemetry events** ([#1640](https://github.com/adap/" -"flower/pull/1640))" -msgstr "" -"**为遥测事件添加新指标**([#1640](https://github.com/adap/flower/pull/1640))" +"**Add new metrics to telemetry events** " +"([#1640](https://github.com/adap/flower/pull/1640))" +msgstr "**为遥测事件添加新指标**([#1640](https://github.com/adap/flower/pull/1640))" -#: ../../source/ref-changelog.md:259 +#: ../../source/ref-changelog.md:386 msgid "" "An updated event structure allows, for example, the clustering of events " "within the same workload." msgstr "例如,更新后的事件结构可以将同一工作负载中的事件集中在一起。" -#: ../../source/ref-changelog.md:261 -msgid "" -"**Add new custom strategy tutorial section** [#1623](https://github.com/adap/" -"flower/pull/1623)" -msgstr "" -"**添加新的自定义策略教程部分** [#1623](https://github.com/adap/flower/" -"pull/1623)" - -#: ../../source/ref-changelog.md:263 -msgid "" -"The Flower tutorial now has a new section that covers implementing a custom " -"strategy from scratch: [Open in Colab](https://colab.research.google.com/" -"github/adap/flower/blob/main/doc/source/tutorial-build-a-strategy-from-" -"scratch-pytorch.ipynb)" -msgstr "" -"Flower 教程新增了一个章节,介绍如何从零开始实施自定义策略: [在 Colab 中打开]" -"(https://colab.research.google.com/github/adap/flower/blob/main/doc/source/" -"tutorial-build-a-strategy-from-scratch-pytorch.ipynb)" - -#: ../../source/ref-changelog.md:265 -msgid "" -"**Add new custom serialization tutorial section** ([#1622](https://github." -"com/adap/flower/pull/1622))" -msgstr "" -"** 添加新的自定义序列化教程部分** ([#1622](https://github.com/adap/flower/" -"pull/1622))" - -#: ../../source/ref-changelog.md:267 -msgid "" -"The Flower tutorial now has a new section that covers custom serialization: " -"[Open in Colab](https://colab.research.google.com/github/adap/flower/blob/" -"main/doc/source/tutorial-customize-the-client-pytorch.ipynb)" -msgstr "" -"Flower 教程现在新增了一个章节,介绍自定义序列化: [在 Colab 中打开](https://" -"colab.research.google.com/github/adap/flower/blob/main/doc/source/tutorial-" -"customize-the-client-pytorch.ipynb)" - -#: ../../source/ref-changelog.md:269 -msgid "" -"**General improvements** ([#1638](https://github.com/adap/flower/pull/1638), " -"[#1634](https://github.com/adap/flower/pull/1634), [#1636](https://github." -"com/adap/flower/pull/1636), [#1635](https://github.com/adap/flower/" -"pull/1635), [#1633](https://github.com/adap/flower/pull/1633), [#1632]" -"(https://github.com/adap/flower/pull/1632), [#1631](https://github.com/adap/" -"flower/pull/1631), [#1630](https://github.com/adap/flower/pull/1630), [#1627]" -"(https://github.com/adap/flower/pull/1627), [#1593](https://github.com/adap/" -"flower/pull/1593), [#1616](https://github.com/adap/flower/pull/1616), [#1615]" -"(https://github.com/adap/flower/pull/1615), [#1607](https://github.com/adap/" -"flower/pull/1607), [#1609](https://github.com/adap/flower/pull/1609), [#1608]" -"(https://github.com/adap/flower/pull/1608), [#1603](https://github.com/adap/" -"flower/pull/1603), [#1590](https://github.com/adap/flower/pull/1590), [#1580]" -"(https://github.com/adap/flower/pull/1580), [#1599](https://github.com/adap/" -"flower/pull/1599), [#1600](https://github.com/adap/flower/pull/1600), [#1601]" -"(https://github.com/adap/flower/pull/1601), [#1597](https://github.com/adap/" -"flower/pull/1597), [#1595](https://github.com/adap/flower/pull/1595), [#1591]" -"(https://github.com/adap/flower/pull/1591), [#1588](https://github.com/adap/" -"flower/pull/1588), [#1589](https://github.com/adap/flower/pull/1589), [#1587]" -"(https://github.com/adap/flower/pull/1587), [#1573](https://github.com/adap/" -"flower/pull/1573), [#1581](https://github.com/adap/flower/pull/1581), [#1578]" -"(https://github.com/adap/flower/pull/1578), [#1574](https://github.com/adap/" -"flower/pull/1574), [#1572](https://github.com/adap/flower/pull/1572), [#1586]" -"(https://github.com/adap/flower/pull/1586))" +#: ../../source/ref-changelog.md:388 +msgid "" +"**Add new custom strategy tutorial section** " +"[#1623](https://github.com/adap/flower/pull/1623)" +msgstr "**添加新的自定义策略教程部分** [#1623](https://github.com/adap/flower/pull/1623)" + +#: ../../source/ref-changelog.md:390 +msgid "" +"The Flower tutorial now has a new section that covers implementing a " +"custom strategy from scratch: [Open in " +"Colab](https://colab.research.google.com/github/adap/flower/blob/main/doc/source" +"/tutorial-build-a-strategy-from-scratch-pytorch.ipynb)" +msgstr "" +"Flower 教程新增了一个章节,介绍如何从零开始实施自定义策略: [在 Colab " +"中打开](https://colab.research.google.com/github/adap/flower/blob/main/doc/source" +"/tutorial-build-a-strategy-from-scratch-pytorch.ipynb)" + +#: ../../source/ref-changelog.md:392 +msgid "" +"**Add new custom serialization tutorial section** " +"([#1622](https://github.com/adap/flower/pull/1622))" +msgstr "** 添加新的自定义序列化教程部分** ([#1622](https://github.com/adap/flower/pull/1622))" + +#: ../../source/ref-changelog.md:394 +msgid "" +"The Flower tutorial now has a new section that covers custom " +"serialization: [Open in " +"Colab](https://colab.research.google.com/github/adap/flower/blob/main/doc/source" +"/tutorial-customize-the-client-pytorch.ipynb)" +msgstr "" +"Flower 教程现在新增了一个章节,介绍自定义序列化: [在 Colab " +"中打开](https://colab.research.google.com/github/adap/flower/blob/main/doc/source" +"/tutorial-customize-the-client-pytorch.ipynb)" + +#: ../../source/ref-changelog.md:396 +msgid "" +"**General improvements** " +"([#1638](https://github.com/adap/flower/pull/1638), " +"[#1634](https://github.com/adap/flower/pull/1634), " +"[#1636](https://github.com/adap/flower/pull/1636), " +"[#1635](https://github.com/adap/flower/pull/1635), " +"[#1633](https://github.com/adap/flower/pull/1633), " +"[#1632](https://github.com/adap/flower/pull/1632), " +"[#1631](https://github.com/adap/flower/pull/1631), " +"[#1630](https://github.com/adap/flower/pull/1630), " +"[#1627](https://github.com/adap/flower/pull/1627), " +"[#1593](https://github.com/adap/flower/pull/1593), " +"[#1616](https://github.com/adap/flower/pull/1616), " +"[#1615](https://github.com/adap/flower/pull/1615), " +"[#1607](https://github.com/adap/flower/pull/1607), " +"[#1609](https://github.com/adap/flower/pull/1609), " +"[#1608](https://github.com/adap/flower/pull/1608), " +"[#1603](https://github.com/adap/flower/pull/1603), " +"[#1590](https://github.com/adap/flower/pull/1590), " +"[#1580](https://github.com/adap/flower/pull/1580), " +"[#1599](https://github.com/adap/flower/pull/1599), " +"[#1600](https://github.com/adap/flower/pull/1600), " +"[#1601](https://github.com/adap/flower/pull/1601), " +"[#1597](https://github.com/adap/flower/pull/1597), " +"[#1595](https://github.com/adap/flower/pull/1595), " +"[#1591](https://github.com/adap/flower/pull/1591), " +"[#1588](https://github.com/adap/flower/pull/1588), " +"[#1589](https://github.com/adap/flower/pull/1589), " +"[#1587](https://github.com/adap/flower/pull/1587), " +"[#1573](https://github.com/adap/flower/pull/1573), " +"[#1581](https://github.com/adap/flower/pull/1581), " +"[#1578](https://github.com/adap/flower/pull/1578), " +"[#1574](https://github.com/adap/flower/pull/1574), " +"[#1572](https://github.com/adap/flower/pull/1572), " +"[#1586](https://github.com/adap/flower/pull/1586))" msgstr "" "**普通改进** ([#1638](https://github.com/adap/flower/pull/1638), " -"[#1634](https://github.com/adap/flower/pull/1634), [#1636](https://github." -"com/adap/flower/pull/1636), [#1635](https://github.com/adap/flower/pull/1635)" -", [#1633](https://github.com/adap/flower/pull/1633), [#1632](https://github." -"com/adap/flower/pull/1632), [#1631](https://github.com/adap/flower/pull/1631)" -", [#1630](https://github.com/adap/flower/pull/1630), [#1627](https://github. " -"com/adap/flower/pull/1627), [#1593](https://github.com/adap/flower/pull/1593)" -", [#1616](https://github.com/adap/flower/pull/1616), [#1615](https://github." -"com/adap/flower/pull/1615), [#1607](https://github.com/adap/flower/pull/1607)" -", [#1609](https://github.com/adap/flower/pull/1609), [#1608](https://github." -"com/adap/flower/pull/1608), [#1603](https://github.com/adap/flower/pull/1603)" -", [#1590](https://github. com/adap/flower/pull/1590), [#1580](https://github." -"com/adap/flower/pull/1580), [#1599](https://github.com/adap/flower/pull/1599)" -", [#1600](https://github.com/adap/flower/pull/1600), [#1601](https://github." -"com/adap/flower/pull/1601), [#1597](https://github.com/adap/flower/pull/1597)" -", [#1595](https://github.com/adap/flower/pull/1595), [#1591](https://github." -"com/adap/flower/pull/1591), [#1588](https://github. com/adap/flower/pull/" -"1588), [#1589](https://github.com/adap/flower/pull/1589), " -"[#1587](https://github.com/adap/flower/pull/1587), [#1573](https://github." -"com/adap/flower/pull/1573), [#1581](https://github.com/adap/flower/pull/1581)" -", [#1578](https://github.com/adap/flower/pull/1578), [#1574](https://github." -"com/adap/flower/pull/1574), [#1572](https://github.com/adap/flower/pull/1572)" -", [#1586](https://github.com/adap/flower/pull/1586))" - -#: ../../source/ref-changelog.md:273 -msgid "" -"**Updated documentation** ([#1629](https://github.com/adap/flower/" -"pull/1629), [#1628](https://github.com/adap/flower/pull/1628), [#1620]" -"(https://github.com/adap/flower/pull/1620), [#1618](https://github.com/adap/" -"flower/pull/1618), [#1617](https://github.com/adap/flower/pull/1617), [#1613]" -"(https://github.com/adap/flower/pull/1613), [#1614](https://github.com/adap/" -"flower/pull/1614))" -msgstr "" -"** 更新文档** ([#1629](https://github.com/adap/flower/pull/1629), [#1628]" -"(https://github.com/adap/flower/pull/1628), [#1620](https://github.com/adap/" -"flower/pull/1620), [#1618](https://github.com/adap/flower/pull/1618), [#1617]" -"(https://github.com/adap/flower/pull/1617), [#1613](https://github.com/adap/" -"flower/pull/1613), [#1614](https://github.com/adap/flower/pull/1614)))" - -#: ../../source/ref-changelog.md:275 ../../source/ref-changelog.md:342 -msgid "" -"As usual, the documentation has improved quite a bit. It is another step in " -"our effort to make the Flower documentation the best documentation of any " -"project. Stay tuned and as always, feel free to provide feedback!" -msgstr "" -"和往常一样,我们的文档有了很大的改进。这是我们努力使 Flower 文档成为所有项目" -"中最好文档的又一步骤。请继续关注,并随时提供反馈意见!" - -#: ../../source/ref-changelog.md:281 +"[#1634](https://github.com/adap/flower/pull/1634), " +"[#1636](https://github.com/adap/flower/pull/1636), " +"[#1635](https://github.com/adap/flower/pull/1635), " +"[#1633](https://github.com/adap/flower/pull/1633), " +"[#1632](https://github.com/adap/flower/pull/1632), " +"[#1631](https://github.com/adap/flower/pull/1631), " +"[#1630](https://github.com/adap/flower/pull/1630), " +"[#1627](https://github. com/adap/flower/pull/1627), " +"[#1593](https://github.com/adap/flower/pull/1593), " +"[#1616](https://github.com/adap/flower/pull/1616), " +"[#1615](https://github.com/adap/flower/pull/1615), " +"[#1607](https://github.com/adap/flower/pull/1607), " +"[#1609](https://github.com/adap/flower/pull/1609), " +"[#1608](https://github.com/adap/flower/pull/1608), " +"[#1603](https://github.com/adap/flower/pull/1603), " +"[#1590](https://github. com/adap/flower/pull/1590), " +"[#1580](https://github.com/adap/flower/pull/1580), " +"[#1599](https://github.com/adap/flower/pull/1599), " +"[#1600](https://github.com/adap/flower/pull/1600), " +"[#1601](https://github.com/adap/flower/pull/1601), " +"[#1597](https://github.com/adap/flower/pull/1597), " +"[#1595](https://github.com/adap/flower/pull/1595), " +"[#1591](https://github.com/adap/flower/pull/1591), " +"[#1588](https://github. com/adap/flower/pull/1588), " +"[#1589](https://github.com/adap/flower/pull/1589), " +"[#1587](https://github.com/adap/flower/pull/1587), " +"[#1573](https://github.com/adap/flower/pull/1573), " +"[#1581](https://github.com/adap/flower/pull/1581), " +"[#1578](https://github.com/adap/flower/pull/1578), " +"[#1574](https://github.com/adap/flower/pull/1574), " +"[#1572](https://github.com/adap/flower/pull/1572), " +"[#1586](https://github.com/adap/flower/pull/1586))" + +#: ../../source/ref-changelog.md:400 +msgid "" +"**Updated documentation** " +"([#1629](https://github.com/adap/flower/pull/1629), " +"[#1628](https://github.com/adap/flower/pull/1628), " +"[#1620](https://github.com/adap/flower/pull/1620), " +"[#1618](https://github.com/adap/flower/pull/1618), " +"[#1617](https://github.com/adap/flower/pull/1617), " +"[#1613](https://github.com/adap/flower/pull/1613), " +"[#1614](https://github.com/adap/flower/pull/1614))" +msgstr "" +"** 更新文档** ([#1629](https://github.com/adap/flower/pull/1629), " +"[#1628](https://github.com/adap/flower/pull/1628), " +"[#1620](https://github.com/adap/flower/pull/1620), " +"[#1618](https://github.com/adap/flower/pull/1618), " +"[#1617](https://github.com/adap/flower/pull/1617), " +"[#1613](https://github.com/adap/flower/pull/1613), " +"[#1614](https://github.com/adap/flower/pull/1614)))" + +#: ../../source/ref-changelog.md:402 ../../source/ref-changelog.md:469 +msgid "" +"As usual, the documentation has improved quite a bit. It is another step " +"in our effort to make the Flower documentation the best documentation of " +"any project. Stay tuned and as always, feel free to provide feedback!" +msgstr "和往常一样,我们的文档有了很大的改进。这是我们努力使 Flower 文档成为所有项目中最好文档的又一步骤。请继续关注,并随时提供反馈意见!" + +#: ../../source/ref-changelog.md:408 msgid "v1.2.0 (2023-01-13)" msgstr "v1.2.0 (2023-01-13)" -#: ../../source/ref-changelog.md:287 +#: ../../source/ref-changelog.md:414 msgid "" -"`Adam Narozniak`, `Charles Beauville`, `Daniel J. Beutel`, `Edoardo`, `L. " -"Jiang`, `Ragy`, `Taner Topal`, `dannymcy`" +"`Adam Narozniak`, `Charles Beauville`, `Daniel J. Beutel`, `Edoardo`, `L." +" Jiang`, `Ragy`, `Taner Topal`, `dannymcy`" msgstr "" -"`Adam Narozniak`, `Charles Beauville`, `Daniel J. Beutel`, `Edoardo`, `L. " -"Jiang`, `Ragy`, `Taner Topal`, `dannymcy`" +"`Adam Narozniak`, `Charles Beauville`, `Daniel J. Beutel`, `Edoardo`, `L." +" Jiang`, `Ragy`, `Taner Topal`, `dannymcy`" -#: ../../source/ref-changelog.md:291 +#: ../../source/ref-changelog.md:418 msgid "" -"**Introduce new Flower Baseline: FedAvg MNIST** ([#1497](https://github.com/" -"adap/flower/pull/1497), [#1552](https://github.com/adap/flower/pull/1552))" +"**Introduce new Flower Baseline: FedAvg MNIST** " +"([#1497](https://github.com/adap/flower/pull/1497), " +"[#1552](https://github.com/adap/flower/pull/1552))" msgstr "" -"**引入新的 Flower Baseline: FedAvg MNIST** ([#1497](https://github.com/adap/" -"flower/pull/1497), [#1552](https://github.com/adap/flower/pull/1552))" +"**引入新的 Flower Baseline: FedAvg MNIST** " +"([#1497](https://github.com/adap/flower/pull/1497), " +"[#1552](https://github.com/adap/flower/pull/1552))" -#: ../../source/ref-changelog.md:293 +#: ../../source/ref-changelog.md:420 msgid "" "Over the coming weeks, we will be releasing a number of new reference " "implementations useful especially to FL newcomers. They will typically " "revisit well known papers from the literature, and be suitable for " "integration in your own application or for experimentation, in order to " -"deepen your knowledge of FL in general. Today's release is the first in this " -"series. [Read more.](https://flower.dev/blog/2023-01-12-fl-starter-pack-" -"fedavg-mnist-cnn/)" +"deepen your knowledge of FL in general. Today's release is the first in " +"this series. [Read more.](https://flower.dev/blog/2023-01-12-fl-starter-" +"pack-fedavg-mnist-cnn/)" msgstr "" -"在未来几周内,我们将发布一些新的参考,特别是对 FL 新手有用的方法。它们通常会" -"重温文献中的知名论文,适合集成到您自己的应用程序中或用于实验,以加深您对 FL " -"的总体了解。今天发布的是该系列中的第一篇。[阅读全文](https://flower.dev/blog/" -"2023-01-12-fl-starter-pack-fedavg-mnist-cnn/)" +"在未来几周内,我们将发布一些新的参考,特别是对 FL " +"新手有用的方法。它们通常会重温文献中的知名论文,适合集成到您自己的应用程序中或用于实验,以加深您对 FL " +"的总体了解。今天发布的是该系列中的第一篇。[阅读全文](https://flower.dev/blog/2023-01-12-fl-" +"starter-pack-fedavg-mnist-cnn/)" -#: ../../source/ref-changelog.md:295 +#: ../../source/ref-changelog.md:422 msgid "" -"**Improve GPU support in simulations** ([#1555](https://github.com/adap/" -"flower/pull/1555))" -msgstr "" -"**改进模拟中的 GPU 支持**([#1555](https://github.com/adap/flower/" -"pull/1555))" +"**Improve GPU support in simulations** " +"([#1555](https://github.com/adap/flower/pull/1555))" +msgstr "**改进模拟中的 GPU 支持**([#1555](https://github.com/adap/flower/pull/1555))" -#: ../../source/ref-changelog.md:297 +#: ../../source/ref-changelog.md:424 msgid "" -"The Ray-based Virtual Client Engine (`start_simulation`) has been updated to " -"improve GPU support. The update includes some of the hard-earned lessons " -"from scaling simulations in GPU cluster environments. New defaults make " -"running GPU-based simulations substantially more robust." +"The Ray-based Virtual Client Engine (`start_simulation`) has been updated" +" to improve GPU support. The update includes some of the hard-earned " +"lessons from scaling simulations in GPU cluster environments. New " +"defaults make running GPU-based simulations substantially more robust." msgstr "" -"基于 Ray 的虚拟客户端引擎 (`start_simulation`)已更新,以改进对 GPU 的支持。" -"此次更新包含了在 GPU 集群环境中扩展模拟的一些经验教训。新的默认设置使基于 " -"GPU 的模拟运行更加稳健。" +"基于 Ray 的虚拟客户端引擎 (`start_simulation`)已更新,以改进对 GPU 的支持。此次更新包含了在 GPU " +"集群环境中扩展模拟的一些经验教训。新的默认设置使基于 GPU 的模拟运行更加稳健。" -#: ../../source/ref-changelog.md:299 +#: ../../source/ref-changelog.md:426 msgid "" -"**Improve GPU support in Jupyter Notebook tutorials** ([#1527](https://" -"github.com/adap/flower/pull/1527), [#1558](https://github.com/adap/flower/" -"pull/1558))" +"**Improve GPU support in Jupyter Notebook tutorials** " +"([#1527](https://github.com/adap/flower/pull/1527), " +"[#1558](https://github.com/adap/flower/pull/1558))" msgstr "" -"**改进 Jupyter Notebook 教程中的 GPU 支持** ([#1527](https://github.com/adap/" -"flower/pull/1527), [#1558](https://github.com/adap/flower/pull/1558))" +"**改进 Jupyter Notebook 教程中的 GPU 支持** " +"([#1527](https://github.com/adap/flower/pull/1527), " +"[#1558](https://github.com/adap/flower/pull/1558))" -#: ../../source/ref-changelog.md:301 +#: ../../source/ref-changelog.md:428 msgid "" -"Some users reported that Jupyter Notebooks have not always been easy to use " -"on GPU instances. We listened and made improvements to all of our Jupyter " -"notebooks! Check out the updated notebooks here:" +"Some users reported that Jupyter Notebooks have not always been easy to " +"use on GPU instances. We listened and made improvements to all of our " +"Jupyter notebooks! Check out the updated notebooks here:" msgstr "" -"一些用户报告说,在 GPU 实例上使用 Jupyter " -"笔记本并不是很方便。我们听取了他们的意见,并对所有 Jupyter " +"一些用户报告说,在 GPU 实例上使用 Jupyter 笔记本并不是很方便。我们听取了他们的意见,并对所有 Jupyter " "笔记本进行了改进!点击这里查看更新后的笔记本:" -#: ../../source/ref-changelog.md:303 +#: ../../source/ref-changelog.md:430 msgid "" -"[An Introduction to Federated Learning](https://flower.dev/docs/framework/" -"tutorial-get-started-with-flower-pytorch.html)" +"[An Introduction to Federated Learning](https://flower.dev/docs/framework" +"/tutorial-get-started-with-flower-pytorch.html)" msgstr "" "[联邦学习简介](https://flower.dev/docs/framework/tutorial-get-started-with-" "flower-pytorch.html)" -#: ../../source/ref-changelog.md:304 +#: ../../source/ref-changelog.md:431 msgid "" -"[Strategies in Federated Learning](https://flower.dev/docs/framework/" -"tutorial-use-a-federated-learning-strategy-pytorch.html)" +"[Strategies in Federated Learning](https://flower.dev/docs/framework" +"/tutorial-use-a-federated-learning-strategy-pytorch.html)" msgstr "" "[联邦学习策略](https://flower.dev/docs/framework/tutorial-use-a-federated-" "learning-strategy-pytorch.html)" -#: ../../source/ref-changelog.md:305 +#: ../../source/ref-changelog.md:432 msgid "" -"[Building a Strategy](https://flower.dev/docs/framework/tutorial-build-a-" -"strategy-from-scratch-pytorch.html)" +"[Building a Strategy](https://flower.dev/docs/framework/tutorial-build-a" +"-strategy-from-scratch-pytorch.html)" msgstr "" "[制定策略](https://flower.dev/docs/framework/tutorial-build-a-strategy-from-" "scratch-pytorch.html)" -#: ../../source/ref-changelog.md:306 +#: ../../source/ref-changelog.md:433 msgid "" "[Client and NumPyClient](https://flower.dev/docs/framework/tutorial-" "customize-the-client-pytorch.html)" @@ -9569,640 +13593,665 @@ msgstr "" "[客户端和 NumPyClient](https://flower.dev/docs/framework/tutorial-customize-" "the-client-pytorch.html)" -#: ../../source/ref-changelog.md:308 +#: ../../source/ref-changelog.md:435 msgid "" -"**Introduce optional telemetry** ([#1533](https://github.com/adap/flower/" -"pull/1533), [#1544](https://github.com/adap/flower/pull/1544), [#1584]" -"(https://github.com/adap/flower/pull/1584))" +"**Introduce optional telemetry** " +"([#1533](https://github.com/adap/flower/pull/1533), " +"[#1544](https://github.com/adap/flower/pull/1544), " +"[#1584](https://github.com/adap/flower/pull/1584))" msgstr "" -"**引入可选遥测**([#1533](https://github.com/adap/flower/pull/1533), [#1544]" -"(https://github.com/adap/flower/pull/1544), [#1584](https://github.com/adap/" -"flower/pull/1584)" +"**引入可选遥测**([#1533](https://github.com/adap/flower/pull/1533), " +"[#1544](https://github.com/adap/flower/pull/1544), " +"[#1584](https://github.com/adap/flower/pull/1584)" -#: ../../source/ref-changelog.md:310 +#: ../../source/ref-changelog.md:437 msgid "" -"After a [request for feedback](https://github.com/adap/flower/issues/1534) " -"from the community, the Flower open-source project introduces optional " -"collection of *anonymous* usage metrics to make well-informed decisions to " -"improve Flower. Doing this enables the Flower team to understand how Flower " -"is used and what challenges users might face." +"After a [request for " +"feedback](https://github.com/adap/flower/issues/1534) from the community," +" the Flower open-source project introduces optional collection of " +"*anonymous* usage metrics to make well-informed decisions to improve " +"Flower. Doing this enables the Flower team to understand how Flower is " +"used and what challenges users might face." msgstr "" "在社区发出[反馈请求](https://github.com/adap/flower/issues/1534)之后,Flower " -"开放源码项目引入了可选的*匿名*使用指标收集,以便在充分知情的情况下做出改进 " -"Flower 的决定。这样做能让 Flower 团队了解 Flower 的使用情况以及用户可能面临的" -"挑战。" +"开放源码项目引入了可选的*匿名*使用指标收集,以便在充分知情的情况下做出改进 Flower 的决定。这样做能让 Flower 团队了解 " +"Flower 的使用情况以及用户可能面临的挑战。" -#: ../../source/ref-changelog.md:312 +#: ../../source/ref-changelog.md:439 msgid "" -"**Flower is a friendly framework for collaborative AI and data science.** " -"Staying true to this statement, Flower makes it easy to disable telemetry " -"for users who do not want to share anonymous usage metrics. [Read more.]" -"(https://flower.dev/docs/telemetry.html)." +"**Flower is a friendly framework for collaborative AI and data science.**" +" Staying true to this statement, Flower makes it easy to disable " +"telemetry for users who do not want to share anonymous usage metrics. " +"[Read more.](https://flower.dev/docs/telemetry.html)." msgstr "" -"**Flower 是一个用于协作式人工智能和数据科学的友好框架。** Flower 遵循这一声" -"明,让不想分享匿名使用指标的用户可以轻松禁用遥测技术。[阅读全文](https://" -"flower.dev/docs/telemetry.html)。" +"**Flower 是一个用于协作式人工智能和数据科学的友好框架。** Flower " +"遵循这一声明,让不想分享匿名使用指标的用户可以轻松禁用遥测技术。[阅读全文](https://flower.dev/docs/telemetry.html)。" -#: ../../source/ref-changelog.md:314 +#: ../../source/ref-changelog.md:441 msgid "" -"**Introduce (experimental) Driver API** ([#1520](https://github.com/adap/" -"flower/pull/1520), [#1525](https://github.com/adap/flower/pull/1525), [#1545]" -"(https://github.com/adap/flower/pull/1545), [#1546](https://github.com/adap/" -"flower/pull/1546), [#1550](https://github.com/adap/flower/pull/1550), [#1551]" -"(https://github.com/adap/flower/pull/1551), [#1567](https://github.com/adap/" -"flower/pull/1567))" -msgstr "" -"**引入(试验性)Driver API** ([#1520](https://github.com/adap/flower/pull/" -"1520), [#1525](https://github.com/adap/flower/pull/1525), " -"[#1545](https://github.com/adap/flower/pull/1545), [#1546](https://github." -"com/adap/flower/pull/1546), [#1550](https://github.com/adap/flower/pull/1550)" -", [#1551](https://github.com/adap/flower/pull/1551), [#1567](https://github." -"com/adap/flower/pull/1567))" +"**Introduce (experimental) Driver API** " +"([#1520](https://github.com/adap/flower/pull/1520), " +"[#1525](https://github.com/adap/flower/pull/1525), " +"[#1545](https://github.com/adap/flower/pull/1545), " +"[#1546](https://github.com/adap/flower/pull/1546), " +"[#1550](https://github.com/adap/flower/pull/1550), " +"[#1551](https://github.com/adap/flower/pull/1551), " +"[#1567](https://github.com/adap/flower/pull/1567))" +msgstr "" +"**引入(试验性)Driver API** ([#1520](https://github.com/adap/flower/pull/1520)," +" [#1525](https://github.com/adap/flower/pull/1525), " +"[#1545](https://github.com/adap/flower/pull/1545), " +"[#1546](https://github.com/adap/flower/pull/1546), " +"[#1550](https://github.com/adap/flower/pull/1550), " +"[#1551](https://github.com/adap/flower/pull/1551), " +"[#1567](https://github.com/adap/flower/pull/1567))" -#: ../../source/ref-changelog.md:316 +#: ../../source/ref-changelog.md:443 msgid "" "Flower now has a new (experimental) Driver API which will enable fully " "programmable, async, and multi-tenant Federated Learning and Federated " -"Analytics applications. Phew, that's a lot! Going forward, the Driver API " -"will be the abstraction that many upcoming features will be built on - and " -"you can start building those things now, too." +"Analytics applications. Phew, that's a lot! Going forward, the Driver API" +" will be the abstraction that many upcoming features will be built on - " +"and you can start building those things now, too." msgstr "" "Flower 现在有了一个新的(试验性的)驱动程序应用程序接口(Driver " -"API),它将支持完全可编程、异步和多租户的联邦学习(Federated " -"Learning)和联邦分析(Federated Analytics)应用程序。展望未来,Driver API " -"将成为许多即将推出的功能的抽象基础,您现在就可以开始构建这些功能。" +"API),它将支持完全可编程、异步和多租户的联邦学习(Federated Learning)和联邦分析(Federated " +"Analytics)应用程序。展望未来,Driver API 将成为许多即将推出的功能的抽象基础,您现在就可以开始构建这些功能。" -#: ../../source/ref-changelog.md:318 +#: ../../source/ref-changelog.md:445 msgid "" -"The Driver API also enables a new execution mode in which the server runs " -"indefinitely. Multiple individual workloads can run concurrently and start " -"and stop their execution independent of the server. This is especially " -"useful for users who want to deploy Flower in production." +"The Driver API also enables a new execution mode in which the server runs" +" indefinitely. Multiple individual workloads can run concurrently and " +"start and stop their execution independent of the server. This is " +"especially useful for users who want to deploy Flower in production." msgstr "" -"驱动程序应用程序接口还支持一种新的执行模式,在这种模式下,服务器可无限期运" -"行。多个单独的工作负载可以同时运行,并独立于服务器启动和停止执行。这对于希望" -"在生产中部署 Flower 的用户来说尤其有用。" +"驱动程序应用程序接口还支持一种新的执行模式,在这种模式下,服务器可无限期运行。多个单独的工作负载可以同时运行,并独立于服务器启动和停止执行。这对于希望在生产中部署" +" Flower 的用户来说尤其有用。" -#: ../../source/ref-changelog.md:320 +#: ../../source/ref-changelog.md:447 msgid "" -"To learn more, check out the `mt-pytorch` code example. We look forward to " -"you feedback!" +"To learn more, check out the `mt-pytorch` code example. We look forward " +"to you feedback!" msgstr "要了解更多信息,请查看 `mt-pytorch` 代码示例。我们期待您的反馈!" -#: ../../source/ref-changelog.md:322 +#: ../../source/ref-changelog.md:449 msgid "" -"Please note: *The Driver API is still experimental and will likely change " -"significantly over time.*" +"Please note: *The Driver API is still experimental and will likely change" +" significantly over time.*" msgstr "请注意:Driver API仍处于试验阶段,随着时间的推移可能会发生重大变化。*" -#: ../../source/ref-changelog.md:324 +#: ../../source/ref-changelog.md:451 msgid "" -"**Add new Federated Analytics with Pandas example** ([#1469](https://github." -"com/adap/flower/pull/1469), [#1535](https://github.com/adap/flower/" -"pull/1535))" +"**Add new Federated Analytics with Pandas example** " +"([#1469](https://github.com/adap/flower/pull/1469), " +"[#1535](https://github.com/adap/flower/pull/1535))" msgstr "" -"** 添加新的使用 Pandas 的联邦分析示例**([#1469](https://github.com/adap/" -"flower/pull/1469), [#1535](https://github.com/adap/flower/pull/1535)" +"** 添加新的使用 Pandas " +"的联邦分析示例**([#1469](https://github.com/adap/flower/pull/1469), " +"[#1535](https://github.com/adap/flower/pull/1535)" -#: ../../source/ref-changelog.md:326 +#: ../../source/ref-changelog.md:453 msgid "" -"A new code example (`quickstart_pandas`) demonstrates federated analytics " -"with Pandas and Flower. You can find it here: [quickstart_pandas](https://" -"github.com/adap/flower/tree/main/examples/quickstart_pandas)." +"A new code example (`quickstart_pandas`) demonstrates federated analytics" +" with Pandas and Flower. You can find it here: " +"[quickstart_pandas](https://github.com/adap/flower/tree/main/examples/quickstart_pandas)." msgstr "" -"新代码示例(`quickstart_pandas`)演示了使用 Pandas 和 Flower " -"进行联邦分析。您可以在此处找到它: [quickstart_pandas](https://github.com/" -"adap/flower/tree/main/examples/quickstart_pandas)。" +"新代码示例(`quickstart_pandas`)演示了使用 Pandas 和 Flower 进行联邦分析。您可以在此处找到它: " +"[quickstart_pandas](https://github.com/adap/flower/tree/main/examples/quickstart_pandas)。" -#: ../../source/ref-changelog.md:328 +#: ../../source/ref-changelog.md:455 msgid "" -"**Add new strategies: Krum and MultiKrum** ([#1481](https://github.com/adap/" -"flower/pull/1481))" +"**Add new strategies: Krum and MultiKrum** " +"([#1481](https://github.com/adap/flower/pull/1481))" msgstr "" -"**添加新策略: Krum 和 MultiKrum** ([#1481](https://github.com/adap/flower/" -"pull/1481))" +"**添加新策略: Krum 和 MultiKrum** " +"([#1481](https://github.com/adap/flower/pull/1481))" -#: ../../source/ref-changelog.md:330 +#: ../../source/ref-changelog.md:457 msgid "" "Edoardo, a computer science student at the Sapienza University of Rome, " -"contributed a new `Krum` strategy that enables users to easily use Krum and " -"MultiKrum in their workloads." +"contributed a new `Krum` strategy that enables users to easily use Krum " +"and MultiKrum in their workloads." msgstr "" -"罗马萨皮恩扎大学(Sapienza University)计算机科学专业的学生埃多尔多" -"(Edoardo)提出了一种新的 \"Krum \"策略,使用户能够在其工作负载中轻松使用 " -"Krum 和 MultiKrum。" +"罗马萨皮恩扎大学(Sapienza University)计算机科学专业的学生埃多尔多(Edoardo)提出了一种新的 \"Krum " +"\"策略,使用户能够在其工作负载中轻松使用 Krum 和 MultiKrum。" -#: ../../source/ref-changelog.md:332 +#: ../../source/ref-changelog.md:459 msgid "" -"**Update C++ example to be compatible with Flower v1.2.0** ([#1495](https://" -"github.com/adap/flower/pull/1495))" +"**Update C++ example to be compatible with Flower v1.2.0** " +"([#1495](https://github.com/adap/flower/pull/1495))" msgstr "" -"** 更新 C++ 示例,与 Flower v1.2.0 兼容** ([#1495](https://github.com/adap/" -"flower/pull/1495))" +"** 更新 C++ 示例,与 Flower v1.2.0 兼容** " +"([#1495](https://github.com/adap/flower/pull/1495))" -#: ../../source/ref-changelog.md:334 +#: ../../source/ref-changelog.md:461 msgid "" -"The C++ code example has received a substantial update to make it compatible " -"with the latest version of Flower." +"The C++ code example has received a substantial update to make it " +"compatible with the latest version of Flower." msgstr "为了与最新版本的 Flower 兼容,C++ 示例代码进行了大幅更新。" -#: ../../source/ref-changelog.md:336 +#: ../../source/ref-changelog.md:463 msgid "" -"**General improvements** ([#1491](https://github.com/adap/flower/pull/1491), " -"[#1504](https://github.com/adap/flower/pull/1504), [#1506](https://github." -"com/adap/flower/pull/1506), [#1514](https://github.com/adap/flower/" -"pull/1514), [#1522](https://github.com/adap/flower/pull/1522), [#1523]" -"(https://github.com/adap/flower/pull/1523), [#1526](https://github.com/adap/" -"flower/pull/1526), [#1528](https://github.com/adap/flower/pull/1528), [#1547]" -"(https://github.com/adap/flower/pull/1547), [#1549](https://github.com/adap/" -"flower/pull/1549), [#1560](https://github.com/adap/flower/pull/1560), [#1564]" -"(https://github.com/adap/flower/pull/1564), [#1566](https://github.com/adap/" -"flower/pull/1566))" +"**General improvements** " +"([#1491](https://github.com/adap/flower/pull/1491), " +"[#1504](https://github.com/adap/flower/pull/1504), " +"[#1506](https://github.com/adap/flower/pull/1506), " +"[#1514](https://github.com/adap/flower/pull/1514), " +"[#1522](https://github.com/adap/flower/pull/1522), " +"[#1523](https://github.com/adap/flower/pull/1523), " +"[#1526](https://github.com/adap/flower/pull/1526), " +"[#1528](https://github.com/adap/flower/pull/1528), " +"[#1547](https://github.com/adap/flower/pull/1547), " +"[#1549](https://github.com/adap/flower/pull/1549), " +"[#1560](https://github.com/adap/flower/pull/1560), " +"[#1564](https://github.com/adap/flower/pull/1564), " +"[#1566](https://github.com/adap/flower/pull/1566))" msgstr "" "**普通改进** ([#1491](https://github.com/adap/flower/pull/1491), " -"[#1504](https://github.com/adap/flower/pull/1504), [#1506](https://github." -"com/adap/flower/pull/1506), [#1514](https://github.com/adap/flower/pull/1514)" -", [#1522](https://github.com/adap/flower/pull/1522), [#1523](https://github." -"com/adap/flower/pull/1523), [#1526](https://github. com/adap/flower/pull/" -"1526), [#1528](https://github.com/adap/flower/pull/1528), " -"[#1547](https://github.com/adap/flower/pull/1547), [#1549](https://github." -"com/adap/flower/pull/1549), [#1560](https://github.com/adap/flower/pull/1560)" -", [#1564](https://github.com/adap/flower/pull/1564), [#1566](https://github." -"com/adap/flower/pull/1566))" +"[#1504](https://github.com/adap/flower/pull/1504), " +"[#1506](https://github.com/adap/flower/pull/1506), " +"[#1514](https://github.com/adap/flower/pull/1514), " +"[#1522](https://github.com/adap/flower/pull/1522), " +"[#1523](https://github.com/adap/flower/pull/1523), " +"[#1526](https://github. com/adap/flower/pull/1526), " +"[#1528](https://github.com/adap/flower/pull/1528), " +"[#1547](https://github.com/adap/flower/pull/1547), " +"[#1549](https://github.com/adap/flower/pull/1549), " +"[#1560](https://github.com/adap/flower/pull/1560), " +"[#1564](https://github.com/adap/flower/pull/1564), " +"[#1566](https://github.com/adap/flower/pull/1566))" -#: ../../source/ref-changelog.md:340 +#: ../../source/ref-changelog.md:467 msgid "" -"**Updated documentation** ([#1494](https://github.com/adap/flower/" -"pull/1494), [#1496](https://github.com/adap/flower/pull/1496), [#1500]" -"(https://github.com/adap/flower/pull/1500), [#1503](https://github.com/adap/" -"flower/pull/1503), [#1505](https://github.com/adap/flower/pull/1505), [#1524]" -"(https://github.com/adap/flower/pull/1524), [#1518](https://github.com/adap/" -"flower/pull/1518), [#1519](https://github.com/adap/flower/pull/1519), [#1515]" -"(https://github.com/adap/flower/pull/1515))" -msgstr "" -"** 更新文档** ([#1494](https://github.com/adap/flower/pull/1494), [#1496]" -"(https://github.com/adap/flower/pull/1496), [#1500](https://github.com/adap/" -"flower/pull/1500), [#1503](https://github.com/adap/flower/pull/1503), [#1505]" -"(https://github.com/adap/flower/pull/1505), [#1524](https://github.com/adap/" -"flower/pull/1524), [#1518](https://github.com/adap/flower/pull/1518), [#1519]" -"(https://github.com/adap/flower/pull/1519), [#1515](https://github.com/adap/" -"flower/pull/1515))" +"**Updated documentation** " +"([#1494](https://github.com/adap/flower/pull/1494), " +"[#1496](https://github.com/adap/flower/pull/1496), " +"[#1500](https://github.com/adap/flower/pull/1500), " +"[#1503](https://github.com/adap/flower/pull/1503), " +"[#1505](https://github.com/adap/flower/pull/1505), " +"[#1524](https://github.com/adap/flower/pull/1524), " +"[#1518](https://github.com/adap/flower/pull/1518), " +"[#1519](https://github.com/adap/flower/pull/1519), " +"[#1515](https://github.com/adap/flower/pull/1515))" +msgstr "" +"** 更新文档** ([#1494](https://github.com/adap/flower/pull/1494), " +"[#1496](https://github.com/adap/flower/pull/1496), " +"[#1500](https://github.com/adap/flower/pull/1500), " +"[#1503](https://github.com/adap/flower/pull/1503), " +"[#1505](https://github.com/adap/flower/pull/1505), " +"[#1524](https://github.com/adap/flower/pull/1524), " +"[#1518](https://github.com/adap/flower/pull/1518), " +"[#1519](https://github.com/adap/flower/pull/1519), " +"[#1515](https://github.com/adap/flower/pull/1515))" -#: ../../source/ref-changelog.md:344 +#: ../../source/ref-changelog.md:471 msgid "" -"One highlight is the new [first time contributor guide](https://flower.dev/" -"docs/first-time-contributors.html): if you've never contributed on GitHub " -"before, this is the perfect place to start!" +"One highlight is the new [first time contributor " +"guide](https://flower.dev/docs/first-time-contributors.html): if you've " +"never contributed on GitHub before, this is the perfect place to start!" msgstr "" "其中一个亮点是新的[首次贡献者指南](https://flower.dev/docs/first-time-" -"contributors.html):如果你以前从未在 GitHub 上做过贡献,这将是一个完美的开" -"始!" +"contributors.html):如果你以前从未在 GitHub 上做过贡献,这将是一个完美的开始!" -#: ../../source/ref-changelog.md:350 +#: ../../source/ref-changelog.md:477 msgid "v1.1.0 (2022-10-31)" msgstr "v1.1.0 (2022-10-31)" -#: ../../source/ref-changelog.md:354 +#: ../../source/ref-changelog.md:481 msgid "" "We would like to give our **special thanks** to all the contributors who " "made the new version of Flower possible (in `git shortlog` order):" -msgstr "" -"在此,我们向所有促成 Flower 新版本的贡献者致以**特别的谢意(按 \"git " -"shortlog \"顺序排列):" +msgstr "在此,我们向所有促成 Flower 新版本的贡献者致以**特别的谢意(按 \"git shortlog \"顺序排列):" -#: ../../source/ref-changelog.md:356 +#: ../../source/ref-changelog.md:483 msgid "" "`Akis Linardos`, `Christopher S`, `Daniel J. Beutel`, `George`, `Jan " "Schlicht`, `Mohammad Fares`, `Pedro Porto Buarque de Gusmão`, `Philipp " -"Wiesner`, `Rob Luke`, `Taner Topal`, `VasundharaAgarwal`, `danielnugraha`, " -"`edogab33`" +"Wiesner`, `Rob Luke`, `Taner Topal`, `VasundharaAgarwal`, " +"`danielnugraha`, `edogab33`" msgstr "" "`Akis Linardos`, `Christopher S`, `Daniel J. Beutel`, `George`, `Jan " "Schlicht`, `Mohammad Fares`, `Pedro Porto Buarque de Gusmão`, `Philipp " -"Wiesner`, `Rob Luke`, `Taner Topal`, `VasundharaAgarwal`, `danielnugraha`, " -"`edogab33`" +"Wiesner`, `Rob Luke`, `Taner Topal`, `VasundharaAgarwal`, " +"`danielnugraha`, `edogab33`" -#: ../../source/ref-changelog.md:360 +#: ../../source/ref-changelog.md:487 msgid "" -"**Introduce Differential Privacy wrappers (preview)** ([#1357](https://" -"github.com/adap/flower/pull/1357), [#1460](https://github.com/adap/flower/" -"pull/1460))" +"**Introduce Differential Privacy wrappers (preview)** " +"([#1357](https://github.com/adap/flower/pull/1357), " +"[#1460](https://github.com/adap/flower/pull/1460))" msgstr "" -"**引入差分隐私包装器(预览)** ([#1357](https://github.com/adap/flower/" -"pull/1357), [#1460](https://github.com/adap/flower/pull/1460))" +"**引入差分隐私包装器(预览)** ([#1357](https://github.com/adap/flower/pull/1357), " +"[#1460](https://github.com/adap/flower/pull/1460))" -#: ../../source/ref-changelog.md:362 +#: ../../source/ref-changelog.md:489 msgid "" -"The first (experimental) preview of pluggable Differential Privacy wrappers " -"enables easy configuration and usage of differential privacy (DP). The " -"pluggable DP wrappers enable framework-agnostic **and** strategy-agnostic " -"usage of both client-side DP and server-side DP. Head over to the Flower " -"docs, a new explainer goes into more detail." +"The first (experimental) preview of pluggable Differential Privacy " +"wrappers enables easy configuration and usage of differential privacy " +"(DP). The pluggable DP wrappers enable framework-agnostic **and** " +"strategy-agnostic usage of both client-side DP and server-side DP. Head " +"over to the Flower docs, a new explainer goes into more detail." msgstr "" -"可插拔差分隐私封装器的首个(实验性)预览版可轻松配置和使用差分隐私(DP)。可" -"插拔的差分隐私封装器可实现客户端差分隐私和服务器端差分隐私的框架无关**以及**" -"策略无关的使用。请访问 Flower 文档,新的解释器会提供更多细节。" +"可插拔差分隐私封装器的首个(实验性)预览版可轻松配置和使用差分隐私(DP)。可插拔的差分隐私封装器可实现客户端差分隐私和服务器端差分隐私的框架无关**以及**策略无关的使用。请访问" +" Flower 文档,新的解释器会提供更多细节。" -#: ../../source/ref-changelog.md:364 +#: ../../source/ref-changelog.md:491 msgid "" -"**New iOS CoreML code example** ([#1289](https://github.com/adap/flower/" -"pull/1289))" -msgstr "" -"**新的 iOS CoreML 代码示例**([#1289](https://github.com/adap/flower/" -"pull/1289))" +"**New iOS CoreML code example** " +"([#1289](https://github.com/adap/flower/pull/1289))" +msgstr "**新的 iOS CoreML 代码示例**([#1289](https://github.com/adap/flower/pull/1289))" -#: ../../source/ref-changelog.md:366 +#: ../../source/ref-changelog.md:493 msgid "" -"Flower goes iOS! A massive new code example shows how Flower clients can be " -"built for iOS. The code example contains both Flower iOS SDK components that " -"can be used for many tasks, and one task example running on CoreML." +"Flower goes iOS! A massive new code example shows how Flower clients can " +"be built for iOS. The code example contains both Flower iOS SDK " +"components that can be used for many tasks, and one task example running " +"on CoreML." msgstr "" -"Flower 进入 iOS!大量新代码示例展示了如何为 iOS 构建 Flower 客户端。该代码示" -"例包含可用于多种任务的 Flower iOS SDK 组件,以及在 CoreML 上运行的一个任务示" -"例。" +"Flower 进入 iOS!大量新代码示例展示了如何为 iOS 构建 Flower 客户端。该代码示例包含可用于多种任务的 Flower iOS " +"SDK 组件,以及在 CoreML 上运行的一个任务示例。" -#: ../../source/ref-changelog.md:368 +#: ../../source/ref-changelog.md:495 msgid "" -"**New FedMedian strategy** ([#1461](https://github.com/adap/flower/" -"pull/1461))" +"**New FedMedian strategy** " +"([#1461](https://github.com/adap/flower/pull/1461))" msgstr "**新的联邦医疗策略** ([#1461](https://github.com/adap/flower/pull/1461))" -#: ../../source/ref-changelog.md:370 +#: ../../source/ref-changelog.md:497 msgid "" -"The new `FedMedian` strategy implements Federated Median (FedMedian) by [Yin " -"et al., 2018](https://arxiv.org/pdf/1803.01498v1.pdf)." +"The new `FedMedian` strategy implements Federated Median (FedMedian) by " +"[Yin et al., 2018](https://arxiv.org/pdf/1803.01498v1.pdf)." msgstr "" -"新的 \"FedMedian \"战略实现了[Yin 等人,2018]的联邦中值(FedMedian)(https://" -"arxiv.org/pdf/1803.01498v1.pdf)。" +"新的 \"FedMedian \"战略实现了[Yin " +"等人,2018]的联邦中值(FedMedian)(https://arxiv.org/pdf/1803.01498v1.pdf)。" -#: ../../source/ref-changelog.md:372 +#: ../../source/ref-changelog.md:499 msgid "" -"**Log** `Client` **exceptions in Virtual Client Engine** ([#1493](https://" -"github.com/adap/flower/pull/1493))" -msgstr "" -"**虚拟客户端引擎中的**日志**`客户端`**异常([#1493](https://github.com/adap/" -"flower/pull/1493))" +"**Log** `Client` **exceptions in Virtual Client Engine** " +"([#1493](https://github.com/adap/flower/pull/1493))" +msgstr "**虚拟客户端引擎中的**日志**`客户端`**异常([#1493](https://github.com/adap/flower/pull/1493))" -#: ../../source/ref-changelog.md:374 +#: ../../source/ref-changelog.md:501 msgid "" -"All `Client` exceptions happening in the VCE are now logged by default and " -"not just exposed to the configured `Strategy` (via the `failures` argument)." -msgstr "" -"VCE 中发生的所有 \"客户端 \"异常现在都会被默认记录下来,而不只是暴露给配置的 " -"`Strategy`(通过 `failures`参数)。" +"All `Client` exceptions happening in the VCE are now logged by default " +"and not just exposed to the configured `Strategy` (via the `failures` " +"argument)." +msgstr "VCE 中发生的所有 \"客户端 \"异常现在都会被默认记录下来,而不只是暴露给配置的 `Strategy`(通过 `failures`参数)。" -#: ../../source/ref-changelog.md:376 +#: ../../source/ref-changelog.md:503 msgid "" -"**Improve Virtual Client Engine internals** ([#1401](https://github.com/adap/" -"flower/pull/1401), [#1453](https://github.com/adap/flower/pull/1453))" -msgstr "" -"**改进虚拟客户端引擎内部**([#1401](https://github.com/adap/flower/" -"pull/1401)、[#1453](https://github.com/adap/flower/pull/1453))" +"**Improve Virtual Client Engine internals** " +"([#1401](https://github.com/adap/flower/pull/1401), " +"[#1453](https://github.com/adap/flower/pull/1453))" +msgstr "**改进虚拟客户端引擎内部**([#1401](https://github.com/adap/flower/pull/1401)、[#1453](https://github.com/adap/flower/pull/1453))" -#: ../../source/ref-changelog.md:378 +#: ../../source/ref-changelog.md:505 msgid "" -"Some internals of the Virtual Client Engine have been revamped. The VCE now " -"uses Ray 2.0 under the hood, the value type of the `client_resources` " -"dictionary changed to `float` to allow fractions of resources to be " +"Some internals of the Virtual Client Engine have been revamped. The VCE " +"now uses Ray 2.0 under the hood, the value type of the `client_resources`" +" dictionary changed to `float` to allow fractions of resources to be " "allocated." msgstr "" -"虚拟客户端引擎的部分内部结构已进行了修改。VCE 现在使用 Ray " -"2.0,\"client_resources \"字典的值类型改为 \"float\",以允许分配分数资源。" +"虚拟客户端引擎的部分内部结构已进行了修改。VCE 现在使用 Ray 2.0,\"client_resources \"字典的值类型改为 " +"\"float\",以允许分配分数资源。" -#: ../../source/ref-changelog.md:380 +#: ../../source/ref-changelog.md:507 msgid "" -"**Support optional** `Client`**/**`NumPyClient` **methods in Virtual Client " -"Engine**" +"**Support optional** `Client`**/**`NumPyClient` **methods in Virtual " +"Client Engine**" msgstr "**支持虚拟客户端引擎中的可选** `Client`**/**`NumPyClient` **方法**" -#: ../../source/ref-changelog.md:382 +#: ../../source/ref-changelog.md:509 msgid "" -"The Virtual Client Engine now has full support for optional `Client` (and " -"`NumPyClient`) methods." +"The Virtual Client Engine now has full support for optional `Client` (and" +" `NumPyClient`) methods." msgstr "虚拟客户端引擎现在完全支持可选的 `Client`(和 `NumPyClient`)方法。" -#: ../../source/ref-changelog.md:384 +#: ../../source/ref-changelog.md:511 msgid "" -"**Provide type information to packages using** `flwr` ([#1377](https://" -"github.com/adap/flower/pull/1377))" +"**Provide type information to packages using** `flwr` " +"([#1377](https://github.com/adap/flower/pull/1377))" msgstr "" -"**使用** `flwr`向软件包提供类型信息 ([#1377](https://github.com/adap/flower/" -"pull/1377))" +"**使用** `flwr`向软件包提供类型信息 " +"([#1377](https://github.com/adap/flower/pull/1377))" -#: ../../source/ref-changelog.md:386 +#: ../../source/ref-changelog.md:513 msgid "" -"The package `flwr` is now bundled with a `py.typed` file indicating that the " -"package is typed. This enables typing support for projects or packages that " -"use `flwr` by enabling them to improve their code using static type checkers " -"like `mypy`." +"The package `flwr` is now bundled with a `py.typed` file indicating that " +"the package is typed. This enables typing support for projects or " +"packages that use `flwr` by enabling them to improve their code using " +"static type checkers like `mypy`." msgstr "" -"软件包 `flwr` 现在捆绑了一个 `py.typed` 文件,表明该软件包是类型化的。这样," -"使用 `flwr` 的项目或软件包就可以使用 `mypy` 等静态类型检查器改进代码,从而获" -"得类型支持。" +"软件包 `flwr` 现在捆绑了一个 `py.typed` 文件,表明该软件包是类型化的。这样,使用 `flwr` 的项目或软件包就可以使用 " +"`mypy` 等静态类型检查器改进代码,从而获得类型支持。" -#: ../../source/ref-changelog.md:388 +#: ../../source/ref-changelog.md:515 msgid "" -"**Updated code example** ([#1344](https://github.com/adap/flower/pull/1344), " +"**Updated code example** " +"([#1344](https://github.com/adap/flower/pull/1344), " "[#1347](https://github.com/adap/flower/pull/1347))" msgstr "" -"** 更新代码示例** ([#1344](https://github.com/adap/flower/pull/1344), [#1347]" -"(https://github.com/adap/flower/pull/1347))" +"** 更新代码示例** ([#1344](https://github.com/adap/flower/pull/1344), " +"[#1347](https://github.com/adap/flower/pull/1347))" -#: ../../source/ref-changelog.md:390 +#: ../../source/ref-changelog.md:517 msgid "" "The code examples covering scikit-learn and PyTorch Lightning have been " "updated to work with the latest version of Flower." -msgstr "" -"涵盖 scikit-learn 和 PyTorch Lightning 的代码示例已更新,以便与最新版本的 " -"Flower 配合使用。" - -#: ../../source/ref-changelog.md:392 -msgid "" -"**Updated documentation** ([#1355](https://github.com/adap/flower/" -"pull/1355), [#1558](https://github.com/adap/flower/pull/1558), [#1379]" -"(https://github.com/adap/flower/pull/1379), [#1380](https://github.com/adap/" -"flower/pull/1380), [#1381](https://github.com/adap/flower/pull/1381), [#1332]" -"(https://github.com/adap/flower/pull/1332), [#1391](https://github.com/adap/" -"flower/pull/1391), [#1403](https://github.com/adap/flower/pull/1403), [#1364]" -"(https://github.com/adap/flower/pull/1364), [#1409](https://github.com/adap/" -"flower/pull/1409), [#1419](https://github.com/adap/flower/pull/1419), [#1444]" -"(https://github.com/adap/flower/pull/1444), [#1448](https://github.com/adap/" -"flower/pull/1448), [#1417](https://github.com/adap/flower/pull/1417), [#1449]" -"(https://github.com/adap/flower/pull/1449), [#1465](https://github.com/adap/" -"flower/pull/1465), [#1467](https://github.com/adap/flower/pull/1467))" -msgstr "" -"**更新文档** ([#1355](https://github.com/adap/flower/pull/1355), [#1558]" -"(https://github.com/adap/flower/pull/1558), [#1379](https://github.com/adap/" -"flower/pull/1379), [#1380](https://github.com/adap/flower/pull/1380), [#1381]" -"(https://github.com/adap/flower/pull/1381), [#1332](https://github.com/adap/" -"flower/pull/1332), [#1391](https://github.com/adap/flower/pull/1391), [#1403]" -"(https://github.com/adap/flower/pull/1403), [#1364](https://github. com/adap/" -"flower/pull/1364), [#1409](https://github.com/adap/flower/pull/1409), [#1419]" -"(https://github.com/adap/flower/pull/1419), [#1444](https://github.com/adap/" -"flower/pull/1444), [#1448](https://github.com/adap/flower/pull/1448), [#1417]" -"(https://github.com/adap/flower/pull/1417), [#1449](https://github.com/adap/" -"flower/pull/1449), [#1465](https://github.com/adap/flower/pull/1465), [#1467]" -"(https://github.com/adap/flower/pull/1467))" - -#: ../../source/ref-changelog.md:394 +msgstr "涵盖 scikit-learn 和 PyTorch Lightning 的代码示例已更新,以便与最新版本的 Flower 配合使用。" + +#: ../../source/ref-changelog.md:519 +msgid "" +"**Updated documentation** " +"([#1355](https://github.com/adap/flower/pull/1355), " +"[#1558](https://github.com/adap/flower/pull/1558), " +"[#1379](https://github.com/adap/flower/pull/1379), " +"[#1380](https://github.com/adap/flower/pull/1380), " +"[#1381](https://github.com/adap/flower/pull/1381), " +"[#1332](https://github.com/adap/flower/pull/1332), " +"[#1391](https://github.com/adap/flower/pull/1391), " +"[#1403](https://github.com/adap/flower/pull/1403), " +"[#1364](https://github.com/adap/flower/pull/1364), " +"[#1409](https://github.com/adap/flower/pull/1409), " +"[#1419](https://github.com/adap/flower/pull/1419), " +"[#1444](https://github.com/adap/flower/pull/1444), " +"[#1448](https://github.com/adap/flower/pull/1448), " +"[#1417](https://github.com/adap/flower/pull/1417), " +"[#1449](https://github.com/adap/flower/pull/1449), " +"[#1465](https://github.com/adap/flower/pull/1465), " +"[#1467](https://github.com/adap/flower/pull/1467))" +msgstr "" +"**更新文档** ([#1355](https://github.com/adap/flower/pull/1355), " +"[#1558](https://github.com/adap/flower/pull/1558), " +"[#1379](https://github.com/adap/flower/pull/1379), " +"[#1380](https://github.com/adap/flower/pull/1380), " +"[#1381](https://github.com/adap/flower/pull/1381), " +"[#1332](https://github.com/adap/flower/pull/1332), " +"[#1391](https://github.com/adap/flower/pull/1391), " +"[#1403](https://github.com/adap/flower/pull/1403), " +"[#1364](https://github. com/adap/flower/pull/1364), " +"[#1409](https://github.com/adap/flower/pull/1409), " +"[#1419](https://github.com/adap/flower/pull/1419), " +"[#1444](https://github.com/adap/flower/pull/1444), " +"[#1448](https://github.com/adap/flower/pull/1448), " +"[#1417](https://github.com/adap/flower/pull/1417), " +"[#1449](https://github.com/adap/flower/pull/1449), " +"[#1465](https://github.com/adap/flower/pull/1465), " +"[#1467](https://github.com/adap/flower/pull/1467))" + +#: ../../source/ref-changelog.md:521 msgid "" "There have been so many documentation updates that it doesn't even make " "sense to list them individually." msgstr "文档更新的数量之多,甚至没有必要逐一列出。" -#: ../../source/ref-changelog.md:396 +#: ../../source/ref-changelog.md:523 msgid "" -"**Restructured documentation** ([#1387](https://github.com/adap/flower/" -"pull/1387))" +"**Restructured documentation** " +"([#1387](https://github.com/adap/flower/pull/1387))" msgstr "**重构文档**([#1387](https://github.com/adap/flower/pull/1387))" -#: ../../source/ref-changelog.md:398 +#: ../../source/ref-changelog.md:525 msgid "" -"The documentation has been restructured to make it easier to navigate. This " -"is just the first step in a larger effort to make the Flower documentation " -"the best documentation of any project ever. Stay tuned!" -msgstr "" -"我们对文档进行了重组,使其更易于浏览。这只是让 Flower 文档成为所有项目中最好" -"文档的第一步。敬请期待!" +"The documentation has been restructured to make it easier to navigate. " +"This is just the first step in a larger effort to make the Flower " +"documentation the best documentation of any project ever. Stay tuned!" +msgstr "我们对文档进行了重组,使其更易于浏览。这只是让 Flower 文档成为所有项目中最好文档的第一步。敬请期待!" -#: ../../source/ref-changelog.md:400 +#: ../../source/ref-changelog.md:527 msgid "" -"**Open in Colab button** ([#1389](https://github.com/adap/flower/pull/1389))" -msgstr "" -"**在 Colab 中打开按钮** ([#1389](https://github.com/adap/flower/pull/1389))" +"**Open in Colab button** " +"([#1389](https://github.com/adap/flower/pull/1389))" +msgstr "**在 Colab 中打开按钮** ([#1389](https://github.com/adap/flower/pull/1389))" -#: ../../source/ref-changelog.md:402 +#: ../../source/ref-changelog.md:529 msgid "" -"The four parts of the Flower Federated Learning Tutorial now come with a new " -"`Open in Colab` button. No need to install anything on your local machine, " -"you can now use and learn about Flower in your browser, it's only a single " -"click away." +"The four parts of the Flower Federated Learning Tutorial now come with a " +"new `Open in Colab` button. No need to install anything on your local " +"machine, you can now use and learn about Flower in your browser, it's " +"only a single click away." msgstr "" -"Flower 联邦学习教程的四个部分现在都带有一个新的 \"在 Colab 中打开 \"按钮。现" -"在,您无需在本地计算机上安装任何软件,只需点击一下,就可以在浏览器中使用和学" -"习 Flower。" +"Flower 联邦学习教程的四个部分现在都带有一个新的 \"在 Colab 中打开 " +"\"按钮。现在,您无需在本地计算机上安装任何软件,只需点击一下,就可以在浏览器中使用和学习 Flower。" -#: ../../source/ref-changelog.md:404 +#: ../../source/ref-changelog.md:531 msgid "" -"**Improved tutorial** ([#1468](https://github.com/adap/flower/pull/1468), " -"[#1470](https://github.com/adap/flower/pull/1470), [#1472](https://github." -"com/adap/flower/pull/1472), [#1473](https://github.com/adap/flower/" -"pull/1473), [#1474](https://github.com/adap/flower/pull/1474), [#1475]" -"(https://github.com/adap/flower/pull/1475))" +"**Improved tutorial** ([#1468](https://github.com/adap/flower/pull/1468)," +" [#1470](https://github.com/adap/flower/pull/1470), " +"[#1472](https://github.com/adap/flower/pull/1472), " +"[#1473](https://github.com/adap/flower/pull/1473), " +"[#1474](https://github.com/adap/flower/pull/1474), " +"[#1475](https://github.com/adap/flower/pull/1475))" msgstr "" -"**改进教程** ([#1468](https://github.com/adap/flower/pull/1468), [#1470]" -"(https://github.com/adap/flower/pull/1470), [#1472](https://github.com/adap/" -"flower/pull/1472), [#1473](https://github.com/adap/flower/pull/1473), [#1474]" -"(https://github.com/adap/flower/pull/1474), [#1475](https://github.com/adap/" -"flower/pull/1475)))" +"**改进教程** ([#1468](https://github.com/adap/flower/pull/1468), " +"[#1470](https://github.com/adap/flower/pull/1470), " +"[#1472](https://github.com/adap/flower/pull/1472), " +"[#1473](https://github.com/adap/flower/pull/1473), " +"[#1474](https://github.com/adap/flower/pull/1474), " +"[#1475](https://github.com/adap/flower/pull/1475)))" -#: ../../source/ref-changelog.md:406 +#: ../../source/ref-changelog.md:533 msgid "" "The Flower Federated Learning Tutorial has two brand-new parts covering " "custom strategies (still WIP) and the distinction between `Client` and " -"`NumPyClient`. The existing parts one and two have also been improved (many " -"small changes and fixes)." +"`NumPyClient`. The existing parts one and two have also been improved " +"(many small changes and fixes)." msgstr "" -"Flower 联邦学习教程有两个全新的部分,涉及自定义策略(仍处于 WIP 阶段)和 " -"`Client` 与 `NumPyClient` " +"Flower 联邦学习教程有两个全新的部分,涉及自定义策略(仍处于 WIP 阶段)和 `Client` 与 `NumPyClient` " "之间的区别。现有的第一和第二部分也得到了改进(许多小改动和修正)。" -#: ../../source/ref-changelog.md:412 +#: ../../source/ref-changelog.md:539 msgid "v1.0.0 (2022-07-28)" msgstr "v1.0.0 (2022-07-28)" -#: ../../source/ref-changelog.md:414 +#: ../../source/ref-changelog.md:541 msgid "Highlights" msgstr "亮点" -#: ../../source/ref-changelog.md:416 +#: ../../source/ref-changelog.md:543 msgid "Stable **Virtual Client Engine** (accessible via `start_simulation`)" msgstr "稳定的**虚拟客户端引擎**(可通过`start_simulation`访问)" -#: ../../source/ref-changelog.md:417 +#: ../../source/ref-changelog.md:544 msgid "All `Client`/`NumPyClient` methods are now optional" msgstr "所有 `Client`/`NumPyClient` 方法现在都是可选的了" -#: ../../source/ref-changelog.md:418 +#: ../../source/ref-changelog.md:545 msgid "Configurable `get_parameters`" msgstr "可配置的`get_parameters`" -#: ../../source/ref-changelog.md:419 +#: ../../source/ref-changelog.md:546 msgid "" -"Tons of small API cleanups resulting in a more coherent developer experience" +"Tons of small API cleanups resulting in a more coherent developer " +"experience" msgstr "对大量小型应用程序接口进行了清理,使开发人员的体验更加一致" -#: ../../source/ref-changelog.md:423 +#: ../../source/ref-changelog.md:550 msgid "" "We would like to give our **special thanks** to all the contributors who " -"made Flower 1.0 possible (in reverse [GitHub Contributors](https://github." -"com/adap/flower/graphs/contributors) order):" -msgstr "" -"在此,我们谨向所有促成 Flower 1.0 的贡献者致以**特别的谢意(按[GitHub 贡献者]" -"(https://github.com/adap/flower/graphs/contributors) 倒序排列):" - -#: ../../source/ref-changelog.md:425 -msgid "" -"[@rtaiello](https://github.com/rtaiello), [@g-pichler](https://github.com/g-" -"pichler), [@rob-luke](https://github.com/rob-luke), [@andreea-zaharia]" -"(https://github.com/andreea-zaharia), [@kinshukdua](https://github.com/" -"kinshukdua), [@nfnt](https://github.com/nfnt), [@tatiana-s](https://github." -"com/tatiana-s), [@TParcollet](https://github.com/TParcollet), [@vballoli]" -"(https://github.com/vballoli), [@negedng](https://github.com/negedng), " -"[@RISHIKESHAVAN](https://github.com/RISHIKESHAVAN), [@hei411](https://github." -"com/hei411), [@SebastianSpeitel](https://github.com/SebastianSpeitel), " -"[@AmitChaulwar](https://github.com/AmitChaulwar), [@Rubiel1](https://github." -"com/Rubiel1), [@FANTOME-PAN](https://github.com/FANTOME-PAN), [@Rono-BC]" -"(https://github.com/Rono-BC), [@lbhm](https://github.com/lbhm), [@sishtiaq]" -"(https://github.com/sishtiaq), [@remde](https://github.com/remde), [@Jueun-" -"Park](https://github.com/Jueun-Park), [@architjen](https://github.com/" -"architjen), [@PratikGarai](https://github.com/PratikGarai), [@mrinaald]" -"(https://github.com/mrinaald), [@zliel](https://github.com/zliel), " -"[@MeiruiJiang](https://github.com/MeiruiJiang), [@sandracl72](https://github." -"com/sandracl72), [@gubertoli](https://github.com/gubertoli), [@Vingt100]" -"(https://github.com/Vingt100), [@MakGulati](https://github.com/MakGulati), " -"[@cozek](https://github.com/cozek), [@jafermarq](https://github.com/" -"jafermarq), [@sisco0](https://github.com/sisco0), [@akhilmathurs](https://" -"github.com/akhilmathurs), [@CanTuerk](https://github.com/CanTuerk), " -"[@mariaboerner1987](https://github.com/mariaboerner1987), [@pedropgusmao]" -"(https://github.com/pedropgusmao), [@tanertopal](https://github.com/" -"tanertopal), [@danieljanes](https://github.com/danieljanes)." -msgstr "" -"[@rtaiello](https://github.com/rtaiello), [@g-pichler](https://github.com/" -"g-pichler), [@rob-luke](https://github.com/rob-luke), [@andreea-" -"zaharia](https://github.com/andreea-zaharia), [@kinshukdua](https://github." -"com/kinshukdua), [@nfnt](https://github.com/nfnt), " -"[@tatiana-s](https://github.com/tatiana-s), [@TParcollet](https://github.com/" -"TParcollet), [@vballoli](https://github.com/vballoli), " -"[@negedng](https://github.com/negedng), [@RISHIKESHAVAN](https://github.com/" -"RISHIKESHAVAN), [@hei411](https://github.com/hei411), " +"made Flower 1.0 possible (in reverse [GitHub " +"Contributors](https://github.com/adap/flower/graphs/contributors) order):" +msgstr "" +"在此,我们谨向所有促成 Flower 1.0 的贡献者致以**特别的谢意(按[GitHub " +"贡献者](https://github.com/adap/flower/graphs/contributors) 倒序排列):" + +#: ../../source/ref-changelog.md:552 +msgid "" +"[@rtaiello](https://github.com/rtaiello), " +"[@g-pichler](https://github.com/g-pichler), [@rob-" +"luke](https://github.com/rob-luke), [@andreea-zaharia](https://github.com" +"/andreea-zaharia), [@kinshukdua](https://github.com/kinshukdua), " +"[@nfnt](https://github.com/nfnt), " +"[@tatiana-s](https://github.com/tatiana-s), " +"[@TParcollet](https://github.com/TParcollet), " +"[@vballoli](https://github.com/vballoli), " +"[@negedng](https://github.com/negedng), " +"[@RISHIKESHAVAN](https://github.com/RISHIKESHAVAN), " +"[@hei411](https://github.com/hei411), " "[@SebastianSpeitel](https://github.com/SebastianSpeitel), " -"[@AmitChaulwar](https://github.com/AmitChaulwar), [@Rubiel1](https://github." -"com/Rubiel1), [@FANTOME-PAN](https://github.com/FANTOME-PAN), [@Rono-" -"BC](https://github.com/Rono-BC), [@lbhm](https://github.com/lbhm), " -"[@sishtiaq](https://github.com/sishtiaq), [@remde](https://github.com/remde)" -", [@Jueun-Park](https://github.com/Jueun-Park), [@architjen](https://github." -"com/architjen), [@PratikGarai](https://github.com/PratikGarai), " -"[@mrinaald](https://github.com/mrinaald), [@zliel](https://github.com/zliel)" -", [@MeiruiJiang](https://github.com/MeiruiJiang), " -"[@sandracl72](https://github.com/sandracl72), [@gubertoli](https://github." -"com/gubertoli), [@Vingt100](https://github.com/Vingt100), " -"[@MakGulati](https://github.com/MakGulati), [@cozek](https://github.com/" -"cozek), [@jafermarq](https://github.com/jafermarq), [@sisco0](https://github." -"com/sisco0), [@akhilmathurs](https://github.com/akhilmathurs), " -"[@CanTuerk](https://github.com/CanTuerk), [@mariaboerner1987](https://github." -"com/mariaboerner1987), [@pedropgusmao](https://github.com/pedropgusmao), " -"[@tanertopal](https://github.com/tanertopal), [@danieljanes](https://github." -"com/danieljanes)." - -#: ../../source/ref-changelog.md:429 -msgid "" -"**All arguments must be passed as keyword arguments** ([#1338](https://" -"github.com/adap/flower/pull/1338))" -msgstr "" -"** 所有参数必须作为关键字参数传递** ([#1338](https://github.com/adap/flower/" -"pull/1338))" - -#: ../../source/ref-changelog.md:431 -msgid "" -"Pass all arguments as keyword arguments, positional arguments are not longer " -"supported. Code that uses positional arguments (e.g., " -"`start_client(\"127.0.0.1:8080\", FlowerClient())`) must add the keyword for " -"each positional argument (e.g., " -"`start_client(server_address=\"127.0.0.1:8080\", client=FlowerClient())`)." -msgstr "" -"以关键字参数传递所有参数,不再支持位置参数。使用位置参数的代码(例如," -"`start_client(\"127.0.0.1:8080\", FlowerClient())`)必须为每个位置参数添加关" -"键字(例如,`start_client(server_address=\"127.0.0.1:8080\", " -"client=FlowerClient())`)。" - -#: ../../source/ref-changelog.md:433 +"[@AmitChaulwar](https://github.com/AmitChaulwar), " +"[@Rubiel1](https://github.com/Rubiel1), [@FANTOME-PAN](https://github.com" +"/FANTOME-PAN), [@Rono-BC](https://github.com/Rono-BC), " +"[@lbhm](https://github.com/lbhm), " +"[@sishtiaq](https://github.com/sishtiaq), " +"[@remde](https://github.com/remde), [@Jueun-Park](https://github.com" +"/Jueun-Park), [@architjen](https://github.com/architjen), " +"[@PratikGarai](https://github.com/PratikGarai), " +"[@mrinaald](https://github.com/mrinaald), " +"[@zliel](https://github.com/zliel), " +"[@MeiruiJiang](https://github.com/MeiruiJiang), " +"[@sandracl72](https://github.com/sandracl72), " +"[@gubertoli](https://github.com/gubertoli), " +"[@Vingt100](https://github.com/Vingt100), " +"[@MakGulati](https://github.com/MakGulati), " +"[@cozek](https://github.com/cozek), " +"[@jafermarq](https://github.com/jafermarq), " +"[@sisco0](https://github.com/sisco0), " +"[@akhilmathurs](https://github.com/akhilmathurs), " +"[@CanTuerk](https://github.com/CanTuerk), " +"[@mariaboerner1987](https://github.com/mariaboerner1987), " +"[@pedropgusmao](https://github.com/pedropgusmao), " +"[@tanertopal](https://github.com/tanertopal), " +"[@danieljanes](https://github.com/danieljanes)." +msgstr "" +"[@rtaiello](https://github.com/rtaiello), " +"[@g-pichler](https://github.com/g-pichler), [@rob-" +"luke](https://github.com/rob-luke), [@andreea-zaharia](https://github.com" +"/andreea-zaharia), [@kinshukdua](https://github.com/kinshukdua), " +"[@nfnt](https://github.com/nfnt), " +"[@tatiana-s](https://github.com/tatiana-s), " +"[@TParcollet](https://github.com/TParcollet), " +"[@vballoli](https://github.com/vballoli), " +"[@negedng](https://github.com/negedng), " +"[@RISHIKESHAVAN](https://github.com/RISHIKESHAVAN), " +"[@hei411](https://github.com/hei411), " +"[@SebastianSpeitel](https://github.com/SebastianSpeitel), " +"[@AmitChaulwar](https://github.com/AmitChaulwar), " +"[@Rubiel1](https://github.com/Rubiel1), [@FANTOME-PAN](https://github.com" +"/FANTOME-PAN), [@Rono-BC](https://github.com/Rono-BC), " +"[@lbhm](https://github.com/lbhm), " +"[@sishtiaq](https://github.com/sishtiaq), " +"[@remde](https://github.com/remde), [@Jueun-Park](https://github.com" +"/Jueun-Park), [@architjen](https://github.com/architjen), " +"[@PratikGarai](https://github.com/PratikGarai), " +"[@mrinaald](https://github.com/mrinaald), " +"[@zliel](https://github.com/zliel), " +"[@MeiruiJiang](https://github.com/MeiruiJiang), " +"[@sandracl72](https://github.com/sandracl72), " +"[@gubertoli](https://github.com/gubertoli), " +"[@Vingt100](https://github.com/Vingt100), " +"[@MakGulati](https://github.com/MakGulati), " +"[@cozek](https://github.com/cozek), " +"[@jafermarq](https://github.com/jafermarq), " +"[@sisco0](https://github.com/sisco0), " +"[@akhilmathurs](https://github.com/akhilmathurs), " +"[@CanTuerk](https://github.com/CanTuerk), " +"[@mariaboerner1987](https://github.com/mariaboerner1987), " +"[@pedropgusmao](https://github.com/pedropgusmao), " +"[@tanertopal](https://github.com/tanertopal), " +"[@danieljanes](https://github.com/danieljanes)." + +#: ../../source/ref-changelog.md:556 +msgid "" +"**All arguments must be passed as keyword arguments** " +"([#1338](https://github.com/adap/flower/pull/1338))" +msgstr "** 所有参数必须作为关键字参数传递** ([#1338](https://github.com/adap/flower/pull/1338))" + +#: ../../source/ref-changelog.md:558 +msgid "" +"Pass all arguments as keyword arguments, positional arguments are not " +"longer supported. Code that uses positional arguments (e.g., " +"`start_client(\"127.0.0.1:8080\", FlowerClient())`) must add the keyword " +"for each positional argument (e.g., " +"`start_client(server_address=\"127.0.0.1:8080\", " +"client=FlowerClient())`)." +msgstr "" +"以关键字参数传递所有参数,不再支持位置参数。使用位置参数的代码(例如,`start_client(\"127.0.0.1:8080\", " +"FlowerClient())`)必须为每个位置参数添加关键字(例如,`start_client(server_address=\"127.0.0.1:8080\"," +" client=FlowerClient())`)。" + +#: ../../source/ref-changelog.md:560 msgid "" "**Introduce configuration object** `ServerConfig` **in** `start_server` " -"**and** `start_simulation` ([#1317](https://github.com/adap/flower/" -"pull/1317))" +"**and** `start_simulation` " +"([#1317](https://github.com/adap/flower/pull/1317))" msgstr "" "**在*** `start_server` ***和*** `start_simulation` 中引入配置对象*** " "`ServerConfig` ([#1317](https://github.com/adap/flower/pull/1317))" -#: ../../source/ref-changelog.md:435 +#: ../../source/ref-changelog.md:562 msgid "" -"Instead of a config dictionary `{\"num_rounds\": 3, \"round_timeout\": 600.0}" -"`, `start_server` and `start_simulation` now expect a configuration object " -"of type `flwr.server.ServerConfig`. `ServerConfig` takes the same arguments " -"that as the previous config dict, but it makes writing type-safe code easier " -"and the default parameters values more transparent." +"Instead of a config dictionary `{\"num_rounds\": 3, \"round_timeout\": " +"600.0}`, `start_server` and `start_simulation` now expect a configuration" +" object of type `flwr.server.ServerConfig`. `ServerConfig` takes the same" +" arguments that as the previous config dict, but it makes writing type-" +"safe code easier and the default parameters values more transparent." msgstr "" -"并非配置字典`{\"num_rounds\": 3, \"round_timeout\": 600.0}`, `start_server`" -"和 `start_simulation`现在用一个类型为 `flwr.server." -"ServerConfig`的配置对象。`ServerConfig`接收的参数与之前的 config dict " +"并非配置字典`{\"num_rounds\": 3, \"round_timeout\": 600.0}`, `start_server`和 " +"`start_simulation`现在用一个类型为 " +"`flwr.server.ServerConfig`的配置对象。`ServerConfig`接收的参数与之前的 config dict " "相同,但它使编写类型安全代码变得更容易,默认参数值也更加透明。" -#: ../../source/ref-changelog.md:437 +#: ../../source/ref-changelog.md:564 msgid "" -"**Rename built-in strategy parameters for clarity** ([#1334](https://github." -"com/adap/flower/pull/1334))" -msgstr "" -"**重新命名内置策略参数,使其更加清晰** ([#1334](https://github.com/adap/" -"flower/pull/1334))" +"**Rename built-in strategy parameters for clarity** " +"([#1334](https://github.com/adap/flower/pull/1334))" +msgstr "**重新命名内置策略参数,使其更加清晰** ([#1334](https://github.com/adap/flower/pull/1334))" -#: ../../source/ref-changelog.md:439 +#: ../../source/ref-changelog.md:566 msgid "" "The following built-in strategy parameters were renamed to improve " "readability and consistency with other API's:" msgstr "以下内置策略参数已重新命名,以提高可读性并与其他 API 保持一致:" -#: ../../source/ref-changelog.md:441 +#: ../../source/ref-changelog.md:568 msgid "`fraction_eval` --> `fraction_evaluate`" msgstr "`fraction_eval` --> `fraction_evaluate`" -#: ../../source/ref-changelog.md:442 +#: ../../source/ref-changelog.md:569 msgid "`min_eval_clients` --> `min_evaluate_clients`" msgstr "`min_eval_clients` --> `min_evaluate_clients`" -#: ../../source/ref-changelog.md:443 +#: ../../source/ref-changelog.md:570 msgid "`eval_fn` --> `evaluate_fn`" msgstr "`eval_fn` --> `evaluate_fn`" -#: ../../source/ref-changelog.md:445 +#: ../../source/ref-changelog.md:572 msgid "" -"**Update default arguments of built-in strategies** ([#1278](https://github." -"com/adap/flower/pull/1278))" -msgstr "" -"**更新内置策略的默认参数** ([#1278](https://github.com/adap/flower/" -"pull/1278))" +"**Update default arguments of built-in strategies** " +"([#1278](https://github.com/adap/flower/pull/1278))" +msgstr "**更新内置策略的默认参数** ([#1278](https://github.com/adap/flower/pull/1278))" -#: ../../source/ref-changelog.md:447 +#: ../../source/ref-changelog.md:574 msgid "" "All built-in strategies now use `fraction_fit=1.0` and " -"`fraction_evaluate=1.0`, which means they select *all* currently available " -"clients for training and evaluation. Projects that relied on the previous " -"default values can get the previous behaviour by initializing the strategy " -"in the following way:" +"`fraction_evaluate=1.0`, which means they select *all* currently " +"available clients for training and evaluation. Projects that relied on " +"the previous default values can get the previous behaviour by " +"initializing the strategy in the following way:" msgstr "" -"所有内置策略现在都使用 \"fraction_fit=1.0 \"和 \"fraction_evaluate=1.0\",这" -"意味着它们会选择*所有*当前可用的客户端进行训练和评估。依赖以前默认值的项目可" -"以通过以下方式初始化策略,获得以前的行为:" +"所有内置策略现在都使用 \"fraction_fit=1.0 \"和 " +"\"fraction_evaluate=1.0\",这意味着它们会选择*所有*当前可用的客户端进行训练和评估。依赖以前默认值的项目可以通过以下方式初始化策略,获得以前的行为:" -#: ../../source/ref-changelog.md:449 +#: ../../source/ref-changelog.md:576 msgid "`strategy = FedAvg(fraction_fit=0.1, fraction_evaluate=0.1)`" msgstr "`strategy = FedAvg(fraction_fit=0.1, fraction_evaluate=0.1)`" -#: ../../source/ref-changelog.md:451 +#: ../../source/ref-changelog.md:578 msgid "" -"**Add** `server_round` **to** `Strategy.evaluate` ([#1334](https://github." -"com/adap/flower/pull/1334))" +"**Add** `server_round` **to** `Strategy.evaluate` " +"([#1334](https://github.com/adap/flower/pull/1334))" msgstr "" -"**添加*** `server_round` ***到*** `Strategy.evaluate` ([#1334](https://" -"github.com/adap/flower/pull/1334))" +"**添加*** `server_round` ***到*** `Strategy.evaluate` " +"([#1334](https://github.com/adap/flower/pull/1334))" -#: ../../source/ref-changelog.md:453 +#: ../../source/ref-changelog.md:580 msgid "" -"The `Strategy` method `evaluate` now receives the current round of federated " -"learning/evaluation as the first parameter." +"The `Strategy` method `evaluate` now receives the current round of " +"federated learning/evaluation as the first parameter." msgstr "`Strategy`的`evaluate` 方法现在会接收当前一轮联邦学习/评估作为第一个参数。" -#: ../../source/ref-changelog.md:455 +#: ../../source/ref-changelog.md:582 msgid "" "**Add** `server_round` **and** `config` **parameters to** `evaluate_fn` " "([#1334](https://github.com/adap/flower/pull/1334))" @@ -10210,106 +14259,103 @@ msgstr "" "**将*** `server_round` **和*** `config` **参数添加到*** `evaluate_fn` " "([#1334](https://github.com/adap/flower/pull/1334))" -#: ../../source/ref-changelog.md:457 +#: ../../source/ref-changelog.md:584 msgid "" "The `evaluate_fn` passed to built-in strategies like `FedAvg` now takes " "three parameters: (1) The current round of federated learning/evaluation " -"(`server_round`), (2) the model parameters to evaluate (`parameters`), and " -"(3) a config dictionary (`config`)." +"(`server_round`), (2) the model parameters to evaluate (`parameters`), " +"and (3) a config dictionary (`config`)." msgstr "" -"传递给内置策略(如 `FedAvg`)的 `evaluate_fn` 现在需要三个参数:(1) " -"当前一轮联邦学习/评估 (`server_round`),(2) 要评估的模型参数 " -"(`parameters`),(3) 配置字典 (`config`)。" +"传递给内置策略(如 `FedAvg`)的 `evaluate_fn` 现在需要三个参数:(1) 当前一轮联邦学习/评估 " +"(`server_round`),(2) 要评估的模型参数 (`parameters`),(3) 配置字典 (`config`)。" -#: ../../source/ref-changelog.md:459 +#: ../../source/ref-changelog.md:586 msgid "" -"**Rename** `rnd` **to** `server_round` ([#1321](https://github.com/adap/" -"flower/pull/1321))" +"**Rename** `rnd` **to** `server_round` " +"([#1321](https://github.com/adap/flower/pull/1321))" msgstr "" -"**重新命名** `rnd` ** to** `server_round` ([#1321](https://github.com/adap/" -"flower/pull/1321))" +"**重新命名** `rnd` ** to** `server_round` " +"([#1321](https://github.com/adap/flower/pull/1321))" -#: ../../source/ref-changelog.md:461 +#: ../../source/ref-changelog.md:588 msgid "" "Several Flower methods and functions (`evaluate_fn`, `configure_fit`, " "`aggregate_fit`, `configure_evaluate`, `aggregate_evaluate`) receive the " -"current round of federated learning/evaluation as their first parameter. To " -"improve reaability and avoid confusion with *random*, this parameter has " -"been renamed from `rnd` to `server_round`." +"current round of federated learning/evaluation as their first parameter. " +"To improve reaability and avoid confusion with *random*, this parameter " +"has been renamed from `rnd` to `server_round`." msgstr "" -"几个 Flower 方法和函数(`evaluate_fn`、`configure_fit`、`aggregate_fit`、`con" -"figure_evaluate`、`aggregate_evaluate`)的第一个参数是当前一轮的联邦学习/评估" -"。为提高可重复性并避免与 *random* 混淆,该参数已从 `rnd` 更名为 " -"`server_round`。" +"几个 Flower " +"方法和函数(`evaluate_fn`、`configure_fit`、`aggregate_fit`、`configure_evaluate`、`aggregate_evaluate`)的第一个参数是当前一轮的联邦学习/评估。为提高可重复性并避免与" +" *random* 混淆,该参数已从 `rnd` 更名为 `server_round`。" -#: ../../source/ref-changelog.md:463 +#: ../../source/ref-changelog.md:590 msgid "" -"**Move** `flwr.dataset` **to** `flwr_baselines` ([#1273](https://github.com/" -"adap/flower/pull/1273))" +"**Move** `flwr.dataset` **to** `flwr_baselines` " +"([#1273](https://github.com/adap/flower/pull/1273))" msgstr "" -"**移动*** `flwr.dataset` **到*** `flwr_baselines` ([#1273](https://github." -"com/adap/flower/pull/1273))" +"**移动*** `flwr.dataset` **到*** `flwr_baselines` " +"([#1273](https://github.com/adap/flower/pull/1273))" -#: ../../source/ref-changelog.md:465 -msgid "" -"The experimental package `flwr.dataset` was migrated to Flower Baselines." +#: ../../source/ref-changelog.md:592 +msgid "The experimental package `flwr.dataset` was migrated to Flower Baselines." msgstr "实验软件包 `flwr.dataset` 已迁移至 Flower Baselines。" -#: ../../source/ref-changelog.md:467 +#: ../../source/ref-changelog.md:594 msgid "" -"**Remove experimental strategies** ([#1280](https://github.com/adap/flower/" -"pull/1280))" +"**Remove experimental strategies** " +"([#1280](https://github.com/adap/flower/pull/1280))" msgstr "**删除实验策略** ([#1280](https://github.com/adap/flower/pull/1280))" -#: ../../source/ref-changelog.md:469 +#: ../../source/ref-changelog.md:596 msgid "" "Remove unmaintained experimental strategies (`FastAndSlow`, `FedFSv0`, " "`FedFSv1`)." msgstr "移除未维护的试验性策略(`FastAndSlow`、`FedFSv0`、`FedFSv1`)。" -#: ../../source/ref-changelog.md:471 +#: ../../source/ref-changelog.md:598 msgid "" -"**Rename** `Weights` **to** `NDArrays` ([#1258](https://github.com/adap/" -"flower/pull/1258), [#1259](https://github.com/adap/flower/pull/1259))" +"**Rename** `Weights` **to** `NDArrays` " +"([#1258](https://github.com/adap/flower/pull/1258), " +"[#1259](https://github.com/adap/flower/pull/1259))" msgstr "" -"**重新命名** `Weights` **到** `NDArrays` ([#1258](https://github.com/adap/" -"flower/pull/1258), [#1259](https://github.com/adap/flower/pull/1259))" +"**重新命名** `Weights` **到** `NDArrays` " +"([#1258](https://github.com/adap/flower/pull/1258), " +"[#1259](https://github.com/adap/flower/pull/1259))" -#: ../../source/ref-changelog.md:473 +#: ../../source/ref-changelog.md:600 msgid "" "`flwr.common.Weights` was renamed to `flwr.common.NDArrays` to better " "capture what this type is all about." -msgstr "" -"flwr.common.Weights \"更名为 \"flwr.common.NDArrays\",以更好地反映该类型的含" -"义。" +msgstr "flwr.common.Weights \"更名为 \"flwr.common.NDArrays\",以更好地反映该类型的含义。" -#: ../../source/ref-changelog.md:475 +#: ../../source/ref-changelog.md:602 msgid "" -"**Remove antiquated** `force_final_distributed_eval` **from** `start_server` " -"([#1258](https://github.com/adap/flower/pull/1258), [#1259](https://github." -"com/adap/flower/pull/1259))" +"**Remove antiquated** `force_final_distributed_eval` **from** " +"`start_server` ([#1258](https://github.com/adap/flower/pull/1258), " +"[#1259](https://github.com/adap/flower/pull/1259))" msgstr "" -"**从** `start_server` 中移除过时的** `force_final_distributed_eval` ([#1258]" -"(https://github.com/adap/flower/pull/1258), [#1259](https://github.com/adap/" -"flower/pull/1259))" +"**从** `start_server` 中移除过时的** `force_final_distributed_eval` " +"([#1258](https://github.com/adap/flower/pull/1258), " +"[#1259](https://github.com/adap/flower/pull/1259))" -#: ../../source/ref-changelog.md:477 +#: ../../source/ref-changelog.md:604 msgid "" -"The `start_server` parameter `force_final_distributed_eval` has long been a " -"historic artefact, in this release it is finally gone for good." +"The `start_server` parameter `force_final_distributed_eval` has long been" +" a historic artefact, in this release it is finally gone for good." msgstr "" -"start_server \"参数 \"force_final_distributed_eval \"长期以来一直是个历史遗留" -"问题,在此版本中终于永远消失了。" +"start_server \"参数 \"force_final_distributed_eval " +"\"长期以来一直是个历史遗留问题,在此版本中终于永远消失了。" -#: ../../source/ref-changelog.md:479 +#: ../../source/ref-changelog.md:606 msgid "" -"**Make** `get_parameters` **configurable** ([#1242](https://github.com/adap/" -"flower/pull/1242))" +"**Make** `get_parameters` **configurable** " +"([#1242](https://github.com/adap/flower/pull/1242))" msgstr "" -"**使** `get_parameters` **可配置** ([#1242](https://github.com/adap/flower/" -"pull/1242))" +"**使** `get_parameters` **可配置** " +"([#1242](https://github.com/adap/flower/pull/1242))" -#: ../../source/ref-changelog.md:481 +#: ../../source/ref-changelog.md:608 msgid "" "The `get_parameters` method now accepts a configuration dictionary, just " "like `get_properties`, `fit`, and `evaluate`." @@ -10317,7 +14363,7 @@ msgstr "" "现在,\"get_parameters \"方法与 \"get_properties\"、\"fit \"和 \"evaluate " "\"一样,都接受配置字典。" -#: ../../source/ref-changelog.md:483 +#: ../../source/ref-changelog.md:610 msgid "" "**Replace** `num_rounds` **in** `start_simulation` **with new** `config` " "**parameter** ([#1281](https://github.com/adap/flower/pull/1281))" @@ -10325,119 +14371,115 @@ msgstr "" "**用新的** `config` 参数** 替换** `num_rounds` ** in** `start_simulation` ** " "([#1281](https://github.com/adap/flower/pull/1281))" -#: ../../source/ref-changelog.md:485 +#: ../../source/ref-changelog.md:612 msgid "" "The `start_simulation` function now accepts a configuration dictionary " -"`config` instead of the `num_rounds` integer. This improves the consistency " -"between `start_simulation` and `start_server` and makes transitioning " -"between the two easier." +"`config` instead of the `num_rounds` integer. This improves the " +"consistency between `start_simulation` and `start_server` and makes " +"transitioning between the two easier." msgstr "" -"现在,`start_simulation`(开始模拟)` 函数接受配置字典 `config` 而不是 " -"`num_rounds` 整数。这改进了 `start_simulation` 和 `start_server` 之间的一致" -"性,并使两者之间的转换更容易。" +"现在,`start_simulation`(开始模拟)` 函数接受配置字典 `config` 而不是 `num_rounds` 整数。这改进了 " +"`start_simulation` 和 `start_server` 之间的一致性,并使两者之间的转换更容易。" -#: ../../source/ref-changelog.md:489 +#: ../../source/ref-changelog.md:616 msgid "" -"**Support Python 3.10** ([#1320](https://github.com/adap/flower/pull/1320))" -msgstr "" -"** 支持 Python 3.10** ([#1320](https://github.com/adap/flower/pull/1320))" +"**Support Python 3.10** " +"([#1320](https://github.com/adap/flower/pull/1320))" +msgstr "** 支持 Python 3.10** ([#1320](https://github.com/adap/flower/pull/1320))" -#: ../../source/ref-changelog.md:491 +#: ../../source/ref-changelog.md:618 msgid "" -"The previous Flower release introduced experimental support for Python 3.10, " -"this release declares Python 3.10 support as stable." -msgstr "" -"上一个 Flower 版本引入了对 Python 3.10 的实验支持,而本版本则宣布对 Python " -"3.10 的支持为稳定支持。" +"The previous Flower release introduced experimental support for Python " +"3.10, this release declares Python 3.10 support as stable." +msgstr "上一个 Flower 版本引入了对 Python 3.10 的实验支持,而本版本则宣布对 Python 3.10 的支持为稳定支持。" -#: ../../source/ref-changelog.md:493 +#: ../../source/ref-changelog.md:620 msgid "" -"**Make all** `Client` **and** `NumPyClient` **methods optional** ([#1260]" -"(https://github.com/adap/flower/pull/1260), [#1277](https://github.com/adap/" -"flower/pull/1277))" +"**Make all** `Client` **and** `NumPyClient` **methods optional** " +"([#1260](https://github.com/adap/flower/pull/1260), " +"[#1277](https://github.com/adap/flower/pull/1277))" msgstr "" -"**使所有** `Client` **和** `NumPyClient` **方法成为可选** ([#1260](https://" -"github.com/adap/flower/pull/1260), [#1277](https://github.com/adap/flower/" -"pull/1277))" +"**使所有** `Client` **和** `NumPyClient` **方法成为可选** " +"([#1260](https://github.com/adap/flower/pull/1260), " +"[#1277](https://github.com/adap/flower/pull/1277))" -#: ../../source/ref-changelog.md:495 +#: ../../source/ref-changelog.md:622 msgid "" "The `Client`/`NumPyClient` methods `get_properties`, `get_parameters`, " -"`fit`, and `evaluate` are all optional. This enables writing clients that " -"implement, for example, only `fit`, but no other method. No need to " +"`fit`, and `evaluate` are all optional. This enables writing clients that" +" implement, for example, only `fit`, but no other method. No need to " "implement `evaluate` when using centralized evaluation!" msgstr "" "`Client`/`NumPyClient`的 \"get_properties\"、\"get_parameters\"、\"fit \"和 " -"\"evaluate \"方法都是可选的。这样就可以编写只实现 `fit` " -"而不实现其他方法的客户端。使用集中评估时,无需实现 `evaluate`!" +"\"evaluate \"方法都是可选的。这样就可以编写只实现 `fit` 而不实现其他方法的客户端。使用集中评估时,无需实现 " +"`evaluate`!" -#: ../../source/ref-changelog.md:497 +#: ../../source/ref-changelog.md:624 msgid "" -"**Enable passing a** `Server` **instance to** `start_simulation` ([#1281]" -"(https://github.com/adap/flower/pull/1281))" +"**Enable passing a** `Server` **instance to** `start_simulation` " +"([#1281](https://github.com/adap/flower/pull/1281))" msgstr "" -"**启用向** `start_simulation` 传递** `Server` 实例 ([#1281](https://github." -"com/adap/flower/pull/1281))" +"**启用向** `start_simulation` 传递** `Server` 实例 " +"([#1281](https://github.com/adap/flower/pull/1281))" -#: ../../source/ref-changelog.md:499 +#: ../../source/ref-changelog.md:626 msgid "" -"Similar to `start_server`, `start_simulation` now accepts a full `Server` " -"instance. This enables users to heavily customize the execution of " -"eperiments and opens the door to running, for example, async FL using the " -"Virtual Client Engine." +"Similar to `start_server`, `start_simulation` now accepts a full `Server`" +" instance. This enables users to heavily customize the execution of " +"eperiments and opens the door to running, for example, async FL using the" +" Virtual Client Engine." msgstr "" -"与 `start_server` 类似,`start_simulation` 现在也接受一个完整的 `Server` 实" -"例。这使得用户可以对实验的执行进行大量自定义,并为使用虚拟客户端引擎运行异步 " -"FL 等打开了大门。" +"与 `start_server` 类似,`start_simulation` 现在也接受一个完整的 `Server` " +"实例。这使得用户可以对实验的执行进行大量自定义,并为使用虚拟客户端引擎运行异步 FL 等打开了大门。" -#: ../../source/ref-changelog.md:501 +#: ../../source/ref-changelog.md:628 msgid "" -"**Update code examples** ([#1291](https://github.com/adap/flower/pull/1291), " -"[#1286](https://github.com/adap/flower/pull/1286), [#1282](https://github." -"com/adap/flower/pull/1282))" +"**Update code examples** " +"([#1291](https://github.com/adap/flower/pull/1291), " +"[#1286](https://github.com/adap/flower/pull/1286), " +"[#1282](https://github.com/adap/flower/pull/1282))" msgstr "" -"**更新代码示例** ([#1291](https://github.com/adap/flower/pull/1291), [#1286]" -"(https://github.com/adap/flower/pull/1286), [#1282](https://github.com/adap/" -"flower/pull/1282))" +"**更新代码示例** ([#1291](https://github.com/adap/flower/pull/1291), " +"[#1286](https://github.com/adap/flower/pull/1286), " +"[#1282](https://github.com/adap/flower/pull/1282))" -#: ../../source/ref-changelog.md:503 +#: ../../source/ref-changelog.md:630 msgid "" -"Many code examples received small or even large maintenance updates, among " -"them are" +"Many code examples received small or even large maintenance updates, " +"among them are" msgstr "许多代码示例都进行了小规模甚至大规模的维护更新,其中包括" -#: ../../source/ref-changelog.md:505 +#: ../../source/ref-changelog.md:632 msgid "`scikit-learn`" msgstr "`scikit-learn`" -#: ../../source/ref-changelog.md:506 +#: ../../source/ref-changelog.md:633 msgid "`simulation_pytorch`" msgstr "`simulation_pytorch`" -#: ../../source/ref-changelog.md:507 +#: ../../source/ref-changelog.md:634 msgid "`quickstart_pytorch`" msgstr "`quickstart_pytorch`" -#: ../../source/ref-changelog.md:508 +#: ../../source/ref-changelog.md:635 msgid "`quickstart_simulation`" msgstr "`quickstart_simulation`" -#: ../../source/ref-changelog.md:509 +#: ../../source/ref-changelog.md:636 msgid "`quickstart_tensorflow`" msgstr "`quickstart_tensorflow`" -#: ../../source/ref-changelog.md:510 +#: ../../source/ref-changelog.md:637 msgid "`advanced_tensorflow`" msgstr "`advanced_tensorflow`" -#: ../../source/ref-changelog.md:512 +#: ../../source/ref-changelog.md:639 msgid "" -"**Remove the obsolete simulation example** ([#1328](https://github.com/adap/" -"flower/pull/1328))" -msgstr "" -"**删除过时的模拟示例** ([#1328](https://github.com/adap/flower/pull/1328))" +"**Remove the obsolete simulation example** " +"([#1328](https://github.com/adap/flower/pull/1328))" +msgstr "**删除过时的模拟示例** ([#1328](https://github.com/adap/flower/pull/1328))" -#: ../../source/ref-changelog.md:514 +#: ../../source/ref-changelog.md:641 msgid "" "Removes the obsolete `simulation` example and renames " "`quickstart_simulation` to `simulation_tensorflow` so it fits withs the " @@ -10446,587 +14488,578 @@ msgstr "" "删除过时的 \"simulation \"示例,并将 \"quickstart_simulation \"重命名为 " "\"simulation_tensorflow\",使其与 \"simulation_pytorch \"的命名一致" -#: ../../source/ref-changelog.md:516 -msgid "" -"**Update documentation** ([#1223](https://github.com/adap/flower/pull/1223), " -"[#1209](https://github.com/adap/flower/pull/1209), [#1251](https://github." -"com/adap/flower/pull/1251), [#1257](https://github.com/adap/flower/" -"pull/1257), [#1267](https://github.com/adap/flower/pull/1267), [#1268]" -"(https://github.com/adap/flower/pull/1268), [#1300](https://github.com/adap/" -"flower/pull/1300), [#1304](https://github.com/adap/flower/pull/1304), [#1305]" -"(https://github.com/adap/flower/pull/1305), [#1307](https://github.com/adap/" -"flower/pull/1307))" -msgstr "" -"**更新文档** ([#1223](https://github.com/adap/flower/pull/1223), [#1209]" -"(https://github.com/adap/flower/pull/1209), [#1251](https://github.com/adap/" -"flower/pull/1251), [#1257](https://github.com/adap/flower/pull/1257), [#1267]" -"(https://github.com/adap/flower/pull/1267), [#1268](https://github.com/adap/" -"flower/pull/1268), [#1300](https://github.com/adap/flower/pull/1300), [#1304]" -"(https://github.com/adap/flower/pull/1304), [#1305](https://github.com/adap/" -"flower/pull/1305), [#1307](https://github.com/adap/flower/pull/1307))" - -#: ../../source/ref-changelog.md:518 +#: ../../source/ref-changelog.md:643 +msgid "" +"**Update documentation** " +"([#1223](https://github.com/adap/flower/pull/1223), " +"[#1209](https://github.com/adap/flower/pull/1209), " +"[#1251](https://github.com/adap/flower/pull/1251), " +"[#1257](https://github.com/adap/flower/pull/1257), " +"[#1267](https://github.com/adap/flower/pull/1267), " +"[#1268](https://github.com/adap/flower/pull/1268), " +"[#1300](https://github.com/adap/flower/pull/1300), " +"[#1304](https://github.com/adap/flower/pull/1304), " +"[#1305](https://github.com/adap/flower/pull/1305), " +"[#1307](https://github.com/adap/flower/pull/1307))" +msgstr "" +"**更新文档** ([#1223](https://github.com/adap/flower/pull/1223), " +"[#1209](https://github.com/adap/flower/pull/1209), " +"[#1251](https://github.com/adap/flower/pull/1251), " +"[#1257](https://github.com/adap/flower/pull/1257), " +"[#1267](https://github.com/adap/flower/pull/1267), " +"[#1268](https://github.com/adap/flower/pull/1268), " +"[#1300](https://github.com/adap/flower/pull/1300), " +"[#1304](https://github.com/adap/flower/pull/1304), " +"[#1305](https://github.com/adap/flower/pull/1305), " +"[#1307](https://github.com/adap/flower/pull/1307))" + +#: ../../source/ref-changelog.md:645 msgid "" "One substantial documentation update fixes multiple smaller rendering " "issues, makes titles more succinct to improve navigation, removes a " -"deprecated library, updates documentation dependencies, includes the `flwr." -"common` module in the API reference, includes support for markdown-based " -"documentation, migrates the changelog from `.rst` to `.md`, and fixes a " -"number of smaller details!" -msgstr "" -"其中一个实质性的文档更新修复了多个较小的渲染问题,使标题更加简洁以改善导航," -"删除了一个已废弃的库,更新了文档依赖关系,在 API 参考中包含了 `flwr.common` " -"模块,包含了对基于 markdown 的文档的支持,将更新日志从 `.rst` 移植到了 `." -"md`,并修复了一些较小的细节!" - -#: ../../source/ref-changelog.md:520 ../../source/ref-changelog.md:575 -#: ../../source/ref-changelog.md:644 ../../source/ref-changelog.md:683 +"deprecated library, updates documentation dependencies, includes the " +"`flwr.common` module in the API reference, includes support for markdown-" +"based documentation, migrates the changelog from `.rst` to `.md`, and " +"fixes a number of smaller details!" +msgstr "" +"其中一个实质性的文档更新修复了多个较小的渲染问题,使标题更加简洁以改善导航,删除了一个已废弃的库,更新了文档依赖关系,在 API 参考中包含了 " +"`flwr.common` 模块,包含了对基于 markdown 的文档的支持,将更新日志从 `.rst` 移植到了 " +"`.md`,并修复了一些较小的细节!" + +#: ../../source/ref-changelog.md:647 ../../source/ref-changelog.md:702 +#: ../../source/ref-changelog.md:771 ../../source/ref-changelog.md:810 msgid "**Minor updates**" msgstr "**小规模更新**" -#: ../../source/ref-changelog.md:522 +#: ../../source/ref-changelog.md:649 msgid "" -"Add round number to fit and evaluate log messages ([#1266](https://github." -"com/adap/flower/pull/1266))" -msgstr "" -"添加四舍五入数字,以适应和评估日志信息([#1266](https://github.com/adap/" -"flower/pull/1266))" +"Add round number to fit and evaluate log messages " +"([#1266](https://github.com/adap/flower/pull/1266))" +msgstr "添加四舍五入数字,以适应和评估日志信息([#1266](https://github.com/adap/flower/pull/1266))" -#: ../../source/ref-changelog.md:523 +#: ../../source/ref-changelog.md:650 msgid "" -"Add secure gRPC connection to the `advanced_tensorflow` code example ([#847]" -"(https://github.com/adap/flower/pull/847))" +"Add secure gRPC connection to the `advanced_tensorflow` code example " +"([#847](https://github.com/adap/flower/pull/847))" msgstr "" -"为 `advanced_tensorflow` 代码示例添加安全 gRPC 连接 ([#847](https://github." -"com/adap/flower/pull/847))" +"为 `advanced_tensorflow` 代码示例添加安全 gRPC 连接 " +"([#847](https://github.com/adap/flower/pull/847))" -#: ../../source/ref-changelog.md:524 +#: ../../source/ref-changelog.md:651 msgid "" -"Update developer tooling ([#1231](https://github.com/adap/flower/pull/1231), " -"[#1276](https://github.com/adap/flower/pull/1276), [#1301](https://github." -"com/adap/flower/pull/1301), [#1310](https://github.com/adap/flower/" -"pull/1310))" +"Update developer tooling " +"([#1231](https://github.com/adap/flower/pull/1231), " +"[#1276](https://github.com/adap/flower/pull/1276), " +"[#1301](https://github.com/adap/flower/pull/1301), " +"[#1310](https://github.com/adap/flower/pull/1310))" msgstr "" -"更新开发人员工具([#1231](https://github.com/adap/flower/pull/1231), [#1276]" -"(https://github.com/adap/flower/pull/1276), [#1301](https://github.com/adap/" -"flower/pull/1301), [#1310](https://github.com/adap/flower/pull/1310)" +"更新开发人员工具([#1231](https://github.com/adap/flower/pull/1231), " +"[#1276](https://github.com/adap/flower/pull/1276), " +"[#1301](https://github.com/adap/flower/pull/1301), " +"[#1310](https://github.com/adap/flower/pull/1310)" -#: ../../source/ref-changelog.md:525 +#: ../../source/ref-changelog.md:652 msgid "" -"Rename ProtoBuf messages to improve consistency ([#1214](https://github.com/" -"adap/flower/pull/1214), [#1258](https://github.com/adap/flower/pull/1258), " +"Rename ProtoBuf messages to improve consistency " +"([#1214](https://github.com/adap/flower/pull/1214), " +"[#1258](https://github.com/adap/flower/pull/1258), " "[#1259](https://github.com/adap/flower/pull/1259))" msgstr "" -"重命名 ProtoBuf 消息以提高一致性([#1214](https://github.com/adap/flower/" -"pull/1214), [#1258](https://github.com/adap/flower/pull/1258), [#1259]" -"(https://github.com/adap/flower/pull/1259)" +"重命名 ProtoBuf 消息以提高一致性([#1214](https://github.com/adap/flower/pull/1214), " +"[#1258](https://github.com/adap/flower/pull/1258), " +"[#1259](https://github.com/adap/flower/pull/1259)" -#: ../../source/ref-changelog.md:527 +#: ../../source/ref-changelog.md:654 msgid "v0.19.0 (2022-05-18)" msgstr "v0.19.0 (2022-05-18)" -#: ../../source/ref-changelog.md:531 +#: ../../source/ref-changelog.md:658 msgid "" -"**Flower Baselines (preview): FedOpt, FedBN, FedAvgM** ([#919](https://" -"github.com/adap/flower/pull/919), [#1127](https://github.com/adap/flower/" -"pull/1127), [#914](https://github.com/adap/flower/pull/914))" +"**Flower Baselines (preview): FedOpt, FedBN, FedAvgM** " +"([#919](https://github.com/adap/flower/pull/919), " +"[#1127](https://github.com/adap/flower/pull/1127), " +"[#914](https://github.com/adap/flower/pull/914))" msgstr "" -"**Flower Baselines(预览): FedOpt、FedBN、FedAvgM** ([#919](https://github." -"com/adap/flower/pull/919), [#1127](https://github.com/adap/flower/pull/1127)" -", [#914](https://github.com/adap/flower/pull/914))" +"**Flower Baselines(预览): FedOpt、FedBN、FedAvgM** " +"([#919](https://github.com/adap/flower/pull/919), " +"[#1127](https://github.com/adap/flower/pull/1127), " +"[#914](https://github.com/adap/flower/pull/914))" -#: ../../source/ref-changelog.md:533 +#: ../../source/ref-changelog.md:660 msgid "" "The first preview release of Flower Baselines has arrived! We're " "kickstarting Flower Baselines with implementations of FedOpt (FedYogi, " -"FedAdam, FedAdagrad), FedBN, and FedAvgM. Check the documentation on how to " -"use [Flower Baselines](https://flower.dev/docs/using-baselines.html). With " -"this first preview release we're also inviting the community to [contribute " -"their own baselines](https://flower.dev/docs/contributing-baselines.html)." +"FedAdam, FedAdagrad), FedBN, and FedAvgM. Check the documentation on how " +"to use [Flower Baselines](https://flower.dev/docs/using-baselines.html). " +"With this first preview release we're also inviting the community to " +"[contribute their own baselines](https://flower.dev/docs/contributing-" +"baselines.html)." msgstr "" "Flower Baselines 的第一个预览版已经发布!我们通过实现 " "FedOpt(FedYogi、FedAdam、FedAdagrad)、FedBN 和 FedAvgM 来启动 Flower " -"Baselines。请查阅文档了解如何使用 [Flower Baselines](https://flower.dev/docs/" -"using-baselines.html)。在首次发布预览版时,我们还邀请社区成员[贡献自己的Basel" -"ines](https://flower.dev/docs/contributing-baselines.html)。" +"Baselines。请查阅文档了解如何使用 [Flower Baselines](https://flower.dev/docs/using-" +"baselines.html)。在首次发布预览版时,我们还邀请社区成员[贡献自己的Baselines](https://flower.dev/docs" +"/contributing-baselines.html)。" -#: ../../source/ref-changelog.md:535 +#: ../../source/ref-changelog.md:662 msgid "" -"**C++ client SDK (preview) and code example** ([#1111](https://github.com/" -"adap/flower/pull/1111))" -msgstr "" -"**C++客户端SDK(预览版)和代码示例**([#1111](https://github.com/adap/flower/" -"pull/1111))" +"**C++ client SDK (preview) and code example** " +"([#1111](https://github.com/adap/flower/pull/1111))" +msgstr "**C++客户端SDK(预览版)和代码示例**([#1111](https://github.com/adap/flower/pull/1111))" -#: ../../source/ref-changelog.md:537 +#: ../../source/ref-changelog.md:664 msgid "" -"Preview support for Flower clients written in C++. The C++ preview includes " -"a Flower client SDK and a quickstart code example that demonstrates a simple " -"C++ client using the SDK." +"Preview support for Flower clients written in C++. The C++ preview " +"includes a Flower client SDK and a quickstart code example that " +"demonstrates a simple C++ client using the SDK." msgstr "" -"预览版支持用 C++ 编写的 Flower 客户端。C++ 预览版包括一个 Flower 客户端 SDK " -"和一个快速入门代码示例,使用 SDK 演示了一个简单的 C++ 客户端。" +"预览版支持用 C++ 编写的 Flower 客户端。C++ 预览版包括一个 Flower 客户端 SDK 和一个快速入门代码示例,使用 SDK " +"演示了一个简单的 C++ 客户端。" -#: ../../source/ref-changelog.md:539 +#: ../../source/ref-changelog.md:666 msgid "" -"**Add experimental support for Python 3.10 and Python 3.11** ([#1135]" -"(https://github.com/adap/flower/pull/1135))" +"**Add experimental support for Python 3.10 and Python 3.11** " +"([#1135](https://github.com/adap/flower/pull/1135))" msgstr "" -"** 增加对 Python 3.10 和 Python 3.11 的实验支持** ([#1135](https://github." -"com/adap/flower/pull/1135))" +"** 增加对 Python 3.10 和 Python 3.11 的实验支持** " +"([#1135](https://github.com/adap/flower/pull/1135))" -#: ../../source/ref-changelog.md:541 +#: ../../source/ref-changelog.md:668 msgid "" -"Python 3.10 is the latest stable release of Python and Python 3.11 is due to " -"be released in October. This Flower release adds experimental support for " -"both Python versions." +"Python 3.10 is the latest stable release of Python and Python 3.11 is due" +" to be released in October. This Flower release adds experimental support" +" for both Python versions." msgstr "" -"Python 3.10 是 Python 的最新稳定版本,Python 3.11 将于 10 月份发布。Flower 版" -"本增加了对这两个 Python 版本的实验支持。" +"Python 3.10 是 Python 的最新稳定版本,Python 3.11 将于 10 月份发布。Flower 版本增加了对这两个 " +"Python 版本的实验支持。" -#: ../../source/ref-changelog.md:543 +#: ../../source/ref-changelog.md:670 msgid "" -"**Aggregate custom metrics through user-provided functions** ([#1144]" -"(https://github.com/adap/flower/pull/1144))" -msgstr "" -"**通过用户提供的函数聚合自定义指标**([#1144](https://github.com/adap/flower/" -"pull/1144))" +"**Aggregate custom metrics through user-provided functions** " +"([#1144](https://github.com/adap/flower/pull/1144))" +msgstr "**通过用户提供的函数聚合自定义指标**([#1144](https://github.com/adap/flower/pull/1144))" -#: ../../source/ref-changelog.md:545 +#: ../../source/ref-changelog.md:672 msgid "" -"Custom metrics (e.g., `accuracy`) can now be aggregated without having to " -"customize the strategy. Built-in strategies support two new arguments, " +"Custom metrics (e.g., `accuracy`) can now be aggregated without having to" +" customize the strategy. Built-in strategies support two new arguments, " "`fit_metrics_aggregation_fn` and `evaluate_metrics_aggregation_fn`, that " "allow passing custom metric aggregation functions." msgstr "" -"现在无需定制策略即可聚合自定义度量(如`准确度`)。内置策略支持两个新参数:" -"`fit_metrics_aggregation_fn` 和`evaluate_metrics_aggregation_fn`,允许传递自" -"定义度量聚合函数。" +"现在无需定制策略即可聚合自定义度量(如`准确度`)。内置策略支持两个新参数:`fit_metrics_aggregation_fn` " +"和`evaluate_metrics_aggregation_fn`,允许传递自定义度量聚合函数。" -#: ../../source/ref-changelog.md:547 +#: ../../source/ref-changelog.md:674 msgid "" -"**User-configurable round timeout** ([#1162](https://github.com/adap/flower/" -"pull/1162))" -msgstr "" -"**用户可配置的回合超时**([#1162](https://github.com/adap/flower/pull/1162))" +"**User-configurable round timeout** " +"([#1162](https://github.com/adap/flower/pull/1162))" +msgstr "**用户可配置的回合超时**([#1162](https://github.com/adap/flower/pull/1162))" -#: ../../source/ref-changelog.md:549 +#: ../../source/ref-changelog.md:676 msgid "" "A new configuration value allows the round timeout to be set for " -"`start_server` and `start_simulation`. If the `config` dictionary contains a " -"`round_timeout` key (with a `float` value in seconds), the server will wait " -"*at least* `round_timeout` seconds before it closes the connection." +"`start_server` and `start_simulation`. If the `config` dictionary " +"contains a `round_timeout` key (with a `float` value in seconds), the " +"server will wait *at least* `round_timeout` seconds before it closes the " +"connection." msgstr "" -"新的配置值允许为 `start_server` 和 `start_simulation` 设置回合超时。如果 " -"`config` 字典中包含一个 `round_timeout` 键(以秒为单位的 `float`值),服务器" -"将至少等待 ** `round_timeout` 秒后才关闭连接。" +"新的配置值允许为 `start_server` 和 `start_simulation` 设置回合超时。如果 `config` 字典中包含一个 " +"`round_timeout` 键(以秒为单位的 `float`值),服务器将至少等待 ** `round_timeout` 秒后才关闭连接。" -#: ../../source/ref-changelog.md:551 +#: ../../source/ref-changelog.md:678 msgid "" -"**Enable both federated evaluation and centralized evaluation to be used at " -"the same time in all built-in strategies** ([#1091](https://github.com/adap/" -"flower/pull/1091))" +"**Enable both federated evaluation and centralized evaluation to be used " +"at the same time in all built-in strategies** " +"([#1091](https://github.com/adap/flower/pull/1091))" msgstr "" -"**允许在所有内置策略中同时使用联邦评价和集中评估** ([#1091](https://github." -"com/adap/flower/pull/1091))" +"**允许在所有内置策略中同时使用联邦评价和集中评估** " +"([#1091](https://github.com/adap/flower/pull/1091))" -#: ../../source/ref-changelog.md:553 +#: ../../source/ref-changelog.md:680 msgid "" -"Built-in strategies can now perform both federated evaluation (i.e., client-" -"side) and centralized evaluation (i.e., server-side) in the same round. " -"Federated evaluation can be disabled by setting `fraction_eval` to `0.0`." +"Built-in strategies can now perform both federated evaluation (i.e., " +"client-side) and centralized evaluation (i.e., server-side) in the same " +"round. Federated evaluation can be disabled by setting `fraction_eval` to" +" `0.0`." msgstr "" -"内置策略现在可以在同一轮中同时执行联邦评估(即客户端)和集中评估(即服务器端" -")。可以通过将 `fraction_eval` 设置为 `0.0`来禁用联邦评估。" +"内置策略现在可以在同一轮中同时执行联邦评估(即客户端)和集中评估(即服务器端)。可以通过将 `fraction_eval` 设置为 " +"`0.0`来禁用联邦评估。" -#: ../../source/ref-changelog.md:555 +#: ../../source/ref-changelog.md:682 msgid "" -"**Two new Jupyter Notebook tutorials** ([#1141](https://github.com/adap/" -"flower/pull/1141))" +"**Two new Jupyter Notebook tutorials** " +"([#1141](https://github.com/adap/flower/pull/1141))" msgstr "" -"**两本新的 Jupyter Notebook 教程** ([#1141](https://github.com/adap/flower/" -"pull/1141))" +"**两本新的 Jupyter Notebook 教程** " +"([#1141](https://github.com/adap/flower/pull/1141))" -#: ../../source/ref-changelog.md:557 +#: ../../source/ref-changelog.md:684 msgid "" -"Two Jupyter Notebook tutorials (compatible with Google Colab) explain basic " -"and intermediate Flower features:" -msgstr "" -"两本 Jupyter Notebook 教程(与 Google Colab 兼容)介绍了 Flower 的基本和中级" -"功能:" +"Two Jupyter Notebook tutorials (compatible with Google Colab) explain " +"basic and intermediate Flower features:" +msgstr "两本 Jupyter Notebook 教程(与 Google Colab 兼容)介绍了 Flower 的基本和中级功能:" -#: ../../source/ref-changelog.md:559 +#: ../../source/ref-changelog.md:686 msgid "" -"*An Introduction to Federated Learning*: [Open in Colab](https://colab." -"research.google.com/github/adap/flower/blob/main/tutorials/Flower-1-Intro-to-" -"FL-PyTorch.ipynb)" +"*An Introduction to Federated Learning*: [Open in " +"Colab](https://colab.research.google.com/github/adap/flower/blob/main/tutorials/Flower-1" +"-Intro-to-FL-PyTorch.ipynb)" msgstr "" -"*联邦学习简介*: [在 Colab 中打开](https://colab.research.google.com/github/" -"adap/flower/blob/main/tutorials/Flower-1-Intro-to-FL-PyTorch.ipynb)" +"*联邦学习简介*: [在 Colab " +"中打开](https://colab.research.google.com/github/adap/flower/blob/main/tutorials/Flower-1" +"-Intro-to-FL-PyTorch.ipynb)" -#: ../../source/ref-changelog.md:561 +#: ../../source/ref-changelog.md:688 msgid "" -"*Using Strategies in Federated Learning*: [Open in Colab](https://colab." -"research.google.com/github/adap/flower/blob/main/tutorials/Flower-2-" -"Strategies-in-FL-PyTorch.ipynb)" +"*Using Strategies in Federated Learning*: [Open in " +"Colab](https://colab.research.google.com/github/adap/flower/blob/main/tutorials/Flower-2" +"-Strategies-in-FL-PyTorch.ipynb)" msgstr "" -"*在联邦学习中使用策略*: [在 Colab 中打开](https://colab.research.google.com/" -"github/adap/flower/blob/main/tutorials/Flower-2-Strategies-in-FL-PyTorch." -"ipynb)" +"*在联邦学习中使用策略*: [在 Colab " +"中打开](https://colab.research.google.com/github/adap/flower/blob/main/tutorials/Flower-2" +"-Strategies-in-FL-PyTorch.ipynb)" -#: ../../source/ref-changelog.md:563 +#: ../../source/ref-changelog.md:690 msgid "" -"**New FedAvgM strategy (Federated Averaging with Server Momentum)** ([#1076]" -"(https://github.com/adap/flower/pull/1076))" +"**New FedAvgM strategy (Federated Averaging with Server Momentum)** " +"([#1076](https://github.com/adap/flower/pull/1076))" msgstr "" -"**新的 FedAvgM 策略(带服务器动量的联邦平均)** ([#1076](https://github.com/" -"adap/flower/pull/1076))" +"**新的 FedAvgM 策略(带服务器动量的联邦平均)** " +"([#1076](https://github.com/adap/flower/pull/1076))" -#: ../../source/ref-changelog.md:565 +#: ../../source/ref-changelog.md:692 msgid "" "The new `FedAvgM` strategy implements Federated Averaging with Server " "Momentum \\[Hsu et al., 2019\\]." msgstr "新的 \"FedAvgM \"策略实现了带服务器动量的联邦平均[Hsu et al., 2019\\]." -#: ../../source/ref-changelog.md:567 +#: ../../source/ref-changelog.md:694 msgid "" -"**New advanced PyTorch code example** ([#1007](https://github.com/adap/" -"flower/pull/1007))" -msgstr "" -"**新的 PyTorch 高级代码示例** ([#1007](https://github.com/adap/flower/" -"pull/1007))" +"**New advanced PyTorch code example** " +"([#1007](https://github.com/adap/flower/pull/1007))" +msgstr "**新的 PyTorch 高级代码示例** ([#1007](https://github.com/adap/flower/pull/1007))" -#: ../../source/ref-changelog.md:569 +#: ../../source/ref-changelog.md:696 msgid "" "A new code example (`advanced_pytorch`) demonstrates advanced Flower " "concepts with PyTorch." msgstr "新代码示例 (`advanced_pytorch`) 演示了 PyTorch 的高级 Flower 概念。" -#: ../../source/ref-changelog.md:571 +#: ../../source/ref-changelog.md:698 msgid "" -"**New JAX code example** ([#906](https://github.com/adap/flower/pull/906), " +"**New JAX code example** " +"([#906](https://github.com/adap/flower/pull/906), " "[#1143](https://github.com/adap/flower/pull/1143))" msgstr "" "**新的 JAX 代码示例**([#906](https://github.com/adap/flower/pull/906), " "[#1143](https://github.com/adap/flower/pull/1143)" -#: ../../source/ref-changelog.md:573 +#: ../../source/ref-changelog.md:700 msgid "" "A new code example (`jax_from_centralized_to_federated`) shows federated " "learning with JAX and Flower." -msgstr "" -"新代码示例(`jax_from_centralized_to_federated`)展示了使用 JAX 和 Flower 的" -"联邦学习。" +msgstr "新代码示例(`jax_from_centralized_to_federated`)展示了使用 JAX 和 Flower 的联邦学习。" -#: ../../source/ref-changelog.md:577 +#: ../../source/ref-changelog.md:704 msgid "" "New option to keep Ray running if Ray was already initialized in " "`start_simulation` ([#1177](https://github.com/adap/flower/pull/1177))" msgstr "" -"新增选项,用于在 \"start_simulation\"(开始模拟)中已初始化 Ray 的情况下保持 " -"Ray 运行([#1177](https://github.com/adap/flower/pull/1177))" +"新增选项,用于在 \"start_simulation\"(开始模拟)中已初始化 Ray 的情况下保持 Ray " +"运行([#1177](https://github.com/adap/flower/pull/1177))" -#: ../../source/ref-changelog.md:578 +#: ../../source/ref-changelog.md:705 msgid "" "Add support for custom `ClientManager` as a `start_simulation` parameter " "([#1171](https://github.com/adap/flower/pull/1171))" msgstr "" -"添加对自定义 \"客户端管理器 \"作为 \"start_simulation \"参数的支持([#1171]" -"(https://github.com/adap/flower/pull/1171))" +"添加对自定义 \"客户端管理器 \"作为 \"start_simulation " +"\"参数的支持([#1171](https://github.com/adap/flower/pull/1171))" -#: ../../source/ref-changelog.md:579 +#: ../../source/ref-changelog.md:706 msgid "" -"New documentation for [implementing strategies](https://flower.dev/docs/" -"framework/how-to-implement-strategies.html) ([#1097](https://github.com/adap/" -"flower/pull/1097), [#1175](https://github.com/adap/flower/pull/1175))" +"New documentation for [implementing " +"strategies](https://flower.dev/docs/framework/how-to-implement-" +"strategies.html) ([#1097](https://github.com/adap/flower/pull/1097), " +"[#1175](https://github.com/adap/flower/pull/1175))" msgstr "" -"[实施战略](https://flower.dev/docs/framework/how-to-implement-strategies." -"html) 的新文件([#1097](https://github.com/adap/flower/pull/1097), " +"[实施战略](https://flower.dev/docs/framework/how-to-implement-" +"strategies.html) 的新文件([#1097](https://github.com/adap/flower/pull/1097), " "[#1175](https://github.com/adap/flower/pull/1175)" -#: ../../source/ref-changelog.md:580 +#: ../../source/ref-changelog.md:707 msgid "" -"New mobile-friendly documentation theme ([#1174](https://github.com/adap/" -"flower/pull/1174))" -msgstr "" -"新的移动友好型文档主题 ([#1174](https://github.com/adap/flower/pull/1174))" +"New mobile-friendly documentation theme " +"([#1174](https://github.com/adap/flower/pull/1174))" +msgstr "新的移动友好型文档主题 ([#1174](https://github.com/adap/flower/pull/1174))" -#: ../../source/ref-changelog.md:581 +#: ../../source/ref-changelog.md:708 msgid "" "Limit version range for (optional) `ray` dependency to include only " -"compatible releases (`>=1.9.2,<1.12.0`) ([#1205](https://github.com/adap/" -"flower/pull/1205))" +"compatible releases (`>=1.9.2,<1.12.0`) " +"([#1205](https://github.com/adap/flower/pull/1205))" msgstr "" "限制(可选)`ray`依赖的版本范围,使其仅包含兼容版本(`>=1.9.2,<1.12.0`) " "([#1205](https://github.com/adap/flower/pull/1205))" -#: ../../source/ref-changelog.md:585 +#: ../../source/ref-changelog.md:712 msgid "" -"**Remove deprecated support for Python 3.6** ([#871](https://github.com/adap/" -"flower/pull/871))" -msgstr "" -"**删除对 Python 3.6 的过时支持** ([#871](https://github.com/adap/flower/" -"pull/871))" +"**Remove deprecated support for Python 3.6** " +"([#871](https://github.com/adap/flower/pull/871))" +msgstr "**删除对 Python 3.6 的过时支持** ([#871](https://github.com/adap/flower/pull/871))" -#: ../../source/ref-changelog.md:586 +#: ../../source/ref-changelog.md:713 msgid "" -"**Remove deprecated KerasClient** ([#857](https://github.com/adap/flower/" -"pull/857))" -msgstr "" -"**移除过时的 KerasClient**([#857](https://github.com/adap/flower/pull/857))" +"**Remove deprecated KerasClient** " +"([#857](https://github.com/adap/flower/pull/857))" +msgstr "**移除过时的 KerasClient**([#857](https://github.com/adap/flower/pull/857))" -#: ../../source/ref-changelog.md:587 +#: ../../source/ref-changelog.md:714 msgid "" -"**Remove deprecated no-op extra installs** ([#973](https://github.com/adap/" -"flower/pull/973))" -msgstr "" -"**移除过时的不操作额外安装** ([#973](https://github.com/adap/flower/" -"pull/973))" +"**Remove deprecated no-op extra installs** " +"([#973](https://github.com/adap/flower/pull/973))" +msgstr "**移除过时的不操作额外安装** ([#973](https://github.com/adap/flower/pull/973))" -#: ../../source/ref-changelog.md:588 +#: ../../source/ref-changelog.md:715 msgid "" "**Remove deprecated proto fields from** `FitRes` **and** `EvaluateRes` " "([#869](https://github.com/adap/flower/pull/869))" msgstr "" -"**从** `FitRes` **和** `EvaluateRes` 中移除已废弃的 proto 字段 ([#869]" -"(https://github.com/adap/flower/pull/869))" +"**从** `FitRes` **和** `EvaluateRes` 中移除已废弃的 proto 字段 " +"([#869](https://github.com/adap/flower/pull/869))" -#: ../../source/ref-changelog.md:589 +#: ../../source/ref-changelog.md:716 msgid "" -"**Remove deprecated QffedAvg strategy (replaced by QFedAvg)** ([#1107]" -"(https://github.com/adap/flower/pull/1107))" +"**Remove deprecated QffedAvg strategy (replaced by QFedAvg)** " +"([#1107](https://github.com/adap/flower/pull/1107))" msgstr "" -"**移除过时的 QffedAvg 策略(由 QFedAvg 取代)** ([#1107](https://github.com/" -"adap/flower/pull/1107))" +"**移除过时的 QffedAvg 策略(由 QFedAvg 取代)** " +"([#1107](https://github.com/adap/flower/pull/1107))" -#: ../../source/ref-changelog.md:590 +#: ../../source/ref-changelog.md:717 msgid "" -"**Remove deprecated DefaultStrategy strategy** ([#1142](https://github.com/" -"adap/flower/pull/1142))" +"**Remove deprecated DefaultStrategy strategy** " +"([#1142](https://github.com/adap/flower/pull/1142))" msgstr "" -"**删除过时的 DefaultStrategy 策略** ([#1142](https://github.com/adap/flower/" -"pull/1142))" +"**删除过时的 DefaultStrategy 策略** " +"([#1142](https://github.com/adap/flower/pull/1142))" -#: ../../source/ref-changelog.md:591 +#: ../../source/ref-changelog.md:718 msgid "" -"**Remove deprecated support for eval_fn accuracy return value** ([#1142]" -"(https://github.com/adap/flower/pull/1142))" +"**Remove deprecated support for eval_fn accuracy return value** " +"([#1142](https://github.com/adap/flower/pull/1142))" msgstr "" -"**删除已过时的对 eval_fn 返回值准确性的支持** ([#1142](https://github.com/" -"adap/flower/pull/1142))" +"**删除已过时的对 eval_fn 返回值准确性的支持** " +"([#1142](https://github.com/adap/flower/pull/1142))" -#: ../../source/ref-changelog.md:592 +#: ../../source/ref-changelog.md:719 msgid "" "**Remove deprecated support for passing initial parameters as NumPy " "ndarrays** ([#1142](https://github.com/adap/flower/pull/1142))" msgstr "" -"**移除对以 NumPy ndarrays 传递初始参数的过时支持** ([#1142](https://github." -"com/adap/flower/pull/1142))" +"**移除对以 NumPy ndarrays 传递初始参数的过时支持** " +"([#1142](https://github.com/adap/flower/pull/1142))" -#: ../../source/ref-changelog.md:594 +#: ../../source/ref-changelog.md:721 msgid "v0.18.0 (2022-02-28)" msgstr "v0.18.0 (2022-02-28)" -#: ../../source/ref-changelog.md:598 +#: ../../source/ref-changelog.md:725 msgid "" "**Improved Virtual Client Engine compatibility with Jupyter Notebook / " -"Google Colab** ([#866](https://github.com/adap/flower/pull/866), [#872]" -"(https://github.com/adap/flower/pull/872), [#833](https://github.com/adap/" -"flower/pull/833), [#1036](https://github.com/adap/flower/pull/1036))" +"Google Colab** ([#866](https://github.com/adap/flower/pull/866), " +"[#872](https://github.com/adap/flower/pull/872), " +"[#833](https://github.com/adap/flower/pull/833), " +"[#1036](https://github.com/adap/flower/pull/1036))" msgstr "" -"**改进了虚拟客户端引擎与 Jupyter Notebook / Google Colab 的兼容性** ([#866]" -"(https://github.com/adap/flower/pull/866), [#872](https://github.com/adap/" -"flower/pull/872), [#833](https://github.com/adap/flower/pull/833), [#1036]" -"(https://github.com/adap/flower/pull/1036))" +"**改进了虚拟客户端引擎与 Jupyter Notebook / Google Colab 的兼容性** " +"([#866](https://github.com/adap/flower/pull/866), " +"[#872](https://github.com/adap/flower/pull/872), " +"[#833](https://github.com/adap/flower/pull/833), " +"[#1036](https://github.com/adap/flower/pull/1036))" -#: ../../source/ref-changelog.md:600 +#: ../../source/ref-changelog.md:727 msgid "" -"Simulations (using the Virtual Client Engine through `start_simulation`) now " -"work more smoothly on Jupyter Notebooks (incl. Google Colab) after " +"Simulations (using the Virtual Client Engine through `start_simulation`) " +"now work more smoothly on Jupyter Notebooks (incl. Google Colab) after " "installing Flower with the `simulation` extra (`pip install " "flwr[simulation]`)." msgstr "" -"通过 `start_simulation` 在 Jupyter 笔记本(包括 Google Colab)上安装 Flower " -"并附加 `simulation` (`pip install flwr[simulation]`)后,模拟(通过 " -"`start_simulation` 使用虚拟客户端引擎)现在可以更流畅地运行。" +"通过 `start_simulation` 在 Jupyter 笔记本(包括 Google Colab)上安装 Flower 并附加 " +"`simulation` (`pip install flwr[simulation]`)后,模拟(通过 `start_simulation` " +"使用虚拟客户端引擎)现在可以更流畅地运行。" -#: ../../source/ref-changelog.md:602 +#: ../../source/ref-changelog.md:729 msgid "" -"**New Jupyter Notebook code example** ([#833](https://github.com/adap/flower/" -"pull/833))" +"**New Jupyter Notebook code example** " +"([#833](https://github.com/adap/flower/pull/833))" msgstr "" -"**新的 Jupyter Notebook 代码示例** ([#833](https://github.com/adap/flower/" -"pull/833))" +"**新的 Jupyter Notebook 代码示例** " +"([#833](https://github.com/adap/flower/pull/833))" -#: ../../source/ref-changelog.md:604 +#: ../../source/ref-changelog.md:731 msgid "" -"A new code example (`quickstart_simulation`) demonstrates Flower simulations " -"using the Virtual Client Engine through Jupyter Notebook (incl. Google " -"Colab)." +"A new code example (`quickstart_simulation`) demonstrates Flower " +"simulations using the Virtual Client Engine through Jupyter Notebook " +"(incl. Google Colab)." msgstr "" "新代码示例(`quickstart_simulation`)通过 Jupyter Notebook(包括 Google " "Colab)演示了使用虚拟客户端引擎进行 Flower 模拟。" -#: ../../source/ref-changelog.md:606 +#: ../../source/ref-changelog.md:733 msgid "" -"**Client properties (feature preview)** ([#795](https://github.com/adap/" -"flower/pull/795))" -msgstr "" -"**客户端属性(功能预览)** ([#795](https://github.com/adap/flower/pull/795))" +"**Client properties (feature preview)** " +"([#795](https://github.com/adap/flower/pull/795))" +msgstr "**客户端属性(功能预览)** ([#795](https://github.com/adap/flower/pull/795))" -#: ../../source/ref-changelog.md:608 +#: ../../source/ref-changelog.md:735 msgid "" -"Clients can implement a new method `get_properties` to enable server-side " -"strategies to query client properties." -msgstr "" -"客户端可以实现一个新方法 `get_properties`,以启用服务器端策略来查询客户端属" -"性。" +"Clients can implement a new method `get_properties` to enable server-side" +" strategies to query client properties." +msgstr "客户端可以实现一个新方法 `get_properties`,以启用服务器端策略来查询客户端属性。" -#: ../../source/ref-changelog.md:610 +#: ../../source/ref-changelog.md:737 msgid "" -"**Experimental Android support with TFLite** ([#865](https://github.com/adap/" -"flower/pull/865))" -msgstr "" -"** 使用 TFLite 实验性支持安卓系统** ([#865](https://github.com/adap/flower/" -"pull/865))" +"**Experimental Android support with TFLite** " +"([#865](https://github.com/adap/flower/pull/865))" +msgstr "** 使用 TFLite 实验性支持安卓系统** ([#865](https://github.com/adap/flower/pull/865))" -#: ../../source/ref-changelog.md:612 +#: ../../source/ref-changelog.md:739 msgid "" "Android support has finally arrived in `main`! Flower is both client-" "agnostic and framework-agnostic by design. One can integrate arbitrary " -"client platforms and with this release, using Flower on Android has become a " -"lot easier." +"client platforms and with this release, using Flower on Android has " +"become a lot easier." msgstr "" -"`main`终于支持 Android 了!Flower " -"的设计与客户端和框架无关。我们可以集成任意客户端平台,有了这个版本," -"在安卓系统上使用 Flower 就变得更容易了。" +"`main`终于支持 Android 了!Flower 的设计与客户端和框架无关。我们可以集成任意客户端平台,有了这个版本,在安卓系统上使用 " +"Flower 就变得更容易了。" -#: ../../source/ref-changelog.md:614 +#: ../../source/ref-changelog.md:741 msgid "" -"The example uses TFLite on the client side, along with a new `FedAvgAndroid` " -"strategy. The Android client and `FedAvgAndroid` are still experimental, but " -"they are a first step towards a fully-fledged Android SDK and a unified " -"`FedAvg` implementation that integrated the new functionality from " -"`FedAvgAndroid`." +"The example uses TFLite on the client side, along with a new " +"`FedAvgAndroid` strategy. The Android client and `FedAvgAndroid` are " +"still experimental, but they are a first step towards a fully-fledged " +"Android SDK and a unified `FedAvg` implementation that integrated the new" +" functionality from `FedAvgAndroid`." msgstr "" "该示例在客户端使用了 TFLite 以及新的 `FedAvgAndroid`策略。Android 客户端和 " -"`FedAvgAndroid`仍处于试验阶段,但这是向成熟的 Android SDK 和集成了 " -"`FedAvgAndroid`新功能的统一 `FedAvg`实现迈出的第一步。" +"`FedAvgAndroid`仍处于试验阶段,但这是向成熟的 Android SDK 和集成了 `FedAvgAndroid`新功能的统一 " +"`FedAvg`实现迈出的第一步。" -#: ../../source/ref-changelog.md:616 +#: ../../source/ref-changelog.md:743 msgid "" -"**Make gRPC keepalive time user-configurable and decrease default keepalive " -"time** ([#1069](https://github.com/adap/flower/pull/1069))" +"**Make gRPC keepalive time user-configurable and decrease default " +"keepalive time** ([#1069](https://github.com/adap/flower/pull/1069))" msgstr "" -"**使 gRPC 保持连接时间可由用户配置,并缩短默认保持连接时间** ([#1069]" -"(https://github.com/adap/flower/pull/1069))" +"**使 gRPC 保持连接时间可由用户配置,并缩短默认保持连接时间** " +"([#1069](https://github.com/adap/flower/pull/1069))" -#: ../../source/ref-changelog.md:618 +#: ../../source/ref-changelog.md:745 msgid "" "The default gRPC keepalive time has been reduced to increase the " -"compatibility of Flower with more cloud environments (for example, Microsoft " -"Azure). Users can configure the keepalive time to customize the gRPC stack " -"based on specific requirements." +"compatibility of Flower with more cloud environments (for example, " +"Microsoft Azure). Users can configure the keepalive time to customize the" +" gRPC stack based on specific requirements." msgstr "" -"为提高 Flower 与更多云环境(如 Microsoft Azure)的兼容性,缩短了默认 gRPC 保" -"持时间。用户可以根据具体要求配置 keepalive 时间,自定义 gRPC 堆栈。" +"为提高 Flower 与更多云环境(如 Microsoft Azure)的兼容性,缩短了默认 gRPC 保持时间。用户可以根据具体要求配置 " +"keepalive 时间,自定义 gRPC 堆栈。" -#: ../../source/ref-changelog.md:620 +#: ../../source/ref-changelog.md:747 msgid "" -"**New differential privacy example using Opacus and PyTorch** ([#805]" -"(https://github.com/adap/flower/pull/805))" +"**New differential privacy example using Opacus and PyTorch** " +"([#805](https://github.com/adap/flower/pull/805))" msgstr "" -"**使用 Opacus 和 PyTorch 的新差分隐私示例** ([#805](https://github.com/adap/" -"flower/pull/805))" +"**使用 Opacus 和 PyTorch 的新差分隐私示例** " +"([#805](https://github.com/adap/flower/pull/805))" -#: ../../source/ref-changelog.md:622 +#: ../../source/ref-changelog.md:749 msgid "" -"A new code example (`opacus`) demonstrates differentially-private federated " -"learning with Opacus, PyTorch, and Flower." -msgstr "一个新的代码示例(\"opacus\")演示了使用 Opacus、PyTorch 和 Flower " -"进行差分隐私的联邦学习。" +"A new code example (`opacus`) demonstrates differentially-private " +"federated learning with Opacus, PyTorch, and Flower." +msgstr "一个新的代码示例(\"opacus\")演示了使用 Opacus、PyTorch 和 Flower 进行差分隐私的联邦学习。" -#: ../../source/ref-changelog.md:624 +#: ../../source/ref-changelog.md:751 msgid "" -"**New Hugging Face Transformers code example** ([#863](https://github.com/" -"adap/flower/pull/863))" +"**New Hugging Face Transformers code example** " +"([#863](https://github.com/adap/flower/pull/863))" msgstr "" -"**新的Hugging Face Transformers代码示例** ([#863](https://github.com/adap/" -"flower/pull/863))" +"**新的Hugging Face Transformers代码示例** " +"([#863](https://github.com/adap/flower/pull/863))" -#: ../../source/ref-changelog.md:626 +#: ../../source/ref-changelog.md:753 msgid "" -"A new code example (`quickstart_huggingface`) demonstrates usage of Hugging " -"Face Transformers with Flower." -msgstr "" -"新的代码示例(`quickstart_huggingface`)证明了结合Flower和Hugging Face " -"Transformers的实用性。" +"A new code example (`quickstart_huggingface`) demonstrates usage of " +"Hugging Face Transformers with Flower." +msgstr "新的代码示例(`quickstart_huggingface`)证明了结合Flower和Hugging Face Transformers的实用性。" -#: ../../source/ref-changelog.md:628 +#: ../../source/ref-changelog.md:755 msgid "" -"**New MLCube code example** ([#779](https://github.com/adap/flower/" -"pull/779), [#1034](https://github.com/adap/flower/pull/1034), [#1065]" -"(https://github.com/adap/flower/pull/1065), [#1090](https://github.com/adap/" -"flower/pull/1090))" +"**New MLCube code example** " +"([#779](https://github.com/adap/flower/pull/779), " +"[#1034](https://github.com/adap/flower/pull/1034), " +"[#1065](https://github.com/adap/flower/pull/1065), " +"[#1090](https://github.com/adap/flower/pull/1090))" msgstr "" "**新的 MLCube 代码示例** ([#779](https://github.com/adap/flower/pull/779), " -"[#1034](https://github.com/adap/flower/pull/1034), [#1065](https://github." -"com/adap/flower/pull/1065), [#1090](https://github.com/adap/flower/" -"pull/1090))" +"[#1034](https://github.com/adap/flower/pull/1034), " +"[#1065](https://github.com/adap/flower/pull/1065), " +"[#1090](https://github.com/adap/flower/pull/1090))" -#: ../../source/ref-changelog.md:630 +#: ../../source/ref-changelog.md:757 msgid "" -"A new code example (`quickstart_mlcube`) demonstrates usage of MLCube with " -"Flower." +"A new code example (`quickstart_mlcube`) demonstrates usage of MLCube " +"with Flower." msgstr "新代码示例(\"quickstart_mlcube\")演示了 MLCube 与 Flower 的用法。" -#: ../../source/ref-changelog.md:632 +#: ../../source/ref-changelog.md:759 msgid "" -"**SSL-enabled server and client** ([#842](https://github.com/adap/flower/" -"pull/842), [#844](https://github.com/adap/flower/pull/844), [#845](https://" -"github.com/adap/flower/pull/845), [#847](https://github.com/adap/flower/" -"pull/847), [#993](https://github.com/adap/flower/pull/993), [#994](https://" -"github.com/adap/flower/pull/994))" +"**SSL-enabled server and client** " +"([#842](https://github.com/adap/flower/pull/842), " +"[#844](https://github.com/adap/flower/pull/844), " +"[#845](https://github.com/adap/flower/pull/845), " +"[#847](https://github.com/adap/flower/pull/847), " +"[#993](https://github.com/adap/flower/pull/993), " +"[#994](https://github.com/adap/flower/pull/994))" msgstr "" -"** 支持 SSL 的服务器和客户端** ([#842](https://github.com/adap/flower/" -"pull/842), [#844](https://github.com/adap/flower/pull/844), [#845](https://" -"github.com/adap/flower/pull/845), [#847](https://github.com/adap/flower/" -"pull/847), [#993](https://github.com/adap/flower/pull/993), [#994](https://" -"github.com/adap/flower/pull/994))" +"** 支持 SSL 的服务器和客户端** ([#842](https://github.com/adap/flower/pull/842), " +"[#844](https://github.com/adap/flower/pull/844), " +"[#845](https://github.com/adap/flower/pull/845), " +"[#847](https://github.com/adap/flower/pull/847), " +"[#993](https://github.com/adap/flower/pull/993), " +"[#994](https://github.com/adap/flower/pull/994))" -#: ../../source/ref-changelog.md:634 +#: ../../source/ref-changelog.md:761 msgid "" -"SSL enables secure encrypted connections between clients and servers. This " -"release open-sources the Flower secure gRPC implementation to make encrypted " -"communication channels accessible to all Flower users." -msgstr "" -"SSL 可实现客户端与服务器之间的安全加密连接。该版本开源了 Flower 安全 gRPC 实" -"现,使所有 Flower 用户都能访问加密通信通道。" +"SSL enables secure encrypted connections between clients and servers. " +"This release open-sources the Flower secure gRPC implementation to make " +"encrypted communication channels accessible to all Flower users." +msgstr "SSL 可实现客户端与服务器之间的安全加密连接。该版本开源了 Flower 安全 gRPC 实现,使所有 Flower 用户都能访问加密通信通道。" -#: ../../source/ref-changelog.md:636 +#: ../../source/ref-changelog.md:763 msgid "" -"**Updated** `FedAdam` **and** `FedYogi` **strategies** ([#885](https://" -"github.com/adap/flower/pull/885), [#895](https://github.com/adap/flower/" -"pull/895))" +"**Updated** `FedAdam` **and** `FedYogi` **strategies** " +"([#885](https://github.com/adap/flower/pull/885), " +"[#895](https://github.com/adap/flower/pull/895))" msgstr "" -"**更新**`FedAdam`**和**`FedYogi`**战略** ([#885](https://github.com/adap/" -"flower/pull/885), [#895](https://github.com/adap/flower/pull/895))" +"**更新**`FedAdam`**和**`FedYogi`**战略** " +"([#885](https://github.com/adap/flower/pull/885), " +"[#895](https://github.com/adap/flower/pull/895))" -#: ../../source/ref-changelog.md:638 +#: ../../source/ref-changelog.md:765 msgid "" -"`FedAdam` and `FedAdam` match the latest version of the Adaptive Federated " -"Optimization paper." +"`FedAdam` and `FedAdam` match the latest version of the Adaptive " +"Federated Optimization paper." msgstr "FedAdam \"和 \"FedAdam \"与最新版本的 \"自适应联邦优化 \"论文相匹配。" -#: ../../source/ref-changelog.md:640 +#: ../../source/ref-changelog.md:767 msgid "" -"**Initialize** `start_simulation` **with a list of client IDs** ([#860]" -"(https://github.com/adap/flower/pull/860))" +"**Initialize** `start_simulation` **with a list of client IDs** " +"([#860](https://github.com/adap/flower/pull/860))" msgstr "" -"**初始化** `start_simulation` **使用客户端 ID 列表** ([#860](https://github." -"com/adap/flower/pull/860))" +"**初始化** `start_simulation` **使用客户端 ID 列表** " +"([#860](https://github.com/adap/flower/pull/860))" -#: ../../source/ref-changelog.md:642 +#: ../../source/ref-changelog.md:769 msgid "" "`start_simulation` can now be called with a list of client IDs " "(`clients_ids`, type: `List[str]`). Those IDs will be passed to the " @@ -11035,301 +15068,270 @@ msgid "" "identifiers." msgstr "" "现在可以使用客户端 ID 列表(`clients_ids`,类型:`List[str]`)调用 " -"`start_simulation`。每当需要初始化客户端时,这些 ID 就会被传递到 `client_fn` " -"中,这样就能更轻松地加载无法通过 `int` 标识符访问的数据分区。" +"`start_simulation`。每当需要初始化客户端时,这些 ID 就会被传递到 `client_fn` 中,这样就能更轻松地加载无法通过 " +"`int` 标识符访问的数据分区。" -#: ../../source/ref-changelog.md:646 +#: ../../source/ref-changelog.md:773 msgid "" -"Update `num_examples` calculation in PyTorch code examples in ([#909]" -"(https://github.com/adap/flower/pull/909))" +"Update `num_examples` calculation in PyTorch code examples in " +"([#909](https://github.com/adap/flower/pull/909))" msgstr "" -"更新 PyTorch 代码示例中的 \"num_examples \"计算 ([#909](https://github.com/" -"adap/flower/pull/909))" +"更新 PyTorch 代码示例中的 \"num_examples \"计算 " +"([#909](https://github.com/adap/flower/pull/909))" -#: ../../source/ref-changelog.md:647 +#: ../../source/ref-changelog.md:774 msgid "" -"Expose Flower version through `flwr.__version__` ([#952](https://github.com/" -"adap/flower/pull/952))" +"Expose Flower version through `flwr.__version__` " +"([#952](https://github.com/adap/flower/pull/952))" msgstr "" -"通过 `flwr.__version__` 公开 Flower 版本 ([#952](https://github.com/adap/" -"flower/pull/952))" +"通过 `flwr.__version__` 公开 Flower 版本 " +"([#952](https://github.com/adap/flower/pull/952))" -#: ../../source/ref-changelog.md:648 +#: ../../source/ref-changelog.md:775 msgid "" -"`start_server` in `app.py` now returns a `History` object containing metrics " -"from training ([#974](https://github.com/adap/flower/pull/974))" +"`start_server` in `app.py` now returns a `History` object containing " +"metrics from training ([#974](https://github.com/adap/flower/pull/974))" msgstr "" "`app.py`中的 `start_server`现在会返回一个 `History` " "对象,其中包含训练中的指标([#974](https://github.com/adap/flower/pull/974))" -#: ../../source/ref-changelog.md:649 +#: ../../source/ref-changelog.md:776 msgid "" -"Make `max_workers` (used by `ThreadPoolExecutor`) configurable ([#978]" -"(https://github.com/adap/flower/pull/978))" +"Make `max_workers` (used by `ThreadPoolExecutor`) configurable " +"([#978](https://github.com/adap/flower/pull/978))" msgstr "" -"使 `max_workers`(由 `ThreadPoolExecutor`使用)可配置([#978](https://github." -"com/adap/flower/pull/978))" +"使 `max_workers`(由 " +"`ThreadPoolExecutor`使用)可配置([#978](https://github.com/adap/flower/pull/978))" -#: ../../source/ref-changelog.md:650 +#: ../../source/ref-changelog.md:777 msgid "" -"Increase sleep time after server start to three seconds in all code examples " -"([#1086](https://github.com/adap/flower/pull/1086))" -msgstr "" -"在所有代码示例中,将服务器启动后的休眠时间延长至三秒([#1086](https://github." -"com/adap/flower/pull/1086))" +"Increase sleep time after server start to three seconds in all code " +"examples ([#1086](https://github.com/adap/flower/pull/1086))" +msgstr "在所有代码示例中,将服务器启动后的休眠时间延长至三秒([#1086](https://github.com/adap/flower/pull/1086))" -#: ../../source/ref-changelog.md:651 +#: ../../source/ref-changelog.md:778 msgid "" -"Added a new FAQ section to the documentation ([#948](https://github.com/adap/" -"flower/pull/948))" -msgstr "" -"在文档中添加了新的常见问题部分 ([#948](https://github.com/adap/flower/" -"pull/948))" +"Added a new FAQ section to the documentation " +"([#948](https://github.com/adap/flower/pull/948))" +msgstr "在文档中添加了新的常见问题部分 ([#948](https://github.com/adap/flower/pull/948))" -#: ../../source/ref-changelog.md:652 +#: ../../source/ref-changelog.md:779 msgid "" "And many more under-the-hood changes, library updates, documentation " "changes, and tooling improvements!" msgstr "还有更多底层更改、库更新、文档更改和工具改进!" -#: ../../source/ref-changelog.md:656 +#: ../../source/ref-changelog.md:783 msgid "" "**Removed** `flwr_example` **and** `flwr_experimental` **from release " "build** ([#869](https://github.com/adap/flower/pull/869))" msgstr "" -"**从发布版中删除**`flwr_example`**和**`flwr_experimental`** ([#869](https://" -"github.com/adap/flower/pull/869))" +"**从发布版中删除**`flwr_example`**和**`flwr_experimental`** " +"([#869](https://github.com/adap/flower/pull/869))" -#: ../../source/ref-changelog.md:658 +#: ../../source/ref-changelog.md:785 msgid "" "The packages `flwr_example` and `flwr_experimental` have been deprecated " "since Flower 0.12.0 and they are not longer included in Flower release " "builds. The associated extras (`baseline`, `examples-pytorch`, `examples-" -"tensorflow`, `http-logger`, `ops`) are now no-op and will be removed in an " -"upcoming release." +"tensorflow`, `http-logger`, `ops`) are now no-op and will be removed in " +"an upcoming release." msgstr "" -"自 Flower 0.12.0 起,软件包 `flwr_example` 和 `flwr_experimental` 已被弃用," -"它们不再包含在 Flower 的发布版本中。相关的额外包(`baseline`, `examples-" -"pytorch`, `examples-tensorflow`, `http-logger`, `ops`)现在已不再使用,并将在" -"即将发布的版本中移除。" +"自 Flower 0.12.0 起,软件包 `flwr_example` 和 `flwr_experimental` 已被弃用,它们不再包含在 " +"Flower 的发布版本中。相关的额外包(`baseline`, `examples-pytorch`, `examples-" +"tensorflow`, `http-logger`, `ops`)现在已不再使用,并将在即将发布的版本中移除。" -#: ../../source/ref-changelog.md:660 +#: ../../source/ref-changelog.md:787 msgid "v0.17.0 (2021-09-24)" msgstr "v0.17.0 (2021-09-24)" -#: ../../source/ref-changelog.md:664 +#: ../../source/ref-changelog.md:791 msgid "" -"**Experimental virtual client engine** ([#781](https://github.com/adap/" -"flower/pull/781) [#790](https://github.com/adap/flower/pull/790) [#791]" -"(https://github.com/adap/flower/pull/791))" +"**Experimental virtual client engine** " +"([#781](https://github.com/adap/flower/pull/781) " +"[#790](https://github.com/adap/flower/pull/790) " +"[#791](https://github.com/adap/flower/pull/791))" msgstr "" "**实验性虚拟客户端引擎** ([#781](https://github.com/adap/flower/pull/781) " -"[#790](https://github.com/adap/flower/pull/790) [#791](https://github.com/" -"adap/flower/pull/791))" +"[#790](https://github.com/adap/flower/pull/790) " +"[#791](https://github.com/adap/flower/pull/791))" -#: ../../source/ref-changelog.md:666 +#: ../../source/ref-changelog.md:793 msgid "" -"One of Flower's goals is to enable research at scale. This release enables a " -"first (experimental) peek at a major new feature, codenamed the virtual " -"client engine. Virtual clients enable simulations that scale to a (very) " -"large number of clients on a single machine or compute cluster. The easiest " -"way to test the new functionality is to look at the two new code examples " -"called `quickstart_simulation` and `simulation_pytorch`." +"One of Flower's goals is to enable research at scale. This release " +"enables a first (experimental) peek at a major new feature, codenamed the" +" virtual client engine. Virtual clients enable simulations that scale to " +"a (very) large number of clients on a single machine or compute cluster. " +"The easiest way to test the new functionality is to look at the two new " +"code examples called `quickstart_simulation` and `simulation_pytorch`." msgstr "" -"Flower 的目标之一是实现大规模研究。这一版本首次(试验性地)展示了代号为 " -"\"虚拟客户端引擎 \"的重要新功能" -"。虚拟客户端可以在单台机器或计算集群上对大量客户端进行模拟。" -"测试新功能的最简单方法是查看名为 \"quickstart_simulation \"和 " -"\"simulation_pytorch \"的两个新代码示例。" +"Flower 的目标之一是实现大规模研究。这一版本首次(试验性地)展示了代号为 \"虚拟客户端引擎 " +"\"的重要新功能。虚拟客户端可以在单台机器或计算集群上对大量客户端进行模拟。测试新功能的最简单方法是查看名为 " +"\"quickstart_simulation \"和 \"simulation_pytorch \"的两个新代码示例。" -#: ../../source/ref-changelog.md:668 +#: ../../source/ref-changelog.md:795 msgid "" -"The feature is still experimental, so there's no stability guarantee for the " -"API. It's also not quite ready for prime time and comes with a few known " -"caveats. However, those who are curious are encouraged to try it out and " -"share their thoughts." +"The feature is still experimental, so there's no stability guarantee for " +"the API. It's also not quite ready for prime time and comes with a few " +"known caveats. However, those who are curious are encouraged to try it " +"out and share their thoughts." msgstr "" -"该功能仍处于试验阶段,因此无法保证 API 的稳定性。此外,它还没有完全准备好进入" -"黄金时间,并有一些已知的注意事项。不过,我们鼓励好奇的用户尝试使用并分享他们" -"的想法。" +"该功能仍处于试验阶段,因此无法保证 API " +"的稳定性。此外,它还没有完全准备好进入黄金时间,并有一些已知的注意事项。不过,我们鼓励好奇的用户尝试使用并分享他们的想法。" -#: ../../source/ref-changelog.md:670 +#: ../../source/ref-changelog.md:797 msgid "" -"**New built-in strategies** ([#828](https://github.com/adap/flower/pull/828) " +"**New built-in strategies** " +"([#828](https://github.com/adap/flower/pull/828) " "[#822](https://github.com/adap/flower/pull/822))" msgstr "" -"**新的内置策略**([#828](https://github.com/adap/flower/pull/828) [#822]" -"(https://github.com/adap/flower/pull/822)" +"**新的内置策略**([#828](https://github.com/adap/flower/pull/828) " +"[#822](https://github.com/adap/flower/pull/822)" -#: ../../source/ref-changelog.md:672 +#: ../../source/ref-changelog.md:799 msgid "" "FedYogi - Federated learning strategy using Yogi on server-side. " "Implementation based on https://arxiv.org/abs/2003.00295" -msgstr "FedYogi - 在服务器端使用 Yogi 的联邦学习策略。基于 https://arxiv.org/abs/" -"2003.00295 实现" +msgstr "FedYogi - 在服务器端使用 Yogi 的联邦学习策略。基于 https://arxiv.org/abs/2003.00295 实现" -#: ../../source/ref-changelog.md:673 +#: ../../source/ref-changelog.md:800 msgid "" "FedAdam - Federated learning strategy using Adam on server-side. " "Implementation based on https://arxiv.org/abs/2003.00295" -msgstr "" -"FedAdam - 在服务器端使用 Adam 的联邦学习策略。基于 https://arxiv.org/" -"abs/2003.00295 实现" +msgstr "FedAdam - 在服务器端使用 Adam 的联邦学习策略。基于 https://arxiv.org/abs/2003.00295 实现" -#: ../../source/ref-changelog.md:675 +#: ../../source/ref-changelog.md:802 msgid "" -"**New PyTorch Lightning code example** ([#617](https://github.com/adap/" -"flower/pull/617))" +"**New PyTorch Lightning code example** " +"([#617](https://github.com/adap/flower/pull/617))" msgstr "" -"**新的 PyTorch Lightning 代码示例** ([#617](https://github.com/adap/flower/" -"pull/617))" +"**新的 PyTorch Lightning 代码示例** " +"([#617](https://github.com/adap/flower/pull/617))" -#: ../../source/ref-changelog.md:677 +#: ../../source/ref-changelog.md:804 msgid "" -"**New Variational Auto-Encoder code example** ([#752](https://github.com/" -"adap/flower/pull/752))" -msgstr "" -"**新的变分自动编码器代码示例** ([#752](https://github.com/adap/flower/" -"pull/752))" +"**New Variational Auto-Encoder code example** " +"([#752](https://github.com/adap/flower/pull/752))" +msgstr "**新的变分自动编码器代码示例** ([#752](https://github.com/adap/flower/pull/752))" -#: ../../source/ref-changelog.md:679 +#: ../../source/ref-changelog.md:806 msgid "" -"**New scikit-learn code example** ([#748](https://github.com/adap/flower/" -"pull/748))" -msgstr "" -"**新的 scikit-learn 代码示例** ([#748](https://github.com/adap/flower/" -"pull/748))" +"**New scikit-learn code example** " +"([#748](https://github.com/adap/flower/pull/748))" +msgstr "**新的 scikit-learn 代码示例** ([#748](https://github.com/adap/flower/pull/748))" -#: ../../source/ref-changelog.md:681 +#: ../../source/ref-changelog.md:808 msgid "" -"**New experimental TensorBoard strategy** ([#789](https://github.com/adap/" -"flower/pull/789))" -msgstr "" -"**新的实验性 TensorBoard 策略**([#789](https://github.com/adap/flower/" -"pull/789))" +"**New experimental TensorBoard strategy** " +"([#789](https://github.com/adap/flower/pull/789))" +msgstr "**新的实验性 TensorBoard 策略**([#789](https://github.com/adap/flower/pull/789))" -#: ../../source/ref-changelog.md:685 +#: ../../source/ref-changelog.md:812 msgid "" -"Improved advanced TensorFlow code example ([#769](https://github.com/adap/" -"flower/pull/769))" -msgstr "" -"改进的高级 TensorFlow 代码示例([#769](https://github.com/adap/flower/" -"pull/769)" +"Improved advanced TensorFlow code example " +"([#769](https://github.com/adap/flower/pull/769))" +msgstr "改进的高级 TensorFlow 代码示例([#769](https://github.com/adap/flower/pull/769)" -#: ../../source/ref-changelog.md:686 +#: ../../source/ref-changelog.md:813 msgid "" -"Warning when `min_available_clients` is misconfigured ([#830](https://github." -"com/adap/flower/pull/830))" +"Warning when `min_available_clients` is misconfigured " +"([#830](https://github.com/adap/flower/pull/830))" msgstr "" -"当 `min_available_clients` 配置错误时发出警告 ([#830](https://github.com/" -"adap/flower/pull/830))" +"当 `min_available_clients` 配置错误时发出警告 " +"([#830](https://github.com/adap/flower/pull/830))" -#: ../../source/ref-changelog.md:687 +#: ../../source/ref-changelog.md:814 msgid "" -"Improved gRPC server docs ([#841](https://github.com/adap/flower/pull/841))" -msgstr "" -"改进了 gRPC 服务器文档([#841](https://github.com/adap/flower/pull/841))" +"Improved gRPC server docs " +"([#841](https://github.com/adap/flower/pull/841))" +msgstr "改进了 gRPC 服务器文档([#841](https://github.com/adap/flower/pull/841))" -#: ../../source/ref-changelog.md:688 +#: ../../source/ref-changelog.md:815 msgid "" -"Improved error message in `NumPyClient` ([#851](https://github.com/adap/" -"flower/pull/851))" -msgstr "" -"改进了 `NumPyClient` 中的错误信息 ([#851](https://github.com/adap/flower/" -"pull/851))" +"Improved error message in `NumPyClient` " +"([#851](https://github.com/adap/flower/pull/851))" +msgstr "改进了 `NumPyClient` 中的错误信息 ([#851](https://github.com/adap/flower/pull/851))" -#: ../../source/ref-changelog.md:689 +#: ../../source/ref-changelog.md:816 msgid "" -"Improved PyTorch quickstart code example ([#852](https://github.com/adap/" -"flower/pull/852))" -msgstr "" -"改进的 PyTorch 快速启动代码示例 ([#852](https://github.com/adap/flower/" -"pull/852))" +"Improved PyTorch quickstart code example " +"([#852](https://github.com/adap/flower/pull/852))" +msgstr "改进的 PyTorch 快速启动代码示例 ([#852](https://github.com/adap/flower/pull/852))" -#: ../../source/ref-changelog.md:693 +#: ../../source/ref-changelog.md:820 msgid "" -"**Disabled final distributed evaluation** ([#800](https://github.com/adap/" -"flower/pull/800))" -msgstr "" -"**禁用最终分布式评价** ([#800](https://github.com/adap/flower/pull/800))" +"**Disabled final distributed evaluation** " +"([#800](https://github.com/adap/flower/pull/800))" +msgstr "**禁用最终分布式评价** ([#800](https://github.com/adap/flower/pull/800))" -#: ../../source/ref-changelog.md:695 +#: ../../source/ref-changelog.md:822 msgid "" -"Prior behaviour was to perform a final round of distributed evaluation on " -"all connected clients, which is often not required (e.g., when using server-" -"side evaluation). The prior behaviour can be enabled by passing " +"Prior behaviour was to perform a final round of distributed evaluation on" +" all connected clients, which is often not required (e.g., when using " +"server-side evaluation). The prior behaviour can be enabled by passing " "`force_final_distributed_eval=True` to `start_server`." msgstr "" -"之前的行为是在所有连接的客户端上执行最后一轮分布式评估,而这通常是不需要的" -"(例如,在使用服务器端评估时)。可以通过向 `start_server` 传递 " -"`force_final_distributed_eval=True` 来启用之前的行为。" +"之前的行为是在所有连接的客户端上执行最后一轮分布式评估,而这通常是不需要的(例如,在使用服务器端评估时)。可以通过向 `start_server`" +" 传递 `force_final_distributed_eval=True` 来启用之前的行为。" -#: ../../source/ref-changelog.md:697 +#: ../../source/ref-changelog.md:824 msgid "" -"**Renamed q-FedAvg strategy** ([#802](https://github.com/adap/flower/" -"pull/802))" -msgstr "" -"**更名为 q-FedAvg 策略** ([#802](https://github.com/adap/flower/pull/802))" +"**Renamed q-FedAvg strategy** " +"([#802](https://github.com/adap/flower/pull/802))" +msgstr "**更名为 q-FedAvg 策略** ([#802](https://github.com/adap/flower/pull/802))" -#: ../../source/ref-changelog.md:699 +#: ../../source/ref-changelog.md:826 msgid "" -"The strategy named `QffedAvg` was renamed to `QFedAvg` to better reflect the " -"notation given in the original paper (q-FFL is the optimization objective, q-" -"FedAvg is the proposed solver). Note the the original (now deprecated) " -"`QffedAvg` class is still available for compatibility reasons (it will be " -"removed in a future release)." +"The strategy named `QffedAvg` was renamed to `QFedAvg` to better reflect " +"the notation given in the original paper (q-FFL is the optimization " +"objective, q-FedAvg is the proposed solver). Note the the original (now " +"deprecated) `QffedAvg` class is still available for compatibility reasons" +" (it will be removed in a future release)." msgstr "" -"名为 `QffedAvg` 的策略已更名为 `QFedAvg`,以更好地反映原始论文中给出的符号" -"(q-FFL 是优化目标,q-FedAvg 是建议的求解器)。请注意,出于兼容性原因,原始" -"(现已废弃)的 `QffedAvg` 类仍然可用(它将在未来的版本中移除)。" +"名为 `QffedAvg` 的策略已更名为 `QFedAvg`,以更好地反映原始论文中给出的符号(q-FFL 是优化目标,q-FedAvg " +"是建议的求解器)。请注意,出于兼容性原因,原始(现已废弃)的 `QffedAvg` 类仍然可用(它将在未来的版本中移除)。" -#: ../../source/ref-changelog.md:701 +#: ../../source/ref-changelog.md:828 msgid "" "**Deprecated and renamed code example** `simulation_pytorch` **to** " -"`simulation_pytorch_legacy` ([#791](https://github.com/adap/flower/pull/791))" +"`simulation_pytorch_legacy` " +"([#791](https://github.com/adap/flower/pull/791))" msgstr "" -"**删除并重命名代码示例**`simulation_pytorch`**为" -"**`simulation_pytorch_legacy` ([#791](https://github.com/adap/flower/" -"pull/791))" +"**删除并重命名代码示例**`simulation_pytorch`**为**`simulation_pytorch_legacy` " +"([#791](https://github.com/adap/flower/pull/791))" -#: ../../source/ref-changelog.md:703 +#: ../../source/ref-changelog.md:830 msgid "" -"This example has been replaced by a new example. The new example is based on " -"the experimental virtual client engine, which will become the new default " -"way of doing most types of large-scale simulations in Flower. The existing " -"example was kept for reference purposes, but it might be removed in the " -"future." +"This example has been replaced by a new example. The new example is based" +" on the experimental virtual client engine, which will become the new " +"default way of doing most types of large-scale simulations in Flower. The" +" existing example was kept for reference purposes, but it might be " +"removed in the future." msgstr "" -"该示例已被新示例取代。新示例基于试验性虚拟客户端引擎,它将成为在 Flower 中进" -"行大多数类型大规模模拟的新的默认方式。现有示例将作为参考保留,但将来可能会删" -"除。" +"该示例已被新示例取代。新示例基于试验性虚拟客户端引擎,它将成为在 Flower " +"中进行大多数类型大规模模拟的新的默认方式。现有示例将作为参考保留,但将来可能会删除。" -#: ../../source/ref-changelog.md:705 +#: ../../source/ref-changelog.md:832 msgid "v0.16.0 (2021-05-11)" msgstr "v0.16.0 (2021-05-11)" -#: ../../source/ref-changelog.md:709 +#: ../../source/ref-changelog.md:836 msgid "" -"**New built-in strategies** ([#549](https://github.com/adap/flower/pull/549))" +"**New built-in strategies** " +"([#549](https://github.com/adap/flower/pull/549))" msgstr "**新的内置策略** ([#549](https://github.com/adap/flower/pull/549))" -#: ../../source/ref-changelog.md:711 +#: ../../source/ref-changelog.md:838 msgid "(abstract) FedOpt" msgstr "(摘要) FedOpt" -#: ../../source/ref-changelog.md:712 -msgid "FedAdagrad" -msgstr "FedAdagrad" - -#: ../../source/ref-changelog.md:714 +#: ../../source/ref-changelog.md:841 msgid "" -"**Custom metrics for server and strategies** ([#717](https://github.com/adap/" -"flower/pull/717))" -msgstr "" -"**服务器和策略的自定义指标** ([#717](https://github.com/adap/flower/" -"pull/717))" +"**Custom metrics for server and strategies** " +"([#717](https://github.com/adap/flower/pull/717))" +msgstr "**服务器和策略的自定义指标** ([#717](https://github.com/adap/flower/pull/717))" -#: ../../source/ref-changelog.md:716 +#: ../../source/ref-changelog.md:843 msgid "" "The Flower server is now fully task-agnostic, all remaining instances of " "task-specific metrics (such as `accuracy`) have been replaced by custom " @@ -11337,429 +15339,421 @@ msgid "" "dictionary containing custom metrics from client to server. As of this " "release, custom metrics replace task-specific metrics on the server." msgstr "" -"Flower 服务器现在完全与任务无关,所有剩余的任务特定度量(如 \"准确度\")都已" -"被自定义度量字典取代。Flower 0.15 引入了从客户端向服务器传递包含自定义指标的" -"字典的功能。从本版本开始,自定义指标将取代服务器上的特定任务指标。" +"Flower 服务器现在完全与任务无关,所有剩余的任务特定度量(如 \"准确度\")都已被自定义度量字典取代。Flower 0.15 " +"引入了从客户端向服务器传递包含自定义指标的字典的功能。从本版本开始,自定义指标将取代服务器上的特定任务指标。" -#: ../../source/ref-changelog.md:718 +#: ../../source/ref-changelog.md:845 msgid "" -"Custom metric dictionaries are now used in two user-facing APIs: they are " -"returned from Strategy methods `aggregate_fit`/`aggregate_evaluate` and they " -"enable evaluation functions passed to build-in strategies (via `eval_fn`) to " -"return more than two evaluation metrics. Strategies can even return " -"*aggregated* metrics dictionaries for the server to keep track of." +"Custom metric dictionaries are now used in two user-facing APIs: they are" +" returned from Strategy methods `aggregate_fit`/`aggregate_evaluate` and " +"they enable evaluation functions passed to build-in strategies (via " +"`eval_fn`) to return more than two evaluation metrics. Strategies can " +"even return *aggregated* metrics dictionaries for the server to keep " +"track of." msgstr "" -"自定义度量字典现在可在两个面向用户的 API 中使用:它们可从策略方法 " -"`aggregate_fit`/`aggregate_evaluate` 返回,还可使传递给内置策略(通过 " -"`eval_fn`)的评估函数返回两个以上的评估度量。策略甚至可以返回 *aggregated* 指" -"标字典,以便服务器跟踪。" +"自定义度量字典现在可在两个面向用户的 API 中使用:它们可从策略方法 `aggregate_fit`/`aggregate_evaluate` " +"返回,还可使传递给内置策略(通过 `eval_fn`)的评估函数返回两个以上的评估度量。策略甚至可以返回 *aggregated* " +"指标字典,以便服务器跟踪。" -#: ../../source/ref-changelog.md:720 +#: ../../source/ref-changelog.md:847 msgid "" "Stratey implementations should migrate their `aggregate_fit` and " "`aggregate_evaluate` methods to the new return type (e.g., by simply " -"returning an empty `{}`), server-side evaluation functions should migrate " -"from `return loss, accuracy` to `return loss, {\"accuracy\": accuracy}`." +"returning an empty `{}`), server-side evaluation functions should migrate" +" from `return loss, accuracy` to `return loss, {\"accuracy\": accuracy}`." msgstr "" -"Stratey 实现应将其 `aggregate_fit` 和 `aggregate_evaluate` 方法迁移到新的返回" -"类型(例如,只需返回空的 `{}`),服务器端评估函数应从 `return loss, " -"accuracy` 迁移到 `return loss, {\"accuracy\": accuracy}`。" +"Stratey 实现应将其 `aggregate_fit` 和 `aggregate_evaluate` " +"方法迁移到新的返回类型(例如,只需返回空的 `{}`),服务器端评估函数应从 `return loss, accuracy` 迁移到 " +"`return loss, {\"accuracy\": accuracy}`。" -#: ../../source/ref-changelog.md:722 +#: ../../source/ref-changelog.md:849 msgid "" "Flower 0.15-style return types are deprecated (but still supported), " "compatibility will be removed in a future release." -msgstr "" -"Flower 0.15 风格的返回类型已被弃用(但仍受支持),兼容性将在未来的版本中移" -"除。" +msgstr "Flower 0.15 风格的返回类型已被弃用(但仍受支持),兼容性将在未来的版本中移除。" -#: ../../source/ref-changelog.md:724 +#: ../../source/ref-changelog.md:851 msgid "" -"**Migration warnings for deprecated functionality** ([#690](https://github." -"com/adap/flower/pull/690))" -msgstr "" -"** 过时功能的迁移警告** ([#690](https://github.com/adap/flower/pull/690))" +"**Migration warnings for deprecated functionality** " +"([#690](https://github.com/adap/flower/pull/690))" +msgstr "** 过时功能的迁移警告** ([#690](https://github.com/adap/flower/pull/690))" -#: ../../source/ref-changelog.md:726 +#: ../../source/ref-changelog.md:853 msgid "" "Earlier versions of Flower were often migrated to new APIs, while " -"maintaining compatibility with legacy APIs. This release introduces detailed " -"warning messages if usage of deprecated APIs is detected. The new warning " -"messages often provide details on how to migrate to more recent APIs, thus " -"easing the transition from one release to another." +"maintaining compatibility with legacy APIs. This release introduces " +"detailed warning messages if usage of deprecated APIs is detected. The " +"new warning messages often provide details on how to migrate to more " +"recent APIs, thus easing the transition from one release to another." msgstr "" -"Flower 早期版本通常会迁移到新的应用程序接口,同时保持与旧版应用程序接口的兼" -"容。如果检测到使用了过时的 API,本版本将引入详细的警告信息。新的警告信息通常" -"会详细说明如何迁移到更新的 API,从而简化从一个版本到另一个版本的过渡。" +"Flower 早期版本通常会迁移到新的应用程序接口,同时保持与旧版应用程序接口的兼容。如果检测到使用了过时的 " +"API,本版本将引入详细的警告信息。新的警告信息通常会详细说明如何迁移到更新的 API,从而简化从一个版本到另一个版本的过渡。" -#: ../../source/ref-changelog.md:728 +#: ../../source/ref-changelog.md:855 msgid "" -"Improved docs and docstrings ([#691](https://github.com/adap/flower/" -"pull/691) [#692](https://github.com/adap/flower/pull/692) [#713](https://" -"github.com/adap/flower/pull/713))" +"Improved docs and docstrings " +"([#691](https://github.com/adap/flower/pull/691) " +"[#692](https://github.com/adap/flower/pull/692) " +"[#713](https://github.com/adap/flower/pull/713))" msgstr "" -"改进了文档和文档说明 ([#691](https://github.com/adap/flower/pull/691) [#692]" -"(https://github.com/adap/flower/pull/692) [#713](https://github.com/adap/" -"flower/pull/713))" +"改进了文档和文档说明 ([#691](https://github.com/adap/flower/pull/691) " +"[#692](https://github.com/adap/flower/pull/692) " +"[#713](https://github.com/adap/flower/pull/713))" -#: ../../source/ref-changelog.md:730 +#: ../../source/ref-changelog.md:857 msgid "MXNet example and documentation" msgstr "MXNet 示例和文档" -#: ../../source/ref-changelog.md:732 +#: ../../source/ref-changelog.md:859 msgid "" "FedBN implementation in example PyTorch: From Centralized To Federated " -"([#696](https://github.com/adap/flower/pull/696) [#702](https://github.com/" -"adap/flower/pull/702) [#705](https://github.com/adap/flower/pull/705))" +"([#696](https://github.com/adap/flower/pull/696) " +"[#702](https://github.com/adap/flower/pull/702) " +"[#705](https://github.com/adap/flower/pull/705))" msgstr "" -"PyTorch 示例中的 FedBN 实现: 从集中到联邦 ([#696](https://github.com/adap/" -"flower/pull/696) [#702](https://github.com/adap/flower/pull/702) " +"PyTorch 示例中的 FedBN 实现: 从集中到联邦 " +"([#696](https://github.com/adap/flower/pull/696) " +"[#702](https://github.com/adap/flower/pull/702) " "[#705](https://github.com/adap/flower/pull/705))" -#: ../../source/ref-changelog.md:736 +#: ../../source/ref-changelog.md:863 msgid "" -"**Serialization-agnostic server** ([#721](https://github.com/adap/flower/" -"pull/721))" +"**Serialization-agnostic server** " +"([#721](https://github.com/adap/flower/pull/721))" msgstr "**序列化无关服务器** ([#721](https://github.com/adap/flower/pull/721))" -#: ../../source/ref-changelog.md:738 +#: ../../source/ref-changelog.md:865 msgid "" -"The Flower server is now fully serialization-agnostic. Prior usage of class " -"`Weights` (which represents parameters as deserialized NumPy ndarrays) was " -"replaced by class `Parameters` (e.g., in `Strategy`). `Parameters` objects " -"are fully serialization-agnostic and represents parameters as byte arrays, " -"the `tensor_type` attributes indicates how these byte arrays should be " -"interpreted (e.g., for serialization/deserialization)." +"The Flower server is now fully serialization-agnostic. Prior usage of " +"class `Weights` (which represents parameters as deserialized NumPy " +"ndarrays) was replaced by class `Parameters` (e.g., in `Strategy`). " +"`Parameters` objects are fully serialization-agnostic and represents " +"parameters as byte arrays, the `tensor_type` attributes indicates how " +"these byte arrays should be interpreted (e.g., for " +"serialization/deserialization)." msgstr "" -"Flower 服务器现在完全不依赖序列化。之前使用的 `Weights` 类(以反序列化的 " -"NumPy ndarrays 表示参数)已被 `Parameters` 类取代(例如在 `Strategy`中)。参" -"数 \"对象与序列化完全无关,它以字节数组的形式表示参数,\"tensor_type \"属性表" -"示如何解释这些字节数组(例如,用于序列化/反序列化)。" +"Flower 服务器现在完全不依赖序列化。之前使用的 `Weights` 类(以反序列化的 NumPy ndarrays 表示参数)已被 " +"`Parameters` 类取代(例如在 `Strategy`中)。参数 " +"\"对象与序列化完全无关,它以字节数组的形式表示参数,\"tensor_type \"属性表示如何解释这些字节数组(例如,用于序列化/反序列化)。" -#: ../../source/ref-changelog.md:740 +#: ../../source/ref-changelog.md:867 msgid "" -"Built-in strategies implement this approach by handling serialization and " -"deserialization to/from `Weights` internally. Custom/3rd-party Strategy " +"Built-in strategies implement this approach by handling serialization and" +" deserialization to/from `Weights` internally. Custom/3rd-party Strategy " "implementations should update to the slighly changed Strategy method " -"definitions. Strategy authors can consult PR [#721](https://github.com/adap/" -"flower/pull/721) to see how strategies can easily migrate to the new format." +"definitions. Strategy authors can consult PR " +"[#721](https://github.com/adap/flower/pull/721) to see how strategies can" +" easily migrate to the new format." msgstr "" -"内置策略通过在内部处理序列化和反序列化到/从`Weights`来实现这种方法。自定义/第" -"三方策略实现应更新为稍有改动的策略方法定义。策略作者可查阅 PR " -"[#721](https://github.com/adap/flower/pull/721) " -"以了解如何将策略轻松迁移到新格式。" +"内置策略通过在内部处理序列化和反序列化到/从`Weights`来实现这种方法。自定义/第三方策略实现应更新为稍有改动的策略方法定义。策略作者可查阅" +" PR [#721](https://github.com/adap/flower/pull/721) 以了解如何将策略轻松迁移到新格式。" -#: ../../source/ref-changelog.md:742 +#: ../../source/ref-changelog.md:869 msgid "" -"Deprecated `flwr.server.Server.evaluate`, use `flwr.server.Server." -"evaluate_round` instead ([#717](https://github.com/adap/flower/pull/717))" +"Deprecated `flwr.server.Server.evaluate`, use " +"`flwr.server.Server.evaluate_round` instead " +"([#717](https://github.com/adap/flower/pull/717))" msgstr "" -"已弃用 `flwr.server.Server.evaluate`,改用 `flwr.server.Server." -"evaluate_round`([#717](https://github.com/adap/flower/pull/717)" +"已弃用 `flwr.server.Server.evaluate`,改用 " +"`flwr.server.Server.evaluate_round`([#717](https://github.com/adap/flower/pull/717)" -#: ../../source/ref-changelog.md:744 +#: ../../source/ref-changelog.md:871 msgid "v0.15.0 (2021-03-12)" msgstr "v0.15.0 (2021-03-12)" -#: ../../source/ref-changelog.md:748 +#: ../../source/ref-changelog.md:875 msgid "" -"**Server-side parameter initialization** ([#658](https://github.com/adap/" -"flower/pull/658))" -msgstr "" -"**服务器端参数初始化** ([#658](https://github.com/adap/flower/pull/658))" +"**Server-side parameter initialization** " +"([#658](https://github.com/adap/flower/pull/658))" +msgstr "**服务器端参数初始化** ([#658](https://github.com/adap/flower/pull/658))" -#: ../../source/ref-changelog.md:750 +#: ../../source/ref-changelog.md:877 msgid "" "Model parameters can now be initialized on the server-side. Server-side " "parameter initialization works via a new `Strategy` method called " "`initialize_parameters`." msgstr "" -"现在可以在服务器端初始化模型参数。服务器端参数初始化通过名为 " -"\"initialize_parameters \"的新 \"Strategy \"方法进行。" +"现在可以在服务器端初始化模型参数。服务器端参数初始化通过名为 \"initialize_parameters \"的新 \"Strategy " +"\"方法进行。" -#: ../../source/ref-changelog.md:752 +#: ../../source/ref-changelog.md:879 msgid "" "Built-in strategies support a new constructor argument called " -"`initial_parameters` to set the initial parameters. Built-in strategies will " -"provide these initial parameters to the server on startup and then delete " -"them to free the memory afterwards." +"`initial_parameters` to set the initial parameters. Built-in strategies " +"will provide these initial parameters to the server on startup and then " +"delete them to free the memory afterwards." msgstr "" -"内置策略支持名为 \"initial_parameters \"的新构造函数参数,用于设置初始参数。" -"内置策略会在启动时向服务器提供这些初始参数,然后删除它们以释放内存。" +"内置策略支持名为 \"initial_parameters " +"\"的新构造函数参数,用于设置初始参数。内置策略会在启动时向服务器提供这些初始参数,然后删除它们以释放内存。" -#: ../../source/ref-changelog.md:771 +#: ../../source/ref-changelog.md:898 msgid "" "If no initial parameters are provided to the strategy, the server will " "continue to use the current behaviour (namely, it will ask one of the " "connected clients for its parameters and use these as the initial global " "parameters)." -msgstr "" -"如果没有向策略提供初始参数,服务器将继续使用当前行为(即向其中一个已连接的客" -"户端询问参数,并将这些参数用作初始全局参数)。" +msgstr "如果没有向策略提供初始参数,服务器将继续使用当前行为(即向其中一个已连接的客户端询问参数,并将这些参数用作初始全局参数)。" -#: ../../source/ref-changelog.md:773 +#: ../../source/ref-changelog.md:900 msgid "Deprecations" msgstr "停用" -#: ../../source/ref-changelog.md:775 +#: ../../source/ref-changelog.md:902 msgid "" -"Deprecate `flwr.server.strategy.DefaultStrategy` (migrate to `flwr.server." -"strategy.FedAvg`, which is equivalent)" +"Deprecate `flwr.server.strategy.DefaultStrategy` (migrate to " +"`flwr.server.strategy.FedAvg`, which is equivalent)" msgstr "" -"停用 `flwr.server.strategy.DefaultStrategy`(迁移到等价的 `flwr.server." -"strategy.FedAvg`)" +"停用 `flwr.server.strategy.DefaultStrategy`(迁移到等价的 " +"`flwr.server.strategy.FedAvg`)" -#: ../../source/ref-changelog.md:777 +#: ../../source/ref-changelog.md:904 msgid "v0.14.0 (2021-02-18)" msgstr "v0.14.0 (2021-02-18)" -#: ../../source/ref-changelog.md:781 +#: ../../source/ref-changelog.md:908 msgid "" "**Generalized** `Client.fit` **and** `Client.evaluate` **return values** " -"([#610](https://github.com/adap/flower/pull/610) [#572](https://github.com/" -"adap/flower/pull/572) [#633](https://github.com/adap/flower/pull/633))" +"([#610](https://github.com/adap/flower/pull/610) " +"[#572](https://github.com/adap/flower/pull/572) " +"[#633](https://github.com/adap/flower/pull/633))" msgstr "" -"**通用** `Client.fit` **和** `Client.evaluate` **返回值** ([#610](https://" -"github.com/adap/flower/pull/610) [#572](https://github.com/adap/flower/" -"pull/572) [#633](https://github.com/adap/flower/pull/633))" +"**通用** `Client.fit` **和** `Client.evaluate` **返回值** " +"([#610](https://github.com/adap/flower/pull/610) " +"[#572](https://github.com/adap/flower/pull/572) " +"[#633](https://github.com/adap/flower/pull/633))" -#: ../../source/ref-changelog.md:783 +#: ../../source/ref-changelog.md:910 msgid "" -"Clients can now return an additional dictionary mapping `str` keys to values " -"of the following types: `bool`, `bytes`, `float`, `int`, `str`. This means " -"one can return almost arbitrary values from `fit`/`evaluate` and make use of " -"them on the server side!" +"Clients can now return an additional dictionary mapping `str` keys to " +"values of the following types: `bool`, `bytes`, `float`, `int`, `str`. " +"This means one can return almost arbitrary values from `fit`/`evaluate` " +"and make use of them on the server side!" msgstr "" -"客户端现在可以返回一个额外的字典,将 `str` 键映射为以下类型的值: bool`、" -"`bytes`、`float`、`int`、`str`。这意味着我们可以从 `fit`/`evaluate` 返回几乎" -"任意的值,并在服务器端使用它们!" +"客户端现在可以返回一个额外的字典,将 `str` 键映射为以下类型的值: " +"bool`、`bytes`、`float`、`int`、`str`。这意味着我们可以从 `fit`/`evaluate` " +"返回几乎任意的值,并在服务器端使用它们!" -#: ../../source/ref-changelog.md:785 +#: ../../source/ref-changelog.md:912 msgid "" -"This improvement also allowed for more consistent return types between `fit` " -"and `evaluate`: `evaluate` should now return a tuple `(float, int, dict)` " -"representing the loss, number of examples, and a dictionary holding " -"arbitrary problem-specific values like accuracy." +"This improvement also allowed for more consistent return types between " +"`fit` and `evaluate`: `evaluate` should now return a tuple `(float, int, " +"dict)` representing the loss, number of examples, and a dictionary " +"holding arbitrary problem-specific values like accuracy." msgstr "" -"这一改进还使 `fit` 和 `evaluate` 之间的返回类型更加一致:`evaluate` 现在应返" -"回一个元组`(float, int, dict)`,代表损失、示例数和一个包含特定问题任意值(如" -"准确度)的字典。" +"这一改进还使 `fit` 和 `evaluate` 之间的返回类型更加一致:`evaluate` 现在应返回一个元组`(float, int, " +"dict)`,代表损失、示例数和一个包含特定问题任意值(如准确度)的字典。" -#: ../../source/ref-changelog.md:787 +#: ../../source/ref-changelog.md:914 msgid "" -"In case you wondered: this feature is compatible with existing projects, the " -"additional dictionary return value is optional. New code should however " -"migrate to the new return types to be compatible with upcoming Flower " -"releases (`fit`: `List[np.ndarray], int, Dict[str, Scalar]`, `evaluate`: " -"`float, int, Dict[str, Scalar]`). See the example below for details." +"In case you wondered: this feature is compatible with existing projects, " +"the additional dictionary return value is optional. New code should " +"however migrate to the new return types to be compatible with upcoming " +"Flower releases (`fit`: `List[np.ndarray], int, Dict[str, Scalar]`, " +"`evaluate`: `float, int, Dict[str, Scalar]`). See the example below for " +"details." msgstr "" -"如果你想知道:此功能与现有项目兼容,额外的字典返回值是可选的。不过,新代码应" -"迁移到新的返回类型,以便与即将发布的 Flower 版本兼容(`fit`: `List[np." -"ndarray], int, Dict[str, Scalar]`,`evaluate`: `float, int, Dict[str, " -"Scalar]`)。详见下面的示例。" +"如果你想知道:此功能与现有项目兼容,额外的字典返回值是可选的。不过,新代码应迁移到新的返回类型,以便与即将发布的 Flower " +"版本兼容(`fit`: `List[np.ndarray], int, Dict[str, Scalar]`,`evaluate`: " +"`float, int, Dict[str, Scalar]`)。详见下面的示例。" -#: ../../source/ref-changelog.md:789 +#: ../../source/ref-changelog.md:916 msgid "" "*Code example:* note the additional dictionary return values in both " "`FlwrClient.fit` and `FlwrClient.evaluate`:" -msgstr "" -"*代码示例:* 注意 `FlwrClient.fit` 和 `FlwrClient.evaluate` 中的附加字典返回" -"值:" +msgstr "*代码示例:* 注意 `FlwrClient.fit` 和 `FlwrClient.evaluate` 中的附加字典返回值:" -#: ../../source/ref-changelog.md:804 +#: ../../source/ref-changelog.md:931 msgid "" -"**Generalized** `config` **argument in** `Client.fit` **and** `Client." -"evaluate` ([#595](https://github.com/adap/flower/pull/595))" +"**Generalized** `config` **argument in** `Client.fit` **and** " +"`Client.evaluate` ([#595](https://github.com/adap/flower/pull/595))" msgstr "" -"**在**`Client.fit` **和**`Client.evaluate`中泛化**`config`参数([#595]" -"(https://github.com/adap/flower/pull/595))" +"**在**`Client.fit` " +"**和**`Client.evaluate`中泛化**`config`参数([#595](https://github.com/adap/flower/pull/595))" -#: ../../source/ref-changelog.md:806 +#: ../../source/ref-changelog.md:933 msgid "" -"The `config` argument used to be of type `Dict[str, str]`, which means that " -"dictionary values were expected to be strings. The new release generalizes " -"this to enable values of the following types: `bool`, `bytes`, `float`, " -"`int`, `str`." +"The `config` argument used to be of type `Dict[str, str]`, which means " +"that dictionary values were expected to be strings. The new release " +"generalizes this to enable values of the following types: `bool`, " +"`bytes`, `float`, `int`, `str`." msgstr "" -"`config`参数曾是 \"字典[str, str]\"类型" -",这意味着字典值应是字符串。新版本将其扩展为以下类型的值: " +"`config`参数曾是 \"字典[str, str]\"类型,这意味着字典值应是字符串。新版本将其扩展为以下类型的值: " "bool`、`bytes`、`float`、`int`、`str`。" -#: ../../source/ref-changelog.md:808 +#: ../../source/ref-changelog.md:935 msgid "" "This means one can now pass almost arbitrary values to `fit`/`evaluate` " -"using the `config` dictionary. Yay, no more `str(epochs)` on the server-side " -"and `int(config[\"epochs\"])` on the client side!" +"using the `config` dictionary. Yay, no more `str(epochs)` on the server-" +"side and `int(config[\"epochs\"])` on the client side!" msgstr "" -"这意味着现在可以使用 `config` 字典向 `fit`/`evaluate` 传递几乎任意的值。耶," -"服务器端不再需要 `str(epochs)`,客户端不再需要 `int(config[\"epochs\"])`!" +"这意味着现在可以使用 `config` 字典向 `fit`/`evaluate` 传递几乎任意的值。耶,服务器端不再需要 " +"`str(epochs)`,客户端不再需要 `int(config[\"epochs\"])`!" -#: ../../source/ref-changelog.md:810 +#: ../../source/ref-changelog.md:937 msgid "" "*Code example:* note that the `config` dictionary now contains non-`str` " "values in both `Client.fit` and `Client.evaluate`:" -msgstr "" -"*代码示例:* 注意 `config` 字典现在在 `Client.fit` 和 `Client.evaluate` 中都" -"包含非 `str` 值:" +msgstr "*代码示例:* 注意 `config` 字典现在在 `Client.fit` 和 `Client.evaluate` 中都包含非 `str` 值:" -#: ../../source/ref-changelog.md:827 +#: ../../source/ref-changelog.md:954 msgid "v0.13.0 (2021-01-08)" msgstr "v0.13.0 (2021-01-08)" -#: ../../source/ref-changelog.md:831 +#: ../../source/ref-changelog.md:958 msgid "" -"New example: PyTorch From Centralized To Federated ([#549](https://github." -"com/adap/flower/pull/549))" -msgstr "新示例: PyTorch 从集中到联邦 ([#549](https://github.com/adap/flower/pull/" -"549))" +"New example: PyTorch From Centralized To Federated " +"([#549](https://github.com/adap/flower/pull/549))" +msgstr "新示例: PyTorch 从集中到联邦 ([#549](https://github.com/adap/flower/pull/549))" -#: ../../source/ref-changelog.md:832 +#: ../../source/ref-changelog.md:959 msgid "Improved documentation" msgstr "改进文档" -#: ../../source/ref-changelog.md:833 -msgid "" -"New documentation theme ([#551](https://github.com/adap/flower/pull/551))" +#: ../../source/ref-changelog.md:960 +msgid "New documentation theme ([#551](https://github.com/adap/flower/pull/551))" msgstr "新文档主题 ([#551](https://github.com/adap/flower/pull/551))" -#: ../../source/ref-changelog.md:834 +#: ../../source/ref-changelog.md:961 msgid "New API reference ([#554](https://github.com/adap/flower/pull/554))" msgstr "新的 API 参考 ([#554](https://github.com/adap/flower/pull/554))" -#: ../../source/ref-changelog.md:835 +#: ../../source/ref-changelog.md:962 msgid "" -"Updated examples documentation ([#549](https://github.com/adap/flower/" -"pull/549))" +"Updated examples documentation " +"([#549](https://github.com/adap/flower/pull/549))" msgstr "更新了示例文档 ([#549](https://github.com/adap/flower/pull/549))" -#: ../../source/ref-changelog.md:836 +#: ../../source/ref-changelog.md:963 msgid "" -"Removed obsolete documentation ([#548](https://github.com/adap/flower/" -"pull/548))" +"Removed obsolete documentation " +"([#548](https://github.com/adap/flower/pull/548))" msgstr "删除了过时的文档 ([#548](https://github.com/adap/flower/pull/548))" -#: ../../source/ref-changelog.md:838 +#: ../../source/ref-changelog.md:965 msgid "Bugfix:" msgstr "错误修正:" -#: ../../source/ref-changelog.md:840 +#: ../../source/ref-changelog.md:967 msgid "" -"`Server.fit` does not disconnect clients when finished, disconnecting the " -"clients is now handled in `flwr.server.start_server` ([#553](https://github." -"com/adap/flower/pull/553) [#540](https://github.com/adap/flower/issues/540))." +"`Server.fit` does not disconnect clients when finished, disconnecting the" +" clients is now handled in `flwr.server.start_server` " +"([#553](https://github.com/adap/flower/pull/553) " +"[#540](https://github.com/adap/flower/issues/540))." msgstr "" -"Server.fit \"完成后不会断开客户端连接,现在断开客户端连接是在 \"flwr.server." -"start_server \"中处理的([#553](https://github.com/adap/flower/pull/553) " +"Server.fit \"完成后不会断开客户端连接,现在断开客户端连接是在 \"flwr.server.start_server " +"\"中处理的([#553](https://github.com/adap/flower/pull/553) " "[#540](https://github.com/adap/flower/issues/540))。" -#: ../../source/ref-changelog.md:842 +#: ../../source/ref-changelog.md:969 msgid "v0.12.0 (2020-12-07)" msgstr "v0.12.0 (2020-12-07)" -#: ../../source/ref-changelog.md:844 ../../source/ref-changelog.md:860 +#: ../../source/ref-changelog.md:971 ../../source/ref-changelog.md:987 msgid "Important changes:" msgstr "重要变更:" -#: ../../source/ref-changelog.md:846 +#: ../../source/ref-changelog.md:973 msgid "" -"Added an example for embedded devices ([#507](https://github.com/adap/flower/" -"pull/507))" +"Added an example for embedded devices " +"([#507](https://github.com/adap/flower/pull/507))" msgstr "添加了嵌入式设备示例 ([#507](https://github.com/adap/flower/pull/507))" -#: ../../source/ref-changelog.md:847 +#: ../../source/ref-changelog.md:974 msgid "" -"Added a new NumPyClient (in addition to the existing KerasClient) ([#504]" -"(https://github.com/adap/flower/pull/504) [#508](https://github.com/adap/" -"flower/pull/508))" +"Added a new NumPyClient (in addition to the existing KerasClient) " +"([#504](https://github.com/adap/flower/pull/504) " +"[#508](https://github.com/adap/flower/pull/508))" msgstr "" -"添加了一个新的 NumPyClient(除现有的 KerasClient 之外)([#504](https://" -"github.com/adap/flower/pull/504) [#508](https://github.com/adap/flower/" -"pull/508)" +"添加了一个新的 NumPyClient(除现有的 KerasClient " +"之外)([#504](https://github.com/adap/flower/pull/504) " +"[#508](https://github.com/adap/flower/pull/508)" -#: ../../source/ref-changelog.md:848 +#: ../../source/ref-changelog.md:975 msgid "" -"Deprecated `flwr_example` package and started to migrate examples into the " -"top-level `examples` directory ([#494](https://github.com/adap/flower/" -"pull/494) [#512](https://github.com/adap/flower/pull/512))" +"Deprecated `flwr_example` package and started to migrate examples into " +"the top-level `examples` directory " +"([#494](https://github.com/adap/flower/pull/494) " +"[#512](https://github.com/adap/flower/pull/512))" msgstr "" -"弃用 `flwr_example` 软件包,并开始将示例迁移到顶层的 `examples` 目录 ([#494]" -"(https://github.com/adap/flower/pull/494) [#512](https://github.com/adap/" -"flower/pull/512))" +"弃用 `flwr_example` 软件包,并开始将示例迁移到顶层的 `examples` 目录 " +"([#494](https://github.com/adap/flower/pull/494) " +"[#512](https://github.com/adap/flower/pull/512))" -#: ../../source/ref-changelog.md:850 +#: ../../source/ref-changelog.md:977 msgid "v0.11.0 (2020-11-30)" msgstr "v0.11.0 (2020-11-30)" -#: ../../source/ref-changelog.md:852 +#: ../../source/ref-changelog.md:979 msgid "Incompatible changes:" msgstr "不兼容的更改:" -#: ../../source/ref-changelog.md:854 +#: ../../source/ref-changelog.md:981 msgid "" -"Renamed strategy methods ([#486](https://github.com/adap/flower/pull/486)) " -"to unify the naming of Flower's public APIs. Other public methods/functions " -"(e.g., every method in `Client`, but also `Strategy.evaluate`) do not use " -"the `on_` prefix, which is why we're removing it from the four methods in " -"Strategy. To migrate rename the following `Strategy` methods accordingly:" +"Renamed strategy methods " +"([#486](https://github.com/adap/flower/pull/486)) to unify the naming of " +"Flower's public APIs. Other public methods/functions (e.g., every method " +"in `Client`, but also `Strategy.evaluate`) do not use the `on_` prefix, " +"which is why we're removing it from the four methods in Strategy. To " +"migrate rename the following `Strategy` methods accordingly:" msgstr "" -"重命名了策略方法([#486](https://github.com/adap/flower/pull/486)),以统一 " -"Flower公共 API 的命名。其他公共方法/函数(例如 `Client` 中的每个方法,以及 " -"`Strategy.evaluate`)不使用 `on_` 前缀,这就是我们从 Strategy " -"中的四个方法中移除它的原因。迁移时,请相应地重命名以下 `Strategy` 方法:" +"重命名了策略方法([#486](https://github.com/adap/flower/pull/486)),以统一 Flower公共 " +"API 的命名。其他公共方法/函数(例如 `Client` 中的每个方法,以及 `Strategy.evaluate`)不使用 `on_` " +"前缀,这就是我们从 Strategy 中的四个方法中移除它的原因。迁移时,请相应地重命名以下 `Strategy` 方法:" -#: ../../source/ref-changelog.md:855 +#: ../../source/ref-changelog.md:982 msgid "`on_configure_evaluate` => `configure_evaluate`" msgstr "`on_configure_evaluate` => `configure_evaluate`" -#: ../../source/ref-changelog.md:856 +#: ../../source/ref-changelog.md:983 msgid "`on_aggregate_evaluate` => `aggregate_evaluate`" msgstr "`on_aggregate_evaluate` => `aggregate_evaluate`" -#: ../../source/ref-changelog.md:857 +#: ../../source/ref-changelog.md:984 msgid "`on_configure_fit` => `configure_fit`" msgstr "`on_configure_fit` => `configure_fit`" -#: ../../source/ref-changelog.md:858 +#: ../../source/ref-changelog.md:985 msgid "`on_aggregate_fit` => `aggregate_fit`" msgstr "`on_aggregate_fit` => `aggregate_fit`" -#: ../../source/ref-changelog.md:862 +#: ../../source/ref-changelog.md:989 msgid "" -"Deprecated `DefaultStrategy` ([#479](https://github.com/adap/flower/" -"pull/479)). To migrate use `FedAvg` instead." +"Deprecated `DefaultStrategy` " +"([#479](https://github.com/adap/flower/pull/479)). To migrate use " +"`FedAvg` instead." msgstr "" -"已废弃的 `DefaultStrategy` ([#479](https://github.com/adap/flower/" -"pull/479)) 。迁移时请使用 `FedAvg`。" +"已废弃的 `DefaultStrategy` ([#479](https://github.com/adap/flower/pull/479)) " +"。迁移时请使用 `FedAvg`。" -#: ../../source/ref-changelog.md:863 +#: ../../source/ref-changelog.md:990 msgid "" -"Simplified examples and baselines ([#484](https://github.com/adap/flower/" -"pull/484))." +"Simplified examples and baselines " +"([#484](https://github.com/adap/flower/pull/484))." msgstr "简化示例和baselines([#484](https://github.com/adap/flower/pull/484))。" -#: ../../source/ref-changelog.md:864 +#: ../../source/ref-changelog.md:991 msgid "" -"Removed presently unused `on_conclude_round` from strategy interface ([#483]" -"(https://github.com/adap/flower/pull/483))." +"Removed presently unused `on_conclude_round` from strategy interface " +"([#483](https://github.com/adap/flower/pull/483))." msgstr "" -"删除了策略界面中目前未使用的 \"on_conclude_round\"([#483](https://github." -"com/adap/flower/pull/483))。" +"删除了策略界面中目前未使用的 " +"\"on_conclude_round\"([#483](https://github.com/adap/flower/pull/483))。" -#: ../../source/ref-changelog.md:865 +#: ../../source/ref-changelog.md:992 msgid "" -"Set minimal Python version to 3.6.1 instead of 3.6.9 ([#471](https://github." -"com/adap/flower/pull/471))." +"Set minimal Python version to 3.6.1 instead of 3.6.9 " +"([#471](https://github.com/adap/flower/pull/471))." msgstr "" -"将最小 Python 版本设为 3.6.1,而不是 3.6.9 ([#471](https://github.com/adap/" -"flower/pull/471))." +"将最小 Python 版本设为 3.6.1,而不是 3.6.9 " +"([#471](https://github.com/adap/flower/pull/471))." -#: ../../source/ref-changelog.md:866 +#: ../../source/ref-changelog.md:993 msgid "" -"Improved `Strategy` docstrings ([#470](https://github.com/adap/flower/" -"pull/470))." +"Improved `Strategy` docstrings " +"([#470](https://github.com/adap/flower/pull/470))." msgstr "" -"改进了 `Strategy` docstrings([#470](https://github.com/adap/flower/" -"pull/470))。" +"改进了 `Strategy` " +"docstrings([#470](https://github.com/adap/flower/pull/470))。" #: ../../source/ref-example-projects.rst:2 msgid "Example projects" @@ -11767,26 +15761,26 @@ msgstr "项目实例" #: ../../source/ref-example-projects.rst:4 msgid "" -"Flower comes with a number of usage examples. The examples demonstrate how " -"Flower can be used to federate different kinds of existing machine learning " -"pipelines, usually leveraging popular machine learning frameworks such as " -"`PyTorch `_ or `TensorFlow `_." +"Flower comes with a number of usage examples. The examples demonstrate " +"how Flower can be used to federate different kinds of existing machine " +"learning pipelines, usually leveraging popular machine learning " +"frameworks such as `PyTorch `_ or `TensorFlow " +"`_." msgstr "" -"Flower 附带了许多使用示例。这些示例演示了如何使用 Flower " -"联邦不同类型的现有机器学习形式,通常是利用流行的机器学习框架,如 `PyTorch " -"`_ 或 `TensorFlow `_。" +"Flower 附带了许多使用示例。这些示例演示了如何使用 Flower 联邦不同类型的现有机器学习形式,通常是利用流行的机器学习框架,如 " +"`PyTorch `_ 或 `TensorFlow " +"`_。" #: ../../source/ref-example-projects.rst:11 msgid "" "Flower usage examples used to be bundled with Flower in a package called " -"``flwr_example``. We are migrating those examples to standalone projects to " -"make them easier to use. All new examples are based in the directory " +"``flwr_example``. We are migrating those examples to standalone projects " +"to make them easier to use. All new examples are based in the directory " "`examples `_." msgstr "" -"Flower 的使用示例曾与 Flower 捆绑在一个名为 ``flwr_example`` 的软件包中。我们" -"正在将这些示例迁移到独立项目中,以使它们更易于使用。所有新示例都位于目录 " -"`examples `_。" +"Flower 的使用示例曾与 Flower 捆绑在一个名为 ``flwr_example`` " +"的软件包中。我们正在将这些示例迁移到独立项目中,以使它们更易于使用。所有新示例都位于目录 `examples " +"`_。" #: ../../source/ref-example-projects.rst:16 msgid "The following examples are available as standalone projects." @@ -11798,32 +15792,31 @@ msgstr "快速入门 TensorFlow/Keras" #: ../../source/ref-example-projects.rst:22 msgid "" -"The TensorFlow/Keras quickstart example shows CIFAR-10 image classification " -"with MobileNetV2:" -msgstr "" -"TensorFlow/Keras 快速入门示例展示了使用 MobileNetV2 进行的 CIFAR-10 图像分" -"类:" +"The TensorFlow/Keras quickstart example shows CIFAR-10 image " +"classification with MobileNetV2:" +msgstr "TensorFlow/Keras 快速入门示例展示了使用 MobileNetV2 进行的 CIFAR-10 图像分类:" #: ../../source/ref-example-projects.rst:25 msgid "" -"`Quickstart TensorFlow (Code) `_" +"`Quickstart TensorFlow (Code) " +"`_" msgstr "" -"`TensorFlow快速入门 (代码) `_" +"`TensorFlow快速入门 (代码) `_" #: ../../source/ref-example-projects.rst:26 msgid "" -"`Quickstart TensorFlow (Tutorial) `_" +"`Quickstart TensorFlow (Tutorial) `_" msgstr "" "`TensorFlow快速入门 (教程) `_" #: ../../source/ref-example-projects.rst:27 msgid "" -"`Quickstart TensorFlow (Blog Post) `_" +"`Quickstart TensorFlow (Blog Post) `_" msgstr "" "`TensorFlow快速入门 (博客) `_" @@ -11835,26 +15828,25 @@ msgstr "PyTorch快速入门" #: ../../source/ref-example-projects.rst:33 msgid "" -"The PyTorch quickstart example shows CIFAR-10 image classification with a " -"simple Convolutional Neural Network:" -msgstr "" -"PyTorch 快速入门范例展示了使用简单卷积神经网络进行 CIFAR-10 图像分类的情况:" +"The PyTorch quickstart example shows CIFAR-10 image classification with a" +" simple Convolutional Neural Network:" +msgstr "PyTorch 快速入门范例展示了使用简单卷积神经网络进行 CIFAR-10 图像分类的情况:" #: ../../source/ref-example-projects.rst:36 msgid "" -"`Quickstart PyTorch (Code) `_" +"`Quickstart PyTorch (Code) " +"`_" msgstr "" -"`PyTorch快速入门 (代码) `_" +"`PyTorch快速入门 (代码) `_" #: ../../source/ref-example-projects.rst:37 msgid "" -"`Quickstart PyTorch (Tutorial) `_" +"`Quickstart PyTorch (Tutorial) `_" msgstr "" -"`PyTorch快速入门 (教程) `_" +"`PyTorch快速入门 (教程) `_" #: ../../source/ref-example-projects.rst:41 msgid "PyTorch: From Centralized To Federated" @@ -11868,19 +15860,21 @@ msgstr "本例展示了如何使用 Flower 联邦化一个普通的 PyTorch 项 #: ../../source/ref-example-projects.rst:45 msgid "" -"`PyTorch: From Centralized To Federated (Code) `_" +"`PyTorch: From Centralized To Federated (Code) " +"`_" msgstr "" -"PyTorch: 从集中式到联邦式(代码) `_" +"PyTorch: 从集中式到联邦式(代码) `_" #: ../../source/ref-example-projects.rst:46 msgid "" -"`PyTorch: From Centralized To Federated (Tutorial) `_" +"`PyTorch: From Centralized To Federated (Tutorial) " +"`_" msgstr "" -"PyTorch: 从集中式到联邦式(教程) `_" +"PyTorch: 从集中式到联邦式(教程) `_" #: ../../source/ref-example-projects.rst:50 msgid "Federated Learning on Raspberry Pi and Nvidia Jetson" @@ -11890,26 +15884,23 @@ msgstr "树莓派和 Nvidia Jetson 上的联邦学习" msgid "" "This example shows how Flower can be used to build a federated learning " "system that run across Raspberry Pi and Nvidia Jetson:" -msgstr "本示例展示了如何利用 Flower 建立一个跨 Raspberry Pi 和 Nvidia Jetson " -"运行的联邦学习系统:" +msgstr "本示例展示了如何利用 Flower 建立一个跨 Raspberry Pi 和 Nvidia Jetson 运行的联邦学习系统:" #: ../../source/ref-example-projects.rst:54 msgid "" -"`Federated Learning on Raspberry Pi and Nvidia Jetson (Code) `_" +"`Federated Learning on Raspberry Pi and Nvidia Jetson (Code) " +"`_" msgstr "" -"Raspberry Pi 和 Nvidia Jetson 上的联邦学习(代码) `_" +"Raspberry Pi 和 Nvidia Jetson 上的联邦学习(代码) " +"`_" #: ../../source/ref-example-projects.rst:55 msgid "" -"`Federated Learning on Raspberry Pi and Nvidia Jetson (Blog Post) `_" +"`Federated Learning on Raspberry Pi and Nvidia Jetson (Blog Post) " +"`_" msgstr "" -"Raspberry Pi和 Nvidia Jetson 上的联邦学习(博客) `_" +"Raspberry Pi和 Nvidia Jetson 上的联邦学习(博客) " +"`_" #: ../../source/ref-example-projects.rst:60 msgid "Legacy Examples (`flwr_example`)" @@ -11917,12 +15908,12 @@ msgstr "传统示例 (`flwr_example`)" #: ../../source/ref-example-projects.rst:63 msgid "" -"The useage examples in `flwr_example` are deprecated and will be removed in " -"the future. New examples are provided as standalone projects in `examples " -"`_." +"The useage examples in `flwr_example` are deprecated and will be removed " +"in the future. New examples are provided as standalone projects in " +"`examples `_." msgstr "" -"在 `flwr_example` 中的使用示例已被弃用,今后将被移除。新示例将作为独立项目在 " -"`examples `_ 中提供。" +"在 `flwr_example` 中的使用示例已被弃用,今后将被移除。新示例将作为独立项目在 `examples " +"`_ 中提供。" #: ../../source/ref-example-projects.rst:69 msgid "Extra Dependencies" @@ -11930,12 +15921,11 @@ msgstr "额外依赖" #: ../../source/ref-example-projects.rst:71 msgid "" -"The core Flower framework keeps a minimal set of dependencies. The examples " -"demonstrate Flower in the context of different machine learning frameworks, " -"so additional dependencies need to be installed before an example can be run." -msgstr "" -"Flower 核心框架只保留了最低限度的依赖项。这些示例在不同机器学习框架的背景下演" -"示了 Flower,因此在运行示例之前需要安装额外的依赖项。" +"The core Flower framework keeps a minimal set of dependencies. The " +"examples demonstrate Flower in the context of different machine learning " +"frameworks, so additional dependencies need to be installed before an " +"example can be run." +msgstr "Flower 核心框架只保留了最低限度的依赖项。这些示例在不同机器学习框架的背景下演示了 Flower,因此在运行示例之前需要安装额外的依赖项。" #: ../../source/ref-example-projects.rst:75 msgid "For PyTorch examples::" @@ -11954,8 +15944,8 @@ msgid "" "Please consult :code:`pyproject.toml` for a full list of possible extras " "(section :code:`[tool.poetry.extras]`)." msgstr "" -"请参阅 :code:`pyproject.toml`,了解可能的 extras 的完整列表(章节 :code:" -"`[tool.poems.extras]`)。" +"请参阅 :code:`pyproject.toml`,了解可能的 extras 的完整列表(章节 " +":code:`[tool.poems.extras]`)。" #: ../../source/ref-example-projects.rst:92 msgid "PyTorch Examples" @@ -11963,11 +15953,9 @@ msgstr "PyTorch 示例" #: ../../source/ref-example-projects.rst:94 msgid "" -"Our PyTorch examples are based on PyTorch 1.7. They should work with other " -"releases as well. So far, we provide the following examples." -msgstr "" -"我们的 PyTorch 示例基于 PyTorch 1.7。它们应该也能在其他版本中使用。到目前为" -"止,我们提供了以下示例。" +"Our PyTorch examples are based on PyTorch 1.7. They should work with " +"other releases as well. So far, we provide the following examples." +msgstr "我们的 PyTorch 示例基于 PyTorch 1.7。它们应该也能在其他版本中使用。到目前为止,我们提供了以下示例。" #: ../../source/ref-example-projects.rst:98 msgid "CIFAR-10 Image Classification" @@ -11975,13 +15963,14 @@ msgstr "CIFAR-10 图像分类" #: ../../source/ref-example-projects.rst:100 msgid "" -"`CIFAR-10 and CIFAR-100 `_ are " -"popular RGB image datasets. The Flower CIFAR-10 example uses PyTorch to " -"train a simple CNN classifier in a federated learning setup with two clients." +"`CIFAR-10 and CIFAR-100 `_ " +"are popular RGB image datasets. The Flower CIFAR-10 example uses PyTorch " +"to train a simple CNN classifier in a federated learning setup with two " +"clients." msgstr "" "CIFAR-10 和 CIFAR-100 ``_ " -"是流行的 RGB 图像数据集。Flower CIFAR-10 示例使用 PyTorch " -"在有两个客户端的联邦学习设置中训练一个简单的 CNN 分类器。" +"是流行的 RGB 图像数据集。Flower CIFAR-10 示例使用 PyTorch 在有两个客户端的联邦学习设置中训练一个简单的 CNN " +"分类器。" #: ../../source/ref-example-projects.rst:104 #: ../../source/ref-example-projects.rst:121 @@ -12013,13 +16002,12 @@ msgstr "ImageNet-2012 图像分类" #: ../../source/ref-example-projects.rst:117 msgid "" -"`ImageNet-2012 `_ is one of the major computer " -"vision datasets. The Flower ImageNet example uses PyTorch to train a " +"`ImageNet-2012 `_ is one of the major computer" +" vision datasets. The Flower ImageNet example uses PyTorch to train a " "ResNet-18 classifier in a federated learning setup with ten clients." msgstr "" -"ImageNet-2012 `_ 是主要的计算机视觉数据集之一。" -"Flower ImageNet 示例使用 PyTorch 在有十个客户端的联邦学习设置中训练 ResNet-" -"18 分类器。" +"ImageNet-2012 `_ 是主要的计算机视觉数据集之一。Flower " +"ImageNet 示例使用 PyTorch 在有十个客户端的联邦学习设置中训练 ResNet-18 分类器。" #: ../../source/ref-example-projects.rst:123 msgid "$ ./src/py/flwr_example/pytorch_imagenet/run-server.sh" @@ -12041,9 +16029,7 @@ msgstr "TensorFlow 示例" msgid "" "Our TensorFlow examples are based on TensorFlow 2.0 or newer. So far, we " "provide the following examples." -msgstr "" -"我们的 TensorFlow 示例基于 TensorFlow 2.0 或更新版本。到目前为止,我们提供了" -"以下示例。" +msgstr "我们的 TensorFlow 示例基于 TensorFlow 2.0 或更新版本。到目前为止,我们提供了以下示例。" #: ../../source/ref-example-projects.rst:139 msgid "Fashion-MNIST Image Classification" @@ -12051,14 +16037,15 @@ msgstr "Fashion-MNIST 图像分类" #: ../../source/ref-example-projects.rst:141 msgid "" -"`Fashion-MNIST `_ is often " -"used as the \"Hello, world!\" of machine learning. We follow this tradition " -"and provide an example which samples random local datasets from Fashion-" -"MNIST and trains a simple image classification model over those partitions." +"`Fashion-MNIST `_ is " +"often used as the \"Hello, world!\" of machine learning. We follow this " +"tradition and provide an example which samples random local datasets from" +" Fashion-MNIST and trains a simple image classification model over those " +"partitions." msgstr "" "`Fashion-MNIST `_ " -"经常被用作机器学习的 \"你好,世界!\"。我们遵循这一传统,提供了一个从Fashion-" -"MNIST 中随机抽样本地数据集的示例,并在这些分区上训练一个简单的图像分类模型。" +"经常被用作机器学习的 \"你好,世界!\"。我们遵循这一传统,提供了一个从Fashion-MNIST " +"中随机抽样本地数据集的示例,并在这些分区上训练一个简单的图像分类模型。" #: ../../source/ref-example-projects.rst:148 msgid "$ ./src/py/flwr_example/tensorflow_fashion_mnist/run-server.sh" @@ -12070,9 +16057,9 @@ msgstr "$ ./src/py/flwr_example/tensorflow_fashion_mnist/run-clients.sh" #: ../../source/ref-example-projects.rst:154 msgid "" -"For more details, see :code:`src/py/flwr_example/tensorflow_fashion_mnist`." -msgstr "" -"更多详情,请参阅 :code:`src/py/flwr_example/tensorflow_fashion_mnist`。" +"For more details, see " +":code:`src/py/flwr_example/tensorflow_fashion_mnist`." +msgstr "更多详情,请参阅 :code:`src/py/flwr_example/tensorflow_fashion_mnist`。" #: ../../source/ref-faq.rst:4 msgid "" @@ -12082,32 +16069,33 @@ msgstr "本页收集了有关 \"Flower 联邦学习 \"常见问题的答案。" #: ../../source/ref-faq.rst msgid ":fa:`eye,mr-1` Can Flower run on Juptyter Notebooks / Google Colab?" -msgstr "" -":fa:`eye,mr-1` Flower 可以在 Juptyter Notebooks / Google Colab 上运行吗?" +msgstr ":fa:`eye,mr-1` Flower 可以在 Juptyter Notebooks / Google Colab 上运行吗?" #: ../../source/ref-faq.rst:8 msgid "" -"Yes, it can! Flower even comes with a few under-the-hood optimizations to " -"make it work even better on Colab. Here's a quickstart example:" -msgstr "" -"是的,它可以!Flower 甚至还进行了一些底层优化,使其在 Colab 上运行得更好。下" -"面是一个快速启动示例:" +"Yes, it can! Flower even comes with a few under-the-hood optimizations to" +" make it work even better on Colab. Here's a quickstart example:" +msgstr "是的,它可以!Flower 甚至还进行了一些底层优化,使其在 Colab 上运行得更好。下面是一个快速启动示例:" #: ../../source/ref-faq.rst:10 msgid "" -"`Flower simulation PyTorch `_" +"`Flower simulation PyTorch " +"`_" msgstr "" -"`Flower 模拟 PyTorch `_" +"`Flower 模拟 PyTorch " +"`_" #: ../../source/ref-faq.rst:11 msgid "" -"`Flower simulation TensorFlow/Keras `_" +"`Flower simulation TensorFlow/Keras " +"`_" msgstr "" -"`Flower模拟TensorFlow/Keras `_" +"`Flower模拟TensorFlow/Keras " +"`_" #: ../../source/ref-faq.rst msgid ":fa:`eye,mr-1` How can I run Federated Learning on a Raspberry Pi?" @@ -12116,36 +16104,35 @@ msgstr ":fa:`eye,mr-1` 如何在 Raspberry Pi 上运行联邦学习?" #: ../../source/ref-faq.rst:15 msgid "" "Find the `blog post about federated learning on embedded device here " -"`_ " -"and the corresponding `GitHub code example `_." +"`_" +" and the corresponding `GitHub code example " +"`_." msgstr "" -"请点击此处查看有关嵌入式设备联邦学习的 \"博文\"`_和相应的 \"GitHub 代码示例\"`_。" +"请点击此处查看有关嵌入式设备联邦学习的 " +"\"博文\"`_和相应的" +" \"GitHub 代码示例\"`_。" #: ../../source/ref-faq.rst -msgid "" -":fa:`eye,mr-1` Does Flower support federated learning on Android devices?" +msgid ":fa:`eye,mr-1` Does Flower support federated learning on Android devices?" msgstr ":fa:`eye,mr-1` Flower 是否支持安卓设备上的联邦学习?" #: ../../source/ref-faq.rst:19 msgid "" -"Yes, it does. Please take a look at our `blog post `_ or " -"check out the code examples:" +"Yes, it does. Please take a look at our `blog post " +"`_ or check out the code examples:" msgstr "" -"是的,确实如此。请查看我们的 \"博客文章 `_\" 或查看代码示例:" +"是的,确实如此。请查看我们的 \"博客文章 `_\" 或查看代码示例:" #: ../../source/ref-faq.rst:21 msgid "" -"`Android Kotlin example `_" +"`Android Kotlin example `_" msgstr "" -"`Android Kotlin 示例 `_" +"`Android Kotlin 示例 `_" #: ../../source/ref-faq.rst:22 msgid "`Android Java example `_" @@ -12163,45 +16150,45 @@ msgstr "当然可以。有关在区块链环境中使用 Flower 的可用示例 #: ../../source/ref-faq.rst:28 msgid "" -"`Flower meets Nevermined GitHub Repository `_." +"`Flower meets Nevermined GitHub Repository `_." msgstr "" -"`Flower meets Nevermined GitHub Repository `_." +"`Flower meets Nevermined GitHub Repository `_." #: ../../source/ref-faq.rst:29 msgid "" -"`Flower meets Nevermined YouTube video `_." +"`Flower meets Nevermined YouTube video " +"`_." msgstr "" -"`Flower meets Nevermined YouTube 视频 `_." +"`Flower meets Nevermined YouTube 视频 " +"`_." #: ../../source/ref-faq.rst:30 msgid "" -"`Flower meets KOSMoS `_." +"`Flower meets KOSMoS `_." msgstr "" -"`Flower meets KOSMoS `_." +"`Flower meets KOSMoS `_." #: ../../source/ref-faq.rst:31 msgid "" "`Flower meets Talan blog post `_ ." +"learning-same-mask-different-faces-imen-" +"ayari/?trackingId=971oIlxLQ9%2BA9RB0IQ73XQ%3D%3D>`_ ." msgstr "" -"`Flower meets Talan博文 `_ 。" +"`Flower meets Talan博文 `_ 。" #: ../../source/ref-faq.rst:32 msgid "" -"`Flower meets Talan GitHub Repository `_ ." +"`Flower meets Talan GitHub Repository " +"`_ ." msgstr "" -"`Flower meets Talan GitHub Repository `_ ." +"`Flower meets Talan GitHub Repository " +"`_ ." #: ../../source/ref-telemetry.md:1 msgid "Telemetry" @@ -12209,64 +16196,60 @@ msgstr "遥测功能" #: ../../source/ref-telemetry.md:3 msgid "" -"The Flower open-source project collects **anonymous** usage metrics to make " -"well-informed decisions to improve Flower. Doing this enables the Flower " -"team to understand how Flower is used and what challenges users might face." +"The Flower open-source project collects **anonymous** usage metrics to " +"make well-informed decisions to improve Flower. Doing this enables the " +"Flower team to understand how Flower is used and what challenges users " +"might face." msgstr "" -"Flower 开源项目收集**匿名**使用指标,以便在充分知情的情况下做出改进 Flower 的" -"决定。这样做能让 Flower 团队了解 Flower 的使用情况以及用户可能面临的挑战。" +"Flower 开源项目收集**匿名**使用指标,以便在充分知情的情况下做出改进 Flower 的决定。这样做能让 Flower 团队了解 " +"Flower 的使用情况以及用户可能面临的挑战。" #: ../../source/ref-telemetry.md:5 msgid "" -"**Flower is a friendly framework for collaborative AI and data science.** " -"Staying true to this statement, Flower makes it easy to disable telemetry " -"for users that do not want to share anonymous usage metrics." -msgstr "" -"**Flower 是一个用于协作式人工智能和数据科学的友好框架。** Flower 遵循这一声" -"明,让不想分享匿名使用指标的用户可以轻松禁用遥测技术。" +"**Flower is a friendly framework for collaborative AI and data science.**" +" Staying true to this statement, Flower makes it easy to disable " +"telemetry for users that do not want to share anonymous usage metrics." +msgstr "**Flower 是一个用于协作式人工智能和数据科学的友好框架。** Flower 遵循这一声明,让不想分享匿名使用指标的用户可以轻松禁用遥测技术。" #: ../../source/ref-telemetry.md:7 msgid "Principles" msgstr "原则" #: ../../source/ref-telemetry.md:9 -msgid "" -"We follow strong principles guarding anonymous usage metrics collection:" +msgid "We follow strong principles guarding anonymous usage metrics collection:" msgstr "我们遵循严格的匿名使用指标收集原则:" #: ../../source/ref-telemetry.md:11 msgid "" -"**Optional:** You will always be able to disable telemetry; read on to learn " -"“[How to opt-out](#how-to-opt-out)”." -msgstr "" -"**可选:** 您始终可以禁用遥测功能;请继续阅读\"[如何退出](#how-to-opt-" -"out)\"。" +"**Optional:** You will always be able to disable telemetry; read on to " +"learn “[How to opt-out](#how-to-opt-out)”." +msgstr "**可选:** 您始终可以禁用遥测功能;请继续阅读\"[如何退出](#how-to-opt-out)\"。" #: ../../source/ref-telemetry.md:12 msgid "" -"**Anonymous:** The reported usage metrics are anonymous and do not contain " -"any personally identifiable information (PII). See “[Collected metrics]" -"(#collected-metrics)” to understand what metrics are being reported." +"**Anonymous:** The reported usage metrics are anonymous and do not " +"contain any personally identifiable information (PII). See “[Collected " +"metrics](#collected-metrics)” to understand what metrics are being " +"reported." msgstr "" -"**匿名:** 报告的使用指标是匿名的,不包含任何个人身份信息 (PII)。请参阅\"[收" -"集的指标](#collected-metrics) \"了解报告的指标。" +"**匿名:** 报告的使用指标是匿名的,不包含任何个人身份信息 (PII)。请参阅\"[收集的指标](#collected-metrics) " +"\"了解报告的指标。" #: ../../source/ref-telemetry.md:13 msgid "" "**Transparent:** You can easily inspect what anonymous metrics are being " -"reported; see the section “[How to inspect what is being reported](#how-to-" -"inspect-what-is-being-reported)”" +"reported; see the section “[How to inspect what is being reported](#how-" +"to-inspect-what-is-being-reported)”" msgstr "" -"**透明:** 您可以轻松查看正在报告的匿名指标;请参阅\"[如何查看正在报告的指标]" -"(#how-to-inspect-what-is-being-reported)\"部分" +"**透明:** 您可以轻松查看正在报告的匿名指标;请参阅\"[如何查看正在报告的指标](#how-to-inspect-what-is-" +"being-reported)\"部分" #: ../../source/ref-telemetry.md:14 msgid "" -"**Open for feedback:** You can always reach out to us if you have feedback; " -"see the section “[How to contact us](#how-to-contact-us)” for details." -msgstr "" -"**欢迎反馈:** 如果您有反馈意见,可以随时联系我们;详情请参见\"[如何联系我们]" -"(#how-to-contact-us) \"部分。" +"**Open for feedback:** You can always reach out to us if you have " +"feedback; see the section “[How to contact us](#how-to-contact-us)” for " +"details." +msgstr "**欢迎反馈:** 如果您有反馈意见,可以随时联系我们;详情请参见\"[如何联系我们](#how-to-contact-us) \"部分。" #: ../../source/ref-telemetry.md:16 msgid "How to opt-out" @@ -12280,17 +16263,17 @@ msgid "" "client, simply do so by prepending your command as in:" msgstr "" "Flower 启动时,会检查环境变量 `FLWR_TELEMETRY_ENABLED` 是否存在。通过设置 " -"`FLWR_TELEMETRY_ENABLED=0` 可以轻松禁用遥测功能。假设你启动的是 Flower 服务器" -"或客户端,只需在命令前添加以下内容即可:" +"`FLWR_TELEMETRY_ENABLED=0` 可以轻松禁用遥测功能。假设你启动的是 Flower " +"服务器或客户端,只需在命令前添加以下内容即可:" #: ../../source/ref-telemetry.md:24 msgid "" -"Alternatively, you can export `FLWR_TELEMETRY_ENABLED=0` in, for example, `." -"bashrc` (or whatever configuration file applies to your environment) to " -"disable Flower telemetry permanently." +"Alternatively, you can export `FLWR_TELEMETRY_ENABLED=0` in, for example," +" `.bashrc` (or whatever configuration file applies to your environment) " +"to disable Flower telemetry permanently." msgstr "" -"或者,你也可以在 `.bashrc`(或任何适用于你的环境的配置文件)中导出 " -"`FLWR_TELEMETRY_ENABLED=0` 来永久禁用 Flower telemetry。" +"或者,你也可以在 `.bashrc`(或任何适用于你的环境的配置文件)中导出 `FLWR_TELEMETRY_ENABLED=0` 来永久禁用 " +"Flower telemetry。" #: ../../source/ref-telemetry.md:26 msgid "Collected metrics" @@ -12302,21 +16285,17 @@ msgstr "Flower 遥测技术收集以下指标:" #: ../../source/ref-telemetry.md:30 msgid "" -"**Flower version.** Understand which versions of Flower are currently being " -"used. This helps us to decide whether we should invest effort into releasing " -"a patch version for an older version of Flower or instead use the bandwidth " -"to build new features." -msgstr "" -"**了解目前使用的 Flower 版本。这有助于我们决定是否应该投入精力为旧版本的 " -"Flower 发布补丁版本,还是利用带宽来构建新功能。" +"**Flower version.** Understand which versions of Flower are currently " +"being used. This helps us to decide whether we should invest effort into " +"releasing a patch version for an older version of Flower or instead use " +"the bandwidth to build new features." +msgstr "**了解目前使用的 Flower 版本。这有助于我们决定是否应该投入精力为旧版本的 Flower 发布补丁版本,还是利用带宽来构建新功能。" #: ../../source/ref-telemetry.md:32 msgid "" "**Operating system.** Enables us to answer questions such as: *Should we " "create more guides for Linux, macOS, or Windows?*" -msgstr "" -"**操作系统**使我们能够回答以下问题: *我们应该为 Linux、macOS 还是 Windows 创" -"建更多指南?*" +msgstr "**操作系统**使我们能够回答以下问题: *我们应该为 Linux、macOS 还是 Windows 创建更多指南?*" #: ../../source/ref-telemetry.md:34 msgid "" @@ -12324,82 +16303,73 @@ msgid "" "decide whether we should invest effort into supporting old versions of " "Python or stop supporting them and start taking advantage of new Python " "features." -msgstr "" -"**例如,了解 Python 版本有助于我们决定是否应该投入精力支持旧版本的 Python,还" -"是停止支持这些版本并开始利用新的 Python 功能。" +msgstr "**例如,了解 Python 版本有助于我们决定是否应该投入精力支持旧版本的 Python,还是停止支持这些版本并开始利用新的 Python 功能。" #: ../../source/ref-telemetry.md:36 msgid "" -"**Hardware properties.** Understanding the hardware environment that Flower " -"is being used in helps to decide whether we should, for example, put more " -"effort into supporting low-resource environments." -msgstr "" -"**硬件属性** 了解 Flower 的硬件使用环境,有助于决定我们是否应在支持低资源环境" -"等方面投入更多精力。" +"**Hardware properties.** Understanding the hardware environment that " +"Flower is being used in helps to decide whether we should, for example, " +"put more effort into supporting low-resource environments." +msgstr "**硬件属性** 了解 Flower 的硬件使用环境,有助于决定我们是否应在支持低资源环境等方面投入更多精力。" #: ../../source/ref-telemetry.md:38 msgid "" -"**Execution mode.** Knowing what execution mode Flower starts in enables us " -"to understand how heavily certain features are being used and better " +"**Execution mode.** Knowing what execution mode Flower starts in enables " +"us to understand how heavily certain features are being used and better " "prioritize based on that." -msgstr "" -"** 执行模式** 了解 Flower 的启动执行模式,能让我们了解某些功能的使用率,并据" -"此更好地确定优先级。" +msgstr "** 执行模式** 了解 Flower 的启动执行模式,能让我们了解某些功能的使用率,并据此更好地确定优先级。" #: ../../source/ref-telemetry.md:40 msgid "" "**Cluster.** Flower telemetry assigns a random in-memory cluster ID each " "time a Flower workload starts. This allows us to understand which device " -"types not only start Flower workloads but also successfully complete them." +"types not only start Flower workloads but also successfully complete " +"them." msgstr "" -"**每次 Flower 工作负载启动时,Flower 遥测都会随机分配一个内存集群 ID。这样," -"我们就能了解哪些设备类型不仅启动了 Flower 工作负载,而且还成功完成了它们。" +"**每次 Flower 工作负载启动时,Flower 遥测都会随机分配一个内存集群 ID。这样,我们就能了解哪些设备类型不仅启动了 Flower " +"工作负载,而且还成功完成了它们。" #: ../../source/ref-telemetry.md:42 msgid "" -"**Source.** Flower telemetry tries to store a random source ID in `~/.flwr/" -"source` the first time a telemetry event is generated. The source ID is " -"important to identify whether an issue is recurring or whether an issue is " -"triggered by multiple clusters running concurrently (which often happens in " -"simulation). For example, if a device runs multiple workloads at the same " -"time, and this results in an issue, then, in order to reproduce the issue, " -"multiple workloads must be started at the same time." +"**Source.** Flower telemetry tries to store a random source ID in " +"`~/.flwr/source` the first time a telemetry event is generated. The " +"source ID is important to identify whether an issue is recurring or " +"whether an issue is triggered by multiple clusters running concurrently " +"(which often happens in simulation). For example, if a device runs " +"multiple workloads at the same time, and this results in an issue, then, " +"in order to reproduce the issue, multiple workloads must be started at " +"the same time." msgstr "" -"**Source.** Flower 遥测会在第一次生成遥测事件时,尝试在 `~/.flwr/source` 中存" -"储一个随机源 ID。源 ID 对于识别问题是否反复出现或问题是否由多个集群同时运行触" -"发(这在模拟中经常发生)非常重要。例如,如果设备同时运行多个工作负载并导致问" -"题,那么为了重现问题,必须同时启动多个工作负载。" +"**Source.** Flower 遥测会在第一次生成遥测事件时,尝试在 `~/.flwr/source` 中存储一个随机源 ID。源 ID " +"对于识别问题是否反复出现或问题是否由多个集群同时运行触发(这在模拟中经常发生)非常重要。例如,如果设备同时运行多个工作负载并导致问题,那么为了重现问题,必须同时启动多个工作负载。" #: ../../source/ref-telemetry.md:44 msgid "" -"You may delete the source ID at any time. If you wish for all events logged " -"under a specific source ID to be deleted, you can send a deletion request " -"mentioning the source ID to `telemetry@flower.dev`. All events related to " -"that source ID will then be permanently deleted." +"You may delete the source ID at any time. If you wish for all events " +"logged under a specific source ID to be deleted, you can send a deletion " +"request mentioning the source ID to `telemetry@flower.dev`. All events " +"related to that source ID will then be permanently deleted." msgstr "" -"您可以随时删除源 ID。如果您希望删除特定源 ID 下记录的所有事件,可以向 " -"`telemetry@flower.dev` 发送删除请求,并提及该源 ID。届时,与该源 ID 相关的所" -"有事件都将被永久删除。" +"您可以随时删除源 ID。如果您希望删除特定源 ID 下记录的所有事件,可以向 `telemetry@flower.dev` " +"发送删除请求,并提及该源 ID。届时,与该源 ID 相关的所有事件都将被永久删除。" #: ../../source/ref-telemetry.md:46 msgid "" -"We will not collect any personally identifiable information. If you think " -"any of the metrics collected could be misused in any way, please [get in " -"touch with us](#how-to-contact-us). We will update this page to reflect any " -"changes to the metrics collected and publish changes in the changelog." +"We will not collect any personally identifiable information. If you think" +" any of the metrics collected could be misused in any way, please [get in" +" touch with us](#how-to-contact-us). We will update this page to reflect " +"any changes to the metrics collected and publish changes in the " +"changelog." msgstr "" -"我们不会收集任何个人身份信息。如果您认为所收集的任何指标可能以任何方式被滥" -"用,请[与我们联系](#how-to-contact-us)。我们将更新本页面,以反映对所收集指" -"标的任何更改,并在更新日志中公布更改内容。" +"我们不会收集任何个人身份信息。如果您认为所收集的任何指标可能以任何方式被滥用,请[与我们联系](#how-to-contact-" +"us)。我们将更新本页面,以反映对所收集指标的任何更改,并在更新日志中公布更改内容。" #: ../../source/ref-telemetry.md:48 msgid "" "If you think other metrics would be helpful for us to better guide our " "decisions, please let us know! We will carefully review them; if we are " "confident that they do not compromise user privacy, we may add them." -msgstr "" -"如果您认为其他指标有助于我们更好地指导决策,请告诉我们!我们将仔细审查这些指" -"标;如果我们确信它们不会损害用户隐私,我们可能会添加这些指标。" +msgstr "如果您认为其他指标有助于我们更好地指导决策,请告诉我们!我们将仔细审查这些指标;如果我们确信它们不会损害用户隐私,我们可能会添加这些指标。" #: ../../source/ref-telemetry.md:50 msgid "How to inspect what is being reported" @@ -12408,23 +16378,21 @@ msgstr "如何检查报告中的内容" #: ../../source/ref-telemetry.md:52 msgid "" "We wanted to make it very easy for you to inspect what anonymous usage " -"metrics are reported. You can view all the reported telemetry information by " -"setting the environment variable `FLWR_TELEMETRY_LOGGING=1`. Logging is " -"disabled by default. You may use logging independently from " +"metrics are reported. You can view all the reported telemetry information" +" by setting the environment variable `FLWR_TELEMETRY_LOGGING=1`. Logging " +"is disabled by default. You may use logging independently from " "`FLWR_TELEMETRY_ENABLED` so that you can inspect the telemetry feature " "without sending any metrics." msgstr "" -"我们希望能让您轻松查看所报告的匿名使用指标。通过设置环境变量 " -"`FLWR_TELEMETRY_LOGGING=1` 可以查看所有报告的遥测信息。日志记录默认为禁用。您" -"可以不使用 `FLWR_TELEMETRY_ENABLED` 而单独使用日志记录,这样就可以在不发送任" -"何指标的情况下检查遥测功能。" +"我们希望能让您轻松查看所报告的匿名使用指标。通过设置环境变量 `FLWR_TELEMETRY_LOGGING=1` " +"可以查看所有报告的遥测信息。日志记录默认为禁用。您可以不使用 `FLWR_TELEMETRY_ENABLED` " +"而单独使用日志记录,这样就可以在不发送任何指标的情况下检查遥测功能。" #: ../../source/ref-telemetry.md:58 msgid "" -"The inspect Flower telemetry without sending any anonymous usage metrics, " -"use both environment variables:" -msgstr "" -"在不发送任何匿名使用指标的情况下检查 Flower 遥测,可使用这两个环境变量:" +"The inspect Flower telemetry without sending any anonymous usage metrics," +" use both environment variables:" +msgstr "在不发送任何匿名使用指标的情况下检查 Flower 遥测,可使用这两个环境变量:" #: ../../source/ref-telemetry.md:64 msgid "How to contact us" @@ -12437,14 +16405,13 @@ msgid "" "[Slack](https://flower.dev/join-slack/) (channel `#telemetry`) or email " "(`telemetry@flower.dev`)." msgstr "" -"我们希望听到您的意见。如果您对如何改进我们处理匿名使用指标的方式有任何反馈或" -"想法,请通过 [Slack](https://flower.dev/join-slack/) (频道 `#telemetry`)或" -"电子邮件 (`telemetry@flower.dev`)与我们联系。" +"我们希望听到您的意见。如果您对如何改进我们处理匿名使用指标的方式有任何反馈或想法,请通过 [Slack](https://flower.dev" +"/join-slack/) (频道 `#telemetry`)或电子邮件 (`telemetry@flower.dev`)与我们联系。" #: ../../source/tutorial-quickstart-android.rst:-1 msgid "" -"Read this Federated Learning quickstart tutorial for creating an Android app " -"using Flower." +"Read this Federated Learning quickstart tutorial for creating an Android " +"app using Flower." msgstr "阅读本联邦学习快速入门教程,了解如何使用 Flower 创建 Android 应用程序。" #: ../../source/tutorial-quickstart-android.rst:5 @@ -12453,23 +16420,24 @@ msgstr "快速入门 Android" #: ../../source/tutorial-quickstart-android.rst:10 msgid "" -"Let's build a federated learning system using TFLite and Flower on Android!" +"Let's build a federated learning system using TFLite and Flower on " +"Android!" msgstr "让我们在 Android 上使用 TFLite 和 Flower 构建一个联邦学习系统!" #: ../../source/tutorial-quickstart-android.rst:12 msgid "" -"Please refer to the `full code example `_ to learn more." +"Please refer to the `full code example " +"`_ to learn " +"more." msgstr "" -"请参阅`完整代码示例 `_了解更多信息。" +"请参阅`完整代码示例 " +"`_了解更多信息。" #: ../../source/tutorial-quickstart-fastai.rst:-1 msgid "" -"Check out this Federated Learning quickstart tutorial for using Flower with " -"FastAI to train a vision model on CIFAR-10." -msgstr "查看此联邦学习快速入门教程,了解如何使用 Flower 和 FastAI 在 CIFAR-10 " -"上训练视觉模型。" +"Check out this Federated Learning quickstart tutorial for using Flower " +"with FastAI to train a vision model on CIFAR-10." +msgstr "查看此联邦学习快速入门教程,了解如何使用 Flower 和 FastAI 在 CIFAR-10 上训练视觉模型。" #: ../../source/tutorial-quickstart-fastai.rst:5 msgid "Quickstart fastai" @@ -12481,18 +16449,18 @@ msgstr "让我们用 fastai 和 Flower 建立一个联邦学习系统!" #: ../../source/tutorial-quickstart-fastai.rst:12 msgid "" -"Please refer to the `full code example `_ to learn more." +"Please refer to the `full code example " +"`_ " +"to learn more." msgstr "" -"请参阅 `完整代码示例 `_了解更多信息。" +"请参阅 `完整代码示例 `_了解更多信息。" #: ../../source/tutorial-quickstart-huggingface.rst:-1 msgid "" -"Check out this Federating Learning quickstart tutorial for using Flower with " -"HuggingFace Transformers in order to fine-tune an LLM." -msgstr "查看此联邦学习 快速入门教程,了解如何使用 Flower 和 HuggingFace Transformers " -"来微调 LLM。" +"Check out this Federating Learning quickstart tutorial for using Flower " +"with HuggingFace Transformers in order to fine-tune an LLM." +msgstr "查看此联邦学习 快速入门教程,了解如何使用 Flower 和 HuggingFace Transformers 来微调 LLM。" #: ../../source/tutorial-quickstart-huggingface.rst:5 msgid "Quickstart 🤗 Transformers" @@ -12500,22 +16468,20 @@ msgstr "🤗 Transformers快速入门" #: ../../source/tutorial-quickstart-huggingface.rst:10 msgid "" -"Let's build a federated learning system using Hugging Face Transformers and " -"Flower!" +"Let's build a federated learning system using Hugging Face Transformers " +"and Flower!" msgstr "让我们用Hugging Face Transformers和Flower来构建一个联邦学习系统!" #: ../../source/tutorial-quickstart-huggingface.rst:12 msgid "" -"We will leverage Hugging Face to federate the training of language models " -"over multiple clients using Flower. More specifically, we will fine-tune a " -"pre-trained Transformer model (distilBERT) for sequence classification over " -"a dataset of IMDB ratings. The end goal is to detect if a movie rating is " -"positive or negative." +"We will leverage Hugging Face to federate the training of language models" +" over multiple clients using Flower. More specifically, we will fine-tune" +" a pre-trained Transformer model (distilBERT) for sequence classification" +" over a dataset of IMDB ratings. The end goal is to detect if a movie " +"rating is positive or negative." msgstr "" -"我们将利用Hugging Face技术,使用 Flower " -"在多个客户端上联邦训练语言模型。更具体地说,我们将对预先训练好的 Transformer " -"模型(distilBERT)进行微调,以便在 IMDB " -"评分数据集上进行序列分类。最终目标是检测电影评分是正面还是负面。" +"我们将利用Hugging Face技术,使用 Flower 在多个客户端上联邦训练语言模型。更具体地说,我们将对预先训练好的 " +"Transformer 模型(distilBERT)进行微调,以便在 IMDB 评分数据集上进行序列分类。最终目标是检测电影评分是正面还是负面。" #: ../../source/tutorial-quickstart-huggingface.rst:18 msgid "Dependencies" @@ -12524,12 +16490,12 @@ msgstr "依赖关系" #: ../../source/tutorial-quickstart-huggingface.rst:20 msgid "" "To follow along this tutorial you will need to install the following " -"packages: :code:`datasets`, :code:`evaluate`, :code:`flwr`, :code:`torch`, " -"and :code:`transformers`. This can be done using :code:`pip`:" +"packages: :code:`datasets`, :code:`evaluate`, :code:`flwr`, " +":code:`torch`, and :code:`transformers`. This can be done using " +":code:`pip`:" msgstr "" -"要学习本教程,您需要安装以下软件包: :code:`datasets`、 :code:`evaluate`、 :" -"code:`flwr`、 :code:`torch`和 :code:`transformers`。这可以通过 :code:`pip` 来" -"完成:" +"要学习本教程,您需要安装以下软件包: :code:`datasets`、 :code:`evaluate`、 :code:`flwr`、 " +":code:`torch`和 :code:`transformers`。这可以通过 :code:`pip` 来完成:" #: ../../source/tutorial-quickstart-huggingface.rst:30 msgid "Standard Hugging Face workflow" @@ -12545,9 +16511,8 @@ msgid "" "library. We then need to tokenize the data and create :code:`PyTorch` " "dataloaders, this is all done in the :code:`load_data` function:" msgstr "" -"为了获取 IMDB 数据集,我们将使用 Hugging Face 的 :code:`datasets` 库。然后," -"我们需要对数据进行标记化,并创建 :code:`PyTorch` 数据加载器,这些都将在 :" -"code:`load_data` 函数中完成:" +"为了获取 IMDB 数据集,我们将使用 Hugging Face 的 :code:`datasets` 库。然后,我们需要对数据进行标记化,并创建" +" :code:`PyTorch` 数据加载器,这些都将在 :code:`load_data` 函数中完成:" #: ../../source/tutorial-quickstart-huggingface.rst:81 msgid "Training and testing the model" @@ -12555,12 +16520,12 @@ msgstr "训练和测试模型" #: ../../source/tutorial-quickstart-huggingface.rst:83 msgid "" -"Once we have a way of creating our trainloader and testloader, we can take " -"care of the training and testing. This is very similar to any :code:" -"`PyTorch` training or testing loop:" +"Once we have a way of creating our trainloader and testloader, we can " +"take care of the training and testing. This is very similar to any " +":code:`PyTorch` training or testing loop:" msgstr "" -"有了创建 trainloader 和 testloader 的方法后,我们就可以进行训练和测试了。这与" -"任何 :code:`PyTorch` 训练或测试循环都非常相似:" +"有了创建 trainloader 和 testloader 的方法后,我们就可以进行训练和测试了。这与任何 :code:`PyTorch` " +"训练或测试循环都非常相似:" #: ../../source/tutorial-quickstart-huggingface.rst:121 msgid "Creating the model itself" @@ -12568,11 +16533,11 @@ msgstr "创建模型本身" #: ../../source/tutorial-quickstart-huggingface.rst:123 msgid "" -"To create the model itself, we will just load the pre-trained distillBERT " -"model using Hugging Face’s :code:`AutoModelForSequenceClassification` :" +"To create the model itself, we will just load the pre-trained distillBERT" +" model using Hugging Face’s :code:`AutoModelForSequenceClassification` :" msgstr "" -"要创建模型本身,我们只需使用 Hugging Face 的 :code:" -"`AutoModelForSequenceClassification` 加载预训练的 distillBERT 模型:" +"要创建模型本身,我们只需使用 Hugging Face 的 :code:`AutoModelForSequenceClassification` " +"加载预训练的 distillBERT 模型:" #: ../../source/tutorial-quickstart-huggingface.rst:136 msgid "Federating the example" @@ -12585,24 +16550,23 @@ msgstr "创建 IMDBClient" #: ../../source/tutorial-quickstart-huggingface.rst:141 msgid "" "To federate our example to multiple clients, we first need to write our " -"Flower client class (inheriting from :code:`flwr.client.NumPyClient`). This " -"is very easy, as our model is a standard :code:`PyTorch` model:" +"Flower client class (inheriting from :code:`flwr.client.NumPyClient`). " +"This is very easy, as our model is a standard :code:`PyTorch` model:" msgstr "" "要将我们的示例联邦到多个客户端,我们首先需要编写 Flower 客户端类(继承自 " -":code:`flwr.client.NumPyClient`)。这很容易,因为我们的模型是一个标准的 " -":code:`PyTorch` 模型:" +":code:`flwr.client.NumPyClient`)。这很容易,因为我们的模型是一个标准的 :code:`PyTorch` 模型:" #: ../../source/tutorial-quickstart-huggingface.rst:169 msgid "" "The :code:`get_parameters` function lets the server get the client's " -"parameters. Inversely, the :code:`set_parameters` function allows the server " -"to send its parameters to the client. Finally, the :code:`fit` function " -"trains the model locally for the client, and the :code:`evaluate` function " -"tests the model locally and returns the relevant metrics." +"parameters. Inversely, the :code:`set_parameters` function allows the " +"server to send its parameters to the client. Finally, the :code:`fit` " +"function trains the model locally for the client, and the " +":code:`evaluate` function tests the model locally and returns the " +"relevant metrics." msgstr "" -":code:`get_parameters` 函数允许服务器获取客户端的参数。相反,:code:" -"`set_parameters`函数允许服务器将其参数发送给客户端。最后,:code:`fit`函数在本" -"地为客户端训练模型,:code:`evaluate`函数在本地测试模型并返回相关指标。" +":code:`get_parameters` " +"函数允许服务器获取客户端的参数。相反,:code:`set_parameters`函数允许服务器将其参数发送给客户端。最后,:code:`fit`函数在本地为客户端训练模型,:code:`evaluate`函数在本地测试模型并返回相关指标。" #: ../../source/tutorial-quickstart-huggingface.rst:175 msgid "Starting the server" @@ -12610,26 +16574,25 @@ msgstr "启动服务器" #: ../../source/tutorial-quickstart-huggingface.rst:177 msgid "" -"Now that we have a way to instantiate clients, we need to create our server " -"in order to aggregate the results. Using Flower, this can be done very " -"easily by first choosing a strategy (here, we are using :code:`FedAvg`, " -"which will define the global weights as the average of all the clients' " -"weights at each round) and then using the :code:`flwr.server.start_server` " -"function:" +"Now that we have a way to instantiate clients, we need to create our " +"server in order to aggregate the results. Using Flower, this can be done " +"very easily by first choosing a strategy (here, we are using " +":code:`FedAvg`, which will define the global weights as the average of " +"all the clients' weights at each round) and then using the " +":code:`flwr.server.start_server` function:" msgstr "" -"现在我们有了实例化客户端的方法,我们需要创建服务器,以便汇总结果。使用 " -"Flower,首先选择一个策略(这里我们使用 " -":code:`FedAvg`,它将把全局模型参数定义为每轮所有客户端模型参数的平均值)," -"然后使用 :code:`flwr.server.start_server`函数,就可以非常轻松地完成这项工作:" +"现在我们有了实例化客户端的方法,我们需要创建服务器,以便汇总结果。使用 Flower,首先选择一个策略(这里我们使用 " +":code:`FedAvg`,它将把全局模型参数定义为每轮所有客户端模型参数的平均值),然后使用 " +":code:`flwr.server.start_server`函数,就可以非常轻松地完成这项工作:" #: ../../source/tutorial-quickstart-huggingface.rst:205 msgid "" -"The :code:`weighted_average` function is there to provide a way to aggregate " -"the metrics distributed amongst the clients (basically this allows us to " -"display a nice average accuracy and loss for every round)." +"The :code:`weighted_average` function is there to provide a way to " +"aggregate the metrics distributed amongst the clients (basically this " +"allows us to display a nice average accuracy and loss for every round)." msgstr "" -"使用 :code:`weighted_average` 函数是为了提供一种方法来汇总分布在客户端的指标" -"(基本上,这可以让我们显示每一轮的平均精度和损失值)。" +"使用 :code:`weighted_average` " +"函数是为了提供一种方法来汇总分布在客户端的指标(基本上,这可以让我们显示每一轮的平均精度和损失值)。" #: ../../source/tutorial-quickstart-huggingface.rst:209 msgid "Putting everything together" @@ -12647,38 +16610,35 @@ msgstr "他们就能连接到服务器,开始联邦训练。" #: ../../source/tutorial-quickstart-huggingface.rst:223 msgid "" -"If you want to check out everything put together, you should check out the " -"full code example: [https://github.com/adap/flower/tree/main/examples/" -"quickstart-huggingface](https://github.com/adap/flower/tree/main/examples/" -"quickstart-huggingface)." +"If you want to check out everything put together, you should check out " +"the full code example: [https://github.com/adap/flower/tree/main/examples" +"/quickstart-" +"huggingface](https://github.com/adap/flower/tree/main/examples" +"/quickstart-huggingface)." msgstr "" -"如果您想查看所有内容,请查看完整的代码示例: [https://github.com/adap/flower/" -"tree/main/examples/quickstart-huggingface](https://github.com/adap/flower/" -"tree/main/examples/quickstart-huggingface)." +"如果您想查看所有内容,请查看完整的代码示例: [https://github.com/adap/flower/tree/main/examples" +"/quickstart-" +"huggingface](https://github.com/adap/flower/tree/main/examples" +"/quickstart-huggingface)." #: ../../source/tutorial-quickstart-huggingface.rst:227 msgid "" -"Of course, this is a very basic example, and a lot can be added or modified, " -"it was just to showcase how simply we could federate a Hugging Face workflow " -"using Flower." -msgstr "" -"当然,这只是一个非常基本的示例,还可以添加或修改很多内容," -"只是为了展示我们可以如何简单地使用 Flower 联合Hugging Face的工作流程。" +"Of course, this is a very basic example, and a lot can be added or " +"modified, it was just to showcase how simply we could federate a Hugging " +"Face workflow using Flower." +msgstr "当然,这只是一个非常基本的示例,还可以添加或修改很多内容,只是为了展示我们可以如何简单地使用 Flower 联合Hugging Face的工作流程。" #: ../../source/tutorial-quickstart-huggingface.rst:230 msgid "" -"Note that in this example we used :code:`PyTorch`, but we could have very " -"well used :code:`TensorFlow`." -msgstr "" -"请注意,在本例中我们使用了 :code:`PyTorch`,但也完全可以使用 :code:" -"`TensorFlow`。" +"Note that in this example we used :code:`PyTorch`, but we could have very" +" well used :code:`TensorFlow`." +msgstr "请注意,在本例中我们使用了 :code:`PyTorch`,但也完全可以使用 :code:`TensorFlow`。" #: ../../source/tutorial-quickstart-ios.rst:-1 msgid "" "Read this Federated Learning quickstart tutorial for creating an iOS app " "using Flower to train a neural network on MNIST." -msgstr "阅读本联邦学习快速入门教程,了解如何使用 Flower 创建 iOS 应用程序,并在 " -"MNIST 上训练神经网络。" +msgstr "阅读本联邦学习快速入门教程,了解如何使用 Flower 创建 iOS 应用程序,并在 MNIST 上训练神经网络。" #: ../../source/tutorial-quickstart-ios.rst:5 msgid "Quickstart iOS" @@ -12686,11 +16646,9 @@ msgstr "快速入门 iOS" #: ../../source/tutorial-quickstart-ios.rst:10 msgid "" -"In this tutorial we will learn how to train a Neural Network on MNIST using " -"Flower and CoreML on iOS devices." -msgstr "" -"在本教程中,我们将学习如何在 iOS 设备上使用 Flower 和 CoreML 在 MNIST 上训练" -"神经网络。" +"In this tutorial we will learn how to train a Neural Network on MNIST " +"using Flower and CoreML on iOS devices." +msgstr "在本教程中,我们将学习如何在 iOS 设备上使用 Flower 和 CoreML 在 MNIST 上训练神经网络。" #: ../../source/tutorial-quickstart-ios.rst:12 msgid "" @@ -12700,36 +16658,30 @@ msgid "" "client implementation in iOS, it is recommended to use Xcode as our IDE." msgstr "" "首先,为了运行 Flower Python 服务器,建议创建一个虚拟环境,并在 `virtualenv " -"`_ 中运行一切。对于在 " -"iOS 中实现 Flower 客户端,建议使用 Xcode 作为我们的集成开发环境。" +"`_ 中运行一切。对于在 iOS 中实现 " +"Flower 客户端,建议使用 Xcode 作为我们的集成开发环境。" #: ../../source/tutorial-quickstart-ios.rst:15 msgid "" -"Our example consists of one Python *server* and two iPhone *clients* that " -"all have the same model." -msgstr "我们的示例包括一个 Python *服务器*和两个 iPhone " -"*客户端*,它们都具有相同的模型。" +"Our example consists of one Python *server* and two iPhone *clients* that" +" all have the same model." +msgstr "我们的示例包括一个 Python *服务器*和两个 iPhone *客户端*,它们都具有相同的模型。" #: ../../source/tutorial-quickstart-ios.rst:17 msgid "" -"*Clients* are responsible for generating individual weight updates for the " -"model based on their local datasets. These updates are then sent to the " -"*server* which will aggregate them to produce a better model. Finally, the " -"*server* sends this improved version of the model back to each *client*. A " -"complete cycle of weight updates is called a *round*." -msgstr "" -"*客户端*负责根据其本地数据集为模型生成独立的模型参数。然后,这些参数更新会被" -"发送到*服务器*,由*服务器*汇总后生成一个更好的模型。最后,*服务器*将改进后的" -"模型发送回每个*客户端*。一个完整的参数更新周期称为一*轮*。" +"*Clients* are responsible for generating individual weight updates for " +"the model based on their local datasets. These updates are then sent to " +"the *server* which will aggregate them to produce a better model. " +"Finally, the *server* sends this improved version of the model back to " +"each *client*. A complete cycle of weight updates is called a *round*." +msgstr "*客户端*负责根据其本地数据集为模型生成独立的模型参数。然后,这些参数更新会被发送到*服务器*,由*服务器*汇总后生成一个更好的模型。最后,*服务器*将改进后的模型发送回每个*客户端*。一个完整的参数更新周期称为一*轮*。" #: ../../source/tutorial-quickstart-ios.rst:21 msgid "" "Now that we have a rough idea of what is going on, let's get started to " -"setup our Flower server environment. We first need to install Flower. You " -"can do this by using pip:" -msgstr "" -"现在我们已经有了一个大致的概念,让我们开始设置 Flower 服务器环境吧。首先,我" -"们需要安装 Flower。你可以使用 pip 来安装:" +"setup our Flower server environment. We first need to install Flower. You" +" can do this by using pip:" +msgstr "现在我们已经有了一个大致的概念,让我们开始设置 Flower 服务器环境吧。首先,我们需要安装 Flower。你可以使用 pip 来安装:" #: ../../source/tutorial-quickstart-ios.rst:27 msgid "Or Poetry:" @@ -12738,30 +16690,29 @@ msgstr "或者Poetry:" #: ../../source/tutorial-quickstart-ios.rst:36 msgid "" "Now that we have all our dependencies installed, let's run a simple " -"distributed training using CoreML as our local training pipeline and MNIST " -"as our dataset. For simplicity reasons we will use the complete Flower " -"client with CoreML, that has been implemented and stored inside the Swift " -"SDK. The client implementation can be seen below:" +"distributed training using CoreML as our local training pipeline and " +"MNIST as our dataset. For simplicity reasons we will use the complete " +"Flower client with CoreML, that has been implemented and stored inside " +"the Swift SDK. The client implementation can be seen below:" msgstr "" "现在我们已经安装了所有依赖项,让我们使用 CoreML 作为本地训练框架和 MNIST " -"作为数据集,运行一个简单的分布式训练。为了简单起见,我们将使用 CoreML 的完整 " -"Flower 客户端,该客户端已在 Swift SDK 中实现并存储。客户端实现如下:" +"作为数据集,运行一个简单的分布式训练。为了简单起见,我们将使用 CoreML 的完整 Flower 客户端,该客户端已在 Swift SDK " +"中实现并存储。客户端实现如下:" #: ../../source/tutorial-quickstart-ios.rst:72 msgid "" -"Let's create a new application project in Xcode and add :code:`flwr` as a " -"dependency in your project. For our application, we will store the logic of " -"our app in :code:`FLiOSModel.swift` and the UI elements in :code:" -"`ContentView.swift`. We will focus more on :code:`FLiOSModel.swift` in this " -"quickstart. Please refer to the `full code example `_ to learn more about the app." +"Let's create a new application project in Xcode and add :code:`flwr` as a" +" dependency in your project. For our application, we will store the logic" +" of our app in :code:`FLiOSModel.swift` and the UI elements in " +":code:`ContentView.swift`. We will focus more on :code:`FLiOSModel.swift`" +" in this quickstart. Please refer to the `full code example " +"`_ to learn more " +"about the app." msgstr "" -"让我们在 Xcode 中创建一个新的应用程序项目,并在项目中添加 :code:`flwr` " -"作为依赖关系。对于我们的应用程序,我们将在 :code:`FLiOSModel.swift` " -"中存储应用程序的逻辑,在 :code:`ContentView.swift` 中存储 UI " -"元素。在本快速入门中,我们将更多地关注 :code:`FLiOSModel.swift`。请参阅 `" -"完整代码示例 `_ " -"以了解更多有关应用程序的信息。" +"让我们在 Xcode 中创建一个新的应用程序项目,并在项目中添加 :code:`flwr` 作为依赖关系。对于我们的应用程序,我们将在 " +":code:`FLiOSModel.swift` 中存储应用程序的逻辑,在 :code:`ContentView.swift` 中存储 UI " +"元素。在本快速入门中,我们将更多地关注 :code:`FLiOSModel.swift`。请参阅 `完整代码示例 " +"`_ 以了解更多有关应用程序的信息。" #: ../../source/tutorial-quickstart-ios.rst:75 msgid "Import Flower and CoreML related packages in :code:`FLiOSModel.swift`:" @@ -12770,29 +16721,29 @@ msgstr "在 :code:`FLiOSModel.swift` 中导入 Flower 和 CoreML 相关软件包 #: ../../source/tutorial-quickstart-ios.rst:83 msgid "" "Then add the mlmodel to the project simply by drag-and-drop, the mlmodel " -"will be bundled inside the application during deployment to your iOS device. " -"We need to pass the url to access mlmodel and run CoreML machine learning " -"processes, it can be retrieved by calling the function :code:`Bundle.main." -"url`. For the MNIST dataset, we need to preprocess it into :code:" -"`MLBatchProvider` object. The preprocessing is done inside :code:`DataLoader." -"swift`." -msgstr "" -"然后通过拖放将 mlmodel 添加到项目中,在部署到 iOS 设备时,mlmodel 将被捆绑到" -"应用程序中。我们需要传递 url 以访问 mlmodel 并运行 CoreML 机器学习进程,可通" -"过调用函数 :code:`Bundle.main.url` 获取。对于 MNIST 数据集,我们需要将其预处" -"理为 :code:`MLBatchProvider` 对象。预处理在 :code:`DataLoader.swift` 中完成。" +"will be bundled inside the application during deployment to your iOS " +"device. We need to pass the url to access mlmodel and run CoreML machine " +"learning processes, it can be retrieved by calling the function " +":code:`Bundle.main.url`. For the MNIST dataset, we need to preprocess it " +"into :code:`MLBatchProvider` object. The preprocessing is done inside " +":code:`DataLoader.swift`." +msgstr "" +"然后通过拖放将 mlmodel 添加到项目中,在部署到 iOS 设备时,mlmodel 将被捆绑到应用程序中。我们需要传递 url 以访问 " +"mlmodel 并运行 CoreML 机器学习进程,可通过调用函数 :code:`Bundle.main.url` 获取。对于 MNIST " +"数据集,我们需要将其预处理为 :code:`MLBatchProvider` 对象。预处理在 :code:`DataLoader.swift` " +"中完成。" #: ../../source/tutorial-quickstart-ios.rst:99 msgid "" -"Since CoreML does not allow the model parameters to be seen before training, " -"and accessing the model parameters during or after the training can only be " -"done by specifying the layer name, we need to know this informations " -"beforehand, through looking at the model specification, which are written as " -"proto files. The implementation can be seen in :code:`MLModelInspect`." +"Since CoreML does not allow the model parameters to be seen before " +"training, and accessing the model parameters during or after the training" +" can only be done by specifying the layer name, we need to know this " +"informations beforehand, through looking at the model specification, " +"which are written as proto files. The implementation can be seen in " +":code:`MLModelInspect`." msgstr "" -"由于 CoreML 不允许在训练前查看模型参数,而在训练过程中或训练后访问模型参数只" -"能通过指定层名来完成,因此我们需要事先通过查看模型规范(写成 proto 文件)来了" -"解这些信息。具体实现可参见 :code:`MLModelInspect`。" +"由于 CoreML 不允许在训练前查看模型参数,而在训练过程中或训练后访问模型参数只能通过指定层名来完成,因此我们需要事先通过查看模型规范(写成 " +"proto 文件)来了解这些信息。具体实现可参见 :code:`MLModelInspect`。" #: ../../source/tutorial-quickstart-ios.rst:102 msgid "" @@ -12802,40 +16753,37 @@ msgstr "获得所有必要信息后,让我们创建 Flower 客户端。" #: ../../source/tutorial-quickstart-ios.rst:117 msgid "" -"Then start the Flower gRPC client and start communicating to the server by " -"passing our Flower client to the function :code:`startFlwrGRPC`." -msgstr "" -"然后启动 Flower gRPC 客户端,并通过将 Flower 客户端传递给函数 :code:" -"`startFlwrGRPC` 来开始与服务器通信。" +"Then start the Flower gRPC client and start communicating to the server " +"by passing our Flower client to the function :code:`startFlwrGRPC`." +msgstr "然后启动 Flower gRPC 客户端,并通过将 Flower 客户端传递给函数 :code:`startFlwrGRPC` 来开始与服务器通信。" #: ../../source/tutorial-quickstart-ios.rst:124 msgid "" -"That's it for the client. We only have to implement :code:`Client` or call " -"the provided :code:`MLFlwrClient` and call :code:`startFlwrGRPC()`. The " -"attribute :code:`hostname` and :code:`port` tells the client which server to " -"connect to. This can be done by entering the hostname and port in the " -"application before clicking the start button to start the federated learning " -"process." +"That's it for the client. We only have to implement :code:`Client` or " +"call the provided :code:`MLFlwrClient` and call :code:`startFlwrGRPC()`. " +"The attribute :code:`hostname` and :code:`port` tells the client which " +"server to connect to. This can be done by entering the hostname and port " +"in the application before clicking the start button to start the " +"federated learning process." msgstr "" -"这就是客户端。我们只需实现 :code:`Client` 或调用提供的 :code:`MLFlwrClient` " -"并调用 :code:`startFlwrGRPC()`。属性 :code:`hostname` 和 :code:`port` 会告诉" -"客户端要连接到哪个服务器。这可以通过在应用程序中输入主机名和端口来实现,然后" -"再点击开始按钮启动联邦学习进程。" +"这就是客户端。我们只需实现 :code:`Client` 或调用提供的 :code:`MLFlwrClient` 并调用 " +":code:`startFlwrGRPC()`。属性 :code:`hostname` 和 :code:`port` " +"会告诉客户端要连接到哪个服务器。这可以通过在应用程序中输入主机名和端口来实现,然后再点击开始按钮启动联邦学习进程。" #: ../../source/tutorial-quickstart-ios.rst:131 -#: ../../source/tutorial-quickstart-mxnet.rst:226 +#: ../../source/tutorial-quickstart-mxnet.rst:228 #: ../../source/tutorial-quickstart-pytorch.rst:205 #: ../../source/tutorial-quickstart-tensorflow.rst:100 msgid "" "For simple workloads we can start a Flower server and leave all the " -"configuration possibilities at their default values. In a file named :code:" -"`server.py`, import Flower and start the server:" +"configuration possibilities at their default values. In a file named " +":code:`server.py`, import Flower and start the server:" msgstr "" -"对于简单的工作负载,我们可以启动 Flower 服务器,并将所有配置选项保留为默认" -"值。在名为 :code:`server.py` 的文件中,导入 Flower 并启动服务器:" +"对于简单的工作负载,我们可以启动 Flower 服务器,并将所有配置选项保留为默认值。在名为 :code:`server.py` 的文件中,导入 " +"Flower 并启动服务器:" #: ../../source/tutorial-quickstart-ios.rst:142 -#: ../../source/tutorial-quickstart-mxnet.rst:237 +#: ../../source/tutorial-quickstart-mxnet.rst:239 #: ../../source/tutorial-quickstart-pytorch.rst:216 #: ../../source/tutorial-quickstart-scikitlearn.rst:215 #: ../../source/tutorial-quickstart-tensorflow.rst:112 @@ -12845,44 +16793,43 @@ msgstr "联邦训练模型!" #: ../../source/tutorial-quickstart-ios.rst:144 #: ../../source/tutorial-quickstart-pytorch.rst:218 #: ../../source/tutorial-quickstart-tensorflow.rst:114 -#: ../../source/tutorial-quickstart-xgboost.rst:522 +#: ../../source/tutorial-quickstart-xgboost.rst:525 msgid "" "With both client and server ready, we can now run everything and see " -"federated learning in action. FL systems usually have a server and multiple " -"clients. We therefore have to start the server first:" -msgstr "客户端和服务器都已准备就绪,我们现在可以运行一切,看看联邦学习的实际效果。FL " -"系统通常有一个服务器和多个客户端。因此,我们必须先启动服务器:" +"federated learning in action. FL systems usually have a server and " +"multiple clients. We therefore have to start the server first:" +msgstr "客户端和服务器都已准备就绪,我们现在可以运行一切,看看联邦学习的实际效果。FL 系统通常有一个服务器和多个客户端。因此,我们必须先启动服务器:" #: ../../source/tutorial-quickstart-ios.rst:152 msgid "" -"Once the server is running we can start the clients in different terminals. " -"Build and run the client through your Xcode, one through Xcode Simulator and " -"the other by deploying it to your iPhone. To see more about how to deploy " -"your app to iPhone or Simulator visit `here `_." +"Once the server is running we can start the clients in different " +"terminals. Build and run the client through your Xcode, one through Xcode" +" Simulator and the other by deploying it to your iPhone. To see more " +"about how to deploy your app to iPhone or Simulator visit `here " +"`_." msgstr "" -"服务器运行后,我们就可以在不同的终端启动客户端。通过 Xcode 构建并运行客户端," -"一个通过 Xcode 模拟器,另一个通过部署到 iPhone。要了解更多有关如何将应用程序" -"部署到 iPhone 或模拟器的信息,请访问 `此处 `_。" +"服务器运行后,我们就可以在不同的终端启动客户端。通过 Xcode 构建并运行客户端,一个通过 Xcode 模拟器,另一个通过部署到 " +"iPhone。要了解更多有关如何将应用程序部署到 iPhone 或模拟器的信息,请访问 `此处 " +"`_。" #: ../../source/tutorial-quickstart-ios.rst:156 msgid "" "Congratulations! You've successfully built and run your first federated " -"learning system in your ios device. The full `source code `_ for this example can be found in :" -"code:`examples/ios`." +"learning system in your ios device. The full `source code " +"`_ for this " +"example can be found in :code:`examples/ios`." msgstr "" -"恭喜您! 您已经成功地在 ios 设备中构建并运行了第一个联邦学习系统。本示例的`" -"完整源代码 `_ 可在 " +"恭喜您! 您已经成功地在 ios 设备中构建并运行了第一个联邦学习系统。本示例的`完整源代码 " +"`_ 可在 " ":code:`examples/ios` 中找到。" #: ../../source/tutorial-quickstart-jax.rst:-1 msgid "" -"Check out this Federated Learning quickstart tutorial for using Flower with " -"Jax to train a linear regression model on a scikit-learn dataset." -msgstr "查看此联邦学习快速入门教程,了解如何使用 Flower 和 Jax 在 scikit-learn " -"数据集上训练线性回归模型。" +"Check out this Federated Learning quickstart tutorial for using Flower " +"with Jax to train a linear regression model on a scikit-learn dataset." +msgstr "查看此联邦学习快速入门教程,了解如何使用 Flower 和 Jax 在 scikit-learn 数据集上训练线性回归模型。" #: ../../source/tutorial-quickstart-jax.rst:5 msgid "Quickstart JAX" @@ -12890,279 +16837,271 @@ msgstr "快速入门 JAX" #: ../../source/tutorial-quickstart-mxnet.rst:-1 msgid "" -"Check out this Federated Learning quickstart tutorial for using Flower with " -"MXNet to train a Sequential model on MNIST." -msgstr "查看此联邦学习 快速入门教程,了解如何使用 Flower 和 MXNet 在 MNIST " -"上训练序列模型。" +"Check out this Federated Learning quickstart tutorial for using Flower " +"with MXNet to train a Sequential model on MNIST." +msgstr "查看此联邦学习 快速入门教程,了解如何使用 Flower 和 MXNet 在 MNIST 上训练序列模型。" #: ../../source/tutorial-quickstart-mxnet.rst:5 msgid "Quickstart MXNet" msgstr "快速入门 MXNet" -#: ../../source/tutorial-quickstart-mxnet.rst:10 +#: ../../source/tutorial-quickstart-mxnet.rst:7 msgid "" -"In this tutorial, we will learn how to train a :code:`Sequential` model on " -"MNIST using Flower and MXNet." +"MXNet is no longer maintained and has been moved into `Attic " +"`_. As a result, we would " +"encourage you to use other ML frameworks alongise Flower, for example, " +"PyTorch. This tutorial might be removed in future versions of Flower." msgstr "" -"在本教程中,我们将学习如何使用 Flower 和 MXNet 在 MNIST 上训练 :code:" -"`Sequential` 模型。" #: ../../source/tutorial-quickstart-mxnet.rst:12 +msgid "" +"In this tutorial, we will learn how to train a :code:`Sequential` model " +"on MNIST using Flower and MXNet." +msgstr "在本教程中,我们将学习如何使用 Flower 和 MXNet 在 MNIST 上训练 :code:`Sequential` 模型。" + +#: ../../source/tutorial-quickstart-mxnet.rst:14 #: ../../source/tutorial-quickstart-scikitlearn.rst:12 msgid "" -"It is recommended to create a virtual environment and run everything within " -"this `virtualenv `_." +"It is recommended to create a virtual environment and run everything " +"within this `virtualenv `_." msgstr "" -"建议创建一个虚拟环境,并在此 `virtualenv `_ 中运行所有内容。" +"建议创建一个虚拟环境,并在此 `virtualenv `_ 中运行所有内容。" -#: ../../source/tutorial-quickstart-mxnet.rst:16 +#: ../../source/tutorial-quickstart-mxnet.rst:18 #: ../../source/tutorial-quickstart-scikitlearn.rst:16 msgid "" -"*Clients* are responsible for generating individual model parameter updates " -"for the model based on their local datasets. These updates are then sent to " -"the *server* which will aggregate them to produce an updated global model. " -"Finally, the *server* sends this improved version of the model back to each " -"*client*. A complete cycle of parameters updates is called a *round*." -msgstr "" -"*客户端*负责根据其本地数据集为模型生成单独的模型参数更新。然后,这些参数更新" -"将被发送到*服务器*,由*服务器*汇总后生成一个更新的全局模型。最后,*服务器*将" -"这一改进版模型发回给每个*客户端*。一个完整的参数更新周期称为一*轮*。" +"*Clients* are responsible for generating individual model parameter " +"updates for the model based on their local datasets. These updates are " +"then sent to the *server* which will aggregate them to produce an updated" +" global model. Finally, the *server* sends this improved version of the " +"model back to each *client*. A complete cycle of parameters updates is " +"called a *round*." +msgstr "*客户端*负责根据其本地数据集为模型生成单独的模型参数更新。然后,这些参数更新将被发送到*服务器*,由*服务器*汇总后生成一个更新的全局模型。最后,*服务器*将这一改进版模型发回给每个*客户端*。一个完整的参数更新周期称为一*轮*。" -#: ../../source/tutorial-quickstart-mxnet.rst:20 +#: ../../source/tutorial-quickstart-mxnet.rst:22 #: ../../source/tutorial-quickstart-scikitlearn.rst:20 msgid "" "Now that we have a rough idea of what is going on, let's get started. We " "first need to install Flower. You can do this by running:" -msgstr "" -"现在,我们已经有了一个大致的概念,让我们开始吧。首先,我们需要安装 Flower。运" -"行:" +msgstr "现在,我们已经有了一个大致的概念,让我们开始吧。首先,我们需要安装 Flower。运行:" -#: ../../source/tutorial-quickstart-mxnet.rst:26 +#: ../../source/tutorial-quickstart-mxnet.rst:28 msgid "Since we want to use MXNet, let's go ahead and install it:" msgstr "既然我们要使用 MXNet,那就继续安装吧:" -#: ../../source/tutorial-quickstart-mxnet.rst:36 +#: ../../source/tutorial-quickstart-mxnet.rst:38 msgid "" "Now that we have all our dependencies installed, let's run a simple " -"distributed training with two clients and one server. Our training procedure " -"and network architecture are based on MXNet´s `Hand-written Digit " -"Recognition tutorial `_." +"distributed training with two clients and one server. Our training " +"procedure and network architecture are based on MXNet´s `Hand-written " +"Digit Recognition tutorial " +"`_." msgstr "" -"现在,我们已经安装了所有依赖项,让我们用两个客户端和一个服务器来运行一个简单" -"的分布式训练。我们的训练程序和网络架构基于 MXNet 的 `手写数字识别教程 " -"`_\"。" +"现在,我们已经安装了所有依赖项,让我们用两个客户端和一个服务器来运行一个简单的分布式训练。我们的训练程序和网络架构基于 MXNet 的 " +"`手写数字识别教程 " +"`_\"。" -#: ../../source/tutorial-quickstart-mxnet.rst:38 +#: ../../source/tutorial-quickstart-mxnet.rst:40 msgid "" -"In a file called :code:`client.py`, import Flower and MXNet related packages:" +"In a file called :code:`client.py`, import Flower and MXNet related " +"packages:" msgstr "在名为 :code:`client.py` 的文件中,导入 Flower 和 MXNet 相关软件包:" -#: ../../source/tutorial-quickstart-mxnet.rst:53 +#: ../../source/tutorial-quickstart-mxnet.rst:55 msgid "In addition, define the device allocation in MXNet with:" msgstr "此外,还可以在 MXNet 中定义设备分配:" -#: ../../source/tutorial-quickstart-mxnet.rst:59 +#: ../../source/tutorial-quickstart-mxnet.rst:61 msgid "" "We use MXNet to load MNIST, a popular image classification dataset of " -"handwritten digits for machine learning. The MXNet utility :code:`mx." -"test_utils.get_mnist()` downloads the training and test data." +"handwritten digits for machine learning. The MXNet utility " +":code:`mx.test_utils.get_mnist()` downloads the training and test data." msgstr "" -"我们使用 MXNet 加载 MNIST,这是一个用于机器学习的流行手写数字图像分类数据集。" -"MXNet 工具 :code:`mx.test_utils.get_mnist()` 会下载训练和测试数据。" +"我们使用 MXNet 加载 MNIST,这是一个用于机器学习的流行手写数字图像分类数据集。MXNet 工具 " +":code:`mx.test_utils.get_mnist()` 会下载训练和测试数据。" -#: ../../source/tutorial-quickstart-mxnet.rst:73 +#: ../../source/tutorial-quickstart-mxnet.rst:75 msgid "" -"Define the training and loss with MXNet. We train the model by looping over " -"the dataset, measure the corresponding loss, and optimize it." -msgstr "用 MXNet 定义训练和损失值。我们在数据集上循环训练模型,测量相应的损失值,并对" -"其进行优化。" +"Define the training and loss with MXNet. We train the model by looping " +"over the dataset, measure the corresponding loss, and optimize it." +msgstr "用 MXNet 定义训练和损失值。我们在数据集上循环训练模型,测量相应的损失值,并对其进行优化。" -#: ../../source/tutorial-quickstart-mxnet.rst:111 +#: ../../source/tutorial-quickstart-mxnet.rst:113 msgid "" -"Next, we define the validation of our machine learning model. We loop over " -"the test set and measure both loss and accuracy on the test set." -msgstr "接下来,我们定义机器学习模型的验证。我们在测试集上循环,测量测试集上的损失值" -"和准确率。" +"Next, we define the validation of our machine learning model. We loop " +"over the test set and measure both loss and accuracy on the test set." +msgstr "接下来,我们定义机器学习模型的验证。我们在测试集上循环,测量测试集上的损失值和准确率。" -#: ../../source/tutorial-quickstart-mxnet.rst:135 +#: ../../source/tutorial-quickstart-mxnet.rst:137 msgid "" -"After defining the training and testing of a MXNet machine learning model, " -"we use these functions to implement a Flower client." -msgstr "" -"在定义了 MXNet 机器学习模型的训练和测试后,我们使用这些函数实现了 Flower 客户" -"端。" +"After defining the training and testing of a MXNet machine learning " +"model, we use these functions to implement a Flower client." +msgstr "在定义了 MXNet 机器学习模型的训练和测试后,我们使用这些函数实现了 Flower 客户端。" -#: ../../source/tutorial-quickstart-mxnet.rst:137 +#: ../../source/tutorial-quickstart-mxnet.rst:139 msgid "Our Flower clients will use a simple :code:`Sequential` model:" msgstr "我们的 Flower 客户端将使用简单的 :code:`Sequential` 模型:" -#: ../../source/tutorial-quickstart-mxnet.rst:156 +#: ../../source/tutorial-quickstart-mxnet.rst:158 msgid "" -"After loading the dataset with :code:`load_data()` we perform one forward " -"propagation to initialize the model and model parameters with :code:" -"`model(init)`. Next, we implement a Flower client." +"After loading the dataset with :code:`load_data()` we perform one forward" +" propagation to initialize the model and model parameters with " +":code:`model(init)`. Next, we implement a Flower client." msgstr "" -"使用 :code:`load_data()` 加载数据集后,我们会执行一次前向传播,使用 :code:" -"`model(init)` 初始化模型和模型参数。接下来,我们实现一个 Flower 客户端。" +"使用 :code:`load_data()` 加载数据集后,我们会执行一次前向传播,使用 :code:`model(init)` " +"初始化模型和模型参数。接下来,我们实现一个 Flower 客户端。" -#: ../../source/tutorial-quickstart-mxnet.rst:158 +#: ../../source/tutorial-quickstart-mxnet.rst:160 #: ../../source/tutorial-quickstart-pytorch.rst:144 #: ../../source/tutorial-quickstart-tensorflow.rst:54 msgid "" -"The Flower server interacts with clients through an interface called :code:" -"`Client`. When the server selects a particular client for training, it sends " -"training instructions over the network. The client receives those " -"instructions and calls one of the :code:`Client` methods to run your code (i." -"e., to train the neural network we defined earlier)." +"The Flower server interacts with clients through an interface called " +":code:`Client`. When the server selects a particular client for training," +" it sends training instructions over the network. The client receives " +"those instructions and calls one of the :code:`Client` methods to run " +"your code (i.e., to train the neural network we defined earlier)." msgstr "" -"Flower 服务器通过一个名为 :code:`Client` 的接口与客户端交互。当服务器选择一个" -"特定的客户端进行训练时,它会通过网络发送训练指令。客户端接收到这些指令后," -"会调用 :code:`Client` " -"方法之一来运行您的代码(即训练我们之前定义的神经网络)。" +"Flower 服务器通过一个名为 :code:`Client` " +"的接口与客户端交互。当服务器选择一个特定的客户端进行训练时,它会通过网络发送训练指令。客户端接收到这些指令后,会调用 :code:`Client`" +" 方法之一来运行您的代码(即训练我们之前定义的神经网络)。" -#: ../../source/tutorial-quickstart-mxnet.rst:164 +#: ../../source/tutorial-quickstart-mxnet.rst:166 msgid "" -"Flower provides a convenience class called :code:`NumPyClient` which makes " -"it easier to implement the :code:`Client` interface when your workload uses " -"MXNet. Implementing :code:`NumPyClient` usually means defining the following " -"methods (:code:`set_parameters` is optional though):" +"Flower provides a convenience class called :code:`NumPyClient` which " +"makes it easier to implement the :code:`Client` interface when your " +"workload uses MXNet. Implementing :code:`NumPyClient` usually means " +"defining the following methods (:code:`set_parameters` is optional " +"though):" msgstr "" -"Flower 提供了一个名为 :code:`NumPyClient` 的便捷类,当您的工作负载使用 MXNet " -"时,它可以让您更轻松地实现 :code:`Client` 接口。实现 :code:`NumPyClient` " +"Flower 提供了一个名为 :code:`NumPyClient` 的便捷类,当您的工作负载使用 MXNet 时,它可以让您更轻松地实现 " +":code:`Client` 接口。实现 :code:`NumPyClient` " "通常意味着定义以下方法(:code:`set_parameters` 是可选的):" -#: ../../source/tutorial-quickstart-mxnet.rst:170 +#: ../../source/tutorial-quickstart-mxnet.rst:172 #: ../../source/tutorial-quickstart-pytorch.rst:156 #: ../../source/tutorial-quickstart-scikitlearn.rst:109 msgid "return the model weight as a list of NumPy ndarrays" msgstr "以 NumPy ndarrays 列表形式返回模型参数" -#: ../../source/tutorial-quickstart-mxnet.rst:171 +#: ../../source/tutorial-quickstart-mxnet.rst:173 #: ../../source/tutorial-quickstart-pytorch.rst:157 #: ../../source/tutorial-quickstart-scikitlearn.rst:111 msgid ":code:`set_parameters` (optional)" msgstr ":code:`set_parameters` (可选)" -#: ../../source/tutorial-quickstart-mxnet.rst:172 +#: ../../source/tutorial-quickstart-mxnet.rst:174 #: ../../source/tutorial-quickstart-pytorch.rst:158 #: ../../source/tutorial-quickstart-scikitlearn.rst:111 msgid "" -"update the local model weights with the parameters received from the server" +"update the local model weights with the parameters received from the " +"server" msgstr "用从服务器接收到的参数更新本地模型参数" -#: ../../source/tutorial-quickstart-mxnet.rst:174 +#: ../../source/tutorial-quickstart-mxnet.rst:176 #: ../../source/tutorial-quickstart-pytorch.rst:160 #: ../../source/tutorial-quickstart-scikitlearn.rst:114 msgid "set the local model weights" msgstr "设置本地模型参数" -#: ../../source/tutorial-quickstart-mxnet.rst:175 +#: ../../source/tutorial-quickstart-mxnet.rst:177 #: ../../source/tutorial-quickstart-pytorch.rst:161 #: ../../source/tutorial-quickstart-scikitlearn.rst:115 msgid "train the local model" msgstr "训练本地模型" -#: ../../source/tutorial-quickstart-mxnet.rst:176 +#: ../../source/tutorial-quickstart-mxnet.rst:178 #: ../../source/tutorial-quickstart-pytorch.rst:162 #: ../../source/tutorial-quickstart-scikitlearn.rst:116 msgid "receive the updated local model weights" msgstr "接收更新的本地模型参数" -#: ../../source/tutorial-quickstart-mxnet.rst:178 +#: ../../source/tutorial-quickstart-mxnet.rst:180 #: ../../source/tutorial-quickstart-pytorch.rst:164 #: ../../source/tutorial-quickstart-scikitlearn.rst:118 msgid "test the local model" msgstr "测试本地模型" -#: ../../source/tutorial-quickstart-mxnet.rst:180 +#: ../../source/tutorial-quickstart-mxnet.rst:182 msgid "They can be implemented in the following way:" msgstr "它们可以通过以下方式实现:" -#: ../../source/tutorial-quickstart-mxnet.rst:210 +#: ../../source/tutorial-quickstart-mxnet.rst:212 msgid "" -"We can now create an instance of our class :code:`MNISTClient` and add one " -"line to actually run this client:" -msgstr "" -"现在我们可以创建一个 :code:`MNISTClient` 类的实例,并添加一行来实际运行该客户" -"端:" +"We can now create an instance of our class :code:`MNISTClient` and add " +"one line to actually run this client:" +msgstr "现在我们可以创建一个 :code:`MNISTClient` 类的实例,并添加一行来实际运行该客户端:" -#: ../../source/tutorial-quickstart-mxnet.rst:217 -#: ../../source/tutorial-quickstart-scikitlearn.rst:150 +#: ../../source/tutorial-quickstart-mxnet.rst:219 msgid "" -"That's it for the client. We only have to implement :code:`Client` or :code:" -"`NumPyClient` and call :code:`fl.client.start_client()`. The string :code:" -"`\"0.0.0.0:8080\"` tells the client which server to connect to. In our case " -"we can run the server and the client on the same machine, therefore we use :" -"code:`\"0.0.0.0:8080\"`. If we run a truly federated workload with the " -"server and clients running on different machines, all that needs to change " -"is the :code:`server_address` we pass to the client." -msgstr "" -"对于客户端就需要做这么多。我们仅需要实现 " -":code:`Client`或者:code:`NumPyClient`然后调用:code:`fl.client." -"start_client()`。字符串 :code:`\"0.0.0.0:8080\"` 告诉客户端要连接到哪个服务器" -"。在我们的例子中,我们可以在同一台机器上运行服务器和客户端,因此我们使用:code" -":`\"0.0.0.0:8080\"" -"`。如果我们运行真正联邦学习的工作负载,服务器和客户端在不同的机器上运行," -"则需要更改的只是我们传递给客户端的 server_address 。" +"That's it for the client. We only have to implement :code:`Client` or " +":code:`NumPyClient` and call :code:`fl.client.start_client()` or " +":code:`fl.client.start_numpy_client()`. The string " +":code:`\"0.0.0.0:8080\"` tells the client which server to connect to. In " +"our case we can run the server and the client on the same machine, " +"therefore we use :code:`\"0.0.0.0:8080\"`. If we run a truly federated " +"workload with the server and clients running on different machines, all " +"that needs to change is the :code:`server_address` we pass to the client." +msgstr "" +"这就是客户端。我们只需实现 :code:`Client` 或 :code:`NumPyClient` 并调用 " +":code:`fl.client.start_client()` 或 " +":code:`fl.client.start_numpy_client()`。字符串 " +":code:`\"0.0.0.0:8080\"`会告诉客户端要连接的服务器。在本例中,我们可以在同一台机器上运行服务器和客户端,因此我们使用 " +":code:`\"0.0.0.0:8080\"`。如果我们运行的是真正的联邦工作负载,服务器和客户端运行在不同的机器上,那么需要改变的只是传递给客户端的" +" :code:`server_address`。" -#: ../../source/tutorial-quickstart-mxnet.rst:239 +#: ../../source/tutorial-quickstart-mxnet.rst:241 msgid "" "With both client and server ready, we can now run everything and see " "federated learning in action. Federated learning systems usually have a " "server and multiple clients. We therefore have to start the server first:" -msgstr "" -"客户端和服务器都准备就绪后,我们现在就可以运行一切,看看联邦学习的运行情况。" -"联邦学习系统通常有一个服务器和多个客户端。因此,我们必须先启动服务器:" +msgstr "客户端和服务器都准备就绪后,我们现在就可以运行一切,看看联邦学习的运行情况。联邦学习系统通常有一个服务器和多个客户端。因此,我们必须先启动服务器:" -#: ../../source/tutorial-quickstart-mxnet.rst:247 +#: ../../source/tutorial-quickstart-mxnet.rst:249 #: ../../source/tutorial-quickstart-pytorch.rst:226 #: ../../source/tutorial-quickstart-scikitlearn.rst:224 #: ../../source/tutorial-quickstart-tensorflow.rst:122 -#: ../../source/tutorial-quickstart-xgboost.rst:530 +#: ../../source/tutorial-quickstart-xgboost.rst:533 msgid "" -"Once the server is running we can start the clients in different terminals. " -"Open a new terminal and start the first client:" -msgstr "" -"服务器运行后,我们就可以在不同终端启动客户端了。打开一个新终端,启动第一个客" -"户端:" +"Once the server is running we can start the clients in different " +"terminals. Open a new terminal and start the first client:" +msgstr "服务器运行后,我们就可以在不同终端启动客户端了。打开一个新终端,启动第一个客户端:" -#: ../../source/tutorial-quickstart-mxnet.rst:254 +#: ../../source/tutorial-quickstart-mxnet.rst:256 #: ../../source/tutorial-quickstart-pytorch.rst:233 #: ../../source/tutorial-quickstart-scikitlearn.rst:231 #: ../../source/tutorial-quickstart-tensorflow.rst:129 -#: ../../source/tutorial-quickstart-xgboost.rst:537 +#: ../../source/tutorial-quickstart-xgboost.rst:540 msgid "Open another terminal and start the second client:" msgstr "打开另一台终端,启动第二个客户端:" -#: ../../source/tutorial-quickstart-mxnet.rst:260 +#: ../../source/tutorial-quickstart-mxnet.rst:262 #: ../../source/tutorial-quickstart-pytorch.rst:239 #: ../../source/tutorial-quickstart-scikitlearn.rst:237 -#: ../../source/tutorial-quickstart-xgboost.rst:543 +#: ../../source/tutorial-quickstart-xgboost.rst:546 msgid "" -"Each client will have its own dataset. You should now see how the training " -"does in the very first terminal (the one that started the server):" -msgstr "" -"每个客户端都有自己的数据集。现在你应该看到第一个终端(启动服务器的终端)的训" -"练效果了:" +"Each client will have its own dataset. You should now see how the " +"training does in the very first terminal (the one that started the " +"server):" +msgstr "每个客户端都有自己的数据集。现在你应该看到第一个终端(启动服务器的终端)的训练效果了:" -#: ../../source/tutorial-quickstart-mxnet.rst:292 +#: ../../source/tutorial-quickstart-mxnet.rst:294 msgid "" "Congratulations! You've successfully built and run your first federated " -"learning system. The full `source code `_ for this example can be found " -"in :code:`examples/quickstart-mxnet`." +"learning system. The full `source code " +"`_ for this example can be found in :code:`examples" +"/quickstart-mxnet`." msgstr "" "恭喜您!您已经成功构建并运行了第一个联邦学习系统。本示例的`完整源代码 " -"`_ 可在 :code:`examples/quickstart-mxnet` 中找到。" +"`_ 可在 :code:`examples/quickstart-mxnet` 中找到。" #: ../../source/tutorial-quickstart-pandas.rst:-1 msgid "" -"Check out this Federated Learning quickstart tutorial for using Flower with " -"Pandas to perform Federated Analytics." +"Check out this Federated Learning quickstart tutorial for using Flower " +"with Pandas to perform Federated Analytics." msgstr "查看此联邦学习快速入门教程,了解如何使用 Flower 和 Pandas 执行联邦分析。" #: ../../source/tutorial-quickstart-pandas.rst:5 @@ -13175,56 +17114,52 @@ msgstr "让我们使用 Pandas 和 Flower 建立一个联邦分析系统!" #: ../../source/tutorial-quickstart-pandas.rst:12 msgid "" -"Please refer to the `full code example `_ to learn more." +"Please refer to the `full code example " +"`_ " +"to learn more." msgstr "" -"请参阅 `完整代码示例 `_\" 了解更多信息。" +"请参阅 `完整代码示例 `_\" 了解更多信息。" #: ../../source/tutorial-quickstart-pytorch.rst:-1 msgid "" -"Check out this Federated Learning quickstart tutorial for using Flower with " -"PyTorch to train a CNN model on MNIST." -msgstr "查看此联邦学习快速入门教程,了解如何使用 Flower 和 PyTorch 在 MNIST 上训练 " -"CNN 模型。" +"Check out this Federated Learning quickstart tutorial for using Flower " +"with PyTorch to train a CNN model on MNIST." +msgstr "查看此联邦学习快速入门教程,了解如何使用 Flower 和 PyTorch 在 MNIST 上训练 CNN 模型。" #: ../../source/tutorial-quickstart-pytorch.rst:13 msgid "" -"In this tutorial we will learn how to train a Convolutional Neural Network " -"on CIFAR10 using Flower and PyTorch." -msgstr "" -"在本教程中,我们将学习如何使用 Flower 和 PyTorch 在 CIFAR10 上训练卷积神经网" -"络。" +"In this tutorial we will learn how to train a Convolutional Neural " +"Network on CIFAR10 using Flower and PyTorch." +msgstr "在本教程中,我们将学习如何使用 Flower 和 PyTorch 在 CIFAR10 上训练卷积神经网络。" #: ../../source/tutorial-quickstart-pytorch.rst:15 -#: ../../source/tutorial-quickstart-xgboost.rst:36 +#: ../../source/tutorial-quickstart-xgboost.rst:39 msgid "" "First of all, it is recommended to create a virtual environment and run " "everything within a `virtualenv `_." msgstr "" -"首先,建议创建一个虚拟环境,并在 `virtualenv `_ 中运行一切。" +"首先,建议创建一个虚拟环境,并在 `virtualenv `_ 中运行一切。" #: ../../source/tutorial-quickstart-pytorch.rst:29 msgid "" -"Since we want to use PyTorch to solve a computer vision task, let's go ahead " -"and install PyTorch and the **torchvision** library:" -msgstr "" -"既然我们想用 PyTorch 解决计算机视觉任务,那就继续安装 PyTorch 和 " -"**torchvision** 库吧:" +"Since we want to use PyTorch to solve a computer vision task, let's go " +"ahead and install PyTorch and the **torchvision** library:" +msgstr "既然我们想用 PyTorch 解决计算机视觉任务,那就继续安装 PyTorch 和 **torchvision** 库吧:" #: ../../source/tutorial-quickstart-pytorch.rst:39 msgid "" "Now that we have all our dependencies installed, let's run a simple " -"distributed training with two clients and one server. Our training procedure " -"and network architecture are based on PyTorch's `Deep Learning with PyTorch " +"distributed training with two clients and one server. Our training " +"procedure and network architecture are based on PyTorch's `Deep Learning " +"with PyTorch " "`_." msgstr "" -"现在我们已经安装了所有的依赖项,让我们用两个客户端和一个服务器来运行一个简单" -"的分布式训练。我们的训练过程和网络架构基于 PyTorch 的《Deep Learning with " -"PyTorch `_》。" +"现在我们已经安装了所有的依赖项,让我们用两个客户端和一个服务器来运行一个简单的分布式训练。我们的训练过程和网络架构基于 PyTorch " +"的《Deep Learning with PyTorch " +"`_》。" #: ../../source/tutorial-quickstart-pytorch.rst:41 msgid "" @@ -13239,38 +17174,35 @@ msgstr "此外,我们还在 PyTorch 中定义了设备分配:" #: ../../source/tutorial-quickstart-pytorch.rst:62 msgid "" "We use PyTorch to load CIFAR10, a popular colored image classification " -"dataset for machine learning. The PyTorch :code:`DataLoader()` downloads the " -"training and test data that are then normalized." +"dataset for machine learning. The PyTorch :code:`DataLoader()` downloads " +"the training and test data that are then normalized." msgstr "" -"我们使用 PyTorch 来加载 CIFAR10,这是一个用于机器学习的流行彩色图像分类数据" -"集。PyTorch :code:`DataLoader()`下载训练数据和测试数据,然后进行归一化处理。" +"我们使用 PyTorch 来加载 CIFAR10,这是一个用于机器学习的流行彩色图像分类数据集。PyTorch " +":code:`DataLoader()`下载训练数据和测试数据,然后进行归一化处理。" #: ../../source/tutorial-quickstart-pytorch.rst:78 msgid "" -"Define the loss and optimizer with PyTorch. The training of the dataset is " -"done by looping over the dataset, measure the corresponding loss and " +"Define the loss and optimizer with PyTorch. The training of the dataset " +"is done by looping over the dataset, measure the corresponding loss and " "optimize it." -msgstr "使用 PyTorch 定义损失和优化器。数据集的训练是通过循环数据集、测量相应的损失值" -"并对其进行优化来完成的。" +msgstr "使用 PyTorch 定义损失和优化器。数据集的训练是通过循环数据集、测量相应的损失值并对其进行优化来完成的。" #: ../../source/tutorial-quickstart-pytorch.rst:94 msgid "" -"Define then the validation of the machine learning network. We loop over " -"the test set and measure the loss and accuracy of the test set." +"Define then the validation of the machine learning network. We loop over" +" the test set and measure the loss and accuracy of the test set." msgstr "然后定义机器学习网络的验证。我们在测试集上循环,计算测试集的损失值和准确率。" #: ../../source/tutorial-quickstart-pytorch.rst:113 msgid "" -"After defining the training and testing of a PyTorch machine learning model, " -"we use the functions for the Flower clients." -msgstr "" -"在定义了 PyTorch 机器学习模型的训练和测试之后,我们将这些功能用于 Flower 客户" -"端。" +"After defining the training and testing of a PyTorch machine learning " +"model, we use the functions for the Flower clients." +msgstr "在定义了 PyTorch 机器学习模型的训练和测试之后,我们将这些功能用于 Flower 客户端。" #: ../../source/tutorial-quickstart-pytorch.rst:115 msgid "" -"The Flower clients will use a simple CNN adapted from 'PyTorch: A 60 Minute " -"Blitz':" +"The Flower clients will use a simple CNN adapted from 'PyTorch: A 60 " +"Minute Blitz':" msgstr "Flower 客户端将使用一个简单的从“PyTorch: 60 分钟突击\"改编的CNN:" #: ../../source/tutorial-quickstart-pytorch.rst:142 @@ -13281,15 +17213,15 @@ msgstr "使用 :code:`load_data()` 加载数据集后,我们定义了 Flower #: ../../source/tutorial-quickstart-pytorch.rst:150 msgid "" -"Flower provides a convenience class called :code:`NumPyClient` which makes " -"it easier to implement the :code:`Client` interface when your workload uses " -"PyTorch. Implementing :code:`NumPyClient` usually means defining the " -"following methods (:code:`set_parameters` is optional though):" +"Flower provides a convenience class called :code:`NumPyClient` which " +"makes it easier to implement the :code:`Client` interface when your " +"workload uses PyTorch. Implementing :code:`NumPyClient` usually means " +"defining the following methods (:code:`set_parameters` is optional " +"though):" msgstr "" -"Flower 提供了一个名为 :code:`NumPyClient` 的便捷类,当您的工作负载使用 " -"PyTorch 时,它使 :code:`Client` 接口的实现变得更容易。实现 " -":code:`NumPyClient` 通常意味着定义以下方法(:code:`set_parameters` " -"是可选的):" +"Flower 提供了一个名为 :code:`NumPyClient` 的便捷类,当您的工作负载使用 PyTorch 时,它使 " +":code:`Client` 接口的实现变得更容易。实现 :code:`NumPyClient` " +"通常意味着定义以下方法(:code:`set_parameters` 是可选的):" #: ../../source/tutorial-quickstart-pytorch.rst:166 msgid "which can be implemented in the following way:" @@ -13298,47 +17230,48 @@ msgstr "可以通过以下方式实现:" #: ../../source/tutorial-quickstart-pytorch.rst:189 #: ../../source/tutorial-quickstart-tensorflow.rst:82 msgid "" -"We can now create an instance of our class :code:`CifarClient` and add one " -"line to actually run this client:" -msgstr "" -"现在我们可以创建一个 :code:`CifarClient` 类的实例,并添加一行来实际运行该客户" -"端:" +"We can now create an instance of our class :code:`CifarClient` and add " +"one line to actually run this client:" +msgstr "现在我们可以创建一个 :code:`CifarClient` 类的实例,并添加一行来实际运行该客户端:" #: ../../source/tutorial-quickstart-pytorch.rst:196 #: ../../source/tutorial-quickstart-tensorflow.rst:90 -msgid "" -"That's it for the client. We only have to implement :code:`Client` or :code:" -"`NumPyClient` and call :code:`fl.client.start_client()`. The string :code:" -"`\"[::]:8080\"` tells the client which server to connect to. In our case we " -"can run the server and the client on the same machine, therefore we use :" -"code:`\"[::]:8080\"`. If we run a truly federated workload with the server " -"and clients running on different machines, all that needs to change is the :" -"code:`server_address` we point the client at." -msgstr "" -"对于客户来说就是这样了。我们只需实现 :code:`Client` 或 :code:`NumPyClient` " -"并调用:code:`fl.client.start_client()` 即可。字符串 :code:`\"[::]:8080\"` 告" -"诉客户端要连接到哪个服务器。在我们的例子中,我们可以在同一台机器上运行服务器" -"和客户端,因此我们使用 :code:`\"[::]:8080\"" -"`。如果我们运行真正联邦的工作负载,服务器和客户端运行在不同的机器上," -"则需要更改的只是我们指向客户端的 server_address 。" +#, fuzzy +msgid "" +"That's it for the client. We only have to implement :code:`Client` or " +":code:`NumPyClient` and call :code:`fl.client.start_client()`. If you " +"implement a client of type :code:`NumPyClient` you'll need to first call " +"its :code:`to_client()` method. The string :code:`\"[::]:8080\"` tells " +"the client which server to connect to. In our case we can run the server " +"and the client on the same machine, therefore we use " +":code:`\"[::]:8080\"`. If we run a truly federated workload with the " +"server and clients running on different machines, all that needs to " +"change is the :code:`server_address` we point the client at." +msgstr "" +"这就是客户端。我们只需实现 :code:`Client` 或 :code:`NumPyClient` 并调用 " +":code:`fl.client.start_client()` 或 " +":code:`fl.client.start_numpy_client()`。字符串 " +":code:`\"[::]:8080\"`会告诉客户端要连接的服务器。在本例中,我们可以在同一台机器上运行服务器和客户端,因此使用 " +":code:`\"[::]:8080\"。如果我们运行的是真正的联邦工作负载,服务器和客户端运行在不同的机器上,那么需要改变的只是客户端指向的 " +":code:`server_address`。" #: ../../source/tutorial-quickstart-pytorch.rst:271 msgid "" "Congratulations! You've successfully built and run your first federated " -"learning system. The full `source code `_ for this example can be found " -"in :code:`examples/quickstart-pytorch`." +"learning system. The full `source code " +"`_ for this example can be found in :code:`examples" +"/quickstart-pytorch`." msgstr "" "恭喜您!您已经成功构建并运行了第一个联邦学习系统。本示例的`完整源代码 " -"`_ 可以在 :code:`examples/quickstart-pytorch` 中找到。" +"`_ 可以在 :code:`examples/quickstart-pytorch` 中找到。" #: ../../source/tutorial-quickstart-pytorch-lightning.rst:-1 msgid "" -"Check out this Federated Learning quickstart tutorial for using Flower with " -"PyTorch Lightning to train an Auto Encoder model on MNIST." -msgstr "查看此联邦学习快速入门教程,了解如何使用 Flower 和 PyTorch Lightning 在 " -"MNIST 上训练自动编码器模型。" +"Check out this Federated Learning quickstart tutorial for using Flower " +"with PyTorch Lightning to train an Auto Encoder model on MNIST." +msgstr "查看此联邦学习快速入门教程,了解如何使用 Flower 和 PyTorch Lightning 在 MNIST 上训练自动编码器模型。" #: ../../source/tutorial-quickstart-pytorch-lightning.rst:5 msgid "Quickstart PyTorch Lightning" @@ -13346,24 +17279,24 @@ msgstr "快速入门 PyTorch Lightning" #: ../../source/tutorial-quickstart-pytorch-lightning.rst:10 msgid "" -"Let's build a horizontal federated learning system using PyTorch Lightning " -"and Flower!" +"Let's build a horizontal federated learning system using PyTorch " +"Lightning and Flower!" msgstr "让我们使用 PyTorch Lightning 和 Flower 构建一个水平联邦学习系统!" #: ../../source/tutorial-quickstart-pytorch-lightning.rst:12 msgid "" -"Please refer to the `full code example `_ to learn more." +"Please refer to the `full code example " +"`_ to learn more." msgstr "" -"请参阅 `完整代码示例 `_ 了解更多信息。" +"请参阅 `完整代码示例 `_ 了解更多信息。" #: ../../source/tutorial-quickstart-scikitlearn.rst:-1 msgid "" -"Check out this Federated Learning quickstart tutorial for using Flower with " -"scikit-learn to train a linear regression model." -msgstr "查看此联邦学习快速入门教程,了解如何使用 Flower 和 scikit-learn " -"训练线性回归模型。" +"Check out this Federated Learning quickstart tutorial for using Flower " +"with scikit-learn to train a linear regression model." +msgstr "查看此联邦学习快速入门教程,了解如何使用 Flower 和 scikit-learn 训练线性回归模型。" #: ../../source/tutorial-quickstart-scikitlearn.rst:5 msgid "Quickstart scikit-learn" @@ -13371,11 +17304,11 @@ msgstr "scikit-learn快速入门" #: ../../source/tutorial-quickstart-scikitlearn.rst:10 msgid "" -"In this tutorial, we will learn how to train a :code:`Logistic Regression` " -"model on MNIST using Flower and scikit-learn." +"In this tutorial, we will learn how to train a :code:`Logistic " +"Regression` model on MNIST using Flower and scikit-learn." msgstr "" -"在本教程中,我们将学习如何使用 Flower 和 scikit-learn 在 MNIST 上训练一个 :" -"code:`Logistic Regression` 模型。" +"在本教程中,我们将学习如何使用 Flower 和 scikit-learn 在 MNIST 上训练一个 :code:`Logistic " +"Regression` 模型。" #: ../../source/tutorial-quickstart-scikitlearn.rst:26 msgid "Since we want to use scikt-learn, let's go ahead and install it:" @@ -13389,15 +17322,13 @@ msgstr "或者直接使用 Poetry 安装所有依赖项:" msgid "" "Now that we have all our dependencies installed, let's run a simple " "distributed training with two clients and one server. However, before " -"setting up the client and server, we will define all functionalities that we " -"need for our federated learning setup within :code:`utils.py`. The :code:" -"`utils.py` contains different functions defining all the machine learning " -"basics:" +"setting up the client and server, we will define all functionalities that" +" we need for our federated learning setup within :code:`utils.py`. The " +":code:`utils.py` contains different functions defining all the machine " +"learning basics:" msgstr "" -"现在我们已经安装了所有的依赖项,让我们用两个客户端和一个服务器来运行一个简单" -"的分布式训练。不过,在设置客户端和服务器之前,我们将在 :code:`utils.py` " -"中定义联邦学习设置所需的所有功能。:code:`utils." -"py`包含定义所有机器学习基础知识的不同函数:" +"现在我们已经安装了所有的依赖项,让我们用两个客户端和一个服务器来运行一个简单的分布式训练。不过,在设置客户端和服务器之前,我们将在 " +":code:`utils.py` 中定义联邦学习设置所需的所有功能。:code:`utils.py`包含定义所有机器学习基础知识的不同函数:" #: ../../source/tutorial-quickstart-scikitlearn.rst:45 msgid ":code:`get_model_parameters()`" @@ -13449,61 +17380,58 @@ msgstr "将数据集分割成多个分区" #: ../../source/tutorial-quickstart-scikitlearn.rst:58 msgid "" -"Please check out :code:`utils.py` `here `_ for more details. The pre-" -"defined functions are used in the :code:`client.py` and imported. The :code:" -"`client.py` also requires to import several packages such as Flower and " -"scikit-learn:" +"Please check out :code:`utils.py` `here " +"`_ for more details. The pre-defined functions are used in" +" the :code:`client.py` and imported. The :code:`client.py` also requires " +"to import several packages such as Flower and scikit-learn:" msgstr "" -"更多详情请查看 :code:`utils.py`` 这里 `_。在 :code:`client.py` 中使用并" -"导入了预定义函数。:code:`client.py` 还需要导入几个软件包,如 Flower 和 " -"scikit-learn:" +"更多详情请查看 :code:`utils.py`` 这里 " +"`_。在 :code:`client.py` 中使用并导入了预定义函数。:code:`client.py` " +"还需要导入几个软件包,如 Flower 和 scikit-learn:" #: ../../source/tutorial-quickstart-scikitlearn.rst:73 msgid "" -"We load the MNIST dataset from `OpenML `_, a " -"popular image classification dataset of handwritten digits for machine " -"learning. The utility :code:`utils.load_mnist()` downloads the training and " -"test data. The training set is split afterwards into 10 partitions with :" -"code:`utils.partition()`." +"We load the MNIST dataset from `OpenML `_, " +"a popular image classification dataset of handwritten digits for machine " +"learning. The utility :code:`utils.load_mnist()` downloads the training " +"and test data. The training set is split afterwards into 10 partitions " +"with :code:`utils.partition()`." msgstr "" -"我们从 `OpenML `_ 中加载 MNIST 数据集,这是一个" -"用于机器学习的流行手写数字图像分类数据集。实用程序 :code:`utils." -"load_mnist()` 下载训练和测试数据。然后使用 :code:`utils.partition()`将训练集" -"分割成 10 个分区。" +"我们从 `OpenML `_ 中加载 MNIST " +"数据集,这是一个用于机器学习的流行手写数字图像分类数据集。实用程序 :code:`utils.load_mnist()` " +"下载训练和测试数据。然后使用 :code:`utils.partition()`将训练集分割成 10 个分区。" #: ../../source/tutorial-quickstart-scikitlearn.rst:85 msgid "" -"Next, the logistic regression model is defined and initialized with :code:" -"`utils.set_initial_params()`." -msgstr "" -"接下来,使用 :code:`utils.set_initial_params()` 对逻辑回归模型进行定义和初始" -"化。" +"Next, the logistic regression model is defined and initialized with " +":code:`utils.set_initial_params()`." +msgstr "接下来,使用 :code:`utils.set_initial_params()` 对逻辑回归模型进行定义和初始化。" #: ../../source/tutorial-quickstart-scikitlearn.rst:97 msgid "" -"The Flower server interacts with clients through an interface called :code:" -"`Client`. When the server selects a particular client for training, it sends " -"training instructions over the network. The client receives those " -"instructions and calls one of the :code:`Client` methods to run your code (i." -"e., to fit the logistic regression we defined earlier)." +"The Flower server interacts with clients through an interface called " +":code:`Client`. When the server selects a particular client for training," +" it sends training instructions over the network. The client receives " +"those instructions and calls one of the :code:`Client` methods to run " +"your code (i.e., to fit the logistic regression we defined earlier)." msgstr "" -"Flower 服务器通过一个名为 :code:`Client` 的接口与客户端交互。当服务器选择一个" -"特定的客户端进行训练时,它会通过网络发送训练指令。客户端接收到这些指令后,会" -"调用 :code:`Client` 方法之一来运行您的代码(即拟合我们之前定义的逻辑回归)。" +"Flower 服务器通过一个名为 :code:`Client` " +"的接口与客户端交互。当服务器选择一个特定的客户端进行训练时,它会通过网络发送训练指令。客户端接收到这些指令后,会调用 :code:`Client`" +" 方法之一来运行您的代码(即拟合我们之前定义的逻辑回归)。" #: ../../source/tutorial-quickstart-scikitlearn.rst:103 msgid "" -"Flower provides a convenience class called :code:`NumPyClient` which makes " -"it easier to implement the :code:`Client` interface when your workload uses " -"scikit-learn. Implementing :code:`NumPyClient` usually means defining the " -"following methods (:code:`set_parameters` is optional though):" +"Flower provides a convenience class called :code:`NumPyClient` which " +"makes it easier to implement the :code:`Client` interface when your " +"workload uses scikit-learn. Implementing :code:`NumPyClient` usually " +"means defining the following methods (:code:`set_parameters` is optional " +"though):" msgstr "" -"Flower 提供了一个名为 :code:`NumPyClient` 的便捷类,当你的工作负载使用 " -"scikit-learn 时,它可以让你更容易地实现 :code:`Client` 接口。实现 " -":code:`NumPyClient` 通常意味着定义以下方法(:code:`set_parameters` " -"是可选的):" +"Flower 提供了一个名为 :code:`NumPyClient` 的便捷类,当你的工作负载使用 scikit-learn " +"时,它可以让你更容易地实现 :code:`Client` 接口。实现 :code:`NumPyClient` " +"通常意味着定义以下方法(:code:`set_parameters` 是可选的):" #: ../../source/tutorial-quickstart-scikitlearn.rst:112 msgid "is directly imported with :code:`utils.set_model_params()`" @@ -13515,20 +17443,38 @@ msgstr "这些方法可以通过以下方式实现:" #: ../../source/tutorial-quickstart-scikitlearn.rst:143 msgid "" -"We can now create an instance of our class :code:`MnistClient` and add one " -"line to actually run this client:" +"We can now create an instance of our class :code:`MnistClient` and add " +"one line to actually run this client:" +msgstr "现在我们可以创建一个 :code:`MnistClient` 类的实例,并添加一行来实际运行该客户端:" + +#: ../../source/tutorial-quickstart-scikitlearn.rst:150 +#, fuzzy +msgid "" +"That's it for the client. We only have to implement :code:`Client` or " +":code:`NumPyClient` and call :code:`fl.client.start_client()`. If you " +"implement a client of type :code:`NumPyClient` you'll need to first call " +"its :code:`to_client()` method. The string :code:`\"0.0.0.0:8080\"` tells" +" the client which server to connect to. In our case we can run the server" +" and the client on the same machine, therefore we use " +":code:`\"0.0.0.0:8080\"`. If we run a truly federated workload with the " +"server and clients running on different machines, all that needs to " +"change is the :code:`server_address` we pass to the client." msgstr "" -"现在我们可以创建一个 :code:`MnistClient` 类的实例,并添加一行来实际运行该客户" -"端:" +"这就是客户端。我们只需实现 :code:`Client` 或 :code:`NumPyClient` 并调用 " +":code:`fl.client.start_client()` 或 " +":code:`fl.client.start_numpy_client()`。字符串 " +":code:`\"0.0.0.0:8080\"`会告诉客户端要连接的服务器。在本例中,我们可以在同一台机器上运行服务器和客户端,因此我们使用 " +":code:`\"0.0.0.0:8080\"`。如果我们运行的是真正的联邦工作负载,服务器和客户端运行在不同的机器上,那么需要改变的只是传递给客户端的" +" :code:`server_address`。" #: ../../source/tutorial-quickstart-scikitlearn.rst:159 msgid "" "The following Flower server is a little bit more advanced and returns an " -"evaluation function for the server-side evaluation. First, we import again " -"all required libraries such as Flower and scikit-learn." +"evaluation function for the server-side evaluation. First, we import " +"again all required libraries such as Flower and scikit-learn." msgstr "" -"下面的 Flower 服务器更先进一些,会返回一个用于服务器端评估的评估函数。首先," -"我们再次导入所有需要的库,如 Flower 和 scikit-learn。" +"下面的 Flower 服务器更先进一些,会返回一个用于服务器端评估的评估函数。首先,我们再次导入所有需要的库,如 Flower 和 scikit-" +"learn。" #: ../../source/tutorial-quickstart-scikitlearn.rst:162 msgid ":code:`server.py`, import Flower and start the server:" @@ -13536,8 +17482,8 @@ msgstr ":code:`server.py`, 导入 Flower 并启动服务器:" #: ../../source/tutorial-quickstart-scikitlearn.rst:173 msgid "" -"The number of federated learning rounds is set in :code:`fit_round()` and " -"the evaluation is defined in :code:`get_evaluate_fn()`. The evaluation " +"The number of federated learning rounds is set in :code:`fit_round()` and" +" the evaluation is defined in :code:`get_evaluate_fn()`. The evaluation " "function is called after each federated learning round and gives you " "information about loss and accuracy." msgstr "" @@ -13546,46 +17492,45 @@ msgstr "" #: ../../source/tutorial-quickstart-scikitlearn.rst:198 msgid "" -"The :code:`main` contains the server-side parameter initialization :code:" -"`utils.set_initial_params()` as well as the aggregation strategy :code:`fl." -"server.strategy:FedAvg()`. The strategy is the default one, federated " -"averaging (or FedAvg), with two clients and evaluation after each federated " -"learning round. The server can be started with the command :code:`fl.server." -"start_server(server_address=\"0.0.0.0:8080\", strategy=strategy, config=fl." -"server.ServerConfig(num_rounds=3))`." +"The :code:`main` contains the server-side parameter initialization " +":code:`utils.set_initial_params()` as well as the aggregation strategy " +":code:`fl.server.strategy:FedAvg()`. The strategy is the default one, " +"federated averaging (or FedAvg), with two clients and evaluation after " +"each federated learning round. The server can be started with the command" +" :code:`fl.server.start_server(server_address=\"0.0.0.0:8080\", " +"strategy=strategy, config=fl.server.ServerConfig(num_rounds=3))`." msgstr "" -":code:`main`包含服务器端参数初始化:code:`utils.set_initial_params()`" -"以及聚合策略 :code:`fl.server.strategy:FedAvg()`。该策略是默认的联邦平均(或 " -"FedAvg)策略,有两个客户端,在每轮联邦学习后进行评估。可以使用 :code:`fl." -"server.start_server(server_address=\"0.0.0.0:8080\", strategy=strategy, " -"config=fl.server.ServerConfig(num_rounds=3))` 命令启动服务器。" +":code:`main`包含服务器端参数初始化:code:`utils.set_initial_params()`以及聚合策略 " +":code:`fl.server.strategy:FedAvg()`。该策略是默认的联邦平均(或 " +"FedAvg)策略,有两个客户端,在每轮联邦学习后进行评估。可以使用 " +":code:`fl.server.start_server(server_address=\"0.0.0.0:8080\", " +"strategy=strategy, config=fl.server.ServerConfig(num_rounds=3))` 命令启动服务器。" #: ../../source/tutorial-quickstart-scikitlearn.rst:217 msgid "" "With both client and server ready, we can now run everything and see " "federated learning in action. Federated learning systems usually have a " -"server and multiple clients. We, therefore, have to start the server first:" -msgstr "" -"客户端和服务器都准备就绪后,我们现在就可以运行一切,看看联邦学习的运行情况。" -"联邦学习系统通常有一个服务器和多个客户端。因此,我们必须先启动服务器:" +"server and multiple clients. We, therefore, have to start the server " +"first:" +msgstr "客户端和服务器都准备就绪后,我们现在就可以运行一切,看看联邦学习的运行情况。联邦学习系统通常有一个服务器和多个客户端。因此,我们必须先启动服务器:" #: ../../source/tutorial-quickstart-scikitlearn.rst:271 msgid "" "Congratulations! You've successfully built and run your first federated " -"learning system. The full `source code `_ for this example can be found in :code:" -"`examples/sklearn-logreg-mnist`." +"learning system. The full `source code " +"`_ for this example can be found in :code:`examples/sklearn-logreg-" +"mnist`." msgstr "" "恭喜您!您已经成功构建并运行了第一个联邦学习系统。本示例的`完整源代码 " -"`_ " -"可以在 :code:`examples/sklearn-logreg-mnist` 中找到。" +"`_ 可以在 :code:`examples/sklearn-logreg-mnist` 中找到。" #: ../../source/tutorial-quickstart-tensorflow.rst:-1 msgid "" -"Check out this Federated Learning quickstart tutorial for using Flower with " -"TensorFlow to train a MobilNetV2 model on CIFAR-10." -msgstr "查看此联邦学习快速入门教程,了解如何使用 Flower 和 TensorFlow 在 CIFAR-10 " -"上训练 MobilNetV2 模型。" +"Check out this Federated Learning quickstart tutorial for using Flower " +"with TensorFlow to train a MobilNetV2 model on CIFAR-10." +msgstr "查看此联邦学习快速入门教程,了解如何使用 Flower 和 TensorFlow 在 CIFAR-10 上训练 MobilNetV2 模型。" #: ../../source/tutorial-quickstart-tensorflow.rst:5 msgid "Quickstart TensorFlow" @@ -13601,8 +17546,8 @@ msgstr "在导入 Flower 之前,我们必须先安装它:" #: ../../source/tutorial-quickstart-tensorflow.rst:21 msgid "" -"Since we want to use the Keras API of TensorFlow (TF), we have to install TF " -"as well:" +"Since we want to use the Keras API of TensorFlow (TF), we have to install" +" TF as well:" msgstr "由于我们要使用 TensorFlow (TF) 的 Keras API,因此还必须安装 TF:" #: ../../source/tutorial-quickstart-tensorflow.rst:31 @@ -13611,32 +17556,31 @@ msgstr "接下来,在名为 :code:`client.py` 的文件中导入 Flower 和 Te #: ../../source/tutorial-quickstart-tensorflow.rst:38 msgid "" -"We use the Keras utilities of TF to load CIFAR10, a popular colored image " -"classification dataset for machine learning. The call to :code:`tf.keras." -"datasets.cifar10.load_data()` downloads CIFAR10, caches it locally, and then " -"returns the entire training and test set as NumPy ndarrays." +"We use the Keras utilities of TF to load CIFAR10, a popular colored image" +" classification dataset for machine learning. The call to " +":code:`tf.keras.datasets.cifar10.load_data()` downloads CIFAR10, caches " +"it locally, and then returns the entire training and test set as NumPy " +"ndarrays." msgstr "" -"我们使用 TF 的 Keras 实用程序加载 CIFAR10,这是一个用于机器学习的流行彩色图像" -"分类数据集。调用 :code:`tf.keras.datasets.cifar10.load_data()` 会下载 " -"CIFAR10,将其缓存到本地,然后以 NumPy ndarrays 的形式返回整个训练集和测试集。" +"我们使用 TF 的 Keras 实用程序加载 CIFAR10,这是一个用于机器学习的流行彩色图像分类数据集。调用 " +":code:`tf.keras.datasets.cifar10.load_data()` 会下载 CIFAR10,将其缓存到本地,然后以 " +"NumPy ndarrays 的形式返回整个训练集和测试集。" #: ../../source/tutorial-quickstart-tensorflow.rst:47 msgid "" -"Next, we need a model. For the purpose of this tutorial, we use MobilNetV2 " -"with 10 output classes:" -msgstr "" -"接下来,我们需要一个模型。在本教程中,我们使用带有 10 个输出类的 MobilNetV2:" +"Next, we need a model. For the purpose of this tutorial, we use " +"MobilNetV2 with 10 output classes:" +msgstr "接下来,我们需要一个模型。在本教程中,我们使用带有 10 个输出类的 MobilNetV2:" #: ../../source/tutorial-quickstart-tensorflow.rst:60 msgid "" -"Flower provides a convenience class called :code:`NumPyClient` which makes " -"it easier to implement the :code:`Client` interface when your workload uses " -"Keras. The :code:`NumPyClient` interface defines three methods which can be " -"implemented in the following way:" +"Flower provides a convenience class called :code:`NumPyClient` which " +"makes it easier to implement the :code:`Client` interface when your " +"workload uses Keras. The :code:`NumPyClient` interface defines three " +"methods which can be implemented in the following way:" msgstr "" -"Flower 提供了一个名为 :code:`NumPyClient` 的便捷类,当您的工作负载使用 Keras " -"时,该类可以更轻松地实现 :code:`Client` 接口。:code:`NumPyClient` " -"接口定义了三个方法,可以通过以下方式实现:" +"Flower 提供了一个名为 :code:`NumPyClient` 的便捷类,当您的工作负载使用 Keras 时,该类可以更轻松地实现 " +":code:`Client` 接口。:code:`NumPyClient` 接口定义了三个方法,可以通过以下方式实现:" #: ../../source/tutorial-quickstart-tensorflow.rst:135 msgid "Each client will have its own dataset." @@ -13644,527 +17588,600 @@ msgstr "每个客户都有自己的数据集。" #: ../../source/tutorial-quickstart-tensorflow.rst:137 msgid "" -"You should now see how the training does in the very first terminal (the one " -"that started the server):" +"You should now see how the training does in the very first terminal (the " +"one that started the server):" msgstr "现在你应该能在第一个终端(启动服务器的终端)看到训练的效果了:" #: ../../source/tutorial-quickstart-tensorflow.rst:169 msgid "" "Congratulations! You've successfully built and run your first federated " -"learning system. The full `source code `_ for this can be found in :" -"code:`examples/quickstart-tensorflow/client.py`." +"learning system. The full `source code " +"`_ for this can be found in :code:`examples" +"/quickstart-tensorflow/client.py`." msgstr "" "恭喜您!您已经成功构建并运行了第一个联邦学习系统。`完整的源代码 " -"`_ 可以在 :code:`examples/quickstart-tensorflow/client.py` 中找到。" +"`_ 可以在 :code:`examples/quickstart-" +"tensorflow/client.py` 中找到。" #: ../../source/tutorial-quickstart-xgboost.rst:-1 msgid "" -"Check out this Federated Learning quickstart tutorial for using Flower with " -"XGBoost to train classification models on trees." +"Check out this Federated Learning quickstart tutorial for using Flower " +"with XGBoost to train classification models on trees." msgstr "查看此联邦学习 快速入门教程,了解如何使用 Flower 和 XGBoost 上训练分类模型。" #: ../../source/tutorial-quickstart-xgboost.rst:5 msgid "Quickstart XGBoost" msgstr "XGBoost快速入门" -#: ../../source/tutorial-quickstart-xgboost.rst:11 +#: ../../source/tutorial-quickstart-xgboost.rst:14 msgid "Federated XGBoost" msgstr "联邦化 XGBoost" -#: ../../source/tutorial-quickstart-xgboost.rst:13 +#: ../../source/tutorial-quickstart-xgboost.rst:16 msgid "" "EXtreme Gradient Boosting (**XGBoost**) is a robust and efficient " -"implementation of gradient-boosted decision tree (**GBDT**), that maximises " -"the computational boundaries for boosted tree methods. It's primarily " -"designed to enhance both the performance and computational speed of machine " -"learning models. In XGBoost, trees are constructed concurrently, unlike the " -"sequential approach taken by GBDT." +"implementation of gradient-boosted decision tree (**GBDT**), that " +"maximises the computational boundaries for boosted tree methods. It's " +"primarily designed to enhance both the performance and computational " +"speed of machine learning models. In XGBoost, trees are constructed " +"concurrently, unlike the sequential approach taken by GBDT." msgstr "" -"EXtreme Gradient Boosting(**XGBoost**)是梯度提升决策树(**GBDT**)的一种稳" -"健而高效的实现方法,能最大限度地提高提升树方法的计算边界。它主要用于提高机器" -"学习模型的性能和计算速度。在 XGBoost 中,决策树是并发构建的,与 GBDT 采用的顺" -"序方法不同。" +"EXtreme Gradient " +"Boosting(**XGBoost**)是梯度提升决策树(**GBDT**)的一种稳健而高效的实现方法,能最大限度地提高提升树方法的计算边界。它主要用于提高机器学习模型的性能和计算速度。在" +" XGBoost 中,决策树是并发构建的,与 GBDT 采用的顺序方法不同。" -#: ../../source/tutorial-quickstart-xgboost.rst:17 +#: ../../source/tutorial-quickstart-xgboost.rst:20 msgid "" "Often, for tabular data on medium-sized datasets with fewer than 10k " -"training examples, XGBoost surpasses the results of deep learning techniques." -msgstr "" -"对于训练示例少于 10k 的中型数据集上的表格数据,XGBoost 的结果往往超过深度学习" -"技术。" +"training examples, XGBoost surpasses the results of deep learning " +"techniques." +msgstr "对于训练示例少于 10k 的中型数据集上的表格数据,XGBoost 的结果往往超过深度学习技术。" -#: ../../source/tutorial-quickstart-xgboost.rst:20 +#: ../../source/tutorial-quickstart-xgboost.rst:23 msgid "Why federated XGBoost?" msgstr "为什么选择联邦 XGBoost?" -#: ../../source/tutorial-quickstart-xgboost.rst:22 +#: ../../source/tutorial-quickstart-xgboost.rst:25 msgid "" "Indeed, as the demand for data privacy and decentralized learning grows, " -"there's an increasing requirement to implement federated XGBoost systems for " -"specialised applications, like survival analysis and financial fraud " +"there's an increasing requirement to implement federated XGBoost systems " +"for specialised applications, like survival analysis and financial fraud " "detection." -msgstr "" -"事实上,随着对数据隐私和分散学习的需求不断增长,越来越多的专业应用(如生存分" -"析和金融欺诈检测)需要实施联邦 XGBoost 系统。" +msgstr "事实上,随着对数据隐私和分散学习的需求不断增长,越来越多的专业应用(如生存分析和金融欺诈检测)需要实施联邦 XGBoost 系统。" -#: ../../source/tutorial-quickstart-xgboost.rst:24 +#: ../../source/tutorial-quickstart-xgboost.rst:27 msgid "" -"Federated learning ensures that raw data remains on the local device, making " -"it an attractive approach for sensitive domains where data security and " -"privacy are paramount. Given the robustness and efficiency of XGBoost, " -"combining it with federated learning offers a promising solution for these " -"specific challenges." +"Federated learning ensures that raw data remains on the local device, " +"making it an attractive approach for sensitive domains where data " +"security and privacy are paramount. Given the robustness and efficiency " +"of XGBoost, combining it with federated learning offers a promising " +"solution for these specific challenges." msgstr "" -"联邦学习可确保原始数据保留在本地设备上,因此对于数据安全和隐私至关重要的敏感" -"领域来说,这是一种极具吸引力的方法。鉴于 XGBoost 的稳健性和高效性,将其与联邦" -"学习相结合为应对这些特定挑战提供了一种前景广阔的解决方案。" +"联邦学习可确保原始数据保留在本地设备上,因此对于数据安全和隐私至关重要的敏感领域来说,这是一种极具吸引力的方法。鉴于 XGBoost " +"的稳健性和高效性,将其与联邦学习相结合为应对这些特定挑战提供了一种前景广阔的解决方案。" -#: ../../source/tutorial-quickstart-xgboost.rst:27 +#: ../../source/tutorial-quickstart-xgboost.rst:30 msgid "" "In this tutorial we will learn how to train a federated XGBoost model on " "HIGGS dataset using Flower and :code:`xgboost` package. We use a simple " -"example (`full code xgboost-quickstart `_) with two *clients* and one *server* to " -"demonstrate how federated XGBoost works, and then we dive into a more " -"complex example (`full code xgboost-comprehensive `_) to run various " -"experiments." -msgstr "" -"在本教程中,我们将学习如何使用 Flower 和 :code:`xgboost` 软件包在 HIGGS 数据" -"集上训练联邦 XGBoost 模型。我们将使用一个包含两个 * 客户端* 和一个 * 服务器* " -"的简单示例 (`完整代码 xgboost-quickstart `_)来演示联邦 XGBoost 如何工作,然后我" -"们将深入到一个更复杂的示例 (`完整代码 xgboost-comprehensive `_),以运行各种实" -"验。" - -#: ../../source/tutorial-quickstart-xgboost.rst:34 +"example (`full code xgboost-quickstart " +"`_)" +" with two *clients* and one *server* to demonstrate how federated XGBoost" +" works, and then we dive into a more complex example (`full code xgboost-" +"comprehensive `_) to run various experiments." +msgstr "" +"在本教程中,我们将学习如何使用 Flower 和 :code:`xgboost` 软件包在 HIGGS 数据集上训练联邦 XGBoost " +"模型。我们将使用一个包含两个 * 客户端* 和一个 * 服务器* 的简单示例 (`完整代码 xgboost-quickstart " +"`_)来演示联邦 XGBoost 如何工作,然后我们将深入到一个更复杂的示例 (`完整代码 xgboost-" +"comprehensive `_),以运行各种实验。" + +#: ../../source/tutorial-quickstart-xgboost.rst:37 msgid "Environment Setup" msgstr "环境设定" -#: ../../source/tutorial-quickstart-xgboost.rst:38 +#: ../../source/tutorial-quickstart-xgboost.rst:41 msgid "" "We first need to install Flower and Flower Datasets. You can do this by " "running :" msgstr "我们首先需要安装 Flower 和 Flower Datasets。您可以通过运行 :" -#: ../../source/tutorial-quickstart-xgboost.rst:44 +#: ../../source/tutorial-quickstart-xgboost.rst:47 msgid "" "Since we want to use :code:`xgboost` package to build up XGBoost trees, " "let's go ahead and install :code:`xgboost`:" -msgstr "" -"既然我们要使用 :code:`xgboost` 软件包来构建 XGBoost 树,那就继续安装 :code:" -"`xgboost`:" +msgstr "既然我们要使用 :code:`xgboost` 软件包来构建 XGBoost 树,那就继续安装 :code:`xgboost`:" -#: ../../source/tutorial-quickstart-xgboost.rst:54 +#: ../../source/tutorial-quickstart-xgboost.rst:57 msgid "" -"*Clients* are responsible for generating individual weight-updates for the " -"model based on their local datasets. Now that we have all our dependencies " -"installed, let's run a simple distributed training with two clients and one " -"server." -msgstr "" -"*客户端*负责根据其本地数据集为模型生成单独的模型参数更新。现在我们已经安装了" -"所有的依赖项,让我们用两个客户端和一个服务器来运行一个简单的分布式训练。" +"*Clients* are responsible for generating individual weight-updates for " +"the model based on their local datasets. Now that we have all our " +"dependencies installed, let's run a simple distributed training with two " +"clients and one server." +msgstr "*客户端*负责根据其本地数据集为模型生成单独的模型参数更新。现在我们已经安装了所有的依赖项,让我们用两个客户端和一个服务器来运行一个简单的分布式训练。" -#: ../../source/tutorial-quickstart-xgboost.rst:57 +#: ../../source/tutorial-quickstart-xgboost.rst:60 msgid "" -"In a file called :code:`client.py`, import xgboost, Flower, Flower Datasets " -"and other related functions:" -msgstr "" -"在名为 :code:`client.py` 的文件中,导入 xgboost、Flower、Flower Datasets 和其" -"他相关函数:" +"In a file called :code:`client.py`, import xgboost, Flower, Flower " +"Datasets and other related functions:" +msgstr "在名为 :code:`client.py` 的文件中,导入 xgboost、Flower、Flower Datasets 和其他相关函数:" -#: ../../source/tutorial-quickstart-xgboost.rst:84 +#: ../../source/tutorial-quickstart-xgboost.rst:87 msgid "Dataset partition and hyper-parameter selection" msgstr "数据集划分和超参数选择" -#: ../../source/tutorial-quickstart-xgboost.rst:86 +#: ../../source/tutorial-quickstart-xgboost.rst:89 msgid "" -"Prior to local training, we require loading the HIGGS dataset from Flower " -"Datasets and conduct data partitioning for FL:" -msgstr "" -"在本地训练之前,我们需要从 Flower Datasets 加载 HIGGS 数据集,并对 FL 进行数" -"据分区:" +"Prior to local training, we require loading the HIGGS dataset from Flower" +" Datasets and conduct data partitioning for FL:" +msgstr "在本地训练之前,我们需要从 Flower Datasets 加载 HIGGS 数据集,并对 FL 进行数据分区:" -#: ../../source/tutorial-quickstart-xgboost.rst:99 +#: ../../source/tutorial-quickstart-xgboost.rst:102 msgid "" "In this example, we split the dataset into two partitions with uniform " -"distribution (:code:`IidPartitioner(num_partitions=2)`). Then, we load the " -"partition for the given client based on :code:`node_id`:" +"distribution (:code:`IidPartitioner(num_partitions=2)`). Then, we load " +"the partition for the given client based on :code:`node_id`:" msgstr "" -"在此示例中,我们将数据集分割成两个均匀分布的分区(:code:" -"`IidPartitioner(num_partitions=2)`)。然后,我们根据 :code:`node_id` 为给定客" -"户端加载分区:" +"在此示例中,我们将数据集分割成两个均匀分布的分区(:code:`IidPartitioner(num_partitions=2)`)。然后,我们根据" +" :code:`node_id` 为给定客户端加载分区:" -#: ../../source/tutorial-quickstart-xgboost.rst:118 +#: ../../source/tutorial-quickstart-xgboost.rst:121 msgid "" "After that, we do train/test splitting on the given partition (client's " "local data), and transform data format for :code:`xgboost` package." -msgstr "" -"然后,我们在给定的分区(客户端的本地数据)上进行训练/测试分割,并为 :code:" -"`xgboost` 软件包转换数据格式。" +msgstr "然后,我们在给定的分区(客户端的本地数据)上进行训练/测试分割,并为 :code:`xgboost` 软件包转换数据格式。" -#: ../../source/tutorial-quickstart-xgboost.rst:131 +#: ../../source/tutorial-quickstart-xgboost.rst:134 msgid "" -"The functions of :code:`train_test_split` and :code:" -"`transform_dataset_to_dmatrix` are defined as below:" -msgstr "" -":code:`train_test_split` 和 :code:`transform_dataset_too_dmatrix` 的函数定义" -"如下:" +"The functions of :code:`train_test_split` and " +":code:`transform_dataset_to_dmatrix` are defined as below:" +msgstr ":code:`train_test_split` 和 :code:`transform_dataset_too_dmatrix` 的函数定义如下:" -#: ../../source/tutorial-quickstart-xgboost.rst:155 +#: ../../source/tutorial-quickstart-xgboost.rst:158 msgid "Finally, we define the hyper-parameters used for XGBoost training." msgstr "最后,我们定义了用于 XGBoost 训练的超参数。" -#: ../../source/tutorial-quickstart-xgboost.rst:171 +#: ../../source/tutorial-quickstart-xgboost.rst:174 msgid "" -"The :code:`num_local_round` represents the number of iterations for local " -"tree boost. We use CPU for the training in default. One can shift it to GPU " -"by setting :code:`tree_method` to :code:`gpu_hist`. We use AUC as evaluation " -"metric." +"The :code:`num_local_round` represents the number of iterations for local" +" tree boost. We use CPU for the training in default. One can shift it to " +"GPU by setting :code:`tree_method` to :code:`gpu_hist`. We use AUC as " +"evaluation metric." msgstr "" -"代码:`num_local_round`表示本地树的迭代次数。我们默认使用 CPU 进行训练。" -"可以通过将 :code:`tree_method` 设置为 :code:`gpu_hist`,将其转换为 GPU。" -"我们使用 AUC 作为评估指标。" +"代码:`num_local_round`表示本地树的迭代次数。我们默认使用 CPU 进行训练。可以通过将 :code:`tree_method` " +"设置为 :code:`gpu_hist`,将其转换为 GPU。我们使用 AUC 作为评估指标。" -#: ../../source/tutorial-quickstart-xgboost.rst:178 +#: ../../source/tutorial-quickstart-xgboost.rst:181 msgid "Flower client definition for XGBoost" msgstr "用于 XGBoost 的 Flower 客户端定义" -#: ../../source/tutorial-quickstart-xgboost.rst:180 +#: ../../source/tutorial-quickstart-xgboost.rst:183 msgid "" -"After loading the dataset we define the Flower client. We follow the general " -"rule to define :code:`XgbClient` class inherited from :code:`fl.client." -"Client`." +"After loading the dataset we define the Flower client. We follow the " +"general rule to define :code:`XgbClient` class inherited from " +":code:`fl.client.Client`." msgstr "" -"加载数据集后,我们定义 Flower 客户端。我们按照一般规则定义从 :code:`fl." -"client.Client` 继承而来的 :code:`XgbClient` 类。" +"加载数据集后,我们定义 Flower 客户端。我们按照一般规则定义从 :code:`fl.client.Client` 继承而来的 " +":code:`XgbClient` 类。" -#: ../../source/tutorial-quickstart-xgboost.rst:190 +#: ../../source/tutorial-quickstart-xgboost.rst:193 msgid "" "The :code:`self.bst` is used to keep the Booster objects that remain " "consistent across rounds, allowing them to store predictions from trees " -"integrated in earlier rounds and maintain other essential data structures " -"for training." +"integrated in earlier rounds and maintain other essential data structures" +" for training." msgstr "" -"代码:`self.bst`用于保存在各轮中保持一致的 Booster 对象,使其能够存储在前几轮" -"中集成的树的预测结果,并维护其他用于训练的重要数据结构。" +"代码:`self.bst`用于保存在各轮中保持一致的 Booster " +"对象,使其能够存储在前几轮中集成的树的预测结果,并维护其他用于训练的重要数据结构。" -#: ../../source/tutorial-quickstart-xgboost.rst:193 +#: ../../source/tutorial-quickstart-xgboost.rst:196 msgid "" -"Then, we override :code:`get_parameters`, :code:`fit` and :code:`evaluate` " -"methods insides :code:`XgbClient` class as follows." +"Then, we override :code:`get_parameters`, :code:`fit` and " +":code:`evaluate` methods insides :code:`XgbClient` class as follows." msgstr "" -"然后,我们在 :code:`XgbClient` 类中重写 :code:`get_parameters`、:code:`fit` " -"和 :code:`evaluate` 方法如下。" +"然后,我们在 :code:`XgbClient` 类中重写 :code:`get_parameters`、:code:`fit` 和 " +":code:`evaluate` 方法如下。" -#: ../../source/tutorial-quickstart-xgboost.rst:207 +#: ../../source/tutorial-quickstart-xgboost.rst:210 msgid "" "Unlike neural network training, XGBoost trees are not started from a " -"specified random weights. In this case, we do not use :code:`get_parameters` " -"and :code:`set_parameters` to initialise model parameters for XGBoost. As a " -"result, let's return an empty tensor in :code:`get_parameters` when it is " -"called by the server at the first round." +"specified random weights. In this case, we do not use " +":code:`get_parameters` and :code:`set_parameters` to initialise model " +"parameters for XGBoost. As a result, let's return an empty tensor in " +":code:`get_parameters` when it is called by the server at the first " +"round." msgstr "" -"与神经网络训练不同,XGBoost 树不是从指定的随机参数开始的。在这种情况下," -"我们不使用 :code:`get_parameters` 和 :code:`set_parameters` 来初始化 XGBoost " -"的模型参数。因此,当服务器在第一轮调用 :code:`get_parameters` 时,让我们在 " -":code:`get_parameters` 中返回一个空张量。" +"与神经网络训练不同,XGBoost 树不是从指定的随机参数开始的。在这种情况下,我们不使用 :code:`get_parameters` 和 " +":code:`set_parameters` 来初始化 XGBoost 的模型参数。因此,当服务器在第一轮调用 " +":code:`get_parameters` 时,让我们在 :code:`get_parameters` 中返回一个空张量。" -#: ../../source/tutorial-quickstart-xgboost.rst:248 +#: ../../source/tutorial-quickstart-xgboost.rst:251 msgid "" -"In :code:`fit`, at the first round, we call :code:`xgb.train()` to build up " -"the first set of trees. the returned Booster object and config are stored " -"in :code:`self.bst` and :code:`self.config`, respectively. From the second " -"round, we load the global model sent from server to :code:`self.bst`, and " -"then update model weights on local training data with function :code:" -"`local_boost` as follows:" +"In :code:`fit`, at the first round, we call :code:`xgb.train()` to build " +"up the first set of trees. the returned Booster object and config are " +"stored in :code:`self.bst` and :code:`self.config`, respectively. From " +"the second round, we load the global model sent from server to " +":code:`self.bst`, and then update model weights on local training data " +"with function :code:`local_boost` as follows:" msgstr "" -"在 :code:`fit`中,第一轮我们调用 :code:`xgb.train()`来建立第一组树,返回的 " -"Booster 对象和 config 分别存储在 :code:`self.bst` 和 :code:`self.config` 中。" -"从第二轮开始,我们将服务器发送的全局模型加载到 :code:`self.bst`,然后使用函" -"数 :code:`local_boost`更新本地训练数据的模型权重,如下所示:" +"在 :code:`fit`中,第一轮我们调用 :code:`xgb.train()`来建立第一组树,返回的 Booster 对象和 config " +"分别存储在 :code:`self.bst` 和 :code:`self.config` 中。从第二轮开始,我们将服务器发送的全局模型加载到 " +":code:`self.bst`,然后使用函数 :code:`local_boost`更新本地训练数据的模型权重,如下所示:" -#: ../../source/tutorial-quickstart-xgboost.rst:266 +#: ../../source/tutorial-quickstart-xgboost.rst:269 msgid "" -"Given :code:`num_local_round`, we update trees by calling :code:`self.bst." -"update` method. After training, the last :code:`N=num_local_round` trees " -"will be extracted to send to the server." +"Given :code:`num_local_round`, we update trees by calling " +":code:`self.bst.update` method. After training, the last " +":code:`N=num_local_round` trees will be extracted to send to the server." msgstr "" -"给定 :code:`num_local_round`,我们通过调用 :code:`self.bst.update`方法更新" -"树。训练结束后,我们将提取最后一个 :code:`N=num_local_round` 树并发送给服务" -"器。" +"给定 :code:`num_local_round`,我们通过调用 " +":code:`self.bst.update`方法更新树。训练结束后,我们将提取最后一个 :code:`N=num_local_round` " +"树并发送给服务器。" -#: ../../source/tutorial-quickstart-xgboost.rst:288 +#: ../../source/tutorial-quickstart-xgboost.rst:291 msgid "" -"In :code:`evaluate`, we call :code:`self.bst.eval_set` function to conduct " -"evaluation on valid set. The AUC value will be returned." -msgstr "" -"在 :code:`evaluate`中,我们调用 :code:`self.bst.eval_set`函数对有效集合进行评" -"估。将返回 AUC 值。" +"In :code:`evaluate`, we call :code:`self.bst.eval_set` function to " +"conduct evaluation on valid set. The AUC value will be returned." +msgstr "在 :code:`evaluate`中,我们调用 :code:`self.bst.eval_set`函数对有效集合进行评估。将返回 AUC 值。" -#: ../../source/tutorial-quickstart-xgboost.rst:291 +#: ../../source/tutorial-quickstart-xgboost.rst:294 msgid "" -"Now, we can create an instance of our class :code:`XgbClient` and add one " -"line to actually run this client:" -msgstr "" -"现在,我们可以创建一个 :code:`XgbClient` 类的实例,并添加一行来实际运行该客户" -"端:" +"Now, we can create an instance of our class :code:`XgbClient` and add one" +" line to actually run this client:" +msgstr "现在,我们可以创建一个 :code:`XgbClient` 类的实例,并添加一行来实际运行该客户端:" -#: ../../source/tutorial-quickstart-xgboost.rst:297 +#: ../../source/tutorial-quickstart-xgboost.rst:300 msgid "" -"That's it for the client. We only have to implement :code:`Client`and call :" -"code:`fl.client.start_client()`. The string :code:`\"[::]:8080\"` tells the " -"client which server to connect to. In our case we can run the server and the " -"client on the same machine, therefore we use :code:`\"[::]:8080\"`. If we " -"run a truly federated workload with the server and clients running on " -"different machines, all that needs to change is the :code:`server_address` " -"we point the client at." +"That's it for the client. We only have to implement :code:`Client`and " +"call :code:`fl.client.start_client()`. The string :code:`\"[::]:8080\"` " +"tells the client which server to connect to. In our case we can run the " +"server and the client on the same machine, therefore we use " +":code:`\"[::]:8080\"`. If we run a truly federated workload with the " +"server and clients running on different machines, all that needs to " +"change is the :code:`server_address` we point the client at." msgstr "" -"这就是客户端。我们只需实现 :code:`客户端`并调用 :code:`fl.client." -"start_client()`。字符串 :code:`\"[::]:8080\"`会告诉客户端要连接的服务器。在本" -"例中,我们可以在同一台机器上运行服务器和客户端,因此我们使用 :code:`\"[::]:" -"8080\"" -"`。如果我们运行的是真正的联邦工作负载,服务器和客户端运行在不同的机器上," -"那么需要改变的只是客户端指向的 :code:`server_address`。" +"这就是客户端。我们只需实现 :code:`客户端`并调用 :code:`fl.client.start_client()`。字符串 " +":code:`\"[::]:8080\"`会告诉客户端要连接的服务器。在本例中,我们可以在同一台机器上运行服务器和客户端,因此我们使用 " +":code:`\"[::]:8080\"`。如果我们运行的是真正的联邦工作负载,服务器和客户端运行在不同的机器上,那么需要改变的只是客户端指向的 " +":code:`server_address`。" -#: ../../source/tutorial-quickstart-xgboost.rst:308 +#: ../../source/tutorial-quickstart-xgboost.rst:311 msgid "" "These updates are then sent to the *server* which will aggregate them to " -"produce a better model. Finally, the *server* sends this improved version of " -"the model back to each *client* to finish a complete FL round." +"produce a better model. Finally, the *server* sends this improved version" +" of the model back to each *client* to finish a complete FL round." msgstr "" -"然后,这些更新会被发送到*服务器*,由*服务器*聚合后生成一个更好的模型。最后,*" -"服务器*将这个改进版的模型发回给每个*客户端*,以完成一轮完整的 FL。" +"然后,这些更新会被发送到*服务器*,由*服务器*聚合后生成一个更好的模型。最后,*服务器*将这个改进版的模型发回给每个*客户端*,以完成一轮完整的" +" FL。" -#: ../../source/tutorial-quickstart-xgboost.rst:311 +#: ../../source/tutorial-quickstart-xgboost.rst:314 msgid "" -"In a file named :code:`server.py`, import Flower and FedXgbBagging from :" -"code:`flwr.server.strategy`." +"In a file named :code:`server.py`, import Flower and FedXgbBagging from " +":code:`flwr.server.strategy`." msgstr "" -"在名为 :code:`server.py` 的文件中,从 :code:`flwr.server.strategy` 导入 " -"Flower 和 FedXgbBagging。" +"在名为 :code:`server.py` 的文件中,从 :code:`flwr.server.strategy` 导入 Flower 和 " +"FedXgbBagging。" -#: ../../source/tutorial-quickstart-xgboost.rst:313 +#: ../../source/tutorial-quickstart-xgboost.rst:316 msgid "We first define a strategy for XGBoost bagging aggregation." msgstr "我们首先定义了 XGBoost bagging聚合策略。" -#: ../../source/tutorial-quickstart-xgboost.rst:336 +#: ../../source/tutorial-quickstart-xgboost.rst:339 msgid "" -"We use two clients for this example. An :code:`evaluate_metrics_aggregation` " -"function is defined to collect and wighted average the AUC values from " -"clients." +"We use two clients for this example. An " +":code:`evaluate_metrics_aggregation` function is defined to collect and " +"wighted average the AUC values from clients." msgstr "" -"本示例使用两个客户端。我们定义了一个 :code:`evaluate_metrics_aggregation` 函" -"数,用于收集客户机的 AUC 值并求取平均值。" +"本示例使用两个客户端。我们定义了一个 :code:`evaluate_metrics_aggregation` 函数,用于收集客户机的 AUC " +"值并求取平均值。" -#: ../../source/tutorial-quickstart-xgboost.rst:339 +#: ../../source/tutorial-quickstart-xgboost.rst:342 msgid "Then, we start the server:" msgstr "然后,我们启动服务器:" -#: ../../source/tutorial-quickstart-xgboost.rst:351 +#: ../../source/tutorial-quickstart-xgboost.rst:354 msgid "Tree-based bagging aggregation" msgstr "基于树的bagging聚合" -#: ../../source/tutorial-quickstart-xgboost.rst:353 +#: ../../source/tutorial-quickstart-xgboost.rst:356 msgid "" -"You must be curious about how bagging aggregation works. Let's look into the " -"details." +"You must be curious about how bagging aggregation works. Let's look into " +"the details." msgstr "您一定很好奇bagging聚合是如何工作的。让我们来详细了解一下。" -#: ../../source/tutorial-quickstart-xgboost.rst:355 +#: ../../source/tutorial-quickstart-xgboost.rst:358 msgid "" -"In file :code:`flwr.server.strategy.fedxgb_bagging.py`, we define :code:" -"`FedXgbBagging` inherited from :code:`flwr.server.strategy.FedAvg`. Then, we " -"override the :code:`aggregate_fit`, :code:`aggregate_evaluate` and :code:" -"`evaluate` methods as follows:" +"In file :code:`flwr.server.strategy.fedxgb_bagging.py`, we define " +":code:`FedXgbBagging` inherited from :code:`flwr.server.strategy.FedAvg`." +" Then, we override the :code:`aggregate_fit`, :code:`aggregate_evaluate` " +"and :code:`evaluate` methods as follows:" msgstr "" -"在文件 :code:`flwr.server.strategy.fedxgb_bagging.py`中,我们定义了从 :code:" -"`flwr.server.strategy.FedAvg`继承的 :code:`FedXgbBagging`。然后,我们覆盖 :" -"code:`aggregate_fit`、:code:`aggregate_evaluate` 和 :code:`evaluate` 方法如" -"下:" +"在文件 :code:`flwr.server.strategy.fedxgb_bagging.py`中,我们定义了从 " +":code:`flwr.server.strategy.FedAvg`继承的 :code:`FedXgbBagging`。然后,我们覆盖 " +":code:`aggregate_fit`、:code:`aggregate_evaluate` 和 :code:`evaluate` 方法如下:" -#: ../../source/tutorial-quickstart-xgboost.rst:451 +#: ../../source/tutorial-quickstart-xgboost.rst:454 msgid "" "In :code:`aggregate_fit`, we sequentially aggregate the clients' XGBoost " "trees by calling :code:`aggregate()` function:" msgstr "" -"在 :code:`aggregate_fit` 中,我们通过调用 :code:`aggregate()` 函数," -"按顺序聚合客户端的 XGBoost 树:" +"在 :code:`aggregate_fit` 中,我们通过调用 :code:`aggregate()` 函数,按顺序聚合客户端的 XGBoost" +" 树:" -#: ../../source/tutorial-quickstart-xgboost.rst:510 +#: ../../source/tutorial-quickstart-xgboost.rst:513 msgid "" "In this function, we first fetch the number of trees and the number of " -"parallel trees for the current and previous model by calling :code:" -"`_get_tree_nums`. Then, the fetched information will be aggregated. After " -"that, the trees (containing model weights) are aggregated to generate a new " -"tree model." +"parallel trees for the current and previous model by calling " +":code:`_get_tree_nums`. Then, the fetched information will be aggregated." +" After that, the trees (containing model weights) are aggregated to " +"generate a new tree model." msgstr "" -"在该函数中,我们首先通过调用 :code:`_get_tree_nums` 获取当前模型和上一个模型" -"的树数和并行树数。然后,对获取的信息进行聚合。然后,聚合树(包含模型参数)生" -"成新的树模型。" +"在该函数中,我们首先通过调用 :code:`_get_tree_nums` " +"获取当前模型和上一个模型的树数和并行树数。然后,对获取的信息进行聚合。然后,聚合树(包含模型参数)生成新的树模型。" -#: ../../source/tutorial-quickstart-xgboost.rst:515 +#: ../../source/tutorial-quickstart-xgboost.rst:518 msgid "" "After traversal of all clients' models, a new global model is generated, " "followed by the serialisation, and sending back to each client." -msgstr "在遍历所有客户端的模型后,会生成一个新的全局模型,然后进行序列化,并发回给每" -"个客户端。" +msgstr "在遍历所有客户端的模型后,会生成一个新的全局模型,然后进行序列化,并发回给每个客户端。" -#: ../../source/tutorial-quickstart-xgboost.rst:520 +#: ../../source/tutorial-quickstart-xgboost.rst:523 msgid "Launch Federated XGBoost!" msgstr "启动联邦 XGBoost!" -#: ../../source/tutorial-quickstart-xgboost.rst:582 +#: ../../source/tutorial-quickstart-xgboost.rst:585 msgid "" "Congratulations! You've successfully built and run your first federated " -"XGBoost system. The AUC values can be checked in :code:" -"`metrics_distributed`. One can see that the average AUC increases over FL " -"rounds." +"XGBoost system. The AUC values can be checked in " +":code:`metrics_distributed`. One can see that the average AUC increases " +"over FL rounds." msgstr "" -"恭喜您!您已成功构建并运行了第一个联邦 XGBoost 系统。可以在 " -":code:`metrics_distributed` 中查看 AUC 值。我们可以看到,平均 AUC 随 FL " -"轮数的增加而增加。" +"恭喜您!您已成功构建并运行了第一个联邦 XGBoost 系统。可以在 :code:`metrics_distributed` 中查看 AUC " +"值。我们可以看到,平均 AUC 随 FL 轮数的增加而增加。" -#: ../../source/tutorial-quickstart-xgboost.rst:587 +#: ../../source/tutorial-quickstart-xgboost.rst:590 msgid "" -"The full `source code `_ for this example can be found in :code:`examples/" -"xgboost-quickstart`." +"The full `source code `_ for this example can be found in :code:`examples" +"/xgboost-quickstart`." msgstr "" -"此示例的`完整源代码 `_ 可在 :code:`examples/xgboost-quickstart` 中找到。" +"此示例的`完整源代码 `_ 可在 :code:`examples/xgboost-quickstart` 中找到。" -#: ../../source/tutorial-quickstart-xgboost.rst:591 +#: ../../source/tutorial-quickstart-xgboost.rst:594 msgid "Comprehensive Federated XGBoost" msgstr "综合的联邦 XGBoost" -#: ../../source/tutorial-quickstart-xgboost.rst:593 +#: ../../source/tutorial-quickstart-xgboost.rst:596 +#, fuzzy +msgid "" +"Now that you have known how federated XGBoost work with Flower, it's time" +" to run some more comprehensive experiments by customising the " +"experimental settings. In the xgboost-comprehensive example (`full code " +"`_), we provide more options to define various experimental" +" setups, including aggregation strategies, data partitioning and " +"centralised/distributed evaluation. We also support `Flower simulation " +"`_ making " +"it easy to simulate large client cohorts in a resource-aware manner. " +"Let's take a look!" +msgstr "" +"既然您已经知道联合 XGBoost 如何与 Flower 协同工作,那么现在就该通过自定义实验设置来运行一些更综合的实验了。在 xgboost-" +"comprehensive 示例 (`完整代码 " +"`_)中,我们提供了更多选项来定义各种实验设置,包括数据分区和集中/分布式评估。让我们一起来看看!" + +#: ../../source/tutorial-quickstart-xgboost.rst:603 +#, fuzzy +msgid "Cyclic training" +msgstr "集中式训练" + +#: ../../source/tutorial-quickstart-xgboost.rst:605 +msgid "" +"In addition to bagging aggregation, we offer a cyclic training scheme, " +"which performs FL in a client-by-client fashion. Instead of aggregating " +"multiple clients, there is only one single client participating in the " +"training per round in the cyclic training scenario. The trained local " +"XGBoost trees will be passed to the next client as an initialised model " +"for next round's boosting." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:609 +msgid "" +"To do this, we first customise a :code:`ClientManager` in " +":code:`server_utils.py`:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:649 +msgid "" +"The customised :code:`ClientManager` samples all available clients in " +"each FL round based on the order of connection to the server. Then, we " +"define a new strategy :code:`FedXgbCyclic` in " +":code:`flwr.server.strategy.fedxgb_cyclic.py`, in order to sequentially " +"select only one client in given round and pass the received model to next" +" client." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:690 msgid "" -"Now that you have known how federated XGBoost work with Flower, it's time to " -"run some more comprehensive experiments by customising the experimental " -"settings. In the xgboost-comprehensive example (`full code `_), we provide " -"more options to define various experimental setups, including data " -"partitioning and centralised/distributed evaluation. Let's take a look!" +"Unlike the original :code:`FedAvg`, we don't perform aggregation here. " +"Instead, we just make a copy of the received client model as global model" +" by overriding :code:`aggregate_fit`." msgstr "" -"既然您已经知道联合 XGBoost 如何与 Flower " -"协同工作,那么现在就该通过自定义实验设置来运行一些更综合的实验了。在 xgboost-" -"comprehensive 示例 (`完整代码 `_)中,我们提供了更多选项来定义各种实验设置," -"包括数据分区和集中/分布式评估。让我们一起来看看!" -#: ../../source/tutorial-quickstart-xgboost.rst:599 +#: ../../source/tutorial-quickstart-xgboost.rst:693 +msgid "" +"Also, the customised :code:`configure_fit` and :code:`configure_evaluate`" +" methods ensure the clients to be sequentially selected given FL round:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:757 msgid "Customised data partitioning" msgstr "定制数据分区" -#: ../../source/tutorial-quickstart-xgboost.rst:601 +#: ../../source/tutorial-quickstart-xgboost.rst:759 msgid "" -"In :code:`dataset.py`, we have a function :code:`instantiate_partitioner` to " -"instantiate the data partitioner based on the given :code:`num_partitions` " -"and :code:`partitioner_type`. Currently, we provide four supported " -"partitioner type to simulate the uniformity/non-uniformity in data quantity " -"(uniform, linear, square, exponential)." +"In :code:`dataset.py`, we have a function :code:`instantiate_partitioner`" +" to instantiate the data partitioner based on the given " +":code:`num_partitions` and :code:`partitioner_type`. Currently, we " +"provide four supported partitioner type to simulate the uniformity/non-" +"uniformity in data quantity (uniform, linear, square, exponential)." msgstr "" -"在 :code:`dataset.py` 中,我们有一个函数 :code:`instantiate_partitioner` 来根" -"据给定的 :code:`num_partitions` 和 :code:`partitioner_type` 来实例化数据分区" -"器。目前,我们提供四种支持的分区器类型(均匀、线性、正方形、指数)来模拟数据" -"量的均匀性/非均匀性。" +"在 :code:`dataset.py` 中,我们有一个函数 :code:`instantiate_partitioner` 来根据给定的 " +":code:`num_partitions` 和 :code:`partitioner_type` " +"来实例化数据分区器。目前,我们提供四种支持的分区器类型(均匀、线性、正方形、指数)来模拟数据量的均匀性/非均匀性。" -#: ../../source/tutorial-quickstart-xgboost.rst:632 +#: ../../source/tutorial-quickstart-xgboost.rst:790 msgid "Customised centralised/distributed evaluation" msgstr "定制的集中/分布式评估" -#: ../../source/tutorial-quickstart-xgboost.rst:634 +#: ../../source/tutorial-quickstart-xgboost.rst:792 +#, fuzzy msgid "" -"To facilitate centralised evaluation, we define a function in :code:`server." -"py`:" +"To facilitate centralised evaluation, we define a function in " +":code:`server_utils.py`:" msgstr "为便于集中评估,我们在 :code:`server.py` 中定义了一个函数:" -#: ../../source/tutorial-quickstart-xgboost.rst:666 +#: ../../source/tutorial-quickstart-xgboost.rst:824 msgid "" -"This function returns a evaluation function which instantiates a :code:" -"`Booster` object and loads the global model weights to it. The evaluation is " -"conducted by calling :code:`eval_set()` method, and the tested AUC value is " -"reported." +"This function returns a evaluation function which instantiates a " +":code:`Booster` object and loads the global model weights to it. The " +"evaluation is conducted by calling :code:`eval_set()` method, and the " +"tested AUC value is reported." +msgstr "" +"此函数返回一个评估函数,该函数实例化一个 :code:`Booster` 对象,并向其加载全局模型参数。评估通过调用 " +":code:`eval_set()` 方法进行,并报告测试的 AUC 值。" + +#: ../../source/tutorial-quickstart-xgboost.rst:827 +#, fuzzy +msgid "" +"As for distributed evaluation on the clients, it's same as the quick-" +"start example by overriding the :code:`evaluate()` method insides the " +":code:`XgbClient` class in :code:`client_utils.py`." +msgstr "" +"至于客户端上的分布式评估,与快速启动示例相同,通过覆盖 :code:`client.py` 中 :code:`XgbClient` 类内部的 " +":code:`evaluate()` 方法。" + +#: ../../source/tutorial-quickstart-xgboost.rst:831 +#, fuzzy +msgid "Flower simulation" +msgstr "运行模拟" + +#: ../../source/tutorial-quickstart-xgboost.rst:832 +msgid "" +"We also provide an example code (:code:`sim.py`) to use the simulation " +"capabilities of Flower to simulate federated XGBoost training on either a" +" single machine or a cluster of machines." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:866 +msgid "" +"After importing all required packages, we define a :code:`main()` " +"function to perform the simulation process:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:921 +msgid "" +"We first load the dataset and perform data partitioning, and the pre-" +"processed data is stored in a :code:`list`. After the simulation begins, " +"the clients won't need to pre-process their partitions again." +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:924 +msgid "Then, we define the strategies and other hyper-parameters:" msgstr "" -"此函数返回一个评估函数,该函数实例化一个 :code:`Booster` " -"对象,并向其加载全局模型参数。评估通过调用 :code:`eval_set()` 方法进行," -"并报告测试的 AUC 值。" -#: ../../source/tutorial-quickstart-xgboost.rst:669 +#: ../../source/tutorial-quickstart-xgboost.rst:975 msgid "" -"As for distributed evaluation on the clients, it's same as the quick-start " -"example by overriding the :code:`evaluate()` method insides the :code:" -"`XgbClient` class in :code:`client.py`." +"After that, we start the simulation by calling " +":code:`fl.simulation.start_simulation`:" msgstr "" -"至于客户端上的分布式评估,与快速启动示例相同,通过覆盖 :code:`client.py` 中 :" -"code:`XgbClient` 类内部的 :code:`evaluate()` 方法。" -#: ../../source/tutorial-quickstart-xgboost.rst:673 +#: ../../source/tutorial-quickstart-xgboost.rst:995 +msgid "" +"One of key parameters for :code:`start_simulation` is :code:`client_fn` " +"which returns a function to construct a client. We define it as follows:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1038 msgid "Arguments parser" msgstr "参数解析器" -#: ../../source/tutorial-quickstart-xgboost.rst:675 +#: ../../source/tutorial-quickstart-xgboost.rst:1040 +#, fuzzy msgid "" -"In :code:`utils.py`, we define the arguments parsers for clients and server, " -"allowing users to specify different experimental settings. Let's first see " -"the sever side:" -msgstr "" -"在 :code:`utils.py` 中,我们定义了客户端和服务器端的参数解析器,允许用户指定" -"不同的实验设置。让我们先看看服务器端:" +"In :code:`utils.py`, we define the arguments parsers for clients, server " +"and simulation, allowing users to specify different experimental " +"settings. Let's first see the sever side:" +msgstr "在 :code:`utils.py` 中,我们定义了客户端和服务器端的参数解析器,允许用户指定不同的实验设置。让我们先看看服务器端:" -#: ../../source/tutorial-quickstart-xgboost.rst:714 +#: ../../source/tutorial-quickstart-xgboost.rst:1086 +#, fuzzy msgid "" -"This allows user to specify the number of total clients / FL rounds / " -"participating clients / clients for evaluation, and evaluation fashion. Note " -"that with :code:`--centralised-eval`, the sever will do centralised " -"evaluation and all functionalities for client evaluation will be disabled." +"This allows user to specify training strategies / the number of total " +"clients / FL rounds / participating clients / clients for evaluation, and" +" evaluation fashion. Note that with :code:`--centralised-eval`, the sever" +" will do centralised evaluation and all functionalities for client " +"evaluation will be disabled." msgstr "" -"这允许用户指定总客户数/FL 轮数/参与客户数/评估客户数以及评估方式。请注意," -"如果使用 :code:`--centralised-" +"这允许用户指定总客户数/FL 轮数/参与客户数/评估客户数以及评估方式。请注意,如果使用 :code:`--centralised-" "eval`,服务器将进行集中评估,客户端评估的所有功能将被禁用。" -#: ../../source/tutorial-quickstart-xgboost.rst:718 +#: ../../source/tutorial-quickstart-xgboost.rst:1090 msgid "Then, the argument parser on client side:" msgstr "然后是客户端的参数解析器:" -#: ../../source/tutorial-quickstart-xgboost.rst:760 +#: ../../source/tutorial-quickstart-xgboost.rst:1144 +#, fuzzy msgid "" -"This defines various options for client data partitioning. Besides, clients " -"also have a option to conduct evaluation on centralised test set by setting :" -"code:`--centralised-eval`." +"This defines various options for client data partitioning. Besides, " +"clients also have an option to conduct evaluation on centralised test set" +" by setting :code:`--centralised-eval`, as well as an option to perform " +"scaled learning rate based on the number of clients by setting :code" +":`--scaled-lr`." +msgstr "这定义了客户端数据分区的各种选项。此外,通过设置 :code:`-centralised-eval`,客户端还可以选择在集中测试集上进行评估。" + +#: ../../source/tutorial-quickstart-xgboost.rst:1148 +msgid "We also have an argument parser for simulation:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1226 +msgid "This integrates all arguments for both client and server sides." msgstr "" -"这定义了客户端数据分区的各种选项。此外,通过设置 :code:`-centralised-eval`," -"客户端还可以选择在集中测试集上进行评估。" -#: ../../source/tutorial-quickstart-xgboost.rst:764 +#: ../../source/tutorial-quickstart-xgboost.rst:1229 msgid "Example commands" msgstr "命令示例" -#: ../../source/tutorial-quickstart-xgboost.rst:766 +#: ../../source/tutorial-quickstart-xgboost.rst:1231 +#, fuzzy msgid "" -"To run a centralised evaluated experiment on 5 clients with exponential " -"distribution for 50 rounds, we first start the server as below:" -msgstr "" -"为了在 5 个客户端上进行 50 轮指数分布的集中评估实验,我们首先启动服务器,如下" -"所示:" +"To run a centralised evaluated experiment with bagging strategy on 5 " +"clients with exponential distribution for 50 rounds, we first start the " +"server as below:" +msgstr "为了在 5 个客户端上进行 50 轮指数分布的集中评估实验,我们首先启动服务器,如下所示:" -#: ../../source/tutorial-quickstart-xgboost.rst:773 +#: ../../source/tutorial-quickstart-xgboost.rst:1238 msgid "Then, on each client terminal, we start the clients:" msgstr "然后,我们在每个客户终端上启动客户机:" -#: ../../source/tutorial-quickstart-xgboost.rst:779 +#: ../../source/tutorial-quickstart-xgboost.rst:1244 +msgid "To run the same experiment with Flower simulation:" +msgstr "" + +#: ../../source/tutorial-quickstart-xgboost.rst:1250 +#, fuzzy msgid "" -"The full `source code `_ for this comprehensive example can be found in :" -"code:`examples/xgboost-comprehensive`." +"The full `code `_ for this comprehensive example can be found in" +" :code:`examples/xgboost-comprehensive`." msgstr "" -"此综合示例的全部`源代码 `_ 可在 :code:`examples/xgboost-comprehensive` " -"中找到。" +"此综合示例的全部`源代码 `_ 可在 :code:`examples/xgboost-comprehensive` 中找到。" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:9 msgid "Build a strategy from scratch" @@ -14174,44 +18191,42 @@ msgstr "从零开始制定策略" msgid "" "Welcome to the third part of the Flower federated learning tutorial. In " "previous parts of this tutorial, we introduced federated learning with " -"PyTorch and Flower (`part 1 `__) and we learned how strategies can be " -"used to customize the execution on both the server and the clients (`part 2 " -"`__)." -msgstr "" -"欢迎来到 Flower 联邦学习教程的第三部分。在本教程的前几部分,我们介绍了 " -"PyTorch 和 Flower 的联邦学习(`part 1 `__),并学习了如何使用策略来定制服务器和客户端的执行(`part 2 " +"PyTorch and Flower (`part 1 `__) and we learned how strategies " +"can be used to customize the execution on both the server and the clients" +" (`part 2 `__)." +msgstr "" +"欢迎来到 Flower 联邦学习教程的第三部分。在本教程的前几部分,我们介绍了 PyTorch 和 Flower 的联邦学习(`part 1 " +"`__),并学习了如何使用策略来定制服务器和客户端的执行(`part 2 " "`__)。" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:13 msgid "" -"In this notebook, we'll continue to customize the federated learning system " -"we built previously by creating a custom version of FedAvg (again, using " -"`Flower `__ and `PyTorch `__)." +"In this notebook, we'll continue to customize the federated learning " +"system we built previously by creating a custom version of FedAvg (again," +" using `Flower `__ and `PyTorch " +"`__)." msgstr "" -"在本笔记中,我们将通过创建 FedAvg 的自定义版本(再次使用 `Flower " -"`__ 和 `PyTorch `__),继续定制我们之前构建的联邦学习系统。" +"在本笔记中,我们将通过创建 FedAvg 的自定义版本(再次使用 `Flower `__ 和 " +"`PyTorch `__),继续定制我们之前构建的联邦学习系统。" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:15 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:16 #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:15 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:15 msgid "" -"`Star Flower on GitHub `__ ⭐️ and join the " -"Flower community on Slack to connect, ask questions, and get help: `Join " -"Slack `__ 🌼 We'd love to hear from you in " -"the ``#introductions`` channel! And if anything is unclear, head over to the " -"``#questions`` channel." +"`Star Flower on GitHub `__ ⭐️ and join " +"the Flower community on Slack to connect, ask questions, and get help: " +"`Join Slack `__ 🌼 We'd love to hear from " +"you in the ``#introductions`` channel! And if anything is unclear, head " +"over to the ``#questions`` channel." msgstr "" -"`Star Flower on GitHub `__ ⭐️ 并加入 Slack 上" -"的 Flower 社区,进行交流、提问并获得帮助: 加入 Slack `__ 🌼 我们希望在 ``#introductions`` 频道听到您的声音!如果有任何" -"不清楚的地方,请访问 ``#questions`` 频道。" +"`Star Flower on GitHub `__ ⭐️ 并加入 Slack " +"上的 Flower 社区,进行交流、提问并获得帮助: 加入 Slack `__ 🌼 " +"我们希望在 ``#introductions`` 频道听到您的声音!如果有任何不清楚的地方,请访问 ``#questions`` 频道。" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:17 msgid "Let's build a new ``Strategy`` from scratch!" @@ -14254,23 +18269,21 @@ msgstr "现在我们已经安装了所有依赖项,可以导入本教程所需 #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:101 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:102 -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:104 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:101 msgid "" -"It is possible to switch to a runtime that has GPU acceleration enabled (on " -"Google Colab: ``Runtime > Change runtime type > Hardware acclerator: GPU > " -"Save``). Note, however, that Google Colab is not always able to offer GPU " -"acceleration. If you see an error related to GPU availability in one of the " -"following sections, consider switching back to CPU-based execution by " -"setting ``DEVICE = torch.device(\"cpu\")``. If the runtime has GPU " -"acceleration enabled, you should see the output ``Training on cuda``, " -"otherwise it'll say ``Training on cpu``." -msgstr "" -"可以切换到已启用 GPU 加速的运行时(在 Google Colab 上: 运行时 > 更改运行时类" -"型 > 硬件加速: GPU > 保存``)。但请注意,Google Colab 并非总能提供 GPU 加" -"速。如果在以下部分中看到与 GPU 可用性相关的错误,请考虑通过设置 ``DEVICE = " -"torch.device(\"cpu\")`` 切回基于 CPU 的执行。如果运行时已启用 GPU 加速,你应" -"该会看到输出``Training on cuda``,否则会显示``Training on cpu``。" +"It is possible to switch to a runtime that has GPU acceleration enabled " +"(on Google Colab: ``Runtime > Change runtime type > Hardware acclerator: " +"GPU > Save``). Note, however, that Google Colab is not always able to " +"offer GPU acceleration. If you see an error related to GPU availability " +"in one of the following sections, consider switching back to CPU-based " +"execution by setting ``DEVICE = torch.device(\"cpu\")``. If the runtime " +"has GPU acceleration enabled, you should see the output ``Training on " +"cuda``, otherwise it'll say ``Training on cpu``." +msgstr "" +"可以切换到已启用 GPU 加速的运行时(在 Google Colab 上: 运行时 > 更改运行时类型 > 硬件加速: GPU > " +"保存``)。但请注意,Google Colab 并非总能提供 GPU 加速。如果在以下部分中看到与 GPU 可用性相关的错误,请考虑通过设置 " +"``DEVICE = torch.device(\"cpu\")`` 切回基于 CPU 的执行。如果运行时已启用 GPU " +"加速,你应该会看到输出``Training on cuda``,否则会显示``Training on cpu``。" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:114 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:115 @@ -14281,16 +18294,15 @@ msgstr "数据加载" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:116 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:116 msgid "" -"Let's now load the CIFAR-10 training and test set, partition them into ten " -"smaller datasets (each split into training and validation set), and wrap " -"everything in their own ``DataLoader``. We introduce a new parameter " -"``num_clients`` which allows us to call ``load_datasets`` with different " -"numbers of clients." +"Let's now load the CIFAR-10 training and test set, partition them into " +"ten smaller datasets (each split into training and validation set), and " +"wrap everything in their own ``DataLoader``. We introduce a new parameter" +" ``num_clients`` which allows us to call ``load_datasets`` with different" +" numbers of clients." msgstr "" -"现在,让我们加载 CIFAR-10 训练集和测试集,将它们分割成 10 个较小的数据集(每" -"个数据集又分为训练集和验证集),并将所有数据都封装在各自的 ``DataLoader`` " -"中。我们引入了一个新参数 ``num_clients``,它允许我们使用不同数量的客户端调用 " -"``load_datasets``。" +"现在,让我们加载 CIFAR-10 训练集和测试集,将它们分割成 10 " +"个较小的数据集(每个数据集又分为训练集和验证集),并将所有数据都封装在各自的 ``DataLoader`` 中。我们引入了一个新参数 " +"``num_clients``,它允许我们使用不同数量的客户端调用 ``load_datasets``。" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:167 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:168 @@ -14302,11 +18314,9 @@ msgstr "模型培训/评估" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:170 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:169 msgid "" -"Let's continue with the usual model definition (including ``set_parameters`` " -"and ``get_parameters``), training and test functions:" -msgstr "" -"让我们继续使用常见的模型定义(包括 `set_parameters` 和 `get_parameters`)、训" -"练和测试函数:" +"Let's continue with the usual model definition (including " +"``set_parameters`` and ``get_parameters``), training and test functions:" +msgstr "让我们继续使用常见的模型定义(包括 `set_parameters` 和 `get_parameters`)、训练和测试函数:" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:258 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:258 @@ -14316,14 +18326,14 @@ msgstr "Flower 客户端" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:260 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:260 msgid "" -"To implement the Flower client, we (again) create a subclass of ``flwr." -"client.NumPyClient`` and implement the three methods ``get_parameters``, " -"``fit``, and ``evaluate``. Here, we also pass the ``cid`` to the client and " -"use it log additional details:" +"To implement the Flower client, we (again) create a subclass of " +"``flwr.client.NumPyClient`` and implement the three methods " +"``get_parameters``, ``fit``, and ``evaluate``. Here, we also pass the " +"``cid`` to the client and use it log additional details:" msgstr "" -"为了实现 Flower 客户端,我们(再次)创建了 ``flwr.client.NumPyClient`` 的子" -"类,并实现了 ``get_parameters``、``fit`` 和 ``evaluate``三个方法。在这里,我" -"们还将 ``cid`` 传递给客户端,并使用它记录其他详细信息:" +"为了实现 Flower 客户端,我们(再次)创建了 ``flwr.client.NumPyClient`` 的子类,并实现了 " +"``get_parameters``、``fit`` 和 ``evaluate``三个方法。在这里,我们还将 ``cid`` " +"传递给客户端,并使用它记录其他详细信息:" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:308 msgid "Let's test what we have so far before we continue:" @@ -14335,15 +18345,14 @@ msgstr "从零开始构建策略" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:341 msgid "" -"Let’s overwrite the ``configure_fit`` method such that it passes a higher " -"learning rate (potentially also other hyperparameters) to the optimizer of a " -"fraction of the clients. We will keep the sampling of the clients as it is " -"in ``FedAvg`` and then change the configuration dictionary (one of the " -"``FitIns`` attributes)." +"Let’s overwrite the ``configure_fit`` method such that it passes a higher" +" learning rate (potentially also other hyperparameters) to the optimizer " +"of a fraction of the clients. We will keep the sampling of the clients as" +" it is in ``FedAvg`` and then change the configuration dictionary (one of" +" the ``FitIns`` attributes)." msgstr "" -"让我们重写 ``configure_fit`` 方法,使其向一部分客户的优化器传递更高的学习率" -"(可能还有其他超参数)。我们将保持 ``FedAvg`` 中的客户端采样,然后更改配置字" -"典(``FitIns`` 属性之一)。" +"让我们重写 ``configure_fit`` 方法,使其向一部分客户的优化器传递更高的学习率(可能还有其他超参数)。我们将保持 " +"``FedAvg`` 中的客户端采样,然后更改配置字典(``FitIns`` 属性之一)。" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:507 msgid "" @@ -14359,52 +18368,50 @@ msgstr "回顾" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:536 msgid "" -"In this notebook, we’ve seen how to implement a custom strategy. A custom " -"strategy enables granular control over client node configuration, result " -"aggregation, and more. To define a custom strategy, you only have to " -"overwrite the abstract methods of the (abstract) base class ``Strategy``. To " -"make custom strategies even more powerful, you can pass custom functions to " -"the constructor of your new class (``__init__``) and then call these " -"functions whenever needed." +"In this notebook, we’ve seen how to implement a custom strategy. A custom" +" strategy enables granular control over client node configuration, result" +" aggregation, and more. To define a custom strategy, you only have to " +"overwrite the abstract methods of the (abstract) base class ``Strategy``." +" To make custom strategies even more powerful, you can pass custom " +"functions to the constructor of your new class (``__init__``) and then " +"call these functions whenever needed." msgstr "" -"在本笔记中,我们了解了如何实施自定义策略。自定义策略可以对客户端节点配置、结" -"果聚合等进行细粒度控制。要定义自定义策略,只需覆盖(抽象)基类 ``Strategy`` " -"的抽象方法即可。为使自定义策略更加强大,您可以将自定义函数传递给新类的构造函" -"数(`__init__``),然后在需要时调用这些函数。" +"在本笔记中,我们了解了如何实施自定义策略。自定义策略可以对客户端节点配置、结果聚合等进行细粒度控制。要定义自定义策略,只需覆盖(抽象)基类 " +"``Strategy`` " +"的抽象方法即可。为使自定义策略更加强大,您可以将自定义函数传递给新类的构造函数(`__init__``),然后在需要时调用这些函数。" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:550 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:948 -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:749 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:729 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:715 #: ../../source/tutorial-series-what-is-federated-learning.ipynb:369 msgid "" -"Before you continue, make sure to join the Flower community on Slack: `Join " -"Slack `__" +"Before you continue, make sure to join the Flower community on Slack: " +"`Join Slack `__" msgstr "" -"在继续之前,请务必加入 Slack 上的 Flower 社区:`Join Slack `__" +"在继续之前,请务必加入 Slack 上的 Flower 社区:`Join Slack `__" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:552 #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:950 -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:751 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:731 #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:717 #: ../../source/tutorial-series-what-is-federated-learning.ipynb:371 msgid "" -"There's a dedicated ``#questions`` channel if you need help, but we'd also " -"love to hear who you are in ``#introductions``!" -msgstr "" -"如果您需要帮助,我们有专门的 ``#questions`` 频道,但我们也很乐意在 " -"``#introductions`` 中了解您是谁!" +"There's a dedicated ``#questions`` channel if you need help, but we'd " +"also love to hear who you are in ``#introductions``!" +msgstr "如果您需要帮助,我们有专门的 ``#questions`` 频道,但我们也很乐意在 ``#introductions`` 中了解您是谁!" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:554 msgid "" -"The `Flower Federated Learning Tutorial - Part 4 `__ introduces " -"``Client``, the flexible API underlying ``NumPyClient``." +"The `Flower Federated Learning Tutorial - Part 4 " +"`__ introduces ``Client``, the flexible API underlying " +"``NumPyClient``." msgstr "" "Flower联邦学习教程 - 第4部分 `__ 介绍了``Client``,它是``NumPyClient``底" -"层的灵活应用程序接口。" +"customize-the-client-pytorch.html>`__ " +"介绍了``Client``,它是``NumPyClient``底层的灵活应用程序接口。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:9 msgid "Customize the client" @@ -14412,39 +18419,37 @@ msgstr "自定义客户端" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:11 msgid "" -"Welcome to the fourth part of the Flower federated learning tutorial. In the " -"previous parts of this tutorial, we introduced federated learning with " -"PyTorch and Flower (`part 1 `__), we learned how strategies can be used " -"to customize the execution on both the server and the clients (`part 2 " +"Welcome to the fourth part of the Flower federated learning tutorial. In " +"the previous parts of this tutorial, we introduced federated learning " +"with PyTorch and Flower (`part 1 `__), we learned how " +"strategies can be used to customize the execution on both the server and " +"the clients (`part 2 `__), and we built our own " +"custom strategy from scratch (`part 3 `__)." +msgstr "" +"欢迎来到 Flower 联邦学习教程的第四部分。在本教程的前几部分中,我们介绍了 PyTorch 和 Flower 的联邦学习(`part 1 " +"`__),了解了如何使用策略来定制服务器和客户端的执行(`part 2 " "`__), and we built our own custom strategy from " -"scratch (`part 3 `__)." -msgstr "" -"欢迎来到 Flower 联邦学习教程的第四部分。在本教程的前几部分中,我们介绍了 " -"PyTorch 和 Flower 的联邦学习(`part 1 `__),了解了如何使用策略来定制" -"服务器和客户端的执行(`part 2 `__),并从头开始构建了我们自" -"己的定制策略(`part 3 `__)。" +"strategy-pytorch.html>`__),并从头开始构建了我们自己的定制策略(`part 3 " +"`__)。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:14 msgid "" -"In this notebook, we revisit ``NumPyClient`` and introduce a new baseclass " -"for building clients, simply named ``Client``. In previous parts of this " -"tutorial, we've based our client on ``NumPyClient``, a convenience class " -"which makes it easy to work with machine learning libraries that have good " -"NumPy interoperability. With ``Client``, we gain a lot of flexibility that " -"we didn't have before, but we'll also have to do a few things the we didn't " -"have to do before." +"In this notebook, we revisit ``NumPyClient`` and introduce a new " +"baseclass for building clients, simply named ``Client``. In previous " +"parts of this tutorial, we've based our client on ``NumPyClient``, a " +"convenience class which makes it easy to work with machine learning " +"libraries that have good NumPy interoperability. With ``Client``, we gain" +" a lot of flexibility that we didn't have before, but we'll also have to " +"do a few things the we didn't have to do before." msgstr "" -"在本笔记中,我们将重温 ``NumPyClient`` 并引入一个用于构建客户端的新基类," -"简单命名为 ``Client``。在本教程的前几部分中,我们的客户端基于``NumPyClient``" -",这是一个便捷类,可以让我们轻松地与具有良好 NumPy " -"互操作性的机器学习库协同工作。有了 ``Client``,我们获得了很多以前没有的灵活性" -",但我们也必须做一些以前不需要做的事情。" +"在本笔记中,我们将重温 ``NumPyClient`` 并引入一个用于构建客户端的新基类,简单命名为 " +"``Client``。在本教程的前几部分中,我们的客户端基于``NumPyClient``,这是一个便捷类,可以让我们轻松地与具有良好 NumPy" +" 互操作性的机器学习库协同工作。有了 ``Client``,我们获得了很多以前没有的灵活性,但我们也必须做一些以前不需要做的事情。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:18 msgid "" @@ -14459,12 +18464,12 @@ msgstr "步骤 0:准备工作" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:117 msgid "" -"Let's now load the CIFAR-10 training and test set, partition them into ten " -"smaller datasets (each split into training and validation set), and wrap " -"everything in their own ``DataLoader``." +"Let's now load the CIFAR-10 training and test set, partition them into " +"ten smaller datasets (each split into training and validation set), and " +"wrap everything in their own ``DataLoader``." msgstr "" -"现在,让我们加载 CIFAR-10 训练集和测试集,将它们分割成十个较小的数据集(每个" -"数据集又分为训练集和验证集),并将所有数据都封装在各自的 ``DataLoader`` 中。" +"现在,让我们加载 CIFAR-10 训练集和测试集,将它们分割成十个较小的数据集(每个数据集又分为训练集和验证集),并将所有数据都封装在各自的 " +"``DataLoader`` 中。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:259 msgid "Step 1: Revisiting NumPyClient" @@ -14472,14 +18477,14 @@ msgstr "步骤 1:重温 NumPyClient" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:261 msgid "" -"So far, we've implemented our client by subclassing ``flwr.client." -"NumPyClient``. The three methods we implemented are ``get_parameters``, " -"``fit``, and ``evaluate``. Finally, we wrap the creation of instances of " -"this class in a function called ``client_fn``:" +"So far, we've implemented our client by subclassing " +"``flwr.client.NumPyClient``. The three methods we implemented are " +"``get_parameters``, ``fit``, and ``evaluate``. Finally, we wrap the " +"creation of instances of this class in a function called ``client_fn``:" msgstr "" -"到目前为止,我们通过子类化 ``flwr.client.NumPyClient`` 实现了我们的客户端。我" -"们实现了三个方法:``get_parameters``, ``fit`, 和``evaluate``。最后,我们用一" -"个名为 ``client_fn`` 的函数来创建该类的实例:" +"到目前为止,我们通过子类化 ``flwr.client.NumPyClient`` " +"实现了我们的客户端。我们实现了三个方法:``get_parameters``, ``fit`, 和``evaluate``。最后,我们用一个名为 " +"``client_fn`` 的函数来创建该类的实例:" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:309 msgid "" @@ -14488,9 +18493,8 @@ msgid "" "``FlowerClient`` to ``FlowerNumPyClient`` and ``client_fn`` to " "``numpyclient_fn``. Let's run it to see the output we get:" msgstr "" -"我们以前见过这种情况,目前没有什么新东西。与之前的笔记相比,唯一*小*的不同是" -"命名,我们把 ``FlowerClient`` 改成了 ``FlowerNumPyClient``,把 `client_fn` " -"改成了 ``numpyclient_fn``。让我们运行它看看输出结果:" +"我们以前见过这种情况,目前没有什么新东西。与之前的笔记相比,唯一*小*的不同是命名,我们把 ``FlowerClient`` 改成了 " +"``FlowerNumPyClient``,把 `client_fn` 改成了 ``numpyclient_fn``。让我们运行它看看输出结果:" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:339 msgid "" @@ -14503,32 +18507,32 @@ msgid "" "Let's dive a little bit deeper and discuss how Flower executes this " "simulation. Whenever a client is selected to do some work, " "``start_simulation`` calls the function ``numpyclient_fn`` to create an " -"instance of our ``FlowerNumPyClient`` (along with loading the model and the " -"data)." +"instance of our ``FlowerNumPyClient`` (along with loading the model and " +"the data)." msgstr "" -"让我们再深入一点,讨论一下 Flower 是如何执行模拟的。每当一个客户端被选中进行" -"工作时,`start_simulation`` 就会调用函数 `numpyclient_fn` 来创建我们的 " -"``FlowerNumPyClient`` 实例(同时加载模型和数据)。" +"让我们再深入一点,讨论一下 Flower 是如何执行模拟的。每当一个客户端被选中进行工作时,`start_simulation`` 就会调用函数 " +"`numpyclient_fn` 来创建我们的 ``FlowerNumPyClient`` 实例(同时加载模型和数据)。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:343 msgid "" "But here's the perhaps surprising part: Flower doesn't actually use the " -"``FlowerNumPyClient`` object directly. Instead, it wraps the object to makes " -"it look like a subclass of ``flwr.client.Client``, not ``flwr.client." -"NumPyClient``. In fact, the Flower core framework doesn't know how to handle " -"``NumPyClient``'s, it only knows how to handle ``Client``'s. ``NumPyClient`` " -"is just a convenience abstraction built on top of ``Client``." -msgstr "" -"但令人惊讶的部分也许就在这里: Flower 实际上并不直接使用 " -"``FlowerNumPyClient`` 对象。相反,它封装了该对象,使其看起来像 ``flwr.client." -"Client`` 的子类,而不是 ``flwr.client.NumPyClient``。事实上,Flower " -"核心框架不知道如何处理 ``NumPyClient``,它只知道如何处理 " -"``Client``。``NumPyClient`` 只是建立在``Client``之上的便捷抽象类。" +"``FlowerNumPyClient`` object directly. Instead, it wraps the object to " +"makes it look like a subclass of ``flwr.client.Client``, not " +"``flwr.client.NumPyClient``. In fact, the Flower core framework doesn't " +"know how to handle ``NumPyClient``'s, it only knows how to handle " +"``Client``'s. ``NumPyClient`` is just a convenience abstraction built on " +"top of ``Client``." +msgstr "" +"但令人惊讶的部分也许就在这里: Flower 实际上并不直接使用 ``FlowerNumPyClient`` " +"对象。相反,它封装了该对象,使其看起来像 ``flwr.client.Client`` 的子类,而不是 " +"``flwr.client.NumPyClient``。事实上,Flower 核心框架不知道如何处理 " +"``NumPyClient``,它只知道如何处理 ``Client``。``NumPyClient`` " +"只是建立在``Client``之上的便捷抽象类。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:345 msgid "" -"Instead of building on top of ``NumPyClient``, we can directly build on top " -"of ``Client``." +"Instead of building on top of ``NumPyClient``, we can directly build on " +"top of ``Client``." msgstr "与其在 ``NumPyClient`` 上构建,我们可以直接在 ``Client`` 上构建。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:357 @@ -14537,81 +18541,70 @@ msgstr "步骤 2:从 ``NumPyClient`` 移至 ``Client``" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:359 msgid "" -"Let's try to do the same thing using ``Client`` instead of ``NumPyClient``." +"Let's try to do the same thing using ``Client`` instead of " +"``NumPyClient``." msgstr "让我们尝试使用 ``Client`` 代替 ``NumPyClient`` 做同样的事情。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:465 msgid "" -"Before we discuss the code in more detail, let's try to run it! Gotta make " -"sure our new ``Client``-based client works, right?" -msgstr "" -"在详细讨论代码之前,让我们试着运行它!必须确保我们基于 ``Client`` 的新客户端" -"能正常运行,对吗?" +"Before we discuss the code in more detail, let's try to run it! Gotta " +"make sure our new ``Client``-based client works, right?" +msgstr "在详细讨论代码之前,让我们试着运行它!必须确保我们基于 ``Client`` 的新客户端能正常运行,对吗?" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:490 msgid "" "That's it, we're now using ``Client``. It probably looks similar to what " "we've done with ``NumPyClient``. So what's the difference?" -msgstr "" -"就是这样,我们现在开始使用 ``Client``。它看起来可能与我们使用 " -"``NumPyClient`` 所做的类似。那么有什么不同呢?" +msgstr "就是这样,我们现在开始使用 ``Client``。它看起来可能与我们使用 ``NumPyClient`` 所做的类似。那么有什么不同呢?" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:492 msgid "" -"First of all, it's more code. But why? The difference comes from the fact " -"that ``Client`` expects us to take care of parameter serialization and " -"deserialization. For Flower to be able to send parameters over the network, " -"it eventually needs to turn these parameters into ``bytes``. Turning " -"parameters (e.g., NumPy ``ndarray``'s) into raw bytes is called " +"First of all, it's more code. But why? The difference comes from the fact" +" that ``Client`` expects us to take care of parameter serialization and " +"deserialization. For Flower to be able to send parameters over the " +"network, it eventually needs to turn these parameters into ``bytes``. " +"Turning parameters (e.g., NumPy ``ndarray``'s) into raw bytes is called " "serialization. Turning raw bytes into something more useful (like NumPy " -"``ndarray``'s) is called deserialization. Flower needs to do both: it needs " -"to serialize parameters on the server-side and send them to the client, the " -"client needs to deserialize them to use them for local training, and then " -"serialize the updated parameters again to send them back to the server, " -"which (finally!) deserializes them again in order to aggregate them with the " -"updates received from other clients." -msgstr "" -"首先,它的代码更多。但为什么呢?区别在于 ``Client`` " -"希望我们处理参数的序列化和反序列化。Flower 要想通过网络发送参数," -"最终需要将这些参数转化为 ``字节``。把参数(例如 NumPy 的 ``ndarray`` " -"参数)变成原始字节叫做序列化。将原始字节转换成更有用的东西(如 NumPy " -"``ndarray`)称为反序列化。Flower 需要同时做这两件事:它需要在服务器端序列化参" -"数并将其发送到客户端,客户端需要反序列化参数以便将其用于本地训练,然后再次序" -"列化更新后的参数并将其发送回服务器,服务器(最后)再次反序列化参数以便将其与" -"从其他客户端接收到的更新汇总在一起。" +"``ndarray``'s) is called deserialization. Flower needs to do both: it " +"needs to serialize parameters on the server-side and send them to the " +"client, the client needs to deserialize them to use them for local " +"training, and then serialize the updated parameters again to send them " +"back to the server, which (finally!) deserializes them again in order to " +"aggregate them with the updates received from other clients." +msgstr "" +"首先,它的代码更多。但为什么呢?区别在于 ``Client`` 希望我们处理参数的序列化和反序列化。Flower " +"要想通过网络发送参数,最终需要将这些参数转化为 ``字节``。把参数(例如 NumPy 的 ``ndarray`` " +"参数)变成原始字节叫做序列化。将原始字节转换成更有用的东西(如 NumPy ``ndarray`)称为反序列化。Flower " +"需要同时做这两件事:它需要在服务器端序列化参数并将其发送到客户端,客户端需要反序列化参数以便将其用于本地训练,然后再次序列化更新后的参数并将其发送回服务器,服务器(最后)再次反序列化参数以便将其与从其他客户端接收到的更新汇总在一起。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:495 msgid "" "The only *real* difference between Client and NumPyClient is that " -"NumPyClient takes care of serialization and deserialization for you. It can " -"do so because it expects you to return parameters as NumPy ndarray's, and it " -"knows how to handle these. This makes working with machine learning " -"libraries that have good NumPy support (most of them) a breeze." +"NumPyClient takes care of serialization and deserialization for you. It " +"can do so because it expects you to return parameters as NumPy ndarray's," +" and it knows how to handle these. This makes working with machine " +"learning libraries that have good NumPy support (most of them) a breeze." msgstr "" "Client 与 NumPyClient 之间的唯一**真正区别在于,NumPyClient " -"会为你处理序列化和反序列化。NumPyClient之所以能做到这一点," -"是因为它预计你会以NumPy ndarray的形式返回参数,而且它知道如何处理这些参数。" -"这使得与具有良好 NumPy 支持的大多数机器学习库一起工作变得轻而易举。" +"会为你处理序列化和反序列化。NumPyClient之所以能做到这一点,是因为它预计你会以NumPy " +"ndarray的形式返回参数,而且它知道如何处理这些参数。这使得与具有良好 NumPy 支持的大多数机器学习库一起工作变得轻而易举。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:497 msgid "" -"In terms of API, there's one major difference: all methods in Client take " -"exactly one argument (e.g., ``FitIns`` in ``Client.fit``) and return exactly " -"one value (e.g., ``FitRes`` in ``Client.fit``). The methods in " +"In terms of API, there's one major difference: all methods in Client take" +" exactly one argument (e.g., ``FitIns`` in ``Client.fit``) and return " +"exactly one value (e.g., ``FitRes`` in ``Client.fit``). The methods in " "``NumPyClient`` on the other hand have multiple arguments (e.g., " -"``parameters`` and ``config`` in ``NumPyClient.fit``) and multiple return " -"values (e.g., ``parameters``, ``num_example``, and ``metrics`` in " -"``NumPyClient.fit``) if there are multiple things to handle. These ``*Ins`` " -"and ``*Res`` objects in ``Client`` wrap all the individual values you're " -"used to from ``NumPyClient``." -msgstr "" -"在 API 方面,有一个主要区别:Client 中的所有方法都只接受一个参数(例如," -"``Client.fit`` 中的 ``FitIns``),并只返回一个值(例如,``Client.fit`` 中的 " -"``FitRes``)。另一方面,``NumPyClient``中的方法有多个参数(例如," -"``NumPyClient.fit``中的``parameters``和``config``)和多个返回值(例如," -"``NumPyClient.fit``中的``parameters``、``num_example``和``metrics``)。在 " -"``Client`` 中的这些 ``*Ins`` 和 ``*Res`` 对象封装了你在 ``NumPyClient`` 中习" -"惯使用的所有单个值。" +"``parameters`` and ``config`` in ``NumPyClient.fit``) and multiple return" +" values (e.g., ``parameters``, ``num_example``, and ``metrics`` in " +"``NumPyClient.fit``) if there are multiple things to handle. These " +"``*Ins`` and ``*Res`` objects in ``Client`` wrap all the individual " +"values you're used to from ``NumPyClient``." +msgstr "" +"在 API 方面,有一个主要区别:Client 中的所有方法都只接受一个参数(例如,``Client.fit`` 中的 " +"``FitIns``),并只返回一个值(例如,``Client.fit`` 中的 " +"``FitRes``)。另一方面,``NumPyClient``中的方法有多个参数(例如,``NumPyClient.fit``中的``parameters``和``config``)和多个返回值(例如,``NumPyClient.fit``中的``parameters``、``num_example``和``metrics``)。在" +" ``Client`` 中的这些 ``*Ins`` 和 ``*Res`` 对象封装了你在 ``NumPyClient`` 中习惯使用的所有单个值。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:510 msgid "Step 3: Custom serialization" @@ -14627,21 +18620,20 @@ msgstr "下面我们将通过一个简单的示例来探讨如何实现自定义 msgid "" "But first what is serialization? Serialization is just the process of " "converting an object into raw bytes, and equally as important, " -"deserialization is the process of converting raw bytes back into an object. " -"This is very useful for network communication. Indeed, without " +"deserialization is the process of converting raw bytes back into an " +"object. This is very useful for network communication. Indeed, without " "serialization, you could not just a Python object through the internet." msgstr "" -"首先,什么是序列化?序列化只是将对象转换为原始字节的过程,同样重要的是,反序" -"列化是将原始字节转换回对象的过程。这对网络通信非常有用。事实上,如果没有序列" -"化,你就无法通过互联网传输一个 Python 对象。" +"首先,什么是序列化?序列化只是将对象转换为原始字节的过程,同样重要的是,反序列化是将原始字节转换回对象的过程。这对网络通信非常有用。事实上,如果没有序列化,你就无法通过互联网传输一个" +" Python 对象。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:516 msgid "" -"Federated Learning relies heavily on internet communication for training by " -"sending Python objects back and forth between the clients and the server. " -"This means that serialization is an essential part of Federated Learning." -msgstr "通过在客户端和服务器之间来回发送 Python 对象,联合学习在很大程度上依赖于互联" -"网通信进行训练。这意味着序列化是联邦学习的重要组成部分。" +"Federated Learning relies heavily on internet communication for training " +"by sending Python objects back and forth between the clients and the " +"server. This means that serialization is an essential part of Federated " +"Learning." +msgstr "通过在客户端和服务器之间来回发送 Python 对象,联合学习在很大程度上依赖于互联网通信进行训练。这意味着序列化是联邦学习的重要组成部分。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:518 msgid "" @@ -14653,9 +18645,8 @@ msgid "" "entries), converting them to a sparse matrix can greatly improve their " "bytesize." msgstr "" -"在下面的章节中,我们将编写一个基本示例,在发送包含参数的 ``ndarray`` 前," -"我们将首先把 ``ndarray`` 转换为稀疏矩阵,而不是发送序列化版本。这种技术可以用" -"来节省带宽,因为在某些情况下,模型的参数是稀疏的(包含许多 0 " +"在下面的章节中,我们将编写一个基本示例,在发送包含参数的 ``ndarray`` 前,我们将首先把 ``ndarray`` " +"转换为稀疏矩阵,而不是发送序列化版本。这种技术可以用来节省带宽,因为在某些情况下,模型的参数是稀疏的(包含许多 0 " "条目),将它们转换成稀疏矩阵可以大大提高它们的字节数。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:521 @@ -14664,18 +18655,17 @@ msgstr "我们的定制序列化/反序列化功能" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:523 msgid "" -"This is where the real serialization/deserialization will happen, especially " -"in ``ndarray_to_sparse_bytes`` for serialization and " +"This is where the real serialization/deserialization will happen, " +"especially in ``ndarray_to_sparse_bytes`` for serialization and " "``sparse_bytes_to_ndarray`` for deserialization." msgstr "" -"这才是真正的序列化/反序列化,尤其是在用于序列化的 " -"``ndarray_too_sparse_bytes`` 和用于反序列化的 ``sparse_bytes_too_ndarray`` " -"中。" +"这才是真正的序列化/反序列化,尤其是在用于序列化的 ``ndarray_too_sparse_bytes`` 和用于反序列化的 " +"``sparse_bytes_too_ndarray`` 中。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:525 msgid "" -"Note that we imported the ``scipy.sparse`` library in order to convert our " -"arrays." +"Note that we imported the ``scipy.sparse`` library in order to convert " +"our arrays." msgstr "请注意,为了转换数组,我们导入了 ``scipy.sparse`` 库。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:613 @@ -14684,34 +18674,34 @@ msgstr "客户端" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:615 msgid "" -"To be able to able to serialize our ``ndarray``\\ s into sparse parameters, " -"we will just have to call our custom functions in our ``flwr.client.Client``." -msgstr "为了能够将我们的 ``ndarray`` 序列化为稀疏参数,我们只需在 ``flwr.client." -"Client`` 中调用我们的自定义函数。" +"To be able to able to serialize our ``ndarray``\\ s into sparse " +"parameters, we will just have to call our custom functions in our " +"``flwr.client.Client``." +msgstr "为了能够将我们的 ``ndarray`` 序列化为稀疏参数,我们只需在 ``flwr.client.Client`` 中调用我们的自定义函数。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:617 msgid "" "Indeed, in ``get_parameters`` we need to serialize the parameters we got " -"from our network using our custom ``ndarrays_to_sparse_parameters`` defined " -"above." +"from our network using our custom ``ndarrays_to_sparse_parameters`` " +"defined above." msgstr "" -"事实上,在 `get_parameters` 中,我们需要使用上文定义的自定义 " -"`ndarrays_too_sparse_parameters` 序列化从网络中获取的参数。" +"事实上,在 `get_parameters` 中,我们需要使用上文定义的自定义 `ndarrays_too_sparse_parameters` " +"序列化从网络中获取的参数。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:619 msgid "" "In ``fit``, we first need to deserialize the parameters coming from the " -"server using our custom ``sparse_parameters_to_ndarrays`` and then we need " -"to serialize our local results with ``ndarrays_to_sparse_parameters``." +"server using our custom ``sparse_parameters_to_ndarrays`` and then we " +"need to serialize our local results with " +"``ndarrays_to_sparse_parameters``." msgstr "" "在 ``fit`` 中,我们首先需要使用自定义的 ``sparse_parameters_to_ndarrays`` " -"反序列化来自服务器的参数,然后使用 ``ndarrays_to_sparse_parameters`` " -"序列化本地结果。" +"反序列化来自服务器的参数,然后使用 ``ndarrays_to_sparse_parameters`` 序列化本地结果。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:621 msgid "" -"In ``evaluate``, we will only need to deserialize the global parameters with " -"our custom function." +"In ``evaluate``, we will only need to deserialize the global parameters " +"with our custom function." msgstr "在 ``evaluate`` 中,我们只需要用自定义函数反序列化全局参数。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:725 @@ -14720,14 +18710,14 @@ msgstr "服务器端" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:727 msgid "" -"For this example, we will just use ``FedAvg`` as a strategy. To change the " -"serialization and deserialization here, we only need to reimplement the " -"``evaluate`` and ``aggregate_fit`` functions of ``FedAvg``. The other " -"functions of the strategy will be inherited from the super class ``FedAvg``." +"For this example, we will just use ``FedAvg`` as a strategy. To change " +"the serialization and deserialization here, we only need to reimplement " +"the ``evaluate`` and ``aggregate_fit`` functions of ``FedAvg``. The other" +" functions of the strategy will be inherited from the super class " +"``FedAvg``." msgstr "" -"在本例中,我们将只使用 ``FedAvg`` 作为策略。要改变这里的序列化和反序列化,我" -"们只需重新实现 ``FedAvg`` 的 ``evaluate`` 和 ``aggregate_fit`` 函数。策略的其" -"他函数将从超类 ``FedAvg`` 继承。" +"在本例中,我们将只使用 ``FedAvg`` 作为策略。要改变这里的序列化和反序列化,我们只需重新实现 ``FedAvg`` 的 " +"``evaluate`` 和 ``aggregate_fit`` 函数。策略的其他函数将从超类 ``FedAvg`` 继承。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:729 msgid "As you can see only one line as change in ``evaluate``:" @@ -14751,26 +18741,22 @@ msgstr "现在我们可以运行自定义序列化示例!" msgid "" "In this part of the tutorial, we've seen how we can build clients by " "subclassing either ``NumPyClient`` or ``Client``. ``NumPyClient`` is a " -"convenience abstraction that makes it easier to work with machine learning " -"libraries that have good NumPy interoperability. ``Client`` is a more " -"flexible abstraction that allows us to do things that are not possible in " -"``NumPyClient``. In order to do so, it requires us to handle parameter " -"serialization and deserialization ourselves." -msgstr "" -"在本部分教程中,我们已经了解了如何通过子类化 ``NumPyClient`` 或 ``Client`` " -"来构建客户端。NumPyClient \"是一个便捷的抽象类,可以让我们更容易地与具有良好N" -"umPy互操作性的机器学习库一起工作。``Client``是一个更灵活的抽象类,允许我们做" -"一些在`NumPyClient``中做不到的事情。为此,它要求我们自己处理参数序列化和反序" -"列化。" +"convenience abstraction that makes it easier to work with machine " +"learning libraries that have good NumPy interoperability. ``Client`` is a" +" more flexible abstraction that allows us to do things that are not " +"possible in ``NumPyClient``. In order to do so, it requires us to handle " +"parameter serialization and deserialization ourselves." +msgstr "" +"在本部分教程中,我们已经了解了如何通过子类化 ``NumPyClient`` 或 ``Client`` 来构建客户端。NumPyClient " +"\"是一个便捷的抽象类,可以让我们更容易地与具有良好NumPy互操作性的机器学习库一起工作。``Client``是一个更灵活的抽象类,允许我们做一些在`NumPyClient``中做不到的事情。为此,它要求我们自己处理参数序列化和反序列化。" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:952 msgid "" -"This is the final part of the Flower tutorial (for now!), congratulations! " -"You're now well equipped to understand the rest of the documentation. There " -"are many topics we didn't cover in the tutorial, we recommend the following " -"resources:" -msgstr "这暂时是 Flower 教程的最后一部分,恭喜您!您现在已经具备了理解其余文档的能力" -"。本教程还有许多内容没有涉及,我们推荐您参考以下资源:" +"This is the final part of the Flower tutorial (for now!), " +"congratulations! You're now well equipped to understand the rest of the " +"documentation. There are many topics we didn't cover in the tutorial, we " +"recommend the following resources:" +msgstr "这暂时是 Flower 教程的最后一部分,恭喜您!您现在已经具备了理解其余文档的能力。本教程还有许多内容没有涉及,我们推荐您参考以下资源:" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:954 msgid "`Read Flower Docs `__" @@ -14778,23 +18764,21 @@ msgstr "阅读Flower文档 `__" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:955 msgid "" -"`Check out Flower Code Examples `__" -msgstr "" -"查看 Flower 代码示例 `__" +"`Check out Flower Code Examples " +"`__" +msgstr "查看 Flower 代码示例 `__" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:956 msgid "" -"`Use Flower Baselines for your research `__" +"`Use Flower Baselines for your research " +"`__" msgstr "使用 \"Flower Baselines \"进行研究 `__" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:957 msgid "" -"`Watch Flower Summit 2023 videos `__" -msgstr "" -"观看 2023 年Flower峰会视频 `__" +"`Watch Flower Summit 2023 videos `__" +msgstr "观看 2023 年Flower峰会视频 `__" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:9 msgid "Get started with Flower" @@ -14806,15 +18790,16 @@ msgid "Welcome to the Flower federated learning tutorial!" msgstr "欢迎阅读Flower联邦学习教程!" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:13 +#, fuzzy msgid "" -"In this notebook, we'll build a federated learning system using Flower and " -"PyTorch. In part 1, we use PyTorch for the model training pipeline and data " -"loading. In part 2, we continue to federate the PyTorch-based pipeline using " +"In this notebook, we'll build a federated learning system using Flower, " +"`Flower Datasets `__ and PyTorch. In " +"part 1, we use PyTorch for the model training pipeline and data loading. " +"In part 2, we continue to federate the PyTorch-based pipeline using " "Flower." msgstr "" -"在本笔记中,我们将使用 Flower 和 PyTorch 构建一个联邦学习系统。在第一部分中," -"我们使用 PyTorch 进行模型训练和数据加载。在第二部分中,我们将继续使用 Flower " -"联邦化基于 PyTorch 的框架。" +"在本笔记中,我们将使用 Flower 和 PyTorch 构建一个联邦学习系统。在第一部分中,我们使用 PyTorch " +"进行模型训练和数据加载。在第二部分中,我们将继续使用 Flower 联邦化基于 PyTorch 的框架。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:17 msgid "Let's get stated!" @@ -14827,537 +18812,511 @@ msgid "" msgstr "在开始编写实际代码之前,让我们先确保我们已经准备好了所需的一切。" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:45 +#, fuzzy msgid "" "Next, we install the necessary packages for PyTorch (``torch`` and " -"``torchvision``) and Flower (``flwr``):" -msgstr "" -"接下来,我们为 PyTorch(`torch`` 和`torchvision``)和 Flower(`flwr`)安装必" -"要的软件包:" - -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:117 +"``torchvision``), Flower Datasets (``flwr-datasets``) and Flower " +"(``flwr``):" +msgstr "接下来,我们为 PyTorch(`torch`` 和`torchvision``)和 Flower(`flwr`)安装必要的软件包:" + +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:105 +#, fuzzy +msgid "" +"It is possible to switch to a runtime that has GPU acceleration enabled " +"(on Google Colab: ``Runtime > Change runtime type > Hardware accelerator:" +" GPU > Save``). Note, however, that Google Colab is not always able to " +"offer GPU acceleration. If you see an error related to GPU availability " +"in one of the following sections, consider switching back to CPU-based " +"execution by setting ``DEVICE = torch.device(\"cpu\")``. If the runtime " +"has GPU acceleration enabled, you should see the output ``Training on " +"cuda``, otherwise it'll say ``Training on cpu``." +msgstr "" +"可以切换到已启用 GPU 加速的运行时(在 Google Colab 上: 运行时 > 更改运行时类型 > 硬件加速: GPU > " +"保存``)。但请注意,Google Colab 并非总能提供 GPU 加速。如果在以下部分中看到与 GPU 可用性相关的错误,请考虑通过设置 " +"``DEVICE = torch.device(\"cpu\")`` 切回基于 CPU 的执行。如果运行时已启用 GPU " +"加速,你应该会看到输出``Training on cuda``,否则会显示``Training on cpu``。" + +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:118 msgid "Loading the data" msgstr "加载数据" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:119 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:120 +#, fuzzy msgid "" -"Federated learning can be applied to many different types of tasks across " -"different domains. In this tutorial, we introduce federated learning by " -"training a simple convolutional neural network (CNN) on the popular CIFAR-10 " -"dataset. CIFAR-10 can be used to train image classifiers that distinguish " -"between images from ten different classes:" +"Federated learning can be applied to many different types of tasks across" +" different domains. In this tutorial, we introduce federated learning by " +"training a simple convolutional neural network (CNN) on the popular " +"CIFAR-10 dataset. CIFAR-10 can be used to train image classifiers that " +"distinguish between images from ten different classes: 'airplane', " +"'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', and " +"'truck'." msgstr "" -"联邦学习可应用于不同领域的多种不同类型任务。在本教程中,我们将通过在流行的 " -"CIFAR-10 数据集上训练一个简单的卷积神经网络 (CNN) 来介绍联合学习。CIFAR-10 可" -"用于训练图像分类器,以区分来自十个不同类别的图像:" +"联邦学习可应用于不同领域的多种不同类型任务。在本教程中,我们将通过在流行的 CIFAR-10 数据集上训练一个简单的卷积神经网络 (CNN) " +"来介绍联合学习。CIFAR-10 可用于训练图像分类器,以区分来自十个不同类别的图像:" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:150 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:131 msgid "" "We simulate having multiple datasets from multiple organizations (also " -"called the \"cross-silo\" setting in federated learning) by splitting the " -"original CIFAR-10 dataset into multiple partitions. Each partition will " -"represent the data from a single organization. We're doing this purely for " -"experimentation purposes, in the real world there's no need for data " -"splitting because each organization already has their own data (so the data " -"is naturally partitioned)." +"called the \"cross-silo\" setting in federated learning) by splitting the" +" original CIFAR-10 dataset into multiple partitions. Each partition will " +"represent the data from a single organization. We're doing this purely " +"for experimentation purposes, in the real world there's no need for data " +"splitting because each organization already has their own data (so the " +"data is naturally partitioned)." msgstr "" -"我们通过将原始 CIFAR-10 数据集拆分成多个分区来模拟来自多个组织的多个数据集(" -"也称为联邦学习中的 \"跨分区 \"设置)。每个分区代表一个组织的数据。我们这样做" -"纯粹是为了实验目的,在现实世界中不需要拆分数据,因为每个组织都已经有了自己的" -"数据(所以数据是自然分区的)。" +"我们通过将原始 CIFAR-10 数据集拆分成多个分区来模拟来自多个组织的多个数据集(也称为联邦学习中的 \"跨分区 " +"\"设置)。每个分区代表一个组织的数据。我们这样做纯粹是为了实验目的,在现实世界中不需要拆分数据,因为每个组织都已经有了自己的数据(所以数据是自然分区的)。" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:152 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:133 +#, fuzzy msgid "" -"Each organization will act as a client in the federated learning system. So " -"having ten organizations participate in a federation means having ten " -"clients connected to the federated learning server:" -msgstr "每个组织都将充当联邦学习系统中的客户端。因此,有十个组织参与联邦学习,就意味" -"着有十个客户端连接到联邦学习服务器:" +"Each organization will act as a client in the federated learning system. " +"So having ten organizations participate in a federation means having ten " +"clients connected to the federated learning server." +msgstr "每个组织都将充当联邦学习系统中的客户端。因此,有十个组织参与联邦学习,就意味着有十个客户端连接到联邦学习服务器:" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:172 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:144 msgid "" -"Let's now load the CIFAR-10 training and test set, partition them into ten " -"smaller datasets (each split into training and validation set), and wrap the " -"resulting partitions by creating a PyTorch ``DataLoader`` for each of them:" +"Let's now create the Federated Dataset abstraction that from ``flwr-" +"datasets`` that partitions the CIFAR-10. We will create small training " +"and test set for each edge device and wrap each of them into a PyTorch " +"``DataLoader``:" msgstr "" -"现在,让我们加载 CIFAR-10 训练集和测试集,将它们分割成 10 个较小的数据集(每" -"个数据集又分为训练集和验证集),并通过为每个数据集创建 PyTorch " -"``DataLoader`` 来包装由此产生的分割集:" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:222 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:198 msgid "" "We now have a list of ten training sets and ten validation sets " -"(``trainloaders`` and ``valloaders``) representing the data of ten different " -"organizations. Each ``trainloader``/``valloader`` pair contains 4500 " -"training examples and 500 validation examples. There's also a single " -"``testloader`` (we did not split the test set). Again, this is only " -"necessary for building research or educational systems, actual federated " -"learning systems have their data naturally distributed across multiple " -"partitions." +"(``trainloaders`` and ``valloaders``) representing the data of ten " +"different organizations. Each ``trainloader``/``valloader`` pair contains" +" 4500 training examples and 500 validation examples. There's also a " +"single ``testloader`` (we did not split the test set). Again, this is " +"only necessary for building research or educational systems, actual " +"federated learning systems have their data naturally distributed across " +"multiple partitions." msgstr "" -"现在,我们有一个包含十个训练集和十个验证集(`trainloaders`` " -"和`valloaders``)的列表,代表十个不同组织的数据。每对 " -"``trainloader``/``valloader`` 都包含 4500 个训练示例和 500 个验证数据。" -"还有一个单独的 ``测试加载器``(我们没有拆分测试集)。同样,这只有在构建研究或" -"教育系统时才有必要,实际的联邦学习系统的数据自然分布在多个分区中。" +"现在,我们有一个包含十个训练集和十个验证集(`trainloaders`` 和`valloaders``)的列表,代表十个不同组织的数据。每对 " +"``trainloader``/``valloader`` 都包含 4500 个训练示例和 500 个验证数据。还有一个单独的 " +"``测试加载器``(我们没有拆分测试集)。同样,这只有在构建研究或教育系统时才有必要,实际的联邦学习系统的数据自然分布在多个分区中。" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:225 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:201 msgid "" "Let's take a look at the first batch of images and labels in the first " "training set (i.e., ``trainloaders[0]``) before we move on:" -msgstr "" -"在继续之前,让我们先看看第一个训练集中的第一批图像和标签(即 " -"``trainloaders[0]``):" +msgstr "在继续之前,让我们先看看第一个训练集中的第一批图像和标签(即 ``trainloaders[0]``):" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:264 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:240 msgid "" "The output above shows a random batch of images from the first " "``trainloader`` in our list of ten ``trainloaders``. It also prints the " "labels associated with each image (i.e., one of the ten possible labels " -"we've seen above). If you run the cell again, you should see another batch " -"of images." +"we've seen above). If you run the cell again, you should see another " +"batch of images." msgstr "" -"上面的输出显示了来自十个 \"trainloader \"列表中第一个 \"trainloader \"的随机" -"图像。它还打印了与每幅图像相关的标签(即我们上面看到的十个可能标签之一)。如" -"果您再次运行该单元,应该会看到另一批图像。" +"上面的输出显示了来自十个 \"trainloader \"列表中第一个 \"trainloader " +"\"的随机图像。它还打印了与每幅图像相关的标签(即我们上面看到的十个可能标签之一)。如果您再次运行该单元,应该会看到另一批图像。" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:276 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:252 msgid "Step 1: Centralized Training with PyTorch" msgstr "步骤 1:使用 PyTorch 进行集中训练" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:287 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:263 msgid "" "Next, we're going to use PyTorch to define a simple convolutional neural " "network. This introduction assumes basic familiarity with PyTorch, so it " "doesn't cover the PyTorch-related aspects in full detail. If you want to " "dive deeper into PyTorch, we recommend `DEEP LEARNING WITH PYTORCH: A 60 " -"MINUTE BLITZ `__." +"MINUTE BLITZ " +"`__." msgstr "" -"接下来,我们将使用 PyTorch 来定义一个简单的卷积神经网络。本介绍假定您对 " -"PyTorch 有基本的了解,因此不会详细介绍与 PyTorch 相关的内容。" -"如果你想更深入地了解 PyTorch,我们推荐你阅读 `DEEP LEARNING WITH PYTORCH: a " -"60 minute blitz `__。" +"接下来,我们将使用 PyTorch 来定义一个简单的卷积神经网络。本介绍假定您对 PyTorch 有基本的了解,因此不会详细介绍与 PyTorch" +" 相关的内容。如果你想更深入地了解 PyTorch,我们推荐你阅读 `DEEP LEARNING WITH PYTORCH: a 60 " +"minute blitz " +"`__。" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:299 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:275 msgid "Defining the model" msgstr "定义模型" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:301 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:277 msgid "" -"We use the simple CNN described in the `PyTorch tutorial `__:" +"We use the simple CNN described in the `PyTorch tutorial " +"`__:" msgstr "" -"我们使用` PyTorch 教程 `__ 中描述的简单 " -"CNN:" +"我们使用` PyTorch 教程 " +"`__ 中描述的简单 CNN:" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:338 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:314 msgid "Let's continue with the usual training and test functions:" msgstr "让我们继续进行常规的训练和测试功能:" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:398 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:374 msgid "Training the model" msgstr "训练模型" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:400 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:376 msgid "" "We now have all the basic building blocks we need: a dataset, a model, a " -"training function, and a test function. Let's put them together to train the " -"model on the dataset of one of our organizations (``trainloaders[0]``). This " -"simulates the reality of most machine learning projects today: each " -"organization has their own data and trains models only on this internal data:" -msgstr "" -"现在我们拥有了所需的所有基本构件:数据集、模型、训练函数和测试函数。让我们把" -"它们放在一起,在我们其中一个组织的数据集(``trainloaders[0]``)上训练模型。这" -"模拟了当今大多数机器学习项目的实际情况:每个组织都有自己的数据,并且只在这些" -"内部数据上训练模型:" +"training function, and a test function. Let's put them together to train " +"the model on the dataset of one of our organizations " +"(``trainloaders[0]``). This simulates the reality of most machine " +"learning projects today: each organization has their own data and trains " +"models only on this internal data:" +msgstr "现在我们拥有了所需的所有基本构件:数据集、模型、训练函数和测试函数。让我们把它们放在一起,在我们其中一个组织的数据集(``trainloaders[0]``)上训练模型。这模拟了当今大多数机器学习项目的实际情况:每个组织都有自己的数据,并且只在这些内部数据上训练模型:" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:430 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:406 msgid "" -"Training the simple CNN on our CIFAR-10 split for 5 epochs should result in " -"a test set accuracy of about 41%, which is not good, but at the same time, " -"it doesn't really matter for the purposes of this tutorial. The intent was " -"just to show a simplistic centralized training pipeline that sets the stage " -"for what comes next - federated learning!" +"Training the simple CNN on our CIFAR-10 split for 5 epochs should result " +"in a test set accuracy of about 41%, which is not good, but at the same " +"time, it doesn't really matter for the purposes of this tutorial. The " +"intent was just to show a simplistic centralized training pipeline that " +"sets the stage for what comes next - federated learning!" msgstr "" "在我们的 CIFAR-10 分片上对简单 CNN 进行 5 个遍历的训练后,测试集的准确率应为 " -"41%,这并不理想,但同时对本教程而言也并不重要。我们只是想展示一个简单的集中式" -"训练流程,为接下来的联邦学习做好铺垫!" +"41%,这并不理想,但同时对本教程而言也并不重要。我们只是想展示一个简单的集中式训练流程,为接下来的联邦学习做好铺垫!" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:442 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:418 msgid "Step 2: Federated Learning with Flower" msgstr "步骤 2:使用 Flower 联邦学习" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:444 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:420 msgid "" -"Step 1 demonstrated a simple centralized training pipeline. All data was in " -"one place (i.e., a single ``trainloader`` and a single ``valloader``). Next, " -"we'll simulate a situation where we have multiple datasets in multiple " -"organizations and where we train a model over these organizations using " -"federated learning." +"Step 1 demonstrated a simple centralized training pipeline. All data was " +"in one place (i.e., a single ``trainloader`` and a single ``valloader``)." +" Next, we'll simulate a situation where we have multiple datasets in " +"multiple organizations and where we train a model over these " +"organizations using federated learning." msgstr "" -"步骤 1 演示了一个简单的集中式训练流程。所有数据都在一个地方(即一个 " -"\"trainloader \"和一个 \"valloader\")。接下来,我们将模拟在多个组织中拥有多" -"个数据集的情况,并使用联邦学习在这些组织中训练一个模型。" +"步骤 1 演示了一个简单的集中式训练流程。所有数据都在一个地方(即一个 \"trainloader \"和一个 " +"\"valloader\")。接下来,我们将模拟在多个组织中拥有多个数据集的情况,并使用联邦学习在这些组织中训练一个模型。" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:456 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:432 msgid "Updating model parameters" msgstr "更新模型参数" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:458 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:434 msgid "" -"In federated learning, the server sends the global model parameters to the " -"client, and the client updates the local model with the parameters received " -"from the server. It then trains the model on the local data (which changes " -"the model parameters locally) and sends the updated/changed model parameters " -"back to the server (or, alternatively, it sends just the gradients back to " -"the server, not the full model parameters)." -msgstr "" -"在联邦学习中,服务器将全局模型参数发送给客户端,客户端根据从服务器接收到的参" -"数更新本地模型。然后,客户端根据本地数据对模型进行训练(在本地更改模型参" -"数),并将更新/更改后的模型参数发回服务器(或者,客户端只将梯度参数发回服务" -"器,而不是全部模型参数)。" +"In federated learning, the server sends the global model parameters to " +"the client, and the client updates the local model with the parameters " +"received from the server. It then trains the model on the local data " +"(which changes the model parameters locally) and sends the " +"updated/changed model parameters back to the server (or, alternatively, " +"it sends just the gradients back to the server, not the full model " +"parameters)." +msgstr "在联邦学习中,服务器将全局模型参数发送给客户端,客户端根据从服务器接收到的参数更新本地模型。然后,客户端根据本地数据对模型进行训练(在本地更改模型参数),并将更新/更改后的模型参数发回服务器(或者,客户端只将梯度参数发回服务器,而不是全部模型参数)。" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:460 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:436 msgid "" "We need two helper functions to update the local model with parameters " -"received from the server and to get the updated model parameters from the " -"local model: ``set_parameters`` and ``get_parameters``. The following two " -"functions do just that for the PyTorch model above." +"received from the server and to get the updated model parameters from the" +" local model: ``set_parameters`` and ``get_parameters``. The following " +"two functions do just that for the PyTorch model above." msgstr "" -"我们需要两个辅助函数,用从服务器接收到的参数更新本地模型,并从本地模型获取更" -"新后的模型参数:`` set_parameters```和`get_parameters``。" -"下面两个函数就是为上面的 PyTorch 模型做这些工作的。" +"我们需要两个辅助函数,用从服务器接收到的参数更新本地模型,并从本地模型获取更新后的模型参数:`` " +"set_parameters```和`get_parameters``。下面两个函数就是为上面的 PyTorch 模型做这些工作的。" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:462 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:438 msgid "" -"The details of how this works are not really important here (feel free to " -"consult the PyTorch documentation if you want to learn more). In essence, we " -"use ``state_dict`` to access PyTorch model parameter tensors. The parameter " -"tensors are then converted to/from a list of NumPy ndarray's (which Flower " -"knows how to serialize/deserialize):" +"The details of how this works are not really important here (feel free to" +" consult the PyTorch documentation if you want to learn more). In " +"essence, we use ``state_dict`` to access PyTorch model parameter tensors." +" The parameter tensors are then converted to/from a list of NumPy " +"ndarray's (which Flower knows how to serialize/deserialize):" msgstr "" -"在这里,如何工作的细节并不重要(如果你想了解更多,请随时查阅 PyTorch 文档)。" -"本质上,我们使用 ``state_dict`` 访问 PyTorch 模型参数张量。然后,参数张量会被" -"转换成/转换成 NumPy ndarray 列表(Flower 知道如何序列化/反序列化):" +"在这里,如何工作的细节并不重要(如果你想了解更多,请随时查阅 PyTorch 文档)。本质上,我们使用 ``state_dict`` 访问 " +"PyTorch 模型参数张量。然后,参数张量会被转换成/转换成 NumPy ndarray 列表(Flower 知道如何序列化/反序列化):" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:490 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:466 msgid "Implementing a Flower client" msgstr "实现 Flower 客户端" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:492 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:468 msgid "" -"With that out of the way, let's move on to the interesting part. Federated " -"learning systems consist of a server and multiple clients. In Flower, we " -"create clients by implementing subclasses of ``flwr.client.Client`` or " -"``flwr.client.NumPyClient``. We use ``NumPyClient`` in this tutorial because " -"it is easier to implement and requires us to write less boilerplate." +"With that out of the way, let's move on to the interesting part. " +"Federated learning systems consist of a server and multiple clients. In " +"Flower, we create clients by implementing subclasses of " +"``flwr.client.Client`` or ``flwr.client.NumPyClient``. We use " +"``NumPyClient`` in this tutorial because it is easier to implement and " +"requires us to write less boilerplate." msgstr "" -"说完这些,让我们进入有趣的部分。联邦学习系统由一个服务器和多个客户端组成。在 " -"Flower 中,我们通过实现 ``flwr.client.Client`` 或 ``flwr.client.NumPyClient``" -" 的子类来创建客户端。在本教程中,我们使用``NumPyClient``,因为它更容易实现," -"需要我们编写的模板也更少。" +"说完这些,让我们进入有趣的部分。联邦学习系统由一个服务器和多个客户端组成。在 Flower 中,我们通过实现 " +"``flwr.client.Client`` 或 ``flwr.client.NumPyClient`` " +"的子类来创建客户端。在本教程中,我们使用``NumPyClient``,因为它更容易实现,需要我们编写的模板也更少。" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:494 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:470 msgid "" -"To implement the Flower client, we create a subclass of ``flwr.client." -"NumPyClient`` and implement the three methods ``get_parameters``, ``fit``, " -"and ``evaluate``:" +"To implement the Flower client, we create a subclass of " +"``flwr.client.NumPyClient`` and implement the three methods " +"``get_parameters``, ``fit``, and ``evaluate``:" msgstr "" -"为实现 Flower 客户端,我们创建了 ``flwr.client.NumPyClient`` 的子类,并实现" -"了 ``get_parameters``、``fit`` 和``evaluate`` 三个方法:" +"为实现 Flower 客户端,我们创建了 ``flwr.client.NumPyClient`` 的子类,并实现了 " +"``get_parameters``、``fit`` 和``evaluate`` 三个方法:" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:496 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:472 msgid "``get_parameters``: Return the current local model parameters" msgstr "``get_parameters``: 返回当前本地模型参数" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:497 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:473 msgid "" "``fit``: Receive model parameters from the server, train the model " -"parameters on the local data, and return the (updated) model parameters to " -"the server" -msgstr "``fit``: 从服务器接收模型参数,在本地数据上训练模型参数,并将(更新的)模型" -"参数返回服务器" +"parameters on the local data, and return the (updated) model parameters " +"to the server" +msgstr "``fit``: 从服务器接收模型参数,在本地数据上训练模型参数,并将(更新的)模型参数返回服务器" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:498 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:474 msgid "" -"``evaluate``: Receive model parameters from the server, evaluate the model " -"parameters on the local data, and return the evaluation result to the server" -msgstr "``evaluate ``: " -"从服务器接收模型参数,在本地数据上评估模型参数,并将评估结果返回服务器" +"``evaluate``: Receive model parameters from the server, evaluate the " +"model parameters on the local data, and return the evaluation result to " +"the server" +msgstr "``evaluate ``: 从服务器接收模型参数,在本地数据上评估模型参数,并将评估结果返回服务器" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:500 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:476 msgid "" "We mentioned that our clients will use the previously defined PyTorch " "components for model training and evaluation. Let's see a simple Flower " "client implementation that brings everything together:" msgstr "" -"我们提到,我们的客户端将使用之前定义的 PyTorch 组件进行模型训练和评估。让我们" -"来看看一个简单的 Flower 客户端实现,它将一切都整合在一起:" +"我们提到,我们的客户端将使用之前定义的 PyTorch 组件进行模型训练和评估。让我们来看看一个简单的 Flower " +"客户端实现,它将一切都整合在一起:" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:537 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:513 msgid "" "Our class ``FlowerClient`` defines how local training/evaluation will be " -"performed and allows Flower to call the local training/evaluation through " -"``fit`` and ``evaluate``. Each instance of ``FlowerClient`` represents a " -"*single client* in our federated learning system. Federated learning systems " -"have multiple clients (otherwise, there's not much to federate), so each " -"client will be represented by its own instance of ``FlowerClient``. If we " -"have, for example, three clients in our workload, then we'd have three " -"instances of ``FlowerClient``. Flower calls ``FlowerClient.fit`` on the " -"respective instance when the server selects a particular client for training " -"(and ``FlowerClient.evaluate`` for evaluation)." -msgstr "" -"我们的类 ``FlowerClient`` 定义了本地训练/评估的执行方式,并允许 Flower 通过 " -"``fit`` 和 ``evaluate`` 调用本地训练/评估。每个 ``FlowerClient`` 实例都代表联" -"邦学习系统中的*单个客户端*。联邦学习系统有多个客户端(否则就没有什么可联邦的" -"),因此每个客户端都将由自己的 ``FlowerClient`` " -"实例来代表。例如,如果我们的工作负载中有三个客户端,那么我们就会有三个 " -"``FlowerClient`` 实例。当服务器选择特定客户端进行训练时,Flower " -"会调用相应实例上的 ``FlowerClient.fit`` (评估时调用 ``FlowerClient." -"evaluate``)。" - -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:541 +"performed and allows Flower to call the local training/evaluation through" +" ``fit`` and ``evaluate``. Each instance of ``FlowerClient`` represents a" +" *single client* in our federated learning system. Federated learning " +"systems have multiple clients (otherwise, there's not much to federate), " +"so each client will be represented by its own instance of " +"``FlowerClient``. If we have, for example, three clients in our workload," +" then we'd have three instances of ``FlowerClient``. Flower calls " +"``FlowerClient.fit`` on the respective instance when the server selects a" +" particular client for training (and ``FlowerClient.evaluate`` for " +"evaluation)." +msgstr "" +"我们的类 ``FlowerClient`` 定义了本地训练/评估的执行方式,并允许 Flower 通过 ``fit`` 和 " +"``evaluate`` 调用本地训练/评估。每个 ``FlowerClient`` " +"实例都代表联邦学习系统中的*单个客户端*。联邦学习系统有多个客户端(否则就没有什么可联邦的),因此每个客户端都将由自己的 " +"``FlowerClient`` 实例来代表。例如,如果我们的工作负载中有三个客户端,那么我们就会有三个 ``FlowerClient`` " +"实例。当服务器选择特定客户端进行训练时,Flower 会调用相应实例上的 ``FlowerClient.fit`` (评估时调用 " +"``FlowerClient.evaluate``)。" + +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:517 msgid "Using the Virtual Client Engine" msgstr "使用虚拟客户端引擎" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:543 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:519 msgid "" -"In this notebook, we want to simulate a federated learning system with 10 " -"clients on a single machine. This means that the server and all 10 clients " -"will live on a single machine and share resources such as CPU, GPU, and " -"memory. Having 10 clients would mean having 10 instances of ``FlowerClient`` " -"in memory. Doing this on a single machine can quickly exhaust the available " -"memory resources, even if only a subset of these clients participates in a " -"single round of federated learning." +"In this notebook, we want to simulate a federated learning system with 10" +" clients on a single machine. This means that the server and all 10 " +"clients will live on a single machine and share resources such as CPU, " +"GPU, and memory. Having 10 clients would mean having 10 instances of " +"``FlowerClient`` in memory. Doing this on a single machine can quickly " +"exhaust the available memory resources, even if only a subset of these " +"clients participates in a single round of federated learning." msgstr "" -"在本笔记中,我们要模拟一个联邦学习系统,在一台机器上有 10 个客户端。" -"这意味着服务器和所有 10 个客户端都将位于一台机器上,并共享 CPU、GPU " -"和内存等资源。有 10 个客户端就意味着内存中有 10 个 ``FlowerClient`` 实例。在" -"单台机器上这样做会很快耗尽可用的内存资源,即使这些客户端中只有一个子集参与了" -"一轮联邦学习。" +"在本笔记中,我们要模拟一个联邦学习系统,在一台机器上有 10 个客户端。这意味着服务器和所有 10 个客户端都将位于一台机器上,并共享 " +"CPU、GPU 和内存等资源。有 10 个客户端就意味着内存中有 10 个 ``FlowerClient`` " +"实例。在单台机器上这样做会很快耗尽可用的内存资源,即使这些客户端中只有一个子集参与了一轮联邦学习。" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:545 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:521 msgid "" "In addition to the regular capabilities where server and clients run on " "multiple machines, Flower, therefore, provides special simulation " "capabilities that create ``FlowerClient`` instances only when they are " "actually necessary for training or evaluation. To enable the Flower " -"framework to create clients when necessary, we need to implement a function " -"called ``client_fn`` that creates a ``FlowerClient`` instance on demand. " -"Flower calls ``client_fn`` whenever it needs an instance of one particular " -"client to call ``fit`` or ``evaluate`` (those instances are usually " -"discarded after use, so they should not keep any local state). Clients are " -"identified by a client ID, or short ``cid``. The ``cid`` can be used, for " -"example, to load different local data partitions for different clients, as " -"can be seen below:" -msgstr "" -"除了服务器和客户端在多台机器上运行的常规功能外,Flower 还提供了特殊的模拟功" -"能,即只有在训练或评估实际需要时才创建 ``FlowerClient`` 实例。为了让 Flower " -"框架能在必要时创建客户端,我们需要实现一个名为 ``client_fn`` 的函数,它能按需" -"创建一个 ``FlowerClient`` 实例。每当 Flower 需要一个特定的客户端实例来调用 " -"``fit`` 或 ``evaluate`` 时,它就会调用 ``client_fn``(这些实例在使用后通常会" -"被丢弃,因此它们不应保留任何本地状态)。客户端由一个客户端 ID 或简短的 " -"``cid`` 标识。例如,可以使用 ``cid`` 为不同的客户端加载不同的本地数据分区,如" -"下所示:" - -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:580 +"framework to create clients when necessary, we need to implement a " +"function called ``client_fn`` that creates a ``FlowerClient`` instance on" +" demand. Flower calls ``client_fn`` whenever it needs an instance of one " +"particular client to call ``fit`` or ``evaluate`` (those instances are " +"usually discarded after use, so they should not keep any local state). " +"Clients are identified by a client ID, or short ``cid``. The ``cid`` can " +"be used, for example, to load different local data partitions for " +"different clients, as can be seen below:" +msgstr "" +"除了服务器和客户端在多台机器上运行的常规功能外,Flower 还提供了特殊的模拟功能,即只有在训练或评估实际需要时才创建 " +"``FlowerClient`` 实例。为了让 Flower 框架能在必要时创建客户端,我们需要实现一个名为 ``client_fn`` " +"的函数,它能按需创建一个 ``FlowerClient`` 实例。每当 Flower 需要一个特定的客户端实例来调用 ``fit`` 或 " +"``evaluate`` 时,它就会调用 " +"``client_fn``(这些实例在使用后通常会被丢弃,因此它们不应保留任何本地状态)。客户端由一个客户端 ID 或简短的 ``cid`` " +"标识。例如,可以使用 ``cid`` 为不同的客户端加载不同的本地数据分区,如下所示:" + +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:556 msgid "Starting the training" msgstr "开始训练" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:582 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:558 msgid "" -"We now have the class ``FlowerClient`` which defines client-side training/" -"evaluation and ``client_fn`` which allows Flower to create ``FlowerClient`` " -"instances whenever it needs to call ``fit`` or ``evaluate`` on one " -"particular client. The last step is to start the actual simulation using " -"``flwr.simulation.start_simulation``." +"We now have the class ``FlowerClient`` which defines client-side " +"training/evaluation and ``client_fn`` which allows Flower to create " +"``FlowerClient`` instances whenever it needs to call ``fit`` or " +"``evaluate`` on one particular client. The last step is to start the " +"actual simulation using ``flwr.simulation.start_simulation``." msgstr "" -"现在我们有了定义客户端训练/评估的类 ``FlowerClient`` 和允许 Flower 在需要调用" -"某个客户端的 ``fit` 或 ``evaluate` 时创建 ``FlowerClient`` 实例的 " -"``client_fn` 类。最后一步是使用 ``flwr.simulation.start_simulation`` 启动实际" -"模拟。" +"现在我们有了定义客户端训练/评估的类 ``FlowerClient`` 和允许 Flower 在需要调用某个客户端的 ``fit` 或 " +"``evaluate` 时创建 ``FlowerClient`` 实例的 ``client_fn` 类。最后一步是使用 " +"``flwr.simulation.start_simulation`` 启动实际模拟。" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:584 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:560 msgid "" "The function ``start_simulation`` accepts a number of arguments, amongst " -"them the ``client_fn`` used to create ``FlowerClient`` instances, the number " -"of clients to simulate (``num_clients``), the number of federated learning " -"rounds (``num_rounds``), and the strategy. The strategy encapsulates the " -"federated learning approach/algorithm, for example, *Federated Averaging* " -"(FedAvg)." +"them the ``client_fn`` used to create ``FlowerClient`` instances, the " +"number of clients to simulate (``num_clients``), the number of federated " +"learning rounds (``num_rounds``), and the strategy. The strategy " +"encapsulates the federated learning approach/algorithm, for example, " +"*Federated Averaging* (FedAvg)." msgstr "" -"函数 ``start_simulation`` 接受许多参数,其中包括用于创建 ``FlowerClient`` " -"实例的 ``client_fn``、要模拟的客户端数量(``num_clients``)、联邦学习轮数(``" -"num_rounds``)和策略。策略封装了联邦学习方法/算法,例如*联邦平均* (FedAvg)。" +"函数 ``start_simulation`` 接受许多参数,其中包括用于创建 ``FlowerClient`` 实例的 " +"``client_fn``、要模拟的客户端数量(``num_clients``)、联邦学习轮数(``num_rounds``)和策略。策略封装了联邦学习方法/算法,例如*联邦平均*" +" (FedAvg)。" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:586 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:562 msgid "" "Flower has a number of built-in strategies, but we can also use our own " -"strategy implementations to customize nearly all aspects of the federated " -"learning approach. For this example, we use the built-in ``FedAvg`` " -"implementation and customize it using a few basic parameters. The last step " -"is the actual call to ``start_simulation`` which - you guessed it - starts " -"the simulation:" +"strategy implementations to customize nearly all aspects of the federated" +" learning approach. For this example, we use the built-in ``FedAvg`` " +"implementation and customize it using a few basic parameters. The last " +"step is the actual call to ``start_simulation`` which - you guessed it - " +"starts the simulation:" msgstr "" -"Flower 有许多内置策略,但我们也可以使用自己的策略实现来定制联邦学习方法的几乎" -"所有方面。在本例中,我们使用内置的 ``FedAvg`` " -"实现,并使用一些基本参数对其进行定制。最后一步是实际调用 " -"``start_simulation``开始模拟:" +"Flower 有许多内置策略,但我们也可以使用自己的策略实现来定制联邦学习方法的几乎所有方面。在本例中,我们使用内置的 ``FedAvg`` " +"实现,并使用一些基本参数对其进行定制。最后一步是实际调用 ``start_simulation``开始模拟:" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:628 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:608 msgid "Behind the scenes" msgstr "幕后" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:630 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:610 msgid "So how does this work? How does Flower execute this simulation?" msgstr "那么它是如何工作的呢?Flower 如何进行模拟?" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:632 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:612 #, python-format msgid "" -"When we call ``start_simulation``, we tell Flower that there are 10 clients " -"(``num_clients=10``). Flower then goes ahead an asks the ``FedAvg`` strategy " -"to select clients. ``FedAvg`` knows that it should select 100% of the " -"available clients (``fraction_fit=1.0``), so it goes ahead and selects 10 " -"random clients (i.e., 100% of 10)." +"When we call ``start_simulation``, we tell Flower that there are 10 " +"clients (``num_clients=10``). Flower then goes ahead an asks the " +"``FedAvg`` strategy to select clients. ``FedAvg`` knows that it should " +"select 100% of the available clients (``fraction_fit=1.0``), so it goes " +"ahead and selects 10 random clients (i.e., 100% of 10)." msgstr "" -"当我们调用 ``start_simulation`` 时,我们会告诉 Flower 有 10 个客户" -"(`num_clients=10``)。然后,Flower 会要求 ``FedAvg`` 策略选择客户。" -"``FedAvg`` 知道它应该选择 100%的可用客户(``fraction_fit=1.0``),所以它会随" -"机选择 10 个客户(即 10 的 100%)。" +"当我们调用 ``start_simulation`` 时,我们会告诉 Flower 有 10 " +"个客户(`num_clients=10``)。然后,Flower 会要求 ``FedAvg`` 策略选择客户。``FedAvg`` 知道它应该选择" +" 100%的可用客户(``fraction_fit=1.0``),所以它会随机选择 10 个客户(即 10 的 100%)。" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:634 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:614 msgid "" -"Flower then asks the selected 10 clients to train the model. When the server " -"receives the model parameter updates from the clients, it hands those " -"updates over to the strategy (*FedAvg*) for aggregation. The strategy " -"aggregates those updates and returns the new global model, which then gets " -"used in the next round of federated learning." +"Flower then asks the selected 10 clients to train the model. When the " +"server receives the model parameter updates from the clients, it hands " +"those updates over to the strategy (*FedAvg*) for aggregation. The " +"strategy aggregates those updates and returns the new global model, which" +" then gets used in the next round of federated learning." msgstr "" -"然后,Flower 会要求选定的 10 个客户端对模型进行训练。服务器收到客户端的模型参" -"数更新后,会将这些更新交给策略(*FedAvg*)进行聚合。策略会聚合这些更新并返回" -"新的全局模型,然后将其用于下一轮联邦学习。" +"然后,Flower 会要求选定的 10 " +"个客户端对模型进行训练。服务器收到客户端的模型参数更新后,会将这些更新交给策略(*FedAvg*)进行聚合。策略会聚合这些更新并返回新的全局模型,然后将其用于下一轮联邦学习。" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:646 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:626 msgid "Where's the accuracy?" msgstr "准确度在哪里找?" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:648 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:628 msgid "" -"You may have noticed that all metrics except for ``losses_distributed`` are " -"empty. Where did the ``{\"accuracy\": float(accuracy)}`` go?" +"You may have noticed that all metrics except for ``losses_distributed`` " +"are empty. Where did the ``{\"accuracy\": float(accuracy)}`` go?" msgstr "" -"您可能已经注意到,除了 ``losses_distributed`` 以外,所有指标都是空的。{\"准确" -"度\": float(准确度)}``去哪儿了?" +"您可能已经注意到,除了 ``losses_distributed`` 以外,所有指标都是空的。{\"准确度\": " +"float(准确度)}``去哪儿了?" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:650 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:630 msgid "" -"Flower can automatically aggregate losses returned by individual clients, " -"but it cannot do the same for metrics in the generic metrics dictionary (the " -"one with the ``accuracy`` key). Metrics dictionaries can contain very " -"different kinds of metrics and even key/value pairs that are not metrics at " -"all, so the framework does not (and can not) know how to handle these " -"automatically." +"Flower can automatically aggregate losses returned by individual clients," +" but it cannot do the same for metrics in the generic metrics dictionary " +"(the one with the ``accuracy`` key). Metrics dictionaries can contain " +"very different kinds of metrics and even key/value pairs that are not " +"metrics at all, so the framework does not (and can not) know how to " +"handle these automatically." msgstr "" -"Flower 可以自动汇总单个客户端返回的损失值,但无法对通用度量字典中的度量进行同" -"样的处理(即带有 \"准确度 \"键的度量字典)。度量值字典可以包含非常不同种类的" -"度量值,甚至包含根本不是度量值的键/值对,因此框架不知道(也无法知道)如何自动" -"处理这些度量值。" +"Flower 可以自动汇总单个客户端返回的损失值,但无法对通用度量字典中的度量进行同样的处理(即带有 \"准确度 " +"\"键的度量字典)。度量值字典可以包含非常不同种类的度量值,甚至包含根本不是度量值的键/值对,因此框架不知道(也无法知道)如何自动处理这些度量值。" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:652 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:632 msgid "" -"As users, we need to tell the framework how to handle/aggregate these custom " -"metrics, and we do so by passing metric aggregation functions to the " -"strategy. The strategy will then call these functions whenever it receives " -"fit or evaluate metrics from clients. The two possible functions are " -"``fit_metrics_aggregation_fn`` and ``evaluate_metrics_aggregation_fn``." +"As users, we need to tell the framework how to handle/aggregate these " +"custom metrics, and we do so by passing metric aggregation functions to " +"the strategy. The strategy will then call these functions whenever it " +"receives fit or evaluate metrics from clients. The two possible functions" +" are ``fit_metrics_aggregation_fn`` and " +"``evaluate_metrics_aggregation_fn``." msgstr "" -"作为用户,我们需要告诉框架如何处理/聚合这些自定义指标,为此,我们将指标聚合函" -"数传递给策略。然后,只要从客户端接收到拟合或评估指标,策略就会调用这些函数。" -"两个可能的函数是 ``fit_metrics_aggregation_fn`` 和 " -"``evaluate_metrics_aggregation_fn``。" +"作为用户,我们需要告诉框架如何处理/聚合这些自定义指标,为此,我们将指标聚合函数传递给策略。然后,只要从客户端接收到拟合或评估指标,策略就会调用这些函数。两个可能的函数是" +" ``fit_metrics_aggregation_fn`` 和 ``evaluate_metrics_aggregation_fn``。" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:654 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:634 msgid "" "Let's create a simple weighted averaging function to aggregate the " "``accuracy`` metric we return from ``evaluate``:" -msgstr "" -"让我们创建一个简单的加权平均函数来汇总从 ``evaluate`` 返回的 ``accuracy`` 指" -"标:" +msgstr "让我们创建一个简单的加权平均函数来汇总从 ``evaluate`` 返回的 ``accuracy`` 指标:" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:680 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:660 msgid "" "The only thing left to do is to tell the strategy to call this function " "whenever it receives evaluation metric dictionaries from the clients:" -msgstr "" -"剩下要做的就是告诉策略,每当它从客户端接收到评估度量字典时,都要调用这个函" -"数:" +msgstr "剩下要做的就是告诉策略,每当它从客户端接收到评估度量字典时,都要调用这个函数:" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:717 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:697 msgid "" "We now have a full system that performs federated training and federated " -"evaluation. It uses the ``weighted_average`` function to aggregate custom " -"evaluation metrics and calculates a single ``accuracy`` metric across all " -"clients on the server side." +"evaluation. It uses the ``weighted_average`` function to aggregate custom" +" evaluation metrics and calculates a single ``accuracy`` metric across " +"all clients on the server side." msgstr "" -"我们现在有了一个完整的系统,可以执行联邦训练和联邦评估。它使用 " -"``weighted_average`` 函数汇总自定义评估指标," -"并在服务器端计算所有客户端的单一 ``accuracy`` 指标。" +"我们现在有了一个完整的系统,可以执行联邦训练和联邦评估。它使用 ``weighted_average`` " +"函数汇总自定义评估指标,并在服务器端计算所有客户端的单一 ``accuracy`` 指标。" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:719 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:699 msgid "" "The other two categories of metrics (``losses_centralized`` and " "``metrics_centralized``) are still empty because they only apply when " -"centralized evaluation is being used. Part two of the Flower tutorial will " -"cover centralized evaluation." +"centralized evaluation is being used. Part two of the Flower tutorial " +"will cover centralized evaluation." msgstr "" -"其他两类指标(`losses_centralized`` 和 `metrics_centralized`)仍然是空的,因" -"为它们只适用于集中评估。Flower 教程的第二部分将介绍集中式评估。" +"其他两类指标(`losses_centralized`` 和 " +"`metrics_centralized`)仍然是空的,因为它们只适用于集中评估。Flower 教程的第二部分将介绍集中式评估。" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:731 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:711 #: ../../source/tutorial-series-what-is-federated-learning.ipynb:351 msgid "Final remarks" msgstr "结束语" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:733 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:713 msgid "" -"Congratulations, you just trained a convolutional neural network, federated " -"over 10 clients! With that, you understand the basics of federated learning " -"with Flower. The same approach you've seen can be used with other machine " -"learning frameworks (not just PyTorch) and tasks (not just CIFAR-10 images " -"classification), for example NLP with Hugging Face Transformers or speech " -"with SpeechBrain." +"Congratulations, you just trained a convolutional neural network, " +"federated over 10 clients! With that, you understand the basics of " +"federated learning with Flower. The same approach you've seen can be used" +" with other machine learning frameworks (not just PyTorch) and tasks (not" +" just CIFAR-10 images classification), for example NLP with Hugging Face " +"Transformers or speech with SpeechBrain." msgstr "" -"恭喜您,你刚刚训练了一个由 10 个客户端组成的卷积神经网络!这样," -"你就了解了使用 Flower " -"进行联邦学习的基础知识。你所看到的方法同样适用于其他机器学习框架(不只是 " -"PyTorch)和任务(不只是 CIFAR-10 图像分类),例如使用 Hugging Face " -"Transformers 的 NLP 或使用 SpeechBrain 的语音。" +"恭喜您,你刚刚训练了一个由 10 个客户端组成的卷积神经网络!这样,你就了解了使用 Flower " +"进行联邦学习的基础知识。你所看到的方法同样适用于其他机器学习框架(不只是 PyTorch)和任务(不只是 CIFAR-10 图像分类),例如使用 " +"Hugging Face Transformers 的 NLP 或使用 SpeechBrain 的语音。" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:735 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:715 msgid "" -"In the next notebook, we're going to cover some more advanced concepts. Want " -"to customize your strategy? Initialize parameters on the server side? Or " -"evaluate the aggregated model on the server side? We'll cover all this and " -"more in the next tutorial." -msgstr "" -"在下一个笔记中,我们将介绍一些更先进的概念。想定制你的策略吗?在服务器端初始" -"化参数?或者在服务器端评估聚合模型?我们将在下一个教程中介绍所有这些内容以及" -"更多。" +"In the next notebook, we're going to cover some more advanced concepts. " +"Want to customize your strategy? Initialize parameters on the server " +"side? Or evaluate the aggregated model on the server side? We'll cover " +"all this and more in the next tutorial." +msgstr "在下一个笔记中,我们将介绍一些更先进的概念。想定制你的策略吗?在服务器端初始化参数?或者在服务器端评估聚合模型?我们将在下一个教程中介绍所有这些内容以及更多。" -#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:753 +#: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:733 msgid "" -"The `Flower Federated Learning Tutorial - Part 2 `__ goes " -"into more depth about strategies and all the advanced things you can build " -"with them." +"The `Flower Federated Learning Tutorial - Part 2 " +"`__ goes into more depth about strategies and all " +"the advanced things you can build with them." msgstr "" -"`Flower 联邦学习教程 - 第 2 部分 `__ " -"更深入地介绍了策略以及可以使用策略构建的所有高级功能。" +"`Flower 联邦学习教程 - 第 2 部分 `__ 更深入地介绍了策略以及可以使用策略构建的所有高级功能。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:9 msgid "Use a federated learning strategy" @@ -15366,22 +19325,22 @@ msgstr "使用联邦学习策略" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:11 msgid "" "Welcome to the next part of the federated learning tutorial. In previous " -"parts of this tutorial, we introduced federated learning with PyTorch and " -"Flower (`part 1 `__)." +"parts of this tutorial, we introduced federated learning with PyTorch and" +" Flower (`part 1 `__)." msgstr "" -"欢迎来到联邦学习教程的下一部分。在本教程的前几部分,我们介绍了使用 PyTorch " -"和 Flower 进行联邦学习(`第 1 部分 `___)。" +"欢迎来到联邦学习教程的下一部分。在本教程的前几部分,我们介绍了使用 PyTorch 和 Flower 进行联邦学习(`第 1 部分 " +"`___)。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:13 msgid "" -"In this notebook, we'll begin to customize the federated learning system we " -"built in the introductory notebook (again, using `Flower `__ and `PyTorch `__)." +"In this notebook, we'll begin to customize the federated learning system " +"we built in the introductory notebook (again, using `Flower " +"`__ and `PyTorch `__)." msgstr "" -"在本笔记中,我们将开始定制在入门笔记中构建的联邦学习系统(再次使用 `Flower " -"`__ 和 `PyTorch `__)。" +"在本笔记中,我们将开始定制在入门笔记中构建的联邦学习系统(再次使用 `Flower `__ 和 " +"`PyTorch `__)。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:17 msgid "Let's move beyond FedAvg with Flower strategies!" @@ -15394,11 +19353,9 @@ msgstr "策略定制" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:311 msgid "" "So far, everything should look familiar if you've worked through the " -"introductory notebook. With that, we're ready to introduce a number of new " -"features." -msgstr "" -"到目前为止,如果您已经阅读过入门笔记本,那么一切都应该很熟悉了。接下来,我们" -"将介绍一些新功能。" +"introductory notebook. With that, we're ready to introduce a number of " +"new features." +msgstr "到目前为止,如果您已经阅读过入门笔记本,那么一切都应该很熟悉了。接下来,我们将介绍一些新功能。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:323 msgid "Server-side parameter **initialization**" @@ -15406,25 +19363,24 @@ msgstr "服务器端参数 **初始化**" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:325 msgid "" -"Flower, by default, initializes the global model by asking one random client " -"for the initial parameters. In many cases, we want more control over " -"parameter initialization though. Flower therefore allows you to directly " -"pass the initial parameters to the Strategy:" +"Flower, by default, initializes the global model by asking one random " +"client for the initial parameters. In many cases, we want more control " +"over parameter initialization though. Flower therefore allows you to " +"directly pass the initial parameters to the Strategy:" msgstr "" -"默认情况下,Flower 会通过向一个随机客户端询问初始参数来初始化全局模型。但在许" -"多情况下,我们需要对参数初始化进行更多控制。因此,Flower 允许您直接将初始参数" -"传递给策略:" +"默认情况下,Flower 会通过向一个随机客户端询问初始参数来初始化全局模型。但在许多情况下,我们需要对参数初始化进行更多控制。因此,Flower" +" 允许您直接将初始参数传递给策略:" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:370 msgid "" -"Passing ``initial_parameters`` to the ``FedAvg`` strategy prevents Flower " -"from asking one of the clients for the initial parameters. If we look " +"Passing ``initial_parameters`` to the ``FedAvg`` strategy prevents Flower" +" from asking one of the clients for the initial parameters. If we look " "closely, we can see that the logs do not show any calls to the " "``FlowerClient.get_parameters`` method." msgstr "" -"向 ``FedAvg`` 策略传递 ``initial_parameters`` 可以防止 Flower 向其中一个客户" -"端询问初始参数。如果我们仔细观察,就会发现日志中没有显示对 ``FlowerClient." -"get_parameters`` 方法的任何调用。" +"向 ``FedAvg`` 策略传递 ``initial_parameters`` 可以防止 Flower " +"向其中一个客户端询问初始参数。如果我们仔细观察,就会发现日志中没有显示对 ``FlowerClient.get_parameters`` " +"方法的任何调用。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:382 msgid "Starting with a customized strategy" @@ -15432,22 +19388,20 @@ msgstr "从定制战略开始" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:384 msgid "" -"We've seen the function ``start_simulation`` before. It accepts a number of " -"arguments, amongst them the ``client_fn`` used to create ``FlowerClient`` " -"instances, the number of clients to simulate ``num_clients``, the number of " -"rounds ``num_rounds``, and the strategy." +"We've seen the function ``start_simulation`` before. It accepts a number " +"of arguments, amongst them the ``client_fn`` used to create " +"``FlowerClient`` instances, the number of clients to simulate " +"``num_clients``, the number of rounds ``num_rounds``, and the strategy." msgstr "" -"我们以前见过函数 ``start_simulation``。它接受许多参数,其中包括用于创建 " -"``FlowerClient`` 实例的 ``client_fn``、要模拟的客户数量 ``num_clients``、回合" -"数 ``num_rounds``和策略。" +"我们以前见过函数 ``start_simulation``。它接受许多参数,其中包括用于创建 ``FlowerClient`` 实例的 " +"``client_fn``、要模拟的客户数量 ``num_clients``、回合数 ``num_rounds``和策略。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:386 msgid "" "The strategy encapsulates the federated learning approach/algorithm, for " -"example, ``FedAvg`` or ``FedAdagrad``. Let's try to use a different strategy " -"this time:" -msgstr "该策略封装了联邦学习方法/算法,例如`FedAvg``或`FedAdagrad``。这次让我们尝试使" -"用不同的策略:" +"example, ``FedAvg`` or ``FedAdagrad``. Let's try to use a different " +"strategy this time:" +msgstr "该策略封装了联邦学习方法/算法,例如`FedAvg``或`FedAdagrad``。这次让我们尝试使用不同的策略:" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:424 msgid "Server-side parameter **evaluation**" @@ -15455,59 +19409,46 @@ msgstr "服务器端参数**评估**" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:426 msgid "" -"Flower can evaluate the aggregated model on the server-side or on the client-" -"side. Client-side and server-side evaluation are similar in some ways, but " -"different in others." -msgstr "" -"Flower 可以在服务器端或客户端评估聚合模型。客户端和服务器端评估在某些方面相" -"似,但也有不同之处。" +"Flower can evaluate the aggregated model on the server-side or on the " +"client-side. Client-side and server-side evaluation are similar in some " +"ways, but different in others." +msgstr "Flower 可以在服务器端或客户端评估聚合模型。客户端和服务器端评估在某些方面相似,但也有不同之处。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:428 msgid "" "**Centralized Evaluation** (or *server-side evaluation*) is conceptually " "simple: it works the same way that evaluation in centralized machine " "learning does. If there is a server-side dataset that can be used for " -"evaluation purposes, then that's great. We can evaluate the newly aggregated " -"model after each round of training without having to send the model to " -"clients. We're also fortunate in the sense that our entire evaluation " -"dataset is available at all times." -msgstr "" -"**集中评估**(或*服务器端评估*)在概念上很简单:它的工作方式与集中式机器学习" -"中的评估方式相同。如果有一个服务器端数据集可用于评估目的,那就太好了。我们可" -"以在每一轮训练后对新聚合的模型进行评估,而无需将模型发送给客户端。我们也很幸" -"运,因为我们的整个评估数据集随时可用。" +"evaluation purposes, then that's great. We can evaluate the newly " +"aggregated model after each round of training without having to send the " +"model to clients. We're also fortunate in the sense that our entire " +"evaluation dataset is available at all times." +msgstr "**集中评估**(或*服务器端评估*)在概念上很简单:它的工作方式与集中式机器学习中的评估方式相同。如果有一个服务器端数据集可用于评估目的,那就太好了。我们可以在每一轮训练后对新聚合的模型进行评估,而无需将模型发送给客户端。我们也很幸运,因为我们的整个评估数据集随时可用。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:430 msgid "" -"**Federated Evaluation** (or *client-side evaluation*) is more complex, but " -"also more powerful: it doesn't require a centralized dataset and allows us " -"to evaluate models over a larger set of data, which often yields more " -"realistic evaluation results. In fact, many scenarios require us to use " -"**Federated Evaluation** if we want to get representative evaluation results " -"at all. But this power comes at a cost: once we start to evaluate on the " -"client side, we should be aware that our evaluation dataset can change over " -"consecutive rounds of learning if those clients are not always available. " -"Moreover, the dataset held by each client can also change over consecutive " -"rounds. This can lead to evaluation results that are not stable, so even if " -"we would not change the model, we'd see our evaluation results fluctuate " -"over consecutive rounds." -msgstr "" -"**联邦评估**(或*客户端评估*)更为复杂,但也更为强大:它不需要集中的数据集," -"允许我们在更大的数据集上对模型进行评估,这通常会产生更真实的评估结果。事实" -"上,如果我们想得到有代表性的评估结果,很多情况下都需要使用**联邦评估**。但" -"是,这种能力是有代价的:一旦我们开始在客户端进行评估,我们就应该意识到,如果" -"这些客户端并不总是可用,我们的评估数据集可能会在连续几轮学习中发生变化。此" -"外,每个客户端所拥有的数据集也可能在连续几轮学习中发生变化。这可能会导致评估" -"结果不稳定,因此即使我们不改变模型,也会看到评估结果在连续几轮中波动。" +"**Federated Evaluation** (or *client-side evaluation*) is more complex, " +"but also more powerful: it doesn't require a centralized dataset and " +"allows us to evaluate models over a larger set of data, which often " +"yields more realistic evaluation results. In fact, many scenarios require" +" us to use **Federated Evaluation** if we want to get representative " +"evaluation results at all. But this power comes at a cost: once we start " +"to evaluate on the client side, we should be aware that our evaluation " +"dataset can change over consecutive rounds of learning if those clients " +"are not always available. Moreover, the dataset held by each client can " +"also change over consecutive rounds. This can lead to evaluation results " +"that are not stable, so even if we would not change the model, we'd see " +"our evaluation results fluctuate over consecutive rounds." +msgstr "**联邦评估**(或*客户端评估*)更为复杂,但也更为强大:它不需要集中的数据集,允许我们在更大的数据集上对模型进行评估,这通常会产生更真实的评估结果。事实上,如果我们想得到有代表性的评估结果,很多情况下都需要使用**联邦评估**。但是,这种能力是有代价的:一旦我们开始在客户端进行评估,我们就应该意识到,如果这些客户端并不总是可用,我们的评估数据集可能会在连续几轮学习中发生变化。此外,每个客户端所拥有的数据集也可能在连续几轮学习中发生变化。这可能会导致评估结果不稳定,因此即使我们不改变模型,也会看到评估结果在连续几轮中波动。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:433 msgid "" "We've seen how federated evaluation works on the client side (i.e., by " -"implementing the ``evaluate`` method in ``FlowerClient``). Now let's see how " -"we can evaluate aggregated model parameters on the server-side:" +"implementing the ``evaluate`` method in ``FlowerClient``). Now let's see " +"how we can evaluate aggregated model parameters on the server-side:" msgstr "" -"我们已经了解了联邦评估如何在客户端工作(即通过在 ``FlowerClient`` 中实现 " -"``evaluate`` 方法)。现在让我们看看如何在服务器端评估聚合模型参数:" +"我们已经了解了联邦评估如何在客户端工作(即通过在 ``FlowerClient`` 中实现 ``evaluate`` " +"方法)。现在让我们看看如何在服务器端评估聚合模型参数:" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:490 msgid "Sending/receiving arbitrary values to/from clients" @@ -15515,66 +19456,63 @@ msgstr "向/从客户端发送/接收任意值" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:492 msgid "" -"In some situations, we want to configure client-side execution (training, " -"evaluation) from the server-side. One example for that is the server asking " -"the clients to train for a certain number of local epochs. Flower provides a " -"way to send configuration values from the server to the clients using a " -"dictionary. Let's look at an example where the clients receive values from " -"the server through the ``config`` parameter in ``fit`` (``config`` is also " -"available in ``evaluate``). The ``fit`` method receives the configuration " -"dictionary through the ``config`` parameter and can then read values from " -"this dictionary. In this example, it reads ``server_round`` and " -"``local_epochs`` and uses those values to improve the logging and configure " -"the number of local training epochs:" -msgstr "" -"在某些情况下,我们希望从服务器端配置客户端的执行(训练、评估)。其中一个例子" -"就是服务器要求客户端训练一定数量的本地遍历。Flower " -"提供了一种使用字典从服务器向客户端发送配置值的方法。让我们来看一个例子:" -"客户端通过 ``fit`` 中的 ``config`` 参数从服务器接收配置值(``evaluate`` " -"中也有 ``config`` 参数)。``fit`` 方法通过 ``config`` " +"In some situations, we want to configure client-side execution (training," +" evaluation) from the server-side. One example for that is the server " +"asking the clients to train for a certain number of local epochs. Flower " +"provides a way to send configuration values from the server to the " +"clients using a dictionary. Let's look at an example where the clients " +"receive values from the server through the ``config`` parameter in " +"``fit`` (``config`` is also available in ``evaluate``). The ``fit`` " +"method receives the configuration dictionary through the ``config`` " +"parameter and can then read values from this dictionary. In this example," +" it reads ``server_round`` and ``local_epochs`` and uses those values to " +"improve the logging and configure the number of local training epochs:" +msgstr "" +"在某些情况下,我们希望从服务器端配置客户端的执行(训练、评估)。其中一个例子就是服务器要求客户端训练一定数量的本地遍历。Flower " +"提供了一种使用字典从服务器向客户端发送配置值的方法。让我们来看一个例子:客户端通过 ``fit`` 中的 ``config`` " +"参数从服务器接收配置值(``evaluate`` 中也有 ``config`` 参数)。``fit`` 方法通过 ``config`` " "参数接收配置字典,然后从字典中读取值。在本例中,它读取了 ``server_round`` 和 " "``local_epochs``,并使用这些值来改进日志记录和配置本地训练遍历的数量:" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:546 msgid "" -"So how can we send this config dictionary from server to clients? The built-" -"in Flower Strategies provide way to do this, and it works similarly to the " -"way server-side evaluation works. We provide a function to the strategy, and " -"the strategy calls this function for every round of federated learning:" +"So how can we send this config dictionary from server to clients? The " +"built-in Flower Strategies provide way to do this, and it works similarly" +" to the way server-side evaluation works. We provide a function to the " +"strategy, and the strategy calls this function for every round of " +"federated learning:" msgstr "" -"那么,如何将配置字典从服务器发送到客户端呢?内置的 \"Flower策略\"(Flower Str" -"ategies)提供了这样的方法,其工作原理与服务器端评估的工作原理类似。我们为策略" -"提供一个函数,策略会在每一轮联邦学习中调用这个函数:" +"那么,如何将配置字典从服务器发送到客户端呢?内置的 \"Flower策略\"(Flower " +"Strategies)提供了这样的方法,其工作原理与服务器端评估的工作原理类似。我们为策略提供一个函数,策略会在每一轮联邦学习中调用这个函数:" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:576 msgid "" -"Next, we'll just pass this function to the FedAvg strategy before starting " -"the simulation:" +"Next, we'll just pass this function to the FedAvg strategy before " +"starting the simulation:" msgstr "接下来,我们只需在开始模拟前将此函数传递给 FedAvg 策略即可:" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:613 msgid "" -"As we can see, the client logs now include the current round of federated " -"learning (which they read from the ``config`` dictionary). We can also " -"configure local training to run for one epoch during the first and second " -"round of federated learning, and then for two epochs during the third round." +"As we can see, the client logs now include the current round of federated" +" learning (which they read from the ``config`` dictionary). We can also " +"configure local training to run for one epoch during the first and second" +" round of federated learning, and then for two epochs during the third " +"round." msgstr "" -"我们可以看到,客户端日志现在包含了当前一轮的联邦学习(从 ``config`` 字典中读" -"取)。我们还可以将本地训练配置为在第一轮和第二轮联邦学习期间运行一个遍历,然" -"后在第三轮联邦学习期间运行两个遍历。" +"我们可以看到,客户端日志现在包含了当前一轮的联邦学习(从 ``config`` " +"字典中读取)。我们还可以将本地训练配置为在第一轮和第二轮联邦学习期间运行一个遍历,然后在第三轮联邦学习期间运行两个遍历。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:615 msgid "" "Clients can also return arbitrary values to the server. To do so, they " -"return a dictionary from ``fit`` and/or ``evaluate``. We have seen and used " -"this concept throughout this notebook without mentioning it explicitly: our " -"``FlowerClient`` returns a dictionary containing a custom key/value pair as " -"the third return value in ``evaluate``." +"return a dictionary from ``fit`` and/or ``evaluate``. We have seen and " +"used this concept throughout this notebook without mentioning it " +"explicitly: our ``FlowerClient`` returns a dictionary containing a custom" +" key/value pair as the third return value in ``evaluate``." msgstr "" "客户端还可以向服务器返回任意值。为此,它们会从 ``fit`` 和/或 ``evaluate`` " -"返回一个字典。我们在本笔记中看到并使用了这一概念,但并未明确提及:我们的 " -"``FlowerClient`` 返回一个包含自定义键/值对的字典,作为 ``evaluate`` " -"中的第三个返回值。" +"返回一个字典。我们在本笔记中看到并使用了这一概念,但并未明确提及:我们的 ``FlowerClient`` 返回一个包含自定义键/值对的字典,作为" +" ``evaluate`` 中的第三个返回值。" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:627 msgid "Scaling federated learning" @@ -15590,20 +19528,19 @@ msgstr "作为本笔记的最后一步,让我们看看如何使用 Flower 对 #, python-format msgid "" "We now have 1000 partitions, each holding 45 training and 5 validation " -"examples. Given that the number of training examples on each client is quite " -"small, we should probably train the model a bit longer, so we configure the " -"clients to perform 3 local training epochs. We should also adjust the " -"fraction of clients selected for training during each round (we don't want " -"all 1000 clients participating in every round), so we adjust " -"``fraction_fit`` to ``0.05``, which means that only 5% of available clients " -"(so 50 clients) will be selected for training each round:" -msgstr "" -"现在我们有 1000 个分区,每个分区有 45 个训练数据和 5 个验证数据。鉴于每个客户" -"端上的训练示例数量较少,我们可能需要对模型进行更长时间的训练," -"因此我们将客户端配置为执行 3 " -"个本地训练遍历。我们还应该调整每轮训练中被选中的客户端的比例(" -"我们不希望每轮训练都有 1000 个客户端参与),因此我们将 ``fraction_fit`` " -"调整为 ``0.05``,这意味着每轮训练只选中 5%的可用客户端(即 50 个客户端):" +"examples. Given that the number of training examples on each client is " +"quite small, we should probably train the model a bit longer, so we " +"configure the clients to perform 3 local training epochs. We should also " +"adjust the fraction of clients selected for training during each round " +"(we don't want all 1000 clients participating in every round), so we " +"adjust ``fraction_fit`` to ``0.05``, which means that only 5% of " +"available clients (so 50 clients) will be selected for training each " +"round:" +msgstr "" +"现在我们有 1000 个分区,每个分区有 45 个训练数据和 5 " +"个验证数据。鉴于每个客户端上的训练示例数量较少,我们可能需要对模型进行更长时间的训练,因此我们将客户端配置为执行 3 " +"个本地训练遍历。我们还应该调整每轮训练中被选中的客户端的比例(我们不希望每轮训练都有 1000 个客户端参与),因此我们将 " +"``fraction_fit`` 调整为 ``0.05``,这意味着每轮训练只选中 5%的可用客户端(即 50 个客户端):" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:699 msgid "" @@ -15611,33 +19548,29 @@ msgid "" "customizing the strategy, initializing parameters on the server side, " "choosing a different strategy, and evaluating models on the server-side. " "That's quite a bit of flexibility with so little code, right?" -msgstr "" -"在本笔记中,我们看到了如何通过自定义策略、在服务器端初始化参数、选择不同的策" -"略以及在服务器端评估模型来逐步增强我们的系统。用这么少的代码就能实现这么大的" -"灵活性,不是吗?" +msgstr "在本笔记中,我们看到了如何通过自定义策略、在服务器端初始化参数、选择不同的策略以及在服务器端评估模型来逐步增强我们的系统。用这么少的代码就能实现这么大的灵活性,不是吗?" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:701 msgid "" -"In the later sections, we've seen how we can communicate arbitrary values " -"between server and clients to fully customize client-side execution. With " -"that capability, we built a large-scale Federated Learning simulation using " -"the Flower Virtual Client Engine and ran an experiment involving 1000 " -"clients in the same workload - all in a Jupyter Notebook!" +"In the later sections, we've seen how we can communicate arbitrary values" +" between server and clients to fully customize client-side execution. " +"With that capability, we built a large-scale Federated Learning " +"simulation using the Flower Virtual Client Engine and ran an experiment " +"involving 1000 clients in the same workload - all in a Jupyter Notebook!" msgstr "" -"在后面的章节中,我们将看到如何在服务器和客户端之间传递任意值,以完全自定义客" -"户端执行。有了这种能力,我们使用 Flower " -"虚拟客户端引擎构建了一个大规模的联邦学习模拟,并在 Jupyter Notebook " -"中进行了一次实验,在相同的工作负载中运行了 1000 个客户端!" +"在后面的章节中,我们将看到如何在服务器和客户端之间传递任意值,以完全自定义客户端执行。有了这种能力,我们使用 Flower " +"虚拟客户端引擎构建了一个大规模的联邦学习模拟,并在 Jupyter Notebook 中进行了一次实验,在相同的工作负载中运行了 1000 " +"个客户端!" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:719 msgid "" -"The `Flower Federated Learning Tutorial - Part 3 `__ shows how " -"to build a fully custom ``Strategy`` from scratch." +"The `Flower Federated Learning Tutorial - Part 3 " +"`__ shows how to build a fully custom ``Strategy`` " +"from scratch." msgstr "" "`Flower 联邦学习教程 - 第 3 部分 `__ " -"展示了如何从头开始构建完全自定义的 \"策略\"。" +"build-a-strategy-from-scratch-pytorch.html>`__ 展示了如何从头开始构建完全自定义的 \"策略\"。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:9 msgid "What is Federated Learning?" @@ -15647,33 +19580,30 @@ msgstr "什么是联邦学习?" msgid "" "In this tutorial, you will learn what federated learning is, build your " "first system in Flower, and gradually extend it. If you work through all " -"parts of the tutorial, you will be able to build advanced federated learning " -"systems that approach the current state of the art in the field." +"parts of the tutorial, you will be able to build advanced federated " +"learning systems that approach the current state of the art in the field." msgstr "" -"在本教程中,你将了解什么是联邦学习,用 Flower 搭建第一个系统,并逐步对其进行" -"扩展。如果你能完成本教程的所有部分,你就能构建高级的联邦学习系统,从而接近该" -"领域当前的技术水平。" +"在本教程中,你将了解什么是联邦学习,用 Flower " +"搭建第一个系统,并逐步对其进行扩展。如果你能完成本教程的所有部分,你就能构建高级的联邦学习系统,从而接近该领域当前的技术水平。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:15 msgid "" -"🧑‍🏫 This tutorial starts at zero and expects no familiarity with federated " -"learning. Only a basic understanding of data science and Python programming " -"is assumed." -msgstr "🧑‍🏫 本教程从零开始,不要求熟悉联邦学习。仅假定对数据科学和 Python " -"编程有基本了解。" +"🧑‍🏫 This tutorial starts at zero and expects no familiarity with " +"federated learning. Only a basic understanding of data science and Python" +" programming is assumed." +msgstr "🧑‍🏫 本教程从零开始,不要求熟悉联邦学习。仅假定对数据科学和 Python 编程有基本了解。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:17 msgid "" -"`Star Flower on GitHub `__ ⭐️ and join the " -"open-source Flower community on Slack to connect, ask questions, and get " -"help: `Join Slack `__ 🌼 We'd love to hear " -"from you in the ``#introductions`` channel! And if anything is unclear, head " -"over to the ``#questions`` channel." +"`Star Flower on GitHub `__ ⭐️ and join " +"the open-source Flower community on Slack to connect, ask questions, and " +"get help: `Join Slack `__ 🌼 We'd love to " +"hear from you in the ``#introductions`` channel! And if anything is " +"unclear, head over to the ``#questions`` channel." msgstr "" -"`Star Flower on GitHub `__ ⭐️ 并加入 Slack 上" -"的开源 Flower 社区,进行交流、提问并获得帮助: 加入 Slack `__ 🌼 我们希望在 ``#introductions`` 频道听到您的声音!如果有" -"任何不清楚的地方,请访问 ``#questions`` 频道。" +"`Star Flower on GitHub `__ ⭐️ 并加入 Slack " +"上的开源 Flower 社区,进行交流、提问并获得帮助: 加入 Slack `__ " +"🌼 我们希望在 ``#introductions`` 频道听到您的声音!如果有任何不清楚的地方,请访问 ``#questions`` 频道。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:19 msgid "Let's get started!" @@ -15685,22 +19615,20 @@ msgstr "经典机器学习" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:33 msgid "" -"Before we begin to discuss federated learning, let us quickly recap how most " -"machine learning works today." +"Before we begin to discuss federated learning, let us quickly recap how " +"most machine learning works today." msgstr "在开始讨论联邦学习之前,让我们先快速回顾一下目前大多数机器学习的工作原理。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:35 msgid "" -"In machine learning, we have a model, and we have data. The model could be a " -"neural network (as depicted here), or something else, like classical linear " -"regression." -msgstr "" -"在机器学习中,我们有一个模型和数据。模型可以是一个神经网络(如图所示),也可" -"以是其他东西,比如经典的线性回归。" +"In machine learning, we have a model, and we have data. The model could " +"be a neural network (as depicted here), or something else, like classical" +" linear regression." +msgstr "在机器学习中,我们有一个模型和数据。模型可以是一个神经网络(如图所示),也可以是其他东西,比如经典的线性回归。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:41 -msgid "|e1dd4b4129b040bea23a894266227080|" -msgstr "|e1dd4b4129b040bea23a894266227080|" +msgid "|31e4b1afa87c4b968327bbeafbf184d4|" +msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:109 msgid "Model and data" @@ -15708,16 +19636,14 @@ msgstr "模型和数据" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:47 msgid "" -"We train the model using the data to perform a useful task. A task could be " -"to detect objects in images, transcribe an audio recording, or play a game " -"like Go." -msgstr "" -"我们使用数据来训练模型,以完成一项有用的任务。任务可以是检测图像中的物体、转" -"录音频或玩围棋等游戏。" +"We train the model using the data to perform a useful task. A task could " +"be to detect objects in images, transcribe an audio recording, or play a " +"game like Go." +msgstr "我们使用数据来训练模型,以完成一项有用的任务。任务可以是检测图像中的物体、转录音频或玩围棋等游戏。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:53 -msgid "|c0d4cc6a442948dca8da40d2440068d9|" -msgstr "|c0d4cc6a442948dca8da40d2440068d9|" +msgid "|c9d935b4284e4c389a33d86b33e07c0a|" +msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:111 msgid "Train model using data" @@ -15725,23 +19651,20 @@ msgstr "使用数据训练模型" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:59 msgid "" -"Now, in practice, the training data we work with doesn't originate on the " -"machine we train the model on. It gets created somewhere else." -msgstr "" -"实际上,我们使用的训练数据并不来自我们训练模型的机器。它是在其他地方创建的。" +"Now, in practice, the training data we work with doesn't originate on the" +" machine we train the model on. It gets created somewhere else." +msgstr "实际上,我们使用的训练数据并不来自我们训练模型的机器。它是在其他地方创建的。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:61 msgid "" "It originates on a smartphone by the user interacting with an app, a car " "collecting sensor data, a laptop receiving input via the keyboard, or a " "smart speaker listening to someone trying to sing a song." -msgstr "" -"它源于智能手机上用户与应用程序的交互、汽车上传感器数据的收集、笔记本电脑上键" -"盘输入的接收,或者智能扬声器上某人试着唱的歌。" +msgstr "它源于智能手机上用户与应用程序的交互、汽车上传感器数据的收集、笔记本电脑上键盘输入的接收,或者智能扬声器上某人试着唱的歌。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:67 -msgid "|174e1e4fa1f149a19bfbc8bc1126f46a|" -msgstr "|174e1e4fa1f149a19bfbc8bc1126f46a|" +msgid "|00727b5faffb468f84dd1b03ded88638|" +msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:113 msgid "Data on a phone" @@ -15750,16 +19673,16 @@ msgstr "手机上的数据" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:73 msgid "" "What's also important to mention, this \"somewhere else\" is usually not " -"just one place, it's many places. It could be several devices all running " -"the same app. But it could also be several organizations, all generating " -"data for the same task." +"just one place, it's many places. It could be several devices all running" +" the same app. But it could also be several organizations, all generating" +" data for the same task." msgstr "" -"值得一提的是,这个 \"其他地方 \"通常不只是一个地方,而是很多地方。它可能是多" -"个运行同一应用程序的设备。但也可能是多个组织,都在为同一任务生成数据。" +"值得一提的是,这个 \"其他地方 " +"\"通常不只是一个地方,而是很多地方。它可能是多个运行同一应用程序的设备。但也可能是多个组织,都在为同一任务生成数据。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:79 -msgid "|4e021a3dc08249d2a89daa3ab03c2714|" -msgstr "|4e021a3dc08249d2a89daa3ab03c2714|" +msgid "|daf0cf0ff4c24fd29439af78416cf47b|" +msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:115 msgid "Data is on many devices" @@ -15767,16 +19690,15 @@ msgstr "数据存在于多种设备中" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:85 msgid "" -"So to use machine learning, or any kind of data analysis, the approach that " -"has been used in the past was to collect all data on a central server. This " -"server can be somewhere in a data center, or somewhere in the cloud." -msgstr "" -"因此,要使用机器学习或任何类型的数据分析,过去使用的方法是在中央服务器上收集" -"所有数据。这个服务器可以在数据中心的某个地方,也可以在云端的某个地方。" +"So to use machine learning, or any kind of data analysis, the approach " +"that has been used in the past was to collect all data on a central " +"server. This server can be somewhere in a data center, or somewhere in " +"the cloud." +msgstr "因此,要使用机器学习或任何类型的数据分析,过去使用的方法是在中央服务器上收集所有数据。这个服务器可以在数据中心的某个地方,也可以在云端的某个地方。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:91 -msgid "|e74a1d5ce7eb49688651f2167a59065b|" -msgstr "|e74a1d5ce7eb49688651f2167a59065b|" +msgid "|9f093007080d471d94ca90d3e9fde9b6|" +msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:117 msgid "Central data collection" @@ -15787,13 +19709,11 @@ msgid "" "Once all the data is collected in one place, we can finally use machine " "learning algorithms to train our model on the data. This is the machine " "learning approach that we've basically always relied on." -msgstr "" -"一旦所有数据都收集到一处,我们最终就可以使用机器学习算法在数据上训练我们的模" -"型。这就是我们基本上一直依赖的机器学习方法。" +msgstr "一旦所有数据都收集到一处,我们最终就可以使用机器学习算法在数据上训练我们的模型。这就是我们基本上一直依赖的机器学习方法。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:103 -msgid "|eb29ec4c7aef4e93976795ed72df647e|" -msgstr "|eb29ec4c7aef4e93976795ed72df647e|" +msgid "|46a26e6150e0479fbd3dfd655f36eb13|" +msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:119 msgid "Central model training" @@ -15805,17 +19725,15 @@ msgstr "经典机器学习面临的挑战" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:132 msgid "" -"The classic machine learning approach we've just seen can be used in some " -"cases. Great examples include categorizing holiday photos, or analyzing web " -"traffic. Cases, where all the data is naturally available on a centralized " -"server." -msgstr "" -"我们刚刚看到的经典机器学习方法可以在某些情况下使用。很好的例子包括对假日照片" -"进行分类或分析网络流量。在这些案例中,所有数据自然都可以在中央服务器上获得。" +"The classic machine learning approach we've just seen can be used in some" +" cases. Great examples include categorizing holiday photos, or analyzing " +"web traffic. Cases, where all the data is naturally available on a " +"centralized server." +msgstr "我们刚刚看到的经典机器学习方法可以在某些情况下使用。很好的例子包括对假日照片进行分类或分析网络流量。在这些案例中,所有数据自然都可以在中央服务器上获得。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:138 -msgid "|c2f699d8ac484f5081721a6f1511f70d|" -msgstr "|c2f699d8ac484f5081721a6f1511f70d|" +msgid "|3daba297595c4c7fb845d90404a6179a|" +msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:173 msgid "Centralized possible" @@ -15823,16 +19741,14 @@ msgstr "可集中管理" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:144 msgid "" -"But the approach can not be used in many other cases. Cases, where the data " -"is not available on a centralized server, or cases where the data available " -"on one server is not enough to train a good model." -msgstr "" -"但这种方法并不适用于许多其他情况。例如,集中服务器上没有数据,或者一台服务器" -"上的数据不足以训练出一个好的模型。" +"But the approach can not be used in many other cases. Cases, where the " +"data is not available on a centralized server, or cases where the data " +"available on one server is not enough to train a good model." +msgstr "但这种方法并不适用于许多其他情况。例如,集中服务器上没有数据,或者一台服务器上的数据不足以训练出一个好的模型。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:150 -msgid "|cf42accdacbf4e5eb4fa0503108ba7a7|" -msgstr "|cf42accdacbf4e5eb4fa0503108ba7a7|" +msgid "|5769874fa9c4455b80b2efda850d39d7|" +msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:175 msgid "Centralized impossible" @@ -15840,12 +19756,10 @@ msgstr "无法集中" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:156 msgid "" -"There are many reasons why the classic centralized machine learning approach " -"does not work for a large number of highly important real-world use cases. " -"Those reasons include:" -msgstr "" -"传统的集中式机器学习方法无法满足现实世界中大量极为重要的使用案例,原因有很" -"多。这些原因包括:" +"There are many reasons why the classic centralized machine learning " +"approach does not work for a large number of highly important real-world " +"use cases. Those reasons include:" +msgstr "传统的集中式机器学习方法无法满足现实世界中大量极为重要的使用案例,原因有很多。这些原因包括:" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:158 msgid "" @@ -15854,48 +19768,39 @@ msgid "" "(Russia), CDPR (China), PDPB (India), PIPA (Korea), APPI (Japan), PDP " "(Indonesia), PDPA (Singapore), APP (Australia), and other regulations " "protect sensitive data from being moved. In fact, those regulations " -"sometimes even prevent single organizations from combining their own users' " -"data for artificial intelligence training because those users live in " -"different parts of the world, and their data is governed by different data " -"protection regulations." -msgstr "" -"**法规**: GDPR(欧洲)、CCPA(加利福尼亚)、PIPEDA(加拿大)、LGPD(巴西)、" -"PDPL(阿根廷)、KVKK(土耳其)、POPI(南非)、FSS(俄罗斯)、CDPR(中国)、" -"PDPB(印度)、PIPA(韩国)、APPI(日本)、PDP(印度尼西亚)、PDPA(新加坡)、" -"APP(澳大利亚)等法规保护敏感数据不被移动。事实上,这些法规有时甚至会阻止单个" -"组织将自己的用户数据用于人工智能培训,因为这些用户生活在世界不同地区,他们的" -"数据受不同的数据保护法规管辖。" +"sometimes even prevent single organizations from combining their own " +"users' data for artificial intelligence training because those users live" +" in different parts of the world, and their data is governed by different" +" data protection regulations." +msgstr "" +"**法规**: " +"GDPR(欧洲)、CCPA(加利福尼亚)、PIPEDA(加拿大)、LGPD(巴西)、PDPL(阿根廷)、KVKK(土耳其)、POPI(南非)、FSS(俄罗斯)、CDPR(中国)、PDPB(印度)、PIPA(韩国)、APPI(日本)、PDP(印度尼西亚)、PDPA(新加坡)、APP(澳大利亚)等法规保护敏感数据不被移动。事实上,这些法规有时甚至会阻止单个组织将自己的用户数据用于人工智能培训,因为这些用户生活在世界不同地区,他们的数据受不同的数据保护法规管辖。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:160 msgid "" -"**User preference**: In addition to regulation, there are use cases where " -"users just expect that no data leaves their device, ever. If you type your " -"passwords and credit card info into the digital keyboard of your phone, you " -"don't expect those passwords to end up on the server of the company that " -"developed that keyboard, do you? In fact, that use case was the reason " -"federated learning was invented in the first place." +"**User preference**: In addition to regulation, there are use cases where" +" users just expect that no data leaves their device, ever. If you type " +"your passwords and credit card info into the digital keyboard of your " +"phone, you don't expect those passwords to end up on the server of the " +"company that developed that keyboard, do you? In fact, that use case was " +"the reason federated learning was invented in the first place." msgstr "" -"**用户偏好**: 除了法规之外,在一些使用案例中,用户只是希望数据永远不会离开他" -"们的设备。如果你在手机的数字键盘上输入密码和信用卡信息,你不会希望这些密码最" -"终出现在开发该键盘的公司的服务器上吧?事实上,这种用例正是联邦学习发明的初衷" -"。" +"**用户偏好**: " +"除了法规之外,在一些使用案例中,用户只是希望数据永远不会离开他们的设备。如果你在手机的数字键盘上输入密码和信用卡信息,你不会希望这些密码最终出现在开发该键盘的公司的服务器上吧?事实上,这种用例正是联邦学习发明的初衷。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:161 msgid "" -"**Data volume**: Some sensors, like cameras, produce such a high data volume " -"that it is neither feasible nor economic to collect all the data (due to, " -"for example, bandwidth or communication efficiency). Think about a national " -"rail service with hundreds of train stations across the country. If each of " -"these train stations is outfitted with a number of security cameras, the " -"volume of raw on-device data they produce requires incredibly powerful and " -"exceedingly expensive infrastructure to process and store. And most of the " -"data isn't even useful." -msgstr "" -"**数据量**: 有些传感器(如摄像头)产生的数据量很大,收集所有数据既不可行,也" -"不经济(例如,由于带宽或通信效率的原因)。试想一下全国铁路服务,全国有数百个" -"火车站。如果每个火车站都安装了许多安全摄像头,那么它们所产生的大量原始设备数" -"据就需要功能强大且极其昂贵的基础设施来处理和存储。而大部分数据甚至都是无用" -"的。" +"**Data volume**: Some sensors, like cameras, produce such a high data " +"volume that it is neither feasible nor economic to collect all the data " +"(due to, for example, bandwidth or communication efficiency). Think about" +" a national rail service with hundreds of train stations across the " +"country. If each of these train stations is outfitted with a number of " +"security cameras, the volume of raw on-device data they produce requires " +"incredibly powerful and exceedingly expensive infrastructure to process " +"and store. And most of the data isn't even useful." +msgstr "" +"**数据量**: " +"有些传感器(如摄像头)产生的数据量很大,收集所有数据既不可行,也不经济(例如,由于带宽或通信效率的原因)。试想一下全国铁路服务,全国有数百个火车站。如果每个火车站都安装了许多安全摄像头,那么它们所产生的大量原始设备数据就需要功能强大且极其昂贵的基础设施来处理和存储。而大部分数据甚至都是无用的。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:164 msgid "Examples where centralized machine learning does not work include:" @@ -15909,7 +19814,8 @@ msgstr "用多家医院的敏感医疗记录训练癌症检测模型" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:167 msgid "" -"Financial information from different organizations to detect financial fraud" +"Financial information from different organizations to detect financial " +"fraud" msgstr "不同组织的财务信息,以侦查财务欺诈行为" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:168 @@ -15922,18 +19828,16 @@ msgstr "端到端加密信息可训练出更好的自动完成模型" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:171 msgid "" -"The popularity of privacy-enhancing systems like the `Brave `__ browser or the `Signal `__ messenger shows " -"that users care about privacy. In fact, they choose the privacy-enhancing " -"version over other alternatives, if such an alernative exists. But what can " -"we do to apply machine learning and data science to these cases to utilize " -"private data? After all, these are all areas that would benefit " -"significantly from recent advances in AI." +"The popularity of privacy-enhancing systems like the `Brave " +"`__ browser or the `Signal `__ " +"messenger shows that users care about privacy. In fact, they choose the " +"privacy-enhancing version over other alternatives, if such an alernative " +"exists. But what can we do to apply machine learning and data science to " +"these cases to utilize private data? After all, these are all areas that " +"would benefit significantly from recent advances in AI." msgstr "" -"像 `Brave `__浏览器或 `Signal `__信" -"息管理器这样的隐私增强系统的流行表明,用户关心隐私。事实上,他们会选择隐私性" -"更好的产品。但是,我们能做些什么来将机器学习和数据科学应用到这些情况中,以利" -"用隐私数据呢?毕竟,这些领域都将从人工智能的最新进展中受益匪浅。" +"像 `Brave `__浏览器或 `Signal " +"`__信息管理器这样的隐私增强系统的流行表明,用户关心隐私。事实上,他们会选择隐私性更好的产品。但是,我们能做些什么来将机器学习和数据科学应用到这些情况中,以利用隐私数据呢?毕竟,这些领域都将从人工智能的最新进展中受益匪浅。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:186 msgid "Federated learning" @@ -15942,10 +19846,10 @@ msgstr "联邦学习" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:188 msgid "" "Federated learning simply reverses this approach. It enables machine " -"learning on distributed data by moving the training to the data, instead of " -"moving the data to the training. Here's the single-sentence explanation:" -msgstr "联邦学习简单地颠覆了这种方法。它通过将训练转移到数据上,而不是将数据转移到训" -"练上,在分布式数据上实现机器学习。下面是一句话的解释:" +"learning on distributed data by moving the training to the data, instead " +"of moving the data to the training. Here's the single-sentence " +"explanation:" +msgstr "联邦学习简单地颠覆了这种方法。它通过将训练转移到数据上,而不是将数据转移到训练上,在分布式数据上实现机器学习。下面是一句话的解释:" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:190 msgid "Central machine learning: move the data to the computation" @@ -15957,28 +19861,22 @@ msgstr "联邦式(机器)学习:将计算转移到数据上" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:193 msgid "" -"By doing so, it enables us to use machine learning (and other data science " -"approaches) in areas where it wasn't possible before. We can now train " -"excellent medical AI models by enabling different hospitals to work " -"together. We can solve financial fraud by training AI models on the data of " -"different financial institutions. We can build novel privacy-enhancing " -"applications (such as secure messaging) that have better built-in AI than " -"their non-privacy-enhancing alternatives. And those are just a few of the " -"examples that come to mind. As we deploy federated learning, we discover " -"more and more areas that can suddenly be reinvented because they now have " -"access to vast amounts of previously inaccessible data." -msgstr "" -"这样,我们就能在以前不可能的领域使用机器学习(和其他数据科学方法)。现在,我" -"们可以通过让不同的医院协同工作来训练优秀的医疗人工智能模型。我们可以通过在不" -"同金融机构的数据上训练人工智能模型来解决金融欺诈问题。我们可以构建新颖的隐私" -"增强型应用(如安全信息),其内置的人工智能比非隐私增强型应用更好。以上只是我" -"想到的几个例子。随着联邦学习的部署,我们会发现越来越多的领域可以突然重获新生" -",因为它们现在可以访问大量以前无法访问的数据。" +"By doing so, it enables us to use machine learning (and other data " +"science approaches) in areas where it wasn't possible before. We can now " +"train excellent medical AI models by enabling different hospitals to work" +" together. We can solve financial fraud by training AI models on the data" +" of different financial institutions. We can build novel privacy-" +"enhancing applications (such as secure messaging) that have better built-" +"in AI than their non-privacy-enhancing alternatives. And those are just a" +" few of the examples that come to mind. As we deploy federated learning, " +"we discover more and more areas that can suddenly be reinvented because " +"they now have access to vast amounts of previously inaccessible data." +msgstr "这样,我们就能在以前不可能的领域使用机器学习(和其他数据科学方法)。现在,我们可以通过让不同的医院协同工作来训练优秀的医疗人工智能模型。我们可以通过在不同金融机构的数据上训练人工智能模型来解决金融欺诈问题。我们可以构建新颖的隐私增强型应用(如安全信息),其内置的人工智能比非隐私增强型应用更好。以上只是我想到的几个例子。随着联邦学习的部署,我们会发现越来越多的领域可以突然重获新生,因为它们现在可以访问大量以前无法访问的数据。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:196 msgid "" -"So how does federated learning work, exactly? Let's start with an intuitive " -"explanation." +"So how does federated learning work, exactly? Let's start with an " +"intuitive explanation." msgstr "那么,联邦学习究竟是如何运作的呢?让我们从直观的解释开始。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:199 @@ -15991,16 +19889,14 @@ msgstr "步骤 0:初始化全局模型" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:204 msgid "" -"We start by initializing the model on the server. This is exactly the same " -"in classic centralized learning: we initialize the model parameters, either " -"randomly or from a previously saved checkpoint." -msgstr "" -"我们首先在服务器上初始化模型。这与经典的集中式学习完全相同:我们随机或从先前" -"保存的检查点初始化模型参数。" +"We start by initializing the model on the server. This is exactly the " +"same in classic centralized learning: we initialize the model parameters," +" either randomly or from a previously saved checkpoint." +msgstr "我们首先在服务器上初始化模型。这与经典的集中式学习完全相同:我们随机或从先前保存的检查点初始化模型参数。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:210 -msgid "|5ec8356bc2564fa09178b1ceed5beccc|" -msgstr "|5ec8356bc2564fa09178b1ceed5beccc|" +msgid "|ba47ffb421814b0f8f9fa5719093d839|" +msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:307 msgid "Initialize global model" @@ -16008,27 +19904,23 @@ msgstr "初始化全局模型" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:217 msgid "" -"Step 1: Send model to a number of connected organizations/devices (client " -"nodes)" +"Step 1: Send model to a number of connected organizations/devices (client" +" nodes)" msgstr "第 1 步:将模型发送到多个连接的组织/设备(客户节点)" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:219 msgid "" "Next, we send the parameters of the global model to the connected client " "nodes (think: edge devices like smartphones or servers belonging to " -"organizations). This is to ensure that each participating node starts their " -"local training using the same model parameters. We often use only a few of " -"the connected nodes instead of all nodes. The reason for this is that " -"selecting more and more client nodes has diminishing returns." -msgstr "" -"接下来,我们会将全局模型的参数发送到连接的客户端节点(如智能手机等边缘设备或" -"企业的服务器)。这是为了确保每个参与节点都使用相同的模型参数开始本地训练。我" -"们通常只使用几个连接节点,而不是所有节点。这样做的原因是,选择越来越多的客户" -"端节点会导致收益递减。" +"organizations). This is to ensure that each participating node starts " +"their local training using the same model parameters. We often use only a" +" few of the connected nodes instead of all nodes. The reason for this is " +"that selecting more and more client nodes has diminishing returns." +msgstr "接下来,我们会将全局模型的参数发送到连接的客户端节点(如智能手机等边缘设备或企业的服务器)。这是为了确保每个参与节点都使用相同的模型参数开始本地训练。我们通常只使用几个连接节点,而不是所有节点。这样做的原因是,选择越来越多的客户端节点会导致收益递减。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:225 -msgid "|7c9329e97bd0430bad335ab605a897a7|" -msgstr "|7c9329e97bd0430bad335ab605a897a7|" +msgid "|aeac5bf79cbf497082e979834717e01b|" +msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:309 msgid "Send global model" @@ -16036,27 +19928,25 @@ msgstr "发送全局模型" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:232 msgid "" -"Step 2: Train model locally on the data of each organization/device (client " -"node)" +"Step 2: Train model locally on the data of each organization/device " +"(client node)" msgstr "步骤 2:在本地对每个机构/设备(客户端节点)的数据进行模型训练" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:234 msgid "" -"Now that all (selected) client nodes have the latest version of the global " -"model parameters, they start the local training. They use their own local " -"dataset to train their own local model. They don't train the model until " -"full convergence, but they only train for a little while. This could be as " -"little as one epoch on the local data, or even just a few steps (mini-" -"batches)." +"Now that all (selected) client nodes have the latest version of the " +"global model parameters, they start the local training. They use their " +"own local dataset to train their own local model. They don't train the " +"model until full convergence, but they only train for a little while. " +"This could be as little as one epoch on the local data, or even just a " +"few steps (mini-batches)." msgstr "" -"现在,所有(选定的)客户端节点都有了最新版本的全局模型参数,它们开始进行本地" -"训练。它们使用自己的本地数据集来训练自己的本地模型。它们不会一直训练到模型完" -"全收敛为止,而只是训练一小段时间。这可能只是本地数据上的一个遍历,甚至只是几" -"个步骤(mini-batches)。" +"现在,所有(选定的)客户端节点都有了最新版本的全局模型参数,它们开始进行本地训练。它们使用自己的本地数据集来训练自己的本地模型。它们不会一直训练到模型完全收敛为止,而只是训练一小段时间。这可能只是本地数据上的一个遍历,甚至只是几个步骤" +"(mini-batches)。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:240 -msgid "|88002bbce1094ba1a83c9151df18f707|" -msgstr "|88002bbce1094ba1a83c9151df18f707|" +msgid "|ce27ed4bbe95459dba016afc42486ba2|" +msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:311 msgid "Train on local data" @@ -16068,21 +19958,18 @@ msgstr "步骤 3:将模型参数更新返回服务器" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:249 msgid "" -"After local training, each client node has a slightly different version of " -"the model parameters they originally received. The parameters are all " +"After local training, each client node has a slightly different version " +"of the model parameters they originally received. The parameters are all " "different because each client node has different examples in its local " -"dataset. The client nodes then send those model updates back to the server. " -"The model updates they send can either be the full model parameters or just " -"the gradients that were accumulated during local training." -msgstr "" -"经过本地训练后,每个客户节点最初收到的模型参数都会略有不同。参数之所以不同," -"是因为每个客户端节点的本地数据集中都有不同的数据。然后,客户端节点将这些模型" -"更新发回服务器。它们发送的模型更新既可以是完整的模型参数,也可以只是本地训练" -"过程中积累的梯度。" +"dataset. The client nodes then send those model updates back to the " +"server. The model updates they send can either be the full model " +"parameters or just the gradients that were accumulated during local " +"training." +msgstr "经过本地训练后,每个客户节点最初收到的模型参数都会略有不同。参数之所以不同,是因为每个客户端节点的本地数据集中都有不同的数据。然后,客户端节点将这些模型更新发回服务器。它们发送的模型更新既可以是完整的模型参数,也可以只是本地训练过程中积累的梯度。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:255 -msgid "|391766aee87c482c834c93f7c22225e2|" -msgstr "|391766aee87c482c834c93f7c22225e2|" +msgid "|ae94a7f71dda443cbec2385751427d41|" +msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:313 msgid "Send model updates" @@ -16095,43 +19982,40 @@ msgstr "步骤 4:将模型更新聚合到新的全局模型中" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:264 msgid "" "The server receives model updates from the selected client nodes. If it " -"selected 100 client nodes, it now has 100 slightly different versions of the " -"original global model, each trained on the local data of one client. But " -"didn't we want to have one model that contains the learnings from the data " -"of all 100 client nodes?" +"selected 100 client nodes, it now has 100 slightly different versions of " +"the original global model, each trained on the local data of one client. " +"But didn't we want to have one model that contains the learnings from the" +" data of all 100 client nodes?" msgstr "" -"服务器从选定的客户端节点接收模型更新。如果服务器选择了 100 个客户端节点,那么" -"它现在就拥有 100 个略有不同的原始全局模型版本,每个版本都是根据一个客户端的本" -"地数据训练出来的。难道我们不希望有一个包含所有 100 个客户节点数据的模型吗?" +"服务器从选定的客户端节点接收模型更新。如果服务器选择了 100 个客户端节点,那么它现在就拥有 100 " +"个略有不同的原始全局模型版本,每个版本都是根据一个客户端的本地数据训练出来的。难道我们不希望有一个包含所有 100 个客户节点数据的模型吗?" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:266 msgid "" -"In order to get one single model, we have to combine all the model updates " -"we received from the client nodes. This process is called *aggregation*, and " -"there are many different ways to do it. The most basic way to do it is " -"called *Federated Averaging* (`McMahan et al., 2016 `__), often abbreviated as *FedAvg*. *FedAvg* takes the 100 " -"model updates and, as the name suggests, averages them. To be more precise, " -"it takes the *weighted average* of the model updates, weighted by the number " -"of examples each client used for training. The weighting is important to " -"make sure that each data example has the same \"influence\" on the resulting " -"global model. If one client has 10 examples, and another client has 100 " -"examples, then - without weighting - each of the 10 examples would influence " -"the global model ten times as much as each of the 100 examples." -msgstr "" -"为了得到一个单一的模型,我们必须将从客户端节点收到的所有模型更新合并起来。这" -"个过程称为*聚合*,有许多不同的方法。最基本的方法称为 *Federated Averaging* " -"(`McMahan等人,2016 `__),通常缩写为*FedAvg*。*FedAvg* 可以把100 个模型更新进行平均。更准确" -"地说,它取的是模型更新的*加权平均值*,根据每个客户端用于训练的数据数量进行加" -"权。加权对于确保每个数据示例对生成的全局模型具有相同的 \"影响 \"非常重要。" -"如果一个客户端有 10 个数据点,而另一个客户有 100 " -"个数据点,那么在不加权的情况下,10 个示例对全局模型的影响是 100 个示例的 10 " -"倍。" +"In order to get one single model, we have to combine all the model " +"updates we received from the client nodes. This process is called " +"*aggregation*, and there are many different ways to do it. The most basic" +" way to do it is called *Federated Averaging* (`McMahan et al., 2016 " +"`__), often abbreviated as *FedAvg*. " +"*FedAvg* takes the 100 model updates and, as the name suggests, averages " +"them. To be more precise, it takes the *weighted average* of the model " +"updates, weighted by the number of examples each client used for " +"training. The weighting is important to make sure that each data example " +"has the same \"influence\" on the resulting global model. If one client " +"has 10 examples, and another client has 100 examples, then - without " +"weighting - each of the 10 examples would influence the global model ten " +"times as much as each of the 100 examples." +msgstr "" +"为了得到一个单一的模型,我们必须将从客户端节点收到的所有模型更新合并起来。这个过程称为*聚合*,有许多不同的方法。最基本的方法称为 " +"*Federated Averaging* (`McMahan等人,2016 " +"`__),通常缩写为*FedAvg*。*FedAvg* 可以把100 " +"个模型更新进行平均。更准确地说,它取的是模型更新的*加权平均值*,根据每个客户端用于训练的数据数量进行加权。加权对于确保每个数据示例对生成的全局模型具有相同的" +" \"影响 \"非常重要。如果一个客户端有 10 个数据点,而另一个客户有 100 个数据点,那么在不加权的情况下,10 个示例对全局模型的影响是" +" 100 个示例的 10 倍。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:273 -msgid "|93b9a15bd27f4e91b40f642c253dfaac|" -msgstr "|93b9a15bd27f4e91b40f642c253dfaac|" +msgid "|e61fce4d43d243e7bb08bdde97d81ce6|" +msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:315 msgid "Aggregate model updates" @@ -16144,56 +20028,50 @@ msgstr "步骤 5:重复步骤 1 至 4,直至模型收敛" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:282 msgid "" "Steps 1 to 4 are what we call a single round of federated learning. The " -"global model parameters get sent to the participating client nodes (step 1), " -"the client nodes train on their local data (step 2), they send their updated " -"models to the server (step 3), and the server then aggregates the model " -"updates to get a new version of the global model (step 4)." +"global model parameters get sent to the participating client nodes (step " +"1), the client nodes train on their local data (step 2), they send their " +"updated models to the server (step 3), and the server then aggregates the" +" model updates to get a new version of the global model (step 4)." msgstr "" -"步骤 1 至 4 " -"就是我们所说的单轮联邦学习。全局模型参数被发送到参与的客户端节点(第 1 " -"步),客户端节点对其本地数据进行训练(第 2 " -"步),然后将更新后的模型发送到服务器(第 3 " -"步),服务器汇总模型更新,得到新版本的全局模型(第 4 步)。" +"步骤 1 至 4 就是我们所说的单轮联邦学习。全局模型参数被发送到参与的客户端节点(第 1 步),客户端节点对其本地数据进行训练(第 2 " +"步),然后将更新后的模型发送到服务器(第 3 步),服务器汇总模型更新,得到新版本的全局模型(第 4 步)。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:284 msgid "" -"During a single round, each client node that participates in that iteration " -"only trains for a little while. This means that after the aggregation step " -"(step 4), we have a model that has been trained on all the data of all " -"participating client nodes, but only for a little while. We then have to " -"repeat this training process over and over again to eventually arrive at a " -"fully trained model that performs well across the data of all client nodes." +"During a single round, each client node that participates in that " +"iteration only trains for a little while. This means that after the " +"aggregation step (step 4), we have a model that has been trained on all " +"the data of all participating client nodes, but only for a little while. " +"We then have to repeat this training process over and over again to " +"eventually arrive at a fully trained model that performs well across the " +"data of all client nodes." msgstr "" -"在一轮迭代中,每个参与迭代的客户节点只训练一小段时间。这意味着,在聚合步骤" -"(步骤 4)之后,我们的模型已经在所有参与的客户节点的所有数据上训练过了,但只" -"训练了一小会儿。然后,我们必须一次又一次地重复这一训练过程,最终得到一个经过" -"全面训练的模型,该模型在所有客户节点的数据中都表现良好。" +"在一轮迭代中,每个参与迭代的客户节点只训练一小段时间。这意味着,在聚合步骤(步骤 " +"4)之后,我们的模型已经在所有参与的客户节点的所有数据上训练过了,但只训练了一小会儿。然后,我们必须一次又一次地重复这一训练过程,最终得到一个经过全面训练的模型,该模型在所有客户节点的数据中都表现良好。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:289 msgid "" "Congratulations, you now understand the basics of federated learning. " -"There's a lot more to discuss, of course, but that was federated learning in " -"a nutshell. In later parts of this tutorial, we will go into more detail. " -"Interesting questions include: How can we select the best client nodes that " -"should participate in the next round? What's the best way to aggregate model " -"updates? How can we handle failing client nodes (stragglers)?" +"There's a lot more to discuss, of course, but that was federated learning" +" in a nutshell. In later parts of this tutorial, we will go into more " +"detail. Interesting questions include: How can we select the best client " +"nodes that should participate in the next round? What's the best way to " +"aggregate model updates? How can we handle failing client nodes " +"(stragglers)?" msgstr "" -"恭喜您,现在您已经了解了联邦学习的基础知识。当然,要讨论的内容还有很多,但这" -"只是联邦学习的一个缩影。在本教程的后半部分,我们将进行更详细的介绍。" -"有趣的问题包括 我们如何选择最好的客户端节点参与下一轮学习?聚合模型更新的最佳" -"方法是什么?如何处理失败的客户端节点(落伍者)?" +"恭喜您,现在您已经了解了联邦学习的基础知识。当然,要讨论的内容还有很多,但这只是联邦学习的一个缩影。在本教程的后半部分,我们将进行更详细的介绍。有趣的问题包括" +" 我们如何选择最好的客户端节点参与下一轮学习?聚合模型更新的最佳方法是什么?如何处理失败的客户端节点(落伍者)?" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:294 msgid "" -"Just like we can train a model on the decentralized data of different client " -"nodes, we can also evaluate the model on that data to receive valuable " -"metrics. This is called federated evaluation, sometimes abbreviated as FE. " -"In fact, federated evaluation is an integral part of most federated learning " -"systems." +"Just like we can train a model on the decentralized data of different " +"client nodes, we can also evaluate the model on that data to receive " +"valuable metrics. This is called federated evaluation, sometimes " +"abbreviated as FE. In fact, federated evaluation is an integral part of " +"most federated learning systems." msgstr "" -"就像我们可以在不同客户节点的分散数据上训练一个模型一样,我们也可以在这些数据" -"上对模型进行评估,以获得有价值的指标。这就是所谓的联邦评估,有时简称为 " -"FE。事实上,联邦评估是大多数联邦学习系统不可或缺的一部分。" +"就像我们可以在不同客户节点的分散数据上训练一个模型一样,我们也可以在这些数据上对模型进行评估,以获得有价值的指标。这就是所谓的联邦评估,有时简称为" +" FE。事实上,联邦评估是大多数联邦学习系统不可或缺的一部分。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:297 msgid "Federated analytics" @@ -16201,18 +20079,15 @@ msgstr "联邦分析" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:299 msgid "" -"In many cases, machine learning isn't necessary to derive value from data. " -"Data analysis can yield valuable insights, but again, there's often not " -"enough data to get a clear answer. What's the average age at which people " -"develop a certain type of health condition? Federated analytics enables such " -"queries over multiple client nodes. It is usually used in conjunction with " -"other privacy-enhancing technologies like secure aggregation to prevent the " -"server from seeing the results submitted by individual client nodes." -msgstr "" -"在很多情况下,机器学习并不是从数据中获取价值的必要条件。数据分析可以产生有价" -"值的见解,但同样,往往没有足够的数据来获得明确的答案。人们患某种健康疾病的平" -"均年龄是多少?联邦分析可以通过多个客户端节点进行此类查询。它通常与安全聚合等" -"其他隐私增强技术结合使用,以防止服务器看到单个客户端节点提交的结果。" +"In many cases, machine learning isn't necessary to derive value from " +"data. Data analysis can yield valuable insights, but again, there's often" +" not enough data to get a clear answer. What's the average age at which " +"people develop a certain type of health condition? Federated analytics " +"enables such queries over multiple client nodes. It is usually used in " +"conjunction with other privacy-enhancing technologies like secure " +"aggregation to prevent the server from seeing the results submitted by " +"individual client nodes." +msgstr "在很多情况下,机器学习并不是从数据中获取价值的必要条件。数据分析可以产生有价值的见解,但同样,往往没有足够的数据来获得明确的答案。人们患某种健康疾病的平均年龄是多少?联邦分析可以通过多个客户端节点进行此类查询。它通常与安全聚合等其他隐私增强技术结合使用,以防止服务器看到单个客户端节点提交的结果。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:303 msgid "Differential Privacy" @@ -16221,17 +20096,15 @@ msgstr "差分隐私" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:305 msgid "" "Differential privacy (DP) is often mentioned in the context of Federated " -"Learning. It is a privacy-preserving method used when analyzing and sharing " -"statistical data, ensuring the privacy of individual participants. DP " -"achieves this by adding statistical noise to the model updates, ensuring any " -"individual participants’ information cannot be distinguished or re-" -"identified. This technique can be considered an optimization that provides a " -"quantifiable privacy protection measure." -msgstr "" -"差分隐私(DP)经常在联邦学习中被提及。这是一种在分析和共享统计数据时使用的隐" -"私保护方法,可确保单个参与者的隐私。DP 通过在模型更新中添加统计噪声来实现这一" -"目的,确保任何个体参与者的信息都无法被区分或重新识别。这种技术可被视为一种优" -"化,提供了一种可量化的隐私保护措施。" +"Learning. It is a privacy-preserving method used when analyzing and " +"sharing statistical data, ensuring the privacy of individual " +"participants. DP achieves this by adding statistical noise to the model " +"updates, ensuring any individual participants’ information cannot be " +"distinguished or re-identified. This technique can be considered an " +"optimization that provides a quantifiable privacy protection measure." +msgstr "" +"差分隐私(DP)经常在联邦学习中被提及。这是一种在分析和共享统计数据时使用的隐私保护方法,可确保单个参与者的隐私。DP " +"通过在模型更新中添加统计噪声来实现这一目的,确保任何个体参与者的信息都无法被区分或重新识别。这种技术可被视为一种优化,提供了一种可量化的隐私保护措施。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:326 msgid "Flower" @@ -16239,132 +20112,381 @@ msgstr "Flower" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:328 msgid "" -"Federated learning, federated evaluation, and federated analytics require " -"infrastructure to move machine learning models back and forth, train and " -"evaluate them on local data, and then aggregate the updated models. Flower " -"provides the infrastructure to do exactly that in an easy, scalable, and " -"secure way. In short, Flower presents a unified approach to federated " -"learning, analytics, and evaluation. It allows the user to federate any " -"workload, any ML framework, and any programming language." +"Federated learning, federated evaluation, and federated analytics require" +" infrastructure to move machine learning models back and forth, train and" +" evaluate them on local data, and then aggregate the updated models. " +"Flower provides the infrastructure to do exactly that in an easy, " +"scalable, and secure way. In short, Flower presents a unified approach to" +" federated learning, analytics, and evaluation. It allows the user to " +"federate any workload, any ML framework, and any programming language." msgstr "" -"联邦学习、联邦评估和联邦分析需要基础框架来来回移动机器学习模型,在本地数据上" -"对其进行训练和评估,然后汇总更新的模型。Flower " +"联邦学习、联邦评估和联邦分析需要基础框架来来回移动机器学习模型,在本地数据上对其进行训练和评估,然后汇总更新的模型。Flower " "提供的基础架构正是以简单、可扩展和安全的方式实现这些目标的。简而言之,Flower " -"为联邦学习、分析和评估提供了一种统一的方法。它允许用户联邦化任何工作负载、" -"任何 ML 框架和任何编程语言。" +"为联邦学习、分析和评估提供了一种统一的方法。它允许用户联邦化任何工作负载、任何 ML 框架和任何编程语言。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:334 -msgid "|a23d9638f96342ef9d25209951e2d564|" -msgstr "|a23d9638f96342ef9d25209951e2d564|" +msgid "|08cb60859b07461588fe44e55810b050|" +msgstr "" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:340 msgid "" -"Flower federated learning server and client nodes (car, scooter, personal " -"computer, roomba, and phone)" +"Flower federated learning server and client nodes (car, scooter, personal" +" computer, roomba, and phone)" msgstr "Flower联邦学习服务器和客户端节点(汽车、滑板车、个人电脑、roomba 和电话)" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:353 msgid "" -"Congratulations, you just learned the basics of federated learning and how " -"it relates to the classic (centralized) machine learning!" -msgstr "恭喜您,您刚刚了解了联邦学习的基础知识,以及它与传统(集中式)机器学习的关系" -"!" +"Congratulations, you just learned the basics of federated learning and " +"how it relates to the classic (centralized) machine learning!" +msgstr "恭喜您,您刚刚了解了联邦学习的基础知识,以及它与传统(集中式)机器学习的关系!" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:355 msgid "" -"In the next part of this tutorial, we are going to build a first federated " -"learning system with Flower." +"In the next part of this tutorial, we are going to build a first " +"federated learning system with Flower." msgstr "在本教程的下一部分,我们将用 Flower 建立第一个联邦学习系统。" #: ../../source/tutorial-series-what-is-federated-learning.ipynb:373 msgid "" -"The `Flower Federated Learning Tutorial - Part 1 `__ shows how to " -"build a simple federated learning system with PyTorch and Flower." +"The `Flower Federated Learning Tutorial - Part 1 " +"`__ shows how to build a simple federated learning system " +"with PyTorch and Flower." msgstr "" -"`Flower 联邦学习教程 - 第 1 部分 `__ 展示了如何使用 PyTorch 和 Flower " +"`Flower 联邦学习教程 - 第 1 部分 `__ 展示了如何使用 PyTorch 和 Flower " "构建一个简单的联邦学习系统。" -#: ../../source/contributor-how-to-install-development-versions.rst:62 -msgid "Upload the whl (e.g., ``flwr-1.6.0-py3-none-any.whl``)" -msgstr "上传 whl(例如 ``flwr-1.6.0-py3-none-any.whl``)" - -#: ../../source/contributor-how-to-install-development-versions.rst:63 -msgid "" -"Change ``!pip install -q 'flwr[simulation]' torch torchvision matplotlib`` " -"to ``!pip install -q 'flwr-1.6.0-py3-none-any.whl[simulation]' torch " -"torchvision matplotlib``" -msgstr "" -"将``!pip install -q 'flwr[simulation]' torch torchvision matplotlib``更改为" -"``!pip install -q 'flwr-1.6.0-py3-none-any.whl[simulation]' torch torch " -"torchvision matplotlib``" - -#: ../../source/example-pytorch-from-centralized-to-federated.rst:280 -msgid "" -"All that's left to do it to define a function that loads both model and " -"data, creates a :code:`CifarClient`, and starts this client. You load your " -"data and model by using :code:`cifar.py`. Start :code:`CifarClient` with the " -"function :code:`fl.client.start_numpy_client()` by pointing it at the same " -"IP adress we used in :code:`server.py`:" -msgstr "" -"剩下要做的就是定义一个加载模型和数据的函数,创建一个 :code:`CifarClient` 并启" -"动该客户端。使用 :code:`cifar.py` 加载数据和模型。使用函数 :code:`fl.client." -"start_numpy_client()` 启动 :code:`CifarClient`,将其指向我们在 :code:`server." -"py` 中使用的相同 IP 地址:" - -#: ../../source/how-to-run-simulations.rst:10 -msgid "" -"The :code:`VirtualClientEngine` schedules, launches and manages `virtual` " -"clients. These clients are identical to `non-virtual` clients (i.e. the ones " -"you launch via the command `flwr.client.start_numpy_client `_) in the sense that they can be configure by " -"creating a class inheriting, for example, from `flwr.client.NumPyClient `_ and therefore behave in an " -"identical way. In addition to that, clients managed by the :code:" -"`VirtualClientEngine` are:" -msgstr "" -"代码:`VirtualClientEngine`调度、启动和管理`虚拟`客户端。这些客户端与 \"非虚拟" -" \"客户端(即通过命令 `flwr.client.start_numpy_client `_启动的客户端)完全相同,它们可以通过创建一个继承自 " -"\"flwr.client.NumPyClient `_\" " -"的类来配置,因此行为方式也完全相同。除此之外,由 :code:`VirtualClientEngine` " -"管理的客户端还包括:" - -#: ../../source/tutorial-quickstart-mxnet.rst:217 -#: ../../source/tutorial-quickstart-scikitlearn.rst:150 -msgid "" -"That's it for the client. We only have to implement :code:`Client` or :code:" -"`NumPyClient` and call :code:`fl.client.start_client()` or :code:`fl.client." -"start_numpy_client()`. The string :code:`\"0.0.0.0:8080\"` tells the client " -"which server to connect to. In our case we can run the server and the client " -"on the same machine, therefore we use :code:`\"0.0.0.0:8080\"`. If we run a " -"truly federated workload with the server and clients running on different " -"machines, all that needs to change is the :code:`server_address` we pass to " -"the client." -msgstr "" -"这就是客户端。我们只需实现 :code:`Client` 或 :code:`NumPyClient` 并调用 " -":code:`fl.client.start_client()` 或 :code:`fl.client.start_numpy_client()`。" -"字符串 :code:`\"0.0.0.0:8080\"`会告诉客户端要连接的服务器。在本例中,我们可以" -"在同一台机器上运行服务器和客户端,因此我们使用 :code:`\"0.0.0.0:8080\"" -"`。如果我们运行的是真正的联邦工作负载,服务器和客户端运行在不同的机器上," -"那么需要改变的只是传递给客户端的 :code:`server_address`。" +#~ msgid "Before the release" +#~ msgstr "发布前" + +#~ msgid "" +#~ "Update the changelog (``changelog.md``) with" +#~ " all relevant changes that happened " +#~ "after the last release. If the " +#~ "last release was tagged ``v1.2.0``, you" +#~ " can use the following URL to " +#~ "see all commits that got merged " +#~ "into ``main`` since then:" +#~ msgstr "" +#~ "更新更新日志 (``changelog.md``),加入上次发布后发生的所有相关变更。如果上次发布的版本被标记为 " +#~ "``v1.2.0``,则可以使用以下 URL 查看此后合并到 ``main`` 的所有提交:" + +#~ msgid "" +#~ "`GitHub: Compare v1.2.0...main " +#~ "`_" +#~ msgstr "" +#~ "`GitHub: Compare v1.2.0...main " +#~ "`_" + +#~ msgid "" +#~ "Thank the authors who contributed since" +#~ " the last release. This can be " +#~ "done by running the ``./dev/add-" +#~ "shortlog.sh`` convenience script (it can " +#~ "be ran multiple times and will " +#~ "update the names in the list if" +#~ " new contributors were added in the" +#~ " meantime)." +#~ msgstr "" +#~ "感谢自上次发布以来做出贡献的作者。可以通过运行 ``./dev/add-shortlog.sh`` " +#~ "方便脚本来完成(可以多次运行,如果在此期间有新的贡献者加入,则会更新列表中的名字)。" + +#~ msgid "" +#~ "Update the ``changelog.md`` section header " +#~ "``Unreleased`` to contain the version " +#~ "number and date for the release " +#~ "you are building. Create a pull " +#~ "request with the change." +#~ msgstr "" +#~ "更新 ``changelog.md`` 部分的标题 ``Unreleased`` " +#~ "以包含你正在构建的版本的版本号和日期。创建一个包含更改的拉取请求。" + +#~ msgid "" +#~ "Second, create a virtual environment " +#~ "(and activate it). If you chose to" +#~ " use :code:`pyenv` (with the :code" +#~ ":`pyenv-virtualenv` plugin) and already " +#~ "have it installed , you can use" +#~ " the following convenience script (by " +#~ "default it will use :code:`Python " +#~ "3.8.17`, but you can change it by" +#~ " providing a specific :code:``)::" +#~ msgstr "" +#~ "其次,创建虚拟环境(并激活它)。如果您选择使用 :code:`pyenv`(使用 :code:`pyenv-" +#~ "virtualenv`插件),并且已经安装了该插件,则可以使用下面的便捷脚本(默认情况下使用 " +#~ ":code:`Python3.8.17`,但您可以通过提供特定的 :code:`<版本>`来更改)::" + +#~ msgid "flwr (Python API reference)" +#~ msgstr "flwr(Python API 参考)" + +#~ msgid "..." +#~ msgstr "..." + +#~ msgid "Starting a client with an insecure server connection:" +#~ msgstr "使用不安全的服务器连接启动客户端:" + +#~ msgid "server.strategy.FedAvg" +#~ msgstr "server.strategy.FedAvg" + +#~ msgid "server.strategy.FedAvgM" +#~ msgstr "server.strategy.FedAvgM" + +#~ msgid "Configurable FedAvg with Momentum strategy implementation." +#~ msgstr "可配置的 FedAvg 动量策略实施。" + +#~ msgid "Fraction of clients used during training. Defaults to 0.1." +#~ msgstr "训练期间使用客户的比例。默认为 0.1。" + +#~ msgid "Fraction of clients used during validation. Defaults to 0.1." +#~ msgstr "验证过程中使用的客户端比例。默认为 0.1。" + +#~ msgid "server.strategy.FedMedian" +#~ msgstr "server.strategy.FedMedian" + +#~ msgid "server.strategy.QFedAvg" +#~ msgstr "server.strategy.QFedAvg" + +#~ msgid "server.strategy.FedOpt" +#~ msgstr "server.strategy.FedOpt" + +#~ msgid "Configurable FedAdagrad strategy implementation." +#~ msgstr "可配置的 FedAdagrad 策略实施。" + +#~ msgid "Federated Optim strategy interface." +#~ msgstr "Federated Optim 策略界面。" + +#~ msgid "server.strategy.FedProx" +#~ msgstr "server.strategy.FedProx" + +#~ msgid "Configurable FedProx strategy implementation." +#~ msgstr "可配置的 FedProx 策略实施。" + +#~ msgid "server.strategy.FedAdagrad" +#~ msgstr "server.strategy.FedAdagrad" + +#~ msgid "Paper: https://arxiv.org/abs/2003.00295" +#~ msgstr "论文: https://arxiv.org/abs/2003.00295" + +#~ msgid "Federated learning strategy using Adagrad on server-side." +#~ msgstr "在服务器端使用 Adagrad 的联邦学习策略。" + +#~ msgid "server.strategy.FedAdam" +#~ msgstr "server.strategy.FedAdam" + +#~ msgid "server.strategy.FedYogi" +#~ msgstr "server.strategy.FedYogi" + +#~ msgid "Adaptive Federated Optimization using Yogi." +#~ msgstr "使用 Yogi 的自适应联合优化。" + +#~ msgid "Federated learning strategy using Yogi on server-side." +#~ msgstr "在服务器端使用 Yogi 的联邦学习策略。" + +#~ msgid "Paper: https://arxiv.org/abs/1803.01498" +#~ msgstr "论文:https://arxiv.org/abs/1803.01498" + +#~ msgid "server.strategy.Krum" +#~ msgstr "server.strategy.Krum" + +#~ msgid "Configurable Krum strategy implementation." +#~ msgstr "可配置的 Krum 策略实施。" + +#~ msgid "server.strategy.Bulyan" +#~ msgstr "server.strategy.Bulyan" + +#~ msgid "Bulyan strategy implementation." +#~ msgstr "Bulyan策略的实施。" + +#~ msgid "server.strategy.FedXgbNnAvg" +#~ msgstr "server.strategy.FedXgbNnAvg" + +#~ msgid "Federated XGBoost [Ma et al., 2023] strategy." +#~ msgstr "Federated XGBoost [Ma 等人,2023] 策略。" + +#~ msgid "server.strategy.DPFedAvgAdaptive" +#~ msgstr "server.strategy.DPFedAvgAdaptive" + +#~ msgid "" +#~ "**Fix the incorrect return types of " +#~ "Strategy** " +#~ "([#2432](https://github.com/adap/flower/pull/2432/files))" +#~ msgstr "" +#~ "**修复策略的错误返回类型** " +#~ "([#2432](https://github.com/adap/flower/pull/2432/files))" + +#~ msgid "" +#~ "The types of the return values in" +#~ " the docstrings in two methods " +#~ "(`aggregate_fit` and `aggregate_evaluate`) now " +#~ "match the hint types in the code." +#~ msgstr "" +#~ "两个方法(\"aggregate_fit \"和 " +#~ "\"aggregate_evaluate\")的文档说明中的返回值类型现在与代码中的提示类型一致。" + +#~ msgid "" +#~ "**Update Flower Examples** " +#~ "([#2384](https://github.com/adap/flower/pull/2384),[#2425](https://github.com/adap/flower/pull/2425)," +#~ " [#2526](https://github.com/adap/flower/pull/2526))" +#~ msgstr "" +#~ "** 更新 Flower Examples** " +#~ "([#2384](https://github.com/adap/flower/pull/2384),[#2425](https://github.com/adap/flower/pull/2425)," +#~ " [#2526](https://github.com/adap/flower/pull/2526))" + +#~ msgid "" +#~ "That's it for the client. We only" +#~ " have to implement :code:`Client` or " +#~ ":code:`NumPyClient` and call " +#~ ":code:`fl.client.start_client()`. The string " +#~ ":code:`\"0.0.0.0:8080\"` tells the client " +#~ "which server to connect to. In our" +#~ " case we can run the server and" +#~ " the client on the same machine, " +#~ "therefore we use :code:`\"0.0.0.0:8080\"`. If" +#~ " we run a truly federated workload" +#~ " with the server and clients running" +#~ " on different machines, all that " +#~ "needs to change is the " +#~ ":code:`server_address` we pass to the " +#~ "client." +#~ msgstr "" +#~ "对于客户端就需要做这么多。我们仅需要实现 " +#~ ":code:`Client`或者:code:`NumPyClient`然后调用:code:`fl.client.start_client()`。字符串" +#~ " :code:`\"0.0.0.0:8080\"` " +#~ "告诉客户端要连接到哪个服务器。在我们的例子中,我们可以在同一台机器上运行服务器和客户端,因此我们使用:code:`\"0.0.0.0:8080\"`。如果我们运行真正联邦学习的工作负载,服务器和客户端在不同的机器上运行,则需要更改的只是我们传递给客户端的" +#~ " server_address 。" + +#~ msgid "" +#~ "That's it for the client. We only" +#~ " have to implement :code:`Client` or " +#~ ":code:`NumPyClient` and call " +#~ ":code:`fl.client.start_client()`. The string " +#~ ":code:`\"[::]:8080\"` tells the client which" +#~ " server to connect to. In our " +#~ "case we can run the server and " +#~ "the client on the same machine, " +#~ "therefore we use :code:`\"[::]:8080\"`. If " +#~ "we run a truly federated workload " +#~ "with the server and clients running " +#~ "on different machines, all that needs" +#~ " to change is the :code:`server_address`" +#~ " we point the client at." +#~ msgstr "" +#~ "对于客户来说就是这样了。我们只需实现 :code:`Client` 或 " +#~ ":code:`NumPyClient` 并调用:code:`fl.client.start_client()` " +#~ "即可。字符串 :code:`\"[::]:8080\"` " +#~ "告诉客户端要连接到哪个服务器。在我们的例子中,我们可以在同一台机器上运行服务器和客户端,因此我们使用 " +#~ ":code:`\"[::]:8080\"`。如果我们运行真正联邦的工作负载,服务器和客户端运行在不同的机器上,则需要更改的只是我们指向客户端的" +#~ " server_address 。" + +#~ msgid "" +#~ "Let's now load the CIFAR-10 training " +#~ "and test set, partition them into " +#~ "ten smaller datasets (each split into" +#~ " training and validation set), and " +#~ "wrap the resulting partitions by " +#~ "creating a PyTorch ``DataLoader`` for " +#~ "each of them:" +#~ msgstr "" +#~ "现在,让我们加载 CIFAR-10 训练集和测试集,将它们分割成 10 " +#~ "个较小的数据集(每个数据集又分为训练集和验证集),并通过为每个数据集创建 PyTorch " +#~ "``DataLoader`` 来包装由此产生的分割集:" + +#~ msgid "|e1dd4b4129b040bea23a894266227080|" +#~ msgstr "|e1dd4b4129b040bea23a894266227080|" + +#~ msgid "|c0d4cc6a442948dca8da40d2440068d9|" +#~ msgstr "|c0d4cc6a442948dca8da40d2440068d9|" + +#~ msgid "|174e1e4fa1f149a19bfbc8bc1126f46a|" +#~ msgstr "|174e1e4fa1f149a19bfbc8bc1126f46a|" + +#~ msgid "|4e021a3dc08249d2a89daa3ab03c2714|" +#~ msgstr "|4e021a3dc08249d2a89daa3ab03c2714|" + +#~ msgid "|e74a1d5ce7eb49688651f2167a59065b|" +#~ msgstr "|e74a1d5ce7eb49688651f2167a59065b|" + +#~ msgid "|eb29ec4c7aef4e93976795ed72df647e|" +#~ msgstr "|eb29ec4c7aef4e93976795ed72df647e|" + +#~ msgid "|c2f699d8ac484f5081721a6f1511f70d|" +#~ msgstr "|c2f699d8ac484f5081721a6f1511f70d|" + +#~ msgid "|cf42accdacbf4e5eb4fa0503108ba7a7|" +#~ msgstr "|cf42accdacbf4e5eb4fa0503108ba7a7|" + +#~ msgid "|5ec8356bc2564fa09178b1ceed5beccc|" +#~ msgstr "|5ec8356bc2564fa09178b1ceed5beccc|" + +#~ msgid "|7c9329e97bd0430bad335ab605a897a7|" +#~ msgstr "|7c9329e97bd0430bad335ab605a897a7|" + +#~ msgid "|88002bbce1094ba1a83c9151df18f707|" +#~ msgstr "|88002bbce1094ba1a83c9151df18f707|" + +#~ msgid "|391766aee87c482c834c93f7c22225e2|" +#~ msgstr "|391766aee87c482c834c93f7c22225e2|" + +#~ msgid "|93b9a15bd27f4e91b40f642c253dfaac|" +#~ msgstr "|93b9a15bd27f4e91b40f642c253dfaac|" + +#~ msgid "|a23d9638f96342ef9d25209951e2d564|" +#~ msgstr "|a23d9638f96342ef9d25209951e2d564|" + +#~ msgid "Upload the whl (e.g., ``flwr-1.6.0-py3-none-any.whl``)" +#~ msgstr "上传 whl(例如 ``flwr-1.6.0-py3-none-any.whl``)" + +#~ msgid "" +#~ "Change ``!pip install -q 'flwr[simulation]'" +#~ " torch torchvision matplotlib`` to ``!pip" +#~ " install -q 'flwr-1.6.0-py3-none-" +#~ "any.whl[simulation]' torch torchvision matplotlib``" +#~ msgstr "" +#~ "将``!pip install -q 'flwr[simulation]' torch" +#~ " torchvision matplotlib``更改为``!pip install -q " +#~ "'flwr-1.6.0-py3-none-any.whl[simulation]' torch " +#~ "torch torchvision matplotlib``" + +#~ msgid "" +#~ "All that's left to do it to " +#~ "define a function that loads both " +#~ "model and data, creates a " +#~ ":code:`CifarClient`, and starts this client." +#~ " You load your data and model " +#~ "by using :code:`cifar.py`. Start " +#~ ":code:`CifarClient` with the function " +#~ ":code:`fl.client.start_numpy_client()` by pointing " +#~ "it at the same IP adress we " +#~ "used in :code:`server.py`:" +#~ msgstr "" +#~ "剩下要做的就是定义一个加载模型和数据的函数,创建一个 :code:`CifarClient` 并启动该客户端。使用" +#~ " :code:`cifar.py` 加载数据和模型。使用函数 " +#~ ":code:`fl.client.start_numpy_client()` 启动 " +#~ ":code:`CifarClient`,将其指向我们在 :code:`server.py` 中使用的相同 " +#~ "IP 地址:" + +#~ msgid "" +#~ "The :code:`VirtualClientEngine` schedules, launches" +#~ " and manages `virtual` clients. These " +#~ "clients are identical to `non-virtual`" +#~ " clients (i.e. the ones you launch" +#~ " via the command `flwr.client.start_numpy_client" +#~ " `_)" +#~ " in the sense that they can be" +#~ " configure by creating a class " +#~ "inheriting, for example, from " +#~ "`flwr.client.NumPyClient `_ and therefore " +#~ "behave in an identical way. In " +#~ "addition to that, clients managed by " +#~ "the :code:`VirtualClientEngine` are:" +#~ msgstr "" +#~ "代码:`VirtualClientEngine`调度、启动和管理`虚拟`客户端。这些客户端与 \"非虚拟 " +#~ "\"客户端(即通过命令 `flwr.client.start_numpy_client `_启动的客户端)完全相同,它们可以通过创建一个继承自 \"flwr.client.NumPyClient " +#~ "`_\" " +#~ "的类来配置,因此行为方式也完全相同。除此之外,由 :code:`VirtualClientEngine` " +#~ "管理的客户端还包括:" -#: ../../source/tutorial-quickstart-pytorch.rst:196 -#: ../../source/tutorial-quickstart-tensorflow.rst:90 -msgid "" -"That's it for the client. We only have to implement :code:`Client` or :code:" -"`NumPyClient` and call :code:`fl.client.start_client()` or :code:`fl.client." -"start_numpy_client()`. The string :code:`\"[::]:8080\"` tells the client " -"which server to connect to. In our case we can run the server and the client " -"on the same machine, therefore we use :code:`\"[::]:8080\"`. If we run a " -"truly federated workload with the server and clients running on different " -"machines, all that needs to change is the :code:`server_address` we point " -"the client at." -msgstr "" -"这就是客户端。我们只需实现 :code:`Client` 或 :code:`NumPyClient` 并调用 " -":code:`fl.client.start_client()` 或 :code:`fl.client.start_numpy_client()`。" -"字符串 :code:`\"[::]:8080\"`会告诉客户端要连接的服务器。在本例中,我们可以在" -"同一台机器上运行服务器和客户端,因此使用 :code:`\"[::]:8080\"" -"。如果我们运行的是真正的联邦工作负载,服务器和客户端运行在不同的机器上," -"那么需要改变的只是客户端指向的 :code:`server_address`。" From d524b80d9decefb370d8d5353b42c86bf23569fd Mon Sep 17 00:00:00 2001 From: Charles Beauville Date: Tue, 13 Feb 2024 12:53:41 +0100 Subject: [PATCH 100/113] Fix minor doc errors (#2940) Co-authored-by: Taner Topal --- doc/source/.gitignore | 1 + doc/source/example-walkthrough-pytorch-mnist.rst | 2 +- doc/source/how-to-use-built-in-mods.rst | 2 +- doc/source/ref-changelog.md | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 doc/source/.gitignore diff --git a/doc/source/.gitignore b/doc/source/.gitignore new file mode 100644 index 000000000000..e9341a1383b7 --- /dev/null +++ b/doc/source/.gitignore @@ -0,0 +1 @@ +ref-api/ diff --git a/doc/source/example-walkthrough-pytorch-mnist.rst b/doc/source/example-walkthrough-pytorch-mnist.rst index ab311813f5de..0be0af6e1ca6 100644 --- a/doc/source/example-walkthrough-pytorch-mnist.rst +++ b/doc/source/example-walkthrough-pytorch-mnist.rst @@ -76,7 +76,7 @@ Inside the server helper script *run-server.sh* you will find the following code We can go a bit deeper and see that :code:`server.py` simply launches a server that will coordinate three rounds of training. -Flower Servers are very customizable, but for simple workloads, we can start a server using the :ref:`start_server ` function and leave all the configuration possibilities at their default values, as seen below. +Flower Servers are very customizable, but for simple workloads, we can start a server using the `start_server `_ function and leave all the configuration possibilities at their default values, as seen below. .. code-block:: python diff --git a/doc/source/how-to-use-built-in-mods.rst b/doc/source/how-to-use-built-in-mods.rst index af7102de9d0b..3c13892356ea 100644 --- a/doc/source/how-to-use-built-in-mods.rst +++ b/doc/source/how-to-use-built-in-mods.rst @@ -86,4 +86,4 @@ Conclusion By following this guide, you have learned how to effectively use mods to enhance your ``ClientApp``'s functionality. Remember that the order of mods is crucial and affects how the input and output are processed. -Enjoy building more robust and flexible ``ClientApp``s with mods! +Enjoy building more robust and flexible ``ClientApp`` s with mods! diff --git a/doc/source/ref-changelog.md b/doc/source/ref-changelog.md index 78d1e0e491a4..e9282632410d 100644 --- a/doc/source/ref-changelog.md +++ b/doc/source/ref-changelog.md @@ -217,7 +217,7 @@ We would like to give our special thanks to all the contributors who made the ne - **Restructure Flower Docs** ([#1824](https://github.com/adap/flower/pull/1824), [#1865](https://github.com/adap/flower/pull/1865), [#1884](https://github.com/adap/flower/pull/1884), [#1887](https://github.com/adap/flower/pull/1887), [#1919](https://github.com/adap/flower/pull/1919), [#1922](https://github.com/adap/flower/pull/1922), [#1920](https://github.com/adap/flower/pull/1920), [#1923](https://github.com/adap/flower/pull/1923), [#1924](https://github.com/adap/flower/pull/1924), [#1962](https://github.com/adap/flower/pull/1962), [#2006](https://github.com/adap/flower/pull/2006), [#2133](https://github.com/adap/flower/pull/2133), [#2203](https://github.com/adap/flower/pull/2203), [#2215](https://github.com/adap/flower/pull/2215), [#2122](https://github.com/adap/flower/pull/2122), [#2223](https://github.com/adap/flower/pull/2223), [#2219](https://github.com/adap/flower/pull/2219), [#2232](https://github.com/adap/flower/pull/2232), [#2233](https://github.com/adap/flower/pull/2233), [#2234](https://github.com/adap/flower/pull/2234), [#2235](https://github.com/adap/flower/pull/2235), [#2237](https://github.com/adap/flower/pull/2237), [#2238](https://github.com/adap/flower/pull/2238), [#2242](https://github.com/adap/flower/pull/2242), [#2231](https://github.com/adap/flower/pull/2231), [#2243](https://github.com/adap/flower/pull/2243), [#2227](https://github.com/adap/flower/pull/2227)) - Much effort went into a completely restructured Flower docs experience. The documentation on [flower.dev/docs](flower.dev/docs) is now divided into Flower Framework, Flower Baselines, Flower Android SDK, Flower iOS SDK, and code example projects. + Much effort went into a completely restructured Flower docs experience. The documentation on [flower.dev/docs](https://flower.dev/docs) is now divided into Flower Framework, Flower Baselines, Flower Android SDK, Flower iOS SDK, and code example projects. - **Introduce Flower Swift SDK** ([#1858](https://github.com/adap/flower/pull/1858), [#1897](https://github.com/adap/flower/pull/1897)) From d213534fccfa57c6b963bf8f73ff7141eff73e7e Mon Sep 17 00:00:00 2001 From: Javier Date: Tue, 13 Feb 2024 18:16:33 +0100 Subject: [PATCH 101/113] Add `node_id` to `Metadata` (#2912) Co-authored-by: Heng Pan <134433891+panh99@users.noreply.github.com> --- src/py/flwr/client/grpc_client/connection.py | 1 + .../flwr/client/grpc_client/connection_test.py | 2 ++ .../client/message_handler/message_handler.py | 8 +++++--- .../message_handler/message_handler_test.py | 2 ++ .../mod/secure_aggregation/secaggplus_mod.py | 9 ++++++++- .../secure_aggregation/secaggplus_mod_test.py | 18 ++++++++++++++++-- src/py/flwr/client/mod/utils_test.py | 4 +++- src/py/flwr/common/message.py | 3 +++ src/py/flwr/common/serde.py | 2 ++ src/py/flwr/common/serde_test.py | 5 +++++ 10 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/py/flwr/client/grpc_client/connection.py b/src/py/flwr/client/grpc_client/connection.py index c7d8494b8fde..aaaf1fcc863c 100644 --- a/src/py/flwr/client/grpc_client/connection.py +++ b/src/py/flwr/client/grpc_client/connection.py @@ -173,6 +173,7 @@ def receive() -> Message: task_id=str(uuid.uuid4()), group_id="", ttl="", + node_id=0, task_type=task_type, ), content=recordset, diff --git a/src/py/flwr/client/grpc_client/connection_test.py b/src/py/flwr/client/grpc_client/connection_test.py index 7ba39568f0a4..e193c9484fff 100644 --- a/src/py/flwr/client/grpc_client/connection_test.py +++ b/src/py/flwr/client/grpc_client/connection_test.py @@ -48,6 +48,7 @@ run_id=0, task_id="", group_id="", + node_id=0, ttl="", task_type=TASK_TYPE_GET_PROPERTIES, ), @@ -60,6 +61,7 @@ run_id=0, task_id="", group_id="", + node_id=0, ttl="", task_type="reconnect", ), diff --git a/src/py/flwr/client/message_handler/message_handler.py b/src/py/flwr/client/message_handler/message_handler.py index c45d13d43f94..52dbdec7691b 100644 --- a/src/py/flwr/client/message_handler/message_handler.py +++ b/src/py/flwr/client/message_handler/message_handler.py @@ -92,6 +92,7 @@ def handle_control_message(message: Message) -> Tuple[Optional[Message], int]: run_id=0, task_id="", group_id="", + node_id=0, ttl="", task_type="reconnect", ), @@ -150,9 +151,10 @@ def handle_legacy_message_from_tasktype( # Return Message out_message = Message( metadata=Metadata( - run_id=0, # Non-user defined - task_id="", # Non-user defined - group_id="", # Non-user defined + run_id=0, + task_id="", + group_id="", + node_id=0, ttl="", task_type=task_type, ), diff --git a/src/py/flwr/client/message_handler/message_handler_test.py b/src/py/flwr/client/message_handler/message_handler_test.py index 288597b764f4..820de9bbe27c 100644 --- a/src/py/flwr/client/message_handler/message_handler_test.py +++ b/src/py/flwr/client/message_handler/message_handler_test.py @@ -124,6 +124,7 @@ def test_client_without_get_properties() -> None: run_id=0, task_id=str(uuid.uuid4()), group_id="", + node_id=0, ttl="", task_type=TASK_TYPE_GET_PROPERTIES, ), @@ -162,6 +163,7 @@ def test_client_with_get_properties() -> None: run_id=0, task_id=str(uuid.uuid4()), group_id="", + node_id=0, ttl="", task_type=TASK_TYPE_GET_PROPERTIES, ), diff --git a/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py b/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py index a6f59b736911..eba5dec658aa 100644 --- a/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py +++ b/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py @@ -207,7 +207,14 @@ def secaggplus_mod( # Return message return Message( - metadata=Metadata(0, "", "", "", TASK_TYPE_FIT), + metadata=Metadata( + run_id=0, + task_id="", + group_id="", + node_id=0, + ttl="", + task_type=TASK_TYPE_FIT, + ), content=RecordSet(configs={RECORD_KEY_CONFIGS: ConfigsRecord(res, False)}), ) diff --git a/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod_test.py b/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod_test.py index 2ca9748f8219..d0f461e7a8de 100644 --- a/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod_test.py +++ b/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod_test.py @@ -57,7 +57,14 @@ def get_test_handler( def empty_ffn(_: Message, _2: Context) -> Message: return Message( - metadata=Metadata(0, "", "", "", TASK_TYPE_FIT), + metadata=Metadata( + run_id=0, + task_id="", + group_id="", + node_id=0, + ttl="", + task_type=TASK_TYPE_FIT, + ), content=RecordSet(), ) @@ -65,7 +72,14 @@ def empty_ffn(_: Message, _2: Context) -> Message: def func(configs: Dict[str, ConfigsRecordValues]) -> Dict[str, ConfigsRecordValues]: in_msg = Message( - metadata=Metadata(0, "", "", "", TASK_TYPE_FIT), + metadata=Metadata( + run_id=0, + task_id="", + group_id="", + node_id=0, + ttl="", + task_type=TASK_TYPE_FIT, + ), content=RecordSet(configs={RECORD_KEY_CONFIGS: ConfigsRecord(configs)}), ) out_msg = app(in_msg, ctxt) diff --git a/src/py/flwr/client/mod/utils_test.py b/src/py/flwr/client/mod/utils_test.py index 00c0ef850dc0..07b38a250d6c 100644 --- a/src/py/flwr/client/mod/utils_test.py +++ b/src/py/flwr/client/mod/utils_test.py @@ -74,7 +74,9 @@ def app(message: Message, context: Context) -> Message: def _get_dummy_flower_message() -> Message: return Message( content=RecordSet(), - metadata=Metadata(run_id=0, task_id="", group_id="", ttl="", task_type="mock"), + metadata=Metadata( + run_id=0, task_id="", group_id="", node_id=0, ttl="", task_type="mock" + ), ) diff --git a/src/py/flwr/common/message.py b/src/py/flwr/common/message.py index 1a971749966e..ada4a617b60d 100644 --- a/src/py/flwr/common/message.py +++ b/src/py/flwr/common/message.py @@ -33,6 +33,8 @@ class Metadata: group_id : str An identifier for grouping tasks. In some settings this is used as the FL round. + node_id : int + An identifier for the node running a task. ttl : str Time-to-live for this task. task_type : str @@ -43,6 +45,7 @@ class Metadata: run_id: int task_id: str group_id: str + node_id: int ttl: str task_type: str diff --git a/src/py/flwr/common/serde.py b/src/py/flwr/common/serde.py index 3b8e4c3a1c2c..5a8c5c753136 100644 --- a/src/py/flwr/common/serde.py +++ b/src/py/flwr/common/serde.py @@ -563,6 +563,7 @@ def message_from_taskins(taskins: TaskIns) -> Message: run_id=taskins.run_id, task_id=taskins.task_id, group_id=taskins.group_id, + node_id=taskins.task.consumer.node_id, ttl=taskins.task.ttl, task_type=taskins.task.task_type, ) @@ -592,6 +593,7 @@ def message_from_taskres(taskres: TaskRes) -> Message: run_id=taskres.run_id, task_id=taskres.task_id, group_id=taskres.group_id, + node_id=taskres.task.consumer.node_id, ttl=taskres.task.ttl, task_type=taskres.task.task_type, ) diff --git a/src/py/flwr/common/serde_test.py b/src/py/flwr/common/serde_test.py index c30f24d3700c..1c36f2171149 100644 --- a/src/py/flwr/common/serde_test.py +++ b/src/py/flwr/common/serde_test.py @@ -219,6 +219,7 @@ def metadata(self) -> Metadata: run_id=self.rng.randint(0, 1 << 30), task_id=self.get_str(64), group_id=self.get_str(30), + node_id=self.rng.randint(0, 1 << 63), ttl=self.get_str(10), task_type=self.get_str(10), ) @@ -309,6 +310,7 @@ def test_message_to_and_from_taskins() -> None: run_id=0, task_id="", group_id="", + node_id=metadata.node_id, ttl=metadata.ttl, task_type=metadata.task_type, ), @@ -320,6 +322,7 @@ def test_message_to_and_from_taskins() -> None: taskins.run_id = metadata.run_id taskins.task_id = metadata.task_id taskins.group_id = metadata.group_id + taskins.task.consumer.node_id = metadata.node_id deserialized = message_from_taskins(taskins) # Assert @@ -337,6 +340,7 @@ def test_message_to_and_from_taskres() -> None: run_id=0, task_id="", group_id="", + node_id=metadata.node_id, ttl=metadata.ttl, task_type=metadata.task_type, ), @@ -348,6 +352,7 @@ def test_message_to_and_from_taskres() -> None: taskres.run_id = metadata.run_id taskres.task_id = metadata.task_id taskres.group_id = metadata.group_id + taskres.task.consumer.node_id = metadata.node_id deserialized = message_from_taskres(taskres) # Assert From d1c0481e254a3d8d7948bd8cbe2ea3bf1a5748cc Mon Sep 17 00:00:00 2001 From: Javier Date: Tue, 13 Feb 2024 19:39:42 +0100 Subject: [PATCH 102/113] Update mt-pytorch example (#2933) --- examples/mt-pytorch/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/mt-pytorch/README.md b/examples/mt-pytorch/README.md index 721a26ed814d..0f676044ee90 100644 --- a/examples/mt-pytorch/README.md +++ b/examples/mt-pytorch/README.md @@ -36,17 +36,17 @@ flower-superlink --insecure In a new terminal window, start the first long-running Flower client: ```bash -flower-client client:app --insecure +flower-client-app client:app --insecure ``` In yet another new terminal window, start the second long-running Flower client: ```bash -flower-client client:app --insecure +flower-client-app client:app --insecure ``` ## Start the driver ```bash -python driver.py +python start_driver.py ``` From db9a527573f2f8beb034e421d76ae702bf1cadc5 Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Wed, 14 Feb 2024 12:46:51 +0100 Subject: [PATCH 103/113] Create ServerApp (#2931) --- doc/source/how-to-use-built-in-mods.rst | 2 +- src/py/flwr/client/clientapp.py | 4 +- src/py/flwr/server/__init__.py | 2 + src/py/flwr/server/serverapp.py | 95 +++++++++++++++++++++++++ src/py/flwr/server/typing.py | 23 ++++++ 5 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 src/py/flwr/server/serverapp.py create mode 100644 src/py/flwr/server/typing.py diff --git a/doc/source/how-to-use-built-in-mods.rst b/doc/source/how-to-use-built-in-mods.rst index 3c13892356ea..341139175074 100644 --- a/doc/source/how-to-use-built-in-mods.rst +++ b/doc/source/how-to-use-built-in-mods.rst @@ -86,4 +86,4 @@ Conclusion By following this guide, you have learned how to effectively use mods to enhance your ``ClientApp``'s functionality. Remember that the order of mods is crucial and affects how the input and output are processed. -Enjoy building more robust and flexible ``ClientApp`` s with mods! +Enjoy building a more robust and flexible ``ClientApp`` with mods! diff --git a/src/py/flwr/client/clientapp.py b/src/py/flwr/client/clientapp.py index 51c912890c7e..2d8e9e652dba 100644 --- a/src/py/flwr/client/clientapp.py +++ b/src/py/flwr/client/clientapp.py @@ -72,12 +72,12 @@ def ffn( self._call = make_ffn(ffn, mods if mods is not None else []) def __call__(self, message: Message, context: Context) -> Message: - """.""" + """Execute `ClientApp`.""" return self._call(message, context) class LoadClientAppError(Exception): - """.""" + """Error when trying to load `ClientApp`.""" def load_client_app(module_attribute_str: str) -> ClientApp: diff --git a/src/py/flwr/server/__init__.py b/src/py/flwr/server/__init__.py index 84c24b4bc2c1..1472bcaf0893 100644 --- a/src/py/flwr/server/__init__.py +++ b/src/py/flwr/server/__init__.py @@ -26,6 +26,7 @@ from .client_manager import SimpleClientManager as SimpleClientManager from .history import History as History from .server import Server as Server +from .serverapp import ServerApp as ServerApp __all__ = [ "ClientManager", @@ -36,6 +37,7 @@ "run_server_app", "run_superlink", "Server", + "ServerApp", "ServerConfig", "SimpleClientManager", "start_server", diff --git a/src/py/flwr/server/serverapp.py b/src/py/flwr/server/serverapp.py new file mode 100644 index 000000000000..1a89093621e1 --- /dev/null +++ b/src/py/flwr/server/serverapp.py @@ -0,0 +1,95 @@ +# Copyright 2024 Flower Labs GmbH. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Flower ServerApp.""" + + +import importlib +from typing import Optional, cast + +from flwr.common.context import Context +from flwr.server.driver.driver import Driver +from flwr.server.strategy import Strategy + +from .app import ServerConfig +from .client_manager import ClientManager +from .server import Server + + +class ServerApp: + """Flower ServerApp.""" + + def __init__( + self, + server: Optional[Server] = None, + config: Optional[ServerConfig] = None, + strategy: Optional[Strategy] = None, + client_manager: Optional[ClientManager] = None, + ) -> None: + self.server = server + self.config = config + self.strategy = strategy + self.client_manager = client_manager + + def __call__(self, driver: Driver, context: Context) -> None: + """Execute `ServerApp`.""" + + +class LoadServerAppError(Exception): + """Error when trying to load `ServerApp`.""" + + +def load_server_app(module_attribute_str: str) -> ServerApp: + """Load the `ServerApp` object specified in a module attribute string. + + The module/attribute string should have the form :. Valid + examples include `server:app` and `project.package.module:wrapper.app`. It + must refer to a module on the PYTHONPATH, the module needs to have the specified + attribute, and the attribute must be of type `ServerApp`. + """ + module_str, _, attributes_str = module_attribute_str.partition(":") + if not module_str: + raise LoadServerAppError( + f"Missing module in {module_attribute_str}", + ) from None + if not attributes_str: + raise LoadServerAppError( + f"Missing attribute in {module_attribute_str}", + ) from None + + # Load module + try: + module = importlib.import_module(module_str) + except ModuleNotFoundError: + raise LoadServerAppError( + f"Unable to load module {module_str}", + ) from None + + # Recursively load attribute + attribute = module + try: + for attribute_str in attributes_str.split("."): + attribute = getattr(attribute, attribute_str) + except AttributeError: + raise LoadServerAppError( + f"Unable to load attribute {attributes_str} from module {module_str}", + ) from None + + # Check type + if not isinstance(attribute, ServerApp): + raise LoadServerAppError( + f"Attribute {attributes_str} is not of type {ServerApp}", + ) from None + + return cast(ServerApp, attribute) diff --git a/src/py/flwr/server/typing.py b/src/py/flwr/server/typing.py new file mode 100644 index 000000000000..728121c2eddf --- /dev/null +++ b/src/py/flwr/server/typing.py @@ -0,0 +1,23 @@ +# Copyright 2024 Flower Labs GmbH. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Custom types for Flower servers.""" + + +from typing import Callable + +from flwr.common.context import Context +from flwr.server.driver import Driver + +ServerAppCallable = Callable[[Driver, Context], None] From 87ad890da6d9a5f947c6b21e46678f5b10c87100 Mon Sep 17 00:00:00 2001 From: Robert Steiner Date: Wed, 14 Feb 2024 13:29:34 +0100 Subject: [PATCH 104/113] Update artifact bucket ID (#2945) --- .github/workflows/e2e.yml | 7 ++++--- .github/workflows/framework-draft-release.yml | 21 +++++++++++-------- .github/workflows/framework-release.yml | 13 +++++++----- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 065e79fff9ab..c89896dd9d6b 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -14,6 +14,7 @@ concurrency: env: FLWR_TELEMETRY_ENABLED: 0 + ARTIFACT_BUCKET: artifact.flower.ai jobs: wheel: @@ -43,7 +44,7 @@ jobs: echo "SHORT_SHA=$sha_short" >> "$GITHUB_OUTPUT" [ -z "${{ github.head_ref }}" ] && dir="${{ github.ref_name }}" || dir="pr/${{ github.head_ref }}" echo "DIR=$dir" >> "$GITHUB_OUTPUT" - aws s3 cp --content-disposition "attachment" --cache-control "no-cache" ./ s3://artifact.flower.dev/py/$dir/$sha_short --recursive + aws s3 cp --content-disposition "attachment" --cache-control "no-cache" ./ s3://${{ env.ARTIFACT_BUCKET }}/py/$dir/$sha_short --recursive outputs: whl_path: ${{ steps.upload.outputs.WHL_PATH }} short_sha: ${{ steps.upload.outputs.SHORT_SHA }} @@ -123,7 +124,7 @@ jobs: - name: Install Flower wheel from artifact store if: ${{ github.repository == 'adap/flower' && !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' }} run: | - python -m pip install https://artifact.flower.dev/py/${{ needs.wheel.outputs.dir }}/${{ needs.wheel.outputs.short_sha }}/${{ needs.wheel.outputs.whl_path }} + python -m pip install https://${{ env.ARTIFACT_BUCKET }}/py/${{ needs.wheel.outputs.dir }}/${{ needs.wheel.outputs.short_sha }}/${{ needs.wheel.outputs.whl_path }} - name: Download dataset if: ${{ matrix.dataset }} run: python -c "${{ matrix.dataset }}" @@ -164,7 +165,7 @@ jobs: - name: Install Flower wheel from artifact store if: ${{ github.repository == 'adap/flower' && !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' }} run: | - python -m pip install https://artifact.flower.dev/py/${{ needs.wheel.outputs.dir }}/${{ needs.wheel.outputs.short_sha }}/${{ needs.wheel.outputs.whl_path }} + python -m pip install https://${{ env.ARTIFACT_BUCKET }}/py/${{ needs.wheel.outputs.dir }}/${{ needs.wheel.outputs.short_sha }}/${{ needs.wheel.outputs.whl_path }} - name: Cache Datasets uses: actions/cache@v3 with: diff --git a/.github/workflows/framework-draft-release.yml b/.github/workflows/framework-draft-release.yml index 959d17249765..91a89953cf96 100644 --- a/.github/workflows/framework-draft-release.yml +++ b/.github/workflows/framework-draft-release.yml @@ -5,6 +5,9 @@ on: tags: - "v*.*.*" +env: + ARTIFACT_BUCKET: artifact.flower.ai + jobs: publish: if: ${{ github.repository == 'adap/flower' }} @@ -26,16 +29,16 @@ jobs: run: | tag_name=$(echo "${GITHUB_REF_NAME}" | cut -c2-) echo "TAG_NAME=$tag_name" >> "$GITHUB_ENV" - + wheel_name="flwr-${tag_name}-py3-none-any.whl" echo "WHEEL_NAME=$wheel_name" >> "$GITHUB_ENV" - + tar_name="flwr-${tag_name}.tar.gz" echo "TAR_NAME=$tar_name" >> "$GITHUB_ENV" - wheel_url="https://artifact.flower.dev/py/main/${GITHUB_SHA::7}/${wheel_name}" - tar_url="https://artifact.flower.dev/py/main/${GITHUB_SHA::7}/${tar_name}" - + wheel_url="https://${{ env.ARTIFACT_BUCKET }}/py/main/${GITHUB_SHA::7}/${wheel_name}" + tar_url="https://${{ env.ARTIFACT_BUCKET }}/py/main/${GITHUB_SHA::7}/${tar_name}" + curl $wheel_url --output $wheel_name curl $tar_url --output $tar_name - name: Upload wheel @@ -44,14 +47,14 @@ jobs: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets. AWS_SECRET_ACCESS_KEY }} run: | - aws s3 cp --content-disposition "attachment" --cache-control "no-cache" ./${{ env.WHEEL_NAME }} s3://artifact.flower.dev/py/release/v${{ env.TAG_NAME }}/${{ env.WHEEL_NAME }} - aws s3 cp --content-disposition "attachment" --cache-control "no-cache" ./${{ env.TAR_NAME }} s3://artifact.flower.dev/py/release/v${{ env.TAG_NAME }}/${{ env.TAR_NAME }} - + aws s3 cp --content-disposition "attachment" --cache-control "no-cache" ./${{ env.WHEEL_NAME }} s3://${{ env.ARTIFACT_BUCKET }}/py/release/v${{ env.TAG_NAME }}/${{ env.WHEEL_NAME }} + aws s3 cp --content-disposition "attachment" --cache-control "no-cache" ./${{ env.TAR_NAME }} s3://${{ env.ARTIFACT_BUCKET }}/py/release/v${{ env.TAG_NAME }}/${{ env.TAR_NAME }} + - name: Generate body run: | ./dev/get-latest-changelog.sh > body.md cat body.md - + - name: Release uses: softprops/action-gh-release@v1 with: diff --git a/.github/workflows/framework-release.yml b/.github/workflows/framework-release.yml index f052d3a4a928..04b68fd38af9 100644 --- a/.github/workflows/framework-release.yml +++ b/.github/workflows/framework-release.yml @@ -3,11 +3,14 @@ name: Publish `flwr` release on PyPI on: release: types: [released] - + concurrency: group: ${{ github.workflow }}-${{ github.ref == 'refs/heads/main' && github.run_id || github.event.pull_request.number || github.ref }} cancel-in-progress: true - + +env: + ARTIFACT_BUCKET: artifact.flower.ai + jobs: publish: if: ${{ github.repository == 'adap/flower' }} @@ -28,11 +31,11 @@ jobs: run: | TAG_NAME=$(echo "${GITHUB_REF_NAME}" | cut -c2-) - wheel_name="flwr-${TAG_NAME}-py3-none-any.whl" + wheel_name="flwr-${TAG_NAME}-py3-none-any.whl" tar_name="flwr-${TAG_NAME}.tar.gz" - wheel_url="https://artifact.flower.dev/py/release/v${TAG_NAME}/${wheel_name}" - tar_url="https://artifact.flower.dev/py/release/v${TAG_NAME}/${tar_name}" + wheel_url="https://${{ env.ARTIFACT_BUCKET }}/py/release/v${TAG_NAME}/${wheel_name}" + tar_url="https://${{ env.ARTIFACT_BUCKET }}/py/release/v${TAG_NAME}/${tar_name}" mkdir -p dist From cbbb813a7e46c165788e5c405a90dbfb6565730b Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Wed, 14 Feb 2024 14:53:21 +0100 Subject: [PATCH 105/113] Load ServerApp (#2934) --- src/py/flwr/server/__init__.py | 2 +- src/py/flwr/server/app.py | 44 +++++++++++++++-------------- src/py/flwr/server/driver/app.py | 3 +- src/py/flwr/server/server_config.py | 31 ++++++++++++++++++++ src/py/flwr/server/serverapp.py | 2 +- src/py/flwr/simulation/app.py | 3 +- 6 files changed, 60 insertions(+), 25 deletions(-) create mode 100644 src/py/flwr/server/server_config.py diff --git a/src/py/flwr/server/__init__.py b/src/py/flwr/server/__init__.py index 1472bcaf0893..b0f95f903811 100644 --- a/src/py/flwr/server/__init__.py +++ b/src/py/flwr/server/__init__.py @@ -16,7 +16,6 @@ from . import driver, strategy -from .app import ServerConfig as ServerConfig from .app import run_driver_api as run_driver_api from .app import run_fleet_api as run_fleet_api from .app import run_server_app as run_server_app @@ -26,6 +25,7 @@ from .client_manager import SimpleClientManager as SimpleClientManager from .history import History as History from .server import Server as Server +from .server_config import ServerConfig as ServerConfig from .serverapp import ServerApp as ServerApp __all__ = [ diff --git a/src/py/flwr/server/app.py b/src/py/flwr/server/app.py index 6e2f1f7dc88d..66adcbdb6b85 100644 --- a/src/py/flwr/server/app.py +++ b/src/py/flwr/server/app.py @@ -19,7 +19,6 @@ import importlib.util import sys import threading -from dataclasses import dataclass from logging import DEBUG, ERROR, INFO, WARN from os.path import isfile from pathlib import Path @@ -43,17 +42,20 @@ from flwr.proto.fleet_pb2_grpc import ( # pylint: disable=E0611 add_FleetServicer_to_server, ) -from flwr.server.client_manager import ClientManager, SimpleClientManager -from flwr.server.history import History -from flwr.server.server import Server -from flwr.server.strategy import FedAvg, Strategy -from flwr.server.superlink.driver.driver_servicer import DriverServicer -from flwr.server.superlink.fleet.grpc_bidi.grpc_server import ( + +from .client_manager import ClientManager, SimpleClientManager +from .history import History +from .server import Server +from .server_config import ServerConfig +from .serverapp import ServerApp, load_server_app +from .strategy import FedAvg, Strategy +from .superlink.driver.driver_servicer import DriverServicer +from .superlink.fleet.grpc_bidi.grpc_server import ( generic_create_grpc_server, start_grpc_server, ) -from flwr.server.superlink.fleet.grpc_rere.fleet_servicer import FleetServicer -from flwr.server.superlink.state import StateFactory +from .superlink.fleet.grpc_rere.fleet_servicer import FleetServicer +from .superlink.state import StateFactory ADDRESS_DRIVER_API = "0.0.0.0:9091" ADDRESS_FLEET_API_GRPC_RERE = "0.0.0.0:9092" @@ -63,18 +65,6 @@ DATABASE = ":flwr-in-memory-state:" -@dataclass -class ServerConfig: - """Flower server config. - - All attributes have default values which allows users to configure just the ones - they care about. - """ - - num_rounds: int = 1 - round_timeout: Optional[float] = None - - def run_server_app() -> None: """Run Flower server app.""" event(EventType.RUN_SERVER_APP_ENTER) @@ -126,6 +116,18 @@ def run_server_app() -> None: log(WARN, "Not implemented: run_server_app") + server_app_dir = args.dir + if server_app_dir is not None: + sys.path.insert(0, server_app_dir) + + def _load() -> ServerApp: + server_app: ServerApp = load_server_app(getattr(args, "server-app")) + return server_app + + server_app = _load() + + log(DEBUG, "server_app: `%s`", server_app) + event(EventType.RUN_SERVER_APP_LEAVE) diff --git a/src/py/flwr/server/driver/app.py b/src/py/flwr/server/driver/app.py index ae47c58f4e9c..b47454b7b4b6 100644 --- a/src/py/flwr/server/driver/app.py +++ b/src/py/flwr/server/driver/app.py @@ -26,10 +26,11 @@ from flwr.common.address import parse_address from flwr.common.logger import log from flwr.proto import driver_pb2 # pylint: disable=E0611 -from flwr.server.app import ServerConfig, init_defaults, run_fl +from flwr.server.app import init_defaults, run_fl from flwr.server.client_manager import ClientManager from flwr.server.history import History from flwr.server.server import Server +from flwr.server.server_config import ServerConfig from flwr.server.strategy import Strategy from .driver_client_proxy import DriverClientProxy diff --git a/src/py/flwr/server/server_config.py b/src/py/flwr/server/server_config.py new file mode 100644 index 000000000000..823f832da6f8 --- /dev/null +++ b/src/py/flwr/server/server_config.py @@ -0,0 +1,31 @@ +# Copyright 2024 Flower Labs GmbH. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Flower ServerConfig.""" + + +from dataclasses import dataclass +from typing import Optional + + +@dataclass +class ServerConfig: + """Flower server config. + + All attributes have default values which allows users to configure just the ones + they care about. + """ + + num_rounds: int = 1 + round_timeout: Optional[float] = None diff --git a/src/py/flwr/server/serverapp.py b/src/py/flwr/server/serverapp.py index 1a89093621e1..1ffa087719dc 100644 --- a/src/py/flwr/server/serverapp.py +++ b/src/py/flwr/server/serverapp.py @@ -22,9 +22,9 @@ from flwr.server.driver.driver import Driver from flwr.server.strategy import Strategy -from .app import ServerConfig from .client_manager import ClientManager from .server import Server +from .server_config import ServerConfig class ServerApp: diff --git a/src/py/flwr/simulation/app.py b/src/py/flwr/simulation/app.py index 6a18a258ac60..b159042588c9 100644 --- a/src/py/flwr/simulation/app.py +++ b/src/py/flwr/simulation/app.py @@ -29,9 +29,10 @@ from flwr.common import EventType, event from flwr.common.logger import log from flwr.server import Server -from flwr.server.app import ServerConfig, init_defaults, run_fl +from flwr.server.app import init_defaults, run_fl from flwr.server.client_manager import ClientManager from flwr.server.history import History +from flwr.server.server_config import ServerConfig from flwr.server.strategy import Strategy from flwr.simulation.ray_transport.ray_actor import ( DefaultActor, From 314492cc64eff9689d98c2d22eba348d801c4d28 Mon Sep 17 00:00:00 2001 From: Heng Pan <134433891+panh99@users.noreply.github.com> Date: Wed, 14 Feb 2024 14:23:59 +0000 Subject: [PATCH 106/113] Rename `task_*` to `message_*` (#2944) --- src/py/flwr/client/clientapp.py | 4 +- src/py/flwr/client/grpc_client/connection.py | 40 +++++++++---------- .../client/grpc_client/connection_test.py | 12 +++--- .../client/message_handler/message_handler.py | 32 +++++++-------- .../message_handler/message_handler_test.py | 20 +++++----- .../mod/secure_aggregation/secaggplus_mod.py | 8 ++-- .../secure_aggregation/secaggplus_mod_test.py | 10 ++--- src/py/flwr/client/mod/utils_test.py | 2 +- src/py/flwr/common/constant.py | 8 ++-- src/py/flwr/common/message.py | 20 +++++----- src/py/flwr/common/serde.py | 12 +++--- src/py/flwr/common/serde_test.py | 16 ++++---- .../flwr/server/driver/driver_client_proxy.py | 16 ++++---- .../server/driver/driver_client_proxy_test.py | 18 ++++----- 14 files changed, 109 insertions(+), 109 deletions(-) diff --git a/src/py/flwr/client/clientapp.py b/src/py/flwr/client/clientapp.py index 2d8e9e652dba..cfc59c9298ed 100644 --- a/src/py/flwr/client/clientapp.py +++ b/src/py/flwr/client/clientapp.py @@ -19,7 +19,7 @@ from typing import List, Optional, cast from flwr.client.message_handler.message_handler import ( - handle_legacy_message_from_tasktype, + handle_legacy_message_from_msgtype, ) from flwr.client.mod.utils import make_ffn from flwr.client.typing import ClientFn, Mod @@ -63,7 +63,7 @@ def ffn( message: Message, context: Context, ) -> Message: # pylint: disable=invalid-name - out_message = handle_legacy_message_from_tasktype( + out_message = handle_legacy_message_from_msgtype( client_fn=client_fn, message=message, context=context ) return out_message diff --git a/src/py/flwr/client/grpc_client/connection.py b/src/py/flwr/client/grpc_client/connection.py index aaaf1fcc863c..e6d21963fcbf 100644 --- a/src/py/flwr/client/grpc_client/connection.py +++ b/src/py/flwr/client/grpc_client/connection.py @@ -27,10 +27,10 @@ from flwr.common import serde from flwr.common.configsrecord import ConfigsRecord from flwr.common.constant import ( - TASK_TYPE_EVALUATE, - TASK_TYPE_FIT, - TASK_TYPE_GET_PARAMETERS, - TASK_TYPE_GET_PROPERTIES, + MESSAGE_TYPE_EVALUATE, + MESSAGE_TYPE_FIT, + MESSAGE_TYPE_GET_PARAMETERS, + MESSAGE_TYPE_GET_PROPERTIES, ) from flwr.common.grpc import create_channel from flwr.common.logger import log @@ -133,33 +133,33 @@ def receive() -> Message: # ServerMessage proto --> *Ins --> RecordSet field = proto.WhichOneof("msg") - task_type = "" + message_type = "" if field == "get_properties_ins": recordset = compat.getpropertiesins_to_recordset( serde.get_properties_ins_from_proto(proto.get_properties_ins) ) - task_type = TASK_TYPE_GET_PROPERTIES + message_type = MESSAGE_TYPE_GET_PROPERTIES elif field == "get_parameters_ins": recordset = compat.getparametersins_to_recordset( serde.get_parameters_ins_from_proto(proto.get_parameters_ins) ) - task_type = TASK_TYPE_GET_PARAMETERS + message_type = MESSAGE_TYPE_GET_PARAMETERS elif field == "fit_ins": recordset = compat.fitins_to_recordset( serde.fit_ins_from_proto(proto.fit_ins), False ) - task_type = TASK_TYPE_FIT + message_type = MESSAGE_TYPE_FIT elif field == "evaluate_ins": recordset = compat.evaluateins_to_recordset( serde.evaluate_ins_from_proto(proto.evaluate_ins), False ) - task_type = TASK_TYPE_EVALUATE + message_type = MESSAGE_TYPE_EVALUATE elif field == "reconnect_ins": recordset = RecordSet() recordset.set_configs( "config", ConfigsRecord({"seconds": proto.reconnect_ins.seconds}) ) - task_type = "reconnect" + message_type = "reconnect" else: raise ValueError( "Unsupported instruction in ServerMessage, " @@ -170,44 +170,44 @@ def receive() -> Message: return Message( metadata=Metadata( run_id=0, - task_id=str(uuid.uuid4()), + message_id=str(uuid.uuid4()), group_id="", ttl="", node_id=0, - task_type=task_type, + message_type=message_type, ), content=recordset, ) def send(message: Message) -> None: - # Retrieve RecordSet and task_type + # Retrieve RecordSet and message_type recordset = message.content - task_type = message.metadata.task_type + message_type = message.metadata.message_type # RecordSet --> *Res --> *Res proto -> ClientMessage proto - if task_type == TASK_TYPE_GET_PROPERTIES: + if message_type == MESSAGE_TYPE_GET_PROPERTIES: getpropres = compat.recordset_to_getpropertiesres(recordset) msg_proto = ClientMessage( get_properties_res=serde.get_properties_res_to_proto(getpropres) ) - elif task_type == TASK_TYPE_GET_PARAMETERS: + elif message_type == MESSAGE_TYPE_GET_PARAMETERS: getparamres = compat.recordset_to_getparametersres(recordset, False) msg_proto = ClientMessage( get_parameters_res=serde.get_parameters_res_to_proto(getparamres) ) - elif task_type == TASK_TYPE_FIT: + elif message_type == MESSAGE_TYPE_FIT: fitres = compat.recordset_to_fitres(recordset, False) msg_proto = ClientMessage(fit_res=serde.fit_res_to_proto(fitres)) - elif task_type == TASK_TYPE_EVALUATE: + elif message_type == MESSAGE_TYPE_EVALUATE: evalres = compat.recordset_to_evaluateres(recordset) msg_proto = ClientMessage(evaluate_res=serde.evaluate_res_to_proto(evalres)) - elif task_type == "reconnect": + elif message_type == "reconnect": reason = cast(Reason.ValueType, recordset.get_configs("config")["reason"]) msg_proto = ClientMessage( disconnect_res=ClientMessage.DisconnectRes(reason=reason) ) else: - raise ValueError(f"Invalid task type: {task_type}") + raise ValueError(f"Invalid task type: {message_type}") # Send ClientMessage proto return queue.put(msg_proto, block=False) diff --git a/src/py/flwr/client/grpc_client/connection_test.py b/src/py/flwr/client/grpc_client/connection_test.py index e193c9484fff..127e27356f64 100644 --- a/src/py/flwr/client/grpc_client/connection_test.py +++ b/src/py/flwr/client/grpc_client/connection_test.py @@ -25,7 +25,7 @@ from flwr.common import recordset_compat as compat from flwr.common.configsrecord import ConfigsRecord -from flwr.common.constant import TASK_TYPE_GET_PROPERTIES +from flwr.common.constant import MESSAGE_TYPE_GET_PROPERTIES from flwr.common.message import Message, Metadata from flwr.common.recordset import RecordSet from flwr.common.typing import Code, GetPropertiesRes, Status @@ -46,11 +46,11 @@ MESSAGE_GET_PROPERTIES = Message( metadata=Metadata( run_id=0, - task_id="", + message_id="", group_id="", node_id=0, ttl="", - task_type=TASK_TYPE_GET_PROPERTIES, + message_type=MESSAGE_TYPE_GET_PROPERTIES, ), content=compat.getpropertiesres_to_recordset( GetPropertiesRes(Status(Code.OK, ""), {}) @@ -59,11 +59,11 @@ MESSAGE_DISCONNECT = Message( metadata=Metadata( run_id=0, - task_id="", + message_id="", group_id="", node_id=0, ttl="", - task_type="reconnect", + message_type="reconnect", ), content=RecordSet(configs={"config": ConfigsRecord({"reason": 0})}), ) @@ -134,7 +134,7 @@ def run_client() -> int: message = receive() messages_received += 1 - if message.metadata.task_type == "reconnect": # type: ignore + if message.metadata.message_type == "reconnect": # type: ignore send(MESSAGE_DISCONNECT) break diff --git a/src/py/flwr/client/message_handler/message_handler.py b/src/py/flwr/client/message_handler/message_handler.py index 52dbdec7691b..93de7d7d8821 100644 --- a/src/py/flwr/client/message_handler/message_handler.py +++ b/src/py/flwr/client/message_handler/message_handler.py @@ -26,10 +26,10 @@ from flwr.client.typing import ClientFn from flwr.common.configsrecord import ConfigsRecord from flwr.common.constant import ( - TASK_TYPE_EVALUATE, - TASK_TYPE_FIT, - TASK_TYPE_GET_PARAMETERS, - TASK_TYPE_GET_PROPERTIES, + MESSAGE_TYPE_EVALUATE, + MESSAGE_TYPE_FIT, + MESSAGE_TYPE_GET_PARAMETERS, + MESSAGE_TYPE_GET_PROPERTIES, ) from flwr.common.context import Context from flwr.common.message import Message, Metadata @@ -75,7 +75,7 @@ def handle_control_message(message: Message) -> Tuple[Optional[Message], int]: sleep_duration : int Number of seconds that the client should disconnect from the server. """ - if message.metadata.task_type == "reconnect": + if message.metadata.message_type == "reconnect": # Retrieve ReconnectIns from recordset recordset = message.content seconds = cast(int, recordset.get_configs("config")["seconds"]) @@ -90,11 +90,11 @@ def handle_control_message(message: Message) -> Tuple[Optional[Message], int]: out_message = Message( metadata=Metadata( run_id=0, - task_id="", + message_id="", group_id="", node_id=0, ttl="", - task_type="reconnect", + message_type="reconnect", ), content=recordset, ) @@ -105,7 +105,7 @@ def handle_control_message(message: Message) -> Tuple[Optional[Message], int]: return None, 0 -def handle_legacy_message_from_tasktype( +def handle_legacy_message_from_msgtype( client_fn: ClientFn, message: Message, context: Context ) -> Message: """Handle legacy message in the inner most mod.""" @@ -113,17 +113,17 @@ def handle_legacy_message_from_tasktype( client.set_context(context) - task_type = message.metadata.task_type + message_type = message.metadata.message_type # Handle GetPropertiesIns - if task_type == TASK_TYPE_GET_PROPERTIES: + if message_type == MESSAGE_TYPE_GET_PROPERTIES: get_properties_res = maybe_call_get_properties( client=client, get_properties_ins=recordset_to_getpropertiesins(message.content), ) out_recordset = getpropertiesres_to_recordset(get_properties_res) # Handle GetParametersIns - elif task_type == TASK_TYPE_GET_PARAMETERS: + elif message_type == MESSAGE_TYPE_GET_PARAMETERS: get_parameters_res = maybe_call_get_parameters( client=client, get_parameters_ins=recordset_to_getparametersins(message.content), @@ -132,31 +132,31 @@ def handle_legacy_message_from_tasktype( get_parameters_res, keep_input=False ) # Handle FitIns - elif task_type == TASK_TYPE_FIT: + elif message_type == MESSAGE_TYPE_FIT: fit_res = maybe_call_fit( client=client, fit_ins=recordset_to_fitins(message.content, keep_input=True), ) out_recordset = fitres_to_recordset(fit_res, keep_input=False) # Handle EvaluateIns - elif task_type == TASK_TYPE_EVALUATE: + elif message_type == MESSAGE_TYPE_EVALUATE: evaluate_res = maybe_call_evaluate( client=client, evaluate_ins=recordset_to_evaluateins(message.content, keep_input=True), ) out_recordset = evaluateres_to_recordset(evaluate_res) else: - raise ValueError(f"Invalid task type: {task_type}") + raise ValueError(f"Invalid task type: {message_type}") # Return Message out_message = Message( metadata=Metadata( run_id=0, - task_id="", + message_id="", group_id="", node_id=0, ttl="", - task_type=task_type, + message_type=message_type, ), content=out_recordset, ) diff --git a/src/py/flwr/client/message_handler/message_handler_test.py b/src/py/flwr/client/message_handler/message_handler_test.py index 820de9bbe27c..c4c65d98b833 100644 --- a/src/py/flwr/client/message_handler/message_handler_test.py +++ b/src/py/flwr/client/message_handler/message_handler_test.py @@ -34,12 +34,12 @@ ) from flwr.common import recordset_compat as compat from flwr.common import typing -from flwr.common.constant import TASK_TYPE_GET_PROPERTIES +from flwr.common.constant import MESSAGE_TYPE_GET_PROPERTIES from flwr.common.context import Context from flwr.common.message import Message, Metadata from flwr.common.recordset import RecordSet -from .message_handler import handle_legacy_message_from_tasktype +from .message_handler import handle_legacy_message_from_msgtype class ClientWithoutProps(Client): @@ -122,17 +122,17 @@ def test_client_without_get_properties() -> None: message = Message( metadata=Metadata( run_id=0, - task_id=str(uuid.uuid4()), + message_id=str(uuid.uuid4()), group_id="", node_id=0, ttl="", - task_type=TASK_TYPE_GET_PROPERTIES, + message_type=MESSAGE_TYPE_GET_PROPERTIES, ), content=recordset, ) # Execute - actual_msg = handle_legacy_message_from_tasktype( + actual_msg = handle_legacy_message_from_msgtype( client_fn=_get_client_fn(client), message=message, context=Context(state=RecordSet()), @@ -150,7 +150,7 @@ def test_client_without_get_properties() -> None: expected_msg = Message(message.metadata, expected_rs) assert actual_msg.content == expected_msg.content - assert actual_msg.metadata.task_type == expected_msg.metadata.task_type + assert actual_msg.metadata.message_type == expected_msg.metadata.message_type def test_client_with_get_properties() -> None: @@ -161,17 +161,17 @@ def test_client_with_get_properties() -> None: message = Message( metadata=Metadata( run_id=0, - task_id=str(uuid.uuid4()), + message_id=str(uuid.uuid4()), group_id="", node_id=0, ttl="", - task_type=TASK_TYPE_GET_PROPERTIES, + message_type=MESSAGE_TYPE_GET_PROPERTIES, ), content=recordset, ) # Execute - actual_msg = handle_legacy_message_from_tasktype( + actual_msg = handle_legacy_message_from_msgtype( client_fn=_get_client_fn(client), message=message, context=Context(state=RecordSet()), @@ -189,4 +189,4 @@ def test_client_with_get_properties() -> None: expected_msg = Message(message.metadata, expected_rs) assert actual_msg.content == expected_msg.content - assert actual_msg.metadata.task_type == expected_msg.metadata.task_type + assert actual_msg.metadata.message_type == expected_msg.metadata.message_type diff --git a/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py b/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py index eba5dec658aa..fa5a9fd24109 100644 --- a/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py +++ b/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py @@ -24,7 +24,7 @@ from flwr.common import ndarray_to_bytes, parameters_to_ndarrays from flwr.common import recordset_compat as compat from flwr.common.configsrecord import ConfigsRecord -from flwr.common.constant import TASK_TYPE_FIT +from flwr.common.constant import MESSAGE_TYPE_FIT from flwr.common.context import Context from flwr.common.logger import log from flwr.common.message import Message, Metadata @@ -168,7 +168,7 @@ def secaggplus_mod( ) -> Message: """Handle incoming message and return results, following the SecAgg+ protocol.""" # Ignore non-fit messages - if msg.metadata.task_type != TASK_TYPE_FIT: + if msg.metadata.message_type != MESSAGE_TYPE_FIT: return call_next(msg, ctxt) # Retrieve local state @@ -209,11 +209,11 @@ def secaggplus_mod( return Message( metadata=Metadata( run_id=0, - task_id="", + message_id="", group_id="", node_id=0, ttl="", - task_type=TASK_TYPE_FIT, + message_type=MESSAGE_TYPE_FIT, ), content=RecordSet(configs={RECORD_KEY_CONFIGS: ConfigsRecord(res, False)}), ) diff --git a/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod_test.py b/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod_test.py index d0f461e7a8de..4033306d0845 100644 --- a/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod_test.py +++ b/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod_test.py @@ -20,7 +20,7 @@ from flwr.client.mod import make_ffn from flwr.common.configsrecord import ConfigsRecord -from flwr.common.constant import TASK_TYPE_FIT +from flwr.common.constant import MESSAGE_TYPE_FIT from flwr.common.context import Context from flwr.common.message import Message, Metadata from flwr.common.recordset import RecordSet @@ -59,11 +59,11 @@ def empty_ffn(_: Message, _2: Context) -> Message: return Message( metadata=Metadata( run_id=0, - task_id="", + message_id="", group_id="", node_id=0, ttl="", - task_type=TASK_TYPE_FIT, + message_type=MESSAGE_TYPE_FIT, ), content=RecordSet(), ) @@ -74,11 +74,11 @@ def func(configs: Dict[str, ConfigsRecordValues]) -> Dict[str, ConfigsRecordValu in_msg = Message( metadata=Metadata( run_id=0, - task_id="", + message_id="", group_id="", node_id=0, ttl="", - task_type=TASK_TYPE_FIT, + message_type=MESSAGE_TYPE_FIT, ), content=RecordSet(configs={RECORD_KEY_CONFIGS: ConfigsRecord(configs)}), ) diff --git a/src/py/flwr/client/mod/utils_test.py b/src/py/flwr/client/mod/utils_test.py index 07b38a250d6c..4a086d9ae3f7 100644 --- a/src/py/flwr/client/mod/utils_test.py +++ b/src/py/flwr/client/mod/utils_test.py @@ -75,7 +75,7 @@ def _get_dummy_flower_message() -> Message: return Message( content=RecordSet(), metadata=Metadata( - run_id=0, task_id="", group_id="", node_id=0, ttl="", task_type="mock" + run_id=0, message_id="", group_id="", node_id=0, ttl="", message_type="mock" ), ) diff --git a/src/py/flwr/common/constant.py b/src/py/flwr/common/constant.py index 8d1d865f084b..fcafd853a349 100644 --- a/src/py/flwr/common/constant.py +++ b/src/py/flwr/common/constant.py @@ -32,7 +32,7 @@ TRANSPORT_TYPE_REST, ] -TASK_TYPE_GET_PROPERTIES = "get_properties" -TASK_TYPE_GET_PARAMETERS = "get_parameters" -TASK_TYPE_FIT = "fit" -TASK_TYPE_EVALUATE = "evaluate" +MESSAGE_TYPE_GET_PROPERTIES = "get_properties" +MESSAGE_TYPE_GET_PARAMETERS = "get_parameters" +MESSAGE_TYPE_FIT = "fit" +MESSAGE_TYPE_EVALUATE = "evaluate" diff --git a/src/py/flwr/common/message.py b/src/py/flwr/common/message.py index ada4a617b60d..9258edccbcd5 100644 --- a/src/py/flwr/common/message.py +++ b/src/py/flwr/common/message.py @@ -22,32 +22,32 @@ @dataclass class Metadata: - """A dataclass holding metadata associated with the current task. + """A dataclass holding metadata associated with the current message. Parameters ---------- run_id : int An identifier for the current run. - task_id : str - An identifier for the current task. + message_id : str + An identifier for the current message. group_id : str - An identifier for grouping tasks. In some settings + An identifier for grouping messages. In some settings this is used as the FL round. node_id : int - An identifier for the node running a task. + An identifier for the node running a message. ttl : str - Time-to-live for this task. - task_type : str + Time-to-live for this message. + message_type : str A string that encodes the action to be executed on the receiving end. """ run_id: int - task_id: str + message_id: str group_id: str node_id: int ttl: str - task_type: str + message_type: str @dataclass @@ -57,7 +57,7 @@ class Message: Parameters ---------- metadata : Metadata - A dataclass including information about the task to be executed. + A dataclass including information about the message to be executed. content : RecordSet Holds records either sent by another entity (e.g. sent by the server-side logic to a client, or vice-versa) or that will be sent to it. diff --git a/src/py/flwr/common/serde.py b/src/py/flwr/common/serde.py index 5a8c5c753136..2808cb88fb5c 100644 --- a/src/py/flwr/common/serde.py +++ b/src/py/flwr/common/serde.py @@ -550,7 +550,7 @@ def message_to_taskins(message: Message) -> TaskIns: return TaskIns( task=Task( ttl=message.metadata.ttl, - task_type=message.metadata.task_type, + task_type=message.metadata.message_type, recordset=recordset_to_proto(message.content), ), ) @@ -561,11 +561,11 @@ def message_from_taskins(taskins: TaskIns) -> Message: # Retrieve the Metadata metadata = Metadata( run_id=taskins.run_id, - task_id=taskins.task_id, + message_id=taskins.task_id, group_id=taskins.group_id, node_id=taskins.task.consumer.node_id, ttl=taskins.task.ttl, - task_type=taskins.task.task_type, + message_type=taskins.task.task_type, ) # Return the Message @@ -580,7 +580,7 @@ def message_to_taskres(message: Message) -> TaskRes: return TaskRes( task=Task( ttl=message.metadata.ttl, - task_type=message.metadata.task_type, + task_type=message.metadata.message_type, recordset=recordset_to_proto(message.content), ), ) @@ -591,11 +591,11 @@ def message_from_taskres(taskres: TaskRes) -> Message: # Retrieve the MetaData metadata = Metadata( run_id=taskres.run_id, - task_id=taskres.task_id, + message_id=taskres.task_id, group_id=taskres.group_id, node_id=taskres.task.consumer.node_id, ttl=taskres.task.ttl, - task_type=taskres.task.task_type, + message_type=taskres.task.task_type, ) # Return the Message diff --git a/src/py/flwr/common/serde_test.py b/src/py/flwr/common/serde_test.py index 1c36f2171149..44085e8d9ab8 100644 --- a/src/py/flwr/common/serde_test.py +++ b/src/py/flwr/common/serde_test.py @@ -217,11 +217,11 @@ def metadata(self) -> Metadata: """Create a Metadata.""" return Metadata( run_id=self.rng.randint(0, 1 << 30), - task_id=self.get_str(64), + message_id=self.get_str(64), group_id=self.get_str(30), node_id=self.rng.randint(0, 1 << 63), ttl=self.get_str(10), - task_type=self.get_str(10), + message_type=self.get_str(10), ) @@ -308,11 +308,11 @@ def test_message_to_and_from_taskins() -> None: original = Message( metadata=Metadata( run_id=0, - task_id="", + message_id="", group_id="", node_id=metadata.node_id, ttl=metadata.ttl, - task_type=metadata.task_type, + message_type=metadata.message_type, ), content=maker.recordset(1, 1, 1), ) @@ -320,7 +320,7 @@ def test_message_to_and_from_taskins() -> None: # Execute taskins = message_to_taskins(original) taskins.run_id = metadata.run_id - taskins.task_id = metadata.task_id + taskins.task_id = metadata.message_id taskins.group_id = metadata.group_id taskins.task.consumer.node_id = metadata.node_id deserialized = message_from_taskins(taskins) @@ -338,11 +338,11 @@ def test_message_to_and_from_taskres() -> None: original = Message( metadata=Metadata( run_id=0, - task_id="", + message_id="", group_id="", node_id=metadata.node_id, ttl=metadata.ttl, - task_type=metadata.task_type, + message_type=metadata.message_type, ), content=maker.recordset(1, 1, 1), ) @@ -350,7 +350,7 @@ def test_message_to_and_from_taskres() -> None: # Execute taskres = message_to_taskres(original) taskres.run_id = metadata.run_id - taskres.task_id = metadata.task_id + taskres.task_id = metadata.message_id taskres.group_id = metadata.group_id taskres.task.consumer.node_id = metadata.node_id deserialized = message_from_taskres(taskres) diff --git a/src/py/flwr/server/driver/driver_client_proxy.py b/src/py/flwr/server/driver/driver_client_proxy.py index e0ff26c035f7..8ea288dbb50c 100644 --- a/src/py/flwr/server/driver/driver_client_proxy.py +++ b/src/py/flwr/server/driver/driver_client_proxy.py @@ -22,10 +22,10 @@ from flwr.common import recordset_compat as compat from flwr.common import serde from flwr.common.constant import ( - TASK_TYPE_EVALUATE, - TASK_TYPE_FIT, - TASK_TYPE_GET_PARAMETERS, - TASK_TYPE_GET_PROPERTIES, + MESSAGE_TYPE_EVALUATE, + MESSAGE_TYPE_FIT, + MESSAGE_TYPE_GET_PARAMETERS, + MESSAGE_TYPE_GET_PROPERTIES, ) from flwr.common.recordset import RecordSet from flwr.proto import driver_pb2, node_pb2, task_pb2 # pylint: disable=E0611 @@ -54,7 +54,7 @@ def get_properties( out_recordset = compat.getpropertiesins_to_recordset(ins) # Fetch response in_recordset = self._send_receive_recordset( - out_recordset, TASK_TYPE_GET_PROPERTIES, timeout + out_recordset, MESSAGE_TYPE_GET_PROPERTIES, timeout ) # RecordSet to Res return compat.recordset_to_getpropertiesres(in_recordset) @@ -67,7 +67,7 @@ def get_parameters( out_recordset = compat.getparametersins_to_recordset(ins) # Fetch response in_recordset = self._send_receive_recordset( - out_recordset, TASK_TYPE_GET_PARAMETERS, timeout + out_recordset, MESSAGE_TYPE_GET_PARAMETERS, timeout ) # RecordSet to Res return compat.recordset_to_getparametersres(in_recordset, False) @@ -78,7 +78,7 @@ def fit(self, ins: common.FitIns, timeout: Optional[float]) -> common.FitRes: out_recordset = compat.fitins_to_recordset(ins, keep_input=True) # Fetch response in_recordset = self._send_receive_recordset( - out_recordset, TASK_TYPE_FIT, timeout + out_recordset, MESSAGE_TYPE_FIT, timeout ) # RecordSet to Res return compat.recordset_to_fitres(in_recordset, keep_input=False) @@ -91,7 +91,7 @@ def evaluate( out_recordset = compat.evaluateins_to_recordset(ins, keep_input=True) # Fetch response in_recordset = self._send_receive_recordset( - out_recordset, TASK_TYPE_EVALUATE, timeout + out_recordset, MESSAGE_TYPE_EVALUATE, timeout ) # RecordSet to Res return compat.recordset_to_evaluateres(in_recordset) diff --git a/src/py/flwr/server/driver/driver_client_proxy_test.py b/src/py/flwr/server/driver/driver_client_proxy_test.py index 18277a7ce80c..aa60448bd72e 100644 --- a/src/py/flwr/server/driver/driver_client_proxy_test.py +++ b/src/py/flwr/server/driver/driver_client_proxy_test.py @@ -25,10 +25,10 @@ from flwr.common import recordset_compat as compat from flwr.common import serde from flwr.common.constant import ( - TASK_TYPE_EVALUATE, - TASK_TYPE_FIT, - TASK_TYPE_GET_PARAMETERS, - TASK_TYPE_GET_PROPERTIES, + MESSAGE_TYPE_EVALUATE, + MESSAGE_TYPE_FIT, + MESSAGE_TYPE_GET_PARAMETERS, + MESSAGE_TYPE_GET_PROPERTIES, ) from flwr.common.typing import ( Code, @@ -56,21 +56,21 @@ def _make_task( res: Union[GetParametersRes, GetPropertiesRes, FitRes, EvaluateRes] ) -> task_pb2.Task: # pylint: disable=E1101 if isinstance(res, GetParametersRes): - task_type = TASK_TYPE_GET_PARAMETERS + message_type = MESSAGE_TYPE_GET_PARAMETERS recordset = compat.getparametersres_to_recordset(res, True) elif isinstance(res, GetPropertiesRes): - task_type = TASK_TYPE_GET_PROPERTIES + message_type = MESSAGE_TYPE_GET_PROPERTIES recordset = compat.getpropertiesres_to_recordset(res) elif isinstance(res, FitRes): - task_type = TASK_TYPE_FIT + message_type = MESSAGE_TYPE_FIT recordset = compat.fitres_to_recordset(res, True) elif isinstance(res, EvaluateRes): - task_type = TASK_TYPE_EVALUATE + message_type = MESSAGE_TYPE_EVALUATE recordset = compat.evaluateres_to_recordset(res) else: raise ValueError(f"Unsupported type: {type(res)}") return task_pb2.Task( # pylint: disable=E1101 - task_type=task_type, + task_type=message_type, recordset=serde.recordset_to_proto(recordset), ) From 06295891c635197ca6629af9518eb4b9500147a2 Mon Sep 17 00:00:00 2001 From: Robert Steiner Date: Thu, 15 Feb 2024 11:33:19 +0100 Subject: [PATCH 107/113] Update URLs in READMEs (#2949) --- README.md | 50 +++++------ baselines/README.md | 6 +- baselines/fedpara/README.md | 84 +++++++++---------- datasets/README.md | 16 ++-- examples/advanced-pytorch/README.md | 2 +- examples/advanced-tensorflow/README.md | 2 +- examples/custom-metrics/README.md | 12 +-- examples/flower-via-docker-compose/README.md | 4 +- .../README.md | 2 +- examples/quickstart-huggingface/README.md | 2 +- examples/quickstart-pandas/README.md | 4 +- .../quickstart-pytorch-lightning/README.md | 2 +- examples/quickstart-pytorch/README.md | 2 +- examples/quickstart-sklearn-tabular/README.md | 2 +- examples/quickstart-tensorflow/README.md | 2 +- examples/simulation-pytorch/README.md | 4 +- examples/simulation-tensorflow/README.md | 4 +- examples/sklearn-logreg-mnist/README.md | 2 +- .../whisper-federated-finetuning/README.md | 4 +- examples/xgboost-comprehensive/README.md | 6 +- examples/xgboost-quickstart/README.md | 2 +- 21 files changed, 107 insertions(+), 107 deletions(-) diff --git a/README.md b/README.md index e4433e517b88..38a11d951fe7 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,16 @@ # Flower: A Friendly Federated Learning Framework

- - Flower Website + + Flower Website

- Website | - Blog | - Docs | - Conference | - Slack + Website | + Blog | + Docs | + Conference | + Slack

@@ -18,7 +18,7 @@ [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/adap/flower/blob/main/CONTRIBUTING.md) ![Build](https://github.com/adap/flower/actions/workflows/framework.yml/badge.svg) [![Downloads](https://static.pepy.tech/badge/flwr)](https://pepy.tech/project/flwr) -[![Slack](https://img.shields.io/badge/Chat-Slack-red)](https://flower.dev/join-slack) +[![Slack](https://img.shields.io/badge/Chat-Slack-red)](https://flower.ai/join-slack) Flower (`flwr`) is a framework for building federated learning systems. The design of Flower is based on a few guiding principles: @@ -39,7 +39,7 @@ design of Flower is based on a few guiding principles: - **Understandable**: Flower is written with maintainability in mind. The community is encouraged to both read and contribute to the codebase. -Meet the Flower community on [flower.dev](https://flower.dev)! +Meet the Flower community on [flower.ai](https://flower.ai)! ## Federated Learning Tutorial @@ -73,19 +73,19 @@ Stay tuned, more tutorials are coming soon. Topics include **Privacy and Securit ## Documentation -[Flower Docs](https://flower.dev/docs): +[Flower Docs](https://flower.ai/docs): -- [Installation](https://flower.dev/docs/framework/how-to-install-flower.html) -- [Quickstart (TensorFlow)](https://flower.dev/docs/framework/tutorial-quickstart-tensorflow.html) -- [Quickstart (PyTorch)](https://flower.dev/docs/framework/tutorial-quickstart-pytorch.html) -- [Quickstart (Hugging Face)](https://flower.dev/docs/framework/tutorial-quickstart-huggingface.html) -- [Quickstart (PyTorch Lightning)](https://flower.dev/docs/framework/tutorial-quickstart-pytorch-lightning.html) -- [Quickstart (Pandas)](https://flower.dev/docs/framework/tutorial-quickstart-pandas.html) -- [Quickstart (fastai)](https://flower.dev/docs/framework/tutorial-quickstart-fastai.html) -- [Quickstart (JAX)](https://flower.dev/docs/framework/tutorial-quickstart-jax.html) -- [Quickstart (scikit-learn)](https://flower.dev/docs/framework/tutorial-quickstart-scikitlearn.html) -- [Quickstart (Android [TFLite])](https://flower.dev/docs/framework/tutorial-quickstart-android.html) -- [Quickstart (iOS [CoreML])](https://flower.dev/docs/framework/tutorial-quickstart-ios.html) +- [Installation](https://flower.ai/docs/framework/how-to-install-flower.html) +- [Quickstart (TensorFlow)](https://flower.ai/docs/framework/tutorial-quickstart-tensorflow.html) +- [Quickstart (PyTorch)](https://flower.ai/docs/framework/tutorial-quickstart-pytorch.html) +- [Quickstart (Hugging Face)](https://flower.ai/docs/framework/tutorial-quickstart-huggingface.html) +- [Quickstart (PyTorch Lightning)](https://flower.ai/docs/framework/tutorial-quickstart-pytorch-lightning.html) +- [Quickstart (Pandas)](https://flower.ai/docs/framework/tutorial-quickstart-pandas.html) +- [Quickstart (fastai)](https://flower.ai/docs/framework/tutorial-quickstart-fastai.html) +- [Quickstart (JAX)](https://flower.ai/docs/framework/tutorial-quickstart-jax.html) +- [Quickstart (scikit-learn)](https://flower.ai/docs/framework/tutorial-quickstart-scikitlearn.html) +- [Quickstart (Android [TFLite])](https://flower.ai/docs/framework/tutorial-quickstart-android.html) +- [Quickstart (iOS [CoreML])](https://flower.ai/docs/framework/tutorial-quickstart-ios.html) ## Flower Baselines @@ -112,9 +112,9 @@ Flower Baselines is a collection of community-contributed projects that reproduc - [FedAvg](https://github.com/adap/flower/tree/main/baselines/flwr_baselines/flwr_baselines/publications/fedavg_mnist) - [FedOpt](https://github.com/adap/flower/tree/main/baselines/flwr_baselines/flwr_baselines/publications/adaptive_federated_optimization) -Please refer to the [Flower Baselines Documentation](https://flower.dev/docs/baselines/) for a detailed categorization of baselines and for additional info including: -* [How to use Flower Baselines](https://flower.dev/docs/baselines/how-to-use-baselines.html) -* [How to contribute a new Flower Baseline](https://flower.dev/docs/baselines/how-to-contribute-baselines.html) +Please refer to the [Flower Baselines Documentation](https://flower.ai/docs/baselines/) for a detailed categorization of baselines and for additional info including: +* [How to use Flower Baselines](https://flower.ai/docs/baselines/how-to-use-baselines.html) +* [How to contribute a new Flower Baseline](https://flower.ai/docs/baselines/how-to-contribute-baselines.html) ## Flower Usage Examples @@ -151,7 +151,7 @@ Other [examples](https://github.com/adap/flower/tree/main/examples): ## Community -Flower is built by a wonderful community of researchers and engineers. [Join Slack](https://flower.dev/join-slack) to meet them, [contributions](#contributing-to-flower) are welcome. +Flower is built by a wonderful community of researchers and engineers. [Join Slack](https://flower.ai/join-slack) to meet them, [contributions](#contributing-to-flower) are welcome. diff --git a/baselines/README.md b/baselines/README.md index a18c0553b2b4..3a84df02d8de 100644 --- a/baselines/README.md +++ b/baselines/README.md @@ -1,7 +1,7 @@ # Flower Baselines -> We are changing the way we structure the Flower baselines. While we complete the transition to the new format, you can still find the existing baselines in the `flwr_baselines` directory. Currently, you can make use of baselines for [FedAvg](https://github.com/adap/flower/tree/main/baselines/flwr_baselines/flwr_baselines/publications/fedavg_mnist), [FedOpt](https://github.com/adap/flower/tree/main/baselines/flwr_baselines/flwr_baselines/publications/adaptive_federated_optimization), and [LEAF-FEMNIST](https://github.com/adap/flower/tree/main/baselines/flwr_baselines/flwr_baselines/publications/leaf/femnist). +> We are changing the way we structure the Flower baselines. While we complete the transition to the new format, you can still find the existing baselines in the `flwr_baselines` directory. Currently, you can make use of baselines for [FedAvg](https://github.com/adap/flower/tree/main/baselines/flwr_baselines/flwr_baselines/publications/fedavg_mnist), [FedOpt](https://github.com/adap/flower/tree/main/baselines/flwr_baselines/flwr_baselines/publications/adaptive_federated_optimization), and [LEAF-FEMNIST](https://github.com/adap/flower/tree/main/baselines/flwr_baselines/flwr_baselines/publications/leaf/femnist). > The documentation below has been updated to reflect the new way of using Flower baselines. @@ -23,7 +23,7 @@ Please note that some baselines might include additional files (e.g. a `requirem ## Running the baselines -Each baseline is self-contained in its own directory. Furthermore, each baseline defines its own Python environment using [Poetry](https://python-poetry.org/docs/) via a `pyproject.toml` file and [`pyenv`](https://github.com/pyenv/pyenv). If you haven't setup `Poetry` and `pyenv` already on your machine, please take a look at the [Documentation](https://flower.dev/docs/baselines/how-to-use-baselines.html#setting-up-your-machine) for a guide on how to do so. +Each baseline is self-contained in its own directory. Furthermore, each baseline defines its own Python environment using [Poetry](https://python-poetry.org/docs/) via a `pyproject.toml` file and [`pyenv`](https://github.com/pyenv/pyenv). If you haven't setup `Poetry` and `pyenv` already on your machine, please take a look at the [Documentation](https://flower.ai/docs/baselines/how-to-use-baselines.html#setting-up-your-machine) for a guide on how to do so. Assuming `pyenv` and `Poetry` are already installed on your system. Running a baseline can be done by: @@ -54,7 +54,7 @@ The steps to follow are: ```bash # This will create a new directory with the same structure as `baseline_template`. ./dev/create-baseline.sh - ``` + ``` 3. Then, go inside your baseline directory and continue with the steps detailed in `EXTENDED_README.md` and `README.md`. 4. Once your code is ready and you have checked that following the instructions in your `README.md` the Python environment can be created correctly and that running the code following your instructions can reproduce the experiments in the paper, you just need to create a Pull Request (PR). Then, the process to merge your baseline into the Flower repo will begin! diff --git a/baselines/fedpara/README.md b/baselines/fedpara/README.md index 068366aa261c..82efe5fac537 100644 --- a/baselines/fedpara/README.md +++ b/baselines/fedpara/README.md @@ -5,7 +5,7 @@ labels: [image classification, personalization, low-rank training, tensor decomp dataset: [CIFAR-10, CIFAR-100, MNIST] --- -# FedPara: Low-rank Hadamard Product for Communication-Efficient Federated Learning +# FedPara: Low-rank Hadamard Product for Communication-Efficient Federated Learning > Note: If you use this baseline in your work, please remember to cite the original authors of the paper as well as the Flower paper. @@ -43,7 +43,7 @@ Specifically, it replicates the results for CIFAR-10 and CIFAR-100 in Figure 3 On a machine with RTX 3090Ti (24GB VRAM) it takes approximately 1h to run each CIFAR-10/100 experiment while using < 12GB of VRAM. You can lower the VRAM footprint my reducing the number of clients allowed to run in parallel in your GPU (do this by raising `client_resources.num_gpus`). -**Contributors:** Yahia Salaheldin Shaaban, Omar Mokhtar and Roeia Amr +**Contributors:** Yahia Salaheldin Shaaban, Omar Mokhtar and Roeia Amr ## Experimental Setup @@ -52,48 +52,48 @@ On a machine with RTX 3090Ti (24GB VRAM) it takes approximately 1h to run each C **Model:** This baseline implements VGG16 with group normalization. -**Dataset:** +**Dataset:** -| Dataset | #classes | #partitions | partitioning method IID | partitioning method non-IID | -|:---------|:--------:|:-----------:|:----------------------:| :----------------------:| -| CIFAR-10 | 10 | 100 | random split | Dirichlet distribution ($\alpha=0.5$)| -| CIFAR-100 | 100 | 50 | random split| Dirichlet distribution ($\alpha=0.5$)| +| Dataset | #classes | #partitions | partitioning method IID | partitioning method non-IID | +| :-------- | :------: | :---------: | :---------------------: | :-----------------------------------: | +| CIFAR-10 | 10 | 100 | random split | Dirichlet distribution ($\alpha=0.5$) | +| CIFAR-100 | 100 | 50 | random split | Dirichlet distribution ($\alpha=0.5$) | **Training Hyperparameters:** -| | Cifar10 IID | Cifar10 Non-IID | Cifar100 IID | Cifar100 Non-IID | MNIST | -|---|-------|-------|------|-------|----------| -| Fraction of client (K) | 16 | 16 | 8 | 8 | 10 | -| Total rounds (T) | 200 | 200 | 400 | 400 | 100 | -| Number of SGD epochs (E) | 10 | 5 | 10 | 5 | 5 | -| Batch size (B) | 64 | 64 | 64 | 64 | 10 | -| Initial learning rate (η) | 0.1 | 0.1 | 0.1 | 0.1 | 0.1-0.01 | -| Learning rate decay (τ) | 0.992 | 0.992 | 0.992| 0.992 | 0.999 | -| Regularization coefficient (λ) | 1 | 1 | 1 | 1 | 0 | +| | Cifar10 IID | Cifar10 Non-IID | Cifar100 IID | Cifar100 Non-IID | MNIST | +| ------------------------------ | ----------- | --------------- | ------------ | ---------------- | -------- | +| Fraction of client (K) | 16 | 16 | 8 | 8 | 10 | +| Total rounds (T) | 200 | 200 | 400 | 400 | 100 | +| Number of SGD epochs (E) | 10 | 5 | 10 | 5 | 5 | +| Batch size (B) | 64 | 64 | 64 | 64 | 10 | +| Initial learning rate (η) | 0.1 | 0.1 | 0.1 | 0.1 | 0.1-0.01 | +| Learning rate decay (τ) | 0.992 | 0.992 | 0.992 | 0.992 | 0.999 | +| Regularization coefficient (λ) | 1 | 1 | 1 | 1 | 0 | As for the parameters ratio ($\gamma$) we use the following model sizes. As in the paper, $\gamma=0.1$ is used for CIFAR-10 and $\gamma=0.4$ for CIFAR-100: | Parameters ratio ($\gamma$) | CIFAR-10 | CIFAR-100 | -|----------|--------|--------| -| 1.0 (original) | 15.25M | 15.30M | -| 0.1 | 1.55M | - | -| 0.4 | - | 4.53M | +| --------------------------- | -------- | --------- | +| 1.0 (original) | 15.25M | 15.30M | +| 0.1 | 1.55M | - | +| 0.4 | - | 4.53M | -### Notes: +### Notes: - Notably, Fedpara's low-rank training technique heavily relies on initialization, with our experiments revealing that employing a 'Fan-in' He initialization (or Kaiming) renders the model incapable of convergence, resulting in a performance akin to that of a random classifier. We found that only Fan-out initialization yielded the anticipated results, and we postulated that this is attributed to the variance conservation during backward propagation. - The paper lacks explicit guidance on calculating the rank, aside from the "Rank_min - Rank_max" equation. To address this, we devised an equation aligning with the literature's explanation and constraint, solving a quadratic equation to determine max_rank and utilizing proposition 2 from the paper to establish min_rank. - The Jacobian correction was not incorporated into our implementation, primarily due to the lack of explicit instructions in the paper regarding the specific implementation of the dual update principle mentioned in the Jacobian correction section. -- It was observed that data generation is crutial for model convergence +- It was observed that data generation is crutial for model convergence ## Environment Setup To construct the Python environment follow these steps: -It is assumed that `pyenv` is installed, `poetry` is installed and python 3.10.6 is installed using `pyenv`. Refer to this [documentation](https://flower.dev/docs/baselines/how-to-usef-baselines.html#setting-up-your-machine) to ensure that your machine is ready. +It is assumed that `pyenv` is installed, `poetry` is installed and python 3.10.6 is installed using `pyenv`. Refer to this [documentation](https://flower.ai/docs/baselines/how-to-usef-baselines.html#setting-up-your-machine) to ensure that your machine is ready. ```bash # Set Python 3.10 @@ -112,7 +112,7 @@ poetry shell Running `FedPara` is easy. You can run it with default parameters directly or by tweaking them directly on the command line. Some command examples are shown below. -```bash +```bash # To run fedpara with default parameters python -m fedpara.main @@ -138,45 +138,45 @@ To reproduce the curves shown below (which correspond to those in Figure 3 in th ```bash # To run fedpara for non-iid CIFAR-10 on vgg16 for lowrank and original schemes -python -m fedpara.main --multirun model.param_type=standard,lowrank +python -m fedpara.main --multirun model.param_type=standard,lowrank # To run fedpara for non-iid CIFAR-100 on vgg16 for lowrank and original schemes -python -m fedpara.main --config-name cifar100 --multirun model.param_type=standard,lowrank +python -m fedpara.main --config-name cifar100 --multirun model.param_type=standard,lowrank # To run fedpara for iid CIFAR-10 on vgg16 for lowrank and original schemes -python -m fedpara.main --multirun model.param_type=standard,lowrank num_epochs=10 dataset_config.partition=iid +python -m fedpara.main --multirun model.param_type=standard,lowrank num_epochs=10 dataset_config.partition=iid # To run fedpara for iid CIFAR-100 on vgg16 for lowrank and original schemes python -m fedpara.main --config-name cifar100 --multirun model.param_type=standard,lowrank num_epochs=10 dataset_config.partition=iid -# To run fedavg for non-iid MINST on FC -python -m fedpara.main --config-name mnist_fedavg -# To run fedper for non-iid MINST on FC -python -m fedpara.main --config-name mnist_fedper -# To run pfedpara for non-iid MINST on FC -python -m fedpara.main --config-name mnist_pfedpara +# To run fedavg for non-iid MINST on FC +python -m fedpara.main --config-name mnist_fedavg +# To run fedper for non-iid MINST on FC +python -m fedpara.main --config-name mnist_fedper +# To run pfedpara for non-iid MINST on FC +python -m fedpara.main --config-name mnist_pfedpara ``` -#### Communication Cost: -Communication costs as measured as described in the paper: +#### Communication Cost: +Communication costs as measured as described in the paper: *"FL evaluation typically measures the required rounds to achieve the target accuracy as communication costs, but we instead assess total transferred bit sizes, 2 × (#participants)×(model size)×(#rounds)"* ### CIFAR-100 (Accuracy vs Communication Cost) -| IID | Non-IID | -|:----:|:----:| -|![Cifar100 iid](_static/Cifar100_iid.jpeg) | ![Cifar100 non-iid](_static/Cifar100_noniid.jpeg) | +| IID | Non-IID | +| :----------------------------------------: | :-----------------------------------------------: | +| ![Cifar100 iid](_static/Cifar100_iid.jpeg) | ![Cifar100 non-iid](_static/Cifar100_noniid.jpeg) | ### CIFAR-10 (Accuracy vs Communication Cost) -| IID | Non-IID | -|:----:|:----:| -|![CIFAR10 iid](_static/Cifar10_iid.jpeg) | ![CIFAR10 non-iid](_static/Cifar10_noniid.jpeg) | +| IID | Non-IID | +| :--------------------------------------: | :---------------------------------------------: | +| ![CIFAR10 iid](_static/Cifar10_iid.jpeg) | ![CIFAR10 non-iid](_static/Cifar10_noniid.jpeg) | ### NON-IID MINST (FedAvg vs FedPer vs pFedPara) The only federated averaging (FedAvg) implementation replicates the results outlined in the paper. However, challenges with convergence were encountered when applying `pFedPara` and `FedPer` methods. -![Personalization algorithms](_static/non-iid_mnist_personalization.png) +![Personalization algorithms](_static/non-iid_mnist_personalization.png) ## Code Acknowledgments Our code is inspired from these repos: diff --git a/datasets/README.md b/datasets/README.md index 876b6f453fa5..61292fe988bf 100644 --- a/datasets/README.md +++ b/datasets/README.md @@ -4,9 +4,9 @@ [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/adap/flower/blob/main/CONTRIBUTING.md) ![Build](https://github.com/adap/flower/actions/workflows/framework.yml/badge.svg) ![Downloads](https://pepy.tech/badge/flwr-datasets) -[![Slack](https://img.shields.io/badge/Chat-Slack-red)](https://flower.dev/join-slack) +[![Slack](https://img.shields.io/badge/Chat-Slack-red)](https://flower.ai/join-slack) -Flower Datasets (`flwr-datasets`) is a library to quickly and easily create datasets for federated learning, federated evaluation, and federated analytics. It was created by the `Flower Labs` team that also created Flower: A Friendly Federated Learning Framework. +Flower Datasets (`flwr-datasets`) is a library to quickly and easily create datasets for federated learning, federated evaluation, and federated analytics. It was created by the `Flower Labs` team that also created Flower: A Friendly Federated Learning Framework. Flower Datasets library supports: * **downloading datasets** - choose the dataset from Hugging Face's `datasets`, * **partitioning datasets** - customize the partitioning scheme, @@ -14,10 +14,10 @@ Flower Datasets library supports: Thanks to using Hugging Face's `datasets` used under the hood, Flower Datasets integrates with the following popular formats/frameworks: * Hugging Face, -* PyTorch, -* TensorFlow, -* Numpy, -* Pandas, +* PyTorch, +* TensorFlow, +* Numpy, +* Pandas, * Jax, * Arrow. @@ -25,7 +25,7 @@ Create **custom partitioning schemes** or choose from the **implemented partitio * Partitioner (the abstract base class) `Partitioner` * IID partitioning `IidPartitioner(num_partitions)` * Natural ID partitioner `NaturalIdPartitioner` -* Size partitioner (the abstract base class for the partitioners dictating the division based the number of samples) `SizePartitioner` +* Size partitioner (the abstract base class for the partitioners dictating the division based the number of samples) `SizePartitioner` * Linear partitioner `LinearPartitioner` * Square partitioner `SquarePartitioner` * Exponential partitioner `ExponentialPartitioner` @@ -83,7 +83,7 @@ Here are a few of the things that we will work on in future releases: * ✅ Support for more datasets (especially the ones that have user id present). * ✅ Creation of custom `Partitioner`s. * ✅ More out-of-the-box `Partitioner`s. -* ✅ Passing `Partitioner`s via `FederatedDataset`'s `partitioners` argument. +* ✅ Passing `Partitioner`s via `FederatedDataset`'s `partitioners` argument. * ✅ Customization of the dataset splitting before the partitioning. * Simplification of the dataset transformation to the popular frameworks/types. * Creation of the synthetic data, diff --git a/examples/advanced-pytorch/README.md b/examples/advanced-pytorch/README.md index 9101105b2618..c1ba85b95879 100644 --- a/examples/advanced-pytorch/README.md +++ b/examples/advanced-pytorch/README.md @@ -1,6 +1,6 @@ # Advanced Flower Example (PyTorch) -This example demonstrates an advanced federated learning setup using Flower with PyTorch. This example uses [Flower Datasets](https://flower.dev/docs/datasets/) and it differs from the quickstart example in the following ways: +This example demonstrates an advanced federated learning setup using Flower with PyTorch. This example uses [Flower Datasets](https://flower.ai/docs/datasets/) and it differs from the quickstart example in the following ways: - 10 clients (instead of just 2) - Each client holds a local dataset of 5000 training examples and 1000 test examples (note that using the `run.sh` script will only select 10 data samples by default, as the `--toy` argument is set). diff --git a/examples/advanced-tensorflow/README.md b/examples/advanced-tensorflow/README.md index b21c0d2545ca..59866fd99a06 100644 --- a/examples/advanced-tensorflow/README.md +++ b/examples/advanced-tensorflow/README.md @@ -1,6 +1,6 @@ # Advanced Flower Example (TensorFlow/Keras) -This example demonstrates an advanced federated learning setup using Flower with TensorFlow/Keras. This example uses [Flower Datasets](https://flower.dev/docs/datasets/) and it differs from the quickstart example in the following ways: +This example demonstrates an advanced federated learning setup using Flower with TensorFlow/Keras. This example uses [Flower Datasets](https://flower.ai/docs/datasets/) and it differs from the quickstart example in the following ways: - 10 clients (instead of just 2) - Each client holds a local dataset of 1/10 of the train datasets and 80% is training examples and 20% as test examples (note that by default only a small subset of this data is used when running the `run.sh` script) diff --git a/examples/custom-metrics/README.md b/examples/custom-metrics/README.md index debcd7919839..317fb6336106 100644 --- a/examples/custom-metrics/README.md +++ b/examples/custom-metrics/README.md @@ -9,7 +9,7 @@ The main takeaways of this implementation are: - the use of the `output_dict` on the client side - inside `evaluate` method on `client.py` - the use of the `evaluate_metrics_aggregation_fn` - to aggregate the metrics on the server side, part of the `strategy` on `server.py` -This example is based on the `quickstart-tensorflow` with CIFAR-10, source [here](https://flower.dev/docs/quickstart-tensorflow.html), with the addition of [Flower Datasets](https://flower.dev/docs/datasets/index.html) to retrieve the CIFAR-10. +This example is based on the `quickstart-tensorflow` with CIFAR-10, source [here](https://flower.ai/docs/quickstart-tensorflow.html), with the addition of [Flower Datasets](https://flower.ai/docs/datasets/index.html) to retrieve the CIFAR-10. Using the CIFAR-10 dataset for classification, this is a multi-class classification problem, thus some changes on how to calculate the metrics using `average='micro'` and `np.argmax` is required. For binary classification, this is not required. Also, for unsupervised learning tasks, such as using a deep autoencoder, a custom metric based on reconstruction error could be implemented on client side. @@ -91,16 +91,16 @@ chmod +x run.sh ./run.sh ``` -You will see that Keras is starting a federated training. Have a look to the [Flower Quickstarter documentation](https://flower.dev/docs/quickstart-tensorflow.html) for a detailed explanation. You can add `steps_per_epoch=3` to `model.fit()` if you just want to evaluate that everything works without having to wait for the client-side training to finish (this will save you a lot of time during development). +You will see that Keras is starting a federated training. Have a look to the [Flower Quickstarter documentation](https://flower.ai/docs/quickstart-tensorflow.html) for a detailed explanation. You can add `steps_per_epoch=3` to `model.fit()` if you just want to evaluate that everything works without having to wait for the client-side training to finish (this will save you a lot of time during development). Running `run.sh` will result in the following output (after 3 rounds): ```shell INFO flwr 2024-01-17 17:45:23,794 | app.py:228 | app_fit: metrics_distributed { - 'accuracy': [(1, 0.10000000149011612), (2, 0.10000000149011612), (3, 0.3393000066280365)], - 'acc': [(1, 0.1), (2, 0.1), (3, 0.3393)], - 'rec': [(1, 0.1), (2, 0.1), (3, 0.3393)], - 'prec': [(1, 0.1), (2, 0.1), (3, 0.3393)], + 'accuracy': [(1, 0.10000000149011612), (2, 0.10000000149011612), (3, 0.3393000066280365)], + 'acc': [(1, 0.1), (2, 0.1), (3, 0.3393)], + 'rec': [(1, 0.1), (2, 0.1), (3, 0.3393)], + 'prec': [(1, 0.1), (2, 0.1), (3, 0.3393)], 'f1': [(1, 0.10000000000000002), (2, 0.10000000000000002), (3, 0.3393)] } ``` diff --git a/examples/flower-via-docker-compose/README.md b/examples/flower-via-docker-compose/README.md index 1d830e46cbdb..3ef1ac37bcda 100644 --- a/examples/flower-via-docker-compose/README.md +++ b/examples/flower-via-docker-compose/README.md @@ -1,7 +1,7 @@ # Leveraging Flower and Docker for Device Heterogeneity Management in Federated Learning

- Flower Website + Flower Website Docker Logo

@@ -141,7 +141,7 @@ By following these steps, you will have a fully functional federated learning en ### Data Pipeline with FLWR-Datasets -We have integrated [`flwr-datasets`](https://flower.dev/docs/datasets/) into our data pipeline, which is managed within the `load_data.py` file in the `helpers/` directory. This script facilitates standardized access to datasets across the federated network and incorporates a `data_sampling_percentage` argument. This argument allows users to specify the percentage of the dataset to be used for training and evaluation, accommodating devices with lower memory capabilities to prevent Out-of-Memory (OOM) errors. +We have integrated [`flwr-datasets`](https://flower.ai/docs/datasets/) into our data pipeline, which is managed within the `load_data.py` file in the `helpers/` directory. This script facilitates standardized access to datasets across the federated network and incorporates a `data_sampling_percentage` argument. This argument allows users to specify the percentage of the dataset to be used for training and evaluation, accommodating devices with lower memory capabilities to prevent Out-of-Memory (OOM) errors. ### Model Selection and Dataset diff --git a/examples/pytorch-from-centralized-to-federated/README.md b/examples/pytorch-from-centralized-to-federated/README.md index fccb14158ecd..06ee89dddcac 100644 --- a/examples/pytorch-from-centralized-to-federated/README.md +++ b/examples/pytorch-from-centralized-to-federated/README.md @@ -2,7 +2,7 @@ This example demonstrates how an already existing centralized PyTorch-based machine learning project can be federated with Flower. -This introductory example for Flower uses PyTorch, but you're not required to be a PyTorch expert to run the example. The example will help you to understand how Flower can be used to build federated learning use cases based on existing machine learning projects. This example uses [Flower Datasets](https://flower.dev/docs/datasets/) to download, partition and preprocess the CIFAR-10 dataset. +This introductory example for Flower uses PyTorch, but you're not required to be a PyTorch expert to run the example. The example will help you to understand how Flower can be used to build federated learning use cases based on existing machine learning projects. This example uses [Flower Datasets](https://flower.ai/docs/datasets/) to download, partition and preprocess the CIFAR-10 dataset. ## Project Setup diff --git a/examples/quickstart-huggingface/README.md b/examples/quickstart-huggingface/README.md index fd868aa1fcce..5fdba887f181 100644 --- a/examples/quickstart-huggingface/README.md +++ b/examples/quickstart-huggingface/README.md @@ -1,6 +1,6 @@ # Federated HuggingFace Transformers using Flower and PyTorch -This introductory example to using [HuggingFace](https://huggingface.co) Transformers with Flower with PyTorch. This example has been extended from the [quickstart-pytorch](https://flower.dev/docs/examples/quickstart-pytorch.html) example. The training script closely follows the [HuggingFace course](https://huggingface.co/course/chapter3?fw=pt), so you are encouraged to check that out for a detailed explanation of the transformer pipeline. +This introductory example to using [HuggingFace](https://huggingface.co) Transformers with Flower with PyTorch. This example has been extended from the [quickstart-pytorch](https://flower.ai/docs/examples/quickstart-pytorch.html) example. The training script closely follows the [HuggingFace course](https://huggingface.co/course/chapter3?fw=pt), so you are encouraged to check that out for a detailed explanation of the transformer pipeline. Like `quickstart-pytorch`, running this example in itself is also meant to be quite easy. diff --git a/examples/quickstart-pandas/README.md b/examples/quickstart-pandas/README.md index a25e6ea6ee36..efcda43cf34d 100644 --- a/examples/quickstart-pandas/README.md +++ b/examples/quickstart-pandas/README.md @@ -1,6 +1,6 @@ # Flower Example using Pandas -This introductory example to Flower uses Pandas, but deep knowledge of Pandas is not necessarily required to run the example. However, it will help you understand how to adapt Flower to your use case. This example uses [Flower Datasets](https://flower.dev/docs/datasets/) to +This introductory example to Flower uses Pandas, but deep knowledge of Pandas is not necessarily required to run the example. However, it will help you understand how to adapt Flower to your use case. This example uses [Flower Datasets](https://flower.ai/docs/datasets/) to download, partition and preprocess the dataset. Running this example in itself is quite easy. @@ -79,4 +79,4 @@ Start client 2 in the second terminal: $ python3 client.py --node-id 1 ``` -You will see that the server is printing aggregated statistics about the dataset distributed amongst clients. Have a look to the [Flower Quickstarter documentation](https://flower.dev/docs/quickstart-pandas.html) for a detailed explanation. +You will see that the server is printing aggregated statistics about the dataset distributed amongst clients. Have a look to the [Flower Quickstarter documentation](https://flower.ai/docs/quickstart-pandas.html) for a detailed explanation. diff --git a/examples/quickstart-pytorch-lightning/README.md b/examples/quickstart-pytorch-lightning/README.md index 1287b50bca65..1d404a5d714f 100644 --- a/examples/quickstart-pytorch-lightning/README.md +++ b/examples/quickstart-pytorch-lightning/README.md @@ -1,6 +1,6 @@ # Flower Example using PyTorch Lightning -This introductory example to Flower uses PyTorch, but deep knowledge of PyTorch Lightning is not necessarily required to run the example. However, it will help you understand how to adapt Flower to your use case. Running this example in itself is quite easy. This example uses [Flower Datasets](https://flower.dev/docs/datasets/) to download, partition and preprocess the MNIST dataset. +This introductory example to Flower uses PyTorch, but deep knowledge of PyTorch Lightning is not necessarily required to run the example. However, it will help you understand how to adapt Flower to your use case. Running this example in itself is quite easy. This example uses [Flower Datasets](https://flower.ai/docs/datasets/) to download, partition and preprocess the MNIST dataset. ## Project Setup diff --git a/examples/quickstart-pytorch/README.md b/examples/quickstart-pytorch/README.md index 6de0dcf7ab32..3b9b9b310608 100644 --- a/examples/quickstart-pytorch/README.md +++ b/examples/quickstart-pytorch/README.md @@ -1,6 +1,6 @@ # Flower Example using PyTorch -This introductory example to Flower uses PyTorch, but deep knowledge of PyTorch is not necessarily required to run the example. However, it will help you understand how to adapt Flower to your use case. Running this example in itself is quite easy. This example uses [Flower Datasets](https://flower.dev/docs/datasets/) to download, partition and preprocess the CIFAR-10 dataset. +This introductory example to Flower uses PyTorch, but deep knowledge of PyTorch is not necessarily required to run the example. However, it will help you understand how to adapt Flower to your use case. Running this example in itself is quite easy. This example uses [Flower Datasets](https://flower.ai/docs/datasets/) to download, partition and preprocess the CIFAR-10 dataset. ## Project Setup diff --git a/examples/quickstart-sklearn-tabular/README.md b/examples/quickstart-sklearn-tabular/README.md index d62525c96c18..373aaea5999c 100644 --- a/examples/quickstart-sklearn-tabular/README.md +++ b/examples/quickstart-sklearn-tabular/README.md @@ -3,7 +3,7 @@ This example of Flower uses `scikit-learn`'s `LogisticRegression` model to train a federated learning system on "iris" (tabular) dataset. It will help you understand how to adapt Flower for use with `scikit-learn`. -Running this example in itself is quite easy. This example uses [Flower Datasets](https://flower.dev/docs/datasets/) to +Running this example in itself is quite easy. This example uses [Flower Datasets](https://flower.ai/docs/datasets/) to download, partition and preprocess the dataset. ## Project Setup diff --git a/examples/quickstart-tensorflow/README.md b/examples/quickstart-tensorflow/README.md index 92d38c9340d7..8d5e9434b086 100644 --- a/examples/quickstart-tensorflow/README.md +++ b/examples/quickstart-tensorflow/README.md @@ -1,7 +1,7 @@ # Flower Example using TensorFlow/Keras This introductory example to Flower uses Keras but deep knowledge of Keras is not necessarily required to run the example. However, it will help you understand how to adapt Flower to your use case. -Running this example in itself is quite easy. This example uses [Flower Datasets](https://flower.dev/docs/datasets/) to download, partition and preprocess the CIFAR-10 dataset. +Running this example in itself is quite easy. This example uses [Flower Datasets](https://flower.ai/docs/datasets/) to download, partition and preprocess the CIFAR-10 dataset. ## Project Setup diff --git a/examples/simulation-pytorch/README.md b/examples/simulation-pytorch/README.md index 11b7a3364376..5ba5ec70dc3e 100644 --- a/examples/simulation-pytorch/README.md +++ b/examples/simulation-pytorch/README.md @@ -1,6 +1,6 @@ # Flower Simulation example using PyTorch -This introductory example uses the simulation capabilities of Flower to simulate a large number of clients on a single machine. Take a look at the [Documentation](https://flower.dev/docs/framework/how-to-run-simulations.html) for a deep dive into how Flower simulation works. This example uses [Flower Datasets](https://flower.dev/docs/datasets/) to download, partition and preprocess the MNIST dataset. This examples uses 100 clients by default. +This introductory example uses the simulation capabilities of Flower to simulate a large number of clients on a single machine. Take a look at the [Documentation](https://flower.ai/docs/framework/how-to-run-simulations.html) for a deep dive into how Flower simulation works. This example uses [Flower Datasets](https://flower.ai/docs/datasets/) to download, partition and preprocess the MNIST dataset. This examples uses 100 clients by default. ## Running the example (via Jupyter Notebook) @@ -79,4 +79,4 @@ python sim.py --num_cpus=2 python sim.py --num_cpus=2 --num_gpus=0.2 ``` -Take a look at the [Documentation](https://flower.dev/docs/framework/how-to-run-simulations.html) for more details on how you can customise your simulation. +Take a look at the [Documentation](https://flower.ai/docs/framework/how-to-run-simulations.html) for more details on how you can customise your simulation. diff --git a/examples/simulation-tensorflow/README.md b/examples/simulation-tensorflow/README.md index f0d94f343d37..75be823db2eb 100644 --- a/examples/simulation-tensorflow/README.md +++ b/examples/simulation-tensorflow/README.md @@ -1,6 +1,6 @@ # Flower Simulation example using TensorFlow/Keras -This introductory example uses the simulation capabilities of Flower to simulate a large number of clients on a single machine. Take a look at the [Documentation](https://flower.dev/docs/framework/how-to-run-simulations.html) for a deep dive into how Flower simulation works. This example uses [Flower Datasets](https://flower.dev/docs/datasets/) to download, partition and preprocess the MNIST dataset. This examples uses 100 clients by default. +This introductory example uses the simulation capabilities of Flower to simulate a large number of clients on a single machine. Take a look at the [Documentation](https://flower.ai/docs/framework/how-to-run-simulations.html) for a deep dive into how Flower simulation works. This example uses [Flower Datasets](https://flower.ai/docs/datasets/) to download, partition and preprocess the MNIST dataset. This examples uses 100 clients by default. ## Running the example (via Jupyter Notebook) @@ -78,4 +78,4 @@ python sim.py --num_cpus=2 python sim.py --num_cpus=2 --num_gpus=0.2 ``` -Take a look at the [Documentation](https://flower.dev/docs/framework/how-to-run-simulations.html) for more details on how you can customise your simulation. +Take a look at the [Documentation](https://flower.ai/docs/framework/how-to-run-simulations.html) for more details on how you can customise your simulation. diff --git a/examples/sklearn-logreg-mnist/README.md b/examples/sklearn-logreg-mnist/README.md index ee3cdfc9768e..50576d98ba3d 100644 --- a/examples/sklearn-logreg-mnist/README.md +++ b/examples/sklearn-logreg-mnist/README.md @@ -1,7 +1,7 @@ # Flower Example using scikit-learn This example of Flower uses `scikit-learn`'s `LogisticRegression` model to train a federated learning system. It will help you understand how to adapt Flower for use with `scikit-learn`. -Running this example in itself is quite easy. This example uses [Flower Datasets](https://flower.dev/docs/datasets/) to download, partition and preprocess the MNIST dataset. +Running this example in itself is quite easy. This example uses [Flower Datasets](https://flower.ai/docs/datasets/) to download, partition and preprocess the MNIST dataset. ## Project Setup diff --git a/examples/whisper-federated-finetuning/README.md b/examples/whisper-federated-finetuning/README.md index e89a09519fed..ddebe51247b2 100644 --- a/examples/whisper-federated-finetuning/README.md +++ b/examples/whisper-federated-finetuning/README.md @@ -110,7 +110,7 @@ An overview of the FL pipeline built with Flower for this example is illustrated 3. Once on-site training is completed, each client sends back the (now updated) classification head to the Flower server. 4. The Flower server aggregates (via FedAvg) the classification heads in order to obtain a new _global_ classification head. This head will be shared with clients in the next round. -Flower supports two ways of doing Federated Learning: simulated and non-simulated FL. The former, managed by the [`VirtualClientEngine`](https://flower.dev/docs/framework/how-to-run-simulations.html), allows you to run large-scale workloads in a system-aware manner, that scales with the resources available on your system (whether it is a laptop, a desktop with a single GPU, or a cluster of GPU servers). The latter is better suited for settings where clients are unique devices (e.g. a server, a smart device, etc). This example shows you how to use both. +Flower supports two ways of doing Federated Learning: simulated and non-simulated FL. The former, managed by the [`VirtualClientEngine`](https://flower.ai/docs/framework/how-to-run-simulations.html), allows you to run large-scale workloads in a system-aware manner, that scales with the resources available on your system (whether it is a laptop, a desktop with a single GPU, or a cluster of GPU servers). The latter is better suited for settings where clients are unique devices (e.g. a server, a smart device, etc). This example shows you how to use both. ### Preparing the dataset @@ -147,7 +147,7 @@ INFO flwr 2023-11-08 14:03:57,557 | app.py:229 | app_fit: metrics_centralized {' With just 5 FL rounds, the global model should be reaching ~95% validation accuracy. A test accuracy of 97% can be reached with 10 rounds of FL training using the default hyperparameters. On an RTX 3090Ti, each round takes ~20-30s depending on the amount of data the clients selected in a round have. -Take a look at the [Documentation](https://flower.dev/docs/framework/how-to-run-simulations.html) for more details on how you can customize your simulation. +Take a look at the [Documentation](https://flower.ai/docs/framework/how-to-run-simulations.html) for more details on how you can customize your simulation. ### Federated Finetuning (non-simulated) diff --git a/examples/xgboost-comprehensive/README.md b/examples/xgboost-comprehensive/README.md index 97ecc39b47f2..01fed646d056 100644 --- a/examples/xgboost-comprehensive/README.md +++ b/examples/xgboost-comprehensive/README.md @@ -1,7 +1,7 @@ # Flower Example using XGBoost (Comprehensive) This example demonstrates a comprehensive federated learning setup using Flower with XGBoost. -We use [HIGGS](https://archive.ics.uci.edu/dataset/280/higgs) dataset to perform a binary classification task. This examples uses [Flower Datasets](https://flower.dev/docs/datasets/) to retrieve, partition and preprocess the data for each Flower client. +We use [HIGGS](https://archive.ics.uci.edu/dataset/280/higgs) dataset to perform a binary classification task. This examples uses [Flower Datasets](https://flower.ai/docs/datasets/) to retrieve, partition and preprocess the data for each Flower client. It differs from the [xgboost-quickstart](https://github.com/adap/flower/tree/main/examples/xgboost-quickstart) example in the following ways: - Arguments parsers of server and clients for hyperparameters selection. @@ -91,7 +91,7 @@ pip install -r requirements.txt ## Run Federated Learning with XGBoost and Flower -You can run this example in two ways: either by manually launching the server, and then several clients that connect to it; or by launching a Flower simulation. Both run the same workload, yielding identical results. The former is ideal for deployments on different machines, while the latter makes it easy to simulate large client cohorts in a resource-aware manner. You can read more about how Flower Simulation works in the [Documentation](https://flower.dev/docs/framework/how-to-run-simulations.html). The commands shown below assume you have activated your environment (if you decide to use Poetry, you can activate it via `poetry shell`). +You can run this example in two ways: either by manually launching the server, and then several clients that connect to it; or by launching a Flower simulation. Both run the same workload, yielding identical results. The former is ideal for deployments on different machines, while the latter makes it easy to simulate large client cohorts in a resource-aware manner. You can read more about how Flower Simulation works in the [Documentation](https://flower.ai/docs/framework/how-to-run-simulations.html). The commands shown below assume you have activated your environment (if you decide to use Poetry, you can activate it via `poetry shell`). ### Independent Client/Server Setup @@ -143,7 +143,7 @@ python sim.py --train-method=cyclic --pool-size=5 --num-rounds=30 --centralised- ``` In addition, we provide more options to customise the experimental settings, including data partitioning and centralised/distributed evaluation (see `utils.py`). -Check the [tutorial](https://flower.dev/docs/framework/tutorial-quickstart-xgboost.html) for a detailed explanation. +Check the [tutorial](https://flower.ai/docs/framework/tutorial-quickstart-xgboost.html) for a detailed explanation. ### Expected Experimental Results diff --git a/examples/xgboost-quickstart/README.md b/examples/xgboost-quickstart/README.md index 5174c236c668..cd99cd4c2895 100644 --- a/examples/xgboost-quickstart/README.md +++ b/examples/xgboost-quickstart/README.md @@ -85,4 +85,4 @@ poetry run ./run.sh ``` Look at the [code](https://github.com/adap/flower/tree/main/examples/xgboost-quickstart) -and [tutorial](https://flower.dev/docs/framework/tutorial-quickstart-xgboost.html) for a detailed explanation. +and [tutorial](https://flower.ai/docs/framework/tutorial-quickstart-xgboost.html) for a detailed explanation. From 5af1679d1dc712f3a027ebbfb028cf3f633b0afc Mon Sep 17 00:00:00 2001 From: Robert Steiner Date: Thu, 15 Feb 2024 11:45:44 +0100 Subject: [PATCH 108/113] Update URL in fedbn README (#2950) --- baselines/fedbn/README.md | 52 +++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/baselines/fedbn/README.md b/baselines/fedbn/README.md index 4b271bd49851..d50c6f5bb605 100644 --- a/baselines/fedbn/README.md +++ b/baselines/fedbn/README.md @@ -34,37 +34,37 @@ dataset: [MNIST, MNIST-M, SVHN, USPS, SynthDigits] **Model:** A six-layer CNN with 14,219,210 parameters following the structure described in appendix D.2. -**Dataset:** This baseline makes use of the pre-processed partitions created and open source by the authors of the FedBN paper. You can read more about how those were created [here](https://github.com/med-air/FedBN). Follow the steps below in the `Environment Setup` section to download them. +**Dataset:** This baseline makes use of the pre-processed partitions created and open source by the authors of the FedBN paper. You can read more about how those were created [here](https://github.com/med-air/FedBN). Follow the steps below in the `Environment Setup` section to download them. A more detailed explanation of the datasets is given in the following table. -| | MNIST | MNIST-M | SVHN | USPS | SynthDigits | -|--- |--- |--- |--- |--- |--- | -| data type| handwritten digits| MNIST modification randomly colored with colored patches| Street view house numbers | handwritten digits from envelopes by the U.S. Postal Service | Syntehtic digits Windows TM font varying the orientation, blur and stroke colors | -| color | greyscale | RGB | RGB | greyscale | RGB | -| pixelsize | 28x28 | 28 x 28 | 32 x32 | 16 x16 | 32 x32 | -| labels | 0-9 | 0-9 | 1-10 | 0-9 | 1-10 | -| number of trainset | 60.000 | 60.000 | 73.257 | 9,298 | 50.000 | -| number of testset| 10.000 | 10.000 | 26.032 | - | - | -| image shape | (28,28) | (28,28,3) | (32,32,3) | (16,16) | (32,32,3) | +| | MNIST | MNIST-M | SVHN | USPS | SynthDigits | +| ------------------ | ------------------ | -------------------------------------------------------- | ------------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------- | +| data type | handwritten digits | MNIST modification randomly colored with colored patches | Street view house numbers | handwritten digits from envelopes by the U.S. Postal Service | Syntehtic digits Windows TM font varying the orientation, blur and stroke colors | +| color | greyscale | RGB | RGB | greyscale | RGB | +| pixelsize | 28x28 | 28 x 28 | 32 x32 | 16 x16 | 32 x32 | +| labels | 0-9 | 0-9 | 1-10 | 0-9 | 1-10 | +| number of trainset | 60.000 | 60.000 | 73.257 | 9,298 | 50.000 | +| number of testset | 10.000 | 10.000 | 26.032 | - | - | +| image shape | (28,28) | (28,28,3) | (32,32,3) | (16,16) | (32,32,3) | **Training Hyperparameters:** By default (i.e. if you don't override anything in the config) these main hyperparameters used are shown in the table below. For a complete list of hyperparameters, please refer to the config files in `fedbn/conf`. -| Description | Value | -| ----------- | ----- | -| rounds | 10 | -| num_clients | 5 | -| strategy_fraction_fit | 1.0 | -| strategy.fraction_evaluate | 0.0 | -| training samples per client| 743 | -| client.l_r | 10E-2 | -| local epochs | 1 | -| loss | cross entropy loss | -| optimizer | SGD | -| client_resources.num_cpu | 2 | -| client_resources.num_gpus | 0.0 | +| Description | Value | +| --------------------------- | ------------------ | +| rounds | 10 | +| num_clients | 5 | +| strategy_fraction_fit | 1.0 | +| strategy.fraction_evaluate | 0.0 | +| training samples per client | 743 | +| client.l_r | 10E-2 | +| local epochs | 1 | +| loss | cross entropy loss | +| optimizer | SGD | +| client_resources.num_cpu | 2 | +| client_resources.num_gpus | 0.0 | ## Environment Setup @@ -93,7 +93,7 @@ cd data .. ## Running the Experiments -First, activate your environment via `poetry shell`. The commands below show how to run the experiments and modify some of its key hyperparameters via the cli. Each time you run an experiment, the log and results will be stored inside `outputs//
{% endif %} diff --git a/doc/source/_templates/sidebar/versioning.html b/doc/source/_templates/sidebar/versioning.html index dde7528d15e4..74f1cd8febb7 100644 --- a/doc/source/_templates/sidebar/versioning.html +++ b/doc/source/_templates/sidebar/versioning.html @@ -59,8 +59,8 @@ -
- +
+
diff --git a/doc/source/conf.py b/doc/source/conf.py index 259d8a988841..88cb5c05b1d8 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -123,25 +123,27 @@ # The full name is still at the top of the page add_module_names = False + def find_test_modules(package_path): """Go through the python files and exclude every *_test.py file.""" full_path_modules = [] for root, dirs, files in os.walk(package_path): for file in files: - if file.endswith('_test.py'): + if file.endswith("_test.py"): # Construct the module path relative to the package directory full_path = os.path.join(root, file) relative_path = os.path.relpath(full_path, package_path) # Convert file path to dotted module path - module_path = os.path.splitext(relative_path)[0].replace(os.sep, '.') + module_path = os.path.splitext(relative_path)[0].replace(os.sep, ".") full_path_modules.append(module_path) modules = [] for full_path_module in full_path_modules: - parts = full_path_module.split('.') + parts = full_path_module.split(".") for i in range(len(parts)): - modules.append('.'.join(parts[i:])) + modules.append(".".join(parts[i:])) return modules + # Stop from documenting the *_test.py files. # That's the only way to do that in autosummary (make the modules as mock_imports). autodoc_mock_imports = find_test_modules(os.path.abspath("../../src/py/flwr")) @@ -249,7 +251,7 @@ def find_test_modules(package_path): html_title = f"Flower Framework" html_logo = "_static/flower-logo.png" html_favicon = "_static/favicon.ico" -html_baseurl = "https://flower.dev/docs/framework/" +html_baseurl = "https://flower.ai/docs/framework/" html_theme_options = { # diff --git a/doc/source/contributor-explanation-architecture.rst b/doc/source/contributor-explanation-architecture.rst index 0e2ea1f6e66b..a20a84313118 100644 --- a/doc/source/contributor-explanation-architecture.rst +++ b/doc/source/contributor-explanation-architecture.rst @@ -4,7 +4,7 @@ Flower Architecture Edge Client Engine ------------------ -`Flower `_ core framework architecture with Edge Client Engine +`Flower `_ core framework architecture with Edge Client Engine .. figure:: _static/flower-architecture-ECE.png :width: 80 % @@ -12,7 +12,7 @@ Edge Client Engine Virtual Client Engine --------------------- -`Flower `_ core framework architecture with Virtual Client Engine +`Flower `_ core framework architecture with Virtual Client Engine .. figure:: _static/flower-architecture-VCE.png :width: 80 % @@ -20,7 +20,7 @@ Virtual Client Engine Virtual Client Engine and Edge Client Engine in the same workload ----------------------------------------------------------------- -`Flower `_ core framework architecture with both Virtual Client Engine and Edge Client Engine +`Flower `_ core framework architecture with both Virtual Client Engine and Edge Client Engine .. figure:: _static/flower-architecture.drawio.png :width: 80 % diff --git a/doc/source/contributor-how-to-build-docker-images.rst b/doc/source/contributor-how-to-build-docker-images.rst index 2c6c7a7ab986..3beae7422bef 100644 --- a/doc/source/contributor-how-to-build-docker-images.rst +++ b/doc/source/contributor-how-to-build-docker-images.rst @@ -17,7 +17,7 @@ Before we can start, we need to meet a few prerequisites in our local developmen #. Verify the Docker daemon is running. Please follow the first section on - `Run Flower using Docker `_ + `Run Flower using Docker `_ which covers this step in more detail. Currently, Flower provides two images, a base image and a server image. There will also be a client diff --git a/doc/source/contributor-how-to-contribute-translations.rst b/doc/source/contributor-how-to-contribute-translations.rst index d97a2cb8c64f..1614b8e5a040 100644 --- a/doc/source/contributor-how-to-contribute-translations.rst +++ b/doc/source/contributor-how-to-contribute-translations.rst @@ -2,7 +2,7 @@ Contribute translations ======================= Since `Flower 1.5 -`_ we +`_ we have introduced translations to our doc pages, but, as you might have noticed, the translations are often imperfect. If you speak languages other than English, you might be able to help us in our effort to make Federated Learning @@ -67,5 +67,5 @@ Add new languages ----------------- If you want to add a new language, you will first have to contact us, either on -`Slack `_, or by opening an issue on our `GitHub +`Slack `_, or by opening an issue on our `GitHub repo `_. diff --git a/doc/source/contributor-ref-good-first-contributions.rst b/doc/source/contributor-ref-good-first-contributions.rst index 523a4679c6ef..cbf21e2845bc 100644 --- a/doc/source/contributor-ref-good-first-contributions.rst +++ b/doc/source/contributor-ref-good-first-contributions.rst @@ -14,7 +14,7 @@ Until the Flower core library matures it will be easier to get PR's accepted if they only touch non-core areas of the codebase. Good candidates to get started are: -- Documentation: What's missing? What could be expressed more clearly? +- Documentation: What's missing? What could be expressed more clearly? - Baselines: See below. - Examples: See below. @@ -22,9 +22,9 @@ are: Request for Flower Baselines ---------------------------- -If you are not familiar with Flower Baselines, you should probably check-out our `contributing guide for baselines `_. +If you are not familiar with Flower Baselines, you should probably check-out our `contributing guide for baselines `_. -You should then check out the open +You should then check out the open `issues `_ for baseline requests. If you find a baseline that you'd like to work on and that has no assignes, feel free to assign it to yourself and start working on it! diff --git a/doc/source/contributor-tutorial-contribute-on-github.rst b/doc/source/contributor-tutorial-contribute-on-github.rst index d409802897e4..273b47a636cc 100644 --- a/doc/source/contributor-tutorial-contribute-on-github.rst +++ b/doc/source/contributor-tutorial-contribute-on-github.rst @@ -3,8 +3,8 @@ Contribute on GitHub This guide is for people who want to get involved with Flower, but who are not used to contributing to GitHub projects. -If you're familiar with how contributing on GitHub works, you can directly checkout our -`getting started guide for contributors `_. +If you're familiar with how contributing on GitHub works, you can directly checkout our +`getting started guide for contributors `_. Setting up the repository @@ -16,9 +16,9 @@ Setting up the repository GitHub, itself, is a code hosting platform for version control and collaboration. It allows for everyone to collaborate and work from anywhere on remote repositories. - If you haven't already, you will need to create an account on `GitHub `_. + If you haven't already, you will need to create an account on `GitHub `_. - The idea behind the generic Git and GitHub workflow boils down to this: + The idea behind the generic Git and GitHub workflow boils down to this: you download code from a remote repository on GitHub, make changes locally and keep track of them using Git and then you upload your new history back to GitHub. 2. **Forking the Flower repository** @@ -26,7 +26,7 @@ Setting up the repository and click the ``Fork`` button situated on the top right of the page. .. image:: _static/fork_button.png - + You can change the name if you want, but this is not necessary as this version of Flower will be yours and will sit inside your own account (i.e., in your own list of repositories). Once created, you should see on the top left corner that you are looking at your own version of Flower. @@ -34,14 +34,14 @@ Setting up the repository 3. **Cloning your forked repository** The next step is to download the forked repository on your machine to be able to make changes to it. - On your forked repository page, you should first click on the ``Code`` button on the right, + On your forked repository page, you should first click on the ``Code`` button on the right, this will give you the ability to copy the HTTPS link of the repository. .. image:: _static/cloning_fork.png Once you copied the \, you can open a terminal on your machine, navigate to the place you want to download the repository to and type: - .. code-block:: shell + .. code-block:: shell $ git clone @@ -58,14 +58,14 @@ Setting up the repository To obtain it, we can do as previously mentioned by going to our fork repository on our GitHub account and copying the link. .. image:: _static/cloning_fork.png - + Once the \ is copied, we can type the following command in our terminal: .. code-block:: shell $ git remote add origin - + 5. **Add upstream** Now we will add an upstream address to our repository. Still in the same directroy, we must run the following command: @@ -76,10 +76,10 @@ Setting up the repository The following diagram visually explains what we did in the previous steps: - .. image:: _static/github_schema.png + .. image:: _static/github_schema.png - The upstream is the GitHub remote address of the parent repository (in this case Flower), - i.e. the one we eventually want to contribute to and therefore need an up-to-date history of. + The upstream is the GitHub remote address of the parent repository (in this case Flower), + i.e. the one we eventually want to contribute to and therefore need an up-to-date history of. The origin is just the GitHub remote address of the forked repository we created, i.e. the copy (fork) in our own account. To make sure our local version of the fork is up-to-date with the latest changes from the Flower repository, @@ -113,9 +113,9 @@ And with Flower's repository: $ git pull upstream main 1. **Create a new branch** - To make the history cleaner and easier to work with, it is good practice to + To make the history cleaner and easier to work with, it is good practice to create a new branch for each feature/project that needs to be implemented. - + To do so, just run the following command inside the repository's directory: .. code-block:: shell @@ -137,7 +137,7 @@ And with Flower's repository: $ ./dev/test.sh # to test that your code can be accepted $ ./baselines/dev/format.sh # same as above but for code added to baselines $ ./baselines/dev/test.sh # same as above but for code added to baselines - + 4. **Stage changes** Before creating a commit that will update your history, you must specify to Git which files it needs to take into account. @@ -184,21 +184,21 @@ Creating and merging a pull request (PR) Once you click the ``Compare & pull request`` button, you should see something similar to this: .. image:: _static/creating_pr.png - + At the top you have an explanation of which branch will be merged where: .. image:: _static/merging_branch.png - + In this example you can see that the request is to merge the branch ``doc-fixes`` from my forked repository to branch ``main`` from the Flower repository. - The input box in the middle is there for you to describe what your PR does and to link it to existing issues. + The input box in the middle is there for you to describe what your PR does and to link it to existing issues. We have placed comments (that won't be rendered once the PR is opened) to guide you through the process. It is important to follow the instructions described in comments. For instance, in order to not break how our changelog system works, you should read the information above the ``Changelog entry`` section carefully. You can also checkout some examples and details in the :ref:`changelogentry` appendix. - At the bottom you will find the button to open the PR. This will notify reviewers that a new PR has been opened and + At the bottom you will find the button to open the PR. This will notify reviewers that a new PR has been opened and that they should look over it to merge or to request changes. If your PR is not yet ready for review, and you don't want to notify anyone, you have the option to create a draft pull request: @@ -218,7 +218,7 @@ Creating and merging a pull request (PR) Merging will be blocked if there are ongoing requested changes. .. image:: _static/changes_requested.png - + To resolve them, just push the necessary changes to the branch associated with the PR: .. image:: _static/make_changes.png @@ -277,12 +277,12 @@ This is a tiny change, but it’ll allow us to test your end-to-end setup. After - Find the source file in ``doc/source`` - Make the change in the ``.rst`` file (beware, the dashes under the title should be the same length as the title itself) -- Build the docs and check the result: ``_ +- Build the docs and check the result: ``_ Rename file ::::::::::: -You might have noticed that the file name still reflects the old wording. +You might have noticed that the file name still reflects the old wording. If we just change the file, then we break all existing links to it - it is **very important** to avoid that, breaking links can harm our search engine ranking. Here’s how to change the file name: @@ -295,7 +295,7 @@ This will cause a redirect from ``saving-progress.html`` to ``save-progress.html Apply changes in the index file ::::::::::::::::::::::::::::::: -For the lateral navigation bar to work properly, it is very important to update the ``index.rst`` file as well. +For the lateral navigation bar to work properly, it is very important to update the ``index.rst`` file as well. This is where we define the whole arborescence of the navbar. - Find and modify the file name in ``index.rst`` @@ -343,7 +343,7 @@ Next steps Once you have made your first PR, and want to contribute more, be sure to check out the following : -- `Good first contributions `_, where you should particularly look into the :code:`baselines` contributions. +- `Good first contributions `_, where you should particularly look into the :code:`baselines` contributions. Appendix @@ -358,10 +358,10 @@ When opening a new PR, inside its description, there should be a ``Changelog ent Above this header you should see the following comment that explains how to write your changelog entry: - Inside the following 'Changelog entry' section, + Inside the following 'Changelog entry' section, you should put the description of your changes that will be added to the changelog alongside your PR title. - If the section is completely empty (without any token) or non-existant, + If the section is completely empty (without any token) or non-existant, the changelog will just contain the title of the PR for the changelog entry, without any description. If the section contains some text other than tokens, it will use it to add a description to the change. diff --git a/doc/source/example-fedbn-pytorch-from-centralized-to-federated.rst b/doc/source/example-fedbn-pytorch-from-centralized-to-federated.rst index 5ebaa337dde8..5d4dac0c0cda 100644 --- a/doc/source/example-fedbn-pytorch-from-centralized-to-federated.rst +++ b/doc/source/example-fedbn-pytorch-from-centralized-to-federated.rst @@ -3,11 +3,11 @@ Example: FedBN in PyTorch - From Centralized To Federated This tutorial will show you how to use Flower to build a federated version of an existing machine learning workload with `FedBN `_, a federated training strategy designed for non-iid data. We are using PyTorch to train a Convolutional Neural Network(with Batch Normalization layers) on the CIFAR-10 dataset. -When applying FedBN, only few changes needed compared to `Example: PyTorch - From Centralized To Federated `_. +When applying FedBN, only few changes needed compared to `Example: PyTorch - From Centralized To Federated `_. Centralized Training -------------------- -All files are revised based on `Example: PyTorch - From Centralized To Federated `_. +All files are revised based on `Example: PyTorch - From Centralized To Federated `_. The only thing to do is modifying the file called :code:`cifar.py`, revised part is shown below: The model architecture defined in class Net() is added with Batch Normalization layers accordingly. @@ -50,8 +50,8 @@ Let's take the next step and use what we've built to create a federated learning Federated Training ------------------ -If you have read `Example: PyTorch - From Centralized To Federated `_, the following parts are easy to follow, onyl :code:`get_parameters` and :code:`set_parameters` function in :code:`client.py` needed to revise. -If not, please read the `Example: PyTorch - From Centralized To Federated `_. first. +If you have read `Example: PyTorch - From Centralized To Federated `_, the following parts are easy to follow, onyl :code:`get_parameters` and :code:`set_parameters` function in :code:`client.py` needed to revise. +If not, please read the `Example: PyTorch - From Centralized To Federated `_. first. Our example consists of one *server* and two *clients*. In FedBN, :code:`server.py` keeps unchanged, we can start the server directly. @@ -66,7 +66,7 @@ Finally, we will revise our *client* logic by changing :code:`get_parameters` an class CifarClient(fl.client.NumPyClient): """Flower client implementing CIFAR-10 image classification using PyTorch.""" - + ... def get_parameters(self, config) -> List[np.ndarray]: @@ -79,7 +79,7 @@ Finally, we will revise our *client* logic by changing :code:`get_parameters` an params_dict = zip(keys, parameters) state_dict = OrderedDict({k: torch.tensor(v) for k, v in params_dict}) self.model.load_state_dict(state_dict, strict=False) - + ... Now, you can now open two additional terminal windows and run diff --git a/doc/source/how-to-configure-clients.rst b/doc/source/how-to-configure-clients.rst index 26c132125ccf..bfb5a8f63761 100644 --- a/doc/source/how-to-configure-clients.rst +++ b/doc/source/how-to-configure-clients.rst @@ -13,7 +13,7 @@ Configuration values are represented as a dictionary with ``str`` keys and value config_dict = { "dropout": True, # str key, bool value "learning_rate": 0.01, # str key, float value - "batch_size": 32, # str key, int value + "batch_size": 32, # str key, int value "optimizer": "sgd", # str key, str value } @@ -56,7 +56,7 @@ To make the built-in strategies use this function, we can pass it to ``FedAvg`` One the client side, we receive the configuration dictionary in ``fit``: .. code-block:: python - + class FlowerClient(flwr.client.NumPyClient): def fit(parameters, config): print(config["batch_size"]) # Prints `32` @@ -86,7 +86,7 @@ Configuring individual clients In some cases, it is necessary to send different configuration values to different clients. -This can be achieved by customizing an existing strategy or by `implementing a custom strategy from scratch `_. Here's a nonsensical example that customizes :code:`FedAvg` by adding a custom ``"hello": "world"`` configuration key/value pair to the config dict of a *single client* (only the first client in the list, the other clients in this round to not receive this "special" config value): +This can be achieved by customizing an existing strategy or by `implementing a custom strategy from scratch `_. Here's a nonsensical example that customizes :code:`FedAvg` by adding a custom ``"hello": "world"`` configuration key/value pair to the config dict of a *single client* (only the first client in the list, the other clients in this round to not receive this "special" config value): .. code-block:: python diff --git a/doc/source/how-to-install-flower.rst b/doc/source/how-to-install-flower.rst index ff3dbb605846..dc88076424f8 100644 --- a/doc/source/how-to-install-flower.rst +++ b/doc/source/how-to-install-flower.rst @@ -57,7 +57,7 @@ Advanced installation options Install via Docker ~~~~~~~~~~~~~~~~~~ -`How to run Flower using Docker `_ +`How to run Flower using Docker `_ Install pre-release ~~~~~~~~~~~~~~~~~~~ diff --git a/doc/source/how-to-run-flower-using-docker.rst b/doc/source/how-to-run-flower-using-docker.rst index 40df1ffcb63c..ed034c820142 100644 --- a/doc/source/how-to-run-flower-using-docker.rst +++ b/doc/source/how-to-run-flower-using-docker.rst @@ -54,7 +54,7 @@ to the Flower server. Here, we are passing the flag ``--insecure``. The ``--insecure`` flag enables insecure communication (using HTTP, not HTTPS) and should only be used for testing purposes. We strongly recommend enabling - `SSL `_ + `SSL `_ when deploying to a production environment. You can use ``--help`` to view all available flags that the server supports: @@ -90,7 +90,7 @@ To enable SSL, you will need a CA certificate, a server certificate and a server .. note:: For testing purposes, you can generate your own self-signed certificates. The - `Enable SSL connections `_ + `Enable SSL connections `_ page contains a section that will guide you through the process. Assuming all files we need are in the local ``certificates`` directory, we can use the flag diff --git a/doc/source/how-to-upgrade-to-flower-1.0.rst b/doc/source/how-to-upgrade-to-flower-1.0.rst index fd380e95d69c..c4429d61d0a9 100644 --- a/doc/source/how-to-upgrade-to-flower-1.0.rst +++ b/doc/source/how-to-upgrade-to-flower-1.0.rst @@ -50,7 +50,7 @@ Strategies / ``start_server`` / ``start_simulation`` - Replace ``num_rounds=1`` in ``start_simulation`` with the new ``config=ServerConfig(...)`` (see previous item) - Remove ``force_final_distributed_eval`` parameter from calls to ``start_server``. Distributed evaluation on all clients can be enabled by configuring the strategy to sample all clients for evaluation after the last round of training. - Rename parameter/ndarray conversion functions: - + - ``parameters_to_weights`` --> ``parameters_to_ndarrays`` - ``weights_to_parameters`` --> ``ndarrays_to_parameters`` @@ -88,4 +88,4 @@ Along with the necessary changes above, there are a number of potential improvem Further help ------------ -Most official `Flower code examples `_ are already updated to Flower 1.0, they can serve as a reference for using the Flower 1.0 API. If there are further questionsm, `join the Flower Slack `_ and use the channgel ``#questions``. +Most official `Flower code examples `_ are already updated to Flower 1.0, they can serve as a reference for using the Flower 1.0 API. If there are further questionsm, `join the Flower Slack `_ and use the channgel ``#questions``. diff --git a/doc/source/index.rst b/doc/source/index.rst index 7e2b4052bee6..ea52a9421b61 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -4,7 +4,7 @@ Flower Framework Documentation .. meta:: :description: Check out the documentation of the main Flower Framework enabling easy Python development for Federated Learning. -Welcome to Flower's documentation. `Flower `_ is a friendly federated learning framework. +Welcome to Flower's documentation. `Flower `_ is a friendly federated learning framework. Join the Flower Community @@ -12,7 +12,7 @@ Join the Flower Community The Flower Community is growing quickly - we're a friendly group of researchers, engineers, students, professionals, academics, and other enthusiasts. -.. button-link:: https://flower.dev/join-slack +.. button-link:: https://flower.ai/join-slack :color: primary :shadow: diff --git a/doc/source/ref-changelog.md b/doc/source/ref-changelog.md index e9282632410d..41dc91873c6c 100644 --- a/doc/source/ref-changelog.md +++ b/doc/source/ref-changelog.md @@ -42,7 +42,7 @@ We would like to give our special thanks to all the contributors who made the ne - **Introduce Docker image for Flower server** ([#2700](https://github.com/adap/flower/pull/2700), [#2688](https://github.com/adap/flower/pull/2688), [#2705](https://github.com/adap/flower/pull/2705), [#2695](https://github.com/adap/flower/pull/2695), [#2747](https://github.com/adap/flower/pull/2747), [#2746](https://github.com/adap/flower/pull/2746), [#2680](https://github.com/adap/flower/pull/2680), [#2682](https://github.com/adap/flower/pull/2682), [#2701](https://github.com/adap/flower/pull/2701)) - The Flower server can now be run using an official Docker image. A new how-to guide explains [how to run Flower using Docker](https://flower.dev/docs/framework/how-to-run-flower-using-docker.html). An official Flower client Docker image will follow. + The Flower server can now be run using an official Docker image. A new how-to guide explains [how to run Flower using Docker](https://flower.ai/docs/framework/how-to-run-flower-using-docker.html). An official Flower client Docker image will follow. - **Introduce** `flower-via-docker-compose` **example** ([#2626](https://github.com/adap/flower/pull/2626)) @@ -52,7 +52,7 @@ We would like to give our special thanks to all the contributors who made the ne - **Update code examples to use Flower Datasets** ([#2450](https://github.com/adap/flower/pull/2450), [#2456](https://github.com/adap/flower/pull/2456), [#2318](https://github.com/adap/flower/pull/2318), [#2712](https://github.com/adap/flower/pull/2712)) - Several code examples were updated to use [Flower Datasets](https://flower.dev/docs/datasets/). + Several code examples were updated to use [Flower Datasets](https://flower.ai/docs/datasets/). - **General updates to Flower Examples** ([#2381](https://github.com/adap/flower/pull/2381), [#2805](https://github.com/adap/flower/pull/2805), [#2782](https://github.com/adap/flower/pull/2782), [#2806](https://github.com/adap/flower/pull/2806), [#2829](https://github.com/adap/flower/pull/2829), [#2825](https://github.com/adap/flower/pull/2825), [#2816](https://github.com/adap/flower/pull/2816), [#2726](https://github.com/adap/flower/pull/2726), [#2659](https://github.com/adap/flower/pull/2659), [#2655](https://github.com/adap/flower/pull/2655)) @@ -213,11 +213,11 @@ We would like to give our special thanks to all the contributors who made the ne The new simulation engine has been rewritten from the ground up, yet it remains fully backwards compatible. It offers much improved stability and memory handling, especially when working with GPUs. Simulations transparently adapt to different settings to scale simulation in CPU-only, CPU+GPU, multi-GPU, or multi-node multi-GPU environments. - Comprehensive documentation includes a new [how-to run simulations](https://flower.dev/docs/framework/how-to-run-simulations.html) guide, new [simulation-pytorch](https://flower.dev/docs/examples/simulation-pytorch.html) and [simulation-tensorflow](https://flower.dev/docs/examples/simulation-tensorflow.html) notebooks, and a new [YouTube tutorial series](https://www.youtube.com/watch?v=cRebUIGB5RU&list=PLNG4feLHqCWlnj8a_E1A_n5zr2-8pafTB). + Comprehensive documentation includes a new [how-to run simulations](https://flower.ai/docs/framework/how-to-run-simulations.html) guide, new [simulation-pytorch](https://flower.ai/docs/examples/simulation-pytorch.html) and [simulation-tensorflow](https://flower.ai/docs/examples/simulation-tensorflow.html) notebooks, and a new [YouTube tutorial series](https://www.youtube.com/watch?v=cRebUIGB5RU&list=PLNG4feLHqCWlnj8a_E1A_n5zr2-8pafTB). - **Restructure Flower Docs** ([#1824](https://github.com/adap/flower/pull/1824), [#1865](https://github.com/adap/flower/pull/1865), [#1884](https://github.com/adap/flower/pull/1884), [#1887](https://github.com/adap/flower/pull/1887), [#1919](https://github.com/adap/flower/pull/1919), [#1922](https://github.com/adap/flower/pull/1922), [#1920](https://github.com/adap/flower/pull/1920), [#1923](https://github.com/adap/flower/pull/1923), [#1924](https://github.com/adap/flower/pull/1924), [#1962](https://github.com/adap/flower/pull/1962), [#2006](https://github.com/adap/flower/pull/2006), [#2133](https://github.com/adap/flower/pull/2133), [#2203](https://github.com/adap/flower/pull/2203), [#2215](https://github.com/adap/flower/pull/2215), [#2122](https://github.com/adap/flower/pull/2122), [#2223](https://github.com/adap/flower/pull/2223), [#2219](https://github.com/adap/flower/pull/2219), [#2232](https://github.com/adap/flower/pull/2232), [#2233](https://github.com/adap/flower/pull/2233), [#2234](https://github.com/adap/flower/pull/2234), [#2235](https://github.com/adap/flower/pull/2235), [#2237](https://github.com/adap/flower/pull/2237), [#2238](https://github.com/adap/flower/pull/2238), [#2242](https://github.com/adap/flower/pull/2242), [#2231](https://github.com/adap/flower/pull/2231), [#2243](https://github.com/adap/flower/pull/2243), [#2227](https://github.com/adap/flower/pull/2227)) - Much effort went into a completely restructured Flower docs experience. The documentation on [flower.dev/docs](https://flower.dev/docs) is now divided into Flower Framework, Flower Baselines, Flower Android SDK, Flower iOS SDK, and code example projects. + Much effort went into a completely restructured Flower docs experience. The documentation on [flower.ai/docs](https://flower.ai/docs) is now divided into Flower Framework, Flower Baselines, Flower Android SDK, Flower iOS SDK, and code example projects. - **Introduce Flower Swift SDK** ([#1858](https://github.com/adap/flower/pull/1858), [#1897](https://github.com/adap/flower/pull/1897)) @@ -303,7 +303,7 @@ We would like to give our special thanks to all the contributors who made the ne - **Introduce new "What is Federated Learning?" tutorial** ([#1657](https://github.com/adap/flower/pull/1657), [#1721](https://github.com/adap/flower/pull/1721)) - A new [entry-level tutorial](https://flower.dev/docs/framework/tutorial-what-is-federated-learning.html) in our documentation explains the basics of Fedetated Learning. It enables anyone who's unfamiliar with Federated Learning to start their journey with Flower. Forward it to anyone who's interested in Federated Learning! + A new [entry-level tutorial](https://flower.ai/docs/framework/tutorial-what-is-federated-learning.html) in our documentation explains the basics of Fedetated Learning. It enables anyone who's unfamiliar with Federated Learning to start their journey with Flower. Forward it to anyone who's interested in Federated Learning! - **Introduce new Flower Baseline: FedProx MNIST** ([#1513](https://github.com/adap/flower/pull/1513), [#1680](https://github.com/adap/flower/pull/1680), [#1681](https://github.com/adap/flower/pull/1681), [#1679](https://github.com/adap/flower/pull/1679)) @@ -417,7 +417,7 @@ We would like to give our special thanks to all the contributors who made the ne - **Introduce new Flower Baseline: FedAvg MNIST** ([#1497](https://github.com/adap/flower/pull/1497), [#1552](https://github.com/adap/flower/pull/1552)) - Over the coming weeks, we will be releasing a number of new reference implementations useful especially to FL newcomers. They will typically revisit well known papers from the literature, and be suitable for integration in your own application or for experimentation, in order to deepen your knowledge of FL in general. Today's release is the first in this series. [Read more.](https://flower.dev/blog/2023-01-12-fl-starter-pack-fedavg-mnist-cnn/) + Over the coming weeks, we will be releasing a number of new reference implementations useful especially to FL newcomers. They will typically revisit well known papers from the literature, and be suitable for integration in your own application or for experimentation, in order to deepen your knowledge of FL in general. Today's release is the first in this series. [Read more.](https://flower.ai/blog/2023-01-12-fl-starter-pack-fedavg-mnist-cnn/) - **Improve GPU support in simulations** ([#1555](https://github.com/adap/flower/pull/1555)) @@ -427,16 +427,16 @@ We would like to give our special thanks to all the contributors who made the ne Some users reported that Jupyter Notebooks have not always been easy to use on GPU instances. We listened and made improvements to all of our Jupyter notebooks! Check out the updated notebooks here: - - [An Introduction to Federated Learning](https://flower.dev/docs/framework/tutorial-get-started-with-flower-pytorch.html) - - [Strategies in Federated Learning](https://flower.dev/docs/framework/tutorial-use-a-federated-learning-strategy-pytorch.html) - - [Building a Strategy](https://flower.dev/docs/framework/tutorial-build-a-strategy-from-scratch-pytorch.html) - - [Client and NumPyClient](https://flower.dev/docs/framework/tutorial-customize-the-client-pytorch.html) + - [An Introduction to Federated Learning](https://flower.ai/docs/framework/tutorial-get-started-with-flower-pytorch.html) + - [Strategies in Federated Learning](https://flower.ai/docs/framework/tutorial-use-a-federated-learning-strategy-pytorch.html) + - [Building a Strategy](https://flower.ai/docs/framework/tutorial-build-a-strategy-from-scratch-pytorch.html) + - [Client and NumPyClient](https://flower.ai/docs/framework/tutorial-customize-the-client-pytorch.html) - **Introduce optional telemetry** ([#1533](https://github.com/adap/flower/pull/1533), [#1544](https://github.com/adap/flower/pull/1544), [#1584](https://github.com/adap/flower/pull/1584)) After a [request for feedback](https://github.com/adap/flower/issues/1534) from the community, the Flower open-source project introduces optional collection of *anonymous* usage metrics to make well-informed decisions to improve Flower. Doing this enables the Flower team to understand how Flower is used and what challenges users might face. - **Flower is a friendly framework for collaborative AI and data science.** Staying true to this statement, Flower makes it easy to disable telemetry for users who do not want to share anonymous usage metrics. [Read more.](https://flower.dev/docs/telemetry.html). + **Flower is a friendly framework for collaborative AI and data science.** Staying true to this statement, Flower makes it easy to disable telemetry for users who do not want to share anonymous usage metrics. [Read more.](https://flower.ai/docs/telemetry.html). - **Introduce (experimental) Driver API** ([#1520](https://github.com/adap/flower/pull/1520), [#1525](https://github.com/adap/flower/pull/1525), [#1545](https://github.com/adap/flower/pull/1545), [#1546](https://github.com/adap/flower/pull/1546), [#1550](https://github.com/adap/flower/pull/1550), [#1551](https://github.com/adap/flower/pull/1551), [#1567](https://github.com/adap/flower/pull/1567)) @@ -468,7 +468,7 @@ We would like to give our special thanks to all the contributors who made the ne As usual, the documentation has improved quite a bit. It is another step in our effort to make the Flower documentation the best documentation of any project. Stay tuned and as always, feel free to provide feedback! - One highlight is the new [first time contributor guide](https://flower.dev/docs/first-time-contributors.html): if you've never contributed on GitHub before, this is the perfect place to start! + One highlight is the new [first time contributor guide](https://flower.ai/docs/first-time-contributors.html): if you've never contributed on GitHub before, this is the perfect place to start! ### Incompatible changes @@ -657,7 +657,7 @@ We would like to give our **special thanks** to all the contributors who made Fl - **Flower Baselines (preview): FedOpt, FedBN, FedAvgM** ([#919](https://github.com/adap/flower/pull/919), [#1127](https://github.com/adap/flower/pull/1127), [#914](https://github.com/adap/flower/pull/914)) - The first preview release of Flower Baselines has arrived! We're kickstarting Flower Baselines with implementations of FedOpt (FedYogi, FedAdam, FedAdagrad), FedBN, and FedAvgM. Check the documentation on how to use [Flower Baselines](https://flower.dev/docs/using-baselines.html). With this first preview release we're also inviting the community to [contribute their own baselines](https://flower.dev/docs/contributing-baselines.html). + The first preview release of Flower Baselines has arrived! We're kickstarting Flower Baselines with implementations of FedOpt (FedYogi, FedAdam, FedAdagrad), FedBN, and FedAvgM. Check the documentation on how to use [Flower Baselines](https://flower.ai/docs/using-baselines.html). With this first preview release we're also inviting the community to [contribute their own baselines](https://flower.ai/docs/contributing-baselines.html). - **C++ client SDK (preview) and code example** ([#1111](https://github.com/adap/flower/pull/1111)) @@ -703,7 +703,7 @@ We would like to give our **special thanks** to all the contributors who made Fl - New option to keep Ray running if Ray was already initialized in `start_simulation` ([#1177](https://github.com/adap/flower/pull/1177)) - Add support for custom `ClientManager` as a `start_simulation` parameter ([#1171](https://github.com/adap/flower/pull/1171)) - - New documentation for [implementing strategies](https://flower.dev/docs/framework/how-to-implement-strategies.html) ([#1097](https://github.com/adap/flower/pull/1097), [#1175](https://github.com/adap/flower/pull/1175)) + - New documentation for [implementing strategies](https://flower.ai/docs/framework/how-to-implement-strategies.html) ([#1097](https://github.com/adap/flower/pull/1097), [#1175](https://github.com/adap/flower/pull/1175)) - New mobile-friendly documentation theme ([#1174](https://github.com/adap/flower/pull/1174)) - Limit version range for (optional) `ray` dependency to include only compatible releases (`>=1.9.2,<1.12.0`) ([#1205](https://github.com/adap/flower/pull/1205)) diff --git a/doc/source/ref-example-projects.rst b/doc/source/ref-example-projects.rst index b47bd8e48997..8eb723000cac 100644 --- a/doc/source/ref-example-projects.rst +++ b/doc/source/ref-example-projects.rst @@ -23,8 +23,8 @@ The TensorFlow/Keras quickstart example shows CIFAR-10 image classification with MobileNetV2: - `Quickstart TensorFlow (Code) `_ -- `Quickstart TensorFlow (Tutorial) `_ -- `Quickstart TensorFlow (Blog Post) `_ +- `Quickstart TensorFlow (Tutorial) `_ +- `Quickstart TensorFlow (Blog Post) `_ Quickstart PyTorch @@ -34,7 +34,7 @@ The PyTorch quickstart example shows CIFAR-10 image classification with a simple Convolutional Neural Network: - `Quickstart PyTorch (Code) `_ -- `Quickstart PyTorch (Tutorial) `_ +- `Quickstart PyTorch (Tutorial) `_ PyTorch: From Centralized To Federated @@ -43,7 +43,7 @@ PyTorch: From Centralized To Federated This example shows how a regular PyTorch project can be federated using Flower: - `PyTorch: From Centralized To Federated (Code) `_ -- `PyTorch: From Centralized To Federated (Tutorial) `_ +- `PyTorch: From Centralized To Federated (Tutorial) `_ Federated Learning on Raspberry Pi and Nvidia Jetson @@ -52,7 +52,7 @@ Federated Learning on Raspberry Pi and Nvidia Jetson This example shows how Flower can be used to build a federated learning system that run across Raspberry Pi and Nvidia Jetson: - `Federated Learning on Raspberry Pi and Nvidia Jetson (Code) `_ -- `Federated Learning on Raspberry Pi and Nvidia Jetson (Blog Post) `_ +- `Federated Learning on Raspberry Pi and Nvidia Jetson (Blog Post) `_ diff --git a/doc/source/ref-faq.rst b/doc/source/ref-faq.rst index 13c44bc64b0e..932396e3c583 100644 --- a/doc/source/ref-faq.rst +++ b/doc/source/ref-faq.rst @@ -6,20 +6,20 @@ This page collects answers to commonly asked questions about Federated Learning .. dropdown:: :fa:`eye,mr-1` Can Flower run on Juptyter Notebooks / Google Colab? Yes, it can! Flower even comes with a few under-the-hood optimizations to make it work even better on Colab. Here's a quickstart example: - + * `Flower simulation PyTorch `_ * `Flower simulation TensorFlow/Keras `_ .. dropdown:: :fa:`eye,mr-1` How can I run Federated Learning on a Raspberry Pi? - Find the `blog post about federated learning on embedded device here `_ and the corresponding `GitHub code example `_. + Find the `blog post about federated learning on embedded device here `_ and the corresponding `GitHub code example `_. .. dropdown:: :fa:`eye,mr-1` Does Flower support federated learning on Android devices? - Yes, it does. Please take a look at our `blog post `_ or check out the code examples: + Yes, it does. Please take a look at our `blog post `_ or check out the code examples: - * `Android Kotlin example `_ - * `Android Java example `_ + * `Android Kotlin example `_ + * `Android Java example `_ .. dropdown:: :fa:`eye,mr-1` Can I combine federated learning with blockchain? diff --git a/doc/source/ref-telemetry.md b/doc/source/ref-telemetry.md index 206e641d8b41..49efef5c8559 100644 --- a/doc/source/ref-telemetry.md +++ b/doc/source/ref-telemetry.md @@ -41,7 +41,7 @@ Flower telemetry collects the following metrics: **Source.** Flower telemetry tries to store a random source ID in `~/.flwr/source` the first time a telemetry event is generated. The source ID is important to identify whether an issue is recurring or whether an issue is triggered by multiple clusters running concurrently (which often happens in simulation). For example, if a device runs multiple workloads at the same time, and this results in an issue, then, in order to reproduce the issue, multiple workloads must be started at the same time. -You may delete the source ID at any time. If you wish for all events logged under a specific source ID to be deleted, you can send a deletion request mentioning the source ID to `telemetry@flower.dev`. All events related to that source ID will then be permanently deleted. +You may delete the source ID at any time. If you wish for all events logged under a specific source ID to be deleted, you can send a deletion request mentioning the source ID to `telemetry@flower.ai`. All events related to that source ID will then be permanently deleted. We will not collect any personally identifiable information. If you think any of the metrics collected could be misused in any way, please [get in touch with us](#how-to-contact-us). We will update this page to reflect any changes to the metrics collected and publish changes in the changelog. @@ -63,4 +63,4 @@ FLWR_TELEMETRY_ENABLED=0 FLWR_TELEMETRY_LOGGING=1 python server.py # or client.p ## How to contact us -We want to hear from you. If you have any feedback or ideas on how to improve the way we handle anonymous usage metrics, reach out to us via [Slack](https://flower.dev/join-slack/) (channel `#telemetry`) or email (`telemetry@flower.dev`). +We want to hear from you. If you have any feedback or ideas on how to improve the way we handle anonymous usage metrics, reach out to us via [Slack](https://flower.ai/join-slack/) (channel `#telemetry`) or email (`telemetry@flower.ai`). diff --git a/doc/source/tutorial-quickstart-ios.rst b/doc/source/tutorial-quickstart-ios.rst index 7c8007baaa75..aa94a72580c1 100644 --- a/doc/source/tutorial-quickstart-ios.rst +++ b/doc/source/tutorial-quickstart-ios.rst @@ -7,14 +7,14 @@ Quickstart iOS .. meta:: :description: Read this Federated Learning quickstart tutorial for creating an iOS app using Flower to train a neural network on MNIST. -In this tutorial we will learn how to train a Neural Network on MNIST using Flower and CoreML on iOS devices. +In this tutorial we will learn how to train a Neural Network on MNIST using Flower and CoreML on iOS devices. -First of all, for running the Flower Python server, it is recommended to create a virtual environment and run everything within a `virtualenv `_. +First of all, for running the Flower Python server, it is recommended to create a virtual environment and run everything within a `virtualenv `_. For the Flower client implementation in iOS, it is recommended to use Xcode as our IDE. -Our example consists of one Python *server* and two iPhone *clients* that all have the same model. +Our example consists of one Python *server* and two iPhone *clients* that all have the same model. -*Clients* are responsible for generating individual weight updates for the model based on their local datasets. +*Clients* are responsible for generating individual weight updates for the model based on their local datasets. These updates are then sent to the *server* which will aggregate them to produce a better model. Finally, the *server* sends this improved version of the model back to each *client*. A complete cycle of weight updates is called a *round*. @@ -44,10 +44,10 @@ For simplicity reasons we will use the complete Flower client with CoreML, that public func getParameters() -> GetParametersRes { let parameters = parameters.weightsToParameters() let status = Status(code: .ok, message: String()) - + return GetParametersRes(parameters: parameters, status: status) } - + /// Calls the routine to fit the local model /// /// - Returns: The result from the local training, e.g., updated parameters @@ -55,17 +55,17 @@ For simplicity reasons we will use the complete Flower client with CoreML, that let status = Status(code: .ok, message: String()) let result = runMLTask(configuration: parameters.parametersToWeights(parameters: ins.parameters), task: .train) let parameters = parameters.weightsToParameters() - + return FitRes(parameters: parameters, numExamples: result.numSamples, status: status) } - + /// Calls the routine to evaluate the local model /// /// - Returns: The result from the evaluation, e.g., loss public func evaluate(ins: EvaluateIns) -> EvaluateRes { let status = Status(code: .ok, message: String()) let result = runMLTask(configuration: parameters.parametersToWeights(parameters: ins.parameters), task: .test) - + return EvaluateRes(loss: Float(result.loss), numExamples: result.numSamples, status: status) } @@ -88,12 +88,12 @@ For the MNIST dataset, we need to preprocess it into :code:`MLBatchProvider` obj // prepare train dataset let trainBatchProvider = DataLoader.trainBatchProvider() { _ in } - + // prepare test dataset let testBatchProvider = DataLoader.testBatchProvider() { _ in } - + // load them together - let dataLoader = MLDataLoader(trainBatchProvider: trainBatchProvider, + let dataLoader = MLDataLoader(trainBatchProvider: trainBatchProvider, testBatchProvider: testBatchProvider) Since CoreML does not allow the model parameters to be seen before training, and accessing the model parameters during or after the training can only be done by specifying the layer name, @@ -122,7 +122,7 @@ Then start the Flower gRPC client and start communicating to the server by passi self.flwrGRPC.startFlwrGRPC(client: self.mlFlwrClient) That's it for the client. We only have to implement :code:`Client` or call the provided -:code:`MLFlwrClient` and call :code:`startFlwrGRPC()`. The attribute :code:`hostname` and :code:`port` tells the client which server to connect to. +:code:`MLFlwrClient` and call :code:`startFlwrGRPC()`. The attribute :code:`hostname` and :code:`port` tells the client which server to connect to. This can be done by entering the hostname and port in the application before clicking the start button to start the federated learning process. Flower Server diff --git a/doc/source/tutorial-quickstart-mxnet.rst b/doc/source/tutorial-quickstart-mxnet.rst index ff8d4b2087dd..08304483af86 100644 --- a/doc/source/tutorial-quickstart-mxnet.rst +++ b/doc/source/tutorial-quickstart-mxnet.rst @@ -9,13 +9,13 @@ Quickstart MXNet .. meta:: :description: Check out this Federated Learning quickstart tutorial for using Flower with MXNet to train a Sequential model on MNIST. -In this tutorial, we will learn how to train a :code:`Sequential` model on MNIST using Flower and MXNet. +In this tutorial, we will learn how to train a :code:`Sequential` model on MNIST using Flower and MXNet. -It is recommended to create a virtual environment and run everything within this `virtualenv `_. +It is recommended to create a virtual environment and run everything within this `virtualenv `_. -Our example consists of one *server* and two *clients* all having the same model. +Our example consists of one *server* and two *clients* all having the same model. -*Clients* are responsible for generating individual model parameter updates for the model based on their local datasets. +*Clients* are responsible for generating individual model parameter updates for the model based on their local datasets. These updates are then sent to the *server* which will aggregate them to produce an updated global model. Finally, the *server* sends this improved version of the model back to each *client*. A complete cycle of parameters updates is called a *round*. @@ -35,12 +35,12 @@ Since we want to use MXNet, let's go ahead and install it: Flower Client ------------- -Now that we have all our dependencies installed, let's run a simple distributed training with two clients and one server. Our training procedure and network architecture are based on MXNet´s `Hand-written Digit Recognition tutorial `_. +Now that we have all our dependencies installed, let's run a simple distributed training with two clients and one server. Our training procedure and network architecture are based on MXNet´s `Hand-written Digit Recognition tutorial `_. In a file called :code:`client.py`, import Flower and MXNet related packages: .. code-block:: python - + import flwr as fl import numpy as np @@ -58,7 +58,7 @@ In addition, define the device allocation in MXNet with: DEVICE = [mx.gpu() if mx.test_utils.list_gpus() else mx.cpu()] -We use MXNet to load MNIST, a popular image classification dataset of handwritten digits for machine learning. The MXNet utility :code:`mx.test_utils.get_mnist()` downloads the training and test data. +We use MXNet to load MNIST, a popular image classification dataset of handwritten digits for machine learning. The MXNet utility :code:`mx.test_utils.get_mnist()` downloads the training and test data. .. code-block:: python @@ -72,7 +72,7 @@ We use MXNet to load MNIST, a popular image classification dataset of handwritte val_data = mx.io.NDArrayIter(mnist["test_data"], mnist["test_label"], batch_size) return train_data, val_data -Define the training and loss with MXNet. We train the model by looping over the dataset, measure the corresponding loss, and optimize it. +Define the training and loss with MXNet. We train the model by looping over the dataset, measure the corresponding loss, and optimize it. .. code-block:: python @@ -110,7 +110,7 @@ Define the training and loss with MXNet. We train the model by looping over the return trainings_metric, num_examples -Next, we define the validation of our machine learning model. We loop over the test set and measure both loss and accuracy on the test set. +Next, we define the validation of our machine learning model. We loop over the test set and measure both loss and accuracy on the test set. .. code-block:: python @@ -155,7 +155,7 @@ Our Flower clients will use a simple :code:`Sequential` model: init = nd.random.uniform(shape=(2, 784)) model(init) -After loading the dataset with :code:`load_data()` we perform one forward propagation to initialize the model and model parameters with :code:`model(init)`. Next, we implement a Flower client. +After loading the dataset with :code:`load_data()` we perform one forward propagation to initialize the model and model parameters with :code:`model(init)`. Next, we implement a Flower client. The Flower server interacts with clients through an interface called :code:`Client`. When the server selects a particular client for training, it @@ -207,7 +207,7 @@ They can be implemented in the following way: [accuracy, loss], num_examples = test(model, val_data) print("Evaluation accuracy & loss", accuracy, loss) return float(loss[1]), val_data.batch_size, {"accuracy": float(accuracy[1])} - + We can now create an instance of our class :code:`MNISTClient` and add one line to actually run this client: diff --git a/doc/source/tutorial-quickstart-pytorch.rst b/doc/source/tutorial-quickstart-pytorch.rst index f15a4a93114e..32f9c5ebb3a1 100644 --- a/doc/source/tutorial-quickstart-pytorch.rst +++ b/doc/source/tutorial-quickstart-pytorch.rst @@ -10,13 +10,13 @@ Quickstart PyTorch .. youtube:: jOmmuzMIQ4c :width: 100% -In this tutorial we will learn how to train a Convolutional Neural Network on CIFAR10 using Flower and PyTorch. +In this tutorial we will learn how to train a Convolutional Neural Network on CIFAR10 using Flower and PyTorch. -First of all, it is recommended to create a virtual environment and run everything within a `virtualenv `_. +First of all, it is recommended to create a virtual environment and run everything within a `virtualenv `_. -Our example consists of one *server* and two *clients* all having the same model. +Our example consists of one *server* and two *clients* all having the same model. -*Clients* are responsible for generating individual weight-updates for the model based on their local datasets. +*Clients* are responsible for generating individual weight-updates for the model based on their local datasets. These updates are then sent to the *server* which will aggregate them to produce a better model. Finally, the *server* sends this improved version of the model back to each *client*. A complete cycle of weight updates is called a *round*. @@ -26,7 +26,7 @@ Now that we have a rough idea of what is going on, let's get started. We first n $ pip install flwr -Since we want to use PyTorch to solve a computer vision task, let's go ahead and install PyTorch and the **torchvision** library: +Since we want to use PyTorch to solve a computer vision task, let's go ahead and install PyTorch and the **torchvision** library: .. code-block:: shell @@ -36,12 +36,12 @@ Since we want to use PyTorch to solve a computer vision task, let's go ahead and Flower Client ------------- -Now that we have all our dependencies installed, let's run a simple distributed training with two clients and one server. Our training procedure and network architecture are based on PyTorch's `Deep Learning with PyTorch `_. +Now that we have all our dependencies installed, let's run a simple distributed training with two clients and one server. Our training procedure and network architecture are based on PyTorch's `Deep Learning with PyTorch `_. In a file called :code:`client.py`, import Flower and PyTorch related packages: .. code-block:: python - + from collections import OrderedDict import torch @@ -59,7 +59,7 @@ In addition, we define the device allocation in PyTorch with: DEVICE = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") -We use PyTorch to load CIFAR10, a popular colored image classification dataset for machine learning. The PyTorch :code:`DataLoader()` downloads the training and test data that are then normalized. +We use PyTorch to load CIFAR10, a popular colored image classification dataset for machine learning. The PyTorch :code:`DataLoader()` downloads the training and test data that are then normalized. .. code-block:: python @@ -75,7 +75,7 @@ We use PyTorch to load CIFAR10, a popular colored image classification dataset f num_examples = {"trainset" : len(trainset), "testset" : len(testset)} return trainloader, testloader, num_examples -Define the loss and optimizer with PyTorch. The training of the dataset is done by looping over the dataset, measure the corresponding loss and optimize it. +Define the loss and optimizer with PyTorch. The training of the dataset is done by looping over the dataset, measure the corresponding loss and optimize it. .. code-block:: python @@ -91,7 +91,7 @@ Define the loss and optimizer with PyTorch. The training of the dataset is done loss.backward() optimizer.step() -Define then the validation of the machine learning network. We loop over the test set and measure the loss and accuracy of the test set. +Define then the validation of the machine learning network. We loop over the test set and measure the loss and accuracy of the test set. .. code-block:: python @@ -139,7 +139,7 @@ The Flower clients will use a simple CNN adapted from 'PyTorch: A 60 Minute Blit net = Net().to(DEVICE) trainloader, testloader, num_examples = load_data() -After loading the data set with :code:`load_data()` we define the Flower interface. +After loading the data set with :code:`load_data()` we define the Flower interface. The Flower server interacts with clients through an interface called :code:`Client`. When the server selects a particular client for training, it diff --git a/doc/source/tutorial-quickstart-scikitlearn.rst b/doc/source/tutorial-quickstart-scikitlearn.rst index 4921f63bab2c..b95118aa091f 100644 --- a/doc/source/tutorial-quickstart-scikitlearn.rst +++ b/doc/source/tutorial-quickstart-scikitlearn.rst @@ -7,13 +7,13 @@ Quickstart scikit-learn .. meta:: :description: Check out this Federated Learning quickstart tutorial for using Flower with scikit-learn to train a linear regression model. -In this tutorial, we will learn how to train a :code:`Logistic Regression` model on MNIST using Flower and scikit-learn. +In this tutorial, we will learn how to train a :code:`Logistic Regression` model on MNIST using Flower and scikit-learn. -It is recommended to create a virtual environment and run everything within this `virtualenv `_. +It is recommended to create a virtual environment and run everything within this `virtualenv `_. -Our example consists of one *server* and two *clients* all having the same model. +Our example consists of one *server* and two *clients* all having the same model. -*Clients* are responsible for generating individual model parameter updates for the model based on their local datasets. +*Clients* are responsible for generating individual model parameter updates for the model based on their local datasets. These updates are then sent to the *server* which will aggregate them to produce an updated global model. Finally, the *server* sends this improved version of the model back to each *client*. A complete cycle of parameters updates is called a *round*. @@ -59,7 +59,7 @@ Please check out :code:`utils.py` `here `_, a popular image classification dataset of handwritten digits for machine learning. The utility :code:`utils.load_mnist()` downloads the training and test data. The training set is split afterwards into 10 partitions with :code:`utils.partition()`. +We load the MNIST dataset from `OpenML `_, a popular image classification dataset of handwritten digits for machine learning. The utility :code:`utils.load_mnist()` downloads the training and test data. The training set is split afterwards into 10 partitions with :code:`utils.partition()`. .. code-block:: python diff --git a/doc/source/tutorial-quickstart-xgboost.rst b/doc/source/tutorial-quickstart-xgboost.rst index 3a7b356c4d2a..ec9101f4b3fd 100644 --- a/doc/source/tutorial-quickstart-xgboost.rst +++ b/doc/source/tutorial-quickstart-xgboost.rst @@ -36,7 +36,7 @@ and then we dive into a more complex example (`full code xgboost-comprehensive < Environment Setup -------------------- -First of all, it is recommended to create a virtual environment and run everything within a `virtualenv `_. +First of all, it is recommended to create a virtual environment and run everything within a `virtualenv `_. We first need to install Flower and Flower Datasets. You can do this by running : @@ -596,7 +596,7 @@ Comprehensive Federated XGBoost Now that you have known how federated XGBoost work with Flower, it's time to run some more comprehensive experiments by customising the experimental settings. In the xgboost-comprehensive example (`full code `_), we provide more options to define various experimental setups, including aggregation strategies, data partitioning and centralised/distributed evaluation. -We also support `Flower simulation `_ making it easy to simulate large client cohorts in a resource-aware manner. +We also support `Flower simulation `_ making it easy to simulate large client cohorts in a resource-aware manner. Let's take a look! Cyclic training diff --git a/doc/source/tutorial-series-customize-the-client-pytorch.ipynb b/doc/source/tutorial-series-customize-the-client-pytorch.ipynb index 0ff67de6f51d..bcfdeb30d3c7 100644 --- a/doc/source/tutorial-series-customize-the-client-pytorch.ipynb +++ b/doc/source/tutorial-series-customize-the-client-pytorch.ipynb @@ -7,11 +7,11 @@ "source": [ "# Customize the client\n", "\n", - "Welcome to the fourth part of the Flower federated learning tutorial. In the previous parts of this tutorial, we introduced federated learning with PyTorch and Flower ([part 1](https://flower.dev/docs/framework/tutorial-get-started-with-flower-pytorch.html)), we learned how strategies can be used to customize the execution on both the server and the clients ([part 2](https://flower.dev/docs/framework/tutorial-use-a-federated-learning-strategy-pytorch.html)), and we built our own custom strategy from scratch ([part 3](https://flower.dev/docs/framework/tutorial-build-a-strategy-from-scratch-pytorch.html)).\n", + "Welcome to the fourth part of the Flower federated learning tutorial. In the previous parts of this tutorial, we introduced federated learning with PyTorch and Flower ([part 1](https://flower.ai/docs/framework/tutorial-get-started-with-flower-pytorch.html)), we learned how strategies can be used to customize the execution on both the server and the clients ([part 2](https://flower.ai/docs/framework/tutorial-use-a-federated-learning-strategy-pytorch.html)), and we built our own custom strategy from scratch ([part 3](https://flower.ai/docs/framework/tutorial-build-a-strategy-from-scratch-pytorch.html)).\n", "\n", "In this notebook, we revisit `NumPyClient` and introduce a new baseclass for building clients, simply named `Client`. In previous parts of this tutorial, we've based our client on `NumPyClient`, a convenience class which makes it easy to work with machine learning libraries that have good NumPy interoperability. With `Client`, we gain a lot of flexibility that we didn't have before, but we'll also have to do a few things the we didn't have to do before.\n", "\n", - "> [Star Flower on GitHub](https://github.com/adap/flower) ⭐️ and join the Flower community on Slack to connect, ask questions, and get help: [Join Slack](https://flower.dev/join-slack) 🌼 We'd love to hear from you in the `#introductions` channel! And if anything is unclear, head over to the `#questions` channel.\n", + "> [Star Flower on GitHub](https://github.com/adap/flower) ⭐️ and join the Flower community on Slack to connect, ask questions, and get help: [Join Slack](https://flower.ai/join-slack) 🌼 We'd love to hear from you in the `#introductions` channel! And if anything is unclear, head over to the `#questions` channel.\n", "\n", "Let's go deeper and see what it takes to move from `NumPyClient` to `Client`!" ] diff --git a/doc/source/tutorial-series-get-started-with-flower-pytorch.ipynb b/doc/source/tutorial-series-get-started-with-flower-pytorch.ipynb index 704ed520bf3e..f4b8acaa5bb8 100644 --- a/doc/source/tutorial-series-get-started-with-flower-pytorch.ipynb +++ b/doc/source/tutorial-series-get-started-with-flower-pytorch.ipynb @@ -9,9 +9,9 @@ "\n", "Welcome to the Flower federated learning tutorial!\n", "\n", - "In this notebook, we'll build a federated learning system using Flower, [Flower Datasets](https://flower.dev/docs/datasets/) and PyTorch. In part 1, we use PyTorch for the model training pipeline and data loading. In part 2, we continue to federate the PyTorch-based pipeline using Flower.\n", + "In this notebook, we'll build a federated learning system using Flower, [Flower Datasets](https://flower.ai/docs/datasets/) and PyTorch. In part 1, we use PyTorch for the model training pipeline and data loading. In part 2, we continue to federate the PyTorch-based pipeline using Flower.\n", "\n", - "> [Star Flower on GitHub](https://github.com/adap/flower) ⭐️ and join the Flower community on Slack to connect, ask questions, and get help: [Join Slack](https://flower.dev/join-slack) 🌼 We'd love to hear from you in the `#introductions` channel! And if anything is unclear, head over to the `#questions` channel.\n", + "> [Star Flower on GitHub](https://github.com/adap/flower) ⭐️ and join the Flower community on Slack to connect, ask questions, and get help: [Join Slack](https://flower.ai/join-slack) 🌼 We'd love to hear from you in the `#introductions` channel! And if anything is unclear, head over to the `#questions` channel.\n", "\n", "Let's get stated!" ] diff --git a/doc/source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb b/doc/source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb index 06f53cd8e1b1..c758b8f637b0 100644 --- a/doc/source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb +++ b/doc/source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb @@ -7,11 +7,11 @@ "source": [ "# Use a federated learning strategy\n", "\n", - "Welcome to the next part of the federated learning tutorial. In previous parts of this tutorial, we introduced federated learning with PyTorch and Flower ([part 1](https://flower.dev/docs/framework/tutorial-get-started-with-flower-pytorch.html)).\n", + "Welcome to the next part of the federated learning tutorial. In previous parts of this tutorial, we introduced federated learning with PyTorch and Flower ([part 1](https://flower.ai/docs/framework/tutorial-get-started-with-flower-pytorch.html)).\n", "\n", - "In this notebook, we'll begin to customize the federated learning system we built in the introductory notebook (again, using [Flower](https://flower.dev/) and [PyTorch](https://pytorch.org/)).\n", + "In this notebook, we'll begin to customize the federated learning system we built in the introductory notebook (again, using [Flower](https://flower.ai/) and [PyTorch](https://pytorch.org/)).\n", "\n", - "> [Star Flower on GitHub](https://github.com/adap/flower) ⭐️ and join the Flower community on Slack to connect, ask questions, and get help: [Join Slack](https://flower.dev/join-slack) 🌼 We'd love to hear from you in the `#introductions` channel! And if anything is unclear, head over to the `#questions` channel.\n", + "> [Star Flower on GitHub](https://github.com/adap/flower) ⭐️ and join the Flower community on Slack to connect, ask questions, and get help: [Join Slack](https://flower.ai/join-slack) 🌼 We'd love to hear from you in the `#introductions` channel! And if anything is unclear, head over to the `#questions` channel.\n", "\n", "Let's move beyond FedAvg with Flower strategies!" ] diff --git a/examples/doc/source/_templates/base.html b/examples/doc/source/_templates/base.html index e4fe80720b74..08030fb08c15 100644 --- a/examples/doc/source/_templates/base.html +++ b/examples/doc/source/_templates/base.html @@ -5,7 +5,7 @@ - + {%- if metatags %}{{ metatags }}{% endif -%} @@ -99,6 +99,6 @@ {%- endblock -%} {%- endblock scripts -%} - + diff --git a/examples/doc/source/conf.py b/examples/doc/source/conf.py index 608aaeaeed6b..bf177aa5ae24 100644 --- a/examples/doc/source/conf.py +++ b/examples/doc/source/conf.py @@ -76,7 +76,7 @@ html_title = f"Flower Examples {release}" html_logo = "_static/flower-logo.png" html_favicon = "_static/favicon.ico" -html_baseurl = "https://flower.dev/docs/examples/" +html_baseurl = "https://flower.ai/docs/examples/" html_theme_options = { #

?D@Xt~YZSLox1pB{TQFkP+ z$&ad*FNF?tRA$()n4U;YE*)1x$ST7L81{lI0`gJC1-LjWIO)d9d}#8={}va4awAqK zr7h0QzyhIH3>1zD=yY*bFgUD(Mj(-rvxzidvnnX#BYtXVjV?9`2Csy!FpZN z&{z#ZeT&IGbJ9M;k9Kp+qU1WGtw0Nxvk6l#$Ft6lp&C@hGuzq*GlCB#knx5qO zP**xJ_qg=7rP^rl)RAZMrtk8Ap(?kqJ8Ze4=%%6X*S~`9-uju(FOC5#qtV)zJD0;r z+1~!85ur~U9!n>O^Ksabb`eDIirWeQO8jMSm&{e#ySFyi%-1TS-n-v5+}qLAdDb#{ z1y+6E^I5NsbZmuzy!0+0UqGC7EZ6`xA{+AhZ@f3OCPf26v7?)lJ>tNGvo6e`QV7_ z+=OKo#Kb!LO7mlO{&V>|Js=GLYv5RPDVN+kGm)72;|ON1+u~se{Pi?r3W_R%zM%b$MJiPGA?Ja z8d{#b>xz8PY0OT!F z&1NJ8DQDYzyC`P7-!cFRCRCi8fti8F#$SJo2aO4fex7{c5m8K*f5d>prC@p1ZDj`Y zz(*<{Q`7NOfzE^>8(v;vre44{r*vA(>Yj5LW|W-pVtr=|8M~85JwW4Jp6G#k?Nw5u zy4(G=1IBJ2f9h8D`*`dK!HVVIXo6G=GImaO#T$%aET|!uz>u+2DBl1nspV5*kzf4| z^Ns_omTszc=9;y)g0T-^%!mofG`bd}Jf?wNMp-e1n1rS3)lI>X3@*BUp3enXY?$pn zq-?mMRiF2d)B|?B3~;=Q5*}{ev%GX9?>-BeK5g9aNPww|xg5xgV*k}EJgvPSHVz%S zf|LvGz0wp{1xpk~Mpvl3g9N>iUm%0mxL1eJ5 z2LVRV6G4?1jM?v|Y%4Y@#@mz)OlTkW%|*bFovNR*A|+UAan>@v9Ap@Y!IS%7j}Ec< zvdMj|cqnSk+P&`ntm}8X!{(xCnhJKzgr`fWLkVY+rnOIkF5{ITc%6O|VTbOKs*hq; zK4$4(6Ee{QDJ_l;wFP`RE|_=K@6EaSZ&#!(>d|ao7?h^~N{R?qZS{d^Duy%$s!l+z zp`|$_ByvyNdi9cZ&UN6sYYlb9E-`*$WW;t}m&cNi z!T6p$vX9Eu#g6U*c`_M&5^a%~jAwBWmiPgV2JH5cxH$En%-5oS)7C!4RIS9W*-!@* z%RV3pE~Q=+EAXO?P1u*r`14)cqaj7hFm6sM&;UC$x0SWp6f}_v`~uqX>r`OK~R?VdUZmf!cTnIQSUm zlesh)CV!2T<&~}hG0pzNhZF<$8I9(=9{3y1NM3nhqzg_S0jY6UV)=^D7T1tnb{MpO zH>ITCw5Ke|WQf{QXpSuPMJ%txt;wXkCxzliljJ9go5$B!I4M(q!uIW5$-|t1d{JDk z?sUCdcKTN7BPy~FCG0B|%QBTay;IKPQn0uufAVL8cdbaMEcJp8-V~i4FiU+$*g4t= z)u{ap@he0aTdgMx@7N!MA%3^0L}wRBTz6fh2_yJe0|+dWp@?AV8PgKVPGo1I_$|gs zgvsBfuiJ}ef8D%+{WpDJMKfA?`I+LZ;kd-?D|>%o2_PYh!L@xmqOYnJ!yrLtEG-m& zSpQjks;$h^$CUp|(`QNd+}KH{s?wB~FlRrvt%b!yu; z@nZ4f890y_c2vjODenuUS8rCwb86&$s)kj`5-Qt^{3uB$+GK(DdjB;s)T!q;%$KQalhQivT5I==ha*5 zuYI0&b_CUpywf=q-mTO1*=}4wh_w1DWo*>-N7k58=5OLc844mr1jNnOz|Si$tDte) zlF>iNw9+$pQ&#&{amqCFb3mk&W#6sk14S08N|u@$p)IJxmRtst>c;Qma(*rcw`Y@+ zP`|}i0|et8E1MY)Fm&ze%)O_iU4LSKAZC#|Q6fbBhr7oF7k3k`-U~Y-?jNpoTes8B6opLk{1x)g z1S0qvoNvjj7-f?QNK`*cx3R61mEq1}OJ5|uG|fS8t-UMBB$~(zG})Ve@t|kkP`;!R zV&mNstiD_90jl3YcI|TFA_*U$$p}D*3F8Hmw9XnnIOq+``Ii}DeQG-LNO%g*Hdwq^ z>>4dMs~Grzmlxy#ba=J_$un^w=LxJMrafPZq*da1GY4Z;s0V=MH~zhYJXFs`)w{vp z$5~niAu7j&8_1?qTSwMUIDQ49l&Vscjk@cL&}2)%BV+(ODWInVuFJF@IOheK3pvs) zRQh(3h67nK5X5TyX};qw>x4mr0%E8vH0iinxZX{L9Ws<#YIYENYAa$J#yL3f_S^H~ z*b3ovm*sVq6;D1iHhl2^BM9-pw!89Kz1{F|ZXl0XZG;13^cG({iD0LPN+YbP@kRN_ z01$c&Qd**MtEBQjH*WpuB~A{j(j2xh?0vy}mLUVwo$%OF%Dy)Ds@S|@N)JofWiRpL za83fYvN{yDN(aG~)ZhCY@R~1ZCho-1=To3TcNNoe z9dnT?UCyWN4l3=o(H%QA@ZyqgBaPtlugH*BsIAejn~81?b%gKc;&hy1(*qi zPw*oj{h+rJ#g)28%lEjfWvpP=*a^qAtdDMKfbJ`9B}Zb$>|DP7HvV7HVxf_C0m#%n zhMbWiCI;K7NAK}+2)dT6f_A(uv{}r`N@~`6`(1a8+SrfV4 znJqOuj0VM$brDB^61pmSma1ed_34kuaQwmi3x+6WIw~gZT%CG}VN+Z0we0+>C$@3B zu~90!;(ysdo<$Df$j{Zy>m{>&(q?$wMDUWM`+uc!v_)N7tt9n##j>FBrVN} z0`Qi+{vh)hylZPwqNq$~eo>;u%Yrdg%REW2i{};|!_L0b%RS}Mf)i_7*7Loz<2mfR+{YXd8;*a)C!r2(35H~ll zFRkiHT||5Goz`^c2q@LS@~99c6iA)IgQe!PfJWIQYMNk}y`-VKE_u|0Kjf04Sm*$90; zs4=Q<@s(Fz)-pc6lYmO=g4CpqTa;W$`&mJJ)~~s}-ikS1gT`rR^hB-qe}}-6gE&!DLn4#~Dx!G%&%#fh*z zRZ@-(YHNHO(}(dlh8H&5s|n<81P%jX+~0MHut;1-B|fS`jt5XHgm!UxP%cm6*#{?o z&;oWcQ(vBXu1<}lww{=y64j`nRQ7BzeVJ4&DNcIsC4j$AZqXu;KhvB)-F(W^q{w63 z?d=eC_{aRmal|4+>7aaSlIZj(q>^m(C>_&&Wbq`H0=DC<`_pE00E{eQg58@9hUs5r_XW71C{7zO-wiN*3{M!IF_t zeT)brB1}3B#g{KGv~;aYEmZc&izHMmWve+eqP7ST(aue4qzAOMN@%Ot1yj0sW^l$bu#tah@}(gQZ&~dK@_yNkC{db| zd9BY*h=)mEtUAiY|(lJ72f;3)2m;BKbSf#YDyX^xqT6obghuhFkrI%_7$odv=9#55DHwka|Ow(S5?n_<4?#MBV}UI1@0R?p0sw^M`ty z@e708d7jTJc+U=kJ5AK_!BY@Bb95tSb&z=g9kGNVgN=1^X4M0+H&-(EQfx@J8TL;b$$KF zAsYrx&bX5isa&A9?|i*gDCB1f26G)WpWx60-STD%I?)RWk-S@7wHlVZakLr98A2s7 zcAoc$ip+Y`Z$EJPVna*UrhGMKp4<7#7|=McZnszEm}#lJaX(otf2Oy|M<#x-@)p0$ z8ZIDANzwbG_C|LZ2o$Cl`ma0`$tIYrFSCgBi;FA#VBN@FJFTtU$z8z$y!c9*Ne{fd zkCc=h%`JG8+@Gy)rZqy*=*0PsSJi&&?7Z(1Tly_1eCl+k=VUN$X_P_2%TdPVePNH+ zIlgTs?}_5UN`f!)1?c{a3=i7?ZAPGr_6XqiUICyC&|R_xu$1QO?PCAaQTc8tv~H&n zfD;C@M3RA?AX=@gtn9LD!*q=UNt5T^3II-6+}~c!yNyW14NEvLApz|}Qn@=vexOrC z8vaUGml%L^5HQTV|H%;034Cb(N+v9upA7hg!DD4fkwc8!RsYWQuFNBHl_?@sEG4Tq zz0Uw2Vy&FOt3PCN-Bzs?zI?LG$=+q8A6fXFR850!;VZp(n5_3eKXP)C01k|ZR7Yil z=xvNAH$4$`FefX%gC@abz6?iHls+MaxZ0b}j1TXaSbxz}hr$HrHo}rh@VjVePRdAT}s?7 zG9x(>S9_2kzt=&)KBQymym7|aTblMG&3ED7yDqS^!1zO&}C#o%JK`|3p6-fuC}xICtjec)>X~G zfd-4s>)FT5w#qhEb%|*SB0RdP&$@UHQ&U&^2fvEC(H!Ll$aU00c;CDs4}(Ayqk{ZT zFl?eD4--b?qrxMfvz6dH#S-%YW1<_|uyKHdoj}?%ojH0-eRD)$>i*rLCnXbM+B z2rT_roWb^v>Qnd-l7s;%!Di6Zsr2G&S<|`UI@y;ObZ4MusQSZBh>7TD z6y=N;ta!r|83GQ(xDuy$>FMbl#`P5@k0hj|Xx{M;3+K(;{rve8i&FSQ9EA`-fMxEA ziDn5|@uk;at!Emv`irO*CR2%d^4S0RE;z+ZPrwllswi~FMc5Jxy5w?Z2!!V?`F062 zyQOdJ@@@4=`UlD2*tA$$?YWxEqGFf5#RPVKLOosLvOx}G1A{*{*30b0G*$E1Z*3mC z&FPnVm~`zl#R7y5wF9oA>R>QMe0 zMrWJc$GzvO=IRM=2iNg($q>%jJiy^Hu{hN)J?=FI0?@(CPfK(PLC3eAK?Vk7fWtvH z#5pRpo3_|L6QugYN>9LMY)Z0&QwC4YQbRaf*X)KNYM@MsNI}woF}wNYD8)(?gtG75 zVkMw^ndV5nv$fXnV~n-6hX1%RZ)j2W^b1%5leT7(H91AaIl08yck%SG69 z+L%mIS4JBi)WTR;lYX|q$>!#0`u&(>9tVkgI~ePzADX~jRw7!%wpVJiX^3}lmthev zk9i(Wz=gqi-^dn#Exh(0CX{P{#R2F9BrFQSk{)>cu9){BZBI`RBV%=`!!$q{437k! z^Z&=BAzS{&?lK=QP`L$QM1cNt1?%bU#t7hhkngM<(oS-ZTRE@ARj|mM#smbVjfT9sU<3ynLzQ;qGjs-_08cB*Z#}(m#mAcA1j#(V=K2) z9r)ADon4iIim+p@ccXm7<{?)uZvVLu_Dau9`ythhe==$kn&4)R=@cLJxRyg$Or-lG z0L0r^n@CuGqoU$;R3CnGe0)4h`Fmq9U0PKY=VW7KBi%M<8MrV8SN2^S6jW8$0sL}f zIf4d!!LbV%g*X6aA{hsqO>}pEPf?T!8Q{S>mbhxJI75{jc!(_xGs=`0wy))@h3Yfs zt1SU~u9%>Du=GX@x4eo#&r|oaz-! z3cQT!l1U6}5p~b@2OZz`hepN$DZ9+#uTE1@+oQsfUNp!sG`l@#ppIUmgmxMoef=QJ zKu>RofCT}vECxU`kDxTReIMxNeKxX%vxns@hX4-mIXinE0H7Rt4iX!gm<$c3^ZzI+ zqGx4|lDb{Sg^Cx})~3$R&bIFyAG@|c#H2Q5bF#9`{y%_VGmakBIxOJeczD69uXHfX z#?_~pA?N4^T%>K|Dl6MnFtHY3jPBCkW-oifhktcsXUDONQF!UrKKSSoFNB16nhXG& z&YcNNBNK;u&b+z@A33!3`g$9qj+S?I9TN5fi))5;pQzB;r<06^C$so!S5tqMA5Qbf zvdGSm<&bx6*|}tmip3}X_$lldC)K`RA;lg3CiU@{a_;Olf+kotIh!q3naH7k1-Fwwd4l&wI-E)XAW%_jY>H z^A6=Ly$OM*3`hW+sq%1tmni`T*hB;${f@i!^6Sj6)eJ3t{XSsc5SWZsq3T+qJT(YF zK(+PsPS!q|xh@7={Pep3U!U&{6y^rb+Oyx|Qzt~E^V=Q+sGeojj5k1!A=lK{EHwLw zUvK8A)V7_^I+O+q)6tJnmM^b~U3fVUJ%BZ9JgaD5}wa#Wne za&q_;masndO?E-Mo+*)c++-6-j03HO9@|&;Rr&K!Qw_AE^Z1<>r(>TdUL=IeY>e|d zGWErM5A!A$n{2%nln>k`I_Hf2onx%HGH3O+HUlxJ7!sCQ0eb4NfmDAdziP(`j34xGf9C)=BOCc2hMLMDq zvM9L^8~9aJ-A>Yycz?!6R@e%Zqvi0^G;YO3n%D++in z%xkmPb#p^SI>l+C9`;R*O8q}%FB;tXI0jbt0w5=W>o?D)UgZ4ge;?I4*=o#t`;_@S zL*b3pn-4`;CJV=|^B$#3WxLm@&R(8^avmp^r$!cvkx<>Kr{Iyk_DL}mBRRC%Q}@C6 z7}_$VvYX*BVKUA43)v&aN*Q#w-wu8TkiM5zm>QnQ-X; zvWrx3oOMlnP>G_x4nc+bJkjE(;iw4%RlZbKi=BQEsn`{%0*zD*1DY33Kc;sR86PRK zoSS$&x$}elMPK(Cpz^*`Z#Fl9@CDF|!5a+?4FJIRbq4P0wqr{H_EvT9+@0>Iv>rf8 z6Y~OB!O)uiSM)L_dDpwe6ad3T7yM6D02sHt`S>Zq%ICB(-*qjwj}CG>3TARz-D}`{ z`^)`Ho@qA}>nGNPJnUa_XW~HYE2WtD!UnF*dYM|dK_@Jk4c>=6CfC$A#$59^7eeWD zu#}Xry6@jjruf1lZlEDk9*SP4TkxRl#9$`DbHM0S+4{T?`YHB#uR937dH`$0D#Rc<2|$z3#qiAwoE;2Dk@Kr|pWjjoP3}RVE=wY3@OFm;KRV$G z+1JLR-33z;1+N^rA1sYU3%*-b=x^<6)od;9{5@*mFd#9R8~l452!sH(#+x~G=`RU@ zqLV9{4ge^MLMtNDFhtnxwAd*naj+vJCYX$>9-1P)!Ap%AXw0Fp5l+H}H-?GAb91(PI`cMaJ zeJGhEO-?9!=3{3)8|M9H@t}8(>@lc*hK4415b;-;HGUU3CVYcyM?VGX2HOS=YfK)JK+LaK%M8Y4#4FCJ0OH5AqYeNE7$#&iv?yVAU0rXNVD_Vl(&T4REgQyLqKku zA+Zmjfx#OZ8Y)vfXTB|ntU1nb*mfvmVqH{5W;PEU-$PecMZ)C zYsRw&ngpG*=fP_~2DLQDtUTQjDc!DPEE*xCHmt^|4vnr^?e3&nTiNqQ(HFh6xa6$D zE{N4(2l=W1h3QYd(Y-TWCm5vdOQ}(VYRv0`mB&x8MI4X?+mhgVaNLmf%Lo*~r8+q! zPIvMEiIut>N{-P3jkH=klMDb$%~u5mxkSU#3h&2ADrdE{Zx<2b+$-Er`t^n9J4&Cjj%-*St@I4$NKhb>S$?16Rk;npEHVjx{^W%g zKlF2JD=WlaGL_4uf9#u51F#`Z7lKd&U~muor~(WV4Fu?G^v(z1xB-R9O<&rH(1JGu z58XTv%hXoXUduFQ0AwBHz$X)7|3Kqda91aQSQ=CP=Zd`6MFeWCx4MiM&ZCR2$KemsP@r<}!zz(@cOg(Je0A-ly11f(hF9 zfV@vhrN;`ph4vtB6zI> z6d$AyKn9JJZ_ckmy>&o0(KWKKEu<87aTQT+6Qb^DztFsg)*KiDYLTtJc~>wR{Qpb+ z(m*fU^Ya;7ueaF|NH(I90MOOI(Ue~Mnz3R%?qP`wW5gkw-UOP(Rb#VIjPQA|SKiO< zp&#IlV{!Vi8p<-!!A=MXBFB4P%IQ=+;>hO)9&u~1XeUxu&Ws!)nB{M{E-FHX{dPcs zjou}+Mn?mA9VOv7<2#ykCKx6DYzvyWDb3<~N)=aeT8#%`BavRCq42|oZA{G|B(+`KC=^;zgX9VTMy>v; zgzkP=4!PgVOF(NZsq1O>IY|?Om=;6zOLf5wYsA2n>N&yhvLb^8znrus!Wa2k(fA<< ze8&RW_b2>R?&7T!_hzl~{*#Nr!+=7(GLB|g>B+~B>Qzn@6GpY_RUQ-qVxCJPz38d( z{4;yg{Js-m2a<6%Z|b_C5!#-WVK(b2ZPm2Y>7B zTAN=kE)FE(&g}I$$vre$(ETAn)sDQK@J8An?fqqh1h9TziV%2m;&A@=#>gP28xqK_ ze<(Rb#k^_A(eh0>t1<84(_v*v!YWpG=J8`49gV60u?eF(jVcdJ;AvU%_pRZaN}BSt z@42|Wt6&gm-8V+d%B*&QdNBoql+3f4GdQ$vJ$3oK_O`=GIW6U}+z`E3(cq*E zg8RF@wyP1ZhcB~QQm0G+KOs7Tx|20cURo{I>=SdfnpM{9HGb!m zZg&7TPPhyBT>@=1HVTkN>jQ1ZtH)71s#UR_bZqtOmIiSky(Xr3tEX&9xu70&^f2=ZVk7^*+->2ms}qVAn=hO18lxI?qq}Sz^|nLNoVkWWztscAoCg7 zTRN#KFXSzZ<IXbY?9iJb90Sx)o zTA8cq%>7etNDx_JQy>Os=1lKkFn@#fC8vAB=E4^N9~_zj8)*D>+4fv(kDlqmwIVTQ z{3DbnG?G~r%Uw@sc#-8F?&(B~u8%~GHM;sCxJNw;uP1F%)i)ilP@Yy{pcP)SxQkVR zU)O<0p__E-22XBur63420(QE&f)Dp`um-f`rm_tw( z1`RJlG7JiFQnyRq)JsuRDvn~%Rjq%jlUQG4$qI2($y})o(E7Io_V0*Vjk28hCI?gy829gt!$;{z!bi?c%NB0 zdyUZol$WG7A5g$lF6;m$o>P5rP+a=WW`MXz(DAeV9a@o)Q>UH*+4Q1uezm(2eREli z@AM)5dt8cWCa(Sb2~x*~Zxj9%0=c-gR94cSid9esr6A=Pjmg5?9(DlWWaCLe;<*(bzfE6qL{nz3&8E-ai$Sg zC+VHistJ_X-@OAUxq(fhC#(3jv34(t8|U`ITm0JeRK9>mKrA$WYCazHK>|zemOhel zQKt@`F8?|`2#gizYym&G+R7XLaucc+A8%wp^UX!S+eY@W2vXT*2D-h9i1zh+q`Il0 zpo`m2L5^4G5k)uxvtFPB%&V=)+%c)v2N#pM!>jMG8g{(C;webGmiq5w3}(XkSE0xt zasNS5N0^wW+@(2iO3fr9i(@Wh1byy!#-nd$*9Aa+(j~>yx4JYplb_AZqJDAKyAwVx z8EK!m72q|Zb1IRFy~tiQi!dI@0m7F%#x;$Z3}fWHq|m{>&!>$#akW6}z`Ou0UzO!T zhM@k>?_cdT7A(7JwCv5jBrTt<$2XIe9blPue2+_GO4BDF*GWL=CJx#7XhVu7cFcZh zZX`KSyIxiIxpD@ss+Is>X;jb2!5ckB&5i(EX!$w%Npy2+f(rR2F8q%9%GL;X$5$!{ z*ef6~W{hZZHEbnM?q$HnfX-rWnq;Dw+(O4vcZXAB>Xd=v+4@lMOVbu>OgSfZ2Pb(M zJV|@)&mQ9b-A@KVpv9fLtRi~}Q$d?g$G^&uQy~K^#ovo&;KO~9w%3QxxX4oh_y%*J zv!RIg1~Ulrs&&Hoteq+cIE*CWsq zcb@&pm)a{U5WOoYyv7$>&4pKoLh#ZED&+Xt28wf7%M(ae(G5lK^zJ6J#1M1BV|JLj z-B<*eA?l)~Dp**_j7i_@phXc(CCHPRFl$CEI3}XddHJ_hl4a%RhY=-nan>&MAZ*YmqdSOE&YGS!F zUAAt%7vq@{Q`wnwZ^J#Nc$uxLz7+^QSp~|R>%OaQXVPLgn8w!M%RQ}$3sT(o1wSk@*XA(c}cK=tw7J) zKYICYn;-~JilASq((u05r3ILxi*zJ>43>3lKywv7eF6A1R|3lCQte8Mt=(dN3mtoI z=(R>Fx;Ceo9YbB<0xw4hR&K&}snHL^4P5vHAP^^~(^aP~J4iYl&!v|v7z0*vbj0$2 z9mbO|1r-vp_SYrp6WZtQfb(Za2#$f5f$52*`OtlNuXrlu8|SLVNvUtN=p+%uPs&+> zPD6|tFkFtihOr2_5(88iAK_pK-+KK5o6cX;4^*YX9q@K3iP80N>XT@2?|4}?STF4z zSbcUlqaRv6PjKxNRPc1FNwoxqpCvNz%2)Hbd6Srvq5^;Oa&3V9#0!qq>$9MwnNb+!POG|#62bBHZHKG9R)14ZY^Wwj>UV`Uk>HVoLpd6 zDmO zIdgJ51_YO%w1KO+7w|_sq{}QP?W!VwLe-lfG*=IS8I@iOc9o9}FVlFtja_;1ZL@;& zf`XJYU=;5v*@O_mU{R%^WPq*rEuA!r%&bVA89ksl7RC>ZV=G3Rpe2`%9NfDv{u}5^ zPBxYG-&Y&cCs|%CV&G-_uPl53Y^skJ(X_8l29f$FonRnj;Y2ke-`fG$)6DRNZX%R2 z+Ie!-i75w>!}6fz+tuV=lArpK4bJ2kQun;e407(~XJ1Mu;cM^%9E2qPwek_lB6LA%zIvl~ERNt;c?x5N=?921Ep^?U%-z0Lz*r5;TjkxFKKY?gKPw*Jw za-3Grd<=jZ7fD@9-+mG-?);m4q1!-(QQ9a3O_2LzP(@bg!@W?=oYxD{VM;Q^dE6j{ z+p{T4HKo12W9ifp+X}(rv^t@+N=FCDwV_y+gDK7=R%u_J)*wWS4iCsDrVm0)D$Z1< zkC{K(2*GF)A9t0VqM!U3eY%E_fdCP)<2!)EHtq+SrnBb+H|*y^vqH3iNL3LdHUPb# zOqBAmx%yp_o@tNUrg|Q{gq4-iI7q^UKPZw(w2@%|*FX$c_wan(cwy$FlBt18@*RMD z-j4L;7)!FH0Gxe%OR8TF-E{5rqG3*3!&ab!Fjngyn*JNr$4dN`f!TA#&+5q>=chv;qrlGq zUS%L8xkc=>C$7%mnZW|@GRUa4Y|a&l@SiID6tZU7={r%{n+upVCnbE&@{Oz9yP0X` zF@o0gdeu@{6nnmHk;lY?>FMaMIAqXgg<})m#CV zY47B&&w5n3D|g{{ncQ$>PlRo)<-j~F-c|vg)(mPwv!4-fYuqB(qnoZjhA=J?9)e92 z{wjs*4}a~{`mbBpnmOdLafFO^ao?Krr?&y56aDD{*W%jRSgWqOxT|t8Z41lhX091o zXJ)q9o@Tw|qK%MIiT-{>K!>|%wHwYhQ%dvmY9b>=9LB9YpE>mhW$#&6lfg6uIsh0w zS%hfnl2_|a?HL1TvZybWEcA3iYzEL$3dH}q6FgRB!?m51B)6hjc_(7`I}@4n(I1V4 z1+mJ_PX;u&8%05`?)F?emK~YJol}eP(;vyS1@FZ$C8YrDlVJ{<6^+eXdJ8ySDd+q7 zn&;v8;U{I0;pKD#eM3gpz#Q$Kg2N_)D<9mHrSdLr0cVO=I@T=+1=~Wmb$kwDghmfq z84&mG(Iv0Y@OXbnv|?T!cm@E23_4Ej?HoCa7Z)a|^SHitwjWl%q<9Bec8)M+ZM(T(pV4@S-0 zkO_=WX8>&f^X0CYf(m_meXVNF*no;?jQs5{@3wS?1cj%KipUP6_#c<=$u;6S_3ZWd z8|*$;q_xfws~@o5w;2{h%{E&2*j_}Hd%V0i=+8p21abg0sU&v8!zIym1WO{%!+8_F zp19ELV+mXOvs@k%iqIXWG8%+m=+S)=RLPc}3n9F|xPr*b>8DAe53`TcixWIOc6B=OxU}wtb$0s{f9lrzZwyVxC-B^l$g(UP5AnOhT z_8FdiWv*M}Wg$3BR-*3Y_G?e0KqvxJmz7Bbmt_Z9y+zLk>$-DJ5kIcb(&L0&%YCi{_tU&z8PhbWGHjZ{fz}9P}fzrvEHw-JQ>?4EnH< z-xM23o+RV@_T=l;X$@!ZJBfB|c@6^OrhE;jSe3R%qYfE_+wZ5w6|8;MRYnhP#wIiI zc((E7%)AtkXr;oy$~e{P#8beMXEz*ze0rrY@FQz4-_?{rS1wf1F%H-0?D8;?BzaP3 zc;V6Jlg3aXQuig2LfJ>SnZIxR$T`}bjunR<9EyCFxCsF1D?j-MPUmRN(pm-hk85p6 zHeYX}J5iW~+$QJ2IXI)=&p8(#avhY#Pux=MO@zX*H6w78r44E%*2S7mBL!|rN!FvS z1g?m^d+RXTPIi0RfudhEL;sgkG8_fEk`_=Z)7sA7>00|)cCPeWWm??|^y9wJtmf&F zo7nr7Oo6*x_ePZ(;-PDQib-9-#Pu-a_VoAw9pVcvnAS+5#tSgaMdZ3@-PfSUnXj~U zx&g3X`h3E?+&QklTwuhA*{$;$xmD%IUFA%`j`g}yAyakXcppRz=NktKP7HQ}WAN8@ z_tldldY8Vdd<-uh*~z-+FTvEvwXNxz8q5>-Qns)Zk+%k&0tO;ff6o zcV354M~1d`N-Kst$hQ==X4rQGUSr-=+b!3hS+C67V3K~Kc0f%O?1xe{n0@pc{%iOy z#4aWB5v(9+*IVXTY?_(r@OG~I>g@Y<=#d%kVeJ-|3fzX0rK)C$z=03AzLsfbUG1Xq zaA&Ifc`+vk;BEx&vIum!Q^=C!=-+SI`A zIQ@pJcPD1f{TeCGHzG-@e@kt+xlDF&LrE6d*Xh8C+{`Y{h;~j%==!2wtN-%V#c@-O z;o8Zlhkqy|Q}w*4hLiFgZqL|`#0~o_Cm~%HOPLqkCq_p6-`1aXr{?228y`@w36|Gx zxQ%P@XeoNlL8s7w3G~`_9{%C!skMPC;qZlS&!gak5n%;{RaNYPwL2^--TXrr(O66M zt{Dq^DO2;6Lq#E)H@(ZHj8*X#W3n&jgp?+`J51;gMe_4D&iqJcsur$73mf4Cnd_%t zoN$V4^!>O4wIxIA0=w7!V_38YqciwB2~^;f1KTzXTgn1l_KG|$#`UgxV^Obsu3M7X zV95}xy*aD{yVH|&J>q2<;rOH9*5tz9#EPAuT`%GVy)^mLcTZiGdi3~r{leoX_4({f zJ!m>eq`GI<;_&jziRXcPX|2S9HlE$npKFTvBN~Es?_DWYG)u|kramuke^=b(&GGUn z8{*X$bavT-W@G;XIwF)@J#|r4Ym`@0&k0lohhDfX^S@u|B%nR0-{F;)!!2x#;s&kx zIC@5VsU@05L)!)!#?e?5ZI4DB7z?e)Py&s(J);hRSa(DWNSf?*K4ADMZMP;G!umiU(zng_tLQ{Ym%8vF0&thUS{yi zsTZC?d`*3C`3x&Zqs*7>RhP?Xr4M82z%q#%oQ#FB%f4zx~di=r#m^~~gv;*uoR zUPvY2Y_E-sQxW@sb+64*fapH}B)+Tm;=FYbAn&0v$ z2dq!~lUEu#?Nu$-JezTe2{rw*k6A67u*uZ*I_mYN!|wpTIf0bN#(%7)FId8bMi}(n zt#}7}%r*6OTGzsALc{oT=Hlh_!q;+A-#p!(djg>x{Vdz_}FQ*W*j7_siV!T9Exy}31nCOUQhnUysQ zScmjMCDzEq~C$cEfkR z!@Vw?Cd!M}PF8mcGShMM%PHy?j`sF?F`*+o+?la;gP+D~yiK*#So;m?YIes6;sZ)` zZc^-PA2v^dk7_aGCX>kjf5u`z?}a0`$|}|}5^G1?Dc0VCMS{XC^M30Jb7cWr$Boa( z>w?5OUN{R(9=iYmNofI+F4Yw%Sg_zCpz;XDXNu}cjJJfR7In`ENRG~XN2oWA*?&Qr z{j-XSB05gWI^k_i0KMDZ*~xt8j^C?nHDyiBC$C;n0`e=-{{DW8@#2qw=_qe%#A~y# z4Rh{1Oli076C!T8#eQ6aYMV36h?o5F!?kCY|c;yjnB@ z#5#MkrX>3vGw>EH?vVg{)u$wUx}Kpy%HMgCeRA6X@D*G(^W0F+SbFq&in32sl$CoO zV_$g~q3>{yr@p=3dyCwl@xrE05Rr<0CH&V1ul?d&1*A**8^gIUh!6{)mhoT!XZ%N9 zFBAk4sO6gm;j2bYJge>%$;)%qMF5T z$qZXV%p6chBYOE(n|7UmLm>(&`MC?{*)gx9>V?ZeK~eARi+p%XV31FZyH~aJr3dT z1t3`q3l1ziVxxuDP=G3AL2^<(ORS4~TmWDv-=>0Hw$Y3$y^sDR#j4hE&$ZI8dhOK2 z=cs`S^KOthaX_azVsJm1V|o?-@Is+t(!@2qD<{>kZ4fa#z0y$OeAjoHTj5#JE8BBO2kr)aUst?p;|Nc4tLfWuSR3 zI=~N?qAnqqXY(mM*tN5Lmhy7rCo9HT>_Zq~$y7A;wn3ABiOXb!Cmso7T6uYS&q&?H z@dSnj00Y`Dci#k!8oOn}R+Hrs09t=7bFc%@WZG*RPCoK6lkX?a^V)g$bJ{aiUhfCV zO6(%zq1RD~DpwNH0~b9N-GuWZXPKL6yKy6Ljy3i~li`>kugpt>skiBk!Q|BL0jEui z)U{s7XD)u&h~!)aOt9})e*EC%J{_{r)753f$H%vOp$0S@<3)jWdC7gR zn1*dS&TtocfeB6?`L@=z6}_ zM$2b(#d+G5RWY-uU*q8OXF7l`%*x5REq=bJc=rgg5Pkq40D@z+c1xXVGw$-QOWwUI zc=pLKi}#&N)w<=cu2Q?52}ytBk${7NqQ3dv5LydOq+|BTm2{-GHo=Zb;@Hc@9ohRs z(JlEo`8Hw3?z1#l6iA9*L-{@?6)i?QCNH|QcP|*eI)pF%cPiX`&Xe+=KLOhX=>3Dg0S+|g-et?7*0+}X@QeKkqrWpge0DJVxiD8FG{X%e!19$d> zLCL^Y1Kyg{K|pQ_)6$ep@W@S{`V=|>ZQuJt;xeAL!|aD-3`boKF+ zdAFWaDt}o;`GqG_Sml#$&L>aOBrdLjjCa|oTSIjp2)Mox;UNx!bgqe-+s?iTGp4n- z*dc%L{Nnwdr~dd3PpT9CvZ~G0vHsx9(j~y}A8O&c(n-S$+A9(|c9G>N5*riEVG6Uu zNzls=eg?e?1%QGUw%nUce`STpac4T2-l`nK`_8jieHytaLs_3604(6HHq*pZ=a!T$ z^>b<4dA-SXG?462vpP#>PCUMLRI5D%eG!7BvQGc4*+h6ieV)1yH)-x(B$*`k#$bF$ zzjuTOp`!HH!{1m1yU-Vpq}4)j;ox+%)KV+>SuWtEBm%8ki-Ipm%RJpLXoexySeMEF zVy0Z{|1Pi9MJ@89l*(dh`o&Iq@r?ky={;LFlMB4Zg>ia{`_=M1LWAtLhKwlH_D6p) zTIMqO_2E&Gto)-#C8uZ1tifQjBb+dVJZ!Ksy00^8 z&E}G<0Mb@Qx4`H&FQ)yu>YVYOo#~0*p*oMo&aHsQUjysLQLPhU0rUX}UQu($eRGkl ze_hh;+W`IRup3UHS7bs2b*<^aF9b}J9o4>HSl1j;0a9J8D-QD3!Tm&)7m|RWwWqXK zT}|zm&72HOE`;WRkBHP~IDQa$s0HG1N>#=68 z-tBe(EkbKnrLwATeM{?njx8{0rqgLTe1hNf3a&qJqkQ*-NB`Y!5G8bmn90RiJivoX zGf8>~`y1E*EZu&;JQK$3!KuqeZdp8Fl!OgtzA)Wi>t!}1jqBz$rh309xnV+ z+Gh_z+Zivv)REoJ{F%)*jd=WYFqNN&uwKmp&tU57ru>=H*nyv~z22UF_!CxfK6y5C zX2X~QqwYH?`^=tn8E{`&2LXgyb`0p(ihB~p5)l*A63wOx9A^E>fwJmCsxauwQHEOR zwrY>TVblDGTBjLAk}hD7&=j|co0FB%3bGskmg;g7EiEY{*yli!7hUMMe8)~DKAX=U*b0J{b;ehGq ztcgL!NVeR4=G(0%d>|Na!~LNR?}rLB=MjdWU5nuh;Q6!|`{j3fuu^2yLC(j|UpQt# z$RHYRo>$=yH9}TRO>b|o+_|#{;-NwSaGVBsPC@Hw1zTHQFlgNxH{0!s6}t(`GG4E9 zMAUAc?D%p^F8BUWYvyA%zH;ZnxZ-b>3?}?jD=422iPlz5ls-y@f<^Hn`Ic#4zQsBW z-efF51q5@N(=**)C67PWdTim^D0lgOO8x18M|DI94ni+i@R{)F1=A2V_Rg~8H9(PR zm4i=MHWz0N3+o_M8JH15Co8*qoNwwdMU(P!!ApOAW5zHfhv zhs@7V8a{wJ7TTnxeUMuy(EFO?gmb(RsdXSSQJpL`s`sU=!s`(>b5#>gosaU!`!Vur z87K&l4fDmUd`u0B0Pu-(AzkFUE2B%<-q~`$YUZbX1XF>m-*ymY70IjJL3Kf!f-j$D zUZb0ihDkP@UthQBy)L{%JsU`@8*%w^Gnan}6h&WHdIW{5*R(UmxvZ(_mNi*qOh`CK zxpZ;HcYm$QY66Mxa_c>+-dzi$_Y0|M3G3>DUq(cBrQp74s0MZj{sD@hKrvx$k+5mD z>v2v#4AY)U9{6P8O$FqBp)n}nc|hztCiPCGHR9jwxn7crX0P>`vq628>GTl zU2YgnmA(QmzX840fEq|OB*z=jbfeFCnN!_jCQ65$%}AI;B8M_jL7XBYfqzQ2m0XGJ zb*COrz9-RKLa<6Gq#ubPlSt49b)++58cR?f4cr5vzY}dhBVKcO)4vDJT|+Wr9bUIB z>ULh|&dbn7?!&OuRrBb4z2wj2l3PUArXF@F{qb7`Y80{D%$1wf*bp)xuze32*awiU ziA$;Twe9mF*O2L1DTp|(Y70!ZHM0pe_cNe5Ux=!)&?)&Ol!IpOP|>X`LcdhtM_ny6 zdyoyKFJ%{vK*?#%sG3p8dPXYPcE^&$!akjacXbR-E@-1q%5JXnC^T^fWhxMLd=W8W zv4J_^Xy|U$9()pRbi^^PF{l86N)Jgsi)TUYbC>cenrYr@H&|V}$Vw zG7$?oC38@4CnLkB!f}XDjRr7WEGZ-{VA;o-h)p^<$bc`) z&N_LvYu4F%Ux-No`>bC{S4ZLPhNu1>w80TX>kXxcRGykeQjq&XDTjS$BbT1gGXtsve+f!mw!nK>8ArjI&W=bmr8`02w4`rV zV8IQlzkJ=}U}Q2wU)z|hul3GIbTz|S;%$YQU9CEcAok0^KLUnmbsFpGzz$bZSee1x zNeYvJ2q2?A+-d^ojRnk0W7A0#8N~^FtlE-a{j|dzjZtsNyVtyAqFYffqoHxF?}evi zabtx+y?Wo9b7Z8nu+-aT{;nhT$`=|iyT^TQOo6DmYW)CoSkH=UfX$@EaIVFLrp8nf`-?LPsN)22t3!--?X-5x}OmX1? zdCMQoduJob*dB0P*7FvJ0LK_PGw8a$j#%45Bq_p%iSO^Fel*!MabNX2u%7XEUiR+N zGxsCw<(`sSQtcW$U-0Kmk}A-$+4wsg9FWfY0Bc%eJ~5SQ^PC0BKplc8XMd6=qxo%K z=Kw|Flgha!*WINV%*5J*bo(l#RZx@L-uiPx+9`HPm!rR)wGk|j58yN1hab@Y9L~l1 za<8>vCx2JTT*y|fQ}g`oZn%%OL2{7q?(p*hbZ~tJ+O2Kx3zF*FcSF~M*dm(f>kQ49 zmuH!xCD=<3)XsNsqB&m^diR+uImfx)4H6);3}1F$@Cq2ah8fIh1jn$xph*gV*%&Sf zZEv`YiN%C8Kh~{S;uxS{_R;!&>89BfF?4PR-jhVdH^I+TXO9T@uWvrd#hFz%y$Av< zP5Lp*rZiww27j9LT`+{--nOgSFty;rHzY z0VbdK+}sKa-yfhHn=?-mdRsiXiA`LUwB}N;SRuvUKi5O}+h%Sk27NTJ*m2RVw&f_C zE4@L*2CevjE68wSzt7AHOq#H6Q-6gcy;qUBH=T-6BtP(j}(?7X6`^gyfB#Jv7=Lxq8HD&ZIs-by$4AG7a zya(s>Y(D(?QO0waMy2z@9(#|lrxh%Z$xgyFGl?N-UYrZ9agd)%WFdOJKQ-Zw^CwG0 zTjPw2B5rs$P0*OdRmIRtn}(>GALHF~n|stb?Me+()u1u=5==RYd4{pdG?JPcj&ilR z%HDU-H{dn9QJ?XAkJ|P*3Ut@NW>=!{Y)+yv;uWs0T>c@}he}vym5v(-aErz#AXpgI zvX)rh1Bu1?U~U!At_nI?+p?6ui+*_;LGj(=&%LWD9(=o%XQ(mpSEtuuYDF*0+1+P@DWPI1Stg%qQJQ=EC1oWKG703KCZt(RJqpSCj?N zC2Te*BL8}OyB2BXPt4E>_#uZrvu1wyyfx8*grDH(woSUyJ8R7}WF7U*dW~dN(M0oP zEf8oSF+FVb^zjAs6z$UgtZ7 z@nS9&zdqX`c5?L*uq--(M5gG;o^>qLNIx+1h0}EYH^}BZk_N z%8-);+|{JsCFUb3zdy?=-Ug6*`0j&ur4|_VpCe@usVjS{)J0fr;x5C!X>#dK9=2Uf z-UAn~p|p^t`5i9i?B+Tacff-RpK)MmQt>SxO1!jJ>TAW`DT#@}O>bIOyLT`wlt>0O$jk@$gXY~9kOjql6 z(N!zvE=>YyKoXaKzQ_TXqMbbc8HY9)hq}5t1tX)^l8S(Lg%P@sre7h~^S+SiB6WhIZ4MytKN)ySH+;*UqV(Q-S1OwdHbJV8i-vB|@ zBo@0DrHiZc5$81utol?hVV~{(cOp>AoD9G83(g_a#j1R~0*fyE!ZDUZb71)Z{I?P4 zhA;t2H^784^(03rZ42N{tC8E8PDo;yg_#*hE#238T6Qo$OpQ_SIY(R)W!sqBCUw$i zyH{z@VX=!?v2dA@Os3o(#3)B?5^|j9V(wC#HY#E(Y}a~03j zfTw|y@Oc%>bTE_Nq>kOWCb6H|5o(m;NB1eS0f%5uL`0etk}z+Thw*&#frq1cC>mhf zX+PgDUI<1W_I)ZN^JbP8t>Z|=mqu?Zi#v48hULp&PU2_EV&h?03LNEHd%8>y=^W+5 zFU*(wQu~0K4de$v8W#ox8X!?8Na+bMQurJ27`2n?y3G0M$8wP?9dB1%lR#Ia{l*m5 z^-`L7^tW;y?FIJn&lN9f`2|3l*PNg8(#Y`#=)Q$ z1#PFm`|Md568G)}^+_T_K+Ah9kTp?#{krqpqhO8Vx5`n5L`^XL@nW-T(3=iawj3QQ zn4iD29G68sJTk0upM*0huK*?)q?F0tb_)!Ua=Ch(FKF~IoR8!Vx^?C`eJI{5 z5Y-(K-;?q026;`%hjDQwxJ3qVimU;DUhs^}EFv@Q!#?QK=8>0=Iv&#F9kYNS-7oAU zF(AHc*Ol%jqxD&yO%8A89m4AKT%^1aEgS57uaoRBus`zM<>vl+cU5Qdk>VrcXQ<#g zI}B3imL-k(`BA;vRHTLW>5|W<0i9)QDr^!2AD&Q&l_2!0!q2}yo?D`VZqc`Kf z7sGP@8s9j_Th3J|Bb^vdL_(6ORc3X#J%wDPygeZ2-zVQeZ;h?nrXxWR-q(a>&iJL$ zDtC{G`1~ft0IP$CZKAG!@(z}gap*!=P$G=Nv+B`4JLiwTJ81y&42nsk+j(`sd?6Mm zJSLA%#l^)@FB2Yb+>=6Mo}eyZvMKJwVYQwv+lecqD&;udy8SifCn4@)wFUE@yA2ob zjRuU@`v2IZi>)&B3AfT#uk$5+6$ z1=K`%JrFkEzI_V}4K>~zEfn8trYK*p@rRDYz5ovE|6IRf=K#pVGKaJjmep4Y-~&+NjM@WhXV#yJ1aNW7%*ey=+&hF zPaXqN8X*t}C!I3D%K_@gKrLsWzBDWAE>M^O<9{=fr&A3iXu4CSQr)*JGRMpzAsTS} z^6(^jzI+MPTPQt1t?YejQ`Jsw@RXHQtq^xxOLAhc{n0yEj)a>&Eu4yk15GwvS<-46 z9^cb$bqlOU9~x5xMUs0phfRF8n#$WAd4~@v{=EDyWQ=zAuDm8V`+!d|el7sSeZ2Og zQg?x?Oth{&^#{6H`v(WEdo9%ANTjf;u~&f&z*QNTmY(K@&jX zpbfH+Aaw}@(5SAgI8WN*0hu-+WT*t3FA&(HmGTk?8St% zFw0DC1uxbG0Cevdk4937{nni&*V9jcPV+d3%{}l6z`IUhKA}( z+5nFw_yh7_DL@JNZT~lxl|Hakpk@FR(t1H#xbOlYT-~^8suz^)TtF%k1JNdhY5?hs zu!X6vJsxeYr{R;_*)b9;N6VqfsE&ESU@q=7Z8+Lp8phfA3g?*>PAZ-^oJLCjJ1?oX zl&(n9qQ*aa((b455~gVVoj7eDzyt#bH6*sp0p}dd8>EtL0pHL4F)8z54p3Fa8p7Ky z?d8Cvpw0ZB^U&Kd(@;NS__opz&{bIOe1L$ z5)xJ}uCU0+$OX~5|BajpQ~zIPCKPX7kE0$Qocj0{=Zt&+B3aD&SDlsrZtT0@prHBc zgI=+`@kN9{()GN<`Jyog7Yf+L!kPWimu#`xF96y%4u{POij?QBXO4y1iVOCilfeF8VNO5y(;%2XXnBIrIKK ztSRQBEliL=XA7dug6Q}14gjShX5TI5*Sh(Y|93n?H!CwT{6VaHkDVQ#ghc9Q31IUR zaM%8yC1)#u2uPe6?66rx;#Gwi?ujHv*Bo%cGInjI*VO%4yQJ7ANbt@{gALYxpXiUD zu?%nRz?96wmh*m&(Zq{nzYrHn9b{khO3Cc>j9vJ@N(TNdGOt8mT}7VktNiO-_I|A7S1)m^q3W#Zdu3slq2mx3eAeOn@#a*{pi`-s-_`zC&C_MlhV{U0Q zTo1T%7yaQAf3-aAv2{GyKZ1o{UlrN_2c}W*sX*$zu}GI_POOdk z%_t}FYc8JFJp!MWR4>-*%5jiPRL=w#j$CVs6w8Zs5~kcP@{syR z!SUbK`Ipt^%4=yo0G9x@wkDo&#}q*Hvm%8Sfg_rj!jSGl*Q>xa54s+ImdKmK!?a}B zsWogPj^#Wk%j!)QD;w)*`d?%QXUo5vo3qI>{orI_$!OW$f)NK`1vK>=RRPJy1bFnr zAF^ueSBRds*yjC_WR;UAQVzPAPfD3BzUC{)u9vl>HPz z({KyTU%apmArwI?HA@!fY6EDhZUFMB8lWEA700~-4l+x-5Ca-e*2nZV8_Xy<9XGMR zXhwkWgA;cZ7z$2`kOc-4z_Qi29lZg>SCA4d*du}>W#Etn{4&K=f@VxF9$+jv8ai|A z?VYo)iQPTisq)%AVo(pP!i}B0Dv7?$h~Cw19BI|(Frj$SL-!~;_T^=^aqXI7hw(7r z*?ktrwe+itOKjVG(&c-d`)(T(yn93sK4pZ4SSo5gk+5>mU^DJ91&ZW&DN<0Om{C( zGI=(WPQB|o_Zl|veGqUHeqFeFS~t^Z0PhQ#%9s|P+k?Ng?~BGrN?{zab%eZcVEYrt zr#OdGRnGS4i<79>*jD2>omRl45{`Tg0VA3MNZNP^A*Dk|<+h#)1yRrdI#!~3aIZ)Z zceVR&ztWQ!&|%bQ#3z9N8@wt2aQ(j(kfX-EPP_CXladqws4Y(04j)jMz(C=452zmQ z0}4tyZ!j}4kRbL;#6o)AN65!NXE;CUK}J><8w6hfd;^pF|Dtsm&T2CWsE0ts$^+m<0NV;9wXVxea06Nah_M^sd;Ac@+-H$t|t2PYEV)HHAxl-*h=}0LS zsw*3y>AJrjq0w!b*!19Uh(>gC!UqLn5h##XQBi@)wFnTj^AP%i=zb5(*=J6z(p|uL z=#{_IU*&9FYBAQ>1klOA#RKLS5Gz7Q<@xEsDd3I?3=g+Hag2(LM1cQs0ikQfZX*GJ zXy93u(P#g83Y=%fcI5`NiQs3TZeQIBG!hYj$PJ`E+-Z39VSr>FTwVc_N*{>2>%pz( z_vYrN-JAPK*R3upo|Jo_{D$+cyWAlwC4Mc18kBnIN(|GZf9Tq=k=ng`5=X+yDS3am z;4=9ULBX2#`ZvMVt3WpOCd6k0h~yZQW?ozIC1{jcF#zbF$k!QuFqa_Kj0T_Lo|XSi zN>OBc9Pn8+KoYFr<2pI=>Db=bRP_|79cv7#xc2T*me;@eWwT{A;-o<4=RTXga(<+5 zm}f4CYm!Hk+=&jcn23a5UOVmH;kyx30yqzdD70OdVgL+r4~?2Z8-lCL2R}bv5I)9o z>oE!+BOT1B&9Wm$X0C|$rSc`osPn>9`7%C{#|-d3%JI0%V~(^>dDhNb8I?lX`~9`b zU$N1_tKc31Sc_aiP_I#-k8yf>O5^{&!|2U9Vs8@Ym})!zc?B*=c-i7>-#i2aqPa9N zy*sQ{{6aiuccywBee*ZsnU6iLRGl*^EYahOZ=5m#p98OPyVh?|8usI_rHE?(#ykVa z8?fqtCOB2n6LK!lXBB`x3Z9aG^%%oLbaukBl5KDkbx`Sl!cWAd~$I!aI4m@LPOV|QQqgvk3NUIt04K}pj2 z&fl`q14@t|O-=2CWWB-Rd6$c88H!txcNP{xG;kpk;J3AfFEy*i3hEl&mx?op7&)$$Ph5dkgZ)&k&%~GW@El_ z!{=K*4k^%Tj@YMoQ25pRZlM2-tiZbi%r_oANb@cJ@cYT*ovMl*rVV2JF`^%7$$bZ# zO~34SCad_1#w7Tidj%Yqyx&O&xJe#bQYr0Q65RYiDs$!LQ=K0;tGc?nkajbq6AU=3 z_6`SMEUc|{07hR|Kq8o>p3ex>r1gQmditM7${*wB7oKRG@WVuX#Zu3hFzO%eG}ilL zJ*&lvBWaR6C``#oN{AAE0TI%29H>?ks#SHJ4z zN&Aut#zf1sNH-E*Y$LilWYHn#M1Z4(@R}m9) zaavp1p`*$vf{Yel`dzU9b%!cqX`3GXckV-6W3Bvy`c3BJa8r}88w~QOe0QvKiKJ(x z{~3ph36=vvvSORW$z&768x2_10O26l^UwDmuszb&)&^9XFJWVuYRHPEP-WUO<98)f zOb?Sz7wZA9jYa#rXGGl8txkDb|5@kGXg;PdrYjp8U68v3#5-dZ_N>66aBgvZwBtG$ zxD#1wfg^qDRwP<4?k@ewnRM%CDf?I}1y@7q35>^}O{+D+J1h<<&^q=Y;}yl_Onm!Q zL1Zr<6GF@&3i#~;2Dbh0uFR|D`f%9WmDY(N-u!xjJ=>oV9_w*@*fV&OpVphQH6=-@ z=utXmy8>Aauinv*T$!Dz-^?uH$Q-5Ie_qdMn% zh1{v`ZfG``ZHWD2M!WjT?my4GkN^8oIwi6vbkRmnNDyy5%qdKKa&<1!67l<9c>%Sz z>Q7vD1qoZH0>gEQ&}XGO|JoPy%;tK(wmHq18rD59WT_CgORnoEP6@8u$ z7NcupPVdScijS2@{;AP^n)jbCvqE2fQ%CeC1wHVz0e<2c{+92X5&bkT6FE0VLI2Qa zOHIxzyEgMbX5H>g1L?Q!D45PmQO%ByW;EjaX+_j6DZvoDFAqzI@9$f^v?FSh z1C4YT?XrDhat9sWKRoFd)-|kHU;h2F%ry#VoD}Fm(O;20gNY39wjKo)ovxp@XWV*L zIu~l~&Bow;r`0`B=}&o41}jO)Pv!qw798lS-=dk1C+Iuo)b592dI}m-nZp&=g_vD zuOXk?9Gx6>%JZarpw3lbeB_8NLD28-7nj1YSHG!rNS2KM6eGvjwK<%vbvudC2BZi$ z>cm(!8h@6=RC&UVovJ5a{A+_UlQ+Pe0&LB+e-$k3^*Z7ovVHx}<08T11_F^*0!Aj71torA3N^$vihTvGO;7XsXV7?T z%gD)*&!WH71zJa@B1|hsxGVn0S5=f)C~Vo)Kc{XuoDYd(c}qH;kj|hdN zPa3~cZ|rf}ZKNo3vh4Z1FwX4H-|vvBJqAy!4zXW(JY9?Bjm^Y*JR*eG9xmuvY(#h8 zq~2d0m}}JD6*J-f>?bg1pxW00?dCrs zwZH1^c`q>am*}^$!M*jG|EzzbATS)i*qB(kbLVUfp0%w}w@hGiyRA)yWkuX5+^D<< zi0k$ft3W4#{5S8}w&>7-JvZw3pZBHo2TzrGhB#7J*xQ3`TIJkocpi}GOOHiQ%#naw z*6ZzH?{3hlPn_-MQYE_U5$=CyFy)_}()bDNl()7s{_pzWX2z(Kuec<0+ZveaMcfP@ zJoPX>eX}>nv%L$Wa2IGCeDxm-T6_-d)gYZwL}vXx7Az_M=gJHnI0$xGnu6uie9DG92R_{Sai-2&EEFfU`REulBVN8ljpHnjfW%UA5>n^I?3 zvM3Dc=sY^T&)XQYC8*~%1##gCf8TU|__iG>Wu!__Gp82DW9MIn?)>(4Cm6{OSIP^CjNR{nU{~rzXV_HaM_~Eh^K)mzEn*UTYvjHoh|o5 ziyCeyCgp>$hixi3{}Ra-ICc`%-I+;4OpyOQwq9yLUuC;M*lxMXdY{gKr+ph-3o84H zASf_ogt2Vmceq^p&0FosNryudRL1%52qA~}X&}s);P-_iq6#rs<}@>J{Z{pgQ3kA_ zdo)<}Ckw8rM3kG*JyhwxEBF~&!KYFY7gsC8TeW$gmfri@&=>gF%ej1c2Z>;E)wZ8V|1wU!jp(7d3Sd@nC#T_f|q zM&kmFhL!z}Ur68;Snufreze%0-SNF?xo4<>Kk#7rlM~qTH6A(tyc!N` z#D^@K0rUlRH0BLHY59jc{w*`@si|f!>e^TR@ZCj+vt?2yWc zTlg+v`ZYk54g@@6oYb2+LEGE6k&P$Mo`K?TjFYo0{wGguk#?^<7jX5lv9b9Skwp0c zntNpyiZxag&g?I0#OZM3pN0|yop2%Jd@sgs)taJWHl6tI>U${0-j)%6(ira!BW7^7 zX>OJUNa1HyV$4j@Dlc>?)SN4E zEI^7IPoFkUfz+>9#lt-2$iIWoh*kmBXONr@3=X~}AQ1EJ&(9dAGFdXne?=D?3i+4G zW3RqlR1JC92ljJ211zccXDjGN1e-F`Qzv!a{9)iz=*A0*A>gZi!NJeWoaGl)K^+9- z1BAuIy28({K0UTwx`C{CW9RJLHaHk%ztU?9Dh>nNVRtc4Uj|*hbAiC$a{VCHl6b?a zFEo4Q+4GYx1%@uj*LHti1Y#;ZjfjsA%*@QhUIAN5meyUvza__otgLnVi z=zg-L_)QVzuNr*itmV={as2Q7>*qE1YSZ;QVY6C>LMk>H=;S}U4vu$IjtG>WX#6Uf zn3#yOdjZTkFsN<+;vR zhJLe7NpP*z&3kMW0PN1vM=m7?vj5{RYNW$u%?~J zMVr44D{%hRk4(+rkdQP`Ed}`p*zEfHQ@}y)ezI-6GhGAHX+AxPLJM14$vckY6B87q zq@PR^fXvAJ!UD!yP@c%zyyAI4&LL`}d1r z%cY|ivbrrIk`NtzP3GZ4UK&E^3I(MIq&J8N2^T>r-BnU9>^gpYrVNdwhfAI#R3HWK zgD)l~2I?A5K+a|)Uyl`7E$C&61bqeoiU7*1mW39G9($;Mc9DDuFk#s_HzS_Pa|QBPfjq85m)QRZ^(hlA)fj>n*Y{2O|1Y zkO+fmfJV+lA#1Kur@?^%4bWBv^Tj1<>;k0A`yh2mMn`wG9x4m7=U4kQ=)>wKCK7>^ z5|6{G5)AMr=NQZ8ZT?bGX%}{<^1dsz>vYo8HkSF8Jv7+IPzr-I`v3@W$k&Tk>s-0n z>BC)j&Zk$Vswrpm@f=hySa09{0DknVxJqStYq};8+(8SxF5KR{d9%B>ck{-LFVf#h zK-@T~^aIPmdwZ&Cu+XqgyNk(nk!*c9m!KY$_=0k$K=zcBo}Qo{q+{(k0sDB(@#HY+ zF_>#ioAn_!(7&i`;mO_y!uk6%++nUR?uCodsA?gCAq#;ArZgfZm1S zeY&-w9~7W=pk3t@3U)*hs3cEJsw%62Z9#tRnr!ZCy9W;g8?&NMzGSAQL5W$|?|eO} zY-0ye27vY<0jL2s(CMgESW*MpIbd{x7LS3i&s&O!h=2jds#4?Tn7#3KvYb~mnK=C# z_)U79DksiTRE+uwFtpYjl+QB%o}hC?C+jYfD|Snw$=uDU5(@ro_~3zL|W z0zI8q8-w#GhpDF1>ArEEUY+iuQ(uxu({Qd92921LMT+qOU1bWOsz2L#SGW{h_^V39 z*F9oKN~)ZEU>>Fs_b1}5xUGG$sr0iA*5{Bb>%4pC4i3!O`9x*=BdN?w!Wcg3I+wj~ z$JKH~6JzB?++Dhv1+|EIf@qc1BR9ElM#~b=x#tKwIJAzN0jU?w&gz4s&(^^q&7|iuHXa^7XlmxtsWd7{DY=kz zJA4b43aA;Cj%|ayeLRl=CUA94;Cus!Haa1zZm>Z>6T*i-qIw>CIA8;cI<9{LdmS`t zwE%i}$c-o}Dh_3x%_)Huo(?KS4c#5LO{NI-1$?1f*ZzTCTk6RWbQLjJ`V znDdS?#yw`a50~AyWypNC^BAnXbLUPob0Q`Q_Z>c5Hkg-OpVxD;ywnW>jqXMnL&&V; zm%2ZD3QpB2;v+X~-MUp!P|&C?>m(L52;(EVqfUTh*TNeYCmMBic8aE(wZ)H&cDO7D z0=#AdpwimfYE&P)8OJ-7y&u7XeWH_V|Gls8QCu9ya5MD>NN}#{>SsME+js1cym|Ae zu&{7OX6Bd3OFM-Z#?GPcNcbizDR~97-*Xmz55P8E_+3xWO*j*$@6O8IoqfSBdHSsD zSxyxIO_s*M<}DkWNPGnWt+X;N9)LqOTD^Fq9t3wEIK&SP4Y-G`ckkY{ovK&8c;P}R zwK7E{@{)h#fhXDZhQgej&k+N^|M+na*M~<|XXgK|p4;>DM~?$i{f+PUG2Ek(m6Zkh zd}PZJt;e6Ql{IvDKV5pq;zB>WeyhGj1WQ-Y>(|jjx2>(I>PP02e_Au59y6Xvo*L~4 z#<>_8T!`r+I`#txC=g;4LV9B14f*Wt)IJ~A79Z?3W04cd1nU}i98IqU^7Sn3Zan7> z7J-MmZZ@s?8aT}Vequ$Gb<`T_>HPcWT6ZmSQzGXi4B z8LuT1lrQX?(#!FnY{7w-R#bfa@PRJuOKDSzp&h83S#U#58Mnf0rueXvu`n?6e^Ex} zQ(n01j_`TE{39{znNgB%#cZ+c$R! zM@Lma{)am&(mP7_3$9x&`Pyo7gdO+{r6e7p67$`f!}Ig=bQ^ZY~xnZKzH3z^akV3{ld1`>8>#nM_0T`JtqI1Aw%|O5*6YnxUy}ZsHp^ZnXG0 zO12Yr;#)8By&fJ#;2S>>R3A4_Mu&;x1eh;Yq=Ss?Y|l4u$^fQs$Cx9^i!LzU`8_sy zo68+e?r#(qR7bl0W%_G0j()5$!J9^sADuW2}Own$p{Hgllvb zlvliVwht7%hfcrNDlP5H4x)B_34r>d&;_XV32Ls>b&J82h$d$m1Im^E-g&R@|rf^4+{(X_G$Qcw%WIA*RB}_KUr|( zHe3#Pa{R3FSq_zWIak^`K*gp$WJ#x52;3gwRPe{ZW9_#oK;k{>HaG}LqX`c*CdIHi z_WAR*)?FW0pERi0M$fi#_Wc$!FVdJiCm6!Mh z1mdt1V}Xsvp|ISlsR?pGSvgio-j#9fTBQ!h2{%b;X{Cdn7q`2KTld%OIceH_f{IB? zmMKtm5fnho(ON?lCQUHNh($x@rIVzp7%43uB^#_F9wtwIX|iAbr0tjUY`2Ak*S@Qs@`)jwi&j&^d#aT`OK&CU~*e49h=-n(aN=8kZyO;c7? zB~uwBq=^)NNz-O(PFiv8pKZ z*N(^3)hSKkEgimB7($tXRwcHvQBD8Ej)^vBgz3#85d2=To<&}YFdf3qjB#0-mB7OA z_VbHz{{4NWa)QQ5`e*>>ale1t`a9jeeOndXQ|%mxvbtYCN-T%XB_t%KpjL@NnZtqG zft)IGm!Xf7zPWi)yYsxM_2QhhK7JUZsmjPGn?sN{QX8I)zhgNU6cofLS1ma4{96>R zX$s>9?13^-l#`G+YfUx8tA~+t66eZ9I#qExty{hNOWFX@u*QvG>3PS+#nCEZ$<+tD zEX6p<@ZD$(x!#bNkdu>hW29lYC7lDIj6NC(BL;{!J1z_^0QF_w9NzBk?&H(bDz343 zo_B;re4M@y4=1qf+EowjSk#rPSE<#Njqk5golQ|*sV*Y9_x^Ts#8WrLXik-YWK^xO zQ_A%1h~t7}pC_(C|J(A;c61h!IIlUlC-l`=Ha`2v%nye)%o`sj@uaN z-%FkCyvKA{v_4w?+;+E5g5?MI?~g{AYh>E7Ku%stowA0cQgjhaDK`&m5q8cL(qHuR z=g;>h96~9~B^u0|81rVMaKso#_H@#gfRYNM@WI^4u-L_~r>W!BmSTff^;NXy)xEUo zn@VD0Vg@1JJbd!x6z^nwmu8lg@r%)wDB!!C z{{%ISit7#`d#gNOEQ9)Ym(S5hL$_Sfo3(Q7wh+q6%SHEDk_jJCg%IZ=9b$TrQ){3+`BcDThN znQQo=&gnk92_Xb)ia7-Qs2MfzE*6&S4t|U9`s3J?S+rzJA{VmN%z@(7rjLedt5?Hd zwZ-D%qO!EKbYc(WAj+u4cxOy-Hs|J$H@v2?un@A~>PXgqrjl+m+??stH#Pg-v3KIM z0YutYt#vU+&5qqnAC2}yBf;M(yJhaDsug+I*mBnqx@YHfj!3<~b2QHDTx*J~{Eh4DH$kr}@!sjTyK0;oq-8jmIKn?^RJDz2k&Y z0X}d$zr}uhCS8bp*p=5Z@c~i-Hv6(~oTpeFmb{xG1Q=^;)Xc~GLJWt5W~gkMij>vz zU)q+xuTMM>>1)IH)GfI1NpR4R*3Y2?om_I3*Hs*ki$>*pclUkpzqn0UFFBAKs5G3^FY|IV{XyI@8ce3Ar*XWh zCk`k5@$+ZJ$0wUCy?>33gmt4rY@=bhvJyI5p;16 z5L)`O^ZC}SU7PCXZd~9>1D6i&2It=-5$+iR@A#%ZiyQ+Bd93&4mQbxYFB*HCr}Hi) zWgq5ep=xOfxL)b;JOOx>*j%zk+KuhvVSmB&W_11y638}yB_AHHE2mZ%ov`REprK$k zYUJ!pTxjX5!ZzKK*F`e#eRix|cBB)H4CK*`qNh9h&U&5JE{+}vvBwIQT*m^-R~tvP zxgAfE4HiZ>aj1kmt5&C(HX>Ccx%>+a69ZpVptS)B9s(7LT*37NscwuXj=)1w`-*th8UIKdQ$ zU_a7pfbfBSRo!W^*Hm5$jj;Lf?p{RTCe8*3Lr`fF-z}7&r%s*fK3t2ATr&+8kLQq2 z5{|4{wTcn~r4)LE9`(pm>1XuxLMpG;0Bb`v@(!9bjB)v!%zAUE{_ggaB~SY|a={aK z_mXSJd)Oc;ISX7RFE7v4?o&uc#wki%?W~5?NNdw|*F2YHXVc&w<$OdVF~*t}s)?ax zvqt$Z+ljT3NRxaN>h=2MS$>{vYg6(47o0YQrYe_3f2gnbMml`&G;ia)IHii!;t}^; zK~iAIVZuH5ZgPba3c%ZgXja0lX%;}9<5cAzU0p@!?Vjf3jUQRe=jgv!wc*E^?@?+k z`7FmhX?}}!+*?s`@!rD@;nb#gv@t%cq2u>zrPrLFpl>sTKN@M}el}B| zA+6DL_Vr01+L8(t!nb$Z?|U(5w(Ofv1JhpotsPfQ?X#U(j;V9Kpx4Kq{27Q$`@(;i{^Ceu60V5 z93O8^a&B6f&7AI-*;KjxPD|bN!RXjw?!We&|IGH}d#ATNfU2>nsRO4^Ys|}VJa5@` zO(St*J5HYZ*`7O}mZrU7pZN0-U_wM9kK?|QE&F6pe6CuvW*_=PH1{MbqYswMj_c8} z%Xkoyfd&CCAL3eCEa(}D2NBj3zl5B_+@$evSxy;mgr<$yVyjPtr&N=7z4K~$t;0Qn z{d((b0H3{3c#6dM-fqI6Kv4T5dPLit3wxdkhJ5Jry z%bS}$cy$v0~+qZ861a7}T zkp6}4F06K-G0#b0&z?PE8ZOguEj}@xW?M)R!z(E{9oG&4eY$#8vUF0z)|SOleX(gr zaXYT+yaZ%Lv1`}%BeukArsMRXxt^@904F6W8)s+dX3O#m%qDo4O5tx_E92%JM2GLay$}8UccSD!3e9FJmPW}!B)#{`mj!rc z6r$5lIN1EI7hnaM++bL@qZ6qMQHkN+9hA+lfmhU0O;jN}^SGM#rR=bfgX``Pj)k%5 zHoo3wN4`SGv!7~P8NS)AH)e%2aK)^ytq`4Km>mb3)k^mhjaj4vj)n#09MKW?Vi z=Y-VWlbWgrClvCXodEk3qZz%kPz-85QBK#?PE`noF(M2V#!Iz;x8*Q*r~1rRa5&j5K}!HaJ+>YtVjx_{D#*`Tf;L z^$nWT>k-=hrE$(W<&u&pXK5y$2xx9C1tpSddicDZvN4cOU`IE{I?s@UB}X!TtOxJ} zW(L9PA(_`eTH3pA57WAJ^~o2uT(flmOl}7+7Xr<+x3}-d;O2%6$WnA_nHC2yce8n9 zt>xvOiq6C^`O6zWYM);9s`vi+TZz_99(F4!_cR(lHoYBR8?))G7k4`2Zf^yR7n=nH zviBaiZE0<-kNTAYBj=EcD zLb7O|8w3EX1`8j+s1$%1Dqm;1=u_{!MMS9?hN~M*rKGX&F_295p;A*<--_ zt6p_-0OSO=k__Qef#5C`d8A~c!WO(-%z@Y5jofrdW~}BM)8_e9y<%f1r|{ndJSWHO zLiIzLxRr%o1m|DsJQv?b(hp>W5v?s~-krkJh#3zOcTU;T~; z^@jBR)~oCLBi3HDw)7R5AcqO z@I@~dZ(-4`J*p}iJGL8E(QfEjbI@Vex}11f{VR%Jl}}yETUXfMUugJim?k4Gk!jsR z+cRqZ*;VqbXv(>R><8Hg8IHqe0pt#>>h#a1u(qeYLqpF}Qh4wP`v#(d z4X}5Mox8G7sGvf>eB7@eBm!_#+|47zfH9PmG`(wUkrS?rbryn`&^x+qYV8_ky4+20s4v4(Kk$ReqZ524q>}&zTW#FedwX^CB{82{g!GjYpK598B#5&aM z1%S8Ek$Jp&RVXl;L#H=2U5>c}9`klV3RxM59^?k`LwL#ZFdsBEyKQLLccn>Y_N4Wo z5~TlYUrXr!o}D#rnFJbU@bU3qWc(uHE0WDKu;Q(fB6b^-lPQna*2sUzWnd_wHPGtF zW|r>d`0KmbjK|Yi_e?FJt!KTgX=rF1e}8{O@NQtnUEjZ-LCQyzJz>`R8thB}Hrp6M zg$cQTg1ueH)ni zdPo#CQjN%*00Ao#WPCN4v5ygBc+6T)fx(hO*9C^>ytufBm)DAdo#r`cl-JnyzkNig z9{ecInZ)BCXv^j!tOBArZ(r+?#|Tf!hSj@?oU+aH=g3GEupttwCIXVOIJcd)Vv~5m zav3|cE=e~SMERt>5UFJ_jK(7D`1;_bH(oY;QrM`LtJbZHz!qhTxCzcfzubqMH?S}_ zl%zuUnH-M_oW+ko=pgmK7=;7=B6I01r*3xo?BjtwX9Yn-;UmBQHVTERQ%#8b=)co#58^UO7J;D+5h}T8`~8G+Af}>BGKU zKs;B+KY-e(HM^AAhUz?{U+MDkkjEArd-f2>9@MXtQ?oDnWm8+t%N|7^A3nG>TWL(; z9M+c@JSX(~UEiZw-8;v2wVSWMs490_AWJ_-HvIEeRz3-v+^=+pa$8+=Se|ADi#4gf zbPB)}0up?TW_qGl8=D~!EnK)z@Zm#P>5THT$pQEXE8&O z^wQi@i@4J5t?rIY7kj%o3>_Ud7?0EIUGRUiF@WfGL(gW}48QT==n8TeVZXVE)vcPH z5PEb<>MIfgKN2I>1*!^2L+-ONLywT@Ep*SJ+r=`Z&tHK*QpG>G@tlKjeC}HFtwg{u zOT`u@OgMHkngLh4-a80BwF#Ph=!G8!2eXnX+WI*Rm>y(xn*0m#WZzJJ%W6+gPguYn zK-M}0NE<6{0t>u7F+H4+`@mHKeXN)&wvPflt=uFlNK=3n7_D+CvTSpY;;&Y(gC9*J z@hAmu(YnS3z3kE|VE-06T@c|yxiD`0DeD=ProS$P(c1BubAAY6-On3?PF@QaV;XXX zHfl^n7LS)NL+FQg@7{g?;X{Q8$<1+7OuGe3aj~VClY0be4AmgoJ}$K+`7j0q$iv>6 z4LIa{D;Rp33FepB$!O3_%CoHoiZF{{?vQ_fLC~^dnAllb123f~eAHun2fu9z?FqNb6_V z9%eW%p2kgJU){n3B?Bo~*_JyyzN|y#(+S+;G6)SVyl4^x78Z<}k`EBFcAvxxuK>PK zEeJ-vq?#V3OZ*;+9#v+|)fQ&z%V0Z|ww~e{$GZINI-_e+_NH8a24)A{2OC1;A;#$f z7)qbG@9C#&$2Z$%OKmLvsv0E1ouEMtgOK?oqcryMz4RLDbuav2YSN|0ZM^;dhRv!_9-yxP8X*~l za;7w#zsKEC=l+I>GogRUABkWs_bU|Ym^0rNY=TaD7;mP3<=H)z0T;R@6P8$>TGED?oD-pS(vk{K`j>bF;t29eOKcZUe_9?{ z{cNn^&XHi%nv`U{>a)Z7!G@FdK}`8li9!FNg7+l};-W~9<&q_Y(pfcWl_-E z;p=aG|BsGE;h_8zw%cD{bTEfF^z0LL7hWC3OB*6c=Vu*xgkp2rHe6fp$>cxc&^?T2 zp++1DU*;=*^JRV2yhr|gbxNCqb8^+qBm1w>)(Djb59%B_@KyF-inIG{tH^`#@D7rh z^Gk8%KgHKHWYlf>j3RV$%hK$ph1Nnhro`KITip8p{`~zP4V?Zx+^g0_5j#fdgV0{I z$rwsFRnOU}&N=Wy)AzFO+NvR0zu<;3i#-{y{`~^hk;hqlJZD#hVtoDax+3+_8`*b1 zuW~u^b!n$T2djS7x{?~3JB=*^lCg3ByaM^Z$?qI6WVme>Sh)Dn{;|kPQI&f-oPsxm zyN8FZ)_VV+Cv^NgZaOi%=QW-7?V%O7vPJ5Hmb9n-N<0`zR}=R{gl4y$mK{QtJSPE3 z(egm|qISn;wfrlm*&g41tJ8z1isFad9zPb1s(o8KfWa%aabjllP$p{M{{7*lLx;@| zPdIFikiyrPMaOe~U0zd@WPdifoQrl+YGr4u%!Fmf-@=bGZWTL1-YJ!gJGiB(=G@&e z_#QCO*OBX)m>QSC8ix6z z3@3I&!$Zt6R||w(sAAKW~W&PUYv6K%VlS}kT=NCA(|;D%`6lRL+4#O%Uc1@QBb2i^X)ru+rjPghA$>|sy1Meh zT7AptC*uBo2{_UF6g&68-A>+X z=!MBJ3JQ=O2Zz=&!Z?SVxrctmfJXw9eahk19Bz_pfoovEcPBf`ch)I-F;wr>Is&X z9#q`Q(aS|EP$ZIm0oAG?T(DWHeNw-LBDPwMwrkHXSC+_3{}4>te+v*RVU!OAJ9>aU zQvibpa_ZO2Oca`Kf~d2V2fR<07Z+y$IonGL|H{gB=H}+)sB@^VuB239N@o^4fE@@a zqp#ts!PCKey(Z)g9Ws9jI!d#q5v1M=?z@G?#>XM*3?$f8{_>)GMMZ^H$v~x-0xEtl z0DEBBL4$YWum<8QFTw8J*AbHA@v%NeQDWZVC5nDHWk^9ma?{fC1GJf_sm4Ij_s-^l zTO+(XMqdh12SQXpnoZK`#;ue8%qAa$Y|bHCTvFm|qpBn>{%{T*CH@xAD_h>#dTH0X z>+#d=O=@lLQ~l<88~M`KaQ}=2R~!*(7ab*{9d$kbn)AY~agAeBI^C*gW>VN(Ko%=1 zD%OMTSH6CI(6nE@I308deKg*gudOEN-v^H##T68Y(zA(TgqNL_m9?k4J3N=yWoZFS zu>0-=%1O)t5+>MBLDC7X8~opf@dL>EsmnXpGEiZvp*59k?h66H9|D{Wg{!`yVN|{O zw|GA=%yok>Tack&v4RZ^*dLC3Go+0_AhnD2X5}$>o_0huGdr6@RkeX7DNx8E?Wn)N zBj^u7EO)XDO^uDooeq?lcX_maR~@Q3%epm8ObzX$WOUIamoO5vUeBIAJ8jYZ7&Q1{ zUS1UtdxXfQkH%&seH1+#woXoNuH}snmI7hqTczt{tnGdK|5t;?mO6AEurEg&3%^DQvUu zXoAi3fNb^7oNcs&=p-Sp#NQN>qlUby_S>TCwjV$5Cmks`Z$8vmo)>J6;zNyQ&|6hU zUOUT5-u3IyR2d|Q5-#Ye45)cMJZ3Q<55gwxonBN=Vn-RKEP@v9Gb$-Bmx}AaCZ2-A z@j4dcbMdepr>%@$I0Y^K-o<-EEy(2_=V)8AL!5SY8f_h6-ihjGc=SPbw!@2QLWfT| zX=hr9;Rz{m40U#fm@4A-NJvOxJL9 zPQvDj%l66h=K!PUZEjguC_pTxh>BlPlAU}g8N24{cfd5D1vOCU6qQI!n=d{^Z61w+ z)>PffDz*9D<$F7X>{GLDe!p93-Q5u8E*wiyhDe8crI>M8K=9;A>gLwQcgTQQ*u`d-6lQrhyKA?hjQO?!E(lTX^e->IFsx=dW9GC?_WP+fo3*e z%tnaTni|dQ+dbUf2(4DCrxtma_&?<%VRjFVeeoe0`+@fhrPaITPMtp8 zYio)orkUwS=(~m2i3$-L+$7g2JGuy&KLsR3H0RL6L2MHRB^u{hq_F_bMcyxcik#d;$ zIxbi0yDcGf*Skw!skD%AOXUdTTd9U@@#Su#Ki$m;FO6)QgtR3zGCgW4b&E52A0}r4 zxh8rm67Tu5+8O&d*U`rC>UQ;SYmBuZWfrA@CE(T-ee4fHEiiUkc)yI8|L>;5Z)@AI>x7Va3g#=9><(+abafJzHsYqWacnt97}0CB45x**$A$m}eh3H?YI z$|VYV+w2~vMzQxqgp3e$*)kil9L4OJ*9pL7dyOed|_Vt)!Wu1}2D(C;;ECr2xnTnNI;YT#2g1T*@E1 zSIia-sPubm}q6aX$4^OL(o| zQ6cx!cFu|$V5HC-Ollolz=&VLE?J8^2eC!d z`=c9G*{7Bkf$C{GIyzIca|nTu!hFEfXw1HyG@aFxsgrc*)TzeaEL>kDK?=jnY#ubZ zAZ65gw6!fXy*mIqI9FF!t)vdHu`1<5Q}zHcG9ZkBZnj!=C%yOU*QG@d)~LgL0geaz zjvSGhUu$rCX~7PXdyTzLrBxnBE8l=r3~3lTw!`gbTefd+rGKBAGc*!7;erRUez*{< z!1PC^M=PSKaLF>!5K&lISTgXa64K&o2Ue|LZvfBNOds{ZhFInDUc;|?M{A%*hApI- zwViY0Y4Ofa$LuGLT^Z2C!Z$UmMd&fcs}&|KZJ`Byo6*WXr?*kJ_YKh}vE11|(bRo! zPN1}a#`XJfLh$9yXT9Vvs_yx9#ds!E3;FHpNNeT-;tuAxenDD7x)kQ?+D%Dc>#?aa zvW#krpY=KgBP}Gwk3j~bqRY2!E$>kO6rVG#`Wi>G2#~7e94msnq6;uqFI-$$=x@&z zfP%yjJq)jlYoD*aCRVJG>WYagCMOEe#cVra^wK6`9zb&1oVdz_m?C~%U;kdh%s z|9nm`Qmvdfw>hgjl2RAbB{`oZe4t&HOkd4#5ASA9Qm_{RmjHgn7x|!SVdi$~(Wg7E zZSm4C{SC{~Vo-tRCN1>Gu6$gD=vabYo4CnAqq-j!oEQWG#@vrRfGYI^pxqi%wX|Xo z9c7BLLdyM97&>|fGtl8>mxW&|4|;wc9Ge*DoF8VuE5baP?-g@KL*%{y5tkss$e`}{ z8YaQy=xDa^;+UVb#@Ou%@BZX&=m-CC8GN{QdlB$rn9+&7aCHDY{Cp>0Rqs68U`J5P zVtU-)WfmRh2MDNSHxMOL=yJ|+FKvZO#g3+|yFtTC6E{8W9xJE+?J~QM?Yx~L?T13K z@A|A~cW&Pf=(5z5f*{7E>z%*5m0O2k`TvmmXthrug| zHE$6QdxciyFIHArME}RnpI^gX%R!l<(q~&Wg6%h}F*54%W4~9A9Yh{zPkEC(5VZuvWE^HWGKz#&YvF8T#{4T) zFNZLc5OIs5I_YNG?V|X1e38BOpH))4xn0io?4oi zeA+yS^u}BVKB$5h(DS0QTr^4bKoRu0T+*)uO1&K$0CjyN}@_SYv=8@jlSP14eB53>Ag& zPAtktAS|9>dao>pWqa%5+aN~K_JtX(4@qp0-$;o311tUiA@aLq>h!mJ?B2T7Fhv@@U(nFIYs+by zUw1cvR9;OiBxb=hPH_4M1O%99qIdH~!$)`2Wy$f)31gH1oBBKQMGksCA?8tlWcuto zpa70b$|vXQMMh$d74Dxer{@5kT&#`kZK=Sl#O0Ia5P%Kgb1(@A^l?Clgo12s&ud;4glT*C@$iLA>3A&-+2^9MsZX5OLHdv`=r2vg$=KfS~erC{MpJ* zIVGqE87k5P)ua}py^@;@<@pKVos)WFd+WYM>)9Rcc}I#DK43u7yfv^}X8oS?#hb7l zu{g-&+$qc6=hJk&|DE60?S7lbV^9$y>3tZZqct&#hY*BPyKhLcuV)pmK!AuhP&&ev zt5c0V2ul$ZEBBBklHs+=^4SMUsSo&fyFTJfeV`x!DbfOU)E zfI*fg@1YwZG62wJbY{}~l+^%9HBYKQW4#s;qwJOJ-$FuxC^&i0^g}Hj7{-l5(a8J_ zdP0WvEYbAydO^+z7uShI=unVtk-~Ne@s&iYwSeb>l zGwz)f3dkC?y&Rz!4yd_14p_$@_Dt{I`Ip2(nLy^%pzj|*4F*};p<~D7H6cDfiF&Z| z9Fvez{GpW;xV4097wYEN-nx?%%4huby#MK+VAQH_J-CfMW;OI}*yoUv+o8x3c6OxDLh4)q}Mm(K*#)cUz_@&eJ z#?YbgNm#d9R!WMD10Zy^_j0ZR{@=<0&8jPMILdS2EVy|ZqTnKP zG1N`YP(~SoZN_%aEmbUdViC{WtFtwNO;}im=CH7EUTStI0K_^Vl_B{1hR^4+GKG?s z)IXyPro%g6nVEBri$C?F{dcC8!zU}x`JK&Cp72$PZRSo;WW6z$e&3#ZoI?aMZu9>p zKUftWr_oSadb%o^WvHsEYBqrirdr;7 zvi}RC9Q1fq)T$gG_J}%YC<%g-X0~$WO63SiZ>`Z=kbCeCazVaD6APIaZ-?yk@NE$M zEalK3D$B{eOl!q}0g9MEe}G6ImgwMO!dw6jH}w8N1$!TdhD6h}SyNJ0Ruzy!d3{iN zdOC23@?Ucp0-)MMktp|Pyn>W|)ONIChXJrqre^zs$p8T)_)v)}K&q_h%D8^L3iLS2 zu3rbN%J8*KEiER)5L%S?_Sv=P*fr15;9DbrZc>-|%-glJvGi4QLq|l=$l6avlNMP8 z<1aF^zkdT*OJ`|;_(g|aBT4LElMhF<-J^?n!TD6HeAFp>I- zr3dQg)E`lhRu2+CG)rCCfK&2uCj3jNNtr_c7rxc8>)A{n4aBWC)*s^*P%{Ml*jDPi z@PdV30hOC1&2_N$yd5M%S#Xt`ENga8%?x8)C>BZ%{-reaCFjPbrWiB_T4-CPXa+HI zM{Rm|@_!Jbdvf%LN|)!{yb~Y3zd&%AzwrVl{^-9f)870Rb8K}6O^y19$kww;a{pTy z#A}aOHX>yJ7EF$H+jZKi0CQ8Alm~+ht@>5+ZpOO)S276d+l6AWq=ppeB++F_;I}b6 z_H85ez~W5ci51 zN(WY~Bx(bAZK9f6zgsZ+(#|O|LuE6p0W#)B)$Mk)%cd=tASpyM)N`1wH|{&6k&t(8 zk6;F1f|DaWfbqEEh1MHHPNLv?kLjr0PLuMqbaZGl082kW14>dKy5}TKnS06vfA|hZ zNn!#GI%g%6@)$0Yll%hUoYaAsXp~V?Q+uDjhzr4NQs}xF;oBoDsLW<%=Bz>b!oZRj z5Q95fZ)n2t>%_AP%cCF3@%_xK3f6g3jvWt=Vby*%w#Sfi2nq=eG^HE@YLrsh@;5PM zhU}vn+4TtqDUpWJBJsdD4t+TjG(ZzK&`-@mgZB_Jj?0j($jV0HzK9ti)Zu6RgDQcq zs%m4n5L^aOv`F;i0G0Gk>@aRg<059vQ13LGuKG6U8;+uy5Z=G=f;KQS-wzDj1sMVc zXnY|p8T+_Nb^|n|hn+S>$VMq`4+=iRoPGcP3S2Gp+T34Lxr_Jk@OToW8a4u5oq9b% z7JpyAcz=xAD}HKl(k+tRMEQMw=IFAN(}sH~L5t>-;^y3a zZzUC-r&HKEfZSt9{glHrC%{-P-&$5>19f$Ev_+lYzsq;e$BH$1IkDzrwus370C)S( ztbR5gv)9Q-zWpdlgzhrw=KmLj7nobtT|4{ zcAROu&2Pq?VbQ~gRQ=6k-wSY3#BXCv;PU`bL^LKZ01@?E(6a?NOjaHu4UH|xR&$g5 z^G$ybB#8MLeC`bDTGfyf;;Z_h^}&&)b;iB(R!d*f{~pSpkU74b`A5AmI|ad%QOXI7 z%zuY_gO*mnmUuqkcmBr;-;h!am^B2^;rH&{voYs;%@Yfc?)()UcdUJ+Cvk=fO@;b6 z4-b!}^!zkN6ntYY&vZ?{LVu(lnQ`j*R&JUN15A>JSD#XEd}wJnc#`Jtnvw_2%1?t{ zOTbve1A16U&{}Ehi7h($BNZ*-eNIWqtCGVp?LTQW^pD@{EYPZ@KOAA=Jn^!uYRV?_)Slyb;WN zyu3a_3dyJ?!R+?=+Tk%9?&1AU!8d|}_PWk`{ulHj_IKR#F&VaT@KWL0ZASsOGB9T? zfyvx<^19No>1bQX3^74h0p&C?a9K;*Om&~{!;q(2_d_HiV)(XBE#n=Nt4Wo0W`GL) z%kRTyS6y~np&b$SFTF-+YHPrQ{Jr|OwubKYkd0tVfy>QI!(T?LKGuJayew^4bVi@% z9oLWy#p<*r!|i|3!S~r@VHBgU(!6?N!);Hf8P1$D=UCm9+~%@$RpBaSB>wvo-?$&9 z17ZL8YcOwxn86P=a2G_JcDSy|dl{4N@wW{7soc#J&%k{S$uOC@W`FV@s@ZNosAkWv zvcV54q#dW`-N8(~v2^ZfZqo_hir{o2t3Iy{DNZ`8&m$eJ=1Xj?notSi6F z^@r)c&*rk<<1c-M>9r%TmQD{kd@E_MS`xogapEx`xNC=8mXv!tb5mMfj{Nh}QHPye zF*FVd*(zxKO5hCu)(;g%2{EY$S$U@cR-|`iqRMBk0#ZjYhkTopJK-XmlA9}pv~TAFi=lm3?ye~M zdNg+L+$ojsyohb!KK-Up?{9eX0C=*56q%rHz^=`!AyKE8LNNGy5draOWgKk8>M zFU)`Zn?frXVAMbA>~Q)Y3$qQy@n3b$U}%p>Gl8$jfsjT6egSGnK+OWpzpm5N zW^gmKdZ;KT2kX~RFo#3Vp@LGIp@8(HId&(Z4dH>MTSDfC#w>q*XyI=$Wr#{Ql1F6Q#BKk1tbZr<(*{y!87+08I`g5h~@7EnrGuH^mv4`xO&{Oi_rn1cVY=<#e>P zXu;|9uv%0aZed~qb8zb$*LRikNHNSPNn{L~_AE_ci#TmH*ZGzaOCxfx)^rFP`f8*2!xbSFb)3Rr>`n z^w*IxQ&qo?> z$F8%7mr-q@W1}g6=RDE97SJ(K$RR#)XPoT}Brp6ukv~7UZ}H546+hi1r>D)bU1WRU zqWU_@_Vy$9qXS@S{2SU~SPe7Kty~|D<*#v+dE-WpBx_eYMp?_U9+9oGk?Cb0@3 zE<1MP-Fv5^I5CpLz=yDwvApnApHWK}+=T`uxP)X#lP zWeWLb5&Nfa0fgkYpJdZ>(p1|xjsAd{n>)#Znk%Vrare21DfOzP<@x;OAInRl%dX>7 zv+NvT|5Kd;I!5*7)0E06xhII;y4lOD2@3b1T`1B&@;mH5VVZ`K1C_QnF`PB^bfwiw? zYYap(9a4bpSj>*=L+3)o<7Dg164eRXY~o{)V)SJ%xKOEk48599pV}8?g(L@4%7zxb z4)|>PAs+U=b&@~3CDWbjv)St+qfZN=RYJ$?^~ESvy$Yl;Ru_jT{-Nx;A9NaQ zAYtjF(XI$p6Gtm0N5`D$$4{RsxITUHLIp-~5px%0WK={J#_ma?_0$oVD!4ajBzM(1 z+(EP1v5;o(VpAFk|XEYfYlUNW}d5eHVz~s_fy{^H$^Pzbj!b6J#a1c| z$)Fqr_wtat!F}O#*oxiQD=Mz`m`0x9RD~>@J{sO#6@%j-?RrK=5-C&Yq1eK{L=)WO zixH>7GMdIZ=m?a7dntP#R`x=r94jC8aIl#gXOAMj9udgWi}mDnujxSBiL7xA13LnO z3xV5=g>sSDT4ZKqM2Cd@{l}I8#lA)YITZYlnu!1`#NvZkQYd4dqNl$!>e&1K_da-yv26|2TIGz2VJ9#IN}`~9Bg52t&CPv2~?xq z3u|JvF!i%ZadvL*Fe-+6?B6MvtT4Cq{l;HPuHQeXec^OY;1bJ%zFM7{!4<1J#EH~de)Jigg+RL_-h&6?~U!&!Wl{JDo~n=*5Im}a9(SpT$Kf}zCm4h$0t_l=DG=tOzo${2Q zsB5Ua5YHQ>w1QWM-@yrEg^)bx>3sc|F8^Cf_fSDHCVtY&dh$gt*$dRSidU^md~Zjy z=gVfwfA5!-yfh(q{mrB1g?2VBQ4uTQM6dQcrSASSDbcq7O-$EwZFLQBFoTo|kW|!B za(<3~53VDMLT(r4AgQ9!@1}=aq5!Q>(}rQA0*?-xuiNGRV3vme#w_#xV3yd(fmhpr zdzKX!i_Pa3>d7HOmnxfs*wz?(2jx)@L|c@efq@txJ*ji(?i5iSXyk%Sh;enL^z`;d zQpk_c($ZQ8VnBd84!i%)e|cs7SB0HMiuI6+skYtc-64h@B~3%-P03;c##fJSOYPuw zg`_F#G_aq%mh>A;<}lgOMD4se z#Oib)tV^nHt;NGqjevqR*4$3k#~#0(`62=8nnHtl;sKQA+tX-eV*`s5?5P)1nkiW6 z5w!!U$MJ(@U%trC50gtb_3xW%H}_fOS%w#p(R?BC_j5?GepQb6i6Otvq) zdrn#caE92H5yoD4V*G%GP>o{<))JToFu1cI^00@$BfO%r1qHF&W#Ja|o0UKghy^KV zC3GRH(0k!SiIJF3q7!^?FB!Yp4OtaEIaLliS7tK3U*UI7T6!&( z85y`m1xExN@KEuStl=}N`J0>(0k05rf;djq4`BcuPloNUy+Ds8^BVMoj6p`9}$+2y6|{HP$`q| zMPVn1*z_M>X_$+@+B6{js$o|)GhRqNEkVwtmNsNr%2V+ zhze4FpTyj8r<5u4uFkK|n0v zu6L2v89qPhSg`Yqa&S!ZtF&g?c2tz+ItovIooZ+6ns3Uf|5-n0O6#yV~RYI%;C^)`$}7Het#=#q@<%miHa&bq zwMNW1CiP+$*_Q}(O%QK5O#l225qa5rM=%{4U4bya+ME@Lq0F1`73=)=`8x$kF+pe< zq>cJJy)%i&$&N)UxRQ9nJQ&eb_Y87+N~KKXughKXzcM_x{qeIEop;~Tv$I#ZR=6BF zFLu(ZO)gY1Oe%Y4@u!AjU+WUq33*(&wg69Mz?s#A!G!Eq&T= z*Aj<9>R*qWgdk-V#7+Y>ZUJQ;$;6z)#s60$oaX)q{+IlYAJA=S^tg6Rz`?-*CvAT2 zDt-oMM1!u6PcqAFZEb5XLjcDV5;e@5WX}9sf=A8?BFKbJ?i-w@bEISFCx)!aoFBY- z%Wf^ON2tLbhXQgnwf?VgNIe9hhQO&*f(^;UAVf7WO4{$Pr>A1#anQ$6aHK;|FVwM^ zt4@4c*q^~0ssK!d#qc9A{+FaOW{8R|0qFTP;^1^K;Gm>(#QGYM-<@=%oq<$|oB#w~ z;}F1la!KHtXeYr%9vUv(c97K$pTFGq$6Si{?SG_tqZ z(r;Po@l*EGC*Q=etKz+fz6LU;TK>ryO|Gx41Cjse1xY4?R_86(U*Pi;{SRTC#`K)O zzOMO=8#nIIP5yt$>H^L3USEFYq^SiD+Q#O2EJx}9nab8r(Ly972d;xGBG%BIolwz0 zmT1-#guy-enDY^W3Js{u_X^7>H|b=N2kiIf(R4mFwIOsXy%SPl)C$^dx z;yjXxO3A9Q5NvnkB;zxbIwFtjtN0_2^WQsl>2YXmDovJ7k|CBlW=#TtDB?aIKq7|M z*Ic&(S)UkrJ}}$2XU`poZfSbiP2vN^a{Ryx5r1Kr5kZsm5bQ4x3J*|G$QoaI@1J!sTVcIz}z* zYFYC6bfh`5XomuVdZoxkJBywg3!;K>ahN>! zJ@RTwSHb%+Wy1Z{!}jHM=6nXC_h+RIvQoGuzE+&ur*E5$0Z#QD>vjIpU%q4iy@=kQ zW)6N4lnL+Cu6d{L2ys^F;ef-P!Me$cqszg>V4 z#iMG8XB6CspQbMTR88mFx58W{K)vLd;(xW%G5!{qTx#L*Q>8q`9Fr(Ee{J9X1lTC* z>oDN6nTe-bcBp$eZJ{r};B|L0E_zDJBf{KnYK>%+`Ppl#19VpMyy3e9B8A*@?7)T9 z#w`Y1S$bt;9u;;j_vzFD&ifnErI4DUmE*Qhpmd6>KaRU@c6yCsfn5P+pK0|n_9R(~ zX{f@$gf9jA%_1CvM|o>q5lyfc0YzJRm%56M&F|J`0HNKJ)1x}Epv;ScVfYM zDK_BXyJ%z-UC$Z^PnKhdEy%MxSdM$CeS?GKyiwW$ zc%GUvJS~oZJXzyP0$6Y3&z(2et3DdI^6nR!U(El1I{OlEuG@CoA4O?aRD?+A|#a%QpU_O&q7F&vmU+Q-uvvcuYJxwUGMw7-&Okm zf5Y?K&wa0Zt#$8HK7PE?fgN+a*!ch7eQU52bJON>4M=jFlA$M*4O%k{iXP>U^!GD_ zXWY@tRrf-Jm$Xb$25b5+=&E;O+36m0amH~E23Ts{^w?M&xu*G4&ne*hT6{;o5=xq< zD6ls3%yPg3T$gis9SK8r>u|WZ^l=BDvQ|}CS&RgX+`hoPGb*vvchXFDMbEDLpX^Bk zmg>0$waAyocXvtzxwyEB2k|(>2lC;e2lZ$O0ww_|3`9Pbl(ZA4R{wpiRQXFw;$vDe z=K;fF;-2+i`p=vZ*?U2zf6|TEBjY5%0d!%wF$621_b{ttPdN*I|1eSs;?CyRZ0Z!M zx0IAn*wtyFt{_CXqN@r6KF5H?r*K6A`q{U!?`b|4c+YcA78MrCEN>;=_}bdx>xJ)& z*c1&mebaitZ zCxZ&1lYH>7LgP3$+)uy3IO@GvELMr8UD8nUzz^DR>A`&WNdao#4= z+@GeKQ!u1wUdbhMZ;fm?F!*Kg@gF{&BQZw`PM108X)4qzA&>;eK@IK)0UQUEfHY@f zXH0v~qnAieE*IpEqN+;b1_Dz?yigg0U(~5ZM!VZ#GlRpLG!xO7)-~;afMlHq8V0x> zKY?`!In41`V4nw$vqpiJXEdhP!=y!T=*UBeTZvQ|Y!c*R@XwY5v-Yt@;wlsn>_(q< z=fkfH#HFLs(iEJS(JM#Ok}&iDs}lRY9*+vTJ)oeF^o-QrxSYRzP~wq}69I(WV?j*| zc3Om+4{;IcPmJVEsDLeE=iu!h>-`WgK}~B(a1_Dt#iDD*_Gvi^&xCgvlRD+k09ggal+O1I5|5x?F=0bK82-u z7Ir*u{0o9Yt$%@rfzY$mny;j(W#3i-^uptJb{6c-J&&{#VjkP08Ce4b--hAVDQMx= zlJ$pStGq%jL9>~YTrYVdnaRu>_iIQJvp~fWmN+;!(#^8 z0OuPt&-MZCPHb^EVB>&D8E>fwgfTOu=VN?*Fnskg9xU;H`T_(T>=bO+pR=>o@NgtX{Af2=f66gf@I1of z!bhm&@-#pMjG}A|#bwyc4n5%VAHfYHesjpOc+kBBs|clE1a$3W1TO+`d`rbzFqznJ zeD*izK+XqtlR3(H;`_01WJ!-FB}R9EG?f59r0m>Ww8xX6(uRX48^mFWSUIj);()QS zPRr1YhQ59q$gKeQAUS(O^4rrtLT77jMFB0~l5;>o9-ErtM&Fna_W}1lcb~Qql)9Yu ziwpF#b?euEKqY04r}kH?)R<*mhTqW1vWjrB{5U)kwPwA3FeP{$(S7Y9j;~V8sINwnkAXUmAN{l3SB&UL_>M2)ap$pMvFHvr6l``e=5R&9 zMd%3+x&*YJ_+S}3phAX!m{GK=5u!LbP4F=g3KYYm)F$%}1Yo5^UxH2i;(ZA6msI_n zJAgPaD)jMV8ht&hqWo$}&#h_PWX}zrXvzql37FC`oHc!HX?ub4 z9ogXZcVW1ZNM-jeVp$~-=~5?Wn^?IgztPXkp(>lzaA!@@nf(rr7f30*kyw}b^v&Pl zNM>Yf8wk=dUWe`zoa#8CHiA<7RCgY!Ig$4e6C}8!!37GrZ1tr{5O1F#QB=>F97bap z0tlwv$7%Z8+ojQT%F09CTolTt;Y+5L1@jfB)VCLy+hPFJ@#B{qa%m1bF7GnAC1u3X zYS`T1gh3}=m5?Ww0L#~pl|ZMM6aSuJn0#!H=G6n_jC9HCK$ZYQ@r3MwwKIEQz9kst z<`ok1-}ukWP7$S^?pqm47(dB__drHM5)*sC@raSQde~UB6hE&#cr!4t(%M6DA9-1X zwuOPF4xlmty~9o;Njq^Mz!Fop@9|aVLZWs;C2Xff<+k~<_SVms7&7D|;Lz?>lPUN< zJgk&3Q`Fob>W7J`(#3&h$@y2j7!{@2KD_hDM&(n$Npj}$VEyO^z`EsC>`IiXXPumU z5K;EvAcH@}8c|3dltQYDHqp3|NoI#y{o7+kGwbWQqL3N%$7*;od% z8uw>MF42GNBlD1kIwjU=%ke5~Zb1A^%+$US?>n=V{|r22j(`UX_3XPJM@gNb7z>vm~Iq%ybU*XWvI&Ua1!`tEz=yG_`nPXDQw zDL!laq`ECkAZN{5Yb=#n2n8F~f z>OhEqd|11=F+hF_XafWmLBK|dYchxp`|HvTZa#cyZ0DGxjm*U#jbX5N zwHggdw@OOhgC+t4c?C{RE5xH%QUV@s?kwkPFPDyI~I)^s5T%UBKRZ3D`Z4B$Q>512jIxzfW#03ZR8N5X8?%88;?ja{^_c~)9(%J zx|OF^G8KZYAm;U340R^oaQf1%RwQF74&2-e)R<67KGNOrl1~z6aaMP4-7P}r^W4x` z=EV#L*TUj(9RvtSoG=w1-H^B@oMfZxPF{;^E% z^JK{c-6iXVThS*vg62(Vc~7II0rs4%uOvhU8(xiogG0G=1u4F0m&`@lxC#mf&^W;Z zYIuKCjAcd~(#p|O4#xA+$W3PImv zFUk{CMdva<;e5EEl1R9gJ~LWAi1gt&I7qezHn0m!pnd)QD{4c*azaH&{YLSut3s7^ z_RLlR&^iKg-qNK@Q5w(4vuKc1{}F$ zY&eljq5<`xp@9Y8C~=|h4U!6gFdysP&`kM=3B$y#@jT|^G$s-OFfnX|R3Abypa%(n zKVqtVyLcSxgoOC~UZVTWh^ z{QNgrh)^c1$Y6G)kc3!|7N-)39vk622zt`K+tYt2qHBbLswP!u9XcKsb*ZJ`c0t%4 z>@+lZK?0&W`NAkG0zgzgM%PR#~sgL89p!Mms!Yee$4{CSdy znwlEvFpFp95P{Fjm-U9rq1RDLVw)A?<~~HIWc&~72SdWb!e~j88?f9Br&K75gcYO6 zWQc+8B6U*$UZP<%A8Ts~HKW%h4Uc31+)CGUXGmuGwrr86`Pk5)!?NNUo2Sx|BWi#+ zKRq=BD~|ND=P^-31~6>CbW?NWP!ll&R)us!*FCg1)c8~5K`AKx(v6F%tM?XL5)T=$ zO|_b&>^iOxLy~~XOV_Vorws;;0%j4`(X+;&s5DM3B33yV6q+!PQ-SX%j{589gE|qY0K>g3A4mcr!_-!4bxu;6XP75f)05_uxso4kRUx>ldS1hWiwWW$3xz zgHgnIHYV*A%;XP2X#K`US!)vY?%JaB+M z^~hTNb7f=^j)n;6p_O(Ji4*P!RmC=38KO5#(wKo|rICJ2Q#zX3zD+5q_qdizZAc&a zIlgLvoip9GT9dGH@=cx*cG`*Ac*lXL13~ePQfeMu%V6Vj@^e|}Z+)3lPmC@)W$wrr zy^MlgN-^hwzKl0|Y0R;NzJyB%8+E&ya|ttkGy#4v#}WWDYLEk5DB2o`eC_jWa+1%b z7{mv=;h18I#h{YgmJLLurXP_781LV^(!vmO(hQ)I%Q>r4#{7dA8H{>^Yn<~De5YC< z9BD_7=*v`=p)*8GbfEI%6B3#pr7Lqg00I<*8?}yBOB^^9#~W{&s22CBIC z#a}MZhngPYfYHjhU<-SmQ`_`XNxH#A#tYfcc^aT=EjoT0@jd6zJM5oioV-oVn~9x} z=(2Bw{Mq;#wyF?N3RW@yc0cr? zkIY`oj|=?5*T0ssyc^l9-6{>u+ykNg`^|QL=@RiaN$2>MmB&CSn`*AD zttDJvY%?HP{F?5e{8x-r&TQDYQTy>^S3TffF{q0Gx)DzR(;VCkSQENPk&K>~|5vT# z@#cU!@Xu*__^)%{O*%ZYc)a=(*5kNA@v{str=W+%G#l8Z=0TP90}i^{zqC~W>=JMK z-_TYLHRs$#lBOfL51uGE70u!K&ZSIYR@{|}&Zjs9NM{cq(^H^_7)zofF!zshOOD|v zKsAso_7M*S3{%}Icdg6)KDr1+ZEZ1x>q!#Pjm%F01ybw&JW;1nBdQDRck^wM^h zdfPvx(A(Be(YhldOY^)~6*ag&HryTEIlD-;zTRIt=F;3}Mp;dP4}E60=nk*v{+LCG za15y<1@nK_+K$4gjw;tE1>>W|R9u;sxUr{{d3tzQnPybJZvFc8EA5g#Ok{YEYek7$ zjYburtb)j$%00yI2W?y+RxKHoK+b7sq)QMo{Bd$rNDxPWSR7=c>+(S@WX?AX1bwsa zk1iZPVBDr;X2wfcGze zcx59%FEyp^6kF6ct!C6uZ6Wsp3l{7=^*Z$c=#)-zb!uzCSck`YYYz{<2hO?L`scQZQT;F|k!|5~ z&l35+wokLqa{thaKw^iE-WJT)z&d=2_9R$D$m%*_XM7r?_+WJ2{g?m?Z#?1~*Ml90 z2&5jHIy(~rnh=2^killw0~;i!|TMC6=F*3A4SMt$->M$CXhorE}?TaX<}I1bCID?J)j^3<_#$bdtHXanB_%8py5yIrJl<>J2|XPCN(DAHm9b3*2=) zuhEkq-oymiI(f>IShFvTx*2MC2df2fym>Gn(FqcV_fgKqHk~hd6QB0O!<`uj$m?u@!N(ZxO%Jz)IPQF#BL0@OLdDV6tzVhH1xq!LbU!SoVXGw(` zHykGM;Z4ol3Uh3&Bb9bC!QHPJ)Ku>j83ePoL~J_up}^mKsZaj>fPl%AV68CVcIqY3 zIS1SiO-Jd3!jJ34;o-BZxBEFf{+`yD%Wln#xoWGCbMPQOpco_U7eg4Q;$>qSW3KNb z?M8D@$k9PLhZ7sHG+b7>5iI;lO{&tL>1n4+>ZyFz2LE5>=+RrXXB#qH8Y7Eagf28k zqQ^}U5ihBvKs2zYGip#g%XG+`W1Fk>$+BldC+DFT1RA`OB97IB%E^2$>L~XE>#pG^ z<+qGjL{x7dM61?}M`D>q!S=H;V{xg3(LfNmfEuw28_K7%&${h1I(cix>%n@F17qi% zcq^g-%U^|7W1Ha9I@sx1WF7_g)~U@DCQW`dhNSh<|CUgmIn(&11g1Goz4mAr$j{@d z`1I-b1Ybr4Jk8!mD{pyv!6Zn%79a+O&@sfQ{eN*GH<)Wd;S?NjkpYPNVJ@x4asGFp3+j`+{9v8dw5zUxe-7 zClEbji>ml*LUljngG@%Rby*l0gHp-?J|0z9UyEY}>-oXq;ha~mfcphf#6=@YM$fLl zH9t4>yamQeYOOOr>kJ_GjCGsPcA)5=Oe22$_#s(;x^&!{VQM*lh7)SR7by=Lnn*8@ z29B<55MZ51cLRq6`nPvIZkyl%G3kvYO=}QstTIzi=;eIaPEI~|hYHoYt|9~K$+f!! z*Z!LaiAS07<1Lt+WGNEf`pPjSG|vVjN*akxxb7AU>nK=`rA)-=q0-#AJ4W+qs#Gp0 zmH2V@vR^3DyPz7%2`zsA{t3#;s7Yl%EMQO>mbB+jw?2Orh~t@?p+i20xZAQjN*J?! zXHaW(o=AC`Ic2|L0V-Rz9Yr=Ah=xxe=?Vod+Bpg11GdQpHWI2*V=#UroUr5 zj)Uh<^++e+oL3m>1r_6RMh3CpAaWXn1VQmAbwAVudoi#K`Z~j|EOcIwCd)$`4eV2+O8hku`w2Zod=*zDb3Cb$^n+|wvvw93HwoPX)utEN^zJO3tT(TWwj zhaUTKw)^=-M20potK03XcBrx68aDnyJE3FLZSs{#qsWfI1Vd#9{xbfgvxdyf-NE11 zJ_u4?FXVH>MPc!^v)9hH7D)XZ&$%V=tm2Qyy}i92;nTfy5%uLaSKAs+=(O4zVSWn6 z0Qj`7EL^s1*%L4=&~0Br?S{DvchTC78-0Jc51))=QO_7mli190yp@ ze9Kh1EQXhbw257IDX=9*)E)OPto(z|*#m`@#4Z*hEdLC_k(n?nLCQzV{ZMFQ#zeD` z^Mv<3cwEYH-~EOmVx&(-MEVqSOh1Twd(5jIanGl(VYy#wYQ%H5q^xWmC2wdLog~MI zmVQTjoUKBJ^BINq`Td-)GQ@T&ef)TgeZ9!@J9pNOVJ?~<{;P3amcHsX8;*&aVDH`R z=s2@Y-gFa^L^_}1gBTi|GI{LiQ6^C8swB{|mfabqETt$fztsQGHpKb7Jbg)zpQ^!O z`~Hmnz`K)&oAIOJrlzLl@V$*w<$cr(_2%Px9wDJ;bw39!*2(&!t;+zjQu8MJ9DVe~ zmLkOESCR>MwSzA)Vv9x^kGk%cp(bBQ&8c|x{>+fjP(M_6hlk-X2CHLL{IMV0HS@pn zZ&r#|cX4wYI6!FAYO1Q=vja0#PP{~3zymvt9|vt=UF+F%!T}NsL6WjhH=Ovu1F|=^ zMtoa7n8aG{EjVzN!y_X95Bi@~qdI_aYMek&$bXGS81c4O&xNAq`}gm+y6<&4 z1=}YS7g~cc;o-cH*v3yH#64=W27ml1h%yorFzQ%|nb?W-1><`i?d{j10h?a~W>k*F z90-PrahiPbjvyR7ih+x$0uH_!C#*Z&w%Lb~uQC|6zDLnAX%8X84$lPOFzW6|tSvlO zTB_^o3xLeTjh?Z3hF!xwi$%$Aw)L5)M<__EoGxPYKi4=bZBu#b2q&j8;N8{u(Q9P+ zqj4{5ZoUK8xd#syb=6877?;86e4cLzK#pAN@6OHhZ}wJ7F2dVd>Nh~g;DmVglWPjR3{jH%LPmFZ?)rD}|#(>B}xNby9wO-3>SFYg0SO^yv zGRrMjd}QO^phC3+b0}ZD6DtFTGGHAb;1MPTI`I!vQ&&LBL7Z1`?BJnamzdpDg$DxH zjX+cq??5@KD^IKU*4Z<-2+DF-CJ)$K?MkHbys({hxATXJCT&xSofW%$w%q+7Uyyx6YfF67YdFM2ohJIpU9AghCG#6&Y=8}z9-^$6^@ia#`vC)U` z{1vXdzXV6Us}s)uaR7A0*|}DhbdMfIYq0pM|F3$hUV=N88%HDj@G3F?`_js6_ob#Vhsqq*eAO8-J zt`jYAdR4mvSupHNaKBq>;u{cp(kh@GfEgYnWl}tg_*`BkaU_CX(9s~^h6Yv4~O;8^`NBv1X2=>#K`)90`NPnd+Rp&CW zM7*gE)Sr|O{*E!|Fy!d_UZZimw$U3~I@^2xAf#%D00A)HDe1OWH5M z~-cyO!_;>BH{oZSHD{6N_d_2oC0>}38+bMPIs z(gt29=sx_iW!J9NRC0yoKwsa_uYb^>sCpr?^8SVp-;!Xy(LV-;hBh6Caha*dyMHEE z_a9|r5DBf|klDr0{|+OrAm6=4x=)B?yaEF9YHEyF8B1`k=)d-0K^bWK*$F-an5T52 z7s(e3Md6GmxtrS@v;^P3{vqRsiRA&I6<3VAu3==ktiSWR{?6X!uec@pSgn+A?d@-9 zTP`(NU3?8H4^d82K2Y!*!R&_O3m7>XAw(DB^=k*!j`)T9v&^cmH4}zk?Jmj)vv*q9#st z-PfTVBe~9_^c0lxgrip52>!1hSP?Su>Zieq!q_dd=XoPY=ElB%lcU}M8{gFI4J-&p z$n~S#@6bDouBlS?n6NlZ~>T3u{xtm)00z9rh2M$NcpjSn^{`HG&NNQv#qOSUdX zhY*dr@?9FKOb%9?!p{wE4=eiyjw@i5=vJF=R?nmh>^iUgxVedyRd>)W#2Rs`q_ot0 z{G}RlZnz?@po9ndoIN}w$(Z0+JH@sezU2ztD@F9OtZr0QssGt~nnp=kc?>>j?Yq2Z zmUr3bB)!|Z$SA;i(S(&JlCUjdW%0Z8#S(NyqXa&q+>h@@Jga$SSepfV0PYQam|*9# zh8CFwdVf~u=RZCiMQ-bYmhWJ#VoI%SO0AMqZ*T9S$1teY)opCw7^%@c7$vbvNT8?T zmxxHQP{gh2>L(aJv+-IWSGk>n9n0xt!OkF`iIIS;yb+RYx z!@N8;kX~siXzA!-Wx8@8CMxPC79mA}roKv1vDj@AUDaued;D|gdpo{%HkNQ5f0QJ* z1+=HM&3~U|F$mdcLS?`Lg5?|KtCii z3wN_^%N7ce1f6Bu^K2DKIIA%e@jZl?u6`lR#{c=#MYb1*oU6Yx^Q4qEf1qZOqo<{2 zW?E7;Gh{sM(naPInJwYzJ3|s*!eqbN(Qw~9(agia>4f`h`<-VTj8vZ9{)W{TD4w;l z{Q0Eu!i$+3xNH1pRruzpdwPX!ZKrh8C6f*ACR?AF6|Mn@31pIy@{h`u+_8fJYApIU zQSTNaAEORG-XR_uU&X8oYJJ`M6sw7e3CpUL9XR_hKYJ!rVj_gudbx#j{DIN@Axa>6 zW`4259>lMpnP;W6Etm*`N4!|o&f4YJl{ILS(@_Ws!u^wc%ZC7b;B0v<WOI7rZta&Ja~*J zrE+p|{6~)C3-BwnFk$%*@b8f4A>rGKnSRnm&9_m+6Q3*^3JvhLNXI6BrR!!c6N*@Y ze^7HczE!*K>gE6Oce5coMqB;R!_LP_X@w0b=td@mX=5V)zV_U zW4v`SJ_ZnPyiR(_3#(sCUkSoPQVtlwG4^X5U}LOWBkJ>SxAf0eI@!iHQIg~Ot$zE$ zmB`DR`p`)%JY&Wn7LxaLVsK2mbwC6MF5~yI+!OEihMl8Ri1|s3+lESc3fNCcG&q6zvJC0wc+&xZ9;Bfu01) ztBF$=#4AF*vxgY)k)cN@&*Srea3&izWjl{@fc$#}Me-Y<*9h{Y2twC!Rclm@q%c<{ z@`2=fujo5>&fME4C*tE%Ash}uMc6AUwo`A_5{)I&S;Tq>XE8csizv`* zq*H3ql4b<_K~7TS5h#<-HcBUzB1(ULpm0;SNqqA93}(e}qP^PE_XiQ{EgGoE2p3W0 zvFN6e35#}6GkL%fgETjQ?MLyOSX@cyVWGP0#j#H;t)0)e7qBGYh`Ww>(0}f#EKQDn z0J=}@K+%7K6Tcf1>B!&521%-mG0r+`W)V#j(9mOpgzhU$DSkYcjq`z1IhYcpI73=V zq=MwzAb&WOCRKd4>@6y0VT5~<>sM7(eFp#g9*PuXIlO#)Z;@ePj?*!?^MK$dJqYWzV4HrtokZ>67CYx_h(&Us(P9>(QOAmzZ_^iPoOtwe&x6vLQvGj zK1%U#kt|RY?(AKj>x9Kn*`6jLtbh}j&cb+bKBle4l)4ekW7T|L9U^I7*d#tTA`KwcM7;AvY*&Y8mO z0H^^y1sJjT@l(bx^T>(zy|V3ot>@^SPM8-!9*{>BW4_C#Ifhe_qQ|WDL8T@b(Yc*! z#{qrlroV4wF#tR;7-(Xr=Jb;^l@gWgrFet{ugY!}1d~O%3^$-`?aDnkh8j(&4A!T& zL&bOMaihLu0>QyYC23jko1z30>fYROHK+(N0~N)g^L2t2q?Lc1c36lBc}HF0VOH0Ru#;W%#|VVvcd zBv^UEt~^UpH*GzRnXfO**8xzVq55F64CII>?VVkN&{Juihb86Z!J$nr%ryqxPBbM? zZ7tKl6Tlcr1a{yNBx6Mduypn6Vm$E45i#YuxVTwYRP{h}S8!}#QE_qt;FnE<1l=rC zmk`m2yF9kVW%zPMNk}Hk+1Ts^5Agu?2Bc^r^-J=%lGQRC|y21W@$DCc{<;vHj z0&M`bn@@7={kp1`+31LD#2jik5{!WvPeWlu@+ELg-UY|4Roey*%u29$`XFpTNTc3- z`9cmM;!=t;VL7D@=bg+Q-X%YXHi=E#elbPt_{axy2l%dtJLuXIZtaSogzD((rAxHU zxz4Mh=_0Zu(6p}uds0N2b)(-%QFL^4D24Xg$!pf4(2w7i1S-*cy!Mo|cb*O7wLF!9@AfqPhEe)j zNJiemu4OAQ5Yr0Qeq|P)*=O-*uzgUc?-FdoO!2zOrqz2auK` z&bd_+|11eV;FfPcrFYb)4X|@1?+Fz+*<9Hck znW-zFm$iaw9~kfh`p3FWAh`&yb5g}Q-S!LO>@#6*#92W(SJxS12Q-VX<7#Os2o4|h zB2@9pm~4l6%mYAsv_57qVIbT{;u<+_|I~Zl3j>~aQog7mBgE7#1VWU!uw?ns!RABl z#s#tEng^W4KxWoqkkuM$F*ODuf25dhGAOYDfO%g304){A3%EP26Be1e8K-P)(m`88 z2Lof?Z>kA1&gwR^iWWE3!|Zo1;LkdO$3f{03ff8n5qxL)C?eRhn;tR9 z|APg!8Zm|sKM8>Kk(|<_H0((l~%maj2Nx`*y z8%Ezj16!NDGN3H9C@xO1`9>rsa8^J~vd2!8N! zQvm-BBccUceEbBC19XBTp+8#s-{8BXfTIBX&~F_bmxzZn!TGvFPJYILq;cJ%8jGWK z9HrlYegOc5MhCX%6{j@D%dx`&TEkzD9w#0d`GZ;@=>GkcFtEVfj8%kuLxwnm@4^VZ zx`@r?&Sz(X7{upHJY9>$OL0E5KmF_Py4 zHyD;^&nX>>h}zH+GwOJZ=TdU-i8RQSLJuIbqovSn{*F$)re%TS;Ce%J)zMUDz{3PM zpop`548-p(Qc?vUtm}H|t&l5JiHwoLbgJM&|60_?w-EWrt${RF4Eo|`cilhek&?_2 z3-T=r5U^(pL5LriRFFps3nqpykh!-w)zD%iynQ?>vP#hXDz>?di>pG~fs5nZdgX<_ zp<#M`7UBx&lcG3LKo1yaBChy6oCCppS&P;d@WN{{owEofPy~BpL`H0O_C_S*7YYaksgr@nf;4M;zi5v1)bTh-8!FqOcNM9HN+v{DG01+X@mc?5x+SEd(=EHWe>l`q2X zd9>C5rag#_rJ&XlL2CUSZ=~jDBm%;M?TQg5Ad*W)%K#r11PlpEc1DcuWW@o$VmumX za5=;B3wX@i5P{ynSnd)ob`ga%ZwZ>RNuH4V@d^qmphy75zyONxBFgC8x$C&%Z&LF! ztKl4R9`@*<4%Keiv!0pxG*WER+d|b&QHX{vn8mgSr9Slro7^C+4d}RO2tZGchC%^CN*(i-=4So=5;usI(Fskq&H#E%s$rkVn_WH6JZ8pO zW4zI0qbQKnP?_C{_7-+JcdpmMQ}Ncui`WtM*#@AAP(He8XfvMHkj1)t<|07w^A+tV z5UL(p$dI{-1a$^!DJWW5N$F1dvCS9+n%2a2&_j$Oy*C_(6&%ko$_^byZDYOKZA~XK zc)%LIM6&t*Rg)q~X=&(qBFia4`Zz{d3pkE{A`$(OUQ51_`R_MMFQwVK_%GT)JTTD7 zJ_9fqnfcw;SMzhD-f(QYI{OfX`ErVvpMP(OLB-&!Pfd`&>!$zemXP@ zwSHH0w%VL*VO6o)~x*sOEHu&D-RgQBFDzmItIWbiz#ezlg`WA@gmkN zyog(m(XAz#63Pf%L+p&Jc&->=NJF8BxZHZIn{N(}5~LN1YKIBgXG_c<;_>ktY+cPR zp_yh2Kpqv(*VNI6ckuVH>nIBOw+KfON@Z9BueBID)wE$*2;bQQbv7!e)BBv0xM_~6TdT)=h#>?vBvn)xY=EB}T)MZBXyMMS7tf+1bUZHXyI z5qyy-3Tfhdcn3VH?%ieZ>I%yH{+9BzoHU*1^muY)$$?n25mom(>7t4uLZ?TsTe&*v zfCbv1gt|pE+WFP9D5%IEBF~^G^jD0Z{3Jny?(fT9zH(&|bXGJJ>Z7Y#DGKC_fcqP% zQ@~p&T6bKM274J(QO0>)S*e08YKd zN+lWqLJ0sh`2lWF#AXx;(R)Gyz}O=U_E?Kb5J?^hdW2LDkMxSz(Oyg%E`(I!3Swqq zQ`06C)o|ql7hngxnt2U)PH7Zis=^9l2n@+O$$)S`kbQ|Hh!l&rgM$~NhP?a%P_fA> r6Nmu^w)~U7Sh4?)ki`E!Q~5cs=$f;defIVh3crphsK}?w8eRHd+V#li literal 0 HcmV?d00001 diff --git a/examples/xgboost-comprehensive/_static/xgboost_flower_auc_cyclic.png b/examples/xgboost-comprehensive/_static/xgboost_flower_auc_cyclic.png new file mode 100644 index 0000000000000000000000000000000000000000..731d0fc3fbbc2b3995e82727aad6e6d50f1c12a4 GIT binary patch literal 69981 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 literal 0 HcmV?d00001 diff --git a/examples/xgboost-comprehensive/client.py b/examples/xgboost-comprehensive/client.py index 0ffb48e1465e..74fbc4f5366a 100644 --- a/examples/xgboost-comprehensive/client.py +++ b/examples/xgboost-comprehensive/client.py @@ -1,21 +1,9 @@ import warnings from logging import INFO -import xgboost as xgb import flwr as fl from flwr_datasets import FederatedDataset from flwr.common.logger import log -from flwr.common import ( - Code, - EvaluateIns, - EvaluateRes, - FitIns, - FitRes, - GetParametersIns, - GetParametersRes, - Parameters, - Status, -) from dataset import ( instantiate_partitioner, @@ -23,7 +11,8 @@ transform_dataset_to_dmatrix, resplit, ) -from utils import client_args_parser, BST_PARAMS +from utils import client_args_parser, BST_PARAMS, NUM_LOCAL_ROUND +from client_utils import XgbClient warnings.filterwarnings("ignore", category=UserWarning) @@ -32,15 +21,13 @@ # Parse arguments for experimental settings args = client_args_parser() -# Load (HIGGS) dataset and conduct partitioning -num_partitions = args.num_partitions - -# Partitioner type is chosen from ["uniform", "linear", "square", "exponential"] -partitioner_type = args.partitioner_type +# Train method (bagging or cyclic) +train_method = args.train_method -# Instantiate partitioner +# Load (HIGGS) dataset and conduct partitioning +# Instantiate partitioner from ["uniform", "linear", "square", "exponential"] partitioner = instantiate_partitioner( - partitioner_type=partitioner_type, num_partitions=num_partitions + partitioner_type=args.partitioner_type, num_partitions=args.num_partitions ) fds = FederatedDataset( dataset="jxie/higgs", @@ -50,8 +37,7 @@ # Load the partition for this `node_id` log(INFO, "Loading partition...") -node_id = args.node_id -partition = fds.load_partition(node_id=node_id, split="train") +partition = fds.load_partition(node_id=args.node_id, split="train") partition.set_format("numpy") if args.centralised_eval: @@ -63,10 +49,8 @@ num_val = valid_data.shape[0] else: # Train/test splitting - SEED = args.seed - test_fraction = args.test_fraction train_data, valid_data, num_train, num_val = train_test_split( - partition, test_fraction=test_fraction, seed=SEED + partition, test_fraction=args.test_fraction, seed=args.seed ) # Reformat data to DMatrix for xgboost @@ -74,101 +58,25 @@ train_dmatrix = transform_dataset_to_dmatrix(train_data) valid_dmatrix = transform_dataset_to_dmatrix(valid_data) - # Hyper-parameters for xgboost training -num_local_round = 1 +num_local_round = NUM_LOCAL_ROUND params = BST_PARAMS - -# Define Flower client -class XgbClient(fl.client.Client): - def __init__(self): - self.bst = None - self.config = None - - def get_parameters(self, ins: GetParametersIns) -> GetParametersRes: - _ = (self, ins) - return GetParametersRes( - status=Status( - code=Code.OK, - message="OK", - ), - parameters=Parameters(tensor_type="", tensors=[]), - ) - - def _local_boost(self): - # Update trees based on local training data. - for i in range(num_local_round): - self.bst.update(train_dmatrix, self.bst.num_boosted_rounds()) - - # Bagging: extract the last N=num_local_round trees for sever aggregation - # Cyclic: return the entire model - bst = ( - self.bst[ - self.bst.num_boosted_rounds() - - num_local_round : self.bst.num_boosted_rounds() - ] - if args.train_method == "bagging" - else self.bst - ) - - return bst - - def fit(self, ins: FitIns) -> FitRes: - if not self.bst: - # First round local training - log(INFO, "Start training at round 1") - bst = xgb.train( - params, - train_dmatrix, - num_boost_round=num_local_round, - evals=[(valid_dmatrix, "validate"), (train_dmatrix, "train")], - ) - self.config = bst.save_config() - self.bst = bst - else: - for item in ins.parameters.tensors: - global_model = bytearray(item) - - # Load global model into booster - self.bst.load_model(global_model) - self.bst.load_config(self.config) - - bst = self._local_boost() - - local_model = bst.save_raw("json") - local_model_bytes = bytes(local_model) - - return FitRes( - status=Status( - code=Code.OK, - message="OK", - ), - parameters=Parameters(tensor_type="", tensors=[local_model_bytes]), - num_examples=num_train, - metrics={}, - ) - - def evaluate(self, ins: EvaluateIns) -> EvaluateRes: - eval_results = self.bst.eval_set( - evals=[(valid_dmatrix, "valid")], - iteration=self.bst.num_boosted_rounds() - 1, - ) - auc = round(float(eval_results.split("\t")[1].split(":")[1]), 4) - - global_round = ins.config["global_round"] - log(INFO, f"AUC = {auc} at round {global_round}") - - return EvaluateRes( - status=Status( - code=Code.OK, - message="OK", - ), - loss=0.0, - num_examples=num_val, - metrics={"AUC": auc}, - ) - +# Setup learning rate +if args.train_method == "bagging" and args.scaled_lr: + new_lr = params["eta"] / args.num_partitions + params.update({"eta": new_lr}) # Start Flower client -fl.client.start_client(server_address="127.0.0.1:8080", client=XgbClient().to_client()) +fl.client.start_client( + server_address="127.0.0.1:8080", + client=XgbClient( + train_dmatrix, + valid_dmatrix, + num_train, + num_val, + num_local_round, + params, + train_method, + ), +) diff --git a/examples/xgboost-comprehensive/client_utils.py b/examples/xgboost-comprehensive/client_utils.py new file mode 100644 index 000000000000..d2e07677ef97 --- /dev/null +++ b/examples/xgboost-comprehensive/client_utils.py @@ -0,0 +1,126 @@ +from logging import INFO +import xgboost as xgb + +import flwr as fl +from flwr.common.logger import log +from flwr.common import ( + Code, + EvaluateIns, + EvaluateRes, + FitIns, + FitRes, + GetParametersIns, + GetParametersRes, + Parameters, + Status, +) + + +class XgbClient(fl.client.Client): + def __init__( + self, + train_dmatrix, + valid_dmatrix, + num_train, + num_val, + num_local_round, + params, + train_method, + ): + self.train_dmatrix = train_dmatrix + self.valid_dmatrix = valid_dmatrix + self.num_train = num_train + self.num_val = num_val + self.num_local_round = num_local_round + self.params = params + self.train_method = train_method + + def get_parameters(self, ins: GetParametersIns) -> GetParametersRes: + _ = (self, ins) + return GetParametersRes( + status=Status( + code=Code.OK, + message="OK", + ), + parameters=Parameters(tensor_type="", tensors=[]), + ) + + def _local_boost(self, bst_input): + # Update trees based on local training data. + for i in range(self.num_local_round): + bst_input.update(self.train_dmatrix, bst_input.num_boosted_rounds()) + + # Bagging: extract the last N=num_local_round trees for sever aggregation + # Cyclic: return the entire model + bst = ( + bst_input[ + bst_input.num_boosted_rounds() + - self.num_local_round : bst_input.num_boosted_rounds() + ] + if self.train_method == "bagging" + else bst_input + ) + + return bst + + def fit(self, ins: FitIns) -> FitRes: + global_round = int(ins.config["global_round"]) + if global_round == 1: + # First round local training + bst = xgb.train( + self.params, + self.train_dmatrix, + num_boost_round=self.num_local_round, + evals=[(self.valid_dmatrix, "validate"), (self.train_dmatrix, "train")], + ) + else: + bst = xgb.Booster(params=self.params) + for item in ins.parameters.tensors: + global_model = bytearray(item) + + # Load global model into booster + bst.load_model(global_model) + + # Local training + bst = self._local_boost(bst) + + # Save model + local_model = bst.save_raw("json") + local_model_bytes = bytes(local_model) + + return FitRes( + status=Status( + code=Code.OK, + message="OK", + ), + parameters=Parameters(tensor_type="", tensors=[local_model_bytes]), + num_examples=self.num_train, + metrics={}, + ) + + def evaluate(self, ins: EvaluateIns) -> EvaluateRes: + # Load global model + bst = xgb.Booster(params=self.params) + for para in ins.parameters.tensors: + para_b = bytearray(para) + bst.load_model(para_b) + + # Run evaluation + eval_results = bst.eval_set( + evals=[(self.valid_dmatrix, "valid")], + iteration=bst.num_boosted_rounds() - 1, + ) + auc = round(float(eval_results.split("\t")[1].split(":")[1]), 4) + + global_round = ins.config["global_round"] + log(INFO, f"AUC = {auc} at round {global_round}") + + return EvaluateRes( + status=Status( + code=Code.OK, + message="OK", + ), + loss=0.0, + num_examples=self.num_val, + metrics={"AUC": auc}, + ) diff --git a/examples/xgboost-comprehensive/dataset.py b/examples/xgboost-comprehensive/dataset.py index bcf2e00b30af..94959925f833 100644 --- a/examples/xgboost-comprehensive/dataset.py +++ b/examples/xgboost-comprehensive/dataset.py @@ -39,12 +39,18 @@ def train_test_split(partition: Dataset, test_fraction: float, seed: int): def transform_dataset_to_dmatrix(data: Union[Dataset, DatasetDict]) -> xgb.core.DMatrix: """Transform dataset to DMatrix format for xgboost.""" - x = data["inputs"] - y = data["label"] + x, y = separate_xy(data) new_data = xgb.DMatrix(x, label=y) return new_data +def separate_xy(data: Union[Dataset, DatasetDict]): + """Return outputs of x (data) and y (labels) .""" + x = data["inputs"] + y = data["label"] + return x, y + + def resplit(dataset: DatasetDict) -> DatasetDict: """Increase the quantity of centralised test samples from 500K to 1M.""" return DatasetDict( diff --git a/examples/xgboost-comprehensive/pyproject.toml b/examples/xgboost-comprehensive/pyproject.toml index bbfbb4134b8d..a4d2d0fd837b 100644 --- a/examples/xgboost-comprehensive/pyproject.toml +++ b/examples/xgboost-comprehensive/pyproject.toml @@ -10,6 +10,6 @@ authors = ["The Flower Authors "] [tool.poetry.dependencies] python = ">=3.8,<3.11" -flwr-nightly = ">=1.0,<2.0" +flwr-nightly = { extras = ["simulation"], version = ">=1.0,<2.0" } flwr-datasets = ">=0.0.2,<1.0.0" xgboost = ">=2.0.0,<3.0.0" diff --git a/examples/xgboost-comprehensive/requirements.txt b/examples/xgboost-comprehensive/requirements.txt index c37ac2b6ad6d..360fbfb066c5 100644 --- a/examples/xgboost-comprehensive/requirements.txt +++ b/examples/xgboost-comprehensive/requirements.txt @@ -1,3 +1,3 @@ -flwr-nightly>=1.0, <2.0 +flwr-nightly[simulation]>=1.0, <2.0 flwr-datasets>=0.0.2, <1.0.0 xgboost>=2.0.0, <3.0.0 diff --git a/examples/xgboost-comprehensive/run_bagging.sh b/examples/xgboost-comprehensive/run_bagging.sh index 7920f6bf5e55..e853a4ef19cb 100755 --- a/examples/xgboost-comprehensive/run_bagging.sh +++ b/examples/xgboost-comprehensive/run_bagging.sh @@ -3,8 +3,8 @@ set -e cd "$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"/ echo "Starting server" -python3 server.py --pool-size=5 --num-rounds=50 --num-clients-per-round=5 --centralised-eval & -sleep 15 # Sleep for 15s to give the server enough time to start +python3 server.py --pool-size=5 --num-rounds=30 --num-clients-per-round=5 --centralised-eval & +sleep 30 # Sleep for 30s to give the server enough time to start for i in `seq 0 4`; do echo "Starting client $i" diff --git a/examples/xgboost-comprehensive/server.py b/examples/xgboost-comprehensive/server.py index 1cf4ba79fa50..c6986dc63ce4 100644 --- a/examples/xgboost-comprehensive/server.py +++ b/examples/xgboost-comprehensive/server.py @@ -1,19 +1,19 @@ import warnings -from typing import Dict, List, Optional from logging import INFO -import xgboost as xgb import flwr as fl from flwr.common.logger import log -from flwr.common import Parameters, Scalar from flwr_datasets import FederatedDataset -from flwr.server.strategy import FedXgbBagging -from flwr.server.strategy import FedXgbCyclic -from flwr.server.client_proxy import ClientProxy -from flwr.server.criterion import Criterion -from flwr.server.client_manager import SimpleClientManager - -from utils import server_args_parser, BST_PARAMS +from flwr.server.strategy import FedXgbBagging, FedXgbCyclic + +from utils import server_args_parser +from server_utils import ( + eval_config, + fit_config, + evaluate_metrics_aggregation, + get_evaluate_fn, + CyclicClientManager, +) from dataset import resplit, transform_dataset_to_dmatrix @@ -34,97 +34,11 @@ fds = FederatedDataset( dataset="jxie/higgs", partitioners={"train": 20}, resplitter=resplit ) + log(INFO, "Loading centralised test set...") test_set = fds.load_full("test") test_set.set_format("numpy") test_dmatrix = transform_dataset_to_dmatrix(test_set) -# Hyper-parameters used for initialisation -params = BST_PARAMS - - -def eval_config(rnd: int) -> Dict[str, str]: - """Return a configuration with global epochs.""" - config = { - "global_round": str(rnd), - } - return config - - -def evaluate_metrics_aggregation(eval_metrics): - """Return an aggregated metric (AUC) for evaluation.""" - total_num = sum([num for num, _ in eval_metrics]) - auc_aggregated = ( - sum([metrics["AUC"] * num for num, metrics in eval_metrics]) / total_num - ) - metrics_aggregated = {"AUC": auc_aggregated} - return metrics_aggregated - - -def get_evaluate_fn(test_data): - """Return a function for centralised evaluation.""" - - def evaluate_fn( - server_round: int, parameters: Parameters, config: Dict[str, Scalar] - ): - # If at the first round, skip the evaluation - if server_round == 0: - return 0, {} - else: - bst = xgb.Booster(params=params) - for para in parameters.tensors: - para_b = bytearray(para) - - # Load global model - bst.load_model(para_b) - # Run evaluation - eval_results = bst.eval_set( - evals=[(test_data, "valid")], - iteration=bst.num_boosted_rounds() - 1, - ) - auc = round(float(eval_results.split("\t")[1].split(":")[1]), 4) - log(INFO, f"AUC = {auc} at round {server_round}") - - return 0, {"AUC": auc} - - return evaluate_fn - - -class CyclicClientManager(SimpleClientManager): - """Provides a cyclic client selection rule.""" - - def sample( - self, - num_clients: int, - min_num_clients: Optional[int] = None, - criterion: Optional[Criterion] = None, - ) -> List[ClientProxy]: - """Sample a number of Flower ClientProxy instances.""" - - # Block until at least num_clients are connected. - if min_num_clients is None: - min_num_clients = num_clients - self.wait_for(min_num_clients) - - # Sample clients which meet the criterion - available_cids = list(self.clients) - if criterion is not None: - available_cids = [ - cid for cid in available_cids if criterion.select(self.clients[cid]) - ] - - if num_clients > len(available_cids): - log( - INFO, - "Sampling failed: number of available clients" - " (%s) is less than number of requested clients (%s).", - len(available_cids), - num_clients, - ) - return [] - - # Return all available clients - return [self.clients[cid] for cid in available_cids] - # Define strategy if train_method == "bagging": @@ -137,6 +51,7 @@ def sample( min_evaluate_clients=num_evaluate_clients if not centralised_eval else 0, fraction_evaluate=1.0 if not centralised_eval else 0.0, on_evaluate_config_fn=eval_config, + on_fit_config_fn=fit_config, evaluate_metrics_aggregation_fn=evaluate_metrics_aggregation if not centralised_eval else None, @@ -149,6 +64,7 @@ def sample( fraction_evaluate=1.0, evaluate_metrics_aggregation_fn=evaluate_metrics_aggregation, on_evaluate_config_fn=eval_config, + on_fit_config_fn=fit_config, ) # Start Flower server diff --git a/examples/xgboost-comprehensive/server_utils.py b/examples/xgboost-comprehensive/server_utils.py new file mode 100644 index 000000000000..35a31bd9adac --- /dev/null +++ b/examples/xgboost-comprehensive/server_utils.py @@ -0,0 +1,101 @@ +from typing import Dict, List, Optional +from logging import INFO +import xgboost as xgb +from flwr.common.logger import log +from flwr.common import Parameters, Scalar +from flwr.server.client_manager import SimpleClientManager +from flwr.server.client_proxy import ClientProxy +from flwr.server.criterion import Criterion +from utils import BST_PARAMS + + +def eval_config(rnd: int) -> Dict[str, str]: + """Return a configuration with global epochs.""" + config = { + "global_round": str(rnd), + } + return config + + +def fit_config(rnd: int) -> Dict[str, str]: + """Return a configuration with global epochs.""" + config = { + "global_round": str(rnd), + } + return config + + +def evaluate_metrics_aggregation(eval_metrics): + """Return an aggregated metric (AUC) for evaluation.""" + total_num = sum([num for num, _ in eval_metrics]) + auc_aggregated = ( + sum([metrics["AUC"] * num for num, metrics in eval_metrics]) / total_num + ) + metrics_aggregated = {"AUC": auc_aggregated} + return metrics_aggregated + + +def get_evaluate_fn(test_data): + """Return a function for centralised evaluation.""" + + def evaluate_fn( + server_round: int, parameters: Parameters, config: Dict[str, Scalar] + ): + # If at the first round, skip the evaluation + if server_round == 0: + return 0, {} + else: + bst = xgb.Booster(params=BST_PARAMS) + for para in parameters.tensors: + para_b = bytearray(para) + + # Load global model + bst.load_model(para_b) + # Run evaluation + eval_results = bst.eval_set( + evals=[(test_data, "valid")], + iteration=bst.num_boosted_rounds() - 1, + ) + auc = round(float(eval_results.split("\t")[1].split(":")[1]), 4) + log(INFO, f"AUC = {auc} at round {server_round}") + + return 0, {"AUC": auc} + + return evaluate_fn + + +class CyclicClientManager(SimpleClientManager): + """Provides a cyclic client selection rule.""" + + def sample( + self, + num_clients: int, + min_num_clients: Optional[int] = None, + criterion: Optional[Criterion] = None, + ) -> List[ClientProxy]: + """Sample a number of Flower ClientProxy instances.""" + + # Block until at least num_clients are connected. + if min_num_clients is None: + min_num_clients = num_clients + self.wait_for(min_num_clients) + + # Sample clients which meet the criterion + available_cids = list(self.clients) + if criterion is not None: + available_cids = [ + cid for cid in available_cids if criterion.select(self.clients[cid]) + ] + + if num_clients > len(available_cids): + log( + INFO, + "Sampling failed: number of available clients" + " (%s) is less than number of requested clients (%s).", + len(available_cids), + num_clients, + ) + return [] + + # Return all available clients + return [self.clients[cid] for cid in available_cids] diff --git a/examples/xgboost-comprehensive/sim.py b/examples/xgboost-comprehensive/sim.py new file mode 100644 index 000000000000..ec05b566dd95 --- /dev/null +++ b/examples/xgboost-comprehensive/sim.py @@ -0,0 +1,188 @@ +import warnings +from logging import INFO +import xgboost as xgb +from tqdm import tqdm + +import flwr as fl +from flwr_datasets import FederatedDataset +from flwr.common.logger import log +from flwr.server.strategy import FedXgbBagging, FedXgbCyclic + +from dataset import ( + instantiate_partitioner, + train_test_split, + transform_dataset_to_dmatrix, + separate_xy, + resplit, +) +from utils import ( + sim_args_parser, + NUM_LOCAL_ROUND, + BST_PARAMS, +) +from server_utils import ( + eval_config, + fit_config, + evaluate_metrics_aggregation, + get_evaluate_fn, + CyclicClientManager, +) +from client_utils import XgbClient + + +warnings.filterwarnings("ignore", category=UserWarning) + + +def get_client_fn( + train_data_list, valid_data_list, train_method, params, num_local_round +): + """Return a function to construct a client. + + The VirtualClientEngine will execute this function whenever a client is sampled by + the strategy to participate. + """ + + def client_fn(cid: str) -> fl.client.Client: + """Construct a FlowerClient with its own dataset partition.""" + x_train, y_train = train_data_list[int(cid)][0] + x_valid, y_valid = valid_data_list[int(cid)][0] + + # Reformat data to DMatrix + train_dmatrix = xgb.DMatrix(x_train, label=y_train) + valid_dmatrix = xgb.DMatrix(x_valid, label=y_valid) + + # Fetch the number of examples + num_train = train_data_list[int(cid)][1] + num_val = valid_data_list[int(cid)][1] + + # Create and return client + return XgbClient( + train_dmatrix, + valid_dmatrix, + num_train, + num_val, + num_local_round, + params, + train_method, + ) + + return client_fn + + +def main(): + # Parse arguments for experimental settings + args = sim_args_parser() + + # Load (HIGGS) dataset and conduct partitioning + partitioner = instantiate_partitioner( + partitioner_type=args.partitioner_type, num_partitions=args.pool_size + ) + fds = FederatedDataset( + dataset="jxie/higgs", + partitioners={"train": partitioner}, + resplitter=resplit, + ) + + # Load centralised test set + if args.centralised_eval or args.centralised_eval_client: + log(INFO, "Loading centralised test set...") + test_data = fds.load_full("test") + test_data.set_format("numpy") + num_test = test_data.shape[0] + test_dmatrix = transform_dataset_to_dmatrix(test_data) + + # Load partitions and reformat data to DMatrix for xgboost + log(INFO, "Loading client local partitions...") + train_data_list = [] + valid_data_list = [] + + # Load and process all client partitions. This upfront cost is amortized soon + # after the simulation begins since clients wont need to preprocess their partition. + for node_id in tqdm(range(args.pool_size), desc="Extracting client partition"): + # Extract partition for client with node_id + partition = fds.load_partition(node_id=node_id, split="train") + partition.set_format("numpy") + + if args.centralised_eval_client: + # Use centralised test set for evaluation + train_data = partition + num_train = train_data.shape[0] + x_test, y_test = separate_xy(test_data) + valid_data_list.append(((x_test, y_test), num_test)) + else: + # Train/test splitting + train_data, valid_data, num_train, num_val = train_test_split( + partition, test_fraction=args.test_fraction, seed=args.seed + ) + x_valid, y_valid = separate_xy(valid_data) + valid_data_list.append(((x_valid, y_valid), num_val)) + + x_train, y_train = separate_xy(train_data) + train_data_list.append(((x_train, y_train), num_train)) + + # Define strategy + if args.train_method == "bagging": + # Bagging training + strategy = FedXgbBagging( + evaluate_function=get_evaluate_fn(test_dmatrix) + if args.centralised_eval + else None, + fraction_fit=(float(args.num_clients_per_round) / args.pool_size), + min_fit_clients=args.num_clients_per_round, + min_available_clients=args.pool_size, + min_evaluate_clients=args.num_evaluate_clients + if not args.centralised_eval + else 0, + fraction_evaluate=1.0 if not args.centralised_eval else 0.0, + on_evaluate_config_fn=eval_config, + on_fit_config_fn=fit_config, + evaluate_metrics_aggregation_fn=evaluate_metrics_aggregation + if not args.centralised_eval + else None, + ) + else: + # Cyclic training + strategy = FedXgbCyclic( + fraction_fit=1.0, + min_available_clients=args.pool_size, + fraction_evaluate=1.0, + evaluate_metrics_aggregation_fn=evaluate_metrics_aggregation, + on_evaluate_config_fn=eval_config, + on_fit_config_fn=fit_config, + ) + + # Resources to be assigned to each virtual client + # In this example we use CPU by default + client_resources = { + "num_cpus": args.num_cpus_per_client, + "num_gpus": 0.0, + } + + # Hyper-parameters for xgboost training + num_local_round = NUM_LOCAL_ROUND + params = BST_PARAMS + + # Setup learning rate + if args.train_method == "bagging" and args.scaled_lr: + new_lr = params["eta"] / args.pool_size + params.update({"eta": new_lr}) + + # Start simulation + fl.simulation.start_simulation( + client_fn=get_client_fn( + train_data_list, + valid_data_list, + args.train_method, + params, + num_local_round, + ), + num_clients=args.pool_size, + client_resources=client_resources, + config=fl.server.ServerConfig(num_rounds=args.num_rounds), + strategy=strategy, + client_manager=CyclicClientManager() if args.train_method == "cyclic" else None, + ) + + +if __name__ == "__main__": + main() diff --git a/examples/xgboost-comprehensive/utils.py b/examples/xgboost-comprehensive/utils.py index 8acdbbb88a7e..102587f4266d 100644 --- a/examples/xgboost-comprehensive/utils.py +++ b/examples/xgboost-comprehensive/utils.py @@ -1,6 +1,8 @@ import argparse +# Hyper-parameters for xgboost training +NUM_LOCAL_ROUND = 1 BST_PARAMS = { "objective": "binary:logistic", "eta": 0.1, # Learning rate @@ -52,7 +54,12 @@ def client_args_parser(): parser.add_argument( "--centralised-eval", action="store_true", - help="Conduct centralised evaluation (True), or client evaluation on hold-out data (False).", + help="Conduct evaluation on centralised test set (True), or on hold-out data (False).", + ) + parser.add_argument( + "--scaled-lr", + action="store_true", + help="Perform scaled learning rate based on the number of clients (True).", ) args = parser.parse_args() @@ -96,3 +103,78 @@ def server_args_parser(): args = parser.parse_args() return args + + +def sim_args_parser(): + """Parse arguments to define experimental settings on server side.""" + parser = argparse.ArgumentParser() + + parser.add_argument( + "--train-method", + default="bagging", + type=str, + choices=["bagging", "cyclic"], + help="Training methods selected from bagging aggregation or cyclic training.", + ) + + # Server side + parser.add_argument( + "--pool-size", default=5, type=int, help="Number of total clients." + ) + parser.add_argument( + "--num-rounds", default=30, type=int, help="Number of FL rounds." + ) + parser.add_argument( + "--num-clients-per-round", + default=5, + type=int, + help="Number of clients participate in training each round.", + ) + parser.add_argument( + "--num-evaluate-clients", + default=5, + type=int, + help="Number of clients selected for evaluation.", + ) + parser.add_argument( + "--centralised-eval", + action="store_true", + help="Conduct centralised evaluation (True), or client evaluation on hold-out data (False).", + ) + parser.add_argument( + "--num-cpus-per-client", + default=2, + type=int, + help="Number of CPUs used for per client.", + ) + + # Client side + parser.add_argument( + "--partitioner-type", + default="uniform", + type=str, + choices=["uniform", "linear", "square", "exponential"], + help="Partitioner types.", + ) + parser.add_argument( + "--seed", default=42, type=int, help="Seed used for train/test splitting." + ) + parser.add_argument( + "--test-fraction", + default=0.2, + type=float, + help="Test fraction for train/test splitting.", + ) + parser.add_argument( + "--centralised-eval-client", + action="store_true", + help="Conduct evaluation on centralised test set (True), or on hold-out data (False).", + ) + parser.add_argument( + "--scaled-lr", + action="store_true", + help="Perform scaled learning rate based on the number of clients (True).", + ) + + args = parser.parse_args() + return args From 938e3af4f5181f33bce6ccf6b57e9db711f9f0ba Mon Sep 17 00:00:00 2001 From: Charles Beauville Date: Thu, 1 Feb 2024 13:42:11 +0100 Subject: [PATCH 066/113] Add PR titles by default in the change log (#2887) --- src/py/flwr_tool/update_changelog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr_tool/update_changelog.py b/src/py/flwr_tool/update_changelog.py index bbd5c7f3dc7b..a158cca21765 100644 --- a/src/py/flwr_tool/update_changelog.py +++ b/src/py/flwr_tool/update_changelog.py @@ -62,7 +62,7 @@ def _extract_changelog_entry(pr_info): f"{CHANGELOG_SECTION_HEADER}(.+?)(?=##|$)", pr_info.body, re.DOTALL ) if not entry_match: - return None, "general" + return None, None entry_text = entry_match.group(1).strip() From 592571657bbbbc26e56b769fbc2e6656192b4256 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 12:56:58 +0000 Subject: [PATCH 067/113] Update pytorch-lightning requirement in /e2e/pytorch-lightning (#2751) Updates the requirements on [pytorch-lightning](https://github.com/Lightning-AI/lightning) to permit the latest version. - [Release notes](https://github.com/Lightning-AI/lightning/releases) - [Commits](https://github.com/Lightning-AI/lightning/compare/1.6.0...2.1.3) --- updated-dependencies: - dependency-name: pytorch-lightning dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Taner Topal --- e2e/pytorch-lightning/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/pytorch-lightning/pyproject.toml b/e2e/pytorch-lightning/pyproject.toml index e79eb72a56df..951349c03a04 100644 --- a/e2e/pytorch-lightning/pyproject.toml +++ b/e2e/pytorch-lightning/pyproject.toml @@ -11,5 +11,5 @@ authors = ["The Flower Authors "] [tool.poetry.dependencies] python = "^3.8" flwr = { path = "../../", develop = true, extras = ["simulation"] } -pytorch-lightning = "1.6.0" +pytorch-lightning = "2.1.3" torchvision = "0.14.1" From 5473a9d1f87cb3d22e55986ad16456403d365f34 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 14:11:03 +0100 Subject: [PATCH 068/113] Update clang-format requirement from ==17.0.4 to ==17.0.6 (#2837) Updates the requirements on [clang-format](https://github.com/ssciwr/clang-format-wheel) to permit the latest version. - [Release notes](https://github.com/ssciwr/clang-format-wheel/releases) - [Commits](https://github.com/ssciwr/clang-format-wheel/compare/v17.0.4...v17.0.6) --- updated-dependencies: - dependency-name: clang-format dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index b944b3e98bfb..f121ac30f44d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -83,7 +83,7 @@ types-dataclasses = "==0.6.6" types-protobuf = "==3.19.18" types-requests = "==2.31.0.20240125" types-setuptools = "==69.0.0.20240125" -clang-format = "==17.0.4" +clang-format = "==17.0.6" isort = "==5.13.2" black = { version = "==23.10.1", extras = ["jupyter"] } docformatter = "==1.7.5" From 038cf759c15dbe2d7cd6c5b9ee8de7263ad6e316 Mon Sep 17 00:00:00 2001 From: Yahia Salaheldin Shaaban <62369984+yehias21@users.noreply.github.com> Date: Thu, 1 Feb 2024 15:22:34 +0200 Subject: [PATCH 069/113] Fedpara updated (#2722) Co-authored-by: Omar Mokhtar Co-authored-by: Roeia Amr <60478505+Roeia99@users.noreply.github.com> Co-authored-by: Yahia Shaaban Co-authored-by: Taner Topal Co-authored-by: jafermarq --- README.md | 1 + baselines/fedpara/.gitignore | 4 + baselines/fedpara/LICENSE | 202 ++++++++ baselines/fedpara/README.md | 185 +++++++ baselines/fedpara/_static/Cifar100_iid.jpeg | Bin 0 -> 38597 bytes .../fedpara/_static/Cifar100_noniid.jpeg | Bin 0 -> 39653 bytes baselines/fedpara/_static/Cifar10_iid.jpeg | Bin 0 -> 39653 bytes baselines/fedpara/_static/Cifar10_noniid.jpeg | Bin 0 -> 40363 bytes .../_static/non-iid_mnist_personalization.png | Bin 0 -> 17118 bytes baselines/fedpara/fedpara/__init__.py | 1 + baselines/fedpara/fedpara/client.py | 197 ++++++++ baselines/fedpara/fedpara/conf/cifar10.yaml | 43 ++ baselines/fedpara/fedpara/conf/cifar100.yaml | 42 ++ .../fedpara/fedpara/conf/mnist_fedavg.yaml | 38 ++ .../fedpara/fedpara/conf/mnist_fedper.yaml | 45 ++ .../fedpara/fedpara/conf/mnist_pfedpara.yaml | 41 ++ baselines/fedpara/fedpara/dataset.py | 139 +++++ .../fedpara/fedpara/dataset_preparation.py | 160 ++++++ baselines/fedpara/fedpara/main.py | 124 +++++ baselines/fedpara/fedpara/models.py | 478 ++++++++++++++++++ baselines/fedpara/fedpara/server.py | 77 +++ baselines/fedpara/fedpara/strategy.py | 5 + baselines/fedpara/fedpara/utils.py | 161 ++++++ baselines/fedpara/pyproject.toml | 142 ++++++ doc/source/ref-changelog.md | 2 + 25 files changed, 2087 insertions(+) create mode 100644 baselines/fedpara/.gitignore create mode 100644 baselines/fedpara/LICENSE create mode 100644 baselines/fedpara/README.md create mode 100644 baselines/fedpara/_static/Cifar100_iid.jpeg create mode 100644 baselines/fedpara/_static/Cifar100_noniid.jpeg create mode 100644 baselines/fedpara/_static/Cifar10_iid.jpeg create mode 100644 baselines/fedpara/_static/Cifar10_noniid.jpeg create mode 100644 baselines/fedpara/_static/non-iid_mnist_personalization.png create mode 100644 baselines/fedpara/fedpara/__init__.py create mode 100644 baselines/fedpara/fedpara/client.py create mode 100644 baselines/fedpara/fedpara/conf/cifar10.yaml create mode 100644 baselines/fedpara/fedpara/conf/cifar100.yaml create mode 100644 baselines/fedpara/fedpara/conf/mnist_fedavg.yaml create mode 100644 baselines/fedpara/fedpara/conf/mnist_fedper.yaml create mode 100644 baselines/fedpara/fedpara/conf/mnist_pfedpara.yaml create mode 100644 baselines/fedpara/fedpara/dataset.py create mode 100644 baselines/fedpara/fedpara/dataset_preparation.py create mode 100644 baselines/fedpara/fedpara/main.py create mode 100644 baselines/fedpara/fedpara/models.py create mode 100644 baselines/fedpara/fedpara/server.py create mode 100644 baselines/fedpara/fedpara/strategy.py create mode 100644 baselines/fedpara/fedpara/utils.py create mode 100644 baselines/fedpara/pyproject.toml diff --git a/README.md b/README.md index 8e32fcde22a0..17a96ddab527 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,7 @@ Flower Baselines is a collection of community-contributed projects that reproduc - [MOON](https://github.com/adap/flower/tree/main/baselines/moon) - [niid-Bench](https://github.com/adap/flower/tree/main/baselines/niid_bench) - [TAMUNA](https://github.com/adap/flower/tree/main/baselines/tamuna) +- [FedPara](https://github.com/adap/flower/tree/main/baselines/fedpara) - [FedAvg](https://github.com/adap/flower/tree/main/baselines/flwr_baselines/flwr_baselines/publications/fedavg_mnist) - [FedOpt](https://github.com/adap/flower/tree/main/baselines/flwr_baselines/flwr_baselines/publications/adaptive_federated_optimization) diff --git a/baselines/fedpara/.gitignore b/baselines/fedpara/.gitignore new file mode 100644 index 000000000000..6244dfada6ee --- /dev/null +++ b/baselines/fedpara/.gitignore @@ -0,0 +1,4 @@ +outputs/ +multirun/ +client_states/ +data/ \ No newline at end of file diff --git a/baselines/fedpara/LICENSE b/baselines/fedpara/LICENSE new file mode 100644 index 000000000000..d64569567334 --- /dev/null +++ b/baselines/fedpara/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/baselines/fedpara/README.md b/baselines/fedpara/README.md new file mode 100644 index 000000000000..068366aa261c --- /dev/null +++ b/baselines/fedpara/README.md @@ -0,0 +1,185 @@ +--- +title: "FedPara: Low-rank Hadamard Product for Communication-Efficient Federated Learning" +url: https://openreview.net/forum?id=d71n4ftoCBy +labels: [image classification, personalization, low-rank training, tensor decomposition] +dataset: [CIFAR-10, CIFAR-100, MNIST] +--- + +# FedPara: Low-rank Hadamard Product for Communication-Efficient Federated Learning + +> Note: If you use this baseline in your work, please remember to cite the original authors of the paper as well as the Flower paper. + +**Paper:** [openreview.net/forum?id=d71n4ftoCBy](https://openreview.net/forum?id=d71n4ftoCBy) + +**Authors:** Nam Hyeon-Woo, Moon Ye-Bin, Tae-Hyun Oh + +**Abstract:** In this work, we propose a communication-efficient parameterization, FedPara, +for federated learning (FL) to overcome the burdens on frequent model uploads +and downloads. Our method re-parameterizes weight parameters of layers using +low-rank weights followed by the Hadamard product. Compared to the conventional low-rank parameterization, our FedPara method is not restricted to lowrank constraints, and thereby it has a far larger capacity. This property enables to +achieve comparable performance while requiring 3 to 10 times lower communication costs than the model with the original layers, which is not achievable by +the traditional low-rank methods. The efficiency of our method can be further improved by combining with other efficient FL optimizers. In addition, we extend +our method to a personalized FL application, pFedPara, which separates parameters into global and local ones. We show that pFedPara outperforms competing +personalized FL methods with more than three times fewer parameters. Project +page: https://github.com/South-hw/FedPara_ICLR22 + + + +## About this baseline + +**What’s implemented:** The code in this directory replicates the experiments in FedPara paper implementing the Low-rank scheme for Convolution module. + +Specifically, it replicates the results for CIFAR-10 and CIFAR-100 in Figure 3 and the results for MNIST in Figure 5(c). + + +**Datasets:** CIFAR-10, CIFAR-100, MNIST from PyTorch's Torchvision + +**Hardware Setup:** The experiments have been conducted on our server with the following specs: + +- **GPU:** 1x RTX A6000 GPU with 48GB VRAM +- **CPU:** 1x24 cores Intel Xeon(R) 6248R +- **RAM:** 150 GB + +On a machine with RTX 3090Ti (24GB VRAM) it takes approximately 1h to run each CIFAR-10/100 experiment while using < 12GB of VRAM. You can lower the VRAM footprint my reducing the number of clients allowed to run in parallel in your GPU (do this by raising `client_resources.num_gpus`). + + +**Contributors:** Yahia Salaheldin Shaaban, Omar Mokhtar and Roeia Amr + + +## Experimental Setup + +**Task:** Image classification + +**Model:** This baseline implements VGG16 with group normalization. + +**Dataset:** + +| Dataset | #classes | #partitions | partitioning method IID | partitioning method non-IID | +|:---------|:--------:|:-----------:|:----------------------:| :----------------------:| +| CIFAR-10 | 10 | 100 | random split | Dirichlet distribution ($\alpha=0.5$)| +| CIFAR-100 | 100 | 50 | random split| Dirichlet distribution ($\alpha=0.5$)| + + +**Training Hyperparameters:** + +| | Cifar10 IID | Cifar10 Non-IID | Cifar100 IID | Cifar100 Non-IID | MNIST | +|---|-------|-------|------|-------|----------| +| Fraction of client (K) | 16 | 16 | 8 | 8 | 10 | +| Total rounds (T) | 200 | 200 | 400 | 400 | 100 | +| Number of SGD epochs (E) | 10 | 5 | 10 | 5 | 5 | +| Batch size (B) | 64 | 64 | 64 | 64 | 10 | +| Initial learning rate (η) | 0.1 | 0.1 | 0.1 | 0.1 | 0.1-0.01 | +| Learning rate decay (τ) | 0.992 | 0.992 | 0.992| 0.992 | 0.999 | +| Regularization coefficient (λ) | 1 | 1 | 1 | 1 | 0 | + +As for the parameters ratio ($\gamma$) we use the following model sizes. As in the paper, $\gamma=0.1$ is used for CIFAR-10 and $\gamma=0.4$ for CIFAR-100: + +| Parameters ratio ($\gamma$) | CIFAR-10 | CIFAR-100 | +|----------|--------|--------| +| 1.0 (original) | 15.25M | 15.30M | +| 0.1 | 1.55M | - | +| 0.4 | - | 4.53M | + + +### Notes: +- Notably, Fedpara's low-rank training technique heavily relies on initialization, with our experiments revealing that employing a 'Fan-in' He initialization (or Kaiming) renders the model incapable of convergence, resulting in a performance akin to that of a random classifier. We found that only Fan-out initialization yielded the anticipated results, and we postulated that this is attributed to the variance conservation during backward propagation. + +- The paper lacks explicit guidance on calculating the rank, aside from the "Rank_min - Rank_max" equation. To address this, we devised an equation aligning with the literature's explanation and constraint, solving a quadratic equation to determine max_rank and utilizing proposition 2 from the paper to establish min_rank. + +- The Jacobian correction was not incorporated into our implementation, primarily due to the lack of explicit instructions in the paper regarding the specific implementation of the dual update principle mentioned in the Jacobian correction section. + +- It was observed that data generation is crutial for model convergence + +## Environment Setup +To construct the Python environment follow these steps: + +It is assumed that `pyenv` is installed, `poetry` is installed and python 3.10.6 is installed using `pyenv`. Refer to this [documentation](https://flower.dev/docs/baselines/how-to-usef-baselines.html#setting-up-your-machine) to ensure that your machine is ready. + +```bash +# Set Python 3.10 +pyenv local 3.10.6 +# Tell poetry to use python 3.10 +poetry env use 3.10.6 + +# Install the base Poetry environment +poetry install + +# Activate the environment +poetry shell +``` + +## Running the Experiments + +Running `FedPara` is easy. You can run it with default parameters directly or by tweaking them directly on the command line. Some command examples are shown below. + +```bash +# To run fedpara with default parameters +python -m fedpara.main + +# Run for more rounds and a different number of local epochs +python -m fedpara.main num_rounds=2024 num_epochs=1 + +# Choose parameterization scheme: lowrank or original (normal weights) +python -m fedpara.main model.param_type=standard # or lowrank (default) + +# Choosing between non IID and IID scheme +python -m fedpara.main dataset_config.partition=iid # or non-iid (default) + +# Choosing the ratio (lambda) of number of parameters to communicate +python -m fedpara.main model.ratio=0.1 + +# Choosing the CIFAR-100 config +python -m fedpara.main --config-name cifar100 # change settings as shown above if desired +``` + +## Expected Results + +To reproduce the curves shown below (which correspond to those in Figure 3 in the paper), run the following commands. Experiments running with `model.param_type=lowrank` correspond to those with `-FedPara` in the legend of the figures below. Those with `model.param_type=standard` are labelled with the `-orig` (as original) tag. + +```bash +# To run fedpara for non-iid CIFAR-10 on vgg16 for lowrank and original schemes +python -m fedpara.main --multirun model.param_type=standard,lowrank +# To run fedpara for non-iid CIFAR-100 on vgg16 for lowrank and original schemes +python -m fedpara.main --config-name cifar100 --multirun model.param_type=standard,lowrank +# To run fedpara for iid CIFAR-10 on vgg16 for lowrank and original schemes +python -m fedpara.main --multirun model.param_type=standard,lowrank num_epochs=10 dataset_config.partition=iid +# To run fedpara for iid CIFAR-100 on vgg16 for lowrank and original schemes +python -m fedpara.main --config-name cifar100 --multirun model.param_type=standard,lowrank num_epochs=10 dataset_config.partition=iid +# To run fedavg for non-iid MINST on FC +python -m fedpara.main --config-name mnist_fedavg +# To run fedper for non-iid MINST on FC +python -m fedpara.main --config-name mnist_fedper +# To run pfedpara for non-iid MINST on FC +python -m fedpara.main --config-name mnist_pfedpara +``` + +#### Communication Cost: +Communication costs as measured as described in the paper: +*"FL evaluation typically measures the required rounds to achieve the target accuracy as communication costs, but we instead assess total transferred bit sizes, 2 × +(#participants)×(model size)×(#rounds)"* + + +### CIFAR-100 (Accuracy vs Communication Cost) + +| IID | Non-IID | +|:----:|:----:| +|![Cifar100 iid](_static/Cifar100_iid.jpeg) | ![Cifar100 non-iid](_static/Cifar100_noniid.jpeg) | + + +### CIFAR-10 (Accuracy vs Communication Cost) + +| IID | Non-IID | +|:----:|:----:| +|![CIFAR10 iid](_static/Cifar10_iid.jpeg) | ![CIFAR10 non-iid](_static/Cifar10_noniid.jpeg) | + +### NON-IID MINST (FedAvg vs FedPer vs pFedPara) + +The only federated averaging (FedAvg) implementation replicates the results outlined in the paper. However, challenges with convergence were encountered when applying `pFedPara` and `FedPer` methods. + +![Personalization algorithms](_static/non-iid_mnist_personalization.png) + +## Code Acknowledgments +Our code is inspired from these repos: +- [Fedpara low rank tensor CNN class structure](https://github.com/South-hw/FedPara_ICLR22) +- [Non-IID mnist data preparation](https://github.com/nimeshagrawal/FedAvg-Pytorch) +- [Cifar non IID data generation](https://github.com/guobbin/PFL-MoE) diff --git a/baselines/fedpara/_static/Cifar100_iid.jpeg b/baselines/fedpara/_static/Cifar100_iid.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..c8b94f94670dbb3b8e0b58411639a8b34366230d GIT binary patch literal 38597 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