Google I/O est terminé ! Suivez les sessions TensorFlow Afficher les sessions

Noyau fédéré

Ce document présente la couche de base de TFF qui sert de base pour l' apprentissage fédéré , et les algorithmes futurs possibles fédérées non-apprentissage.

Pour une introduction en douceur à Federated Core, veuillez lire les didacticiels suivants, car ils présentent certains des concepts fondamentaux par l'exemple et illustrent étape par étape la construction d'un algorithme de moyenne fédérée simple.

Nous vous encourageons également à vous familiariser avec l' apprentissage fédéré et les tutoriels associés sur la classification d'images et génération de texte , comme l'utilisation de l'API de base fédérée (API FC) pour l' apprentissage fédéré fournissent un contexte important pour certains des choix que nous avons fait dans concevoir cette couche.

Aperçu

Objectifs, utilisations prévues et portée

Federated Core (FC) est mieux compris comme un environnement de programmation pour la mise en œuvre de calculs distribués, c'est-à-dire des calculs qui impliquent plusieurs ordinateurs (téléphones mobiles, tablettes, appareils intégrés, ordinateurs de bureau, capteurs, serveurs de bases de données, etc.) qui peuvent chacun effectuer des opérations non- traitement trivial localement, et communiquent à travers le réseau pour coordonner leur travail.

Le terme distribué est très générique et TFF ne vise pas tous les types possibles d'algorithmes distribués là - bas, donc nous préférons utiliser le terme moins générique calcul fédéré pour décrire les types d'algorithmes qui peuvent être exprimés dans ce cadre.

Lors de la définition du terme calcul fédéré d'une manière totalement formelle est en dehors de la portée de ce document, penser aux types d'algorithmes que vous pourriez voir exprimés en pseudocode dans une publication de recherche qui décrit un nouvel algorithme d' apprentissage distribué.

Le but de FC, dans un nusthell, est de permettre une représentation compacte de la même, à un même niveau d'abstraction comme pseudo - code, de la logique de programme qui ne pseudocode, mais plutôt, qui est exécutable dans une variété d'environnements cibles.

La principale caractéristique définissant les types d'algorithmes que FC est conçu pour exprimer est que les actions des participants au système sont décrites de manière collective. , Nous avons donc tendance à parler de chaque appareil transformation des données localement, et les dispositifs de coordination travail par une diffusion de coordonnateur centralisé, la collecte, l' agrégation ou leurs résultats.

Alors que TFF a été conçu pour être en mesure d'aller au - delà de simples architectures client-serveur, la notion de traitement collective est fondamentale. Cela est dû aux origines de TFF dans l'apprentissage fédéré, une technologie conçue à l'origine pour prendre en charge les calculs sur des données potentiellement sensibles qui restent sous le contrôle des appareils clients, et qui ne peuvent pas être simplement téléchargées vers un emplacement centralisé pour des raisons de confidentialité. Bien que chaque client dans de tels systèmes fournisse des données et une puissance de traitement pour le calcul d'un résultat par le système (un résultat que l'on s'attend généralement à ce qu'il soit utile à tous les participants), nous nous efforçons également de préserver la confidentialité et l'anonymat de chaque client.

Ainsi, alors que la plupart des frameworks pour l'informatique distribuée sont conçus pour exprimer le traitement du point de vue des participants individuels - c'est-à-dire au niveau des échanges de messages point à point individuels, et l'interdépendance des transitions d'état local du participant avec les messages entrants et sortants , fédérés de TFF de base est conçu pour décrire le comportement du système dans la perspective globale du système à l' échelle (tout comme, par exemple, MapReduce ).

Par conséquent, alors que les cadres distribués à des fins générales peuvent offrir des opérations telles que l' envoi et recevoir comme des blocs de construction, le FC fournit des blocs de construction tels que tff.federated_sum , tff.federated_reduce ou tff.federated_broadcast que simple encapsulent protocoles distribués.

Langue

Interface Python

TFF utilise un langage interne pour représenter les calculs fédérés, dont la syntaxe est définie par la représentation serializable dans computation.proto . Cependant, les utilisateurs de l'API FC n'auront généralement pas besoin d'interagir directement avec ce langage. Au contraire, nous fournissons une API Python (le tff d'espace de noms) qui enveloppe contournements comme un moyen de définir des calculs.

Plus précisément, TFF fournit des décorateurs de fonctions Python tels que tff.federated_computation qui trace les corps des fonctions décorées et produire des représentations sérialisée de la logique de calcul fédérée dans la langue de TFF. Une fonction décorée avec tff.federated_computation agit comme support d' une telle représentation sérialisée, et peut l' intégrer comme un bloc de construction dans le corps d'un autre calcul, ou l' exécuter à la demande lorsqu'elle est invoquée.

Voici juste un exemple ; d' autres exemples peuvent être trouvés dans les algorithmes personnalisés tutoriels.

@tff.federated_computation(tff.type_at_clients(tf.float32))
def get_average_temperature(sensor_readings):
  return tff.federated_mean(sensor_readings)

Les lecteurs familiers avec tensorflow non désireux trouveront cette approche analogue à l' écriture du code Python qui utilise des fonctions telles que tf.add ou tf.reduce_sum dans une section de code Python qui définit un graphe de tensorflow. Bien que le code est techniquement exprimée en python, son but est de construire une représentation d'un serializable tf.Graph dessous, et il est le graphique, pas le code Python, qui est exécuté en interne par le moteur d'exécution tensorflow. De même, on peut penser à tff.federated_mean que l' insertion d' une op fédérée dans un calcul fédéré représenté par get_average_temperature .

Une partie de la raison pour laquelle FC définit un langage est liée au fait que, comme indiqué ci-dessus, les calculs fédérés spécifient des comportements collectifs distribués et, en tant que tels, leur logique est non locale. Par exemple, TFF met à disposition des opérateurs dont les entrées et sorties peuvent exister à différents endroits du réseau.

Cela nécessite un langage et un système de types qui capturent la notion de distribution.

Type Système

Federated Core propose les catégories de types suivantes. En décrivant ces types, nous soulignons les constructeurs de types et introduisons une notation compacte, car c'est un moyen pratique de décrire des types de calculs et d'opérateurs.

Tout d'abord, voici les catégories de types qui sont conceptuellement similaires à ceux trouvés dans les langages traditionnels existants :

  • Types Tensor ( tff.TensorType ). Tout comme dans tensorflow, ceux - ci ont dtype et shape . La seule différence est que les objets de ce type ne sont pas limités à tf.Tensor cas en Python qui représentent les sorties des opérations tensorflow dans un graphique de tensorflow, mais peut également comprendre des unités de données qui peuvent être produites, par exemple, en tant que sortie d'une distribution protocole d'agrégation. Ainsi, le type de tenseur TFF est simplement une version abstraite d'une représentation physique concrète d'un tel type en Python ou TensorFlow.

    De TFF TensorTypes peuvent être plus strictes dans leur (statique) traitement des formes que tensorflow. Par exemple, les traite typesystem de TFF un tenseur de rang inconnu assignable de tout autre tenseur du même dtype , mais pas affectables à un tenseur de rang fixe. Ce traitement évite certains échecs d'exécution (par exemple, tenter de remodeler un tenseur de rang inconnu en une forme avec un nombre incorrect d'éléments), au prix d'une plus grande rigueur dans les calculs que TFF accepte comme valides.

    La notation compacte pour les types de tenseur est dtype ou dtype[shape] . Par exemple, int32 et int32[10] sont les types d'entiers et des vecteurs int, respectivement.

  • Types de séquence ( tff.SequenceType ). Ceux - ci sont équivalents abstraits de TFF du concept de béton de tensorflow de tf.data.Dataset s. Les éléments de séquences peuvent être consommés de manière séquentielle et peuvent inclure des types complexes.

    La représentation compacte des types de séquence est T* , où T est le type d'éléments. Par exemple int32* représente une séquence de nombres entiers.

  • Nommés types de tuple ( tff.StructType ). Ce sont la manière de TFF de construire tuples et dictionnaire comme des structures qui ont un nombre prédéfini d'éléments avec des types de spécifiques, nommées ou non. Il est important de noter que le concept de tuple nommé de TFF englobe l'équivalent abstrait des tuples d'argument de Python, c'est-à-dire des collections d'éléments dont certains, mais pas tous, sont nommés, et certains sont positionnels.

    La notation compacte pour tuples est nommé <n_1=T_1, ..., n_k=T_k> , où n_k sont les noms d'éléments optionnels et T_k sont les types d'éléments. Par exemple, <int32,int32> est une notation compacte pour une paire de nombres entiers non identifiés, et <X=float32,Y=float32> est une notation compacte pour une paire de flotteurs nommé X et Y qui peuvent représenter un point dans un plan . Tuples peuvent être imbriquées, ainsi que d' autres types mélangés avec, par exemple, <X=float32,Y=float32>* serait une notation compacte pour une séquence de points.

  • Types de fonction ( tff.FunctionType ). TFF est un cadre de programmation fonctionnelle, avec des fonctions traitées comme des valeurs de première classe . Les fonctions ont au plus un argument et exactement un résultat.

    La notation compacte pour les fonctions est (T -> U) , où T est le type d'un argument, et U est le type du résultat, ou ( -> U) s'il n'y a pas d' argument (bien que les fonctions sans argument sont un dégénéré concept qui n'existe principalement qu'au niveau Python). Par exemple (int32* -> int32) est une notation pour un type de fonctions qui permettent de réduire une séquence de nombre entier à une seule valeur de nombre entier.

Les types suivants traitent de l'aspect des systèmes distribués des calculs TFF. Étant donné que ces concepts sont un peu unique de TFF, nous vous encourageons à consulter les algorithmes personnalisés tutoriel pour des commentaires supplémentaires et des exemples.

  • Type de placement. Ce type n'a pas encore été exposé dans l'API publique autre que sous la forme de 2 littéraux tff.SERVER et tff.CLIENTS que vous pouvez considérer comme des constantes de ce type. Il est cependant utilisé en interne et sera introduit dans l'API publique dans les prochaines versions. La représentation compacte de ce type est placement en placement .

    Un placement représente un collectif des participants au système qui jouent un rôle particulier. La version initiale vise les calculs client-serveur, dans lequel il y a 2 groupes de participants: les clients et un serveur (vous pouvez penser de ce dernier en tant que groupe singleton). Cependant, dans des architectures plus élaborées, il pourrait y avoir d'autres rôles, tels que des agrégateurs intermédiaires dans un système à plusieurs niveaux, qui pourraient effectuer différents types d'agrégation, ou utiliser des types de compression/décompression de données différents de ceux utilisés par le serveur ou les clients.

    L'objectif principal de définir la notion de placements est comme base pour la définition des types fédérés.

  • Types fédérés ( tff.FederatedType ). Une valeur d'un type fédéré est celui qui est hébergé par un groupe de participants au système défini par un emplacement spécifique (comme tff.SERVER ou tff.CLIENTS ). Un type fédéré est défini par la valeur de placement (ainsi, il est un type dépendant ), le type de composants membres (quel type de contenu chacun des participants est l' hôte local) et le bit supplémentaire all_equal indiquant si tous les participants sont localement hébergeant le même élément.

    La notation compacte pour le type fédéré de valeurs qui comprennent des éléments (constituants membres) de type T , chacun hébergé par groupe (placement) G est T@G ou {T}@G avec le all_equal bit ou non défini, respectivement.

    Par exemple:

    • {int32}@CLIENTS représente une valeur fédérée qui se compose d'un ensemble d'entiers potentiellement distincts, un par dispositif client. Notez que nous parlons d'une seule valeur fédérée comme englobant plusieurs éléments de données qui apparaissent dans plusieurs endroits à travers le réseau. Une façon de penser est comme une sorte de tenseur avec une dimension « réseau », bien que cette analogie est pas parfait , car TFF ne permet l' accès aléatoire aux électeurs membres d'une valeur fédérée.

    • {<X=float32,Y=float32>*}@CLIENTS représente un ensemble de données fédérée, une valeur qui se compose de plusieurs séquences de XY coordonnées, une séquence par machine cliente.

    • <weights=float32[10,5],bias=float32[5]>@SERVER représente un tuple nommé de tenseurs de poids et de biais au niveau du serveur. Depuis que nous avons laissé tomber les accolades, cela indique le all_equal bit est défini, par exemple, il n'y a qu'un seul tuple (quel que soit le nombre de serveurs répliques qu'il pourrait y avoir dans un cluster d' hébergement de cette valeur).

Blocs de construction

La langue de base fédérée est une forme de lambda-calcul , avec quelques éléments supplémentaires.

Il fournit les abstractions de programmation suivantes actuellement exposées dans l'API publique :

  • Tensorflow calculs ( tff.tf_computation ). Ce sont des sections de code tensorflow enveloppé comme composants réutilisables dans TFF en utilisant le tff.tf_computation décorateur. Ils ont toujours des types fonctionnels et, contrairement aux fonctions de TensorFlow, ils peuvent prendre des paramètres structurés ou renvoyer des résultats structurés d'un type de séquence.

    Voici un exemple, un calcul de TF de type (int32* -> int) qui utilise le tf.data.Dataset.reduce opérateur pour calculer une somme des entiers:

    @tff.tf_computation(tff.SequenceType(tf.int32))
    def add_up_integers(x):
      return x.reduce(np.int32(0), lambda x, y: x + y)
    
  • Intrinsics ou opérateurs fédérés ( tff.federated_... ). Ceci est une bibliothèque de fonctions telles que tff.federated_sum ou tff.federated_broadcast qui constituent la majeure partie de l' API FC, dont la plupart représentent distribué des opérateurs de communication pour une utilisation avec TFF.

    Nous nous référons à ces derniers comme intrinsics parce que, un peu comme les fonctions intrinsèques , ils sont une composition non limitée, ensemble extensible d'opérateurs qui sont compris par TFF, et compilé vers le bas dans le code de niveau inférieur.

    La plupart de ces opérateurs ont des paramètres et des résultats de types fédérés, et la plupart sont des modèles qui peuvent être appliqués à différents types de données.

    Par exemple, tff.federated_broadcast peut être considéré comme un opérateur de modèle d'un type fonctionnel T@SERVER -> T@CLIENTS .

  • Les expressions lambda ( tff.federated_computation ). Une expression lambda dans la FFT est l'équivalent d'un lambda ou def dans le python; il se compose du nom du paramètre et d'un corps (expression) qui contient des références à ce paramètre.

    Dans le code Python, ceux - ci peuvent être créés par la décoration de fonctions Python avec tff.federated_computation et définissant un argument.

    Voici un exemple d'expression lambda que nous avons déjà mentionné précédemment :

    @tff.federated_computation(tff.type_at_clients(tf.float32))
    def get_average_temperature(sensor_readings):
      return tff.federated_mean(sensor_readings)
    
  • Littéraux de placement. Pour l' instant, seulement tff.SERVER et tff.CLIENTS pour permettre de définir des calculs simples client-serveur.

  • Invocations de fonction ( __call__ ). Tout ce qui a un type fonctionnel peut être invoqué en utilisant la norme Python __call__ syntaxe. L'invocation est une expression dont le type est le même que le type du résultat de la fonction invoquée.

    Par exemple:

    • add_up_integers(x) représente une invocation du calcul de tensorflow défini plus haut sur un argument x . Le type de cette expression est int32 .

    • tff.federated_mean(sensor_readings) représente une invocation de l'opérateur fédéré de moyenne sur sensor_readings . Le type de cette expression est float32@SERVER ( en supposant le contexte de l'exemple ci - dessus).

  • La formation tuples et sélectionner leurs éléments. Expressions Python de la forme [x, y] , x[y] , ou xy qui apparaissent dans les corps des fonctions décorées avec tff.federated_computation .