Article
federated-learningflower-frameworkpythonmachine-learningdata-privacydistributed-trainingtensorflow
Build a Federated Learning System with Python and Flower
Implement a basic Federated Learning system using the Flower framework. This guide shows you how to train a single machine learning model across two simulated clients without sharing their local data, demonstrating the core principles of privacy-preserving AI.
intermediate30 min4 steps
The play
- Install DependenciesSet up your Python environment by installing Flower and a machine learning framework like TensorFlow. Flower orchestrates the federated process, and TensorFlow will be used to define and train the local models on each client.
- Define the ML Model and DataCreate a simple Keras model and generate dummy datasets for two clients. In a real-world Federated Learning scenario, this data would reside on separate devices and never be moved to a central location.
- Create a Flower ClientImplement a Flower client class. This class wraps your local model and data, defining how it trains (fit), evaluates (evaluate), and communicates model weight updates with the central server.
- Start the Federated Learning SimulationUse Flower's simulation engine to start the Federated Learning process. The server will coordinate multiple training rounds. In each round, it sends the global model to clients, they train it on their local data, and send their updates back for aggregation.
Starter code
import flwr as fl
import tensorflow as tf
import numpy as np
from typing import Tuple, Dict, List
# 1. Define a simple model and compile it
model = tf.keras.models.Sequential([
tf.keras.layers.Dense(10, activation='relu', input_shape=(10,)),
tf.keras.layers.Dense(1, activation='sigmoid')
])
model.compile("adam", "binary_crossentropy", metrics=["accuracy"])
# 2. Create dummy datasets for two clients
# In a real scenario, this data would be on separate devices.
(x_train_1, y_train_1) = (np.random.rand(100, 10).astype(np.float32), np.random.randint(0, 2, 100))
(x_train_2, y_train_2) = (np.random.rand(100, 10).astype(np.float32), np.random.randint(0, 2, 100))
client_data = { "0": (x_train_1, y_train_1), "1": (x_train_2, y_train_2) }
# 3. Define the Flower client
class FlowerClient(fl.client.NumPyClient):
def __init__(self, model, x_train, y_train):
self.model = model
self.x_train, self.y_train = x_train, y_train
def get_parameters(self, config: Dict[str, str]) -> List[np.ndarray]:
# Return the current local model weights
return self.model.get_weights()
def fit(self, parameters: List[np.ndarray], config: Dict[str, str]) -> Tuple[List[np.ndarray], int, Dict]:
# Set the local model weights from the server
self.model.set_weights(parameters)
# Train the model on local data
self.model.fit(self.x_train, self.y_train, epochs=1, batch_size=32, verbose=0)
# Return the updated model weights, number of examples, and an empty metrics dict
return self.model.get_weights(), len(self.x_train), {}
def evaluate(self, parameters: List[np.ndarray], config: Dict[str, str]) -> Tuple[float, int, Dict]:
# Set the local model weights from the server
self.model.set_weights(parameters)
# Evaluate the model on local data
loss, accuracy = self.model.evaluate(self.x_train, self.y_train, verbose=0)
# Return the loss, number of examples, and accuracy metric
return float(loss), len(self.x_train), {"accuracy": float(accuracy)}
# 4. Define a function to instantiate a client for a given ID
def client_fn(cid: str) -> FlowerClient:
# Get the data for the client ID
x_train, y_train = client_data[cid]
# Create and return a new client
return FlowerClient(model, x_train, y_train)
# 5. Start the simulation
print("Starting Federated Learning simulation...")
history = fl.simulation.start_simulation(
client_fn=client_fn,
num_clients=2, # Number of clients to simulate
config=fl.server.ServerConfig(num_rounds=3), # Number of training rounds
strategy=fl.server.strategy.FedAvg(), # Aggregation strategy
)
print("Simulation finished.")
print(f"Aggregated loss: {history.losses_distributed}")