Use strategies¶

Flower allows full customization of the learning process through the Strategy abstraction. A number of built-in strategies are provided in the core framework.

There are three ways to customize the way Flower orchestrates the learning process on the server side:

  • Use an existing strategy, for example, FedAvg

  • Customize an existing strategy with callback functions

  • Implement a novel strategy

Use an existing strategy¶

Flower comes with a number of popular federated learning Strategies which can be instantiated as follows:

from flwr.common import Context
from flwr.server.strategy import FedAvg
from flwr.server import ServerApp, ServerAppComponents, ServerConfig


def server_fn(context: Context):
    # Optional context-based parameters specification
    num_rounds = context.run_config["num-server-rounds"]
    config = ServerConfig(num_rounds=num_rounds)

    # Instantiate FedAvg strategy
    strategy = FedAvg(
        fraction_fit=context.run_config["fraction-fit"],
        fraction_evaluate=1.0,
    )

    # Create and return ServerAppComponents
    return ServerAppComponents(strategy=strategy, config=config)


# Create ServerApp
app = ServerApp(server_fn=server_fn)

To make the ServerApp use this strategy, pass a server_fn function to the ServerApp constructor. The server_fn function should return a ServerAppComponents object that contains the strategy instance and a ServerConfig instance.

Both Strategy and ServerConfig classes can be configured with parameters. The Context object passed to server_fn contains the values specified in the [tool.flwr.app.config] table in your pyproject.toml (a snippet is shown below). To access these values, use context.run_config.

# ...

[tool.flwr.app.config]
num-server-rounds = 10
fraction-fit = 0.5

# ...

Customize an existing strategy with callback functions¶

Existing strategies provide several ways to customize their behavior. Callback functions allow strategies to call user-provided code during execution. This approach enables you to modify the strategy’s partial behavior without rewriting the whole class from zero.

Configuring client fit and client evaluate¶

The server can pass new configuration values to the client each round by providing a function to on_fit_config_fn. The provided function will be called by the strategy and must return a dictionary of configuration key value pairs that will be sent to the client. It must return a dictionary of arbitrary configuration values client.fit and client.evaluate functions during each round of federated learning.

from flwr.common import Context
from flwr.server.strategy import FedAvg
from flwr.server import ServerApp, ServerAppComponents, ServerConfig


def get_on_fit_config_fn() -> Callable[[int], Dict[str, str]]:
    """Return a function which returns training configurations."""

    def fit_config(server_round: int) -> Dict[str, str]:
        """Return a configuration with static batch size and (local) epochs."""
        config = {
            "learning_rate": str(0.001),
            "batch_size": str(32),
        }
        return config

    return fit_config


def server_fn(context: Context):
    # Read num_rounds from context
    num_rounds = context.run_config["num-server-rounds"]
    config = ServerConfig(num_rounds=num_rounds)

    # Instantiate FedAvg strategy
    strategy = FedAvg(
        fraction_fit=context.run_config["fraction-fit"],
        fraction_evaluate=1.0,
        on_fit_config_fn=get_on_fit_config_fn(),
    )

    # Create and return ServerAppComponents
    return ServerAppComponents(strategy=strategy, config=config)


# Create ServerApp
app = ServerApp(server_fn=server_fn)

The 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 on_fit_config_fn in its own client.fit() function. And while the values can be also passed directly via the context this function can be a place to implement finer control over the fit behaviour that may not be achieved by the context, which sets fixed values.

Similar to on_fit_config_fn, there is also on_evaluate_config_fn to customize the configuration sent to client.evaluate()

Configuring server-side evaluation¶

Server-side evaluation can be enabled by passing an evaluation function to evaluate_fn.

Implement a novel strategy¶

Writing a fully custom strategy is a bit more involved, but it provides the most flexibility. Read the Implementing Strategies guide to learn more.