Apprendimento federato

Panoramica

Questo documento introduce interfacce che facilitano le attività di apprendimento federato, come la formazione federata o la valutazione con modelli di machine learning esistenti implementati in TensorFlow. Nel progettare queste interfacce, il nostro obiettivo principale era rendere possibile la sperimentazione dell'apprendimento federato senza richiedere la conoscenza di come funziona dietro le quinte e valutare gli algoritmi di apprendimento federato implementati su una varietà di modelli e dati esistenti. Ti invitiamo a contribuire nuovamente alla piattaforma. TFF è stato progettato pensando all'estensibilità e alla componibilità e accogliamo con favore i contributi; siamo entusiasti di vedere cosa inventerai!

Le interfacce offerte da questo livello sono costituite dalle seguenti tre parti chiave:

  • Modelli . Classi e funzioni helper che consentono di racchiudere i modelli esistenti da utilizzare con TFF. Il wrapper di un modello può essere semplice come richiamare una singola funzione di wrapper (ad esempio, tff.learning.models.from_keras_model ) o definire una sottoclasse dell'interfaccia tff.learning.models.VariableModel per una completa personalizzazione.

  • Costruttori di calcolo federati . Funzioni di supporto che creano calcoli federati per l'addestramento o la valutazione, utilizzando i modelli esistenti.

  • Set di dati . Raccolte predefinite di dati che è possibile scaricare e a cui è possibile accedere in Python per l'utilizzo nella simulazione di scenari di apprendimento federati. Sebbene l’apprendimento federato sia progettato per l’uso con dati decentralizzati che non possono essere semplicemente scaricati in una posizione centralizzata, nelle fasi di ricerca e sviluppo è spesso conveniente condurre esperimenti iniziali utilizzando dati che possono essere scaricati e manipolati localmente, soprattutto per gli sviluppatori che potrebbero essere nuovo per l'approccio.

Queste interfacce sono definite principalmente nello spazio dei nomi tff.learning , ad eccezione dei set di dati di ricerca e di altre funzionalità relative alla simulazione che sono state raggruppate in tff.simulation . Questo livello viene implementato utilizzando le interfacce di livello inferiore offerte dal Federated Core (FC) , che fornisce anche un ambiente runtime.

Prima di procedere, ti consigliamo di rivedere i tutorial sulla classificazione delle immagini e sulla generazione del testo , poiché introducono la maggior parte dei concetti qui descritti utilizzando esempi concreti. Se sei interessato a saperne di più su come funziona TFF, potresti voler dare un'occhiata al tutorial sugli algoritmi personalizzati come introduzione alle interfacce di livello inferiore che utilizziamo per esprimere la logica dei calcoli federati e studiare l'implementazione esistente del interfacce tff.learning .

Modelli

Ipotesi architettoniche

Serializzazione

TFF mira a supportare una varietà di scenari di apprendimento distribuito in cui il codice del modello di machine learning scritto potrebbe essere eseguito su un gran numero di client eterogenei con funzionalità diverse. Mentre a un'estremità dello spettro, in alcune applicazioni questi client potrebbero essere potenti server di database, molti usi importanti che la nostra piattaforma intende supportare coinvolgono dispositivi mobili e integrati con risorse limitate. Non possiamo presumere che questi dispositivi siano in grado di ospitare runtime Python; l'unica cosa che possiamo supporre a questo punto è che siano in grado di ospitare un runtime TensorFlow locale. Pertanto, un presupposto architettonico fondamentale che facciamo in TFF è che il codice del modello deve essere serializzabile come grafico TensorFlow.

Puoi (e dovresti) continuare a sviluppare il tuo codice TF seguendo le migliori pratiche più recenti come l'utilizzo della modalità desiderosa. Tuttavia, il codice finale deve essere serializzabile (ad esempio, può essere racchiuso come una tf.function per il codice in modalità desiderosa). Ciò garantisce che qualsiasi stato Python o flusso di controllo necessario al momento dell'esecuzione possa essere serializzato (possibilmente con l'aiuto di Autograph ).

Attualmente, TensorFlow non supporta completamente la serializzazione e la deserializzazione di TensorFlow in modalità desiderosa. Pertanto, la serializzazione in TFF attualmente segue il modello TF 1.0, in cui tutto il codice deve essere costruito all'interno di un tf.Graph controllato da TFF. Ciò significa che attualmente TFF non può consumare un modello già costruito; invece, la logica di definizione del modello è racchiusa in una funzione no-arg che restituisce un tff.learning.models.VariableModel . Questa funzione viene quindi richiamata da TFF per garantire che tutti i componenti del modello siano serializzati. Inoltre, essendo un ambiente fortemente tipizzato, TFF richiederà alcuni metadati aggiuntivi, come una specifica del tipo di input del modello.

Aggregazione

Consigliamo vivamente alla maggior parte degli utenti di costruire modelli utilizzando Keras, vedere la sezione Convertitori per Keras di seguito. Questi wrapper gestiscono automaticamente l'aggregazione degli aggiornamenti del modello e qualsiasi metrica definita per il modello. Tuttavia, potrebbe essere comunque utile comprendere come viene gestita l'aggregazione per un tff.learning.models.VariableModel generale.

Ci sono sempre almeno due livelli di aggregazione nell'apprendimento federato: aggregazione locale sul dispositivo e aggregazione tra dispositivi (o federata):

  • Aggregazione locale . Questo livello di aggregazione si riferisce all'aggregazione tra più batch di esempi di proprietà di un singolo cliente. Si applica sia ai parametri del modello (variabili), che continuano ad evolversi in sequenza man mano che il modello viene addestrato localmente, sia alle statistiche calcolate (come perdita media, precisione e altri parametri), che il modello aggiornerà nuovamente localmente mentre esegue l'iterazione sul flusso di dati locale di ogni singolo client.

    L'esecuzione dell'aggregazione a questo livello è responsabilità del codice del modello e viene eseguita utilizzando i costrutti TensorFlow standard.

    La struttura generale del trattamento è la seguente:

    • Il modello costruisce innanzitutto tf.Variable s per contenere aggregati, come il numero di batch o il numero di esempi elaborati, la somma delle perdite per batch o per esempio, ecc.

    • TFF richiama il metodo forward_pass sul tuo Model più volte, in sequenza su batch successivi di dati del cliente, che ti consente di aggiornare le variabili che contengono vari aggregati come effetto collaterale.

    • Infine, TFF richiama il metodo report_local_unfinalized_metrics sul tuo modello per consentire al tuo modello di compilare tutte le statistiche di riepilogo raccolte in un insieme compatto di parametri da esportare dal client. È qui che il codice modello può, ad esempio, dividere la somma delle perdite per il numero di esempi elaborati per esportare la perdita media, ecc.

  • Aggregazione federata . Questo livello di aggregazione si riferisce all'aggregazione tra più client (dispositivi) nel sistema. Ancora una volta, si applica sia ai parametri del modello (variabili), di cui viene calcolata la media tra i client, sia alle metriche esportate dal modello come risultato dell'aggregazione locale.

    L'esecuzione dell'aggregazione a questo livello è responsabilità del TFF. In qualità di creatore di modelli, tuttavia, puoi controllare questo processo (ne parleremo più avanti).

    La struttura generale del trattamento è la seguente:

    • Il modello iniziale e tutti i parametri richiesti per la formazione vengono distribuiti da un server a un sottoinsieme di client che parteciperanno a un ciclo di formazione o valutazione.

    • Su ciascun client, indipendentemente e in parallelo, il codice del modello viene richiamato ripetutamente su un flusso di batch di dati locali per produrre un nuovo set di parametri del modello (durante l'addestramento) e un nuovo set di metriche locali, come descritto sopra (questo è locale aggregazione).

    • TFF esegue un protocollo di aggregazione distribuita per accumulare e aggregare i parametri del modello e le metriche esportate localmente nel sistema. Questa logica è espressa in modo dichiarativo utilizzando il linguaggio di calcolo federato di TFF (non in TensorFlow). Consulta il tutorial sugli algoritmi personalizzati per ulteriori informazioni sull'API di aggregazione.

Interfacce astratte

Questo costruttore di base + interfaccia metadati è rappresentato dall'interfaccia tff.learning.models.VariableModel , come segue:

  • I metodi costruttore, forward_pass e report_local_unfinalized_metrics dovrebbero costruire le variabili del modello, il forward pass e le statistiche che desideri segnalare, di conseguenza. Il TensorFlow costruito con questi metodi deve essere serializzabile, come discusso sopra.

  • La proprietà input_spec , così come le 3 proprietà che restituiscono sottoinsiemi delle variabili addestrabili, non addestrabili e locali rappresentano i metadati. TFF utilizza queste informazioni per determinare come connettere parti del modello agli algoritmi di ottimizzazione federati e per definire firme di tipo interne per assistere nella verifica della correttezza del sistema costruito (in modo che il modello non possa essere istanziato su dati che non corrispondono a ciò il modello è progettato per consumare).

Inoltre, l'interfaccia astratta tff.learning.models.VariableModel espone una proprietà metric_finalizers che accetta i valori non finalizzati di una metrica (restituiti da report_local_unfinalized_metrics() ) e restituisce i valori della metrica finalizzati. Il metodo metric_finalizers e report_local_unfinalized_metrics() verranno utilizzati insieme per creare un aggregatore di parametri tra client durante la definizione dei processi di formazione federati o dei calcoli di valutazione. Ad esempio, un semplice aggregatore tff.learning.metrics.sum_then_finalize sommerà prima i valori metrici non finalizzati dai client, quindi chiamerà le funzioni del finalizzatore sul server.

Puoi trovare esempi di come definire il tuo tff.learning.models.VariableModel personalizzato nella seconda parte del nostro tutorial sulla classificazione delle immagini , nonché nei modelli di esempio che utilizziamo per i test in model_examples.py .

Convertitori per Keras

Quasi tutte le informazioni richieste da TFF possono essere derivate chiamando le interfacce tf.keras , quindi se disponi di un modello Keras, puoi fare affidamento su tff.learning.models.from_keras_model per costruire un tff.learning.models.VariableModel .

Tieni presente che TFF desidera comunque che tu fornisca un costruttore, una funzione del modello senza argomenti come la seguente:

def model_fn():
  keras_model = ...
  return tff.learning.models.from_keras_model(keras_model, sample_batch, loss=...)

Oltre al modello stesso, fornisci un campione di dati che TFF utilizza per determinare il tipo e la forma dell'input del tuo modello. Ciò garantisce che TFF possa istanziare correttamente il modello per i dati che saranno effettivamente presenti sui dispositivi client (poiché presumiamo che questi dati non siano generalmente disponibili nel momento in cui stai costruendo TensorFlow da serializzare).

L'uso dei wrapper Keras è illustrato nei nostri tutorial sulla classificazione delle immagini e sulla generazione del testo .

Costruttori di calcoli federati

Il pacchetto tff.learning fornisce diversi builder per tff.Computation che eseguono attività relative all'apprendimento; ci aspettiamo che l'insieme di tali calcoli si espanda in futuro.

Ipotesi architettoniche

Esecuzione

Esistono due fasi distinte nell'esecuzione di un calcolo federato.

  • Compilazione : TFF compila innanzitutto gli algoritmi di apprendimento federato in una rappresentazione serializzata astratta dell'intero calcolo distribuito. Questo è il momento in cui avviene la serializzazione di TensorFlow, ma possono verificarsi altre trasformazioni per supportare un'esecuzione più efficiente. Ci riferiamo alla rappresentazione serializzata emessa dal compilatore come calcolo federato .

  • Execute TFF fornisce modi per eseguire questi calcoli. Per ora, l'esecuzione è supportata solo tramite una simulazione locale (ad esempio, in un notebook utilizzando dati decentralizzati simulati).

Un calcolo federato generato dalla Federated Learning API di TFF, come un algoritmo di training che utilizza la media del modello federato o una valutazione federata, include una serie di elementi, in particolare:

  • Una forma serializzata del codice del modello e codice TensorFlow aggiuntivo costruito dal framework Federated Learning per guidare il ciclo di addestramento/valutazione del modello (come la costruzione di ottimizzatori, l'applicazione di aggiornamenti del modello, l'iterazione su tf.data.Dataset e il calcolo delle metriche, e applicando l'aggiornamento aggregato sul server, solo per citarne alcuni).

  • Una specifica dichiarativa della comunicazione tra i client e un server (tipicamente varie forme di aggregazione tra i dispositivi client e trasmissione dal server a tutti i client) e il modo in cui questa comunicazione distribuita è interlacciata con l'esecuzione locale del client o del server del codice TensorFlow.

I calcoli federati rappresentati in questo modulo serializzato sono espressi in un linguaggio interno indipendente dalla piattaforma distinto da Python, ma per utilizzare la Federated Learning API non dovrai preoccuparti dei dettagli di questa rappresentazione. I calcoli sono rappresentati nel codice Python come oggetti di tipo tff.Computation , che per la maggior parte è possibile trattare come callable Python opache.

Nei tutorial, invocherai questi calcoli federati come se fossero normali funzioni Python, da eseguire localmente. Tuttavia, TFF è progettato per esprimere calcoli federati in modo indipendente dalla maggior parte degli aspetti dell'ambiente di esecuzione, in modo che possano essere potenzialmente implementabili, ad esempio, su gruppi di dispositivi che eseguono Android o su cluster in un data center. Ancora una volta, la conseguenza principale di ciò sono forti presupposti sulla serializzazione . In particolare, quando si richiama uno dei metodi build_... descritti di seguito, il calcolo viene completamente serializzato.

Stato di modellazione

TFF è un ambiente di programmazione funzionale, tuttavia molti processi di interesse nell’apprendimento federato sono stateful. Ad esempio, un ciclo di addestramento che coinvolge più cicli di media del modello federato è un esempio di ciò che potremmo classificare come processo con stato . In questo processo, lo stato che evolve da un ciclo all'altro include l'insieme di parametri del modello che vengono addestrati e possibilmente uno stato aggiuntivo associato all'ottimizzatore (ad esempio, un vettore di quantità di moto).

Poiché TFF è funzionale, i processi con stato sono modellati in TFF come calcoli che accettano lo stato corrente come input e quindi forniscono lo stato aggiornato come output. Per definire completamente un processo con stato, è necessario anche specificare da dove proviene lo stato iniziale (altrimenti non possiamo avviare il processo). Questo viene catturato nella definizione della classe helper tff.templates.IterativeProcess , con le 2 proprietà initialize e next corrispondenti rispettivamente all'inizializzazione e all'iterazione.

Costruttori disponibili

Al momento, TFF fornisce varie funzioni di builder che generano calcoli federati per la formazione e la valutazione federate. Due esempi notevoli includono:

Set di dati

Ipotesi architettoniche

Selezione del cliente

Nel tipico scenario di apprendimento federato, abbiamo una vasta popolazione potenzialmente di centinaia di milioni di dispositivi client, di cui solo una piccola parte può essere attiva e disponibile per la formazione in un dato momento (ad esempio, ciò potrebbe essere limitata ai client che sono collegato a una fonte di alimentazione, non a una rete a consumo e altrimenti inattivo). In genere, l'insieme di client disponibili per partecipare alla formazione o alla valutazione è fuori dal controllo dello sviluppatore. Inoltre, poiché non è pratico coordinare milioni di clienti, un tipico ciclo di formazione o valutazione includerà solo una frazione dei clienti disponibili, che potrebbero essere campionati in modo casuale .

La conseguenza principale di ciò è che i calcoli federati, in base alla progettazione, sono espressi in un modo che ignora l'esatto insieme di partecipanti; tutta l'elaborazione è espressa come operazioni aggregate su un gruppo astratto di clienti anonimi e tale gruppo può variare da un ciclo di formazione all'altro. Il legame effettivo del calcolo con i partecipanti concreti, e quindi con i dati concreti che inseriscono nel calcolo, è quindi modellato al di fuori del calcolo stesso.

Per simulare una distribuzione realistica del tuo codice di apprendimento federato, generalmente scriverai un ciclo di formazione simile a questo:

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

Per facilitare ciò, quando si utilizza TFF nelle simulazioni, i dati federati vengono accettati come list Python, con un elemento per dispositivo client partecipante per rappresentare tf.data.Dataset locale di quel dispositivo.

Interfacce astratte

Per standardizzare la gestione dei set di dati federati simulati, TFF fornisce un'interfaccia astratta tff.simulation.datasets.ClientData , che consente di enumerare l'insieme di client e di costruire un tf.data.Dataset che contiene i dati di un particolare cliente. Tali tf.data.Dataset possono essere forniti direttamente come input ai calcoli federati generati in modalità desiderosa.

Va notato che la capacità di accedere alle identità dei clienti è una funzionalità fornita solo dai set di dati per l'uso nelle simulazioni, dove potrebbe essere necessaria la capacità di addestrarsi sui dati di sottoinsiemi specifici di clienti (ad esempio, per simulare la disponibilità diurna di diversi tipologie di clienti). I calcoli compilati e il runtime sottostante non implicano alcuna nozione di identità del client. Una volta che i dati di uno specifico sottoinsieme di client sono stati selezionati come input, ad esempio, in una chiamata a tff.templates.IterativeProcess.next , le identità del client non appaiono più al suo interno.

Set di dati disponibili

Abbiamo dedicato lo spazio dei nomi tff.simulation.datasets per i set di dati che implementano l'interfaccia tff.simulation.datasets.ClientData da utilizzare nelle simulazioni e lo abbiamo seminato con set di dati per supportare i tutorial sulla classificazione delle immagini e sulla generazione di testo . Vorremmo incoraggiarti a contribuire con i tuoi set di dati alla piattaforma.