diff --git a/.github/workflows/datasets.yml b/.github/workflows/datasets.yml index 47e9f2aed926..80cece262754 100644 --- a/.github/workflows/datasets.yml +++ b/.github/workflows/datasets.yml @@ -16,6 +16,9 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref == 'refs/heads/main' && github.run_id || github.event.pull_request.number || github.ref }} cancel-in-progress: true +env: + FLWR_TELEMETRY_ENABLED: 0 + defaults: run: working-directory: datasets diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 46430b39561e..73b258e285f6 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -164,6 +164,9 @@ jobs: - name: Run driver test with client authentication if: ${{ matrix.directory == 'bare-client-auth' }} run: ./../test_driver.sh bare client-auth + - name: Run reconnection test with SQLite database + if: ${{ matrix.directory == 'bare' }} + run: ./../test_reconnection.sh sqlite - name: Cache save Python location id: cache-save-python uses: actions/cache/save@v4 diff --git a/.github/workflows/framework.yml b/.github/workflows/framework.yml index 784f04750c5e..feb08229be06 100644 --- a/.github/workflows/framework.yml +++ b/.github/workflows/framework.yml @@ -31,6 +31,8 @@ jobs: steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Bootstrap uses: ./.github/actions/bootstrap with: diff --git a/README.md b/README.md index a010abfcb2f5..5f61d616775b 100644 --- a/README.md +++ b/README.md @@ -153,6 +153,7 @@ Other [examples](https://github.com/adap/flower/tree/main/examples): - [Flower with KaplanMeierFitter from the lifelines library](https://github.com/adap/flower/tree/main/examples/federated-kaplan-meier-fitter) - [Sample Level Privacy with Opacus](https://github.com/adap/flower/tree/main/examples/opacus) - [Sample Level Privacy with TensorFlow-Privacy](https://github.com/adap/flower/tree/main/examples/tensorflow-privacy) +- [Flower with a Tabular Dataset](https://github.com/adap/flower/tree/main/examples/fl-tabular) ## Community diff --git a/benchmarks/flowertune-llm/README.md b/benchmarks/flowertune-llm/README.md new file mode 100644 index 000000000000..0cb69e7ff9c7 --- /dev/null +++ b/benchmarks/flowertune-llm/README.md @@ -0,0 +1,61 @@ +![](_static/flower_llm.jpg) + +# FlowerTune LLM Leaderboard + +This repository guides you through the process of federated LLM instruction tuning with a +pre-trained [Mistral-7B](https://huggingface.co/mistralai/Mistral-7B-v0.3) model across 4 domains --- general NLP, finance, medical and code. + +Please follow the instructions to run and evaluate the federated LLMs. + +## Create a new project + +As the first step, please register a Flower account on [Flower website](https://flower.ai/login). +Assuming `flwr` package is already installed on your system (check [here](https://flower.ai/docs/framework/how-to-install-flower.html) for `flwr` installation). +We provide a single-line command to create a new project directory based on your selected challenge: + +```shell +flwr new --framework=flwrtune --username=your_flower_account +``` + +Then you will see a prompt to ask your project name and the choice of LLM challenges from the set of general NLP, finance, medical and code. +Type your project name and select your preferred challenge, +and then a new project directory will be generated automatically. + +### Structure + +After running `flwr new`, you will see a new directory generated with the following structure: + +```bash + + ├── README.md # <- Instructions + ├── pyproject.toml # <- Environment dependencies + └── + ├── app.py # <- Flower ClientApp/ServerApp build + ├── client.py # <- Flower client constructor + ├── server.py # <- Sever-related functions + ├── models.py # <- Model build + ├── dataset.py # <- Dataset and tokenizer build + ├── conf/config.yaml # <- User configuration + └── conf/static_config.yaml # <- Static configuration +``` + +This can serve as the starting point for you to build up your own federated LLM fine-tuning methods. +Please note that any modification to the content of `conf/static_config.yaml` is strictly prohibited for those who wish to participate in the [LLM Leaderboard](https://flower.ai/benchmarks/llm-leaderboard). +Otherwise, the submission will not be considered. + +## Run FlowerTune LLM challenges + +With a new project directory created, running a baseline challenge can be done by: + +1. Navigate inside the directory that you just created. + + +2. Follow the `Environments setup` section of `README.md` in the project directory to install project dependencies. + + +3. Run the challenge as indicated in the `Running the challenge` section in the `README.md`. + +## Evaluate pre-trained LLMs + +After the LLM fine-tuning finished, evaluate the performance of your pre-trained LLMs +following the `README.md` in `evaluation` directory. diff --git a/benchmarks/flowertune-llm/_static/flower_llm.jpg b/benchmarks/flowertune-llm/_static/flower_llm.jpg new file mode 100644 index 000000000000..96081d9c2ad1 Binary files /dev/null and b/benchmarks/flowertune-llm/_static/flower_llm.jpg differ diff --git a/datasets/README.md b/datasets/README.md index cf5caac3e1cd..1d8014d57ea3 100644 --- a/datasets/README.md +++ b/datasets/README.md @@ -7,6 +7,21 @@ [![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. + + +> [!TIP] +> For complete documentation that includes API docs, how-to guides and tutorials please visit the [Flower Datasets Documentation](https://flower.ai/docs/datasets/) and for full FL example see the [Flower Examples page](https://github.com/adap/flower/tree/main/examples). + +## Installation + +For a complete installation guide visit the [Flower Datasets Documenation](https://flower.ai/docs/datasets/) + +```bash +pip install flwr-datasets[vision] +``` + +## Overview + Flower Datasets library supports: * **downloading datasets** - choose the dataset from Hugging Face's `datasets`, * **partitioning datasets** - customize the partitioning scheme, @@ -21,43 +36,28 @@ Thanks to using Hugging Face's `datasets` used under the hood, Flower Datasets i * Jax, * Arrow. -Create **custom partitioning schemes** or choose from the **implemented partitioning schemes**: +Create **custom partitioning schemes** or choose from the **implemented [partitioning schemes](https://flower.ai/docs/datasets/ref-api/flwr_datasets.partitioner.html#module-flwr_datasets.partitioner)**: + * Partitioner (the abstract base class) `Partitioner` * IID partitioning `IidPartitioner(num_partitions)` -* Natural ID partitioner `NaturalIdPartitioner` +* Dirichlet partitioning `DirichletPartitioner(num_partitions, partition_by, alpha)` +* InnerDirichlet partitioning `InnerDirichletPartitioner(partition_sizes, partition_by, alpha)` +* Natural ID partitioner `NaturalIdPartitioner(partition_by)` * 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` -* more to come in future releases. - -# Installation - -## With pip +* Linear partitioner `LinearPartitioner(num_partitions)` +* Square partitioner `SquarePartitioner(num_partitions)` +* Exponential partitioner `ExponentialPartitioner(num_partitions)` +* more to come in the future releases (contributions are welcome). +

+ Comparison of partitioning schemes. +
+ Comparison of Partitioning Schemes on CIFAR10 +

-Flower Datasets can be installed from PyPi - -```bash -pip install flwr-datasets -``` - -Install with an extension: - -* for image datasets: - -```bash -pip install flwr-datasets[vision] -``` - -* for audio datasets: - -```bash -pip install flwr-datasets[audio] -``` +PS: This plot was generated using a library function (see [flwr_datasets.visualization](https://flower.ai/docs/datasets/ref-api/flwr_datasets.visualization.html) package for more). -If you plan to change the type of the dataset to run the code with your ML framework, make sure to have it installed too. -# Usage +## Usage Flower Datasets exposes the `FederatedDataset` abstraction to represent the dataset needed for federated learning/evaluation/analytics. It has two powerful methods that let you handle the dataset preprocessing: `load_partition(partition_id, split)` and `load_split(split)`. @@ -67,16 +67,16 @@ Here's a basic quickstart example of how to partition the MNIST dataset: from flwr_datasets import FederatedDataset # The train split of the MNIST dataset will be partitioned into 100 partitions -mnist_fds = FederatedDataset("mnist", partitioners={"train": 100} +fds = FederatedDataset("mnist", partitioners={"train": 100}) -mnist_partition_0 = mnist_fds.load_partition(0, "train") +partition = fds.load_partition(0) -centralized_data = mnist_fds.load_split("test") +centralized_data = fds.load_split("test") ``` For more details, please refer to the specific how-to guides or tutorial. They showcase customization and more advanced features. -# Future release +## Future release Here are a few of the things that we will work on in future releases: @@ -85,6 +85,6 @@ Here are a few of the things that we will work on in future releases: * ✅ More out-of-the-box `Partitioner`s. * ✅ 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. +* ✅ Simplification of the dataset transformation to the popular frameworks/types. * Creation of the synthetic data, * Support for Vertical FL. diff --git a/datasets/dev/format.sh b/datasets/dev/format.sh index 8292e0b3ed79..c6977982dd6c 100755 --- a/datasets/dev/format.sh +++ b/datasets/dev/format.sh @@ -3,9 +3,16 @@ set -e cd "$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"/../ # Python -echo "Formatting started" +echo "Formatting started: Python" python -m isort flwr_datasets/ python -m black -q flwr_datasets/ python -m docformatter -i -r flwr_datasets/ python -m ruff check --fix flwr_datasets/ -echo "Formatting done" +echo "Formatting done: Python" + +# Notebooks +echo "Formatting started: Notebooks" +python -m black --ipynb -q doc/source/*.ipynb +KEYS="metadata.celltoolbar metadata.language_info metadata.toc metadata.notify_time metadata.varInspector metadata.accelerator metadata.vscode cell.metadata.id cell.metadata.heading_collapsed cell.metadata.hidden cell.metadata.code_folding cell.metadata.tags cell.metadata.init_cell cell.metadata.vscode cell.metadata.pycharm" +python -m nbstripout --keep-output doc/source/*.ipynb --extra-keys "$KEYS" +echo "Formatting done: Notebooks" diff --git a/datasets/doc/source/_static/readme/comparison_of_partitioning_schemes.png b/datasets/doc/source/_static/readme/comparison_of_partitioning_schemes.png new file mode 100644 index 000000000000..ed2e323ef649 Binary files /dev/null and b/datasets/doc/source/_static/readme/comparison_of_partitioning_schemes.png differ diff --git a/datasets/doc/source/conf.py b/datasets/doc/source/conf.py index 755147bc9e1d..11285c375f96 100644 --- a/datasets/doc/source/conf.py +++ b/datasets/doc/source/conf.py @@ -38,7 +38,7 @@ author = "The Flower Authors" # The full version, including alpha/beta/rc tags -release = "0.1.0" +release = "0.2.0" # -- General configuration --------------------------------------------------- diff --git a/datasets/doc/source/how-to-install-flwr-datasets.rst b/datasets/doc/source/how-to-install-flwr-datasets.rst index d2fd7923a817..c690ffb1b09c 100644 --- a/datasets/doc/source/how-to-install-flwr-datasets.rst +++ b/datasets/doc/source/how-to-install-flwr-datasets.rst @@ -42,5 +42,5 @@ If everything worked, it should print the version of Flower Datasets to the comm .. code-block:: none - 0.0.1 + 0.2.0 diff --git a/datasets/doc/source/how-to-visualize-label-distribution.ipynb b/datasets/doc/source/how-to-visualize-label-distribution.ipynb new file mode 100644 index 000000000000..26db72047cff --- /dev/null +++ b/datasets/doc/source/how-to-visualize-label-distribution.ipynb @@ -0,0 +1,1122 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fb7e89caa9e6d772", + "metadata": {}, + "source": [ + "# Visualize Label Distribution" + ] + }, + { + "cell_type": "markdown", + "id": "67c54a8d7c872547", + "metadata": {}, + "source": [ + "If you partition datasets to simulate heterogeneity through label skew and/or size skew, you can now effortlessly visualize the partitioned dataset using `flwr-datasets`.\n", + "\n", + "In this how-to guide, you'll learn how to visualize and compare partitioned datasets when applying different methods or parameters.\n", + "\n", + "All the described visualization functions are compatible with all ``Partitioner`` you can find in\n", + "[flwr_datasets.partitioner](https://flower.ai/docs/datasets/ref-api/flwr_datasets.partitioner.html#module-flwr_datasets.partitioner)\n" + ] + }, + { + "cell_type": "markdown", + "id": "7220467f2c6ba432", + "metadata": {}, + "source": [ + "## Common Setup" + ] + }, + { + "cell_type": "markdown", + "id": "4e2ad2f0a0f7174d", + "metadata": {}, + "source": [ + "Install Flower Datasets library:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c46514b679f394ce", + "metadata": {}, + "outputs": [], + "source": [ + "! pip install -q \"flwr-datasets[vision]\"" + ] + }, + { + "cell_type": "markdown", + "id": "d7ffd5b6836a5ee0", + "metadata": {}, + "source": [ + "## Plot Label Distribution" + ] + }, + { + "cell_type": "markdown", + "id": "38fbbdfe6b930916", + "metadata": {}, + "source": [ + "### Bar plot" + ] + }, + { + "cell_type": "markdown", + "id": "a5778edf97a7ee04", + "metadata": {}, + "source": [ + "Let's visualize the result of `DirichletPartitioner`.\n", + "We will create a `FederatedDataset` and assign `DirichletPartitioner` to the `train` split:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "42397afaaf50529e", + "metadata": {}, + "outputs": [], + "source": [ + "from flwr_datasets import FederatedDataset\n", + "from flwr_datasets.partitioner import DirichletPartitioner\n", + "from flwr_datasets.visualization import plot_label_distributions\n", + "\n", + "\n", + "fds = FederatedDataset(\n", + " dataset=\"cifar10\",\n", + " partitioners={\n", + " \"train\": DirichletPartitioner(\n", + " num_partitions=10,\n", + " partition_by=\"label\",\n", + " alpha=0.3,\n", + " seed=42,\n", + " min_partition_size=0,\n", + " ),\n", + " },\n", + ")\n", + "\n", + "partitioner = fds.partitioners[\"train\"]" + ] + }, + { + "cell_type": "markdown", + "id": "c4d5855ee8a605d3", + "metadata": {}, + "source": [ + "Once we have the partitioner with the dataset assigned, we are ready to pass it to the plotting function:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f75b48256ed68897", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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ACBkZGSU7kkgIiIileHvb5ISyexjXtVxH1QiIqKqh7+/SUoku8aciIiIiOh9wsSciIiIiEgCmJgTEREREUkAE3MiIiIiIglgYk5EREREJAFMzImIiIiIJEBD1QEQEREpW50N/ZTex59+vyq9DyKq3jhjTkREREQkAUzMiYiIiIgkgIk5EREREZEEMDEnIiIiIpIAJuZERERERBLAxJyIiIiISAKYmBMRERERSQATcyIiIiIiCWBiTkREREQkAUzMiYiIiIgkgIk5EREREZEEMDEnIiIiIpIAJuZERERERBLAxJyIiIiISAKYmBMRERERSQATcyIiIiIiCWBiTkREREQkAUzMiYiIiIgkQEPVARARESlb33pmqg6BiOhfccaciIiIiEgCmJgTEREREUkAE3MiIiIiIglgYk5EREREJAFMzImIiIiIJICJORERERGRBDAxJyIiIiKSACbmREREREQSwMSciIiIiEgCmJgTEREREUkAE3MiIiIiIglgYk5EREREJAFMzImIiIiIJICJORERERGRBDAxJyIiIiKSACbmREREREQSwMSciIiIiEgCmJgTEREREUkAE3MiIiIiIglgYk5EREREJAFMzImIiIiIJICJORERERGRBDAxJyIiIiKSAA1VB0BERKRsk9w7qDoEIqJ/xRlzIiIiIiIJYGJORERERCQBXMpCREREVAnkcjlyc3NVHQZVIk1NTairq5e4PhNzIiIiIiXLzc1FcnIy5HK5qkOhSmZiYgJra2vIZLJ/rcvEnIiIiEiJBEHAgwcPoK6uDjs7O6ipcSXx+0AQBDx//hxpaWkAABsbm3+9hok5ERERkRLl5+fj+fPnsLW1hZ6enqrDoUqkq6sLAEhLS4OlpeW/LmvhRzYiIiIiJSooKAAAaGlpqTgSUoXCD2N5eXn/WpeJOREREVElKMkaY6p+SvO6MzEnIiIiIpIAJuZEREREVCE2btwIExOTcrcjk8mwZ8+ecrdT1TAxJyIiIiKRr68vevfureow3ktMzImIiIiIJEDSiXlBQQGmT58OR0dH6OrqwsnJCbNnz4YgCGIdQRAwY8YM2NjYQFdXF15eXrh165ZCO0+ePMGgQYNgZGQEExMT+Pn5ISsrS6HO5cuX0aFDB+jo6MDOzg7z58+vlDESERERVRWLFy9Go0aNoK+vDzs7O3z99ddFcioA2LNn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i4uLg76+fqX2WdUxMSciIiKiCmdhYaHqEKocLmUhIiIiomLt3LkTjRo1gq6uLszNzeHl5YXs7Gzx/MKFC2FjYwNzc3P4+/sjLy9PPPfmUhaZTIY1a9agW7du0NXVRZ06dbBz587KHI7kMTEnIiIioiIePHiAgQMHYujQoUhMTER0dDT69u0LQRAAACdOnMCdO3dw4sQJREREYOPGjdi4ceM725w+fTr69euHS5cuYdCgQRgwYAASExMrYTRVA5eyEBEREVERDx48QH5+Pvr27Qt7e3sAQKNGjcTzpqamWLlyJdTV1VG/fn306NEDUVFRGD58+Fvb/PTTTzFs2DAAwOzZsxEZGYkVK1Zg9erVyh1MFcEZcyIiIiIqokmTJujcuTMaNWqETz/9FOvXr8fTp0/F8w0aNIC6urp4bGNjg7S0tHe26eHhUeSYM+b/j4k5ERERERWhrq6OyMhIHDp0CG5ublixYgVcXFyQnJwMANDU1FSoL5PJIJfLVRFqtcHEnIiIiIiKJZPJ0K5dOwQHB+PixYvQ0tLC7t27y9ze2bNnixy7urqWN8xqg2vMiYiIiKiI2NhYREVFoUuXLrC0tERsbCwePXoEV1dXXL58uUxt/vLLL3B3d0f79u2xZcsWnDt3Dhs2bKjgyKsuJuZEREREVISRkRFOnTqFpUuXIjMzE/b29li0aBG6deuG7du3l6nN4OBgbNu2DV9//TVsbGzw888/w83NrYIjr7qYmBMRUbVn8aISOtGthD6oWqnsO3GWlqurKw4fPlzsueK2RXx9z3IASElJKVLH1tYWR48erYDoqieuMSciIiIikgAm5kREREREEsClLERERESkdIV3DKW344w5EREREZEEMDEnIiIiIpIAJuZERERERBLAxJyIiIiISAKYmBMRERERSQB3ZVGxCb8PV2r7CzusV2r7RERERFQxOGNOREREREV4enoiMDBQ1WG8VzhjTkRERKQCyv6r+Zv4V3Tp44w5ERERESldbm6uqkOQPCbmRERERFQsuVyOSZMmwczMDNbW1ggKChLP3b17F7169YKBgQGMjIzw2WefITU1VTwfFBSEpk2b4ocffoCjoyN0dHQAADt37kSjRo2gq6sLc3NzeHl5ITs7W7zuhx9+gKurK3R0dFC/fn2sXr260saralzKQkRERETFioiIwPjx4xEbG4uYmBj4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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax, df = plot_label_distributions(\n", + " partitioner,\n", + " label_name=\"label\",\n", + " plot_type=\"bar\",\n", + " size_unit=\"absolute\",\n", + " partition_id_axis=\"x\",\n", + " legend=True,\n", + " verbose_labels=True,\n", + " title=\"Per Partition Labels Distribution\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "be05badab744d9f7", + "metadata": {}, + "source": [ + "You can configure many details directly using the function parameters. The ones that can interest you the most are:\n", + "\n", + "* `size_unit` to have the sizes normalized such that they sum up to 1 and express the fraction of the data in each partition,\n", + "* `legend` and `verbose_labels` in case the dataset has more descriptive names and not numbers,\n", + "* `cmap` to change the values of the bars (for an overview of the available colors, have a look at [link](https://matplotlib.org/stable/users/explain/colors/colormaps.html); check out `cmap=\"tab20b\"`) \n", + "\n", + " And for even greater control, you can specify `plot_kwargs` and `legend_kwargs` as `Dict`, which will be further passed to the `plot` and `legend` functions." + ] + }, + { + "cell_type": "markdown", + "id": "3dbf6dc4ede79f05", + "metadata": {}, + "source": [ + "You can also inspect the exact numbers that were used to create this plot. Three objects are returned (see reference [here](https://flower.ai/docs/datasets/ref-api/flwr_datasets.visualization.plot_label_distributions.html#flwr_datasets.visualization.plot_label_distributions)). Let's inspect the returned DataFrame." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f6edd14d8b260e9e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
airplaneautomobilebirdcatdeerdogfroghorseshiptruck
Partition ID
08177941462212343225456384149
11416697530340903868
2041124543511158421
37621591100511201662198213512175
424371421924004251151477
5677917025255247727445900
6422244863809290380506
7122281159721741038172716825154
825629342751848151122401417
91136107350357126711223
\n", + "
" + ], + "text/plain": [ + " airplane automobile bird cat deer dog frog horse ship \\\n", + "Partition ID \n", + "0 817 794 1462 2123 432 25 456 384 14 \n", + "1 1416 6 97 5 3 0 3409 0 3 \n", + "2 0 4 11 2 454 3 511 15 84 \n", + "3 762 159 1100 51 120 166 2 1982 1351 \n", + "4 2 43 714 2 19 2400 425 1 151 \n", + "5 67 79 170 25 2552 477 27 44 590 \n", + "6 422 2 4 486 380 92 90 380 50 \n", + "7 122 2811 597 2174 1038 1727 1 682 515 \n", + "8 256 29 342 75 1 84 8 1511 2240 \n", + "9 1136 1073 503 57 1 26 71 1 2 \n", + "\n", + " truck \n", + "Partition ID \n", + "0 9 \n", + "1 868 \n", + "2 21 \n", + "3 2175 \n", + "4 477 \n", + "5 0 \n", + "6 6 \n", + "7 4 \n", + "8 1417 \n", + "9 23 " + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df" + ] + }, + { + "cell_type": "markdown", + "id": "2902213a", + "metadata": {}, + "source": [ + "Each row represents a unique partition ID, and the columns represent unique labels (either in the verbose version if `verbose_labels=True` or typically `int` values otherwise, representing the partition IDs).\n", + "That you can index the DataFrame `df[partition_id, label_id]` to get the number of samples in `partition_id` for the specified `label_id.`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8ffe4039", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "714" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.loc[4, \"bird\"]" + ] + }, + { + "cell_type": "markdown", + "id": "2e6c17af529a668f", + "metadata": {}, + "source": [ + "Let's see a plot with `size_unit=\"percent\"`, which is another excellent way to understand the partitions. In this mode, the number of datapoints for each class in a given partition are normalized, so they sum up to 100." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a241894a47f3cc9f", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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SgAAAPsKCwuTu7u7Nm/enGnf999/r5CQEI0ePVr169dXWFiYfv/9d4tjXFxclJ6enl/lFgmFYslHUlKSevToocWLF2vSpEnm9itXrujtt9/We++9p4ceekjSzdv7hYeH64cfftD9999vr5IBAADsws3NTSNHjtSIESPk4uKiJk2a6MKFC/rll18UFhamU6dO6YMPPlCDBg30+eefa82aNRbnlytXTidOnFBCQoLKlCkjb29viwf7IbNCEahjYmLUtm1bRUZGWgTqvXv36saNG4qMjDS3ValSRWXLltXOnTvvGKhTUlKUkpJi3k5MTLRd8QAAoMjJzwet5MaYMWPk5OSksWPH6s8//1RgYKCee+459e7dWy+88IJiY2OVkpKitm3basyYMRo/frz53M6dO2v16tV68MEHdfnyZS1ZskTR0dF2u5bCoMAH6g8++ED79u3T7t27M+07e/asXFxc5Ovra9Hu7++vs2fP3rHPqVOnKi4uLq9LBQAAKBAcHBw0evRojR49OtO+6dOna/r06RZt//58mqurqz7++GNbl1ikFOg11KdPn9agQYO0cuVKubm55Vm/L774oq5cuWJ+nT59Os/6BgAAwL2lQAfqvXv36vz586pbt66cnJzk5OSkbdu2ae7cuXJycpK/v79SU1N1+fJli/POnTt313snurq6ysfHx+IFAAAA5EaBXvLRsmVLHThwwKLtmWeeUZUqVTRy5EgFBwfL2dlZmzdvVufOnSVJhw8f1qlTpxQREWGPkgEAKJL27V2VD6PUzocxgLxXoAO1t7e3qlevbtHm6ekpPz8/c3vv3r01ZMgQlShRQj4+PhowYIAiIiK4wwcAAADyRYEO1Nnx2muvycHBQZ07d1ZKSopatWqlBQsW2LssAADMHvpf3n0OCEDBU+gC9datWy223dzc9Prrr+v111+3T0EAAAC4pxXoDyUCAAAABR2BGgAAALACgRoAAACwAoEaAACgiGnRooXF0w9vV65cOc2ePTvH/Y4fP161a9fOdV1FVaH7UCIAAIC99Xmpcb6O99aU7/O0v927d8vT0zNP+7yXEagBAAXW6lX7bD5Gm9o2HwIocEqWLHnX/Tdu3JCzs3M+VVP4seQDAACgCEpLS1NsbKyKFSum++67T2PGjJFhGJIyL/kwmUxauHChHnvsMXl6emry5MmSpFdeeUX+/v7y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SBkZGapevbpSU1PveI6np2e+jevs7Gz+2mQySZIyMjIkSUlJSXr22Wc1cODATP2XLVvW6hrzGoEaAACgiLl48aIOHz6sxYsXq1mzZpJufsgvN06dOqU///xTQUFBkqQffvhBDg4Oqly5ss3GrVu3rg4ePKiKFSvmqub8RqAGAAAoYooXLy4/Pz+9+eabCgwM1KlTpzRq1Khc9eXm5qaoqCjNmDFDiYmJGjhwoJ544oks10/n1bgjR47U/fffr9jYWPXp00eenp46ePCgNm3apPnz5+fqOmyJNdQAAABFjIODgz744APt3btX1atX1wsvvKBXX301V31VrFhRnTp1Ups2bfTwww+rZs2aWrAg69v75tW4NWvW1LZt23TkyBE1a9ZMderU0dixY82z5AUNM9QAUEStXrXPpv23qW3T7oECLa8ftGILkZGROnjwoEWbYRhZft2iRQuL7dv1799f/fv3z3Lf0qVLczRuuXLlMo3l6+ubqa1Bgwb66quv7lhTQUKgBoAiivvMA0D+YMkHAAAAYAUCNQAAALI0fvz4uz5ZETcV6EA9depUNWjQQN7e3ipVqpQ6dOiQ6Sbi169fV0xMjPz8/OTl5aXOnTvr3LlzdqoYAAAA95oCHai3bdummJgY/fDDD9q0aZNu3Lihhx9+WMnJyeZjXnjhBX366af66KOPtG3bNv3555/q1KmTHasGAADAvaRAfyhxw4YNFttLly5VqVKltHfvXj3wwAO6cuWK3n77bb333nt66KGHJElLlixReHi4fvjhB91///32KBsAABQhd7v7BYq27P7sC/QM9e2uXLkiSSpRooQkae/evbpx44YiIyPNx1SpUkVly5bVzp0779hPSkqKEhMTLV4AAAD/duvR2NeuXbNzJbCXWz/7fz8mPSsFeob63zIyMjR48GA1adJE1atXlySdPXtWLi4u8vX1tTjW399fZ8+evWNfU6dOVVxcnC3LBQAAhZyjo6N8fX11/vx5SZKHh4dMJpOdq0J+MAxD165d0/nz5+Xr6ytHR8e7Hl9oAnVMTIx+/vnnXD+H/t9efPFFDRkyxLydmJio4OBgq/sFAABFy63Ha98K1bi3+Pr6ZvmI9dsVikAdGxurzz77TN9++63KlCljbg8ICFBqaqouX75sMUt97ty5u168q6urXF1dbVkyAAAoAkwmkwIDA1WqVCnd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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax, df = plot_label_distributions(\n", + " partitioner,\n", + " label_name=\"label\",\n", + " plot_type=\"bar\",\n", + " size_unit=\"percent\",\n", + " partition_id_axis=\"x\",\n", + " legend=True,\n", + " verbose_labels=True,\n", + " cmap=\"tab20b\",\n", + " title=\"Per Partition Labels Distribution\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "e7d1fe2e1c0f14c", + "metadata": {}, + "source": [ + "### Heatmap" + ] + }, + { + "cell_type": "markdown", + "id": "ad6a2e53de3cc084", + "metadata": {}, + "source": [ + "You might want to visualize the results of partitioning as a heatmap, which can be especially useful for binary labels. Here's how:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "14a4b4e574866120", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax, df = plot_label_distributions(\n", + " partitioner,\n", + " label_name=\"label\",\n", + " plot_type=\"heatmap\",\n", + " size_unit=\"absolute\",\n", + " partition_id_axis=\"x\",\n", + " legend=True,\n", + " verbose_labels=True,\n", + " title=\"Per Partition Labels Distribution\",\n", + " plot_kwargs={\"annot\": True},\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "5167593e67fa3dbb", + "metadata": {}, + "source": [ + "Note: we used the `plot_kwargs={\"annot\": True}` to add the number directly to the plot." + ] + }, + { + "cell_type": "markdown", + "id": "e2e41273551ac32a", + "metadata": {}, + "source": [ + "If you are a `pandas` fan, then you might be interested that a similar heatmap can be created with the DataFrame object for visualization in jupyter notebook:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fcc90b52bfd650cf", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 airplaneautomobilebirdcatdeerdogfroghorseshiptruck
Partition ID          
08177941462212343225456384149
11416697530340903868
2041124543511158421
37621591100511201662198213512175
424371421924004251151477
5677917025255247727445900
6422244863809290380506
7122281159721741038172716825154
825629342751848151122401417
91136107350357126711223
\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.style.background_gradient(axis=None, cmap=\"Greens\", vmin=0)" + ] + }, + { + "cell_type": "markdown", + "id": "37d85e1b40d54918", + "metadata": {}, + "source": [ + "## Plot Comparison of Label Distributions" + ] + }, + { + "cell_type": "markdown", + "id": "4f49259a3de7dd17", + "metadata": {}, + "source": [ + "Now, once you know how to visualize a single partitioned dataset, you'll learn how to compare a few of them on a single plot.\n", + "\n", + "Let's compare:\n", + "\n", + "- IidPartitioner,\n", + "- DirichletPartitioner,\n", + "- ShardPartitioner\n", + "still using the `cifar10` dataset.\n", + "\n", + "We need to create a list of partitioners. Each partitioner needs to have a dataset assigned to it (it does not have to be the same dataset so you can also compare the same partitioning on different datasets)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9e84a9192a266f3e", + "metadata": {}, + "outputs": [], + "source": [ + "from flwr_datasets import FederatedDataset\n", + "from flwr_datasets.partitioner import (\n", + " IidPartitioner,\n", + " DirichletPartitioner,\n", + " ShardPartitioner,\n", + ")\n", + "\n", + "partitioner_list = []\n", + "title_list = [\"IidPartitioner\", \"DirichletPartitioner\", \"ShardPartitioner\"]\n", + "\n", + "## IidPartitioner\n", + "fds = FederatedDataset(\n", + " dataset=\"cifar10\",\n", + " partitioners={\n", + " \"train\": IidPartitioner(num_partitions=10),\n", + " },\n", + ")\n", + "partitioner_list.append(fds.partitioners[\"train\"])\n", + "\n", + "## DirichletPartitioner\n", + "fds = FederatedDataset(\n", + " dataset=\"cifar10\",\n", + " partitioners={\n", + " \"train\": DirichletPartitioner(\n", + " num_partitions=10,\n", + " partition_by=\"label\",\n", + " alpha=1.0,\n", + " min_partition_size=0,\n", + " ),\n", + " },\n", + ")\n", + "partitioner_list.append(fds.partitioners[\"train\"])\n", + "\n", + "## ShardPartitioner\n", + "fds = FederatedDataset(\n", + " dataset=\"cifar10\",\n", + " partitioners={\n", + " \"train\": ShardPartitioner(\n", + " num_partitions=10, partition_by=\"label\", num_shards_per_partition=2\n", + " )\n", + " },\n", + ")\n", + "partitioner_list.append(fds.partitioners[\"train\"])" + ] + }, + { + "cell_type": "markdown", + "id": "d18bae80", + "metadata": {}, + "source": [ + "Now let's visualize them side by side" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f2ee2864", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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+7wm9ml10URu6LKSlNfiv58hsjTwS4HU5vALzf1+JfVp5zRf2yFQKcczlURERERERKQyFpVERERERESkMhaVREREREREpDKdKypfvHiB4OBgODk5wcTEBM2aNcPFixe1HRYREREREVGZpHNF5dChQ3H06FFs3LgRN27cQNu2beHn54fHj/mgBSIiIiIiouKmU0Vleno6du7cifnz56Nly5Zwd3dHSEgI3N3dER4eru3wiIiIiIiIyhydeqVIVlYWsrOzYWxsrDDexMQEp0+fznOejIwMZGRkyIdTUlI0GiMREREREVFZolNnKi0sLNC0aVPMnj0bT548QXZ2NjZt2oRz587h6dOnec4TFhYGKysr+cfR0bGYoyYiIiIiIiq9dKqoBICNGzdCCIHKlStDKpVi+fLl6Nu3L/T08l6VqVOnIjk5Wf559OhRMUdMRERERERUeunU5a8A4ObmhlOnTiEtLQ0pKSmwt7dH79694erqmmd7qVQKqVRazFESERERERGVDTp3pjKHmZkZ7O3tkZiYiMOHD6Nz587aDomIiIiIiKjM0bkzlYcPH4YQAtWrV8eDBw8wadIkeHp6YtCgQdoOjYiIiIiIqMzRuTOVycnJGDNmDDw9PTFgwAC0aNEChw8fhqGhobZDIyIiIiIiKnN07kxlr1690KtXL22HQURERERERNDBM5VERERERERUckiEEELbQRSnlJQUWFlZITk5GZaWltoOh6hM0HTeMa+Jip8m8445TVT8mHf0PnimkoiIiIiIiFTGopKIiIiIiIhUxqKSiIiIiIiIVMaikoiIiIiIiFTGopKIiIiIiIhUxqKSiIiIiIiIVMaikoiIiIiIiFTGopKIiIiIiIhUxqKSiIiIiIiIVMaikoiIiIiIiFTGopKIiIiIiIhUxqKSiIiIiIiIVMaikoiIiIiIiFTGopKIiIiIiIhUxqKSiIiIiIiIVMaikoiIiIiIiFRmoO0AtGWbVQOYQl+tfTb2Vv/XWcXPSe19AoC0TTW19iep00Ct/SWYqLU7uSvxN9XaX2Rcolr7A4Bd9/5Te585Yi49Vmt/Ivy8Wvt7X9EfecNcX7m8Liy31J0j2qZKjiaYqD9nNEETeahp6s5zdeZ2ScprTfyuJvX66nsvbYdASvhryE5th0ClHM9UEhERERERkcpYVBIREREREZHKWFQSERERERGRylhUEhERERERkcp0qqjMzs7G9OnT4eLiAhMTE7i5uWH27NkQQmg7NCIiIiIiojJJp57+Om/ePISHh2PDhg2oVasWLl26hEGDBsHKygrjxo3TdnhERERERERljk4VlWfPnkXnzp3Rvn17AICzszN+/vln/PHHH1qOjIiIiIiIqGzSqctfmzVrhmPHjuHevXsAgOvXr+P06dMICAjId56MjAykpKQofIiIiIiIiEg9dOpM5RdffIGUlBR4enpCX18f2dnZmDt3Lvr375/vPGFhYQgNDS3GKImIiIiIiMoOnSoqt23bhs2bN+Onn35CrVq1cO3aNQQHB8PBwQEDBw7Mc56pU6diwoQJ8uGUlBQ4OjoWV8hERERERDotOzsbr1+/1nYYVIz09fVhYGAAiUSiVHudKionTZqEL774An369AEA1K5dGw8fPkRYWFi+RaVUKoVUKi3OMImIiIiISoXU1FT8/ffffNtCGWRqagp7e3sYGRkV2lanisqXL19CT0/xNlB9fX3IZDItRUREREREVDplZ2fj77//hqmpKWxtbZU+a0W6TQiBzMxMJCQkICYmBh4eHrlqsHfpVFHZsWNHzJ07F1WrVkWtWrVw9epVLF68GIMHD9Z2aEREREREpcrr168hhICtrS1MTEy0HQ4VIxMTExgaGuLhw4fIzMyEsbFxge11qqhcsWIFpk+fjtGjRyM+Ph4ODg4YMWIEZsyYoe3QiIiIiIhKJZ6hLJsKOzv5Np0qKi0sLLB06VIsXbpU26EQERERERERdOw9lURERERERFSySEQZe5RTSkoKrKyskJycDEtLS22HQ1QmaDrvmNdExU+TececJip+eeXdq1evEBMTAxcXl0LvqdN169evR3BwMJKSkt6rH4lEgt27d6NLly5qiUubirL9eaaSiIiIiIh0XmBgYKko5nQRi0oiIiIiIiJSGYtKIiIiIiIq1RYvXozatWvDzMwMjo6OGD16NFJTU3O127NnDzw8PGBsbAx/f388evRIYfrevXvRoEEDGBsbw9XVFaGhocjKyspzmZmZmQgKCoK9vT2MjY3h5OSEsLAwjayftrGoJCIiIiKiUk1PTw/Lly/HrVu3sGHDBhw/fhyTJ09WaPPy5UvMnTsXP/74I86cOYOkpCT06dNHPv3333/HgAED8Nlnn+H27dtYs2YN1q9fj7lz5+a5zOXL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uqKw40BJyuuE9J/xylADvwhIbSpO4P1kuqAk5XVxuHDhAo4dO4a2bdvCzs4OFy5cQEJCAmrUqIE///xTpT63b9+ORo0aoUWLFti8eTP++OMPrFu3Ts2R664yW1QSEREREVHR/TVkp7ZDKJClpSV+++03LF26FCkpKXBycsKiRYsQEBCArVu3qtRnaGgotmzZgtGjR8Pe3h4///wzatasqebIdReLSiIiIiIiKjVq1KiBQ4cO5Tktr1eHvP1OSgCIjY3N1cbBwQFHjhxRQ3SlE++pJCIiIiIiIpWxqCQiIiIiIiKV6VxR+fjxY3zyySewsbGBiYkJateujUuXLmk7LCIiIiIiKoWEEOjSpYu2wyjRdOqeysTERDRv3hwffvghDh48CFtbW9y/fx/lypXTdmhERERERERlkk4VlfPmzYOjoyMiIiLk41xcXAqcJyMjAxkZGfLhlJQUjcVHRERERERU1ujU5a+//PILGjVqhJ49e8LOzg7169fH2rVrC5wnLCwMVlZW8o+jo2MxRUtERERERFT66VRR+ddffyE8PBweHh44fPgwRo0ahXHjxmHDhg35zjN16lQkJyfLP48ePSrGiImIiIiIiEo3nbr8VSaToVGjRvj6668BAPXr18fNmzexevVqDBw4MM95pFIppFJpcYZJRERERERUZujUmUp7e3vUrFlTYVyNGjUQFxenpYiIiIiIiIjKNp06U9m8eXNERUUpjLt37x6cnJy0FBERERERUdky8fdhxbq8hT4FP0PlXa1atUK9evWwdOlSzQREuejUmcrx48fj/Pnz+Prrr/HgwQP89NNP+O677zBmzBhth0ZERERERFQm6VRR2bhxY+zevRs///wzvLy8MHv2bCxduhT9+/fXdmhERERERFQKZWZmajuEEk+nikoA6NChA27cuIFXr17hzp07GDaseE+/ExERERFRySaTyTB58mSUL18elSpVQkhIiHxaXFwcOnfuDHNzc1haWqJXr1549uyZfHpISAjq1auH77//Hi4uLjA2NgYA7NixA7Vr14aJiQlsbGzg5+eHtLQ0+Xzff/89atSoAWNjY3h6emLVqlXFtr7apvI9lampqYiNjcWLFy9gYWEBFxcXmJmZqTM2IiIiIiKiItuwYQMmTJiACxcu4Ny5cwgMDETz5s3RunVreUF56tQpZGVlYcyYMejduzdO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VBIREREREZHKWFQSERERERGRylhUEhERERERkcpYVBIREREREZHKWFQSERERERGRylhUEhERERERkcpYVBIREREREZHKWFQSERERERGRylhUEhERERERkcpYVBIREREREZHKWFQSERERERGRylhUEhERERERkcpYVBIREREREZHKWFQSERERERGRylhUEhERERERkcpYVBIREREREZHKDLQdgLZss2oAU+irpa/G3ur/Gqv4Oam1P2mbamrpR1KngVr6eVeCiUa6xZX4mxrpNzIuUSP9AsCue/+pvc+YS4/V3icAiPDzGulXVerMa1Vp4nhQVOo+fqhDUY9Byhxr3ue4kXNsUDWXNZGn2pDXsaEk5bX472eILA39giC1mHTrd22HQEpY6LNW2yFQKcczlURERERERKQyFpVERERERESkMhaVREREREREpDKdLCq//fZbODs7w9jYGE2aNMEff/yh7ZCIiIiIiIjKJJ0rKrdu3YoJEyZg5syZuHLlCurWrQt/f3/Ex8drOzQiIiIiIqIyR+eKysWLF2PYsGEYNGgQatasidWrV8PU1BQ//PCDtkMjIiIiIiIqc3SqqMzMzMTly5fh5+cnH6enpwc/Pz+cO3cuz3kyMjKQkpKi8CEiIiIiIiL10Kmi8t9//0V2djYqVqyoML5ixYr4559/8pwnLCwMVlZW8o+jo2NxhEpERERERFQm6FRRqYqpU6ciOTlZ/nn06JG2QyIiIiIiIio1DLQdQFFUqFAB+vr6ePbsmcL4Z8+eoVKlSnnOI5VKIZVKiyM8IiIiIiKiMkenzlQaGRmhYcOGOHbsmHycTCbDsWPH0LRpUy1GRkREREREVDbp1JlKAJgwYQIGDhyIRo0awdvbG0uXLkVaWhoGDRqk7dCIiIiIiIjKHJ0rKnv37o2EhATMmDED//zzD+rVq4dDhw7lengPERERERERaZ7OFZUAEBQUhKCgIG2HQUREREREVObp1D2VREREREREVLKwqCQiIiIiIiKVSYQQQttBFKeUlBRYWVkhOTkZlpaW2g6HqEzQdN4xr4mKnybzjjlNVPyYd/Q+eKaSiIiIiIiIVMaikoiIiIiIiFTGopKIiIiIiIhUxqKSiIiIiIiIVMaikoiIiIiIiFTGopKIiIiIiIhUZqDtAIpbzhtUUlJStBwJUdmRk2+aeoMR85qo+Gkyr5nTRMVP07+rqXQrc0Xl8+fPAQCOjo5ajoSo7Hnx4gWsrKzU3i/zmkh7NJHXzGki7dHU72oq3cpcUVm+fHkAQFxcXKlImJSUFDg6OuLRo0el5kW1XCfdUJR1EkLgxYsXcHBw0EgszOuSj+ukG0pKXpe2nAa4v+iKsrxOmv5dTaVbmSsq9fTe3EZqZWVVag4WAGBpaVmq1gfgOukKZddJk38YMq91B9dJN2g7r0trTgNle3/RJWV1nUrLP3Go+PFBPURERERERKQyFpVERERERESksjJXVEqlUsycORNSqVTboahFaVsfgOukK0rSOpWkWNShtK0PwHXSFSVlnUpKHOrEddINXCci1UgEnxtMREREREREKipzZyqJiIiIiIhIfVhUEhERERERkcpYVBIREREREZHKWFQSERERERGRyspUUfntt9/C2dkZxsbGaNKkCf744w9th6S0sLAwNG7cGBYWFrCzs0OXLl0QFRWl0KZVq1aQSCQKn5EjR2op4sKFhITkitfT01M+/dWrVxgzZgxsbGxgbm6O7t2749mzZ1qMuHDOzs651kkikWDMmDEASv42+u2339CxY0c4ODhAIpFgz549CtOFEJgxYwbs7e1hYmICPz8/3L9/X6HNf//9h/79+8PS0hLW1tYYMmQIUlNTNRYz87pkYV6XvG3EvC5epS2vmdMlc/voYl5T6VZmisqtW7diwoQJmDlzJq5cuYK6devC398f8fHx2g5NKadOncKYMWNw/vx5HD16FK9fv0bbtm2Rlpam0G7YsGF4+vSp/DN//nwtRaycWrVqKcR7+vRp+bTx48fj119/xfbt23Hq1Ck8efIE3bp102K0hbt48aLC+hw9ehQA0LNnT3mbkryN0tLSULduXXz77bd5Tp8/fz6WL1+O1atX48KFCzAzM4O/vz9evXolb9O/f3/cunULR48exb59+/Dbb79h+PDhGomXeV0yMa9L1jZiXhev0pjXzOmSt310La+pDBBlhLe3txgzZox8ODs7Wzg4OIiwsDAtRqW6+Ph4AUCcOnVKPs7X11d89tln2guqiGbOnCnq1q2b57SkpCRhaGgotm/fLh93584dAUCcO3eumCJ8f5999plwc3MTMplMCKFb2wiA2L17t3xYJpOJSpUqiQULFsjHJSUlCalUKn7++WchhBC3b98WAMTFixflbQ4ePCgkEol4/Pix2mNkXpc8zOuSjXld/HQ9r5nTJZ8u5DWVfmXiTGVmZiYuX74MPz8/+Tg9PT34+fnh3LlzWoxMdcnJyQCA8uXLK4zfvHkzKlSoAC8vL0ydOhUvX77URnhKu3//PhwcHODq6or+/fsjLi4OAHD58mW8fv1aYZt5enqiatWqOrPNMjMzsWnTJgwePBgSiUQ+Xte2UY6YmBj8888/CtvEysoKTZo0kW+Tc+fOwdraGo0aNZK38fPzg56eHi5cuKDWeJjXJRfzuuRvoxzMa80rDXnNnC7Z2+ddJS2vqWww0HYAxeHff/9FdnY2KlasqDC+YsWKuHv3rpaiUp1MJkNwcDCaN28OLy8v+fh+/frByckJDg4O+PPPPzFlyhRERUVh165dWow2f02aNMH69etRvXp1PH36FKGhofDx8cHNmzfxzz//wMjICNbW1grzVKxYEf/88492Ai6iPXv2ICkpCYGBgfJxuraN3pbzveeVRznT/vnnH9jZ2SlMNzAwQPny5dW+3ZjXJXOfYV6X/G30Nua1ZpWGvGZOl+ztk5eSltdUNpSJorK0GTNmDG7evKlwTwMAhevga9euDXt7e7Ru3RrR0dFwc3Mr7jALFRAQIP+5Tp06aNKkCZycnLBt2zaYmJhoMTL1WLduHQICAuDg4CAfp2vbiIoP81o3MK+pKEpDXjOnS/b2ISopysTlrxUqVIC+vn6up5E9e/YMlSpV0lJUqgkKCsK+fftw4sQJVKlSpcC2TZo0AQA8ePCgOEJ7b9bW1qhWrRoePHiASpUqITMzE0lJSQptdGWbPXz4EJGRkRg6dGiB7XRpG+V87wXlUaVKlXI9TCMrKwv//fef2rcb87rk7zMA87qkY15rTmnNa+Z0yVfS8prKhjJRVBoZGaFhw4Y4duyYfJxMJsOxY8fQtGlTLUamPCEEgoKCsHv3bhw/fhwuLi6FznPt2jUAgL29vYajU4/U1FRER0fD3t4eDRs2hKGhocI2i4qKQlxcnE5ss4iICNjZ2aF9+/YFttOlbeTi4oJKlSopbJOUlBRcuHBBvk2aNm2KpKQkXL58Wd7m+PHjkMlk8l/K6sK8Lvn7DMC8LumY1+pX2vOaOV3ylbS8pjJCyw8KKjZbtmwRUqlUrF+/Xty+fVsMHz5cWFtbi3/++UfboSll1KhRwsrKSpw8eVI8ffpU/nn58qUQQogHDx6IWbNmiUuXLomYmBixd+9e4erqKlq2bKnlyPP3+eefi5MnT4qYmBhx5swZ4efnJypUqCDi4+OFEEKMHDlSVK1aVRw/flxcunRJNG3aVDRt2lTLURcuOztbVK1aVUyZMkVhvC5soxcvXoirV6+Kq1evCgBi8eLF4urVq+Lhw4dCCCG++eYbYW1tLfbu3Sv+/PNP0blzZ+Hi4iLS09PlfbRr107Ur19fXLhwQZw+fVp4eHiIvn37aiRe5nXJw7wueduIeV28SlteM6dL5vbRtbym0q/MFJVCCLFixQpRtWpVYWRkJLy9vcX58+e1HZLSAOT5iYiIEEIIERcXJ1q2bCnKly8vpFKpcHd3F5MmTRLJycnaDbwAvXv3Fvb29sLIyEhUrlxZ9O7dWzx48EA+PT09XYwePVqUK1dOmJqaiq5du4qnT59qMWLlHD58WAAQUVFRCuN1YRudOHEiz/1s4MCBQog3jymfPn26qFixopBKpaJ169a51vP58+eib9++wtzcXFhaWopBgwaJFy9eaCxm5nXJwrwueduIeV28SlteM6dL5vbRxbym0k0ihBAaPBFKREREREREpViZuKeSiIiIiIiININFJREREREREamMRSURERERERGpjEUlERERERERqYxFJREREREREamMRSURERERERGpjEUlERERERERqYxFJREREREREamMRSURERERERGpjEUlERERERERqYxFJREREREREamMRSURERERERGpjEUlERERERERqYxFJREREREREamMRSURERERERGpjEUlERERERERqYxFJREREREREamMRSURERERERGpjEUlERERERERqYxFJREREREREamMRSURERERERGpjEUlERERERERqYxFJREREREREamMRSURERERERGpjEUlERERERERqYxFJREREREREamMRSURERERERGpjEUlERERERERqYxFJRGRCpydnREYGKjtMJQSEhICiUSiMK644o+NjYVEIsH69evl4wIDA2Fubq7xZeeQSCQICQkptuURERGVNSwqiYjeEh0djREjRsDV1RXGxsawtLRE8+bNsWzZMqSnp2s7PK06cOBAiS3OSnJsREREpZ2BtgMgIiop9u/fj549e0IqlWLAgAHw8vJCZmYmTp8+jUmTJuHWrVv47rvvtB2mWkRFRUFPr2j/Vzxw4AC+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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from flwr_datasets.visualization import plot_comparison_label_distribution\n", + "\n", + "fig, axes, df_list = plot_comparison_label_distribution(\n", + " partitioner_list=partitioner_list,\n", + " label_name=\"label\",\n", + " subtitle=\"Comparison of Partitioning Schemes on CIFAR10\",\n", + " titles=title_list,\n", + " legend=True,\n", + " verbose_labels=True,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "862899eb04695380", + "metadata": {}, + "source": [ + "## Bonus: Natural Id Dataset" + ] + }, + { + "cell_type": "markdown", + "id": "4f3f8aaf", + "metadata": {}, + "source": [ + "Nothing stops you from using the `NaturalIdPartitioner` to visualize a dataset with the `id` in it and does not need the artificial partitioning but has the pre-existing partitions. For that dataset, we use `NaturalIdPartitioner`. Let's look at the `speech-commands` dataset that has `speaker_id`, and there are quite a few speakers; therefore, we will show only the first 20 partitions. And since we have quite a few different labels, let's specify `legend_kwargs={\"ncols\": 2}` to display them in two columns (we will also shift the legend slightly to the right)." + ] + }, + { + "cell_type": "markdown", + "id": "f016d21a", + "metadata": {}, + "source": [ + "You'll be using the [Google SpeechCommands](https://huggingface.co/datasets/google/speech_commands) dataset, which is a speech-based dataset. For this, you'll need to install the `\"audio\"` extension for Flower Datasets. It can be easily done like this:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fd5ca8f4", + "metadata": {}, + "outputs": [], + "source": [ + "! pip install -q \"flwr-datasets[audio]\"" + ] + }, + { + "cell_type": "markdown", + "id": "90ea3642", + "metadata": {}, + "source": [ + "With everything ready, let's visualize the partitions for a naturally partitioned dataset." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4fe70116", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from flwr_datasets import FederatedDataset\n", + "from flwr_datasets.partitioner import NaturalIdPartitioner\n", + "from flwr_datasets.visualization import plot_label_distributions\n", + "\n", + "\n", + "fds = FederatedDataset(\n", + " dataset=\"google/speech_commands\",\n", + " subset=\"v0.01\",\n", + " partitioners={\n", + " \"train\": NaturalIdPartitioner(\n", + " partition_by=\"speaker_id\",\n", + " ),\n", + " },\n", + ")\n", + "\n", + "partitioner = fds.partitioners[\"train\"]\n", + "\n", + "fix, ax, df = plot_label_distributions(\n", + " partitioner=partitioner,\n", + " label_name=\"label\",\n", + " max_num_partitions=20,\n", + " plot_type=\"bar\",\n", + " size_unit=\"percent\",\n", + " partition_id_axis=\"x\",\n", + " legend=True,\n", + " title=\"Per Partition Labels Distribution\",\n", + " verbose_labels=True,\n", + " legend_kwargs={\"ncols\": 2, \"bbox_to_anchor\": (1.25, 0.5)},\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "4442c99c", + "metadata": {}, + "source": [ + "## More resources\n", + "\n", + "If you are looking for more resorces, feel free to check:\n", + "\n", + "* `flwr-dataset` documentation\n", + " * [plot_label_distributions](https://flower.ai/docs/datasets/ref-api/flwr_datasets.visualization.plot_label_distributions.html#flwr_datasets.visualization.plot_label_distributions)\n", + " * [plot_comparison_label_distribution](https://flower.ai/docs/datasets/ref-api/flwr_datasets.visualization.plot_comparison_label_distribution.html#flwr_datasets.visualization.plot_comparison_label_distribution)\n", + "* if you want to do any custom modification of the returned plots\n", + " * [matplotlib](https://matplotlib.org/)\n", + " * [seaborn](https://seaborn.pydata.org/)\n", + " * or plot directly using pandas object [pd.DataFrame.plot](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.plot.html)" + ] + }, + { + "cell_type": "markdown", + "id": "52655972", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "flwr", + "language": "python", + "name": "python3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/datasets/doc/source/index.rst b/datasets/doc/source/index.rst index 2144c527f8cd..bdcea7650bbc 100644 --- a/datasets/doc/source/index.rst +++ b/datasets/doc/source/index.rst @@ -7,6 +7,15 @@ learning/analytics/evaluation. It is created by the ``Flower Labs`` team that al Flower Datasets Framework ------------------------- +Install +~~~~~~~ + +.. code-block:: bash + + python -m pip install "flwr-datasets[vision]" + +Check out all the details on how to install Flower Datasets in :doc:`how-to-install-flwr-datasets`. + Tutorials ~~~~~~~~~ @@ -32,6 +41,7 @@ Problem-oriented how-to guides show step-by-step how to achieve a specific goal. how-to-use-with-tensorflow how-to-use-with-numpy how-to-use-with-local-data + how-to-visualize-label-distribution how-to-disable-enable-progress-bar References @@ -47,15 +57,26 @@ Information-oriented API reference and other reference material. flwr_datasets +.. toctree:: + :maxdepth: 1 + :caption: Reference docs + ref-telemetry Main features ------------- Flower Datasets library supports: -- **downloading datasets** - choose the dataset from Hugging Face's ``dataset`` -- **partitioning datasets** - customize the partitioning scheme +- **downloading datasets** - choose the dataset from Hugging Face's ``dataset`` (`link `_) +- **partitioning datasets** - choose one of the implemented partitioning scheme or create your own. - **creating centralized datasets** - leave parts of the dataset unpartitioned (e.g. for centralized evaluation) +- **visualization of the partitioned datasets** - visualize the label distribution of the partitioned dataset (and compare the results on different parameters of the same partitioning schemes, different datasets, different partitioning schemes, or any mix of them) + + +.. image:: ./_static/readme/comparison_of_partitioning_schemes.png + :align: center + :alt: Comparison of Partitioning Schemes on CIFAR10 + Thanks to using Hugging Face's ``datasets`` used under the hood, Flower Datasets integrates with the following popular formats/frameworks: @@ -67,28 +88,19 @@ Thanks to using Hugging Face's ``datasets`` used under the hood, Flower Datasets - Jax - Arrow -Install -------- - -The simplest install is - -.. code-block:: bash - - python -m pip install flwr-datasets - -If you plan to use the image datasets - -.. code-block:: bash - - python -m pip install flwr-datasets[vision] - -If you plan to use the audio datasets - -.. code-block:: bash +Here are a few of the ``Partitioner`` s that are available: (for a full list see `link `_ ) - python -m pip install flwr-datasets[audio] +* Partitioner (the abstract base class) ``Partitioner`` +* IID partitioning ``IidPartitioner(num_partitions)`` +* Dirichlet partitioning ``DirichletPartitioner(num_partitions, partition_by, alpha)`` +* InnerDirichlet partitioning ``InnerDirichletPartitioner(partition_sizes, partition_by, alpha)`` +* Natural ID partitioner ``NaturalIdPartitioner(partition_by)`` +* Size partitioner (the abstract base class for the partitioners dictating the division based the number of samples) ``SizePartitioner`` +* Linear partitioner ``LinearPartitioner(num_partitions)`` +* Square partitioner ``SquarePartitioner(num_partitions)`` +* Exponential partitioner ``ExponentialPartitioner(num_partitions)`` +* more to come in the future releases (contributions are welcome). -Check out the full details on the download in :doc:`how-to-install-flwr-datasets`. How To Use the library ---------------------- diff --git a/datasets/doc/source/ref-telemetry.md b/datasets/doc/source/ref-telemetry.md new file mode 100644 index 000000000000..a4fc9b6b0061 --- /dev/null +++ b/datasets/doc/source/ref-telemetry.md @@ -0,0 +1,66 @@ +# Telemetry + +The Flower Datasets open-source project collects **anonymous** usage metrics to make well-informed decisions to improve Flower Datasets. Doing this enables the Flower team to understand how Flower Datasets 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 that do not want to share anonymous usage metrics. + +## Principles + +We follow strong principles guarding anonymous usage metrics collection: + +- **Optional:** You will always be able to disable telemetry; read on to learn “[How to opt-out](#how-to-opt-out)”. +- **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. +- **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)” +- **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. + +## How to opt-out + +When Flower Datasets 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 using Flower Datasets in a Flower server or client, simply do so by prepending your command as in: + +```bash +FLWR_TELEMETRY_ENABLED=0 python server.py # or client.py +``` + +Alternatively, you can export `FLWR_TELEMETRY_ENABLED=0` in, for example, `.bashrc` (or whatever configuration file applies to your environment) to disable Flower Datasets telemetry permanently. + +## Collected metrics + +Flower telemetry collects the following metrics: + +**Flower version.** Understand which versions of Flower Datasets 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 Datasets or instead use the bandwidth to build new features. + +**Operating system.** Enables us to answer questions such as: *Should we create more guides for Linux, macOS, or Windows?* + +**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. + +**Hardware properties.** Understanding the hardware environment that Flower Datasets is being used in helps to decide whether we should, for example, put more effort into supporting low-resource environments. + +**Dataset and Partitioners names.** Knowing what datasets and Partitioners are used enables us to provide more detailed code examples and tutorials and better prioritize work on development and support for them. + +**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. + +**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.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. + +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. + +## How to inspect what is being reported + +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. + +```bash +FLWR_TELEMETRY_LOGGING=1 python server.py # or client.py +``` + +The inspect Flower telemetry without sending any anonymous usage metrics, use both environment variables: + +```bash +FLWR_TELEMETRY_ENABLED=0 FLWR_TELEMETRY_LOGGING=1 python server.py # or client.py +``` + +## 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.ai/join-slack/) (channel `#telemetry`) or email (`telemetry@flower.ai`). diff --git a/datasets/flwr_datasets/__init__.py b/datasets/flwr_datasets/__init__.py index d084780102ce..bd68fa43c606 100644 --- a/datasets/flwr_datasets/__init__.py +++ b/datasets/flwr_datasets/__init__.py @@ -23,11 +23,12 @@ __all__ = [ "FederatedDataset", - "partitioner", "metrics", - "visualization", + "partitioner", "preprocessor", "utils", + "visualization", ] + __version__ = _package_version diff --git a/datasets/flwr_datasets/common/__init__.py b/datasets/flwr_datasets/common/__init__.py index b4f12f8641b3..efb4eaf55b70 100644 --- a/datasets/flwr_datasets/common/__init__.py +++ b/datasets/flwr_datasets/common/__init__.py @@ -13,3 +13,12 @@ # limitations under the License. # ============================================================================== """Common components in Flower Datasets.""" + + +from .telemetry import EventType as EventType +from .telemetry import event as event + +__all__ = [ + "EventType", + "event", +] diff --git a/datasets/flwr_datasets/common/telemetry.py b/datasets/flwr_datasets/common/telemetry.py new file mode 100644 index 000000000000..ca484fdda73f --- /dev/null +++ b/datasets/flwr_datasets/common/telemetry.py @@ -0,0 +1,224 @@ +# 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 telemetry.""" + + +import datetime +import json +import logging +import os +import platform +import urllib.request +import uuid +from concurrent.futures import Future, ThreadPoolExecutor +from enum import Enum, auto +from pathlib import Path +from typing import Any, Dict, List, Optional, Union, cast + +from flwr_datasets.common.version import package_name, package_version + +FLWR_TELEMETRY_ENABLED = os.getenv("FLWR_TELEMETRY_ENABLED", "1") +FLWR_TELEMETRY_LOGGING = os.getenv("FLWR_TELEMETRY_LOGGING", "0") + +TELEMETRY_EVENTS_URL = "https://telemetry.flower.ai/api/v1/event" + +LOGGER_NAME = "flwr-datasets-telemetry" +LOGGER_LEVEL = logging.DEBUG + + +def _configure_logger(log_level: int) -> None: + console_handler = logging.StreamHandler() + console_handler.setLevel(log_level) + console_handler.setFormatter( + logging.Formatter( + "%(levelname)s %(name)s %(asctime)s | %(filename)s:%(lineno)d | %(message)s" + ) + ) + + logger = logging.getLogger(LOGGER_NAME) + logger.setLevel(log_level) + logger.addHandler(console_handler) + + +_configure_logger(LOGGER_LEVEL) + + +def log(msg: Union[str, Exception]) -> None: + """Log message using logger at DEBUG level.""" + logging.getLogger(LOGGER_NAME).log(LOGGER_LEVEL, msg) + + +def _get_home() -> Path: + return Path().home() + + +def _get_source_id() -> str: + """Get existing or new source ID.""" + source_id = "unavailable" + # Check if .flwr in home exists + try: + home = _get_home() + except RuntimeError: + # If the home directory can’t be resolved, RuntimeError is raised. + return source_id + + flwr_dir = home.joinpath(".flwr") + # Create .flwr directory if it does not exist yet. + try: + flwr_dir.mkdir(parents=True, exist_ok=True) + except PermissionError: + return source_id + + source_file = flwr_dir.joinpath("source") + + # If no source_file exists create one and write it + if not source_file.exists(): + try: + source_file.touch(exist_ok=True) + source_file.write_text(str(uuid.uuid4()), encoding="utf-8") + except PermissionError: + return source_id + + source_id = source_file.read_text(encoding="utf-8").strip() + + try: + uuid.UUID(source_id) + except ValueError: + source_id = "invalid" + + return source_id + + +# Using str as first base type to make it JSON serializable as +# otherwise the following exception will be thrown when serializing +# the event dict: +# TypeError: Object of type EventType is not JSON serializable +class EventType(str, Enum): + """Types of telemetry events.""" + + # This method combined with auto() will set the property value to + # the property name e.g. + # `START_CLIENT = auto()` becomes `START_CLIENT = "START_CLIENT"` + # The type signature is not compatible with mypy, pylint and flake8 + # so each of those needs to be disabled for this line. + # pylint: disable-next=no-self-argument,arguments-differ,line-too-long + def _generate_next_value_(name: str, start: int, count: int, last_values: List[Any]) -> Any: # type: ignore # noqa: E501 + return name + + PING = auto() + + LOAD_PARTITION_CALLED = auto() + LOAD_SPLIT_CALLED = auto() + PLOT_LABEL_DISTRIBUTION_CALLED = auto() + PLOT_COMPARISON_LABEL_DISTRIBUTION_CALLED = auto() + + +# Use the ThreadPoolExecutor with max_workers=1 to have a queue +# and also ensure that telemetry calls are not blocking. +state: Dict[str, Union[Optional[str], Optional[ThreadPoolExecutor]]] = { + # Will be assigned ThreadPoolExecutor(max_workers=1) + # in event() the first time it's required + "executor": None, + "source": None, + "cluster": None, +} + + +# In Python 3.7 pylint will throw an error stating that +# "Value 'Future' is unsubscriptable". +# This pylint disable line can be remove when dropping support +# for Python 3.7 +# pylint: disable-next=unsubscriptable-object +def event( + event_type: EventType, + event_details: Optional[Dict[str, Any]] = None, +) -> Future: # type: ignore + """Submit create_event to ThreadPoolExecutor to avoid blocking.""" + if state["executor"] is None: + state["executor"] = ThreadPoolExecutor(max_workers=1) + + executor: ThreadPoolExecutor = cast(ThreadPoolExecutor, state["executor"]) + + result = executor.submit(create_event, event_type, event_details) + return result + + +def create_event(event_type: EventType, event_details: Optional[Dict[str, Any]]) -> str: + """Create telemetry event.""" + if state["source"] is None: + state["source"] = _get_source_id() + + if state["cluster"] is None: + state["cluster"] = str(uuid.uuid4()) + + if event_details is None: + event_details = {} + + date = datetime.datetime.now(tz=datetime.timezone.utc).isoformat() + context = { + "source": state["source"], + "cluster": state["cluster"], + "date": date, + "package": { + "package_name": package_name, + "package_version": package_version, + }, + "hw": { + "cpu_count": os.cpu_count(), + }, + "platform": { + "system": platform.system(), + "release": platform.release(), + "platform": platform.platform(), + "python_implementation": platform.python_implementation(), + "python_version": platform.python_version(), + "machine": platform.machine(), + "architecture": platform.architecture(), + "version": platform.uname().version, + }, + } + payload = { + "event_type": event_type, + "event_details": event_details, + "context": context, + } + payload_json = json.dumps(payload) + if FLWR_TELEMETRY_LOGGING == "1": + log(" - ".join([date, "POST", payload_json])) + + # If telemetry is not disabled with setting FLWR_TELEMETRY_ENABLED=0 + # create a request and send it to the telemetry backend + if FLWR_TELEMETRY_ENABLED == "1": + request = urllib.request.Request( + url=TELEMETRY_EVENTS_URL, + data=payload_json.encode("utf-8"), + headers={ + "User-Agent": f"{package_name}/{package_version}", + "Content-Type": "application/json", + }, + method="POST", + ) + try: + with urllib.request.urlopen(request, timeout=60) as response: + result = response.read() + + response_json: str = result.decode("utf-8") + + return response_json + except urllib.error.URLError as ex: + if FLWR_TELEMETRY_LOGGING == "1": + log(ex) + + return "disabled" diff --git a/datasets/flwr_datasets/common/telemetry_test.py b/datasets/flwr_datasets/common/telemetry_test.py new file mode 100644 index 000000000000..f46b7b9a2ddf --- /dev/null +++ b/datasets/flwr_datasets/common/telemetry_test.py @@ -0,0 +1,115 @@ +# 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. +# ============================================================================== +"""Telemetry tests.""" + + +import time +import unittest +from typing import Callable +from unittest import mock + +from flwr_datasets.common.telemetry import EventType, _get_source_id, event + + +class TelemetryTest(unittest.TestCase): + """Tests for the telemetry module.""" + + @mock.patch("flwr_datasets.common.telemetry.FLWR_TELEMETRY_ENABLED", "1") + def test_event(self) -> None: + """Test if sending works against the actual API.""" + # Prepare + expected = '{\n "status": "created"\n}' + + # Execute + future = event(EventType.PING) + actual = future.result() + + # Assert + self.assertEqual(actual, expected) + + @mock.patch("flwr_datasets.common.telemetry.FLWR_TELEMETRY_ENABLED", "1") + def test_not_blocking(self) -> None: + """Test if the code is blocking. + + If the code does not block duration_actual should be less than + 0.001s. + """ + # Prepare + # Use 0.1ms as any blocking networked call would take longer. + duration_max = 0.001 + start = time.time() + + # Execute + event(EventType.PING) + duration_actual = time.time() - start + + # Assert + self.assertLess(duration_actual, duration_max) + + @mock.patch("flwr_datasets.common.telemetry.FLWR_TELEMETRY_ENABLED", "0") + def test_telemetry_disabled(self) -> None: + """Test opt-out.""" + # Prepare + expected = "disabled" + + # Execute + future = event(EventType.PING) + actual = future.result() + + # Assert + self.assertEqual(actual, expected) + + def test_get_source_id(self) -> None: + """Test if _get_source_id returns an ID successfully. + + This test might fail if the UNIX user invoking the test has no home directory. + """ + # Prepare + # nothing to prepare + + # Execute + source_id = _get_source_id() + + # Assert + # source_id should be len 36 as it's a uuid4 in the current + # implementation + self.assertIsNotNone(source_id) + self.assertEqual(len(source_id), 36) + + def test_get_source_id_no_home(self) -> None: + """Test if _get_source_id returns unavailable without a home dir.""" + + # Prepare + def new_callable() -> Callable[[], None]: + def _new_failing_get_home() -> None: + raise RuntimeError + + return _new_failing_get_home + + except_value = "unavailable" + + # Execute + with mock.patch( + "flwr_datasets.common.telemetry._get_home", + new_callable=new_callable, + ): + source_id = _get_source_id() + + # Assert + self.assertEqual(source_id, except_value) + + +if __name__ == "__main__": + unittest.main() diff --git a/datasets/flwr_datasets/federated_dataset.py b/datasets/flwr_datasets/federated_dataset.py index 5d98d01d4941..accfb783f368 100644 --- a/datasets/flwr_datasets/federated_dataset.py +++ b/datasets/flwr_datasets/federated_dataset.py @@ -19,6 +19,7 @@ import datasets from datasets import Dataset, DatasetDict +from flwr_datasets.common import EventType, event from flwr_datasets.partitioner import Partitioner from flwr_datasets.preprocessor import Preprocessor from flwr_datasets.utils import ( @@ -35,8 +36,9 @@ class FederatedDataset: Download, partition data among clients (edge devices), or load full dataset. - Partitions are created using IidPartitioner. Support for different partitioners - specification and types will come in future releases. + Partitions are created per-split-basis using Partitioners from + `flwr_datasets.partitioner` specified in `partitioners` (see `partitioners` + parameter for more information). Parameters ---------- @@ -56,23 +58,43 @@ class FederatedDataset: into). One or multiple `Partitioner` objects can be specified in that manner, but at most, one per split. shuffle : bool - Whether to randomize the order of samples. Applied prior to resplitting, - speratelly to each of the present splits in the dataset. It uses the `seed` - argument. Defaults to True. + Whether to randomize the order of samples. Applied prior to preprocessing + operations, speratelly to each of the present splits in the dataset. It uses + the `seed` argument. Defaults to True. seed : Optional[int] Seed used for dataset shuffling. It has no effect if `shuffle` is False. The - seed cannot be set in the later stages. If `None`, then fresh, unpredictable entropy - will be pulled from the OS. Defaults to 42. + seed cannot be set in the later stages. If `None`, then fresh, unpredictable + entropy will be pulled from the OS. Defaults to 42. Examples -------- Use MNIST dataset for Federated Learning with 100 clients (edge devices): - >>> mnist_fds = FederatedDataset(dataset="mnist", partitioners={"train": 100}) + >>> from flwr_datasets import FederatedDataset + >>> + >>> fds = FederatedDataset(dataset="mnist", partitioners={"train": 100}) >>> # Load partition for client with ID 10. - >>> partition = mnist_fds.load_partition(10, "train") + >>> partition = fds.load_partition(10) >>> # Use test split for centralized evaluation. - >>> centralized = mnist_fds.load_split("test") + >>> centralized = fds.load_split("test") + + Use CIFAR10 dataset for Federated Laerning with 100 clients: + >>> from flwr_datasets import FederatedDataset + >>> from flwr_datasets.partitioner import DirichletPartitioner + >>> + >>> partitioner = DirichletPartitioner(num_partitions=10, partition_by="label", + >>> alpha=0.5, min_partition_size=10) + >>> fds = FederatedDataset(dataset="cifar10", partitioners={"train": partitioner}) + >>> partition = fds.load_partition(partition_id=0) + + Visualize the partitioned datasets + >>> from flwr_datasets.visualization import plot_label_distributions + >>> + >>> _ = plot_label_distributions( + >>> partitioner=fds.partitioners["train"], + >>> label_name="label", + >>> legend=True, + >>> ) """ # pylint: disable=too-many-instance-attributes @@ -102,6 +124,9 @@ def __init__( self._dataset: Optional[DatasetDict] = None # Indicate if the dataset is prepared for `load_partition` or `load_split` self._dataset_prepared: bool = False + self._event = { + "load_partition": {split: False for split in self._partitioners}, + } def load_partition( self, @@ -141,7 +166,20 @@ def load_partition( self._check_if_split_possible_to_federate(split) partitioner: Partitioner = self._partitioners[split] self._assign_dataset_to_partitioner(split) - return partitioner.load_partition(partition_id) + partition = partitioner.load_partition(partition_id) + if not self._event["load_partition"][split]: + event( + EventType.LOAD_PARTITION_CALLED, + { + "federated_dataset_id": id(self), + "dataset_name": self._dataset_name, + "split": split, + "partitioner": partitioner.__class__.__name__, + "num_partitions": partitioner.num_partitions, + }, + ) + self._event["load_partition"][split] = True + return partition def load_split(self, split: str) -> Dataset: """Load the full split of the dataset. @@ -164,7 +202,20 @@ def load_split(self, split: str) -> Dataset: if self._dataset is None: raise ValueError("Dataset is not loaded yet.") self._check_if_split_present(split) - return self._dataset[split] + dataset_split = self._dataset[split] + + if not self._event["load_split"][split]: + event( + EventType.LOAD_SPLIT_CALLED, + { + "federated_dataset_id": id(self), + "dataset_name": self._dataset_name, + "split": split, + }, + ) + self._event["load_split"][split] = True + + return dataset_split @property def partitioners(self) -> Dict[str, Partitioner]: @@ -246,6 +297,8 @@ def _prepare_dataset(self) -> None: self._dataset = self._dataset.shuffle(seed=self._seed) if self._preprocessor: self._dataset = self._preprocessor(self._dataset) + available_splits = list(self._dataset.keys()) + self._event["load_split"] = {split: False for split in available_splits} self._dataset_prepared = True def _check_if_no_split_keyword_possible(self) -> None: diff --git a/datasets/flwr_datasets/partitioner/__init__.py b/datasets/flwr_datasets/partitioner/__init__.py index 0d1edbfcb04a..1fc00ed90323 100644 --- a/datasets/flwr_datasets/partitioner/__init__.py +++ b/datasets/flwr_datasets/partitioner/__init__.py @@ -27,14 +27,14 @@ from .square_partitioner import SquarePartitioner __all__ = [ + "DirichletPartitioner", + "ExponentialPartitioner", "IidPartitioner", - "Partitioner", + "InnerDirichletPartitioner", + "LinearPartitioner", "NaturalIdPartitioner", - "DirichletPartitioner", + "Partitioner", + "ShardPartitioner", "SizePartitioner", - "LinearPartitioner", - "InnerDirichletPartitioner", "SquarePartitioner", - "ShardPartitioner", - "ExponentialPartitioner", ] diff --git a/datasets/flwr_datasets/preprocessor/__init__.py b/datasets/flwr_datasets/preprocessor/__init__.py index bab5d82a2035..67b2aaadc3d2 100644 --- a/datasets/flwr_datasets/preprocessor/__init__.py +++ b/datasets/flwr_datasets/preprocessor/__init__.py @@ -20,7 +20,7 @@ from .preprocessor import Preprocessor __all__ = [ + "Divider", "Merger", "Preprocessor", - "Divider", ] diff --git a/datasets/flwr_datasets/visualization/__init__.py b/datasets/flwr_datasets/visualization/__init__.py index 801a38dcafc6..b55e406c71db 100644 --- a/datasets/flwr_datasets/visualization/__init__.py +++ b/datasets/flwr_datasets/visualization/__init__.py @@ -19,6 +19,6 @@ from .label_distribution import plot_label_distributions __all__ = [ - "plot_label_distributions", "plot_comparison_label_distribution", + "plot_label_distributions", ] diff --git a/datasets/flwr_datasets/visualization/bar_plot.py b/datasets/flwr_datasets/visualization/bar_plot.py index 6326b24a9695..339ff0967906 100644 --- a/datasets/flwr_datasets/visualization/bar_plot.py +++ b/datasets/flwr_datasets/visualization/bar_plot.py @@ -38,7 +38,6 @@ def _plot_bar( plot_kwargs: Optional[Dict[str, Any]], legend_kwargs: Optional[Dict[str, Any]], ) -> Axes: - if axis is None: if figsize is None: figsize = _initialize_figsize( diff --git a/datasets/flwr_datasets/visualization/comparison_label_distribution.py b/datasets/flwr_datasets/visualization/comparison_label_distribution.py index d59f8c47986d..554f6d78d59a 100644 --- a/datasets/flwr_datasets/visualization/comparison_label_distribution.py +++ b/datasets/flwr_datasets/visualization/comparison_label_distribution.py @@ -23,6 +23,7 @@ from matplotlib.axes import Axes from matplotlib.figure import Figure +from flwr_datasets.common import EventType, event from flwr_datasets.partitioner import Partitioner from flwr_datasets.visualization.constants import PLOT_TYPES from flwr_datasets.visualization.label_distribution import plot_label_distributions @@ -132,6 +133,13 @@ def plot_comparison_label_distribution( >>> titles=[f"Concentration = {alpha}" for alpha in alpha_list], >>> ) """ + event( + EventType.PLOT_COMPARISON_LABEL_DISTRIBUTION_CALLED, + { + "num_compare": len(partitioner_list), + "plot_type": plot_type, + }, + ) num_partitioners = len(partitioner_list) if isinstance(label_name, str): label_name = [label_name] * num_partitioners diff --git a/datasets/flwr_datasets/visualization/heatmap_plot.py b/datasets/flwr_datasets/visualization/heatmap_plot.py index 2e593a79368e..3c87de7693ae 100644 --- a/datasets/flwr_datasets/visualization/heatmap_plot.py +++ b/datasets/flwr_datasets/visualization/heatmap_plot.py @@ -39,7 +39,6 @@ def _plot_heatmap( plot_kwargs: Optional[Dict[str, Any]], legend_kwargs: Optional[Dict[str, Any]], ) -> Axes: - if axis is None: if figsize is None: figsize = _initialize_figsize( @@ -92,7 +91,6 @@ def _initialize_figsize( num_partitions: int, num_labels: int, ) -> Tuple[float, float]: - figsize = (0.0, 0.0) if partition_id_axis == "x": figsize = (3 * np.sqrt(num_partitions), np.sqrt(num_labels)) diff --git a/datasets/flwr_datasets/visualization/label_distribution.py b/datasets/flwr_datasets/visualization/label_distribution.py index 940b0e8f91bd..0c47bd204a17 100644 --- a/datasets/flwr_datasets/visualization/label_distribution.py +++ b/datasets/flwr_datasets/visualization/label_distribution.py @@ -22,6 +22,7 @@ from matplotlib.axes import Axes from matplotlib.figure import Figure +from flwr_datasets.common import EventType, event from flwr_datasets.metrics.utils import compute_counts, compute_frequencies from flwr_datasets.partitioner import Partitioner from flwr_datasets.visualization.bar_plot import _plot_bar @@ -191,6 +192,12 @@ def plot_label_distributions( You can also visualize the returned DataFrame in Jupyter Notebook >>> dataframe.style.background_gradient(axis=None) """ + event( + EventType.PLOT_LABEL_DISTRIBUTION_CALLED, + { + "plot_type": plot_type, + }, + ) _validate_parameters(plot_type, size_unit, partition_id_axis) dataframe = pd.DataFrame() diff --git a/datasets/pyproject.toml b/datasets/pyproject.toml index 56cf3038f4ef..017374181f59 100644 --- a/datasets/pyproject.toml +++ b/datasets/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "flwr-datasets" -version = "0.1.0" +version = "0.2.0" description = "Flower Datasets" license = "Apache-2.0" authors = ["The Flower Authors "] diff --git a/dev/changelog_config.toml b/dev/changelog_config.toml index 898f9bfdb221..c5ff1bcdd1c1 100644 --- a/dev/changelog_config.toml +++ b/dev/changelog_config.toml @@ -44,6 +44,7 @@ allowed_verbs=[ "Align", "Allow", "Alter", + "Amend", "Analyse", "Analyze", "Anchor", diff --git a/dev/format.sh b/dev/format.sh index b9e3b00dffe1..71edf9c6065a 100755 --- a/dev/format.sh +++ b/dev/format.sh @@ -3,6 +3,7 @@ set -e cd "$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"/../ # Python +python -m flwr_tool.check_copyright src/py/flwr python -m flwr_tool.init_py_fix src/py/flwr python -m isort --skip src/py/flwr/proto src/py python -m black -q --exclude src/py/flwr/proto src/py diff --git a/dev/test.sh b/dev/test.sh index 7cabf35abf41..8cbe88c9298b 100755 --- a/dev/test.sh +++ b/dev/test.sh @@ -23,7 +23,7 @@ python -m flwr_tool.init_py_check src/py/flwr src/py/flwr_tool echo "- init_py_check: done" echo "- docformatter: start" -python -m docformatter -c -r src/py/flwr e2e -e src/py/flwr/proto +python -m docformatter -c -r src/py/flwr e2e -e src/py/flwr/proto echo "- docformatter: done" echo "- ruff: start" @@ -58,6 +58,10 @@ echo "- All Markdown checks passed" echo "- Start license checks" +echo "- copyright: start" +python -m flwr_tool.check_copyright src/py/flwr +echo "- copyright: done" + echo "- licensecheck: start" python -m licensecheck -u poetry --fail-licenses gpl --zero echo "- licensecheck: done" diff --git a/doc/build-versioned-docs.sh b/doc/build-versioned-docs.sh index 6c1b6dd9c5fc..4d3462718385 100755 --- a/doc/build-versioned-docs.sh +++ b/doc/build-versioned-docs.sh @@ -82,9 +82,9 @@ done # Build the main version (main for GH CI, local branch for local) if [ $GITHUB_ACTIONS ] then - git switch main + git checkout --force main else - git switch $current_branch + git checkout --force $current_branch fi current_version=main diff --git a/doc/locales/ko/LC_MESSAGES/framework-docs.po b/doc/locales/ko/LC_MESSAGES/framework-docs.po index 9c8d2f5ff19b..f01f9eaf7bd9 100644 --- a/doc/locales/ko/LC_MESSAGES/framework-docs.po +++ b/doc/locales/ko/LC_MESSAGES/framework-docs.po @@ -8,15 +8,16 @@ msgstr "" "Project-Id-Version: Flower main\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-06-17 16:09+0200\n" -"PO-Revision-Date: 2024-06-16 09:09+0000\n" -"Last-Translator: 박태현 \n" +"PO-Revision-Date: 2024-06-25 10:43+0000\n" +"Last-Translator: \"Young D. Kwon\" \n" +"Language-Team: Korean \n" "Language: ko\n" -"Language-Team: Korean \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.6-rc\n" "Generated-By: Babel 2.15.0\n" #: ../../source/contributor-explanation-architecture.rst:2 @@ -29,9 +30,11 @@ msgstr "엣지 클라이언트 엔진" #: ../../source/contributor-explanation-architecture.rst:7 msgid "" -"`Flower `_ core framework architecture with Edge " -"Client Engine" -msgstr "`Flower `_의 핵심 프레임워크 아키텍처와 엣지 클라이언트 엔진" +"`Flower `_ core framework architecture with Edge Client " +"Engine" +msgstr "" +"`Flower `_의 핵심 프레임워크 아키텍처와 엣지 클라이언트 엔" +"진" #: ../../source/contributor-explanation-architecture.rst:13 msgid "Virtual Client Engine" @@ -41,7 +44,9 @@ msgstr "가상 클라이언트 엔진" msgid "" "`Flower `_ core framework architecture with Virtual " "Client Engine" -msgstr "`Flower `_의 핵심 프레임워크 아키텍처와 가상 클라이언트 엔진" +msgstr "" +"`Flower `_의 핵심 프레임워크 아키텍처와 가상 클라이언트 엔" +"진" #: ../../source/contributor-explanation-architecture.rst:21 msgid "Virtual Client Engine and Edge Client Engine in the same workload" @@ -49,30 +54,31 @@ 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-to-build-docker-images.rst:2 msgid "How to build Docker Flower images locally" msgstr "Docker Flower 이미지를 Locally 구축하는 방법" #: ../../source/contributor-how-to-build-docker-images.rst:4 -#, fuzzy -msgid "" -"Flower provides pre-made docker images on `Docker Hub " -"`_ that include all necessary dependencies" -" for running the SuperLink, SuperNode or ServerApp. You can also build " -"your own custom docker images from scratch with a different version of " -"Python or Linux distribution (Ubuntu/Alpine) if that is what you need. In" -" this guide, we will explain what images exist and how to build them " -"locally." -msgstr "" -"Flower는 'Docker Hub '_에서 미리 만들어진 Docker " -"이미지들을 제공합니다. 해당 이미지들은 SuperLink, ServerNode 또는 ServerApp을 실행하는 데 필요한 모든 " -"dependencies를 포함합니다. 필요한 경우 다른 버전의 Python이나 Linux 배포판(Ubuntu/Alpine)을 사용해" -" 처음부터 사용자 정의 Docker 이미지를 빌드할 수도 있습니다. 이 가이드에서는 존재하는 이미지들과 이들을 로컬에서 빌드하는 " -"방법에 대해 설명하겠습니다." +msgid "" +"Flower provides pre-made docker images on `Docker Hub `_ that include all necessary dependencies for running the " +"SuperLink, SuperNode or ServerApp. You can also build your own custom docker " +"images from scratch with a different version of Python or Linux distribution " +"(Ubuntu/Alpine) if that is what you need. In this guide, we will explain " +"what images exist and how to build them locally." +msgstr "" +"Flower는 'Docker Hub '_에서 미리 만들어진 " +"Docker 이미지들을 제공합니다. 해당 이미지들은 SuperLink, ServerNode 또는 " +"ServerApp을 실행하는 데 필요한 모든 dependencies를 포함합니다. 필요한 경우 다" +"른 버전의 Python이나 Linux 배포판(Ubuntu/Alpine)을 사용해 처음부터 사용자 정" +"의 Docker 이미지를 빌드할 수도 있습니다. 이 가이드에서는 존재하는 이미지들과 " +"이들을 로컬에서 빌드하는 방법에 대해 설명하겠습니다." #: ../../source/contributor-how-to-build-docker-images.rst:10 msgid "" @@ -82,7 +88,7 @@ msgstr "시작하기 전에, 로컬 개발 환경에서 몇 가지 전제 조건 #: ../../source/contributor-how-to-build-docker-images.rst:12 msgid "Clone the flower repository." -msgstr "Flower 리포지토리를 복제합니다." +msgstr "Flower 레포지토리를 복제합니다." #: ../../source/contributor-how-to-build-docker-images.rst:18 #: ../../source/how-to-run-flower-using-docker.rst:165 @@ -92,45 +98,45 @@ msgstr "Docker 데몬이 실행 중인지 확인하십시오." #: ../../source/contributor-how-to-build-docker-images.rst:20 #: ../../source/how-to-run-flower-using-docker.rst:167 msgid "" -"Please follow the first section on :doc:`Run Flower using Docker ` which covers this step in more detail." +"Please follow the first section on :doc:`Run Flower using Docker ` which covers this step in more detail." msgstr "" -":doc:Run Flower using Docker 의 첫 번째 섹션을 " -"따라 주십시오. 해당 부분을 더 자세히 설명해 줍니다." +":doc:Run Flower using Docker 의 첫 번째 섹션" +"을 따라 주십시오. 해당 부분을 더 자세히 설명해 줍니다." #: ../../source/contributor-how-to-build-docker-images.rst:25 msgid "" "The build instructions that assemble the images are located in the " -"respective Dockerfiles. You can find them in the subdirectories of " -"``src/docker``." +"respective Dockerfiles. You can find them in the subdirectories of ``src/" +"docker``." msgstr "" -"이미지들을 조합하는 빌드 instruction들은 해당 Dockerfile에 있습니다. \"src/docker\" 의 하위 " -"디렉토리에서 찾을 수 있습니다." +"이미지들을 조합하는 빌드 명령어들은 해당 Dockerfile에 있습니다. \"src/" +"docker\" 의 하위 디렉토리에서 찾을 수 있습니다." #: ../../source/contributor-how-to-build-docker-images.rst:28 -#, fuzzy msgid "" "Flower Docker images are configured via build arguments. Through build " -"arguments, we can make the creation of images 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 "" -"base 이미지와 SuperLink 이미지 둘 다 빌드 argument들을 통해 구성됩니다. 빌드 argument들을 통해, 빌드를" -" 더 유연하게 만들 수 있습니다. 예를 들어, base 이미지에서 \"PYTHON_VERSION\" 빌드 argument를 사용하여" -" Python 버전을 지정할 수 있습니다. 일부 빌드 argument들은 기본값이며, 이미지를 빌드할 때 지정해야 합니다. 각 " -"이미지에 사용할 수 있는 모든 빌드 argument는 아래 표 중에 있습니다." +"arguments, we can make the creation of images 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 "" +"Flower Docker는 빌드 전달인자를 통해 구성됩니다. 빌드 argument들을 통해, " +"이미지를 보다 유연하게 생성할 수 있습니다. 예를 들어, base 이미지에서 " +"\"PYTHON_VERSION\" 빌드 전달인자를 사용하여 Python 버전을 지정할 수 " +"있습니다. 일부 빌드 전달인자들은 기본값이며, 이미지를 빌드할 때 지정해야 " +"합니다. 각 이미지에 사용할 수 있는 모든 빌드 전달인자는 아래 표 중에 " +"있습니다." #: ../../source/contributor-how-to-build-docker-images.rst:35 msgid "Building the base image" -msgstr "base 이미지 빌드" +msgstr "기본 이미지 빌드" #: ../../source/contributor-how-to-build-docker-images.rst:41 #: ../../source/contributor-how-to-build-docker-images.rst:98 msgid "Build argument" -msgstr "빌드 argument" +msgstr "빌드 전달인자" #: ../../source/contributor-how-to-build-docker-images.rst:42 #: ../../source/contributor-how-to-build-docker-images.rst:99 @@ -149,12 +155,11 @@ msgstr "예시" #: ../../source/contributor-how-to-build-docker-images.rst:45 msgid "``DISTRO``" -msgstr "" +msgstr "``DISTRO``" #: ../../source/contributor-how-to-build-docker-images.rst:46 -#, fuzzy msgid "The Linux distribution to use as the base image." -msgstr "base 이미지의 Ubuntu 버전." +msgstr "기본 이미지 사용을 위한 Linux 배포판." #: ../../source/contributor-how-to-build-docker-images.rst:47 #: ../../source/contributor-how-to-build-docker-images.rst:51 @@ -162,26 +167,23 @@ msgstr "base 이미지의 Ubuntu 버전." #: ../../source/contributor-how-to-build-docker-images.rst:71 #: ../../source/contributor-how-to-build-docker-images.rst:104 msgid "No" -msgstr "" +msgstr "아니오" #: ../../source/contributor-how-to-build-docker-images.rst:48 -#, fuzzy msgid "``ubuntu``" -msgstr "``UBUNTU_VERSION``" +msgstr "``ubuntu``" #: ../../source/contributor-how-to-build-docker-images.rst:49 -#, fuzzy msgid "``DISTRO_VERSION``" -msgstr "``PIP_VERSION``" +msgstr "``DISTRO_VERSION``" #: ../../source/contributor-how-to-build-docker-images.rst:50 msgid "Version of the Linux distribution." -msgstr "" +msgstr "Linux 배포판 버전." #: ../../source/contributor-how-to-build-docker-images.rst:52 -#, fuzzy msgid "``22.04``" -msgstr "``23.0.1``" +msgstr "``22.04``" #: ../../source/contributor-how-to-build-docker-images.rst:53 msgid "``PYTHON_VERSION``" @@ -193,7 +195,7 @@ msgstr "설치 된 ``python`` 버전." #: ../../source/contributor-how-to-build-docker-images.rst:56 msgid "``3.11`` or ``3.11.1``" -msgstr "" +msgstr "``3.11`` 또는 ``3.11.1``" #: ../../source/contributor-how-to-build-docker-images.rst:57 msgid "``PIP_VERSION``" @@ -243,34 +245,34 @@ msgid "``FLWR_PACKAGE``" msgstr "``FLWR_PACKAGE``" #: ../../source/contributor-how-to-build-docker-images.rst:70 -#, fuzzy msgid "The Flower package to be installed." -msgstr "설치 할 PyPI 패키지." +msgstr "설치 할 Flower 패키지." #: ../../source/contributor-how-to-build-docker-images.rst:72 msgid "``flwr`` or ``flwr-nightly``" -msgstr "" +msgstr "``flwr`` 또는 ``flwr-nightly``" #: ../../source/contributor-how-to-build-docker-images.rst:75 -#, fuzzy msgid "" -"The following example creates a base Ubuntu/Alpine image with Python " -"3.11.0, pip 23.0.1, setuptools 69.0.2 and Flower 1.8.0:" -msgstr "다음 예시에서는 Python 3.11.0, pip 23.0.1 그리고 setuptools 69.0.2의 base 이미지를 만듭니다:" +"The following example creates a base Ubuntu/Alpine image with Python 3.11.0, " +"pip 23.0.1, setuptools 69.0.2 and Flower 1.8.0:" +msgstr "" +"다음 예시에서는 Python 3.11.0, pip 23.0.1, setuptools 및 Flower 1.8.0으로 기" +"본 Ubuntu/Alpine 이미지를 만듭니다:" #: ../../source/contributor-how-to-build-docker-images.rst:88 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." +"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 "" -"이미지의 이름은 ``flwr_base``이고 태그는 ``0.1.0``입니다. 필요에 따라 빌드 argument들 뿐만 아니라 이름과" -" 태그도 정할 수 있습니다. 이 값들은 예시일 뿐입니다." +"이미지의 이름은 ``flwr_base``이고 태그는 ``0.1.0``입니다. 필요에 따라 빌드 " +"전달인자들 뿐만 아니라 이름과 태그도 정할 수 있습니다. 이 값들은 예시일 " +"뿐입니다." #: ../../source/contributor-how-to-build-docker-images.rst:92 -#, fuzzy msgid "Building the SuperLink/SuperNode or ServerApp image" -msgstr "SuperLink 이미지 빌드" +msgstr "SuperLink/SuperNode 또는 ServerApp 이미지 빌드" #: ../../source/contributor-how-to-build-docker-images.rst:102 msgid "``BASE_REPOSITORY``" @@ -278,45 +280,39 @@ msgstr "``BASE_REPOSITORY``" #: ../../source/contributor-how-to-build-docker-images.rst:103 msgid "The repository name of the base image." -msgstr "base 이미지의 리포지토리 이름." +msgstr "기본 이미지의 레포지토리 이름." #: ../../source/contributor-how-to-build-docker-images.rst:105 -#, fuzzy msgid "``flwr/base``" -msgstr "``FLWR_PACKAGE``" +msgstr "``flwr/base``" #: ../../source/contributor-how-to-build-docker-images.rst:106 -#, fuzzy msgid "``BASE_IMAGE``" -msgstr "``BASE_REPOSITORY``" +msgstr "``BASE_IMAGE``" #: ../../source/contributor-how-to-build-docker-images.rst:107 -#, fuzzy msgid "The Tag of the Flower base image." -msgstr "base 이미지의 리포지토리 이름." +msgstr "Flower 기본 이미지의 태그." #: ../../source/contributor-how-to-build-docker-images.rst:109 msgid "``1.8.0-py3.10-ubuntu22.04``" -msgstr "" +msgstr "``1.8.0-py3.10-ubuntu22.04``" #: ../../source/contributor-how-to-build-docker-images.rst:111 -#, fuzzy msgid "" -"The following example creates a SuperLink/SuperNode or ServerApp image " -"with the official Flower base image:" +"The following example creates a SuperLink/SuperNode or ServerApp image with " +"the official Flower base image:" msgstr "" -"다음 예시에서는 py3.11-ubuntu22.04 및 Flower 1.8.0의 공식 Flower base 이미지로 SuperLink" -" 이미지를 만듭니다:" +"다음 예시에서는 공식 Flower 기본 이미지로 SuperLink/SuperNode 또는 ServerApp" +"이미지를 만듭니다:" #: ../../source/contributor-how-to-build-docker-images.rst:122 -#, fuzzy 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`` build " -"argument." +"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`` build argument." msgstr "" -"공식 Flower base 이미지 대신 자체 base 이미지를 사용 하길 원한다면, ``BASE_REPOSITORY``, " -"``PYTHON_VERSION`` 및 ``UBUNTU_VERSION`` 빌드 argument들을 설정해야 합니다." +"공식 Flower 기본 이미지 대신 자체 기본 이미지를 사용 하길 원한다면, " +"``BASE_REPOSITORY`` 빌드 전달인자들을 설정해야 합니다." #: ../../source/contributor-how-to-build-docker-images.rst:133 msgid "After creating the image, we can test whether the image is working:" @@ -328,29 +324,30 @@ 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 prerequisites." -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 " +"prerequisites." +msgstr "" +"`Flower 1.5 `_ 부터 문서 페이지에 번역을 도입했지만, 아시다시피 " +"번역이 불안전한 경우가 많습니다. 만일 영어 이외의 언어를 사용한다면, 많은 " +"사람들이 연합 학습에 접근할 수 있도록 번역 작업에 기여함으로써 저희의 노력에 " +"도움을 주실 수 있습니다! 이는 전제 조건이 거의 없는 오픈 소스 기여자가 " +"되고자 하는 사람들에게 좋은 기회가 될 수도 있습니다." #: ../../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 `_에서 공개적으로 진행되며, 대부분의 작업이 이곳에서 이루어집니다." +"번역 프로젝트는 `Weblate `_에서 공개적으로 진행되며, 대부분의 작업이 이곳에서 이루어집니다." #: ../../source/contributor-how-to-contribute-translations.rst:18 msgid "Contribute to existing languages" @@ -358,43 +355,43 @@ 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 "" -"기여를 하기 위해 가장 먼저 해야 할 일은 해당 `page " -"`_에서 무료 Weblate 계정을 만드는 " -"것입니다. 프로필 설정에 대한 자세한 정보는 `here " -"`_를 참조하세요." +"기여를 하기 위해 가장 먼저 해야 할 일은 해당 `page `_에서 무료 Weblate 계정을 만드는 것입니다. 프로필 설" +"정에 대한 자세한 정보는 `here `_를 참조하세요." #: ../../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 project " -"`_로 이동할 수 " -"있습니다. 여기에서 웹사이트에 있는 다양한 기존 언어들을 확인할 수 있습니다." +"Weblate에 로그인한 후, `Flower Framework project `_로 이동할 수 있습니다. 여기에서 웹사이트에 " +"있는 다양한 기존 언어들을 확인할 수 있습니다." #: ../../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." +"button on the top right (in the ``Translation status`` section). This will " +"automatically bring you to the translation interface for untranslated " +"strings." msgstr "" -"여기서 가장 간단한 옵션은 오른쪽 상단(``Translation status`` 부분)에 있는 ``Translate`` 버튼을 " -"클릭하는 것 입니다. 번역되지 않은 문장에 대한 번역 인터페이스로 자동으로 이동합니다." +"여기서 가장 간단한 옵션은 오른쪽 상단(``Translation status`` 부분)에 있는 " +"``Translate`` 버튼을 클릭하는 것 입니다. 번역되지 않은 문장에 대한 번역 인터" +"페이스로 자동으로 이동합니다." #: ../../source/contributor-how-to-contribute-translations.rst:43 msgid "This is what the interface looks like:" @@ -402,44 +399,47 @@ msgstr "인터페이스는 다음과 같습니다:" #: ../../source/contributor-how-to-contribute-translations.rst:47 msgid "" -"You input your translation in the text box 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 text box 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 "" -"번역문을 상단의 텍스트 상자에 입력한 후, 번역이 만족스러우면 ``Save and continue``(번역을 저장하고 다음 미번역 " -"문장으로 이동), ``Save and stay``(번역을 저장하고 해당 페이지에 머무르기), ``Suggest`` (다른 사용자가 " -"볼 수 있도록 번역을 제안 항목에 추가), ``Skip``(아무것도 저장하지 않고 다음 미번역 문장으로 이동) 중 하나를 선택하면 " -"됩니다." +"번역문을 상단의 텍스트 상자에 입력한 후, 번역이 만족스러우면 ``Save and " +"continue``(번역을 저장하고 다음 미번역 문장으로 이동), ``Save and stay``(번역" +"을 저장하고 해당 페이지에 머무르기), ``Suggest`` (다른 사용자가 볼 수 있도록 " +"번역을 제안 항목에 추가), ``Skip``(아무것도 저장하지 않고 다음 미번역 문장으" +"로 이동) 중 하나를 선택하면 됩니다." #: ../../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 "오른쪽의 ``문자열 정보``에서 ``원본 문자열 위치``를 클릭하여 해당 문장이 포함된 문서의 파일 소스를 볼 수도 있습니다." +"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 " -"`_." +"For more information about translating using Weblate, you can check out this " +"`in-depth guide `_." msgstr "" -"Weblate를 통한 번역에 대한 자세한 정보는 `in-depth guide " -"`_를 확인하세요." +"Weblate를 통한 번역에 대한 자세한 정보는 `in-depth guide `_를 확인하세요." #: ../../source/contributor-how-to-contribute-translations.rst:67 msgid "Add new languages" @@ -447,12 +447,13 @@ 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 " -"`_에서 issue에 들어가 문의 해야 합니다." +"새 언어를 추가하려면, `Slack `에 문의하거나 " +"`GitHub repo `_에서 issue에 들어가 문의 해야 " +"합니다." #: ../../source/contributor-how-to-develop-in-vscode-dev-containers.rst:2 msgid "Develop in VSCode Dev Containers" @@ -460,49 +461,52 @@ msgstr "VSCode Dev Container에서 개발" #: ../../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 Remote Containers 확장을 사용하고 있습니다. 그것이 무엇인지 알아보기 위해 다음 인용문을 " -"읽어보세요:" +"Flower 프레임워크 작업시, 모든 기여자들이 코드 포맷팅이나 테스트 실행을 위해 " +"동일한 개발 환경을 사용하길 원합니다. 이를 위해 VSCode Remote Containers 확장" +"을 사용하고 있습니다. 그것이 무엇인지 알아보기 위해 다음 인용문을 읽어보세요:" #: ../../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 - 컨테이너 확장을 사용하면 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 - 컨테이너 확장을 사용하면 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 @@ -511,52 +515,57 @@ 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 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 "" -"`Dockerfile`을 설정하고 구성하는 것과 개발 컨테이너 구성은 약간 복잡할 수 있습니다. 다행히도, 이를 직접 할 필요는 " -"없습니다. 일반적으로 시스템에 `Docker `_를 " -"설치하고 커맨드 라인에서 사용할 수 있는지 확인하는 것으로 충분합니다. 추가로 `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 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 "" +"`Dockerfile`을 설정하고 구성하는 것과 개발 컨테이너 구성은 약간 복잡할 수 있" +"습니다. 다행히도, 이를 직접 할 필요는 없습니다. 일반적으로 시스템에 `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에 수동으로 개발 컨테이너를 사용하도록 지시하려면, 확장을 설치한 후, VSCode 창의 왼쪽 하단에 있는 " -"초록색 부을 클릭하고 *(Re)Open Folder in Container* 옵션을 선택하세요." +"이제 준비가 완료되었습니다. VSCode를 시작하면 컨테이너 환경에서 실행할지를 묻" +"고, 확인하면 자동으로 컨테이너를 빌드하고 사용할 것입니다. VSCode에 수동으로 " +"개발 컨테이너를 사용하도록 지시하려면, 확장을 설치한 후, VSCode 창의 왼쪽 하" +"단에 있는 초록색 부을 클릭하고 *(Re)Open Folder in Container* 옵션을 선택하세" +"요." #: ../../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 " -"`_" -msgstr "`컨테이너 원격 개발`_" +"`Remote development in Containers `_" +msgstr "" +"`컨테이너 원격 개발`_" #: ../../source/contributor-how-to-install-development-versions.rst:2 msgid "Install development versions" @@ -572,19 +581,20 @@ msgstr "Poetry 사용하기(권장)" #: ../../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``의 dependency를 " -"업데이트한 다음, 재설치하세요(``poetry 설치``이전에 ``poetry.lock`` (``rm poetry.lock``)를 " -"제거하는 것을 잊지 마세요)." +"PyPI에서 ``flwr`` 사전 릴리스 설치하기: ``pyproject.toml``에서 ``flwr``의 " +"의존성을 업데이트한 다음, 재설치하세요(``poetry 설치``이전에 ``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 }`` (extras 제외)" +msgstr "" +"``flwr = { version = \"1.0.0a0\", allow-prereleases = true }`` (extras 제외)" #: ../../source/contributor-how-to-install-development-versions.rst:13 msgid "" @@ -596,9 +606,11 @@ 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``:" -msgstr "``pyproject.toml``을 통해 Flower 소스 코드의 로컬 복사본에서 ``flwr``을 설치하세요:" +"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)" @@ -606,11 +618,11 @@ msgstr "``flwr = { path = \"../../\", develop = true }`` (extras 제외)" #: ../../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\"] " -"}`` (extras 포함)" +"``flwr = { path = \"../../\", develop = true, extras = [\"simulation\"] }`` " +"(extras 포함)" #: ../../source/contributor-how-to-install-development-versions.rst:20 msgid "Install ``flwr`` from a local wheel file via ``pyproject.toml``:" @@ -618,11 +630,11 @@ msgstr "``pyproject.toml``을 통해 로컬 wheel file에서 ``flwr``을 설치 #: ../../source/contributor-how-to-install-development-versions.rst:22 msgid "" -"``flwr = { path = \"../../dist/flwr-1.8.0-py3-none-any.whl\" }`` (without" -" extras)" +"``flwr = { path = \"../../dist/flwr-1.8.0-py3-none-any.whl\" }`` (without " +"extras)" msgstr "" -"``flwr = { path = \"../../dist/flwr-1.8.0-py3-none-any.whl\" }`` (extras " -"제외)" +"``flwr = { path = \"../../dist/flwr-1.8.0-py3-none-any.whl\" }`` (extras 제" +"외)" #: ../../source/contributor-how-to-install-development-versions.rst:23 msgid "" @@ -638,8 +650,8 @@ msgid "" "Dependency Specification `_" msgstr "" -"자세한 내용은 Poetry 문서를 참고하세요: `Poetry Dependency Specification `_" +"자세한 내용은 Poetry 문서를 참고하세요: `Poetry Dependency Specification " +"`_" #: ../../source/contributor-how-to-install-development-versions.rst:28 msgid "Using pip (recommended on Colab)" @@ -647,7 +659,7 @@ msgstr "pip 사용하기(Colab에서 권장)" #: ../../source/contributor-how-to-install-development-versions.rst:30 msgid "Install a ``flwr`` pre-release from PyPI:" -msgstr "PyPI에서 ``flwr`` 사전 릴리스를 설치하기:" +msgstr "PyPI에서 ``flwr`` 사전 릴리즈를 설치하기:" #: ../../source/contributor-how-to-install-development-versions.rst:32 msgid "``pip install -U --pre flwr`` (without extras)" @@ -662,8 +674,8 @@ 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를 " -"설치하세요." +"Python 패키지는 git 저장소에서 설치할 수 있습니다. 다음 명령어 중 하나를 사용" +"하여 GitHub에서 직접 Flower를 설치하세요." #: ../../source/contributor-how-to-install-development-versions.rst:37 msgid "Install ``flwr`` from the default GitHub branch (``main``):" @@ -671,9 +683,9 @@ msgstr "기본 GitHub branch (``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`` (extras 제외)" +"``pip install flwr@git+https://github.com/adap/flower.git`` (without extras)" +msgstr "" +"``pip install flwr@git+https://github.com/adap/flower.git`` (extras 제외)" #: ../../source/contributor-how-to-install-development-versions.rst:40 msgid "" @@ -697,11 +709,11 @@ msgstr "" #: ../../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 install flwr[simulation]@git+https://github.com/adap/flower.git" -"@branch-name`` (extras 포함)" +"``pip install flwr[simulation]@git+https://github.com/adap/flower.git@branch-" +"name`` (extras 포함)" #: ../../source/contributor-how-to-install-development-versions.rst:49 msgid "Open Jupyter Notebooks on Google Colab" @@ -712,32 +724,32 @@ msgid "" "Open the notebook ``doc/source/tutorial-series-get-started-with-flower-" "pytorch.ipynb``:" msgstr "" -"``doc/source/tutorial-series-get-started-with-flower-" -"pytorch.ipynb``notebook을 엽니다:" +"``doc/source/tutorial-series-get-started-with-flower-pytorch.ipynb``notebook" +"을 엽니다:" #: ../../source/contributor-how-to-install-development-versions.rst:53 msgid "" -"https://colab.research.google.com/github/adap/flower/blob/main/doc/source" -"/tutorial-series-get-started-with-flower-pytorch.ipynb" +"https://colab.research.google.com/github/adap/flower/blob/main/doc/source/" +"tutorial-series-get-started-with-flower-pytorch.ipynb" msgstr "" -"https://colab.research.google.com/github/adap/flower/blob/main/doc/source" -"/tutorial-series-get-started-with-flower-pytorch.ipynb" +"https://colab.research.google.com/github/adap/flower/blob/main/doc/source/" +"tutorial-series-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`` 바로 뒤)으로 변경하여 동일한 notebook의 개발 버전을 브랜치 " -"`branch-name`에서 엽니다 :" +"``main``을 ``branch-name``(``blob`` 바로 뒤)으로 변경하여 동일한 notebook의 " +"개발 버전을 브랜치 `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-series-get-started-with-flower-pytorch.ipynb" +"https://colab.research.google.com/github/adap/flower/blob/branch-name/doc/" +"source/tutorial-series-get-started-with-flower-pytorch.ipynb" msgstr "" -"https://colab.research.google.com/github/adap/flower/blob/branch-" -"name/doc/source/tutorial-series-get-started-with-flower-pytorch.ipynb" +"https://colab.research.google.com/github/adap/flower/blob/branch-name/doc/" +"source/tutorial-series-get-started-with-flower-pytorch.ipynb" #: ../../source/contributor-how-to-install-development-versions.rst:59 msgid "Install a `whl` on Google Colab:" @@ -745,9 +757,11 @@ 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 "왼쪽의 수직 아이콘 그리드에서 ``Files`` > ``Upload to session storage``를 선택하세요" +"In the vertical icon grid on the left hand side, select ``Files`` > ``Upload " +"to session storage``" +msgstr "" +"왼쪽의 수직 아이콘 그리드에서 ``Files`` > ``Upload to session storage``를 선" +"택하세요" #: ../../source/contributor-how-to-install-development-versions.rst:62 msgid "Upload the whl (e.g., ``flwr-1.8.0-py3-none-any.whl``)" @@ -755,13 +769,13 @@ msgstr "whl (예:``flwr-1.8.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.8.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.8.0-py3-none-any.whl[simulation]' torch " -"torchvision matplotlib``로 바꾸세요" +"``!pip install -q 'flwr[simulation]' torch torchvision matplotlib``를 ``!pip " +"install -q 'flwr-1.8.0-py3-none-any.whl[simulation]' torch torchvision " +"matplotlib``로 바꾸세요" #: ../../source/contributor-how-to-release-flower.rst:2 msgid "Release Flower" @@ -771,7 +785,8 @@ msgstr "Flower 릴리즈 하기" 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 "During the release" @@ -779,12 +794,11 @@ msgstr "릴리즈 동안에" #: ../../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 " -"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의 새 버전을 릴리즈하려면 다음 작업이 " -"순서대로 수행되어야 합니다:" +"릴리즈의 버전 번호는 ``pyproject.toml``에 명시되어 있습니다. Flower의 새 버전" +"을 릴리즈하려면 다음 작업이 순서대로 수행되어야 합니다:" #: ../../source/contributor-how-to-release-flower.rst:11 msgid "" @@ -792,998 +806,1184 @@ msgid "" "order to add every new change to the changelog (feel free to make manual " "changes to the changelog afterwards until it looks good)." msgstr "" -"모든 새로운 변경 사항을 변경 로그에 추가하기 위해``python3 " -"src/py/flwr_tool/update_changelog.py ``을 실행합니다 (변경 로그가 " -"만족스러워질 때까지 수동으로 변경해도 됩니다)." +"모든 새로운 변경 사항을 변경 로그에 추가하기 위해``python3 src/py/flwr_tool/" +"update_changelog.py ``을 실행합니다 (변경 로그가 만족스러워질 " +"때까지 수동으로 변경해도 됩니다)." #: ../../source/contributor-how-to-release-flower.rst:12 msgid "" -"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." +"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 "" -"모든 변경 사항으로 변경 로그가 업데이트되면,``./dev/prepare-release-changelog.sh " -"v``을 실행합니다. 여기서 ````은 ``pyproject.toml``에 명시된 " -"버전 번호입니다 (앞에 ``v``가 추가된 것을 주의하세요). 이 명령어는 변경 로그의 ``Unreleased``헤더를 해당 버전과" -" 현재 날짜로 교체하고, 기여자들에게 감사 메시지가 추가됩니다. 이러한 변경 사항으로 pull request합니다." +"모든 변경 사항으로 변경 로그가 업데이트되면,``./dev/prepare-release-" +"changelog.sh v``을 실행합니다. 여기서 ````은 " +"``pyproject.toml``에 명시된 버전 번호입니다 (앞에 ``v``가 추가된 것을 주의하" +"세요). 이 명령어는 변경 로그의 ``Unreleased``헤더를 해당 버전과 현재 날짜로 " +"교체하고, 기여자들에게 감사 메시지가 추가됩니다. 이러한 변경 사항으로 pull " +"request합니다." #: ../../source/contributor-how-to-release-flower.rst:13 msgid "" "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." +"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 "" +"pull request가 병합되면, PR이 병합되는 즉시 버전 번호로 릴리즈 커밋에 태그를 " +"지정합니다:``git tag v`` (버전 번호 앞에 ``v``가 추가된 것을 확" +"인), 그 다음 ``git push --tags``. 이렇게 하면 올바른 아티팩트와 변경 로그의 " +"관련 부분이 포함된 초안 릴리즈가 GitHub에 생성됩니다." #: ../../source/contributor-how-to-release-flower.rst:14 -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:15 -#, fuzzy msgid "Trigger the CI for building the Docker images." -msgstr "공식 Ubuntu Docker 이미지 버전." +msgstr "Docker 이미지 빌드를 위해 CI를 트리거합니다." #: ../../source/contributor-how-to-release-flower.rst:17 msgid "" -"To trigger the workflow, a collaborator must create a " -"``workflow_dispatch`` event in the GitHub CI. This can be done either " -"through the UI or via the GitHub CLI. The event requires only one input, " -"the Flower version, to be released." +"To trigger the workflow, a collaborator must create a ``workflow_dispatch`` " +"event in the GitHub CI. This can be done either through the UI or via the " +"GitHub CLI. The event requires only one input, the Flower version, to be " +"released." msgstr "" +"워크플로우를 트리거하려면 공동 작업자가 GitHub CI에서 ``workflow_dispatch``" +"를 생성해야 합니다. 이 작업은 UI 또는 GitHub CLI 를 통해 수행할 수 있습니다. " +"이벤트는 Flower 버전 한 가지 입력만 필요합니다." #: ../../source/contributor-how-to-release-flower.rst:21 msgid "**Via the UI**" -msgstr "" +msgstr "**UI를 통해서**" #: ../../source/contributor-how-to-release-flower.rst:23 msgid "" -"Go to the ``Build docker images`` workflow `page " -"`_." +"Go to the ``Build docker images`` workflow `page `_." msgstr "" +"``Build docker images`` 워크플로우 `페이지 `_로 이동합니다." #: ../../source/contributor-how-to-release-flower.rst:24 msgid "" -"Click on the ``Run workflow`` button and type the new version of Flower " -"in the ``Version of Flower`` input field." +"Click on the ``Run workflow`` button and type the new version of Flower in " +"the ``Version of Flower`` input field." msgstr "" +"``Run workflow`` 버튼을 누르고 ``Version of Flower``에 Flower의 새버전을 입력" +"합니다." #: ../../source/contributor-how-to-release-flower.rst:25 msgid "Click on the **green** ``Run workflow`` button." -msgstr "" +msgstr "**초록색**의 ``Run workflow``버튼을 클릭합니다." #: ../../source/contributor-how-to-release-flower.rst:29 msgid "**Via the GitHub CI**" -msgstr "" +msgstr "**GitHub CI를 통해서**" #: ../../source/contributor-how-to-release-flower.rst:31 msgid "" "Make sure you are logged in via ``gh auth login`` and that the current " "working directory is the root of the Flower repository." msgstr "" +"``gh auth login``을 통해 로그인 했는지, 현재 작업 디렉토리가 Flower 리포지토" +"리의 root인지 확인하세요." #: ../../source/contributor-how-to-release-flower.rst:32 msgid "" "Trigger the workflow via ``gh workflow run docker-images.yml -f flwr-" "version=``." msgstr "" +"``gh workflow run docker-images.yml -f flwr-version=``을 통해 워" +"크플로우 를 트리거합니다." #: ../../source/contributor-how-to-release-flower.rst:35 msgid "After the release" -msgstr "" +msgstr "릴리즈 후에" #: ../../source/contributor-how-to-release-flower.rst:37 msgid "Create a pull request which contains the following changes:" -msgstr "" +msgstr "다음 변경 사항이 포함된 pull request를 만듭니다:" #: ../../source/contributor-how-to-release-flower.rst:39 msgid "Increase the minor version in ``pyproject.toml`` by one." -msgstr "" +msgstr "``pyproject.toml``의 마이너 버전을 하나씩 늘립니다." #: ../../source/contributor-how-to-release-flower.rst:40 msgid "Update all files which contain the current version number if necessary." -msgstr "" +msgstr "필요한 경우 현재 버전 번호가 포함된 모든 파일을 업데이트합니다." #: ../../source/contributor-how-to-release-flower.rst:41 msgid "Add a new ``Unreleased`` section in ``changelog.md``." -msgstr "" +msgstr "``changelog.md``에 ``Unreleased`` 섹션을 새로 추가합니다." #: ../../source/contributor-how-to-release-flower.rst:43 msgid "" -"Merge the pull request on the same day (i.e., before a new nightly " -"release gets published to PyPI)." +"Merge the pull request on the same day (i.e., before a new nightly release " +"gets published to PyPI)." msgstr "" +"pull request를 같은 날(즉, 새로운 nightly 릴리즈가 PyPI에 게시되기 전에) 병합" +"하세요." #: ../../source/contributor-how-to-release-flower.rst:46 msgid "Publishing a pre-release" -msgstr "" +msgstr "사전 릴리즈 게시" #: ../../source/contributor-how-to-release-flower.rst:49 msgid "Pre-release naming" -msgstr "" +msgstr "사전 릴리즈 이름" #: ../../source/contributor-how-to-release-flower.rst:51 msgid "" -"PyPI supports pre-releases (alpha, beta, release candidate). Pre-releases" -" MUST use one of the following naming patterns:" +"PyPI supports pre-releases (alpha, beta, release candidate). Pre-releases " +"MUST use one of the following naming patterns:" msgstr "" +"PyPI는 사전 릴리즈(알파, 베타, 릴리스 후보)를 지원합니다. 사전 릴리즈는 반드" +"시 다음 명명 패턴 중 하나를 사용해야 합니다:" #: ../../source/contributor-how-to-release-flower.rst:53 msgid "Alpha: ``MAJOR.MINOR.PATCHaN``" -msgstr "" +msgstr "Alpha: ``MAJOR.MINOR.PATCHaN``" #: ../../source/contributor-how-to-release-flower.rst:54 msgid "Beta: ``MAJOR.MINOR.PATCHbN``" -msgstr "" +msgstr "Beta: ``MAJOR.MINOR.PATCHbN``" #: ../../source/contributor-how-to-release-flower.rst:55 msgid "Release candidate (RC): ``MAJOR.MINOR.PATCHrcN``" -msgstr "" +msgstr "Release candidate (RC): ``MAJOR.MINOR.PATCHrcN``" #: ../../source/contributor-how-to-release-flower.rst:57 msgid "Examples include:" -msgstr "" +msgstr "예시:" #: ../../source/contributor-how-to-release-flower.rst:59 msgid "``1.0.0a0``" -msgstr "" +msgstr "``1.0.0a0``" #: ../../source/contributor-how-to-release-flower.rst:60 msgid "``1.0.0b0``" -msgstr "" +msgstr "``1.0.0b0``" #: ../../source/contributor-how-to-release-flower.rst:61 msgid "``1.0.0rc0``" -msgstr "" +msgstr "``1.0.0rc0``" #: ../../source/contributor-how-to-release-flower.rst:62 msgid "``1.0.0rc1``" -msgstr "" +msgstr "``1.0.0rc1``" #: ../../source/contributor-how-to-release-flower.rst:64 msgid "" "This is in line with PEP-440 and the recommendations from the Python " "Packaging Authority (PyPA):" msgstr "" +"이는 PEP-440 및 Python Packaging Authority (PyPA)의 권장 사항과 일치합니다:" #: ../../source/contributor-how-to-release-flower.rst:67 msgid "`PEP-440 `_" -msgstr "" +msgstr "`PEP-440 `_" #: ../../source/contributor-how-to-release-flower.rst:68 msgid "" -"`PyPA Choosing a versioning scheme " -"`_" +"`PyPA Choosing a versioning scheme `_" msgstr "" +"`PyPA 버전 관리 체계 선택하기 `_" #: ../../source/contributor-how-to-release-flower.rst:70 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 사양과 호환되지 않으며, 자세한 내용" +"은`Semantic Versioning 관리 사양 `_ (특히 항목 11이 우선순위)을 참조하세요." #: ../../source/contributor-how-to-release-flower.rst:73 msgid "Pre-release classification" -msgstr "" +msgstr "사전 릴리즈 분류" #: ../../source/contributor-how-to-release-flower.rst:75 -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:77 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: 기능 완료, 알려진 문제 없음(다음 stable 릴리즈에서 \"수정되지 않음\"으로 " +"분류된 문제 제외) - 문제가 나타나지 않으면 다음 stable 릴리즈가 됩니다" #: ../../source/contributor-how-to-release-flower.rst:78 msgid "Beta: feature complete, allowed to have known issues" -msgstr "" +msgstr "베타: 기능 완료, 알려진 문제 발생 가능" #: ../../source/contributor-how-to-release-flower.rst:79 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 "" +"가상 환경 내에서 파이썬 설정을 실행하는 것이 좋습니다. 이 가이드에서는 pyenv " +"virtualenv, poetry 또는 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 "" -"Due to a known incompatibility with `ray " -"`_, we currently recommend utilizing at " -"most `Python 3.11 `_ for running Flower " -"simulations." +"Due to a known incompatibility with `ray `_, " +"we currently recommend utilizing at most `Python 3.11 `_ for running Flower simulations." msgstr "" +"`Ray `__와 호환되지 않는 것으로 알려져 있으므" +"로, 현재 Flower 시뮬레이션을 실행할 때는 최대 `Python 3.11 `_을 사용하는 것이 좋습니다." #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:19 msgid "Virtualenv with Pyenv/Virtualenv" -msgstr "" +msgstr "Pyenv/Virtualenv를 사용한 가상 환경" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:21 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 examples `_를 " +"참조하세요." #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:23 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:29 msgid "Create the virtualenv with:" -msgstr "" +msgstr "가상 환경을 만듭니다:" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:36 msgid "Activate the virtualenv by running the following command:" -msgstr "" +msgstr "다음 명령을 실행하여 가상 환경을 활성화합니다:" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:44 msgid "Virtualenv with Poetry" -msgstr "" +msgstr "Poetry를 사용한 가상 환경" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:46 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 examples은 의존성을 관리하기 위해 `Poetry `_를 기반으로 합니다. Poetry를 설치한 후 가상 환경을 생성하기만 하면 " +"됩니다:" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:52 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:60 msgid "Virtualenv with Anaconda" -msgstr "" +msgstr "Anaconda를 사용한 가상 환경" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:62 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:68 msgid "and activate the virtual environment with:" -msgstr "" +msgstr "그 후 가상 환경을 활성화합니다:" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:76 msgid "And then?" -msgstr "" +msgstr "그다음은?" #: ../../source/contributor-how-to-set-up-a-virtual-env.rst:78 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 examples `_ 중 하나를 클론합니다." #: ../../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:169 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 "" +"문서를 컴파일합니다: ``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 "" +"Flower에 대한 기여를 환영합니다! 하지만 어디서부터 시작해야 할지 알기란 쉽지 " +"않습니다. 그래서 저희는 여러분의 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 "Baselines: 아래를 참조하세요." #: ../../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 Baselines 요청" #: ../../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 Baseline에 익숙하지 않다면 ' Baseline 기여 가이드 `_를 확인해보세요." #: ../../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 assignees, 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 " +"assignees, feel free to assign it to yourself and start working on it!" msgstr "" +"그런 다음 오픈 된 `issues `_에서 baseline " +"요청을 확인해야 합니다. 작업하고 싶은 기준선을 찾았지만 담당자가 없는 경우, " +"자유롭게 자신에게 할당하고 작업을 시작하세요!" #: ../../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 "" +"그렇지 않으면 작업하고 싶은 baseline을 찾지 못하면 baseline 요청 템플릿으로 " +"새 이슈를 열어야 합니다!" #: ../../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 "Llama 2 미세 조정, Hugging Face Transformer와 파이토치 포함" #: ../../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 "Android ONNX 온디바이스 훈련" #: ../../source/contributor-ref-secure-aggregation-protocols.rst:2 msgid "Secure Aggregation Protocols" -msgstr "" +msgstr "Secure Aggregation 프로토콜" #: ../../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 "The :code:`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 "" +"구현에서는 각 클라이언트에 secure aggregation를 위한 고유 인덱스(int)가 할당" +"되므로 사용되는 많은 파이썬 dictionaries에는 ClientProxy 타입이 아닌 int 타입" +"의 키가 있습니다." #: ../../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 "The :code:`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." +"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 :doc:`getting started guide for contributors " -"`." +"If you're familiar with how contributing on GitHub works, you can directly " +"checkout our :doc:`getting started guide for contributors `." msgstr "" +"깃허브에서 기여하는 방식에 익숙하다면 :doc:`기여자를 위한 시작 가이드" +"`를 직접 확인하세요." #: ../../source/contributor-tutorial-contribute-on-github.rst:10 msgid "Setting up the repository" -msgstr "" +msgstr "레포지토리 설정하기" #: ../../source/contributor-tutorial-contribute-on-github.rst:21 msgid "**Create a GitHub account and setup Git**" -msgstr "" +msgstr "**GitHub 계정을 만들고 Git을 설정합니다**" #: ../../source/contributor-tutorial-contribute-on-github.rst:13 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:16 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:18 msgid "" "If you haven't already, you will need to create an account on `GitHub " "`_." msgstr "" +"아직 계정을 만들지 않았다면 `GitHub `_에서 계정을 " +"만들어야 합니다." #: ../../source/contributor-tutorial-contribute-on-github.rst:20 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:32 msgid "**Forking the Flower repository**" -msgstr "" +msgstr "**Flower 레포지토리 포크하기**" #: ../../source/contributor-tutorial-contribute-on-github.rst:24 msgid "" -"A fork is a personal copy of a GitHub repository. To create one for " -"Flower, you must navigate to ``_ (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 ``_ (while connected to " +"your GitHub account) and click the ``Fork`` button situated on the top right " +"of the page." msgstr "" +"포크는 GitHub 리포지토리의 개인 복사본입니다. Flower용 포크를 만들려면 " +"``_로 이동하여(GitHub 계정에 연결된 상태에" +"서) 페이지 오른쪽 상단에 있는 ``포크`` 버튼을 클릭해야 합니다." #: ../../source/contributor-tutorial-contribute-on-github.rst:29 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:47 msgid "**Cloning your forked repository**" -msgstr "" +msgstr "**포크된 레포지토리 클론하기**" #: ../../source/contributor-tutorial-contribute-on-github.rst:35 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 "" +"다음 단계는 컴퓨터에서 포크된 레포지토리를 변경할 수 있도록 다운로드하는 것입" +"니다. 포크된 포지토리 페이지에서 먼저 오른쪽의 ``Code`` 버튼을 클릭하면 레포" +"지토리의 HTTPS 링크를 복사할 수 있습니다." #: ../../source/contributor-tutorial-contribute-on-github.rst:41 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:47 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/``(또는 포크 이름을 변경한 경우 포크 이름) 폴더" +"가 생성됩니다." #: ../../source/contributor-tutorial-contribute-on-github.rst:66 msgid "**Add origin**" -msgstr "" +msgstr "**origin 추가**" #: ../../source/contributor-tutorial-contribute-on-github.rst:50 msgid "You can then go into the repository folder:" -msgstr "" +msgstr "그런 다음 레포지토리 폴더로 이동할 수 있습니다:" #: ../../source/contributor-tutorial-contribute-on-github.rst:56 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은 원격 포크 레포지토리" +"의 \\입니다. origin을 얻으려면 앞서 설명한 대로 GitHub 계정의 포크 레" +"포지토리로 이동하여 링크를 복사하면 됩니다." #: ../../source/contributor-tutorial-contribute-on-github.rst:61 msgid "" "Once the \\ is copied, we can type the following command in our " "terminal:" -msgstr "" +msgstr "\\ 이 복사되면 터미널에 다음 명령을 입력하면 됩니다:" #: ../../source/contributor-tutorial-contribute-on-github.rst:90 msgid "**Add upstream**" -msgstr "" +msgstr "**Upstream 추가하기**" #: ../../source/contributor-tutorial-contribute-on-github.rst:69 msgid "" "Now we will add an upstream address to our repository. Still in the same " "directory, we must run the following command:" msgstr "" +"이제 레포지토리에 upstream 주소를 추가하겠습니다. 여전히 같은 디렉터리에서 다" +"음 명령을 실행해야 합니다:" #: ../../source/contributor-tutorial-contribute-on-github.rst:76 -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:80 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 "" +"upstream은 부모 레포지토리(이 경우 Flower)의 GitHub 원격 주소, 즉 우리가 최종" +"적으로 기여하고 싶고 따라서 최신 기록이 필요한 레포지토리입니다. origin은 우" +"리가 만든 포크된 레포지토리의 GitHub 원격 주소, 즉 우리 계정에 있는 사본(포" +"크)입니다." #: ../../source/contributor-tutorial-contribute-on-github.rst:84 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:93 msgid "Setting up the coding environment" -msgstr "" +msgstr "코딩 환경 설정" #: ../../source/contributor-tutorial-contribute-on-github.rst:95 msgid "" "This can be achieved by following this :doc:`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 "" +":doc:'기여자를 위한 시작 가이드 '를 참조하세요(레포지토리를 복제할 필요는 없습니다). 코드를 " +"작성하고 테스트할 수 있게 되면 드디어 변경을 시작할 수 있습니다!" #: ../../source/contributor-tutorial-contribute-on-github.rst:100 msgid "Making changes" -msgstr "" +msgstr "변경하기" #: ../../source/contributor-tutorial-contribute-on-github.rst:102 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:108 msgid "And with Flower's repository:" -msgstr "" +msgstr "Flower의 레포지토리도 있습니다:" #: ../../source/contributor-tutorial-contribute-on-github.rst:122 msgid "**Create a new branch**" -msgstr "" +msgstr "**새 브랜치 만들기**" #: ../../source/contributor-tutorial-contribute-on-github.rst:115 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:118 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:125 msgid "**Make changes**" -msgstr "" +msgstr "**변경하기**" #: ../../source/contributor-tutorial-contribute-on-github.rst:125 -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:138 msgid "**Test and format your code**" -msgstr "" +msgstr "**코드 테스트 및 서식 지정**" #: ../../source/contributor-tutorial-contribute-on-github.rst:128 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:131 msgid "To do so, we have written a few scripts that you can execute:" -msgstr "" +msgstr "이를 위해 실행할 수 있는 몇 가지 스크립트를 작성했습니다:" #: ../../source/contributor-tutorial-contribute-on-github.rst:150 msgid "**Stage changes**" -msgstr "" +msgstr "**Stage 변경**" #: ../../source/contributor-tutorial-contribute-on-github.rst:141 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:143 msgid "This can be done with:" -msgstr "" +msgstr "이 작업을 수행할 수 있습니다:" #: ../../source/contributor-tutorial-contribute-on-github.rst:149 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:160 msgid "**Commit changes**" -msgstr "" +msgstr "**Commit 변경**" #: ../../source/contributor-tutorial-contribute-on-github.rst:153 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:159 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:171 msgid "**Push the changes to the fork**" -msgstr "" +msgstr "**변경 사항을 포크에 푸시**" #: ../../source/contributor-tutorial-contribute-on-github.rst:163 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:170 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:174 msgid "Creating and merging a pull request (PR)" -msgstr "" +msgstr "pull request(PR) 만들기 및 병합하기" #: ../../source/contributor-tutorial-contribute-on-github.rst:206 msgid "**Create the PR**" -msgstr "" +msgstr "**PR 만들기**" #: ../../source/contributor-tutorial-contribute-on-github.rst:177 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:181 msgid "Otherwise you can always find this option in the ``Branches`` page." msgstr "" +"그렇지 않으면 언제든지 ``Branches`` 페이지에서 이 옵션을 찾을 수 있습니다." #: ../../source/contributor-tutorial-contribute-on-github.rst:183 msgid "" "Once you click the ``Compare & pull request`` button, you should see " "something similar to this:" msgstr "" +"``Compare & pull request`` 버튼을 클릭하면 이와 비슷한 화면이 표시됩니다:" #: ../../source/contributor-tutorial-contribute-on-github.rst:187 -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:191 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:193 msgid "" "The title should be changed to adhere to the :ref:`pr_title_format` " -"guidelines, otherwise it won't be possible to merge the PR. So in this " -"case, a correct title might be ``docs(framework:skip) Fix typos``." +"guidelines, otherwise it won't be possible to merge the PR. So in this case, " +"a correct title might be ``docs(framework:skip) Fix typos``." msgstr "" +"제목은 :ref:`pr_title_format` 가이드라인을 준수하도록 변경해야 하며, 그렇지 " +"않으면 PR을 병합할 수 없습니다. 따라서 이 경우 올바른 제목은 " +"``docs(framework:skip) Fix typos``이 될 수 있습니다." #: ../../source/contributor-tutorial-contribute-on-github.rst:196 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:199 msgid "It is important to follow the instructions described in comments." -msgstr "" +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." +"reviewers that a new PR has been opened and that they should look over it to " +"merge or to request changes." msgstr "" +"하단에는 PR을 여는 버튼이 있습니다. 이렇게 하면 검토자에게 새 PR이 열렸으며 " +"병합하거나 변경을 요청하기 위해 검토해야 함을 알립니다." #: ../../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:" +"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이 아직 검토할 준비가 되지 않았고 다른 사람에게 알리고 싶지 않은 경우 pull " +"request 초안을 만드는 옵션이 있습니다:" #: ../../source/contributor-tutorial-contribute-on-github.rst:209 msgid "**Making new changes**" -msgstr "" +msgstr "**new changes 만들기**" #: ../../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." +"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:231 msgid "**Review the PR**" -msgstr "" +msgstr "**PR 검토하기**" #: ../../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: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:218 msgid "Merging will be blocked if there are ongoing requested changes." -msgstr "" +msgstr "진행 중인 변경 요청이 있는 경우 병합이 차단됩니다." #: ../../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:226 msgid "And resolve the conversation:" -msgstr "" +msgstr "그리고 소통을 통해 해결하세요:" #: ../../source/contributor-tutorial-contribute-on-github.rst:230 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:251 msgid "**Once the PR is merged**" -msgstr "" +msgstr "**PR이 병합되면**" #: ../../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." +"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: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에서 브랜치를 삭제할 수 있으며(삭제 버튼이 표시되어야 " +"함), 로컬에서도 삭제할 수 있습니다:" #: ../../source/contributor-tutorial-contribute-on-github.rst:245 msgid "Then you should update your forked repository by doing:" -msgstr "" +msgstr "그런 다음 다음을 수행하여 포크된 레포지토리를 업데이트해야 합니다:" #: ../../source/contributor-tutorial-contribute-on-github.rst:254 msgid "Example of first contribution" -msgstr "" +msgstr "첫 번째 기여의 예" #: ../../source/contributor-tutorial-contribute-on-github.rst:257 msgid "Problem" -msgstr "" +msgstr "문제" #: ../../source/contributor-tutorial-contribute-on-github.rst:259 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:261 msgid "" -"Our \"How to\" guides should have titles that continue the sentence \"How" -" to …\", for example, \"How to upgrade to Flower 1.0\"." +"Our \"How to\" guides should have titles that continue the sentence \"How to " +"…\", for example, \"How to upgrade to Flower 1.0\"." msgstr "" +"'How to' 가이드의 제목은 \"How to …\"라는 문장을 이어가는 제목이어야 합니다" +"(예: \"How to upgrade to Flower 1.0\")." #: ../../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:265 msgid "" -"This issue is about changing the title of a doc from present continuous " -"to present simple." +"This issue is about changing the title of a doc from present continuous to " +"present simple." msgstr "" +"이번 이슈는 문서 제목을 현재 연속형에서 현재 단순형으로 변경하는 것에 관한 것" +"입니다." #: ../../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 "" +"\"How to saving progress\"을 \"How to save progress\"으로 변경한 예를 들어 보" +"겠습니다. 이것이 우리의 점검을 통과했나요?" #: ../../source/contributor-tutorial-contribute-on-github.rst:269 msgid "Before: \"How to saving progress\" ❌" -msgstr "" +msgstr "Before: \"How to saving progress\" ❌" #: ../../source/contributor-tutorial-contribute-on-github.rst:271 msgid "After: \"How to save progress\" ✅" -msgstr "" +msgstr "After: \"How to save progress\" ✅" #: ../../source/contributor-tutorial-contribute-on-github.rst:274 msgid "Solution" -msgstr "" +msgstr "해결법" #: ../../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 "" +"이것은 사소한 변경이지만 end-to-end 설정을 테스트할 수 있습니다. Flower " +"레포지토리를 복제하고 설정한 후에는 다음과 같이 하세요:" #: ../../source/contributor-tutorial-contribute-on-github.rst:278 msgid "Find the source file in ``doc/source``" -msgstr "" +msgstr "``doc/source``에서 소스 파일을 찾습니다" #: ../../source/contributor-tutorial-contribute-on-github.rst:279 msgid "" "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:280 msgid "" -"Build the docs and `check the result `_" +"Build the docs and `check the result `_" msgstr "" +"문서를 빌드하고 '결과 확인 `_'합니다" #: ../../source/contributor-tutorial-contribute-on-github.rst:283 msgid "Rename file" -msgstr "" +msgstr "파일 이름 바꾸기" #: ../../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:288 msgid "Here's how to change the file name:" -msgstr "" +msgstr "파일 이름을 변경하는 방법은 다음과 같습니다:" #: ../../source/contributor-tutorial-contribute-on-github.rst:290 msgid "Change the file name to ``save-progress.rst``" -msgstr "" +msgstr "파일 이름을 ``save-progress.rst``로 변경합니다" #: ../../source/contributor-tutorial-contribute-on-github.rst:291 msgid "Add a redirect rule to ``doc/source/conf.py``" -msgstr "" +msgstr "'doc/source/conf.py'에 리디렉션 규칙을 추가합니다" #: ../../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 "" +"이렇게 하면 ``saving-progress.html``에서 ``save-progress.html``로 리디렉션되" +"며, 이전 링크는 계속 작동합니다." #: ../../source/contributor-tutorial-contribute-on-github.rst:296 msgid "Apply changes in the index file" -msgstr "" +msgstr "인덱스 파일에 변경 사항 적용" #: ../../source/contributor-tutorial-contribute-on-github.rst:298 msgid "" @@ -1791,38 +1991,43 @@ 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:301 msgid "Find and modify the file name in ``index.rst``" -msgstr "" +msgstr "``index.rst``에서 파일 이름을 찾아 수정합니다" #: ../../source/contributor-tutorial-contribute-on-github.rst:304 msgid "Open PR" -msgstr "" +msgstr "PR 열기" #: ../../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 "" +"변경 사항을 커밋합니다(커밋 메시지는 항상 필수 메시지입니다:\"Do " +"something\"(이 경우 는 \"Change …\" )" #: ../../source/contributor-tutorial-contribute-on-github.rst:307 msgid "Push the changes to your fork" -msgstr "" +msgstr "변경 사항을 포크에 푸시합니다" #: ../../source/contributor-tutorial-contribute-on-github.rst:308 msgid "" -"Open a PR (as shown above) with title ``docs(framework) Update how-to " -"guide title``" +"Open a PR (as shown above) with title ``docs(framework) Update how-to guide " +"title``" msgstr "" +"``docs(framework) Update how-to guide title`` 제목으로 PR(위와 같이)을 엽니다" #: ../../source/contributor-tutorial-contribute-on-github.rst:309 msgid "Wait for it to be approved!" -msgstr "" +msgstr "승인될 때까지 기다리세요!" #: ../../source/contributor-tutorial-contribute-on-github.rst:310 msgid "Congrats! 🥳 You're now officially a Flower contributor!" -msgstr "" +msgstr "축하합니다! 이제 공식적으로 Flower 기여자가 되셨습니다!" #: ../../source/contributor-tutorial-contribute-on-github.rst:314 #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:548 @@ -1831,622 +2036,769 @@ 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:316 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:318 msgid "" -":doc:`Good first contributions `, where you should particularly look into the " -":code:`baselines` contributions." +":doc:`Good first contributions `, " +"where you should particularly look into the :code:`baselines` contributions." msgstr "" +":doc:`훌륭한 첫 번째 기여 `, 특히 :" +"code:`baselines` 기여를 살펴봐야 합니다." #: ../../source/contributor-tutorial-contribute-on-github.rst:322 #: ../../source/fed/0000-20200102-fed-template.md:60 msgid "Appendix" -msgstr "" +msgstr "부록" #: ../../source/contributor-tutorial-contribute-on-github.rst:327 msgid "PR title format" -msgstr "" +msgstr "PR 제목 형식" #: ../../source/contributor-tutorial-contribute-on-github.rst:329 msgid "We enforce the following PR title format:" -msgstr "" +msgstr "다음과 같은 PR 제목 형식을 적용합니다:" #: ../../source/contributor-tutorial-contribute-on-github.rst:335 msgid "" -"(or ``(:skip) `` to ignore the PR in the " -"changelog)" +"(or ``(:skip) `` to ignore the PR in the changelog)" msgstr "" +"(또는 ``(:skip) ``를 사용하면 변경 로그에서 PR을 무시" +"합니다.)" #: ../../source/contributor-tutorial-contribute-on-github.rst:337 msgid "" -"Where ```` needs to be in ``{ci, fix, feat, docs, refactor, " -"break}``, ```` should be in ``{framework, baselines, datasets, " -"examples, or '*' when modifying multiple projects which requires the " -"':skip' flag to be used}``, and ```` starts with a capitalised " -"verb in the imperative mood." +"Where ```` needs to be in ``{ci, fix, feat, docs, refactor, break}``, " +"```` should be in ``{framework, baselines, datasets, examples, or " +"'*' when modifying multiple projects which requires the ':skip' flag to be " +"used}``, and ```` starts with a capitalised verb in the imperative " +"mood." msgstr "" +"여기서 ````은 ``{ci, fix, feat, docs, refactor, break}``, ````" +"는 ``{framework, baselines, datasets, examples, or '*' ':skip' 플래그를 사용" +"해야 하는 여러 프로젝트를 수정하는 경우}``로 입력해야 하며, ````는 " +"대문자로 시작해야 합니다." #: ../../source/contributor-tutorial-contribute-on-github.rst:341 msgid "Valid examples:" -msgstr "" +msgstr "유효한 예시입니다:" #: ../../source/contributor-tutorial-contribute-on-github.rst:343 msgid "``feat(framework) Add flwr build CLI command``" -msgstr "" +msgstr "``feat(framework) Add flwr build CLI command``" #: ../../source/contributor-tutorial-contribute-on-github.rst:344 msgid "``refactor(examples:skip) Improve quickstart-pytorch logging``" -msgstr "" +msgstr "``refactor(examples:skip) Improve quickstart-pytorch logging``" #: ../../source/contributor-tutorial-contribute-on-github.rst:345 msgid "``ci(*:skip) Enforce PR title format``" -msgstr "" +msgstr "``ci(*:skip) Enforce PR title format``" #: ../../source/contributor-tutorial-contribute-on-github.rst:347 msgid "Invalid examples:" -msgstr "" +msgstr "잘못된 예시입니다:" #: ../../source/contributor-tutorial-contribute-on-github.rst:349 msgid "``feat(framework): Add flwr build CLI command`` (extra ``:``)" -msgstr "" +msgstr "``feat(framework): Add flwr build CLI command`` ( ``:``제외)" #: ../../source/contributor-tutorial-contribute-on-github.rst:350 msgid "" "``feat(*) Add flwr build CLI command`` (missing ``skip`` flag along with " "``*``)" msgstr "" +"``feat(*) Add flwr build CLI command`` (``skip`` flag와 함께 ``*``누락)" #: ../../source/contributor-tutorial-contribute-on-github.rst:351 msgid "``feat(skip) Add flwr build CLI command`` (missing ````)" -msgstr "" +msgstr "``feat(skip) Add flwr build CLI command`` (````누락)" #: ../../source/contributor-tutorial-contribute-on-github.rst:352 msgid "``feat(framework) add flwr build CLI command`` (non capitalised verb)" msgstr "" +"``feat(framework) add flwr build CLI command`` (대문자로 표기되지 않은 동사)" #: ../../source/contributor-tutorial-contribute-on-github.rst:353 msgid "``feat(framework) Add flwr build CLI command.`` (dot at the end)" -msgstr "" +msgstr "``feat(framework) Add flwr build CLI command.`` (끝에 마침표)" #: ../../source/contributor-tutorial-contribute-on-github.rst:354 msgid "``Add flwr build CLI command.`` (missing ``()``)" -msgstr "" +msgstr "``Add flwr build CLI command.`` ( ``()``누락)" #: ../../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 #: ../../source/how-to-run-flower-using-docker.rst:153 msgid "Prerequisites" -msgstr "" +msgstr "전제 조건" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:7 msgid "`Python 3.8 `_ or above" -msgstr "" +msgstr "Python 3.8 `_ 이상" #: ../../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는 dependencies을 관리하고 개발 도구(이를 지원하는 도구)를 구성하기 위" +"해 :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:21 msgid "Preliminarities" -msgstr "" +msgstr "사전 준비" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:22 msgid "Some system-wide dependencies are needed." -msgstr "" +msgstr "일부 시스템 전체에 대한 의존성이 필요합니다." #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:25 msgid "For macOS" -msgstr "" +msgstr "macOS의 경우" #: ../../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." +"Install `homebrew `_. Don't forget the post-installation " +"actions to add `brew` to your PATH." msgstr "" +"`homebrew `_를 설치합니다. 설치 후 `brew`를 PATH에 추가하" +"는 작업을 잊지 마세요." #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:28 msgid "" -"Install `xz` (to install different Python versions) and `pandoc` to build" -" the docs::" +"Install `xz` (to install different Python versions) and `pandoc` to build " +"the docs::" msgstr "" +"xz`(다른 Python 버전을 설치하려면)와 `pandoc`을 설치하여 문서를 빌드합니다::" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:34 msgid "For Ubuntu" -msgstr "" +msgstr "Ubuntu의 경우" #: ../../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::" +"Ensure you system (Ubuntu 22.04+) is up-to-date, and you have all necessary " +"packages::" msgstr "" +"시스템(우분투 22.04 이상)이 최신 상태이고 필요한 패키지가 모두 설치되어 있는" +"지 확인하세요:" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:44 msgid "Create Flower Dev Environment" -msgstr "" +msgstr "Flower 개발 환경 만들기" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:46 msgid "" "1. Clone the `Flower repository `_ from " "GitHub::" msgstr "" +"1. 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 " +"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 "" +"Flower의 모든 것을 위한 파이썬 환경을 만들어 보겠습니다.:code:`pyenv`를 사용" +"하고자 하는 경우 사용할 수 있는 두 가지 편의 스크립트를 제공합니다.:code:" +"`pyenv`가 아닌 다른 것을 사용하려면 새 환경을 생성하고 활성화한 후 모든 패키" +"지가 설치된 마지막 지점으로 건너뛰세요." #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:54 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)::" +"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:`Python 3.8.17` 사용):" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:58 msgid "" "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)::" +"virtualenv` plugin), you can use the following convenience script (with :" +"code:`Python 3.8.17` by default)::" msgstr "" +":code:`pyenv`가 이미 설치되어 있는 경우( :code:`pyenv-virtualenv` 플러그인과 " +"함께) 다음과 같은 편의 스크립트를 사용할 수 있습니다(기본적으로 코드:`Python " +"3.8.17` 사용):" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:62 msgid "" -"3. Install the Flower package in development mode (think :code:`pip " -"install -e`) along with all necessary dependencies::" +"3. Install the Flower package in development mode (think :code:`pip install -" +"e`) along with all necessary dependencies::" msgstr "" +"3. 필요한 모든 dependencies와 함께 개발 모드에서 Flower 패키지를 설치합니다" +"(예:code:`pip install -e`)::" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:69 msgid "Convenience Scripts" -msgstr "" +msgstr "편의 스크립트" #: ../../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 " -"amongst 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 amongst the " +"most important ones:" msgstr "" +"Flower 레포지토리에는 반복적인 개발 작업을 더 쉽고 오류를 줄이기 위한 여러 가" +"지 편의 스크립트가 포함되어 있습니다. 전체 목록은 :code:`/dev` 하위 디렉터리" +"를 참조하세요. 다음 스크립트는 가장 중요한 스크립트 중 하나입니다:" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:77 msgid "Create/Delete Virtual Environment" -msgstr "" +msgstr "가상 환경 생성/삭제" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:85 msgid "Compile ProtoBuf Definitions" -msgstr "" +msgstr "ProtoBuf 정의 컴파일" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:92 msgid "Auto-Format Code" -msgstr "" +msgstr "자동 포맷 코드" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:99 msgid "Run Linters and Tests" -msgstr "" +msgstr "린터 및 테스트 실행" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:106 msgid "Add a pre-commit hook" -msgstr "" +msgstr "사전 커밋 훅 추가" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:108 msgid "" -"Developers may integrate a pre-commit hook into their workflow utilizing " -"the `pre-commit `_ library. The pre-" -"commit hook is configured to execute two primary operations: " -"``./dev/format.sh`` and ``./dev/test.sh`` scripts." +"Developers may integrate a pre-commit hook into their workflow utilizing the " +"`pre-commit `_ library. The pre-commit hook " +"is configured to execute two primary operations: ``./dev/format.sh`` and ``./" +"dev/test.sh`` scripts." msgstr "" +"개발자는 `pre-commit `_ 라이브러리를 사용하" +"여 사전 커밋 훅을 워크플로에 통합할 수 있습니다. 사전 커밋 훅은 두 가지 기본 " +"작업을 실행하도록 구성됩니다:``./dev/format.sh`` 및 ``./dev/test.sh`` 스크립" +"트." #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:110 msgid "There are multiple ways developers can use this:" -msgstr "" +msgstr "개발자가 이것을 사용할 수 있는 여러가지 방법이 있습니다:" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:112 -msgid "Install the pre-commit hook to your local git directory by simply running:" -msgstr "" +msgid "" +"Install the pre-commit hook to your local git directory by simply running:" +msgstr "간단하게 실행하여 로컬 git 디렉터리에 사전 커밋 훅을 설치하세요:" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:118 msgid "" -"Each ``git commit`` will trigger the execution of formatting and " -"linting/test scripts." -msgstr "" +"Each ``git commit`` will trigger the execution of formatting and linting/" +"test scripts." +msgstr "각 ``git 커밋``은 포맷 및 린팅/테스트 스크립트의 실행을 트리거합니다." #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:119 msgid "" -"If in a hurry, bypass the hook using ``--no-verify`` with the ``git " -"commit`` command. ::" +"If in a hurry, bypass the hook using ``--no-verify`` with the ``git commit`` " +"command. ::" msgstr "" +"급한 경우 ``git commit`` 명령과 함께 `--no-verify``를 사용하여 훅을 넘기세요:" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:124 msgid "" "For developers who prefer not to install the hook permanently, it is " -"possible to execute a one-time check prior to committing changes by using" -" the following command:" +"possible to execute a one-time check prior to committing changes by using " +"the following command:" msgstr "" +"훅을 영구적으로 설치하지 않으려는 개발자의 경우 다음 명령을 사용하여 변경 사" +"항을 커밋하기 전에 일회성 검사를 실행할 수 있습니다:" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:130 msgid "" "This executes the formatting and linting checks/tests on all the files " "without modifying the default behavior of ``git commit``." msgstr "" +"이렇게 하면 ``git commit``의 기본 동작을 수정하지 않고 모든 파일에 대해 포맷 " +"및 린팅 검사/테스트를 실행합니다." #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:133 msgid "Run Github Actions (CI) locally" -msgstr "" +msgstr "로컬에서 Github Action(CI) 실행하기" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:135 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:142 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:147 msgid "Build Release" -msgstr "" +msgstr "릴리즈 빌드" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:149 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:154 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:159 msgid "Build Documentation" -msgstr "" +msgstr "문서 빌드" #: ../../source/contributor-tutorial-get-started-as-a-contributor.rst:161 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:167 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 :doc:`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 :doc:`Example: PyTorch - From Centralized To " +"Federated `." +msgstr "" +"이 튜토리얼에서는 non-iid data를 위해 설계된 federated 훈련 전략인 `FedBN " +"`_으로 기존 머신러닝 워크로드의 federated " +"버전을 구축하기 위해 Flower를 사용하는 방법을 보여드립니다. 우리는 PyTorch를 " +"사용하여 CIFAR-10 데이터 세트에서 컨볼루션 신경망(일괄 정규화 레이어 포함)을 " +"훈련하고 있습니다. FedBN을 적용할 때, :doc:`예제: 파이토치 -중앙 집중식에서 " +"연합식으로 ` 와 비교했을 때 " +"몇 가지 사항만 변경 하면 됩니다." #: ../../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 :doc:`Example: PyTorch - From Centralized " -"To Federated `. The only " -"thing to do is modifying the file called :code:`cifar.py`, revised part " -"is shown below:" +"All files are revised based on :doc:`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 "" +"모든 파일은 :doc:`예제: 파이토치 -중앙 집중식에서 연합식으로 `를 기반으로 수정합니다. :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 "" +"Net() 클래스에 정의된 모델 아키텍처는 그에 따라 배치 정규화 레이어가 추가됩니" +"다." #: ../../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 system 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 system consists of one server and two " +"clients." msgstr "" +"지금까지는 파이토치를 사용해 본 적이 있다면 상당히 익숙하게 보일 것입니다. " +"다음 단계로 넘어가서 우리가 구축한 것을 사용하여 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 :doc:`Example: PyTorch - From Centralized To Federated " -"`, the following parts are" -" easy to follow, only :code:`get_parameters` and :code:`set_parameters` " -"function in :code:`client.py` needed to revise. If not, please read the " -":doc:`Example: PyTorch - From Centralized To Federated `. first." -msgstr "" +"`, the following parts are " +"easy to follow, only :code:`get_parameters` and :code:`set_parameters` " +"function in :code:`client.py` needed to revise. If not, please read the :doc:" +"`Example: PyTorch - From Centralized To Federated `. first." +msgstr "" +":doc:`예제: 파이토치 - 중앙 집중식에서 연합식으로 `를 읽었다면, 다음 부분은 쉽게 따라할 수 있으며 " +":code:`client.py`의 :code:`get_parameters`와 :code:`set_parameters` 함수만 " +"수정해야 합니다. 그렇지 않은 경우 :doc:`예제: 파이토치 - 중앙 집중식에서 " +"연합식으로 `를 먼저 " +"읽어보세요." #: ../../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 "" +"마지막으로, :code:`client.py`에서 :code:`get_parameters` 및 :code:" +"`set_parameters`를 변경하여 *client* 로직을 수정할 것입니다. 서버로 보내거나 " +"서버에서 받을 때 모델 파라미터 목록에서 배치 정규화 파라미터를 제외할 수 있습" +"니다." #: ../../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 #: ../../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 Federated 실행" #: ../../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 데이터 세트에서 선형 회귀 " +"모델을 훈련하고 있습니다. 예제는 '파이토치 - Centralized에서 Federated으로 " +"`_ 워크스루와 유사하게 구성하겠습니다. 먼저, `JAX를 사용한 선형 " +"회귀 `_ 튜토리얼`을 기반으로 centralized 학습 접근 방식을 구축합니다. 그런 " +"다음 centralized 트레이닝 코드를 기반으로 federated 방식으로 트레이닝을 " +"실행합니다." #: ../../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:`선형 회귀` 모델을 기반으로 하는 중앙 집중식 훈련 코드에 대한 " +"간략한 설명부터 시작하겠습니다. 더 자세한 설명을 원하시면 공식 `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:`make_regression`을 사용하고 데이터 세트를 학습 및 테스트 세트로 " +"분할하기 위해 :code:`train_test_split`을 사용하므로 :code:`sklearn`을 " +"가져와야 합니다. 연합 학습을 위해 아직 :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()`." +"The model architecture (a very simple :code:`Linear Regression` model) is " +"defined in :code:`load_model()`." msgstr "" +"모델 아키텍처(매우 간단한 :code:`선형 회귀` 모델)는 :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:`loss_fn()`) 훈련(함수 :code:`train()`)을 정의해야 합니다. 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-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`를 설정해 보겠습니다. *server*는 Flower 패키지 :code:`flwr`" +"를 가져와야 합니다. 다음으로, :code:`start_server` 함수를 사용하여 서버를 " +"시작하고 세 차례의 연합 학습을 수행하도록 지시합니다." #: ../../source/example-jax-from-centralized-to-federated.rst:133 #: ../../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 교육을 기반으로 빌드합니다. *클라이언" +"트*는 :code:`flwr`을 가져와야 하며, JAX 모델의 파라미터를 업데이트하기 위해 :" +"code:`jax` 및 :code:`jaxlib`도 가져와야 합니다:" #: ../../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 *클라이언트*를 구현한다는 것은 기본적으로 :code:`flwr.client.Client` " +"또는 :code:`flwr.client.NumPyClient`의 서브클래스를 구현하는 것을 의미합니" +"다. 구현은 :code:`flwr.client.NumPyClient`를 기반으로 하며, 이를 :code:" +"`FlowerClient`라고 부를 것입니다. :code:`NumPyClient`는 필요한 일부 보일러플" +"레이를 피할 수 있기 때문에 NumPy 상호 운용성이 좋은 프레임워크(예: JAX)를 사" +"용하는 경우 :code:`Client`보다 구현하기가 약간 더 쉽습니다. code:" +"`FlowerClient`는 모델 매개변수를 가져오거나 설정하는 메서드 2개, 모델 학습을 " +"위한 메서드 1개, 모델 테스트를 위한 메서드 1개 등 총 4개의 메서드를 구현해야 " +"합니다:" #: ../../source/example-jax-from-centralized-to-federated.rst:161 #: ../../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-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-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-pytorch-from-centralized-to-federated.rst:221 @@ -2454,15 +2806,17 @@ msgstr "" #: ../../source/tutorial-quickstart-pytorch.rst:155 #: ../../source/tutorial-quickstart-scikitlearn.rst:118 msgid ":code:`get_parameters`" -msgstr "" +msgstr ":code:`get_parameters`" #: ../../source/example-jax-from-centralized-to-federated.rst:164 #: ../../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-pytorch-from-centralized-to-federated.rst:225 @@ -2470,7 +2824,7 @@ msgstr "" #: ../../source/tutorial-quickstart-pytorch.rst:161 #: ../../source/tutorial-quickstart-scikitlearn.rst:125 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 @@ -2479,20 +2833,20 @@ 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-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-pytorch-from-centralized-to-federated.rst:230 @@ -2500,108 +2854,140 @@ msgstr "" #: ../../source/tutorial-quickstart-pytorch.rst:164 #: ../../source/tutorial-quickstart-scikitlearn.rst:128 msgid ":code:`evaluate`" -msgstr "" +msgstr ":code:`evaluate`" #: ../../source/example-jax-from-centralized-to-federated.rst:171 #: ../../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에" +"게 알려주는 것입니다. 전달되는 데이터 유형을 더 잘 이해할 수 있도록 유형 " +"type annotation을 포함했습니다." #: ../../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-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-pytorch-from-centralized-to-federated.rst:2 msgid "Example: PyTorch - From Centralized To Federated" -msgstr "" +msgstr "예제: 파이토치 - 중앙 집중식에서 연합식으로" #: ../../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 " +"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 데이터 " +"세트에서 컨볼루션 신경망을 훈련합니다. 먼저, 'PyTorch로 딥 러닝 " "`_ " -"tutorial. Then, we build upon the centralized training code to run the " -"training in a federated fashion." -msgstr "" +"튜토리얼을 기반으로 centralized 학습 접근 방식을 사용하여 이 머신 러닝 " +"작업을 소개합니다. 그런 다음 centralized 훈련 코드를 기반으로 연합 방식 " +"훈련을 실행합니다." #: ../../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 튜토리얼 " +"`_을 " +"참조하세요." #: ../../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." -msgstr "" +"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 "" +"CIFAR-10에 대한 기존 (중앙 집중식) 교육에 필요한 모든 구성 요소가 포함된 " +":code:`cifar.py`라는 새 파일을 생성해 보겠습니다. 먼저, 필요한 모든 " +"패키지(예: :code:`torch` 및 :code:`torchvision`)를 가져와야 합니다. 연합 " +"학습을 위한 패키지를 가져오지 않는 것을 확인 할 수 있습니. 나중에 연합 학습 " +"구성 요소를 추가할 때에도 이러한 모든 가져오기를 그대로 유지할 수 있습니다." #: ../../source/example-pytorch-from-centralized-to-federated.rst:32 msgid "" @@ -2609,163 +2995,230 @@ 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." +"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을 훈련할 수 있습니다." #: ../../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 "" +"지금까지는 파이토치를 사용해 본 적이 있다면 상당히 익숙하게 보일 것입니다. 다" +"음 단계로 넘어가서 구축한 것을 사용하여 하나의 서버와 두 개의 클라이언트로 구" +"성된 간단한 연합 학습 시스템을 만들어 보겠습니다." #: ../../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 "" +"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." +"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 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 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 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:`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 parameters 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 " +"parameters on our PyTorch model:" msgstr "" +"마지막으로, :code:`client.py`에서 *client* 로직을 정의하고 :code:`cifar.py`" +"에서 이전에 정의한 중앙 집중식 학습을 기반으로 구축합니다. *클라이언트*는 " +":code:`flwr`을 가져와야 하며, PyTorch 모델의 파라미터를 업데이트하기 위해 " +":code:`torch`도 가져와야 합니다:" #: ../../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 slightly 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 slightly 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 *클라이언트*를 구현한다는 것은 기본적으로 :code:`flwr.client.Client` " +"또는 :code:`flwr.client.NumPyClient`의 서브클래스를 구현하는 것을 의미합니" +"다. 우리의 구현은 :code:`flwr.client.NumPyClient`를 기반으로 하며, 이를 :" +"code:`CifarClient`라고 부를 것입니다. :code:`NumPyClient`는 파이토치나 텐서플" +"로우/Keras처럼 NumPy 상호운용성이 좋은 프레임워크를 사용하는 경우 필요한 일" +"부 보일러플레이트를 피하기 때문에 :code:`Client`보다 구현하기가 조금 더 쉽습" +"니다. code:`CifarClient`는 모델 파라미터를 가져오거나 설정하는 메서드 2개, 모" +"델 학습을 위한 메서드 1개, 모델 테스트를 위한 메서드 1개 등 네 가지 메서드를 " +"구현해야 합니다:" #: ../../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:226 msgid "get the updated local model weights and return them to the server" -msgstr "" +msgstr "업데이트된 로컬 모델 가중치를 가져와 서버로 반환합니다" #: ../../source/example-pytorch-from-centralized-to-federated.rst:230 msgid "return the local loss and accuracy to the server" -msgstr "" +msgstr "로컬 손실 및 정확도를 서버에 반환합니다" #: ../../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에 알려주는 것입니" +"다. 전달되는 데이터 유형을 더 잘 이해할 수 있도록 type annotations을 포함했습" +"니다." #: ../../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 address 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 " +"address we used in :code:`server.py`:" msgstr "" +"이제 모델과 데이터를 모두 로드하는 함수를 정의하고, :code:`CifarClient`를 생" +"성하고, 이 클라이언트를 시작하는 작업만 남았습니다. 코드:`cifar.py`를 사용하" +"여 데이터와 모델을 로드합니다. :code:`server.py`에서 사용한 것과 동일한 IP 주" +"소를 지정하여 :code:`fl.client.start_client()` 함수로 :code:`CifarClient`를 " +"시작합니다:" #: ../../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!" +"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 "" +"이 예제의 전체 소스 코드: `파이토치: 중앙 Centralized에서 Federated으로 (코" +"드) `_. 물론 이 예제는 두 클라이언트가 완전히 동일한 데" +"이터 세트를 로드하기 때문에 다소 지나치게 단순화되어 있으며, 이는 현실적이지 " +"않습니다. 이제 이 주제를 더 자세히 살펴볼 준비가 되셨습니다. 각 클라이언트에" +"서 서로 다른 CIFAR-10의 하위 집합을 사용해 보는 것은 어떨까요? 클라이언트를 " +"더 추가하는 것은 어떨까요?" #: ../../source/explanation-differential-privacy.rst:2 #: ../../source/explanation-differential-privacy.rst:11 #: ../../source/tutorial-series-what-is-federated-learning.ipynb:303 msgid "Differential Privacy" -msgstr "" +msgstr "차분 프라이버시" #: ../../source/explanation-differential-privacy.rst:3 msgid "" -"The information in datasets like healthcare, financial transactions, user" -" preferences, etc., is valuable and has the potential for scientific " -"breakthroughs and provides important business insights. However, such " -"data is also sensitive and there is a risk of compromising individual " -"privacy." +"The information in datasets like healthcare, financial transactions, user " +"preferences, etc., is valuable and has the potential for scientific " +"breakthroughs and provides important business insights. However, such data " +"is also sensitive and there is a risk of compromising individual privacy." msgstr "" +"의료, 금융 거래, 사용자 선호도 등과 같은 데이터 세트의 정보는 가치 있고 과학" +"적 혁신의 잠재력을 지니고 있으며 중요한 비즈니스 인사이트를 제공합니다. 그러" +"나 이러한 데이터는 또한 민감한 정보이며 개인의 프라이버시를 침해할 위험이 있" +"습니다." #: ../../source/explanation-differential-privacy.rst:6 msgid "" "Traditional methods like anonymization alone would not work because of " -"attacks like Re-identification and Data Linkage. That's where " -"differential privacy comes in. It provides the possibility of analyzing " -"data while ensuring the privacy of individuals." +"attacks like Re-identification and Data Linkage. That's where differential " +"privacy comes in. It provides the possibility of analyzing data while " +"ensuring the privacy of individuals." msgstr "" +"익명화와 같은 기존 방법만으로는 재식별 및 데이터 연결과 같은 공격으로 인해 효" +"과가 없습니다. 그래서 차분 프라이버시가 등장했습니다. 차등 개인정보 보호는 개" +"인의 프라이버시를 보장하면서 데이터를 분석할 수 있는 가능성을 제공합니다." #: ../../source/explanation-differential-privacy.rst:12 msgid "" @@ -2773,226 +3226,309 @@ msgid "" "instance, Alice's data). Differential Privacy (DP) guarantees that any " "analysis (M), like calculating the average income, will produce nearly " "identical results for both datasets (O and O' would be similar). This " -"preserves group patterns while obscuring individual details, ensuring the" -" individual's information remains hidden in the crowd." +"preserves group patterns while obscuring individual details, ensuring the " +"individual's information remains hidden in the crowd." msgstr "" +"하나의 레코드(예: 앨리스의 데이터)를 제외하고는 동일한 두 개의 데이터 세트가 " +"있다고 상상해 보세요. 차분 프라이버(DP)는 평균 소득 계산과 같은 모든 분석(M)" +"이 두 데이터 세트에 대해 거의 동일한 결과를 산출하도록 보장합니다(O와 O' 는 " +"비슷할 것입니다). 이렇게 하면 그룹 패턴은 보존하면서 개별 세부 정보는 가려져 " +"개인의 정보가 군중 속에 숨겨집니다." #: ../../source/explanation-differential-privacy.rst:-1 msgid "DP Intro" -msgstr "" +msgstr "DP 소개" #: ../../source/explanation-differential-privacy.rst:22 msgid "" "One of the most commonly used mechanisms to achieve DP is adding enough " "noise to the output of the analysis to mask the contribution of each " -"individual in the data while preserving the overall accuracy of the " -"analysis." +"individual in the data while preserving the overall accuracy of the analysis." msgstr "" +"DP를 달성하기 위해 가장 일반적으로 사용되는 메커니즘 중 하나는 분석의 전반적" +"인 정확도를 유지하면서 데이터에서 각 개인의 기여도를 가릴 수 있도록 분석 결과" +"에 충분한 노이즈를 추가하는 것입니다." #: ../../source/explanation-differential-privacy.rst:25 msgid "Formal Definition" -msgstr "" +msgstr "공식 정의" #: ../../source/explanation-differential-privacy.rst:26 msgid "" "Differential Privacy (DP) provides statistical guarantees against the " "information an adversary can infer through the output of a randomized " -"algorithm. It provides an unconditional upper bound on the influence of a" -" single individual on the output of the algorithm by adding noise [1]. A " -"randomized mechanism M provides (:math:`\\epsilon`, " -":math:`\\delta`)-differential privacy if for any two neighboring " -"databases, D :sub:`1` and D :sub:`2`, that differ in only a single " -"record, and for all possible outputs S ⊆ Range(A):" -msgstr "" +"algorithm. It provides an unconditional upper bound on the influence of a " +"single individual on the output of the algorithm by adding noise [1]. A " +"randomized mechanism M provides (:math:`\\epsilon`, :math:`\\delta`)-" +"differential privacy if for any two neighboring databases, D :sub:`1` and D :" +"sub:`2`, that differ in only a single record, and for all possible outputs S " +"⊆ Range(A):" +msgstr "" +"차분 프라이버시(DP)는 공격자가 무작위 알고리즘의 출력을 통해 유추할 수 있는 " +"정보에 대해 통계적 보장을 제공합니다. 이는 노이즈를 추가하여 알고리즘의 출력" +"에 대한 한 개인의 영향력에 대한 무조건적인 상한선을 제공합니다[1]. 무작위 메" +"커니즘 M은 하나의 레코드만 다른 두 개의 인접 데이터베이스인 D:sub:`1`과 D:" +"sub:`2`의 경우, 가능한 모든 출력 S ⊆ Range(A)에 대해 (:math:`\\epsilon`, :" +"math:`\\delta`)-차분 프라이버시를 제공합니다:" #: ../../source/explanation-differential-privacy.rst:32 msgid "" "\\small\n" "P[M(D_{1} \\in A)] \\leq e^{\\delta} P[M(D_{2} \\in A)] + \\delta" msgstr "" +"\\small\n" +"P[M(D_{1} \\in A)] \\leq e^{\\delta} P[M(D_{2} \\in A)] + \\delta" #: ../../source/explanation-differential-privacy.rst:38 msgid "" "The :math:`\\epsilon` parameter, also known as the privacy budget, is a " "metric of privacy loss. It also controls the privacy-utility trade-off; " "lower :math:`\\epsilon` values indicate higher levels of privacy but are " -"likely to reduce utility as well. The :math:`\\delta` parameter accounts " -"for a small probability on which the upper bound :math:`\\epsilon` does " -"not hold. The amount of noise needed to achieve differential privacy is " -"proportional to the sensitivity of the output, which measures the maximum" -" change in the output due to the inclusion or removal of a single record." -msgstr "" +"likely to reduce utility as well. The :math:`\\delta` parameter accounts for " +"a small probability on which the upper bound :math:`\\epsilon` does not " +"hold. The amount of noise needed to achieve differential privacy is " +"proportional to the sensitivity of the output, which measures the maximum " +"change in the output due to the inclusion or removal of a single record." +msgstr "" +"프라이버시 예산이라고도 하는 :math:`\\epsilon` 매개변수는 프라이버시 손실을 " +"측정하는 지표입니다. 이 매개변수는 프라이버시와 효용의 균형을 제어하며, :" +"math:`\\epsilon` 값이 낮을수록 프라이버시 수준이 높지만 효용도 감소할 가능성" +"이 높습니다. math:`\\delta` 매개변수는 상한값인 :math:`\\epsilon`이 적용되지 " +"않는 작은 확률을 설명합니다. 차분 프라이버시를 달성하는 데 필요한 노이즈의 양" +"은 출력의 감도에 비례하며, 이는 단일 레코드의 포함 또는 제거로 인한 출력의 최" +"대 변화를 측정합니다." #: ../../source/explanation-differential-privacy.rst:45 msgid "Differential Privacy in Machine Learning" -msgstr "" +msgstr "머신 러닝의 차분 프라이버시" #: ../../source/explanation-differential-privacy.rst:46 msgid "" "DP can be utilized in machine learning to preserve the privacy of the " "training data. Differentially private machine learning algorithms are " -"designed in a way to prevent the algorithm to learn any specific " -"information about any individual data points and subsequently prevent the" -" model from revealing sensitive information. Depending on the stage at " -"which noise is introduced, various methods exist for applying DP to " -"machine learning algorithms. One approach involves adding noise to the " -"training data (either to the features or labels), while another method " -"entails injecting noise into the gradients of the loss function during " -"model training. Additionally, such noise can be incorporated into the " -"model's output." -msgstr "" +"designed in a way to prevent the algorithm to learn any specific information " +"about any individual data points and subsequently prevent the model from " +"revealing sensitive information. Depending on the stage at which noise is " +"introduced, various methods exist for applying DP to machine learning " +"algorithms. One approach involves adding noise to the training data (either " +"to the features or labels), while another method entails injecting noise " +"into the gradients of the loss function during model training. Additionally, " +"such noise can be incorporated into the model's output." +msgstr "" +"머신 러닝에서 DP를 활용하여 학습 데이터의 개인정보를 보호할 수 있습니다. 차" +"분 비공개 머신 러닝 알고리즘은 알고리즘이 개별 데이터 포인트에 대한 특정 정보" +"를 학습하지 못하도록 하여 모델이 민감한 정보를 노출하지 않도록 하는 방식으로 " +"설계되었습니다. 노이즈가 도입되는 단계에 따라 머신 러닝 알고리즘에 DP를 적용" +"하는 다양한 방법이 존재합니다. 한 가지 방법은 학습 데이터(특징 또는 레이블)" +"에 노이즈를 추가하는 것이고, 다른 방법은 모델 학습 중에 손실 함수의 기울기에 " +"노이즈를 주입하는 것입니다. 또한 이러한 노이즈를 모델의 출력에 통합할 수도 있" +"습니다." #: ../../source/explanation-differential-privacy.rst:53 msgid "Differential Privacy in Federated Learning" -msgstr "" +msgstr "연합 학습의 차분 프라이버시" #: ../../source/explanation-differential-privacy.rst:54 msgid "" "Federated learning is a data minimization approach that allows multiple " "parties to collaboratively train a model without sharing their raw data. " "However, federated learning also introduces new privacy challenges. The " -"model updates between parties and the central server can leak information" -" about the local data. These leaks can be exploited by attacks such as " +"model updates between parties and the central server can leak information " +"about the local data. These leaks can be exploited by attacks such as " "membership inference and property inference attacks, or model inversion " "attacks." msgstr "" +"연합 학습은 여러 당사자가 원시 데이터를 공유하지 않고도 공동으로 모델을 " +"학습할 수 있는 데이터 최소화 접근 방식입니다. 그러나 연합 학습은 새로운 " +"개인정보 보호 문제를 야기하기도 합니다. 당사자와 중앙 서버 간의 모델 " +"업데이트는 로컬 데이터에 대한 정보를 유출할 수 있습니다. 이러한 유출은 " +"멤버십 추론 및 속성 추론 공격이나 모델 반전 공격과 같은 공격에 악용될 수 " +"있습니다." #: ../../source/explanation-differential-privacy.rst:58 msgid "" -"DP can play a crucial role in federated learning to provide privacy for " -"the clients' data." -msgstr "" +"DP can play a crucial role in federated learning to provide privacy for the " +"clients' data." +msgstr "DP는 연합 학습에서 클라이언트의 데이터에 대한 개인 정보 보호를 제공하는 데 " +"중요한 역할을 할 수 있습니다." #: ../../source/explanation-differential-privacy.rst:60 msgid "" -"Depending on the granularity of privacy provision or the location of " -"noise addition, different forms of DP exist in federated learning. In " -"this explainer, we focus on two approaches of DP utilization in federated" -" learning based on where the noise is added: at the server (also known as" -" the center) or at the client (also known as the local)." +"Depending on the granularity of privacy provision or the location of noise " +"addition, different forms of DP exist in federated learning. In this " +"explainer, we focus on two approaches of DP utilization in federated " +"learning based on where the noise is added: at the server (also known as the " +"center) or at the client (also known as the local)." msgstr "" +"개인 정보 제공의 세분성 또는 노이즈 추가 위치에 따라 연합 학습에는 다양한 " +"형태의 DP가 존재합니다. 이 설명에서는 노이즈가 추가되는 위치에 따라 서버(" +"중앙이라고도 함) 또는 클라이언트(로컬이라고도 함)에서의 연합 학습에서 DP를 " +"활용하는 두 가지 접근 방식에 중점을 둡니다." #: ../../source/explanation-differential-privacy.rst:63 msgid "" -"**Central Differential Privacy**: DP is applied by the server and the " -"goal is to prevent the aggregated model from leaking information about " -"each client's data." +"**Central Differential Privacy**: DP is applied by the server and the goal " +"is to prevent the aggregated model from leaking information about each " +"client's data." msgstr "" +"**중앙 차분 프라이버시**: DP는 서버에서 적용되며 집계된 모델이 각 클라이언트" +"의 데이터에 대한 정보를 유출하는 것을 방지하는 것이 목표입니다." #: ../../source/explanation-differential-privacy.rst:65 msgid "" "**Local Differential Privacy**: DP is applied on the client side before " -"sending any information to the server and the goal is to prevent the " -"updates that are sent to the server from leaking any information about " -"the client's data." +"sending any information to the server and the goal is to prevent the updates " +"that are sent to the server from leaking any information about the client's " +"data." msgstr "" +"**로컬 차분 개인정보 보호**: DP는 정보를 서버로 보내기 전에 클라이언트 측에" +"서 적용되며, 서버로 전송되는 업데이트가 클라이언트 데이터에 대한 정보를 유출" +"하는 것을 방지하는 것이 목표입니다." #: ../../source/explanation-differential-privacy.rst:-1 #: ../../source/explanation-differential-privacy.rst:68 #: ../../source/how-to-use-differential-privacy.rst:11 msgid "Central Differential Privacy" -msgstr "" +msgstr "중앙 차분 프라이버시" #: ../../source/explanation-differential-privacy.rst:69 msgid "" -"In this approach, which is also known as user-level DP, the central " -"server is responsible for adding noise to the globally aggregated " -"parameters. It should be noted that trust in the server is required." +"In this approach, which is also known as user-level DP, the central server " +"is responsible for adding noise to the globally aggregated parameters. It " +"should be noted that trust in the server is required." msgstr "" +"사용자 수준 DP라고도 하는 이 접근 방식에서는 중앙 서버가 전역적으로 집계된 매" +"개변수에 노이즈를 추가하는 역할을 담당합니다. 서버에 대한 신뢰가 필요하다는 " +"점에 유의해야 합니다." #: ../../source/explanation-differential-privacy.rst:76 msgid "" -"While there are various ways to implement central DP in federated " -"learning, we concentrate on the algorithms proposed by [2] and [3]. The " -"overall approach is to clip the model updates sent by the clients and add" -" some amount of noise to the aggregated model. In each iteration, a " -"random set of clients is chosen with a specific probability for training." -" Each client performs local training on its own data. The update of each " -"client is then clipped by some value `S` (sensitivity `S`). This would " -"limit the impact of any individual client which is crucial for privacy " -"and often beneficial for robustness. A common approach to achieve this is" -" by restricting the `L2` norm of the clients' model updates, ensuring " -"that larger updates are scaled down to fit within the norm `S`." -msgstr "" +"While there are various ways to implement central DP in federated learning, " +"we concentrate on the algorithms proposed by [2] and [3]. The overall " +"approach is to clip the model updates sent by the clients and add some " +"amount of noise to the aggregated model. In each iteration, a random set of " +"clients is chosen with a specific probability for training. Each client " +"performs local training on its own data. The update of each client is then " +"clipped by some value `S` (sensitivity `S`). This would limit the impact of " +"any individual client which is crucial for privacy and often beneficial for " +"robustness. A common approach to achieve this is by restricting the `L2` " +"norm of the clients' model updates, ensuring that larger updates are scaled " +"down to fit within the norm `S`." +msgstr "" +"연합 학습에서 중앙 DP를 구현하는 방법은 여러 가지가 있지만, 여기서는 [2]와 " +"[3]에서 제안한 알고리즘에 집중합니다. 전반적인 접근 방식은 클라이언트가 " +"전송한 모델 업데이트를 잘라내고 집계된 모델에 약간의 노이즈를 추가하는 " +"것입니다. 각 반복에서 특정 확률로 훈련할 무작위 클라이언트 세트가 " +"선택됩니다. 각 클라이언트는 자체 데이터에 대해 로컬 학습을 수행합니다. 그런 " +"다음 각 클라이언트의 업데이트는 특정 값 `S`(민감도 `S`)에 의해 잘립니다. " +"이렇게 하면 개별 클라이언트의 영향을 제한할 수 있어 개인정보 보호에 중요하고 " +"견고성에 도움이 되는 경우가 많습니다. 이를 달성하기 위한 일반적인 접근 " +"방식은 클라이언트 모델 업데이트의 `L2` 규범을 제한하여 더 큰 업데이트가 규범 " +"`S`에 맞도록 축소되도록 하는 것입니다." #: ../../source/explanation-differential-privacy.rst:-1 msgid "clipping" -msgstr "" +msgstr "클리핑" #: ../../source/explanation-differential-privacy.rst:89 msgid "" -"Afterwards, the Gaussian mechanism is used to add noise in order to " -"distort the sum of all clients' updates. The amount of noise is scaled to" -" the sensitivity value to obtain a privacy guarantee. The Gaussian " -"mechanism is used with a noise sampled from `N (0, σ²)` where `σ = ( " -"noise_scale * S ) / (number of sampled clients)`." +"Afterwards, the Gaussian mechanism is used to add noise in order to distort " +"the sum of all clients' updates. The amount of noise is scaled to the " +"sensitivity value to obtain a privacy guarantee. The Gaussian mechanism is " +"used with a noise sampled from `N (0, σ²)` where `σ = ( noise_scale * S ) / " +"(number of sampled clients)`." msgstr "" +"그 후 가우시안 메커니즘을 사용하여 모든 클라이언트의 업데이트 합계를 왜곡하" +"기 위해 노이즈를 추가합니다. 노이즈의 양은 감도 값에 따라 조정되어 프라이버" +"시 보장을 얻습니다. 가우시안 메커니즘은 `N (0, σ²)`에서 샘플링된 노이즈와 함" +"께 사용됩니다. 여기서 `σ = (noise_scale * S) / (샘플링된 클라이언트 수)`입니" +"다." #: ../../source/explanation-differential-privacy.rst:94 msgid "Clipping" -msgstr "" +msgstr "클리핑" #: ../../source/explanation-differential-privacy.rst:96 msgid "" -"There are two forms of clipping commonly used in Central DP: Fixed " -"Clipping and Adaptive Clipping." -msgstr "" +"There are two forms of clipping commonly used in Central DP: Fixed Clipping " +"and Adaptive Clipping." +msgstr "중앙 DP에서 일반적으로 사용되는 클리핑에는 고정 클리핑과 조정 클리핑의 두 " +"가지 형태가 있습니다." #: ../../source/explanation-differential-privacy.rst:98 msgid "" -"**Fixed Clipping** : A predefined fix threshold is set for the magnitude " -"of clients' updates. Any update exceeding this threshold is clipped back " -"to the threshold value." +"**Fixed Clipping** : A predefined fix threshold is set for the magnitude of " +"clients' updates. Any update exceeding this threshold is clipped back to the " +"threshold value." msgstr "" +"**고정 클리핑** : 클라이언트의 업데이트 크기에 대해 미리 정의된 고정 임계값" +"이 설정됩니다. 이 임계값을 초과하는 모든 업데이트는 임계값으로 다시 클리핑됩" +"니다." #: ../../source/explanation-differential-privacy.rst:100 msgid "" -"**Adaptive Clipping** : The clipping threshold dynamically adjusts based " -"on the observed update distribution [4]. It means that the clipping value" -" is tuned during the rounds with respect to the quantile of the update " -"norm distribution." +"**Adaptive Clipping** : The clipping threshold dynamically adjusts based on " +"the observed update distribution [4]. It means that the clipping value is " +"tuned during the rounds with respect to the quantile of the update norm " +"distribution." msgstr "" +"**조정 클리핑** : 클리핑 임계값은 관찰된 업데이트 분포에 따라 동적으로 " +"조정됩니다[4]. 즉, 클리핑 값은 업데이트 표준 분포의 사분위수에 따라 라운드가 " +"진행되는 동안 조정됩니다." #: ../../source/explanation-differential-privacy.rst:102 msgid "" -"The choice between fixed and adaptive clipping depends on various factors" -" such as privacy requirements, data distribution, model complexity, and " +"The choice between fixed and adaptive clipping depends on various factors " +"such as privacy requirements, data distribution, model complexity, and " "others." msgstr "" +"고정 클리핑과 조정 클리핑 중 선택은 개인정보 보호 요구 사항, 데이터 배포, 모" +"델 복잡성 등 다양한 요인에 따라 달라집니다." #: ../../source/explanation-differential-privacy.rst:-1 #: ../../source/explanation-differential-privacy.rst:105 #: ../../source/how-to-use-differential-privacy.rst:96 msgid "Local Differential Privacy" -msgstr "" +msgstr "로컬 차분 프라이버시" #: ../../source/explanation-differential-privacy.rst:107 msgid "" "In this approach, each client is responsible for performing DP. Local DP " -"avoids the need for a fully trusted aggregator, but it should be noted " -"that local DP leads to a decrease in accuracy but better privacy in " -"comparison to central DP." +"avoids the need for a fully trusted aggregator, but it should be noted that " +"local DP leads to a decrease in accuracy but better privacy in comparison to " +"central DP." msgstr "" +"이 접근 방식에서는 각 클라이언트가 DP를 수행할 책임이 있습니다. 로컬 DP는 완" +"전히 신뢰할 수 있는 애그리게이터가 필요하지 않지만, 로컬 DP는 중앙 DP에 비해 " +"정확도는 떨어져도 개인 정보 보호는 더 우수하다는 점에 유의해야 합니다." #: ../../source/explanation-differential-privacy.rst:116 msgid "In this explainer, we focus on two forms of achieving Local DP:" -msgstr "" +msgstr "이 설명에서는 로컬 DP를 달성하는 두 가지 형태에 중점을 둡니다:" #: ../../source/explanation-differential-privacy.rst:118 msgid "" "Each client adds noise to the local updates before sending them to the " -"server. To achieve (:math:`\\epsilon`, :math:`\\delta`)-DP, considering " -"the sensitivity of the local model to be ∆, Gaussian noise is applied " -"with a noise scale of σ where:" +"server. To achieve (:math:`\\epsilon`, :math:`\\delta`)-DP, considering the " +"sensitivity of the local model to be ∆, Gaussian noise is applied with a " +"noise scale of σ where:" msgstr "" +"각 클라이언트는 로컬 업데이트를 서버로 보내기 전에 로컬 업데이트에 노이즈를 " +"추가합니다. 로컬 모델의 감도를 ∆로 간주하여 가우시안 노이즈가 σ의 노이즈 스케" +"일로 적용되어 (:math:`\\epsilon`, :math:`\\delta`)-DP를 달성하기 위해, 여기" +"서 σ는 노이즈 스케일입니다:" #: ../../source/explanation-differential-privacy.rst:120 msgid "" "\\small\n" -"\\frac{∆ \\times \\sqrt{2 \\times " -"\\log\\left(\\frac{1.25}{\\delta}\\right)}}{\\epsilon}\n" +"\\frac{∆ \\times \\sqrt{2 \\times \\log\\left(\\frac{1.25}{\\delta}\\right)}}" +"{\\epsilon}\n" "\n" msgstr "" +"\\small\n" +"\\frac{∆ \\times \\sqrt{2 \\times \\log\\left(\\frac{1.25}{\\delta}\\right)}}" +"{\\epsilon}\n" +"\n" #: ../../source/explanation-differential-privacy.rst:125 msgid "" @@ -3000,56 +3536,63 @@ msgid "" "training (DP-SGD). More specifically, in this approach, gradients are " "clipped and an amount of calibrated noise is injected into the gradients." msgstr "" +"각 클라이언트는 로컬 트레이닝(DP-SGD) 중에 모델의 gradient에 노이즈를 추가합" +"니다. 보다 구체적으로, 이 접근 방식에서는 gradient이 클리핑되고 보정된 노이즈" +"가 gradient에 주입됩니다." #: ../../source/explanation-differential-privacy.rst:128 msgid "" "Please note that these two approaches are providing privacy at different " "levels." msgstr "" +"이 두 가지 접근 방식은 서로 다른 수준의 개인정보 보호 기능을 제공한다는 점에 " +"유의하세요." #: ../../source/explanation-differential-privacy.rst:131 msgid "**References:**" -msgstr "" +msgstr "**참고:**" #: ../../source/explanation-differential-privacy.rst:133 msgid "[1] Dwork et al. The Algorithmic Foundations of Differential Privacy." -msgstr "" +msgstr "[1] Dwork 외. 차분 프라이버시의 알고리즘적 기초." #: ../../source/explanation-differential-privacy.rst:135 msgid "" -"[2] McMahan et al. Learning Differentially Private Recurrent Language " -"Models." -msgstr "" +"[2] McMahan et al. Learning Differentially Private Recurrent Language Models." +msgstr "[2] McMahan 외. 차분적 개인 반복 언어 모델 학습." #: ../../source/explanation-differential-privacy.rst:137 msgid "" -"[3] Geyer et al. Differentially Private Federated Learning: A Client " -"Level Perspective." -msgstr "" +"[3] Geyer et al. Differentially Private Federated Learning: A Client Level " +"Perspective." +msgstr "[3] Geyer 외. 차분적 개인 연합 학습: 고객 수준의 관점." #: ../../source/explanation-differential-privacy.rst:139 -msgid "[4] Galen et al. Differentially Private Learning with Adaptive Clipping." -msgstr "" +msgid "" +"[4] Galen et al. Differentially Private Learning with Adaptive Clipping." +msgstr "[4] Galen 외. 조정형 클리핑을 통한 차분적 개인 학습." #: ../../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." +"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 "" @@ -3058,177 +3601,206 @@ 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:`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`입니다. 코드:`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`. 코드:`fraction_evaluate`가 :code:`0.1`로 설정되어 있고 :code:" +"`fraction_evaluate`가 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`: federated 평가 단계를 시작하기 전에 서버에 연" +"결해야 하는 최소 클라이언트 수를 정의하는 :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`은 임의의 " +"평가 결과를 dictionary로 반환할 수 있습니다:" #: ../../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 "" +"연합 평가와 중앙 집중식 평가를 모두 사용하는 전체 코드 예제는 *고급 " +"텐서플로우 예제*(다른 프레임워크에서 구현된 워크로드에도 동일한 접근 방식을 " +"적용할 수 있음)를 참조하세요: 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 "[목차](#목차)" #: ../../source/fed/0000-20200102-fed-template.md:15 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:15 msgid "[Summary](#summary)" -msgstr "" +msgstr "[요약](#요약)" #: ../../source/fed/0000-20200102-fed-template.md:16 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:16 msgid "[Motivation](#motivation)" -msgstr "" +msgstr "[동기](#동기)" #: ../../source/fed/0000-20200102-fed-template.md:17 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:17 msgid "[Goals](#goals)" -msgstr "" +msgstr "[목표](#목표)" #: ../../source/fed/0000-20200102-fed-template.md:18 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:18 msgid "[Non-Goals](#non-goals)" -msgstr "" +msgstr "[비목표](#비목표)" #: ../../source/fed/0000-20200102-fed-template.md:19 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:19 msgid "[Proposal](#proposal)" -msgstr "" +msgstr "[제안](#제안)" #: ../../source/fed/0000-20200102-fed-template.md:20 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:23 msgid "[Drawbacks](#drawbacks)" -msgstr "" +msgstr "[단점](#단점)" #: ../../source/fed/0000-20200102-fed-template.md:21 #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:24 msgid "[Alternatives Considered](#alternatives-considered)" -msgstr "" +msgstr "[고려되는 대안](#고려되는 대안)" #: ../../source/fed/0000-20200102-fed-template.md:22 msgid "[Appendix](#appendix)" -msgstr "" +msgstr "[부록](#부록)" #: ../../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 - 문장 1: 문제 요약\\]" #: ../../source/fed/0000-20200102-fed-template.md:28 msgid "\\[TODO - sentence 2: summary of the solution\\]" -msgstr "" +msgstr "\\[TODO - 문장 2: 솔루션 요약\\]" #: ../../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 @@ -3238,993 +3810,1228 @@ 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 msgid "\\[Alternative 1\\]" -msgstr "" +msgstr "\\[대안 1\\]" #: ../../source/fed/0000-20200102-fed-template.md:56 msgid "\\[Alternative 2\\]" -msgstr "" +msgstr "\\[대안 2\\]" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:10 msgid "Flower Enhancement Doc" -msgstr "" +msgstr "Flower Enhancement Doc" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:20 msgid "[Enhancement Doc Template](#enhancement-doc-template)" -msgstr "" +msgstr "[Enhancement Doc 템플릿](#enhancement-doc-템플릿)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:21 msgid "[Metadata](#metadata)" -msgstr "" +msgstr "[Metadata](#metadata)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:22 msgid "[Workflow](#workflow)" -msgstr "" +msgstr "[워크플로우](#워크플로우)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:25 msgid "[GitHub Issues](#github-issues)" -msgstr "" +msgstr "[GitHub Issues](#github-issues)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:26 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 Enhancement는 다음과 같은 표준화된 개발 프로세스입니다" #: ../../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 "운행 중 작업 추적을 위한 깃허브 이슈를 예약합니다" #: ../../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 "따라서 Enhancement 문서에는 다음과 같은 측면이 결합되어 있습니다" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:41 msgid "a feature, and effort-tracking document" -msgstr "" +msgstr "기능 및 effort-tracking 문서" #: ../../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 이슈 또는 pull request를 넘어서" +"는 abstraction이 필요합니다." #: ../../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 "" +"개선 사항은 정의된 템플릿과 참조용으로 Enhancement Doc.를 검토하고 저장하는 " +"워크플로우를 따르는 Markdown 파일에 캡처됩니다." #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:69 msgid "Enhancement Doc Template" -msgstr "" +msgstr "Enhancement Doc 템플릿" #: ../../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 ([아래 설명](#metadata) YAML preamble 형식)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:74 msgid "Title (same as in metadata)" -msgstr "" +msgstr "Title (metadata와 같게)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:75 msgid "Table of Contents (if needed)" -msgstr "" +msgstr "Table of Contents (필요시)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:81 msgid "Notes/Constraints/Caveats (optional)" -msgstr "" +msgstr "Notes/Constraints/Caveats (선택 사항)" #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:82 msgid "Design Details (optional)" -msgstr "" +msgstr "Design Details (선택 사항)" #: ../../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 #: ../../source/ref-api/flwr.common.Metadata.rst:2 msgid "Metadata" -msgstr "" +msgstr "Metadata" #: ../../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 "" +"**피드 번호** (필수) 마지막 Flower Enhancement 문서의 `피드 번호` + 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 "" +"**상태** (필수) 제안의 현재 상태입니다. 가능한 상태는 [워크플로](#워크플로)" +"를 참조하세요." #: ../../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 "" +"**마지막 업데이트** (선택 사항) 제안서가 마지막으로 크게 변경된 날짜입니다." #: ../../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 "" +"개선 사항을 구성하는 아이디어는 이미 커뮤니티에서 논의되었거나 제안된 적이 있" +"어야 합니다. 따라서 개선 사항을 주도하는 사(보통 작성자)이 필요합니다. 이 사" +"람은 또한 제안을 검토할 의향이 있는 Flower 커미터를 찾아야 합니다." #: ../../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`은 Flower 개선 문서 번호이고 `enhancements`에 해당합니다. 모든 " +"개선 사항은 pull request의 일부로 `잠정` 상태에서 시작됩니다. 토론은 pull " +"request 검토의 일부로 이루어집니다." #: ../../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 "" +"개선 사항이 검토 및 승인되면 상태가 '구현 가능'으로 변경됩니다. 그런 다음 실" +"제 구현은 별도의 pull requests를 통해 이루어집니다. 이러한 pull requests는 설" +"명의 일부로 해당 개선 사항을 언급해야 합니다. 구현이 완료되면 제안 상태는 '구" +"현됨'으로 변경됩니다." #: ../../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." +"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." +"`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에서 이미 제공하는 프로세스(이슈 및 Pull Requests)에 추가 프로세스를 추" +"가하면 더 복잡해지고 잠재적인 처음인 기여자에게는 장벽이 될 수 있습니다." #: ../../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 이슈를 사용하면 가능합니다. 예를 들어 태그" +"를 사용하여 다른 이슈와 구별하고 필터링할 수 있습니다. 주요 이슈는 개선 사항" +"에 대해 토론하고 검토하는 것입니다: GitHub 이슈에는 댓글 스레드가 하나만 있습" +"니다. 개선 사항에는 일반적으로 문서의 여러 부분에 대해 동시에 여러 개의 토론 " +"스레드가 있습니다. GitHub 이슈를 사용할 때 이러한 여러 토론을 관리하면 혼란스" +"러울 수 있습니다." #: ../../source/fed/0001-20220311-flower-enhancement-doc.md:141 msgid "Google Docs" -msgstr "" +msgstr "Google 문서 도구" #: ../../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 "" +"Google 문서는 여러 스레드의 토론을 허용합니다. 하지만 Google 문서는 프로젝트 " +"외부에서 호스팅되므로 커뮤니티에서 검색할 수 있도록 관리해야 합니다. 모든 제" +"안에 대한 링크 목록을 관리하고 커뮤니티에 제공해야 합니다. 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`-사용자 지정 방식을 사용하여 개별 클라이언트로부터 오" +"는 사용자 지정 평가 결과를 집계할 수 있습니다. 클라이언트는 dictionary를 반환" +"하여 사용자 지정 지표를 서버에 반환할 수 있습니다:" #: ../../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 "" +"그런 다음 서버는 사용자 지정 전략을 사용하여 이러한 dictionaries에서 제공하" +"는 메트릭을 집계할 수 있습니다:" #: ../../source/how-to-authenticate-supernodes.rst:2 msgid "Authenticate SuperNodes" -msgstr "" +msgstr "SuperNodes 인증하기" #: ../../source/how-to-authenticate-supernodes.rst:4 msgid "" -"Flower has built-in support for authenticated SuperNodes that you can use" -" to verify the identities of each SuperNode connecting to a SuperLink. " -"Flower node authentication works similar to how GitHub SSH authentication" -" works:" +"Flower has built-in support for authenticated SuperNodes that you can use to " +"verify the identities of each SuperNode connecting to a SuperLink. Flower " +"node authentication works similar to how GitHub SSH authentication works:" msgstr "" +"Flower는 SuperLink에 연결하는 각 SuperNodes의 신원을 확인하는 데 사용할 수 있" +"는 인증된 SuperNodes에 대한 기본 지원을 제공합니다. Flower 노드 인증은 " +"GitHub SSH 인증 방식과 유사하게 작동합니다:" #: ../../source/how-to-authenticate-supernodes.rst:7 msgid "SuperLink (server) stores a list of known (client) node public keys" -msgstr "" +msgstr "SuperLink(서버)는 알려진 (클라이언트) 노드 공개키 목록을 저장합니다" #: ../../source/how-to-authenticate-supernodes.rst:8 msgid "" -"Using ECDH, both SuperNode and SuperLink independently derive a shared " -"secret" +"Using ECDH, both SuperNode and SuperLink independently derive a shared secret" msgstr "" +"SuperNode와 SuperLink는 ECDH를 사용하여 독립적으로 공유된 비밀을 도출합니다" #: ../../source/how-to-authenticate-supernodes.rst:9 msgid "" "Shared secret is used to compute the HMAC value of the message sent from " "SuperNode to SuperLink as a token" msgstr "" +"비밀 공유는 SuperNode에서 SuperLink로 토큰으로 전송된 메시지의 HMAC 값을 계산" +"하는 데 사용됩니다" #: ../../source/how-to-authenticate-supernodes.rst:10 msgid "SuperLink verifies the token" -msgstr "" +msgstr "SuperLink가 토큰을 확인합니다" #: ../../source/how-to-authenticate-supernodes.rst:12 msgid "" -"We recommend you to check out the complete `code example " -"`_ demonstrating federated learning with Flower in an " -"authenticated setting." +"We recommend you to check out the complete `code example `_ demonstrating " +"federated learning with Flower in an authenticated setting." msgstr "" +"인증된 환경에서 Flower로 연합 학습을 시연하는 전체 '코드 예제 `_를 확인하는 것이 " +"좋습니다." #: ../../source/how-to-authenticate-supernodes.rst:15 msgid "" -"This guide covers a preview feature that might change in future versions " -"of Flower." +"This guide covers a preview feature that might change in future versions of " +"Flower." msgstr "" +"이 가이드에서는 향후 버전의 Flower에서 변경될 수 있는 미리보기 기능에 대해 설" +"명합니다." #: ../../source/how-to-authenticate-supernodes.rst:18 msgid "" -"For increased security, node authentication can only be used when " -"encrypted connections (SSL/TLS) are enabled." +"For increased security, node authentication can only be used when encrypted " +"connections (SSL/TLS) are enabled." msgstr "" +"보안을 강화하기 위해 노드 인증은 암호화된 연결(SSL/TLS)을 사용하도록 설정한 " +"경우에만 사용할 수 있습니다." #: ../../source/how-to-authenticate-supernodes.rst:21 msgid "Enable node authentication in :code:`SuperLink`" -msgstr "" +msgstr ":code:`SuperLink`에서 노드 인증 활성화" #: ../../source/how-to-authenticate-supernodes.rst:23 msgid "" "To enable node authentication, first you need to configure SSL/TLS " -"connections to secure the SuperLink<>SuperNode communication. You can " -"find the complete guide `here `_. After configuring secure connections, you" -" can enable client authentication in a long-running Flower " -":code:`SuperLink`. Use the following terminal command to start a Flower " -":code:`SuperNode` that has both secure connections and node " -"authentication enabled:" -msgstr "" +"connections to secure the SuperLink<>SuperNode communication. You can find " +"the complete guide `here `_. After configuring secure connections, you can enable " +"client authentication in a long-running Flower :code:`SuperLink`. Use the " +"following terminal command to start a Flower :code:`SuperNode` that has both " +"secure connections and node authentication enabled:" +msgstr "" +"노드 인증을 활성화하려면 먼저 SuperLink<>SuperNode 통신을 보호하기 위해 SSL/" +"TLS 연결을 구성해야 합니다. 전체 가이드는 `여기 `_에서 확인할 수 있습니다. 보안 " +"연결을 구성한 후, 장기 실행하는 Flower :code:`SuperLink`에서 클라이언트 인증" +"을 활성화할 수 있습니다. 다음 터미널 명령을 사용하여 보안 연결과 노드 인증이 " +"모두 활성화된 Flower :code:`SuperNode`를 시작하세요:" #: ../../source/how-to-authenticate-supernodes.rst:38 msgid "Let's break down the authentication flags:" -msgstr "" +msgstr "인증 플래그를 세분화해 보겠습니다:" #: ../../source/how-to-authenticate-supernodes.rst:40 msgid "" -"The first flag :code:`--auth-list-public-keys` expects a path to a CSV " -"file storing all known node public keys. You need to store all known node" -" public keys that are allowed to participate in a federation in one CSV " -"file (:code:`.csv`)." +"The first flag :code:`--auth-list-public-keys` expects a path to a CSV file " +"storing all known node public keys. You need to store all known node public " +"keys that are allowed to participate in a federation in one CSV file (:code:" +"`.csv`)." msgstr "" +"첫 번째 플래그 :code:`--auth-list-public-keys`는 알려진 모든 노드 공개키를 저" +"장하는 CSV 파일의 경로를 기대합니다. federation에 참여하도록 허용된 모든 알려" +"진 노드 공개 키를 하나의 CSV 파일(:code:`.csv`)에 저장해야 합니다." #: ../../source/how-to-authenticate-supernodes.rst:42 msgid "" "A valid CSV file storing known node public keys should list the keys in " "OpenSSH format, separated by commas and without any comments. For an " -"example, refer to our code sample, which contains a CSV file with two " -"known node public keys." +"example, refer to our code sample, which contains a CSV file with two known " +"node public keys." msgstr "" +"알려진 노드 공개키를 저장하는 유효한 CSV 파일은 쉼표로 구분하고 주석 없이 " +"OpenSSH 형식으로 키를 나열해야 합니다. 예를 들어, 두 개의 알려진 노드 공개키" +"가 포함된 CSV 파일이 포함된 코드 샘플을 참조하세요." #: ../../source/how-to-authenticate-supernodes.rst:44 msgid "" -"The second and third flags :code:`--auth-superlink-private-key` and :code" -":`--auth-superlink-public-key` expect paths to the server's private and " -"public keys. For development purposes, you can generate a private and " -"public key pair using :code:`ssh-keygen -t ecdsa -b 384`." +"The second and third flags :code:`--auth-superlink-private-key` and :code:`--" +"auth-superlink-public-key` expect paths to the server's private and public " +"keys. For development purposes, you can generate a private and public key " +"pair using :code:`ssh-keygen -t ecdsa -b 384`." msgstr "" +"두 번째 및 세 번째 플래그 :code:`--auth-superlink-private-key` 및 :code:`--" +"auth-superlink-public-key`는 서버의 개인 및 공개 키의 경로를 예상합니다. 개" +"발 목적으로 :code:`ssh-keygen -t ecdsa -b 384`를 사용하여 개인 및 공개 키 쌍" +"을 생성할 수 있습니다." #: ../../source/how-to-authenticate-supernodes.rst:47 msgid "" "In Flower 1.9, there is no support for dynamically removing, editing, or " -"adding known node public keys to the SuperLink. To change the set of " -"known nodes, you need to shut the server down, edit the CSV file, and " -"start the server again. Support for dynamically changing the set of known" -" nodes is on the roadmap to be released in Flower 1.10 (ETA: June)." +"adding known node public keys to the SuperLink. To change the set of known " +"nodes, you need to shut the server down, edit the CSV file, and start the " +"server again. Support for dynamically changing the set of known nodes is on " +"the roadmap to be released in Flower 1.10 (ETA: June)." msgstr "" +"Flower 1.9에서는 알려진 노드 공개키를 SuperLink에 동적으로 제거, 편집 또는 추" +"가하는 기능이 지원되지 않습니다. 알려진 노드 집합을 변경하려면 서버를 종료하" +"고 CSV 파일을 편집한 다음 서버를 다시 시작해야 합니다. 알려진 노드 집합을 동" +"적으로 변경하는 기능은 Flower 1.10(출시 예정일: 6월)에서 로드맵에 포함되어 있" +"습니다." #: ../../source/how-to-authenticate-supernodes.rst:53 msgid "Enable node authentication in :code:`SuperNode`" -msgstr "" +msgstr ":code:`SuperNode`에서 노드 인증을 활성화합니다" #: ../../source/how-to-authenticate-supernodes.rst:55 msgid "" "Similar to the long-running Flower server (:code:`SuperLink`), you can " -"easily enable node authentication in the long-running Flower client " -"(:code:`SuperNode`). Use the following terminal command to start an " -"authenticated :code:`SuperNode`:" +"easily enable node authentication in the long-running Flower client (:code:" +"`SuperNode`). Use the following terminal command to start an authenticated :" +"code:`SuperNode`:" msgstr "" +"장기 실행 중인 Flower 서버(:code:`SuperLink`)와 마찬가지로, 장기 실행 중인 " +"Flower 클라이언트(:code:`SuperNode`)에서도 노드 인증을 쉽게 활성화할 수 있습" +"니다. 다음 터미널 명령을 사용하여 인증된 :code:`SuperNode`를 시작하세요:" #: ../../source/how-to-authenticate-supernodes.rst:66 msgid "" -"The :code:`--auth-supernode-private-key` flag expects a path to the " -"node's private key file and the :code:`--auth-supernode-public-key` flag " -"expects a path to the node's public key file. For development purposes, " -"you can generate a private and public key pair using :code:`ssh-keygen -t" -" ecdsa -b 384`." +"The :code:`--auth-supernode-private-key` flag expects a path to the node's " +"private key file and the :code:`--auth-supernode-public-key` flag expects a " +"path to the node's public key file. For development purposes, you can " +"generate a private and public key pair using :code:`ssh-keygen -t ecdsa -b " +"384`." msgstr "" +":code:`--auth-supernode-private-key` 플래그는 노드의 개인 키 파일 경로를, :" +"code:`--auth-supernode-public-key` 플래그는 노드의 공개 키 파일 경로를 예상합" +"니다. 개발 목적으로 :code:`ssh-keygen -t ecdsa -b 384`를 사용하여 개인 및 공" +"개 키 쌍을 생성할 수 있습니다." #: ../../source/how-to-authenticate-supernodes.rst:70 msgid "Security notice" -msgstr "" +msgstr "보안 공지" #: ../../source/how-to-authenticate-supernodes.rst:72 msgid "" -"The system's security relies on the credentials of the SuperLink and each" -" SuperNode. Therefore, it is imperative to safeguard and safely store the" -" credentials to avoid security risks such as Public Key Infrastructure " -"(PKI) impersonation attacks. The node authentication mechanism also " -"involves human interaction, so please ensure that all of the " -"communication is done in a secure manner, using trusted communication " -"methods." +"The system's security relies on the credentials of the SuperLink and each " +"SuperNode. Therefore, it is imperative to safeguard and safely store the " +"credentials to avoid security risks such as Public Key Infrastructure (PKI) " +"impersonation attacks. The node authentication mechanism also involves human " +"interaction, so please ensure that all of the communication is done in a " +"secure manner, using trusted communication methods." msgstr "" +"시스템의 보안은 SuperLink와 각SuperNode의 자격 증명에 의존합니다. 따라서 공개" +"키 기반구조(PKI) 사칭 공격과 같은 보안 위험을 피하기 위해 자격 증명을 보호하" +"고 안전하게 보관하는 것이 필수적입니다. 노드 인증 메커니즘에는 사람의 상호 작" +"용도 포함되므로 모든 통신이 신뢰할 수 있는 통신 방법을 사용하여 안전한 방식으" +"로 이루어지도록 하세요." #: ../../source/how-to-authenticate-supernodes.rst:77 #: ../../source/how-to-enable-ssl-connections.rst:68 #: ../../source/how-to-use-built-in-mods.rst:85 #: ../../source/tutorial-series-what-is-federated-learning.ipynb:287 msgid "Conclusion" -msgstr "" +msgstr "결론" #: ../../source/how-to-authenticate-supernodes.rst:79 msgid "" -"You should now have learned how to start a long-running Flower server " -"(:code:`SuperLink`) and client (:code:`SuperNode`) with node " -"authentication enabled. You should also know the significance of the " -"private key and store it safely to minimize security risks." +"You should now have learned how to start a long-running Flower server (:code:" +"`SuperLink`) and client (:code:`SuperNode`) with node authentication " +"enabled. You should also know the significance of the private key and store " +"it safely to minimize security risks." msgstr "" +"이제 노드 인증이 활성화된 상태에서 장기간 실행되는 Flower 서버(:code:" +"`SuperLink`)와 클라이언트(:code:`SuperNode`)를 시작하는 방법을 배웠을 것입니" +"다. 또한 보안 위험을 최소화하기 위해 개인키의 중요성을 알고 안전하게 보관해" +"야 합니다." #: ../../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는 이러한 구성 dictionaries(또는 줄여서 *config dict*)를 ProtoBuf 표현" +"으로 직렬화하고, gRPC를 사용하여 클라이언트로 전송한 다음 다시 Python " +"dictionaries로 역직렬화합니다." #: ../../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 문자열로 변환한 다음 구성 dictionary" +"을 사용하여 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``으로 구성 dictionary을 받습니다:" #: ../../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`을 호출하면 연속된 라운드에서 config dict를 변경/" +"변경할 수 있습니다. 예를 들어 이후 라운드에서 로컬 에포크 수를 늘리기 위해 하" +"이퍼파라미터 일정을 구현하려면 다음과 같이 할 수 있습니다:" #: ../../source/how-to-configure-clients.rst:82 msgid "The :code:`FedAvg` strategy will call this function *every round*." -msgstr "" +msgstr ":code:`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 "" +"경우에 따라 다른 구성 값을 다른 클라이언트에 보내야 하는 경우도 있습니다." #: ../../source/how-to-configure-clients.rst:89 msgid "" -"This can be achieved by customizing an existing strategy or by " -":doc:`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 :doc:" +"`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 "" +"이는 기존 전략을 사용자 지정하거나 :doc:`implementing a custom strategy from " +"scratch `를 통해 수행할 수 있습니다. 다음은 사용" +"자 지정 ``\"hello\"'를 추가하여 :code:`FedAvg`를 사용자 지정하는 무의미한 예" +"입니다: \"world\"`` 구성 키/값 쌍을 *단일 클라이언트*의 config 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 로거는 federated 학습 워크로드에서 발생하는 모든 핵심 이벤트를 추적합" +"니다. 기본적으로 표준 메시지 형식에 따라 정보를 표시합니다:" #: ../../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 로그는 Federated 학습 워크로드를 실행하는 터미널에 출력됩니" +"다. 이는 gRPC 기반 페더레이션(즉,:code:`fl.simulation.start_simulation`를 실" +"행하는 경우)과 :code:`VirtualClientEngine`을 사용하는 경우(즉, :코드:`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 wish 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 " +"wish to backup or analyze the logs somewhere else." +msgstr "" +"또한 :code:`fl.common.logger.configure` 함수를 사용하면 네이티브 Python :" +"code:`logging.handler.HTTPHandler`를 통해 로그를 푸시할 수 있는 호스트를 지정" +"할 수 있습니다(:code:`POST`를 통해). 이는 모든 엔티티(예: 서버 및 클라이언트)" +"에서 로그를 수집하는 것이 번거로울 수 있는 :code:`gRPC` 기반 Federated 학습 " +"워크로드에서 특히 유용한 기능입니다. 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 " -"(:code:`SuperLink`) can be started and how a Flower client " -"(:code:`SuperNode`) can establish a secure connections to it." +"This guide describes how to a SSL-enabled secure Flower server (:code:" +"`SuperLink`) can be started and how a Flower client (:code:`SuperNode`) can " +"establish a secure connections to it." msgstr "" +"이 가이드에서는 SSL을 지원하는 보안 Flower 서버(:코드:`SuperLink`)를 시작하" +"는 방법과 Flower 클라이언트(:코드:`SuperNode`)가 이 서버에 보안 연결을 설정하" +"는 방법을 설명합니다." #: ../../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 :code:`README.md` file which explains how " -"to start it. Although it is already SSL-enabled, it might be less " -"descriptive on how it does so. Stick to this guide for a deeper " -"introduction to the topic." +"The code example comes with a :code:`README.md` file which explains how to " +"start it. Although it is already SSL-enabled, it might be less descriptive " +"on how it does so. Stick to this guide for a deeper introduction to the " +"topic." msgstr "" +"코드 예제에는 시작 방법을 설명하는 :code:`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` with the following command sequence:" +"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` with the following command sequence:" msgstr "" +"SSL 사용 연결을 사용하려면 서버와 클라이언트에 인증서를 전달해야 합니다. 이 " +"가이드에서는 자체 서명된 인증서를 생성하겠습니다. 이 과정은 상당히 복잡할 수 " +"있으므로 다음 명령 시퀀스를 사용하여 :code:`examples/advanced-tensorflow/" +"certificates/generate.sh`에서 스크립트를 실행하도록 요청하겠습니다:" #: ../../source/how-to-enable-ssl-connections.rst:29 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:31 msgid "" -"The approach for generating SSL certificates in the context of this " -"example can serve as an inspiration and starting point, but it should not" -" be used as a reference for production environments. Please refer to " -"other sources regarding the issue of correctly generating certificates " -"for production environments. For non-critical prototyping or research " -"projects, it might be sufficient to use the self-signed certificates " -"generated using the scripts mentioned in this guide." +"The approach for generating SSL certificates in the context of this example " +"can serve as an inspiration and starting point, but it should not be used as " +"a reference for production environments. Please refer to other sources " +"regarding the issue of correctly generating certificates for production " +"environments. For non-critical prototyping or research projects, it might be " +"sufficient to use the self-signed certificates generated using the scripts " +"mentioned in this guide." msgstr "" +"이 예의 맥락에서 SSL 인증서를 생성하는 접근 방식은 영감과 출발점이 될 수 있지" +"만 프로덕션 환경에 대한 참조로 사용해서는 안 됩니다. 프로덕션 환경용 인증서" +"를 올바르게 생성하는 문제에 대해서는 다른 출처를 참조하세요. 중요하지 않은 프" +"로토타이핑 또는 연구 프로젝트의 경우, 이 가이드에 언급된 스크립트를 사용하여 " +"생성한 자체 서명 인증서를 사용하는 것으로 충분할 수 있습니다." #: ../../source/how-to-enable-ssl-connections.rst:39 msgid "Server (SuperLink)" -msgstr "" +msgstr "서버(SuperLink)" #: ../../source/how-to-enable-ssl-connections.rst:41 msgid "" -"Use the following terminal command to start a sever (SuperLink) that uses" -" the previously generated certificates:" +"Use the following terminal command to start a sever (SuperLink) that uses " +"the previously generated certificates:" msgstr "" +"다음 터미널 명령을 사용하여 이전에 생성한 인증서를 사용하는 서버(SuperLink)" +"를 시작합니다:" #: ../../source/how-to-enable-ssl-connections.rst:50 msgid "" "When providing certificates, the server expects a tuple of three " -"certificates paths: CA certificate, server certificate and server private" -" key." +"certificates paths: CA certificate, server certificate and server private " +"key." msgstr "" +"인증서를 제공할 때 서버는 세 가지 인증서 경로의 튜플을 기대합니다: CA 인증" +"서, 서버 인증서 및 서버 개인 키입니다." #: ../../source/how-to-enable-ssl-connections.rst:54 msgid "Client (SuperNode)" -msgstr "" +msgstr "클라이언트(SuperNode)" #: ../../source/how-to-enable-ssl-connections.rst:56 msgid "" -"Use the following terminal command to start a client (SuperNode) that " -"uses the previously generated certificates:" +"Use the following terminal command to start a client (SuperNode) that uses " +"the previously generated certificates:" msgstr "" +"다음 터미널 명령을 사용하여 이전에 생성한 인증서를 사용하는 클라이언트" +"(SuperNode)를 시작합니다:" #: ../../source/how-to-enable-ssl-connections.rst:64 msgid "" -"When setting :code:`root_certificates`, the client expects a file path to" -" PEM-encoded root certificates." +"When setting :code:`root_certificates`, the client expects a file path to " +"PEM-encoded root certificates." msgstr "" +"코드:`root_certificates`를 설정하면 클라이언트는 PEM 인코딩된 루트 인증서의 " +"파일 경로를 예상합니다." #: ../../source/how-to-enable-ssl-connections.rst:70 msgid "" -"You should now have learned how to generate self-signed certificates " -"using the given script, start an 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 an SSL-enabled server and have a client establish a " +"secure connection to it." msgstr "" +"이제 주어진 스크립트를 사용하여 자체 서명 인증서를 생성하고, SSL 사용 서버를 " +"시작하고, 클라이언트가 보안 연결을 설정하는 방법을 배웠을 것입니다." #: ../../source/how-to-enable-ssl-connections.rst:75 msgid "Additional resources" -msgstr "" +msgstr "추가 리소스" #: ../../source/how-to-enable-ssl-connections.rst:77 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:79 msgid "`Let's Encrypt `_" -msgstr "" +msgstr "'암호화하세요 `_'" #: ../../source/how-to-enable-ssl-connections.rst:80 msgid "`certbot `_" -msgstr "" +msgstr "`인증봇 `_" #: ../../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 ":code:`Strategy` 추상화" #: ../../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 ":code:`initialize_parameters` 메서드" #: ../../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:`initial_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 msgid "The :code:`configure_fit` method" -msgstr "" +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`의 시그니처를 보면 이를 명확히 알 수 있습니다:" #: ../../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 @@ -4232,379 +5039,475 @@ 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 " -"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 list " +"returned from :code:`configure_fit`." msgstr "" +"보다 정교한 구현은 :code:`configure_fit`을 사용하여 사용자 지정 클라이언트 선" +"택 로직을 구현할 수 있습니다. 클라이언트는 :code:`configure_fit`에서 반환된 " +"목록에 해당 :code:`ClientProxy`가 포함된 경우에만 라운드에 참여합니다." #: ../../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 "" +"이 반환 값의 구조는 사용자에게 많은 유연성을 제공합니다. instructions은 " +"클라이언트별로 정의되므로 각 클라이언트에 서로 다른 명령어를 전송할 수 " +"있습니다. 이를 통해 예를 들어 클라이언트마다 다른 모델을 학습시키거나 " +"클라이언트마다 다른 하이퍼파라미터를 사용하는 사용자 지정 전략을 사용할 수 " +"있습니다(: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` 개체와 집계된 메트릭의 " +"dictionary를 반환합니다. :code:`Parameters` 반환 값은 :code:`aggregate_fit`" +"이 제공된 결과가 집계에 충분하지 않다고 판단할 수 있으므로(예: 실패 수가 너" +"무 많음) 선택 사항입니다." #: ../../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 "" -":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 " -"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 list " +"returned from :code:`configure_evaluate`." msgstr "" +"보다 정교한 구현은 :code:`configure_evaluate`를 사용하여 사용자 지정 클라이언" +"트 선택 로직을 구현할 수 있습니다. 클라이언트는 :code:`configure_evaluate`에" +"서 반환된 목록에 해당 :code:`ClientProxy`가 포함된 경우에만 라운드에 참여합니" +"다." #: ../../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 ":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`에서 선택되어 평가를 요" +"청한 클라이언트가 반환한 결과를 집계하는 역할을 담당합니다." #: ../../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`(손실)와 집계된 메트릭의 " +"dictionary를 반환합니다. 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 "" ":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`" +"를 사용하면 서버 측과 클라이언트 측(federated) 평가를 모두 수행할 수 있는 전" +"략을 사용할 수 있습니다." #: ../../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:15 #: ../../source/how-to-upgrade-to-flower-next.rst:46 msgid "Using pip" -msgstr "" +msgstr "pip 사용" #: ../../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:21 msgid "" "For simulations that use the Virtual Client Engine, ``flwr`` should be " "installed with the ``simulation`` extra::" msgstr "" +"가상 클라이언트 엔진을 사용하는 시뮬레이션의 경우 ``flwr``을 " +"``simulation``extra와 함께 설치해야 합니다:" #: ../../source/how-to-install-flower.rst:27 msgid "Using conda (or mamba)" -msgstr "" +msgstr "conda(또는 mamba) 사용" #: ../../source/how-to-install-flower.rst:29 msgid "Flower can also be installed from the ``conda-forge`` channel." -msgstr "" +msgstr "Flower은 'conda-forge' 채널에서도 설치할 수 있습니다." #: ../../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 "" +"If you have not added ``conda-forge`` to your channels, you will first need " +"to run the following::" +msgstr "채널에 'conda-forge'를 추가하지 않은 경우 먼저 다음을 실행해야 합니다:" #: ../../source/how-to-install-flower.rst:36 msgid "" -"Once the ``conda-forge`` channel has been enabled, ``flwr`` can be " -"installed with ``conda``::" +"Once the ``conda-forge`` channel has been enabled, ``flwr`` can be installed " +"with ``conda``::" msgstr "" +"conda-forge`` 채널이 활성화되면 ``flwr``을 ``conda``로 설치할 수 있습니다::" #: ../../source/how-to-install-flower.rst:40 msgid "or with ``mamba``::" -msgstr "" +msgstr "또는 ``mamba``::" #: ../../source/how-to-install-flower.rst:46 msgid "Verify installation" -msgstr "" +msgstr "설치 확인" #: ../../source/how-to-install-flower.rst:48 msgid "" "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::" +"installed. If everything worked, it should print the version of Flower to " +"the command line::" msgstr "" +"다음 명령을 사용하여 Flower가 성공적으로 설치되었는지 확인할 수 있습니다. 모" +"든 것이 정상적으로 작동하면 명령줄에 Flower의 버전이 출력됩니다:" #: ../../source/how-to-install-flower.rst:55 msgid "Advanced installation options" -msgstr "" +msgstr "고급 설치 옵션" #: ../../source/how-to-install-flower.rst:58 msgid "Install via Docker" -msgstr "" +msgstr "Docker를 통해 설치" #: ../../source/how-to-install-flower.rst:60 msgid ":doc:`How to run Flower using Docker `" msgstr "" +":doc:`Docker를 사용하여 Flower를 실행하는 방법 `" #: ../../source/how-to-install-flower.rst:63 msgid "Install pre-release" -msgstr "" +msgstr "사전 릴리즈 설치" #: ../../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::" +"New (possibly unstable) versions of Flower are sometimes available as pre-" +"release versions (alpha, beta, release candidate) before the stable release " +"happens::" msgstr "" +"새(불안정할 수 있는) 버전의 Flower는 안정 버전이 출시되기 전에 사전 릴리즈 버" +"전(알파, 베타, 릴리즈 후보)으로 제공되는 경우가 있습니다:" #: ../../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`` extra와 함께 설치해야 합니다:" #: ../../source/how-to-install-flower.rst:74 msgid "Install nightly release" -msgstr "" +msgstr "야간 릴리즈 설치" #: ../../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: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`` extr와 함께 설치해야 합니다::" #: ../../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 "이전 세대 Intel 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:" +"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 "" +"터미널 편집기가 열리면 이전과 마찬가지로 다음 구성을 적용할 수 있습니다." #: ../../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 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 "" +"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:" +"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 대시보드입니다. 메트릭(왼쪽 패널의 가장 아래 옵션)으로 이동할 수 있습니" +"다." #: ../../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 "" @@ -4612,377 +5515,495 @@ 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):" +"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`를 지정하면 시뮬" +"레이션이 시작되지 않습니다(GPU가 2개이지만 :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 "" +"A: 기간이 제대로 설정되지 않았을 수 있습니다. 설정은 오른쪽 상단에 있습니다" +"(기본값은 '지난 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 서버가 감지되지 않았습니다. Ray 대시보드의 메트릭 탭으로 이동" +"한 후 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 "" +"A: Grafana가 실행되고 있지 않을 수 있습니다. 실행 중인 서비스를 확인하세요" #: ../../source/how-to-monitor-simulation.rst:226 msgid "" "Q: I see \"This site can't be reached\" when going to " "``_." msgstr "" +"Q: ``_로 이동할 때 \"이 사이트에 연결할 수 없습니다." +"\"라는 메시지가 표시됩니다." #: ../../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 "A: 시뮬레이션이 이미 완료되었거나 아직 Prometheus를 시작해야 합니다." #: ../../source/how-to-monitor-simulation.rst:232 msgid "Resources" -msgstr "" +msgstr "리소스" #: ../../source/how-to-monitor-simulation.rst:234 msgid "" "Ray Dashboard: ``_" msgstr "" +"Ray 대시보드: ``_" #: ../../source/how-to-monitor-simulation.rst:236 msgid "Ray Metrics: ``_" -msgstr "" +msgstr "Ray 메트릭: ``_" #: ../../source/how-to-run-flower-using-docker.rst:2 msgid "Run Flower using Docker" -msgstr "" +msgstr "Docker를 사용하여 Flower 실행" #: ../../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 " -"`__. Supported architectures include " -"``amd64`` and ``arm64v8``." +"The simplest way to get started with Flower is by using the pre-made Docker " +"images, which you can find on `Docker Hub `__. Supported architectures include ``amd64`` and ``arm64v8``." msgstr "" +"Flower를 시작하는 가장 간단한 방법은 `Docker Hub `__에서 찾을 수 있는 미리 만들어진 Docker 이미지를 사용하는 것입니다. 지" +"원되는 아키텍처는 ``amd64`` 및 ``arm64v8``입니다." #: ../../source/how-to-run-flower-using-docker.rst:8 msgid "Before you start, make sure that the Docker daemon is running:" -msgstr "" +msgstr "시작하기 전에 Docker daemon이 실행 중인지 확인하세요:" #: ../../source/how-to-run-flower-using-docker.rst:15 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 `_." +"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 "" +"전이 표시되지 않고 대신 명령을 찾을 수 없다는 오류가 표시되는 경우 먼저 " +"Docker를 설치해야 합니다. `여기 `_에서 " +"설치 지침을 찾을 수 있습니다." #: ../../source/how-to-run-flower-using-docker.rst:21 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." +"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 "" +"Linux에서 Docker 명령을 실행하려면 ``sudo`` 권한이 필요합니다. ``sudo`` 를 " +"사용하지 않으려면 공식 Docker 웹사이트의 `Post-installation steps " +"`_를 따르세요." #: ../../source/how-to-run-flower-using-docker.rst:27 msgid "" -"To ensure optimal performance and compatibility, the SuperLink, SuperNode" -" and ServerApp image must have the same version when running together. " -"This guarantees seamless integration and avoids potential conflicts or " -"issues that may arise from using different versions." +"To ensure optimal performance and compatibility, the SuperLink, SuperNode " +"and ServerApp image must have the same version when running together. This " +"guarantees seamless integration and avoids potential conflicts or issues " +"that may arise from using different versions." msgstr "" +"최적의 성능과 호환성을 보장하려면 SuperLink, SuperNode 및 ServerApp 이미지를 " +"함께 실행할 때 버전이 동일해야 합니다. 이렇게 하면 원활한 통합을 보장하고 서" +"로 다른 버전을 사용할 때 발생할 수 있는 잠재적인 충돌이나 문제를 방지할 수 있" +"습니다." #: ../../source/how-to-run-flower-using-docker.rst:32 msgid "Flower SuperLink" -msgstr "" +msgstr "Flower SuperLink" #: ../../source/how-to-run-flower-using-docker.rst:35 msgid "Quickstart" -msgstr "" +msgstr "빠른 시작" #: ../../source/how-to-run-flower-using-docker.rst:37 msgid "If you're looking to try out Flower, you can use the following command:" -msgstr "" +msgstr "Flower를 사용해보고 싶다면 다음 명령을 사용하면 됩니다:" #: ../../source/how-to-run-flower-using-docker.rst:43 msgid "" -"The command pulls the Docker image with the tag ``1.8.0`` from Docker " -"Hub. The tag specifies the Flower version. In this case, Flower 1.8.0. " -"The ``--rm`` flag tells Docker to remove the container after it exits." +"The command pulls the Docker image with the tag ``1.8.0`` from Docker Hub. " +"The tag specifies the Flower version. In this case, Flower 1.8.0. The ``--" +"rm`` flag tells Docker to remove the container after it exits." msgstr "" +"이 명령은 Docker Hub에서 ``1.8.0`` 태그가 있는 Docker 이미지를 가져옵니다. " +"이 태그는 Flower 버전을 지정합니다. 이 경우, Flower 1.8.0입니다. '`--rm`` 플" +"래그는 컨테이너가 종료된 후 컨테이너를 제거하도록 Docker에 지시합니다." #: ../../source/how-to-run-flower-using-docker.rst:49 msgid "" "By default, the Flower SuperLink 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." +"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 "" +"기본적으로 Flower SuperLink는 상태를 in-memory에 유지합니다. Docker 플래그 " +"`--rm``을 사용하는 경우 컨테이너 시작 사이에 상태가 유지되지 않습니다. 아래에" +"서 호스트 시스템의 파일에 상태를 저장하는 방법을 보여드리겠습니다." #: ../../source/how-to-run-flower-using-docker.rst:53 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 SuperLink. Here, we are passing the" -" flag ``--insecure``." +"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 SuperLink. Here, we are passing the flag ``--insecure``." msgstr "" +"``-p :`` 플래그는 호스트의 포트 ``9091``/``9092``를 컨테이너" +"의 ``9091``/``9092``에 매핑하여 ``http://localhost:9091``의 드라이버 API와 " +"``http://localhost:9092``의 Fleet API에 액세스할 수 있도록 Docker에 지시합니" +"다. 마지막으로, 태그 뒤에 오는 모든 플래그는 Flower SuperLink에 전달됩니다. " +"여기서는 ``--insecure``플래그를 전달합니다." #: ../../source/how-to-run-flower-using-docker.rst:60 #: ../../source/how-to-run-flower-using-docker.rst:259 #: ../../source/how-to-run-flower-using-docker.rst:376 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." +"HTTPS) and should only be used for testing purposes. We strongly recommend " +"enabling `SSL `__ when deploying to a " +"production environment." msgstr "" +"``--insecure`` 플래그는 안전하지 않은 통신(HTTPS가 아닌 HTTP 사용)을 활성화하" +"며 테스트 목적으로만 사용해야 합니다. 프로덕션 환경에 배포할 때는 `SSL " +"`__을 활성화할 것을 강력히 권장합니" +"다." #: ../../source/how-to-run-flower-using-docker.rst:65 msgid "" "You can use ``--help`` to view all available flags that the SuperLink " "supports:" msgstr "" +"'`--help``을 사용하면 SuperLink가 지원하는 모든 플래그를 볼 수 있습니다:" #: ../../source/how-to-run-flower-using-docker.rst:72 msgid "Mounting a volume to store the state on the host system" -msgstr "" +msgstr "호스트 시스템에 상태를 저장할 볼륨 마운트하기" #: ../../source/how-to-run-flower-using-docker.rst:74 msgid "" -"If you want to persist the state of the SuperLink on your host system, " -"all you need to do is specify a directory where you want to save the file" -" on your host system and a name for the database file. By default, the " -"SuperLink container runs with a non-root user called ``app`` with the " -"user ID ``49999``. It is recommended to create new directory and change " -"the user ID of the directory to ``49999`` to ensure the mounted directory" -" has the proper permissions. If you later want to delete the directory, " -"you can change the user ID back to the current user ID by running ``sudo " -"chown -R $USER:$(id -gn) state``." -msgstr "" +"If you want to persist the state of the SuperLink on your host system, all " +"you need to do is specify a directory where you want to save the file on " +"your host system and a name for the database file. By default, the SuperLink " +"container runs with a non-root user called ``app`` with the user ID " +"``49999``. It is recommended to create new directory and change the user ID " +"of the directory to ``49999`` to ensure the mounted directory has the proper " +"permissions. If you later want to delete the directory, you can change the " +"user ID back to the current user ID by running ``sudo chown -R $USER:$(id -" +"gn) state``." +msgstr "" +"호스트 시스템에서 SuperLink의 상태를 유지하려면 호스트 시스템에서 파일을 저장" +"할 디렉터리와 데이터베이스 파일의 이름을 지정하기만 하면 됩니다. 기본적으로 " +"SuperLink 컨테이너는 사용자 ID가 ``49999``인 ``app``이라는 루트가 아닌 사용자" +"로 실행됩니다. 마운트된 디렉터리에 적절한 권한이 있는지 확인하려면 새 디렉터" +"리를 생성하고 디렉터리의 사용자 ID를 ``49999``로 변경하는 것이 좋습니다. 나중" +"에 디렉터리를 삭제하려면 ``sudo chown -R $USER:$(id -gn) state``를 실행하여 " +"사용자 ID를 현재 사용자 ID로 다시 변경할 수 있습니다." #: ../../source/how-to-run-flower-using-docker.rst:82 msgid "" -"In the example below, we create a new directory, change the user ID and " -"tell Docker via the flag ``--volume`` to mount the local ``state`` " -"directory into the ``/app/state`` directory of the container. " -"Furthermore, we use the flag ``--database`` to specify the name of the " -"database file." +"In the example below, we create a new directory, change the user ID and tell " +"Docker via the flag ``--volume`` to mount the local ``state`` directory into " +"the ``/app/state`` directory of the container. Furthermore, we use the flag " +"``--database`` to specify the name of the database file." msgstr "" +"아래 예에서는 새 디렉터리를 생성하고, 사용자 ID를 변경하고, 플래그 ``--" +"volume``을 통해 Docker에게 로컬 ``state`` 디렉터리를 컨테이너의 ``/app/" +"state`` 디렉터리에 마운트하도록 지시합니다. 또한 ``--database`` 플래그를 사용" +"하여 데이터베이스 파일의 이름을 지정합니다." #: ../../source/how-to-run-flower-using-docker.rst:95 msgid "" "As soon as the SuperLink starts, the file ``state.db`` is created in the " "``state`` directory on your host system. If the file already exists, the " -"SuperLink tries to restore the state from the file. To start the " -"SuperLink with an empty database, simply remove the ``state.db`` file." +"SuperLink tries to restore the state from the file. To start the SuperLink " +"with an empty database, simply remove the ``state.db`` file." msgstr "" +"SuperLink가 시작되자마자 호스트 시스템의 ``state`` 디렉터리에 ``state.db`` 파" +"일이 생성됩니다. 파일이 이미 존재하는 경우 SuperLink는 파일에서 상태를 복원하" +"려고 시도합니다. 빈 데이터베이스로 SuperLink를 시작하려면 ``state.db`` 파일" +"을 제거하면 됩니다." #: ../../source/how-to-run-flower-using-docker.rst:100 #: ../../source/how-to-run-flower-using-docker.rst:281 #: ../../source/how-to-run-flower-using-docker.rst:397 msgid "Enabling SSL for secure connections" -msgstr "" +msgstr "보안 연결을 위한 SSL 사용 설정" #: ../../source/how-to-run-flower-using-docker.rst:102 msgid "" -"To enable SSL, you will need a PEM-encoded root certificate, a PEM-" -"encoded private key and a PEM-encoded certificate chain." +"To enable SSL, you will need a PEM-encoded root certificate, a PEM-encoded " +"private key and a PEM-encoded certificate chain." msgstr "" +"SSL을 사용하려면 PEM으로 인코딩된 루트 인증서, PEM으로 인코딩된 개인 키 및 " +"PEM으로 인코딩된 인증서 체인이 필요합니다." #: ../../source/how-to-run-flower-using-docker.rst:106 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." +"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 "" +"테스트 목적으로 자체 서명된 인증서를 생성할 수 있습니다. 'SSL 연결 사용 " +"`__ 페이지에 프로세스를 안내하는 섹션이 있습니다." #: ../../source/how-to-run-flower-using-docker.rst:110 msgid "" -"Assuming all files we need are in the local ``certificates`` directory, " -"we can use the flag ``--volume`` to mount the local directory into the " -"``/app/certificates/`` directory of the container. This allows the " -"SuperLink to access the files within the container. The ``ro`` stands for" -" ``read-only``. Docker volumes default to ``read-write``; that option " -"tells Docker to make the volume ``read-only`` instead. Finally, we pass " -"the names of the certificates and key file to the SuperLink with the " -"``--ssl-ca-certfile``, ``--ssl-certfile`` and ``--ssl-keyfile`` flag." -msgstr "" +"Assuming all files we need are in the local ``certificates`` directory, we " +"can use the flag ``--volume`` to mount the local directory into the ``/app/" +"certificates/`` directory of the container. This allows the SuperLink to " +"access the files within the container. The ``ro`` stands for ``read-only``. " +"Docker volumes default to ``read-write``; that option tells Docker to make " +"the volume ``read-only`` instead. Finally, we pass the names of the " +"certificates and key file to the SuperLink with the ``--ssl-ca-certfile``, " +"``--ssl-certfile`` and ``--ssl-keyfile`` flag." +msgstr "" +"필요한 모든 파일이 로컬``certificates`` 디렉터리에 있다고 가정하면, ``--" +"volume``플래그를 사용하여 로컬 디렉터리를 컨테이너의 ``/app/certificates/`` " +"디렉터리에 마운트할 수 있습니다. 이렇게 하면 SuperLink 가 컨테이너 내의 파일" +"에 액세스할 수 있습니다. ``ro``는 ``read-only``을 의미합니다. Docker 볼륨은 " +"기본적으로 ``read-write``로 설정되어 있는데, 이 옵션을 사용하면 볼륨을 " +"``read-only``으로 만들 수 있습니다. 마지막으로 인증서 및 키 파일의 이름을 " +"``--ssl-ca-certfile``, ``--ssl-certfile`` 및 ``--ssl-keyfile`` 플래그와 함께 " +"SuperLink에 전달합니다." #: ../../source/how-to-run-flower-using-docker.rst:128 msgid "" -"Because Flower containers, by default, run with a non-root user ``app``, " -"the mounted files and directories must have the proper permissions for " -"the user ID ``49999``. For example, to change the user ID of all files in" -" the ``certificates/`` directory, you can run ``sudo chown -R 49999:49999" -" certificates/*``." +"Because Flower containers, by default, run with a non-root user ``app``, the " +"mounted files and directories must have the proper permissions for the user " +"ID ``49999``. For example, to change the user ID of all files in the " +"``certificates/`` directory, you can run ``sudo chown -R 49999:49999 " +"certificates/*``." msgstr "" +"기본적으로 Flower 컨테이너는 루트가 아닌 사용자 ``app``로 실행되므로 마운트" +"된 파일과 디렉터리에 사용자 ID ``49999``에 대한 적절한 권한이 있어야 합니다. " +"예를 들어, ``certificates/`` 디렉터리에 있는 모든 파일의 사용자 ID를 변경하려" +"면 ``sudo chown -R 49999:49999 certificates/*``를 실행하면 됩니다." #: ../../source/how-to-run-flower-using-docker.rst:134 msgid "Flower SuperNode" -msgstr "" +msgstr "Flower SuperNode" #: ../../source/how-to-run-flower-using-docker.rst:136 msgid "" -"The SuperNode Docker image comes with a pre-installed version of Flower " -"and serves as a base for building your own SuperNode image." +"The SuperNode Docker image comes with a pre-installed version of Flower and " +"serves as a base for building your own SuperNode image." msgstr "" +"SuperNode Docker 이미지는 Flower의 사전 설치된 버전과 함께 제공되며, 자체 " +"SuperNode 이미지를 구축하기 위한 기반 역할을 합니다." #: ../../source/how-to-run-flower-using-docker.rst:141 msgid "" "The SuperNode Docker image currently works only with the 1.9.0-nightly " -"release. A stable version will be available when Flower 1.9.0 (stable) " -"gets released (ETA: May). A SuperNode nightly image must be paired with " -"the corresponding SuperLink and ServerApp nightly images released on the " -"same day. To ensure the versions are in sync, using the concrete tag, " -"e.g., ``1.9.0.dev20240501`` instead of ``nightly`` is recommended." -msgstr "" +"release. A stable version will be available when Flower 1.9.0 (stable) gets " +"released (ETA: May). A SuperNode nightly image must be paired with the " +"corresponding SuperLink and ServerApp nightly images released on the same " +"day. To ensure the versions are in sync, using the concrete tag, e.g., " +"``1.9.0.dev20240501`` instead of ``nightly`` is recommended." +msgstr "" +"SuperNode Docker 이미지는 현재 1.9.0 야간 릴리스에서만 작동합니다. 안정 버전" +"은 Flower 1.9.0(안정)이 출시되면 사용할 수 있습니다(예상 출시일: 5월). " +"SuperNode 야간 이미지는 같은 날 릴리스된 해당 SuperLink 및 서버앱 야간 이미지" +"와 페어링되어야 합니다. 버전이 동기화되도록 하려면 ``nightly`` 대신 ``1.9.0." +"dev20240501``과 같은 구체적인 태그를 사용하는 것이 좋습니다." #: ../../source/how-to-run-flower-using-docker.rst:147 msgid "" -"We will use the ``quickstart-pytorch`` example, which you can find in the" -" Flower repository, to illustrate how you can dockerize your ClientApp." +"We will use the ``quickstart-pytorch`` example, which you can find in the " +"Flower repository, to illustrate how you can dockerize your ClientApp." msgstr "" +"Flower 레포지토리에서 찾을 수 있는 ``quickstart-pytorch`` 예제를 사용하여 " +"ClientApp을 도커라이즈하는 방법을 설명하겠습니다." #: ../../source/how-to-run-flower-using-docker.rst:155 msgid "" "Before we can start, we need to meet a few prerequisites in our local " -"development environment. You can skip the first part if you want to run " -"your ClientApp instead of the ``quickstart-pytorch`` example." +"development environment. You can skip the first part if you want to run your " +"ClientApp instead of the ``quickstart-pytorch`` example." msgstr "" +"시작하기 전에 로컬 개발 환경에서 몇 가지 전제 조건을 충족해야 합니다. " +"'quickstart-pytorch' 예제 대신 ClientApp을 실행하려는 경우 첫 번째 부분을 건" +"너뛸 수 있습니다." #: ../../source/how-to-run-flower-using-docker.rst:159 msgid "Clone the Flower repository." -msgstr "" +msgstr "플라워 레포지토리를 클론합니다." #: ../../source/how-to-run-flower-using-docker.rst:173 msgid "Creating a SuperNode Dockerfile" -msgstr "" +msgstr "SuperNode Dockerfile 만들기" #: ../../source/how-to-run-flower-using-docker.rst:175 #: ../../source/how-to-run-flower-using-docker.rst:311 msgid "Let's assume the following project layout:" -msgstr "" +msgstr "다음과 같은 프로젝트 레이아웃을 가정해 보겠습니다:" #: ../../source/how-to-run-flower-using-docker.rst:184 msgid "" -"First, we need to create a ``requirements.txt`` file in the directory " -"where the ``ClientApp`` code is located. In the file, we list all the " -"dependencies that the ClientApp requires." +"First, we need to create a ``requirements.txt`` file in the directory where " +"the ``ClientApp`` code is located. In the file, we list all the dependencies " +"that the ClientApp requires." msgstr "" +"먼저 ``ClientApp`` 코드가 있는 디렉토리에 ``requirements.txt`` 파일을 " +"만들어야 합니다. 이 파일에는 클라이언트 앱에 필요한 모든 의존성을 나열합니다." #: ../../source/how-to-run-flower-using-docker.rst:196 msgid "" -"Note that `flwr `__ is already installed " -"in the ``flwr/supernode`` base image, so you only need to include other " -"package dependencies in your ``requirements.txt``, such as ``torch``, " +"Note that `flwr `__ is already installed in " +"the ``flwr/supernode`` base image, so you only need to include other package " +"dependencies in your ``requirements.txt``, such as ``torch``, " "``tensorflow``, etc." msgstr "" +"`flwr `__ 는 이미 ``flwr/supernode`` 기본 이" +"미지에 설치되어 있으므로, ``torch``, ``tensorflow`` 등과 같은 다른 패키지 " +"dependencies만 ``requirements.txt``에 포함시키면 됩니다." #: ../../source/how-to-run-flower-using-docker.rst:200 msgid "" -"Next, we create a Dockerfile. If you use the ``quickstart-pytorch`` " -"example, create a new file called ``Dockerfile.supernode`` in ``examples" -"/quickstart-pytorch``." +"Next, we create a Dockerfile. If you use the ``quickstart-pytorch`` example, " +"create a new file called ``Dockerfile.supernode`` in ``examples/quickstart-" +"pytorch``." msgstr "" +"다음으로, Dockerfile을 생성합니다.``quickstart-pytorch`` 예제를 사용하는 경" +"우 ``examples/quickstart-pytorch``에 ``Dockerfile.supernode``라는 새 파일을 " +"생성합니다." #: ../../source/how-to-run-flower-using-docker.rst:203 msgid "" "The ``Dockerfile.supernode`` contains the instructions that assemble the " "SuperNode image." msgstr "" +"``Dockerfile.supernode``에는 SuperNode 이미지를 조립하는 지침이 포함되어 있습" +"니다." #: ../../source/how-to-run-flower-using-docker.rst:217 msgid "" -"In the first two lines, we instruct Docker to use the SuperNode image " -"tagged ``nightly`` as a base image and set our working directory to " -"``/app``. The following instructions will now be executed in the ``/app``" -" directory. Next, we install the ClientApp dependencies by copying the " -"``requirements.txt`` file into the image and run ``pip install``. In the " -"last two lines, we copy the ``client.py`` module into the image and set " -"the entry point to ``flower-client-app`` with the argument " -"``client:app``. The argument is the object reference of the ClientApp " -"(``:``) that will be run inside the ClientApp." -msgstr "" +"In the first two lines, we instruct Docker to use the SuperNode image tagged " +"``nightly`` as a base image and set our working directory to ``/app``. The " +"following instructions will now be executed in the ``/app`` directory. Next, " +"we install the ClientApp dependencies by copying the ``requirements.txt`` " +"file into the image and run ``pip install``. In the last two lines, we copy " +"the ``client.py`` module into the image and set the entry point to ``flower-" +"client-app`` with the argument ``client:app``. The argument is the object " +"reference of the ClientApp (``:``) that will be run " +"inside the ClientApp." +msgstr "" +"처음 두 줄에서는 ``nightly`` 태그가 붙은 SuperNode 이미지를 기본 이미지로 사" +"용하고 작업 디렉터리를 ``/app``로 설정하도록 Docker에 지시합니다. 이제 ``/" +"app`` 디렉토리에서 다음 명령이 실행됩니다. 다음으로, ``requirements.txt`` 파" +"일을 이미지에 복사하여 ClientApp dependencies 요소를 설치하고 ``pip install``" +"을 실행합니다. 마지막 두 줄에서 ``client.py`` 모듈을 이미지에 복사하고 " +"``client:app`` 인수를 사용하여 진입점을 ``flower-client-app``로 설정합니다. " +"인수는 클라이언트앱 내부에서 실행될 클라이언트앱의 객체 참조 (``:" +"``) 입니다." #: ../../source/how-to-run-flower-using-docker.rst:226 msgid "Building the SuperNode Docker image" -msgstr "" +msgstr "SuperNode Docker 이미지 빌드" #: ../../source/how-to-run-flower-using-docker.rst:228 msgid "" -"Next, we build the SuperNode Docker image by running the following " -"command in the directory where Dockerfile and ClientApp code are located." +"Next, we build the SuperNode Docker image by running the following command " +"in the directory where Dockerfile and ClientApp code are located." msgstr "" +"다음으로, Dockerfile 및 ClientApp 코드가 있는 디렉터리에서 다음 명령을 실행하" +"여 SuperNode Docker 이미지를 빌드합니다." #: ../../source/how-to-run-flower-using-docker.rst:235 msgid "" @@ -4990,143 +6011,181 @@ msgid "" "Remember that the here chosen values only serve as an example. You can " "change them to your needs." msgstr "" +"이미지에 ``flwr_supernode``라는 이름을 붙이고 ``0.0.1`` 태그를 붙였습니다. 여" +"기서 선택한 값은 예시일 뿐이라는 점을 기억하세요. 필요에 따라 변경할 수 있습" +"니다." #: ../../source/how-to-run-flower-using-docker.rst:240 msgid "Running the SuperNode Docker image" -msgstr "" +msgstr "SuperNode Docker 이미지 실행" #: ../../source/how-to-run-flower-using-docker.rst:242 msgid "Now that we have built the SuperNode image, we can finally run it." -msgstr "" +msgstr "이제 SuperNode 이미지를 빌드했으니 이제 실행할 수 있습니다." #: ../../source/how-to-run-flower-using-docker.rst:250 #: ../../source/how-to-run-flower-using-docker.rst:367 msgid "Let's break down each part of this command:" -msgstr "" +msgstr "이 명령의 각 부분을 자세히 살펴보겠습니다:" #: ../../source/how-to-run-flower-using-docker.rst:252 #: ../../source/how-to-run-flower-using-docker.rst:369 msgid "``docker run``: This is the command to run a new Docker container." -msgstr "" +msgstr "``docker run``: 새 Docker 컨테이너를 실행하는 명령입니다." #: ../../source/how-to-run-flower-using-docker.rst:253 #: ../../source/how-to-run-flower-using-docker.rst:370 msgid "" -"``--rm``: This option specifies that the container should be " -"automatically removed when it stops." +"``--rm``: This option specifies that the container should be automatically " +"removed when it stops." msgstr "" +"``--rm``: 이 옵션은 컨테이너가 중지될 때 자동으로 제거되도록 지정합니다." #: ../../source/how-to-run-flower-using-docker.rst:254 msgid "``flwr_supernode:0.0.1``: The name the tag of the Docker image to use." -msgstr "" +msgstr "``flwr_supernode:0.0.1``: 사용할 Docker 이미지의 태그 이름입니다." #: ../../source/how-to-run-flower-using-docker.rst:255 #: ../../source/how-to-run-flower-using-docker.rst:372 msgid "``--insecure``: This option enables insecure communication." -msgstr "" +msgstr "``--insecure``: 이 옵션은 보안되지 않은 통신을 활성화합니다." #: ../../source/how-to-run-flower-using-docker.rst msgid "" -"``--superlink 192.168.1.100:9092``: This option specifies the address of " -"the SuperLinks Fleet" +"``--superlink 192.168.1.100:9092``: This option specifies the address of the " +"SuperLinks Fleet" msgstr "" +"``--superlink 192.168.1.100:9092``: 이 옵션은 SuperLinks Fleet의 주소를 지정" +"합니다" #: ../../source/how-to-run-flower-using-docker.rst msgid "API to connect to. Remember to update it with your SuperLink IP." msgstr "" +"API에 연결할 수 있습니다. SuperLink IP로 업데이트하는 것을 잊지 마세요." #: ../../source/how-to-run-flower-using-docker.rst:269 msgid "" -"To test running Flower locally, you can create a `bridge network " -"`__, use the ``--network`` argument and pass the " -"name of the Docker network to run your SuperNodes." +"To test running Flower locally, you can create a `bridge network `__, use the ``--network`` argument and pass the name of the Docker " +"network to run your SuperNodes." msgstr "" +"로컬에서 Flower를 실행하는 것을 테스트하려면 `bridge network `__를 생성하고 ``--network`` argument를 사용하고 SuperNodes를 실행" +"할 Docker 네트워크의 이름을 전달하면 됩니다." #: ../../source/how-to-run-flower-using-docker.rst:273 msgid "" "Any argument that comes after the tag is passed to the Flower SuperNode " "binary. To see all available flags that the SuperNode supports, run:" msgstr "" +"태그 뒤에 오는 모든 argument는 Flower SuperNode 바이너리에 전달됩니다. " +"SuperNode가 지원하는 사용 가능한 모든 플래그를 보려면 실행하세요:" #: ../../source/how-to-run-flower-using-docker.rst:283 msgid "" "To enable SSL, we will need to mount a PEM-encoded root certificate into " "your SuperNode container." msgstr "" +"SSL을 사용하려면 PEM 인코딩된 루트 인증서를 SuperNode 컨테이너에 마운트해야 " +"합니다." #: ../../source/how-to-run-flower-using-docker.rst:285 msgid "" -"Assuming the certificate already exists locally, we can use the flag " -"``--volume`` to mount the local certificate into the container's " -"``/app/`` directory. This allows the SuperNode to access the certificate " -"within the container. Use the ``--root-certificates`` flag when starting " -"the container." +"Assuming the certificate already exists locally, we can use the flag ``--" +"volume`` to mount the local certificate into the container's ``/app/`` " +"directory. This allows the SuperNode to access the certificate within the " +"container. Use the ``--root-certificates`` flag when starting the container." msgstr "" +"인증서가 이미 로컬에 존재한다고 가정하면, ``--volume`` 플래그를 사용하여 로" +"컬 인증서를 컨테이너의 ``/app/`` 디렉터리에 마운트할 수 있습니다. 이렇게 하" +"면 SuperNode가 컨테이너 내의 인증서에 액세스할 수 있습니다. 컨테이너를 시작" +"할 때 ``--root-certificates`` 플래그를 사용하세요." #: ../../source/how-to-run-flower-using-docker.rst:297 msgid "Flower ServerApp" -msgstr "" +msgstr "Flower 서버앱" #: ../../source/how-to-run-flower-using-docker.rst:299 msgid "" -"The procedure for building and running a ServerApp image is almost " -"identical to the SuperNode image." +"The procedure for building and running a ServerApp image is almost identical " +"to the SuperNode image." msgstr "" +"ServerApp 이미지를 빌드하고 실행하는 절차는 SuperNode 이미지와 거의 동일합니" +"다." #: ../../source/how-to-run-flower-using-docker.rst:301 msgid "" -"Similar to the SuperNode image, the ServerApp Docker image comes with a " -"pre-installed version of Flower and serves as a base for building your " -"own ServerApp image." +"Similar to the SuperNode image, the ServerApp Docker image comes with a pre-" +"installed version of Flower and serves as a base for building your own " +"ServerApp image." msgstr "" +"SuperNode 이미지와 마찬가지로 ServerApp Docker 이미지는 Flower의 사전 설치된 " +"버전과 함께 제공되며, 자체 ServerApp 이미지를 구축하기 위한 기본 역할을 합니" +"다." #: ../../source/how-to-run-flower-using-docker.rst:304 msgid "" -"We will use the same ``quickstart-pytorch`` example as we do in the " -"Flower SuperNode section. If you have not already done so, please follow " -"the `SuperNode Prerequisites`_ before proceeding." +"We will use the same ``quickstart-pytorch`` example as we do in the Flower " +"SuperNode section. If you have not already done so, please follow the " +"`SuperNode Prerequisites`_ before proceeding." msgstr "" +"여기서는 Flower SuperNode 섹션에서와 동일한`quickstart-pytorch`` 예제를 사용" +"하겠습니다. 아직 수행하지 않았다면 계속 진행하기 전에 `SuperNode " +"Prerequisites`_ 을 따르세요." #: ../../source/how-to-run-flower-using-docker.rst:309 msgid "Creating a ServerApp Dockerfile" -msgstr "" +msgstr "ServerApp Dockerfile 만들기" #: ../../source/how-to-run-flower-using-docker.rst:320 msgid "" "First, we need to create a Dockerfile in the directory where the " "``ServerApp`` code is located. If you use the ``quickstart-pytorch`` " -"example, create a new file called ``Dockerfile.serverapp`` in ``examples" -"/quickstart-pytorch``." +"example, create a new file called ``Dockerfile.serverapp`` in ``examples/" +"quickstart-pytorch``." msgstr "" +"먼저, ``ServerApp`` 코드가 있는 디렉토리에 Docker파일을 생성해야 합니다. " +"``quickstart-pytorch`` 예제를 사용하는 경우 ``examples/quickstart-pytorch``" +"에 ``Dockerfile.serverapp``이라는 새 파일을 생성합니다." #: ../../source/how-to-run-flower-using-docker.rst:324 msgid "" "The ``Dockerfile.serverapp`` contains the instructions that assemble the " "ServerApp image." msgstr "" +"``Dockerfile.serverapp``에는 ServerApp 이미지를 합치는 지침이 포함되어 있습니" +"다." #: ../../source/how-to-run-flower-using-docker.rst:335 msgid "" -"In the first two lines, we instruct Docker to use the ServerApp image " -"tagged ``1.8.0`` as a base image and set our working directory to " -"``/app``. The following instructions will now be executed in the ``/app``" -" directory. In the last two lines, we copy the ``server.py`` module into " -"the image and set the entry point to ``flower-server-app`` with the " -"argument ``server:app``. The argument is the object reference of the " -"ServerApp (``:``) that will be run inside the " -"ServerApp container." -msgstr "" +"In the first two lines, we instruct Docker to use the ServerApp image tagged " +"``1.8.0`` as a base image and set our working directory to ``/app``. The " +"following instructions will now be executed in the ``/app`` directory. In " +"the last two lines, we copy the ``server.py`` module into the image and set " +"the entry point to ``flower-server-app`` with the argument ``server:app``. " +"The argument is the object reference of the ServerApp (``:" +"``) that will be run inside the ServerApp container." +msgstr "" +"처음 두 줄에서는 ``1.8.0`` 태그가 붙은 ServerApp 이미지를 기본 이미지로 사용" +"하고 작업 디렉터리를 ``/app``로 설정하도록 Docker에 지시합니다. 이제 ``/" +"app`` 디렉토리에서 다음 명령이 실행됩니다. 마지막 두 줄에서는 ``server.py`` " +"모듈을 이미지에 복사하고 ``server:app`` argument를 사용하여 진입점을 " +"``flower-server-app``로 설정합니다. 인수는 ServerApp 컨테이너 내에서 실행될 " +"ServerApp의 객체 참조(``:``)입니다." #: ../../source/how-to-run-flower-using-docker.rst:343 msgid "Building the ServerApp Docker image" -msgstr "" +msgstr "ServerApp Docker 이미지 빌드" #: ../../source/how-to-run-flower-using-docker.rst:345 msgid "" -"Next, we build the ServerApp Docker image by running the following " -"command in the directory where Dockerfile and ServerApp code are located." +"Next, we build the ServerApp Docker image by running the following command " +"in the directory where Dockerfile and ServerApp code are located." msgstr "" +"다음으로, Docker파일과 ServerApp 코드가 있는 디렉터리에서 다음 명령을 실행하" +"여 ServerApp Docker 이미지를 빌드합니다." #: ../../source/how-to-run-flower-using-docker.rst:352 msgid "" @@ -5134,453 +6193,600 @@ msgid "" "Remember that the here chosen values only serve as an example. You can " "change them to your needs." msgstr "" +"이미지에``flwr_serverapp``이라는 이름을 붙이고 ``0.0.1``이라는 태그를 붙였습" +"니다. 여기서 선택한 값은 예시일 뿐이라는 점을 기억하세요. 필요에 따라 변경할 " +"수 있습니다." #: ../../source/how-to-run-flower-using-docker.rst:357 msgid "Running the ServerApp Docker image" -msgstr "" +msgstr "ServerApp Docker 이미지 실행" #: ../../source/how-to-run-flower-using-docker.rst:359 msgid "Now that we have built the ServerApp image, we can finally run it." -msgstr "" +msgstr "이제 ServerApp 이미지를 빌드했으니 이제 실행할 수 있습니다." #: ../../source/how-to-run-flower-using-docker.rst:371 msgid "``flwr_serverapp:0.0.1``: The name the tag of the Docker image to use." -msgstr "" +msgstr "``flwr_serverapp:0.0.1``: 사용할 Docker 이미지의 태그 이름입니다." #: ../../source/how-to-run-flower-using-docker.rst msgid "" -"``--superlink 192.168.1.100:9091``: This option specifies the address of " -"the SuperLinks Driver" +"``--superlink 192.168.1.100:9091``: This option specifies the address of the " +"SuperLinks Driver" msgstr "" +"``--superlink 192.168.1.100:9091``: 이 옵션은 SuperLinks 드라이버의 주소를 지" +"정합니다" #: ../../source/how-to-run-flower-using-docker.rst:385 msgid "" -"To test running Flower locally, you can create a `bridge network " -"`__, use the ``--network`` argument and pass the " -"name of the Docker network to run your ServerApps." +"To test running Flower locally, you can create a `bridge network `__, use the ``--network`` argument and pass the name of the Docker " +"network to run your ServerApps." msgstr "" +"로컬에서 Flower를 실행하는 것을 테스트하려면 `bridge network `__,를 생성하고 ``--network`` argument를 사용하여 ServerApp을 실행" +"할 Docker 네트워크의 이름을 전달하면 됩니다." #: ../../source/how-to-run-flower-using-docker.rst:389 msgid "" "Any argument that comes after the tag is passed to the Flower ServerApp " "binary. To see all available flags that the ServerApp supports, run:" msgstr "" +"태그 뒤에 오는 모든 argument는 Flower ServerApp 바이너리에 전달됩니다. " +"ServerApp에서 지원하는 사용 가능한 모든 플래그를 보려면 실행하세요:" #: ../../source/how-to-run-flower-using-docker.rst:399 msgid "" "To enable SSL, we will need to mount a PEM-encoded root certificate into " "your ServerApp container." msgstr "" +"SSL을 사용하려면 PEM 인코딩된 루트 인증서를 ServerApp 컨테이너에 마운트해야 " +"합니다." #: ../../source/how-to-run-flower-using-docker.rst:401 msgid "" -"Assuming the certificate already exists locally, we can use the flag " -"``--volume`` to mount the local certificate into the container's " -"``/app/`` directory. This allows the ServerApp to access the certificate " -"within the container. Use the ``--root-certificates`` flags when starting" -" the container." +"Assuming the certificate already exists locally, we can use the flag ``--" +"volume`` to mount the local certificate into the container's ``/app/`` " +"directory. This allows the ServerApp to access the certificate within the " +"container. Use the ``--root-certificates`` flags when starting the container." msgstr "" +"인증서가 이미 로컬에 존재한다고 가정하면, ``--volume`` 플래그를 사용하여 로" +"컬 인증서를 컨테이너의 ``/app/`` 디렉터리에 마운트할 수 있습니다. 이렇게 하" +"면 ServerApp이 컨테이너 내의 인증서에 액세스할 수 있습니다. 컨테이너를 시작" +"할 때 ``--root-certificates`` 플래그를 사용하세요." #: ../../source/how-to-run-flower-using-docker.rst:412 msgid "Advanced Docker options" -msgstr "" +msgstr "고급 Docker 옵션" #: ../../source/how-to-run-flower-using-docker.rst:415 msgid "Run with root user privileges" -msgstr "" +msgstr "루트 사용자 권한으로 실행" #: ../../source/how-to-run-flower-using-docker.rst:417 msgid "" -"Flower Docker images, by default, run with a non-root user " -"(username/groupname: ``app``, UID/GID: ``49999``). Using root user is not" -" recommended unless it is necessary for specific tasks during the build " -"process. Always make sure to run the container as a non-root user in " -"production to maintain security best practices." +"Flower Docker images, by default, run with a non-root user (username/" +"groupname: ``app``, UID/GID: ``49999``). Using root user is not recommended " +"unless it is necessary for specific tasks during the build process. Always " +"make sure to run the container as a non-root user in production to maintain " +"security best practices." msgstr "" +"기본적으로 Flower Docker 이미지는 루트 사용자가 아닌 사용자(사용자명/그룹명:" +"``app``, UID/GID: ``49999``)로 실행됩니다. 빌드 프로세스 중 특정 작업에 필요" +"한 경우가 아니라면 루트 사용자를 사용하지 않는 것이 좋습니다. 보안 모범 사례" +"를 유지하려면 항상 프로덕션 환경에서 루트 사용자가 아닌 사용자로 컨테이너를 " +"실행해야 합니다." #: ../../source/how-to-run-flower-using-docker.rst:422 msgid "**Run a container with root user privileges**" -msgstr "" +msgstr "**루트 사용자 권한으로 컨테이너 실행하기**" #: ../../source/how-to-run-flower-using-docker.rst:424 msgid "" "Run the Docker image with the ``-u`` flag and specify ``root`` as the " "username:" msgstr "" +"``-u`` 플래그를 사용하여 Docker 이미지를 실행하고 사용자 이름으로 ``root``를 " +"지정합니다:" #: ../../source/how-to-run-flower-using-docker.rst:430 msgid "This command will run the Docker container with root user privileges." -msgstr "" +msgstr "이 명령은 루트 사용자 권한으로 Docker 컨테이너를 실행합니다." #: ../../source/how-to-run-flower-using-docker.rst:432 msgid "**Run the build process with root user privileges**" -msgstr "" +msgstr "**루트 사용자 권한으로 빌드 프로세스를 실행합니다**" #: ../../source/how-to-run-flower-using-docker.rst:434 msgid "" "If you want to switch to the root user during the build process of the " -"Docker image to install missing system dependencies, you can use the " -"``USER root`` directive within your Dockerfile." +"Docker image to install missing system dependencies, you can use the ``USER " +"root`` directive within your Dockerfile." msgstr "" +"Docker 이미지 빌드 과정에서 루트 사용자로 전환하여 누락된 시스템 의존성을 " +"설치하려면 Dockerfile 내에서 ``USER root`` 지시어를 사용할 수 있습니다." #: ../../source/how-to-run-flower-using-docker.rst:454 msgid "Using a different Flower version" -msgstr "" +msgstr "다른 Flower 버전 사용" #: ../../source/how-to-run-flower-using-docker.rst:456 msgid "" "If you want to use a different version of Flower, for example Flower " -"nightly, you can do so by changing the tag. All available versions are on" -" `Docker Hub `__." +"nightly, you can do so by changing the tag. All available versions are on " +"`Docker Hub `__." msgstr "" +"다른 버전의 Flower를 사용하려면 태그를 변경하여 사용할 수 있습니다(예: " +"Flower nightly). 사용 가능한 모든 버전은 `Docker Hub `__에 있습니다." #: ../../source/how-to-run-flower-using-docker.rst:460 msgid "Pinning a Docker image to a specific version" -msgstr "" +msgstr "특정 버전에 Docker 이미지 고정하기" #: ../../source/how-to-run-flower-using-docker.rst:462 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." +"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 "" +"태그 뒤에 있는 이미지가 업데이트될 수 있습니다. 이러한 업데이트에는 " +"일반적으로 Flower의 기능을 변경해서는 안 되는 시스템 의존성에 대한 보안 " +"업데이트가 포함됩니다. 그러나 항상 동일한 이미지를 사용하려면 태그 대신 " +"이미지의 해시를 지정할 수 있습니다." #: ../../source/how-to-run-flower-using-docker.rst:467 msgid "" "The following command returns the current image hash referenced by the " "``superlink:1.8.0`` tag:" msgstr "" +"다음 명령은 ``superlink:1.8.0`` 태그가 참조하는 현재 이미지 해시를 반환합니" +"다:" #: ../../source/how-to-run-flower-using-docker.rst:474 msgid "Next, we can pin the hash when running a new SuperLink container:" -msgstr "" +msgstr "다음으로, 새 SuperLink 컨테이너를 실행할 때 해시를 고정할 수 있습니다:" #: ../../source/how-to-run-flower-using-docker.rst:483 msgid "Setting environment variables" -msgstr "" +msgstr "환경 변수 설정" #: ../../source/how-to-run-flower-using-docker.rst:485 msgid "" "To set a variable inside a Docker container, you can use the ``-e " "=`` flag." msgstr "" +"Docker 컨테이너 내에서 변수를 설정하려면 ``-e =`` 플래그를 사용" +"하면 됩니다." #: ../../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 "" +"Federated 학습 워크로드 시뮬레이션은 다양한 사용 사례에 유용합니다. 대규모 클" +"라이언트 집단에서 워크로드를 실행하되 많은 수의 물리적 장치를 소싱, 구성 및 " +"관리할 필요가 없는 경우, 복잡한 설정 과정을 거치지 않고도 액세스 가능한 컴퓨" +"팅 시스템에서 최대한 빠르게 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 "" +"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`은 `virtual` 클라이언트를 예약, 실행 및 관리합니" +"다. 이러한 클라이언트는 `non-virtual` 클라이언트(예: `flwr.client." +"start_client `_ 명령을 통해 실행하는 클라이언" +"트)와 동일하며, `flwr.client.NumPyClient `_에서 상속하는 클래스 생성으로 구성될 수 있으므로 동일한 방식으" +"로 동작합니다. 그 외에도 :code:`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 "" +"resource-aware: 이는 각 클라이언트가 시스템에서 컴퓨팅 및 메모리의 일부를 할" +"당받는다는 것을 의미합니다. 사용자는 시뮬레이션을 시작할 때 이를 제어할 수 있" +"으며, 이를 통해 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 "" +"self-managed: 이는 사용자가 클라이언트를 수동으로 실행할 필요가 없으며, 대" +"신 :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 "" +":code:`VirtualClientEngine`은 확장 가능한 파이썬 워크로드를 위한 오픈 소스 프" +"레임워크인 `Ray `_를 사용하여 `virtual` 클라이언트를 구" +"현합니다. 특히 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 "VirtualClientEngine 리소스" #: ../../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를 시작할 때의 기본 동작이기도 합니다. 그러나 일부 설정에서" +"는 시뮬레이션에 사용되는 시스템 리소스의 수를 제한하고 싶을 수 있습니다. 이 " +"설정은 VCE가 내부적으로 Ray의 :code:`ray.init` 명령에 전달하는 :code:" +"`start_simulation`에 대한 :code:`ray_init_args` 입력 인수를 통해 수행할 수 있" +"습니다. 구성할 수 있는 전체 설정 목록은 `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` argument를 `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 "" +":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 "" +":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개의 작업(각각 전략에서 샘플링한 클라이언트를 시뮬레이션)을 예약한 다" +"음 리소스 인식 방식으로 8개씩 일괄적으로 실행합니다." #: ../../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와 파이토치에서 바로 실행할 수 있는 몇 가지 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 "" +"파이토치 시뮬레이션 `_: 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:`simulation " +"considerations `에서 확인하세요)" #: ../../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:`ray start --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 "" +"여기에서는 멀티 노드 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)" -msgstr "" +"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 "" +"Flower 시뮬레이션으로 모든 FL 워크로드를 간편하게 실행할 수 있도록 이러한 측" +"면에서 적극적으로 노력하고 있습니다." #: ../../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를 사용하면 개인 노트북에서 간단한 시나리오를 프로토타이핑하든, 여러 " +"고성능 GPU 노드에서 복잡한 FL 파이프라인을 훈련하든 상관없이 시뮬레이션 모드" +"에서 Federated 학습 워크로드를 실행할 수 있습니다. 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 메모리 공유를 할당합니다. 즉, (VCE에서 내부적으로 사용하는) Ray가 기본" +"적으로 사용됩니다:" #: ../../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을 인식하지 못합니다. 즉, 시스템에 서로 다른(예: " +"32GB와 8GB) VRAM 용량을 가진 두 개의 GPU가 있고 :code:`num_gpus=0.5`를 설정하" +"면 둘 다 동시에 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 "" +"관련 없는(즉, VCE에 의해 생성되지 않은) 다른 워크로드가 GPU에서 실행되고 있는" +"지 알지 못합니다. 여기서 두 가지 시사점을 얻을 수 있습니다:" #: ../../source/how-to-run-simulations.rst:149 msgid "" @@ -5588,178 +6794,237 @@ msgid "" "aggregation (by instance when making use of the `evaluate method `_)" msgstr "" +"집계 후 '글로벌 모델'을 평가하려면 Flower 서버에 GPU가 필요할 수 있습니다" +"(예: `evaluate method `_를 사용할 때)" #: ../../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 " -"`_." -msgstr "" +"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의 거의 전체 GPU 메모리가 매핑됩니다. 이는 최적화 목" +"적으로 TensorFlow에서 수행됩니다. 그러나 GPU를 여러 개의 '가상' 클라이언트로 " +"분할하려는 FL 시뮬레이션과 같은 설정에서는 이는 바람직한 메커니즘이 아닙니" +"다. 다행히도 '메모리 증가 활성화 `_'를 통해 이 기본 동작을 비활성화할 수 있습니" +"다." #: ../../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 Simulation `_ 예제에서 사용된 메커니즘입니다." #: ../../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:`FedAvg` 전략을 사용자 지정한 새로운 :code:" +"`SaveModelStrategy`를 정의합니다. 특히, 기본 클래스(: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 "파이토치 체크포인트 저장 및 로드" #: ../../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 "" +"이전 예제와 비슷하지만 몇 가지 단계가 추가되어 ``torch.save`` 함수를 사용하" +"여 파이토치 체크포인트를 저장하는 방법을 보여드리겠습니다. 먼저, " +"``aggregate_fit``은 ``Parameters`` 객체를 반환하는데, 이 객체는 NumPy " +"``ndarray``의 목록으로 변환되어야 하며, ``OrderedDict`` 클래스 구조에 따라 파" +"이토치 ``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``." +"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 "" +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 #: ../../source/how-to-upgrade-to-flower-next.rst:43 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:" +"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 "" @@ -5767,140 +7032,170 @@ msgid "" "reinstall (don't forget to delete ``poetry.lock`` via ``rm poetry.lock`` " "before running ``poetry install``)." msgstr "" +"Poetry: ``pyproject.toml``에서 ``flwr`` dependency을 업데이트한 다음 다시 설" +"치하세요(``poetry 설치``를 실행하기 전에 ``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 #: ../../source/how-to-upgrade-to-flower-next.rst:100 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:37 #: ../../source/ref-api/flwr.client.Client.rst:2 msgid "Client" -msgstr "" +msgstr "클라이언트" #: ../../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 "" +"``클라이언트``의 서브클래스: ``def get_parameters(self):``를 ``def " +"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 "" +"Dictionary 대신 ``ServerConfig``를 ``start_server`` 및 ``start_simulation``" +"에 전달합니다. 다음은 예제입니다:" #: ../../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 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 "매개변수/ndarray 변환 함수의 이름을 바꿉니다:" #: ../../source/how-to-upgrade-to-flower-1.0.rst:54 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 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``을 호출하여)는 이제 " +"``fraction_fit`` 및 ``fraction_evaluate``를 ``0.1``로 설정하여 FedAvg를 수동" +"으로 초기화해야 합니다." #: ../../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 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 "" @@ -5908,72 +7203,90 @@ 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 "``server_round`` 및 ``config``를 ``evaluate_fn``에 추가합니다:" #: ../../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]]]:``" #: ../../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]]]:``" #: ../../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]]``(``aggregate_fit``" +"에서) 및 ``List[Union[Tuple[ClientProxy], EvaluateRes], " +"BaseException]]``(``aggregate_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``는 현재 federated 학습/평가 라운드를 첫 " +"번째 파라미터로 받습니다:" #: ../../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]]]:``" #: ../../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]]]:``" #: ../../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 "" +"위의 필수 변경 사항과 함께 방금 가능한 여러 가지 잠재적 개선 사항이 있습니다:" #: ../../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 " -"empty placeholder implementations of ``evaluate`` are no longer " -"necessary." +"``NumPyClient``. If you, for example, use server-side evaluation, then empty " +"placeholder implementations of ``evaluate`` are no longer necessary." msgstr "" +"``Client`` 또는 ``NumPyClient``의 서브 클래스에서 \"placeholder\" 메서드를 제" +"거합니다. 예를 들어 서버 측 평가를 사용하는 경우 ``evaluate``의 빈 자리 표시" +"자 구현은 더 이상 필요하지 않습니다." #: ../../source/how-to-upgrade-to-flower-1.0.rst:85 msgid "" @@ -5981,69 +7294,84 @@ 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 #: ../../source/how-to-upgrade-to-flower-next.rst:317 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 questions, `join the Flower Slack " -"`_ and use the channel ``#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 questions, " +"`join the Flower Slack `_ and use the channel " +"``#questions``." msgstr "" +"대부분의 공식 ``Flower code 예제 `_는 이미 Flower 1.0으로 업데이트되어 있으며, Flower 1.0 API를 사용" +"하기 위한 참고 자료로 사용할 수 있습니다. 더 궁금한 점이 있다면 ``플라워 슬" +"랙 `_에 가입하여 ``#questions`` 채널을 이용하" +"세요." #: ../../source/how-to-upgrade-to-flower-next.rst:2 msgid "Upgrade to Flower Next" -msgstr "" +msgstr "Flower Next 업그레이드" #: ../../source/how-to-upgrade-to-flower-next.rst:4 msgid "" -"Welcome to the migration guide for updating Flower to Flower Next! " -"Whether you're a seasoned user or just getting started, this guide will " -"help you smoothly transition your existing setup to take advantage of the" -" latest features and improvements in Flower Next, starting from version " -"1.8." +"Welcome to the migration guide for updating Flower to Flower Next! Whether " +"you're a seasoned user or just getting started, this guide will help you " +"smoothly transition your existing setup to take advantage of the latest " +"features and improvements in Flower Next, starting from version 1.8." msgstr "" +"Flower에서 Flower Next로의 업데이트를 위한 이동 가이드에 오신 것을 환영합니" +"다! 이 가이드는 숙련된 사용자든 이제 막 시작한 사용자든 상관없이 기존 설정을 " +"원활하게 전환하여 버전 1.8부터 Flower Next의 최신 기능 및 개선 사항을 활용할 " +"수 있도록 도와드립니다." #: ../../source/how-to-upgrade-to-flower-next.rst:9 msgid "" "This guide shows how to reuse pre-``1.8`` Flower code with minimum code " -"changes by using the *compatibility layer* in Flower Next. In another " -"guide, we will show how to run Flower Next end-to-end with pure Flower " -"Next APIs." +"changes by using the *compatibility layer* in Flower Next. In another guide, " +"we will show how to run Flower Next end-to-end with pure Flower Next APIs." msgstr "" +"이 가이드에서는 Flower Next의 *호환성 레이어*를 사용하여 최소한의 코드 변경으" +"로 ``1.8`` 이전의 Flower 코드를 재사용하는 방법을 보여줍니다. 다른 가이드에서" +"는 순수한 Flower Next API로 Flower Next를 end-to-end로 실행하는 방법을 보여드" +"리겠습니다." #: ../../source/how-to-upgrade-to-flower-next.rst:13 msgid "Let's dive in!" -msgstr "" +msgstr "자세히 알아봅시다!" #: ../../source/how-to-upgrade-to-flower-next.rst:48 msgid "" -"Here's how to update an existing installation of Flower to Flower Next " -"with ``pip``:" +"Here's how to update an existing installation of Flower to Flower Next with " +"``pip``:" msgstr "" +"기존에 설치된 Flower to Flower Next를 ``pip``으로 업데이트하는 방법은 다음과 " +"같습니다:" #: ../../source/how-to-upgrade-to-flower-next.rst:54 msgid "or if you need Flower Next with simulation:" -msgstr "" +msgstr "또는 시뮬레이션이 포함된 Flower Next가 필요한 경우:" #: ../../source/how-to-upgrade-to-flower-next.rst:61 msgid "" -"Ensure you set the following version constraint in your " -"``requirements.txt``" -msgstr "" +"Ensure you set the following version constraint in your ``requirements.txt``" +msgstr "``requirements.txt``에서 다음 버전 제약 조건을 설정했는지 확인하세요" #: ../../source/how-to-upgrade-to-flower-next.rst:71 msgid "or ``pyproject.toml``:" -msgstr "" +msgstr "또는 ``pyproject.toml``:" #: ../../source/how-to-upgrade-to-flower-next.rst:82 msgid "Using Poetry" -msgstr "" +msgstr "Poetry 사용" #: ../../source/how-to-upgrade-to-flower-next.rst:84 msgid "" @@ -6051,122 +7379,155 @@ msgid "" "(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-next.rst:86 msgid "" -"Ensure you set the following version constraint in your " -"``pyproject.toml``:" -msgstr "" +"Ensure you set the following version constraint in your ``pyproject.toml``:" +msgstr "``pyproject.toml``에 다음 버전 제약 조건을 설정했는지 확인하세요:" #: ../../source/how-to-upgrade-to-flower-next.rst:102 msgid "" "In Flower Next, the *infrastructure* and *application layers* have been " -"decoupled. Instead of starting a client in code via ``start_client()``, " -"you create a |clientapp_link|_ and start it via the command line. Instead" -" of starting a server in code via ``start_server()``, you create a " -"|serverapp_link|_ and start it via the command line. The long-running " +"decoupled. Instead of starting a client in code via ``start_client()``, you " +"create a |clientapp_link|_ and start it via the command line. Instead of " +"starting a server in code via ``start_server()``, you create a |" +"serverapp_link|_ and start it via the command line. The long-running " "components of server and client are called SuperLink and SuperNode. The " -"following non-breaking changes that require manual updates and allow you " -"to run your project both in the traditional way and in the Flower Next " -"way:" +"following non-breaking changes that require manual updates and allow you to " +"run your project both in the traditional way and in the Flower Next way:" msgstr "" +"Flower Next에서는 *infrastructure*와 *application layers*가 분리되었습니다. " +"코드에서 ``start_client()``를 통해 클라이언트를 시작하는 대신, 명령줄을 통해 " +"|clientapp_link|_를 생성하여 시작합니다. 코드에서 ``start_server()``를 통해 " +"서버를 시작하는 대신 |serverapp_link|_를 생성하고 명령줄을 통해 서버를 시작합" +"니다. 서버와 클라이언트의 장기 실행 컴포넌트를 SuperLink와 SuperNode라고 합니" +"다. 수동 업데이트가 필요하지 않고 기존 방식과 Flower Next 방식 모두에서 프로" +"젝트를 실행할 수 있는 non-breaking 변경 사항은 다음과 같습니다:" #: ../../source/how-to-upgrade-to-flower-next.rst:109 msgid "|clientapp_link|_" -msgstr "" +msgstr "|clientapp_link|_" #: ../../source/how-to-upgrade-to-flower-next.rst:110 msgid "" -"Wrap your existing client with |clientapp_link|_ instead of launching it " -"via |startclient_link|_. Here's an example:" +"Wrap your existing client with |clientapp_link|_ instead of launching it via " +"|startclient_link|_. Here's an example:" msgstr "" +"|clientapp_link|_를 통해 실행하는 대신 기존 클라이언트를 |clientapp_link|_로 " +"래핑하세요. 다음은 예시입니다:" #: ../../source/how-to-upgrade-to-flower-next.rst:132 msgid "|serverapp_link|_" -msgstr "" +msgstr "|serverapp_link|_" #: ../../source/how-to-upgrade-to-flower-next.rst:133 msgid "" -"Wrap your existing strategy with |serverapp_link|_ instead of starting " -"the server via |startserver_link|_. Here's an example:" +"Wrap your existing strategy with |serverapp_link|_ instead of starting the " +"server via |startserver_link|_. Here's an example:" msgstr "" +"서버를 시작하려면 |startserver_link|_를 통해 서버를 시작하는 대신 기존 전략" +"을 |serverapp_link|_로 래핑하세요. 다음은 예시입니다:" #: ../../source/how-to-upgrade-to-flower-next.rst:154 msgid "Deployment" -msgstr "" +msgstr "배포" #: ../../source/how-to-upgrade-to-flower-next.rst:155 msgid "" -"Run the ``SuperLink`` using |flowernext_superlink_link|_ before running, " -"in sequence, |flowernext_clientapp_link|_ (2x) and " -"|flowernext_serverapp_link|_. There is no need to execute `client.py` and" -" `server.py` as Python scripts." +"Run the ``SuperLink`` using |flowernext_superlink_link|_ before running, in " +"sequence, |flowernext_clientapp_link|_ (2x) and |flowernext_serverapp_link|" +"_. There is no need to execute `client.py` and `server.py` as Python scripts." msgstr "" +"실행하기 전에 |flowernext_superlink_link|_를 사용하여 ``SuperLink``를 실행한 " +"후 |flowernext_clientapp_link|_(2회) 및 |flowernext_serverapp_link|_를 " +"순서대로 실행합니다. 'client.py'와 'server.py'를 Python 스크립트로 실행할 " +"필요는 없습니다." #: ../../source/how-to-upgrade-to-flower-next.rst:158 msgid "" -"Here's an example to start the server without HTTPS (only for " -"prototyping):" +"Here's an example to start the server without HTTPS (only for prototyping):" msgstr "" +"다음은 HTTPS 없이 서버를 시작하는 예제입니다(프로토타이핑용으로만 사용):" #: ../../source/how-to-upgrade-to-flower-next.rst:174 msgid "" -"Here's another example to start with HTTPS. Use the ``--ssl-ca-" -"certfile``, ``--ssl-certfile``, and ``--ssl-keyfile`` command line " -"options to pass paths to (CA certificate, server certificate, and server " -"private key)." +"Here's another example to start with HTTPS. Use the ``--ssl-ca-certfile``, " +"``--ssl-certfile``, and ``--ssl-keyfile`` command line options to pass paths " +"to (CA certificate, server certificate, and server private key)." msgstr "" +"다음은 HTTPS로 시작하는 또 다른 예제입니다. '`--ssl-ca-certfile``, '`--ssl-" +"certfile``, '`--ssl-keyfile`` 명령줄 옵션을 사용하여 (CA 인증서, 서버 인증서 " +"및 서버 개인 키)의 경로를 전달합니다." #: ../../source/how-to-upgrade-to-flower-next.rst:201 msgid "Simulation in CLI" -msgstr "" +msgstr "CLI 시뮬레이션" #: ../../source/how-to-upgrade-to-flower-next.rst:202 msgid "" -"Wrap your existing client and strategy with |clientapp_link|_ and " -"|serverapp_link|_, respectively. There is no need to use |startsim_link|_" -" anymore. Here's an example:" +"Wrap your existing client and strategy with |clientapp_link|_ and |" +"serverapp_link|_, respectively. There is no need to use |startsim_link|_ " +"anymore. Here's an example:" msgstr "" +"기존 클라이언트와 전략을 각각 |clientapp_link|_와 |serverapp_link|_로 래핑하" +"세요. 더 이상 |startsim_link|_를 사용할 필요가 없습니다. 다음은 예시입니다:" #: ../../source/how-to-upgrade-to-flower-next.rst:232 msgid "" "Run |flower_simulation_link|_ in CLI and point to the ``server_app`` / " -"``client_app`` object in the code instead of executing the Python script." -" Here's an example (assuming the ``server_app`` and ``client_app`` " -"objects are in a ``sim.py`` module):" +"``client_app`` object in the code instead of executing the Python script. " +"Here's an example (assuming the ``server_app`` and ``client_app`` objects " +"are in a ``sim.py`` module):" msgstr "" +"CLI에서 |flower_simulation_link|_를 실행하고 Python 스크립트를 실행하는 대신 " +"코드에서 ``server_app`` / ``client_app`` 개체를 가리키세요. 다음은 예제입니다" +"(``server_app`` 및 ``client_app`` 객체가 ``sim.py`` 모듈에 있다고 가정):" #: ../../source/how-to-upgrade-to-flower-next.rst:249 msgid "" "Set default resources for each |clientapp_link|_ using the ``--backend-" -"config`` command line argument instead of setting the " -"``client_resources`` argument in |startsim_link|_. Here's an example:" +"config`` command line argument instead of setting the ``client_resources`` " +"argument in |startsim_link|_. Here's an example:" msgstr "" +"|startsim_link|_에서 ``client_resources`` 인수를 설정하는 대신 ``--backend-" +"config`` 명령줄 인수를 사용하여 각 |clientapp_link|_에 대한 기본 리소스를 설" +"정하세요. 다음은 예시입니다:" #: ../../source/how-to-upgrade-to-flower-next.rst:275 msgid "Simulation in a Notebook" -msgstr "" +msgstr "Notebook에서 시뮬레이션" #: ../../source/how-to-upgrade-to-flower-next.rst:276 msgid "" -"Run |runsim_link|_ in your notebook instead of |startsim_link|_. Here's " -"an example:" +"Run |runsim_link|_ in your notebook instead of |startsim_link|_. Here's an " +"example:" msgstr "" +"notebook에서 |startsim_link|_ 대신 |runsim_link|_를 실행하세요. 다음은 예시입" +"니다:" #: ../../source/how-to-upgrade-to-flower-next.rst:319 msgid "" -"Some official `Flower code examples `_ " -"are already updated to Flower Next so they can serve as a reference for " -"using the Flower Next API. If there are further questions, `join the " -"Flower Slack `_ and use the channel " -"``#questions``. You can also `participate in Flower Discuss " -"`_ where you can find us answering questions," -" or share and learn from others about migrating to Flower Next." -msgstr "" +"Some official `Flower code examples `_ are " +"already updated to Flower Next so they can serve as a reference for using " +"the Flower Next API. If there are further questions, `join the Flower Slack " +"`_ and use the channel ``#questions``. You " +"can also `participate in Flower Discuss `_ where " +"you can find us answering questions, or share and learn from others about " +"migrating to Flower Next." +msgstr "" +"일부 공식 ``Flower 코드 예제 `_는 이미 플라" +"워 넥스트에 업데이트되어 있으므로 플라워 넥스트 API를 사용하는 데 참고할 수 " +"있습니다. 더 궁금한 점이 있다면 ``플라워 슬랙 `_에 가입하고 ``#questions`` 채널을 이용하세요. 또한, ``Flower Discuss " +"`_에 참여하여 질문에 대한 답변을 확인하거나 다른 " +"사람들과 Flower Next로의 이동에 대해 공유하고 배울 수 있습니다." #: ../../source/how-to-upgrade-to-flower-next.rst:325 msgid "Important" -msgstr "" +msgstr "중요" #: ../../source/how-to-upgrade-to-flower-next.rst:328 msgid "" @@ -6174,322 +7535,399 @@ msgid "" "periodically updating this guide. Please feel free to share any feedback " "with us!" msgstr "" +"Flower Next는 빠른 속도로 지속적으로 개선되고 있으므로 이 가이드는 주기적으" +"로 업데이트될 예정입니다. 피드백이 있으면 언제든지 공유해 주세요!" #: ../../source/how-to-upgrade-to-flower-next.rst:334 msgid "Happy migrating! 🚀" -msgstr "" +msgstr "행복한 마이그레이션! 🚀" #: ../../source/how-to-use-built-in-mods.rst:2 msgid "Use Built-in Mods" -msgstr "" +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.**" +"**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``." +"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 "" +"이 튜토리얼에서는 내장 모드를 활용하여 ``ClientApp``의 동작을 보강하는 방법" +"을 배우겠습니다. Mods(Modifiers라고도 함)를 사용하면 ``ClientApp``에서 작업" +"이 처리되기 전과 후에 작업을 수행할 수 있습니다." #: ../../source/how-to-use-built-in-mods.rst:9 msgid "What are Mods?" -msgstr "" +msgstr "Mods란 무엇인가요?" #: ../../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:" +"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 "" +"Mod는 ``ClientApp``을 감싸는 콜러블입니다. 들어오는 ``Message``와 그 결과로 " +"나가는 ``Message``를 조작하거나 검사할 수 있습니다. ``Mod``의 시그니처는 다음" +"과 같습니다:" #: ../../source/how-to-use-built-in-mods.rst:18 msgid "A typical mod function might look something like this:" -msgstr "" +msgstr "일반적인 mod 함수는 다음과 같은 모습일 수 있습니다:" #: ../../source/how-to-use-built-in-mods.rst:31 msgid "Using Mods" -msgstr "" +msgstr "Mods 사용" #: ../../source/how-to-use-built-in-mods.rst:33 msgid "To use mods in your ``ClientApp``, you can follow these steps:" -msgstr "" +msgstr "``ClientApp``에서 mods를 사용하려면 다음 단계를 따르세요:" #: ../../source/how-to-use-built-in-mods.rst:36 msgid "1. Import the required mods" -msgstr "" +msgstr "1. 필요한 mods를 가져옵니다" #: ../../source/how-to-use-built-in-mods.rst:38 msgid "First, import the built-in mod you intend to use:" -msgstr "" +msgstr "먼저 사용하려는 기본 제공 mod를 가져옵니다:" #: ../../source/how-to-use-built-in-mods.rst:46 msgid "2. Define your client function" -msgstr "" +msgstr "2. 클라이언트 기능 정의" #: ../../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 "" +msgstr "mod(s)로 래핑할 클라이언트 함수('``client_fn``)를 정의합니다:" #: ../../source/how-to-use-built-in-mods.rst:57 msgid "3. Create the ``ClientApp`` with mods" -msgstr "" +msgstr "3. mods로 ``ClientApp``을 생성합니다" #: ../../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 "" +"``ClientApp``을 생성하고 mods를 ``mods`` argument에 목록으로 전달합니다. mods" +"를 제공하는 순서가 중요합니다:" #: ../../source/how-to-use-built-in-mods.rst:72 msgid "Order of execution" -msgstr "" +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 "" +msgstr "``ClientApp``이 실행되면 목록에 제공된 순서대로 모드가 실행됩니다:" #: ../../source/how-to-use-built-in-mods.rst:76 msgid "``example_mod_1`` (outermost mod)" -msgstr "" +msgstr "``example_mod_1``(가장 바깥쪽 mod)" #: ../../source/how-to-use-built-in-mods.rst:77 msgid "``example_mod_2`` (next mod)" -msgstr "" +msgstr "``example_mod_2`` (다음 mod)" #: ../../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 "" +"Message handler(들어오는 ``Message``를 처리하고 나가는 ``Message``를 반환하" +"는 핵심 함수)" #: ../../source/how-to-use-built-in-mods.rst:79 msgid "``example_mod_2`` (on the way back)" -msgstr "" +msgstr "``example_mod_2``(돌아가는 방법)" #: ../../source/how-to-use-built-in-mods.rst:80 msgid "``example_mod_1`` (outermost mod on the way back)" -msgstr "" +msgstr "``example_mod_1``(돌아가는 방법에 가장 바깥쪽 모드)" #: ../../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." +"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 "" +"각 mod는 다음 mod로 전달하기 전에 들어오는 ``Message``를 검사하고 수정할 기회" +"가 있으며, 스택 위로 반환하기 전에 나가는 ``Message``도 마찬가지로 검사하고 " +"수정할 수 있습니다." #: ../../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." +"enhance your ``ClientApp``'s functionality. Remember that the order of mods " +"is crucial and affects how the input and output are processed." msgstr "" +"이 가이드를 따라 mods를 효과적으로 사용하여 ``ClientApp``의 기능을 향상시키" +"는 방법을 배웠습니다. mods 순서는 매우 중요하며 입력과 출력이 처리되는 방식" +"에 영향을 미친다는 점을 기억하세요." #: ../../source/how-to-use-built-in-mods.rst:89 msgid "Enjoy building a more robust and flexible ``ClientApp`` with mods!" -msgstr "" +msgstr "Mods를 통해 더욱 강력하고 유연한 ``ClientApp``을 구축해 보세요!" #: ../../source/how-to-use-differential-privacy.rst:2 msgid "Use Differential Privacy" -msgstr "" +msgstr "차분 개인정보 보호 사용" #: ../../source/how-to-use-differential-privacy.rst:3 msgid "" -"This guide explains how you can utilize differential privacy in the " -"Flower framework. If you are not yet familiar with differential privacy, " -"you can refer to :doc:`explanation-differential-privacy`." +"This guide explains how you can utilize differential privacy in the Flower " +"framework. If you are not yet familiar with differential privacy, you can " +"refer to :doc:`explanation-differential-privacy`." msgstr "" +"이 가이드에서는 Flower 프레임워크에서 차분 개인정보 보호 기능을 활용하는 방법" +"을 설명합니다. 차분 개인정보 보호에 대해 아직 익숙하지 않은 경우 :doc:" +"`explanation-differential-privacy`를 참조하세요." #: ../../source/how-to-use-differential-privacy.rst:7 msgid "" "Differential Privacy in Flower is in a preview phase. If you plan to use " -"these features in a production environment with sensitive data, feel free" -" contact us to discuss your requirements and to receive guidance on how " -"to best use these features." +"these features in a production environment with sensitive data, feel free " +"contact us to discuss your requirements and to receive guidance on how to " +"best use these features." msgstr "" +"Flower의 차분 개인정보 보호는 현재 프리뷰 단계에 있습니다. 민감한 데이터가 있" +"는 프로덕션 환경에서 이러한 기능을 사용할 계획이라면 언제든지 문의하여 요구 " +"사항을 논의하고 이러한 기능을 가장 잘 사용하는 방법에 대한 안내를 받으세요." #: ../../source/how-to-use-differential-privacy.rst:12 msgid "" -"This approach consists of two seprate phases: clipping of the updates and" -" adding noise to the aggregated model. For the clipping phase, Flower " -"framework has made it possible to decide whether to perform clipping on " -"the server side or the client side." +"This approach consists of two seprate phases: clipping of the updates and " +"adding noise to the aggregated model. For the clipping phase, Flower " +"framework has made it possible to decide whether to perform clipping on the " +"server side or the client side." msgstr "" +"이 접근 방식은 업데이트 클리핑과 집계된 모델에 노이즈 추가라는 두 가지 단계" +"로 구성됩니다. 클리핑 단계의 경우, Flower 프레임워크는 클리핑을 서버 측에서 " +"수행할지 클라이언트 측에서 수행할지 결정할 수 있도록 했습니다." #: ../../source/how-to-use-differential-privacy.rst:15 msgid "" "**Server-side Clipping**: This approach has the advantage of the server " "enforcing uniform clipping across all clients' updates and reducing the " "communication overhead for clipping values. However, it also has the " -"disadvantage of increasing the computational load on the server due to " -"the need to perform the clipping operation for all clients." +"disadvantage of increasing the computational load on the server due to the " +"need to perform the clipping operation for all clients." msgstr "" +"**Server-side Clipping**: 이 방식은 서버가 모든 클라이언트의 업데이트에 대해 " +"균일한 클리핑을 적용하고 클리핑 값에 대한 통신 오버헤드를 줄일 수 있다는 장점" +"이 있습니다. 하지만 모든 클라이언트에 대해 클리핑 작업을 수행해야 하기 때문" +"에 서버의 계산 부하가 증가한다는 단점도 있습니다." #: ../../source/how-to-use-differential-privacy.rst:16 msgid "" -"**Client-side Clipping**: This approach has the advantage of reducing the" -" computational overhead on the server. However, it also has the " -"disadvantage of lacking centralized control, as the server has less " -"control over the clipping process." +"**Client-side Clipping**: This approach has the advantage of reducing the " +"computational overhead on the server. However, it also has the disadvantage " +"of lacking centralized control, as the server has less control over the " +"clipping process." msgstr "" +"**Client-side Clipping**: 이 방식은 서버의 계산 오버헤드를 줄일 수 있다는 장" +"점이 있습니다. 하지만 서버가 클리핑 프로세스에 대한 통제력이 떨어지기 때문에 " +"centralized 제어가 부족하다는 단점도 있습니다." #: ../../source/how-to-use-differential-privacy.rst:21 msgid "Server-side Clipping" -msgstr "" +msgstr "서버 측 클리핑" #: ../../source/how-to-use-differential-privacy.rst:22 msgid "" "For central DP with server-side clipping, there are two :code:`Strategy` " "classes that act as wrappers around the actual :code:`Strategy` instance " -"(for example, :code:`FedAvg`). The two wrapper classes are " -":code:`DifferentialPrivacyServerSideFixedClipping` and " -":code:`DifferentialPrivacyServerSideAdaptiveClipping` for fixed and " -"adaptive clipping." +"(for example, :code:`FedAvg`). The two wrapper classes are :code:" +"`DifferentialPrivacyServerSideFixedClipping` and :code:" +"`DifferentialPrivacyServerSideAdaptiveClipping` for fixed and adaptive " +"clipping." msgstr "" +"서버 측 클리핑이 있는 중앙 DP의 경우, 실제 :code:`Strategy` 인스턴스를 감싸" +"는 래퍼 역할을 하는 두 개의 :code:`Strategy` 클래스가 있습니다(예: :code:" +"`FedAvg`). 두 개의 래퍼 클래스는 고정 및 적응형 클리핑을 위한 :code:" +"`DifferentialPrivacyServerSideFixedClipping`과 :code:" +"`DifferentialPrivacyServerSideAdaptiveClipping`입니다." #: ../../source/how-to-use-differential-privacy.rst:-1 msgid "server side clipping" -msgstr "" +msgstr "서버 측 클리핑" #: ../../source/how-to-use-differential-privacy.rst:31 msgid "" -"The code sample below enables the :code:`FedAvg` strategy to use server-" -"side fixed clipping using the " -":code:`DifferentialPrivacyServerSideFixedClipping` wrapper class. The " -"same approach can be used with " -":code:`DifferentialPrivacyServerSideAdaptiveClipping` by adjusting the " +"The code sample below enables the :code:`FedAvg` strategy to use server-side " +"fixed clipping using the :code:`DifferentialPrivacyServerSideFixedClipping` " +"wrapper class. The same approach can be used with :code:" +"`DifferentialPrivacyServerSideAdaptiveClipping` by adjusting the " "corresponding input parameters." msgstr "" +"아래 코드 샘플은 :code:`FedAvg` 전략이 :code:" +"`DifferentialPrivacyServerSideFixedClipping` 래퍼 클래스를 사용하여 서버 측 " +"고정 클리핑을 사용할 수 있도록 합니다. 해당 입력 매개변수를 조정하여 :code:" +"`DifferentialPrivacyServerSideAdaptiveClipping`과 동일한 접근 방식을 사용할 " +"수 있습니다." #: ../../source/how-to-use-differential-privacy.rst:52 msgid "Client-side Clipping" -msgstr "" +msgstr "클라이언트 측 클리핑" #: ../../source/how-to-use-differential-privacy.rst:53 msgid "" "For central DP with client-side clipping, the server sends the clipping " -"value to selected clients on each round. Clients can use existing Flower " -":code:`Mods` to perform the clipping. Two mods are available for fixed " -"and adaptive client-side clipping: :code:`fixedclipping_mod` and " -":code:`adaptiveclipping_mod` with corresponding server-side wrappers " -":code:`DifferentialPrivacyClientSideFixedClipping` and " -":code:`DifferentialPrivacyClientSideAdaptiveClipping`." -msgstr "" +"value to selected clients on each round. Clients can use existing Flower :" +"code:`Mods` to perform the clipping. Two mods are available for fixed and " +"adaptive client-side clipping: :code:`fixedclipping_mod` and :code:" +"`adaptiveclipping_mod` with corresponding server-side wrappers :code:" +"`DifferentialPrivacyClientSideFixedClipping` and :code:" +"`DifferentialPrivacyClientSideAdaptiveClipping`." +msgstr "" +"클라이언트 측 클리핑이 있는 중앙 DP의 경우 서버는 각 라운드마다 선택한 클라이" +"언트에 클리핑 값을 보냅니다. 클라이언트는 기존 Flower :code:`Mods`를 사용하" +"여 클리핑을 수행할 수 있습니다. 고정 및 적응형 클라이언트 측 클리핑에는 두 가" +"지 모드를 사용할 수 있습니다: :code:`fixedclipping_mod` 및 :code:" +"`adaptiveclipping_mod`와 해당 서버 측 래퍼 :code:" +"`DifferentialPrivacyClientSideFixedClipping` 및 :code:" +"`DifferentialPrivacyClientSideAdaptiveClipping`이 있습니다." #: ../../source/how-to-use-differential-privacy.rst:-1 msgid "client side clipping" -msgstr "" +msgstr "클라이언트 측 클리핑" #: ../../source/how-to-use-differential-privacy.rst:63 msgid "" "The code sample below enables the :code:`FedAvg` strategy to use " -"differential privacy with client-side fixed clipping using both the " -":code:`DifferentialPrivacyClientSideFixedClipping` wrapper class and, on " -"the client, :code:`fixedclipping_mod`:" +"differential privacy with client-side fixed clipping using both the :code:" +"`DifferentialPrivacyClientSideFixedClipping` wrapper class and, on the " +"client, :code:`fixedclipping_mod`:" msgstr "" +"아래 코드 샘플은 :code:`FedAvg` 전략이 클라이언트 측 고정 클리핑과 함께 차분 " +"프라이버시를 사용할 수 있도록 :code:" +"`DifferentialPrivacyClientSideFixedClipping` 래퍼 클래스와 클라이언트에서 :" +"code:`fixedclipping_mod`를 모두 사용하도록 합니다:" #: ../../source/how-to-use-differential-privacy.rst:80 msgid "" -"In addition to the server-side strategy wrapper, the :code:`ClientApp` " -"needs to configure the matching :code:`fixedclipping_mod` to perform the " -"client-side clipping:" +"In addition to the server-side strategy wrapper, the :code:`ClientApp` needs " +"to configure the matching :code:`fixedclipping_mod` to perform the client-" +"side clipping:" msgstr "" +"서버 측 전략 래퍼 외에도 클라이언트 측 클리핑을 수행하려면 :code:`ClientApp`" +"이 일치하는 :code:`fixedclipping_mod`를 구성해야 합니다:" #: ../../source/how-to-use-differential-privacy.rst:97 msgid "" -"To utilize local differential privacy (DP) and add noise to the client " -"model parameters before transmitting them to the server in Flower, you " -"can use the `LocalDpMod`. The following hyperparameters need to be set: " -"clipping norm value, sensitivity, epsilon, and delta." +"To utilize local differential privacy (DP) and add noise to the client model " +"parameters before transmitting them to the server in Flower, you can use the " +"`LocalDpMod`. The following hyperparameters need to be set: clipping norm " +"value, sensitivity, epsilon, and delta." msgstr "" +"로컬 차분 프라이버시(DP)를 활용하고 클라이언트 모델 파라미터를 서버로 전송하" +"기 전에 노이즈를 추가하려면 `LocalDpMod`를 사용하면 됩니다. 클리핑 노멀 값, " +"감도, 엡실론, 델타 등의 하이퍼파라미터를 설정해야 합니다." #: ../../source/how-to-use-differential-privacy.rst:-1 msgid "local DP mod" -msgstr "" +msgstr "로컬 DP mod" #: ../../source/how-to-use-differential-privacy.rst:104 msgid "Below is a code example that shows how to use :code:`LocalDpMod`:" -msgstr "" +msgstr "다음은 :code:`LocalDpMod`를 사용하는 방법을 보여주는 코드 예시입니다:" #: ../../source/how-to-use-differential-privacy.rst:122 msgid "" -"Please note that the order of mods, especially those that modify " -"parameters, is important when using multiple modifiers. Typically, " -"differential privacy (DP) modifiers should be the last to operate on " -"parameters." +"Please note that the order of mods, especially those that modify parameters, " +"is important when using multiple modifiers. Typically, differential privacy " +"(DP) modifiers should be the last to operate on parameters." msgstr "" +"여러 개의 수정자를 사용할 때는 수정자, 특히 매개변수를 수정하는 수정자의 순서" +"가 중요하다는 점에 유의하세요. 일반적으로 차분 프라이버시(DP) 수정자는 매개변" +"수에서 가장 마지막에 작동해야 합니다." #: ../../source/how-to-use-differential-privacy.rst:125 msgid "Local Training using Privacy Engines" -msgstr "" +msgstr "Privacy Engines을 사용한 로컬 훈련" #: ../../source/how-to-use-differential-privacy.rst:126 msgid "" -"For ensuring data instance-level privacy during local model training on " -"the client side, consider leveraging privacy engines such as Opacus and " -"TensorFlow Privacy. For examples of using Flower with these engines, " -"please refer to the Flower examples directory (`Opacus " -"`_, `Tensorflow" -" Privacy `_)." +"For ensuring data instance-level privacy during local model training on the " +"client side, consider leveraging privacy engines such as Opacus and " +"TensorFlow Privacy. For examples of using Flower with these engines, please " +"refer to the Flower examples directory (`Opacus `_, `Tensorflow Privacy `_)." msgstr "" +"클라이언트 측에서 로컬 모델을 훈련하는 동안 데이터 인스턴스 수준의 개인 정보 " +"보호를 보장하려면 Opacus 및 TensorFlow Privacy와 같은 개인 정보 보호 엔진을 " +"활용하는 것을 고려하세요. 이러한 엔진과 함께 Flower를 사용하는 예제는 Flower " +"examples directory (`Opacus `_, `Tensorflow Privacy `_)를 참조하세요." #: ../../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` abstraction를 통해 학습 과정을 완전히 사용자 정의" +"할 수 있습니다. 핵심 프레임워크에는 여러 가지 기본 제공 전략이 제공됩니다." #: ../../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 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:" +"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 "" @@ -6497,118 +7935,138 @@ 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 arbitrary configuration values :code:`client.fit`" -" and :code:`client.evaluate` functions during each round of federated " -"learning." -msgstr "" +"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 " +"arbitrary configuration values :code:`client.fit` and :code:`client." +"evaluate` functions during each round of federated learning." +msgstr "" +"서버는 매 라운드마다 새로운 설정 값을 클라이언트에 전달하기 위해 " +":code:`on_fit_config_fn`에 함수를 제공할 수 있습니다. 제공된 함수는 전략에 " +"의해 호출되며 클라이언트에 전송될 구성 키 값 쌍의 dictionary를 반환해야 " +"합니다. 연합 학습의 각 라운드 동안 임의의 구성 값 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`이 반환한 dictionary를 받습니다." #: ../../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:`client.evaluate()`로 전송되는 구" +"성을 사용자 지정하는 :code:`on_evaluate_config_fn`도 있습니다" #: ../../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`." +"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 "" +"완전한 사용자 지정 전략을 작성하는 것은 조금 더 복잡하지만 유연성이 가장 뛰어" +"납니다. 자세한 내용은 `Implementing Strategies `_ 가이드를 참조하세요." #: ../../source/index.rst:34 msgid "Tutorial" -msgstr "" +msgstr "튜토리얼" #: ../../source/index.rst:44 msgid "Quickstart tutorials" -msgstr "" +msgstr "빠른 시작 튜토리얼" #: ../../source/index.rst:74 ../../source/index.rst:78 msgid "How-to guides" -msgstr "" +msgstr "사용 방법 가이드" #: ../../source/index.rst:99 msgid "Legacy example guides" -msgstr "" +msgstr "레거시 예제 가이드" #: ../../source/index.rst:108 ../../source/index.rst:112 msgid "Explanations" -msgstr "" +msgstr "설명" #: None:-1 msgid "API reference" -msgstr "" +msgstr "API 참조" #: ../../source/index.rst:137 msgid "Reference docs" -msgstr "" +msgstr "참조 문서" #: ../../source/index.rst:153 msgid "Contributor tutorials" -msgstr "" +msgstr "기여자 튜토리얼" #: ../../source/index.rst:160 msgid "Contributor how-to guides" -msgstr "" +msgstr "기여자 사용법 가이드" #: ../../source/index.rst:172 msgid "Contributor explanations" -msgstr "" +msgstr "기여자 설명" #: ../../source/index.rst:178 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 "연합 학습을 위한 Python 개발을 쉽게 할 수 있는 주요 Flower 프레임워크의 " +"설명서를 확인하세요." #: ../../source/index.rst:2 msgid "Flower Framework Documentation" -msgstr "" +msgstr "플라워 프레임워크 문서" #: ../../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 "" @@ -6616,158 +8074,175 @@ 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:61 msgid "" -"QUICKSTART TUTORIALS: :doc:`PyTorch ` | " -":doc:`TensorFlow ` | :doc:`🤗 Transformers" -" ` | :doc:`JAX ` | :doc:`Pandas ` | :doc:`fastai " -"` | :doc:`PyTorch Lightning ` | :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:`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:`scikit-learn ` | :doc:" +"`XGBoost ` | :doc:`Android ` | :doc:`iOS `" #: ../../source/index.rst:63 msgid "We also made video tutorials for PyTorch:" -msgstr "" +msgstr "파이토치용 동영상 튜토리얼도 만들었습니다:" #: ../../source/index.rst:68 msgid "And TensorFlow:" -msgstr "" +msgstr "그리고 TensorFlow도:" #: ../../source/index.rst:76 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:110 msgid "" "Understanding-oriented concept guides explain and discuss key topics and " "underlying ideas behind Flower and collaborative AI." msgstr "" +"이해 중심의 개념 가이드에서는 Flower와 협업 AI의 주요 주제와 기본 아이디어를 " +"설명하고 토론합니다." #: ../../source/index.rst:120 msgid "References" -msgstr "" +msgstr "참조" #: ../../source/index.rst:122 msgid "Information-oriented API reference and other reference material." -msgstr "" +msgstr "정보 지향 API 참조 및 기타 참고 자료." #: ../../source/index.rst:131::1 msgid ":py:obj:`flwr `\\" -msgstr "" +msgstr ":py:obj:`flwr `\\" #: ../../source/index.rst:131::1 flwr:1 of msgid "Flower main package." -msgstr "" +msgstr "Flower 메인 패키지." #: ../../source/index.rst:148 msgid "Contributor docs" -msgstr "" +msgstr "기여자 문서" #: ../../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 msgid "Flower CLI reference" -msgstr "" +msgstr "Flower CLI 참조" #: ../../source/ref-api-cli.rst:7 msgid "flower-simulation" -msgstr "" +msgstr "flower 시뮬레이션" #: ../../source/ref-api-cli.rst:17 msgid "flower-superlink" -msgstr "" +msgstr "flower 초연결" #: ../../source/ref-api-cli.rst:27 msgid "flower-client-app" -msgstr "" +msgstr "flower 클라이언트 앱" #: ../../source/ref-api-cli.rst:37 msgid "flower-server-app" -msgstr "" +msgstr "flower 서버 프로그램" #: ../../source/ref-api/flwr.rst:2 msgid "flwr" -msgstr "" +msgstr "flwr" #: ../../source/ref-api/flwr.client.rst:45 ../../source/ref-api/flwr.rst:25 #: ../../source/ref-api/flwr.server.rst:49 msgid "Modules" -msgstr "" +msgstr "Modules" #: ../../source/ref-api/flwr.rst:35::1 msgid ":py:obj:`flwr.client `\\" -msgstr "" +msgstr ":py:obj:`flwr.client `\\" #: ../../source/ref-api/flwr.rst:35::1 flwr.client:1 of msgid "Flower client." -msgstr "" +msgstr "Flower 클라이언트." #: ../../source/ref-api/flwr.rst:35::1 msgid ":py:obj:`flwr.common `\\" -msgstr "" +msgstr ":py:obj:`flwr.common `\\" #: ../../source/ref-api/flwr.rst:35::1 flwr.common:1 of msgid "Common components shared between server and client." -msgstr "" +msgstr "서버와 클라이언트 간에 공유되는 공통 구성 요소입니다." #: ../../source/ref-api/flwr.rst:35::1 msgid ":py:obj:`flwr.server `\\" -msgstr "" +msgstr ":py:obj:`flwr.server `\\" #: ../../source/ref-api/flwr.rst:35::1 #: ../../source/ref-api/flwr.server.rst:38::1 flwr.server:1 #: flwr.server.server.Server:1 of msgid "Flower server." -msgstr "" +msgstr "Flower 서버." #: ../../source/ref-api/flwr.rst:35::1 msgid ":py:obj:`flwr.simulation `\\" -msgstr "" +msgstr ":py:obj:`flwr.simulation `\\" #: ../../source/ref-api/flwr.rst:35::1 flwr.simulation:1 of msgid "Flower simulation." -msgstr "" +msgstr "Flower 시뮬레이션." #: ../../source/ref-api/flwr.client.rst:2 msgid "client" -msgstr "" +msgstr "클라이언트" #: ../../source/ref-api/flwr.client.mod.rst:13 #: ../../source/ref-api/flwr.client.rst:13 @@ -6775,47 +8250,51 @@ msgstr "" #: ../../source/ref-api/flwr.server.rst:13 #: ../../source/ref-api/flwr.simulation.rst:13 msgid "Functions" -msgstr "" +msgstr "함수" #: ../../source/ref-api/flwr.client.rst:25::1 msgid ":py:obj:`run_client_app `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`run_client_app `\\ \\(\\)" #: ../../source/ref-api/flwr.client.rst:25::1 #: flwr.client.supernode.app.run_client_app:1 of msgid "Run Flower client app." -msgstr "" +msgstr "Flower 클라이언트 앱을 실행합니다." #: ../../source/ref-api/flwr.client.rst:25::1 msgid ":py:obj:`run_supernode `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`run_supernode `\\ \\(\\)" #: ../../source/ref-api/flwr.client.rst:25::1 #: flwr.client.supernode.app.run_supernode:1 of msgid "Run Flower SuperNode." -msgstr "" +msgstr "Flower SuperNode를 실행합니다." #: ../../source/ref-api/flwr.client.rst:25::1 msgid "" ":py:obj:`start_client `\\ \\(\\*\\, " "server\\_address\\[\\, client\\_fn\\, ...\\]\\)" msgstr "" +":py:obj:`start_client `\\ \\(\\*\\, " +"server\\_address\\[\\, client\\_fn\\, ...\\]\\)" #: ../../source/ref-api/flwr.client.rst:25::1 #: flwr.client.app.start_client:1 of msgid "Start a Flower client node which connects to a Flower server." -msgstr "" +msgstr "Flower 서버에 연결되는 Flower 클라이언트 노드를 시작합니다." #: ../../source/ref-api/flwr.client.rst:25::1 msgid "" -":py:obj:`start_numpy_client `\\ \\(\\*\\," -" server\\_address\\, client\\)" +":py:obj:`start_numpy_client `\\ \\(\\*\\, " +"server\\_address\\, client\\)" msgstr "" +":py:obj:`start_numpy_client `\\ \\(\\*\\, " +"server\\_address\\, client\\)" #: ../../source/ref-api/flwr.client.rst:25::1 #: flwr.client.app.start_numpy_client:1 of msgid "Start a Flower NumPyClient which connects to a gRPC server." -msgstr "" +msgstr "gRPC 서버에 연결되는 Flower NumPyClient를 시작합니다." #: ../../source/ref-api/flwr.client.mod.rst:30 #: ../../source/ref-api/flwr.client.rst:27 @@ -6824,51 +8303,51 @@ msgstr "" #: ../../source/ref-api/flwr.server.strategy.rst:17 #: ../../source/ref-api/flwr.server.workflow.rst:17 msgid "Classes" -msgstr "" +msgstr "클래스" #: ../../source/ref-api/flwr.client.rst:34::1 msgid ":py:obj:`Client `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`Client `\\ \\(\\)" #: ../../source/ref-api/flwr.client.rst:34::1 #: flwr.client.client.Client:1 of msgid "Abstract base class for Flower clients." -msgstr "" +msgstr "Flower 클라이언트를 위한 추상 베이스 클래스입니다." #: ../../source/ref-api/flwr.client.rst:34::1 msgid "" -":py:obj:`ClientApp `\\ \\(\\[client\\_fn\\, " -"mods\\]\\)" +":py:obj:`ClientApp `\\ \\(\\[client\\_fn\\, mods\\]\\)" msgstr "" +":py:obj:`ClientApp `\\ \\(\\[client\\_fn\\, mods\\]\\)" #: ../../source/ref-api/flwr.client.rst:34::1 #: flwr.client.client_app.ClientApp:1 of msgid "Flower ClientApp." -msgstr "" +msgstr "Flower ClientApp." #: ../../source/ref-api/flwr.client.rst:34::1 msgid ":py:obj:`NumPyClient `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`NumPyClient `\\ \\(\\)" #: ../../source/ref-api/flwr.client.rst:34::1 #: flwr.client.numpy_client.NumPyClient:1 of msgid "Abstract base class for Flower clients using NumPy." -msgstr "" +msgstr "NumPy를 사용하는 Flower 클라이언트를 위한 추상 베이스 클래스입니다." #: ../../source/ref-api/flwr.client.rst:52::1 msgid ":py:obj:`flwr.client.mod `\\" -msgstr "" +msgstr ":py:obj:`flwr.client.mod `\\" #: ../../source/ref-api/flwr.client.rst:52::1 flwr.client.mod:1 of msgid "Flower Built-in Mods." -msgstr "" +msgstr "Flower 내장 모드." #: flwr.client.client.Client:1 flwr.client.numpy_client.NumPyClient:1 #: flwr.server.client_manager.ClientManager:1 #: flwr.server.driver.driver.Driver:1 flwr.server.strategy.strategy.Strategy:1 #: of msgid "Bases: :py:class:`~abc.ABC`" -msgstr "" +msgstr "Bases: :py:class:`~abc.ABC`" #: ../../source/ref-api/flwr.client.Client.rst:15 #: ../../source/ref-api/flwr.client.ClientApp.rst:15 @@ -6936,78 +8415,82 @@ msgstr "" #: ../../source/ref-api/flwr.server.workflow.SecAggPlusWorkflow.rst:15 #: ../../source/ref-api/flwr.server.workflow.SecAggWorkflow.rst:15 msgid "Methods" -msgstr "" +msgstr "메소드" #: ../../source/ref-api/flwr.client.Client.rst:44::1 msgid ":py:obj:`evaluate `\\ \\(ins\\)" -msgstr "" +msgstr ":py:obj:`evaluate `\\ \\(ins\\)" #: ../../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 "" +msgstr "로컬로 보유한 데이터 세트를 사용하여 제공된 매개변수를 평가합니다." #: ../../source/ref-api/flwr.client.Client.rst:44::1 msgid ":py:obj:`fit `\\ \\(ins\\)" -msgstr "" +msgstr ":py:obj:`fit `\\ \\(ins\\)" #: ../../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 "" +msgstr "로컬로 보유한 데이터 세트를 사용하여 제공된 매개변수를 구체화합니다." #: ../../source/ref-api/flwr.client.Client.rst:44::1 msgid ":py:obj:`get_context `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`get_context `\\ \\(\\)" #: ../../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 "" +msgstr "이 클라이언트에서 실행 컨텍스트를 가져옵니다." #: ../../source/ref-api/flwr.client.Client.rst:44::1 -msgid ":py:obj:`get_parameters `\\ \\(ins\\)" +msgid "" +":py:obj:`get_parameters `\\ \\(ins\\)" msgstr "" +":py:obj:`get_parameters `\\ \\(ins\\)" #: ../../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 "" +msgstr "현재 로컬 모델 파라미터를 반환합니다." #: ../../source/ref-api/flwr.client.Client.rst:44::1 -msgid ":py:obj:`get_properties `\\ \\(ins\\)" +msgid "" +":py:obj:`get_properties `\\ \\(ins\\)" msgstr "" +":py:obj:`get_properties `\\ \\(ins\\)" #: ../../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 "" +msgstr "클라이언트의 속성 집합을 반환합니다." #: ../../source/ref-api/flwr.client.Client.rst:44::1 msgid ":py:obj:`set_context `\\ \\(context\\)" -msgstr "" +msgstr ":py:obj:`set_context `\\ \\(context\\)" #: ../../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 "" +msgstr "이 클라이언트에 실행 컨텍스트를 적용합니다." #: ../../source/ref-api/flwr.client.Client.rst:44::1 msgid ":py:obj:`to_client `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`to_client `\\ \\(\\)" #: ../../source/ref-api/flwr.client.Client.rst:44::1 #: flwr.client.client.Client.to_client:1 of msgid "Return client (itself)." -msgstr "" +msgstr "클라이언트(자체)를 반환합니다." #: ../../source/ref-api/flwr.client.Client.rst:46 #: ../../source/ref-api/flwr.client.NumPyClient.rst:46 @@ -7038,11 +8521,11 @@ msgstr "" #: ../../source/ref-api/flwr.server.LegacyContext.rst:25 #: ../../source/ref-api/flwr.server.ServerConfig.rst:25 msgid "Attributes" -msgstr "" +msgstr "속성" #: flwr.client.client.Client.evaluate:1::1 of msgid ":py:obj:`context `\\" -msgstr "" +msgstr ":py:obj:`context `\\" #: ../../source/ref-api/flwr.common.Parameters.rst:2 #: flwr.client.app.start_client flwr.client.app.start_numpy_client @@ -7092,14 +8575,16 @@ msgstr "" #: flwr.simulation.app.start_simulation #: flwr.simulation.run_simulation.run_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 @@ -7128,13 +8613,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 @@ -7161,44 +8648,49 @@ msgstr "" #: flwr.server.strategy.strategy.Strategy.initialize_parameters #: flwr.simulation.app.start_simulation of msgid "Return type" -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." +"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 "" +"구성 값 dictionary이 포함된 서버에서 받은 매개변수 가져오기 명령어입니다." #: flwr.client.client.Client.get_parameters:7 of msgid "The current local model parameters." -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 "구성 값 dictionary이 포함된 서버로부터 받은 속성 가져오기 명령입니다." #: flwr.client.client.Client.get_properties:7 of msgid "The current client properties." -msgstr "" +msgstr "현재 클라이언트 속성입니다." #: ../../source/ref-api/flwr.client.ClientApp.rst:2 msgid "ClientApp" -msgstr "" +msgstr "클라이언트앱" #: flwr.client.client_app.ClientApp:1 flwr.client.mod.localdp_mod.LocalDpMod:1 #: flwr.common.constant.MessageType:1 flwr.common.constant.MessageTypeLegacy:1 @@ -7219,7 +8711,7 @@ msgstr "" #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow:1 #: of msgid "Bases: :py:class:`object`" -msgstr "" +msgstr "Bases: :py:class:`object`" #: flwr.client.app.start_client:41 flwr.client.app.start_numpy_client:36 #: flwr.client.client_app.ClientApp:4 @@ -7234,112 +8726,127 @@ msgstr "" #: flwr.server.strategy.dp_fixed_clipping.DifferentialPrivacyServerSideFixedClipping:14 #: of msgid "Examples" -msgstr "" +msgstr "예시" #: flwr.client.client_app.ClientApp:5 of msgid "" "Assuming a typical `Client` implementation named `FlowerClient`, you can " "wrap it in a `ClientApp` as follows:" msgstr "" +"일반적인 `Client` 구현의 이름이 `FlowerClient`라고 가정하면, 다음과 같이 " +"`ClientApp`으로 래핑할 수 있습니다:" #: flwr.client.client_app.ClientApp:16 of msgid "" -"If the above code is in a Python module called `client`, it can be " -"started as follows:" +"If the above code is in a Python module called `client`, it can be started " +"as follows:" msgstr "" +"위의 코드가 'client'라는 Python 모듈에 있는 경우 다음과 같이 시작할 수 있습니" +"다:" #: flwr.client.client_app.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`." +"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 "" +"이 `client:app` 예제에서 `client`는 이전 코드가 있는 Python 모듈 `client.py`" +"를 가리키고 `app`는 `ClientApp` 유형의 객체를 가리키는 전역 속성 `app`을 가리" +"킵니다." #: flwr.client.client_app.ClientApp.evaluate:1::1 of msgid ":py:obj:`evaluate `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`evaluate `\\ \\(\\)" #: flwr.client.client_app.ClientApp.evaluate:1 #: flwr.client.client_app.ClientApp.evaluate:1::1 of msgid "Return a decorator that registers the evaluate fn with the client app." -msgstr "" +msgstr "클라이언트 앱에 평가함수를 등록하는 데코레이터를 반환합니다." #: flwr.client.client_app.ClientApp.evaluate:1::1 of msgid ":py:obj:`query `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`query `\\ \\(\\)" #: flwr.client.client_app.ClientApp.evaluate:1::1 #: flwr.client.client_app.ClientApp.query:1 of msgid "Return a decorator that registers the query fn with the client app." -msgstr "" +msgstr "클라이언트 앱에 query fn을 등록하는 데코레이터를 반환합니다." #: flwr.client.client_app.ClientApp.evaluate:1::1 of msgid ":py:obj:`train `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`train `\\ \\(\\)" #: flwr.client.client_app.ClientApp.evaluate:1::1 #: flwr.client.client_app.ClientApp.train:1 of msgid "Return a decorator that registers the train fn with the client app." -msgstr "" +msgstr "클라이언트 앱에 train fn을 등록하는 데코레이터를 반환합니다." #: ../../source/ref-api/flwr.client.NumPyClient.rst:2 msgid "NumPyClient" -msgstr "" +msgstr "NumPyClient" #: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 msgid "" ":py:obj:`evaluate `\\ \\(parameters\\, " "config\\)" msgstr "" +":py:obj:`evaluate `\\ \\(parameters\\, " +"config\\)" #: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 -msgid ":py:obj:`fit `\\ \\(parameters\\, config\\)" +msgid "" +":py:obj:`fit `\\ \\(parameters\\, config\\)" msgstr "" +":py:obj:`fit `\\ \\(parameters\\, config\\)" #: ../../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 "" +msgstr "로컬로 보유한 데이터 세트를 사용하여 제공된 파라미터를 학습합니다." #: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 msgid ":py:obj:`get_context `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`get_context `\\ \\(\\)" #: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 msgid "" ":py:obj:`get_parameters `\\ " "\\(config\\)" msgstr "" +":py:obj:`get_parameters `\\ " +"\\(config\\)" #: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 msgid "" ":py:obj:`get_properties `\\ " "\\(config\\)" msgstr "" +":py:obj:`get_properties `\\ " +"\\(config\\)" #: ../../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 "" +msgstr "클라이언트의 속성 집합을 반환합니다." #: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 msgid "" -":py:obj:`set_context `\\ " -"\\(context\\)" +":py:obj:`set_context `\\ \\(context\\)" msgstr "" +":py:obj:`set_context `\\ \\(context\\)" #: ../../source/ref-api/flwr.client.NumPyClient.rst:44::1 msgid ":py:obj:`to_client `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`to_client `\\ \\(\\)" #: ../../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 "" +msgstr "객체를 클라이언트 유형으로 변환하고 반환합니다." #: flwr.client.numpy_client.NumPyClient.evaluate:1::1 of msgid ":py:obj:`context `\\" -msgstr "" +msgstr ":py:obj:`context `\\" #: flwr.client.numpy_client.NumPyClient.evaluate:3 #: flwr.client.numpy_client.NumPyClient.fit:3 @@ -7349,262 +8856,311 @@ 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]*) -- 임의의 문자열 키를 부울, 바이트, float, int 또는 " +"str 유형의 값에 매핑하는 dictionary입니다. 임의의 값을 서버에 다시 전달하는 " +"데 사용할 수 있습니다." #: 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 타입의 값에 매핑하는 dictionary입니다. 임의의 값을 서버에 다시 " +"전달하는 데 사용할 수 있습니다." #: 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 "" +"이전 반환 유형 형식(int, float, float)과 확장 형식(int, float, float, " +"Dict[str, Scalar])은 Flower 0.19부터 더 이상 사용되지 않으며 제거되었습니다." #: 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 " +"타입의 값에 매핑하는 dictionary입니다. 임의의 값을 서버에 다시 전달하는 데 사" +"용할 수 있습니다." #: 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 배열 목록으로 표시합니다." #: 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 타입의 " +"값에 매핑하는 dictionary입니다. 임의의 속성 값을 서버에 다시 전달하는 데 사용" +"할 수 있습니다." #: ../../source/ref-api/flwr.client.mod.rst:2 msgid "mod" -msgstr "" +msgstr "mod" #: ../../source/ref-api/flwr.client.mod.rst:28::1 msgid "" ":py:obj:`adaptiveclipping_mod `\\ " "\\(msg\\, ctxt\\, call\\_next\\)" msgstr "" +":py:obj:`adaptiveclipping_mod `\\ " +"\\(msg\\, ctxt\\, call\\_next\\)" #: ../../source/ref-api/flwr.client.mod.rst:28::1 #: flwr.client.mod.centraldp_mods.adaptiveclipping_mod:1 of msgid "Client-side adaptive clipping modifier." -msgstr "" +msgstr "클라이언트 측 적응형 클리핑 수정자." #: ../../source/ref-api/flwr.client.mod.rst:28::1 msgid "" -":py:obj:`fixedclipping_mod `\\ " -"\\(msg\\, ctxt\\, call\\_next\\)" +":py:obj:`fixedclipping_mod `\\ \\(msg\\, " +"ctxt\\, call\\_next\\)" msgstr "" +":py:obj:`fixedclipping_mod `\\ \\(msg\\, " +"ctxt\\, call\\_next\\)" #: ../../source/ref-api/flwr.client.mod.rst:28::1 #: flwr.client.mod.centraldp_mods.fixedclipping_mod:1 of msgid "Client-side fixed clipping modifier." -msgstr "" +msgstr "클라이언트 측 고정 클리핑 수정자." #: ../../source/ref-api/flwr.client.mod.rst:28::1 msgid ":py:obj:`make_ffn `\\ \\(ffn\\, mods\\)" -msgstr "" +msgstr ":py:obj:`make_ffn `\\ \\(ffn\\, mods\\)" #: ../../source/ref-api/flwr.client.mod.rst:28::1 #: flwr.client.mod.utils.make_ffn:1 of msgid "." -msgstr "" +msgstr "." #: ../../source/ref-api/flwr.client.mod.rst:28::1 msgid "" ":py:obj:`secagg_mod `\\ \\(msg\\, ctxt\\, " "call\\_next\\)" msgstr "" +":py:obj:`secagg_mod `\\ \\(msg\\, ctxt\\, " +"call\\_next\\)" #: ../../source/ref-api/flwr.client.mod.rst:28::1 #: flwr.client.mod.secure_aggregation.secagg_mod.secagg_mod:1 of -msgid "Handle incoming message and return results, following the SecAgg protocol." -msgstr "" +msgid "" +"Handle incoming message and return results, following the SecAgg protocol." +msgstr "SecAgg 프로토콜에 따라 수신 메시지를 처리하고 결과를 반환합니다." #: ../../source/ref-api/flwr.client.mod.rst:28::1 msgid "" ":py:obj:`secaggplus_mod `\\ \\(msg\\, " "ctxt\\, call\\_next\\)" msgstr "" +":py:obj:`secaggplus_mod `\\ \\(msg\\, " +"ctxt\\, call\\_next\\)" #: ../../source/ref-api/flwr.client.mod.rst:28::1 #: flwr.client.mod.secure_aggregation.secaggplus_mod.secaggplus_mod:1 of msgid "" -"Handle incoming message and return results, following the SecAgg+ " -"protocol." -msgstr "" +"Handle incoming message and return results, following the SecAgg+ protocol." +msgstr "SecAgg+ 프로토콜에 따라 수신 메시지를 처리하고 결과를 반환합니다." #: ../../source/ref-api/flwr.client.mod.rst:28::1 msgid "" -":py:obj:`message_size_mod `\\ \\(msg\\," -" ctxt\\, call\\_next\\)" +":py:obj:`message_size_mod `\\ \\(msg\\, " +"ctxt\\, call\\_next\\)" msgstr "" +":py:obj:`message_size_mod `\\ \\(msg\\, " +"ctxt\\, call\\_next\\)" #: ../../source/ref-api/flwr.client.mod.rst:28::1 #: flwr.client.mod.comms_mods.message_size_mod:1 of msgid "Message size mod." -msgstr "" +msgstr "메시지 크기 수정." #: ../../source/ref-api/flwr.client.mod.rst:28::1 msgid "" ":py:obj:`parameters_size_mod `\\ " "\\(msg\\, ctxt\\, call\\_next\\)" msgstr "" +":py:obj:`parameters_size_mod `\\ " +"\\(msg\\, ctxt\\, call\\_next\\)" #: ../../source/ref-api/flwr.client.mod.rst:28::1 #: flwr.client.mod.comms_mods.parameters_size_mod:1 of msgid "Parameters size mod." -msgstr "" +msgstr "매개변수 크기 mod." #: ../../source/ref-api/flwr.client.mod.rst:35::1 msgid "" -":py:obj:`LocalDpMod `\\ \\(clipping\\_norm\\," -" sensitivity\\, ...\\)" +":py:obj:`LocalDpMod `\\ \\(clipping\\_norm\\, " +"sensitivity\\, ...\\)" msgstr "" +":py:obj:`LocalDpMod `\\ \\(clipping\\_norm\\, " +"sensitivity\\, ...\\)" #: ../../source/ref-api/flwr.client.mod.rst:35::1 #: flwr.client.mod.localdp_mod.LocalDpMod:1 of msgid "Modifier for local differential privacy." -msgstr "" +msgstr "로컬 차분 프라이버시를 위한 수정자." #: ../../source/ref-api/flwr.client.mod.LocalDpMod.rst:2 msgid "LocalDpMod" -msgstr "" +msgstr "LocalDpMod" #: flwr.client.mod.localdp_mod.LocalDpMod:3 of msgid "" -"This mod clips the client model updates and adds noise to the params " -"before sending them to the server." +"This mod clips the client model updates and adds noise to the params before " +"sending them to the server." msgstr "" +"이 모드는 클라이언트 모델 업데이트를 클립하고 서버로 보내기 전에 파라미터에 " +"노이즈를 추가합니다." #: flwr.client.mod.centraldp_mods.adaptiveclipping_mod:12 #: flwr.client.mod.centraldp_mods.fixedclipping_mod:10 #: flwr.client.mod.localdp_mod.LocalDpMod:6 of msgid "It operates on messages of type `MessageType.TRAIN`." -msgstr "" +msgstr "이 함수는 `MessageType.TRAIN` 유형의 메시지에 대해 작동합니다." #: flwr.client.mod.localdp_mod.LocalDpMod:8 #: flwr.server.strategy.dp_fixed_clipping.DifferentialPrivacyClientSideFixedClipping:15 #: flwr.server.strategy.dp_fixed_clipping.DifferentialPrivacyServerSideFixedClipping:8 #: of msgid "The value of the clipping norm." -msgstr "" +msgstr "클리핑 기준값입니다." #: flwr.client.mod.localdp_mod.LocalDpMod:10 of msgid "The sensitivity of the client model." -msgstr "" +msgstr "클라이언트 모델의 민감도입니다." #: flwr.client.mod.localdp_mod.LocalDpMod:12 of msgid "" "The privacy budget. Smaller value of epsilon indicates a higher level of " "privacy protection." msgstr "" +"개인정보 보호 예산. 엡실론 값이 작을수록 개인정보 보호 수준이 높음을 나타냅니" +"다." #: flwr.client.mod.localdp_mod.LocalDpMod:15 of msgid "" -"The failure probability. The probability that the privacy mechanism fails" -" to provide the desired level of privacy. A smaller value of delta " -"indicates a stricter privacy guarantee." +"The failure probability. The probability that the privacy mechanism fails to " +"provide the desired level of privacy. A smaller value of delta indicates a " +"stricter privacy guarantee." msgstr "" +"실패 확률입니다. 프라이버시 메커니즘이 원하는 수준의 프라이버시를 제공하지 못" +"할 확률입니다. 델타 값이 작을수록 프라이버시가 더 엄격하게 보장된다는 의미입" +"니다." #: flwr.client.mod.localdp_mod.LocalDpMod:23 of -msgid "Create an instance of the local DP mod and add it to the client-side mods:" -msgstr "" +msgid "" +"Create an instance of the local DP mod and add it to the client-side mods:" +msgstr "로컬 DP 모드의 인스턴스를 생성하고 클라이언트 측 모드에 추가합니다:" #: ../../source/ref-api/flwr.client.mod.adaptiveclipping_mod.rst:2 msgid "adaptiveclipping\\_mod" -msgstr "" +msgstr "adaptiveclipping\\_mod" #: flwr.client.mod.centraldp_mods.adaptiveclipping_mod:3 of msgid "" "This mod needs to be used with the " -"DifferentialPrivacyClientSideAdaptiveClipping server-side strategy " -"wrapper." +"DifferentialPrivacyClientSideAdaptiveClipping server-side strategy wrapper." msgstr "" +"이 모드는 서버 측 전략 래퍼인 차분 프라이버시 클라이언트 측 적응형 클리핑과 " +"함께 사용해야 합니다." #: flwr.client.mod.centraldp_mods.adaptiveclipping_mod:6 #: flwr.client.mod.centraldp_mods.fixedclipping_mod:6 of msgid "The wrapper sends the clipping_norm value to the client." -msgstr "" +msgstr "래퍼는 클라이언트에 clipping_norm 값을 전송합니다." #: flwr.client.mod.centraldp_mods.adaptiveclipping_mod:8 #: flwr.client.mod.centraldp_mods.fixedclipping_mod:8 of -msgid "This mod clips the client model updates before sending them to the server." -msgstr "" +msgid "" +"This mod clips the client model updates before sending them to the server." +msgstr "이 모드는 클라이언트 모델 업데이트를 서버로 보내기 전에 클립합니다." #: flwr.client.mod.centraldp_mods.adaptiveclipping_mod:10 of msgid "" "It also sends KEY_NORM_BIT to the server for computing the new clipping " "value." -msgstr "" +msgstr "또한 새 클리핑 값을 계산하기 위해 서버로 KEY_NORM_BIT을 전송합니다." #: flwr.client.mod.centraldp_mods.adaptiveclipping_mod:15 #: flwr.client.mod.centraldp_mods.fixedclipping_mod:13 @@ -7613,240 +9169,280 @@ msgstr "" #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow:60 #: of msgid "Notes" -msgstr "" +msgstr "참고" #: flwr.client.mod.centraldp_mods.adaptiveclipping_mod:16 #: flwr.client.mod.centraldp_mods.fixedclipping_mod:14 of msgid "Consider the order of mods when using multiple." -msgstr "" +msgstr "여러 개를 사용할 때는 모드의 순서를 고려하세요." #: flwr.client.mod.centraldp_mods.adaptiveclipping_mod:18 of -msgid "Typically, adaptiveclipping_mod should be the last to operate on params." +msgid "" +"Typically, adaptiveclipping_mod should be the last to operate on params." msgstr "" +"일반적으로 adaptiveclipping_mod는 매개변수에서 가장 마지막으로 작동해야 합니" +"다." #: ../../source/ref-api/flwr.client.mod.fixedclipping_mod.rst:2 msgid "fixedclipping\\_mod" -msgstr "" +msgstr "fixedclipping\\_mod" #: flwr.client.mod.centraldp_mods.fixedclipping_mod:3 of msgid "" "This mod needs to be used with the " "DifferentialPrivacyClientSideFixedClipping server-side strategy wrapper." msgstr "" +"이 모드는 서버 측 전략 래퍼인 DifferentialPrivacyClientSideFixedClipping과 함" +"께 사용해야 합니다." #: flwr.client.mod.centraldp_mods.fixedclipping_mod:16 of msgid "Typically, fixedclipping_mod should be the last to operate on params." msgstr "" +"일반적으로 fixedclipping_mod는 매개변수에서 가장 마지막으로 작동해야 합니다." #: ../../source/ref-api/flwr.client.mod.make_ffn.rst:2 msgid "make\\_ffn" -msgstr "" +msgstr "make\\_ffn" #: ../../source/ref-api/flwr.client.mod.message_size_mod.rst:2 msgid "message\\_size\\_mod" -msgstr "" +msgstr "message\\_size\\_mod" #: flwr.client.mod.comms_mods.message_size_mod:3 of msgid "This mod logs the size in bytes of the message being transmited." -msgstr "" +msgstr "이 모드는 전송되는 메시지의 크기를 바이트 단위로 기록합니다." #: ../../source/ref-api/flwr.client.mod.parameters_size_mod.rst:2 msgid "parameters\\_size\\_mod" -msgstr "" +msgstr "parameters\\_size\\_mod" #: flwr.client.mod.comms_mods.parameters_size_mod:3 of msgid "" -"This mod logs the number of parameters transmitted in the message as well" -" as their size in bytes." +"This mod logs the number of parameters transmitted in the message as well as " +"their size in bytes." msgstr "" +"이 모드는 메시지에서 전송된 매개변수의 수와 그 크기를 바이트 단위로 기록합니" +"다." #: ../../source/ref-api/flwr.client.mod.secagg_mod.rst:2 msgid "secagg\\_mod" -msgstr "" +msgstr "secagg\\_mod" #: ../../source/ref-api/flwr.client.mod.secaggplus_mod.rst:2 msgid "secaggplus\\_mod" -msgstr "" +msgstr "secaggplus\\_mod" #: ../../source/ref-api/flwr.client.run_client_app.rst:2 msgid "run\\_client\\_app" -msgstr "" +msgstr "run\\_client\\_app" #: ../../source/ref-api/flwr.client.run_supernode.rst:2 msgid "run\\_supernode" -msgstr "" +msgstr "run\\_supernode" #: ../../source/ref-api/flwr.client.start_client.rst:2 msgid "start\\_client" -msgstr "" +msgstr "start\\_client" #: 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\"`." +"same machine on port 8080, then `server_address` would be `\"[::]:8080\"`." msgstr "" +"서버의 IPv4 또는 IPv6 주소입니다. Flower 서버가 포트 8080의 동일한 컴퓨터에" +"서 실행되는 경우 `서버_주소`는 `\"[::]:8080\"`이 됩니다." #: flwr.client.app.start_client:7 of msgid "A callable that instantiates a Client. (default: None)" -msgstr "" +msgstr "클라이언트를 인스턴스화하는 호출 가능 항목입니다. (기본값: None)" #: flwr.client.app.start_client:9 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`의 구현(기본값: None)" #: 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." +"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:19 flwr.client.app.start_numpy_client:22 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: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." +"Starts an insecure gRPC connection when True. Enables HTTPS connection when " +"False, using system certificates if `root_certificates` is None." msgstr "" +"True일 경우 안전하지 않은 gRPC 연결을 시작합니다. root_certificates`가 None" +"인 경우 시스템 인증서를 사용하여 False일 때 HTTPS 연결을 활성화합니다." #: 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)" +"bidirectional streaming - 'grpc-rere': gRPC, request-response (experimental) " +"- 'rest': HTTP (experimental)" msgstr "" +"전송 계층을 구성합니다. 허용되는 값입니다: - 'grpc-bidi': gRPC, 양방향 스트리" +"밍 - 'grpc-rere': gRPC, 요청-응답(실험적) - 'rest': HTTP(실험적)" #: flwr.client.app.start_client:31 of msgid "" "The maximum number of times the client will try to connect to the server " -"before giving up in case of a connection error. If set to None, there is " -"no limit to the number of tries." +"before giving up in case of a connection error. If set to None, there is no " +"limit to the number of tries." msgstr "" +"연결 오류 발생 시 클라이언트가 서버 연결을 포기하기 전에 시도하는 최대 횟수입" +"니다. None으로 설정하면 시도 횟수에 제한이 없습니다." #: flwr.client.app.start_client:35 of msgid "" -"The maximum duration before the client stops trying to connect to the " -"server in case of connection error. If set to None, there is no limit to " -"the total time." +"The maximum duration before the client stops trying to connect to the server " +"in case of connection error. If set to None, there is no limit to the total " +"time." msgstr "" +"연결 오류 발생 시 클라이언트가 서버에 대한 연결을 시도하지 않는 최대 기간입니" +"다. None으로 설정하면 총 시간에는 제한이 없습니다." #: flwr.client.app.start_client:42 flwr.client.app.start_numpy_client:37 of msgid "Starting a gRPC client with an insecure server connection:" -msgstr "" +msgstr "안전하지 않은 서버 연결로 gRPC 클라이언트 시작하기:" #: flwr.client.app.start_client:49 flwr.client.app.start_numpy_client:44 of msgid "Starting an SSL-enabled gRPC client using system certificates:" -msgstr "" +msgstr "시스템 인증서를 사용하여 SSL 사용 gRPC 클라이언트를 시작합니다:" #: flwr.client.app.start_client:60 flwr.client.app.start_numpy_client:52 of msgid "Starting an SSL-enabled gRPC client using provided certificates:" -msgstr "" +msgstr "제공된 인증서를 사용하여 SSL 지원 gRPC 클라이언트를 시작합니다:" #: ../../source/ref-api/flwr.client.start_numpy_client.rst:2 msgid "start\\_numpy\\_client" -msgstr "" +msgstr "start\\_numpy\\_client" #: 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." +"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 "" +"이 함수는 1.7.0부터 더 이상 사용되지 않습니다. 대신 :code:`flwr.client." +"start_client`를 사용하고 먼저 :code:`to_client()` 메서드를 실행하여 :code:" +"`NumPyClient`를 :code:`flwr.client.Client` 유형으로 변환합니다." #: flwr.client.app.start_numpy_client:13 of msgid "An implementation of the abstract base class `flwr.client.NumPyClient`." -msgstr "" +msgstr "추상 베이스 클래스 `flwr.client.NumPyClient`의 구현입니다." #: ../../source/ref-api/flwr.common.rst:2 msgid "common" -msgstr "" +msgstr "공통" #: ../../source/ref-api/flwr.common.rst:30::1 -msgid ":py:obj:`array_from_numpy `\\ \\(ndarray\\)" +msgid "" +":py:obj:`array_from_numpy `\\ \\(ndarray\\)" msgstr "" +":py:obj:`array_from_numpy `\\ \\(ndarray\\)" #: ../../source/ref-api/flwr.common.rst:30::1 #: flwr.common.record.conversion_utils.array_from_numpy:1 of msgid "Create Array from NumPy ndarray." -msgstr "" +msgstr "NumPy에서 배열을 만듭니다." #: ../../source/ref-api/flwr.common.rst:30::1 -msgid ":py:obj:`bytes_to_ndarray `\\ \\(tensor\\)" +msgid "" +":py:obj:`bytes_to_ndarray `\\ \\(tensor\\)" msgstr "" +":py:obj:`bytes_to_ndarray `\\ \\(tensor\\)" #: ../../source/ref-api/flwr.common.rst:30::1 #: flwr.common.parameter.bytes_to_ndarray:1 of msgid "Deserialize NumPy ndarray from bytes." -msgstr "" +msgstr "바이트에서 NumPy를 역직렬화합니다." #: ../../source/ref-api/flwr.common.rst:30::1 msgid "" ":py:obj:`configure `\\ \\(identifier\\[\\, " "filename\\, host\\]\\)" msgstr "" +":py:obj:`configure `\\ \\(identifier\\[\\, " +"filename\\, host\\]\\)" #: ../../source/ref-api/flwr.common.rst:30::1 #: flwr.common.logger.configure:1 of msgid "Configure logging to file and/or remote log server." -msgstr "" +msgstr "파일 및/또는 원격 로그 서버에 로깅을 구성합니다." #: ../../source/ref-api/flwr.common.rst:30::1 msgid "" ":py:obj:`event `\\ \\(event\\_type\\[\\, " "event\\_details\\]\\)" msgstr "" +":py:obj:`event `\\ \\(event\\_type\\[\\, " +"event\\_details\\]\\)" #: ../../source/ref-api/flwr.common.rst:30::1 #: flwr.common.telemetry.event:1 of msgid "Submit create_event to ThreadPoolExecutor to avoid blocking." -msgstr "" +msgstr "차단을 피하기 위해 create_event를 ThreadPoolExecutor에 제출합니다." #: ../../source/ref-api/flwr.common.rst:30::1 msgid "" ":py:obj:`log `\\ \\(level\\, msg\\, \\*args\\, " "\\*\\*kwargs\\)" msgstr "" +":py:obj:`log `\\ \\(level\\, msg\\, \\*args\\, " +"\\*\\*kwargs\\)" #: ../../source/ref-api/flwr.common.rst:30::1 logging.Logger.log:1 #: of msgid "Log 'msg % args' with the integer severity 'level'." -msgstr "" +msgstr "정수 심각도 'level'과 함께 'msg % args'를 기록합니다." #: ../../source/ref-api/flwr.common.rst:30::1 -msgid ":py:obj:`ndarray_to_bytes `\\ \\(ndarray\\)" +msgid "" +":py:obj:`ndarray_to_bytes `\\ \\(ndarray\\)" msgstr "" +":py:obj:`ndarray_to_bytes `\\ \\(ndarray\\)" #: ../../source/ref-api/flwr.common.rst:30::1 #: flwr.common.parameter.ndarray_to_bytes:1 of msgid "Serialize NumPy ndarray to bytes." -msgstr "" +msgstr "NumPy와 배열을 바이트열로 직렬화합니다." #: ../../source/ref-api/flwr.common.rst:30::1 msgid ":py:obj:`now `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`now `\\ \\(\\)" #: ../../source/ref-api/flwr.common.rst:30::1 #: flwr.common.date.now:1 of msgid "Construct a datetime from time.time() with time zone set to UTC." -msgstr "" +msgstr "표준 시간대를 UTC로 설정하여 time.time()에서 날짜 시간을 생성합니다." #: ../../source/ref-api/flwr.common.rst:30::1 msgid "" ":py:obj:`ndarrays_to_parameters `\\ " "\\(ndarrays\\)" msgstr "" +":py:obj:`ndarrays_to_parameters `\\ " +"\\(ndarrays\\)" #: ../../source/ref-api/flwr.common.rst:30::1 #: flwr.common.parameter.ndarrays_to_parameters:1 @@ -7854,1333 +9450,1485 @@ msgstr "" #: flwr.server.strategy.fedavg_android.FedAvgAndroid.ndarrays_to_parameters:1 #: of msgid "Convert NumPy ndarrays to parameters object." -msgstr "" +msgstr "NumPy 배열을 매개변수 객체로 변환합니다." #: ../../source/ref-api/flwr.common.rst:30::1 msgid "" ":py:obj:`parameters_to_ndarrays `\\ " "\\(parameters\\)" msgstr "" +":py:obj:`parameters_to_ndarrays `\\ " +"\\(parameters\\)" #: ../../source/ref-api/flwr.common.rst:30::1 #: flwr.common.parameter.parameters_to_ndarrays:1 of msgid "Convert parameters object to NumPy ndarrays." -msgstr "" +msgstr "매개변수 객체를 NumPy 배열로 변환합니다." #: ../../source/ref-api/flwr.common.rst:64::1 msgid "" -":py:obj:`Array `\\ \\(dtype\\, shape\\, stype\\, " -"data\\)" +":py:obj:`Array `\\ \\(dtype\\, shape\\, stype\\, data\\)" msgstr "" +":py:obj:`Array `\\ \\(dtype\\, shape\\, stype\\, data\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.record.parametersrecord.Array:1 of msgid "Array type." -msgstr "" +msgstr "배열 유형." #: ../../source/ref-api/flwr.common.rst:64::1 msgid "" ":py:obj:`ClientMessage `\\ " "\\(\\[get\\_properties\\_res\\, ...\\]\\)" msgstr "" +":py:obj:`ClientMessage `\\ " +"\\(\\[get\\_properties\\_res\\, ...\\]\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.typing.ClientMessage:1 of msgid "ClientMessage is a container used to hold one result message." msgstr "" +"ClientMessage는 하나의 결과 메시지를 저장하는 데 사용되는 컨테이너입니다." #: ../../source/ref-api/flwr.common.rst:64::1 msgid ":py:obj:`Code `\\ \\(value\\)" -msgstr "" +msgstr ":py:obj:`Code `\\ \\(value\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.typing.Code:1 of msgid "Client status codes." -msgstr "" +msgstr "클라이언트 상태 코드." #: ../../source/ref-api/flwr.common.rst:64::1 msgid "" ":py:obj:`ConfigsRecord `\\ " "\\(\\[configs\\_dict\\, keep\\_input\\]\\)" msgstr "" +":py:obj:`ConfigsRecord `\\ " +"\\(\\[configs\\_dict\\, keep\\_input\\]\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.record.configsrecord.ConfigsRecord:1 of msgid "Configs record." -msgstr "" +msgstr "레코드를 설정합니다." #: ../../source/ref-api/flwr.common.rst:64::1 msgid ":py:obj:`Context `\\ \\(state\\)" -msgstr "" +msgstr ":py:obj:`Context `\\ \\(state\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.context.Context:1 of msgid "State of your run." -msgstr "" +msgstr "실행 상태." #: ../../source/ref-api/flwr.common.rst:64::1 msgid ":py:obj:`DisconnectRes `\\ \\(reason\\)" -msgstr "" +msgstr ":py:obj:`DisconnectRes `\\ \\(reason\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.typing.DisconnectRes:1 of msgid "DisconnectRes message from client to server." -msgstr "" +msgstr "클라이언트에서 서버로 연결 해제 메시지를 보냅니다." #: ../../source/ref-api/flwr.common.rst:64::1 msgid "" -":py:obj:`EvaluateIns `\\ \\(parameters\\, " -"config\\)" +":py:obj:`EvaluateIns `\\ \\(parameters\\, config\\)" msgstr "" +":py:obj:`EvaluateIns `\\ \\(parameters\\, config\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.typing.EvaluateIns:1 of msgid "Evaluate instructions for a client." -msgstr "" +msgstr "클라이언트에 대한 지침을 평가합니다." #: ../../source/ref-api/flwr.common.rst:64::1 msgid "" ":py:obj:`EvaluateRes `\\ \\(status\\, loss\\, " "num\\_examples\\, metrics\\)" msgstr "" +":py:obj:`EvaluateRes `\\ \\(status\\, loss\\, " +"num\\_examples\\, metrics\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.typing.EvaluateRes:1 of msgid "Evaluate response from a client." -msgstr "" +msgstr "클라이언트의 응답을 평가합니다." #: ../../source/ref-api/flwr.common.rst:64::1 msgid ":py:obj:`EventType `\\ \\(value\\)" -msgstr "" +msgstr ":py:obj:`EventType `\\ \\(value\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.telemetry.EventType:1 of msgid "Types of telemetry events." -msgstr "" +msgstr "원격 분석 이벤트의 유형." #: ../../source/ref-api/flwr.common.rst:64::1 msgid ":py:obj:`FitIns `\\ \\(parameters\\, config\\)" -msgstr "" +msgstr ":py:obj:`FitIns `\\ \\(parameters\\, config\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.typing.FitIns:1 of msgid "Fit instructions for a client." -msgstr "" +msgstr "고객을 위한 맞춤 지침." #: ../../source/ref-api/flwr.common.rst:64::1 msgid "" ":py:obj:`FitRes `\\ \\(status\\, parameters\\, " "num\\_examples\\, metrics\\)" msgstr "" +":py:obj:`FitRes `\\ \\(status\\, parameters\\, " +"num\\_examples\\, metrics\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.typing.FitRes:1 of msgid "Fit response from a client." -msgstr "" +msgstr "클라이언트의 적합성 응답." #: ../../source/ref-api/flwr.common.rst:64::1 msgid ":py:obj:`Error `\\ \\(code\\[\\, reason\\]\\)" -msgstr "" +msgstr ":py:obj:`Error `\\ \\(code\\[\\, reason\\]\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.message.Error:1 of msgid "A dataclass that stores information about an error that occurred." -msgstr "" +msgstr "발생한 오류에 대한 정보를 저장하는 데이터 클래스입니다." #: ../../source/ref-api/flwr.common.rst:64::1 -msgid ":py:obj:`GetParametersIns `\\ \\(config\\)" +msgid "" +":py:obj:`GetParametersIns `\\ \\(config\\)" msgstr "" +":py:obj:`GetParametersIns `\\ \\(config\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.typing.GetParametersIns:1 of msgid "Parameters request for a client." -msgstr "" +msgstr "클라이언트에 대한 매개변수 요청입니다." #: ../../source/ref-api/flwr.common.rst:64::1 msgid "" ":py:obj:`GetParametersRes `\\ \\(status\\, " "parameters\\)" msgstr "" +":py:obj:`GetParametersRes `\\ \\(status\\, " +"parameters\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.typing.GetParametersRes:1 of msgid "Response when asked to return parameters." -msgstr "" +msgstr "매개변수 반환 요청 시 응답합니다." #: ../../source/ref-api/flwr.common.rst:64::1 -msgid ":py:obj:`GetPropertiesIns `\\ \\(config\\)" +msgid "" +":py:obj:`GetPropertiesIns `\\ \\(config\\)" msgstr "" +":py:obj:`GetPropertiesIns `\\ \\(config\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.typing.GetPropertiesIns:1 of msgid "Properties request for a client." -msgstr "" +msgstr "클라이언트에 대한 속성 요청." #: ../../source/ref-api/flwr.common.rst:64::1 msgid "" ":py:obj:`GetPropertiesRes `\\ \\(status\\, " "properties\\)" msgstr "" +":py:obj:`GetPropertiesRes `\\ \\(status\\, " +"properties\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.typing.GetPropertiesRes:1 of msgid "Properties response from a client." -msgstr "" +msgstr "클라이언트의 속성 응답을 확인합니다." #: ../../source/ref-api/flwr.common.rst:64::1 msgid "" ":py:obj:`Message `\\ \\(metadata\\[\\, content\\, " "error\\]\\)" msgstr "" +":py:obj:`Message `\\ \\(metadata\\[\\, content\\, " +"error\\]\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.message.Message:1 of msgid "State of your application from the viewpoint of the entity using it." -msgstr "" +msgstr "애플리케이션을 사용하는 엔티티의 관점에서 애플리케이션의 상태입니다." #: ../../source/ref-api/flwr.common.rst:64::1 msgid ":py:obj:`MessageType `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`MessageType `\\ \\(\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.constant.MessageType:1 of msgid "Message type." -msgstr "" +msgstr "메시지 타입." #: ../../source/ref-api/flwr.common.rst:64::1 msgid ":py:obj:`MessageTypeLegacy `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`MessageTypeLegacy `\\ \\(\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.constant.MessageTypeLegacy:1 of msgid "Legacy message type." -msgstr "" +msgstr "레거시 메시지 타입." #: ../../source/ref-api/flwr.common.rst:64::1 msgid "" -":py:obj:`Metadata `\\ \\(run\\_id\\, " -"message\\_id\\, src\\_node\\_id\\, ...\\)" +":py:obj:`Metadata `\\ \\(run\\_id\\, message\\_id\\, " +"src\\_node\\_id\\, ...\\)" msgstr "" +":py:obj:`Metadata `\\ \\(run\\_id\\, message\\_id\\, " +"src\\_node\\_id\\, ...\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.message.Metadata:1 of msgid "A dataclass holding metadata associated with the current message." -msgstr "" +msgstr "현재 메시지와 관련된 메타데이터를 보유한 데이터 클래스입니다." #: ../../source/ref-api/flwr.common.rst:64::1 msgid "" ":py:obj:`MetricsRecord `\\ " "\\(\\[metrics\\_dict\\, keep\\_input\\]\\)" msgstr "" +":py:obj:`MetricsRecord `\\ " +"\\(\\[metrics\\_dict\\, keep\\_input\\]\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.record.metricsrecord.MetricsRecord:1 of msgid "Metrics record." -msgstr "" +msgstr "메트릭 기록." #: ../../source/ref-api/flwr.common.rst:64::1 msgid ":py:obj:`NDArray `\\" -msgstr "" +msgstr ":py:obj:`NDArray `\\" #: ../../source/ref-api/flwr.common.rst:64::1 msgid "" -"alias of :py:class:`~numpy.ndarray`\\ [:py:obj:`~typing.Any`, " -":py:class:`~numpy.dtype`\\ [:py:obj:`~typing.Any`]]" +"alias of :py:class:`~numpy.ndarray`\\ [:py:obj:`~typing.Any`, :py:class:" +"`~numpy.dtype`\\ [:py:obj:`~typing.Any`]]" msgstr "" +"alias of :py:class:`~numpy.ndarray`\\ [:py:obj:`~typing.Any`, :py:class:" +"`~numpy.dtype`\\ [:py:obj:`~typing.Any`]]" #: ../../source/ref-api/flwr.common.rst:64::1 msgid "" ":py:obj:`Parameters `\\ \\(tensors\\, " "tensor\\_type\\)" msgstr "" +":py:obj:`Parameters `\\ \\(tensors\\, " +"tensor\\_type\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.typing.Parameters:1 of msgid "Model parameters." -msgstr "" +msgstr "모델 매개변수." #: ../../source/ref-api/flwr.common.rst:64::1 msgid "" ":py:obj:`ParametersRecord `\\ " "\\(\\[array\\_dict\\, keep\\_input\\]\\)" msgstr "" +":py:obj:`ParametersRecord `\\ " +"\\(\\[array\\_dict\\, keep\\_input\\]\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.record.parametersrecord.ParametersRecord:1 of msgid "Parameters record." -msgstr "" +msgstr "매개변수 기록." #: ../../source/ref-api/flwr.common.rst:64::1 msgid ":py:obj:`ReconnectIns `\\ \\(seconds\\)" -msgstr "" +msgstr ":py:obj:`ReconnectIns `\\ \\(seconds\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.typing.ReconnectIns:1 of msgid "ReconnectIns message from server to client." -msgstr "" +msgstr "서버에서 클라이언트로 메시지를 다시 연결합니다." #: ../../source/ref-api/flwr.common.rst:64::1 msgid "" ":py:obj:`RecordSet `\\ " "\\(\\[parameters\\_records\\, ...\\]\\)" msgstr "" +":py:obj:`RecordSet `\\ " +"\\(\\[parameters\\_records\\, ...\\]\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.record.recordset.RecordSet:1 of msgid "RecordSet stores groups of parameters, metrics and configs." -msgstr "" +msgstr "RecordSet은 매개변수, 메트릭 및 설정 그룹을 저장합니다." #: ../../source/ref-api/flwr.common.rst:64::1 msgid "" ":py:obj:`ServerMessage `\\ " "\\(\\[get\\_properties\\_ins\\, ...\\]\\)" msgstr "" +":py:obj:`ServerMessage `\\ " +"\\(\\[get\\_properties\\_ins\\, ...\\]\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.typing.ServerMessage:1 of msgid "ServerMessage is a container used to hold one instruction message." msgstr "" +"ServerMessage는 하나의 instruction 메시지를 저장하는 데 사용되는 컨테이너입니" +"다." #: ../../source/ref-api/flwr.common.rst:64::1 msgid ":py:obj:`Status `\\ \\(code\\, message\\)" -msgstr "" +msgstr ":py:obj:`Status `\\ \\(code\\, message\\)" #: ../../source/ref-api/flwr.common.rst:64::1 #: flwr.common.typing.Status:1 of msgid "Client status." -msgstr "" +msgstr "클라이언트 상태." #: ../../source/ref-api/flwr.common.Array.rst:2 msgid "Array" -msgstr "" +msgstr "배열" #: flwr.common.record.parametersrecord.Array:3 of msgid "" "A dataclass containing serialized data from an array-like or tensor-like " "object along with some metadata about it." msgstr "" +"배열형 또는 텐서형 객체의 직렬화된 데이터와 그에 대한 일부 메타데이터를 포함" +"하는 데이터 클래스입니다." #: flwr.common.record.parametersrecord.Array:6 of msgid "" -"A string representing the data type of the serialised object (e.g. " -"`np.float32`)" -msgstr "" +"A string representing the data type of the serialised object (e.g. `np." +"float32`)" +msgstr "직렬화된 객체의 데이터 유형을 나타내는 문자열(예: `np.float32`)" #: flwr.common.record.parametersrecord.Array:8 of msgid "" -"A list representing the shape of the unserialized array-like object. This" -" is used to deserialize the data (depending on the serialization method) " -"or simply as a metadata field." +"A list representing the shape of the unserialized array-like object. This is " +"used to deserialize the data (depending on the serialization method) or " +"simply as a metadata field." msgstr "" +"직렬화되지 않은 배열과 같은 객체의 모양을 나타내는 목록입니다. 직렬화 방법에 " +"따라 데이터를 역직렬화하는 데 사용되거나 단순히 메타데이터 필드로 사용됩니다." #: flwr.common.record.parametersrecord.Array:12 of msgid "" -"A string indicating the type of serialisation mechanism used to generate " -"the bytes in `data` from an array-like or tensor-like object." +"A string indicating the type of serialisation mechanism used to generate the " +"bytes in `data` from an array-like or tensor-like object." msgstr "" +"배열형 또는 텐서형 객체에서 `데이터`의 바이트를 생성하는 데 사용되는 직렬화 " +"메커니즘의 유형을 나타내는 문자열입니다." #: flwr.common.record.parametersrecord.Array:15 of msgid "A buffer of bytes containing the data." -msgstr "" +msgstr "데이터를 포함하는 바이트 버퍼입니다." #: ../../source/ref-api/flwr.common.Array.rst:26::1 msgid ":py:obj:`numpy `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`numpy `\\ \\(\\)" #: ../../source/ref-api/flwr.common.Array.rst:26::1 #: flwr.common.record.parametersrecord.Array.numpy:1 of msgid "Return the array as a NumPy array." -msgstr "" +msgstr "배열을 NumPy 배열로 반환합니다." #: flwr.common.record.parametersrecord.Array.numpy:1::1 of msgid ":py:obj:`dtype `\\" -msgstr "" +msgstr ":py:obj:`dtype `\\" #: flwr.common.record.parametersrecord.Array.numpy:1::1 of msgid ":py:obj:`shape `\\" -msgstr "" +msgstr ":py:obj:`shape `\\" #: flwr.common.record.parametersrecord.Array.numpy:1::1 of msgid ":py:obj:`stype `\\" -msgstr "" +msgstr ":py:obj:`stype `\\" #: flwr.common.record.parametersrecord.Array.numpy:1::1 of msgid ":py:obj:`data `\\" -msgstr "" +msgstr ":py:obj:`data `\\" #: ../../source/ref-api/flwr.common.ClientMessage.rst:2 msgid "ClientMessage" -msgstr "" +msgstr "클라이언트 메시지" #: ../../source/ref-api/flwr.common.ClientMessage.rst:31::1 msgid ":py:obj:`evaluate_res `\\" -msgstr "" +msgstr ":py:obj:`evaluate_res `\\" #: ../../source/ref-api/flwr.common.ClientMessage.rst:31::1 msgid ":py:obj:`fit_res `\\" -msgstr "" +msgstr ":py:obj:`fit_res `\\" #: ../../source/ref-api/flwr.common.ClientMessage.rst:31::1 msgid "" -":py:obj:`get_parameters_res " -"`\\" +":py:obj:`get_parameters_res `\\" msgstr "" +":py:obj:`get_parameters_res `\\" #: ../../source/ref-api/flwr.common.ClientMessage.rst:31::1 msgid "" -":py:obj:`get_properties_res " -"`\\" +":py:obj:`get_properties_res `\\" msgstr "" +":py:obj:`get_properties_res `\\" #: ../../source/ref-api/flwr.common.Code.rst:2 msgid "Code" -msgstr "" +msgstr "코드" #: flwr.common.typing.Code:1 of msgid "Bases: :py:class:`~enum.Enum`" -msgstr "" +msgstr "Bases: :py:class:`~enum.Enum`" #: ../../source/ref-api/flwr.common.Code.rst:26::1 msgid ":py:obj:`OK `\\" -msgstr "" +msgstr ":py:obj:`OK `\\" #: ../../source/ref-api/flwr.common.Code.rst:26::1 msgid "" -":py:obj:`GET_PROPERTIES_NOT_IMPLEMENTED " -"`\\" +":py:obj:`GET_PROPERTIES_NOT_IMPLEMENTED `\\" msgstr "" +":py:obj:`GET_PROPERTIES_NOT_IMPLEMENTED `\\" #: ../../source/ref-api/flwr.common.Code.rst:26::1 msgid "" -":py:obj:`GET_PARAMETERS_NOT_IMPLEMENTED " -"`\\" +":py:obj:`GET_PARAMETERS_NOT_IMPLEMENTED `\\" msgstr "" +":py:obj:`GET_PARAMETERS_NOT_IMPLEMENTED `\\" #: ../../source/ref-api/flwr.common.Code.rst:26::1 msgid ":py:obj:`FIT_NOT_IMPLEMENTED `\\" -msgstr "" +msgstr ":py:obj:`FIT_NOT_IMPLEMENTED `\\" #: ../../source/ref-api/flwr.common.Code.rst:26::1 msgid "" -":py:obj:`EVALUATE_NOT_IMPLEMENTED " -"`\\" +":py:obj:`EVALUATE_NOT_IMPLEMENTED `\\" msgstr "" +":py:obj:`EVALUATE_NOT_IMPLEMENTED `\\" #: ../../source/ref-api/flwr.common.ConfigsRecord.rst:2 msgid "ConfigsRecord" -msgstr "" +msgstr "컨피그 레코드" #: flwr.common.record.configsrecord.ConfigsRecord:1 of msgid "" -"Bases: :py:class:`~flwr.common.record.typeddict.TypedDict`\\ " -"[:py:class:`str`, :py:class:`int` | :py:class:`float` | :py:class:`str` |" -" :py:class:`bytes` | :py:class:`bool` | :py:class:`~typing.List`\\ " -"[:py:class:`int`] | :py:class:`~typing.List`\\ [:py:class:`float`] | " -":py:class:`~typing.List`\\ [:py:class:`str`] | :py:class:`~typing.List`\\" -" [:py:class:`bytes`] | :py:class:`~typing.List`\\ [:py:class:`bool`]]" +"Bases: :py:class:`~flwr.common.record.typeddict.TypedDict`\\ [:py:class:" +"`str`, :py:class:`int` | :py:class:`float` | :py:class:`str` | :py:class:" +"`bytes` | :py:class:`bool` | :py:class:`~typing.List`\\ [:py:class:`int`] | :" +"py:class:`~typing.List`\\ [:py:class:`float`] | :py:class:`~typing.List`\\ [:" +"py:class:`str`] | :py:class:`~typing.List`\\ [:py:class:`bytes`] | :py:class:" +"`~typing.List`\\ [:py:class:`bool`]]" msgstr "" +"Bases: :py:class:`~flwr.common.record.typeddict.TypedDict`\\ [:py:class:`str`" +", :py:class:`int` | :py:class:`float` | :py:class:`str` | :py:class:`bytes` |" +" :py:class:`bool` | :py:class:`~typing.List`\\ [:py:class:`int`] | " +":py:class:`~typing.List`\\ [:py:class:`float`] | :py:class:`~typing.List`\\ " +"[:py:class:`str`] | :py:class:`~typing.List`\\ [:py:class:`bytes`] | " +":py:class:`~typing.List`\\ [:py:class:`bool`]]" #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid ":py:obj:`clear `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`clear `\\ \\(\\)" #: flwr.common.record.typeddict.TypedDict.clear:1 #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid "Remove all items from R." -msgstr "" +msgstr "R에서 모든 항목을 제거합니다." #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid ":py:obj:`count_bytes `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`count_bytes `\\ \\(\\)" #: flwr.common.record.configsrecord.ConfigsRecord.count_bytes:1 #: flwr.common.record.metricsrecord.MetricsRecord.count_bytes:1 #: flwr.common.record.parametersrecord.ParametersRecord.count_bytes:1 #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid "Return number of Bytes stored in this object." -msgstr "" +msgstr "이 객체에 저장된 바이트 수를 반환합니다." #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid ":py:obj:`get `\\ \\(k\\[\\,d\\]\\)" -msgstr "" +msgstr ":py:obj:`get `\\ \\(k\\[\\,d\\]\\)" #: flwr.common.record.typeddict.TypedDict.clear:1::1 #: flwr.common.record.typeddict.TypedDict.get:1 of msgid "d defaults to None." -msgstr "" +msgstr "d는 기본값이 None입니다." #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid ":py:obj:`items `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`items `\\ \\(\\)" #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid ":py:obj:`keys `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`keys `\\ \\(\\)" #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid ":py:obj:`pop `\\ \\(k\\[\\,d\\]\\)" -msgstr "" +msgstr ":py:obj:`pop `\\ \\(k\\[\\,d\\]\\)" #: flwr.common.record.typeddict.TypedDict.clear:1::1 #: flwr.common.record.typeddict.TypedDict.pop:1 of -msgid "If key is not found, d is returned if given, otherwise KeyError is raised." -msgstr "" +msgid "" +"If key is not found, d is returned if given, otherwise KeyError is raised." +msgstr "키를 찾을 수 없으면 주어진 경우 d가 반환되고, 그렇지 않으면 KeyError가 " +"발생합니다." #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid "" ":py:obj:`update `\\ \\(\\[E\\, " "\\]\\*\\*F\\)" msgstr "" +":py:obj:`update `\\ \\(\\[E\\, \\]\\*\\*F\\" +")" #: flwr.common.record.typeddict.TypedDict.clear:1::1 #: flwr.common.record.typeddict.TypedDict.update:1 of msgid "Update R from dict/iterable E and F." -msgstr "" +msgstr "dict/iterable E 및 F에서 R을 업데이트합니다." #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid ":py:obj:`values `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`values `\\ \\(\\)" #: flwr.common.record.configsrecord.ConfigsRecord.count_bytes:3 of msgid "This function counts booleans as occupying 1 Byte." -msgstr "" +msgstr "이 함수는 booleans을 1바이트를 차지하는 것으로 계산합니다." #: ../../source/ref-api/flwr.common.Context.rst:2 msgid "Context" -msgstr "" +msgstr "컨텍스트" #: flwr.common.context.Context:3 of msgid "" -"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 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)" +"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 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)" msgstr "" +"특정 실행에서 엔티티가 추가한 레코드를 보유하며 로컬에 유지됩니다. 즉, " +"저장된 데이터는 실행 중인 시스템을 벗어나지 않습니다. 모드를 실행할 때 중간 " +"저장소나 스크래치 패드로 사용할 수 있습니다. 또한 이 엔티티의 수명 주기 동안 " +"다른 시점에서 액세스하기 위한 메모리로도 사용할 수 있습니다(예: 여러 " +"라운드에 걸쳐)" #: ../../source/ref-api/flwr.common.Context.rst:28::1 msgid ":py:obj:`state `\\" -msgstr "" +msgstr ":py:obj:`state `\\" #: ../../source/ref-api/flwr.common.DisconnectRes.rst:2 msgid "DisconnectRes" -msgstr "" +msgstr "연결 해제" #: ../../source/ref-api/flwr.common.DisconnectRes.rst:28::1 msgid ":py:obj:`reason `\\" -msgstr "" +msgstr ":py:obj:`reason `\\" #: ../../source/ref-api/flwr.common.Error.rst:2 msgid "Error" -msgstr "" +msgstr "오류" #: flwr.common.message.Error:3 of msgid "An identifier for the error." -msgstr "" +msgstr "오류 식별자입니다." #: flwr.common.message.Error:5 of msgid "A reason for why the error arose (e.g. an exception stack-trace)" -msgstr "" +msgstr "오류가 발생한 이유(예: 예외 스택 추적)" #: flwr.common.Error.code:1::1 of msgid ":py:obj:`code `\\" -msgstr "" +msgstr ":py:obj:`code `\\" #: flwr.common.Error.code:1 flwr.common.Error.code:1::1 of msgid "Error code." -msgstr "" +msgstr "오류 코드." #: flwr.common.Error.code:1::1 of msgid ":py:obj:`reason `\\" -msgstr "" +msgstr ":py:obj:`reason `\\" #: flwr.common.Error.code:1::1 flwr.common.Error.reason:1 of msgid "Reason reported about the error." -msgstr "" +msgstr "오류에 대해 보고된 사유입니다." #: ../../source/ref-api/flwr.common.EvaluateIns.rst:2 msgid "EvaluateIns" -msgstr "" +msgstr "평가" #: ../../source/ref-api/flwr.common.EvaluateIns.rst:29::1 msgid ":py:obj:`parameters `\\" -msgstr "" +msgstr ":py:obj:`parameters `\\" #: ../../source/ref-api/flwr.common.EvaluateIns.rst:29::1 msgid ":py:obj:`config `\\" -msgstr "" +msgstr ":py:obj:`config `\\" #: ../../source/ref-api/flwr.common.EvaluateRes.rst:2 msgid "EvaluateRes" -msgstr "" +msgstr "EvaluateRes" #: ../../source/ref-api/flwr.common.EvaluateRes.rst:31::1 msgid ":py:obj:`status `\\" -msgstr "" +msgstr ":py:obj:`status `\\" #: ../../source/ref-api/flwr.common.EvaluateRes.rst:31::1 msgid ":py:obj:`loss `\\" -msgstr "" +msgstr ":py:obj:`loss `\\" #: ../../source/ref-api/flwr.common.EvaluateRes.rst:31::1 msgid ":py:obj:`num_examples `\\" -msgstr "" +msgstr ":py:obj:`num_examples `\\" #: ../../source/ref-api/flwr.common.EvaluateRes.rst:31::1 msgid ":py:obj:`metrics `\\" -msgstr "" +msgstr ":py:obj:`metrics `\\" #: ../../source/ref-api/flwr.common.EventType.rst:2 msgid "EventType" -msgstr "" +msgstr "이벤트 타입" #: flwr.common.telemetry.EventType:1 of msgid "Bases: :py:class:`str`, :py:class:`~enum.Enum`" -msgstr "" +msgstr "Bases: :py:class:`str`, :py:class:`~enum.Enum`" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "" ":py:obj:`encode `\\ \\(\\[encoding\\, " "errors\\]\\)" msgstr "" +":py:obj:`encode `\\ \\(\\[encoding\\, errors\\]" +"\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.encode:1 of msgid "Encode the string using the codec registered for encoding." -msgstr "" +msgstr "인코딩용으로 등록된 코덱을 사용하여 문자열을 인코딩합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "" ":py:obj:`replace `\\ \\(old\\, new\\[\\, " "count\\]\\)" msgstr "" +":py:obj:`replace `\\ \\(old\\, new\\[\\, " +"count\\]\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.replace:1 of msgid "Return a copy with all occurrences of substring old replaced by new." -msgstr "" +msgstr "이전 하위 문자열이 모두 새 하위 문자열로 바뀐 사본을 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "" -":py:obj:`split `\\ \\(\\[sep\\, " -"maxsplit\\]\\)" +":py:obj:`split `\\ \\(\\[sep\\, maxsplit\\]\\)" msgstr "" +":py:obj:`split `\\ \\(\\[sep\\, maxsplit\\]\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.rsplit:1 flwr.common.EventType.split:1 of msgid "" -"Return a list of the substrings in the string, using sep as the separator" -" string." -msgstr "" +"Return a list of the substrings in the string, using sep as the separator " +"string." +msgstr "sep를 구분 문자열로 사용하여 문자열의 하위 문자열 목록을 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "" -":py:obj:`rsplit `\\ \\(\\[sep\\, " -"maxsplit\\]\\)" +":py:obj:`rsplit `\\ \\(\\[sep\\, maxsplit\\]\\)" msgstr "" +":py:obj:`rsplit `\\ \\(\\[sep\\, maxsplit\\]\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`join `\\ \\(iterable\\, \\/\\)" -msgstr "" +msgstr ":py:obj:`join `\\ \\(iterable\\, \\/\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.join:1 of msgid "Concatenate any number of strings." -msgstr "" +msgstr "원하는 수의 문자열을 연결합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`capitalize `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`capitalize `\\ \\(\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.capitalize:1 of msgid "Return a capitalized version of the string." -msgstr "" +msgstr "대문자로 된 문자열을 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`casefold `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`casefold `\\ \\(\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.casefold:1 of msgid "Return a version of the string suitable for caseless comparisons." -msgstr "" +msgstr "대소문자 구분 없는 비교에 적합한 문자열을 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`title `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`title `\\ \\(\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.title:1 of msgid "Return a version of the string where each word is titlecased." -msgstr "" +msgstr "각 단어의 제목이 대소문자로 구분된 문자열을 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "" ":py:obj:`center `\\ \\(width\\[\\, " "fillchar\\]\\)" msgstr "" +":py:obj:`center `\\ \\(width\\[\\, fillchar\\]" +"\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.center:1 of msgid "Return a centered string of length width." -msgstr "" +msgstr "길이 너비의 가운데 문자열을 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "" ":py:obj:`count `\\ \\(sub\\[\\, start\\[\\, " "end\\]\\]\\)" msgstr "" +":py:obj:`count `\\ \\(sub\\[\\, start\\[\\, " +"end\\]\\]\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "" -"Return the number of non-overlapping occurrences of substring sub in " -"string S[start:end]." -msgstr "" +"Return the number of non-overlapping occurrences of substring sub in string " +"S[start:end]." +msgstr "문자열 S[start:end]에서 하위 문자열 sub이 겹치지 않는 횟수를 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "" -":py:obj:`expandtabs `\\ " -"\\(\\[tabsize\\]\\)" +":py:obj:`expandtabs `\\ \\(\\[tabsize\\]\\)" msgstr "" +":py:obj:`expandtabs `\\ \\(\\[tabsize\\]\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.expandtabs:1 of msgid "Return a copy where all tab characters are expanded using spaces." -msgstr "" +msgstr "모든 탭 문자가 공백을 사용하여 확장된 사본을 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "" ":py:obj:`find `\\ \\(sub\\[\\, start\\[\\, " "end\\]\\]\\)" msgstr "" +":py:obj:`find `\\ \\(sub\\[\\, start\\[\\, end\\]" +"\\]\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "" -"Return the lowest index in S where substring sub is found, such that sub " -"is contained within S[start:end]." -msgstr "" +"Return the lowest index in S where substring sub is found, such that sub is " +"contained within S[start:end]." +msgstr "하위 문자열 sub이 발견되는 S에서 하위가 S[start:end] 내에 포함되는 가장 낮은 " +"인덱스를 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 -msgid ":py:obj:`partition `\\ \\(sep\\, \\/\\)" +msgid "" +":py:obj:`partition `\\ \\(sep\\, \\/\\)" msgstr "" +":py:obj:`partition `\\ \\(sep\\, \\/\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.partition:1 flwr.common.EventType.rpartition:1 of msgid "Partition the string into three parts using the given separator." -msgstr "" +msgstr "지정된 구분 기호를 사용하여 문자열을 세 부분으로 분할합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "" ":py:obj:`index `\\ \\(sub\\[\\, start\\[\\, " "end\\]\\]\\)" msgstr "" +":py:obj:`index `\\ \\(sub\\[\\, start\\[\\, " +"end\\]\\]\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "" -":py:obj:`ljust `\\ \\(width\\[\\, " -"fillchar\\]\\)" +":py:obj:`ljust `\\ \\(width\\[\\, fillchar\\]\\)" msgstr "" +":py:obj:`ljust `\\ \\(width\\[\\, fillchar\\]\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.ljust:1 of msgid "Return a left-justified string of length width." -msgstr "" +msgstr "왼쪽으로 정렬된 길이의 문자열을 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`lower `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`lower `\\ \\(\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.lower:1 of msgid "Return a copy of the string converted to lowercase." -msgstr "" +msgstr "소문자로 변환된 문자열 사본을 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`lstrip `\\ \\(\\[chars\\]\\)" -msgstr "" +msgstr ":py:obj:`lstrip `\\ \\(\\[chars\\]\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.lstrip:1 of msgid "Return a copy of the string with leading whitespace removed." -msgstr "" +msgstr "선행 공백이 제거된 문자열의 복사본을 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "" ":py:obj:`rfind `\\ \\(sub\\[\\, start\\[\\, " "end\\]\\]\\)" msgstr "" +":py:obj:`rfind `\\ \\(sub\\[\\, start\\[\\, " +"end\\]\\]\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "" -"Return the highest index in S where substring sub is found, such that sub" -" is contained within S[start:end]." -msgstr "" +"Return the highest index in S where substring sub is found, such that sub is " +"contained within S[start:end]." +msgstr "부분 문자열 sub이 발견되는 곳에서 sub이 S[start:end] 내에 포함되도록 S에서 " +"가장 높은 인덱스를 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "" -":py:obj:`rindex `\\ \\(sub\\[\\, " -"start\\[\\, end\\]\\]\\)" +":py:obj:`rindex `\\ \\(sub\\[\\, start\\[\\, " +"end\\]\\]\\)" msgstr "" +":py:obj:`rindex `\\ \\(sub\\[\\, start\\[\\, " +"end\\]\\]\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "" -":py:obj:`rjust `\\ \\(width\\[\\, " -"fillchar\\]\\)" +":py:obj:`rjust `\\ \\(width\\[\\, fillchar\\]\\)" msgstr "" +":py:obj:`rjust `\\ \\(width\\[\\, fillchar\\]\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.rjust:1 of msgid "Return a right-justified string of length width." -msgstr "" +msgstr "길이 너비의 오른쪽 정렬된 문자열을 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`rstrip `\\ \\(\\[chars\\]\\)" -msgstr "" +msgstr ":py:obj:`rstrip `\\ \\(\\[chars\\]\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.rstrip:1 of msgid "Return a copy of the string with trailing whitespace removed." -msgstr "" +msgstr "후행 공백이 제거된 문자열의 복사본을 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 -msgid ":py:obj:`rpartition `\\ \\(sep\\, \\/\\)" +msgid "" +":py:obj:`rpartition `\\ \\(sep\\, \\/\\)" msgstr "" +":py:obj:`rpartition `\\ \\(sep\\, \\/\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "" ":py:obj:`splitlines `\\ " "\\(\\[keepends\\]\\)" msgstr "" +":py:obj:`splitlines `\\ \\(\\[keepends\\]\\" +")" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.splitlines:1 of msgid "Return a list of the lines in the string, breaking at line boundaries." -msgstr "" +msgstr "문자열의 줄 목록을 줄 경계에서 구분하여 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`strip `\\ \\(\\[chars\\]\\)" -msgstr "" +msgstr ":py:obj:`strip `\\ \\(\\[chars\\]\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.strip:1 of -msgid "Return a copy of the string with leading and trailing whitespace removed." -msgstr "" +msgid "" +"Return a copy of the string with leading and trailing whitespace removed." +msgstr "선행 및 후행 공백이 제거된 문자열 사본을 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`swapcase `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`swapcase `\\ \\(\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.swapcase:1 of msgid "" "Convert uppercase characters to lowercase and lowercase characters to " "uppercase." -msgstr "" +msgstr "대문자를 소문자로, 소문자를 대문자로 변환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 -msgid ":py:obj:`translate `\\ \\(table\\, \\/\\)" +msgid "" +":py:obj:`translate `\\ \\(table\\, \\/\\)" msgstr "" +":py:obj:`translate `\\ \\(table\\, \\/\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.translate:1 of msgid "Replace each character in the string using the given translation table." -msgstr "" +msgstr "주어진 번역 테이블을 사용하여 문자열의 각 문자를 바꿉니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`upper `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`upper `\\ \\(\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.upper:1 of msgid "Return a copy of the string converted to uppercase." -msgstr "" +msgstr "Return a copy of the string converted to uppercase." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "" -":py:obj:`startswith `\\ \\(prefix\\[\\," -" start\\[\\, end\\]\\]\\)" +":py:obj:`startswith `\\ \\(prefix\\[\\, " +"start\\[\\, end\\]\\]\\)" msgstr "" +":py:obj:`startswith `\\ \\(prefix\\[\\, " +"start\\[\\, end\\]\\]\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "Return True if S starts with the specified prefix, False otherwise." -msgstr "" +msgstr "S가 지정된 접두사로 시작하면 True를 반환하고, 그렇지 않으면 False를 " +"반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "" ":py:obj:`endswith `\\ \\(suffix\\[\\, " "start\\[\\, end\\]\\]\\)" msgstr "" +":py:obj:`endswith `\\ \\(suffix\\[\\, start\\" +"[\\, end\\]\\]\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "Return True if S ends with the specified suffix, False otherwise." -msgstr "" +msgstr "S가 지정된 접미사로 끝나면 True를 반환하고 그렇지 않으면 False을 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "" -":py:obj:`removeprefix `\\ " -"\\(prefix\\, \\/\\)" +":py:obj:`removeprefix `\\ \\(prefix\\, " +"\\/\\)" msgstr "" +":py:obj:`removeprefix `\\ \\(prefix\\, \\" +"/\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.removeprefix:1 of msgid "Return a str with the given prefix string removed if present." -msgstr "" +msgstr "주어진 접두사 문자열이 있는 경우 제거된 문자열을 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "" -":py:obj:`removesuffix `\\ " -"\\(suffix\\, \\/\\)" +":py:obj:`removesuffix `\\ \\(suffix\\, " +"\\/\\)" msgstr "" +":py:obj:`removesuffix `\\ \\(suffix\\, \\" +"/\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.removesuffix:1 of msgid "Return a str with the given suffix string removed if present." -msgstr "" +msgstr "주어진 접미사 문자열이 있는 경우 제거된 문자열을 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`isascii `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`isascii `\\ \\(\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.isascii:1 of msgid "Return True if all characters in the string are ASCII, False otherwise." -msgstr "" +msgstr "문자열의 모든 문자가 ASCII인 경우 True를 반환하고, 그렇지 않으면 False를 " +"반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`islower `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`islower `\\ \\(\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.islower:1 of msgid "Return True if the string is a lowercase string, False otherwise." -msgstr "" +msgstr "문자열이 소문자 문자열이면 True를 반환하고, 그렇지 않으면 False를 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`isupper `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`isupper `\\ \\(\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.isupper:1 of msgid "Return True if the string is an uppercase string, False otherwise." -msgstr "" +msgstr "문자열이 대문자 문자열이면 True를 반환하고, 그렇지 않으면 False를 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`istitle `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`istitle `\\ \\(\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.istitle:1 of msgid "Return True if the string is a title-cased string, False otherwise." -msgstr "" +msgstr "문자열이 제목 대/소문자가 구분된 문자열이면 True를 반환하고, 그렇지 않으면 " +"False를 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`isspace `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`isspace `\\ \\(\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.isspace:1 of msgid "Return True if the string is a whitespace string, False otherwise." -msgstr "" +msgstr "문자열이 공백 문자열이면 True를 반환하고, 그렇지 않으면 False를 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`isdecimal `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`isdecimal `\\ \\(\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.isdecimal:1 of msgid "Return True if the string is a decimal string, False otherwise." -msgstr "" +msgstr "문자열이 10진수 문자열이면 True를 반환하고, 그렇지 않으면 False를 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`isdigit `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`isdigit `\\ \\(\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.isdigit:1 of msgid "Return True if the string is a digit string, False otherwise." -msgstr "" +msgstr "문자열이 숫자 문자열이면 True를 반환하고, 그렇지 않으면 False를 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`isnumeric `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`isnumeric `\\ \\(\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.isnumeric:1 of msgid "Return True if the string is a numeric string, False otherwise." -msgstr "" +msgstr "문자열이 숫자 문자열이면 True를 반환하고, 그렇지 않으면 False를 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`isalpha `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`isalpha `\\ \\(\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.isalpha:1 of msgid "Return True if the string is an alphabetic string, False otherwise." -msgstr "" +msgstr "문자열이 알파벳 문자열이면 True를 반환하고, 그렇지 않으면 False를 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`isalnum `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`isalnum `\\ \\(\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.isalnum:1 of msgid "Return True if the string is an alpha-numeric string, False otherwise." -msgstr "" +msgstr "문자열이 영-숫자 문자열이면 True를 반환하고, 그렇지 않으면 False를 " +"반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`isidentifier `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`isidentifier `\\ \\(\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.isidentifier:1 of -msgid "Return True if the string is a valid Python identifier, False otherwise." -msgstr "" +msgid "" +"Return True if the string is a valid Python identifier, False otherwise." +msgstr "문자열이 유효한 파이썬 식별자인 경우 True를 반환하고, 그렇지 않으면 False를 " +"반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`isprintable `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`isprintable `\\ \\(\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.isprintable:1 of msgid "Return True if the string is printable, False otherwise." -msgstr "" +msgstr "문자열을 인쇄할 수 있으면 True를 반환하고, 그렇지 않으면 False를 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`zfill `\\ \\(width\\, \\/\\)" -msgstr "" +msgstr ":py:obj:`zfill `\\ \\(width\\, \\/\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.zfill:1 of msgid "" -"Pad a numeric string with zeros on the left, to fill a field of the given" -" width." -msgstr "" +"Pad a numeric string with zeros on the left, to fill a field of the given " +"width." +msgstr "숫자 문자열을 왼쪽에 0으로 채워서 지정된 너비의 필드를 채웁니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "" ":py:obj:`format `\\ \\(\\*args\\, " "\\*\\*kwargs\\)" msgstr "" +":py:obj:`format `\\ \\(\\*args\\, \\*\\*" +"kwargs\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 -msgid "Return a formatted version of S, using substitutions from args and kwargs." -msgstr "" +msgid "" +"Return a formatted version of S, using substitutions from args and kwargs." +msgstr "args와 kwarg의 치환을 사용하여 형식이 지정된 S를 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`format_map `\\ \\(mapping\\)" -msgstr "" +msgstr ":py:obj:`format_map `\\ \\(mapping\\)" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid "Return a formatted version of S, using substitutions from mapping." -msgstr "" +msgstr "매핑의 치환을 사용하여 형식이 지정된 S를 반환합니다." #: ../../source/ref-api/flwr.common.EventType.rst:163::1 msgid ":py:obj:`maketrans `\\" -msgstr "" +msgstr ":py:obj:`maketrans `\\" #: ../../source/ref-api/flwr.common.EventType.rst:163::1 #: flwr.common.EventType.maketrans:1 of msgid "Return a translation table usable for str.translate()." -msgstr "" +msgstr "str.translate()에 사용할 수 있는 번역 테이블을 반환합니다." #: flwr.common.EventType.capitalize:1::1 of msgid ":py:obj:`PING `\\" -msgstr "" +msgstr ":py:obj:`PING `\\" #: flwr.common.EventType.capitalize:1::1 of -msgid ":py:obj:`START_CLIENT_ENTER `\\" +msgid "" +":py:obj:`START_CLIENT_ENTER `\\" msgstr "" +":py:obj:`START_CLIENT_ENTER `\\" #: flwr.common.EventType.capitalize:1::1 of -msgid ":py:obj:`START_CLIENT_LEAVE `\\" +msgid "" +":py:obj:`START_CLIENT_LEAVE `\\" msgstr "" +":py:obj:`START_CLIENT_LEAVE `\\" #: flwr.common.EventType.capitalize:1::1 of -msgid ":py:obj:`START_SERVER_ENTER `\\" +msgid "" +":py:obj:`START_SERVER_ENTER `\\" msgstr "" +":py:obj:`START_SERVER_ENTER `\\" #: flwr.common.EventType.capitalize:1::1 of -msgid ":py:obj:`START_SERVER_LEAVE `\\" +msgid "" +":py:obj:`START_SERVER_LEAVE `\\" msgstr "" +":py:obj:`START_SERVER_LEAVE `\\" #: flwr.common.EventType.capitalize:1::1 of msgid "" -":py:obj:`RUN_DRIVER_API_ENTER " -"`\\" +":py:obj:`RUN_DRIVER_API_ENTER `\\" msgstr "" +":py:obj:`RUN_DRIVER_API_ENTER `\\" #: flwr.common.EventType.capitalize:1::1 of msgid "" -":py:obj:`RUN_DRIVER_API_LEAVE " -"`\\" +":py:obj:`RUN_DRIVER_API_LEAVE `\\" msgstr "" +":py:obj:`RUN_DRIVER_API_LEAVE `\\" #: flwr.common.EventType.capitalize:1::1 of msgid "" -":py:obj:`RUN_FLEET_API_ENTER " -"`\\" +":py:obj:`RUN_FLEET_API_ENTER `\\" msgstr "" +":py:obj:`RUN_FLEET_API_ENTER `\\" #: flwr.common.EventType.capitalize:1::1 of msgid "" -":py:obj:`RUN_FLEET_API_LEAVE " -"`\\" +":py:obj:`RUN_FLEET_API_LEAVE `\\" msgstr "" +":py:obj:`RUN_FLEET_API_LEAVE `\\" #: flwr.common.EventType.capitalize:1::1 of msgid "" -":py:obj:`RUN_SUPERLINK_ENTER " -"`\\" +":py:obj:`RUN_SUPERLINK_ENTER `\\" msgstr "" +":py:obj:`RUN_SUPERLINK_ENTER `\\" #: flwr.common.EventType.capitalize:1::1 of msgid "" -":py:obj:`RUN_SUPERLINK_LEAVE " -"`\\" +":py:obj:`RUN_SUPERLINK_LEAVE `\\" msgstr "" +":py:obj:`RUN_SUPERLINK_LEAVE `\\" #: flwr.common.EventType.capitalize:1::1 of msgid "" -":py:obj:`START_SIMULATION_ENTER " -"`\\" +":py:obj:`START_SIMULATION_ENTER `\\" msgstr "" +":py:obj:`START_SIMULATION_ENTER `\\" #: flwr.common.EventType.capitalize:1::1 of msgid "" -":py:obj:`START_SIMULATION_LEAVE " -"`\\" +":py:obj:`START_SIMULATION_LEAVE `\\" msgstr "" +":py:obj:`START_SIMULATION_LEAVE `\\" #: flwr.common.EventType.capitalize:1::1 of msgid ":py:obj:`DRIVER_CONNECT `\\" -msgstr "" +msgstr ":py:obj:`DRIVER_CONNECT `\\" #: flwr.common.EventType.capitalize:1::1 of msgid ":py:obj:`DRIVER_DISCONNECT `\\" -msgstr "" +msgstr ":py:obj:`DRIVER_DISCONNECT `\\" #: flwr.common.EventType.capitalize:1::1 of -msgid ":py:obj:`START_DRIVER_ENTER `\\" +msgid "" +":py:obj:`START_DRIVER_ENTER `\\" msgstr "" +":py:obj:`START_DRIVER_ENTER `\\" #: flwr.common.EventType.capitalize:1::1 of -msgid ":py:obj:`START_DRIVER_LEAVE `\\" +msgid "" +":py:obj:`START_DRIVER_LEAVE `\\" msgstr "" +":py:obj:`START_DRIVER_LEAVE `\\" #: flwr.common.EventType.capitalize:1::1 of msgid "" -":py:obj:`RUN_CLIENT_APP_ENTER " -"`\\" +":py:obj:`RUN_CLIENT_APP_ENTER `\\" msgstr "" +":py:obj:`RUN_CLIENT_APP_ENTER `\\" #: flwr.common.EventType.capitalize:1::1 of msgid "" -":py:obj:`RUN_CLIENT_APP_LEAVE " -"`\\" +":py:obj:`RUN_CLIENT_APP_LEAVE `\\" msgstr "" +":py:obj:`RUN_CLIENT_APP_LEAVE `\\" #: flwr.common.EventType.capitalize:1::1 of msgid "" -":py:obj:`RUN_SERVER_APP_ENTER " -"`\\" +":py:obj:`RUN_SERVER_APP_ENTER `\\" msgstr "" +":py:obj:`RUN_SERVER_APP_ENTER `\\" #: flwr.common.EventType.capitalize:1::1 of msgid "" -":py:obj:`RUN_SERVER_APP_LEAVE " -"`\\" +":py:obj:`RUN_SERVER_APP_LEAVE `\\" msgstr "" +":py:obj:`RUN_SERVER_APP_LEAVE `\\" #: flwr.common.EventType.capitalize:1::1 of msgid "" -":py:obj:`RUN_SUPERNODE_ENTER " -"`\\" +":py:obj:`RUN_SUPERNODE_ENTER `\\" msgstr "" +":py:obj:`RUN_SUPERNODE_ENTER `\\" #: flwr.common.EventType.capitalize:1::1 of msgid "" -":py:obj:`RUN_SUPERNODE_LEAVE " -"`\\" +":py:obj:`RUN_SUPERNODE_LEAVE `\\" msgstr "" +":py:obj:`RUN_SUPERNODE_LEAVE `\\" #: flwr.common.EventType.capitalize:1::1 of msgid "" -":py:obj:`RUN_SUPEREXEC_ENTER " -"`\\" +":py:obj:`RUN_SUPEREXEC_ENTER `\\" msgstr "" +":py:obj:`RUN_SUPEREXEC_ENTER `\\" #: flwr.common.EventType.capitalize:1::1 of msgid "" -":py:obj:`RUN_SUPEREXEC_LEAVE " -"`\\" +":py:obj:`RUN_SUPEREXEC_LEAVE `\\" msgstr "" +":py:obj:`RUN_SUPEREXEC_LEAVE `\\" #: flwr.common.EventType.capitalize:3 of msgid "" "More specifically, make the first character have upper case and the rest " "lower case." -msgstr "" +msgstr "보다 구체적으로, 첫 번째 문자는 대문자로, 나머지는 소문자로 만듭니다." #: flwr.common.EventType.center:3 flwr.common.EventType.ljust:3 #: flwr.common.EventType.rjust:3 of -msgid "Padding is done using the specified fill character (default is a space)." -msgstr "" +msgid "" +"Padding is done using the specified fill character (default is a space)." +msgstr "패딩은 지정된 채우기 문자를 사용하여 수행됩니다(기본값은 공백)." #: flwr.common.EventType.count:1 of msgid "" -"Return the number of non-overlapping occurrences of substring sub in " -"string S[start:end]. Optional arguments start and end are interpreted as" -" in slice notation." +"Return the number of non-overlapping occurrences of substring sub in string " +"S[start:end]. Optional arguments start and end are interpreted as in slice " +"notation." msgstr "" +"문자열 S[start:end]에서 부분 문자열 sub의 겹치지 않는 횟수를 반환합니다. " +"선택적 인자 start와 end는 슬라이스 표기법과 같이 해석됩니다." #: flwr.common.EventType.encode:3 of msgid "encoding" -msgstr "" +msgstr "인코딩" #: flwr.common.EventType.encode:4 of msgid "The encoding in which to encode the string." -msgstr "" +msgstr "문자열을 인코딩합니다." #: flwr.common.EventType.encode:9 of msgid "errors" -msgstr "" +msgstr "오류" #: flwr.common.EventType.encode:6 of msgid "" "The error handling scheme to use for encoding errors. The default is " "'strict' meaning that encoding errors raise a UnicodeEncodeError. Other " -"possible values are 'ignore', 'replace' and 'xmlcharrefreplace' as well " -"as any other name registered with codecs.register_error that can handle " +"possible values are 'ignore', 'replace' and 'xmlcharrefreplace' as well as " +"any other name registered with codecs.register_error that can handle " "UnicodeEncodeErrors." msgstr "" +"인코딩 오류에 사용할 오류 처리 방식입니다. 기본값은 'strict'로, 인코딩 " +"오류가 발생하면 UnicodeEncodeError를 발생시킵니다. 다른 가능한 값으로는 " +"'ignore', 'replace', 'xmlcharrefreplace', 그리고 UnicodeEncodeError를 처리할 " +"수 있는 codecs.register_error에 등록된 다른 이름도 사용할 수 있습니다." #: flwr.common.EventType.endswith:1 of msgid "" "Return True if S ends with the specified suffix, False otherwise. With " -"optional start, test S beginning at that position. With optional end, " -"stop comparing S at that position. suffix can also be a tuple of strings " -"to try." +"optional start, test S beginning at that position. With optional end, stop " +"comparing S at that position. suffix can also be a tuple of strings to try." msgstr "" +"S가 지정된 접미사로 끝나면 True를 반환하고, 그렇지 않으면 False를 " +"반환합니다. 시작 옵션을 사용하면 해당 위치부터 S를 테스트합니다. end 옵션을 " +"사용하면 해당 위치에서 S 비교를 중지합니다. 접미사는 시도할 문자열의 튜플일 " +"수도 있습니다." #: flwr.common.EventType.expandtabs:3 of msgid "If tabsize is not given, a tab size of 8 characters is assumed." -msgstr "" +msgstr "탭 크기를 지정하지 않으면 크기가 8로 지정됩니다." #: flwr.common.EventType.find:1 flwr.common.EventType.index:1 of msgid "" -"Return the lowest index in S where substring sub is found, such that sub " -"is contained within S[start:end]. Optional arguments start and end are " +"Return the lowest index in S where substring sub is found, such that sub is " +"contained within S[start:end]. Optional arguments start and end are " "interpreted as in slice notation." msgstr "" +"부분 문자열 sub가 발견되는 곳의 가장 낮은 인덱스를 반환하며, sub는 " +"S[start:end] 내에 포함되어야 합니다. 선택적 인자 start와 end는 슬라이스 " +"표기법과 같이 해석됩니다." #: flwr.common.EventType.find:5 flwr.common.EventType.rfind:5 of msgid "Return -1 on failure." -msgstr "" +msgstr "실패 시 -1을 반환합니다." #: flwr.common.EventType.format:1 of msgid "" -"Return a formatted version of S, using substitutions from args and " -"kwargs. The substitutions are identified by braces ('{' and '}')." -msgstr "" +"Return a formatted version of S, using substitutions from args and kwargs. " +"The substitutions are identified by braces ('{' and '}')." +msgstr "args와 kwargs의 치환을 사용하여 형식이 지정된 S를 반환합니다. 치환은 " +"중괄호('{' 및 '}')로 식별됩니다." #: flwr.common.EventType.format_map:1 of msgid "" "Return a formatted version of S, using substitutions from mapping. The " "substitutions are identified by braces ('{' and '}')." -msgstr "" +msgstr "매핑의 치환을 사용하여 형식이 지정된 S를 반환합니다. 치환은 중괄호('{' 및 " +"'}')로 식별됩니다." #: flwr.common.EventType.index:5 flwr.common.EventType.rindex:5 of msgid "Raises ValueError when the substring is not found." -msgstr "" +msgstr "부분 문자열을 찾을 수 없을 때 ValueError를 발생시킵니다." #: flwr.common.EventType.isalnum:3 of msgid "" -"A string is alpha-numeric if all characters in the string are alpha-" -"numeric and there is at least one character in the string." -msgstr "" +"A string is alpha-numeric if all characters in the string are alpha-numeric " +"and there is at least one character in the string." +msgstr "문자열의 모든 문자가 영숫자이고 문자열에 하나 이상의 문자가 있는 경우 " +"문자열은 영-숫자입니다." #: flwr.common.EventType.isalpha:3 of msgid "" -"A string is alphabetic if all characters in the string are alphabetic and" -" there is at least one character in the string." -msgstr "" +"A string is alphabetic if all characters in the string are alphabetic and " +"there is at least one character in the string." +msgstr "문자열의 모든 문자가 알파벳이고 문자열에 하나 이상의 문자가 있는 경우 " +"문자열은 알파벳입니다." #: flwr.common.EventType.isascii:3 of msgid "" -"ASCII characters have code points in the range U+0000-U+007F. Empty " -"string is ASCII too." -msgstr "" +"ASCII characters have code points in the range U+0000-U+007F. Empty string " +"is ASCII too." +msgstr "ASCII 문자는 U+0000-U+007F 범위의 코드 포인트가 있습니다. 빈 문자열도 " +"ASCII입니다." #: flwr.common.EventType.isdecimal:3 of msgid "" -"A string is a decimal string if all characters in the string are decimal " -"and there is at least one character in the string." -msgstr "" +"A string is a decimal string if all characters in the string are decimal and " +"there is at least one character in the string." +msgstr "문자열의 모든 문자가 10진수이고 문자열에 하나 이상의 문자가 있는 경우 " +"문자열은 10진수 문자열입니다." #: flwr.common.EventType.isdigit:3 of msgid "" -"A string is a digit string if all characters in the string are digits and" -" there is at least one character in the string." -msgstr "" +"A string is a digit string if all characters in the string are digits and " +"there is at least one character in the string." +msgstr "문자열의 모든 문자가 숫자이고 문자열에 하나 이상의 문자가 있는 경우 문자열은 " +"숫자 문자열입니다." #: flwr.common.EventType.isidentifier:3 of msgid "" -"Call keyword.iskeyword(s) to test whether string s is a reserved " -"identifier, such as \"def\" or \"class\"." +"Call keyword.iskeyword(s) to test whether string s is a reserved identifier, " +"such as \"def\" or \"class\"." msgstr "" +"keyword.iskeyword(s)를 호출하여 문자열 s가 \"def\" 또는 \"class\"와 같은 " +"예약 식별자인지 테스트합니다." #: flwr.common.EventType.islower:3 of msgid "" -"A string is lowercase if all cased characters in the string are lowercase" -" and there is at least one cased character in the string." -msgstr "" +"A string is lowercase if all cased characters in the string are lowercase " +"and there is at least one cased character in the string." +msgstr "문자열이 모두 소문자이고 문자열에 문자가 하나 이상 있는 경우 문자열은 " +"소문자입니다." #: flwr.common.EventType.isnumeric:3 of msgid "" -"A string is numeric if all characters in the string are numeric and there" -" is at least one character in the string." -msgstr "" +"A string is numeric if all characters in the string are numeric and there is " +"at least one character in the string." +msgstr "문자열의 모든 문자가 숫자이고 문자열에 하나 이상의 문자가 있는 경우 문자열은 " +"숫자입니다." #: flwr.common.EventType.isprintable:3 of msgid "" -"A string is printable if all of its characters are considered printable " -"in repr() or if it is empty." -msgstr "" +"A string is printable if all of its characters are considered printable in " +"repr() or if it is empty." +msgstr "문자열은 repr()에서 모든 문자가 인쇄 가능한 것으로 간주되거나 비어 있는 경우 " +"인쇄할 수 있습니다." #: flwr.common.EventType.isspace:3 of msgid "" -"A string is whitespace if all characters in the string are whitespace and" -" there is at least one character in the string." -msgstr "" +"A string is whitespace if all characters in the string are whitespace and " +"there is at least one character in the string." +msgstr "문자열의 모든 문자가 공백이고 문자열에 하나 이상의 문자가 있는 경우 문자열은 " +"공백입니다." #: flwr.common.EventType.istitle:3 of msgid "" -"In a title-cased string, upper- and title-case characters may only follow" -" uncased characters and lowercase characters only cased ones." -msgstr "" +"In a title-cased string, upper- and title-case characters may only follow " +"uncased characters and lowercase characters only cased ones." +msgstr "제목 대/소문자 문자열에서 대문자와 제목 대문자는 대소문자만, 소문자는 " +"대문자만 뒤에 올 수 있습니다." #: flwr.common.EventType.isupper:3 of msgid "" -"A string is uppercase if all cased characters in the string are uppercase" -" and there is at least one cased character in the string." -msgstr "" +"A string is uppercase if all cased characters in the string are uppercase " +"and there is at least one cased character in the string." +msgstr "문자열의 모든 문자가 대문자이고 문자열에 문자가 하나 이상 있는 경우 문자열은 " +"대문자입니다." #: flwr.common.EventType.join:3 of msgid "" -"The string whose method is called is inserted in between each given " -"string. The result is returned as a new string." -msgstr "" +"The string whose method is called is inserted in between each given string. " +"The result is returned as a new string." +msgstr "메서드가 호출되는 문자열은 주어진 각 문자열 사이에 삽입됩니다. 결과는 새 " +"문자열로 반환됩니다." #: flwr.common.EventType.join:6 of msgid "Example: '.'.join(['ab', 'pq', 'rs']) -> 'ab.pq.rs'" -msgstr "" +msgstr "Example: '.'.join(['ab', 'pq', 'rs']) -> 'ab.pq.rs'" #: flwr.common.EventType.lstrip:3 flwr.common.EventType.rstrip:3 #: flwr.common.EventType.strip:3 of msgid "If chars is given and not None, remove characters in chars instead." -msgstr "" +msgstr "None이 아닌 문자가 지정되면 대신 문자열에서 문자를 제거합니다." #: flwr.common.EventType.maketrans:3 of msgid "" @@ -9188,10 +10936,15 @@ msgid "" "ordinals (integers) or characters to Unicode ordinals, strings or None. " "Character keys will be then converted to ordinals. If there are two " "arguments, they must be strings of equal length, and in the resulting " -"dictionary, each character in x will be mapped to the character at the " -"same position in y. If there is a third argument, it must be a string, " -"whose characters will be mapped to None in the result." +"dictionary, each character in x will be mapped to the character at the same " +"position in y. If there is a third argument, it must be a string, whose " +"characters will be mapped to None in the result." msgstr "" +"argument이 하나만 있는 경우, 유니코드 서수(정수) 또는 문자를 유니코드 서수, " +"문자열 또는 None에 매핑하는 dictionary이어야 합니다. 그러면 문자 키가 서수로 " +"변환됩니다. 인수가 두 개이면 길이가 같은 문자열이어야 하며, 결과 " +"dictionary에서 x의 각 문자는 y의 같은 위치에 있는 문자에 매핑됩니다. 세 번째 " +"인수가 있으면 문자열이어야 하며, 그 문자는 결과에서 None에 매핑됩니다." #: flwr.common.EventType.partition:3 of msgid "" @@ -9199,18 +10952,23 @@ msgid "" "found, returns a 3-tuple containing the part before the separator, the " "separator itself, and the part after it." msgstr "" +"문자열에서 구분 기호를 검색합니다. 구분 기호가 발견되면 구분 기호 앞 부분, " +"구분 기호 자체, 구분 기호 뒤 부분을 포함하는 3-tuple을 반환합니다." #: flwr.common.EventType.partition:7 of msgid "" "If the separator is not found, returns a 3-tuple containing the original " "string and two empty strings." -msgstr "" +msgstr "구분 기호를 찾을 수 없으면 원래 문자열과 빈 문자열 2개를 포함하는 3-튜플을 " +"반환합니다." #: flwr.common.EventType.removeprefix:3 of msgid "" -"If the string starts with the prefix string, return string[len(prefix):]." -" Otherwise, return a copy of the original string." +"If the string starts with the prefix string, return string[len(prefix):]. " +"Otherwise, return a copy of the original string." msgstr "" +"문자열이 접두사 문자열로 시작하면 문자열[len(prefix):]을 반환합니다. 그렇지 " +"않으면 원본 문자열의 복사본을 반환합니다." #: flwr.common.EventType.removesuffix:3 of msgid "" @@ -9218,667 +10976,727 @@ msgid "" "return string[:-len(suffix)]. Otherwise, return a copy of the original " "string." msgstr "" +"문자열이 접미사 문자열로 끝나고 해당 접미사가 비어 있지 않으면 " +"문자열[:-len(suffix)]을 반환합니다. 그렇지 않으면 원본 문자열의 복사본을 " +"반환합니다." #: flwr.common.EventType.replace:5 of msgid "count" -msgstr "" +msgstr "카운트" #: flwr.common.EventType.replace:4 of msgid "" "Maximum number of occurrences to replace. -1 (the default value) means " "replace all occurrences." -msgstr "" +msgstr "대체할 최대 발생 횟수입니다. -1(기본값)은 모든 항목을 교체한다는 의미입니다." #: flwr.common.EventType.replace:7 of msgid "" -"If the optional argument count is given, only the first count occurrences" -" are replaced." -msgstr "" +"If the optional argument count is given, only the first count occurrences " +"are replaced." +msgstr "선택적 argument 개수를 지정하면 첫 번째 개수만 바뀝니다." #: flwr.common.EventType.rfind:1 flwr.common.EventType.rindex:1 of msgid "" -"Return the highest index in S where substring sub is found, such that sub" -" is contained within S[start:end]. Optional arguments start and end are " +"Return the highest index in S where substring sub is found, such that sub is " +"contained within S[start:end]. Optional arguments start and end are " "interpreted as in slice notation." msgstr "" +"부분 문자열 sub가 발견되는 곳의 가장 높은 인덱스를 반환하며, sub는 " +"S[start:end] 내에 포함되어야 합니다. 선택적 인자 start와 end는 슬라이스 " +"표기법과 같이 해석됩니다." #: flwr.common.EventType.rpartition:3 of msgid "" -"This will search for the separator in the string, starting at the end. If" -" the separator is found, returns a 3-tuple containing the part before the" -" separator, the separator itself, and the part after it." +"This will search for the separator in the string, starting at the end. If " +"the separator is found, returns a 3-tuple containing the part before the " +"separator, the separator itself, and the part after it." msgstr "" +"그러면 문자열에서 끝 부분부터 시작하여 구분 기호를 검색합니다. 구분 기호가 " +"발견되면 구분 기호 앞 부분, 구분 기호 자체, 구분 기호 뒤 부분을 포함하는 3-" +"tuple을 반환합니다." #: flwr.common.EventType.rpartition:7 of msgid "" "If the separator is not found, returns a 3-tuple containing two empty " "strings and the original string." -msgstr "" +msgstr "구분 기호를 찾을 수 없는 경우 빈 문자열 2개와 원래 문자열을 포함하는 3-" +"tuple을 반환합니다." #: flwr.common.EventType.rsplit:7 flwr.common.EventType.split:7 of msgid "sep" -msgstr "" +msgstr "sep" #: flwr.common.EventType.rsplit:4 flwr.common.EventType.split:4 of msgid "The separator used to split the string." -msgstr "" +msgstr "문자열을 분할하는 데 사용되는 구분 기호입니다." #: flwr.common.EventType.rsplit:6 flwr.common.EventType.split:6 of msgid "" -"When set to None (the default value), will split on any whitespace " -"character (including \\\\n \\\\r \\\\t \\\\f and spaces) and will discard" -" empty strings from the result." +"When set to None (the default value), will split on any whitespace character " +"(including \\\\n \\\\r \\\\t \\\\f and spaces) and will discard empty " +"strings from the result." msgstr "" +"None(기본값)으로 설정하면 모든 공백 문자(\\\\n" +" \\\\r \\\\t \\\\f 및 공백 포함)를 분할하고 결과에서 빈 문자열을 삭제합니다." #: flwr.common.EventType.rsplit:11 flwr.common.EventType.split:11 of msgid "maxsplit" -msgstr "" +msgstr "maxsplit" #: flwr.common.EventType.rsplit:10 flwr.common.EventType.split:10 of msgid "" -"Maximum number of splits (starting from the left). -1 (the default value)" -" means no limit." -msgstr "" +"Maximum number of splits (starting from the left). -1 (the default value) " +"means no limit." +msgstr "최대 분할 횟수(왼쪽부터 시작). -1(기본값)은 제한이 없음을 의미합니다." #: flwr.common.EventType.rsplit:13 of msgid "Splitting starts at the end of the string and works to the front." -msgstr "" +msgstr "분할은 문자열 끝에서 시작하여 앞쪽으로 진행됩니다." #: flwr.common.EventType.split:13 of msgid "" "Note, str.split() is mainly useful for data that has been intentionally " -"delimited. With natural text that includes punctuation, consider using " -"the regular expression module." +"delimited. With natural text that includes punctuation, consider using the " +"regular expression module." msgstr "" +"참고로 str.split()은 주로 의도적으로 구분된 데이터에 유용합니다. 구두점이 " +"포함된 자연 텍스트의 경우 정규식 모듈을 사용하는 것이 좋습니다." #: flwr.common.EventType.splitlines:3 of msgid "" -"Line breaks are not included in the resulting list unless keepends is " -"given and true." -msgstr "" +"Line breaks are not included in the resulting list unless keepends is given " +"and true." +msgstr "줄 바꿈은 keepends가 주어지고 참이 아니면 결과 목록에 포함되지 않습니다." #: flwr.common.EventType.startswith:1 of msgid "" "Return True if S starts with the specified prefix, False otherwise. With " -"optional start, test S beginning at that position. With optional end, " -"stop comparing S at that position. prefix can also be a tuple of strings " -"to try." +"optional start, test S beginning at that position. With optional end, stop " +"comparing S at that position. prefix can also be a tuple of strings to try." msgstr "" +"S가 지정된 접두사로 시작하면 True를 반환하고, 그렇지 않으면 False를 " +"반환합니다. 시작 옵션을 사용하면 해당 위치에서 시작되는 S를 테스트합니다. " +"선택적 end를 사용하면 해당 위치에서 S 비교를 중지합니다. 접두사는 시도할 " +"문자열의 튜플일 수도 있습니다." #: flwr.common.EventType.title:3 of msgid "" -"More specifically, words start with uppercased characters and all " -"remaining cased characters have lower case." -msgstr "" +"More specifically, words start with uppercased characters and all remaining " +"cased characters have lower case." +msgstr "보다 구체적으로, 단어는 대문자로 시작하고 나머지 모든 대소문자는 소문자로 " +"표기합니다." #: flwr.common.EventType.translate:5 of msgid "table" -msgstr "" +msgstr "table" #: flwr.common.EventType.translate:4 of msgid "" -"Translation table, which must be a mapping of Unicode ordinals to Unicode" -" ordinals, strings, or None." -msgstr "" +"Translation table, which must be a mapping of Unicode ordinals to Unicode " +"ordinals, strings, or None." +msgstr "유니코드 서수를 유니코드 서수, 문자열 또는 없음으로 매핑하는 번역 " +"테이블이어야 합니다." #: flwr.common.EventType.translate:7 of msgid "" "The table must implement lookup/indexing via __getitem__, for instance a " -"dictionary or list. If this operation raises LookupError, the character " -"is left untouched. Characters mapped to None are deleted." +"dictionary or list. If this operation raises LookupError, the character is " +"left untouched. Characters mapped to None are deleted." msgstr "" +"테이블은 사전이나 목록과 같이 __getitem__을 통해 조회/색인을 구현해야 " +"합니다. 이 작업에서 LookupError가 발생하면 문자는 그대로 유지됩니다. " +"없음으로 매핑된 문자는 삭제됩니다." #: flwr.common.EventType.zfill:3 of msgid "The string is never truncated." -msgstr "" +msgstr "문자열은 잘리지 않습니다." #: ../../source/ref-api/flwr.common.FitIns.rst:2 msgid "FitIns" -msgstr "" +msgstr "FitIns" #: ../../source/ref-api/flwr.common.FitIns.rst:29::1 msgid ":py:obj:`parameters `\\" -msgstr "" +msgstr ":py:obj:`parameters `\\" #: ../../source/ref-api/flwr.common.FitIns.rst:29::1 msgid ":py:obj:`config `\\" -msgstr "" +msgstr ":py:obj:`config `\\" #: ../../source/ref-api/flwr.common.FitRes.rst:2 msgid "FitRes" -msgstr "" +msgstr "FitRes" #: ../../source/ref-api/flwr.common.FitRes.rst:31::1 msgid ":py:obj:`status `\\" -msgstr "" +msgstr ":py:obj:`status `\\" #: ../../source/ref-api/flwr.common.FitRes.rst:31::1 msgid ":py:obj:`parameters `\\" -msgstr "" +msgstr ":py:obj:`parameters `\\" #: ../../source/ref-api/flwr.common.FitRes.rst:31::1 msgid ":py:obj:`num_examples `\\" -msgstr "" +msgstr ":py:obj:`num_examples `\\" #: ../../source/ref-api/flwr.common.FitRes.rst:31::1 msgid ":py:obj:`metrics `\\" -msgstr "" +msgstr ":py:obj:`metrics `\\" #: ../../source/ref-api/flwr.common.GetParametersIns.rst:2 msgid "GetParametersIns" -msgstr "" +msgstr "GetParametersIns" #: ../../source/ref-api/flwr.common.GetParametersIns.rst:28::1 msgid ":py:obj:`config `\\" -msgstr "" +msgstr ":py:obj:`config `\\" #: ../../source/ref-api/flwr.common.GetParametersRes.rst:2 msgid "GetParametersRes" -msgstr "" +msgstr "GetParametersRes" #: ../../source/ref-api/flwr.common.GetParametersRes.rst:29::1 msgid ":py:obj:`status `\\" -msgstr "" +msgstr ":py:obj:`status `\\" #: ../../source/ref-api/flwr.common.GetParametersRes.rst:29::1 msgid ":py:obj:`parameters `\\" -msgstr "" +msgstr ":py:obj:`parameters `\\" #: ../../source/ref-api/flwr.common.GetPropertiesIns.rst:2 msgid "GetPropertiesIns" -msgstr "" +msgstr "GetPropertiesIns" #: ../../source/ref-api/flwr.common.GetPropertiesIns.rst:28::1 msgid ":py:obj:`config `\\" -msgstr "" +msgstr ":py:obj:`config `\\" #: ../../source/ref-api/flwr.common.GetPropertiesRes.rst:2 msgid "GetPropertiesRes" -msgstr "" +msgstr "GetPropertiesRes" #: ../../source/ref-api/flwr.common.GetPropertiesRes.rst:29::1 msgid ":py:obj:`status `\\" -msgstr "" +msgstr ":py:obj:`status `\\" #: ../../source/ref-api/flwr.common.GetPropertiesRes.rst:29::1 msgid ":py:obj:`properties `\\" -msgstr "" +msgstr ":py:obj:`properties `\\" #: ../../source/ref-api/flwr.common.Message.rst:2 msgid "Message" -msgstr "" +msgstr "Message" #: flwr.common.Message.content:1::1 flwr.common.Message.metadata:1 #: flwr.common.message.Message:3 of msgid "A dataclass including information about the message to be executed." -msgstr "" +msgstr "실행할 메시지에 대한 정보를 포함한 데이터 클래스입니다." #: flwr.common.message.Message:5 of msgid "" -"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." -msgstr "" +"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." +msgstr "다른 엔터티(예: 서버 측 로직이 클라이언트로 전송하거나 그 반대로 전송하는 등)" +"가 전송했거나 전송할 레코드를 보유합니다." #: flwr.common.message.Message:8 of msgid "" -"A dataclass that captures information about an error that took place when" -" processing another message." -msgstr "" +"A dataclass that captures information about an error that took place when " +"processing another message." +msgstr "다른 메시지를 처리할 때 발생한 오류에 대한 정보를 캡처하는 데이터 " +"클래스입니다." #: ../../source/ref-api/flwr.common.Message.rst:35::1 msgid "" ":py:obj:`create_error_reply `\\ " "\\(error\\[\\, ttl\\]\\)" msgstr "" +":py:obj:`create_error_reply `\\ \\(" +"error\\[\\, ttl\\]\\)" #: ../../source/ref-api/flwr.common.Message.rst:35::1 #: flwr.common.message.Message.create_error_reply:1 of msgid "Construct a reply message indicating an error happened." -msgstr "" +msgstr "오류가 발생했음을 나타내는 답장 메시지를 작성합니다." #: ../../source/ref-api/flwr.common.Message.rst:35::1 msgid "" -":py:obj:`create_reply `\\ " -"\\(content\\[\\, ttl\\]\\)" +":py:obj:`create_reply `\\ \\(content\\[\\, " +"ttl\\]\\)" msgstr "" +":py:obj:`create_reply `\\ \\(content\\[\\, " +"ttl\\]\\)" #: ../../source/ref-api/flwr.common.Message.rst:35::1 #: flwr.common.message.Message.create_reply:1 of msgid "Create a reply to this message with specified content and TTL." -msgstr "" +msgstr "지정된 콘텐츠와 TTL을 사용하여 이 메시지에 대한 답글을 작성합니다." #: ../../source/ref-api/flwr.common.Message.rst:35::1 msgid ":py:obj:`has_content `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`has_content `\\ \\(\\)" #: ../../source/ref-api/flwr.common.Message.rst:35::1 #: flwr.common.message.Message.has_content:1 of msgid "Return True if message has content, else False." -msgstr "" +msgstr "메시지에 콘텐츠가 있으면 True을 반환하고, 그렇지 않으면 False을 반환합니다." #: ../../source/ref-api/flwr.common.Message.rst:35::1 msgid ":py:obj:`has_error `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`has_error `\\ \\(\\)" #: ../../source/ref-api/flwr.common.Message.rst:35::1 #: flwr.common.message.Message.has_error:1 of msgid "Return True if message has an error, else False." -msgstr "" +msgstr "메시지에 오류가 있으면 True을 반환하고, 그렇지 않으면 False을 반환합니다." #: flwr.common.Message.content:1::1 of msgid ":py:obj:`content `\\" -msgstr "" +msgstr ":py:obj:`content `\\" #: flwr.common.Message.content:1 flwr.common.Message.content:1::1 #: of msgid "The content of this message." -msgstr "" +msgstr "이 메시지의 내용입니다." #: flwr.common.Message.content:1::1 of msgid ":py:obj:`error `\\" -msgstr "" +msgstr ":py:obj:`error `\\" #: flwr.common.Message.content:1::1 flwr.common.Message.error:1 of msgid "Error captured by this message." -msgstr "" +msgstr "이 메시지가 캡처한 오류입니다." #: flwr.common.Message.content:1::1 of msgid ":py:obj:`metadata `\\" -msgstr "" +msgstr ":py:obj:`metadata `\\" #: flwr.common.message.Message.create_error_reply:3 of msgid "The error that was encountered." -msgstr "" +msgstr "오류가 발생했습니다." #: flwr.common.message.Message.create_error_reply:5 #: flwr.common.message.Message.create_reply:9 of msgid "" -"Time-to-live for this message in seconds. If unset, it will be set based " -"on the remaining time for the received message before it expires. This " -"follows the equation: ttl = msg.meta.ttl - (reply.meta.created_at - " -"msg.meta.created_at)" +"Time-to-live for this message in seconds. If unset, it will be set based on " +"the remaining time for the received message before it expires. This follows " +"the equation: ttl = msg.meta.ttl - (reply.meta.created_at - msg.meta." +"created_at)" msgstr "" +"이 메시지의 남은 시간(초)입니다. 설정하지 않으면 수신된 메시지가 만료되기 " +"전까지 남은 시간을 기준으로 설정됩니다. 이는 다음과 같은 공식을 따릅니다: " +"ttl = msg.meta.ttl - (reply.meta.created_at - msg.meta.created_at)" #: flwr.common.message.Message.create_error_reply:5 #: flwr.common.message.Message.create_reply:9 of msgid "" -"Time-to-live for this message in seconds. If unset, it will be set based " -"on the remaining time for the received message before it expires. This " -"follows the equation:" +"Time-to-live for this message in seconds. If unset, it will be set based on " +"the remaining time for the received message before it expires. This follows " +"the equation:" msgstr "" +"이 메시지의 남은 시간(초)입니다. 설정하지 않으면 수신된 메시지가 만료되기 " +"전까지 남은 시간을 기준으로 설정됩니다. 이는 다음 공식을 따릅니다:" #: flwr.common.message.Message.create_error_reply:9 #: flwr.common.message.Message.create_reply:13 of msgid "ttl = msg.meta.ttl - (reply.meta.created_at - msg.meta.created_at)" -msgstr "" +msgstr "ttl = msg.meta.ttl - (reply.meta.created_at - msg.meta.created_at)" #: flwr.common.message.Message.create_reply:3 of msgid "" -"The method generates a new `Message` as a reply to this message. It " -"inherits 'run_id', 'src_node_id', 'dst_node_id', and 'message_type' from " -"this message and sets 'reply_to_message' to the ID of this message." +"The method generates a new `Message` as a reply to this message. It inherits " +"'run_id', 'src_node_id', 'dst_node_id', and 'message_type' from this message " +"and sets 'reply_to_message' to the ID of this message." msgstr "" +"이 메서드는 이 메시지에 대한 응답으로 새로운 '메시지'를 생성합니다. 이 " +"메시지에서 'run_id', 'src_node_id', 'dst_node_id', 'message_type'을 상속하고 " +"'reply_to_message'를 이 메시지의 ID로 설정합니다." #: flwr.common.message.Message.create_reply:7 of msgid "The content for the reply message." -msgstr "" +msgstr "답장 메시지의 콘텐츠입니다." #: flwr.common.message.Message.create_reply:16 of msgid "A new `Message` instance representing the reply." -msgstr "" +msgstr "답장을 나타내는 새로운 `메시지` 인스턴스입니다." #: ../../source/ref-api/flwr.common.MessageType.rst:2 msgid "MessageType" -msgstr "" +msgstr "MessageType" #: ../../source/ref-api/flwr.common.MessageType.rst:30::1 msgid ":py:obj:`EVALUATE `\\" -msgstr "" +msgstr ":py:obj:`EVALUATE `\\" #: ../../source/ref-api/flwr.common.MessageType.rst:30::1 msgid ":py:obj:`QUERY `\\" -msgstr "" +msgstr ":py:obj:`QUERY `\\" #: ../../source/ref-api/flwr.common.MessageType.rst:30::1 msgid ":py:obj:`TRAIN `\\" -msgstr "" +msgstr ":py:obj:`TRAIN `\\" #: ../../source/ref-api/flwr.common.MessageTypeLegacy.rst:2 msgid "MessageTypeLegacy" -msgstr "" +msgstr "MessageTypeLegacy" #: ../../source/ref-api/flwr.common.MessageTypeLegacy.rst:29::1 -msgid ":py:obj:`GET_PARAMETERS `\\" +msgid "" +":py:obj:`GET_PARAMETERS `\\" msgstr "" +":py:obj:`GET_PARAMETERS `\\" #: ../../source/ref-api/flwr.common.MessageTypeLegacy.rst:29::1 -msgid ":py:obj:`GET_PROPERTIES `\\" +msgid "" +":py:obj:`GET_PROPERTIES `\\" msgstr "" +":py:obj:`GET_PROPERTIES `\\" #: flwr.common.Metadata.created_at:1::1 #: flwr.common.Metadata.run_id:1 flwr.common.message.Metadata:3 of msgid "An identifier for the current run." -msgstr "" +msgstr "현재 실행에 대한 식별자입니다." #: flwr.common.Metadata.created_at:1::1 #: flwr.common.Metadata.message_id:1 flwr.common.message.Metadata:5 of msgid "An identifier for the current message." -msgstr "" +msgstr "현재 메시지의 식별자입니다." #: flwr.common.Metadata.created_at:1::1 #: flwr.common.Metadata.src_node_id:1 flwr.common.message.Metadata:7 of msgid "An identifier for the node sending this message." -msgstr "" +msgstr "이 메시지를 보내는 노드의 식별자입니다." #: flwr.common.Metadata.created_at:1::1 #: flwr.common.Metadata.dst_node_id:1 flwr.common.message.Metadata:9 of msgid "An identifier for the node receiving this message." -msgstr "" +msgstr "이 메시지를 수신하는 노드의 식별자입니다." #: flwr.common.Metadata.created_at:1::1 #: flwr.common.Metadata.reply_to_message:1 flwr.common.message.Metadata:11 of msgid "An identifier for the message this message replies to." -msgstr "" +msgstr "이 메시지가 회신하는 메시지의 식별자입니다." #: flwr.common.message.Metadata:13 of msgid "" -"An identifier for grouping messages. In some settings, this is used as " -"the FL round." -msgstr "" +"An identifier for grouping messages. In some settings, this is used as the " +"FL round." +msgstr "메시지를 그룹화하기 위한 식별자입니다. 일부 설정에서는 FL 라운드로 " +"사용됩니다." #: flwr.common.message.Metadata:16 of msgid "Time-to-live for this message in seconds." -msgstr "" +msgstr "이 메시지의 유효 시간(초)입니다." #: flwr.common.Metadata.created_at:1::1 #: flwr.common.Metadata.message_type:1 flwr.common.message.Metadata:18 of msgid "A string that encodes the action to be executed on the receiving end." -msgstr "" +msgstr "수신 측에서 실행할 작업을 인코딩하는 문자열입니다." #: flwr.common.message.Metadata:21 of msgid "" -"An identifier that can be used when loading a particular data partition " -"for a ClientApp. Making use of this identifier is more relevant when " -"conducting simulations." +"An identifier that can be used when loading a particular data partition for " +"a ClientApp. Making use of this identifier is more relevant when conducting " +"simulations." msgstr "" +"클라이언트 앱의 특정 데이터 파티션을 로드할 때 사용할 수 있는 식별자입니다. " +"시뮬레이션을 수행할 때 이 식별자를 사용하는 것이 더 적절합니다." #: flwr.common.Metadata.created_at:1::1 of msgid ":py:obj:`created_at `\\" -msgstr "" +msgstr ":py:obj:`created_at `\\" #: flwr.common.Metadata.created_at:1 #: flwr.common.Metadata.created_at:1::1 of msgid "Unix timestamp when the message was created." -msgstr "" +msgstr "메시지가 생성된 때의 Unix timestamp입니다." #: flwr.common.Metadata.created_at:1::1 of msgid ":py:obj:`dst_node_id `\\" -msgstr "" +msgstr ":py:obj:`dst_node_id `\\" #: flwr.common.Metadata.created_at:1::1 of msgid ":py:obj:`group_id `\\" -msgstr "" +msgstr ":py:obj:`group_id `\\" #: flwr.common.Metadata.created_at:1::1 #: flwr.common.Metadata.group_id:1 of msgid "An identifier for grouping messages." -msgstr "" +msgstr "메시지를 그룹화하기 위한 식별자입니다." #: flwr.common.Metadata.created_at:1::1 of msgid ":py:obj:`message_id `\\" -msgstr "" +msgstr ":py:obj:`message_id `\\" #: flwr.common.Metadata.created_at:1::1 of msgid ":py:obj:`message_type `\\" -msgstr "" +msgstr ":py:obj:`message_type `\\" #: flwr.common.Metadata.created_at:1::1 of msgid ":py:obj:`partition_id `\\" -msgstr "" +msgstr ":py:obj:`partition_id `\\" #: flwr.common.Metadata.created_at:1::1 #: flwr.common.Metadata.partition_id:1 of msgid "An identifier telling which data partition a ClientApp should use." -msgstr "" +msgstr "클라이언트앱이 사용해야 하는 데이터 파티션을 알려주는 식별자입니다." #: flwr.common.Metadata.created_at:1::1 of msgid ":py:obj:`reply_to_message `\\" -msgstr "" +msgstr ":py:obj:`reply_to_message `\\" #: flwr.common.Metadata.created_at:1::1 of msgid ":py:obj:`run_id `\\" -msgstr "" +msgstr ":py:obj:`run_id `\\" #: flwr.common.Metadata.created_at:1::1 of msgid ":py:obj:`src_node_id `\\" -msgstr "" +msgstr ":py:obj:`src_node_id `\\" #: flwr.common.Metadata.created_at:1::1 of msgid ":py:obj:`ttl `\\" -msgstr "" +msgstr ":py:obj:`ttl `\\" #: flwr.common.Metadata.created_at:1::1 flwr.common.Metadata.ttl:1 #: of msgid "Time-to-live for this message." -msgstr "" +msgstr "이 메시지를 기다리는 시간입니다." #: ../../source/ref-api/flwr.common.MetricsRecord.rst:2 msgid "MetricsRecord" -msgstr "" +msgstr "MetricsRecord" #: flwr.common.record.metricsrecord.MetricsRecord:1 of msgid "" -"Bases: :py:class:`~flwr.common.record.typeddict.TypedDict`\\ " -"[:py:class:`str`, :py:class:`int` | :py:class:`float` | " -":py:class:`~typing.List`\\ [:py:class:`int`] | :py:class:`~typing.List`\\" -" [:py:class:`float`]]" +"Bases: :py:class:`~flwr.common.record.typeddict.TypedDict`\\ [:py:class:" +"`str`, :py:class:`int` | :py:class:`float` | :py:class:`~typing.List`\\ [:py:" +"class:`int`] | :py:class:`~typing.List`\\ [:py:class:`float`]]" msgstr "" +"Bases: :py:class:`~flwr.common.record.typeddict.TypedDict`\\ [:py:class:`str`" +", :py:class:`int` | :py:class:`float` | :py:class:`~typing.List`\\ " +"[:py:class:`int`] | :py:class:`~typing.List`\\ [:py:class:`float`]]" #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid ":py:obj:`clear `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`clear `\\ \\(\\)" #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid ":py:obj:`count_bytes `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`count_bytes `\\ \\(\\)" #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid ":py:obj:`get `\\ \\(k\\[\\,d\\]\\)" -msgstr "" +msgstr ":py:obj:`get `\\ \\(k\\[\\,d\\]\\)" #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid ":py:obj:`items `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`items `\\ \\(\\)" #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid ":py:obj:`keys `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`keys `\\ \\(\\)" #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid ":py:obj:`pop `\\ \\(k\\[\\,d\\]\\)" -msgstr "" +msgstr ":py:obj:`pop `\\ \\(k\\[\\,d\\]\\)" #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid "" ":py:obj:`update `\\ \\(\\[E\\, " "\\]\\*\\*F\\)" msgstr "" +":py:obj:`update `\\ \\(\\[E\\, \\]\\*\\*F\\" +")" #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid ":py:obj:`values `\\ \\(\\)" msgstr "" +":py:obj:`update `\\ \\(\\[E\\, \\]\\*\\*F\\" +")" #: ../../source/ref-api/flwr.common.NDArray.rst:2 msgid "NDArray" -msgstr "" +msgstr "NDArray" #: ../../source/ref-api/flwr.common.Parameters.rst:29::1 msgid ":py:obj:`tensors `\\" -msgstr "" +msgstr ":py:obj:`tensors `\\" #: ../../source/ref-api/flwr.common.Parameters.rst:29::1 msgid ":py:obj:`tensor_type `\\" -msgstr "" +msgstr ":py:obj:`tensor_type `\\" #: ../../source/ref-api/flwr.common.ParametersRecord.rst:2 msgid "ParametersRecord" -msgstr "" +msgstr "ParametersRecord" #: flwr.common.record.parametersrecord.ParametersRecord:1 of msgid "" -"Bases: :py:class:`~flwr.common.record.typeddict.TypedDict`\\ " -"[:py:class:`str`, :py:class:`~flwr.common.record.parametersrecord.Array`]" +"Bases: :py:class:`~flwr.common.record.typeddict.TypedDict`\\ [:py:class:" +"`str`, :py:class:`~flwr.common.record.parametersrecord.Array`]" msgstr "" +"Bases: :py:class:`~flwr.common.record.typeddict.TypedDict`\\ [:py:class:`str`" +", :py:class:`~flwr.common.record.parametersrecord.Array`]" #: flwr.common.record.parametersrecord.ParametersRecord:3 of msgid "" -"A dataclass storing named Arrays in order. This means that it holds " -"entries as an OrderedDict[str, Array]. ParametersRecord objects can be " -"viewed as an equivalent to PyTorch's state_dict, but holding serialised " -"tensors instead." +"A dataclass storing named Arrays in order. This means that it holds entries " +"as an OrderedDict[str, Array]. ParametersRecord objects can be viewed as an " +"equivalent to PyTorch's state_dict, but holding serialised tensors instead." msgstr "" +"Arrays라는 이름의 데이터 클래스를 순서대로 저장합니다. 즉, OrderedDict[str, " +"Array]로 항목을 보유합니다. ParametersRecord 객체는 파이토치의 state_dict와 " +"동등한 것으로 볼 수 있지만, 대신 직렬화된 텐서를 보유합니다." #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid ":py:obj:`clear `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`clear `\\ \\(\\)" #: flwr.common.record.typeddict.TypedDict.clear:1::1 of -msgid ":py:obj:`count_bytes `\\ \\(\\)" +msgid "" +":py:obj:`count_bytes `\\ \\(\\)" msgstr "" +":py:obj:`count_bytes `\\ \\(\\)" #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid ":py:obj:`get `\\ \\(k\\[\\,d\\]\\)" -msgstr "" +msgstr ":py:obj:`get `\\ \\(k\\[\\,d\\]\\)" #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid ":py:obj:`items `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`items `\\ \\(\\)" #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid ":py:obj:`keys `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`keys `\\ \\(\\)" #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid ":py:obj:`pop `\\ \\(k\\[\\,d\\]\\)" -msgstr "" +msgstr ":py:obj:`pop `\\ \\(k\\[\\,d\\]\\)" #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid "" ":py:obj:`update `\\ \\(\\[E\\, " "\\]\\*\\*F\\)" msgstr "" +":py:obj:`update `\\ \\(\\[E\\, \\]\\*\\*" +"F\\)" #: flwr.common.record.typeddict.TypedDict.clear:1::1 of msgid ":py:obj:`values `\\ \\(\\)" -msgstr "" +msgstr ":py:obj:`values `\\ \\(\\)" #: flwr.common.record.parametersrecord.ParametersRecord.count_bytes:3 of msgid "" -"Note that a small amount of Bytes might also be included in this counting" -" that correspond to metadata of the serialized object (e.g. of NumPy " -"array) needed for deseralization." -msgstr "" +"Note that a small amount of Bytes might also be included in this counting " +"that correspond to metadata of the serialized object (e.g. of NumPy array) " +"needed for deseralization." +msgstr "역직렬화에 필요한 직렬화된 객체의 메타데이터(예: NumPy 배열)에 해당하는 " +"소량의 바이트도 이 카운팅에 포함될 수 있습니다." #: ../../source/ref-api/flwr.common.ReconnectIns.rst:2 msgid "ReconnectIns" -msgstr "" +msgstr "ReconnectIns" #: ../../source/ref-api/flwr.common.ReconnectIns.rst:28::1 msgid ":py:obj:`seconds `\\" -msgstr "" +msgstr ":py:obj:`seconds `\\" #: ../../source/ref-api/flwr.common.RecordSet.rst:2 msgid "RecordSet" -msgstr "" +msgstr "RecordSet" #: flwr.common.RecordSet.configs_records:1::1 of msgid ":py:obj:`configs_records `\\" -msgstr "" +msgstr ":py:obj:`configs_records `\\" #: flwr.common.RecordSet.configs_records:1 #: flwr.common.RecordSet.configs_records:1::1 of msgid "Dictionary holding ConfigsRecord instances." -msgstr "" +msgstr "Dictionary holding ConfigsRecord instances." #: flwr.common.RecordSet.configs_records:1::1 of msgid ":py:obj:`metrics_records `\\" -msgstr "" +msgstr ":py:obj:`metrics_records `\\" #: flwr.common.RecordSet.configs_records:1::1 #: flwr.common.RecordSet.metrics_records:1 of msgid "Dictionary holding MetricsRecord instances." -msgstr "" +msgstr "Dictionary holding MetricsRecord instances." #: flwr.common.RecordSet.configs_records:1::1 of -msgid ":py:obj:`parameters_records `\\" +msgid "" +":py:obj:`parameters_records `\\" msgstr "" +":py:obj:`parameters_records `\\" #: flwr.common.RecordSet.configs_records:1::1 #: flwr.common.RecordSet.parameters_records:1 of msgid "Dictionary holding ParametersRecord instances." -msgstr "" +msgstr "Dictionary holding ParametersRecord instances." #: ../../source/ref-api/flwr.common.ServerMessage.rst:2 msgid "ServerMessage" -msgstr "" +msgstr "ServerMessage" #: ../../source/ref-api/flwr.common.ServerMessage.rst:31::1 msgid ":py:obj:`evaluate_ins `\\" -msgstr "" +msgstr ":py:obj:`evaluate_ins `\\" #: ../../source/ref-api/flwr.common.ServerMessage.rst:31::1 msgid ":py:obj:`fit_ins `\\" -msgstr "" +msgstr ":py:obj:`fit_ins `\\" #: ../../source/ref-api/flwr.common.ServerMessage.rst:31::1 msgid "" -":py:obj:`get_parameters_ins " -"`\\" +":py:obj:`get_parameters_ins `\\" msgstr "" +":py:obj:`get_parameters_ins `\\" #: ../../source/ref-api/flwr.common.ServerMessage.rst:31::1 msgid "" -":py:obj:`get_properties_ins " -"`\\" +":py:obj:`get_properties_ins `\\" msgstr "" +":py:obj:`get_properties_ins `\\" #: ../../source/ref-api/flwr.common.Status.rst:2 msgid "Status" -msgstr "" +msgstr "Status" #: ../../source/ref-api/flwr.common.Status.rst:29::1 msgid ":py:obj:`code `\\" -msgstr "" +msgstr ":py:obj:`code `\\" #: ../../source/ref-api/flwr.common.Status.rst:29::1 msgid ":py:obj:`message `\\" -msgstr "" +msgstr ":py:obj:`message `\\" #: ../../source/ref-api/flwr.common.array_from_numpy.rst:2 msgid "array\\_from\\_numpy" -msgstr "" +msgstr "array\\_from\\_numpy" #: ../../source/ref-api/flwr.common.bytes_to_ndarray.rst:2 msgid "bytes\\_to\\_ndarray" -msgstr "" +msgstr "bytes\\_to\\_ndarray" #: ../../source/ref-api/flwr.common.configure.rst:2 msgid "configure" -msgstr "" +msgstr "구성" #: ../../source/ref-api/flwr.common.event.rst:2 msgid "event" -msgstr "" +msgstr "이벤트" #: ../../source/ref-api/flwr.common.log.rst:2 msgid "log" -msgstr "" +msgstr "로그" #: 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 "예외 정보를 전달하려면 키워드 argument exc_info를 참 값과 함께 사용합니다." #: logging.Logger.log:6 of #, python-format @@ -9991,8 +11809,8 @@ msgstr "" #: ../../source/ref-api/flwr.server.rst:38::1 msgid "" -":py:obj:`ServerConfig `\\ \\(\\[num\\_rounds\\," -" round\\_timeout\\]\\)" +":py:obj:`ServerConfig `\\ \\(\\[num\\_rounds\\, " +"round\\_timeout\\]\\)" msgstr "" #: ../../source/ref-api/flwr.server.rst:38::1 @@ -10001,7 +11819,8 @@ msgid "Flower server config." msgstr "" #: ../../source/ref-api/flwr.server.rst:38::1 -msgid ":py:obj:`SimpleClientManager `\\ \\(\\)" +msgid "" +":py:obj:`SimpleClientManager `\\ \\(\\)" msgstr "" #: ../../source/ref-api/flwr.server.rst:38::1 @@ -10043,7 +11862,8 @@ msgid "Return all available clients." msgstr "" #: flwr.server.client_manager.ClientManager.all:1::1 of -msgid ":py:obj:`num_available `\\ \\(\\)" +msgid "" +":py:obj:`num_available `\\ \\(\\)" msgstr "" #: flwr.server.client_manager.ClientManager.all:1::1 @@ -10066,8 +11886,8 @@ msgstr "" #: flwr.server.client_manager.ClientManager.all:1::1 of msgid "" -":py:obj:`sample `\\ " -"\\(num\\_clients\\[\\, min\\_num\\_clients\\, criterion\\]\\)" +":py:obj:`sample `\\ \\(num\\_clients\\[\\, " +"min\\_num\\_clients\\, criterion\\]\\)" msgstr "" #: flwr.server.client_manager.ClientManager.all:1::1 @@ -10078,7 +11898,8 @@ msgid "Sample a number of Flower ClientProxy instances." msgstr "" #: flwr.server.client_manager.ClientManager.all:1::1 of -msgid ":py:obj:`unregister `\\ \\(client\\)" +msgid "" +":py:obj:`unregister `\\ \\(client\\)" msgstr "" #: flwr.server.client_manager.ClientManager.all:1::1 @@ -10110,8 +11931,7 @@ msgstr "" #: 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." +"ClientProxy is already registered or can not be registered for any reason." msgstr "" #: flwr.server.client_manager.ClientManager.unregister:3 @@ -10125,8 +11945,8 @@ msgstr "" #: flwr.server.driver.driver.Driver.create_message:1::1 of msgid "" -":py:obj:`create_message `\\ " -"\\(content\\, message\\_type\\, ...\\[\\, ttl\\]\\)" +":py:obj:`create_message `\\ \\(content\\, " +"message\\_type\\, ...\\[\\, ttl\\]\\)" msgstr "" #: flwr.server.driver.driver.Driver.create_message:1 @@ -10156,8 +11976,7 @@ msgstr "" #: flwr.server.driver.driver.Driver.create_message:1::1 of msgid "" -":py:obj:`push_messages `\\ " -"\\(messages\\)" +":py:obj:`push_messages `\\ \\(messages\\)" msgstr "" #: flwr.server.driver.driver.Driver.create_message:1::1 @@ -10178,20 +11997,20 @@ msgstr "" #: flwr.server.driver.driver.Driver.create_message:3 of msgid "" -"This method constructs a new `Message` with given content and metadata. " -"The `run_id` and `src_node_id` will be set automatically." +"This method constructs a new `Message` with given content and metadata. The " +"`run_id` and `src_node_id` will be set automatically." msgstr "" #: flwr.server.driver.driver.Driver.create_message:6 of msgid "" -"The content for the new message. This holds records that are to be sent " -"to the destination node." +"The content for the new message. This holds records that are to be sent to " +"the destination node." msgstr "" #: flwr.server.driver.driver.Driver.create_message:9 of msgid "" -"The type of the message, defining the action to be executed on the " -"receiving end." +"The type of the message, defining the action to be executed on the receiving " +"end." msgstr "" #: flwr.server.driver.driver.Driver.create_message:12 of @@ -10200,17 +12019,16 @@ msgstr "" #: flwr.server.driver.driver.Driver.create_message:14 of msgid "" -"The ID of the group to which this message is associated. In some " -"settings, this is used as the FL round." +"The ID of the group to which this message is associated. In some settings, " +"this is used as the FL round." msgstr "" #: flwr.server.driver.driver.Driver.create_message:17 of msgid "" -"Time-to-live for the round trip of this message, i.e., the time from " -"sending this message to receiving a reply. It specifies in seconds the " -"duration for which the message and its potential reply are considered " -"valid. If unset, the default TTL (i.e., `common.DEFAULT_TTL`) will be " -"used." +"Time-to-live for the round trip of this message, i.e., the time from sending " +"this message to receiving a reply. It specifies in seconds the duration for " +"which the message and its potential reply are considered valid. If unset, " +"the default TTL (i.e., `common.DEFAULT_TTL`) will be used." msgstr "" #: flwr.server.driver.driver.Driver.create_message:23 of @@ -10221,12 +12039,13 @@ msgstr "" #: flwr.server.driver.driver.Driver.pull_messages:3 of msgid "" -"This method is used to collect messages from the SuperLink that " -"correspond to a set of given message IDs." +"This method is used to collect messages from the SuperLink that correspond " +"to a set of given message IDs." msgstr "" #: flwr.server.driver.driver.Driver.pull_messages:6 of -msgid "An iterable of message IDs for which reply messages are to be retrieved." +msgid "" +"An iterable of message IDs for which reply messages are to be retrieved." msgstr "" #: flwr.server.driver.driver.Driver.pull_messages:9 of @@ -10235,8 +12054,8 @@ msgstr "" #: flwr.server.driver.driver.Driver.push_messages:3 of msgid "" -"This method takes an iterable of messages and sends each message to the " -"node specified in `dst_node_id`." +"This method takes an iterable of messages and sends each message to the node " +"specified in `dst_node_id`." msgstr "" #: flwr.server.driver.driver.Driver.push_messages:6 @@ -10246,34 +12065,35 @@ msgstr "" #: flwr.server.driver.driver.Driver.push_messages:9 of msgid "" -"**message_ids** -- An iterable of IDs for the messages that were sent, " -"which can be used to pull replies." +"**message_ids** -- An iterable of IDs for the messages that were sent, which " +"can be used to pull replies." msgstr "" #: flwr.server.driver.driver.Driver.send_and_receive:3 of msgid "" -"This method sends a list of messages to their destination node IDs and " -"then waits for the replies. It continues to pull replies until either all" -" replies are received or the specified timeout duration is exceeded." +"This method sends a list of messages to their destination node IDs and then " +"waits for the replies. It continues to pull replies until either all replies " +"are received or the specified timeout duration is exceeded." msgstr "" #: flwr.server.driver.driver.Driver.send_and_receive:9 of msgid "" "The timeout duration in seconds. If specified, the method will wait for " -"replies for this duration. If `None`, there is no time limit and the " -"method will wait until replies for all messages are received." +"replies for this duration. If `None`, there is no time limit and the method " +"will wait until replies for all messages are received." msgstr "" #: flwr.server.driver.driver.Driver.send_and_receive:14 of -msgid "**replies** -- An iterable of reply messages received from the SuperLink." +msgid "" +"**replies** -- An iterable of reply messages received from the SuperLink." msgstr "" #: flwr.server.driver.driver.Driver.send_and_receive:19 of msgid "" -"This method uses `push_messages` to send the messages and `pull_messages`" -" to collect the replies. If `timeout` is set, the method may not return " -"replies for all sent messages. A message remains valid until its TTL, " -"which is not affected by `timeout`." +"This method uses `push_messages` to send the messages and `pull_messages` to " +"collect the replies. If `timeout` is set, the method may not return replies " +"for all sent messages. A message remains valid until its TTL, which is not " +"affected by `timeout`." msgstr "" #: ../../source/ref-api/flwr.server.History.rst:2 @@ -10282,9 +12102,8 @@ msgstr "" #: flwr.server.history.History.add_loss_centralized:1::1 of msgid "" -":py:obj:`add_loss_centralized " -"`\\ \\(server\\_round\\, " -"loss\\)" +":py:obj:`add_loss_centralized `\\ " +"\\(server\\_round\\, loss\\)" msgstr "" #: flwr.server.history.History.add_loss_centralized:1 @@ -10294,9 +12113,8 @@ msgstr "" #: flwr.server.history.History.add_loss_centralized:1::1 of msgid "" -":py:obj:`add_loss_distributed " -"`\\ \\(server\\_round\\, " -"loss\\)" +":py:obj:`add_loss_distributed `\\ " +"\\(server\\_round\\, loss\\)" msgstr "" #: flwr.server.history.History.add_loss_centralized:1::1 @@ -10306,9 +12124,8 @@ msgstr "" #: flwr.server.history.History.add_loss_centralized:1::1 of msgid "" -":py:obj:`add_metrics_centralized " -"`\\ \\(server\\_round\\, " -"metrics\\)" +":py:obj:`add_metrics_centralized `\\ \\(server\\_round\\, metrics\\)" msgstr "" #: flwr.server.history.History.add_loss_centralized:1::1 @@ -10318,9 +12135,8 @@ msgstr "" #: flwr.server.history.History.add_loss_centralized:1::1 of msgid "" -":py:obj:`add_metrics_distributed " -"`\\ \\(server\\_round\\, " -"metrics\\)" +":py:obj:`add_metrics_distributed `\\ \\(server\\_round\\, metrics\\)" msgstr "" #: flwr.server.history.History.add_loss_centralized:1::1 @@ -10330,9 +12146,8 @@ msgstr "" #: flwr.server.history.History.add_loss_centralized:1::1 of msgid "" -":py:obj:`add_metrics_distributed_fit " -"`\\ \\(server\\_round\\," -" ...\\)" +":py:obj:`add_metrics_distributed_fit `\\ \\(server\\_round\\, ...\\)" msgstr "" #: flwr.server.history.History.add_loss_centralized:1::1 @@ -10383,8 +12198,8 @@ msgstr "" #: flwr.server.server.Server.client_manager:1::1 of msgid "" -":py:obj:`disconnect_all_clients " -"`\\ \\(timeout\\)" +":py:obj:`disconnect_all_clients `\\ \\(timeout\\)" msgstr "" #: flwr.server.server.Server.client_manager:1::1 @@ -10414,8 +12229,8 @@ msgstr "" #: flwr.server.server.Server.client_manager:1::1 of msgid "" -":py:obj:`fit_round `\\ \\(server\\_round\\," -" timeout\\)" +":py:obj:`fit_round `\\ \\(server\\_round\\, " +"timeout\\)" msgstr "" #: flwr.server.server.Server.client_manager:1::1 @@ -10435,7 +12250,8 @@ msgid "Set the max_workers used by ThreadPoolExecutor." msgstr "" #: flwr.server.server.Server.client_manager:1::1 of -msgid ":py:obj:`set_strategy `\\ \\(strategy\\)" +msgid "" +":py:obj:`set_strategy `\\ \\(strategy\\)" msgstr "" #: flwr.server.server.Server.client_manager:1::1 @@ -10470,8 +12286,8 @@ msgstr "" #: flwr.server.server_config.ServerConfig:3 of msgid "" -"All attributes have default values which allows users to configure just " -"the ones they care about." +"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 @@ -10496,14 +12312,13 @@ msgstr "" #: flwr.server.client_manager.SimpleClientManager.all:1::1 of msgid "" -":py:obj:`num_available `\\" -" \\(\\)" +":py:obj:`num_available `\\ " +"\\(\\)" msgstr "" #: flwr.server.client_manager.SimpleClientManager.all:1::1 of msgid "" -":py:obj:`register `\\ " -"\\(client\\)" +":py:obj:`register `\\ \\(client\\)" msgstr "" #: flwr.server.client_manager.SimpleClientManager.all:1::1 of @@ -10526,8 +12341,8 @@ 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." +"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 @@ -10568,8 +12383,8 @@ 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." +"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:9 flwr.simulation.app.start_simulation:28 of @@ -10580,41 +12395,41 @@ msgstr "" #: 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.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.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 "" #: 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 "" #: 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 "" #: flwr.server.app.start_server:32 of @@ -10647,8 +12462,8 @@ msgstr "" #: ../../source/ref-api/flwr.server.strategy.rst:45::1 msgid "" -":py:obj:`Bulyan `\\ \\(\\*\\, " -"fraction\\_fit\\, fraction\\_evaluate\\, ...\\)" +":py:obj:`Bulyan `\\ \\(\\*\\, fraction\\_fit\\, " +"fraction\\_evaluate\\, ...\\)" msgstr "" #: ../../source/ref-api/flwr.server.strategy.rst:45::1 @@ -10680,9 +12495,8 @@ msgstr "" #: ../../source/ref-api/flwr.server.strategy.rst:45::1 msgid "" -":py:obj:`DifferentialPrivacyClientSideAdaptiveClipping " -"`\\ " -"\\(...\\)" +":py:obj:`DifferentialPrivacyClientSideAdaptiveClipping `\\ \\(...\\)" msgstr "" #: ../../source/ref-api/flwr.server.strategy.rst:45::1 @@ -10693,9 +12507,8 @@ msgstr "" #: ../../source/ref-api/flwr.server.strategy.rst:45::1 msgid "" -":py:obj:`DifferentialPrivacyServerSideAdaptiveClipping " -"`\\ " -"\\(...\\)" +":py:obj:`DifferentialPrivacyServerSideAdaptiveClipping `\\ \\(...\\)" msgstr "" #: ../../source/ref-api/flwr.server.strategy.rst:45::1 @@ -10706,9 +12519,8 @@ msgstr "" #: ../../source/ref-api/flwr.server.strategy.rst:45::1 msgid "" -":py:obj:`DifferentialPrivacyClientSideFixedClipping " -"`\\ " -"\\(...\\)" +":py:obj:`DifferentialPrivacyClientSideFixedClipping `\\ \\(...\\)" msgstr "" #: ../../source/ref-api/flwr.server.strategy.rst:45::1 @@ -10719,9 +12531,8 @@ msgstr "" #: ../../source/ref-api/flwr.server.strategy.rst:45::1 msgid "" -":py:obj:`DifferentialPrivacyServerSideFixedClipping " -"`\\ " -"\\(...\\)" +":py:obj:`DifferentialPrivacyServerSideFixedClipping `\\ \\(...\\)" msgstr "" #: ../../source/ref-api/flwr.server.strategy.rst:45::1 @@ -10766,8 +12577,8 @@ msgstr "" #: ../../source/ref-api/flwr.server.strategy.rst:45::1 msgid "" -":py:obj:`FedAvgAndroid `\\ " -"\\(\\*\\[\\, fraction\\_fit\\, ...\\]\\)" +":py:obj:`FedAvgAndroid `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, ...\\]\\)" msgstr "" #: ../../source/ref-api/flwr.server.strategy.rst:45::1 @@ -10816,8 +12627,8 @@ msgstr "" #: ../../source/ref-api/flwr.server.strategy.rst:45::1 msgid "" -":py:obj:`FedTrimmedAvg `\\ " -"\\(\\*\\[\\, fraction\\_fit\\, ...\\]\\)" +":py:obj:`FedTrimmedAvg `\\ \\(\\*\\[\\, " +"fraction\\_fit\\, ...\\]\\)" msgstr "" #: ../../source/ref-api/flwr.server.strategy.rst:45::1 @@ -10871,9 +12682,8 @@ msgstr "" #: ../../source/ref-api/flwr.server.strategy.rst:45::1 msgid "" -":py:obj:`FaultTolerantFedAvg " -"`\\ \\(\\*\\[\\, " -"fraction\\_fit\\, ...\\]\\)" +":py:obj:`FaultTolerantFedAvg `\\ " +"\\(\\*\\[\\, fraction\\_fit\\, ...\\]\\)" msgstr "" #: ../../source/ref-api/flwr.server.strategy.rst:45::1 @@ -10883,8 +12693,8 @@ msgstr "" #: ../../source/ref-api/flwr.server.strategy.rst:45::1 msgid "" -":py:obj:`Krum `\\ \\(\\*\\[\\, " -"fraction\\_fit\\, fraction\\_evaluate\\, ...\\]\\)" +":py:obj:`Krum `\\ \\(\\*\\[\\, fraction\\_fit\\, " +"fraction\\_evaluate\\, ...\\]\\)" msgstr "" #: ../../source/ref-api/flwr.server.strategy.rst:45::1 @@ -10894,8 +12704,8 @@ msgstr "" #: ../../source/ref-api/flwr.server.strategy.rst:45::1 msgid "" -":py:obj:`QFedAvg `\\ \\(\\*\\[\\, " -"q\\_param\\, qffl\\_learning\\_rate\\, ...\\]\\)" +":py:obj:`QFedAvg `\\ \\(\\*\\[\\, q\\_param\\, " +"qffl\\_learning\\_rate\\, ...\\]\\)" msgstr "" #: ../../source/ref-api/flwr.server.strategy.rst:45::1 @@ -11063,8 +12873,8 @@ 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)" +"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 @@ -11073,9 +12883,8 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`aggregate_evaluate " -"`\\ \\(server\\_round\\, " -"results\\, ...\\)" +":py:obj:`aggregate_evaluate `\\ \\(server\\_round\\, results\\, ...\\)" msgstr "" #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1 @@ -11102,9 +12911,8 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`configure_evaluate " -"`\\ \\(server\\_round\\, " -"parameters\\, ...\\)" +":py:obj:`configure_evaluate `\\ \\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyClientSideAdaptiveClipping.aggregate_evaluate:1::1 @@ -11183,9 +12991,8 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`initialize_parameters " -"`\\ " -"\\(client\\_manager\\)" +":py:obj:`initialize_parameters `\\ \\(client\\_manager\\)" msgstr "" #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 @@ -11202,9 +13009,8 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`num_evaluation_clients " -"`\\ " -"\\(num\\_available\\_clients\\)" +":py:obj:`num_evaluation_clients `\\ \\(num\\_available\\_clients\\)" msgstr "" #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 @@ -11221,8 +13027,8 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`num_fit_clients `\\" -" \\(num\\_available\\_clients\\)" +":py:obj:`num_fit_clients `\\ " +"\\(num\\_available\\_clients\\)" msgstr "" #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 @@ -11253,9 +13059,8 @@ msgstr "" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`aggregate_evaluate " -"`\\ " -"\\(server\\_round\\, results\\, ...\\)" +":py:obj:`aggregate_evaluate `\\ \\(server\\_round\\, results\\, ...\\)" msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyClientSideAdaptiveClipping.aggregate_evaluate:1 @@ -11275,9 +13080,8 @@ msgstr "" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`aggregate_fit " -"`\\ " -"\\(server\\_round\\, results\\, failures\\)" +":py:obj:`aggregate_fit `\\ \\(server\\_round\\, results\\, failures\\)" msgstr "" #: flwr.server.strategy.dpfedavg_adaptive.DPFedAvgAdaptive.aggregate_fit:1 @@ -11289,9 +13093,8 @@ msgstr "" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`configure_evaluate " -"`\\ " -"\\(server\\_round\\, parameters\\, ...\\)" +":py:obj:`configure_evaluate `\\ \\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 @@ -11302,9 +13105,8 @@ msgstr "" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`configure_fit " -"`\\ " -"\\(server\\_round\\, parameters\\, ...\\)" +":py:obj:`configure_fit `\\ \\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 @@ -11324,15 +13126,15 @@ msgstr "" #: flwr.server.strategy.dp_fixed_clipping.DifferentialPrivacyServerSideFixedClipping.evaluate:1 #: 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." +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\\)" +":py:obj:`initialize_parameters `\\ \\(client\\_manager\\)" msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyClientSideAdaptiveClipping.aggregate_evaluate:1::1 @@ -11371,9 +13173,9 @@ msgstr "" 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 "" #: ../../source/ref-api/flwr.server.strategy.DPFedAvgFixed.rst:2 @@ -11393,16 +13195,14 @@ msgstr "" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`aggregate_evaluate " -"`\\ " -"\\(server\\_round\\, results\\, ...\\)" +":py:obj:`aggregate_evaluate `\\ \\(server\\_round\\, results\\, ...\\)" msgstr "" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`aggregate_fit " -"`\\ " +":py:obj:`aggregate_fit `\\ " "\\(server\\_round\\, results\\, failures\\)" msgstr "" @@ -11414,24 +13214,21 @@ msgstr "" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`configure_evaluate " -"`\\ " -"\\(server\\_round\\, parameters\\, ...\\)" +":py:obj:`configure_evaluate `\\ \\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`configure_fit " -"`\\ " +":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)." +"Configure the next round of training incorporating Differential Privacy (DP)." msgstr "" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 @@ -11444,25 +13241,23 @@ msgstr "" #: flwr.server.strategy.dpfedavg_fixed.DPFedAvgFixed.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`initialize_parameters " -"`\\ " -"\\(client\\_manager\\)" +":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." +"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." +"**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.DifferentialPrivacyClientSideAdaptiveClipping.rst:2 @@ -11479,9 +13274,8 @@ msgstr "" msgid "" "In comparison to `DifferentialPrivacyServerSideAdaptiveClipping`, which " "performs clipping on the server-side, " -"`DifferentialPrivacyClientSideAdaptiveClipping` expects clipping to " -"happen on the client-side, usually by using the built-in " -"`adaptiveclipping_mod`." +"`DifferentialPrivacyClientSideAdaptiveClipping` expects clipping to happen " +"on the client-side, usually by using the built-in `adaptiveclipping_mod`." msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyClientSideAdaptiveClipping:10 @@ -11517,22 +13311,23 @@ msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyClientSideAdaptiveClipping:19 #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyServerSideAdaptiveClipping:12 #: of -msgid "The desired quantile of updates which should be clipped. Defaults to 0.5." +msgid "" +"The desired quantile of updates which should be clipped. Defaults to 0.5." msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyClientSideAdaptiveClipping:21 #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyServerSideAdaptiveClipping:14 #: of msgid "" -"The learning rate for the clipping norm adaptation. Defaults to 0.2. " -"Andrew et al. recommends to set to 0.2." +"The learning rate for the clipping norm adaptation. Defaults to 0.2. Andrew " +"et al. recommends to set to 0.2." msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyClientSideAdaptiveClipping:24 #: of msgid "" -"The stddev of the noise added to the count of updates currently below the" -" estimate. Andrew et al. recommends to set to `expected_num_records/20`" +"The stddev of the noise added to the count of updates currently below the " +"estimate. Andrew et al. recommends to set to `expected_num_records/20`" msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyClientSideAdaptiveClipping:30 @@ -11546,8 +13341,8 @@ msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyClientSideAdaptiveClipping:34 #: of msgid "" -"Wrap the strategy with the " -"`DifferentialPrivacyClientSideAdaptiveClipping` wrapper:" +"Wrap the strategy with the `DifferentialPrivacyClientSideAdaptiveClipping` " +"wrapper:" msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyClientSideAdaptiveClipping:40 @@ -11558,17 +13353,17 @@ msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyClientSideAdaptiveClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`aggregate_evaluate " -"`\\" -" \\(server\\_round\\, results\\, ...\\)" +":py:obj:`aggregate_evaluate `\\ " +"\\(server\\_round\\, results\\, ...\\)" msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyClientSideAdaptiveClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`aggregate_fit " -"`\\" -" \\(server\\_round\\, results\\, failures\\)" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyClientSideAdaptiveClipping.aggregate_evaluate:1::1 @@ -11582,33 +13377,33 @@ msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyClientSideAdaptiveClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`configure_evaluate " -"`\\" -" \\(server\\_round\\, parameters\\, ...\\)" +":py:obj:`configure_evaluate `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyClientSideAdaptiveClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`configure_fit " -"`\\" -" \\(server\\_round\\, parameters\\, ...\\)" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyClientSideAdaptiveClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`evaluate " -"`\\" -" \\(server\\_round\\, parameters\\)" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyClientSideAdaptiveClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`initialize_parameters " -"`\\" -" \\(client\\_manager\\)" +":py:obj:`initialize_parameters `\\ " +"\\(client\\_manager\\)" msgstr "" #: ../../source/ref-api/flwr.server.strategy.DifferentialPrivacyClientSideFixedClipping.rst:2 @@ -11625,16 +13420,16 @@ msgstr "" msgid "" "In comparison to `DifferentialPrivacyServerSideFixedClipping`, which " "performs clipping on the server-side, " -"`DifferentialPrivacyClientSideFixedClipping` expects clipping to happen " -"on the client-side, usually by using the built-in `fixedclipping_mod`." +"`DifferentialPrivacyClientSideFixedClipping` expects clipping to happen on " +"the client-side, usually by using the built-in `fixedclipping_mod`." msgstr "" #: flwr.server.strategy.dp_fixed_clipping.DifferentialPrivacyClientSideFixedClipping:12 #: flwr.server.strategy.dp_fixed_clipping.DifferentialPrivacyServerSideFixedClipping:5 #: of msgid "" -"The noise multiplier for the Gaussian mechanism for model updates. A " -"value of 1.0 or higher is recommended for strong privacy." +"The noise multiplier for the Gaussian mechanism for model updates. A value " +"of 1.0 or higher is recommended for strong privacy." msgstr "" #: flwr.server.strategy.dp_fixed_clipping.DifferentialPrivacyClientSideFixedClipping:26 @@ -11652,17 +13447,17 @@ msgstr "" #: flwr.server.strategy.dp_fixed_clipping.DifferentialPrivacyClientSideFixedClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`aggregate_evaluate " -"`\\" -" \\(server\\_round\\, results\\, ...\\)" +":py:obj:`aggregate_evaluate `\\ " +"\\(server\\_round\\, results\\, ...\\)" msgstr "" #: flwr.server.strategy.dp_fixed_clipping.DifferentialPrivacyClientSideFixedClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`aggregate_fit " -"`\\" -" \\(server\\_round\\, results\\, failures\\)" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" msgstr "" #: flwr.server.strategy.dp_fixed_clipping.DifferentialPrivacyClientSideFixedClipping.aggregate_evaluate:1::1 @@ -11674,33 +13469,33 @@ msgstr "" #: flwr.server.strategy.dp_fixed_clipping.DifferentialPrivacyClientSideFixedClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`configure_evaluate " -"`\\" -" \\(server\\_round\\, parameters\\, ...\\)" +":py:obj:`configure_evaluate `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.dp_fixed_clipping.DifferentialPrivacyClientSideFixedClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`configure_fit " -"`\\" -" \\(server\\_round\\, parameters\\, ...\\)" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.dp_fixed_clipping.DifferentialPrivacyClientSideFixedClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`evaluate " -"`\\" -" \\(server\\_round\\, parameters\\)" +":py:obj:`evaluate `\\ \\(server\\_round\\, " +"parameters\\)" msgstr "" #: flwr.server.strategy.dp_fixed_clipping.DifferentialPrivacyClientSideFixedClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`initialize_parameters " -"`\\" -" \\(client\\_manager\\)" +":py:obj:`initialize_parameters `\\ " +"\\(client\\_manager\\)" msgstr "" #: ../../source/ref-api/flwr.server.strategy.DifferentialPrivacyServerSideAdaptiveClipping.rst:2 @@ -11710,9 +13505,8 @@ msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyServerSideAdaptiveClipping:17 #: of msgid "" -"The standard deviation of the noise added to the count of updates below " -"the estimate. Andrew et al. recommends to set to " -"`expected_num_records/20`" +"The standard deviation of the noise added to the count of updates below the " +"estimate. Andrew et al. recommends to set to `expected_num_records/20`" msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyServerSideAdaptiveClipping:27 @@ -11725,49 +13519,49 @@ msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyServerSideAdaptiveClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`aggregate_evaluate " -"`\\" -" \\(server\\_round\\, results\\, ...\\)" +":py:obj:`aggregate_evaluate `\\ " +"\\(server\\_round\\, results\\, ...\\)" msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyServerSideAdaptiveClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`aggregate_fit " -"`\\" -" \\(server\\_round\\, results\\, failures\\)" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyServerSideAdaptiveClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`configure_evaluate " -"`\\" -" \\(server\\_round\\, parameters\\, ...\\)" +":py:obj:`configure_evaluate `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyServerSideAdaptiveClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`configure_fit " -"`\\" -" \\(server\\_round\\, parameters\\, ...\\)" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyServerSideAdaptiveClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`evaluate " -"`\\" -" \\(server\\_round\\, parameters\\)" +":py:obj:`evaluate `\\ " +"\\(server\\_round\\, parameters\\)" msgstr "" #: flwr.server.strategy.dp_adaptive_clipping.DifferentialPrivacyServerSideAdaptiveClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`initialize_parameters " -"`\\" -" \\(client\\_manager\\)" +":py:obj:`initialize_parameters `\\ " +"\\(client\\_manager\\)" msgstr "" #: ../../source/ref-api/flwr.server.strategy.DifferentialPrivacyServerSideFixedClipping.rst:2 @@ -11777,24 +13571,23 @@ msgstr "" #: flwr.server.strategy.dp_fixed_clipping.DifferentialPrivacyServerSideFixedClipping:19 #: of msgid "" -"Wrap the strategy with the DifferentialPrivacyServerSideFixedClipping " -"wrapper" +"Wrap the strategy with the DifferentialPrivacyServerSideFixedClipping wrapper" msgstr "" #: flwr.server.strategy.dp_fixed_clipping.DifferentialPrivacyServerSideFixedClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`aggregate_evaluate " -"`\\" -" \\(server\\_round\\, results\\, ...\\)" +":py:obj:`aggregate_evaluate `\\ " +"\\(server\\_round\\, results\\, ...\\)" msgstr "" #: flwr.server.strategy.dp_fixed_clipping.DifferentialPrivacyServerSideFixedClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`aggregate_fit " -"`\\" -" \\(server\\_round\\, results\\, failures\\)" +":py:obj:`aggregate_fit `\\ " +"\\(server\\_round\\, results\\, failures\\)" msgstr "" #: flwr.server.strategy.dp_fixed_clipping.DifferentialPrivacyServerSideFixedClipping.aggregate_evaluate:1::1 @@ -11806,33 +13599,33 @@ msgstr "" #: flwr.server.strategy.dp_fixed_clipping.DifferentialPrivacyServerSideFixedClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`configure_evaluate " -"`\\" -" \\(server\\_round\\, parameters\\, ...\\)" +":py:obj:`configure_evaluate `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.dp_fixed_clipping.DifferentialPrivacyServerSideFixedClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`configure_fit " -"`\\" -" \\(server\\_round\\, parameters\\, ...\\)" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.dp_fixed_clipping.DifferentialPrivacyServerSideFixedClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`evaluate " -"`\\" -" \\(server\\_round\\, parameters\\)" +":py:obj:`evaluate `\\ \\(server\\_round\\, " +"parameters\\)" msgstr "" #: flwr.server.strategy.dp_fixed_clipping.DifferentialPrivacyServerSideFixedClipping.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`initialize_parameters " -"`\\" -" \\(client\\_manager\\)" +":py:obj:`initialize_parameters `\\ " +"\\(client\\_manager\\)" msgstr "" #: flwr.server.strategy.dp_fixed_clipping.DifferentialPrivacyServerSideFixedClipping.aggregate_fit:3 @@ -11847,17 +13640,15 @@ msgstr "" #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`aggregate_evaluate " -"`\\ " -"\\(server\\_round\\, results\\, ...\\)" +":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\\)" +":py:obj:`aggregate_fit `\\ \\(server\\_round\\, results\\, failures\\)" msgstr "" #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 @@ -11879,17 +13670,15 @@ msgstr "" #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`configure_evaluate " -"`\\ " -"\\(server\\_round\\, parameters\\, ...\\)" +":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\\, ...\\)" +":py:obj:`configure_fit `\\ \\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 @@ -11902,25 +13691,22 @@ msgstr "" #: flwr.server.strategy.fault_tolerant_fedavg.FaultTolerantFedAvg.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`initialize_parameters " -"`\\ " -"\\(client\\_manager\\)" +":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\\)" +":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\\)" +":py:obj:`num_fit_clients `\\ \\(num\\_available\\_clients\\)" msgstr "" #: ../../source/ref-api/flwr.server.strategy.FedAdagrad.rst:2 @@ -11973,28 +13759,26 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`aggregate_evaluate " -"`\\ " -"\\(server\\_round\\, results\\, ...\\)" +":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\\)" +":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\\, ...\\)" +":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\\, ...\\)" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of @@ -12005,23 +13789,20 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`initialize_parameters " -"`\\ " -"\\(client\\_manager\\)" +":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\\)" +":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\\)" +":py:obj:`num_fit_clients `\\ \\(num\\_available\\_clients\\)" msgstr "" #: ../../source/ref-api/flwr.server.strategy.FedAdam.rst:2 @@ -12040,9 +13821,8 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`aggregate_evaluate " -"`\\ \\(server\\_round\\," -" results\\, ...\\)" +":py:obj:`aggregate_evaluate `\\ \\(server\\_round\\, results\\, ...\\)" msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of @@ -12053,9 +13833,8 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`configure_evaluate " -"`\\ \\(server\\_round\\," -" parameters\\, ...\\)" +":py:obj:`configure_evaluate `\\ \\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of @@ -12072,22 +13851,19 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`initialize_parameters " -"`\\ " -"\\(client\\_manager\\)" +":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\\)" +":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 " -"`\\ " +":py:obj:`num_fit_clients `\\ " "\\(num\\_available\\_clients\\)" msgstr "" @@ -12104,17 +13880,16 @@ msgstr "" #: 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 "" #: 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." +"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:33 of @@ -12123,9 +13898,8 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`aggregate_evaluate " -"`\\ \\(server\\_round\\, " -"results\\, ...\\)" +":py:obj:`aggregate_evaluate `\\ \\(server\\_round\\, results\\, ...\\)" msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of @@ -12136,9 +13910,8 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`configure_evaluate " -"`\\ \\(server\\_round\\, " -"parameters\\, ...\\)" +":py:obj:`configure_evaluate `\\ \\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of @@ -12155,22 +13928,20 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`initialize_parameters " -"`\\ " -"\\(client\\_manager\\)" +":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\\)" +":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\\)" +":py:obj:`num_fit_clients `\\ " +"\\(num\\_available\\_clients\\)" msgstr "" #: ../../source/ref-api/flwr.server.strategy.FedAvgAndroid.rst:2 @@ -12180,24 +13951,22 @@ msgstr "" #: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`aggregate_evaluate " -"`\\ " -"\\(server\\_round\\, results\\, ...\\)" +":py:obj:`aggregate_evaluate `\\ \\(server\\_round\\, results\\, ...\\)" msgstr "" #: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`aggregate_fit " -"`\\ " +":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\\)" +":py:obj:`bytes_to_ndarray `\\ \\(tensor\\)" msgstr "" #: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 @@ -12208,16 +13977,14 @@ msgstr "" #: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`configure_evaluate " -"`\\ " -"\\(server\\_round\\, parameters\\, ...\\)" +":py:obj:`configure_evaluate `\\ \\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`configure_fit " -"`\\ " +":py:obj:`configure_fit `\\ " "\\(server\\_round\\, parameters\\, ...\\)" msgstr "" @@ -12231,16 +13998,15 @@ msgstr "" #: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`initialize_parameters " -"`\\ " -"\\(client\\_manager\\)" +":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\\)" +":py:obj:`ndarray_to_bytes `\\ \\(ndarray\\)" msgstr "" #: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 @@ -12251,33 +14017,29 @@ msgstr "" #: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`ndarrays_to_parameters " -"`\\ " -"\\(ndarrays\\)" +":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\\)" +":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\\)" +":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\\)" +":py:obj:`parameters_to_ndarrays `\\ \\(parameters\\)" msgstr "" #: flwr.server.strategy.fedavg_android.FedAvgAndroid.aggregate_evaluate:1::1 @@ -12296,8 +14058,7 @@ msgstr "" #: flwr.server.strategy.fedavgm.FedAvgM:25 of msgid "" -"Server-side learning rate used in server-side optimization. Defaults to " -"1.0." +"Server-side learning rate used in server-side optimization. Defaults to 1.0." msgstr "" #: flwr.server.strategy.fedavgm.FedAvgM:28 of @@ -12306,9 +14067,8 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`aggregate_evaluate " -"`\\ \\(server\\_round\\," -" results\\, ...\\)" +":py:obj:`aggregate_evaluate `\\ \\(server\\_round\\, results\\, ...\\)" msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of @@ -12319,9 +14079,8 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`configure_evaluate " -"`\\ \\(server\\_round\\," -" parameters\\, ...\\)" +":py:obj:`configure_evaluate `\\ \\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of @@ -12338,22 +14097,19 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`initialize_parameters " -"`\\ " -"\\(client\\_manager\\)" +":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\\)" +":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 " -"`\\ " +":py:obj:`num_fit_clients `\\ " "\\(num\\_available\\_clients\\)" msgstr "" @@ -12363,9 +14119,8 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`aggregate_evaluate " -"`\\ " -"\\(server\\_round\\, results\\, ...\\)" +":py:obj:`aggregate_evaluate `\\ \\(server\\_round\\, results\\, ...\\)" msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of @@ -12381,9 +14136,8 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`configure_evaluate " -"`\\ " -"\\(server\\_round\\, parameters\\, ...\\)" +":py:obj:`configure_evaluate `\\ \\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of @@ -12400,22 +14154,19 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`initialize_parameters " -"`\\ " -"\\(client\\_manager\\)" +":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\\)" +":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 " -"`\\ " +":py:obj:`num_fit_clients `\\ " "\\(num\\_available\\_clients\\)" msgstr "" @@ -12433,9 +14184,8 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`aggregate_evaluate " -"`\\ \\(server\\_round\\, " -"results\\, ...\\)" +":py:obj:`aggregate_evaluate `\\ \\(server\\_round\\, results\\, ...\\)" msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of @@ -12446,9 +14196,8 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`configure_evaluate " -"`\\ \\(server\\_round\\, " -"parameters\\, ...\\)" +":py:obj:`configure_evaluate `\\ \\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of @@ -12465,22 +14214,20 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`initialize_parameters " -"`\\ " -"\\(client\\_manager\\)" +":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\\)" +":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\\)" +":py:obj:`num_fit_clients `\\ " +"\\(num\\_available\\_clients\\)" msgstr "" #: ../../source/ref-api/flwr.server.strategy.FedProx.rst:2 @@ -12493,9 +14240,9 @@ 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:" +"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 @@ -12528,15 +14275,14 @@ msgstr "" 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 "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`aggregate_evaluate " -"`\\ \\(server\\_round\\," -" results\\, ...\\)" +":py:obj:`aggregate_evaluate `\\ \\(server\\_round\\, results\\, ...\\)" msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of @@ -12547,9 +14293,8 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`configure_evaluate " -"`\\ \\(server\\_round\\," -" parameters\\, ...\\)" +":py:obj:`configure_evaluate `\\ \\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of @@ -12566,22 +14311,19 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`initialize_parameters " -"`\\ " -"\\(client\\_manager\\)" +":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\\)" +":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 " -"`\\ " +":py:obj:`num_fit_clients `\\ " "\\(num\\_available\\_clients\\)" msgstr "" @@ -12603,15 +14345,13 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`aggregate_evaluate " -"`\\ " -"\\(server\\_round\\, results\\, ...\\)" +":py:obj:`aggregate_evaluate `\\ \\(server\\_round\\, results\\, ...\\)" msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`aggregate_fit " -"`\\ " +":py:obj:`aggregate_fit `\\ " "\\(server\\_round\\, results\\, failures\\)" msgstr "" @@ -12622,15 +14362,13 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`configure_evaluate " -"`\\ " -"\\(server\\_round\\, parameters\\, ...\\)" +":py:obj:`configure_evaluate `\\ \\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`configure_fit " -"`\\ " +":py:obj:`configure_fit `\\ " "\\(server\\_round\\, parameters\\, ...\\)" msgstr "" @@ -12642,23 +14380,20 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`initialize_parameters " -"`\\ " -"\\(client\\_manager\\)" +":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\\)" +":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\\)" +":py:obj:`num_fit_clients `\\ \\(num\\_available\\_clients\\)" msgstr "" #: ../../source/ref-api/flwr.server.strategy.FedXgbBagging.rst:2 @@ -12668,9 +14403,8 @@ msgstr "" #: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`aggregate_evaluate " -"`\\ " -"\\(server\\_round\\, results\\, ...\\)" +":py:obj:`aggregate_evaluate `\\ \\(server\\_round\\, results\\, ...\\)" msgstr "" #: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1 @@ -12684,8 +14418,7 @@ msgstr "" #: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`aggregate_fit " -"`\\ " +":py:obj:`aggregate_fit `\\ " "\\(server\\_round\\, results\\, failures\\)" msgstr "" @@ -12699,16 +14432,14 @@ msgstr "" #: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`configure_evaluate " -"`\\ " -"\\(server\\_round\\, parameters\\, ...\\)" +":py:obj:`configure_evaluate `\\ \\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`configure_fit " -"`\\ " +":py:obj:`configure_fit `\\ " "\\(server\\_round\\, parameters\\, ...\\)" msgstr "" @@ -12722,25 +14453,22 @@ msgstr "" #: flwr.server.strategy.fedxgb_bagging.FedXgbBagging.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`initialize_parameters " -"`\\ " -"\\(client\\_manager\\)" +":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\\)" +":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\\)" +":py:obj:`num_fit_clients `\\ \\(num\\_available\\_clients\\)" msgstr "" #: ../../source/ref-api/flwr.server.strategy.FedXgbCyclic.rst:2 @@ -12750,33 +14478,29 @@ msgstr "" #: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`aggregate_evaluate " -"`\\ " -"\\(server\\_round\\, results\\, ...\\)" +":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\\)" +":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\\, ...\\)" +":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\\, ...\\)" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 @@ -12789,25 +14513,22 @@ msgstr "" #: flwr.server.strategy.fedxgb_cyclic.FedXgbCyclic.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`initialize_parameters " -"`\\ " -"\\(client\\_manager\\)" +":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\\)" +":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\\)" +":py:obj:`num_fit_clients `\\ \\(num\\_available\\_clients\\)" msgstr "" #: ../../source/ref-api/flwr.server.strategy.FedXgbNnAvg.rst:2 @@ -12817,36 +14538,31 @@ 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." +"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\\, ...\\)" +":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\\)" +":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\\, ...\\)" +":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\\, ...\\)" +":py:obj:`configure_fit `\\ " +"\\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of @@ -12857,23 +14573,20 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`initialize_parameters " -"`\\ " -"\\(client\\_manager\\)" +":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\\)" +":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\\)" +":py:obj:`num_fit_clients `\\ \\(num\\_available\\_clients\\)" msgstr "" #: ../../source/ref-api/flwr.server.strategy.FedYogi.rst:2 @@ -12894,9 +14607,8 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`aggregate_evaluate " -"`\\ \\(server\\_round\\," -" results\\, ...\\)" +":py:obj:`aggregate_evaluate `\\ \\(server\\_round\\, results\\, ...\\)" msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of @@ -12907,9 +14619,8 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`configure_evaluate " -"`\\ \\(server\\_round\\," -" parameters\\, ...\\)" +":py:obj:`configure_evaluate `\\ \\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of @@ -12926,22 +14637,19 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`initialize_parameters " -"`\\ " -"\\(client\\_manager\\)" +":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\\)" +":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 " -"`\\ " +":py:obj:`num_fit_clients `\\ " "\\(num\\_available\\_clients\\)" msgstr "" @@ -12955,15 +14663,14 @@ 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." +"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\\, ...\\)" +":py:obj:`aggregate_evaluate `\\ \\(server\\_round\\, results\\, ...\\)" msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of @@ -12979,9 +14686,8 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`configure_evaluate " -"`\\ \\(server\\_round\\, " -"parameters\\, ...\\)" +":py:obj:`configure_evaluate `\\ \\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of @@ -12998,16 +14704,14 @@ msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`initialize_parameters " -"`\\ " -"\\(client\\_manager\\)" +":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\\)" +":py:obj:`num_evaluation_clients `\\ \\(num\\_available\\_clients\\)" msgstr "" #: flwr.server.strategy.fedavg.FedAvg.aggregate_evaluate:1::1 of @@ -13022,9 +14726,8 @@ msgstr "" #: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`aggregate_evaluate " -"`\\ \\(server\\_round\\," -" results\\, ...\\)" +":py:obj:`aggregate_evaluate `\\ \\(server\\_round\\, results\\, ...\\)" msgstr "" #: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of @@ -13035,9 +14738,8 @@ msgstr "" #: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`configure_evaluate " -"`\\ \\(server\\_round\\," -" parameters\\, ...\\)" +":py:obj:`configure_evaluate `\\ \\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of @@ -13054,22 +14756,19 @@ msgstr "" #: flwr.server.strategy.qfedavg.QFedAvg.aggregate_evaluate:1::1 of msgid "" -":py:obj:`initialize_parameters " -"`\\ " -"\\(client\\_manager\\)" +":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\\)" +":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 " -"`\\ " +":py:obj:`num_fit_clients `\\ " "\\(num\\_available\\_clients\\)" msgstr "" @@ -13080,9 +14779,8 @@ msgstr "" #: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`aggregate_evaluate " -"`\\ " -"\\(server\\_round\\, results\\, ...\\)" +":py:obj:`aggregate_evaluate `\\ \\(server\\_round\\, results\\, ...\\)" msgstr "" #: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1 @@ -13106,9 +14804,8 @@ msgstr "" #: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`configure_evaluate " -"`\\ " -"\\(server\\_round\\, parameters\\, ...\\)" +":py:obj:`configure_evaluate `\\ \\(server\\_round\\, parameters\\, ...\\)" msgstr "" #: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 @@ -13133,9 +14830,8 @@ msgstr "" #: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 #: of msgid "" -":py:obj:`initialize_parameters " -"`\\ " -"\\(client\\_manager\\)" +":py:obj:`initialize_parameters `\\ \\(client\\_manager\\)" msgstr "" #: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:1::1 @@ -13145,17 +14841,18 @@ 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 "" #: 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." +msgid "" +"Exceptions that occurred while the server was waiting for client updates." msgstr "" #: flwr.server.strategy.strategy.Strategy.aggregate_evaluate:16 of @@ -13166,23 +14863,22 @@ 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 "" #: 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 "" #: flwr.server.strategy.strategy.Strategy.evaluate:3 of @@ -13193,9 +14889,8 @@ 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 "" #: flwr.server.strategy.strategy.Strategy.initialize_parameters:6 of @@ -13253,17 +14948,17 @@ msgstr "" #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow:3 #: of msgid "" -"The SecAgg+ protocol ensures the secure summation of integer vectors " -"owned by multiple parties, without accessing any individual integer " -"vector. This workflow allows the server to compute the weighted average " -"of model parameters across all clients, ensuring individual contributions" -" remain private. This is achieved by clients sending both, a weighting " -"factor and a weighted version of the locally updated parameters, both of " -"which are masked for privacy. Specifically, each client uploads \"[w, w *" -" params]\" with masks, where weighting factor 'w' is the number of " -"examples ('num_examples') and 'params' represents the model parameters " -"('parameters') from the client's `FitRes`. The server then aggregates " -"these contributions to compute the weighted average of model parameters." +"The SecAgg+ protocol ensures the secure summation of integer vectors owned " +"by multiple parties, without accessing any individual integer vector. This " +"workflow allows the server to compute the weighted average of model " +"parameters across all clients, ensuring individual contributions remain " +"private. This is achieved by clients sending both, a weighting factor and a " +"weighted version of the locally updated parameters, both of which are masked " +"for privacy. Specifically, each client uploads \"[w, w * params]\" with " +"masks, where weighting factor 'w' is the number of examples ('num_examples') " +"and 'params' represents the model parameters ('parameters') from the " +"client's `FitRes`. The server then aggregates these contributions to compute " +"the weighted average of model parameters." msgstr "" #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow:14 @@ -13300,39 +14995,39 @@ msgstr "" #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow:22 #: of msgid "" -"Only the aggregated model parameters are exposed and passed to " -"`Strategy.aggregate_fit`, ensuring individual data privacy." +"Only the aggregated model parameters are exposed and passed to `Strategy." +"aggregate_fit`, ensuring individual data privacy." msgstr "" #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow:25 #: of msgid "" -"The number of shares into which each client's private key is split under " -"the SecAgg+ protocol. If specified as a float, it represents the " -"proportion of all selected clients, and the number of shares will be set " -"dynamically in the run time. A private key can be reconstructed from " -"these shares, allowing for the secure aggregation of model updates. Each " -"client sends one share to each of its neighbors while retaining one." +"The number of shares into which each client's private key is split under the " +"SecAgg+ protocol. If specified as a float, it represents the proportion of " +"all selected clients, and the number of shares will be set dynamically in " +"the run time. A private key can be reconstructed from these shares, allowing " +"for the secure aggregation of model updates. Each client sends one share to " +"each of its neighbors while retaining one." msgstr "" #: flwr.server.workflow.secure_aggregation.secagg_workflow.SecAggWorkflow:25 #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow:32 #: of msgid "" -"The minimum number of shares required to reconstruct a client's private " -"key, or, if specified as a float, it represents the proportion of the " -"total number of shares needed for reconstruction. This threshold ensures " -"privacy by allowing for the recovery of contributions from dropped " -"clients during aggregation, without compromising individual client data." +"The minimum number of shares required to reconstruct a client's private key, " +"or, if specified as a float, it represents the proportion of the total " +"number of shares needed for reconstruction. This threshold ensures privacy " +"by allowing for the recovery of contributions from dropped clients during " +"aggregation, without compromising individual client data." msgstr "" #: flwr.server.workflow.secure_aggregation.secagg_workflow.SecAggWorkflow:31 #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow:38 #: of msgid "" -"The maximum value of the weight that can be assigned to any single " -"client's update during the weighted average calculation on the server " -"side, e.g., in the FedAvg algorithm." +"The maximum value of the weight that can be assigned to any single client's " +"update during the weighted average calculation on the server side, e.g., in " +"the FedAvg algorithm." msgstr "" #: flwr.server.workflow.secure_aggregation.secagg_workflow.SecAggWorkflow:35 @@ -13340,8 +15035,8 @@ msgstr "" #: of msgid "" "The range within which model parameters are clipped before quantization. " -"This parameter ensures each model parameter is bounded within " -"[-clipping_range, clipping_range], facilitating quantization." +"This parameter ensures each model parameter is bounded within [-" +"clipping_range, clipping_range], facilitating quantization." msgstr "" #: flwr.server.workflow.secure_aggregation.secagg_workflow.SecAggWorkflow:39 @@ -13359,31 +15054,32 @@ msgstr "" #: of msgid "" "The range of values from which random mask entries are uniformly sampled " -"([0, modulus_range-1]). `modulus_range` must be less than 4294967296. " -"Please use 2**n values for `modulus_range` to prevent overflow issues." +"([0, modulus_range-1]). `modulus_range` must be less than 4294967296. Please " +"use 2**n values for `modulus_range` to prevent overflow issues." msgstr "" #: flwr.server.workflow.secure_aggregation.secagg_workflow.SecAggWorkflow:47 #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow:54 #: of msgid "" -"The timeout duration in seconds. If specified, the workflow will wait for" -" replies for this duration each time. If `None`, there is no time limit " -"and the workflow will wait until replies for all messages are received." +"The timeout duration in seconds. If specified, the workflow will wait for " +"replies for this duration each time. If `None`, there is no time limit and " +"the workflow will wait until replies for all messages are received." msgstr "" #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow:61 #: of msgid "" "Generally, higher `num_shares` means more robust to dropouts while " -"increasing the computational costs; higher `reconstruction_threshold` " -"means better privacy guarantees but less tolerance to dropouts." +"increasing the computational costs; higher `reconstruction_threshold` means " +"better privacy guarantees but less tolerance to dropouts." msgstr "" #: flwr.server.workflow.secure_aggregation.secagg_workflow.SecAggWorkflow:58 #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow:64 #: of -msgid "Too large `max_weight` may compromise the precision of the quantization." +msgid "" +"Too large `max_weight` may compromise the precision of the quantization." msgstr "" #: flwr.server.workflow.secure_aggregation.secagg_workflow.SecAggWorkflow:59 @@ -13396,35 +15092,34 @@ msgstr "" #: of msgid "" "When `num_shares` is a float, it is interpreted as the proportion of all " -"selected clients, and hence the number of shares will be determined in " -"the runtime. This allows for dynamic adjustment based on the total number" -" of participating clients." +"selected clients, and hence the number of shares will be determined in the " +"runtime. This allows for dynamic adjustment based on the total number of " +"participating clients." msgstr "" #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow:69 #: of msgid "" -"Similarly, when `reconstruction_threshold` is a float, it is interpreted " -"as the proportion of the number of shares needed for the reconstruction " -"of a private key. This feature enables flexibility in setting the " -"security threshold relative to the number of distributed shares." +"Similarly, when `reconstruction_threshold` is a float, it is interpreted as " +"the proportion of the number of shares needed for the reconstruction of a " +"private key. This feature enables flexibility in setting the security " +"threshold relative to the number of distributed shares." msgstr "" #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow:73 #: of msgid "" -"`num_shares`, `reconstruction_threshold`, and the quantization parameters" -" (`clipping_range`, `quantization_range`, `modulus_range`) play critical " -"roles in balancing privacy, robustness, and efficiency within the SecAgg+" -" protocol." +"`num_shares`, `reconstruction_threshold`, and the quantization parameters " +"(`clipping_range`, `quantization_range`, `modulus_range`) play critical " +"roles in balancing privacy, robustness, and efficiency within the SecAgg+ " +"protocol." msgstr "" #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow.collect_masked_vectors_stage:1::1 #: of msgid "" -":py:obj:`collect_masked_vectors_stage " -"`\\" -" \\(driver\\, ...\\)" +":py:obj:`collect_masked_vectors_stage `\\ \\(driver\\, ...\\)" msgstr "" #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow.collect_masked_vectors_stage:1 @@ -13436,9 +15131,8 @@ msgstr "" #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow.collect_masked_vectors_stage:1::1 #: of msgid "" -":py:obj:`setup_stage " -"`\\ \\(driver\\, " -"context\\, state\\)" +":py:obj:`setup_stage `\\ \\(driver\\, context\\, state\\)" msgstr "" #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow.collect_masked_vectors_stage:1::1 @@ -13450,9 +15144,8 @@ msgstr "" #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow.collect_masked_vectors_stage:1::1 #: of msgid "" -":py:obj:`share_keys_stage " -"`\\ " -"\\(driver\\, context\\, state\\)" +":py:obj:`share_keys_stage `\\ \\(driver\\, context\\, state\\)" msgstr "" #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow.collect_masked_vectors_stage:1::1 @@ -13464,9 +15157,8 @@ msgstr "" #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow.collect_masked_vectors_stage:1::1 #: of msgid "" -":py:obj:`unmask_stage " -"`\\ \\(driver\\, " -"context\\, state\\)" +":py:obj:`unmask_stage `\\ \\(driver\\, context\\, state\\)" msgstr "" #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow.collect_masked_vectors_stage:1::1 @@ -13481,51 +15173,50 @@ msgstr "" #: flwr.server.workflow.secure_aggregation.secagg_workflow.SecAggWorkflow:1 of msgid "" -"Bases: " -":py:class:`~flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow`" +"Bases: :py:class:`~flwr.server.workflow.secure_aggregation." +"secaggplus_workflow.SecAggPlusWorkflow`" msgstr "" #: flwr.server.workflow.secure_aggregation.secagg_workflow.SecAggWorkflow:3 of msgid "" -"The SecAgg protocol ensures the secure summation of integer vectors owned" -" by multiple parties, without accessing any individual integer vector. " -"This workflow allows the server to compute the weighted average of model " +"The SecAgg protocol ensures the secure summation of integer vectors owned by " +"multiple parties, without accessing any individual integer vector. This " +"workflow allows the server to compute the weighted average of model " "parameters across all clients, ensuring individual contributions remain " -"private. This is achieved by clients sending both, a weighting factor and" -" a weighted version of the locally updated parameters, both of which are " -"masked for privacy. Specifically, each client uploads \"[w, w * params]\"" -" with masks, where weighting factor 'w' is the number of examples " -"('num_examples') and 'params' represents the model parameters " -"('parameters') from the client's `FitRes`. The server then aggregates " -"these contributions to compute the weighted average of model parameters." +"private. This is achieved by clients sending both, a weighting factor and a " +"weighted version of the locally updated parameters, both of which are masked " +"for privacy. Specifically, each client uploads \"[w, w * params]\" with " +"masks, where weighting factor 'w' is the number of examples ('num_examples') " +"and 'params' represents the model parameters ('parameters') from the " +"client's `FitRes`. The server then aggregates these contributions to compute " +"the weighted average of model parameters." msgstr "" #: flwr.server.workflow.secure_aggregation.secagg_workflow.SecAggWorkflow:14 of msgid "" -"The protocol involves four main stages: - 'setup': Send SecAgg " -"configuration to clients and collect their public keys. - 'share keys': " -"Broadcast public keys among clients and collect encrypted secret" +"The protocol involves four main stages: - 'setup': Send SecAgg configuration " +"to clients and collect their public keys. - 'share keys': Broadcast public " +"keys among clients and collect encrypted secret" msgstr "" #: flwr.server.workflow.secure_aggregation.secagg_workflow.SecAggWorkflow:54 of msgid "" -"Each client's private key is split into N shares under the SecAgg " -"protocol, where N is the number of selected clients." +"Each client's private key is split into N shares under the SecAgg protocol, " +"where N is the number of selected clients." msgstr "" #: flwr.server.workflow.secure_aggregation.secagg_workflow.SecAggWorkflow:56 of msgid "" -"Generally, higher `reconstruction_threshold` means better privacy " -"guarantees but less tolerance to dropouts." +"Generally, higher `reconstruction_threshold` means better privacy guarantees " +"but less tolerance to dropouts." msgstr "" #: flwr.server.workflow.secure_aggregation.secagg_workflow.SecAggWorkflow:60 of msgid "" "When `reconstruction_threshold` is a float, it is interpreted as the " "proportion of the number of all selected clients needed for the " -"reconstruction of a private key. This feature enables flexibility in " -"setting the security threshold relative to the number of selected " -"clients." +"reconstruction of a private key. This feature enables flexibility in setting " +"the security threshold relative to the number of selected clients." msgstr "" #: flwr.server.workflow.secure_aggregation.secagg_workflow.SecAggWorkflow:64 of @@ -13539,32 +15230,29 @@ msgstr "" #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow.collect_masked_vectors_stage:1::1 #: of msgid "" -":py:obj:`collect_masked_vectors_stage " -"`\\ " -"\\(driver\\, ...\\)" +":py:obj:`collect_masked_vectors_stage `\\ \\(driver\\, ...\\)" msgstr "" #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow.collect_masked_vectors_stage:1::1 #: of msgid "" -":py:obj:`setup_stage `\\" -" \\(driver\\, context\\, state\\)" +":py:obj:`setup_stage `\\ " +"\\(driver\\, context\\, state\\)" msgstr "" #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow.collect_masked_vectors_stage:1::1 #: of msgid "" -":py:obj:`share_keys_stage " -"`\\ \\(driver\\, " -"context\\, state\\)" +":py:obj:`share_keys_stage `\\ \\(driver\\, context\\, state\\)" msgstr "" #: flwr.server.workflow.secure_aggregation.secaggplus_workflow.SecAggPlusWorkflow.collect_masked_vectors_stage:1::1 #: of msgid "" -":py:obj:`unmask_stage " -"`\\ \\(driver\\, " -"context\\, state\\)" +":py:obj:`unmask_stage `\\ " +"\\(driver\\, context\\, state\\)" msgstr "" #: ../../source/ref-api/flwr.simulation.rst:2 @@ -13573,8 +15261,8 @@ msgstr "" #: ../../source/ref-api/flwr.simulation.rst:18::1 msgid "" -":py:obj:`start_simulation `\\ \\(\\*\\," -" client\\_fn\\[\\, ...\\]\\)" +":py:obj:`start_simulation `\\ \\(\\*\\, " +"client\\_fn\\[\\, ...\\]\\)" msgstr "" #: ../../source/ref-api/flwr.simulation.rst:18::1 @@ -13605,15 +15293,14 @@ msgstr "" #: flwr.simulation.run_simulation.run_simulation:6 of msgid "" -"The `ClientApp` to be executed by each of the SuperNodes. It will receive" -" messages sent by the `ServerApp`." +"The `ClientApp` to be executed by each of the SuperNodes. It will receive " +"messages sent by the `ServerApp`." msgstr "" #: flwr.simulation.run_simulation.run_simulation:9 of msgid "" -"Number of nodes that run a ClientApp. They can be sampled by a Driver in " -"the ServerApp and receive a Message describing what the ClientApp should " -"perform." +"Number of nodes that run a ClientApp. They can be sampled by a Driver in the " +"ServerApp and receive a Message describing what the ClientApp should perform." msgstr "" #: flwr.simulation.run_simulation.run_simulation:13 of @@ -13622,26 +15309,26 @@ msgstr "" #: flwr.simulation.run_simulation.run_simulation:15 of msgid "" -"'A dictionary, e.g {\"\": , \"\": } to " -"configure a backend. Values supported in are those included by " -"`flwr.common.typing.ConfigsRecordValues`." +"'A dictionary, e.g {\"\": , \"\": } to configure a " +"backend. Values supported in are those included by `flwr.common." +"typing.ConfigsRecordValues`." msgstr "" #: flwr.simulation.run_simulation.run_simulation:19 of msgid "" -"A boolean to indicate whether to enable GPU growth on the main thread. " -"This is desirable if you make use of a TensorFlow model on your " -"`ServerApp` while having your `ClientApp` running on the same GPU. " -"Without enabling this, you might encounter an out-of-memory error because" -" TensorFlow, by default, allocates all GPU memory. Read more about how " -"`tf.config.experimental.set_memory_growth()` works in the TensorFlow " -"documentation: https://www.tensorflow.org/api/stable." +"A boolean to indicate whether to enable GPU growth on the main thread. This " +"is desirable if you make use of a TensorFlow model on your `ServerApp` while " +"having your `ClientApp` running on the same GPU. Without enabling this, you " +"might encounter an out-of-memory error because TensorFlow, by default, " +"allocates all GPU memory. Read more about how `tf.config.experimental." +"set_memory_growth()` works in the TensorFlow documentation: https://www." +"tensorflow.org/api/stable." msgstr "" #: flwr.simulation.run_simulation.run_simulation:26 of msgid "" -"When diabled, only INFO, WARNING and ERROR log messages will be shown. If" -" enabled, DEBUG-level logs will be displayed." +"When diabled, only INFO, WARNING and ERROR log messages will be shown. If " +"enabled, DEBUG-level logs will be displayed." msgstr "" #: ../../source/ref-api/flwr.simulation.start_simulation.rst:2 @@ -13650,15 +15337,15 @@ 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, " +"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 "" #: flwr.simulation.app.start_simulation:13 of @@ -13669,16 +15356,16 @@ 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 " +"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." +"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 @@ -13689,16 +15376,16 @@ 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`." +"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`." +"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 @@ -13707,8 +15394,7 @@ 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 "" #: flwr.simulation.app.start_simulation:39 of @@ -13724,14 +15410,13 @@ 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." +"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`." +"Set to True to prevent `ray.shutdown()` in case `ray.is_initialized()=True`." msgstr "" #: flwr.simulation.app.start_simulation:50 of @@ -13743,19 +15428,19 @@ 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." +"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" +"(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 @@ -13783,16 +15468,16 @@ msgstr "" #: ../../source/ref-changelog.md:364 ../../source/ref-changelog.md:448 #: ../../source/ref-changelog.md:512 ../../source/ref-changelog.md:570 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 "" #: ../../source/ref-changelog.md:9 msgid "" -"`Adam Narozniak`, `Charles Beauville`, `Chong Shen Ng`, `Daniel J. " -"Beutel`, `Daniel Nata Nugraha`, `Heng Pan`, `Javier`, `Mahdi Beitollahi`," -" `Robert Steiner`, `Taner Topal`, `Yan Gao`, `bapic`, `mohammadnaseri` " +"`Adam Narozniak`, `Charles Beauville`, `Chong Shen Ng`, `Daniel J. Beutel`, " +"`Daniel Nata Nugraha`, `Heng Pan`, `Javier`, `Mahdi Beitollahi`, `Robert " +"Steiner`, `Taner Topal`, `Yan Gao`, `bapic`, `mohammadnaseri` " msgstr "" #: ../../source/ref-changelog.md:11 ../../source/ref-changelog.md:111 @@ -13809,33 +15494,28 @@ msgstr "" #: ../../source/ref-changelog.md:13 msgid "" -"**Introduce built-in authentication (preview)** " -"([#2946](https://github.com/adap/flower/pull/2946), " -"[#3388](https://github.com/adap/flower/pull/3388), " -"[#2948](https://github.com/adap/flower/pull/2948), " -"[#2917](https://github.com/adap/flower/pull/2917), " -"[#3386](https://github.com/adap/flower/pull/3386), " -"[#3308](https://github.com/adap/flower/pull/3308), " -"[#3001](https://github.com/adap/flower/pull/3001), " -"[#3409](https://github.com/adap/flower/pull/3409), " -"[#2999](https://github.com/adap/flower/pull/2999), " -"[#2979](https://github.com/adap/flower/pull/2979), " -"[#3389](https://github.com/adap/flower/pull/3389), " -"[#3503](https://github.com/adap/flower/pull/3503), " -"[#3366](https://github.com/adap/flower/pull/3366), " -"[#3357](https://github.com/adap/flower/pull/3357))" +"**Introduce built-in authentication (preview)** ([#2946](https://github.com/" +"adap/flower/pull/2946), [#3388](https://github.com/adap/flower/pull/3388), " +"[#2948](https://github.com/adap/flower/pull/2948), [#2917](https://github." +"com/adap/flower/pull/2917), [#3386](https://github.com/adap/flower/" +"pull/3386), [#3308](https://github.com/adap/flower/pull/3308), [#3001]" +"(https://github.com/adap/flower/pull/3001), [#3409](https://github.com/adap/" +"flower/pull/3409), [#2999](https://github.com/adap/flower/pull/2999), [#2979]" +"(https://github.com/adap/flower/pull/2979), [#3389](https://github.com/adap/" +"flower/pull/3389), [#3503](https://github.com/adap/flower/pull/3503), [#3366]" +"(https://github.com/adap/flower/pull/3366), [#3357](https://github.com/adap/" +"flower/pull/3357))" msgstr "" #: ../../source/ref-changelog.md:15 msgid "" "Flower 1.9 introduces the first build-in version of client node " -"authentication. In previous releases, users often wrote glue code to " -"connect Flower to external authentication systems. With this release, the" -" SuperLink can authenticate SuperNodes using a built-in authentication " -"system. A new [how-to guide](https://flower.ai/docs/framework/how-to-" -"authenticate-supernodes.html) and a new [code " -"example](https://github.com/adap/flower/tree/main/examples/flower-" -"authentication) help you to get started." +"authentication. In previous releases, users often wrote glue code to connect " +"Flower to external authentication systems. With this release, the SuperLink " +"can authenticate SuperNodes using a built-in authentication system. A new " +"[how-to guide](https://flower.ai/docs/framework/how-to-authenticate-" +"supernodes.html) and a new [code example](https://github.com/adap/flower/" +"tree/main/examples/flower-authentication) help you to get started." msgstr "" #: ../../source/ref-changelog.md:17 @@ -13847,118 +15527,104 @@ msgstr "" #: ../../source/ref-changelog.md:19 msgid "" -"**Introduce end-to-end Docker support** " -"([#3483](https://github.com/adap/flower/pull/3483), " -"[#3266](https://github.com/adap/flower/pull/3266), " -"[#3390](https://github.com/adap/flower/pull/3390), " -"[#3283](https://github.com/adap/flower/pull/3283), " -"[#3285](https://github.com/adap/flower/pull/3285), " -"[#3391](https://github.com/adap/flower/pull/3391), " -"[#3403](https://github.com/adap/flower/pull/3403), " -"[#3458](https://github.com/adap/flower/pull/3458), " -"[#3533](https://github.com/adap/flower/pull/3533), " -"[#3453](https://github.com/adap/flower/pull/3453), " -"[#3486](https://github.com/adap/flower/pull/3486), " -"[#3290](https://github.com/adap/flower/pull/3290))" +"**Introduce end-to-end Docker support** ([#3483](https://github.com/adap/" +"flower/pull/3483), [#3266](https://github.com/adap/flower/pull/3266), [#3390]" +"(https://github.com/adap/flower/pull/3390), [#3283](https://github.com/adap/" +"flower/pull/3283), [#3285](https://github.com/adap/flower/pull/3285), [#3391]" +"(https://github.com/adap/flower/pull/3391), [#3403](https://github.com/adap/" +"flower/pull/3403), [#3458](https://github.com/adap/flower/pull/3458), [#3533]" +"(https://github.com/adap/flower/pull/3533), [#3453](https://github.com/adap/" +"flower/pull/3453), [#3486](https://github.com/adap/flower/pull/3486), [#3290]" +"(https://github.com/adap/flower/pull/3290))" msgstr "" #: ../../source/ref-changelog.md:21 msgid "" "Full Flower Next Docker support is here! With the release of Flower 1.9, " -"Flower provides stable Docker images for the Flower SuperLink, the Flower" -" SuperNode, and the Flower `ServerApp`. This set of images enables you to" -" run all Flower components in Docker. Check out the new [how-to " -"guide](https://flower.ai/docs/framework/how-to-run-flower-using-" -"docker.html) to get stated." +"Flower provides stable Docker images for the Flower SuperLink, the Flower " +"SuperNode, and the Flower `ServerApp`. This set of images enables you to run " +"all Flower components in Docker. Check out the new [how-to guide](https://" +"flower.ai/docs/framework/how-to-run-flower-using-docker.html) to get stated." msgstr "" #: ../../source/ref-changelog.md:23 msgid "" -"**Re-architect Flower Next simulation engine** " -"([#3307](https://github.com/adap/flower/pull/3307), " -"[#3355](https://github.com/adap/flower/pull/3355), " -"[#3272](https://github.com/adap/flower/pull/3272), " -"[#3273](https://github.com/adap/flower/pull/3273), " -"[#3417](https://github.com/adap/flower/pull/3417), " -"[#3281](https://github.com/adap/flower/pull/3281), " -"[#3343](https://github.com/adap/flower/pull/3343), " -"[#3326](https://github.com/adap/flower/pull/3326))" +"**Re-architect Flower Next simulation engine** ([#3307](https://github.com/" +"adap/flower/pull/3307), [#3355](https://github.com/adap/flower/pull/3355), " +"[#3272](https://github.com/adap/flower/pull/3272), [#3273](https://github." +"com/adap/flower/pull/3273), [#3417](https://github.com/adap/flower/" +"pull/3417), [#3281](https://github.com/adap/flower/pull/3281), [#3343]" +"(https://github.com/adap/flower/pull/3343), [#3326](https://github.com/adap/" +"flower/pull/3326))" msgstr "" #: ../../source/ref-changelog.md:25 msgid "" -"Flower Next simulations now use a new in-memory `Driver` that improves " -"the reliability of simulations, especially in notebook environments. This" -" is a significant step towards a complete overhaul of the Flower Next " -"simulation architecture." +"Flower Next simulations now use a new in-memory `Driver` that improves the " +"reliability of simulations, especially in notebook environments. This is a " +"significant step towards a complete overhaul of the Flower Next simulation " +"architecture." msgstr "" #: ../../source/ref-changelog.md:27 msgid "" -"**Upgrade simulation engine** " -"([#3354](https://github.com/adap/flower/pull/3354), " -"[#3378](https://github.com/adap/flower/pull/3378), " -"[#3262](https://github.com/adap/flower/pull/3262), " -"[#3435](https://github.com/adap/flower/pull/3435), " -"[#3501](https://github.com/adap/flower/pull/3501), " -"[#3482](https://github.com/adap/flower/pull/3482), " -"[#3494](https://github.com/adap/flower/pull/3494))" +"**Upgrade simulation engine** ([#3354](https://github.com/adap/flower/" +"pull/3354), [#3378](https://github.com/adap/flower/pull/3378), [#3262]" +"(https://github.com/adap/flower/pull/3262), [#3435](https://github.com/adap/" +"flower/pull/3435), [#3501](https://github.com/adap/flower/pull/3501), [#3482]" +"(https://github.com/adap/flower/pull/3482), [#3494](https://github.com/adap/" +"flower/pull/3494))" msgstr "" #: ../../source/ref-changelog.md:29 msgid "" "The Flower Next simulation engine comes with improved and configurable " -"logging. The Ray-based simulation backend in Flower 1.9 was updated to " -"use Ray 2.10." +"logging. The Ray-based simulation backend in Flower 1.9 was updated to use " +"Ray 2.10." msgstr "" #: ../../source/ref-changelog.md:31 msgid "" -"**Introduce FedPFT baseline** " -"([#3268](https://github.com/adap/flower/pull/3268))" +"**Introduce FedPFT baseline** ([#3268](https://github.com/adap/flower/" +"pull/3268))" msgstr "" #: ../../source/ref-changelog.md:33 msgid "" "FedPFT allows you to perform one-shot Federated Learning by leveraging " -"widely available foundational models, dramatically reducing communication" -" costs while delivering high performing models. This is work led by Mahdi" -" Beitollahi from Huawei Noah's Ark Lab (Montreal, Canada). Read all the " -"details in their paper: \"Parametric Feature Transfer: One-shot Federated" -" Learning with Foundation Models\" " -"([arxiv](https://arxiv.org/abs/2402.01862))" +"widely available foundational models, dramatically reducing communication " +"costs while delivering high performing models. This is work led by Mahdi " +"Beitollahi from Huawei Noah's Ark Lab (Montreal, Canada). Read all the " +"details in their paper: \"Parametric Feature Transfer: One-shot Federated " +"Learning with Foundation Models\" ([arxiv](https://arxiv.org/abs/2402.01862))" msgstr "" #: ../../source/ref-changelog.md:35 msgid "" "**Launch additional** `flwr new` **templates for Apple MLX, Hugging Face " -"Transformers, scikit-learn and TensorFlow** " -"([#3291](https://github.com/adap/flower/pull/3291), " -"[#3139](https://github.com/adap/flower/pull/3139), " -"[#3284](https://github.com/adap/flower/pull/3284), " -"[#3251](https://github.com/adap/flower/pull/3251), " -"[#3376](https://github.com/adap/flower/pull/3376), " -"[#3287](https://github.com/adap/flower/pull/3287))" +"Transformers, scikit-learn and TensorFlow** ([#3291](https://github.com/adap/" +"flower/pull/3291), [#3139](https://github.com/adap/flower/pull/3139), [#3284]" +"(https://github.com/adap/flower/pull/3284), [#3251](https://github.com/adap/" +"flower/pull/3251), [#3376](https://github.com/adap/flower/pull/3376), [#3287]" +"(https://github.com/adap/flower/pull/3287))" msgstr "" #: ../../source/ref-changelog.md:37 msgid "" -"The `flwr` CLI's `flwr new` command is starting to become everone's " -"favorite way of creating new Flower projects. This release introduces " -"additional `flwr new` templates for Apple MLX, Hugging Face Transformers," -" scikit-learn and TensorFlow. In addition to that, existing templates " -"also received updates." +"The `flwr` CLI's `flwr new` command is starting to become everone's favorite " +"way of creating new Flower projects. This release introduces additional " +"`flwr new` templates for Apple MLX, Hugging Face Transformers, scikit-learn " +"and TensorFlow. In addition to that, existing templates also received " +"updates." msgstr "" #: ../../source/ref-changelog.md:39 msgid "" -"**Refine** `RecordSet` **API** " -"([#3209](https://github.com/adap/flower/pull/3209), " -"[#3331](https://github.com/adap/flower/pull/3331), " -"[#3334](https://github.com/adap/flower/pull/3334), " -"[#3335](https://github.com/adap/flower/pull/3335), " -"[#3375](https://github.com/adap/flower/pull/3375), " -"[#3368](https://github.com/adap/flower/pull/3368))" +"**Refine** `RecordSet` **API** ([#3209](https://github.com/adap/flower/" +"pull/3209), [#3331](https://github.com/adap/flower/pull/3331), [#3334]" +"(https://github.com/adap/flower/pull/3334), [#3335](https://github.com/adap/" +"flower/pull/3335), [#3375](https://github.com/adap/flower/pull/3375), [#3368]" +"(https://github.com/adap/flower/pull/3368))" msgstr "" #: ../../source/ref-changelog.md:41 @@ -13971,29 +15637,25 @@ msgstr "" #: ../../source/ref-changelog.md:43 msgid "" "**Beautify logging** ([#3379](https://github.com/adap/flower/pull/3379), " -"[#3430](https://github.com/adap/flower/pull/3430), " -"[#3461](https://github.com/adap/flower/pull/3461), " -"[#3360](https://github.com/adap/flower/pull/3360), " -"[#3433](https://github.com/adap/flower/pull/3433))" +"[#3430](https://github.com/adap/flower/pull/3430), [#3461](https://github." +"com/adap/flower/pull/3461), [#3360](https://github.com/adap/flower/" +"pull/3360), [#3433](https://github.com/adap/flower/pull/3433))" msgstr "" #: ../../source/ref-changelog.md:45 msgid "" -"Logs received a substantial update. Not only are logs now much nicer to " -"look at, but they are also more configurable." +"Logs received a substantial update. Not only are logs now much nicer to look " +"at, but they are also more configurable." msgstr "" #: ../../source/ref-changelog.md:47 msgid "" -"**Improve reliability** " -"([#3564](https://github.com/adap/flower/pull/3564), " -"[#3561](https://github.com/adap/flower/pull/3561), " -"[#3566](https://github.com/adap/flower/pull/3566), " -"[#3462](https://github.com/adap/flower/pull/3462), " -"[#3225](https://github.com/adap/flower/pull/3225), " -"[#3514](https://github.com/adap/flower/pull/3514), " -"[#3535](https://github.com/adap/flower/pull/3535), " -"[#3372](https://github.com/adap/flower/pull/3372))" +"**Improve reliability** ([#3564](https://github.com/adap/flower/pull/3564), " +"[#3561](https://github.com/adap/flower/pull/3561), [#3566](https://github." +"com/adap/flower/pull/3566), [#3462](https://github.com/adap/flower/" +"pull/3462), [#3225](https://github.com/adap/flower/pull/3225), [#3514]" +"(https://github.com/adap/flower/pull/3514), [#3535](https://github.com/adap/" +"flower/pull/3535), [#3372](https://github.com/adap/flower/pull/3372))" msgstr "" #: ../../source/ref-changelog.md:49 @@ -14004,50 +15666,40 @@ msgstr "" #: ../../source/ref-changelog.md:51 msgid "" -"**Update Swift and C++ SDKs** " -"([#3321](https://github.com/adap/flower/pull/3321), " -"[#2763](https://github.com/adap/flower/pull/2763))" +"**Update Swift and C++ SDKs** ([#3321](https://github.com/adap/flower/" +"pull/3321), [#2763](https://github.com/adap/flower/pull/2763))" msgstr "" #: ../../source/ref-changelog.md:53 msgid "" -"In the C++ SDK, communication-related code is now separate from main " -"client logic. A new abstract class `Communicator` has been introduced " -"alongside a gRPC implementation of it." +"In the C++ SDK, communication-related code is now separate from main client " +"logic. A new abstract class `Communicator` has been introduced alongside a " +"gRPC implementation of it." msgstr "" #: ../../source/ref-changelog.md:55 msgid "" -"**Improve testing, tooling and CI/CD infrastructure** " -"([#3294](https://github.com/adap/flower/pull/3294), " -"[#3282](https://github.com/adap/flower/pull/3282), " -"[#3311](https://github.com/adap/flower/pull/3311), " -"[#2878](https://github.com/adap/flower/pull/2878), " -"[#3333](https://github.com/adap/flower/pull/3333), " -"[#3255](https://github.com/adap/flower/pull/3255), " -"[#3349](https://github.com/adap/flower/pull/3349), " -"[#3400](https://github.com/adap/flower/pull/3400), " -"[#3401](https://github.com/adap/flower/pull/3401), " -"[#3399](https://github.com/adap/flower/pull/3399), " -"[#3346](https://github.com/adap/flower/pull/3346), " -"[#3398](https://github.com/adap/flower/pull/3398), " -"[#3397](https://github.com/adap/flower/pull/3397), " -"[#3347](https://github.com/adap/flower/pull/3347), " -"[#3502](https://github.com/adap/flower/pull/3502), " -"[#3387](https://github.com/adap/flower/pull/3387), " -"[#3542](https://github.com/adap/flower/pull/3542), " -"[#3396](https://github.com/adap/flower/pull/3396), " -"[#3496](https://github.com/adap/flower/pull/3496), " -"[#3465](https://github.com/adap/flower/pull/3465), " -"[#3473](https://github.com/adap/flower/pull/3473), " -"[#3484](https://github.com/adap/flower/pull/3484), " -"[#3521](https://github.com/adap/flower/pull/3521), " -"[#3363](https://github.com/adap/flower/pull/3363), " -"[#3497](https://github.com/adap/flower/pull/3497), " -"[#3464](https://github.com/adap/flower/pull/3464), " -"[#3495](https://github.com/adap/flower/pull/3495), " -"[#3478](https://github.com/adap/flower/pull/3478), " -"[#3271](https://github.com/adap/flower/pull/3271))" +"**Improve testing, tooling and CI/CD infrastructure** ([#3294](https://" +"github.com/adap/flower/pull/3294), [#3282](https://github.com/adap/flower/" +"pull/3282), [#3311](https://github.com/adap/flower/pull/3311), [#2878]" +"(https://github.com/adap/flower/pull/2878), [#3333](https://github.com/adap/" +"flower/pull/3333), [#3255](https://github.com/adap/flower/pull/3255), [#3349]" +"(https://github.com/adap/flower/pull/3349), [#3400](https://github.com/adap/" +"flower/pull/3400), [#3401](https://github.com/adap/flower/pull/3401), [#3399]" +"(https://github.com/adap/flower/pull/3399), [#3346](https://github.com/adap/" +"flower/pull/3346), [#3398](https://github.com/adap/flower/pull/3398), [#3397]" +"(https://github.com/adap/flower/pull/3397), [#3347](https://github.com/adap/" +"flower/pull/3347), [#3502](https://github.com/adap/flower/pull/3502), [#3387]" +"(https://github.com/adap/flower/pull/3387), [#3542](https://github.com/adap/" +"flower/pull/3542), [#3396](https://github.com/adap/flower/pull/3396), [#3496]" +"(https://github.com/adap/flower/pull/3496), [#3465](https://github.com/adap/" +"flower/pull/3465), [#3473](https://github.com/adap/flower/pull/3473), [#3484]" +"(https://github.com/adap/flower/pull/3484), [#3521](https://github.com/adap/" +"flower/pull/3521), [#3363](https://github.com/adap/flower/pull/3363), [#3497]" +"(https://github.com/adap/flower/pull/3497), [#3464](https://github.com/adap/" +"flower/pull/3464), [#3495](https://github.com/adap/flower/pull/3495), [#3478]" +"(https://github.com/adap/flower/pull/3478), [#3271](https://github.com/adap/" +"flower/pull/3271))" msgstr "" #: ../../source/ref-changelog.md:57 @@ -14058,75 +15710,61 @@ msgstr "" #: ../../source/ref-changelog.md:59 msgid "" -"**Improve documentation** " -"([#3530](https://github.com/adap/flower/pull/3530), " -"[#3539](https://github.com/adap/flower/pull/3539), " -"[#3425](https://github.com/adap/flower/pull/3425), " -"[#3520](https://github.com/adap/flower/pull/3520), " -"[#3286](https://github.com/adap/flower/pull/3286), " -"[#3516](https://github.com/adap/flower/pull/3516), " -"[#3523](https://github.com/adap/flower/pull/3523), " -"[#3545](https://github.com/adap/flower/pull/3545), " -"[#3498](https://github.com/adap/flower/pull/3498), " -"[#3439](https://github.com/adap/flower/pull/3439), " -"[#3440](https://github.com/adap/flower/pull/3440), " -"[#3382](https://github.com/adap/flower/pull/3382), " -"[#3559](https://github.com/adap/flower/pull/3559), " -"[#3432](https://github.com/adap/flower/pull/3432), " -"[#3278](https://github.com/adap/flower/pull/3278), " -"[#3371](https://github.com/adap/flower/pull/3371), " -"[#3519](https://github.com/adap/flower/pull/3519), " -"[#3267](https://github.com/adap/flower/pull/3267), " -"[#3204](https://github.com/adap/flower/pull/3204), " -"[#3274](https://github.com/adap/flower/pull/3274))" +"**Improve documentation** ([#3530](https://github.com/adap/flower/" +"pull/3530), [#3539](https://github.com/adap/flower/pull/3539), [#3425]" +"(https://github.com/adap/flower/pull/3425), [#3520](https://github.com/adap/" +"flower/pull/3520), [#3286](https://github.com/adap/flower/pull/3286), [#3516]" +"(https://github.com/adap/flower/pull/3516), [#3523](https://github.com/adap/" +"flower/pull/3523), [#3545](https://github.com/adap/flower/pull/3545), [#3498]" +"(https://github.com/adap/flower/pull/3498), [#3439](https://github.com/adap/" +"flower/pull/3439), [#3440](https://github.com/adap/flower/pull/3440), [#3382]" +"(https://github.com/adap/flower/pull/3382), [#3559](https://github.com/adap/" +"flower/pull/3559), [#3432](https://github.com/adap/flower/pull/3432), [#3278]" +"(https://github.com/adap/flower/pull/3278), [#3371](https://github.com/adap/" +"flower/pull/3371), [#3519](https://github.com/adap/flower/pull/3519), [#3267]" +"(https://github.com/adap/flower/pull/3267), [#3204](https://github.com/adap/" +"flower/pull/3204), [#3274](https://github.com/adap/flower/pull/3274))" msgstr "" #: ../../source/ref-changelog.md:61 msgid "" -"As always, the Flower documentation has received many updates. Notable " -"new pages include:" +"As always, the Flower documentation has received many updates. Notable new " +"pages include:" msgstr "" #: ../../source/ref-changelog.md:63 msgid "" -"[How-to upgrate to Flower Next (Flower Next migration " -"guide)](https://flower.ai/docs/framework/how-to-upgrade-to-flower-" -"next.html)" +"[How-to upgrate to Flower Next (Flower Next migration guide)](https://flower." +"ai/docs/framework/how-to-upgrade-to-flower-next.html)" msgstr "" #: ../../source/ref-changelog.md:65 msgid "" -"[How-to run Flower using Docker](https://flower.ai/docs/framework/how-to-" -"run-flower-using-docker.html)" +"[How-to run Flower using Docker](https://flower.ai/docs/framework/how-to-run-" +"flower-using-docker.html)" msgstr "" #: ../../source/ref-changelog.md:67 msgid "" -"[Flower Mods reference](https://flower.ai/docs/framework/ref-" -"api/flwr.client.mod.html#module-flwr.client.mod)" +"[Flower Mods reference](https://flower.ai/docs/framework/ref-api/flwr.client." +"mod.html#module-flwr.client.mod)" msgstr "" #: ../../source/ref-changelog.md:69 msgid "" -"**General updates to Flower Examples** " -"([#3205](https://github.com/adap/flower/pull/3205), " -"[#3226](https://github.com/adap/flower/pull/3226), " -"[#3211](https://github.com/adap/flower/pull/3211), " -"[#3252](https://github.com/adap/flower/pull/3252), " -"[#3427](https://github.com/adap/flower/pull/3427), " -"[#3410](https://github.com/adap/flower/pull/3410), " -"[#3426](https://github.com/adap/flower/pull/3426), " -"[#3228](https://github.com/adap/flower/pull/3228), " -"[#3342](https://github.com/adap/flower/pull/3342), " -"[#3200](https://github.com/adap/flower/pull/3200), " -"[#3202](https://github.com/adap/flower/pull/3202), " -"[#3394](https://github.com/adap/flower/pull/3394), " -"[#3488](https://github.com/adap/flower/pull/3488), " -"[#3329](https://github.com/adap/flower/pull/3329), " -"[#3526](https://github.com/adap/flower/pull/3526), " -"[#3392](https://github.com/adap/flower/pull/3392), " -"[#3474](https://github.com/adap/flower/pull/3474), " -"[#3269](https://github.com/adap/flower/pull/3269))" +"**General updates to Flower Examples** ([#3205](https://github.com/adap/" +"flower/pull/3205), [#3226](https://github.com/adap/flower/pull/3226), [#3211]" +"(https://github.com/adap/flower/pull/3211), [#3252](https://github.com/adap/" +"flower/pull/3252), [#3427](https://github.com/adap/flower/pull/3427), [#3410]" +"(https://github.com/adap/flower/pull/3410), [#3426](https://github.com/adap/" +"flower/pull/3426), [#3228](https://github.com/adap/flower/pull/3228), [#3342]" +"(https://github.com/adap/flower/pull/3342), [#3200](https://github.com/adap/" +"flower/pull/3200), [#3202](https://github.com/adap/flower/pull/3202), [#3394]" +"(https://github.com/adap/flower/pull/3394), [#3488](https://github.com/adap/" +"flower/pull/3488), [#3329](https://github.com/adap/flower/pull/3329), [#3526]" +"(https://github.com/adap/flower/pull/3526), [#3392](https://github.com/adap/" +"flower/pull/3392), [#3474](https://github.com/adap/flower/pull/3474), [#3269]" +"(https://github.com/adap/flower/pull/3269))" msgstr "" #: ../../source/ref-changelog.md:71 @@ -14135,41 +15773,30 @@ msgstr "" #: ../../source/ref-changelog.md:73 msgid "" -"**General improvements** " -"([#3532](https://github.com/adap/flower/pull/3532), " -"[#3318](https://github.com/adap/flower/pull/3318), " -"[#3565](https://github.com/adap/flower/pull/3565), " -"[#3296](https://github.com/adap/flower/pull/3296), " -"[#3305](https://github.com/adap/flower/pull/3305), " -"[#3246](https://github.com/adap/flower/pull/3246), " -"[#3224](https://github.com/adap/flower/pull/3224), " -"[#3475](https://github.com/adap/flower/pull/3475), " -"[#3297](https://github.com/adap/flower/pull/3297), " -"[#3317](https://github.com/adap/flower/pull/3317), " -"[#3429](https://github.com/adap/flower/pull/3429), " -"[#3196](https://github.com/adap/flower/pull/3196), " -"[#3534](https://github.com/adap/flower/pull/3534), " -"[#3240](https://github.com/adap/flower/pull/3240), " -"[#3365](https://github.com/adap/flower/pull/3365), " -"[#3407](https://github.com/adap/flower/pull/3407), " -"[#3563](https://github.com/adap/flower/pull/3563), " -"[#3344](https://github.com/adap/flower/pull/3344), " -"[#3330](https://github.com/adap/flower/pull/3330), " -"[#3436](https://github.com/adap/flower/pull/3436), " -"[#3300](https://github.com/adap/flower/pull/3300), " -"[#3327](https://github.com/adap/flower/pull/3327), " -"[#3254](https://github.com/adap/flower/pull/3254), " -"[#3253](https://github.com/adap/flower/pull/3253), " -"[#3419](https://github.com/adap/flower/pull/3419), " -"[#3289](https://github.com/adap/flower/pull/3289), " -"[#3208](https://github.com/adap/flower/pull/3208), " -"[#3245](https://github.com/adap/flower/pull/3245), " -"[#3319](https://github.com/adap/flower/pull/3319), " -"[#3203](https://github.com/adap/flower/pull/3203), " -"[#3423](https://github.com/adap/flower/pull/3423), " -"[#3352](https://github.com/adap/flower/pull/3352), " -"[#3292](https://github.com/adap/flower/pull/3292), " -"[#3261](https://github.com/adap/flower/pull/3261))" +"**General improvements** ([#3532](https://github.com/adap/flower/pull/3532), " +"[#3318](https://github.com/adap/flower/pull/3318), [#3565](https://github." +"com/adap/flower/pull/3565), [#3296](https://github.com/adap/flower/" +"pull/3296), [#3305](https://github.com/adap/flower/pull/3305), [#3246]" +"(https://github.com/adap/flower/pull/3246), [#3224](https://github.com/adap/" +"flower/pull/3224), [#3475](https://github.com/adap/flower/pull/3475), [#3297]" +"(https://github.com/adap/flower/pull/3297), [#3317](https://github.com/adap/" +"flower/pull/3317), [#3429](https://github.com/adap/flower/pull/3429), [#3196]" +"(https://github.com/adap/flower/pull/3196), [#3534](https://github.com/adap/" +"flower/pull/3534), [#3240](https://github.com/adap/flower/pull/3240), [#3365]" +"(https://github.com/adap/flower/pull/3365), [#3407](https://github.com/adap/" +"flower/pull/3407), [#3563](https://github.com/adap/flower/pull/3563), [#3344]" +"(https://github.com/adap/flower/pull/3344), [#3330](https://github.com/adap/" +"flower/pull/3330), [#3436](https://github.com/adap/flower/pull/3436), [#3300]" +"(https://github.com/adap/flower/pull/3300), [#3327](https://github.com/adap/" +"flower/pull/3327), [#3254](https://github.com/adap/flower/pull/3254), [#3253]" +"(https://github.com/adap/flower/pull/3253), [#3419](https://github.com/adap/" +"flower/pull/3419), [#3289](https://github.com/adap/flower/pull/3289), [#3208]" +"(https://github.com/adap/flower/pull/3208), [#3245](https://github.com/adap/" +"flower/pull/3245), [#3319](https://github.com/adap/flower/pull/3319), [#3203]" +"(https://github.com/adap/flower/pull/3203), [#3423](https://github.com/adap/" +"flower/pull/3423), [#3352](https://github.com/adap/flower/pull/3352), [#3292]" +"(https://github.com/adap/flower/pull/3292), [#3261](https://github.com/adap/" +"flower/pull/3261))" msgstr "" #: ../../source/ref-changelog.md:75 ../../source/ref-changelog.md:1058 @@ -14182,36 +15809,36 @@ msgstr "" #: ../../source/ref-changelog.md:79 msgid "" -"Python 3.8 will stop receiving security fixes in [October " -"2024](https://devguide.python.org/versions/). Support for Python 3.8 is " -"now deprecated and will be removed in an upcoming release." +"Python 3.8 will stop receiving security fixes in [October 2024](https://" +"devguide.python.org/versions/). Support for Python 3.8 is now deprecated and " +"will be removed in an upcoming release." msgstr "" #: ../../source/ref-changelog.md:81 msgid "" -"**Deprecate (experimental)** `flower-driver-api` **and** `flower-fleet-" -"api` ([#3416](https://github.com/adap/flower/pull/3416), " -"[#3420](https://github.com/adap/flower/pull/3420))" +"**Deprecate (experimental)** `flower-driver-api` **and** `flower-fleet-api` " +"([#3416](https://github.com/adap/flower/pull/3416), [#3420](https://github." +"com/adap/flower/pull/3420))" msgstr "" #: ../../source/ref-changelog.md:83 msgid "" -"Flower 1.9 deprecates the two (experimental) commands `flower-driver-api`" -" and `flower-fleet-api`. Both commands will be removed in an upcoming " +"Flower 1.9 deprecates the two (experimental) commands `flower-driver-api` " +"and `flower-fleet-api`. Both commands will be removed in an upcoming " "release. Use `flower-superlink` instead." msgstr "" #: ../../source/ref-changelog.md:85 msgid "" -"**Deprecate** `--server` **in favor of** `--superlink` " -"([#3518](https://github.com/adap/flower/pull/3518))" +"**Deprecate** `--server` **in favor of** `--superlink` ([#3518](https://" +"github.com/adap/flower/pull/3518))" msgstr "" #: ../../source/ref-changelog.md:87 msgid "" -"The commands `flower-server-app` and `flower-client-app` should use " -"`--superlink` instead of the now deprecated `--server`. Support for " -"`--server` will be removed in a future release." +"The commands `flower-server-app` and `flower-client-app` should use `--" +"superlink` instead of the now deprecated `--server`. Support for `--server` " +"will be removed in a future release." msgstr "" #: ../../source/ref-changelog.md:89 ../../source/ref-changelog.md:163 @@ -14226,48 +15853,46 @@ msgstr "" #: ../../source/ref-changelog.md:91 msgid "" -"**Replace** `flower-superlink` **CLI option** `--certificates` **with** " -"`--ssl-ca-certfile` **,** `--ssl-certfile` **and** `--ssl-keyfile` " -"([#3512](https://github.com/adap/flower/pull/3512), " -"[#3408](https://github.com/adap/flower/pull/3408))" +"**Replace** `flower-superlink` **CLI option** `--certificates` **with** `--" +"ssl-ca-certfile` **,** `--ssl-certfile` **and** `--ssl-keyfile` ([#3512]" +"(https://github.com/adap/flower/pull/3512), [#3408](https://github.com/adap/" +"flower/pull/3408))" msgstr "" #: ../../source/ref-changelog.md:93 msgid "" "SSL-related `flower-superlink` CLI arguments were restructured in an " "incompatible way. Instead of passing a single `--certificates` flag with " -"three values, you now need to pass three flags (`--ssl-ca-certfile`, " -"`--ssl-certfile` and `--ssl-keyfile`) with one value each. Check out the " -"[SSL connections](https://flower.ai/docs/framework/how-to-enable-ssl-" -"connections.html) documentation page for details." +"three values, you now need to pass three flags (`--ssl-ca-certfile`, `--ssl-" +"certfile` and `--ssl-keyfile`) with one value each. Check out the [SSL " +"connections](https://flower.ai/docs/framework/how-to-enable-ssl-connections." +"html) documentation page for details." msgstr "" #: ../../source/ref-changelog.md:95 msgid "" -"**Remove SuperLink** `--vce` **option** " -"([#3513](https://github.com/adap/flower/pull/3513))" +"**Remove SuperLink** `--vce` **option** ([#3513](https://github.com/adap/" +"flower/pull/3513))" msgstr "" #: ../../source/ref-changelog.md:97 msgid "" -"Instead of separately starting a SuperLink and a `ServerApp` for " -"simulation, simulations must now be started using the single `flower-" -"simulation` command." +"Instead of separately starting a SuperLink and a `ServerApp` for simulation, " +"simulations must now be started using the single `flower-simulation` command." msgstr "" #: ../../source/ref-changelog.md:99 msgid "" -"**Merge** `--grpc-rere` **and** `--rest` **SuperLink options** " -"([#3527](https://github.com/adap/flower/pull/3527))" +"**Merge** `--grpc-rere` **and** `--rest` **SuperLink options** ([#3527]" +"(https://github.com/adap/flower/pull/3527))" msgstr "" #: ../../source/ref-changelog.md:101 msgid "" -"To simplify the usage of `flower-superlink`, previously separate sets of " -"CLI options for gRPC and REST were merged into one unified set of " -"options. Consult the [Flower CLI reference " -"documentation](https://flower.ai/docs/framework/ref-api-cli.html) for " -"details." +"To simplify the usage of `flower-superlink`, previously separate sets of CLI " +"options for gRPC and REST were merged into one unified set of options. " +"Consult the [Flower CLI reference documentation](https://flower.ai/docs/" +"framework/ref-api-cli.html) for details." msgstr "" #: ../../source/ref-changelog.md:103 @@ -14277,237 +15902,212 @@ msgstr "" #: ../../source/ref-changelog.md:109 msgid "" "`Adam Narozniak`, `Charles Beauville`, `Daniel J. Beutel`, `Daniel Nata " -"Nugraha`, `Danny`, `Gustavo Bertoli`, `Heng Pan`, `Ikko Eltociear " -"Ashimine`, `Jack Cook`, `Javier`, `Raj Parekh`, `Robert Steiner`, " -"`Sebastian van der Voort`, `Taner Topal`, `Yan Gao`, `mohammadnaseri`, " -"`tabdar-khan` " +"Nugraha`, `Danny`, `Gustavo Bertoli`, `Heng Pan`, `Ikko Eltociear Ashimine`, " +"`Jack Cook`, `Javier`, `Raj Parekh`, `Robert Steiner`, `Sebastian van der " +"Voort`, `Taner Topal`, `Yan Gao`, `mohammadnaseri`, `tabdar-khan` " msgstr "" #: ../../source/ref-changelog.md:113 msgid "" -"**Introduce Flower Next high-level API (stable)** " -"([#3002](https://github.com/adap/flower/pull/3002), " -"[#2934](https://github.com/adap/flower/pull/2934), " -"[#2958](https://github.com/adap/flower/pull/2958), " -"[#3173](https://github.com/adap/flower/pull/3173), " -"[#3174](https://github.com/adap/flower/pull/3174), " -"[#2923](https://github.com/adap/flower/pull/2923), " -"[#2691](https://github.com/adap/flower/pull/2691), " -"[#3079](https://github.com/adap/flower/pull/3079), " -"[#2961](https://github.com/adap/flower/pull/2961), " -"[#2924](https://github.com/adap/flower/pull/2924), " -"[#3166](https://github.com/adap/flower/pull/3166), " -"[#3031](https://github.com/adap/flower/pull/3031), " -"[#3057](https://github.com/adap/flower/pull/3057), " -"[#3000](https://github.com/adap/flower/pull/3000), " -"[#3113](https://github.com/adap/flower/pull/3113), " -"[#2957](https://github.com/adap/flower/pull/2957), " -"[#3183](https://github.com/adap/flower/pull/3183), " -"[#3180](https://github.com/adap/flower/pull/3180), " -"[#3035](https://github.com/adap/flower/pull/3035), " -"[#3189](https://github.com/adap/flower/pull/3189), " -"[#3185](https://github.com/adap/flower/pull/3185), " -"[#3190](https://github.com/adap/flower/pull/3190), " -"[#3191](https://github.com/adap/flower/pull/3191), " -"[#3195](https://github.com/adap/flower/pull/3195), " -"[#3197](https://github.com/adap/flower/pull/3197))" +"**Introduce Flower Next high-level API (stable)** ([#3002](https://github." +"com/adap/flower/pull/3002), [#2934](https://github.com/adap/flower/" +"pull/2934), [#2958](https://github.com/adap/flower/pull/2958), [#3173]" +"(https://github.com/adap/flower/pull/3173), [#3174](https://github.com/adap/" +"flower/pull/3174), [#2923](https://github.com/adap/flower/pull/2923), [#2691]" +"(https://github.com/adap/flower/pull/2691), [#3079](https://github.com/adap/" +"flower/pull/3079), [#2961](https://github.com/adap/flower/pull/2961), [#2924]" +"(https://github.com/adap/flower/pull/2924), [#3166](https://github.com/adap/" +"flower/pull/3166), [#3031](https://github.com/adap/flower/pull/3031), [#3057]" +"(https://github.com/adap/flower/pull/3057), [#3000](https://github.com/adap/" +"flower/pull/3000), [#3113](https://github.com/adap/flower/pull/3113), [#2957]" +"(https://github.com/adap/flower/pull/2957), [#3183](https://github.com/adap/" +"flower/pull/3183), [#3180](https://github.com/adap/flower/pull/3180), [#3035]" +"(https://github.com/adap/flower/pull/3035), [#3189](https://github.com/adap/" +"flower/pull/3189), [#3185](https://github.com/adap/flower/pull/3185), [#3190]" +"(https://github.com/adap/flower/pull/3190), [#3191](https://github.com/adap/" +"flower/pull/3191), [#3195](https://github.com/adap/flower/pull/3195), [#3197]" +"(https://github.com/adap/flower/pull/3197))" msgstr "" #: ../../source/ref-changelog.md:115 msgid "" "The Flower Next high-level API is stable! Flower Next is the future of " -"Flower - all new features (like Flower Mods) will be built on top of it. " -"You can start to migrate your existing projects to Flower Next by using " -"`ServerApp` and `ClientApp` (check out `quickstart-pytorch` or " -"`quickstart-tensorflow`, a detailed migration guide will follow shortly)." -" Flower Next allows you to run multiple projects concurrently (we call " -"this multi-run) and execute the same project in either simulation " -"environments or deployment environments without having to change a single" -" line of code. The best part? It's fully compatible with existing Flower " -"projects that use `Strategy`, `NumPyClient` & co." +"Flower - all new features (like Flower Mods) will be built on top of it. You " +"can start to migrate your existing projects to Flower Next by using " +"`ServerApp` and `ClientApp` (check out `quickstart-pytorch` or `quickstart-" +"tensorflow`, a detailed migration guide will follow shortly). Flower Next " +"allows you to run multiple projects concurrently (we call this multi-run) " +"and execute the same project in either simulation environments or deployment " +"environments without having to change a single line of code. The best part? " +"It's fully compatible with existing Flower projects that use `Strategy`, " +"`NumPyClient` & co." msgstr "" #: ../../source/ref-changelog.md:117 msgid "" -"**Introduce Flower Next low-level API (preview)** " -"([#3062](https://github.com/adap/flower/pull/3062), " -"[#3034](https://github.com/adap/flower/pull/3034), " -"[#3069](https://github.com/adap/flower/pull/3069))" +"**Introduce Flower Next low-level API (preview)** ([#3062](https://github." +"com/adap/flower/pull/3062), [#3034](https://github.com/adap/flower/" +"pull/3034), [#3069](https://github.com/adap/flower/pull/3069))" msgstr "" #: ../../source/ref-changelog.md:119 msgid "" "In addition to the Flower Next *high-level* API that uses `Strategy`, " -"`NumPyClient` & co, Flower 1.8 also comes with a preview version of the " -"new Flower Next *low-level* API. The low-level API allows for granular " -"control of every aspect of the learning process by sending/receiving " -"individual messages to/from client nodes. The new `ServerApp` supports " -"registering a custom `main` function that allows writing custom training " -"loops for methods like async FL, cyclic training, or federated analytics." -" The new `ClientApp` supports registering `train`, `evaluate` and `query`" -" functions that can access the raw message received from the `ServerApp`." -" New abstractions like `RecordSet`, `Message` and `Context` further " -"enable sending multiple models, multiple sets of config values and " -"metrics, stateful computations on the client node and implementations of " -"custom SMPC protocols, to name just a few." +"`NumPyClient` & co, Flower 1.8 also comes with a preview version of the new " +"Flower Next *low-level* API. The low-level API allows for granular control " +"of every aspect of the learning process by sending/receiving individual " +"messages to/from client nodes. The new `ServerApp` supports registering a " +"custom `main` function that allows writing custom training loops for methods " +"like async FL, cyclic training, or federated analytics. The new `ClientApp` " +"supports registering `train`, `evaluate` and `query` functions that can " +"access the raw message received from the `ServerApp`. New abstractions like " +"`RecordSet`, `Message` and `Context` further enable sending multiple models, " +"multiple sets of config values and metrics, stateful computations on the " +"client node and implementations of custom SMPC protocols, to name just a few." msgstr "" #: ../../source/ref-changelog.md:121 msgid "" -"**Introduce Flower Mods (preview)** " -"([#3054](https://github.com/adap/flower/pull/3054), " -"[#2911](https://github.com/adap/flower/pull/2911), " -"[#3083](https://github.com/adap/flower/pull/3083))" +"**Introduce Flower Mods (preview)** ([#3054](https://github.com/adap/flower/" +"pull/3054), [#2911](https://github.com/adap/flower/pull/2911), [#3083]" +"(https://github.com/adap/flower/pull/3083))" msgstr "" #: ../../source/ref-changelog.md:123 msgid "" "Flower Modifiers (we call them Mods) can intercept messages and analyze, " -"edit or handle them directly. Mods can be used to develop pluggable " -"modules that work across different projects. Flower 1.8 already includes " -"mods to log the size of a message, the number of parameters sent over the" -" network, differential privacy with fixed clipping and adaptive clipping," -" local differential privacy and secure aggregation protocols SecAgg and " -"SecAgg+. The Flower Mods API is released as a preview, but researchers " -"can already use it to experiment with arbirtrary SMPC protocols." +"edit or handle them directly. Mods can be used to develop pluggable modules " +"that work across different projects. Flower 1.8 already includes mods to log " +"the size of a message, the number of parameters sent over the network, " +"differential privacy with fixed clipping and adaptive clipping, local " +"differential privacy and secure aggregation protocols SecAgg and SecAgg+. " +"The Flower Mods API is released as a preview, but researchers can already " +"use it to experiment with arbirtrary SMPC protocols." msgstr "" #: ../../source/ref-changelog.md:125 msgid "" -"**Fine-tune LLMs with LLM FlowerTune** " -"([#3029](https://github.com/adap/flower/pull/3029), " -"[#3089](https://github.com/adap/flower/pull/3089), " -"[#3092](https://github.com/adap/flower/pull/3092), " -"[#3100](https://github.com/adap/flower/pull/3100), " -"[#3114](https://github.com/adap/flower/pull/3114), " -"[#3162](https://github.com/adap/flower/pull/3162), " -"[#3172](https://github.com/adap/flower/pull/3172))" +"**Fine-tune LLMs with LLM FlowerTune** ([#3029](https://github.com/adap/" +"flower/pull/3029), [#3089](https://github.com/adap/flower/pull/3089), [#3092]" +"(https://github.com/adap/flower/pull/3092), [#3100](https://github.com/adap/" +"flower/pull/3100), [#3114](https://github.com/adap/flower/pull/3114), [#3162]" +"(https://github.com/adap/flower/pull/3162), [#3172](https://github.com/adap/" +"flower/pull/3172))" msgstr "" #: ../../source/ref-changelog.md:127 msgid "" -"We are introducing LLM FlowerTune, an introductory example that " -"demonstrates federated LLM fine-tuning of pre-trained Llama2 models on " -"the Alpaca-GPT4 dataset. The example is built to be easily adapted to use" -" different models and/or datasets. Read our blog post [LLM FlowerTune: " -"Federated LLM Fine-tuning with Flower](https://flower.ai/blog/2024-03-14" -"-llm-flowertune-federated-llm-finetuning-with-flower/) for more details." +"We are introducing LLM FlowerTune, an introductory example that demonstrates " +"federated LLM fine-tuning of pre-trained Llama2 models on the Alpaca-GPT4 " +"dataset. The example is built to be easily adapted to use different models " +"and/or datasets. Read our blog post [LLM FlowerTune: Federated LLM Fine-" +"tuning with Flower](https://flower.ai/blog/2024-03-14-llm-flowertune-" +"federated-llm-finetuning-with-flower/) for more details." msgstr "" #: ../../source/ref-changelog.md:129 msgid "" -"**Introduce built-in Differential Privacy (preview)** " -"([#2798](https://github.com/adap/flower/pull/2798), " -"[#2959](https://github.com/adap/flower/pull/2959), " -"[#3038](https://github.com/adap/flower/pull/3038), " -"[#3147](https://github.com/adap/flower/pull/3147), " -"[#2909](https://github.com/adap/flower/pull/2909), " -"[#2893](https://github.com/adap/flower/pull/2893), " -"[#2892](https://github.com/adap/flower/pull/2892), " -"[#3039](https://github.com/adap/flower/pull/3039), " -"[#3074](https://github.com/adap/flower/pull/3074))" +"**Introduce built-in Differential Privacy (preview)** ([#2798](https://" +"github.com/adap/flower/pull/2798), [#2959](https://github.com/adap/flower/" +"pull/2959), [#3038](https://github.com/adap/flower/pull/3038), [#3147]" +"(https://github.com/adap/flower/pull/3147), [#2909](https://github.com/adap/" +"flower/pull/2909), [#2893](https://github.com/adap/flower/pull/2893), [#2892]" +"(https://github.com/adap/flower/pull/2892), [#3039](https://github.com/adap/" +"flower/pull/3039), [#3074](https://github.com/adap/flower/pull/3074))" msgstr "" #: ../../source/ref-changelog.md:131 msgid "" "Built-in Differential Privacy is here! Flower supports both central and " -"local differential privacy (DP). Central DP can be configured with either" -" fixed or adaptive clipping. The clipping can happen either on the " -"server-side or the client-side. Local DP does both clipping and noising " -"on the client-side. A new documentation page [explains Differential " -"Privacy approaches](https://flower.ai/docs/framework/explanation-" -"differential-privacy.html) and a new how-to guide describes [how to use " -"the new Differential Privacy components](https://flower.ai/docs/framework" -"/how-to-use-differential-privacy.html) in Flower." +"local differential privacy (DP). Central DP can be configured with either " +"fixed or adaptive clipping. The clipping can happen either on the server-" +"side or the client-side. Local DP does both clipping and noising on the " +"client-side. A new documentation page [explains Differential Privacy " +"approaches](https://flower.ai/docs/framework/explanation-differential-" +"privacy.html) and a new how-to guide describes [how to use the new " +"Differential Privacy components](https://flower.ai/docs/framework/how-to-use-" +"differential-privacy.html) in Flower." msgstr "" #: ../../source/ref-changelog.md:133 msgid "" -"**Introduce built-in Secure Aggregation (preview)** " -"([#3120](https://github.com/adap/flower/pull/3120), " -"[#3110](https://github.com/adap/flower/pull/3110), " -"[#3108](https://github.com/adap/flower/pull/3108))" +"**Introduce built-in Secure Aggregation (preview)** ([#3120](https://github." +"com/adap/flower/pull/3120), [#3110](https://github.com/adap/flower/" +"pull/3110), [#3108](https://github.com/adap/flower/pull/3108))" msgstr "" #: ../../source/ref-changelog.md:135 msgid "" -"Built-in Secure Aggregation is here! Flower now supports different secure" -" aggregation protocols out-of-the-box. The best part? You can add secure " -"aggregation to your Flower projects with only a few lines of code. In " -"this initial release, we inlcude support for SecAgg and SecAgg+, but more" -" protocols will be implemented shortly. We'll also add detailed docs that" -" explain secure aggregation and how to use it in Flower. You can already " +"Built-in Secure Aggregation is here! Flower now supports different secure " +"aggregation protocols out-of-the-box. The best part? You can add secure " +"aggregation to your Flower projects with only a few lines of code. In this " +"initial release, we inlcude support for SecAgg and SecAgg+, but more " +"protocols will be implemented shortly. We'll also add detailed docs that " +"explain secure aggregation and how to use it in Flower. You can already " "check out the new code example that shows how to use Flower to easily " -"combine Federated Learning, Differential Privacy and Secure Aggregation " -"in the same project." +"combine Federated Learning, Differential Privacy and Secure Aggregation in " +"the same project." msgstr "" #: ../../source/ref-changelog.md:137 msgid "" -"**Introduce** `flwr` **CLI (preview)** " -"([#2942](https://github.com/adap/flower/pull/2942), " -"[#3055](https://github.com/adap/flower/pull/3055), " -"[#3111](https://github.com/adap/flower/pull/3111), " -"[#3130](https://github.com/adap/flower/pull/3130), " -"[#3136](https://github.com/adap/flower/pull/3136), " -"[#3094](https://github.com/adap/flower/pull/3094), " -"[#3059](https://github.com/adap/flower/pull/3059), " -"[#3049](https://github.com/adap/flower/pull/3049), " -"[#3142](https://github.com/adap/flower/pull/3142))" +"**Introduce** `flwr` **CLI (preview)** ([#2942](https://github.com/adap/" +"flower/pull/2942), [#3055](https://github.com/adap/flower/pull/3055), [#3111]" +"(https://github.com/adap/flower/pull/3111), [#3130](https://github.com/adap/" +"flower/pull/3130), [#3136](https://github.com/adap/flower/pull/3136), [#3094]" +"(https://github.com/adap/flower/pull/3094), [#3059](https://github.com/adap/" +"flower/pull/3059), [#3049](https://github.com/adap/flower/pull/3049), [#3142]" +"(https://github.com/adap/flower/pull/3142))" msgstr "" #: ../../source/ref-changelog.md:139 msgid "" -"A new `flwr` CLI command allows creating new Flower projects (`flwr new`)" -" and then running them using the Simulation Engine (`flwr run`)." +"A new `flwr` CLI command allows creating new Flower projects (`flwr new`) " +"and then running them using the Simulation Engine (`flwr run`)." msgstr "" #: ../../source/ref-changelog.md:141 msgid "" -"**Introduce Flower Next Simulation Engine** " -"([#3024](https://github.com/adap/flower/pull/3024), " -"[#3061](https://github.com/adap/flower/pull/3061), " -"[#2997](https://github.com/adap/flower/pull/2997), " -"[#2783](https://github.com/adap/flower/pull/2783), " -"[#3184](https://github.com/adap/flower/pull/3184), " -"[#3075](https://github.com/adap/flower/pull/3075), " -"[#3047](https://github.com/adap/flower/pull/3047), " -"[#2998](https://github.com/adap/flower/pull/2998), " -"[#3009](https://github.com/adap/flower/pull/3009), " -"[#3008](https://github.com/adap/flower/pull/3008))" +"**Introduce Flower Next Simulation Engine** ([#3024](https://github.com/adap/" +"flower/pull/3024), [#3061](https://github.com/adap/flower/pull/3061), [#2997]" +"(https://github.com/adap/flower/pull/2997), [#2783](https://github.com/adap/" +"flower/pull/2783), [#3184](https://github.com/adap/flower/pull/3184), [#3075]" +"(https://github.com/adap/flower/pull/3075), [#3047](https://github.com/adap/" +"flower/pull/3047), [#2998](https://github.com/adap/flower/pull/2998), [#3009]" +"(https://github.com/adap/flower/pull/3009), [#3008](https://github.com/adap/" +"flower/pull/3008))" msgstr "" #: ../../source/ref-changelog.md:143 msgid "" -"The Flower Simulation Engine can now run Flower Next projects. For " -"notebook environments, there's also a new `run_simulation` function that " -"can run `ServerApp` and `ClientApp`." +"The Flower Simulation Engine can now run Flower Next projects. For notebook " +"environments, there's also a new `run_simulation` function that can run " +"`ServerApp` and `ClientApp`." msgstr "" #: ../../source/ref-changelog.md:145 msgid "" -"**Handle SuperNode connection errors** " -"([#2969](https://github.com/adap/flower/pull/2969))" +"**Handle SuperNode connection errors** ([#2969](https://github.com/adap/" +"flower/pull/2969))" msgstr "" #: ../../source/ref-changelog.md:147 msgid "" -"A SuperNode will now try to reconnect indefinitely to the SuperLink in " -"case of connection errors. The arguments `--max-retries` and `--max-wait-" -"time` can now be passed to the `flower-client-app` command. `--max-" -"retries` will define the number of tentatives the client should make " -"before it gives up trying to reconnect to the SuperLink, and, `--max-" -"wait-time` defines the time before the SuperNode gives up trying to " -"reconnect to the SuperLink." +"A SuperNode will now try to reconnect indefinitely to the SuperLink in case " +"of connection errors. The arguments `--max-retries` and `--max-wait-time` " +"can now be passed to the `flower-client-app` command. `--max-retries` will " +"define the number of tentatives the client should make before it gives up " +"trying to reconnect to the SuperLink, and, `--max-wait-time` defines the " +"time before the SuperNode gives up trying to reconnect to the SuperLink." msgstr "" #: ../../source/ref-changelog.md:149 msgid "" -"**General updates to Flower Baselines** " -"([#2904](https://github.com/adap/flower/pull/2904), " -"[#2482](https://github.com/adap/flower/pull/2482), " -"[#2985](https://github.com/adap/flower/pull/2985), " -"[#2968](https://github.com/adap/flower/pull/2968))" +"**General updates to Flower Baselines** ([#2904](https://github.com/adap/" +"flower/pull/2904), [#2482](https://github.com/adap/flower/pull/2482), [#2985]" +"(https://github.com/adap/flower/pull/2985), [#2968](https://github.com/adap/" +"flower/pull/2968))" msgstr "" #: ../../source/ref-changelog.md:151 @@ -14518,133 +16118,100 @@ msgstr "" #: ../../source/ref-changelog.md:153 msgid "" -"**Improve documentation and translations** " -"([#3050](https://github.com/adap/flower/pull/3050), " -"[#3044](https://github.com/adap/flower/pull/3044), " -"[#3043](https://github.com/adap/flower/pull/3043), " -"[#2986](https://github.com/adap/flower/pull/2986), " -"[#3041](https://github.com/adap/flower/pull/3041), " -"[#3046](https://github.com/adap/flower/pull/3046), " -"[#3042](https://github.com/adap/flower/pull/3042), " -"[#2978](https://github.com/adap/flower/pull/2978), " -"[#2952](https://github.com/adap/flower/pull/2952), " -"[#3167](https://github.com/adap/flower/pull/3167), " -"[#2953](https://github.com/adap/flower/pull/2953), " -"[#3045](https://github.com/adap/flower/pull/3045), " -"[#2654](https://github.com/adap/flower/pull/2654), " -"[#3082](https://github.com/adap/flower/pull/3082), " -"[#2990](https://github.com/adap/flower/pull/2990), " -"[#2989](https://github.com/adap/flower/pull/2989))" +"**Improve documentation and translations** ([#3050](https://github.com/adap/" +"flower/pull/3050), [#3044](https://github.com/adap/flower/pull/3044), [#3043]" +"(https://github.com/adap/flower/pull/3043), [#2986](https://github.com/adap/" +"flower/pull/2986), [#3041](https://github.com/adap/flower/pull/3041), [#3046]" +"(https://github.com/adap/flower/pull/3046), [#3042](https://github.com/adap/" +"flower/pull/3042), [#2978](https://github.com/adap/flower/pull/2978), [#2952]" +"(https://github.com/adap/flower/pull/2952), [#3167](https://github.com/adap/" +"flower/pull/3167), [#2953](https://github.com/adap/flower/pull/2953), [#3045]" +"(https://github.com/adap/flower/pull/3045), [#2654](https://github.com/adap/" +"flower/pull/2654), [#3082](https://github.com/adap/flower/pull/3082), [#2990]" +"(https://github.com/adap/flower/pull/2990), [#2989](https://github.com/adap/" +"flower/pull/2989))" msgstr "" #: ../../source/ref-changelog.md:155 msgid "" "As usual, we merged many smaller and larger improvements to the " -"documentation. A special thank you goes to [Sebastian van der " -"Voort](https://github.com/svdvoort) for landing a big documentation PR!" +"documentation. A special thank you goes to [Sebastian van der Voort](https://" +"github.com/svdvoort) for landing a big documentation PR!" msgstr "" #: ../../source/ref-changelog.md:157 msgid "" -"**General updates to Flower Examples** " -"([3134](https://github.com/adap/flower/pull/3134), " -"[2996](https://github.com/adap/flower/pull/2996), " -"[2930](https://github.com/adap/flower/pull/2930), " -"[2967](https://github.com/adap/flower/pull/2967), " -"[2467](https://github.com/adap/flower/pull/2467), " -"[2910](https://github.com/adap/flower/pull/2910), " -"[#2918](https://github.com/adap/flower/pull/2918), " -"[#2773](https://github.com/adap/flower/pull/2773), " -"[#3063](https://github.com/adap/flower/pull/3063), " -"[#3116](https://github.com/adap/flower/pull/3116), " -"[#3117](https://github.com/adap/flower/pull/3117))" +"**General updates to Flower Examples** ([3134](https://github.com/adap/" +"flower/pull/3134), [2996](https://github.com/adap/flower/pull/2996), [2930]" +"(https://github.com/adap/flower/pull/2930), [2967](https://github.com/adap/" +"flower/pull/2967), [2467](https://github.com/adap/flower/pull/2467), [2910]" +"(https://github.com/adap/flower/pull/2910), [#2918](https://github.com/adap/" +"flower/pull/2918), [#2773](https://github.com/adap/flower/pull/2773), [#3063]" +"(https://github.com/adap/flower/pull/3063), [#3116](https://github.com/adap/" +"flower/pull/3116), [#3117](https://github.com/adap/flower/pull/3117))" msgstr "" #: ../../source/ref-changelog.md:159 msgid "" -"Two new examples show federated training of a Vision Transformer (ViT) " -"and federated learning in a medical context using the popular MONAI " -"library. `quickstart-pytorch` and `quickstart-tensorflow` demonstrate the" -" new Flower Next `ServerApp` and `ClientApp`. Many other examples " -"received considerable updates as well." +"Two new examples show federated training of a Vision Transformer (ViT) and " +"federated learning in a medical context using the popular MONAI library. " +"`quickstart-pytorch` and `quickstart-tensorflow` demonstrate the new Flower " +"Next `ServerApp` and `ClientApp`. Many other examples received considerable " +"updates as well." msgstr "" #: ../../source/ref-changelog.md:161 msgid "" -"**General improvements** " -"([#3171](https://github.com/adap/flower/pull/3171), " -"[3099](https://github.com/adap/flower/pull/3099), " -"[3003](https://github.com/adap/flower/pull/3003), " -"[3145](https://github.com/adap/flower/pull/3145), " -"[3017](https://github.com/adap/flower/pull/3017), " -"[3085](https://github.com/adap/flower/pull/3085), " -"[3012](https://github.com/adap/flower/pull/3012), " -"[3119](https://github.com/adap/flower/pull/3119), " -"[2991](https://github.com/adap/flower/pull/2991), " -"[2970](https://github.com/adap/flower/pull/2970), " -"[2980](https://github.com/adap/flower/pull/2980), " -"[3086](https://github.com/adap/flower/pull/3086), " -"[2932](https://github.com/adap/flower/pull/2932), " -"[2928](https://github.com/adap/flower/pull/2928), " -"[2941](https://github.com/adap/flower/pull/2941), " -"[2933](https://github.com/adap/flower/pull/2933), " -"[3181](https://github.com/adap/flower/pull/3181), " -"[2973](https://github.com/adap/flower/pull/2973), " -"[2992](https://github.com/adap/flower/pull/2992), " -"[2915](https://github.com/adap/flower/pull/2915), " -"[3040](https://github.com/adap/flower/pull/3040), " -"[3022](https://github.com/adap/flower/pull/3022), " -"[3032](https://github.com/adap/flower/pull/3032), " -"[2902](https://github.com/adap/flower/pull/2902), " -"[2931](https://github.com/adap/flower/pull/2931), " -"[3005](https://github.com/adap/flower/pull/3005), " -"[3132](https://github.com/adap/flower/pull/3132), " -"[3115](https://github.com/adap/flower/pull/3115), " -"[2944](https://github.com/adap/flower/pull/2944), " -"[3064](https://github.com/adap/flower/pull/3064), " -"[3106](https://github.com/adap/flower/pull/3106), " -"[2974](https://github.com/adap/flower/pull/2974), " -"[3178](https://github.com/adap/flower/pull/3178), " -"[2993](https://github.com/adap/flower/pull/2993), " -"[3186](https://github.com/adap/flower/pull/3186), " -"[3091](https://github.com/adap/flower/pull/3091), " -"[3125](https://github.com/adap/flower/pull/3125), " -"[3093](https://github.com/adap/flower/pull/3093), " -"[3013](https://github.com/adap/flower/pull/3013), " -"[3033](https://github.com/adap/flower/pull/3033), " -"[3133](https://github.com/adap/flower/pull/3133), " -"[3068](https://github.com/adap/flower/pull/3068), " -"[2916](https://github.com/adap/flower/pull/2916), " -"[2975](https://github.com/adap/flower/pull/2975), " -"[2984](https://github.com/adap/flower/pull/2984), " -"[2846](https://github.com/adap/flower/pull/2846), " -"[3077](https://github.com/adap/flower/pull/3077), " -"[3143](https://github.com/adap/flower/pull/3143), " -"[2921](https://github.com/adap/flower/pull/2921), " -"[3101](https://github.com/adap/flower/pull/3101), " -"[2927](https://github.com/adap/flower/pull/2927), " -"[2995](https://github.com/adap/flower/pull/2995), " -"[2972](https://github.com/adap/flower/pull/2972), " -"[2912](https://github.com/adap/flower/pull/2912), " -"[3065](https://github.com/adap/flower/pull/3065), " -"[3028](https://github.com/adap/flower/pull/3028), " -"[2922](https://github.com/adap/flower/pull/2922), " -"[2982](https://github.com/adap/flower/pull/2982), " -"[2914](https://github.com/adap/flower/pull/2914), " -"[3179](https://github.com/adap/flower/pull/3179), " -"[3080](https://github.com/adap/flower/pull/3080), " -"[2994](https://github.com/adap/flower/pull/2994), " -"[3187](https://github.com/adap/flower/pull/3187), " -"[2926](https://github.com/adap/flower/pull/2926), " -"[3018](https://github.com/adap/flower/pull/3018), " -"[3144](https://github.com/adap/flower/pull/3144), " -"[3011](https://github.com/adap/flower/pull/3011), " -"[#3152](https://github.com/adap/flower/pull/3152), " -"[#2836](https://github.com/adap/flower/pull/2836), " -"[#2929](https://github.com/adap/flower/pull/2929), " -"[#2943](https://github.com/adap/flower/pull/2943), " -"[#2955](https://github.com/adap/flower/pull/2955), " -"[#2954](https://github.com/adap/flower/pull/2954))" +"**General improvements** ([#3171](https://github.com/adap/flower/pull/3171), " +"[3099](https://github.com/adap/flower/pull/3099), [3003](https://github.com/" +"adap/flower/pull/3003), [3145](https://github.com/adap/flower/pull/3145), " +"[3017](https://github.com/adap/flower/pull/3017), [3085](https://github.com/" +"adap/flower/pull/3085), [3012](https://github.com/adap/flower/pull/3012), " +"[3119](https://github.com/adap/flower/pull/3119), [2991](https://github.com/" +"adap/flower/pull/2991), [2970](https://github.com/adap/flower/pull/2970), " +"[2980](https://github.com/adap/flower/pull/2980), [3086](https://github.com/" +"adap/flower/pull/3086), [2932](https://github.com/adap/flower/pull/2932), " +"[2928](https://github.com/adap/flower/pull/2928), [2941](https://github.com/" +"adap/flower/pull/2941), [2933](https://github.com/adap/flower/pull/2933), " +"[3181](https://github.com/adap/flower/pull/3181), [2973](https://github.com/" +"adap/flower/pull/2973), [2992](https://github.com/adap/flower/pull/2992), " +"[2915](https://github.com/adap/flower/pull/2915), [3040](https://github.com/" +"adap/flower/pull/3040), [3022](https://github.com/adap/flower/pull/3022), " +"[3032](https://github.com/adap/flower/pull/3032), [2902](https://github.com/" +"adap/flower/pull/2902), [2931](https://github.com/adap/flower/pull/2931), " +"[3005](https://github.com/adap/flower/pull/3005), [3132](https://github.com/" +"adap/flower/pull/3132), [3115](https://github.com/adap/flower/pull/3115), " +"[2944](https://github.com/adap/flower/pull/2944), [3064](https://github.com/" +"adap/flower/pull/3064), [3106](https://github.com/adap/flower/pull/3106), " +"[2974](https://github.com/adap/flower/pull/2974), [3178](https://github.com/" +"adap/flower/pull/3178), [2993](https://github.com/adap/flower/pull/2993), " +"[3186](https://github.com/adap/flower/pull/3186), [3091](https://github.com/" +"adap/flower/pull/3091), [3125](https://github.com/adap/flower/pull/3125), " +"[3093](https://github.com/adap/flower/pull/3093), [3013](https://github.com/" +"adap/flower/pull/3013), [3033](https://github.com/adap/flower/pull/3033), " +"[3133](https://github.com/adap/flower/pull/3133), [3068](https://github.com/" +"adap/flower/pull/3068), [2916](https://github.com/adap/flower/pull/2916), " +"[2975](https://github.com/adap/flower/pull/2975), [2984](https://github.com/" +"adap/flower/pull/2984), [2846](https://github.com/adap/flower/pull/2846), " +"[3077](https://github.com/adap/flower/pull/3077), [3143](https://github.com/" +"adap/flower/pull/3143), [2921](https://github.com/adap/flower/pull/2921), " +"[3101](https://github.com/adap/flower/pull/3101), [2927](https://github.com/" +"adap/flower/pull/2927), [2995](https://github.com/adap/flower/pull/2995), " +"[2972](https://github.com/adap/flower/pull/2972), [2912](https://github.com/" +"adap/flower/pull/2912), [3065](https://github.com/adap/flower/pull/3065), " +"[3028](https://github.com/adap/flower/pull/3028), [2922](https://github.com/" +"adap/flower/pull/2922), [2982](https://github.com/adap/flower/pull/2982), " +"[2914](https://github.com/adap/flower/pull/2914), [3179](https://github.com/" +"adap/flower/pull/3179), [3080](https://github.com/adap/flower/pull/3080), " +"[2994](https://github.com/adap/flower/pull/2994), [3187](https://github.com/" +"adap/flower/pull/3187), [2926](https://github.com/adap/flower/pull/2926), " +"[3018](https://github.com/adap/flower/pull/3018), [3144](https://github.com/" +"adap/flower/pull/3144), [3011](https://github.com/adap/flower/pull/3011), " +"[#3152](https://github.com/adap/flower/pull/3152), [#2836](https://github." +"com/adap/flower/pull/2836), [#2929](https://github.com/adap/flower/" +"pull/2929), [#2943](https://github.com/adap/flower/pull/2943), [#2955]" +"(https://github.com/adap/flower/pull/2955), [#2954](https://github.com/adap/" +"flower/pull/2954))" msgstr "" #: ../../source/ref-changelog.md:165 ../../source/ref-changelog.md:442 @@ -14659,97 +16226,91 @@ msgstr "" #: ../../source/ref-changelog.md:173 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` " +"`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:177 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))" +"**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:179 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." +"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:181 msgid "" -"**Improve performance** " -"([#2293](https://github.com/adap/flower/pull/2293))" +"**Improve performance** ([#2293](https://github.com/adap/flower/pull/2293))" msgstr "" #: ../../source/ref-changelog.md:183 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." +"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:185 msgid "" -"**Support Federated Learning with Apple MLX and Flower** " -"([#2693](https://github.com/adap/flower/pull/2693))" +"**Support Federated Learning with Apple MLX and Flower** ([#2693](https://" +"github.com/adap/flower/pull/2693))" msgstr "" #: ../../source/ref-changelog.md:187 msgid "" -"Flower has official support for federated learning using [Apple " -"MLX](https://ml-explore.github.io/mlx) via the new `quickstart-mlx` code " -"example." +"Flower has official support for federated learning using [Apple MLX](https://" +"ml-explore.github.io/mlx) via the new `quickstart-mlx` code example." msgstr "" #: ../../source/ref-changelog.md:189 msgid "" -"**Introduce new XGBoost cyclic strategy** " -"([#2666](https://github.com/adap/flower/pull/2666), " -"[#2668](https://github.com/adap/flower/pull/2668))" +"**Introduce new XGBoost cyclic strategy** ([#2666](https://github.com/adap/" +"flower/pull/2666), [#2668](https://github.com/adap/flower/pull/2668))" msgstr "" #: ../../source/ref-changelog.md:191 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." +"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-changelog.md:193 msgid "" -"**Support Python 3.11** " -"([#2394](https://github.com/adap/flower/pull/2394))" +"**Support Python 3.11** ([#2394](https://github.com/adap/flower/pull/2394))" msgstr "" #: ../../source/ref-changelog.md:195 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." +"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-changelog.md:197 msgid "" -"**Update gRPC and ProtoBuf dependencies** " -"([#2814](https://github.com/adap/flower/pull/2814))" +"**Update gRPC and ProtoBuf dependencies** ([#2814](https://github.com/adap/" +"flower/pull/2814))" msgstr "" #: ../../source/ref-changelog.md:199 @@ -14760,72 +16321,65 @@ msgstr "" #: ../../source/ref-changelog.md:201 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))" +"**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-changelog.md:203 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.ai/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." msgstr "" #: ../../source/ref-changelog.md:205 msgid "" -"**Introduce** `flower-via-docker-compose` **example** " -"([#2626](https://github.com/adap/flower/pull/2626))" +"**Introduce** `flower-via-docker-compose` **example** ([#2626](https://" +"github.com/adap/flower/pull/2626))" msgstr "" #: ../../source/ref-changelog.md:207 msgid "" -"**Introduce** `quickstart-sklearn-tabular` **example** " -"([#2719](https://github.com/adap/flower/pull/2719))" +"**Introduce** `quickstart-sklearn-tabular` **example** ([#2719](https://" +"github.com/adap/flower/pull/2719))" msgstr "" #: ../../source/ref-changelog.md:209 msgid "" -"**Introduce** `custom-metrics` **example** " -"([#1958](https://github.com/adap/flower/pull/1958))" +"**Introduce** `custom-metrics` **example** ([#1958](https://github.com/adap/" +"flower/pull/1958))" msgstr "" #: ../../source/ref-changelog.md:211 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))" +"**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-changelog.md:213 msgid "" -"Several code examples were updated to use [Flower " -"Datasets](https://flower.ai/docs/datasets/)." +"Several code examples were updated to use [Flower Datasets](https://flower." +"ai/docs/datasets/)." msgstr "" #: ../../source/ref-changelog.md:215 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))" +"**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 "" #: ../../source/ref-changelog.md:217 @@ -14838,8 +16392,8 @@ msgstr "" #: ../../source/ref-changelog.md:221 msgid "" -"HFedXGBoost ([#2226](https://github.com/adap/flower/pull/2226), " -"[#2771](https://github.com/adap/flower/pull/2771))" +"HFedXGBoost ([#2226](https://github.com/adap/flower/pull/2226), [#2771]" +"(https://github.com/adap/flower/pull/2771))" msgstr "" #: ../../source/ref-changelog.md:222 @@ -14864,149 +16418,119 @@ msgstr "" #: ../../source/ref-changelog.md:228 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))" +"**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:230 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))" +"**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:232 msgid "" -"The Flower testing and development infrastructure has received " -"substantial updates. This makes Flower 1.7 the most tested release ever." +"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:234 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))" +"**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:236 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))" +"**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:240 msgid "" -"**Deprecate** `start_numpy_client` " -"([#2563](https://github.com/adap/flower/pull/2563), " -"[#2718](https://github.com/adap/flower/pull/2718))" +"**Deprecate** `start_numpy_client` ([#2563](https://github.com/adap/flower/" +"pull/2563), [#2718](https://github.com/adap/flower/pull/2718))" msgstr "" #: ../../source/ref-changelog.md:242 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." +"`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:244 msgid "" -"**Deprecate legacy DP wrappers** " -"([#2749](https://github.com/adap/flower/pull/2749))" +"**Deprecate legacy DP wrappers** ([#2749](https://github.com/adap/flower/" +"pull/2749))" msgstr "" #: ../../source/ref-changelog.md:246 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." +"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:248 @@ -15017,28 +16541,26 @@ msgstr "" #: ../../source/ref-changelog.md:250 msgid "" -"**Rename** `certificates` **to** `root_certificates` **in** `Driver` " -"([#2890](https://github.com/adap/flower/pull/2890))" +"**Rename** `certificates` **to** `root_certificates` **in** `Driver` ([#2890]" +"(https://github.com/adap/flower/pull/2890))" msgstr "" #: ../../source/ref-changelog.md:252 msgid "" -"**Drop experimental** `Task` **fields** " -"([#2866](https://github.com/adap/flower/pull/2866), " -"[#2865](https://github.com/adap/flower/pull/2865))" +"**Drop experimental** `Task` **fields** ([#2866](https://github.com/adap/" +"flower/pull/2866), [#2865](https://github.com/adap/flower/pull/2865))" msgstr "" #: ../../source/ref-changelog.md:254 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." +"`legacy_client_message` were removed from `Task` message. The removed fields " +"are superseded by the new `RecordSet` abstraction." msgstr "" #: ../../source/ref-changelog.md:256 msgid "" -"**Retire MXNet examples** " -"([#2724](https://github.com/adap/flower/pull/2724))" +"**Retire MXNet examples** ([#2724](https://github.com/adap/flower/pull/2724))" msgstr "" #: ../../source/ref-changelog.md:258 @@ -15056,65 +16578,62 @@ msgstr "" 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` " +"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:270 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 "" #: ../../source/ref-changelog.md:272 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))" +"**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 "" #: ../../source/ref-changelog.md:274 msgid "" -"We have added a new `xgboost-quickstart` example alongside a new " -"`xgboost-comprehensive` example that goes more in-depth." +"We have added a new `xgboost-quickstart` example alongside a new `xgboost-" +"comprehensive` example that goes more in-depth." msgstr "" #: ../../source/ref-changelog.md:276 msgid "" -"**Add Vertical FL example** " -"([#2598](https://github.com/adap/flower/pull/2598))" +"**Add Vertical FL example** ([#2598](https://github.com/adap/flower/" +"pull/2598))" msgstr "" #: ../../source/ref-changelog.md:278 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)." +"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 "" #: ../../source/ref-changelog.md:280 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 "" #: ../../source/ref-changelog.md:282 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 "" #: ../../source/ref-changelog.md:284 msgid "" -"**Update the Android SDK** " -"([#2187](https://github.com/adap/flower/pull/2187))" +"**Update the Android SDK** ([#2187](https://github.com/adap/flower/" +"pull/2187))" msgstr "" #: ../../source/ref-changelog.md:286 @@ -15123,11 +16642,10 @@ msgstr "" #: ../../source/ref-changelog.md:288 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 "" #: ../../source/ref-changelog.md:290 @@ -15136,93 +16654,90 @@ msgstr "" #: ../../source/ref-changelog.md:292 msgid "" -"**Make HTTPS the new default** " -"([#2591](https://github.com/adap/flower/pull/2591), " -"[#2636](https://github.com/adap/flower/pull/2636))" +"**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:294 msgid "" "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." +"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:296 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`." +"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:298 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 "" #: ../../source/ref-changelog.md:300 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. The `to_client()` function is introduced to " +"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 "" #: ../../source/ref-changelog.md:302 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 "" #: ../../source/ref-changelog.md:304 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 "" #: ../../source/ref-changelog.md:306 msgid "" -"**Add new** `XGB Bagging` **strategy** " -"([#2611](https://github.com/adap/flower/pull/2611))" +"**Add new** `XGB Bagging` **strategy** ([#2611](https://github.com/adap/" +"flower/pull/2611))" msgstr "" #: ../../source/ref-changelog.md:308 ../../source/ref-changelog.md:310 msgid "" -"**Introduce `WorkloadState`** " -"([#2564](https://github.com/adap/flower/pull/2564), " -"[#2632](https://github.com/adap/flower/pull/2632))" +"**Introduce `WorkloadState`** ([#2564](https://github.com/adap/flower/" +"pull/2564), [#2632](https://github.com/adap/flower/pull/2632))" msgstr "" #: ../../source/ref-changelog.md:314 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:316 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 "" #: ../../source/ref-changelog.md:318 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:320 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:322 @@ -15255,125 +16770,106 @@ msgstr "" #: ../../source/ref-changelog.md:336 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:338 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))" +"**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:340 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))" +"**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 "" #: ../../source/ref-changelog.md:342 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))" +"**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 "" #: ../../source/ref-changelog.md:344 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))" +"**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:346 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))" +"**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:348 ../../source/ref-changelog.md:438 #: ../../source/ref-changelog.md:502 ../../source/ref-changelog.md:556 #: ../../source/ref-changelog.md:623 -msgid "Flower received many improvements under the hood, too many to list here." +msgid "" +"Flower received many improvements under the hood, too many to list here." msgstr "" #: ../../source/ref-changelog.md:352 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 "" #: ../../source/ref-changelog.md:354 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 "" #: ../../source/ref-changelog.md:356 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 "" #: ../../source/ref-changelog.md:358 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 "" #: ../../source/ref-changelog.md:360 @@ -15391,125 +16887,108 @@ msgstr "" #: ../../source/ref-changelog.md:370 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 "" #: ../../source/ref-changelog.md:372 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 "" #: ../../source/ref-changelog.md:374 msgid "" -"Comprehensive documentation includes a new [how-to run " -"simulations](https://flower.ai/docs/framework/how-to-run-" -"simulations.html) guide, new [simulation-" +"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)." +"tensorflow.html) notebooks, and a new [YouTube tutorial series](https://www." +"youtube.com/watch?v=cRebUIGB5RU&list=PLNG4feLHqCWlnj8a_E1A_n5zr2-8pafTB)." msgstr "" #: ../../source/ref-changelog.md:376 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:378 msgid "" -"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." +"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." msgstr "" #: ../../source/ref-changelog.md:380 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:382 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 "" #: ../../source/ref-changelog.md:384 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 "" #: ../../source/ref-changelog.md:386 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 "" #: ../../source/ref-changelog.md:388 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:390 msgid "" -"A new testing infrastructure ensures that new changes stay compatible " -"with existing framework integrations or strategies." +"A new testing infrastructure ensures that new changes stay compatible with " +"existing framework integrations or strategies." msgstr "" #: ../../source/ref-changelog.md:392 @@ -15518,124 +16997,121 @@ msgstr "" #: ../../source/ref-changelog.md:394 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 "" #: ../../source/ref-changelog.md:396 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 "" #: ../../source/ref-changelog.md:398 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 "" #: ../../source/ref-changelog.md:400 msgid "" -"**Introduce start_driver** " -"([#1697](https://github.com/adap/flower/pull/1697))" +"**Introduce start_driver** ([#1697](https://github.com/adap/flower/" +"pull/1697))" msgstr "" #: ../../source/ref-changelog.md:402 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 "" #: ../../source/ref-changelog.md:404 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 "" #: ../../source/ref-changelog.md:406 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 "" #: ../../source/ref-changelog.md:408 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 "" #: ../../source/ref-changelog.md:410 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 "" #: ../../source/ref-changelog.md:412 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 "" #: ../../source/ref-changelog.md:414 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 "" #: ../../source/ref-changelog.md:416 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 "" #: ../../source/ref-changelog.md:418 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 "" #: ../../source/ref-changelog.md:420 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 "" #: ../../source/ref-changelog.md:422 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 "" #: ../../source/ref-changelog.md:424 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 "" #: ../../source/ref-changelog.md:426 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 "" #: ../../source/ref-changelog.md:428 msgid "" -"**Improve example notebooks** " -"([#2005](https://github.com/adap/flower/pull/2005))" +"**Improve example notebooks** ([#2005](https://github.com/adap/flower/" +"pull/2005))" msgstr "" #: ../../source/ref-changelog.md:430 @@ -15645,36 +17121,31 @@ msgstr "" #: ../../source/ref-changelog.md:432 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 "" #: ../../source/ref-changelog.md:434 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 "" #: ../../source/ref-changelog.md:436 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 "" #: ../../source/ref-changelog.md:444 @@ -15684,110 +17155,103 @@ msgstr "" #: ../../source/ref-changelog.md:450 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:454 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 "" #: ../../source/ref-changelog.md:456 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" -"/xgboost-quickstart) 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/xgboost-quickstart) that demonstrates the usage of " +"this new strategy in an XGBoost project." msgstr "" #: ../../source/ref-changelog.md:458 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 "" #: ../../source/ref-changelog.md:460 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 "" #: ../../source/ref-changelog.md:462 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 "" #: ../../source/ref-changelog.md:464 msgid "" -"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 " +"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!" msgstr "" #: ../../source/ref-changelog.md:466 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 "" #: ../../source/ref-changelog.md:468 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 heterogeneous 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 heterogeneous settings." msgstr "" #: ../../source/ref-changelog.md:470 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 "" #: ../../source/ref-changelog.md:472 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 "" #: ../../source/ref-changelog.md:474 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 "" #: ../../source/ref-changelog.md:476 @@ -15805,132 +17269,112 @@ msgstr "" #: ../../source/ref-changelog.md:480 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))" +"**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 "" #: ../../source/ref-changelog.md:482 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 "" #: ../../source/ref-changelog.md:484 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 "" #: ../../source/ref-changelog.md:486 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 "" #: ../../source/ref-changelog.md:488 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 "" #: ../../source/ref-changelog.md:490 msgid "" -"TabNet is a powerful and flexible framework for training machine learning" -" models on tabular data. We now have a federated example using Flower: " -"[quickstart-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: " +"[quickstart-tabnet](https://github.com/adap/flower/tree/main/examples/" +"quickstart-tabnet)." msgstr "" #: ../../source/ref-changelog.md:492 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 "" #: ../../source/ref-changelog.md:494 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:496 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 "" #: ../../source/ref-changelog.md:498 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 "" #: ../../source/ref-changelog.md:500 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))" +"**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 "" #: ../../source/ref-changelog.md:508 @@ -15939,8 +17383,8 @@ msgstr "" #: ../../source/ref-changelog.md:514 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 "" #: ../../source/ref-changelog.md:518 @@ -15951,24 +17395,24 @@ msgstr "" #: ../../source/ref-changelog.md:520 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 "" #: ../../source/ref-changelog.md:522 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 "" #: ../../source/ref-changelog.md:524 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 "" #: ../../source/ref-changelog.md:526 @@ -15983,55 +17427,51 @@ msgstr "" #: ../../source/ref-changelog.md:530 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 "" #: ../../source/ref-changelog.md:532 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 "" #: ../../source/ref-changelog.md:534 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 "" #: ../../source/ref-changelog.md:536 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 "" #: ../../source/ref-changelog.md:538 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 "" #: ../../source/ref-changelog.md:540 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 "" #: ../../source/ref-changelog.md:542 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 "" #: ../../source/ref-changelog.md:544 @@ -16042,87 +17482,73 @@ msgstr "" #: ../../source/ref-changelog.md:546 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 "" #: ../../source/ref-changelog.md:548 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 "" #: ../../source/ref-changelog.md:550 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 "" #: ../../source/ref-changelog.md:552 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 "" #: ../../source/ref-changelog.md:554 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))" +"**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 "" #: ../../source/ref-changelog.md:558 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 "" #: ../../source/ref-changelog.md:560 ../../source/ref-changelog.md:627 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 "" #: ../../source/ref-changelog.md:566 @@ -16131,15 +17557,14 @@ msgstr "" #: ../../source/ref-changelog.md:572 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 "" #: ../../source/ref-changelog.md:576 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 "" #: ../../source/ref-changelog.md:578 @@ -16148,207 +17573,195 @@ 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.ai/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.ai/blog/2023-01-12-fl-starter-pack-" +"fedavg-mnist-cnn/)" msgstr "" #: ../../source/ref-changelog.md:580 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 "" #: ../../source/ref-changelog.md:582 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 "" #: ../../source/ref-changelog.md:584 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 "" #: ../../source/ref-changelog.md:586 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 "" #: ../../source/ref-changelog.md:588 msgid "" -"[An Introduction to Federated Learning](https://flower.ai/docs/framework" -"/tutorial-get-started-with-flower-pytorch.html)" +"[An Introduction to Federated Learning](https://flower.ai/docs/framework/" +"tutorial-get-started-with-flower-pytorch.html)" msgstr "" #: ../../source/ref-changelog.md:589 msgid "" -"[Strategies in Federated Learning](https://flower.ai/docs/framework" -"/tutorial-use-a-federated-learning-strategy-pytorch.html)" +"[Strategies in Federated Learning](https://flower.ai/docs/framework/tutorial-" +"use-a-federated-learning-strategy-pytorch.html)" msgstr "" #: ../../source/ref-changelog.md:590 msgid "" -"[Building a Strategy](https://flower.ai/docs/framework/tutorial-build-a" -"-strategy-from-scratch-pytorch.html)" +"[Building a Strategy](https://flower.ai/docs/framework/tutorial-build-a-" +"strategy-from-scratch-pytorch.html)" msgstr "" #: ../../source/ref-changelog.md:591 msgid "" -"[Client and NumPyClient](https://flower.ai/docs/framework/tutorial-" -"customize-the-client-pytorch.html)" +"[Client and NumPyClient](https://flower.ai/docs/framework/tutorial-customize-" +"the-client-pytorch.html)" msgstr "" #: ../../source/ref-changelog.md:593 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 "" #: ../../source/ref-changelog.md:595 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 "" #: ../../source/ref-changelog.md:597 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.ai/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)." msgstr "" #: ../../source/ref-changelog.md:599 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 "" #: ../../source/ref-changelog.md:601 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 "" #: ../../source/ref-changelog.md:603 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 "" #: ../../source/ref-changelog.md:605 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 "" #: ../../source/ref-changelog.md:607 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:609 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 "" #: ../../source/ref-changelog.md:611 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 "" #: ../../source/ref-changelog.md:613 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 "" #: ../../source/ref-changelog.md:615 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 "" #: ../../source/ref-changelog.md:617 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 "" #: ../../source/ref-changelog.md:619 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 "" #: ../../source/ref-changelog.md:621 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 "" #: ../../source/ref-changelog.md:625 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))" +"**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 "" #: ../../source/ref-changelog.md:629 msgid "" -"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!" +"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!" msgstr "" #: ../../source/ref-changelog.md:635 @@ -16365,110 +17778,106 @@ msgstr "" 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:645 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 "" #: ../../source/ref-changelog.md:647 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 "" #: ../../source/ref-changelog.md:649 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 "" #: ../../source/ref-changelog.md:651 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 "" #: ../../source/ref-changelog.md:653 msgid "" -"**New FedMedian strategy** " -"([#1461](https://github.com/adap/flower/pull/1461))" +"**New FedMedian strategy** ([#1461](https://github.com/adap/flower/" +"pull/1461))" msgstr "" #: ../../source/ref-changelog.md:655 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 "" #: ../../source/ref-changelog.md:657 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 "" #: ../../source/ref-changelog.md:659 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 "" #: ../../source/ref-changelog.md:661 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 "" #: ../../source/ref-changelog.md:663 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 "" #: ../../source/ref-changelog.md:665 msgid "" -"**Support optional** `Client`**/**`NumPyClient` **methods in Virtual " -"Client Engine**" +"**Support optional** `Client`**/**`NumPyClient` **methods in Virtual Client " +"Engine**" msgstr "" #: ../../source/ref-changelog.md:667 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 "" #: ../../source/ref-changelog.md:669 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 "" #: ../../source/ref-changelog.md:671 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 "" #: ../../source/ref-changelog.md:673 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 "" @@ -16480,24 +17889,18 @@ msgstr "" #: ../../source/ref-changelog.md:677 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))" +"**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 "" #: ../../source/ref-changelog.md:679 @@ -16508,47 +17911,45 @@ msgstr "" #: ../../source/ref-changelog.md:681 msgid "" -"**Restructured documentation** " -"([#1387](https://github.com/adap/flower/pull/1387))" +"**Restructured documentation** ([#1387](https://github.com/adap/flower/" +"pull/1387))" msgstr "" #: ../../source/ref-changelog.md:683 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 "" #: ../../source/ref-changelog.md:685 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 "" #: ../../source/ref-changelog.md:687 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 "" #: ../../source/ref-changelog.md:689 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 "" #: ../../source/ref-changelog.md:691 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 "" #: ../../source/ref-changelog.md:697 @@ -16573,93 +17974,79 @@ msgstr "" #: ../../source/ref-changelog.md:704 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:708 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 "" #: ../../source/ref-changelog.md:710 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), " -"[@sancarlim](https://github.com/sancarlim), " -"[@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), [@sancarlim](https://github." +"com/sancarlim), [@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:714 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 "" #: ../../source/ref-changelog.md:716 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 "" #: ../../source/ref-changelog.md:718 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 "" #: ../../source/ref-changelog.md:720 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 "" #: ../../source/ref-changelog.md:722 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 "" #: ../../source/ref-changelog.md:724 @@ -16682,17 +18069,17 @@ msgstr "" #: ../../source/ref-changelog.md:730 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 "" #: ../../source/ref-changelog.md:732 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 "" #: ../../source/ref-changelog.md:734 @@ -16701,14 +18088,14 @@ msgstr "" #: ../../source/ref-changelog.md:736 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 "" #: ../../source/ref-changelog.md:738 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 "" #: ../../source/ref-changelog.md:740 @@ -16721,39 +18108,40 @@ msgstr "" 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 "" #: ../../source/ref-changelog.md:744 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 "" #: ../../source/ref-changelog.md:746 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 "" #: ../../source/ref-changelog.md:748 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 "" #: ../../source/ref-changelog.md:750 -msgid "The experimental package `flwr.dataset` was migrated to Flower Baselines." +msgid "" +"The experimental package `flwr.dataset` was migrated to Flower Baselines." msgstr "" #: ../../source/ref-changelog.md:752 msgid "" -"**Remove experimental strategies** " -"([#1280](https://github.com/adap/flower/pull/1280))" +"**Remove experimental strategies** ([#1280](https://github.com/adap/flower/" +"pull/1280))" msgstr "" #: ../../source/ref-changelog.md:754 @@ -16764,9 +18152,8 @@ msgstr "" #: ../../source/ref-changelog.md:756 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 "" #: ../../source/ref-changelog.md:758 @@ -16777,21 +18164,21 @@ msgstr "" #: ../../source/ref-changelog.md:760 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 "" #: ../../source/ref-changelog.md:762 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 "" #: ../../source/ref-changelog.md:764 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 "" #: ../../source/ref-changelog.md:766 @@ -16809,64 +18196,62 @@ msgstr "" #: ../../source/ref-changelog.md:770 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 "" #: ../../source/ref-changelog.md:774 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 "" #: ../../source/ref-changelog.md:776 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 "" #: ../../source/ref-changelog.md:778 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 "" #: ../../source/ref-changelog.md:780 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 "" #: ../../source/ref-changelog.md:782 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 "" #: ../../source/ref-changelog.md:784 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 "" #: ../../source/ref-changelog.md:786 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 "" #: ../../source/ref-changelog.md:788 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:790 @@ -16895,8 +18280,8 @@ msgstr "" #: ../../source/ref-changelog.md:797 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 "" #: ../../source/ref-changelog.md:799 @@ -16908,27 +18293,24 @@ msgstr "" #: ../../source/ref-changelog.md:801 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))" +"**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 "" #: ../../source/ref-changelog.md:803 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 "" #: ../../source/ref-changelog.md:805 ../../source/ref-changelog.md:860 @@ -16938,30 +18320,28 @@ msgstr "" #: ../../source/ref-changelog.md:807 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 "" #: ../../source/ref-changelog.md:808 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 "" #: ../../source/ref-changelog.md:809 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 "" #: ../../source/ref-changelog.md:810 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 "" @@ -16971,123 +18351,120 @@ msgstr "" #: ../../source/ref-changelog.md:816 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 "" #: ../../source/ref-changelog.md:818 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.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/baselines/how-to-" -"contribute-baselines.html)." +"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/baselines/how-to-contribute-" +"baselines.html)." msgstr "" #: ../../source/ref-changelog.md:820 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 "" #: ../../source/ref-changelog.md:822 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 "" #: ../../source/ref-changelog.md:824 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 "" #: ../../source/ref-changelog.md:826 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 "" #: ../../source/ref-changelog.md:828 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 "" #: ../../source/ref-changelog.md:830 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 "" #: ../../source/ref-changelog.md:832 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 "" #: ../../source/ref-changelog.md:834 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 "" #: ../../source/ref-changelog.md:836 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 "" #: ../../source/ref-changelog.md:838 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 "" #: ../../source/ref-changelog.md:840 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 "" #: ../../source/ref-changelog.md:842 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 "" #: ../../source/ref-changelog.md:844 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 "" #: ../../source/ref-changelog.md:846 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 "" #: ../../source/ref-changelog.md:848 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 "" #: ../../source/ref-changelog.md:850 @@ -17098,8 +18475,8 @@ msgstr "" #: ../../source/ref-changelog.md:852 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 "" #: ../../source/ref-changelog.md:854 @@ -17110,8 +18487,7 @@ msgstr "" #: ../../source/ref-changelog.md:856 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 "" @@ -17135,41 +18511,40 @@ msgstr "" #: ../../source/ref-changelog.md:864 msgid "" -"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 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))" msgstr "" #: ../../source/ref-changelog.md:865 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 "" #: ../../source/ref-changelog.md:866 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 "" #: ../../source/ref-changelog.md:870 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 "" #: ../../source/ref-changelog.md:871 msgid "" -"**Remove deprecated KerasClient** " -"([#857](https://github.com/adap/flower/pull/857))" +"**Remove deprecated KerasClient** ([#857](https://github.com/adap/flower/" +"pull/857))" msgstr "" #: ../../source/ref-changelog.md:872 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 "" #: ../../source/ref-changelog.md:873 @@ -17180,20 +18555,20 @@ msgstr "" #: ../../source/ref-changelog.md:874 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 "" #: ../../source/ref-changelog.md:875 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 "" #: ../../source/ref-changelog.md:876 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 "" #: ../../source/ref-changelog.md:877 @@ -17209,156 +18584,152 @@ msgstr "" #: ../../source/ref-changelog.md:883 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 "" #: ../../source/ref-changelog.md:885 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 "" #: ../../source/ref-changelog.md:887 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 "" #: ../../source/ref-changelog.md:889 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 "" #: ../../source/ref-changelog.md:891 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 "" #: ../../source/ref-changelog.md:893 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 "" #: ../../source/ref-changelog.md:895 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 "" #: ../../source/ref-changelog.md:897 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 "" #: ../../source/ref-changelog.md:899 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 "" #: ../../source/ref-changelog.md:901 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 "" #: ../../source/ref-changelog.md:903 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 "" #: ../../source/ref-changelog.md:905 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 "" #: ../../source/ref-changelog.md:907 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 "" #: ../../source/ref-changelog.md:909 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 "" #: ../../source/ref-changelog.md:911 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:913 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 "" #: ../../source/ref-changelog.md:915 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 "" #: ../../source/ref-changelog.md:917 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 "" #: ../../source/ref-changelog.md:919 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 "" #: ../../source/ref-changelog.md:921 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 "" #: ../../source/ref-changelog.md:923 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 "" #: ../../source/ref-changelog.md:925 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 "" #: ../../source/ref-changelog.md:927 @@ -17372,38 +18743,38 @@ msgstr "" #: ../../source/ref-changelog.md:931 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 "" #: ../../source/ref-changelog.md:932 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 "" #: ../../source/ref-changelog.md:933 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 "" #: ../../source/ref-changelog.md:934 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 "" #: ../../source/ref-changelog.md:935 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 "" #: ../../source/ref-changelog.md:936 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 "" #: ../../source/ref-changelog.md:937 @@ -17423,8 +18794,8 @@ 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 "" #: ../../source/ref-changelog.md:945 @@ -17433,34 +18804,32 @@ msgstr "" #: ../../source/ref-changelog.md:949 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 "" #: ../../source/ref-changelog.md:951 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 "" #: ../../source/ref-changelog.md:953 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 "" #: ../../source/ref-changelog.md:955 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 "" @@ -17478,101 +18847,99 @@ msgstr "" #: ../../source/ref-changelog.md:960 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 "" #: ../../source/ref-changelog.md:962 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 "" #: ../../source/ref-changelog.md:964 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 "" #: ../../source/ref-changelog.md:966 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 "" #: ../../source/ref-changelog.md:970 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 "" #: ../../source/ref-changelog.md:971 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 "" #: ../../source/ref-changelog.md:972 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 "" #: ../../source/ref-changelog.md:973 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 "" #: ../../source/ref-changelog.md:974 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 "" #: ../../source/ref-changelog.md:978 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 "" #: ../../source/ref-changelog.md:980 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 "" #: ../../source/ref-changelog.md:982 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 "" #: ../../source/ref-changelog.md:984 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 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 original (now deprecated) " +"`QffedAvg` class is still available for compatibility reasons (it will be " +"removed in a future release)." msgstr "" #: ../../source/ref-changelog.md:986 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 "" #: ../../source/ref-changelog.md:988 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 "" #: ../../source/ref-changelog.md:990 @@ -17581,8 +18948,7 @@ msgstr "" #: ../../source/ref-changelog.md:994 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 "" #: ../../source/ref-changelog.md:996 @@ -17591,8 +18957,8 @@ msgstr "" #: ../../source/ref-changelog.md:999 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 "" #: ../../source/ref-changelog.md:1001 @@ -17606,20 +18972,19 @@ msgstr "" #: ../../source/ref-changelog.md:1003 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 built-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 built-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 "" #: ../../source/ref-changelog.md:1005 msgid "" "Strategy 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 "" #: ../../source/ref-changelog.md:1007 @@ -17630,25 +18995,24 @@ msgstr "" #: ../../source/ref-changelog.md:1009 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 "" #: ../../source/ref-changelog.md:1011 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 "" #: ../../source/ref-changelog.md:1013 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 "" #: ../../source/ref-changelog.md:1015 @@ -17658,43 +19022,39 @@ msgstr "" #: ../../source/ref-changelog.md:1017 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 "" #: ../../source/ref-changelog.md:1021 msgid "" -"**Serialization-agnostic server** " -"([#721](https://github.com/adap/flower/pull/721))" +"**Serialization-agnostic server** ([#721](https://github.com/adap/flower/" +"pull/721))" msgstr "" #: ../../source/ref-changelog.md:1023 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 "" #: ../../source/ref-changelog.md:1025 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 slightly 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 "" #: ../../source/ref-changelog.md:1027 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 "" #: ../../source/ref-changelog.md:1029 @@ -17703,8 +19063,8 @@ msgstr "" #: ../../source/ref-changelog.md:1033 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 "" #: ../../source/ref-changelog.md:1035 @@ -17717,9 +19077,9 @@ msgstr "" #: ../../source/ref-changelog.md:1037 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 "" #: ../../source/ref-changelog.md:1056 @@ -17732,8 +19092,8 @@ msgstr "" #: ../../source/ref-changelog.md:1060 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 "" #: ../../source/ref-changelog.md:1062 @@ -17743,35 +19103,33 @@ msgstr "" #: ../../source/ref-changelog.md:1066 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 "" #: ../../source/ref-changelog.md:1068 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 "" #: ../../source/ref-changelog.md:1070 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 "" #: ../../source/ref-changelog.md:1072 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 "" #: ../../source/ref-changelog.md:1074 @@ -17782,23 +19140,23 @@ msgstr "" #: ../../source/ref-changelog.md:1089 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 "" #: ../../source/ref-changelog.md:1091 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 "" #: ../../source/ref-changelog.md:1093 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 "" #: ../../source/ref-changelog.md:1095 @@ -17813,8 +19171,8 @@ msgstr "" #: ../../source/ref-changelog.md:1116 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 "" #: ../../source/ref-changelog.md:1117 @@ -17822,7 +19180,8 @@ msgid "Improved documentation" msgstr "" #: ../../source/ref-changelog.md:1118 -msgid "New documentation theme ([#551](https://github.com/adap/flower/pull/551))" +msgid "" +"New documentation theme ([#551](https://github.com/adap/flower/pull/551))" msgstr "" #: ../../source/ref-changelog.md:1119 @@ -17831,14 +19190,14 @@ msgstr "" #: ../../source/ref-changelog.md:1120 msgid "" -"Updated examples documentation " -"([#549](https://github.com/adap/flower/pull/549))" +"Updated examples documentation ([#549](https://github.com/adap/flower/" +"pull/549))" msgstr "" #: ../../source/ref-changelog.md:1121 msgid "" -"Removed obsolete documentation " -"([#548](https://github.com/adap/flower/pull/548))" +"Removed obsolete documentation ([#548](https://github.com/adap/flower/" +"pull/548))" msgstr "" #: ../../source/ref-changelog.md:1123 @@ -17847,10 +19206,9 @@ msgstr "" #: ../../source/ref-changelog.md:1125 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 "" #: ../../source/ref-changelog.md:1127 @@ -17863,23 +19221,22 @@ msgstr "" #: ../../source/ref-changelog.md:1131 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 "" #: ../../source/ref-changelog.md:1132 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 "" #: ../../source/ref-changelog.md:1133 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 "" #: ../../source/ref-changelog.md:1135 @@ -17892,12 +19249,11 @@ msgstr "" #: ../../source/ref-changelog.md:1139 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 "" #: ../../source/ref-changelog.md:1140 @@ -17918,33 +19274,32 @@ msgstr "" #: ../../source/ref-changelog.md:1147 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 "" #: ../../source/ref-changelog.md:1148 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 "" #: ../../source/ref-changelog.md:1149 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 "" #: ../../source/ref-changelog.md:1150 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 "" #: ../../source/ref-changelog.md:1151 msgid "" -"Improved `Strategy` docstrings " -"([#470](https://github.com/adap/flower/pull/470))." +"Improved `Strategy` docstrings ([#470](https://github.com/adap/flower/" +"pull/470))." msgstr "" #: ../../source/ref-example-projects.rst:2 @@ -17953,11 +19308,11 @@ 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 "" #: ../../source/ref-example-projects.rst:10 @@ -17968,25 +19323,25 @@ msgstr "" #: ../../source/ref-example-projects.rst:14 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 "" #: ../../source/ref-example-projects.rst:17 msgid "" -"`Quickstart TensorFlow (Code) " -"`_" +"`Quickstart TensorFlow (Code) `_" msgstr "" #: ../../source/ref-example-projects.rst:18 -msgid ":doc:`Quickstart TensorFlow (Tutorial) `" +msgid "" +":doc:`Quickstart TensorFlow (Tutorial) `" msgstr "" #: ../../source/ref-example-projects.rst:19 msgid "" -"`Quickstart TensorFlow (Blog Post) `_" +"`Quickstart TensorFlow (Blog Post) `_" msgstr "" #: ../../source/ref-example-projects.rst:23 @@ -17996,14 +19351,14 @@ msgstr "" #: ../../source/ref-example-projects.rst:25 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 "" #: ../../source/ref-example-projects.rst:28 msgid "" -"`Quickstart PyTorch (Code) " -"`_" +"`Quickstart PyTorch (Code) `_" msgstr "" #: ../../source/ref-example-projects.rst:29 @@ -18022,9 +19377,8 @@ msgstr "" #: ../../source/ref-example-projects.rst:37 msgid "" -"`PyTorch: From Centralized To Federated (Code) " -"`_" +"`PyTorch: From Centralized To Federated (Code) `_" msgstr "" #: ../../source/ref-example-projects.rst:38 @@ -18045,14 +19399,15 @@ msgstr "" #: ../../source/ref-example-projects.rst:46 msgid "" -"`Federated Learning on Raspberry Pi and Nvidia Jetson (Code) " -"`_" +"`Federated Learning on Raspberry Pi and Nvidia Jetson (Code) `_" msgstr "" #: ../../source/ref-example-projects.rst:47 msgid "" -"`Federated Learning on Raspberry Pi and Nvidia Jetson (Blog Post) " -"`_" +"`Federated Learning on Raspberry Pi and Nvidia Jetson (Blog Post) `_" msgstr "" #: ../../source/ref-faq.rst:4 @@ -18067,22 +19422,20 @@ msgstr "" #: ../../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 "" #: ../../source/ref-faq.rst:10 msgid "" -"`Flower simulation PyTorch " -"`_" +"`Flower simulation PyTorch `_" msgstr "" #: ../../source/ref-faq.rst:11 msgid "" -"`Flower simulation TensorFlow/Keras " -"`_" +"`Flower simulation TensorFlow/Keras `_" msgstr "" #: ../../source/ref-faq.rst @@ -18092,26 +19445,28 @@ msgstr "" #: ../../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 "" #: ../../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 "" #: ../../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 "" #: ../../source/ref-faq.rst:22 @@ -18130,33 +19485,33 @@ msgstr "" #: ../../source/ref-faq.rst:28 msgid "" -"`Flower meets Nevermined GitHub Repository `_." +"`Flower meets Nevermined GitHub Repository `_." msgstr "" #: ../../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 "" #: ../../source/ref-faq.rst:32 msgid "" -"`Flower meets Talan GitHub Repository " -"`_ ." +"`Flower meets Talan GitHub Repository `_ ." msgstr "" #: ../../source/ref-telemetry.md:1 @@ -18165,17 +19520,16 @@ 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 "" #: ../../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 "" #: ../../source/ref-telemetry.md:7 @@ -18183,35 +19537,34 @@ 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)”." +"**Optional:** You will always be able to disable telemetry; read on to learn " +"“[How to opt-out](#how-to-opt-out)”." msgstr "" #: ../../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 "" #: ../../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 "" #: ../../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 "" #: ../../source/ref-telemetry.md:16 @@ -18228,9 +19581,9 @@ msgstr "" #: ../../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 "" #: ../../source/ref-telemetry.md:26 @@ -18243,10 +19596,10 @@ msgstr "" #: ../../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 "" #: ../../source/ref-telemetry.md:32 @@ -18265,15 +19618,15 @@ msgstr "" #: ../../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 "" #: ../../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 "" @@ -18281,37 +19634,34 @@ msgstr "" 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 "" #: ../../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/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.ai`. 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." msgstr "" #: ../../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 "" #: ../../source/ref-telemetry.md:48 @@ -18328,17 +19678,17 @@ 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 "" #: ../../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 "" #: ../../source/ref-telemetry.md:64 @@ -18355,8 +19705,8 @@ msgstr "" #: ../../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 "" #: ../../source/tutorial-quickstart-android.rst:5 @@ -18365,21 +19715,19 @@ msgstr "" #: ../../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 "" #: ../../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 "" #: ../../source/tutorial-quickstart-fastai.rst:5 @@ -18392,15 +19740,14 @@ msgstr "" #: ../../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 "" #: ../../source/tutorial-quickstart-huggingface.rst:5 @@ -18409,17 +19756,17 @@ 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 "" #: ../../source/tutorial-quickstart-huggingface.rst:18 @@ -18429,9 +19776,8 @@ 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 "" #: ../../source/tutorial-quickstart-huggingface.rst:30 @@ -18455,9 +19801,9 @@ 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 "" #: ../../source/tutorial-quickstart-huggingface.rst:121 @@ -18466,8 +19812,8 @@ 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 "" #: ../../source/tutorial-quickstart-huggingface.rst:136 @@ -18481,18 +19827,17 @@ msgstr "" #: ../../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 "" #: ../../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 "" #: ../../source/tutorial-quickstart-huggingface.rst:175 @@ -18501,19 +19846,19 @@ 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 "" #: ../../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 "" #: ../../source/tutorial-quickstart-huggingface.rst:209 @@ -18532,22 +19877,22 @@ 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 `_ ." +"If you want to check out everything put together, you should check out the " +"`full code example `_ ." msgstr "" #: ../../source/tutorial-quickstart-huggingface.rst:226 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 "" #: ../../source/tutorial-quickstart-huggingface.rst:229 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 "" #: ../../source/tutorial-quickstart-ios.rst:-1 @@ -18562,38 +19907,38 @@ msgstr "" #: ../../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 "" #: ../../source/tutorial-quickstart-ios.rst:12 msgid "" "First of all, for running the Flower Python server, it is recommended to " -"create a virtual environment and run everything within a :doc:`virtualenv" -" `. For the Flower client " +"create a virtual environment and run everything within a :doc:`virtualenv " +"`. For the Flower client " "implementation in iOS, it is recommended to use Xcode as our IDE." msgstr "" #: ../../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 "" #: ../../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 "" #: ../../source/tutorial-quickstart-ios.rst:27 @@ -18611,21 +19956,20 @@ 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 "" #: ../../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 "" #: ../../source/tutorial-quickstart-ios.rst:75 @@ -18635,22 +19979,21 @@ 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`." +"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 " -"information 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 information " +"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 @@ -18661,18 +20004,18 @@ 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`." +"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." +"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:129 @@ -18688,8 +20031,8 @@ 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 "" #: ../../source/tutorial-quickstart-ios.rst:142 @@ -18705,32 +20048,31 @@ msgstr "" #: ../../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:" +"federated learning in action. FL systems usually have a server and multiple " +"clients. We therefore have to start the server first:" msgstr "" #: ../../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 "" #: ../../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 "" #: ../../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 "" #: ../../source/tutorial-quickstart-jax.rst:5 @@ -18739,8 +20081,8 @@ msgstr "" #: ../../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 "" #: ../../source/tutorial-quickstart-pandas.rst:5 @@ -18753,45 +20095,44 @@ msgstr "" #: ../../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 "" #: ../../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 "" #: ../../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 :doc:`virtualenv `." +"everything within a :doc:`virtualenv `." msgstr "" #: ../../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/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/tutorial-quickstart-pytorch.rst:23 @@ -18802,16 +20143,15 @@ msgstr "" #: ../../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 "" #: ../../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 "" @@ -18828,33 +20168,33 @@ msgstr "" #: ../../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 "" #: ../../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 "" #: ../../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 "" #: ../../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 "" #: ../../source/tutorial-quickstart-pytorch.rst:142 @@ -18866,20 +20206,19 @@ msgstr "" #: ../../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 "" #: ../../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 "" #: ../../source/tutorial-quickstart-pytorch.rst:156 @@ -18895,8 +20234,7 @@ msgstr "" #: ../../source/tutorial-quickstart-pytorch.rst:158 #: ../../source/tutorial-quickstart-scikitlearn.rst:121 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-pytorch.rst:160 @@ -18926,22 +20264,22 @@ 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 "" #: ../../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()`. 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." +"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 "" #: ../../source/tutorial-quickstart-pytorch.rst:226 @@ -18949,8 +20287,8 @@ msgstr "" #: ../../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:" +"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-pytorch.rst:233 @@ -18964,24 +20302,22 @@ msgstr "" #: ../../source/tutorial-quickstart-scikitlearn.rst:252 #: ../../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):" +"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-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 "" #: ../../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 "" #: ../../source/tutorial-quickstart-pytorch-lightning.rst:5 @@ -18990,21 +20326,20 @@ msgstr "" #: ../../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 "" #: ../../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 "" #: ../../source/tutorial-quickstart-scikitlearn.rst:5 @@ -19013,24 +20348,23 @@ 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 "" #: ../../source/tutorial-quickstart-scikitlearn.rst:12 msgid "" -"It is recommended to create a virtual environment and run everything " -"within this :doc:`virtualenv `." +"It is recommended to create a virtual environment and run everything within " +"this :doc:`virtualenv `." msgstr "" #: ../../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-scikitlearn.rst:20 @@ -19051,10 +20385,10 @@ msgstr "" 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 "" #: ../../source/tutorial-quickstart-scikitlearn.rst:45 @@ -19083,46 +20417,44 @@ msgstr "" #: ../../source/tutorial-quickstart-scikitlearn.rst:52 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 "" #: ../../source/tutorial-quickstart-scikitlearn.rst:67 msgid "" -"Prior to local training, we need to load the MNIST dataset, a popular " -"image classification dataset of handwritten digits for machine learning, " -"and partition the dataset for FL. This can be conveniently achieved using" -" `Flower Datasets `_. The " -":code:`FederatedDataset.load_partition()` method loads the partitioned " -"training set for each partition ID defined in the :code:`--partition-id` " -"argument." +"Prior to local training, we need to load the MNIST dataset, a popular image " +"classification dataset of handwritten digits for machine learning, and " +"partition the dataset for FL. This can be conveniently achieved using " +"`Flower Datasets `_. The :code:" +"`FederatedDataset.load_partition()` method loads the partitioned training " +"set for each partition ID defined in the :code:`--partition-id` argument." msgstr "" #: ../../source/tutorial-quickstart-scikitlearn.rst:95 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 "" #: ../../source/tutorial-quickstart-scikitlearn.rst:107 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 "" #: ../../source/tutorial-quickstart-scikitlearn.rst:113 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 "" #: ../../source/tutorial-quickstart-scikitlearn.rst:122 @@ -19135,28 +20467,28 @@ msgstr "" #: ../../source/tutorial-quickstart-scikitlearn.rst:153 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 "" #: ../../source/tutorial-quickstart-scikitlearn.rst:160 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." +"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 "" #: ../../source/tutorial-quickstart-scikitlearn.rst:169 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 "" #: ../../source/tutorial-quickstart-scikitlearn.rst:172 @@ -19165,46 +20497,44 @@ msgstr "" #: ../../source/tutorial-quickstart-scikitlearn.rst:185 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. Note that we also make use of Flower" -" Datasets here to load the test split of the MNIST dataset for server-" -"side evaluation." +"information about loss and accuracy. Note that we also make use of Flower " +"Datasets here to load the test split of the MNIST dataset for server-side " +"evaluation." msgstr "" #: ../../source/tutorial-quickstart-scikitlearn.rst:213 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 "" #: ../../source/tutorial-quickstart-scikitlearn.rst:232 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:286 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 "" #: ../../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 "" #: ../../source/tutorial-quickstart-tensorflow.rst:5 @@ -19221,8 +20551,8 @@ msgstr "" #: ../../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 "" #: ../../source/tutorial-quickstart-tensorflow.rst:31 @@ -19231,25 +20561,24 @@ msgstr "" #: ../../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 "" #: ../../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 "" #: ../../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 "" #: ../../source/tutorial-quickstart-tensorflow.rst:135 @@ -19258,23 +20587,22 @@ 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 "" #: ../../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 "" #: ../../source/tutorial-quickstart-xgboost.rst:5 @@ -19288,18 +20616,17 @@ msgstr "" #: ../../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 "" #: ../../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." +"training examples, XGBoost surpasses the results of deep learning techniques." msgstr "" #: ../../source/tutorial-quickstart-xgboost.rst:23 @@ -19309,30 +20636,30 @@ 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 " +"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." +"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." +"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 @@ -19353,16 +20680,16 @@ 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." +"*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:" +"In a file called :code:`client.py`, import xgboost, Flower, Flower Datasets " +"and other related functions:" msgstr "" #: ../../source/tutorial-quickstart-xgboost.rst:87 @@ -19371,15 +20698,15 @@ 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:" +"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`:" +"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 @@ -19390,8 +20717,8 @@ 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:" +"The functions of :code:`train_test_split` and :code:" +"`transform_dataset_to_dmatrix` are defined as below:" msgstr "" #: ../../source/tutorial-quickstart-xgboost.rst:158 @@ -19400,10 +20727,10 @@ 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." +"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 @@ -19412,86 +20739,85 @@ 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`." +"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." +"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." +"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." +"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:" +"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." +"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." +"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:" +"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." +"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." +"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`." +"In a file named :code:`server.py`, import Flower and FedXgbBagging from :" +"code:`flwr.server.strategy`." msgstr "" #: ../../source/tutorial-quickstart-xgboost.rst:316 @@ -19500,9 +20826,9 @@ 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." +"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 @@ -19515,16 +20841,16 @@ msgstr "" #: ../../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 "" #: ../../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 "" #: ../../source/tutorial-quickstart-xgboost.rst:454 @@ -19536,10 +20862,10 @@ 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." +"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 @@ -19555,16 +20881,16 @@ 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." +"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`." +"The full `source code `_ for this example can be found in :code:`examples/" +"xgboost-quickstart`." msgstr "" #: ../../source/tutorial-quickstart-xgboost.rst:594 @@ -19573,15 +20899,15 @@ 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 :doc:`Flower " -"simulation ` making it easy to simulate large " -"client cohorts in a resource-aware manner. 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 aggregation " +"strategies, data partitioning and centralised/distributed evaluation. We " +"also support :doc:`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 @@ -19590,41 +20916,40 @@ 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." +"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`:" +"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." +"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`." +"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:" +"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 @@ -19633,11 +20958,11 @@ 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)." +"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 @@ -19646,23 +20971,23 @@ msgstr "" #: ../../source/tutorial-quickstart-xgboost.rst:792 msgid "" -"To facilitate centralised evaluation, we define a function in " -":code:`server_utils.py`:" +"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." +"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`." +"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 @@ -19672,21 +20997,21 @@ 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." +"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:" +"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." +"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 @@ -19695,8 +21020,8 @@ msgstr "" #: ../../source/tutorial-quickstart-xgboost.rst:975 msgid "" -"After that, we start the simulation by calling " -":code:`fl.simulation.start_simulation`:" +"After that, we start the simulation by calling :code:`fl.simulation." +"start_simulation`:" msgstr "" #: ../../source/tutorial-quickstart-xgboost.rst:995 @@ -19711,18 +21036,18 @@ 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:" +"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." +"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 @@ -19731,11 +21056,10 @@ 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`." +"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 @@ -19752,9 +21076,9 @@ 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:" +"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 @@ -19767,9 +21091,9 @@ msgstr "" #: ../../source/tutorial-quickstart-xgboost.rst:1250 msgid "" -"The full `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 "" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:9 @@ -19780,19 +21104,18 @@ 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 `__)." +"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 "" #: ../../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 "" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:15 @@ -19800,11 +21123,11 @@ msgstr "" #: ../../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 "" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:17 @@ -19850,14 +21173,14 @@ msgstr "" #: ../../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``." +"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 "" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:114 @@ -19869,11 +21192,11 @@ 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 "" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:167 @@ -19886,8 +21209,8 @@ 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:" +"Let's continue with the usual model definition (including ``set_parameters`` " +"and ``get_parameters``), training and test functions:" msgstr "" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:258 @@ -19898,10 +21221,10 @@ msgstr "" #: ../../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 "" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:308 @@ -19914,11 +21237,11 @@ 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 "" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:507 @@ -19935,13 +21258,13 @@ 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 "" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:550 @@ -19950,8 +21273,8 @@ 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 "" #: ../../source/tutorial-series-build-a-strategy-from-scratch-pytorch.ipynb:552 @@ -19960,16 +21283,15 @@ 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 "" #: ../../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 "" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:9 @@ -19978,26 +21300,26 @@ 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 `__)." +"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 "" #: ../../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 "" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:18 @@ -20013,9 +21335,9 @@ msgstr "" #: ../../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 "" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:259 @@ -20024,10 +21346,10 @@ msgstr "" #: ../../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 "" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:309 @@ -20049,25 +21371,24 @@ 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 "" #: ../../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``." +"``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 "" #: ../../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 "" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:357 @@ -20076,14 +21397,13 @@ msgstr "" #: ../../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 "" #: ../../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 "" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:490 @@ -20094,40 +21414,40 @@ msgstr "" #: ../../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." +"``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 "" #: ../../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 "" #: ../../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``." +"``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 "" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:510 @@ -20144,17 +21464,16 @@ 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 "" #: ../../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 "" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:518 @@ -20174,15 +21493,15 @@ 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 "" #: ../../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 "" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:613 @@ -20191,30 +21510,28 @@ msgstr "" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:615 msgid "" -"To be 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 serialize our ``ndarray``\\ s into sparse parameters, we will " +"just have to call our custom functions in our ``flwr.client.Client``." msgstr "" #: ../../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 "" #: ../../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 "" #: ../../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 "" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:725 @@ -20223,11 +21540,10 @@ 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 "" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:729 @@ -20252,19 +21568,19 @@ 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." +"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 "" #: ../../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 "" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:954 @@ -20273,20 +21589,20 @@ msgstr "" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:955 msgid "" -"`Check out Flower Code Examples " -"`__" +"`Check out Flower Code Examples `__" msgstr "" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:956 msgid "" -"`Use Flower Baselines for your research " -"`__" +"`Use Flower Baselines for your research `__" msgstr "" #: ../../source/tutorial-series-customize-the-client-pytorch.ipynb:957 msgid "" -"`Watch Flower Summit 2023 videos `__" +"`Watch Flower Summit 2023 videos `__" msgstr "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:9 @@ -20301,10 +21617,9 @@ msgstr "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:13 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." +"`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 @@ -20321,20 +21636,19 @@ msgstr "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:45 msgid "" "Next, we install the necessary packages for PyTorch (``torch`` and " -"``torchvision``), Flower Datasets (``flwr-datasets``) 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``." +"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:118 @@ -20343,51 +21657,50 @@ msgstr "" #: ../../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: 'airplane', " -"'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', and " -"'truck'." +"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 "" #: ../../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 "" #: ../../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 " +"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:144 msgid "" "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 " +"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: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" -" 4000 training examples and 1000 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 4000 " +"training examples and 1000 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 "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:201 @@ -20401,8 +21714,8 @@ 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 "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:252 @@ -20415,8 +21728,8 @@ 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 "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:275 @@ -20425,9 +21738,9 @@ msgstr "" #: ../../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 "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:314 @@ -20441,20 +21754,19 @@ msgstr "" #: ../../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:" +"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 "" #: ../../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 "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:418 @@ -20463,11 +21775,11 @@ msgstr "" #: ../../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 "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:432 @@ -20476,30 +21788,29 @@ msgstr "" #: ../../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)." +"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: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 "" #: ../../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 "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:466 @@ -20508,19 +21819,18 @@ msgstr "" #: ../../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 "" #: ../../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 "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:472 @@ -20530,15 +21840,14 @@ msgstr "" #: ../../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" +"parameters on the local data, and return the (updated) model parameters to " +"the server" msgstr "" #: ../../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" +"``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:476 @@ -20551,16 +21860,15 @@ msgstr "" #: ../../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)." +"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 "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:517 @@ -20569,13 +21877,13 @@ msgstr "" #: ../../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 "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:521 @@ -20584,14 +21892,14 @@ 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:" +"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 "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:556 @@ -20600,31 +21908,31 @@ msgstr "" #: ../../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 "" #: ../../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 "" #: ../../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 "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:608 @@ -20638,20 +21946,20 @@ msgstr "" #: ../../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 "" #: ../../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 "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:626 @@ -20660,28 +21968,27 @@ msgstr "" #: ../../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 "" #: ../../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 "" #: ../../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 "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:634 @@ -20699,17 +22006,17 @@ msgstr "" #: ../../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 "" #: ../../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 "" #: ../../source/tutorial-series-get-started-with-flower-pytorch.ipynb:711 @@ -20719,28 +22026,28 @@ msgstr "" #: ../../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 "" #: ../../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." +"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: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 "" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:9 @@ -20750,16 +22057,16 @@ 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 "" #: ../../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 "" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:17 @@ -20773,8 +22080,8 @@ 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 @@ -20783,16 +22090,16 @@ 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 "" #: ../../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 "" @@ -20803,17 +22110,17 @@ 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 "" #: ../../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 "" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:424 @@ -20822,9 +22129,9 @@ 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 "" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:428 @@ -20832,33 +22139,33 @@ 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." +"**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 "" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:490 @@ -20867,50 +22174,48 @@ 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:" +"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 "" #: ../../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 "" #: ../../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 "" #: ../../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 "" #: ../../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 "" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:627 @@ -20927,14 +22232,13 @@ msgstr "" #, 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:" +"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 "" #: ../../source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb:699 @@ -20947,94 +22251,112 @@ 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 "" #: ../../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 "" #: ../../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 "" +"🧑‍🏫이 튜토리얼은 사전 지식을 많이 필요로 하지 않으며 연합 학습에 대해 " +"상세히알 필요는 없습니다. 데이터 과학과 파이썬 프로그래밍에 대한 기본적인 " +"이해만 가정합니다." #: ../../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: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." -msgstr "" +"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 "|93b02017c78049bbbd5ae456dcb2c91b|" -msgstr "" +msgstr "|93b02017c78049bbbd5ae456dcb2c91b|" #: ../../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 "|01471150fd5144c080a176b43e92a3ff|" -msgstr "" +msgstr "|01471150fd5144c080a176b43e92a3ff|" #: ../../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." -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 "" @@ -21042,46 +22364,54 @@ 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 "|9bc21c7dbd17444a8f070c60786e3484|" -msgstr "" +msgstr "|9bc21c7dbd17444a8f070c60786e3484|" #: ../../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 "|3047bbce54b34099ae559963d0420d79|" -msgstr "" +msgstr "|3047bbce54b34099ae559963d0420d79|" #: ../../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 "|e9f8ce948593444fb838d2f354c7ec5d|" -msgstr "" +msgstr "|e9f8ce948593444fb838d2f354c7ec5d|" #: ../../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 "" @@ -21089,56 +22419,68 @@ 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 "|c24c1478b30e4f74839208628a842d1e|" -msgstr "" +msgstr "|c24c1478b30e4f74839208628a842d1e|" #: ../../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 "|1b3613d7a58847b59e1d3180802dbc09|" -msgstr "" +msgstr "|1b3613d7a58847b59e1d3180802dbc09|" #: ../../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 "|9980b5213db547d0b8024a50992b9e3f|" -msgstr "" +msgstr "|9980b5213db547d0b8024a50992b9e3f|" #: ../../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 "" @@ -21147,376 +22489,478 @@ 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 alternative" -" 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 "" +"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 alternative 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 `__ " +"메신저와 같은 개인 정보 보호 시스템의 인기는 사용자들이 개인 정보 보호에 " +"신경 쓴다는 것을 보여줍니다. 실제로 그러한 대안이 존재하는 경우 다른 " +"대안보다 개인 정보 보호 강화 버전을 선택합니다. 그런데 이러한 사례에 " +"머신러닝 및 데이터 과학을 적용하여 프라이버시 데이터를 활용하려면 어떻게 " +"해야 합니까? 이 모든 분야는 최근 AI의 발전으로 상당한 이익을 얻을 수 있는 " +"분야입니다." #: ../../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 "" +"이를 통해 이전에는 불가능했던 분야에서 머신러닝(및 기타 데이터 과학 방법)을 " +"사용할 수 있습니다. 이제 다양한 병원이 협력할 수 있도록 함으로써 우수한 의료 " +"AI 모델을 훈련할 수 있습니다. 다양한 금융 기관의 데이터에 대한 AI 모델을 " +"훈련하여 금융 사기를 해결할 수 있습니다. 개인 정보 보호를 강화하지 않는 " +"대안보다 더 나은 AI가 내장된 새로운 개인 정보 보호 강화 애플리케이션(예: " +"보안 메시징)을 구축할 수 있습니다. 그것들은 떠오르는 몇 가지 예에 " +"불과합니다. 연합 학습을 구축함에 따라 이전에 액세스할 수 없었던 많은 " +"데이터에 액세스할 수 있게 되었기 때문에 갑자기 재생될 수 있는 영역이 점점 더 " +"많아지고 있습니다." #: ../../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 "연합 학습의 5단계" #: ../../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 "|c7afb4c92d154bfaa5e8cb9a150e17f1|" -msgstr "" +msgstr "|c7afb4c92d154bfaa5e8cb9a150e17f1|" #: ../../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 "|032eb6fed6924ac387b9f13854919196|" -msgstr "" +msgstr "|032eb6fed6924ac387b9f13854919196|" #: ../../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 "" +"이제 모든(선택된) 클라이언트 노드에는 최신 버전의 글로벌 모델 파라미터가 " +"있으며 로컬 훈련을 시작합니다. 그들은 자신의 로컬 데이터 세트를 사용하여 " +"자신의 로컬 모델을 훈련합니다. 모델이 완전히 수렴할 때까지 훈련하지 않고 " +"잠시만 훈련합니다. 이는 로컬 데이터에서 한 단계 정도로 짧거나 몇 단계(mini-" +"batches)에 불과할 수 있습니다." #: ../../source/tutorial-series-what-is-federated-learning.ipynb:240 msgid "|fbf225add7fd4df5a9bf25a95597d954|" -msgstr "" +msgstr "|fbf225add7fd4df5a9bf25a95597d954|" #: ../../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 "" +"로컬 훈련 후에는 클라이언트 노드마다 원래 받은 모델 파라미터의 버전이 조금씩 " +"다릅니다. 파라미터가 다른 이유는 각 클라이언트 노드의 로컬 데이터 세트에 " +"다른 데이터가 있기 때문입니다. 그런 다음 클라이언트 노드는 이러한 모델 " +"업데이트를 서버로 다시 보냅니다. 보내는 모델 업데이트는 전체 모델 " +"파라미터거나 로컬 교육 중에 누적된 그레디언트(gradient)일 수 있습니다." #: ../../source/tutorial-series-what-is-federated-learning.ipynb:255 msgid "|7efbe3d29d8349b89594e8947e910525|" -msgstr "" +msgstr "|7efbe3d29d8349b89594e8947e910525|" #: ../../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 et al., 2016 `__)이라고 하고 보통 줄여서 *FedAvg*로 표기합니다. " +"*FedAvg* 는 100개의 모델 업데이트를 받아 이름에서 알 수 있듯이 모델 " +"업데이트를 평균화합니다. 더 정확히 말하면, 모델 업데이트의 *가중 평균* 을 각 " +"클라이언트가 훈련에 사용한 예제 수에 따라 가중치를 부여합니다. 가중치는 각 " +"데이터 예제가 결과 글로벌 모델에 동일한 \"영향\" 을 미치는지 확인하는 데 " +"중요합니다. 한 클라이언트에 10개의 데이터 포인트가 있고 다른 클라이언트에 " +"100개의 데이터 포인트가 있다면 가중치를 부여하지 않고 10개의 예가 100개의 " +"사례보다 글로벌 모델에 10배 더 많은 영향을 미칩니다." #: ../../source/tutorial-series-what-is-federated-learning.ipynb:273 msgid "|329fb3c04c744eda83bb51fa444c2266|" -msgstr "" +msgstr "|329fb3c04c744eda83bb51fa444c2266|" #: ../../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)?" -msgstr "" +"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 "" +"다양한 클라이언트 노드의 분산된 데이터에 대해 모델을 훈련할 수 있는 것처럼 " +"해당 데이터에 대한 모델을 평가하여 가치 있는 메트릭(metrics)을 받을 수도 " +"있습니다. 이를 연합 평가라고 하며 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." -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 "" +"많은 경우 머신러닝은 데이터로부터 가치를 얻기 위한 필수 조건이 아닙니다. " +"데이터 분석을 통해 귀중한 통찰력을 얻을 수 있지만, 명확한 답변을 얻기에는 " +"데이터가 충분하지 않은 경우가 많습니다. 특정 유형의 건강 상태가 발생하는 " +"평균 연령은 몇 살입니까? 연합 분석을 사용하면 여러 클라이언트 노드에서 " +"이러한 쿼리(query)를 실행할 수 있습니다. 서버가 단일 클라이언트 노드에서 " +"제출한 결과를 보지 못하도록 보안을 강화한 집합 방식과 같은 다른 프라이버시 " +"향상 기술과 함께 자주 사용됩니다." #: ../../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 "" +"차분 프라이버시(Differential Privacy)는 연합 학습의 맥락에서 종종 " +"언급됩니다. 통계 데이터를 분석하고 공유할 때 사용하는 프라이버시 보호 " +"방식으로, 참가자 개인의 프라이버시를 보장합니다. 차분 프라이버시는 모델 " +"업데이트에 통계적 잡음(noise)를 추가하여 개별 참가자의 정보를 구별하거나 " +"재식별할 수 없도록 함으로써 이를 달성합니다. 이 기술은 정량적 개인 정보 보호 " +"조치를 제공하는 최적화라고 볼 수 있습니다." #: ../../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." -msgstr "" +"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는 " +"연합 학습, 분석 및 평가를 위한 통합 접근 방식을 제공합니다. 이를 통해 " +"사용자는 모든 워크로드, 머신러닝 프레임워크 및 모든 프로그래밍 언어를 통합할 " +"수 있습니다." #: ../../source/tutorial-series-what-is-federated-learning.ipynb:334 msgid "|c00bf2750bc24d229737a0fe1395f0fc|" -msgstr "" +msgstr "|c00bf2750bc24d229737a0fe1395f0fc|" #: ../../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 federated learning server and client nodes (car, scooter, personal " +"computer, roomba, and phone)" +msgstr "Flower 연합 학습 서버 및 클라이언트 노드(자동차, 스쿠터, 개인용 컴퓨터, " +"룸바, 전화)" #: ../../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." -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를 사용하여 간단한 " +"연합 학습 시스템을 구축하는 방법을 보여줍니다." #~ msgid "" -#~ "Currently, Flower provides two images, a" -#~ " ``base`` image and a ``superlink`` " -#~ "image. The base image, as the name" -#~ " suggests, contains basic dependencies that" -#~ " the SuperLink needs. This includes " -#~ "system dependencies, Python and Python " -#~ "tools. The SuperLink image is based " -#~ "on the base image, but it " -#~ "additionally installs the SuperLink using " -#~ "``pip``." +#~ "Currently, Flower provides two images, a ``base`` image and a " +#~ "``superlink`` image. The base image, as the name suggests, contains basic " +#~ "dependencies that the SuperLink needs. This includes system dependencies, " +#~ "Python and Python tools. The SuperLink image is based on the base image, " +#~ "but it additionally installs the SuperLink using ``pip``." #~ msgstr "" -#~ "현재, Flower는 \"base\" 이미지 그리고 " -#~ "\"superlink\" 이미지를 제공합니다. base 이미지는 이름에서" -#~ " 알 수 있듯이 SuperLink가 필요로 하는 기본" -#~ " dependencies를 포함하고 있습니다. 여기에는 시스템 " -#~ "dependencies, Python 및 Python 도구가 포함됩니다." -#~ " SuperLink 이미지는 base 이미지를 기반으로 하지만" -#~ " \"pip\"을 사용하여 SuperLink를 추가로 설치합니다." +#~ "현재, Flower는 \"base\" 이미지 그리고 \"superlink\" 이미지를 제공합니다. " +#~ "base 이미지는 이름에서 알 수 있듯이 SuperLink가 필요로 하는 기본 " +#~ "dependencies를 포함하고 있습니다. 여기에는 시스템 dependencies, Python 및 " +#~ "Python 도구가 포함됩니다. SuperLink 이미지는 base 이미지를 기반으로 하지" +#~ "만 \"pip\"을 사용하여 SuperLink를 추가로 설치합니다." #~ msgid "``3.11``" #~ msgstr "``3.11``" @@ -21540,279 +22984,10 @@ msgstr "" #~ msgstr "``flwr``이 기본값." #~ msgid "" -#~ "The name of image is ``flwr_superlink``" -#~ " 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 "" -#~ "이미지의 이름은 ``flwr_superlink``이고 태그는 " -#~ "``0.1.0``입니다. 필요에 따라 빌드 argument들 뿐만 " -#~ "아니라 이름과 태그도 정할 수 있습니다. 이 값들은" -#~ " 예시일 뿐입니다." - -#~ msgid "Creating New Messages" -#~ msgstr "" - -#~ msgid "" -#~ "This is a simple guide for " -#~ "creating a new type of message " -#~ "between the server and clients in " -#~ "Flower." -#~ msgstr "" - -#~ msgid "" -#~ "Let's suppose we have the following " -#~ "example functions in :code:`server.py` and " -#~ ":code:`numpy_client.py`..." -#~ msgstr "" - -#~ msgid "Server's side:" -#~ msgstr "" - -#~ msgid "Client's side:" -#~ msgstr "" - -#~ 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 "" - -#~ msgid "Message Types for Protocol Buffers" -#~ msgstr "" - -#~ 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 "" - -#~ msgid "Within the :code:`ServerMessage` block:" -#~ msgstr "" - -#~ msgid "Within the ClientMessage block:" -#~ msgstr "" - -#~ msgid "" -#~ "Make sure to also add a field " -#~ "of the newly created message type " -#~ "in :code:`oneof msg`." -#~ msgstr "" - -#~ msgid "Once that is done, we will compile the file with:" -#~ msgstr "" - -#~ msgid "If it compiles successfully, you should see the following message:" -#~ msgstr "" - -#~ msgid "Serialization and Deserialization Functions" -#~ msgstr "" - -#~ 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 "" - -#~ msgid "The four functions:" -#~ msgstr "" - -#~ msgid "Sending the Message from the Server" -#~ msgstr "" - -#~ 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 "" - -#~ msgid "Receiving the Message by the Client" -#~ msgstr "" - -#~ 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 "" - -#~ msgid "Within the handle function:" -#~ msgstr "" - -#~ msgid "And add a new function:" -#~ msgstr "" - -#~ msgid "Hopefully, when you run your program you will get the intended result!" -#~ msgstr "" - -#~ 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 "" - -#~ msgid "" -#~ "If you want to persist the state" -#~ " of the SuperLink 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 ``--volume``" -#~ " 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 "" - -#~ msgid "" -#~ "As soon as the SuperLink starts, " -#~ "the file ``state.db`` is created in " -#~ "the user's home directory on your " -#~ "host system. If the file already " -#~ "exists, the SuperLink tries to restore" -#~ " the state from the file. To " -#~ "start the SuperLink with an empty " -#~ "database, simply remove the ``state.db`` " -#~ "file." -#~ msgstr "" - -#~ msgid "" -#~ "Assuming all files we need are in" -#~ " the local ``certificates`` directory, we" -#~ " can use the flag ``--volume`` to " -#~ "mount the local directory into the " -#~ "``/app/`` directory of the container. " -#~ "This allows the SuperLink to access " -#~ "the files within the container. Finally," -#~ " we pass the names of the " -#~ "certificates to the SuperLink with the" -#~ " ``--certificates`` flag." -#~ msgstr "" - -#~ msgid "" -#~ "``--server 192.168.1.100:9092``: This option " -#~ "specifies the address of the SuperLinks" -#~ " Fleet" -#~ msgstr "" - -#~ msgid "" -#~ "Assuming the certificate already exists " -#~ "locally, we can use the flag " -#~ "``--volume`` to mount the local " -#~ "certificate into the container's ``/app/`` " -#~ "directory. This allows the SuperNode to" -#~ " access the certificate within the " -#~ "container. Use the ``--certificates`` flag " -#~ "when starting the container." -#~ msgstr "" - -#~ msgid "" -#~ "``--server 192.168.1.100:9091``: This option " -#~ "specifies the address of the SuperLinks" -#~ " Driver" -#~ msgstr "" - -#~ msgid "" -#~ "Assuming the certificate already exists " -#~ "locally, we can use the flag " -#~ "``--volume`` to mount the local " -#~ "certificate into the container's ``/app/`` " -#~ "directory. This allows the ServerApp to" -#~ " access the certificate within the " -#~ "container. Use the ``--certificates`` flag " -#~ "when starting the container." -#~ msgstr "" - -#~ msgid "" -#~ "If you want to use a different " -#~ "version of Flower, for example Flower" -#~ " nightly, you can do so by " -#~ "changing the tag. All available versions" -#~ " are on `Docker Hub " -#~ "`__." -#~ msgstr "" - -#~ msgid "" -#~ "Here's another example to start with " -#~ "HTTPS. Use the ``--certificates`` command " -#~ "line argument to pass paths to (CA" -#~ " certificate, server certificate, and " -#~ "server private key)." -#~ msgstr "" - -#~ msgid ":py:obj:`run_driver_api `\\ \\(\\)" -#~ msgstr "" - -#~ msgid "Run Flower server (Driver API)." -#~ msgstr "" - -#~ msgid ":py:obj:`run_fleet_api `\\ \\(\\)" -#~ msgstr "" - -#~ msgid "Run Flower server (Fleet API)." -#~ msgstr "" - -#~ msgid "Unreleased" -#~ msgstr "" - -#~ msgid "|d8bf04f23d9b46d8a23cc6f4887d7873|" -#~ msgstr "" - -#~ msgid "|5aa1711387d74d0f8b9c499e1a51627e|" -#~ msgstr "" - -#~ msgid "|2bc8e069228d4873804061ff4a95048c|" -#~ msgstr "" - -#~ msgid "|c258488766324dc9a6807f0e7c4fd5f4|" -#~ msgstr "" - -#~ msgid "|d5f962c3f4ec48529efda980868c14b0|" -#~ msgstr "" - -#~ msgid "|a5eccea18d4c43a68b54b65043cabef8|" -#~ msgstr "" - -#~ msgid "|f17662f7df2d42f68cac70a1fdeda8a7|" -#~ msgstr "" - -#~ msgid "|241fc906441a4f038c625a19d30d01b2|" -#~ msgstr "" - -#~ msgid "|0aa5aa05810b44b6a835cecce28f3137|" -#~ msgstr "" - -#~ msgid "|c742940dd4bf4de09d8d0d5e8d179638|" -#~ msgstr "" - -#~ msgid "|1f169ab4601a47e1a226f1628f4ebddb|" -#~ msgstr "" - -#~ msgid "|12cfa9cde14440ecb8c8f6c1d7185bec|" -#~ msgstr "" - -#~ msgid "|72939caf6e294b0986fee6dde96614d7|" -#~ msgstr "" - -#~ msgid "|83a8daee45da4a98b8d6f24ae098fc50|" +#~ "The name of image is ``flwr_superlink`` 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 "" - +#~ "이미지의 이름은 ``flwr_superlink``이고 태그는 ``0.1.0``입니다. 필요에 따" +#~ "라 빌드 argument들 뿐만 아니라 이름과 태그도 정할 수 있습니다. 이 값들은 " +#~ "예시일 뿐입니다." diff --git a/doc/source/_templates/sidebar/lang.html b/doc/source/_templates/sidebar/lang.html index b377a53f9c40..bbea57571838 100644 --- a/doc/source/_templates/sidebar/lang.html +++ b/doc/source/_templates/sidebar/lang.html @@ -1,9 +1,14 @@ {% if versions or lang %} - + - + {% endif %} diff --git a/doc/source/conf.py b/doc/source/conf.py index 85bfe9404521..1452f9c9a7b0 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -108,6 +108,7 @@ "sphinxcontrib.youtube", "sphinx_reredirects", "nbsphinx", + "sphinx_click", ] # Generate .rst files diff --git a/doc/source/contributor-how-to-build-docker-images.rst b/doc/source/contributor-how-to-build-docker-images.rst index 2efc739f54f0..4c178f439a07 100644 --- a/doc/source/contributor-how-to-build-docker-images.rst +++ b/doc/source/contributor-how-to-build-docker-images.rst @@ -65,7 +65,7 @@ Building the base image * - ``FLWR_VERSION`` - Version of Flower to be installed. - Yes - - ``1.8.0`` + - ``1.9.0`` * - ``FLWR_PACKAGE`` - The Flower package to be installed. - No @@ -73,14 +73,14 @@ Building the base image The following example creates a base Ubuntu/Alpine image with Python 3.11.0, pip 23.0.1, -setuptools 69.0.2 and Flower 1.8.0: +setuptools 69.0.2 and Flower 1.9.0: .. code-block:: bash $ cd src/docker/base/ $ docker build \ --build-arg PYTHON_VERSION=3.11.0 \ - --build-arg FLWR_VERSION=1.8.0 \ + --build-arg FLWR_VERSION=1.9.0 \ --build-arg PIP_VERSION=23.0.1 \ --build-arg SETUPTOOLS_VERSION=69.0.2 \ -t flwr_base:0.1.0 . @@ -106,7 +106,7 @@ Building the SuperLink/SuperNode or ServerApp image * - ``BASE_IMAGE`` - The Tag of the Flower base image. - Yes - - ``1.8.0-py3.10-ubuntu22.04`` + - ``1.9.0-py3.10-ubuntu22.04`` The following example creates a SuperLink/SuperNode or ServerApp image with the official Flower base image: diff --git a/doc/source/contributor-tutorial-get-started-as-a-contributor.rst b/doc/source/contributor-tutorial-get-started-as-a-contributor.rst index 43f9739987ac..d7d647996a3d 100644 --- a/doc/source/contributor-tutorial-get-started-as-a-contributor.rst +++ b/doc/source/contributor-tutorial-get-started-as-a-contributor.rst @@ -17,8 +17,8 @@ supports `PEP 517 `_. Developer Machine Setup ----------------------- -Preliminarities -~~~~~~~~~~~~~~~ +Preliminaries +~~~~~~~~~~~~~ Some system-wide dependencies are needed. For macOS diff --git a/doc/source/how-to-install-flower.rst b/doc/source/how-to-install-flower.rst index 725a7468090c..b00e2ae803ab 100644 --- a/doc/source/how-to-install-flower.rst +++ b/doc/source/how-to-install-flower.rst @@ -20,7 +20,7 @@ Stable releases are available on `PyPI `_:: For simulations that use the Virtual Client Engine, ``flwr`` should be installed with the ``simulation`` extra:: - python -m pip install flwr[simulation] + python -m pip install "flwr[simulation]" Using conda (or mamba) diff --git a/doc/source/how-to-run-flower-using-docker.rst b/doc/source/how-to-run-flower-using-docker.rst index 54079968d417..7d9ec883960a 100644 --- a/doc/source/how-to-run-flower-using-docker.rst +++ b/doc/source/how-to-run-flower-using-docker.rst @@ -38,10 +38,10 @@ 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/superlink:1.8.0 --insecure + $ docker run --rm -p 9091:9091 -p 9092:9092 flwr/superlink:1.9.0 --insecure -The command pulls the Docker image with the tag ``1.8.0`` from Docker Hub. The tag specifies -the Flower version. In this case, Flower 1.8.0. The ``--rm`` flag tells Docker to remove the +The command pulls the Docker image with the tag ``1.9.0`` from Docker Hub. The tag specifies +the Flower version. In this case, Flower 1.9.0. The ``--rm`` flag tells Docker to remove the container after it exits. .. note:: @@ -66,7 +66,7 @@ You can use ``--help`` to view all available flags that the SuperLink supports: .. code-block:: bash - $ docker run --rm flwr/superlink:1.8.0 --help + $ docker run --rm flwr/superlink:1.9.0 --help Mounting a volume to store the state on the host system ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -88,7 +88,7 @@ container. Furthermore, we use the flag ``--database`` to specify the name of th $ mkdir state $ sudo chown -R 49999:49999 state $ docker run --rm \ - -p 9091:9091 -p 9092:9092 --volume ./state/:/app/state flwr/superlink:1.8.0 \ + -p 9091:9091 -p 9092:9092 --volume ./state/:/app/state flwr/superlink:1.9.0 \ --insecure \ --database state.db @@ -118,7 +118,7 @@ with the ``--ssl-ca-certfile``, ``--ssl-certfile`` and ``--ssl-keyfile`` flag. $ docker run --rm \ -p 9091:9091 -p 9092:9092 \ - --volume ./certificates/:/app/certificates/:ro flwr/superlink:nightly \ + --volume ./certificates/:/app/certificates/:ro flwr/superlink:1.9.0 \ --ssl-ca-certfile certificates/ca.crt \ --ssl-certfile certificates/server.pem \ --ssl-keyfile certificates/server.key @@ -136,14 +136,6 @@ Flower SuperNode The SuperNode Docker image comes with a pre-installed version of Flower and serves as a base for building your own SuperNode image. -.. important:: - - The SuperNode Docker image currently works only with the 1.9.0-nightly release. A stable version - will be available when Flower 1.9.0 (stable) gets released (ETA: May). A SuperNode nightly image - must be paired with the corresponding SuperLink and ServerApp nightly images released on the same - day. To ensure the versions are in sync, using the concrete tag, e.g., ``1.9.0.dev20240501`` - instead of ``nightly`` is recommended. - We will use the ``quickstart-pytorch`` example, which you can find in the Flower repository, to illustrate how you can dockerize your ClientApp. @@ -204,7 +196,7 @@ The ``Dockerfile.supernode`` contains the instructions that assemble the SuperNo .. code-block:: dockerfile - FROM flwr/supernode:nightly + FROM flwr/supernode:1.9.0 WORKDIR /app @@ -214,7 +206,7 @@ The ``Dockerfile.supernode`` contains the instructions that assemble the SuperNo COPY client.py ./ ENTRYPOINT ["flower-client-app", "client:app"] -In the first two lines, we instruct Docker to use the SuperNode image tagged ``nightly`` as a base +In the first two lines, we instruct Docker to use the SuperNode image tagged ``1.9.0`` as a base image and set our working directory to ``/app``. The following instructions will now be executed in the ``/app`` directory. Next, we install the ClientApp dependencies by copying the ``requirements.txt`` file into the image and run ``pip install``. In the last two lines, @@ -275,7 +267,7 @@ To see all available flags that the SuperNode supports, run: .. code-block:: bash - $ docker run --rm flwr/supernode:nightly --help + $ docker run --rm flwr/supernode:1.9.0 --help Enabling SSL for secure connections ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -325,14 +317,14 @@ The ``Dockerfile.serverapp`` contains the instructions that assemble the ServerA .. code-block:: dockerfile - FROM flwr/serverapp:1.8.0 + FROM flwr/serverapp:1.9.0 WORKDIR /app COPY server.py ./ ENTRYPOINT ["flower-server-app", "server:app"] -In the first two lines, we instruct Docker to use the ServerApp image tagged ``1.8.0`` as a base +In the first two lines, we instruct Docker to use the ServerApp image tagged ``1.9.0`` as a base image and set our working directory to ``/app``. The following instructions will now be executed in the ``/app`` directory. In the last two lines, we copy the ``server.py`` module into the image and set the entry point to ``flower-server-app`` with the argument ``server:app``. @@ -391,7 +383,7 @@ To see all available flags that the ServerApp supports, run: .. code-block:: bash - $ docker run --rm flwr/serverapp:1.8.0 --help + $ docker run --rm flwr/serverapp:1.9.0 --help Enabling SSL for secure connections ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -425,7 +417,7 @@ Run the Docker image with the ``-u`` flag and specify ``root`` as the username: .. code-block:: bash - $ docker run --rm -u root flwr/superlink:1.8.0 + $ docker run --rm -u root flwr/superlink:1.9.0 This command will run the Docker container with root user privileges. @@ -436,7 +428,7 @@ missing system dependencies, you can use the ``USER root`` directive within your .. code-block:: dockerfile - FROM flwr/supernode:1.8.0 + FROM flwr/supernode:1.9.0 # Switch to root user USER root @@ -456,6 +448,13 @@ Using a different Flower version If you want to use a different version of Flower, for example Flower nightly, you can do so by changing the tag. All available versions are on `Docker Hub `__. +.. important:: + + When using Flower nightly, the SuperLink nightly image must be paired with the corresponding + SuperNode and ServerApp nightly images released on the same day. To ensure the versions are + in sync, using the concrete tag, e.g., ``1.10.0.dev20240610`` instead of ``nightly`` is + recommended. + Pinning a Docker image to a specific version ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -464,19 +463,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 ``superlink:1.8.0`` tag: +The following command returns the current image hash referenced by the ``superlink:1.9.0`` tag: .. code-block:: bash - $ docker inspect --format='{{index .RepoDigests 0}}' flwr/superlink:1.8.0 - flwr/superlink@sha256:1b855d1fa4e344e4d95db99793f2bb35d8c63f6a1decdd736863bfe4bb0fe46c + $ docker inspect --format='{{index .RepoDigests 0}}' flwr/superlink:1.9.0 + flwr/superlink@sha256:985c24b2b337ab7f15a554fde9d860cede95079bcaa244fda8f12c0805e34c7d Next, we can pin the hash when running a new SuperLink container: .. code-block:: bash $ docker run \ - --rm flwr/superlink@sha256:1b855d1fa4e344e4d95db99793f2bb35d8c63f6a1decdd736863bfe4bb0fe46c \ + --rm flwr/superlink@sha256:985c24b2b337ab7f15a554fde9d860cede95079bcaa244fda8f12c0805e34c7d \ --insecure Setting environment variables @@ -487,4 +486,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/superlink:1.8.0 --insecure + --rm flwr/superlink:1.9.0 --insecure diff --git a/doc/source/how-to-use-differential-privacy.rst b/doc/source/how-to-use-differential-privacy.rst index c8901bd906cc..5d4fa3dca1a4 100644 --- a/doc/source/how-to-use-differential-privacy.rst +++ b/doc/source/how-to-use-differential-privacy.rst @@ -9,7 +9,7 @@ This guide explains how you can utilize differential privacy in the Flower frame Central Differential Privacy ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -This approach consists of two seprate phases: clipping of the updates and adding noise to the aggregated model. +This approach consists of two separate phases: clipping of the updates and adding noise to the aggregated model. For the clipping phase, Flower framework has made it possible to decide whether to perform clipping on the server side or the client side. - **Server-side Clipping**: This approach has the advantage of the server enforcing uniform clipping across all clients' updates and reducing the communication overhead for clipping values. However, it also has the disadvantage of increasing the computational load on the server due to the need to perform the clipping operation for all clients. diff --git a/doc/source/how-to-use-strategies.rst b/doc/source/how-to-use-strategies.rst index d0e2cd63a091..8ac120124951 100644 --- a/doc/source/how-to-use-strategies.rst +++ b/doc/source/how-to-use-strategies.rst @@ -72,7 +72,7 @@ It must return a dictionary of arbitrary configuration values :code:`client.fit ) fl.server.start_server(config=fl.server.ServerConfig(num_rounds=3), strategy=strategy) -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 :code:`on_fit_config_fn` can be used to pass arbitrary configuration values from server to client, and potentially 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. Similar to :code:`on_fit_config_fn`, there is also :code:`on_evaluate_config_fn` to customize the configuration sent to :code:`client.evaluate()` diff --git a/doc/source/ref-api-cli.rst b/doc/source/ref-api-cli.rst index 296c2219a065..4397ae056941 100644 --- a/doc/source/ref-api-cli.rst +++ b/doc/source/ref-api-cli.rst @@ -1,6 +1,15 @@ Flower CLI reference ==================== +.. _flwr-apiref: + +flwr CLI +~~~~~~~~ + +.. click:: flwr.cli.app:typer_click_object + :prog: flwr + :nested: full + .. _flower-simulation-apiref: flower-simulation diff --git a/e2e/test_reconnection.sh b/e2e/test_reconnection.sh new file mode 100755 index 000000000000..7f8eaa94bf27 --- /dev/null +++ b/e2e/test_reconnection.sh @@ -0,0 +1,88 @@ +#!/bin/bash +set -e + +case "$1" in + rest) + rest_arg="--rest" + server_app_address="http://localhost:9091" + server_address="http://localhost:9093" + db_arg="--database :flwr-in-memory-state:" + ;; + sqlite) + rest_arg="" + server_address="127.0.0.1:9092" + server_app_address="127.0.0.1:9091" + db_arg="--database $(date +%s).db" + ;; + *) + rest_arg="" + server_address="127.0.0.1:9092" + server_app_address="127.0.0.1:9091" + db_arg="--database :flwr-in-memory-state:" + ;; +esac + +dir_arg="--dir ./.." + +timeout 2m flower-superlink --insecure $db_arg $rest_arg & +sl_pid=$! +echo "Starting SuperLink" +sleep 3 + +timeout 2m flower-client-app client:app --insecure $rest_arg --server $server_address & +cl1_pid=$! +echo "Starting first client" +sleep 3 + +timeout 2m flower-client-app client:app --insecure $rest_arg --server $server_address & +cl2_pid=$! +echo "Starting second client" +sleep 3 + +# Kill superlink, this should send the clients into their retry loops +kill $sl_pid +echo "Killing Superlink" +sleep 3 + +# Restart superlink, the clients should now be able to reconnect to it +timeout 2m flower-superlink --insecure $db_arg $rest_arg & +sl_pid=$! +echo "Restarting Superlink" +sleep 20 + +# Kill first client, this should send a DeleteNode message to the Superlink +kill $cl1_pid +echo "Killing first client" +sleep 3 + +# Starting new client, this is so we have enough clients to start the server-app +timeout 2m flower-client-app client:app --insecure $rest_arg --server $server_address & +cl1_pid=$! +echo "Starting new client" +sleep 5 + +# We start the server-app to begining the training +timeout 2m flower-server-app server:app --insecure $dir_arg $rest_arg --server $server_app_address & +pid=$! +echo "Starting server-app to start training" + +# Kill first client as soon as the training starts, +# the server-app should just receive a failure in this case and continue the rounds +# when enough clients are connected +kill $cl1_pid +echo "Killing first client" +sleep 1 + +# Restart first client so enough clients are connected to continue the FL rounds +timeout 2m flower-client-app client:app --insecure $rest_arg --server $server_address & +cl1_pid=$! +echo "Starting new client" + +wait $pid +res=$? + +if [[ "$res" = "0" ]]; + 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/fl-tabular/README.md b/examples/fl-tabular/README.md new file mode 100644 index 000000000000..58afd1080b70 --- /dev/null +++ b/examples/fl-tabular/README.md @@ -0,0 +1,39 @@ +# Flower Example on Adult Census Income Tabular Dataset + +This code exemplifies a federated learning setup using the Flower framework on the ["Adult Census Income"](https://huggingface.co/datasets/scikit-learn/adult-census-income) tabular dataset. The "Adult Census Income" dataset contains demographic information such as age, education, occupation, etc., with the target attribute being income level (\<=50K or >50K). The dataset is partitioned into subsets, simulating a federated environment with 5 clients, each holding a distinct portion of the data. Categorical variables are one-hot encoded, and the data is split into training and testing sets. Federated learning is conducted using the FedAvg strategy for 5 rounds. + +This example uses [Flower Datasets](https://flower.ai/docs/datasets/) to download, partition and preprocess the dataset. + +## Environments Setup + +Start by cloning the example. 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/fl-tabular . && rm -rf flower && cd fl-tabular +``` + +This will create a new directory called `fl-tabular` containing the following files: + +```shell +-- pyproject.toml +-- client.py +-- server.py +-- task.py +-- README.md +``` + +### Installing dependencies + +Project dependencies are defined in `pyproject.toml`. Install them with: + +```shell +pip install . +``` + +## Running Code + +### Federated Using Flower Simulation + +```bash +flower-simulation --server-app server:app --client-app client:app --num-supernodes 5 +``` diff --git a/examples/fl-tabular/client.py b/examples/fl-tabular/client.py new file mode 100644 index 000000000000..228183f4edc4 --- /dev/null +++ b/examples/fl-tabular/client.py @@ -0,0 +1,38 @@ +from flwr.client import Client, ClientApp, NumPyClient +from flwr_datasets import FederatedDataset +from task import set_weights, get_weights, train, evaluate, IncomeClassifier, load_data + +NUMBER_OF_CLIENTS = 5 + + +class FlowerClient(NumPyClient): + def __init__(self, net, trainloader, testloader): + self.net = net + self.trainloader = trainloader + self.testloader = testloader + + def fit(self, parameters, config): + set_weights(self.net, parameters) + train(self.net, self.trainloader) + return get_weights(self.net), len(self.trainloader), {} + + def evaluate(self, parameters, config): + set_weights(self.net, parameters) + loss, accuracy = evaluate(self.net, self.testloader) + return loss, len(self.testloader), {"accuracy": accuracy} + + +def get_client_fn(dataset: FederatedDataset): + def client_fn(cid: str) -> Client: + train_loader, test_loader = load_data(partition_id=int(cid), fds=dataset) + net = IncomeClassifier(14) + return FlowerClient(net, train_loader, test_loader).to_client() + + return client_fn + + +fds = FederatedDataset( + dataset="scikit-learn/adult-census-income", + partitioners={"train": NUMBER_OF_CLIENTS}, +) +app = ClientApp(client_fn=get_client_fn(fds)) diff --git a/examples/fl-tabular/pyproject.toml b/examples/fl-tabular/pyproject.toml new file mode 100644 index 000000000000..21498f73a4f3 --- /dev/null +++ b/examples/fl-tabular/pyproject.toml @@ -0,0 +1,20 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "fl-tabular" +version = "0.1.0" +description = "Adult Census Income Tabular Dataset and Federated Learning in Flower" +authors = [ + { name = "The Flower Authors", email = "hello@flower.ai" }, +] +dependencies = [ + "flwr[simulation]>=1.9.0,<2.0", + "flwr-datasets>=0.1.0,<1.0.0", + "torch==2.1.1", + "scikit-learn==1.5.0", +] + +[tool.hatch.build.targets.wheel] +packages = ["."] diff --git a/examples/fl-tabular/server.py b/examples/fl-tabular/server.py new file mode 100644 index 000000000000..376726f832f7 --- /dev/null +++ b/examples/fl-tabular/server.py @@ -0,0 +1,24 @@ +from flwr.common import ndarrays_to_parameters +from flwr.server import ServerApp, ServerConfig +from flwr.server.strategy import FedAvg +from task import IncomeClassifier, get_weights + +net = IncomeClassifier(input_dim=14) +params = ndarrays_to_parameters(get_weights(net)) + + +def weighted_average(metrics): + accuracies = [num_examples * m["accuracy"] for num_examples, m in metrics] + examples = [num_examples for num_examples, _ in metrics] + + return {"accuracy": sum(accuracies) / sum(examples)} + + +strategy = FedAvg( + initial_parameters=params, + evaluate_metrics_aggregation_fn=weighted_average, +) +app = ServerApp( + strategy=strategy, + config=ServerConfig(num_rounds=5), +) diff --git a/examples/fl-tabular/task.py b/examples/fl-tabular/task.py new file mode 100644 index 000000000000..b07365c733d6 --- /dev/null +++ b/examples/fl-tabular/task.py @@ -0,0 +1,108 @@ +import torch +import torch.nn as nn +import torch.optim as optim +from torch.utils.data import TensorDataset, DataLoader +from sklearn.model_selection import train_test_split +from sklearn.preprocessing import StandardScaler, OrdinalEncoder +from sklearn.compose import ColumnTransformer +from sklearn.pipeline import Pipeline +from collections import OrderedDict +from flwr_datasets import FederatedDataset + + +def load_data(partition_id: int, fds: FederatedDataset): + dataset = fds.load_partition(partition_id, "train").with_format("pandas")[:] + + dataset.dropna(inplace=True) + + categorical_cols = dataset.select_dtypes(include=["object"]).columns + ordinal_encoder = OrdinalEncoder() + dataset[categorical_cols] = ordinal_encoder.fit_transform(dataset[categorical_cols]) + + X = dataset.drop("income", axis=1) + y = dataset["income"] + + X_train, X_test, y_train, y_test = train_test_split( + X, y, test_size=0.2, random_state=42 + ) + + numeric_features = X.select_dtypes(include=["float64", "int64"]).columns + numeric_transformer = Pipeline(steps=[("scaler", StandardScaler())]) + + preprocessor = ColumnTransformer( + transformers=[("num", numeric_transformer, numeric_features)] + ) + + X_train = preprocessor.fit_transform(X_train) + X_test = preprocessor.transform(X_test) + + X_train_tensor = torch.tensor(X_train, dtype=torch.float32) + X_test_tensor = torch.tensor(X_test, dtype=torch.float32) + y_train_tensor = torch.tensor(y_train.values, dtype=torch.float32).view(-1, 1) + y_test_tensor = torch.tensor(y_test.values, dtype=torch.float32).view(-1, 1) + + train_dataset = TensorDataset(X_train_tensor, y_train_tensor) + test_dataset = TensorDataset(X_test_tensor, y_test_tensor) + train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True) + test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False) + + return train_loader, test_loader + + +class IncomeClassifier(nn.Module): + def __init__(self, input_dim: int): + super(IncomeClassifier, self).__init__() + self.layer1 = nn.Linear(input_dim, 128) + self.layer2 = nn.Linear(128, 64) + self.output = nn.Linear(64, 1) + self.relu = nn.ReLU() + self.sigmoid = nn.Sigmoid() + + def forward(self, x): + x = self.relu(self.layer1(x)) + x = self.relu(self.layer2(x)) + x = self.sigmoid(self.output(x)) + return x + + +def train(model, train_loader, num_epochs=1): + criterion = nn.BCELoss() + optimizer = optim.Adam(model.parameters(), lr=0.001) + model.train() + for epoch in range(num_epochs): + for X_batch, y_batch in train_loader: + optimizer.zero_grad() + outputs = model(X_batch) + loss = criterion(outputs, y_batch) + loss.backward() + optimizer.step() + + +def evaluate(model, test_loader): + model.eval() + criterion = nn.BCELoss() + loss = 0.0 + correct = 0 + total = 0 + with torch.no_grad(): + for X_batch, y_batch in test_loader: + outputs = model(X_batch) + batch_loss = criterion(outputs, y_batch) + loss += batch_loss.item() + predicted = (outputs > 0.5).float() + total += y_batch.size(0) + correct += (predicted == y_batch).sum().item() + accuracy = correct / total + loss = loss / len(test_loader) + return loss, accuracy + + +def set_weights(net, 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 get_weights(net): + ndarrays = [val.cpu().numpy() for _, val in net.state_dict().items()] + return ndarrays diff --git a/examples/xgboost-comprehensive/client.py b/examples/xgboost-comprehensive/client.py index 2d54c3fd63c7..08dd548a386b 100644 --- a/examples/xgboost-comprehensive/client.py +++ b/examples/xgboost-comprehensive/client.py @@ -32,7 +32,7 @@ fds = FederatedDataset( dataset="jxie/higgs", partitioners={"train": partitioner}, - resplitter=resplit, + preprocessor=resplit, ) # Load the partition for this `partition_id` diff --git a/examples/xgboost-comprehensive/pyproject.toml b/examples/xgboost-comprehensive/pyproject.toml index 2d44c06d6e3f..c9259ffa1db4 100644 --- a/examples/xgboost-comprehensive/pyproject.toml +++ b/examples/xgboost-comprehensive/pyproject.toml @@ -11,5 +11,5 @@ authors = ["The Flower Authors "] [tool.poetry.dependencies] python = ">=3.8,<3.11" flwr = { extras = ["simulation"], version = ">=1.7.0,<2.0" } -flwr-datasets = ">=0.1.0,<1.0.0" +flwr-datasets = ">=0.2.0,<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 16eb78f484e3..840e19529953 100644 --- a/examples/xgboost-comprehensive/requirements.txt +++ b/examples/xgboost-comprehensive/requirements.txt @@ -1,3 +1,3 @@ flwr[simulation]>=1.7.0, <2.0 -flwr-datasets>=0.1.0, <1.0.0 +flwr-datasets>=0.2.0, <1.0.0 xgboost>=2.0.0, <3.0.0 diff --git a/examples/xgboost-comprehensive/server.py b/examples/xgboost-comprehensive/server.py index 939819641438..07dc4bed6db4 100644 --- a/examples/xgboost-comprehensive/server.py +++ b/examples/xgboost-comprehensive/server.py @@ -32,7 +32,7 @@ # Load centralised test set if centralised_eval: fds = FederatedDataset( - dataset="jxie/higgs", partitioners={"train": 20}, resplitter=resplit + dataset="jxie/higgs", partitioners={"train": 20}, preprocessor=resplit ) log(INFO, "Loading centralised test set...") test_set = fds.load_split("test") diff --git a/examples/xgboost-comprehensive/sim.py b/examples/xgboost-comprehensive/sim.py index c9481f1cdd5d..09ebbb81fcb4 100644 --- a/examples/xgboost-comprehensive/sim.py +++ b/examples/xgboost-comprehensive/sim.py @@ -80,7 +80,7 @@ def main(): fds = FederatedDataset( dataset="jxie/higgs", partitioners={"train": partitioner}, - resplitter=resplit, + preprocessor=resplit, ) # Load centralised test set diff --git a/pyproject.toml b/pyproject.toml index 2dd592050468..dbab703c7671 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -105,6 +105,7 @@ rope = "==1.11.0" semver = "==3.0.2" sphinx = "==6.2.1" sphinx-intl = "==2.2.0" +sphinx-click = "==5.1.0" myst-parser = "==1.0.0" sphinx-design = "==0.5.0" sphinx-copybutton = "==0.5.2" diff --git a/src/py/flwr/cli/app.py b/src/py/flwr/cli/app.py index 477b990bf1da..d1b270026cd7 100644 --- a/src/py/flwr/cli/app.py +++ b/src/py/flwr/cli/app.py @@ -15,6 +15,7 @@ """Flower command line interface.""" import typer +from typer.main import get_command from .build import build from .example import example @@ -37,5 +38,7 @@ app.command()(build) app.command()(install) +typer_click_object = get_command(app) + if __name__ == "__main__": app() diff --git a/src/py/flwr/cli/build.py b/src/py/flwr/cli/build.py index 2981eacf925d..4a9b54f9223f 100644 --- a/src/py/flwr/cli/build.py +++ b/src/py/flwr/cli/build.py @@ -36,13 +36,9 @@ def build( ) -> str: """Build a Flower project into a Flower App Bundle (FAB). - You can run `flwr build` without any argument to bundle the current directory: - - `flwr build` - - You can also build a specific directory: - - `flwr build --directory ./projects/flower-hello-world` + You can run ``flwr build`` without any arguments to bundle the current directory, + or you can use ``--directory`` to build a specific directory: + ``flwr build --directory ./projects/flower-hello-world``. """ if directory is None: directory = Path.cwd() diff --git a/src/py/flwr/cli/new/new.py b/src/py/flwr/cli/new/new.py index 9bbc016de1a8..9367cf6c9ffb 100644 --- a/src/py/flwr/cli/new/new.py +++ b/src/py/flwr/cli/new/new.py @@ -41,6 +41,16 @@ class MlFramework(str, Enum): HUGGINGFACE = "HF" MLX = "MLX" SKLEARN = "sklearn" + FLOWERTUNE = "FlowerTune" + + +class LlmChallengeName(str, Enum): + """Available LLM challenges.""" + + GENERALNLP = "GeneralNLP" + FINANCE = "Finance" + MEDICAL = "Medical" + CODE = "Code" class TemplateNotFound(Exception): @@ -81,6 +91,7 @@ def render_and_create(file_path: str, template: str, context: Dict[str, str]) -> create_file(file_path, content) +# pylint: disable=too-many-locals,too-many-branches,too-many-statements def new( project_name: Annotated[ Optional[str], @@ -125,6 +136,19 @@ def new( framework_str = framework_str.lower() + if framework_str == "flowertune": + llm_challenge_value = prompt_options( + "Please select LLM challenge by typing in the number", + sorted([challenge.value for challenge in LlmChallengeName]), + ) + selected_value = [ + name + for name, value in vars(LlmChallengeName).items() + if value == llm_challenge_value + ] + llm_challenge_str = selected_value[0] + llm_challenge_str = llm_challenge_str.lower() + print( typer.style( f"\n🔨 Creating Flower project {project_name}...", @@ -139,33 +163,6 @@ def new( import_name = package_name.replace("-", "_") project_dir = os.path.join(cwd, package_name) - # List of files to render - files = { - ".gitignore": {"template": "app/.gitignore.tpl"}, - "README.md": {"template": "app/README.md.tpl"}, - "pyproject.toml": {"template": f"app/pyproject.{framework_str}.toml.tpl"}, - f"{import_name}/__init__.py": {"template": "app/code/__init__.py.tpl"}, - f"{import_name}/server.py": { - "template": f"app/code/server.{framework_str}.py.tpl" - }, - f"{import_name}/client.py": { - "template": f"app/code/client.{framework_str}.py.tpl" - }, - } - - # Depending on the framework, generate task.py file - frameworks_with_tasks = [ - MlFramework.PYTORCH.value.lower(), - MlFramework.JAX.value.lower(), - MlFramework.HUGGINGFACE.value.lower(), - MlFramework.MLX.value.lower(), - MlFramework.TENSORFLOW.value.lower(), - ] - if framework_str in frameworks_with_tasks: - files[f"{import_name}/task.py"] = { - "template": f"app/code/task.{framework_str}.py.tpl" - } - context = { "project_name": project_name, "package_name": package_name, @@ -173,6 +170,85 @@ def new( "username": username, } + # List of files to render + if framework_str == "flowertune": + files = { + ".gitignore": {"template": "app/.gitignore.tpl"}, + "pyproject.toml": {"template": f"app/pyproject.{framework_str}.toml.tpl"}, + "README.md": {"template": f"app/README.{framework_str}.md.tpl"}, + f"{import_name}/__init__.py": {"template": "app/code/__init__.py.tpl"}, + f"{import_name}/server.py": { + "template": "app/code/flwr_tune/server.py.tpl" + }, + f"{import_name}/client.py": { + "template": "app/code/flwr_tune/client.py.tpl" + }, + f"{import_name}/app.py": {"template": "app/code/flwr_tune/app.py.tpl"}, + f"{import_name}/models.py": { + "template": "app/code/flwr_tune/models.py.tpl" + }, + f"{import_name}/dataset.py": { + "template": "app/code/flwr_tune/dataset.py.tpl" + }, + f"{import_name}/conf/config.yaml": { + "template": "app/code/flwr_tune/config.yaml.tpl" + }, + f"{import_name}/conf/static_config.yaml": { + "template": "app/code/flwr_tune/static_config.yaml.tpl" + }, + } + + # Challenge specific context + fraction_fit = "0.2" if llm_challenge_str == "code" else "0.1" + if llm_challenge_str == "generalnlp": + challenge_name = "General NLP" + num_clients = "20" + dataset_name = "vicgalle/alpaca-gpt4" + elif llm_challenge_str == "finance": + challenge_name = "Finance" + num_clients = "50" + dataset_name = "FinGPT/fingpt-sentiment-train" + elif llm_challenge_str == "medical": + challenge_name = "Medical" + num_clients = "20" + dataset_name = "medalpaca/medical_meadow_medical_flashcards" + else: + challenge_name = "Code" + num_clients = "10" + dataset_name = "lucasmccabe-lmi/CodeAlpaca-20k" + + context["llm_challenge_str"] = llm_challenge_str + context["fraction_fit"] = fraction_fit + context["challenge_name"] = challenge_name + context["num_clients"] = num_clients + context["dataset_name"] = dataset_name + else: + files = { + ".gitignore": {"template": "app/.gitignore.tpl"}, + "README.md": {"template": "app/README.md.tpl"}, + "pyproject.toml": {"template": f"app/pyproject.{framework_str}.toml.tpl"}, + f"{import_name}/__init__.py": {"template": "app/code/__init__.py.tpl"}, + f"{import_name}/server.py": { + "template": f"app/code/server.{framework_str}.py.tpl" + }, + f"{import_name}/client.py": { + "template": f"app/code/client.{framework_str}.py.tpl" + }, + } + + # Depending on the framework, generate task.py file + frameworks_with_tasks = [ + MlFramework.PYTORCH.value.lower(), + MlFramework.JAX.value.lower(), + MlFramework.HUGGINGFACE.value.lower(), + MlFramework.MLX.value.lower(), + MlFramework.TENSORFLOW.value.lower(), + ] + if framework_str in frameworks_with_tasks: + files[f"{import_name}/task.py"] = { + "template": f"app/code/task.{framework_str}.py.tpl" + } + for file_path, value in files.items(): render_and_create( file_path=os.path.join(project_dir, file_path), @@ -190,7 +266,7 @@ def new( ) print( typer.style( - f" cd {project_name}\n" + " pip install -e .\n flwr run\n", + f" cd {package_name}\n" + " pip install -e .\n flwr run\n", fg=typer.colors.BRIGHT_CYAN, bold=True, ) diff --git a/src/py/flwr/cli/new/templates/app/README.flowertune.md.tpl b/src/py/flwr/cli/new/templates/app/README.flowertune.md.tpl new file mode 100644 index 000000000000..2b59937e4130 --- /dev/null +++ b/src/py/flwr/cli/new/templates/app/README.flowertune.md.tpl @@ -0,0 +1,56 @@ +# FlowerTune LLM on $challenge_name Dataset + +This directory conducts federated instruction tuning with a pretrained [Mistral-7B](https://huggingface.co/mistralai/Mistral-7B-v0.3) model on a [$challenge_name dataset](https://huggingface.co/datasets/$dataset_name). +We use [Flower Datasets](https://flower.dev/docs/datasets/) to download, partition and preprocess the dataset. +Flower's Simulation Engine is used to simulate the LLM fine-tuning process in federated way, +which allows users to perform the training on a single GPU. + + +## Methodology + +This baseline performs federated LLM fine-tuning with [LoRA](https://arxiv.org/pdf/2106.09685) using the [🤗PEFT](https://huggingface.co/docs/peft/en/index) library. +The clients' models are aggregated with FedAvg strategy. +This provides a baseline performance for the leaderboard of $challenge_name challenge. + + +## Environments setup + +Project dependencies are defined in `pyproject.toml`. Install them in an activated Python environment with: + +```shell +pip install -e . +``` + +## Experimental setup + +The dataset is partitioned into $num_clients shards with IID fashion serving as clients. +We randomly sample $fraction_fit clients to be available for each round, +and the federated fine-tuning lasts for `200` rounds. +All settings are defined in `$project_name/conf/static_config.yaml`, which is not allowed to be modified for fair competition if you plan to participated in the [LLM leaderboard](https://flower.ai/benchmarks/llm-leaderboard). + + +## Running the challenge + +First make sure that you have got the access to [Mistral-7B](https://huggingface.co/mistralai/Mistral-7B-v0.3) model with your Hugging-Face account. You can request access directly from the Hugging-Face website. +Then, follow the instruction [here](https://huggingface.co/docs/huggingface_hub/en/quick-start#login-command) to log in your account. Note you only need to complete this stage once in your development machine: + +```bash +huggingface-cli login +``` + +Run the challenge with default config values. +The configs are in `$project_name/conf/config.yaml` and `$project_name/conf/static_config.yaml`, and are loaded automatically. + +```bash +flwr run +``` + +## VRAM consumption + +We use Mistral-7B model with 4-bit quantization as default. The estimated VRAM consumption per client for each challenge is shown below: + +| Challenges | GeneralNLP | Finance | Medical | Code | +| :--------: | :--------: | :--------: | :--------: | :--------: | +| VRAM | ~25.50 GB | ~17.30 GB | ~22.80 GB | ~17.40 GB | + +You can adjust the CPU/GPU resources you assign to each of the clients based on your device, which is specified with `flower.engine.simulation` in `pyproject.toml`. diff --git a/src/py/flwr/cli/new/templates/app/code/flwr_tune/__init__.py b/src/py/flwr/cli/new/templates/app/code/flwr_tune/__init__.py new file mode 100644 index 000000000000..6d886f216bc9 --- /dev/null +++ b/src/py/flwr/cli/new/templates/app/code/flwr_tune/__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 CLI `new` command app / code / flwr_tune templates.""" diff --git a/src/py/flwr/cli/new/templates/app/code/flwr_tune/app.py.tpl b/src/py/flwr/cli/new/templates/app/code/flwr_tune/app.py.tpl new file mode 100644 index 000000000000..ecb87bd71e3f --- /dev/null +++ b/src/py/flwr/cli/new/templates/app/code/flwr_tune/app.py.tpl @@ -0,0 +1,86 @@ +"""$project_name: A Flower / FlowerTune app.""" + +import os +import warnings +from datetime import datetime + +from flwr_datasets import FederatedDataset +from hydra import compose, initialize +from hydra.utils import instantiate + +from flwr.client import ClientApp +from flwr.common import ndarrays_to_parameters +from flwr.server import ServerApp, ServerConfig + +from $import_name.client import gen_client_fn, get_parameters +from $import_name.dataset import get_tokenizer_and_data_collator_and_propt_formatting +from $import_name.models import get_model +from $import_name.server import fit_weighted_average, get_evaluate_fn, get_on_fit_config + +# Avoid warnings +warnings.filterwarnings("ignore", category=UserWarning) +os.environ["TOKENIZERS_PARALLELISM"] = "true" +os.environ["RAY_DISABLE_DOCKER_CPU_WARNING"] = "1" + +# Initialise regular config +with initialize(config_path="conf", version_base="1.1"): + cfg = compose(config_name="config") + +# Initialise static config +with initialize(config_path="conf", version_base="1.1"): + cfg_static = compose(config_name="static_config") + +cfg.train.num_rounds = cfg_static.num_rounds + +# Create output directory given current timestamp +current_time = datetime.now() +folder_name = current_time.strftime("%Y-%m-%d_%H-%M-%S") +save_path = os.path.join(os.getcwd(), f"results/{folder_name}") +os.makedirs(save_path, exist_ok=True) + +# Partition dataset and get dataloaders +partitioner = instantiate(cfg_static.partitioner) +fds = FederatedDataset( + dataset=cfg_static.dataset.name, partitioners={"train": partitioner} +) +( + tokenizer, + data_collator, + formatting_prompts_func, +) = get_tokenizer_and_data_collator_and_propt_formatting(cfg.model.name) + +# ClientApp for Flower Next +client = ClientApp( + client_fn=gen_client_fn( + fds, + tokenizer, + formatting_prompts_func, + data_collator, + cfg.model, + cfg.train, + save_path, + ), +) + +# Get initial model weights +init_model = get_model(cfg.model) +init_model_parameters = get_parameters(init_model) +init_model_parameters = ndarrays_to_parameters(init_model_parameters) + +# Instantiate strategy according to config. Here we pass other arguments +# that are only defined at runtime. +strategy = instantiate( + cfg.strategy, + on_fit_config_fn=get_on_fit_config(), + fit_metrics_aggregation_fn=fit_weighted_average, + initial_parameters=init_model_parameters, + evaluate_fn=get_evaluate_fn( + cfg.model, cfg.train.save_every_round, cfg_static.num_rounds, save_path + ), +) + +# ServerApp for Flower Next +server = ServerApp( + config=ServerConfig(num_rounds=cfg_static.num_rounds), + strategy=strategy, +) diff --git a/src/py/flwr/cli/new/templates/app/code/flwr_tune/client.py.tpl b/src/py/flwr/cli/new/templates/app/code/flwr_tune/client.py.tpl new file mode 100644 index 000000000000..c0d5842964fd --- /dev/null +++ b/src/py/flwr/cli/new/templates/app/code/flwr_tune/client.py.tpl @@ -0,0 +1,124 @@ +"""$project_name: A Flower / FlowerTune app.""" + +from collections import OrderedDict +from typing import Callable, Dict, Tuple + +import torch +from omegaconf import DictConfig +from peft import get_peft_model_state_dict, set_peft_model_state_dict +from transformers import TrainingArguments +from trl import SFTTrainer + +from flwr.client import NumPyClient +from flwr.common.typing import NDArrays, Scalar +from $import_name.dataset import reformat +from $import_name.models import cosine_annealing, get_model + + +# pylint: disable=too-many-arguments +# pylint: disable=too-many-instance-attributes +class FlowerClient(NumPyClient): + """Standard Flower client for CNN training.""" + + def __init__( + self, + model_cfg: DictConfig, + train_cfg: DictConfig, + trainset, + tokenizer, + formatting_prompts_func, + data_collator, + save_path, + ): # pylint: disable=too-many-arguments + self.device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") + self.train_cfg = train_cfg + self.training_argumnets = TrainingArguments(**train_cfg.training_arguments) + self.tokenizer = tokenizer + self.formatting_prompts_func = formatting_prompts_func + self.data_collator = data_collator + self.save_path = save_path + + # instantiate model + self.model = get_model(model_cfg) + + self.trainset = trainset + + def fit( + self, parameters: NDArrays, config: Dict[str, Scalar] + ) -> Tuple[NDArrays, int, Dict]: + """Implement distributed fit function for a given client.""" + set_parameters(self.model, parameters) + + new_lr = cosine_annealing( + int(config["current_round"]), + self.train_cfg.num_rounds, + self.train_cfg.learning_rate_max, + self.train_cfg.learning_rate_min, + ) + + self.training_argumnets.learning_rate = new_lr + self.training_argumnets.output_dir = self.save_path + + # Construct trainer + trainer = SFTTrainer( + model=self.model, + tokenizer=self.tokenizer, + args=self.training_argumnets, + max_seq_length=self.train_cfg.seq_length, + train_dataset=self.trainset, + formatting_func=self.formatting_prompts_func, + data_collator=self.data_collator, + ) + + # Do local training + results = trainer.train() + + return ( + get_parameters(self.model), + len(self.trainset), + {"train_loss": results.training_loss}, + ) + + +def set_parameters(model, parameters: NDArrays) -> None: + """Change the parameters of the model using the given ones.""" + peft_state_dict_keys = get_peft_model_state_dict(model).keys() + params_dict = zip(peft_state_dict_keys, parameters) + state_dict = OrderedDict({k: torch.Tensor(v) for k, v in params_dict}) + set_peft_model_state_dict(model, state_dict) + + +def get_parameters(model) -> NDArrays: + """Return the parameters of the current net.""" + state_dict = get_peft_model_state_dict(model) + return [val.cpu().numpy() for _, val in state_dict.items()] + + +def gen_client_fn( + fds, + tokenizer, + formatting_prompts_func, + data_collator, + model_cfg: DictConfig, + train_cfg: DictConfig, + save_path: str, +) -> Callable[[str], FlowerClient]: # pylint: disable=too-many-arguments + """Generate the client function that creates the Flower Clients.""" + + def client_fn(cid: str) -> FlowerClient: + """Create a Flower client representing a single organization.""" + # Let's get the partition corresponding to the i-th client + client_trainset = fds.load_partition(int(cid), "train") + client_trainset = reformat(client_trainset, llm_task="$llm_challenge_str") + + return FlowerClient( + model_cfg, + train_cfg, + client_trainset, + tokenizer, + formatting_prompts_func, + data_collator, + save_path, + ).to_client() + + return client_fn diff --git a/src/py/flwr/cli/new/templates/app/code/flwr_tune/config.yaml.tpl b/src/py/flwr/cli/new/templates/app/code/flwr_tune/config.yaml.tpl new file mode 100644 index 000000000000..9f700dd5b8da --- /dev/null +++ b/src/py/flwr/cli/new/templates/app/code/flwr_tune/config.yaml.tpl @@ -0,0 +1,34 @@ +# Federated Instruction Tuning +--- +model: + name: "mistralai/Mistral-7B-v0.3" + quantization: 4 # 8 or 4 if you want to do quantization with BitsAndBytes + gradient_checkpointing: True + lora: + peft_lora_r: 32 + peft_lora_alpha: 64 + +train: + num_rounds: null + save_every_round: 5 + learning_rate_max: 5e-5 + learning_rate_min: 1e-6 + seq_length: 512 + training_arguments: + output_dir: null # to be set by hydra + learning_rate: null # to be set by the client + per_device_train_batch_size: 16 + gradient_accumulation_steps: 1 + logging_steps: 10 + num_train_epochs: 3 + max_steps: 10 + report_to: null + save_steps: 1000 + save_total_limit: 10 + gradient_checkpointing: True + lr_scheduler_type: "constant" + +strategy: + _target_: flwr.server.strategy.FedAvg + fraction_fit: $fraction_fit + fraction_evaluate: 0.0 # no client evaluation diff --git a/src/py/flwr/cli/new/templates/app/code/flwr_tune/dataset.py.tpl b/src/py/flwr/cli/new/templates/app/code/flwr_tune/dataset.py.tpl new file mode 100644 index 000000000000..1b3691d7cf3c --- /dev/null +++ b/src/py/flwr/cli/new/templates/app/code/flwr_tune/dataset.py.tpl @@ -0,0 +1,57 @@ +"""$project_name: A Flower / FlowerTune app.""" + +from transformers import AutoTokenizer +from trl import DataCollatorForCompletionOnlyLM + + +def formatting_prompts_func(example): + """Construct prompts.""" + output_texts = [] + # Constructing a standard Alpaca + # (https://github.com/tatsu-lab/stanford_alpaca#data-release) prompt + mssg = ( + "Below is an instruction that describes a task. " + "Write a response that appropriately completes the request." + ) + for i in range(len(example["instruction"])): + text = ( + f"{mssg}\n### Instruction:\n{example['instruction'][i]}\n" + f"### Response: {example['response'][i]}" + ) + output_texts.append(text) + return output_texts + + +def get_tokenizer_and_data_collator_and_propt_formatting(model_name: str): + """Get tokenizer, data_collator and prompt formatting.""" + # From: https://huggingface.co/docs/trl/en/sft_trainer + tokenizer = AutoTokenizer.from_pretrained( + model_name, use_fast=True, padding_side="right" + ) + tokenizer.pad_token = tokenizer.eos_token + response_template_with_context = "\n### Response:" # alpaca response tag + response_template_ids = tokenizer.encode( + response_template_with_context, add_special_tokens=False + )[2:] + data_collator = DataCollatorForCompletionOnlyLM( + response_template_ids, tokenizer=tokenizer + ) + + return tokenizer, data_collator, formatting_prompts_func + + +def formatting(dataset): + """Format dataset.""" + dataset["instruction"] = dataset["instruction"] + " " + dataset["input"] + return dataset + + +def reformat(dataset, llm_task): + """Reformat datasets.""" + dataset = dataset.rename_column("output", "response") + if llm_task == "finance" or llm_task == "code": + dataset = dataset.map(formatting, remove_columns=["input"]) + if llm_task == "medical": + dataset = dataset.remove_columns(["instruction"]) + dataset = dataset.rename_column("input", "instruction") + return dataset diff --git a/src/py/flwr/cli/new/templates/app/code/flwr_tune/models.py.tpl b/src/py/flwr/cli/new/templates/app/code/flwr_tune/models.py.tpl new file mode 100644 index 000000000000..a2794f35518c --- /dev/null +++ b/src/py/flwr/cli/new/templates/app/code/flwr_tune/models.py.tpl @@ -0,0 +1,59 @@ +"""$project_name: A Flower / FlowerTune app.""" + +import math + +import torch +from omegaconf import DictConfig +from peft import LoraConfig, get_peft_model +from peft.utils import prepare_model_for_kbit_training +from transformers import AutoModelForCausalLM, BitsAndBytesConfig + + +def cosine_annealing( + current_round: int, + total_round: int, + lrate_max: float = 0.001, + lrate_min: float = 0.0, +) -> float: + """Implement cosine annealing learning rate schedule.""" + cos_inner = math.pi * current_round / total_round + return lrate_min + 0.5 * (lrate_max - lrate_min) * (1 + math.cos(cos_inner)) + + +def get_model(model_cfg: DictConfig): + """Load model with appropriate quantization config and other optimizations. + + Please refer to this example for `peft + BitsAndBytes`: + https://github.com/huggingface/peft/blob/main/examples/fp4_finetuning/finetune_fp4_opt_bnb_peft.py + """ + if model_cfg.quantization == 4: + quantization_config = BitsAndBytesConfig(load_in_4bit=True) + elif model_cfg.quantization == 8: + quantization_config = BitsAndBytesConfig(load_in_8bit=True) + else: + raise ValueError( + f"Use 4-bit or 8-bit quantization. You passed: {model_cfg.quantization}/" + ) + + model = AutoModelForCausalLM.from_pretrained( + model_cfg.name, + quantization_config=quantization_config, + torch_dtype=torch.bfloat16, + low_cpu_mem_usage=True, + ) + + model = prepare_model_for_kbit_training( + model, use_gradient_checkpointing=model_cfg.gradient_checkpointing + ) + + peft_config = LoraConfig( + r=model_cfg.lora.peft_lora_r, + lora_alpha=model_cfg.lora.peft_lora_alpha, + lora_dropout=0.075, + task_type="CAUSAL_LM", + ) + + if model_cfg.gradient_checkpointing: + model.config.use_cache = False + + return get_peft_model(model, peft_config) diff --git a/src/py/flwr/cli/new/templates/app/code/flwr_tune/server.py.tpl b/src/py/flwr/cli/new/templates/app/code/flwr_tune/server.py.tpl new file mode 100644 index 000000000000..19223148bca5 --- /dev/null +++ b/src/py/flwr/cli/new/templates/app/code/flwr_tune/server.py.tpl @@ -0,0 +1,48 @@ +"""$project_name: A Flower / FlowerTune app.""" + +from $import_name.client import set_parameters +from $import_name.models import get_model + + +# Get function that will be executed by the strategy's evaluate() method +# Here we use it to save global model checkpoints +def get_evaluate_fn(model_cfg, save_every_round, total_round, save_path): + """Return an evaluation function for saving global model.""" + + def evaluate(server_round: int, parameters, config): + # Save model + if server_round != 0 and ( + server_round == total_round or server_round % save_every_round == 0 + ): + # Init model + model = get_model(model_cfg) + set_parameters(model, parameters) + + model.save_pretrained(f"{save_path}/peft_{server_round}") + + return 0.0, {} + + return evaluate + + +def get_on_fit_config(): + """ + Return a function that will be used to construct the config + that the client's fit() method will receive. + """ + + def fit_config_fn(server_round: int): + fit_config = {"current_round": server_round} + return fit_config + + return fit_config_fn + + +def fit_weighted_average(metrics): + """Aggregate (federated) evaluation metrics.""" + # Multiply accuracy of each client by number of examples used + losses = [num_examples * m["train_loss"] for num_examples, m in metrics] + examples = [num_examples for num_examples, _ in metrics] + + # Aggregate and return custom metric (weighted average) + return {"train_loss": sum(losses) / sum(examples)} diff --git a/src/py/flwr/cli/new/templates/app/code/flwr_tune/static_config.yaml.tpl b/src/py/flwr/cli/new/templates/app/code/flwr_tune/static_config.yaml.tpl new file mode 100644 index 000000000000..a8a4039fc831 --- /dev/null +++ b/src/py/flwr/cli/new/templates/app/code/flwr_tune/static_config.yaml.tpl @@ -0,0 +1,11 @@ +# Federated Instruction Tuning (static) +--- +dataset: + name: $dataset_name + +# FL experimental settings +num_clients: $num_clients # total number of clients +num_rounds: 200 +partitioner: + _target_: flwr_datasets.partitioner.IidPartitioner + num_partitions: $num_clients diff --git a/src/py/flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl b/src/py/flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl new file mode 100644 index 000000000000..2ed6bd36fd89 --- /dev/null +++ b/src/py/flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl @@ -0,0 +1,42 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "$package_name" +version = "1.0.0" +description = "" +authors = [ + { name = "The Flower Authors", email = "hello@flower.ai" }, +] +license = { text = "Apache License (2.0)" } +dependencies = [ + "flwr[simulation]>=1.9.0,<2.0", + "flwr-datasets>=0.1.0,<1.0.0", + "hydra-core==1.3.2", + "trl==0.8.1", + "bitsandbytes==0.43.0", + "scipy==1.13.0", + "peft==0.6.2", + "transformers==4.39.3", + "sentencepiece==0.2.0", +] + +[tool.hatch.build.targets.wheel] +packages = ["."] + +[flower] +publisher = "$username" + +[flower.components] +serverapp = "$import_name.app:server" +clientapp = "$import_name.app:client" + +[flower.engine] +name = "simulation" + +[flower.engine.simulation.supernode] +num = $num_clients + +[flower.engine.simulation] +backend_config = { client_resources = { num_cpus = 8, num_gpus = 1.0 } } diff --git a/src/py/flwr/cli/run/run.py b/src/py/flwr/cli/run/run.py index 7577d9efbd8c..4c95a4041c05 100644 --- a/src/py/flwr/cli/run/run.py +++ b/src/py/flwr/cli/run/run.py @@ -41,7 +41,10 @@ class Engine(str, Enum): def run( engine: Annotated[ Optional[Engine], - typer.Option(case_sensitive=False, help="The execution engine to run the app"), + typer.Option( + case_sensitive=False, + help="The engine to run FL with (currently only simulation is supported).", + ), ] = None, use_superexec: Annotated[ bool, @@ -87,12 +90,16 @@ def run( if engine == Engine.SIMULATION: num_supernodes = config["flower"]["engine"]["simulation"]["supernode"]["num"] + backend_config = config["flower"]["engine"]["simulation"].get( + "backend_config", None + ) typer.secho("Starting run... ", fg=typer.colors.BLUE) _run_simulation( server_app_attr=server_app_ref, client_app_attr=client_app_ref, num_supernodes=num_supernodes, + backend_config=backend_config, ) else: typer.secho( diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index cdb7b25cbf6b..1226a0d7bc21 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -31,6 +31,7 @@ from flwr.common.address import parse_address from flwr.common.constant import ( MISSING_EXTRA_REST, + TRANSPORT_TYPE_GRPC_ADAPTER, TRANSPORT_TYPE_GRPC_BIDI, TRANSPORT_TYPE_GRPC_RERE, TRANSPORT_TYPE_REST, @@ -41,6 +42,7 @@ from flwr.common.message import Error from flwr.common.retry_invoker import RetryInvoker, RetryState, exponential +from .grpc_adapter_client.connection import grpc_adapter 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 @@ -600,6 +602,8 @@ def _init_connection(transport: Optional[str], server_address: str) -> Tuple[ connection, error_type = http_request_response, RequestsConnectionError elif transport == TRANSPORT_TYPE_GRPC_RERE: connection, error_type = grpc_request_response, RpcError + elif transport == TRANSPORT_TYPE_GRPC_ADAPTER: + connection, error_type = grpc_adapter, RpcError elif transport == TRANSPORT_TYPE_GRPC_BIDI: connection, error_type = grpc_connection, RpcError else: diff --git a/src/py/flwr/client/app_test.py b/src/py/flwr/client/app_test.py index 56d6308a0fe2..74ade03f973a 100644 --- a/src/py/flwr/client/app_test.py +++ b/src/py/flwr/client/app_test.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2022 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. diff --git a/src/py/flwr/client/client_app.py b/src/py/flwr/client/client_app.py index 82539834eaad..2e810f6560f2 100644 --- a/src/py/flwr/client/client_app.py +++ b/src/py/flwr/client/client_app.py @@ -1,4 +1,4 @@ -# Copyright 2023 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. diff --git a/src/py/flwr/client/client_test.py b/src/py/flwr/client/client_test.py index 373c676e5edc..343b6cf093b2 100644 --- a/src/py/flwr/client/client_test.py +++ b/src/py/flwr/client/client_test.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2022 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. diff --git a/src/py/flwr/client/dpfedavg_numpy_client.py b/src/py/flwr/client/dpfedavg_numpy_client.py index ab31a289d29b..c592d10936d5 100644 --- a/src/py/flwr/client/dpfedavg_numpy_client.py +++ b/src/py/flwr/client/dpfedavg_numpy_client.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2022 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. diff --git a/src/py/flwr/client/grpc_rere_client/__init__.py b/src/py/flwr/client/grpc_rere_client/__init__.py index 93903e725776..e7c9408c0047 100644 --- a/src/py/flwr/client/grpc_rere_client/__init__.py +++ b/src/py/flwr/client/grpc_rere_client/__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. diff --git a/src/py/flwr/client/grpc_rere_client/client_interceptor_test.py b/src/py/flwr/client/grpc_rere_client/client_interceptor_test.py index cc35ffef46db..9607dac5679e 100644 --- a/src/py/flwr/client/grpc_rere_client/client_interceptor_test.py +++ b/src/py/flwr/client/grpc_rere_client/client_interceptor_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. diff --git a/src/py/flwr/client/grpc_rere_client/connection.py b/src/py/flwr/client/grpc_rere_client/connection.py index b1c268d51d55..34dc0e417383 100644 --- a/src/py/flwr/client/grpc_rere_client/connection.py +++ b/src/py/flwr/client/grpc_rere_client/connection.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. diff --git a/src/py/flwr/client/message_handler/__init__.py b/src/py/flwr/client/message_handler/__init__.py index 653563963de5..a345b4af3ef2 100644 --- a/src/py/flwr/client/message_handler/__init__.py +++ b/src/py/flwr/client/message_handler/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2022 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. diff --git a/src/py/flwr/client/message_handler/message_handler.py b/src/py/flwr/client/message_handler/message_handler.py index e5acbe0cc9d0..68326852970f 100644 --- a/src/py/flwr/client/message_handler/message_handler.py +++ b/src/py/flwr/client/message_handler/message_handler.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2022 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. 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 8a2db1804e4a..40907942513d 100644 --- a/src/py/flwr/client/message_handler/message_handler_test.py +++ b/src/py/flwr/client/message_handler/message_handler_test.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2022 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. diff --git a/src/py/flwr/client/mod/__init__.py b/src/py/flwr/client/mod/__init__.py index 0b4cf6488421..35d1fa81805c 100644 --- a/src/py/flwr/client/mod/__init__.py +++ b/src/py/flwr/client/mod/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2023 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. diff --git a/src/py/flwr/client/mod/secure_aggregation/__init__.py b/src/py/flwr/client/mod/secure_aggregation/__init__.py index 8892d8c03935..a64bc89e62c9 100644 --- a/src/py/flwr/client/mod/secure_aggregation/__init__.py +++ b/src/py/flwr/client/mod/secure_aggregation/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2023 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. diff --git a/src/py/flwr/client/mod/utils.py b/src/py/flwr/client/mod/utils.py index 4c3c32944f01..c8fb21379783 100644 --- a/src/py/flwr/client/mod/utils.py +++ b/src/py/flwr/client/mod/utils.py @@ -1,4 +1,4 @@ -# Copyright 2023 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. diff --git a/src/py/flwr/client/mod/utils_test.py b/src/py/flwr/client/mod/utils_test.py index 4676a2c02c4b..035e41639b10 100644 --- a/src/py/flwr/client/mod/utils_test.py +++ b/src/py/flwr/client/mod/utils_test.py @@ -1,4 +1,4 @@ -# Copyright 2023 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. diff --git a/src/py/flwr/client/numpy_client_test.py b/src/py/flwr/client/numpy_client_test.py index 526098798e45..06a0deafe2c9 100644 --- a/src/py/flwr/client/numpy_client_test.py +++ b/src/py/flwr/client/numpy_client_test.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2022 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. diff --git a/src/py/flwr/client/rest_client/__init__.py b/src/py/flwr/client/rest_client/__init__.py index c3485483ad35..a24d822a6d75 100644 --- a/src/py/flwr/client/rest_client/__init__.py +++ b/src/py/flwr/client/rest_client/__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. diff --git a/src/py/flwr/client/rest_client/connection.py b/src/py/flwr/client/rest_client/connection.py index 5f5e153f9d8d..db5bd7eb6770 100644 --- a/src/py/flwr/client/rest_client/connection.py +++ b/src/py/flwr/client/rest_client/connection.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. diff --git a/src/py/flwr/client/supernode/app.py b/src/py/flwr/client/supernode/app.py index 362b09c5d5b5..c9a16edeaf15 100644 --- a/src/py/flwr/client/supernode/app.py +++ b/src/py/flwr/client/supernode/app.py @@ -30,6 +30,11 @@ from flwr.client.client_app import ClientApp, LoadClientAppError from flwr.common import EventType, event from flwr.common.config import get_flwr_dir, get_project_config, get_project_dir +from flwr.common.constant import ( + TRANSPORT_TYPE_GRPC_ADAPTER, + TRANSPORT_TYPE_GRPC_RERE, + TRANSPORT_TYPE_REST, +) from flwr.common.exit_handlers import register_exit_handlers from flwr.common.logger import log, warn_deprecated_feature from flwr.common.object_ref import load_app, validate @@ -56,7 +61,7 @@ def run_supernode() -> None: _start_client_internal( server_address=args.superlink, load_client_app_fn=load_fn, - transport="rest" if args.rest else "grpc-rere", + transport=args.transport, root_certificates=root_certificates, insecure=args.insecure, authentication_keys=authentication_keys, @@ -87,7 +92,7 @@ def run_client_app() -> None: _start_client_internal( server_address=args.superlink, load_client_app_fn=load_fn, - transport="rest" if args.rest else "grpc-rere", + transport=args.transport, root_certificates=root_certificates, insecure=args.insecure, authentication_keys=authentication_keys, @@ -262,7 +267,7 @@ def _parse_args_run_supernode() -> argparse.ArgumentParser: "--flwr-dir", default=None, help="""The path containing installed Flower Apps. - By default, this value isequal to: + By default, this value is equal to: - `$FLWR_HOME/` if `$FLWR_HOME` is defined - `$XDG_DATA_HOME/.flwr/` if `$XDG_DATA_HOME` is defined @@ -295,9 +300,27 @@ def _parse_args_common(parser: argparse.ArgumentParser) -> None: 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( + ex_group = parser.add_mutually_exclusive_group() + ex_group.add_argument( + "--grpc-rere", + action="store_const", + dest="transport", + const=TRANSPORT_TYPE_GRPC_RERE, + default=TRANSPORT_TYPE_GRPC_RERE, + help="Use grpc-rere as a transport layer for the client.", + ) + ex_group.add_argument( + "--grpc-adapter", + action="store_const", + dest="transport", + const=TRANSPORT_TYPE_GRPC_ADAPTER, + help="Use grpc-adapter as a transport layer for the client.", + ) + ex_group.add_argument( "--rest", - action="store_true", + action="store_const", + dest="transport", + const=TRANSPORT_TYPE_REST, help="Use REST as a transport layer for the client.", ) parser.add_argument( diff --git a/src/py/flwr/common/address.py b/src/py/flwr/common/address.py index 71b6d684597f..1c6481b80a74 100644 --- a/src/py/flwr/common/address.py +++ b/src/py/flwr/common/address.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. diff --git a/src/py/flwr/common/address_test.py b/src/py/flwr/common/address_test.py index 420b89871d69..d5901ed640b1 100644 --- a/src/py/flwr/common/address_test.py +++ b/src/py/flwr/common/address_test.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. diff --git a/src/py/flwr/common/config.py b/src/py/flwr/common/config.py index 95bf8ce31c45..20de00a6fba9 100644 --- a/src/py/flwr/common/config.py +++ b/src/py/flwr/common/config.py @@ -24,14 +24,16 @@ from flwr.common.constant import APP_DIR, FAB_CONFIG_FILE, FLWR_HOME -def get_flwr_dir() -> Path: +def get_flwr_dir(provided_path: Optional[str] = None) -> Path: """Return the Flower home directory based on env variables.""" - return Path( - os.getenv( - FLWR_HOME, - f"{os.getenv('XDG_DATA_HOME', os.getenv('HOME'))}/.flwr", + if provided_path is None or not Path(provided_path).is_dir(): + return Path( + os.getenv( + FLWR_HOME, + f"{os.getenv('XDG_DATA_HOME', os.getenv('HOME'))}/.flwr", + ) ) - ) + return Path(provided_path).absolute() def get_project_dir( diff --git a/src/py/flwr/common/constant.py b/src/py/flwr/common/constant.py index ac35549d2051..ce29b3edb30e 100644 --- a/src/py/flwr/common/constant.py +++ b/src/py/flwr/common/constant.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. @@ -27,6 +27,7 @@ TRANSPORT_TYPE_GRPC_BIDI = "grpc-bidi" TRANSPORT_TYPE_GRPC_RERE = "grpc-rere" +TRANSPORT_TYPE_GRPC_ADAPTER = "grpc-adapter" TRANSPORT_TYPE_REST = "rest" TRANSPORT_TYPE_VCE = "vce" TRANSPORT_TYPES = [ @@ -45,6 +46,9 @@ PING_RANDOM_RANGE = (-0.1, 0.1) PING_MAX_INTERVAL = 1e300 +GRPC_ADAPTER_METADATA_FLOWER_VERSION_KEY = "flower-version" +GRPC_ADAPTER_METADATA_SHOULD_EXIT_KEY = "should-exit" + # Constants for FAB APP_DIR = "apps" FAB_CONFIG_FILE = "pyproject.toml" diff --git a/src/py/flwr/common/date.py b/src/py/flwr/common/date.py index f47ad5470106..7f30f5e0591a 100644 --- a/src/py/flwr/common/date.py +++ b/src/py/flwr/common/date.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. diff --git a/src/py/flwr/common/dp.py b/src/py/flwr/common/dp.py index 83a72b8ce749..527805c8ef42 100644 --- a/src/py/flwr/common/dp.py +++ b/src/py/flwr/common/dp.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2022 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. diff --git a/src/py/flwr/common/grpc.py b/src/py/flwr/common/grpc.py index ead0329ca79c..ec8fe823a7eb 100644 --- a/src/py/flwr/common/grpc.py +++ b/src/py/flwr/common/grpc.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2022 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. diff --git a/src/py/flwr/common/message_test.py b/src/py/flwr/common/message_test.py index 19f8aeb1eb63..daee57896903 100644 --- a/src/py/flwr/common/message_test.py +++ b/src/py/flwr/common/message_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. diff --git a/src/py/flwr/common/secure_aggregation/__init__.py b/src/py/flwr/common/secure_aggregation/__init__.py index b4e0acc0c148..77e1ea3842d7 100644 --- a/src/py/flwr/common/secure_aggregation/__init__.py +++ b/src/py/flwr/common/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. diff --git a/src/py/flwr/common/secure_aggregation/crypto/__init__.py b/src/py/flwr/common/secure_aggregation/crypto/__init__.py index 2cb34493f7d0..3788dbc0ca15 100644 --- a/src/py/flwr/common/secure_aggregation/crypto/__init__.py +++ b/src/py/flwr/common/secure_aggregation/crypto/__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. diff --git a/src/py/flwr/common/secure_aggregation/crypto/shamir.py b/src/py/flwr/common/secure_aggregation/crypto/shamir.py index e56e21b89371..688bfa2153ea 100644 --- a/src/py/flwr/common/secure_aggregation/crypto/shamir.py +++ b/src/py/flwr/common/secure_aggregation/crypto/shamir.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. diff --git a/src/py/flwr/common/secure_aggregation/crypto/symmetric_encryption.py b/src/py/flwr/common/secure_aggregation/crypto/symmetric_encryption.py index 1d004a398ea8..59ca84d604b8 100644 --- a/src/py/flwr/common/secure_aggregation/crypto/symmetric_encryption.py +++ b/src/py/flwr/common/secure_aggregation/crypto/symmetric_encryption.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. diff --git a/src/py/flwr/common/secure_aggregation/ndarrays_arithmetic.py b/src/py/flwr/common/secure_aggregation/ndarrays_arithmetic.py index e926a9531bea..207c15b61518 100644 --- a/src/py/flwr/common/secure_aggregation/ndarrays_arithmetic.py +++ b/src/py/flwr/common/secure_aggregation/ndarrays_arithmetic.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. diff --git a/src/py/flwr/common/secure_aggregation/quantization.py b/src/py/flwr/common/secure_aggregation/quantization.py index 56c25e2bd59c..7946276b6a4f 100644 --- a/src/py/flwr/common/secure_aggregation/quantization.py +++ b/src/py/flwr/common/secure_aggregation/quantization.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. diff --git a/src/py/flwr/common/secure_aggregation/secaggplus_constants.py b/src/py/flwr/common/secure_aggregation/secaggplus_constants.py index 8a15908c13c5..545507eb44ed 100644 --- a/src/py/flwr/common/secure_aggregation/secaggplus_constants.py +++ b/src/py/flwr/common/secure_aggregation/secaggplus_constants.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. diff --git a/src/py/flwr/common/secure_aggregation/secaggplus_utils.py b/src/py/flwr/common/secure_aggregation/secaggplus_utils.py index c373573477b9..cf6ac3bfb003 100644 --- a/src/py/flwr/common/secure_aggregation/secaggplus_utils.py +++ b/src/py/flwr/common/secure_aggregation/secaggplus_utils.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. diff --git a/src/py/flwr/common/serde_test.py b/src/py/flwr/common/serde_test.py index f9969426fc36..afb11b6956f2 100644 --- a/src/py/flwr/common/serde_test.py +++ b/src/py/flwr/common/serde_test.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2021 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. diff --git a/src/py/flwr/common/version.py b/src/py/flwr/common/version.py index 6808c66606b1..ac13f70d8a88 100644 --- a/src/py/flwr/common/version.py +++ b/src/py/flwr/common/version.py @@ -1,3 +1,17 @@ +# 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 package version helper.""" import importlib.metadata as importlib_metadata diff --git a/src/py/flwr/server/app.py b/src/py/flwr/server/app.py index 1574ec46f968..822defdb5b13 100644 --- a/src/py/flwr/server/app.py +++ b/src/py/flwr/server/app.py @@ -36,6 +36,7 @@ from flwr.common.address import parse_address from flwr.common.constant import ( MISSING_EXTRA_REST, + TRANSPORT_TYPE_GRPC_ADAPTER, TRANSPORT_TYPE_GRPC_RERE, TRANSPORT_TYPE_REST, ) @@ -48,6 +49,7 @@ from flwr.proto.fleet_pb2_grpc import ( # pylint: disable=E0611 add_FleetServicer_to_server, ) +from flwr.proto.grpcadapter_pb2_grpc import add_GrpcAdapterServicer_to_server from .client_manager import ClientManager from .history import History @@ -55,6 +57,7 @@ from .server_config import ServerConfig from .strategy import Strategy from .superlink.driver.driver_grpc import run_driver_api_grpc +from .superlink.fleet.grpc_adapter.grpc_adapter_servicer import GrpcAdapterServicer from .superlink.fleet.grpc_bidi.grpc_server import ( generic_create_grpc_server, start_grpc_server, @@ -218,11 +221,13 @@ def run_superlink() -> None: grpc_servers = [driver_server] bckg_threads = [] if not args.fleet_api_address: - args.fleet_api_address = ( - ADDRESS_FLEET_API_GRPC_RERE - if args.fleet_api_type == TRANSPORT_TYPE_GRPC_RERE - else ADDRESS_FLEET_API_REST - ) + if args.fleet_api_type in [ + TRANSPORT_TYPE_GRPC_RERE, + TRANSPORT_TYPE_GRPC_ADAPTER, + ]: + args.fleet_api_address = ADDRESS_FLEET_API_GRPC_RERE + elif args.fleet_api_type == TRANSPORT_TYPE_REST: + args.fleet_api_address = ADDRESS_FLEET_API_REST fleet_address, host, port = _format_address(args.fleet_api_address) @@ -293,6 +298,13 @@ def run_superlink() -> None: interceptors=interceptors, ) grpc_servers.append(fleet_server) + elif args.fleet_api_type == TRANSPORT_TYPE_GRPC_ADAPTER: + fleet_server = _run_fleet_api_grpc_adapter( + address=fleet_address, + state_factory=state_factory, + certificates=certificates, + ) + grpc_servers.append(fleet_server) else: raise ValueError(f"Unknown fleet_api_type: {args.fleet_api_type}") @@ -419,7 +431,7 @@ def _try_obtain_certificates( log(WARN, "Option `--insecure` was set. Starting insecure HTTP server.") return None # Check if certificates are provided - if args.fleet_api_type == TRANSPORT_TYPE_GRPC_RERE: + if args.fleet_api_type in [TRANSPORT_TYPE_GRPC_RERE, TRANSPORT_TYPE_GRPC_ADAPTER]: if args.ssl_certfile and args.ssl_keyfile and args.ssl_ca_certfile: if not isfile(args.ssl_ca_certfile): sys.exit("Path argument `--ssl-ca-certfile` does not point to a file.") @@ -491,6 +503,30 @@ def _run_fleet_api_grpc_rere( return fleet_grpc_server +def _run_fleet_api_grpc_adapter( + address: str, + state_factory: StateFactory, + certificates: Optional[Tuple[bytes, bytes, bytes]], +) -> grpc.Server: + """Run Fleet API (GrpcAdapter).""" + # Create Fleet API gRPC server + fleet_servicer = GrpcAdapterServicer( + state_factory=state_factory, + ) + fleet_add_servicer_to_server_fn = add_GrpcAdapterServicer_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 (GrpcAdapter) on %s", address) + fleet_grpc_server.start() + + return fleet_grpc_server + + # pylint: disable=import-outside-toplevel,too-many-arguments def _run_fleet_api_rest( host: str, @@ -606,7 +642,11 @@ def _add_args_fleet_api(parser: argparse.ArgumentParser) -> None: "--fleet-api-type", default=TRANSPORT_TYPE_GRPC_RERE, type=str, - choices=[TRANSPORT_TYPE_GRPC_RERE, TRANSPORT_TYPE_REST], + choices=[ + TRANSPORT_TYPE_GRPC_RERE, + TRANSPORT_TYPE_GRPC_ADAPTER, + TRANSPORT_TYPE_REST, + ], help="Start a gRPC-rere or REST (experimental) Fleet API server.", ) parser.add_argument( diff --git a/src/py/flwr/server/client_proxy_test.py b/src/py/flwr/server/client_proxy_test.py index 685698558e3a..6ca37052a87d 100644 --- a/src/py/flwr/server/client_proxy_test.py +++ b/src/py/flwr/server/client_proxy_test.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2022 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. diff --git a/src/py/flwr/server/compat/app.py b/src/py/flwr/server/compat/app.py index 4bb23b846ab7..e978359fa828 100644 --- a/src/py/flwr/server/compat/app.py +++ b/src/py/flwr/server/compat/app.py @@ -1,4 +1,4 @@ -# Copyright 2022 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. diff --git a/src/py/flwr/server/compat/app_utils.py b/src/py/flwr/server/compat/app_utils.py index 1cdf1efbffb9..baff27307b88 100644 --- a/src/py/flwr/server/compat/app_utils.py +++ b/src/py/flwr/server/compat/app_utils.py @@ -91,7 +91,7 @@ def _update_client_manager( node_id=node_id, driver=driver, anonymous=False, - run_id=driver.run_id, # type: ignore + run_id=driver.run.run_id, ) if client_manager.register(client_proxy): registered_nodes[node_id] = client_proxy diff --git a/src/py/flwr/server/compat/driver_client_proxy.py b/src/py/flwr/server/compat/driver_client_proxy.py index 150803786f98..7190786784ec 100644 --- a/src/py/flwr/server/compat/driver_client_proxy.py +++ b/src/py/flwr/server/compat/driver_client_proxy.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. diff --git a/src/py/flwr/server/compat/driver_client_proxy_test.py b/src/py/flwr/server/compat/driver_client_proxy_test.py index d9e3d3bc0824..31b917fa869b 100644 --- a/src/py/flwr/server/compat/driver_client_proxy_test.py +++ b/src/py/flwr/server/compat/driver_client_proxy_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. diff --git a/src/py/flwr/server/driver/driver.py b/src/py/flwr/server/driver/driver.py index b95cec95ab47..4f888323e586 100644 --- a/src/py/flwr/server/driver/driver.py +++ b/src/py/flwr/server/driver/driver.py @@ -19,11 +19,17 @@ from typing import Iterable, List, Optional from flwr.common import Message, RecordSet +from flwr.common.typing import Run class Driver(ABC): """Abstract base Driver class for the Driver API.""" + @property + @abstractmethod + def run(self) -> Run: + """Run information.""" + @abstractmethod def create_message( # pylint: disable=too-many-arguments self, diff --git a/src/py/flwr/server/driver/grpc_driver.py b/src/py/flwr/server/driver/grpc_driver.py index d339f1b232f9..e614df659e3f 100644 --- a/src/py/flwr/server/driver/grpc_driver.py +++ b/src/py/flwr/server/driver/grpc_driver.py @@ -1,4 +1,4 @@ -# Copyright 2022 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,7 +17,7 @@ import time import warnings from logging import DEBUG, ERROR, WARNING -from typing import Iterable, List, Optional, Tuple +from typing import Iterable, List, Optional, Tuple, cast import grpc @@ -25,6 +25,7 @@ from flwr.common.grpc import create_channel from flwr.common.logger import log from flwr.common.serde import message_from_taskres, message_to_taskins +from flwr.common.typing import Run from flwr.proto.driver_pb2 import ( # pylint: disable=E0611 CreateRunRequest, CreateRunResponse, @@ -37,6 +38,7 @@ ) from flwr.proto.driver_pb2_grpc import DriverStub # pylint: disable=E0611 from flwr.proto.node_pb2 import Node # pylint: disable=E0611 +from flwr.proto.run_pb2 import GetRunRequest, GetRunResponse # pylint: disable=E0611 from flwr.proto.task_pb2 import TaskIns # pylint: disable=E0611 from .driver import Driver @@ -46,13 +48,24 @@ ERROR_MESSAGE_DRIVER_NOT_CONNECTED = """ [Driver] Error: Not connected. -Call `connect()` on the `GrpcDriverHelper` instance before calling any of the other -`GrpcDriverHelper` methods. +Call `connect()` on the `GrpcDriverStub` instance before calling any of the other +`GrpcDriverStub` methods. """ -class GrpcDriverHelper: - """`GrpcDriverHelper` provides access to the gRPC Driver API/service.""" +class GrpcDriverStub: + """`GrpcDriverStub` provides access to the gRPC Driver API/service. + + Parameters + ---------- + driver_service_address : Optional[str] + The IPv4 or IPv6 address of the Driver API server. + Defaults to `"[::]:9091"`. + root_certificates : Optional[bytes] (default: None) + The PEM-encoded root certificates as a byte string. + If provided, a secure connection using the certificates will be + established to an SSL-enabled Flower server. + """ def __init__( self, @@ -64,6 +77,10 @@ def __init__( self.channel: Optional[grpc.Channel] = None self.stub: Optional[DriverStub] = None + def is_connected(self) -> bool: + """Return True if connected to the Driver API server, otherwise False.""" + return self.channel is not None + def connect(self) -> None: """Connect to the Driver API.""" event(EventType.DRIVER_CONNECT) @@ -95,18 +112,29 @@ def create_run(self, req: CreateRunRequest) -> CreateRunResponse: # Check if channel is open if self.stub is None: log(ERROR, ERROR_MESSAGE_DRIVER_NOT_CONNECTED) - raise ConnectionError("`GrpcDriverHelper` instance not connected") + raise ConnectionError("`GrpcDriverStub` instance not connected") # Call Driver API res: CreateRunResponse = self.stub.CreateRun(request=req) return res + def get_run(self, req: GetRunRequest) -> GetRunResponse: + """Get run information.""" + # Check if channel is open + if self.stub is None: + log(ERROR, ERROR_MESSAGE_DRIVER_NOT_CONNECTED) + raise ConnectionError("`GrpcDriverStub` instance not connected") + + # Call gRPC Driver API + res: GetRunResponse = self.stub.GetRun(request=req) + return res + def get_nodes(self, req: GetNodesRequest) -> GetNodesResponse: """Get client IDs.""" # Check if channel is open if self.stub is None: log(ERROR, ERROR_MESSAGE_DRIVER_NOT_CONNECTED) - raise ConnectionError("`GrpcDriverHelper` instance not connected") + raise ConnectionError("`GrpcDriverStub` instance not connected") # Call gRPC Driver API res: GetNodesResponse = self.stub.GetNodes(request=req) @@ -117,7 +145,7 @@ def push_task_ins(self, req: PushTaskInsRequest) -> PushTaskInsResponse: # Check if channel is open if self.stub is None: log(ERROR, ERROR_MESSAGE_DRIVER_NOT_CONNECTED) - raise ConnectionError("`GrpcDriverHelper` instance not connected") + raise ConnectionError("`GrpcDriverStub` instance not connected") # Call gRPC Driver API res: PushTaskInsResponse = self.stub.PushTaskIns(request=req) @@ -128,7 +156,7 @@ def pull_task_res(self, req: PullTaskResRequest) -> PullTaskResResponse: # Check if channel is open if self.stub is None: log(ERROR, ERROR_MESSAGE_DRIVER_NOT_CONNECTED) - raise ConnectionError("`GrpcDriverHelper` instance not connected") + raise ConnectionError("`GrpcDriverStub` instance not connected") # Call Driver API res: PullTaskResResponse = self.stub.PullTaskRes(request=req) @@ -140,56 +168,52 @@ class GrpcDriver(Driver): Parameters ---------- - driver_service_address : Optional[str] - The IPv4 or IPv6 address of the Driver API server. - Defaults to `"[::]:9091"`. - certificates : bytes (default: None) - 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. - fab_id : str (default: None) - The identifier of the FAB used in the run. - fab_version : str (default: None) - The version of the FAB used in the run. + run_id : int + The identifier of the run. + stub : Optional[GrpcDriverStub] (default: None) + The ``GrpcDriverStub`` instance used to communicate with the SuperLink. + If None, an instance connected to "[::]:9091" will be created. """ - def __init__( + def __init__( # pylint: disable=too-many-arguments self, - driver_service_address: str = DEFAULT_SERVER_ADDRESS_DRIVER, - root_certificates: Optional[bytes] = None, - fab_id: Optional[str] = None, - fab_version: Optional[str] = None, + run_id: int, + stub: Optional[GrpcDriverStub] = None, ) -> None: - self.addr = driver_service_address - self.root_certificates = root_certificates - self.driver_helper: Optional[GrpcDriverHelper] = None - self.run_id: Optional[int] = None - self.fab_id = fab_id if fab_id is not None else "" - self.fab_version = fab_version if fab_version is not None else "" + self._run_id = run_id + self._run: Optional[Run] = None + self.stub = stub if stub is not None else GrpcDriverStub() self.node = Node(node_id=0, anonymous=True) - def _get_grpc_driver_helper_and_run_id(self) -> Tuple[GrpcDriverHelper, int]: - # Check if the GrpcDriverHelper is initialized - if self.driver_helper is None or self.run_id is None: - # Connect and create run - self.driver_helper = GrpcDriverHelper( - driver_service_address=self.addr, - root_certificates=self.root_certificates, + @property + def run(self) -> Run: + """Run information.""" + self._get_stub_and_run_id() + return Run(**vars(cast(Run, self._run))) + + def _get_stub_and_run_id(self) -> Tuple[GrpcDriverStub, int]: + # Check if is initialized + if self._run is None: + # Connect + if not self.stub.is_connected(): + self.stub.connect() + # Get the run info + req = GetRunRequest(run_id=self._run_id) + res = self.stub.get_run(req) + if not res.HasField("run"): + raise RuntimeError(f"Cannot find the run with ID: {self._run_id}") + self._run = Run( + run_id=res.run.run_id, + fab_id=res.run.fab_id, + fab_version=res.run.fab_version, ) - self.driver_helper.connect() - req = CreateRunRequest(fab_id=self.fab_id, fab_version=self.fab_version) - res = self.driver_helper.create_run(req) - self.run_id = res.run_id - return self.driver_helper, self.run_id + + return self.stub, self._run.run_id def _check_message(self, message: Message) -> None: # Check if the message is valid if not ( - message.metadata.run_id == self.run_id + message.metadata.run_id == cast(Run, self._run).run_id and message.metadata.src_node_id == self.node.node_id and message.metadata.message_id == "" and message.metadata.reply_to_message == "" @@ -210,7 +234,7 @@ def create_message( # pylint: disable=too-many-arguments This method constructs a new `Message` with given content and metadata. The `run_id` and `src_node_id` will be set automatically. """ - _, run_id = self._get_grpc_driver_helper_and_run_id() + _, run_id = self._get_stub_and_run_id() if ttl: warnings.warn( "A custom TTL was set, but note that the SuperLink does not enforce " @@ -234,9 +258,9 @@ def create_message( # pylint: disable=too-many-arguments def get_node_ids(self) -> List[int]: """Get node IDs.""" - grpc_driver_helper, run_id = self._get_grpc_driver_helper_and_run_id() - # Call GrpcDriverHelper method - res = grpc_driver_helper.get_nodes(GetNodesRequest(run_id=run_id)) + stub, run_id = self._get_stub_and_run_id() + # Call GrpcDriverStub method + res = stub.get_nodes(GetNodesRequest(run_id=run_id)) return [node.node_id for node in res.nodes] def push_messages(self, messages: Iterable[Message]) -> Iterable[str]: @@ -245,7 +269,7 @@ def push_messages(self, messages: Iterable[Message]) -> Iterable[str]: This method takes an iterable of messages and sends each message to the node specified in `dst_node_id`. """ - grpc_driver_helper, _ = self._get_grpc_driver_helper_and_run_id() + stub, _ = self._get_stub_and_run_id() # Construct TaskIns task_ins_list: List[TaskIns] = [] for msg in messages: @@ -255,10 +279,8 @@ def push_messages(self, messages: Iterable[Message]) -> Iterable[str]: taskins = message_to_taskins(msg) # Add to list task_ins_list.append(taskins) - # Call GrpcDriverHelper method - res = grpc_driver_helper.push_task_ins( - PushTaskInsRequest(task_ins_list=task_ins_list) - ) + # Call GrpcDriverStub method + res = stub.push_task_ins(PushTaskInsRequest(task_ins_list=task_ins_list)) return list(res.task_ids) def pull_messages(self, message_ids: Iterable[str]) -> Iterable[Message]: @@ -267,9 +289,9 @@ def pull_messages(self, message_ids: Iterable[str]) -> Iterable[Message]: This method is used to collect messages from the SuperLink that correspond to a set of given message IDs. """ - grpc_driver, _ = self._get_grpc_driver_helper_and_run_id() + stub, _ = self._get_stub_and_run_id() # Pull TaskRes - res = grpc_driver.pull_task_res( + res = stub.pull_task_res( PullTaskResRequest(node=self.node, task_ids=message_ids) ) # Convert TaskRes to Message @@ -308,8 +330,8 @@ def send_and_receive( def close(self) -> None: """Disconnect from the SuperLink if connected.""" - # Check if GrpcDriverHelper is initialized - if self.driver_helper is None: + # Check if `connect` was called before + if not self.stub.is_connected(): return # Disconnect - self.driver_helper.disconnect() + self.stub.disconnect() diff --git a/src/py/flwr/server/driver/grpc_driver_test.py b/src/py/flwr/server/driver/grpc_driver_test.py index fbead0e3043d..72efc5f8b2c6 100644 --- a/src/py/flwr/server/driver/grpc_driver_test.py +++ b/src/py/flwr/server/driver/grpc_driver_test.py @@ -1,4 +1,4 @@ -# Copyright 2022 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. @@ -27,6 +27,7 @@ PullTaskResRequest, PushTaskInsRequest, ) +from flwr.proto.run_pb2 import Run # pylint: disable=E0611 from flwr.proto.task_pb2 import Task, TaskRes # pylint: disable=E0611 from .grpc_driver import GrpcDriver @@ -36,58 +37,36 @@ class TestGrpcDriver(unittest.TestCase): """Tests for `GrpcDriver` class.""" def setUp(self) -> None: - """Initialize mock GrpcDriverHelper and Driver instance before each test.""" - mock_response = Mock() - mock_response.run_id = 61016 - self.mock_grpc_driver_helper = Mock() - self.mock_grpc_driver_helper.create_run.return_value = mock_response - self.patcher = patch( - "flwr.server.driver.grpc_driver.GrpcDriverHelper", - return_value=self.mock_grpc_driver_helper, + """Initialize mock GrpcDriverStub and Driver instance before each test.""" + mock_response = Mock( + run=Run(run_id=61016, fab_id="mock/mock", fab_version="v1.0.0") ) - self.patcher.start() - self.driver = GrpcDriver() - - def tearDown(self) -> None: - """Cleanup after each test.""" - self.patcher.stop() - - def test_check_and_init_grpc_driver_already_initialized(self) -> None: - """Test that GrpcDriverHelper doesn't initialize if run is created.""" - # Prepare - self.driver.driver_helper = self.mock_grpc_driver_helper - self.driver.run_id = 61016 - - # Execute - # pylint: disable-next=protected-access - self.driver._get_grpc_driver_helper_and_run_id() + self.mock_grpc_driver_stub = Mock() + self.mock_grpc_driver_stub.get_run.return_value = mock_response + self.mock_grpc_driver_stub.HasField.return_value = True + self.driver = GrpcDriver(run_id=61016, stub=self.mock_grpc_driver_stub) + def test_init_grpc_driver(self) -> None: + """Test GrpcDriverStub initialization.""" # Assert - self.mock_grpc_driver_helper.connect.assert_not_called() - - def test_check_and_init_grpc_driver_needs_initialization(self) -> None: - """Test GrpcDriverHelper initialization when run is not created.""" - # Execute - # pylint: disable-next=protected-access - self.driver._get_grpc_driver_helper_and_run_id() - - # Assert - self.mock_grpc_driver_helper.connect.assert_called_once() - self.assertEqual(self.driver.run_id, 61016) + self.assertEqual(self.driver.run.run_id, 61016) + self.assertEqual(self.driver.run.fab_id, "mock/mock") + self.assertEqual(self.driver.run.fab_version, "v1.0.0") + self.mock_grpc_driver_stub.get_run.assert_called_once() def test_get_nodes(self) -> None: """Test retrieval of nodes.""" # Prepare mock_response = Mock() mock_response.nodes = [Mock(node_id=404), Mock(node_id=200)] - self.mock_grpc_driver_helper.get_nodes.return_value = mock_response + self.mock_grpc_driver_stub.get_nodes.return_value = mock_response # Execute node_ids = self.driver.get_node_ids() - args, kwargs = self.mock_grpc_driver_helper.get_nodes.call_args + args, kwargs = self.mock_grpc_driver_stub.get_nodes.call_args # Assert - self.mock_grpc_driver_helper.connect.assert_called_once() + self.mock_grpc_driver_stub.get_run.assert_called_once() self.assertEqual(len(args), 1) self.assertEqual(len(kwargs), 0) self.assertIsInstance(args[0], GetNodesRequest) @@ -98,7 +77,7 @@ def test_push_messages_valid(self) -> None: """Test pushing valid messages.""" # Prepare mock_response = Mock(task_ids=["id1", "id2"]) - self.mock_grpc_driver_helper.push_task_ins.return_value = mock_response + self.mock_grpc_driver_stub.push_task_ins.return_value = mock_response msgs = [ self.driver.create_message(RecordSet(), "", 0, "", DEFAULT_TTL) for _ in range(2) @@ -106,10 +85,10 @@ def test_push_messages_valid(self) -> None: # Execute msg_ids = self.driver.push_messages(msgs) - args, kwargs = self.mock_grpc_driver_helper.push_task_ins.call_args + args, kwargs = self.mock_grpc_driver_stub.push_task_ins.call_args # Assert - self.mock_grpc_driver_helper.connect.assert_called_once() + self.mock_grpc_driver_stub.get_run.assert_called_once() self.assertEqual(len(args), 1) self.assertEqual(len(kwargs), 0) self.assertIsInstance(args[0], PushTaskInsRequest) @@ -121,7 +100,7 @@ def test_push_messages_invalid(self) -> None: """Test pushing invalid messages.""" # Prepare mock_response = Mock(task_ids=["id1", "id2"]) - self.mock_grpc_driver_helper.push_task_ins.return_value = mock_response + self.mock_grpc_driver_stub.push_task_ins.return_value = mock_response msgs = [ self.driver.create_message(RecordSet(), "", 0, "", DEFAULT_TTL) for _ in range(2) @@ -145,16 +124,16 @@ def test_pull_messages_with_given_message_ids(self) -> None: ), TaskRes(task=Task(ancestry=["id3"], error=error_to_proto(Error(code=0)))), ] - self.mock_grpc_driver_helper.pull_task_res.return_value = mock_response + self.mock_grpc_driver_stub.pull_task_res.return_value = mock_response msg_ids = ["id1", "id2", "id3"] # Execute msgs = self.driver.pull_messages(msg_ids) reply_tos = {msg.metadata.reply_to_message for msg in msgs} - args, kwargs = self.mock_grpc_driver_helper.pull_task_res.call_args + args, kwargs = self.mock_grpc_driver_stub.pull_task_res.call_args # Assert - self.mock_grpc_driver_helper.connect.assert_called_once() + self.mock_grpc_driver_stub.get_run.assert_called_once() self.assertEqual(len(args), 1) self.assertEqual(len(kwargs), 0) self.assertIsInstance(args[0], PullTaskResRequest) @@ -165,14 +144,14 @@ def test_send_and_receive_messages_complete(self) -> None: """Test send and receive all messages successfully.""" # Prepare mock_response = Mock(task_ids=["id1"]) - self.mock_grpc_driver_helper.push_task_ins.return_value = mock_response + self.mock_grpc_driver_stub.push_task_ins.return_value = mock_response # The response message must include either `content` (i.e. a recordset) or # an `Error`. We choose the latter in this case error_proto = error_to_proto(Error(code=0)) mock_response = Mock( task_res_list=[TaskRes(task=Task(ancestry=["id1"], error=error_proto))] ) - self.mock_grpc_driver_helper.pull_task_res.return_value = mock_response + self.mock_grpc_driver_stub.pull_task_res.return_value = mock_response msgs = [self.driver.create_message(RecordSet(), "", 0, "", DEFAULT_TTL)] # Execute @@ -187,9 +166,9 @@ def test_send_and_receive_messages_timeout(self) -> None: # Prepare sleep_fn = time.sleep mock_response = Mock(task_ids=["id1"]) - self.mock_grpc_driver_helper.push_task_ins.return_value = mock_response + self.mock_grpc_driver_stub.push_task_ins.return_value = mock_response mock_response = Mock(task_res_list=[]) - self.mock_grpc_driver_helper.pull_task_res.return_value = mock_response + self.mock_grpc_driver_stub.pull_task_res.return_value = mock_response msgs = [self.driver.create_message(RecordSet(), "", 0, "", DEFAULT_TTL)] # Execute @@ -204,19 +183,21 @@ def test_send_and_receive_messages_timeout(self) -> None: def test_del_with_initialized_driver(self) -> None: """Test cleanup behavior when Driver is initialized.""" # Prepare - # pylint: disable-next=protected-access - self.driver._get_grpc_driver_helper_and_run_id() + self.mock_grpc_driver_stub.is_connected.return_value = True # Execute self.driver.close() # Assert - self.mock_grpc_driver_helper.disconnect.assert_called_once() + self.mock_grpc_driver_stub.disconnect.assert_called_once() def test_del_with_uninitialized_driver(self) -> None: """Test cleanup behavior when Driver is not initialized.""" + # Prepare + self.mock_grpc_driver_stub.is_connected.return_value = False + # Execute self.driver.close() # Assert - self.mock_grpc_driver_helper.disconnect.assert_not_called() + self.mock_grpc_driver_stub.disconnect.assert_not_called() diff --git a/src/py/flwr/server/driver/inmemory_driver.py b/src/py/flwr/server/driver/inmemory_driver.py index 8c71b1067293..53406796750f 100644 --- a/src/py/flwr/server/driver/inmemory_driver.py +++ b/src/py/flwr/server/driver/inmemory_driver.py @@ -17,11 +17,12 @@ import time import warnings -from typing import Iterable, List, Optional +from typing import Iterable, List, Optional, cast from uuid import UUID from flwr.common import DEFAULT_TTL, Message, Metadata, RecordSet from flwr.common.serde import message_from_taskres, message_to_taskins +from flwr.common.typing import Run from flwr.proto.node_pb2 import Node # pylint: disable=E0611 from flwr.server.superlink.state import StateFactory @@ -33,30 +34,27 @@ class InMemoryDriver(Driver): Parameters ---------- + run_id : int + The identifier of the run. state_factory : StateFactory A StateFactory embedding a state that this driver can interface with. - fab_id : str (default: None) - The identifier of the FAB used in the run. - fab_version : str (default: None) - The version of the FAB used in the run. """ def __init__( self, + run_id: int, state_factory: StateFactory, - fab_id: Optional[str] = None, - fab_version: Optional[str] = None, ) -> None: - self.run_id: Optional[int] = None - self.fab_id = fab_id if fab_id is not None else "" - self.fab_version = fab_version if fab_version is not None else "" - self.node = Node(node_id=0, anonymous=True) + self._run_id = run_id + self._run: Optional[Run] = None self.state = state_factory.state() + self.node = Node(node_id=0, anonymous=True) def _check_message(self, message: Message) -> None: + self._init_run() # Check if the message is valid if not ( - message.metadata.run_id == self.run_id + message.metadata.run_id == cast(Run, self._run).run_id and message.metadata.src_node_id == self.node.node_id and message.metadata.message_id == "" and message.metadata.reply_to_message == "" @@ -64,16 +62,20 @@ def _check_message(self, message: Message) -> None: ): raise ValueError(f"Invalid message: {message}") - def _get_run_id(self) -> int: - """Return run_id. - - If unset, create a new run. - """ - if self.run_id is None: - self.run_id = self.state.create_run( - fab_id=self.fab_id, fab_version=self.fab_version - ) - return self.run_id + def _init_run(self) -> None: + """Initialize the run.""" + if self._run is not None: + return + run = self.state.get_run(self._run_id) + if run is None: + raise RuntimeError(f"Cannot find the run with ID: {self._run_id}") + self._run = run + + @property + def run(self) -> Run: + """Run ID.""" + self._init_run() + return Run(**vars(cast(Run, self._run))) def create_message( # pylint: disable=too-many-arguments self, @@ -88,7 +90,7 @@ def create_message( # pylint: disable=too-many-arguments This method constructs a new `Message` with given content and metadata. The `run_id` and `src_node_id` will be set automatically. """ - run_id = self._get_run_id() + self._init_run() if ttl: warnings.warn( "A custom TTL was set, but note that the SuperLink does not enforce " @@ -99,7 +101,7 @@ def create_message( # pylint: disable=too-many-arguments ttl_ = DEFAULT_TTL if ttl is None else ttl metadata = Metadata( - run_id=run_id, + run_id=cast(Run, self._run).run_id, message_id="", # Will be set by the server src_node_id=self.node.node_id, dst_node_id=dst_node_id, @@ -112,8 +114,8 @@ def create_message( # pylint: disable=too-many-arguments def get_node_ids(self) -> List[int]: """Get node IDs.""" - run_id = self._get_run_id() - return list(self.state.get_nodes(run_id)) + self._init_run() + return list(self.state.get_nodes(cast(Run, self._run).run_id)) def push_messages(self, messages: Iterable[Message]) -> Iterable[str]: """Push messages to specified node IDs. diff --git a/src/py/flwr/server/driver/inmemory_driver_test.py b/src/py/flwr/server/driver/inmemory_driver_test.py index 95c2a0b277af..eff38f548826 100644 --- a/src/py/flwr/server/driver/inmemory_driver_test.py +++ b/src/py/flwr/server/driver/inmemory_driver_test.py @@ -1,4 +1,4 @@ -# Copyright 2022 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. @@ -31,8 +31,9 @@ message_to_taskres, recordset_to_proto, ) +from flwr.common.typing import Run from flwr.proto.task_pb2 import Task, TaskRes # pylint: disable=E0611 -from flwr.server.superlink.state import StateFactory +from flwr.server.superlink.state import InMemoryState, SqliteState, StateFactory from .inmemory_driver import InMemoryDriver @@ -79,12 +80,24 @@ def setUp(self) -> None: """ # Create driver self.num_nodes = 42 - self.driver = InMemoryDriver(StateFactory("")) - self.driver.state = MagicMock() - self.driver.state.get_nodes.return_value = [ + self.state = MagicMock() + self.state.get_nodes.return_value = [ int.from_bytes(os.urandom(8), "little", signed=True) for _ in range(self.num_nodes) ] + self.state.get_run.return_value = Run( + run_id=61016, fab_id="mock/mock", fab_version="v1.0.0" + ) + state_factory = MagicMock(state=lambda: self.state) + self.driver = InMemoryDriver(run_id=61016, state_factory=state_factory) + self.driver.state = self.state + + def test_get_run(self) -> None: + """Test the InMemoryDriver starting with run_id.""" + # Assert + self.assertEqual(self.driver.run.run_id, 61016) + self.assertEqual(self.driver.run.fab_id, "mock/mock") + self.assertEqual(self.driver.run.fab_version, "v1.0.0") def test_get_nodes(self) -> None: """Test retrieval of nodes.""" @@ -104,7 +117,7 @@ def test_push_messages_valid(self) -> None: ] taskins_ids = [uuid4() for _ in range(num_messages)] - self.driver.state.store_task_ins.side_effect = taskins_ids # type: ignore + self.state.store_task_ins.side_effect = taskins_ids # Execute msg_ids = list(self.driver.push_messages(msgs)) @@ -141,7 +154,7 @@ def test_pull_messages_with_given_message_ids(self) -> None: task=Task(ancestry=[msg_ids[1]], error=error_to_proto(Error(code=0))) ), ] - self.driver.state.get_task_res.return_value = task_res_list # type: ignore + self.state.get_task_res.return_value = task_res_list # Execute pulled_msgs = list(self.driver.pull_messages(msg_ids)) @@ -167,8 +180,8 @@ def test_send_and_receive_messages_complete(self) -> None: task=Task(ancestry=[msg_ids[1]], error=error_to_proto(Error(code=0))) ), ] - self.driver.state.store_task_ins.side_effect = msg_ids # type: ignore - self.driver.state.get_task_res.return_value = task_res_list # type: ignore + self.state.store_task_ins.side_effect = msg_ids + self.state.get_task_res.return_value = task_res_list # Execute ret_msgs = list(self.driver.send_and_receive(msgs)) @@ -193,8 +206,8 @@ def test_send_and_receive_messages_timeout(self) -> None: task=Task(ancestry=[msg_ids[1]], error=error_to_proto(Error(code=0))) ), ] - self.driver.state.store_task_ins.side_effect = msg_ids # type: ignore - self.driver.state.get_task_res.return_value = task_res_list # type: ignore + self.state.store_task_ins.side_effect = msg_ids + self.state.get_task_res.return_value = task_res_list # Execute with patch("time.sleep", side_effect=lambda t: time.sleep(t * 0.01)): @@ -208,19 +221,23 @@ def test_send_and_receive_messages_timeout(self) -> None: def test_task_store_consistency_after_push_pull_sqlitestate(self) -> None: """Test tasks are deleted in sqlite state once messages are pulled.""" # Prepare - self.driver = InMemoryDriver(StateFactory("")) + state = StateFactory("").state() + self.driver = InMemoryDriver( + state.create_run("", ""), MagicMock(state=lambda: state) + ) msg_ids, node_id = push_messages(self.driver, self.num_nodes) + assert isinstance(state, SqliteState) # Check recorded - task_ins = self.driver.state.query("SELECT * FROM task_ins;") # type: ignore + task_ins = state.query("SELECT * FROM task_ins;") self.assertEqual(len(task_ins), len(list(msg_ids))) # Prepare: create replies reply_tos = get_replies(self.driver, msg_ids, node_id) # Query number of task_ins and task_res in State - task_res = self.driver.state.query("SELECT * FROM task_res;") # type: ignore - task_ins = self.driver.state.query("SELECT * FROM task_ins;") # type: ignore + task_res = state.query("SELECT * FROM task_res;") + task_ins = state.query("SELECT * FROM task_ins;") # Assert self.assertEqual(reply_tos, msg_ids) @@ -230,18 +247,19 @@ def test_task_store_consistency_after_push_pull_sqlitestate(self) -> None: def test_task_store_consistency_after_push_pull_inmemory_state(self) -> None: """Test tasks are deleted in in-memory state once messages are pulled.""" # Prepare - self.driver = InMemoryDriver(StateFactory(":flwr-in-memory-state:")) + state_factory = StateFactory(":flwr-in-memory-state:") + state = state_factory.state() + self.driver = InMemoryDriver(state.create_run("", ""), state_factory) msg_ids, node_id = push_messages(self.driver, self.num_nodes) + assert isinstance(state, InMemoryState) # Check recorded - self.assertEqual( - len(self.driver.state.task_ins_store), len(list(msg_ids)) # type: ignore - ) + self.assertEqual(len(state.task_ins_store), len(list(msg_ids))) # Prepare: create replies reply_tos = get_replies(self.driver, msg_ids, node_id) # Assert self.assertEqual(reply_tos, msg_ids) - self.assertEqual(len(self.driver.state.task_res_store), 0) # type: ignore - self.assertEqual(len(self.driver.state.task_ins_store), 0) # type: ignore + self.assertEqual(len(state.task_res_store), 0) + self.assertEqual(len(state.task_ins_store), 0) diff --git a/src/py/flwr/server/history_test.py b/src/py/flwr/server/history_test.py index adb9d697e409..b53357149623 100644 --- a/src/py/flwr/server/history_test.py +++ b/src/py/flwr/server/history_test.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2021 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. diff --git a/src/py/flwr/server/run_serverapp.py b/src/py/flwr/server/run_serverapp.py index efd3f6846264..3505ebfdb0a9 100644 --- a/src/py/flwr/server/run_serverapp.py +++ b/src/py/flwr/server/run_serverapp.py @@ -22,10 +22,13 @@ from typing import Optional from flwr.common import Context, EventType, RecordSet, event +from flwr.common.config import get_flwr_dir, get_project_config, get_project_dir from flwr.common.logger import log, update_console_handler, warn_deprecated_feature from flwr.common.object_ref import load_app +from flwr.proto.driver_pb2 import CreateRunRequest # pylint: disable=E0611 -from .driver import Driver, GrpcDriver +from .driver import Driver +from .driver.grpc_driver import GrpcDriver, GrpcDriverStub from .server_app import LoadServerAppError, ServerApp ADDRESS_DRIVER_API = "0.0.0.0:9091" @@ -41,7 +44,7 @@ def run( if not (server_app_attr is None) ^ (loaded_server_app is None): raise ValueError( "Either `server_app_attr` or `loaded_server_app` should be set " - "but not both. " + "but not both." ) if server_app_dir is not None: @@ -74,7 +77,7 @@ def _load() -> ServerApp: log(DEBUG, "ServerApp finished running.") -def run_server_app() -> None: +def run_server_app() -> None: # pylint: disable=too-many-branches """Run Flower server app.""" event(EventType.RUN_SERVER_APP_ENTER) @@ -134,11 +137,43 @@ def run_server_app() -> None: cert_path, ) - log( - DEBUG, - "Flower will load ServerApp `%s`", - getattr(args, "server-app"), + server_app_attr: Optional[str] = getattr(args, "server-app") + if not (server_app_attr is None) ^ (args.run_id is None): + raise sys.exit( + "Please provide either a ServerApp reference or a Run ID, but not both. " + "For more details, use: ``flower-server-app -h``" + ) + + stub = GrpcDriverStub( + driver_service_address=args.superlink, root_certificates=root_certificates ) + if args.run_id is not None: + # User provided `--run-id`, but not `server-app` + run_id = args.run_id + else: + # User provided `server-app`, but not `--run-id` + # Create run if run_id is not provided + stub.connect() + req = CreateRunRequest(fab_id=args.fab_id, fab_version=args.fab_version) + res = stub.create_run(req) + run_id = res.run_id + + # Initialize GrpcDriver + driver = GrpcDriver(run_id=run_id, stub=stub) + + # Dynamically obtain ServerApp path based on run_id + if args.run_id is not None: + # User provided `--run-id`, but not `server-app` + flwr_dir = get_flwr_dir(args.flwr_dir) + run_ = driver.run + server_app_dir = str(get_project_dir(run_.fab_id, run_.fab_version, flwr_dir)) + config = get_project_config(server_app_dir) + server_app_attr = config["flower"]["components"]["serverapp"] + else: + # User provided `server-app`, but not `--run-id` + server_app_dir = str(Path(args.dir).absolute()) + + log(DEBUG, "Flower will load ServerApp `%s` in %s", server_app_attr, server_app_dir) log( DEBUG, @@ -146,17 +181,6 @@ def run_server_app() -> None: root_certificates, ) - server_app_dir = args.dir - server_app_attr = getattr(args, "server-app") - - # Initialize GrpcDriver - driver = GrpcDriver( - driver_service_address=args.superlink, - root_certificates=root_certificates, - fab_id=args.fab_id, - fab_version=args.fab_version, - ) - # Run the ServerApp with the Driver run(driver=driver, server_app_dir=server_app_dir, server_app_attr=server_app_attr) @@ -174,6 +198,8 @@ def _parse_args_run_server_app() -> argparse.ArgumentParser: parser.add_argument( "server-app", + nargs="?", + default=None, help="For example: `server:app` or `project.package.module:wrapper.app`", ) parser.add_argument( @@ -223,5 +249,22 @@ def _parse_args_run_server_app() -> argparse.ArgumentParser: type=str, help="The version of the FAB used in the run.", ) + parser.add_argument( + "--run-id", + default=None, + type=int, + help="The identifier of the run.", + ) + parser.add_argument( + "--flwr-dir", + default=None, + help="""The path containing installed Flower Apps. + By default, this value is equal to: + + - `$FLWR_HOME/` if `$FLWR_HOME` is defined + - `$XDG_DATA_HOME/.flwr/` if `$XDG_DATA_HOME` is defined + - `$HOME/.flwr/` in all other cases + """, + ) return parser diff --git a/src/py/flwr/server/server_app_test.py b/src/py/flwr/server/server_app_test.py index 38c0d6240d90..0751a0cb2bc5 100644 --- a/src/py/flwr/server/server_app_test.py +++ b/src/py/flwr/server/server_app_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. diff --git a/src/py/flwr/server/strategy/bulyan.py b/src/py/flwr/server/strategy/bulyan.py index 1e4f97530ab7..a81406c255ad 100644 --- a/src/py/flwr/server/strategy/bulyan.py +++ b/src/py/flwr/server/strategy/bulyan.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. diff --git a/src/py/flwr/server/strategy/bulyan_test.py b/src/py/flwr/server/strategy/bulyan_test.py index 299ed49066fb..93a9ebda3783 100644 --- a/src/py/flwr/server/strategy/bulyan_test.py +++ b/src/py/flwr/server/strategy/bulyan_test.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. diff --git a/src/py/flwr/server/strategy/dpfedavg_adaptive.py b/src/py/flwr/server/strategy/dpfedavg_adaptive.py index a908679ed668..423ddddeb379 100644 --- a/src/py/flwr/server/strategy/dpfedavg_adaptive.py +++ b/src/py/flwr/server/strategy/dpfedavg_adaptive.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2022 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. diff --git a/src/py/flwr/server/strategy/dpfedavg_fixed.py b/src/py/flwr/server/strategy/dpfedavg_fixed.py index c54379fc7087..d122f0688922 100644 --- a/src/py/flwr/server/strategy/dpfedavg_fixed.py +++ b/src/py/flwr/server/strategy/dpfedavg_fixed.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2022 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. diff --git a/src/py/flwr/server/strategy/fedadagrad.py b/src/py/flwr/server/strategy/fedadagrad.py index 4a8f52d98e18..f13c5358da25 100644 --- a/src/py/flwr/server/strategy/fedadagrad.py +++ b/src/py/flwr/server/strategy/fedadagrad.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2021 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. diff --git a/src/py/flwr/server/strategy/fedadagrad_test.py b/src/py/flwr/server/strategy/fedadagrad_test.py index 0c966442ecaf..b43a4c75d123 100644 --- a/src/py/flwr/server/strategy/fedadagrad_test.py +++ b/src/py/flwr/server/strategy/fedadagrad_test.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2021 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. diff --git a/src/py/flwr/server/strategy/fedadam.py b/src/py/flwr/server/strategy/fedadam.py index 8a47cf0dd8ac..dc90e90c7568 100644 --- a/src/py/flwr/server/strategy/fedadam.py +++ b/src/py/flwr/server/strategy/fedadam.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2021 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. diff --git a/src/py/flwr/server/strategy/fedavg_android.py b/src/py/flwr/server/strategy/fedavg_android.py index 6678b7ced114..2f49cf8784c9 100644 --- a/src/py/flwr/server/strategy/fedavg_android.py +++ b/src/py/flwr/server/strategy/fedavg_android.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2021 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. diff --git a/src/py/flwr/server/strategy/fedavgm.py b/src/py/flwr/server/strategy/fedavgm.py index fb9261abe89d..ab3d37249db6 100644 --- a/src/py/flwr/server/strategy/fedavgm.py +++ b/src/py/flwr/server/strategy/fedavgm.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2022 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. diff --git a/src/py/flwr/server/strategy/fedavgm_test.py b/src/py/flwr/server/strategy/fedavgm_test.py index a0e942171627..39da5f4b82c4 100644 --- a/src/py/flwr/server/strategy/fedavgm_test.py +++ b/src/py/flwr/server/strategy/fedavgm_test.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2022 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. diff --git a/src/py/flwr/server/strategy/fedmedian.py b/src/py/flwr/server/strategy/fedmedian.py index 17e979d92beb..e7cba5324fa8 100644 --- a/src/py/flwr/server/strategy/fedmedian.py +++ b/src/py/flwr/server/strategy/fedmedian.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2022 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. diff --git a/src/py/flwr/server/strategy/fedmedian_test.py b/src/py/flwr/server/strategy/fedmedian_test.py index 57cf08d8c01d..3960ad70b145 100644 --- a/src/py/flwr/server/strategy/fedmedian_test.py +++ b/src/py/flwr/server/strategy/fedmedian_test.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2022 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. diff --git a/src/py/flwr/server/strategy/fedopt.py b/src/py/flwr/server/strategy/fedopt.py index be5f260d96fa..c581d4797123 100644 --- a/src/py/flwr/server/strategy/fedopt.py +++ b/src/py/flwr/server/strategy/fedopt.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2021 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. diff --git a/src/py/flwr/server/strategy/fedprox.py b/src/py/flwr/server/strategy/fedprox.py index d20f578b193d..f15271e06060 100644 --- a/src/py/flwr/server/strategy/fedprox.py +++ b/src/py/flwr/server/strategy/fedprox.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. diff --git a/src/py/flwr/server/strategy/fedxgb_bagging.py b/src/py/flwr/server/strategy/fedxgb_bagging.py index a8e8adddafbb..a74ee81976a6 100644 --- a/src/py/flwr/server/strategy/fedxgb_bagging.py +++ b/src/py/flwr/server/strategy/fedxgb_bagging.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. diff --git a/src/py/flwr/server/strategy/fedxgb_cyclic.py b/src/py/flwr/server/strategy/fedxgb_cyclic.py index 2605daab29f4..75025a89728b 100644 --- a/src/py/flwr/server/strategy/fedxgb_cyclic.py +++ b/src/py/flwr/server/strategy/fedxgb_cyclic.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. diff --git a/src/py/flwr/server/strategy/fedxgb_nn_avg.py b/src/py/flwr/server/strategy/fedxgb_nn_avg.py index 8dedc925f350..4562663287ae 100644 --- a/src/py/flwr/server/strategy/fedxgb_nn_avg.py +++ b/src/py/flwr/server/strategy/fedxgb_nn_avg.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. diff --git a/src/py/flwr/server/strategy/fedyogi.py b/src/py/flwr/server/strategy/fedyogi.py index 7c77aab7ae73..c7b2ebb51667 100644 --- a/src/py/flwr/server/strategy/fedyogi.py +++ b/src/py/flwr/server/strategy/fedyogi.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2021 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. diff --git a/src/py/flwr/server/strategy/krum.py b/src/py/flwr/server/strategy/krum.py index 16eb5212940e..074d018c35a3 100644 --- a/src/py/flwr/server/strategy/krum.py +++ b/src/py/flwr/server/strategy/krum.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2022 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. diff --git a/src/py/flwr/server/strategy/krum_test.py b/src/py/flwr/server/strategy/krum_test.py index 653dc9a8475d..b34982325b39 100644 --- a/src/py/flwr/server/strategy/krum_test.py +++ b/src/py/flwr/server/strategy/krum_test.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2022 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. diff --git a/src/py/flwr/server/strategy/multikrum_test.py b/src/py/flwr/server/strategy/multikrum_test.py index f874dc2f9800..7a1a4c3ecf38 100644 --- a/src/py/flwr/server/strategy/multikrum_test.py +++ b/src/py/flwr/server/strategy/multikrum_test.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2022 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. diff --git a/src/py/flwr/server/strategy/qfedavg.py b/src/py/flwr/server/strategy/qfedavg.py index 758e8e608e9f..26a397d4cf8c 100644 --- a/src/py/flwr/server/strategy/qfedavg.py +++ b/src/py/flwr/server/strategy/qfedavg.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2021 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. diff --git a/src/py/flwr/server/superlink/driver/__init__.py b/src/py/flwr/server/superlink/driver/__init__.py index 2bfe63e6065f..58fbc479478f 100644 --- a/src/py/flwr/server/superlink/driver/__init__.py +++ b/src/py/flwr/server/superlink/driver/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022 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. diff --git a/src/py/flwr/server/superlink/driver/driver_grpc.py b/src/py/flwr/server/superlink/driver/driver_grpc.py index f74000bc59c4..782935481945 100644 --- a/src/py/flwr/server/superlink/driver/driver_grpc.py +++ b/src/py/flwr/server/superlink/driver/driver_grpc.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. diff --git a/src/py/flwr/server/superlink/driver/driver_servicer.py b/src/py/flwr/server/superlink/driver/driver_servicer.py index e808616af778..03128f02158e 100644 --- a/src/py/flwr/server/superlink/driver/driver_servicer.py +++ b/src/py/flwr/server/superlink/driver/driver_servicer.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. @@ -35,7 +35,11 @@ PushTaskInsResponse, ) from flwr.proto.node_pb2 import Node # pylint: disable=E0611 -from flwr.proto.run_pb2 import GetRunRequest, GetRunResponse # pylint: disable=E0611 +from flwr.proto.run_pb2 import ( # pylint: disable=E0611 + GetRunRequest, + GetRunResponse, + Run, +) from flwr.proto.task_pb2 import TaskRes # pylint: disable=E0611 from flwr.server.superlink.state import State, StateFactory from flwr.server.utils.validator import validate_task_ins_or_res @@ -134,7 +138,15 @@ def GetRun( self, request: GetRunRequest, context: grpc.ServicerContext ) -> GetRunResponse: """Get run information.""" - raise NotImplementedError + log(DEBUG, "DriverServicer.GetRun") + + # Init state + state: State = self.state_factory.state() + + # Retrieve run information + run = state.get_run(request.run_id) + run_proto = None if run is None else Run(**vars(run)) + return GetRunResponse(run=run_proto) def _raise_if(validation_error: bool, detail: str) -> None: diff --git a/src/py/flwr/server/superlink/driver/driver_servicer_test.py b/src/py/flwr/server/superlink/driver/driver_servicer_test.py index 99f7cc007a89..394d6be7ee6a 100644 --- a/src/py/flwr/server/superlink/driver/driver_servicer_test.py +++ b/src/py/flwr/server/superlink/driver/driver_servicer_test.py @@ -1,4 +1,4 @@ -# Copyright 2022 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. diff --git a/src/py/flwr/server/superlink/fleet/__init__.py b/src/py/flwr/server/superlink/fleet/__init__.py index d3c3ef90163d..c236ed06ae1c 100644 --- a/src/py/flwr/server/superlink/fleet/__init__.py +++ b/src/py/flwr/server/superlink/fleet/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022 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. diff --git a/src/py/flwr/server/superlink/fleet/grpc_bidi/__init__.py b/src/py/flwr/server/superlink/fleet/grpc_bidi/__init__.py index bae8bc431edd..6b2c2bf3ffec 100644 --- a/src/py/flwr/server/superlink/fleet/grpc_bidi/__init__.py +++ b/src/py/flwr/server/superlink/fleet/grpc_bidi/__init__.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. diff --git a/src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py b/src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py index 6f94ea844e38..79f1a8f9902b 100644 --- a/src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +++ b/src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.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. diff --git a/src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer_test.py b/src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer_test.py index bd93554a6a32..03e8555f8ecf 100644 --- a/src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer_test.py +++ b/src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer_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. diff --git a/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py b/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py index d5b4a915c609..5fe0396696ab 100644 --- a/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +++ b/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.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. diff --git a/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge_test.py b/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge_test.py index f7c236acd7a1..f9b6b97030f0 100644 --- a/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge_test.py +++ b/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge_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. diff --git a/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py b/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py index ac62ad014950..03497743becd 100644 --- a/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +++ b/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.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. diff --git a/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy_test.py b/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy_test.py index e7077dfd39ae..6d3eb4f67e30 100644 --- a/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy_test.py +++ b/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy_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. diff --git a/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server.py b/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server.py index 6aeaa7ef413f..1b4286c87b92 100644 --- a/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +++ b/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server.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. @@ -29,6 +29,9 @@ ) from flwr.server.client_manager import ClientManager from flwr.server.superlink.driver.driver_servicer import DriverServicer +from flwr.server.superlink.fleet.grpc_adapter.grpc_adapter_servicer import ( + GrpcAdapterServicer, +) from flwr.server.superlink.fleet.grpc_bidi.flower_service_servicer import ( FlowerServiceServicer, ) @@ -154,6 +157,7 @@ def start_grpc_server( # pylint: disable=too-many-arguments def generic_create_grpc_server( # pylint: disable=too-many-arguments servicer_and_add_fn: Union[ Tuple[FleetServicer, AddServicerToServerFn], + Tuple[GrpcAdapterServicer, AddServicerToServerFn], Tuple[FlowerServiceServicer, AddServicerToServerFn], Tuple[DriverServicer, AddServicerToServerFn], ], diff --git a/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server_test.py b/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server_test.py index 8afa37515950..7ff730b17afa 100644 --- a/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server_test.py +++ b/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server_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. diff --git a/src/py/flwr/server/superlink/fleet/grpc_rere/__init__.py b/src/py/flwr/server/superlink/fleet/grpc_rere/__init__.py index 61ab71d91400..03c8ded2423a 100644 --- a/src/py/flwr/server/superlink/fleet/grpc_rere/__init__.py +++ b/src/py/flwr/server/superlink/fleet/grpc_rere/__init__.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. diff --git a/src/py/flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py b/src/py/flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py index 13e024eb31e4..89342a46eb48 100644 --- a/src/py/flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +++ b/src/py/flwr/server/superlink/fleet/grpc_rere/fleet_servicer.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. diff --git a/src/py/flwr/server/superlink/fleet/message_handler/__init__.py b/src/py/flwr/server/superlink/fleet/message_handler/__init__.py index 18b0f11fa6c5..3db0ef5d1611 100644 --- a/src/py/flwr/server/superlink/fleet/message_handler/__init__.py +++ b/src/py/flwr/server/superlink/fleet/message_handler/__init__.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. diff --git a/src/py/flwr/server/superlink/fleet/message_handler/message_handler.py b/src/py/flwr/server/superlink/fleet/message_handler/message_handler.py index dceb18cab453..b70cd54035fe 100644 --- a/src/py/flwr/server/superlink/fleet/message_handler/message_handler.py +++ b/src/py/flwr/server/superlink/fleet/message_handler/message_handler.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. diff --git a/src/py/flwr/server/superlink/fleet/message_handler/message_handler_test.py b/src/py/flwr/server/superlink/fleet/message_handler/message_handler_test.py index c135f6fb7b61..ec521b328eb8 100644 --- a/src/py/flwr/server/superlink/fleet/message_handler/message_handler_test.py +++ b/src/py/flwr/server/superlink/fleet/message_handler/message_handler_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. diff --git a/src/py/flwr/server/superlink/fleet/rest_rere/__init__.py b/src/py/flwr/server/superlink/fleet/rest_rere/__init__.py index a926f9ca0bfc..f24db2a2e12f 100644 --- a/src/py/flwr/server/superlink/fleet/rest_rere/__init__.py +++ b/src/py/flwr/server/superlink/fleet/rest_rere/__init__.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. diff --git a/src/py/flwr/server/superlink/fleet/rest_rere/rest_api.py b/src/py/flwr/server/superlink/fleet/rest_rere/rest_api.py index c7ff496d39bf..1ed67e5eb0aa 100644 --- a/src/py/flwr/server/superlink/fleet/rest_rere/rest_api.py +++ b/src/py/flwr/server/superlink/fleet/rest_rere/rest_api.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. diff --git a/src/py/flwr/server/superlink/fleet/vce/backend/raybackend.py b/src/py/flwr/server/superlink/fleet/vce/backend/raybackend.py index 93aca583af9c..8a21393db590 100644 --- a/src/py/flwr/server/superlink/fleet/vce/backend/raybackend.py +++ b/src/py/flwr/server/superlink/fleet/vce/backend/raybackend.py @@ -15,7 +15,7 @@ """Ray backend for the Fleet API using the Simulation Engine.""" import pathlib -from logging import DEBUG, ERROR, WARNING +from logging import DEBUG, ERROR from typing import Callable, Dict, List, Tuple, Union import ray @@ -24,16 +24,15 @@ from flwr.common.context import Context from flwr.common.logger import log from flwr.common.message import Message -from flwr.simulation.ray_transport.ray_actor import ( - BasicActorPool, - ClientAppActor, - init_ray, -) +from flwr.common.typing import ConfigsRecordValues +from flwr.simulation.ray_transport.ray_actor import BasicActorPool, ClientAppActor from flwr.simulation.ray_transport.utils import enable_tf_gpu_growth from .backend import Backend, BackendConfig ClientResourcesDict = Dict[str, Union[int, float]] +ActorArgsDict = Dict[str, Union[int, float, Callable[[], None]]] +RunTimeEnvDict = Dict[str, Union[str, List[str]]] class RayBackend(Backend): @@ -51,40 +50,29 @@ def __init__( if not pathlib.Path(work_dir).exists(): raise ValueError(f"Specified work_dir {work_dir} does not exist.") - # Init ray and append working dir if needed - runtime_env = ( - self._configure_runtime_env(work_dir=work_dir) if work_dir else None - ) - - if backend_config.get("mute_logging", False): - init_ray( - logging_level=WARNING, log_to_driver=False, runtime_env=runtime_env - ) - elif backend_config.get("silent", False): - init_ray(logging_level=WARNING, log_to_driver=True, runtime_env=runtime_env) - else: - init_ray(runtime_env=runtime_env) + # Initialise ray + self.init_args_key = "init_args" + self.init_ray(backend_config, work_dir) # Validate client resources self.client_resources_key = "client_resources" + client_resources = self._validate_client_resources(config=backend_config) # Create actor pool - use_tf = backend_config.get("tensorflow", False) - actor_kwargs = {"on_actor_init_fn": enable_tf_gpu_growth} if use_tf else {} + actor_kwargs = self._validate_actor_arguments(config=backend_config) - client_resources = self._validate_client_resources(config=backend_config) self.pool = BasicActorPool( actor_type=ClientAppActor, client_resources=client_resources, actor_kwargs=actor_kwargs, ) - def _configure_runtime_env(self, work_dir: str) -> Dict[str, Union[str, List[str]]]: + def _configure_runtime_env(self, work_dir: str) -> RunTimeEnvDict: """Return list of files/subdirectories to exclude relative to work_dir. Without this, Ray will push everything to the Ray Cluster. """ - runtime_env: Dict[str, Union[str, List[str]]] = {"working_dir": work_dir} + runtime_env: RunTimeEnvDict = {"working_dir": work_dir} excludes = [] path = pathlib.Path(work_dir) @@ -125,6 +113,37 @@ def _validate_client_resources(self, config: BackendConfig) -> ClientResourcesDi return client_resources + def _validate_actor_arguments(self, config: BackendConfig) -> ActorArgsDict: + actor_args_config = config.get("actor", False) + actor_args: ActorArgsDict = {} + if actor_args_config: + use_tf = actor_args.get("tensorflow", False) + if use_tf: + actor_args["on_actor_init_fn"] = enable_tf_gpu_growth + return actor_args + + def init_ray(self, backend_config: BackendConfig, work_dir: str) -> None: + """Intialises Ray if not already initialised.""" + if not ray.is_initialized(): + # Init ray and append working dir if needed + runtime_env = ( + self._configure_runtime_env(work_dir=work_dir) if work_dir else None + ) + + ray_init_args: Dict[ + str, + Union[ConfigsRecordValues, RunTimeEnvDict], + ] = {} + + if backend_config.get(self.init_args_key): + for k, v in backend_config[self.init_args_key].items(): + ray_init_args[k] = v + + if runtime_env is not None: + ray_init_args["runtime_env"] = runtime_env + + ray.init(**ray_init_args) + @property def num_workers(self) -> int: """Return number of actors in pool.""" @@ -152,7 +171,7 @@ async def process_message( partition_id = message.metadata.partition_id try: - # Submite a task to the pool + # Submit a task to the pool future = await self.pool.submit( lambda a, a_fn, mssg, cid, state: a.run.remote(a_fn, mssg, cid, state), (app, message, str(partition_id), context), diff --git a/src/py/flwr/server/superlink/fleet/vce/backend/raybackend_test.py b/src/py/flwr/server/superlink/fleet/vce/backend/raybackend_test.py index dcac0b81d666..57c952cc9310 100644 --- a/src/py/flwr/server/superlink/fleet/vce/backend/raybackend_test.py +++ b/src/py/flwr/server/superlink/fleet/vce/backend/raybackend_test.py @@ -38,6 +38,7 @@ ) from flwr.common.object_ref import load_app from flwr.common.recordset_compat import getpropertiesins_to_recordset +from flwr.server.superlink.fleet.vce.backend.backend import BackendConfig from flwr.server.superlink.fleet.vce.backend.raybackend import RayBackend @@ -215,3 +216,35 @@ def test_backend_creation_submit_and_termination_existing_client_app_unsetworkdi workdir="/?&%$^#%@$!", ) self.addAsyncCleanup(self.on_cleanup) + + def test_backend_creation_with_init_arguments(self) -> None: + """Testing whether init args are properly parsed to Ray.""" + backend_config_4: BackendConfig = { + "init_args": {"num_cpus": 4}, + "client_resources": {"num_cpus": 1, "num_gpus": 0}, + } + + backend_config_2: BackendConfig = { + "init_args": {"num_cpus": 2}, + "client_resources": {"num_cpus": 1, "num_gpus": 0}, + } + + RayBackend( + backend_config=backend_config_4, + work_dir="", + ) + nodes = ray.nodes() + + assert nodes[0]["Resources"]["CPU"] == backend_config_4["init_args"]["num_cpus"] + + ray.shutdown() + + RayBackend( + backend_config=backend_config_2, + work_dir="", + ) + nodes = ray.nodes() + + assert nodes[0]["Resources"]["CPU"] == backend_config_2["init_args"]["num_cpus"] + + self.addAsyncCleanup(self.on_cleanup) diff --git a/src/py/flwr/server/superlink/state/__init__.py b/src/py/flwr/server/superlink/state/__init__.py index 7f260d733bbe..9d3bd220403b 100644 --- a/src/py/flwr/server/superlink/state/__init__.py +++ b/src/py/flwr/server/superlink/state/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2023 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. diff --git a/src/py/flwr/server/superlink/state/in_memory_state.py b/src/py/flwr/server/superlink/state/in_memory_state.py index e03260355db9..da9c754c3115 100644 --- a/src/py/flwr/server/superlink/state/in_memory_state.py +++ b/src/py/flwr/server/superlink/state/in_memory_state.py @@ -1,4 +1,4 @@ -# Copyright 2023 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. diff --git a/src/py/flwr/server/superlink/state/sqlite_state.py b/src/py/flwr/server/superlink/state/sqlite_state.py index b9672757b0e6..4df9470ded62 100644 --- a/src/py/flwr/server/superlink/state/sqlite_state.py +++ b/src/py/flwr/server/superlink/state/sqlite_state.py @@ -1,4 +1,4 @@ -# Copyright 2023 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. diff --git a/src/py/flwr/server/superlink/state/sqlite_state_test.py b/src/py/flwr/server/superlink/state/sqlite_state_test.py index 20927df1cf12..10e12da96bd5 100644 --- a/src/py/flwr/server/superlink/state/sqlite_state_test.py +++ b/src/py/flwr/server/superlink/state/sqlite_state_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. diff --git a/src/py/flwr/server/superlink/state/state.py b/src/py/flwr/server/superlink/state/state.py index d1fc9465c9f2..65e2c63cab69 100644 --- a/src/py/flwr/server/superlink/state/state.py +++ b/src/py/flwr/server/superlink/state/state.py @@ -1,4 +1,4 @@ -# Copyright 2022 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. diff --git a/src/py/flwr/server/superlink/state/state_factory.py b/src/py/flwr/server/superlink/state/state_factory.py index 62a00d910828..96c8d445c16e 100644 --- a/src/py/flwr/server/superlink/state/state_factory.py +++ b/src/py/flwr/server/superlink/state/state_factory.py @@ -1,4 +1,4 @@ -# Copyright 2022 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. @@ -26,7 +26,16 @@ class StateFactory: - """Factory class that creates State instances.""" + """Factory class that creates State instances. + + Parameters + ---------- + database : str + A string representing the path to the database file that will be opened. + Note that passing ':memory:' will open a connection to a database that is + in RAM, instead of on disk. For more information on special in-memory + databases, please refer to https://sqlite.org/inmemorydb.html. + """ def __init__(self, database: str) -> None: self.database = database diff --git a/src/py/flwr/server/superlink/state/state_test.py b/src/py/flwr/server/superlink/state/state_test.py index 81307d938400..373202d5cde6 100644 --- a/src/py/flwr/server/superlink/state/state_test.py +++ b/src/py/flwr/server/superlink/state/state_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. diff --git a/src/py/flwr/server/utils/__init__.py b/src/py/flwr/server/utils/__init__.py index c370716adaac..8994374c4d08 100644 --- a/src/py/flwr/server/utils/__init__.py +++ b/src/py/flwr/server/utils/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2021 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. diff --git a/src/py/flwr/server/utils/tensorboard.py b/src/py/flwr/server/utils/tensorboard.py index 3e8d1e62411e..5d38fc159657 100644 --- a/src/py/flwr/server/utils/tensorboard.py +++ b/src/py/flwr/server/utils/tensorboard.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2021 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. diff --git a/src/py/flwr/server/utils/tensorboard_test.py b/src/py/flwr/server/utils/tensorboard_test.py index 1827a42cf6e6..689755c6da16 100644 --- a/src/py/flwr/server/utils/tensorboard_test.py +++ b/src/py/flwr/server/utils/tensorboard_test.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2021 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. diff --git a/src/py/flwr/simulation/__init__.py b/src/py/flwr/simulation/__init__.py index 3d648b14edba..5db90a352e3f 100644 --- a/src/py/flwr/simulation/__init__.py +++ b/src/py/flwr/simulation/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2021 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. diff --git a/src/py/flwr/simulation/app.py b/src/py/flwr/simulation/app.py index 4b4b7249ccd3..856d6fc45e22 100644 --- a/src/py/flwr/simulation/app.py +++ b/src/py/flwr/simulation/app.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2021 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. diff --git a/src/py/flwr/simulation/ray_transport/__init__.py b/src/py/flwr/simulation/ray_transport/__init__.py index 0e82b75bb4b3..ed4971935a15 100644 --- a/src/py/flwr/simulation/ray_transport/__init__.py +++ b/src/py/flwr/simulation/ray_transport/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2021 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. diff --git a/src/py/flwr/simulation/ray_transport/ray_actor.py b/src/py/flwr/simulation/ray_transport/ray_actor.py index 9caf0fc3e6c0..7afffb865334 100644 --- a/src/py/flwr/simulation/ray_transport/ray_actor.py +++ b/src/py/flwr/simulation/ray_transport/ray_actor.py @@ -399,12 +399,6 @@ def get_client_result( return self._fetch_future_result(cid) -def init_ray(*args: Any, **kwargs: Any) -> None: - """Intialises Ray if not already initialised.""" - if not ray.is_initialized(): - ray.init(*args, **kwargs) - - class BasicActorPool: """A basic actor pool.""" 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 5e344eb087ee..d3d103bb377a 100644 --- a/src/py/flwr/simulation/ray_transport/ray_client_proxy.py +++ b/src/py/flwr/simulation/ray_transport/ray_client_proxy.py @@ -1,4 +1,4 @@ -# Copyright 2020 Flower Labs GmbH. All Rights Reserved. +# Copyright 2021 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. diff --git a/src/py/flwr/simulation/run_simulation.py b/src/py/flwr/simulation/run_simulation.py index 3532c5a4e877..7c7a412a245b 100644 --- a/src/py/flwr/simulation/run_simulation.py +++ b/src/py/flwr/simulation/run_simulation.py @@ -22,16 +22,17 @@ import traceback from logging import DEBUG, ERROR, INFO, WARNING from time import sleep -from typing import Dict, Optional +from typing import Optional from flwr.client import ClientApp from flwr.common import EventType, event, log from flwr.common.logger import set_logger_propagation, update_console_handler -from flwr.common.typing import ConfigsRecordValues +from flwr.common.typing import Run from flwr.server.driver import Driver, InMemoryDriver from flwr.server.run_serverapp import run from flwr.server.server_app import ServerApp from flwr.server.superlink.fleet import vce +from flwr.server.superlink.fleet.vce.backend.backend import BackendConfig from flwr.server.superlink.state import StateFactory from flwr.simulation.ray_transport.utils import ( enable_tf_gpu_growth as enable_gpu_growth, @@ -66,7 +67,7 @@ def run_simulation( client_app: ClientApp, num_supernodes: int, backend_name: str = "ray", - backend_config: Optional[Dict[str, ConfigsRecordValues]] = None, + backend_config: Optional[BackendConfig] = None, enable_tf_gpu_growth: bool = False, verbose_logging: bool = False, ) -> None: @@ -90,9 +91,12 @@ def run_simulation( backend_name : str (default: ray) A simulation backend that runs `ClientApp`s. - backend_config : Optional[Dict[str, ConfigsRecordValues]] - 'A dictionary, e.g {"": , "": } to configure a - backend. Values supported in are those included by + backend_config : Optional[BackendConfig] + 'A dictionary to configure a backend. Separate dictionaries to configure + different elements of backend. Supported top-level keys are `init_args` + for values parsed to initialisation of backend, `client_resources` + to define the resources for clients, and `actor` to define the actor + parameters. Values supported in are those included by `flwr.common.typing.ConfigsRecordValues`. enable_tf_gpu_growth : bool (default: False) @@ -104,7 +108,7 @@ def run_simulation( works in the TensorFlow documentation: https://www.tensorflow.org/api/stable. verbose_logging : bool (default: False) - When diabled, only INFO, WARNING and ERROR log messages will be shown. If + When disabled, only INFO, WARNING and ERROR log messages will be shown. If enabled, DEBUG-level logs will be displayed. """ _run_simulation( @@ -133,7 +137,7 @@ def run_serverapp_th( def server_th_with_start_checks( # type: ignore tf_gpu_growth: bool, stop_event: asyncio.Event, **kwargs ) -> None: - """Run SeverApp, after check if GPU memory grouwth has to be set. + """Run SeverApp, after check if GPU memory growth has to be set. Upon exception, trigger stop event for Simulation Engine. """ @@ -169,11 +173,14 @@ def server_th_with_start_checks( # type: ignore return serverapp_th -def _init_run_id(driver: InMemoryDriver, state: StateFactory, run_id: int) -> None: - """Create a run with a given `run_id`.""" +def _override_run_id(state: StateFactory, run_id_to_replace: int, run_id: int) -> None: + """Override the run_id of an existing Run.""" log(DEBUG, "Pre-registering run with id %s", run_id) - state.state().run_ids[run_id] = ("", "") # type: ignore - driver.run_id = run_id + # Remove run + run_info: Run = state.state().run_ids.pop(run_id_to_replace) # type: ignore + # Update with new run_id and insert back in state + run_info.run_id = run_id + state.state().run_ids[run_id] = run_info # type: ignore # pylint: disable=too-many-locals @@ -191,7 +198,7 @@ def _main_loop( ) -> None: """Launch SuperLink with Simulation Engine, then ServerApp on a separate thread. - Everything runs on the main thread or a separate one, depening on whether the main + Everything runs on the main thread or a separate one, depending on whether the main thread already contains a running Asyncio event loop. This is the case if running the Simulation Engine on a Jupyter/Colab notebook. """ @@ -201,11 +208,15 @@ def _main_loop( f_stop = asyncio.Event() serverapp_th = None try: - # Initialize Driver - driver = InMemoryDriver(state_factory) + # Create run (with empty fab_id and fab_version) + run_id_ = state_factory.state().create_run("", "") if run_id: - _init_run_id(driver, state_factory, run_id) + _override_run_id(state_factory, run_id_to_replace=run_id_, run_id=run_id) + run_id_ = run_id + + # Initialize Driver + driver = InMemoryDriver(run_id=run_id_, state_factory=state_factory) # Get and run ServerApp thread serverapp_th = run_serverapp_th( @@ -252,7 +263,7 @@ def _run_simulation( client_app: Optional[ClientApp] = None, server_app: Optional[ServerApp] = None, backend_name: str = "ray", - backend_config: Optional[Dict[str, ConfigsRecordValues]] = None, + backend_config: Optional[BackendConfig] = None, client_app_attr: Optional[str] = None, server_app_attr: Optional[str] = None, app_dir: str = "", @@ -279,9 +290,12 @@ def _run_simulation( backend_name : str (default: ray) A simulation backend that runs `ClientApp`s. - backend_config : Optional[Dict[str, ConfigsRecordValues]] - 'A dictionary, e.g {"":, "":} to configure a - backend. Values supported in are those included by + backend_config : Optional[BackendConfig] + 'A dictionary to configure a backend. Separate dictionaries to configure + different elements of backend. Supported top-level keys are `init_args` + for values parsed to initialisation of backend, `client_resources` + to define the resources for clients, and `actor` to define the actor + parameters. Values supported in are those included by `flwr.common.typing.ConfigsRecordValues`. client_app_attr : str @@ -303,30 +317,34 @@ def _run_simulation( A boolean to indicate whether to enable GPU growth on the main thread. This is desirable if you make use of a TensorFlow model on your `ServerApp` while having your `ClientApp` running on the same GPU. Without enabling this, you - might encounter an out-of-memory error becasue TensorFlow by default allocates + might encounter an out-of-memory error because TensorFlow by default allocates all GPU memory. Read mor about how `tf.config.experimental.set_memory_growth()` works in the TensorFlow documentation: https://www.tensorflow.org/api/stable. verbose_logging : bool (default: False) - When diabled, only INFO, WARNING and ERROR log messages will be shown. If + When disabled, only INFO, WARNING and ERROR log messages will be shown. If enabled, DEBUG-level logs will be displayed. """ if backend_config is None: backend_config = {} + if "init_args" not in backend_config: + backend_config["init_args"] = {} + # Set logging level logger = logging.getLogger("flwr") if verbose_logging: update_console_handler(level=DEBUG, timestamps=True, colored=True) else: - backend_config["silent"] = True + backend_config["init_args"]["logging_level"] = WARNING + backend_config["init_args"]["log_to_driver"] = True if enable_tf_gpu_growth: # Check that Backend config has also enabled using GPU growth - use_tf = backend_config.get("tensorflow", False) + use_tf = backend_config.get("actor", {}).get("tensorflow", False) if not use_tf: log(WARNING, "Enabling GPU growth for your backend.") - backend_config["tensorflow"] = True + backend_config["actor"]["tensorflow"] = True # Convert config to original JSON-stream format backend_config_stream = json.dumps(backend_config) @@ -345,7 +363,7 @@ def _run_simulation( server_app_attr, ) # Detect if there is an Asyncio event loop already running. - # If yes, run everything on a separate thread. In environmnets + # If yes, run everything on a separate thread. In environments # like Jupyter/Colab notebooks, there is an event loop present. run_in_thread = False try: @@ -357,7 +375,7 @@ def _run_simulation( run_in_thread = True except RuntimeError: - log(DEBUG, "No asyncio event loop runnig") + log(DEBUG, "No asyncio event loop running") finally: if run_in_thread: @@ -402,7 +420,8 @@ def _parse_args_run_simulation() -> argparse.ArgumentParser: parser.add_argument( "--backend-config", type=str, - default='{"client_resources": {"num_cpus":2, "num_gpus":0.0}, "tensorflow": 0}', + default='{"client_resources": {"num_cpus":2, "num_gpus":0.0},' + '"actor": {"tensorflow": 0}}', help='A JSON formatted stream, e.g \'{"":, "":}\' to ' "configure a backend. Values supported in are those included by " "`flwr.common.typing.ConfigsRecordValues`. ", diff --git a/src/py/flwr_tool/check_copyright.py b/src/py/flwr_tool/check_copyright.py new file mode 100755 index 000000000000..96870ba67bd0 --- /dev/null +++ b/src/py/flwr_tool/check_copyright.py @@ -0,0 +1,76 @@ +# Copyright 2024 Flower Labs GmbH. All Rights Reserved. +"""Check if copyright notices are present in all Python files. + +Example: + python -m flwr_tool.check_copyright src/py/flwr +""" + + +import os +import subprocess +import sys +from pathlib import Path +from typing import List + +from flwr_tool.init_py_check import get_init_dir_list_and_warnings + +COPYRIGHT_FORMAT = """# Copyright {} 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. +# ==============================================================================""" + + +def _get_file_creation_year(filepath: str) -> str: + result = subprocess.run( + ["git", "log", "--diff-filter=A", "--format=%ai", "--", filepath], + stdout=subprocess.PIPE, + text=True, + check=True, + ) + date_str = result.stdout.splitlines()[-1] # Get the first commit date + creation_year = date_str.split("-")[0] # Extract the year + return creation_year + + +def _check_copyright(dir_list: List[str]) -> None: + warning_list = [] + for valid_dir in dir_list: + if "proto" in valid_dir: + continue + + dir_path = Path(valid_dir) + for py_file in dir_path.glob("*.py"): + creation_year = _get_file_creation_year(str(py_file.absolute())) + expected_copyright = COPYRIGHT_FORMAT.format(creation_year) + + if expected_copyright not in py_file.read_text(): + warning_message = "- " + str(py_file) + warning_list.append(warning_message) + + if len(warning_list) > 0: + print("Missing or incorrect copyright notice in the following files:") + for warning in warning_list: + print(warning) + sys.exit(1) + + +if __name__ == "__main__": + if len(sys.argv) == 0: + raise Exception( # pylint: disable=W0719 + "Please provide at least one directory path relative " + "to your current working directory." + ) + for i, _ in enumerate(sys.argv): + abs_path: str = os.path.abspath(os.path.join(os.getcwd(), sys.argv[i])) + __, init_dirs = get_init_dir_list_and_warnings(abs_path) + _check_copyright(init_dirs) diff --git a/src/py/flwr_tool/fix_copyright.py b/src/py/flwr_tool/fix_copyright.py new file mode 100755 index 000000000000..a5bbbdf616f7 --- /dev/null +++ b/src/py/flwr_tool/fix_copyright.py @@ -0,0 +1,59 @@ +# Copyright 2024 Flower Labs GmbH. All Rights Reserved. +"""Fix copyright notices in all Python files of a given directory. + +Example: + python -m flwr_tool.fix_copyright src/py/flwr +""" + + +import os +import sys +from pathlib import Path +from typing import List + +from flwr_tool.check_copyright import COPYRIGHT_FORMAT, _get_file_creation_year +from flwr_tool.init_py_check import get_init_dir_list_and_warnings + + +def _insert_or_edit_copyright(py_file: Path) -> None: + contents = py_file.read_text() + lines = contents.splitlines() + creation_year = _get_file_creation_year(str(py_file.absolute())) + expected_copyright = COPYRIGHT_FORMAT.format(creation_year) + + if expected_copyright not in contents: + if "Copyright" in lines[0]: + end_index = 0 + for idx, line in enumerate(lines): + if ( + line.strip() + == COPYRIGHT_FORMAT.rsplit("\n", maxsplit=1)[-1].strip() + ): + end_index = idx + 1 + break + lines = lines[end_index:] + + lines.insert(0, expected_copyright) + py_file.write_text("\n".join(lines) + "\n") + + +def _fix_copyright(dir_list: List[str]) -> None: + for valid_dir in dir_list: + if "proto" in valid_dir: + continue + + dir_path = Path(valid_dir) + for py_file in dir_path.glob("*.py"): + _insert_or_edit_copyright(py_file) + + +if __name__ == "__main__": + if len(sys.argv) == 0: + raise Exception( # pylint: disable=W0719 + "Please provide at least one directory path relative " + "to your current working directory." + ) + for i, _ in enumerate(sys.argv): + abs_path: str = os.path.abspath(os.path.join(os.getcwd(), sys.argv[i])) + __, init_dirs = get_init_dir_list_and_warnings(abs_path) + _fix_copyright(init_dirs)