Configurez un ClientApp¶
Flower fournit la capacité d’envoyer des valeurs de configuration aux clients, permettant ainsi un contrôle côté-serveur sur le comportement du client. Cette fonctionnalité permet une ajustement flexible et dynamique des hyperparamètres côté-client, améliorant la collaboration et l’expérimentation.
Sending ConfigRecords to a ClientApp¶
Faites usage d’un ConfigRecord pour envoyer des valeurs de configuration dans un Message à partir de votre ServerApp vers un ClientApp. Un ConfigRecord est un type spécial de dictionnaire Python qui permet la communication de types de base tels que int, float, string, bool et également bytes si vous avez besoin de communiquer des structures de données plus complexes qui doivent être sérialisées. Les listes de ces types sont également prises en charge.
Voyons quelques exemples :
from flwr.app import ConfigRecord
# A config record can hold basic scalars
config = ConfigRecord({"lr": 0.1, "max-local-steps": 20000, "loss-w": [0.1, 0.2]})
# It can also communicate strings and booleans
config = ConfigRecord({"augment": True, "wandb-project-name": "awesome-flower-app"})
Lorsque vous utilisez une stratégie Flower, la manière la plus simple de communiquer votre ConfigRecord comme partie intégrante du Message qui est envoyé vers le ClientApp est en passant par le start de votre stratégie de choix (par exemple, FedAvg). Voyons comment cela ressemble dans le code :
# Create ServerApp
app = ServerApp()
@app.main()
def main(grid: Grid, context: Context) -> None:
"""Main entry point for the ServerApp."""
# ... Read run config, initialize global model, etc
# Initialize FedAvg strategy
strategy = FedAvg()
# Construct the config to be embedded into the Messages that will
# be sent to the ClientApps
config = ConfigRecord({"lr": 0.1, "optim": "adam-w", "augment": True})
# Start strategy, run FedAvg for `num_rounds`
result = strategy.start(
grid=grid,
initial_arrays=arrays,
train_config=config,
num_rounds=10,
)
En passant la valeur ci-dessus ConfigRecord à la méthode start du strategy garantit que l’exacte même ConfigRecord est reçue côté-client. Mais qu’est-ce si nous voulions que la configuration change au cours de la procédure d’apprentissage fédéré ou en fonction des tours ?
Note
Notez que les stratégies Flower insèrent le numéro actuel du tour serveur dans ConfigRecord pour vous sous la clé server-round. De cette façon, le ClientApp sait quel est le tour actuel de la procédure d’apprentissage fédéré. Notez que ceci se produit toujours même si aucune valeur n’est passée à la méthode ConfigRecord du strategy start. Lorsque cela se produit, seul le contenu de la clé server-round avec le numéro correspondant du tour sera reçu côté-client.
Dynamic modification of ConfigRecord¶
Étant donné une valeur ConfigRecord passée lors de l’exécution d’une stratégie (c’est-à-dire passée à la méthode start), les contenus de la clé ConfigRecord qui arrivent au ClientApp ne changeront pas (sauf pour la valeur sous la clé server-round)
Cependant, certaines applications bénéficient ou même nécessitent une certaine dynamique dans les valeurs de configuration que l’on pourrait envoyer vers le ClientApps. Par exemple, la vitesse d’apprentissage que les optimiseurs locaux utilisés au ClientApps font usage. À mesure que les tours d’apprentissage fédéré se succèdent, il est souvent raisonnable de réduire la vitesse d’apprentissage. Cette dynamique peut être introduite à la stratégie en mettant en place une stratégie personnalisée qui simplement surcharge la méthode configure_train. Cette méthode est responsable, entre autres aspects, de créer les Messages qui seront envoyés vers le ClientApps. Ces Messages comporteraient généralement un ArrayRecord portant les paramètres du modèle à fédérer ainsi que le ConfigRecord contenant les configurations que l’on souhaite utiliser. Voyons comment concevoir une stratégie personnalisée qui modifie les ConfigRecord transmis vers la méthode start.
Astuce
Pour en savoir plus sur la façon dont les configure_train et d’autres méthodes dans les stratégies fonctionnent, consultez le Strategies Explainer.
Créons une nouvelle classe héritant de FedAvg et surchargons la méthode configure_train. Nous utilisons ensuite cette nouvelle stratégie dans notre ServerApp.
from typing import Iterable
from flwr.serverapp import Grid
from flwr.serverapp.strategy import FedAvg
from flwr.app import ArrayRecord, ConfigRecord, Message
class CustomFedAdagrad(FedAvg):
def configure_train(
self, server_round: int, arrays: ArrayRecord, config: ConfigRecord, grid: Grid
) -> Iterable[Message]:
"""Configure the next round of federated training and maybe do LR decay."""
# Decrease learning rate by a factor of 0.5 every 5 rounds
# Note: server_round starts at 1, not 0
if server_round % 5 == 0:
config["lr"] *= 0.5
print("LR decreased to:", config["lr"])
# Pass the updated config and the rest of arguments to the parent class
return super().configure_train(server_round, arrays, config, grid)
Dans ce guide pratique, nous avons montré comment définir (lorsque l’on appelle la méthode start de la stratégie) et modifier (en surchargeant la méthode configure_train) un ConfigRecord pour personnaliser la façon dont les ClientApps effectuent des entraînements. Vous pouvez suivre les mêmes étapes pour définir et personnaliser le ConfigRecord pour une ronde d’évaluation. Pour cela, utilisez l’argument evaluate_config dans la méthode start de la stratégie et surchargez ensuite éventuellement la méthode configure_evaluate.