Skip to content

Commit

Permalink
Merge branch 'main' into doc/docker-improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert-Steiner authored Oct 23, 2024
2 parents 34bd99c + 76e1c28 commit 5dd6817
Show file tree
Hide file tree
Showing 56 changed files with 711 additions and 475 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,12 @@ jobs:
python -m pip install "${WHEEL_URL}"
fi
- name: >
Run SuperExec test /
Run Exec API test /
${{ matrix.connection }} /
${{ matrix.authentication }} /
${{ matrix.engine }}
working-directory: e2e/${{ matrix.directory }}
run: ./../test_superexec.sh "${{ matrix.connection }}" "${{ matrix.authentication}}" "${{ matrix.engine }}"
run: ./../test_exec_api.sh "${{ matrix.connection }}" "${{ matrix.authentication}}" "${{ matrix.engine }}"
frameworks:
runs-on: ubuntu-22.04
Expand Down
2 changes: 1 addition & 1 deletion datasets/doc/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
author = "The Flower Authors"

# The full version, including alpha/beta/rc tags
release = "0.3.0"
release = "0.4.0"


# -- General configuration ---------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion datasets/doc/source/how-to-install-flwr-datasets.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,5 @@ If everything worked, it should print the version of Flower Datasets to the comm

.. code-block:: none
0.3.0
0.4.0
2 changes: 1 addition & 1 deletion datasets/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"

[tool.poetry]
name = "flwr-datasets"
version = "0.3.0"
version = "0.4.0"
description = "Flower Datasets"
license = "Apache-2.0"
authors = ["The Flower Authors <[email protected]>"]
Expand Down
2 changes: 1 addition & 1 deletion doc/source/docker/enable-tls.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ For example, to change the user ID of all files in the ``certificates/`` directo
can run ``sudo chown -R 49999:49999 certificates/*``.

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``.
current user ID by running ``sudo chown -R $USER:$(id -gn) certificates``.

SuperLink
---------
Expand Down
34 changes: 16 additions & 18 deletions e2e/test_superexec.sh → e2e/test_exec_api.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@ case "$1" in
--ssl-certfile ../certificates/server.pem
--ssl-keyfile ../certificates/server.key'
client_arg='--root-certificates ../certificates/ca.crt'
# For $superexec_arg, note special ordering of single- and double-quotes
superexec_arg='--executor-config 'root-certificates=\"../certificates/ca.crt\"''
superexec_arg="$server_arg $superexec_arg"
# For $executor_config, note special ordering of single- and double-quotes
executor_config='root-certificates="../certificates/ca.crt"'
;;
insecure)
server_arg='--insecure'
client_arg=$server_arg
superexec_arg=$server_arg
executor_config=''
;;
esac

Expand All @@ -43,11 +42,11 @@ esac
# Set engine
case "$3" in
deployment-engine)
superexec_engine_arg='--executor flwr.superexec.deployment:executor'
executor_arg="--executor flwr.superexec.deployment:executor"
;;
simulation-engine)
superexec_engine_arg='--executor flwr.superexec.simulation:executor
--executor-config 'num-supernodes=10''
executor_config="$executor_config num-supernodes=10"
executor_arg="--executor flwr.superexec.simulation:executor"
;;
esac

Expand All @@ -69,14 +68,17 @@ pip install -e . --no-deps
# Check if the first argument is 'insecure'
if [ "$1" == "insecure" ]; then
# If $1 is 'insecure', append the first line
echo -e $"\n[tool.flwr.federations.superexec]\naddress = \"127.0.0.1:9093\"\ninsecure = true" >> pyproject.toml
echo -e $"\n[tool.flwr.federations.e2e]\naddress = \"127.0.0.1:9093\"\ninsecure = true" >> pyproject.toml
else
# Otherwise, append the second line
echo -e $"\n[tool.flwr.federations.superexec]\naddress = \"127.0.0.1:9093\"\nroot-certificates = \"../certificates/ca.crt\"" >> pyproject.toml
echo -e $"\n[tool.flwr.federations.e2e]\naddress = \"127.0.0.1:9093\"\nroot-certificates = \"../certificates/ca.crt\"" >> pyproject.toml
fi

timeout 2m flower-superlink $server_arg $server_auth &
sl_pid=$!
# Combine the arguments into a single command for flower-superlink
combined_args="$server_arg $server_auth $exec_api_arg $executor_arg"

timeout 2m flower-superlink $combined_args --executor-config "$executor_config" 2>&1 | tee flwr_output.log &
sl_pid=$(pgrep -f "flower-superlink")
sleep 2

timeout 2m flower-supernode ./ $client_arg \
Expand All @@ -91,11 +93,7 @@ timeout 2m flower-supernode ./ $client_arg \
cl2_pid=$!
sleep 2

timeout 2m flower-superexec $superexec_arg $superexec_engine_arg 2>&1 | tee flwr_output.log &
se_pid=$(pgrep -f "flower-superexec")
sleep 2

timeout 1m flwr run --run-config num-server-rounds=1 ../e2e-tmp-test superexec
timeout 1m flwr run --run-config num-server-rounds=1 ../e2e-tmp-test e2e

# Initialize a flag to track if training is successful
found_success=false
Expand All @@ -107,7 +105,7 @@ while [ "$found_success" = false ] && [ $elapsed -lt $timeout ]; do
if grep -q "Run finished" flwr_output.log; then
echo "Training worked correctly!"
found_success=true
kill $cl1_pid; kill $cl2_pid; sleep 1; kill $sl_pid; kill $se_pid;
kill $cl1_pid; kill $cl2_pid; sleep 1; kill $sl_pid;
else
echo "Waiting for training ... ($elapsed seconds elapsed)"
fi
Expand All @@ -118,5 +116,5 @@ done

if [ "$found_success" = false ]; then
echo "Training had an issue and timed out."
kill $cl1_pid; kill $cl2_pid; kill $sl_pid; kill $se_pid;
kill $cl1_pid; kill $cl2_pid; kill $sl_pid;
fi
2 changes: 1 addition & 1 deletion e2e/test_superlink.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ case "$2" in
rest)
rest_arg_superlink="--fleet-api-type rest"
rest_arg_supernode="--rest"
server_address="http://localhost:9093"
server_address="http://localhost:9095"
server_app_address="127.0.0.1:9091"
db_arg="--database :flwr-in-memory-state:"
server_auth=""
Expand Down
90 changes: 36 additions & 54 deletions examples/quickstart-jax/README.md
Original file line number Diff line number Diff line change
@@ -1,85 +1,67 @@
---
tags: [quickstart, linear regression]
dataset: [Synthetic]
framework: [JAX]
framework: [JAX, FLAX]
---

# JAX: From Centralized To Federated
# Federated Learning with JAX and Flower (Quickstart Example)

This example demonstrates how an already existing centralized JAX-based machine learning project can be federated with Flower.
This introductory example to Flower uses JAX, but deep knowledge of JAX is not necessarily required to run the example. However, it will help you understand how to adapt Flower to your use case. Running this example in itself is quite easy. This example uses [FLAX](https://flax.readthedocs.io/en/latest/index.html) to define and train a small CNN model. This example uses [Flower Datasets](https://flower.ai/docs/datasets/) to download, partition and preprocess the MINST dataset.

This introductory example for Flower uses JAX, but you're not required to be a JAX expert to run the example. The example will help you to understand how Flower can be used to build federated learning use cases based on an existing JAX project.
## Set up the project

## Project Setup
### Clone the project

Start by cloning the example project. We prepared a single-line command that you can copy into your shell which will checkout the example for you:
Start by cloning the example project:

```shell
git clone --depth=1 https://github.com/adap/flower.git && mv flower/examples/quickstart-jax . && rm -rf flower && cd quickstart-jax
git clone --depth=1 https://github.com/adap/flower.git _tmp \
&& mv _tmp/examples/quickstart-jax . \
&& rm -rf _tmp \
&& cd quickstart-jax
```

This will create a new directory called `quickstart-jax`, containing the following files:
This will create a new directory called `quickstart-jax` with the following structure:

```shell
-- pyproject.toml
-- requirements.txt
-- jax_training.py
-- client.py
-- server.py
-- README.md
quickstart-jax
├── jaxexample
│ ├── __init__.py
│ ├── client_app.py # Defines your ClientApp
│ ├── server_app.py # Defines your ServerApp
│ └── task.py # Defines your model, training and data loading
├── pyproject.toml # Project metadata like dependencies and configs
└── README.md
```

### Installing Dependencies
### Install dependencies and project

Project dependencies (such as `jax` and `flwr`) are defined in `pyproject.toml` and `requirements.txt`. We recommend [Poetry](https://python-poetry.org/docs/) to install those dependencies and manage your virtual environment ([Poetry installation](https://python-poetry.org/docs/#installation)) or [pip](https://pip.pypa.io/en/latest/development/), but feel free to use a different way of installing dependencies and managing virtual environments if you have other preferences.
Install the dependencies defined in `pyproject.toml` as well as the `jaxexample` package.

#### Poetry

```shell
poetry install
poetry shell
```

Poetry will install all your dependencies in a newly created virtual environment. To verify that everything works correctly you can run the following command:

```shell
poetry run python3 -c "import flwr"
```

If you don't see any errors you're good to go!

#### pip

Write the command below in your terminal to install the dependencies according to the configuration file requirements.txt.

```shell
pip install -r requirements.txt
```bash
pip install -e .
```

## Run JAX Federated
## Run the project

This JAX example is based on the [Linear Regression with JAX](https://coax.readthedocs.io/en/latest/examples/linear_regression/jax.html) tutorial and uses a sklearn dataset (generating a random dataset for a regression problem). Feel free to consult the tutorial if you want to get a better understanding of JAX. If you play around with the dataset, please keep in mind that the data samples are generated randomly depending on the settings being done while calling the dataset function. Please checkout out the [scikit-learn tutorial for further information](https://scikit-learn.org/stable/modules/generated/sklearn.datasets.make_regression.html). The file `jax_training.py` contains all the steps that are described in the tutorial. It loads the train and test dataset and a linear regression model, trains the model with the training set, and evaluates the trained model on the test set.
You can run your Flower project in both _simulation_ and _deployment_ mode without making changes to the code. If you are starting with Flower, we recommend you using the _simulation_ mode as it requires fewer components to be launched manually. By default, `flwr run` will make use of the Simulation Engine.

The only things we need are a simple Flower server (in `server.py`) and a Flower client (in `client.py`). The Flower client basically takes model and training code tells Flower how to call it.
### Run with the Simulation Engine

Start the server in a terminal as follows:

```shell
python3 server.py
```bash
flwr run .
```

Now that the server is running and waiting for clients, we can start two clients that will participate in the federated learning process. To do so simply open two more terminal windows and run the following commands.
You can also override some of the settings for your `ClientApp` and `ServerApp` defined in `pyproject.toml`. For example:

Start client 1 in the first terminal:

```shell
python3 client.py
```bash
flwr run . --run-config "num-server-rounds=5 batch-size=32"
```

Start client 2 in the second terminal:
> \[!TIP\]
> For a more detailed walk-through check our [quickstart JAX tutorial](https://flower.ai/docs/framework/tutorial-quickstart-jax.html)
```shell
python3 client.py
```
### Run with the Deployment Engine

You are now training a JAX-based linear regression model, federated across two clients. The setup is of course simplified since both clients hold a similar dataset, but you can now continue with your own explorations. How about changing from a linear regression to a more sophisticated model? How about adding more clients?
> \[!NOTE\]
> An update to this example will show how to run this Flower application with the Deployment Engine and TLS certificates, or with Docker.
54 changes: 0 additions & 54 deletions examples/quickstart-jax/client.py

This file was deleted.

74 changes: 0 additions & 74 deletions examples/quickstart-jax/jax_training.py

This file was deleted.

1 change: 1 addition & 0 deletions examples/quickstart-jax/jaxexample/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""jaxexample: A Flower / JAX app."""
Loading

0 comments on commit 5dd6817

Please sign in to comment.