From 1204920654b020618ef9c9c1384a4b17faa0255f Mon Sep 17 00:00:00 2001 From: jafermarq Date: Fri, 20 Sep 2024 18:41:36 +0100 Subject: [PATCH] updated readme and pyproject.toml --- examples/advanced-pytorch-low-level/README.md | 25 +++++++++++++----- .../_static/fmnist_50_lda.png | Bin 0 -> 33801 bytes .../advanced-pytorch-low-level/pyproject.toml | 5 ++-- 3 files changed, 22 insertions(+), 8 deletions(-) create mode 100644 examples/advanced-pytorch-low-level/_static/fmnist_50_lda.png diff --git a/examples/advanced-pytorch-low-level/README.md b/examples/advanced-pytorch-low-level/README.md index 7158f9f8ec44..95d102f79526 100644 --- a/examples/advanced-pytorch-low-level/README.md +++ b/examples/advanced-pytorch-low-level/README.md @@ -1,7 +1,13 @@ -# Federated Learning with PyTorch and Flower (Low level API) +--- +tags: [advanced, vision, fds, wandb, low-level] +dataset: [Fashion-MNIST] +framework: [torch, torchvision] +--- + +# Federated Learning with PyTorch and Flower (Advanced Example with Low level API) > \[!CAUTION\] -> This example uses Flower's low-level API which is a preview feature and subject to change. +> This example uses Flower's low-level API which is a preview feature and subject to change. If you are not ready for the low-level API, the [advanced-pytorch](https://github.com/adap/flower/tree/main/examples/advanced-pytorch) example demonstrates near identical functionality but using higher level components such as Flower's _Strategies_ and _NumPyClient_. This example demonstrates how to use Flower's low-level API to write a `ServerApp` a _"for loop"_, enabling you to define what a "round" means and construct [Message](https://flower.ai/docs/framework/ref-api/flwr.common.Message.html) objects to communicate arbitrary data structures as [RecordSet](https://flower.ai/docs/framework/ref-api/flwr.common.RecordSet.html) objects. Just like the the counterpart to this example using the strategies API (find it in the parent directory), it: @@ -11,16 +17,23 @@ This example demonstrates how to use Flower's low-level API to write a `ServerAp 4. Implement a simple decaying learning rate schedule across rounds > \[!NOTE\] -> The code in this example is particularly rich in comments, but the code itself is intended to be easy to follow. Note that in `task.py` you'll make use of many of the same components (model, train/evaluate functions, data loaders) as were first presented in the [pytorch-example](https://github.com/adap/flower/tree/main/examples/advanced-pytorch/pytorch-example) in the parent directory that uses strategies. +> The code in this example is particularly rich in comments, but the code itself is intended to be easy to follow. Note that in `task.py` you'll make use of many of the same components (model, train/evaluate functions, data loaders) as were first presented in the [advanced-pytorch](https://github.com/adap/flower/tree/main/examples/advanced-pytorch/pytorch-example) in the parent directory that uses strategies. + +This examples uses [Flower Datasets](https://flower.ai/docs/datasets/) with the [Dirichlet Partitioner](https://flower.ai/docs/datasets/ref-api/flwr_datasets.partitioner.DirichletPartitioner.html#flwr_datasets.partitioner.DirichletPartitioner) to partition the [Fashion-MNIST](https://huggingface.co/datasets/zalando-datasets/fashion_mnist) dataset in a non-IID fashion into 50 partitions. + +![](_static/fmnist_50_lda.png) + +> \[!TIP\] +> You can use Flower Datasets [built-in visualization tools](https://flower.ai/docs/datasets/tutorial-visualize-label-distribution.html) to easily generate plots like the one above. ```shell -pytorch-pytorch-low-level +advanced-pytorch-low-level ├── pytorch_example_low_level │ ├── __init__.py │ ├── client_app.py # Defines your ClientApp │ ├── server_app.py # Defines your ServerApp -│ ├── utils.py # Defines utility functions -│ └── task.py # Defines your model, training and data loading +│ ├── task.py # Defines your model, training and data loading +│ └── utils.py # Defines utility functions ├── pyproject.toml # Project metadata like dependencies and configs └── README.md ``` diff --git a/examples/advanced-pytorch-low-level/_static/fmnist_50_lda.png b/examples/advanced-pytorch-low-level/_static/fmnist_50_lda.png new file mode 100644 index 0000000000000000000000000000000000000000..9dfedc59a3de86c3670f0a6ab1175dcef15fd04c GIT binary patch literal 33801 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 vf`1Cs{~N=1.11.0", + "flwr[simulation]>=1.11.1", "flwr-datasets[vision]>=0.3.0", "torch==2.2.1", "torchvision==0.17.1", + "wandb==0.17.8", ] [tool.hatch.build.targets.wheel]