Développement d’un Swarm

Introduction

Dans la plateforme Manta, le développement de Swarm permet aux utilisateurs de créer des algorithmes décentralisés et collaboratifs, distribués sur plusieurs nœuds. Un Swarm se compose de diverses tâches définies par l’utilisateur, exécutées de manière collaborative sur les nœuds. Le Manta Core fournit les outils et abstractions nécessaires pour développer, déployer et surveiller efficacement ces Swarms, permettant l’exécution fluide de workflows complexes et distribués.

Qu’est-ce qu’un Swarm ?

Swarm Swarm

Un Swarm est un pipeline décentralisé composé de tâches interconnectées qui s’exécutent de manière collaborative sur des nœuds dans un système distribué. Chaque Swarm définit une séquence d’opérations, organisées en tâches, qui réalisent collectivement un algorithme plus complexe. La caractéristique principale d’un Swarm est sa capacité à définir une itération qui se répète jusqu’à ce qu’une condition ou un critère d’achèvement soit atteint. Cette approche itérative permet un traitement continu et un raffinement des données à travers plusieurs étapes.

Composants d’un Swarm :

  • Tâches : Les éléments de base d’un Swarm, chaque tâche exécute une opération ou un calcul spécifique. Les tâches peuvent dépendre les unes des autres, permettant ainsi de construire des workflows complexes.

  • Dépendances : Les tâches au sein d’un Swarm peuvent être interconnectées via des dépendances définies, créant un graphe orienté d’opérations. Ces dépendances contrôlent le flux de données et l’ordre d’exécution entre les tâches.

  • Cycle d’itération : Un Swarm est conçu pour fonctionner en cycles, où les tâches définies sont exécutées de manière répétée jusqu’à ce que le Swarm atteigne son objectif.

Comment fonctionnent les Swarms

Les Swarms fonctionnent en définissant un workflow itératif distribué sur plusieurs nœuds. À chaque itération, les tâches traitent des données, communiquent entre elles et contribuent à la progression globale du Swarm. Cette configuration est particulièrement utile pour les algorithmes collaboratifs, où les nœuds doivent coopérer pour atteindre un objectif commun.

The above diagram illustrates a Swarm consisting of seven tasks distributed across nodes. The tasks communicate with each other to pass data and synchronize their operations. After completing one cycle, the Swarm proceeds to the next iteration until it reaches the termination condition.

Classe Swarm

Pour créer un nouveau Swarm, vous définissez une classe Python qui hérite de la classe de base manta.swarm.Swarm. Cette classe personnalisée spécifie les tâches, leurs dépendances et la structure globale de l’algorithme décentralisé.

Pour plus d’informations détaillées sur l’implémentation d’une classe Swarm, reportez-vous à la documentation de l’API Swarm.

Classe Module

Module définit une tâche au sein du Swarm et sert de bloc de construction pour tout algorithme décentralisé. Chaque module représente une tâche individuelle qui fonctionne de manière indépendante, effectuant des calculs basés sur les données locales du nœud et contribuant au processus global du Swarm. Les modules sont exécutés dans des environnements de conteneur, permettant des déploiements isolés, reproductibles et évolutifs sur des dispositifs hétérogènes, des serveurs haute puissance aux dispositifs de périphérie.

Fonctionnalités principales d’un module :

  • Exécution conteneurisée : Chaque module spécifie une image de conteneur (par exemple, Docker) qui encapsule l’environnement de la tâche, garantissant la cohérence entre différents nœuds.

  • Indépendance des tâches : Les modules sont autonomes, ce qui signifie qu’ils peuvent fonctionner sans dépendances à d’autres modules, sauf pour les chemins de communication ou d’échange de données définis.

Création d’un module :

Pour définir un module, vous créez une instance de la classe Module, en spécifiant le script ou l’ensemble de scripts qui forment la tâche, l’environnement du conteneur et divers paramètres d’exécution. Voici un exemple de définition d’un module :

from manta.module import Module
from pathlib import Path

# Define a Worker Module
worker_module = Module(
    Path("modules/worker.py"),  # Path to the script defining the task
    "fl-pytorch-mnist:latest",  # Container image for task execution
    maximum=4,                  # Maximum number of instances allowed
    alias="worker",             # Alias for referencing the module in the Swarm
    method="any"                # Execution method (e.g., any, all)
)

Paramètres clés :

  • Chemin : Spécifie l’emplacement des scripts définissant la tâche.

  • Image du conteneur : L’image Docker ou similaire qui encapsule l’environnement de la tâche.

  • Maximum : Le nombre maximum d’instances pouvant être exécutées pour ce module.

  • Alias : Un nom court utilisé pour identifier le module au sein du Swarm.

  • Méthode : La méthode d’exécution qui définit la manière dont le module est planifié (par exemple, exécution unique ou exécutions simultanées).

Les modules constituent l’épine dorsale du Swarm, permettant la décomposition d’algorithmes complexes en tâches gérables, réutilisables et évolutives, pouvant être distribuées sur un réseau d’appareils.

Note

Pour des informations plus détaillées sur l’implémentation d’une classe Module, reportez-vous à la documentation de l’API Module.

Exemple : Développement d’un Swarm

Présentation de l’apprentissage fédéré

L’apprentissage fédéré (FL) est une approche décentralisée pour entraîner des modèles de machine learning, où les données restent sur les appareils locaux, et seules les mises à jour du modèle sont partagées et agrégées. Ce processus améliore la confidentialité en conservant les données sur les nœuds, ce qui est particulièrement utile dans les applications sensibles comme les soins de santé, la finance et la personnalisation des appareils mobiles. Pour une analyse plus approfondie des concepts de l’apprentissage fédéré, consultez notre article détaillé sur l”apprentissage fédéré.

Dans la plateforme Manta, l’apprentissage fédéré est mis en œuvre à l’aide d’un Swarm de tâches réparties sur plusieurs nœuds, chacun contribuant à un processus de formation collaborative. Le pipeline du Swarm inclut généralement des workers, des agrégateurs et des planificateurs, comme illustré sur l’image ci-dessous :

Swarm d'apprentissage fédéré Swarm d'apprentissage fédéré

Structure d’un Swarm :

  • Worker : chaque nœud de travail entraîne un modèle sur des données locales et envoie les mises à jour.

  • Agrégateur : regroupe les mises à jour du modèle de plusieurs workers.

  • Planificateur : gère le workflow, vérifie la convergence et décide quand mettre fin au Swarm.

Définition d’un Swarm d’apprentissage fédéré

Vous trouverez ci-dessous un exemple de code définissant un Swarm d’apprentissage fédéré en utilisant la plateforme Manta. La classe FLSwarm montre comment configurer les modules de worker, agrégateur et planificateur.

from pathlib import Path
from manta.module import Module
from manta.swarm import Swarm
from manta_light.utils import numpy_to_bytes
from modules.worker.model import MLP

class FLSwarm(Swarm):
    def __init__(self, n_workers: int = 4):
        super().__init__()

        # Define the Aggregator module, which combines updates from all workers
        self.aggregator = Module(
            Path("modules/aggregator.py"),
            "fl-pytorch-mnist:latest",  # Docker image used for the aggregator
            method="any",               # Execution method
            fixed=False,
            maximum=1,                  # Only one aggregator is used
            alias="aggregator",
        )

        # Define the Worker module, which handles local model training
        self.worker = Module(
            Path("modules/worker"),
            "fl-pytorch-mnist:latest",  # Docker image used for workers
            maximum=n_workers,          # Number of worker nodes
            alias="worker",
        )

        # Define the Scheduler module, which manages the swarm's iterations
        self.scheduler = Module(
            Path("modules/scheduler.py"),
            "fl-pytorch-mnist:latest",  # Docker image used for the scheduler
            maximum=1,
            alias="scheduler",
        )

        # Set global hyperparameters shared by all tasks in the swarm
        self.set_global(
            "hyperparameters",
            {
                "epochs": 1,
                "batch_size": 32,
                "loss": "CrossEntropyLoss",
                "loss_params": {},
                "optimizer": "SGD",
                "optimizer_params": {"lr": 0.01, "momentum": 0.9},
            },
        )

        # Initialize the global model parameters,
        # converting them to bytes for transmission
        self.set_global("global_model_params", numpy_to_bytes(MLP().get_weights()))

    def execute(self):
        """
        Define the execution flow of the swarm:
        - Each iteration starts with the Worker.
        - The results are then sent to the Aggregator.
        - The Scheduler decides if the swarm should continue or stop based on convergence.

        +--------+     +------------+     +-----------+ if has_converged
        | Worker | --> | Aggregator | --> | Scheduler | ----------------> END PROGRAM
        +--------+     +------------+     +-----------+
            |                                   | else
            +--<<<----------<<<----------<<<----+
        """
        m = self.worker()          # Start with the worker task
        m = self.aggregator(m)     # Aggregate results from the workers
        return self.scheduler(m)   # Check for convergence or continue the loop