Aperçu
Ce document présente des interfaces qui facilitent les tâches d'apprentissage fédéré, telles que la formation fédérée ou l'évaluation avec des modèles d'apprentissage automatique existants implémentés dans TensorFlow. Lors de la conception de ces interfaces, notre objectif principal était de rendre possible l'expérimentation de l'apprentissage fédéré sans nécessiter la connaissance de son fonctionnement sous le capot, et d'évaluer les algorithmes d'apprentissage fédéré mis en œuvre sur une variété de modèles et de données existants. Nous vous encourageons à contribuer à la plateforme. TFF a été conçu dans un souci d'extensibilité et de composabilité, et nous accueillons les contributions ; nous sommes impatients de voir ce que vous proposez !
Les interfaces offertes par cette couche se composent des trois éléments clés suivants :
Modèles . Classes et fonctions d'assistance qui vous permettent d'encapsuler vos modèles existants pour les utiliser avec TFF. L'encapsulation d'un modèle peut être aussi simple que d'appeler une seule fonction d'encapsulation (par exemple,
tff.learning.models.from_keras_model
) ou de définir une sous-classe de l'interfacetff.learning.models.VariableModel
pour une personnalisation complète.Constructeurs de calculs fédérés . Fonctions d'assistance qui construisent des calculs fédérés pour la formation ou l'évaluation, à l'aide de vos modèles existants.
Ensembles de données . Collections prédéfinies de données que vous pouvez télécharger et accéder en Python pour une utilisation dans la simulation de scénarios d'apprentissage fédéré. Bien que l'apprentissage fédéré soit conçu pour être utilisé avec des données décentralisées qui ne peuvent pas être simplement téléchargées à un emplacement centralisé, aux stades de la recherche et du développement, il est souvent pratique de mener des expériences initiales en utilisant des données qui peuvent être téléchargées et manipulées localement, en particulier pour les développeurs qui pourraient être nouveau dans l'approche.
Ces interfaces sont définies principalement dans l'espace de noms tff.learning
, à l'exception des ensembles de données de recherche et d'autres fonctionnalités liées à la simulation qui ont été regroupées dans tff.simulation
. Cette couche est implémentée à l'aide d'interfaces de niveau inférieur proposées par le Federated Core (FC) , qui fournit également un environnement d'exécution.
Avant de poursuivre, nous vous recommandons de consulter d'abord les didacticiels sur la classification d'images et la génération de texte , car ils présentent la plupart des concepts décrits ici à l'aide d'exemples concrets. Si vous souhaitez en savoir plus sur le fonctionnement de TFF, vous pouvez parcourir le didacticiel sur les algorithmes personnalisés en tant qu'introduction aux interfaces de niveau inférieur que nous utilisons pour exprimer la logique des calculs fédérés et pour étudier l'implémentation existante de la interfaces tff.learning
.
Des modèles
Hypothèses architecturales
Sérialisation
TFF vise à prendre en charge une variété de scénarios d'apprentissage distribué dans lesquels le code du modèle d'apprentissage automatique que vous écrivez peut s'exécuter sur un grand nombre de clients hétérogènes avec des capacités diverses. Alors qu'à une extrémité du spectre, dans certaines applications, ces clients peuvent être de puissants serveurs de base de données, de nombreuses utilisations importantes que notre plate-forme entend prendre en charge impliquent des appareils mobiles et intégrés avec des ressources limitées. Nous ne pouvons pas supposer que ces appareils sont capables d'héberger des runtimes Python ; la seule chose que nous pouvons supposer à ce stade est qu'ils sont capables d'héberger un runtime TensorFlow local. Ainsi, une hypothèse architecturale fondamentale que nous faisons dans TFF est que votre code de modèle doit être sérialisable en tant que graphe TensorFlow.
Vous pouvez (et devriez) toujours développer votre code TF en suivant les dernières meilleures pratiques comme l'utilisation du mode impatient. Cependant, le code final doit être sérialisable (par exemple, peut être enveloppé comme une tf.function
pour le code en mode impatient). Cela garantit que tout état Python ou flux de contrôle nécessaire au moment de l'exécution peut être sérialisé (éventuellement à l'aide de Autograph ).
Actuellement, TensorFlow ne prend pas entièrement en charge la sérialisation et la désérialisation de TensorFlow en mode impatient. Ainsi, la sérialisation dans TFF suit actuellement le modèle TF 1.0, où tout le code doit être construit à l'intérieur d'un tf.Graph
que TFF contrôle. Cela signifie qu'actuellement, TFF ne peut pas utiliser un modèle déjà construit ; à la place, la logique de définition du modèle est empaquetée dans une fonction sans argument qui renvoie un tff.learning.models.VariableModel
. Cette fonction est ensuite appelée par TFF pour s'assurer que tous les composants du modèle sont sérialisés. De plus, étant un environnement fortement typé, TFF nécessitera un peu de métadonnées supplémentaires, telles qu'une spécification du type d'entrée de votre modèle.
Agrégation
Nous recommandons fortement à la plupart des utilisateurs de construire des modèles à l'aide de Keras, voir la section Convertisseurs pour Keras ci-dessous. Ces wrappers gèrent automatiquement l'agrégation des mises à jour du modèle ainsi que toutes les métriques définies pour le modèle. Cependant, il peut toujours être utile de comprendre comment l'agrégation est gérée pour un tff.learning.models.VariableModel
général.
Il existe toujours au moins deux couches d'agrégation dans l'apprentissage fédéré : l'agrégation locale sur l'appareil et l'agrégation inter-appareils (ou fédérée) :
Agrégation locale . Ce niveau d'agrégation fait référence à l'agrégation de plusieurs lots d'exemples appartenant à un client individuel. Il s'applique à la fois aux paramètres du modèle (variables), qui continuent d'évoluer séquentiellement au fur et à mesure que le modèle est formé localement, ainsi qu'aux statistiques que vous calculez (telles que la perte moyenne, la précision et d'autres mesures), que votre modèle mettra à nouveau à jour localement. car il itère sur le flux de données local de chaque client individuel.
L'agrégation à ce niveau relève de la responsabilité du code de votre modèle et s'effectue à l'aide de constructions TensorFlow standard.
La structure générale du traitement est la suivante :
Le modèle construit d'abord
tf.Variable
s pour contenir des agrégats, tels que le nombre de lots ou le nombre d'exemples traités, la somme des pertes par lot ou par exemple, etc.TFF appelle plusieurs fois la méthode
forward_pass
sur votreModel
, de manière séquentielle sur les lots suivants de données client, ce qui vous permet de mettre à jour les variables contenant divers agrégats comme effet secondaire.Enfin, TFF appelle la méthode
report_local_unfinalized_metrics
sur votre modèle pour permettre à votre modèle de compiler toutes les statistiques récapitulatives qu'il a collectées dans un ensemble compact de métriques à exporter par le client. C'est là que votre code de modèle peut, par exemple, diviser la somme des pertes par le nombre d'exemples traités pour exporter la perte moyenne, etc.
Agrégation fédérée . Ce niveau d'agrégation fait référence à l'agrégation sur plusieurs clients (appareils) du système. Encore une fois, cela s'applique à la fois aux paramètres du modèle (variables), dont la moyenne est calculée sur les clients, ainsi qu'aux métriques que votre modèle a exportées à la suite de l'agrégation locale.
L'agrégation à ce niveau relève de la responsabilité de la TFF. En tant que créateur de modèle, cependant, vous pouvez contrôler ce processus (plus d'informations à ce sujet ci-dessous).
La structure générale du traitement est la suivante :
Le modèle initial et tous les paramètres requis pour la formation sont distribués par un serveur à un sous-ensemble de clients qui participeront à un cycle de formation ou d'évaluation.
Sur chaque client, indépendamment et en parallèle, votre code de modèle est appelé à plusieurs reprises sur un flux de lots de données locaux pour produire un nouvel ensemble de paramètres de modèle (lors de la formation) et un nouvel ensemble de métriques locales, comme décrit ci-dessus (c'est local agrégation).
TFF exécute un protocole d'agrégation distribué pour accumuler et agréger les paramètres du modèle et les métriques exportées localement à travers le système. Cette logique est exprimée de manière déclarative à l'aide du propre langage de calcul fédéré de TFF (pas dans TensorFlow). Consultez le didacticiel sur les algorithmes personnalisés pour en savoir plus sur l'API d'agrégation.
Interfaces abstraites
Cette interface constructeur + métadonnées de base est représentée par l'interface tff.learning.models.VariableModel
, comme suit :
Les méthodes constructeur,
forward_pass
etreport_local_unfinalized_metrics
doivent construire les variables de modèle, la passe avant et les statistiques que vous souhaitez signaler, en conséquence. Le TensorFlow construit par ces méthodes doit être sérialisable, comme indiqué ci-dessus.La propriété
input_spec
, ainsi que les 3 propriétés qui renvoient des sous-ensembles de vos variables entraînables, non entraînables et locales représentent les métadonnées. TFF utilise ces informations pour déterminer comment connecter des parties de votre modèle aux algorithmes d'optimisation fédérés et pour définir des signatures de type internes pour aider à vérifier l'exactitude du système construit (afin que votre modèle ne puisse pas être instancié sur des données qui ne correspondent pas à ce le modèle est conçu pour consommer).
De plus, l'interface abstraite tff.learning.models.VariableModel
expose une propriété metric_finalizers
qui prend les valeurs non finalisées d'une métrique (renvoyées par report_local_unfinalized_metrics()
) et renvoie les valeurs de métrique finalisées. Les méthodes metric_finalizers
et report_local_unfinalized_metrics()
seront utilisées ensemble pour créer un agrégateur de métriques inter-clients lors de la définition des processus de formation fédérés ou des calculs d'évaluation. Par exemple, un simple agrégateur tff.learning.metrics.sum_then_finalize
additionnera d'abord les valeurs de métrique non finalisées des clients, puis appellera les fonctions de finalisation sur le serveur.
Vous pouvez trouver des exemples de définition de votre propre tff.learning.models.VariableModel
personnalisé dans la deuxième partie de notre didacticiel de classification d'images , ainsi que dans les exemples de modèles que nous utilisons pour les tests dans model_examples.py
.
Convertisseurs pour Keras
Presque toutes les informations requises par TFF peuvent être dérivées en appelant les interfaces tf.keras
, donc si vous avez un modèle Keras, vous pouvez compter sur tff.learning.models.from_keras_model
pour construire un tff.learning.models.VariableModel
.
Notez que TFF souhaite toujours que vous fournissiez un constructeur - une fonction de modèle sans argument telle que la suivante :
def model_fn():
keras_model = ...
return tff.learning.models.from_keras_model(keras_model, sample_batch, loss=...)
En plus du modèle lui-même, vous fournissez un exemple de lot de données que TFF utilise pour déterminer le type et la forme de l'entrée de votre modèle. Cela garantit que TFF peut correctement instancier le modèle pour les données qui seront réellement présentes sur les appareils clients (puisque nous supposons que ces données ne sont généralement pas disponibles au moment où vous construisez le TensorFlow à sérialiser).
L'utilisation des wrappers Keras est illustrée dans nos tutoriels de classification d'images et de génération de texte .
Générateurs de calculs fédérés
Le package tff.learning
fournit plusieurs générateurs pour tff.Computation
qui effectuent des tâches liées à l'apprentissage ; nous nous attendons à ce que l'ensemble de ces calculs se développe à l'avenir.
Hypothèses architecturales
Exécution
Il existe deux phases distinctes dans l'exécution d'un calcul fédéré.
Compiler : TFF compile d'abord les algorithmes d'apprentissage fédéré en une représentation sérialisée abstraite de l'ensemble du calcul distribué. C'est à ce moment que la sérialisation de TensorFlow se produit, mais d'autres transformations peuvent se produire pour prendre en charge une exécution plus efficace. Nous appelons calcul fédéré la représentation sérialisée émise par le compilateur.
Execute TFF fournit des moyens d' exécuter ces calculs. Pour l'instant, l'exécution n'est prise en charge que via une simulation locale (par exemple, dans un notebook utilisant des données décentralisées simulées).
Un calcul fédéré généré par l'API d'apprentissage fédéré de TFF, tel qu'un algorithme de formation qui utilise la moyenne d'un modèle fédéré ou une évaluation fédérée, comprend un certain nombre d'éléments, notamment :
Une forme sérialisée de votre code de modèle ainsi que du code TensorFlow supplémentaire construit par le framework d'apprentissage fédéré pour piloter la boucle de formation/d'évaluation de votre modèle (comme la construction d'optimiseurs, l'application de mises à jour de modèle, l'itération sur
tf.data.Dataset
s et le calcul de métriques, et appliquer la mise à jour agrégée sur le serveur, pour n'en nommer que quelques-uns).Une spécification déclarative de la communication entre les clients et un serveur (généralement diverses formes d' agrégation entre les appareils clients et la diffusion du serveur à tous les clients), et comment cette communication distribuée est entrelacée avec l'exécution client-local ou serveur-local du code TensorFlow.
Les calculs fédérés représentés sous cette forme sérialisée sont exprimés dans un langage interne indépendant de la plate-forme distinct de Python, mais pour utiliser l'API d'apprentissage fédéré, vous n'aurez pas besoin de vous préoccuper des détails de cette représentation. Les calculs sont représentés dans votre code Python sous la forme d'objets de type tff.Computation
, que vous pouvez pour la plupart traiter comme des s callable
Python opaques.
Dans les didacticiels, vous invoquerez ces calculs fédérés comme s'il s'agissait de fonctions Python normales, à exécuter localement. Cependant, TFF est conçu pour exprimer des calculs fédérés d'une manière indépendante de la plupart des aspects de l'environnement d'exécution, de sorte qu'ils peuvent potentiellement être déployés, par exemple, sur des groupes d'appareils exécutant Android
ou sur des clusters dans un centre de données. Encore une fois, la principale conséquence de ceci sont des hypothèses fortes sur la sérialisation . En particulier, lorsque vous appelez l'une des méthodes build_...
décrites ci-dessous, le calcul est entièrement sérialisé.
État de modélisation
TFF est un environnement de programmation fonctionnel, mais de nombreux processus d'intérêt dans l'apprentissage fédéré sont avec état. Par exemple, une boucle de formation qui implique plusieurs cycles de calcul de la moyenne d'un modèle fédéré est un exemple de ce que nous pourrions classer comme un processus avec état . Dans ce processus, l'état qui évolue d'un cycle à l'autre comprend l'ensemble des paramètres du modèle qui sont en cours d'apprentissage, et éventuellement un état supplémentaire associé à l'optimiseur (par exemple, un vecteur d'impulsion).
Puisque TFF est fonctionnel, les processus avec état sont modélisés dans TFF comme des calculs qui acceptent l'état actuel comme entrée, puis fournissent l'état mis à jour comme sortie. Afin de définir complètement un processus avec état, il faut également spécifier d'où vient l'état initial (sinon nous ne pouvons pas amorcer le processus). Ceci est capturé dans la définition de la classe d'assistance tff.templates.IterativeProcess
, avec les 2 propriétés initialize
et next
correspondant respectivement à l'initialisation et à l'itération.
Constructeurs disponibles
À l'heure actuelle, TFF fournit diverses fonctions de création qui génèrent des calculs fédérés pour la formation et l'évaluation fédérées. Deux exemples notables incluent:
tff.learning.algorithms.build_weighted_fed_avg
, qui prend en entrée une fonction de modèle et un optimiseur client , et renvoie untff.learning.templates.LearningProcess
avec état (qui sous-classetff.templates.IterativeProcess
).tff.learning.build_federated_evaluation
prend une fonction de modèle et renvoie un seul calcul fédéré pour l'évaluation fédérée des modèles, car l'évaluation n'est pas avec état.
Jeux de données
Hypothèses architecturales
Sélection des clients
Dans le scénario d'apprentissage fédéré typique, nous avons une grande population de centaines de millions d'appareils clients, dont seule une petite partie peut être active et disponible pour la formation à un moment donné (par exemple, cela peut être limité aux clients qui sont branché à une source d'alimentation, pas sur un réseau mesuré, et autrement inactif). Généralement, l'ensemble des clients disponibles pour participer à la formation ou à l'évaluation est hors du contrôle du développeur. De plus, comme il n'est pas pratique de coordonner des millions de clients, un cycle typique de formation ou d'évaluation n'inclura qu'une fraction des clients disponibles, qui peuvent être échantillonnés au hasard .
La principale conséquence de ceci est que les calculs fédérés, par conception, sont exprimés d'une manière qui ne tient pas compte de l'ensemble exact de participants ; tous les traitements sont exprimés sous forme d'opérations agrégées sur un groupe abstrait de clients anonymes, et ce groupe peut varier d'un cycle de formation à l'autre. La liaison réelle du calcul aux participants concrets, et donc aux données concrètes qu'ils alimentent dans le calcul, est ainsi modélisée en dehors du calcul lui-même.
Afin de simuler un déploiement réaliste de votre code d'apprentissage fédéré, vous écrirez généralement une boucle de formation qui ressemble à ceci :
trainer = tff.learning.algorithms.build_weighted_fed_avg(...)
state = trainer.initialize()
federated_training_data = ...
def sample(federate_data):
return ...
while True:
data_for_this_round = sample(federated_training_data)
result = trainer.next(state, data_for_this_round)
state = result.state
Afin de faciliter cela, lors de l'utilisation de TFF dans des simulations, les données fédérées sont acceptées en tant que list
Python, avec un élément par périphérique client participant pour représenter le tf.data.Dataset
local de ce périphérique.
Interfaces abstraites
Afin de normaliser le traitement des ensembles de données fédérés simulés, TFF fournit une interface abstraite tff.simulation.datasets.ClientData
, qui permet d'énumérer l'ensemble de clients et de construire un tf.data.Dataset
qui contient les données d'un particulier client. Ces tf.data.Dataset
s peuvent être alimentés directement en entrée des calculs fédérés générés en mode impatient.
Il convient de noter que la possibilité d'accéder aux identités des clients est une fonctionnalité fournie uniquement par les ensembles de données à utiliser dans les simulations, où la capacité de s'entraîner sur les données de sous-ensembles spécifiques de clients peut être nécessaire (par exemple, pour simuler la disponibilité diurne de différents type de clientèle). Les calculs compilés et le runtime sous-jacent n'impliquent aucune notion d'identité du client. Une fois que les données d'un sous-ensemble spécifique de clients ont été sélectionnées comme entrée, par exemple, dans un appel à tff.templates.IterativeProcess.next
, les identités des clients n'y apparaissent plus.
Ensembles de données disponibles
Nous avons dédié l'espace de noms tff.simulation.datasets
aux ensembles de données qui implémentent l'interface tff.simulation.datasets.ClientData
pour une utilisation dans les simulations, et l'avons ensemencé avec des ensembles de données pour prendre en charge les didacticiels de classification d'images et de génération de texte . Nous aimerions vous encourager à contribuer vos propres ensembles de données à la plate-forme.
Aperçu
Ce document présente des interfaces qui facilitent les tâches d'apprentissage fédéré, telles que la formation fédérée ou l'évaluation avec des modèles d'apprentissage automatique existants implémentés dans TensorFlow. Lors de la conception de ces interfaces, notre objectif principal était de rendre possible l'expérimentation de l'apprentissage fédéré sans nécessiter la connaissance de son fonctionnement sous le capot, et d'évaluer les algorithmes d'apprentissage fédéré mis en œuvre sur une variété de modèles et de données existants. Nous vous encourageons à contribuer à la plateforme. TFF a été conçu dans un souci d'extensibilité et de composabilité, et nous accueillons les contributions ; nous sommes impatients de voir ce que vous proposez !
Les interfaces offertes par cette couche se composent des trois éléments clés suivants :
Modèles . Classes et fonctions d'assistance qui vous permettent d'encapsuler vos modèles existants pour les utiliser avec TFF. L'encapsulation d'un modèle peut être aussi simple que d'appeler une seule fonction d'encapsulation (par exemple,
tff.learning.models.from_keras_model
) ou de définir une sous-classe de l'interfacetff.learning.models.VariableModel
pour une personnalisation complète.Constructeurs de calculs fédérés . Fonctions d'assistance qui construisent des calculs fédérés pour la formation ou l'évaluation, à l'aide de vos modèles existants.
Ensembles de données . Collections prédéfinies de données que vous pouvez télécharger et accéder en Python pour une utilisation dans la simulation de scénarios d'apprentissage fédéré. Bien que l'apprentissage fédéré soit conçu pour être utilisé avec des données décentralisées qui ne peuvent pas être simplement téléchargées à un emplacement centralisé, aux stades de la recherche et du développement, il est souvent pratique de mener des expériences initiales en utilisant des données qui peuvent être téléchargées et manipulées localement, en particulier pour les développeurs qui pourraient être nouveau dans l'approche.
Ces interfaces sont définies principalement dans l'espace de noms tff.learning
, à l'exception des ensembles de données de recherche et d'autres fonctionnalités liées à la simulation qui ont été regroupées dans tff.simulation
. Cette couche est implémentée à l'aide d'interfaces de niveau inférieur proposées par le Federated Core (FC) , qui fournit également un environnement d'exécution.
Avant de poursuivre, nous vous recommandons de consulter d'abord les didacticiels sur la classification d'images et la génération de texte , car ils présentent la plupart des concepts décrits ici à l'aide d'exemples concrets. Si vous souhaitez en savoir plus sur le fonctionnement de TFF, vous pouvez parcourir le didacticiel sur les algorithmes personnalisés en tant qu'introduction aux interfaces de niveau inférieur que nous utilisons pour exprimer la logique des calculs fédérés et pour étudier l'implémentation existante de la interfaces tff.learning
.
Des modèles
Hypothèses architecturales
Sérialisation
TFF vise à prendre en charge une variété de scénarios d'apprentissage distribué dans lesquels le code du modèle d'apprentissage automatique que vous écrivez peut s'exécuter sur un grand nombre de clients hétérogènes avec des capacités diverses. Alors qu'à une extrémité du spectre, dans certaines applications, ces clients peuvent être de puissants serveurs de base de données, de nombreuses utilisations importantes que notre plate-forme entend prendre en charge impliquent des appareils mobiles et intégrés avec des ressources limitées. Nous ne pouvons pas supposer que ces appareils sont capables d'héberger des runtimes Python ; la seule chose que nous pouvons supposer à ce stade est qu'ils sont capables d'héberger un runtime TensorFlow local. Ainsi, une hypothèse architecturale fondamentale que nous faisons dans TFF est que votre code de modèle doit être sérialisable en tant que graphe TensorFlow.
Vous pouvez (et devriez) toujours développer votre code TF en suivant les dernières meilleures pratiques comme l'utilisation du mode impatient. Cependant, le code final doit être sérialisable (par exemple, peut être enveloppé comme une tf.function
pour le code en mode impatient). Cela garantit que tout état Python ou flux de contrôle nécessaire au moment de l'exécution peut être sérialisé (éventuellement à l'aide de Autograph ).
Actuellement, TensorFlow ne prend pas entièrement en charge la sérialisation et la désérialisation de TensorFlow en mode impatient. Ainsi, la sérialisation dans TFF suit actuellement le modèle TF 1.0, où tout le code doit être construit à l'intérieur d'un tf.Graph
que TFF contrôle. Cela signifie qu'actuellement, TFF ne peut pas utiliser un modèle déjà construit ; à la place, la logique de définition du modèle est empaquetée dans une fonction sans argument qui renvoie un tff.learning.models.VariableModel
. Cette fonction est ensuite appelée par TFF pour s'assurer que tous les composants du modèle sont sérialisés. De plus, étant un environnement fortement typé, TFF nécessitera un peu de métadonnées supplémentaires, telles qu'une spécification du type d'entrée de votre modèle.
Agrégation
Nous recommandons fortement à la plupart des utilisateurs de construire des modèles à l'aide de Keras, voir la section Convertisseurs pour Keras ci-dessous. Ces wrappers gèrent automatiquement l'agrégation des mises à jour du modèle ainsi que toutes les métriques définies pour le modèle. Cependant, il peut toujours être utile de comprendre comment l'agrégation est gérée pour un tff.learning.models.VariableModel
général.
Il existe toujours au moins deux couches d'agrégation dans l'apprentissage fédéré : l'agrégation locale sur l'appareil et l'agrégation inter-appareils (ou fédérée) :
Agrégation locale . Ce niveau d'agrégation fait référence à l'agrégation de plusieurs lots d'exemples appartenant à un client individuel. Il s'applique à la fois aux paramètres du modèle (variables), qui continuent d'évoluer séquentiellement au fur et à mesure que le modèle est formé localement, ainsi qu'aux statistiques que vous calculez (telles que la perte moyenne, la précision et d'autres mesures), que votre modèle mettra à nouveau à jour localement. car il itère sur le flux de données local de chaque client individuel.
L'agrégation à ce niveau relève de la responsabilité du code de votre modèle et s'effectue à l'aide de constructions TensorFlow standard.
La structure générale du traitement est la suivante :
Le modèle construit d'abord
tf.Variable
s pour contenir des agrégats, tels que le nombre de lots ou le nombre d'exemples traités, la somme des pertes par lot ou par exemple, etc.TFF appelle plusieurs fois la méthode
forward_pass
sur votreModel
, de manière séquentielle sur les lots suivants de données client, ce qui vous permet de mettre à jour les variables contenant divers agrégats comme effet secondaire.Enfin, TFF appelle la méthode
report_local_unfinalized_metrics
sur votre modèle pour permettre à votre modèle de compiler toutes les statistiques récapitulatives qu'il a collectées dans un ensemble compact de métriques à exporter par le client. C'est là que votre code de modèle peut, par exemple, diviser la somme des pertes par le nombre d'exemples traités pour exporter la perte moyenne, etc.
Agrégation fédérée . Ce niveau d'agrégation fait référence à l'agrégation sur plusieurs clients (appareils) du système. Encore une fois, cela s'applique à la fois aux paramètres du modèle (variables), dont la moyenne est calculée sur les clients, ainsi qu'aux métriques que votre modèle a exportées à la suite de l'agrégation locale.
L'agrégation à ce niveau relève de la responsabilité de la TFF. En tant que créateur de modèle, cependant, vous pouvez contrôler ce processus (plus d'informations à ce sujet ci-dessous).
La structure générale du traitement est la suivante :
Le modèle initial et tous les paramètres requis pour la formation sont distribués par un serveur à un sous-ensemble de clients qui participeront à un cycle de formation ou d'évaluation.
Sur chaque client, indépendamment et en parallèle, votre code de modèle est appelé à plusieurs reprises sur un flux de lots de données locaux pour produire un nouvel ensemble de paramètres de modèle (lors de la formation) et un nouvel ensemble de métriques locales, comme décrit ci-dessus (c'est local agrégation).
TFF exécute un protocole d'agrégation distribué pour accumuler et agréger les paramètres du modèle et les métriques exportées localement à travers le système. Cette logique est exprimée de manière déclarative à l'aide du propre langage de calcul fédéré de TFF (pas dans TensorFlow). Consultez le didacticiel sur les algorithmes personnalisés pour en savoir plus sur l'API d'agrégation.
Interfaces abstraites
Cette interface constructeur + métadonnées de base est représentée par l'interface tff.learning.models.VariableModel
, comme suit :
Les méthodes constructeur,
forward_pass
etreport_local_unfinalized_metrics
doivent construire les variables de modèle, la passe avant et les statistiques que vous souhaitez signaler, en conséquence. Le TensorFlow construit par ces méthodes doit être sérialisable, comme indiqué ci-dessus.La propriété
input_spec
, ainsi que les 3 propriétés qui renvoient des sous-ensembles de vos variables entraînables, non entraînables et locales représentent les métadonnées. TFF utilise ces informations pour déterminer comment connecter des parties de votre modèle aux algorithmes d'optimisation fédérés et pour définir des signatures de type internes pour aider à vérifier l'exactitude du système construit (afin que votre modèle ne puisse pas être instancié sur des données qui ne correspondent pas à ce le modèle est conçu pour consommer).
De plus, l'interface abstraite tff.learning.models.VariableModel
expose une propriété metric_finalizers
qui prend les valeurs non finalisées d'une métrique (renvoyées par report_local_unfinalized_metrics()
) et renvoie les valeurs de métrique finalisées. Les méthodes metric_finalizers
et report_local_unfinalized_metrics()
seront utilisées ensemble pour créer un agrégateur de métriques inter-clients lors de la définition des processus de formation fédérés ou des calculs d'évaluation. Par exemple, un simple agrégateur tff.learning.metrics.sum_then_finalize
additionnera d'abord les valeurs de métrique non finalisées des clients, puis appellera les fonctions de finalisation sur le serveur.
Vous pouvez trouver des exemples de définition de votre propre tff.learning.models.VariableModel
personnalisé dans la deuxième partie de notre didacticiel de classification d'images , ainsi que dans les exemples de modèles que nous utilisons pour les tests dans model_examples.py
.
Convertisseurs pour Keras
Presque toutes les informations requises par TFF peuvent être dérivées en appelant les interfaces tf.keras
, donc si vous avez un modèle Keras, vous pouvez compter sur tff.learning.models.from_keras_model
pour construire un tff.learning.models.VariableModel
.
Notez que TFF souhaite toujours que vous fournissiez un constructeur - une fonction de modèle sans argument telle que la suivante :
def model_fn():
keras_model = ...
return tff.learning.models.from_keras_model(keras_model, sample_batch, loss=...)
En plus du modèle lui-même, vous fournissez un exemple de lot de données que TFF utilise pour déterminer le type et la forme de l'entrée de votre modèle. Cela garantit que TFF peut correctement instancier le modèle pour les données qui seront réellement présentes sur les appareils clients (puisque nous supposons que ces données ne sont généralement pas disponibles au moment où vous construisez le TensorFlow à sérialiser).
L'utilisation des wrappers Keras est illustrée dans nos tutoriels de classification d'images et de génération de texte .
Générateurs de calculs fédérés
Le package tff.learning
fournit plusieurs générateurs pour tff.Computation
qui effectuent des tâches liées à l'apprentissage ; nous nous attendons à ce que l'ensemble de ces calculs se développe à l'avenir.
Hypothèses architecturales
Exécution
Il existe deux phases distinctes dans l'exécution d'un calcul fédéré.
Compiler : TFF compile d'abord les algorithmes d'apprentissage fédéré en une représentation sérialisée abstraite de l'ensemble du calcul distribué. C'est à ce moment que la sérialisation de TensorFlow se produit, mais d'autres transformations peuvent se produire pour prendre en charge une exécution plus efficace. Nous appelons calcul fédéré la représentation sérialisée émise par le compilateur.
Execute TFF fournit des moyens d' exécuter ces calculs. Pour l'instant, l'exécution n'est prise en charge que via une simulation locale (par exemple, dans un notebook utilisant des données décentralisées simulées).
Un calcul fédéré généré par l'API d'apprentissage fédéré de TFF, tel qu'un algorithme de formation qui utilise la moyenne d'un modèle fédéré ou une évaluation fédérée, comprend un certain nombre d'éléments, notamment :
Une forme sérialisée de votre code de modèle ainsi que du code TensorFlow supplémentaire construit par le framework d'apprentissage fédéré pour piloter la boucle de formation/d'évaluation de votre modèle (comme la construction d'optimiseurs, l'application de mises à jour de modèle, l'itération sur
tf.data.Dataset
s et le calcul de métriques, et appliquer la mise à jour agrégée sur le serveur, pour n'en nommer que quelques-uns).Une spécification déclarative de la communication entre les clients et un serveur (généralement diverses formes d' agrégation entre les appareils clients et la diffusion du serveur à tous les clients), et comment cette communication distribuée est entrelacée avec l'exécution client-local ou serveur-local du code TensorFlow.
Les calculs fédérés représentés sous cette forme sérialisée sont exprimés dans un langage interne indépendant de la plate-forme distinct de Python, mais pour utiliser l'API d'apprentissage fédéré, vous n'aurez pas besoin de vous préoccuper des détails de cette représentation. Les calculs sont représentés dans votre code Python sous la forme d'objets de type tff.Computation
, que vous pouvez pour la plupart traiter comme des s callable
Python opaques.
Dans les didacticiels, vous invoquerez ces calculs fédérés comme s'il s'agissait de fonctions Python normales, à exécuter localement. Cependant, TFF est conçu pour exprimer des calculs fédérés d'une manière indépendante de la plupart des aspects de l'environnement d'exécution, de sorte qu'ils peuvent potentiellement être déployés, par exemple, sur des groupes d'appareils exécutant Android
ou sur des clusters dans un centre de données. Encore une fois, la principale conséquence de ceci sont des hypothèses fortes sur la sérialisation . En particulier, lorsque vous appelez l'une des méthodes build_...
décrites ci-dessous, le calcul est entièrement sérialisé.
État de modélisation
TFF est un environnement de programmation fonctionnel, mais de nombreux processus d'intérêt dans l'apprentissage fédéré sont avec état. Par exemple, une boucle de formation qui implique plusieurs cycles de calcul de la moyenne d'un modèle fédéré est un exemple de ce que nous pourrions classer comme un processus avec état . Dans ce processus, l'état qui évolue d'un cycle à l'autre comprend l'ensemble des paramètres du modèle qui sont en cours d'apprentissage, et éventuellement un état supplémentaire associé à l'optimiseur (par exemple, un vecteur d'impulsion).
Puisque TFF est fonctionnel, les processus avec état sont modélisés dans TFF comme des calculs qui acceptent l'état actuel comme entrée, puis fournissent l'état mis à jour comme sortie. Afin de définir complètement un processus avec état, il faut également spécifier d'où vient l'état initial (sinon nous ne pouvons pas amorcer le processus). Ceci est capturé dans la définition de la classe d'assistance tff.templates.IterativeProcess
, avec les 2 propriétés initialize
et next
correspondant respectivement à l'initialisation et à l'itération.
Constructeurs disponibles
At the moment, TFF provides various builder functions that generate federated computations for federated training and evaluation. Two notable examples include:
tff.learning.algorithms.build_weighted_fed_avg
, which takes as input a model function and a client optimizer , and returns a statefultff.learning.templates.LearningProcess
(which subclassestff.templates.IterativeProcess
).tff.learning.build_federated_evaluation
takes a model function and returns a single federated computation for federated evaluation of models, since evaluation is not stateful.
Datasets
Architectural assumptions
Client selection
In the typical federated learning scenario, we have a large population of potentially hundreds of millions of client devices, of which only a small portion may be active and available for training at any given moment (for example, this may be limited to clients that are plugged in to a power source, not on a metered network, and otherwise idle). Generally, the set of clients available to participate in training or evaluation is outside of the developer's control. Furthermore, as it's impractical to coordinate millions of clients, a typical round of training or evaluation will include only a fraction of the available clients, which may be sampled at random .
The key consequence of this is that federated computations, by design, are expressed in a manner that is oblivious to the exact set of participants; all processing is expressed as aggregate operations on an abstract group of anonymous clients , and that group might vary from one round of training to another. The actual binding of the computation to the concrete participants, and thus to the concrete data they feed into the computation, is thus modeled outside of the computation itself.
In order to simulate a realistic deployment of your federated learning code, you will generally write a training loop that looks like this:
trainer = tff.learning.algorithms.build_weighted_fed_avg(...)
state = trainer.initialize()
federated_training_data = ...
def sample(federate_data):
return ...
while True:
data_for_this_round = sample(federated_training_data)
result = trainer.next(state, data_for_this_round)
state = result.state
In order to facilitate this, when using TFF in simulations, federated data is accepted as Python list
s, with one element per participating client device to represent that device's local tf.data.Dataset
.
Abstract interfaces
In order to standardize dealing with simulated federated data sets, TFF provides an abstract interface tff.simulation.datasets.ClientData
, which allows one to enumerate the set of clients, and to construct a tf.data.Dataset
that contains the data of a particular client. Those tf.data.Dataset
s can be fed directly as input to the generated federated computations in eager mode.
It should be noted that the ability to access client identities is a feature that's only provided by the datasets for use in simulations, where the ability to train on data from specific subsets of clients may be needed (eg, to simulate the diurnal availability of different types of clients). The compiled computations and the underlying runtime do not involve any notion of client identity. Once data from a specific subset of clients has been selected as an input, eg, in a call to tff.templates.IterativeProcess.next
, client identities no longer appear in it.
Available data sets
We have dedicated the namespace tff.simulation.datasets
for datasets that implement the tff.simulation.datasets.ClientData
interface for use in simulations, and seeded it with datasets to support the image classification and text generation tutorials. We'd like to encourage you to contribute your own datasets to the platform.
Overview
This document introduces interfaces that facilitate federated learning tasks, such as federated training or evaluation with existing machine learning models implemented in TensorFlow. In designing these interfaces, our primary goal was to make it possible to experiment with federated learning without requiring the knowledge of how it works under the hood, and to evaluate the implemented federated learning algorithms on a variety of existing models and data. We encourage you to contribute back to the platform. TFF has been designed with extensibility and composability in mind, and we welcome contributions; we are excited to see what you come up with!
The interfaces offered by this layer consist of the following three key parts:
Models . Classes and helper functions that allow you to wrap your existing models for use with TFF. Wrapping a model can be as simple as calling a single wrapping function (eg,
tff.learning.models.from_keras_model
), or defining a subclass of thetff.learning.models.VariableModel
interface for full customizability.Federated Computation Builders . Helper functions that construct federated computations for training or evaluation, using your existing models.
Datasets . Canned collections of data that you can download and access in Python for use in simulating federated learning scenarios. Although federated learning is designed for use with decentralized data that cannot be simply downloaded at a centralized location, at the research and development stages it is often convenient to conduct initial experiments using data that can be downloaded and manipulated locally, especially for developers who might be new to the approach.
These interfaces are defined primarily in the tff.learning
namespace, except for research data sets and other simulation-related capabilities that have been grouped in tff.simulation
. This layer is implemented using lower-level interfaces offered by the Federated Core (FC) , which also provides a runtime environment.
Before proceeding, we recommend that you first review the tutorials on image classification and text generation , as they introduce most of the concepts described here using concrete examples. If you're interested in learning more about how TFF works, you may want to skim over the custom algorithms tutorial as an introduction to the lower-level interfaces we use to express the logic of federated computations, and to study the existing implementation of the tff.learning
interfaces.
Models
Architectural assumptions
Serialization
TFF aims at supporting a variety of distributed learning scenarios in which the machine learning model code you write might be executing on a large number of heterogeneous clients with diverse capabilities. While at one end of the spectrum, in some applications those clients might be powerful database servers, many important uses our platform intends to support involve mobile and embedded devices with limited resources. We cannot assume that these devices are capable of hosting Python runtimes; the only thing we can assume at this point is that they are capable of hosting a local TensorFlow runtime. Thus, a fundamental architectural assumption we make in TFF is that your model code must be serializable as a TensorFlow graph.
You can (and should) still develop your TF code following the latest best practices like using eager mode. However, the final code must be serializable (eg, can be wrapped as a tf.function
for eager-mode code). This ensures that any Python state or control flow necessary at execution time can be serialized (possibly with the help of Autograph ).
Currently, TensorFlow does not fully support serializing and deserializing eager-mode TensorFlow. Thus, serialization in TFF currently follows the TF 1.0 pattern, where all code must be constructed inside a tf.Graph
that TFF controls. This means currently TFF cannot consume an already-constructed model; instead, the model definition logic is packaged in a no-arg function that returns a tff.learning.models.VariableModel
. This function is then called by TFF to ensure all components of the model are serialized. In addition, being a strongly-typed environment, TFF will require a little bit of additional metadata , such as a specification of your model's input type.
Aggregation
We strongly recommend most users construct models using Keras, see the Converters for Keras section below. These wrappers handle the aggregation of model updates as well as any metrics defined for the model automatically. However, it may still be useful to understand how aggregation is handled for a general tff.learning.models.VariableModel
.
There are always at least two layers of aggregation in federated learning: local on-device aggregation, and cross-device (or federated) aggregation:
Local aggregation . This level of aggregation refers to aggregation across multiple batches of examples owned by an individual client. It applies to both the model parameters (variables), which continue to sequentially evolve as the model is locally trained, as well as the statistics you compute (such as average loss, accuracy, and other metrics), which your model will again update locally as it iterates over each individual client's local data stream.
Performing aggregation at this level is the responsibility of your model code, and is accomplished using standard TensorFlow constructs.
The general structure of processing is as follows:
The model first constructs
tf.Variable
s to hold aggregates, such as the number of batches or the number of examples processed, the sum of per-batch or per-example losses, etc.TFF invokes the
forward_pass
method on yourModel
multiple times, sequentially over subsequent batches of client data, which allows you to update the variables holding various aggregates as a side effect.Finally, TFF invokes the
report_local_unfinalized_metrics
method on your Model to allow your model to compile all the summary statistics it collected into a compact set of metrics to be exported by the client. This is where your model code may, for example, divide the sum of losses by the number of examples processed to export the average loss, etc.
Federated aggregation . This level of aggregation refers to aggregation across multiple clients (devices) in the system. Again, it applies to both the model parameters (variables), which are being averaged across clients, as well as the metrics your model exported as a result of local aggregation.
Performing aggregation at this level is the responsibility of TFF. As a model creator, however, you can control this process (more on this below).
The general structure of processing is as follows:
The initial model, and any parameters required for training, are distributed by a server to a subset of clients that will participate in a round of training or evaluation.
On each client, independently and in parallel, your model code is invoked repeatedly on a stream of local data batches to produce a new set of model parameters (when training), and a new set of local metrics, as described above (this is local aggregation).
TFF runs a distributed aggregation protocol to accumulate and aggregate the model parameters and locally exported metrics across the system. This logic is expressed in a declarative manner using TFF's own federated computation language (not in TensorFlow). See the custom algorithms tutorial for more on the aggregation API.
Abstract interfaces
This basic constructor + metadata interface is represented by the interface tff.learning.models.VariableModel
, as follows:
The constructor,
forward_pass
, andreport_local_unfinalized_metrics
methods should construct model variables, forward pass, and statistics you wish to report, correspondingly. The TensorFlow constructed by those methods must be serializable, as discussed above.The
input_spec
property, as well as the 3 properties that return subsets of your trainable, non-trainable, and local variables represent the metadata. TFF uses this information to determine how to connect parts of your model to the federated optimization algorithms, and to define internal type signatures to assist in verifying the correctness of the constructed system (so that your model cannot be instantiated over data that does not match what the model is designed to consume).
In addition, the abstract interface tff.learning.models.VariableModel
exposes a property metric_finalizers
that takes in a metric's unfinalized values (returned by report_local_unfinalized_metrics()
) and returns the finalized metric values. The metric_finalizers
and report_local_unfinalized_metrics()
method will be used together to build a cross-client metrics aggregator when defining the federated training processes or evaluation computations. For example, a simple tff.learning.metrics.sum_then_finalize
aggregator will first sum the unfinalized metric values from clients, and then call the finalizer functions at the server.
You can find examples of how to define your own custom tff.learning.models.VariableModel
in the second part of our image classification tutorial, as well as in the example models we use for testing in model_examples.py
.
Converters for Keras
Nearly all the information that's required by TFF can be derived by calling tf.keras
interfaces, so if you have a Keras model, you can rely on tff.learning.models.from_keras_model
to construct a tff.learning.models.VariableModel
.
Note that TFF still wants you to provide a constructor - a no-argument model function such as the following:
def model_fn():
keras_model = ...
return tff.learning.models.from_keras_model(keras_model, sample_batch, loss=...)
In addition to the model itself, you supply a sample batch of data which TFF uses to determine the type and shape of your model's input. This ensures that TFF can properly instantiate the model for the data that will actually be present on client devices (since we assume this data is not generally available at the time you are constructing the TensorFlow to be serialized).
The use of Keras wrappers is illustrated in our image classification and text generation tutorials.
Federated Computation Builders
The tff.learning
package provides several builders for tff.Computation
s that perform learning-related tasks; we expect the set of such computations to expand in the future.
Architectural assumptions
Execution
There are two distinct phases in running a federated computation.
Compile : TFF first compiles federated learning algorithms into an abstract serialized representation of the entire distributed computation. This is when TensorFlow serialization happens, but other transformations can occur to support more efficient execution. We refer to the serialized representation emitted by the compiler as a federated computation .
Execute TFF provides ways to execute these computations. For now, execution is only supported via a local simulation (eg, in a notebook using simulated decentralized data).
A federated computation generated by TFF's Federated Learning API, such as a training algorithm that uses federated model averaging , or a federated evaluation, includes a number of elements, most notably:
A serialized form of your model code as well as additional TensorFlow code constructed by the Federated Learning framework to drive your model's training/evaluation loop (such as constructing optimizers, applying model updates, iterating over
tf.data.Dataset
s, and computing metrics, and applying the aggregated update on the server, to name a few).A declarative specification of the communication between the clients and a server (typically various forms of aggregation across the client devices, and broadcasting from the server to all clients), and how this distributed communication is interleaved with the client-local or server-local execution of TensorFlow code.
The federated computations represented in this serialized form are expressed in a platform-independent internal language distinct from Python, but to use the Federated Learning API, you won't need to concern yourself with the details of this representation. The computations are represented in your Python code as objects of type tff.Computation
, which for the most part you can treat as opaque Python callable
s.
In the tutorials, you will invoke those federated computations as if they were regular Python functions, to be executed locally. However, TFF is designed to express federated computations in a manner agnostic to most aspects of the execution environment, so that they can potentially be deployable to, eg, groups of devices running Android
, or to clusters in a datacenter. Again, the main consequence of this are strong assumptions about serialization . In particular, when you invoke one of the build_...
methods described below the computation is fully serialized.
Modeling state
TFF is a functional programming environment, yet many processes of interest in federated learning are stateful. For example, a training loop that involves multiple rounds of federated model averaging is an example of what we could classify as a stateful process . In this process, the state that evolves from round to round includes the set of model parameters that are being trained, and possibly additional state associated with the optimizer (eg, a momentum vector).
Since TFF is functional, stateful processes are modeled in TFF as computations that accept the current state as an input and then provide the updated state as an output. In order to fully define a stateful process, one also needs to specify where the initial state comes from (otherwise we cannot bootstrap the process). This is captured in the definition of the helper class tff.templates.IterativeProcess
, with the 2 properties initialize
and next
corresponding to the initialization and iteration, respectively.
Available builders
At the moment, TFF provides various builder functions that generate federated computations for federated training and evaluation. Two notable examples include:
tff.learning.algorithms.build_weighted_fed_avg
, which takes as input a model function and a client optimizer , and returns a statefultff.learning.templates.LearningProcess
(which subclassestff.templates.IterativeProcess
).tff.learning.build_federated_evaluation
takes a model function and returns a single federated computation for federated evaluation of models, since evaluation is not stateful.
Datasets
Architectural assumptions
Client selection
In the typical federated learning scenario, we have a large population of potentially hundreds of millions of client devices, of which only a small portion may be active and available for training at any given moment (for example, this may be limited to clients that are plugged in to a power source, not on a metered network, and otherwise idle). Generally, the set of clients available to participate in training or evaluation is outside of the developer's control. Furthermore, as it's impractical to coordinate millions of clients, a typical round of training or evaluation will include only a fraction of the available clients, which may be sampled at random .
The key consequence of this is that federated computations, by design, are expressed in a manner that is oblivious to the exact set of participants; all processing is expressed as aggregate operations on an abstract group of anonymous clients , and that group might vary from one round of training to another. The actual binding of the computation to the concrete participants, and thus to the concrete data they feed into the computation, is thus modeled outside of the computation itself.
In order to simulate a realistic deployment of your federated learning code, you will generally write a training loop that looks like this:
trainer = tff.learning.algorithms.build_weighted_fed_avg(...)
state = trainer.initialize()
federated_training_data = ...
def sample(federate_data):
return ...
while True:
data_for_this_round = sample(federated_training_data)
result = trainer.next(state, data_for_this_round)
state = result.state
In order to facilitate this, when using TFF in simulations, federated data is accepted as Python list
s, with one element per participating client device to represent that device's local tf.data.Dataset
.
Abstract interfaces
In order to standardize dealing with simulated federated data sets, TFF provides an abstract interface tff.simulation.datasets.ClientData
, which allows one to enumerate the set of clients, and to construct a tf.data.Dataset
that contains the data of a particular client. Those tf.data.Dataset
s can be fed directly as input to the generated federated computations in eager mode.
It should be noted that the ability to access client identities is a feature that's only provided by the datasets for use in simulations, where the ability to train on data from specific subsets of clients may be needed (eg, to simulate the diurnal availability of different types of clients). The compiled computations and the underlying runtime do not involve any notion of client identity. Once data from a specific subset of clients has been selected as an input, eg, in a call to tff.templates.IterativeProcess.next
, client identities no longer appear in it.
Available data sets
We have dedicated the namespace tff.simulation.datasets
for datasets that implement the tff.simulation.datasets.ClientData
interface for use in simulations, and seeded it with datasets to support the image classification and text generation tutorials. We'd like to encourage you to contribute your own datasets to the platform.
Overview
This document introduces interfaces that facilitate federated learning tasks, such as federated training or evaluation with existing machine learning models implemented in TensorFlow. In designing these interfaces, our primary goal was to make it possible to experiment with federated learning without requiring the knowledge of how it works under the hood, and to evaluate the implemented federated learning algorithms on a variety of existing models and data. We encourage you to contribute back to the platform. TFF has been designed with extensibility and composability in mind, and we welcome contributions; we are excited to see what you come up with!
The interfaces offered by this layer consist of the following three key parts:
Models . Classes and helper functions that allow you to wrap your existing models for use with TFF. Wrapping a model can be as simple as calling a single wrapping function (eg,
tff.learning.models.from_keras_model
), or defining a subclass of thetff.learning.models.VariableModel
interface for full customizability.Federated Computation Builders . Helper functions that construct federated computations for training or evaluation, using your existing models.
Datasets . Canned collections of data that you can download and access in Python for use in simulating federated learning scenarios. Although federated learning is designed for use with decentralized data that cannot be simply downloaded at a centralized location, at the research and development stages it is often convenient to conduct initial experiments using data that can be downloaded and manipulated locally, especially for developers who might be new to the approach.
These interfaces are defined primarily in the tff.learning
namespace, except for research data sets and other simulation-related capabilities that have been grouped in tff.simulation
. This layer is implemented using lower-level interfaces offered by the Federated Core (FC) , which also provides a runtime environment.
Before proceeding, we recommend that you first review the tutorials on image classification and text generation , as they introduce most of the concepts described here using concrete examples. If you're interested in learning more about how TFF works, you may want to skim over the custom algorithms tutorial as an introduction to the lower-level interfaces we use to express the logic of federated computations, and to study the existing implementation of the tff.learning
interfaces.
Models
Architectural assumptions
Serialization
TFF aims at supporting a variety of distributed learning scenarios in which the machine learning model code you write might be executing on a large number of heterogeneous clients with diverse capabilities. While at one end of the spectrum, in some applications those clients might be powerful database servers, many important uses our platform intends to support involve mobile and embedded devices with limited resources. We cannot assume that these devices are capable of hosting Python runtimes; the only thing we can assume at this point is that they are capable of hosting a local TensorFlow runtime. Thus, a fundamental architectural assumption we make in TFF is that your model code must be serializable as a TensorFlow graph.
You can (and should) still develop your TF code following the latest best practices like using eager mode. However, the final code must be serializable (eg, can be wrapped as a tf.function
for eager-mode code). This ensures that any Python state or control flow necessary at execution time can be serialized (possibly with the help of Autograph ).
Currently, TensorFlow does not fully support serializing and deserializing eager-mode TensorFlow. Thus, serialization in TFF currently follows the TF 1.0 pattern, where all code must be constructed inside a tf.Graph
that TFF controls. This means currently TFF cannot consume an already-constructed model; instead, the model definition logic is packaged in a no-arg function that returns a tff.learning.models.VariableModel
. This function is then called by TFF to ensure all components of the model are serialized. In addition, being a strongly-typed environment, TFF will require a little bit of additional metadata , such as a specification of your model's input type.
Aggregation
We strongly recommend most users construct models using Keras, see the Converters for Keras section below. These wrappers handle the aggregation of model updates as well as any metrics defined for the model automatically. However, it may still be useful to understand how aggregation is handled for a general tff.learning.models.VariableModel
.
There are always at least two layers of aggregation in federated learning: local on-device aggregation, and cross-device (or federated) aggregation:
Local aggregation . This level of aggregation refers to aggregation across multiple batches of examples owned by an individual client. It applies to both the model parameters (variables), which continue to sequentially evolve as the model is locally trained, as well as the statistics you compute (such as average loss, accuracy, and other metrics), which your model will again update locally as it iterates over each individual client's local data stream.
Performing aggregation at this level is the responsibility of your model code, and is accomplished using standard TensorFlow constructs.
The general structure of processing is as follows:
The model first constructs
tf.Variable
s to hold aggregates, such as the number of batches or the number of examples processed, the sum of per-batch or per-example losses, etc.TFF invokes the
forward_pass
method on yourModel
multiple times, sequentially over subsequent batches of client data, which allows you to update the variables holding various aggregates as a side effect.Finally, TFF invokes the
report_local_unfinalized_metrics
method on your Model to allow your model to compile all the summary statistics it collected into a compact set of metrics to be exported by the client. This is where your model code may, for example, divide the sum of losses by the number of examples processed to export the average loss, etc.
Federated aggregation . This level of aggregation refers to aggregation across multiple clients (devices) in the system. Again, it applies to both the model parameters (variables), which are being averaged across clients, as well as the metrics your model exported as a result of local aggregation.
Performing aggregation at this level is the responsibility of TFF. As a model creator, however, you can control this process (more on this below).
The general structure of processing is as follows:
The initial model, and any parameters required for training, are distributed by a server to a subset of clients that will participate in a round of training or evaluation.
On each client, independently and in parallel, your model code is invoked repeatedly on a stream of local data batches to produce a new set of model parameters (when training), and a new set of local metrics, as described above (this is local aggregation).
TFF runs a distributed aggregation protocol to accumulate and aggregate the model parameters and locally exported metrics across the system. This logic is expressed in a declarative manner using TFF's own federated computation language (not in TensorFlow). See the custom algorithms tutorial for more on the aggregation API.
Abstract interfaces
This basic constructor + metadata interface is represented by the interface tff.learning.models.VariableModel
, as follows:
The constructor,
forward_pass
, andreport_local_unfinalized_metrics
methods should construct model variables, forward pass, and statistics you wish to report, correspondingly. The TensorFlow constructed by those methods must be serializable, as discussed above.The
input_spec
property, as well as the 3 properties that return subsets of your trainable, non-trainable, and local variables represent the metadata. TFF uses this information to determine how to connect parts of your model to the federated optimization algorithms, and to define internal type signatures to assist in verifying the correctness of the constructed system (so that your model cannot be instantiated over data that does not match what the model is designed to consume).
In addition, the abstract interface tff.learning.models.VariableModel
exposes a property metric_finalizers
that takes in a metric's unfinalized values (returned by report_local_unfinalized_metrics()
) and returns the finalized metric values. The metric_finalizers
and report_local_unfinalized_metrics()
method will be used together to build a cross-client metrics aggregator when defining the federated training processes or evaluation computations. For example, a simple tff.learning.metrics.sum_then_finalize
aggregator will first sum the unfinalized metric values from clients, and then call the finalizer functions at the server.
You can find examples of how to define your own custom tff.learning.models.VariableModel
in the second part of our image classification tutorial, as well as in the example models we use for testing in model_examples.py
.
Converters for Keras
Nearly all the information that's required by TFF can be derived by calling tf.keras
interfaces, so if you have a Keras model, you can rely on tff.learning.models.from_keras_model
to construct a tff.learning.models.VariableModel
.
Note that TFF still wants you to provide a constructor - a no-argument model function such as the following:
def model_fn():
keras_model = ...
return tff.learning.models.from_keras_model(keras_model, sample_batch, loss=...)
In addition to the model itself, you supply a sample batch of data which TFF uses to determine the type and shape of your model's input. This ensures that TFF can properly instantiate the model for the data that will actually be present on client devices (since we assume this data is not generally available at the time you are constructing the TensorFlow to be serialized).
The use of Keras wrappers is illustrated in our image classification and text generation tutorials.
Federated Computation Builders
The tff.learning
package provides several builders for tff.Computation
s that perform learning-related tasks; we expect the set of such computations to expand in the future.
Architectural assumptions
Execution
There are two distinct phases in running a federated computation.
Compile : TFF first compiles federated learning algorithms into an abstract serialized representation of the entire distributed computation. This is when TensorFlow serialization happens, but other transformations can occur to support more efficient execution. We refer to the serialized representation emitted by the compiler as a federated computation .
Execute TFF provides ways to execute these computations. For now, execution is only supported via a local simulation (eg, in a notebook using simulated decentralized data).
A federated computation generated by TFF's Federated Learning API, such as a training algorithm that uses federated model averaging , or a federated evaluation, includes a number of elements, most notably:
A serialized form of your model code as well as additional TensorFlow code constructed by the Federated Learning framework to drive your model's training/evaluation loop (such as constructing optimizers, applying model updates, iterating over
tf.data.Dataset
s, and computing metrics, and applying the aggregated update on the server, to name a few).A declarative specification of the communication between the clients and a server (typically various forms of aggregation across the client devices, and broadcasting from the server to all clients), and how this distributed communication is interleaved with the client-local or server-local execution of TensorFlow code.
The federated computations represented in this serialized form are expressed in a platform-independent internal language distinct from Python, but to use the Federated Learning API, you won't need to concern yourself with the details of this representation. The computations are represented in your Python code as objects of type tff.Computation
, which for the most part you can treat as opaque Python callable
s.
In the tutorials, you will invoke those federated computations as if they were regular Python functions, to be executed locally. However, TFF is designed to express federated computations in a manner agnostic to most aspects of the execution environment, so that they can potentially be deployable to, eg, groups of devices running Android
, or to clusters in a datacenter. Again, the main consequence of this are strong assumptions about serialization . In particular, when you invoke one of the build_...
methods described below the computation is fully serialized.
Modeling state
TFF is a functional programming environment, yet many processes of interest in federated learning are stateful. For example, a training loop that involves multiple rounds of federated model averaging is an example of what we could classify as a stateful process . In this process, the state that evolves from round to round includes the set of model parameters that are being trained, and possibly additional state associated with the optimizer (eg, a momentum vector).
Since TFF is functional, stateful processes are modeled in TFF as computations that accept the current state as an input and then provide the updated state as an output. In order to fully define a stateful process, one also needs to specify where the initial state comes from (otherwise we cannot bootstrap the process). This is captured in the definition of the helper class tff.templates.IterativeProcess
, with the 2 properties initialize
and next
corresponding to the initialization and iteration, respectively.
Available builders
At the moment, TFF provides various builder functions that generate federated computations for federated training and evaluation. Two notable examples include:
tff.learning.algorithms.build_weighted_fed_avg
, which takes as input a model function and a client optimizer , and returns a statefultff.learning.templates.LearningProcess
(which subclassestff.templates.IterativeProcess
).tff.learning.build_federated_evaluation
takes a model function and returns a single federated computation for federated evaluation of models, since evaluation is not stateful.
Datasets
Architectural assumptions
Client selection
In the typical federated learning scenario, we have a large population of potentially hundreds of millions of client devices, of which only a small portion may be active and available for training at any given moment (for example, this may be limited to clients that are plugged in to a power source, not on a metered network, and otherwise idle). Generally, the set of clients available to participate in training or evaluation is outside of the developer's control. Furthermore, as it's impractical to coordinate millions of clients, a typical round of training or evaluation will include only a fraction of the available clients, which may be sampled at random .
The key consequence of this is that federated computations, by design, are expressed in a manner that is oblivious to the exact set of participants; all processing is expressed as aggregate operations on an abstract group of anonymous clients , and that group might vary from one round of training to another. The actual binding of the computation to the concrete participants, and thus to the concrete data they feed into the computation, is thus modeled outside of the computation itself.
In order to simulate a realistic deployment of your federated learning code, you will generally write a training loop that looks like this:
trainer = tff.learning.algorithms.build_weighted_fed_avg(...)
state = trainer.initialize()
federated_training_data = ...
def sample(federate_data):
return ...
while True:
data_for_this_round = sample(federated_training_data)
result = trainer.next(state, data_for_this_round)
state = result.state
In order to facilitate this, when using TFF in simulations, federated data is accepted as Python list
s, with one element per participating client device to represent that device's local tf.data.Dataset
.
Abstract interfaces
In order to standardize dealing with simulated federated data sets, TFF provides an abstract interface tff.simulation.datasets.ClientData
, which allows one to enumerate the set of clients, and to construct a tf.data.Dataset
that contains the data of a particular client. Those tf.data.Dataset
s can be fed directly as input to the generated federated computations in eager mode.
It should be noted that the ability to access client identities is a feature that's only provided by the datasets for use in simulations, where the ability to train on data from specific subsets of clients may be needed (eg, to simulate the diurnal availability of different types of clients). The compiled computations and the underlying runtime do not involve any notion of client identity. Once data from a specific subset of clients has been selected as an input, eg, in a call to tff.templates.IterativeProcess.next
, client identities no longer appear in it.
Available data sets
We have dedicated the namespace tff.simulation.datasets
for datasets that implement the tff.simulation.datasets.ClientData
interface for use in simulations, and seeded it with datasets to support the image classification and text generation tutorials. We'd like to encourage you to contribute your own datasets to the platform.