RSVP per il tuo evento TensorFlow Everywhere locale oggi!
Questa pagina è stata tradotta dall'API Cloud Translation.
Switch to English

Federated Core

Questo documento introduce il livello principale di TFF che funge da base per l' apprendimento federato e possibili futuri algoritmi federati non di apprendimento.

Per una breve introduzione a Federated Core, leggere i seguenti tutorial, poiché introducono alcuni dei concetti fondamentali tramite esempi e dimostrano passo dopo passo la costruzione di un semplice algoritmo di media federato.

Ti invitiamo inoltre a familiarizzare con Federated Learning e le esercitazioni associate sulla classificazione delle immagini e la generazione di testo , poiché gli usi dell'API Federated Core (API FC) per l'apprendimento federato forniscono un contesto importante per alcune delle scelte che abbiamo fatto in progettando questo livello.

Panoramica

Obiettivi, usi previsti e ambito

Federated Core (FC) è meglio inteso come un ambiente di programmazione per l'implementazione di calcoli distribuiti, vale a dire, calcoli che coinvolgono più computer (telefoni cellulari, tablet, dispositivi embedded, computer desktop, sensori, server di database, ecc.) Che possono eseguire ciascuno non elaborazione banale a livello locale e comunicare attraverso la rete per coordinare il proprio lavoro.

Il termine distribuito è molto generico e TFF non si rivolge a tutti i possibili tipi di algoritmi distribuiti là fuori, quindi preferiamo utilizzare il termine meno generico calcolo federato per descrivere i tipi di algoritmi che possono essere espressi in questo framework.

Sebbene la definizione del termine calcolo federato in modo completamente formale esuli dallo scopo di questo documento, pensa ai tipi di algoritmi che potresti vedere espressi in pseudocodice in una pubblicazione di ricerca che descrive un nuovo algoritmo di apprendimento distribuito.

L'obiettivo di FC, in poche parole, è di consentire una rappresentazione compatta in modo simile, a un livello di astrazione simile allo pseudocodice, della logica del programma che non è pseudocodice, ma piuttosto eseguibile in una varietà di ambienti di destinazione.

La caratteristica chiave che definisce i tipi di algoritmi che FC è progettato per esprimere è che le azioni dei partecipanti al sistema sono descritte in modo collettivo. Pertanto, tendiamo a parlare di ogni dispositivo che trasforma localmente i dati e dei dispositivi che coordinano il lavoro da parte di un coordinatore centralizzato che trasmette , raccoglie o aggrega i risultati.

Sebbene TFF sia stato progettato per essere in grado di andare oltre le semplici architetture client-server , la nozione di elaborazione collettiva è fondamentale. Ciò è dovuto alle origini del TFF nell'apprendimento federato, una tecnologia originariamente progettata per supportare calcoli su dati potenzialmente sensibili che rimane sotto il controllo dei dispositivi client e che potrebbe non essere semplicemente scaricata in una posizione centralizzata per motivi di privacy. Sebbene ogni cliente in tali sistemi contribuisca ai dati e alla potenza di elaborazione per l'elaborazione di un risultato da parte del sistema (un risultato che generalmente ci aspetteremmo sia di valore per tutti i partecipanti), ci sforziamo anche di preservare la privacy e l'anonimato di ogni cliente.

Pertanto, mentre la maggior parte dei framework per il calcolo distribuito sono progettati per esprimere l'elaborazione dal punto di vista dei singoli partecipanti, ovvero a livello di scambi di messaggi individuali punto a punto e l'interdipendenza delle transizioni di stato locale del partecipante con i messaggi in entrata e in uscita , Federated Core di TFF è progettato per descrivere il comportamento del sistema dal punto di vista globale del sistema (in modo simile, ad esempio, a MapReduce ).

Di conseguenza, mentre i framework distribuiti per scopi generali possono offrire operazioni come inviare e ricevere come blocchi di costruzione, FC fornisce blocchi di costruzione come tff.federated_sum , tff.federated_reduce o tff.federated_broadcast che incapsulano semplici protocolli distribuiti.

linguaggio

Interfaccia Python

TFF utilizza un linguaggio interno per rappresentare i calcoli federati, la cui sintassi è definita dalla rappresentazione serializzabile in computation.proto . Tuttavia, gli utenti dell'API FC generalmente non devono interagire direttamente con questa lingua. Piuttosto, forniamo un'API Python (lo spazio tff nomi tff ) che lo avvolge come un modo per definire i calcoli.

In particolare, TFF fornisce decoratori di funzioni Python come tff.federated_computation che tracciano i corpi delle funzioni decorate e producono rappresentazioni serializzate della logica di calcolo federato nel linguaggio di TFF. Una funzione decorata con tff.federated_computation funge da vettore di tale rappresentazione serializzata e può incorporarla come blocco tff.federated_computation nel corpo di un altro calcolo o eseguirla su richiesta quando viene invocata.

Ecco solo un esempio; ulteriori esempi possono essere trovati nei tutorial sugli algoritmi personalizzati .

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

I lettori che hanno familiarità con TensorFlow troveranno questo approccio analogo alla scrittura di codice Python che utilizza funzioni come tf.add o tf.reduce_sum in una sezione del codice Python che definisce un grafo TensorFlow. Sebbene il codice sia tecnicamente espresso in Python, il suo scopo è costruire una rappresentazione serializzabile di un tf.Graph sottostante, ed è il grafico, non il codice Python, che viene eseguito internamente dal runtime TensorFlow. Allo stesso modo, si può pensare a tff.federated_mean come a inserire un op federato in un calcolo federato rappresentato da get_average_temperature .

Una parte del motivo per cui FC definisce un linguaggio ha a che fare con il fatto che, come notato sopra, i calcoli federati specificano comportamenti collettivi distribuiti e, come tali, la loro logica non è locale. Ad esempio, TFF fornisce operatori i cui input e output possono esistere in punti diversi della rete.

Ciò richiede un linguaggio e un sistema di tipi che catturino la nozione di distribuzione.

Digitare System

Federated Core offre le seguenti categorie di tipi. Nel descrivere questi tipi, indichiamo i costruttori di tipi e introduciamo una notazione compatta, poiché è un modo pratico o descrive i tipi di calcoli e operatori.

Innanzitutto, ecco le categorie di tipi concettualmente simili a quelli che si trovano nelle lingue tradizionali esistenti:

  • Tipi di tensore ( tff.TensorType ). Proprio come in TensorFlow, questi hanno dtype e shape . L'unica differenza è che gli oggetti di questo tipo non sono limitati a tf.Tensor istanze in Python che rappresentano output di operazioni TensorFlow in un grafico TensorFlow, ma possono anche includere unità di dati che possono essere prodotte, ad esempio, come output di un protocollo di aggregazione. Pertanto, il tipo tensore TFF è semplicemente una versione astratta di una rappresentazione fisica concreta di tale tipo in Python o TensorFlow.

    La notazione compatta per i tipi tensoriali è dtype o dtype[shape] . Ad esempio, int32 e int32[10] sono i tipi di numeri interi e vettori int, rispettivamente.

  • Tipi di sequenza ( tff.SequenceType ). Questi sono l'equivalente astratto di TFF del concetto concreto di TensorFlow ditf.data.Dataset s. Gli elementi delle sequenze possono essere utilizzati in modo sequenziale e possono includere tipi complessi.

    La rappresentazione compatta dei tipi di sequenza è T* , dove T è il tipo di elementi. Ad esempio int32* rappresenta una sequenza intera.

  • Tipi di tupla denominati ( tff.StructType ). Questi sono il modo in cui TFF costruisce tuple e strutture simili a dizionari che hanno un numero predefinito di elementi con tipi specifici, denominati o senza nome. È importante sottolineare che il concetto di tupla denominata di TFF comprende l'equivalente astratto delle tuple degli argomenti di Python, cioè raccolte di elementi di cui alcuni, ma non tutti, sono nominati, e alcuni sono posizionali.

    La notazione compatta per le tuple con nome è <n_1=T_1, ..., n_k=T_k> , dove n_k sono nomi di elementi opzionali e T_k sono tipi di elementi. Ad esempio, <int32,int32> è una notazione compatta per una coppia di interi senza nome e <X=float32,Y=float32> è una notazione compatta per una coppia di float denominati X e Y che possono rappresentare un punto su un piano . Le tuple possono essere annidate così come mescolate con altri tipi, ad esempio, <X=float32,Y=float32>* sarebbe una notazione compatta per una sequenza di punti.

  • Tipi di funzione ( tff.FunctionType ). TFF è un framework di programmazione funzionale, con funzioni trattate come valori di prima classe . Le funzioni hanno al massimo un argomento e esattamente un risultato.

    La notazione compatta per le funzioni è (T -> U) , dove T è il tipo di un argomento e U è il tipo del risultato, o ( -> U) se non ci sono argomenti (sebbene le funzioni senza argomenti siano degenerate concetto che esiste principalmente solo a livello di Python). Ad esempio (int32* -> int32) è una notazione per un tipo di funzioni che riducono una sequenza intera a un singolo valore intero.

I seguenti tipi affrontano l'aspetto dei sistemi distribuiti dei calcoli TFF. Poiché questi concetti sono in qualche modo unici per TFF, ti invitiamo a fare riferimento al tutorial sugli algoritmi personalizzati per ulteriori commenti ed esempi.

  • Tipo di posizionamento . Questo tipo non è ancora esposto nell'API pubblica se non sotto forma di 2 letterali tff.SERVER e tff.CLIENTS che puoi pensare come costanti di questo tipo. Tuttavia, viene utilizzato internamente e verrà introdotto nell'API pubblica nelle versioni future. La rappresentazione compatta di questo tipo è il placement .

    Un posizionamento rappresenta un collettivo di partecipanti al sistema che svolgono un ruolo particolare. La versione iniziale è destinata ai calcoli client-server, in cui sono presenti 2 gruppi di partecipanti: client e un server (si può pensare a quest'ultimo come a un gruppo singleton). Tuttavia, in architetture più elaborate, potrebbero esserci altri ruoli, come aggregatori intermedi in un sistema a più livelli, che potrebbero eseguire diversi tipi di aggregazione o utilizzare diversi tipi di compressione / decompressione dei dati rispetto a quelli utilizzati dal server o i clienti.

    Lo scopo principale della definizione della nozione di posizionamenti è come base per la definizione dei tipi federati .

  • Tipi federati ( tff.FederatedType ). Un valore di un tipo federato è quello ospitato da un gruppo di partecipanti al sistema definiti da un posizionamento specifico (come tff.SERVER o tff.CLIENTS ). Un tipo federato è definito dal valore di posizionamento (quindi, è un tipo dipendente ), dal tipo di componenti membri (che tipo di contenuto ciascuno dei partecipanti ospita localmente) e dal bit aggiuntivo all_equal che specifica se tutti i partecipanti sono localmente ospitare lo stesso oggetto.

    La notazione compatta per il tipo federato di valori che includono elementi (componenti membri) di tipo T , ciascuno ospitato dal gruppo (posizionamento) G è T@G o {T}@G con il bit all_equal impostato o non impostato, rispettivamente.

    Per esempio:

    • {int32}@CLIENTS rappresenta un valore federato costituito da un insieme di numeri interi potenzialmente distinti, uno per dispositivo client. Si noti che stiamo parlando di un singolo valore federato che comprende più elementi di dati che appaiono in più posizioni sulla rete. Un modo per pensarci è come una sorta di tensore con una dimensione "di rete", sebbene questa analogia non sia perfetta perché TFF non consente l'accesso casuale a componenti di un valore federato.

    • {<X=float32,Y=float32>*}@CLIENTS rappresenta un set di dati federato , un valore costituito da più sequenze di coordinate XY , una sequenza per dispositivo client.

    • <weights=float32[10,5],bias=float32[5]>@SERVER rappresenta una tupla con nome di tensori di peso e bias sul server. Poiché abbiamo lasciato cadere le parentesi graffe, questo indica che il bit all_equal è impostato, cioè c'è solo una singola tupla (indipendentemente dal numero di repliche del server che potrebbero esserci in un cluster che ospita questo valore).

Costruzioni

Il linguaggio di Federated Core è una forma di lambda-calcolo , con alcuni elementi aggiuntivi.

Fornisce le seguenti astrazioni di programmazione attualmente esposte nell'API pubblica:

  • tff.tf_computation TensorFlow ( tff.tf_computation ). Queste sono sezioni del codice TensorFlow racchiuse come componenti riutilizzabili in TFF utilizzando il decoratore tff.tf_computation . Hanno sempre tipi funzionali e, a differenza delle funzioni in TensorFlow, possono accettare parametri strutturati o restituire risultati strutturati di un tipo di sequenza.

    Ecco un esempio, un calcolo TF di tipo (int32* -> int) che utilizza l'operatore tf.data.Dataset.reduce per calcolare una somma di interi:

    @tff.tf_computation(tff.SequenceType(tf.int32))
    def add_up_integers(x):
      return x.reduce(np.int32(0), lambda x, y: x + y)
    
  • Intrinseci o operatori federati ( tff.federated_... ). Questa è una libreria di funzioni come tff.federated_sum o tff.federated_broadcast che costituiscono la maggior parte delle API FC, la maggior parte delle quali rappresentano operatori di comunicazione distribuita da utilizzare con TFF.

    Ci riferiamo a questi come intrinseci perché, un po 'come le funzioni intrinseche , sono un insieme aperto ed estensibile di operatori che vengono compresi da TFF e compilati in codice di livello inferiore.

    La maggior parte di questi operatori ha parametri e risultati di tipi federati e la maggior parte sono modelli che possono essere applicati a vari tipi di dati.

    Ad esempio, tff.federated_broadcast può essere pensato come un operatore modello di un tipo funzionale T@SERVER -> T@CLIENTS .

  • Espressioni lambda ( tff.federated_computation ). Un'espressione lambda in TFF è l'equivalente di lambda o def in Python; è costituito dal nome del parametro e da un corpo (espressione) che contiene riferimenti a questo parametro.

    Nel codice Python, questi possono essere creati decorando le funzioni Python con tff.federated_computation e definendo un argomento.

    Ecco un esempio di un'espressione lambda che abbiamo già menzionato in precedenza:

    @tff.federated_computation(tff.type_at_clients(tf.float32))
    def get_average_temperature(sensor_readings):
      return tff.federated_mean(sensor_readings)
    
  • Letterali di posizionamento . Per ora, solo tff.SERVER e tff.CLIENTS per consentire la definizione di semplici calcoli client-server.

  • __call__ funzioni ( __call__ ). Tutto ciò che ha un tipo funzionale può essere invocato usando la sintassi standard di Python __call__ . L'invocazione è un'espressione, il cui tipo è uguale al tipo del risultato della funzione invocata.

    Per esempio:

    • add_up_integers(x) rappresenta un'invocazione del calcolo TensorFlow definito in precedenza su un argomento x . Il tipo di questa espressione è int32 .

    • tff.federated_mean(sensor_readings) rappresenta un'invocazione dell'operatore di media federato su sensor_readings . Il tipo di questa espressione è float32@SERVER (presupponendo il contesto dell'esempio precedente).

  • Formazione di tuple e selezione dei loro elementi. Espressioni Python nella forma [x, y] , x[y] o xy che appaiono nei corpi delle funzioni decorate con tff.federated_computation .