Add an algorithm to fluke

Introduction

In this section, we will show how to add a new algorithm to be used in fluke.

Attention

This page will go into the details of the implementation of the server, the client, and the federated learning algorithm. For a gentle introduction, please refer to New federated algorithm with fluke tutorial.

When a new federated learning algorithm is defined, its functioning can be described by detailing the behavior of the server and the clients. This is exactly what you need to do to add a new algorithm to be used in fluke. You must define:

You are not obliged to redefine both the server and the client classes, it depends on the algorithm you want to implement. For example, if your algorithm only differs from the standard FedAvg only in the way the clients behave, you only need to redefine the client class.

After having defined the server and the client classes, you must define the class representing the federated learning algorithm itself. This class must inherit from the CentralizedFL class and it is responsible for the initialization of the server and the clients. There is no much more to it, as the actual execution of the algorithm is delegated to the server. However, you must override the following methods:

  • get_client_class: this method must return the client class you defined (if any);

  • get_server_class: this method must return the server class you defined (if any).

As pointed out before, only one of the two methods can be overridden according to the needs of the algorithm you are implementing.

The details of the implementation of the server, the client, and the federated learning algorithm are provided in the following sections:

Running your algorithm using fluke

Using the fluke CLI to run your algorithm is as easy as changing a few lines in the configuration file of the algorithm. Let’s assume to have defined our algorithm in a python file named my_algorithm.py and that the class representing the algorithm is named MyAlgorithm. The configuration file of the algorithm must be structured as follows (please make sure to run fluke from the right directory):

 1# THIS IS KEY
 2# The name of the algorithm must be the fully qualified name to the algorithm's class
 3name: my_algorithm.MyAlgorithm
 4# Please refer to the algorithm's implementation to know which are its HPs
 5hyperparameters:
 6   # HPs of the clients
 7   client:
 8      batch_size: 10 # only an example
 9      local_epochs: 5 # only an example
10      loss: CrossEntropyLoss # only an example
11      # Your client-side extra hyper-parameters (if any)
12      hyperparam1: value1
13      hyperparam2: value2
14      ...
15      optimizer:
16         ...
17      scheduler:
18         ...
19   server:
20      # Your server-side hyper-parameters (if any)
21      hyperparam1: value1
22      hyperparam2: value2
23      ...
24model: ...
 1from fluke.algorithms import CentralizedFL
 2from typing import Iterable
 3from fluke.client import Client
 4from fluke.server import Server
 5import numpy as np
 6
 7
 8class MyServer(Server):
 9
10   # we override the aggregate method to implement our aggregation strategy
11   def aggregate(self, eligible: Iterable[Client]) -> None:
12      # eligible is a list of clients that participated in the last round
13      # here we randomly select only two of them
14
15      selected = np.random.choice(eligible, 2, replace=False)
16
17      # we call the parent class method to aggregate the selected clients
18      return super().aggregate(selected)
19
20
21class MyClient(Client):
22
23   # we override the fit method to implement our training "strategy"
24   def fit(self, override_local_epochs: int = 0) -> float:
25      # we can override the number of local epochs and call the parent class method
26      new_local_epochs = np.random.randint(1, self.hyper_params.local_epochs + 1)
27      return super().fit(new_local_epochs)
28
29
30class MyFLAlgorithm(CentralizedFL):
31
32   def get_client_class(self) -> Client:
33      return MyClient
34
35   def get_server_class(self) -> Server:
36      return MyServer