Apprendimento federato

Panoramica

Questo documento introduce le interfacce che facilitano le attività di apprendimento federato, come la formazione federata o la valutazione con i modelli di machine learning esistenti implementati in TensorFlow. Nella progettazione di queste interfacce, il nostro obiettivo principale era quello di rendere possibile sperimentare l'apprendimento federato senza richiedere la conoscenza di come funziona sotto il cofano e di 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'estendibilità e alla componibilità e accogliamo con favore i contributi; siamo entusiasti di vedere cosa ti viene in mente!

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

  • Modelli . Classi e funzioni di supporto che ti consentono di avvolgere i tuoi modelli esistenti per l'uso con TFF. Il wrapping di un modello può essere semplice come chiamare una singola funzione di wrapping (ad esempio, tff.learning.from_keras_model ), o definire una sottoclasse dell'interfaccia tff.learning.Model per una completa personalizzazione.

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

  • Set di dati . Raccolte predefinite di dati che puoi scaricare e accedere in Python per l'uso nella simulazione di scenari di apprendimento federato. 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 interfacce di livello inferiore offerte da Federated Core (FC) , che fornisce anche un ambiente di 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 sfogliare il tutorial sugli algoritmi personalizzati come introduzione alle interfacce di livello inferiore che utilizziamo per esprimere la logica dei calcoli federati e per studiare l'implementazione esistente del tff.learning .

Modelli

Presupposti architettonici

Serializzazione

TFF mira a supportare una varietà di scenari di apprendimento distribuito in cui il codice del modello di apprendimento automatico che scrivi potrebbe essere eseguito su un gran numero di client eterogenei con capacità diverse. Mentre a un'estremità dello spettro, in alcune applicazioni quei client potrebbero essere potenti server di database, molti usi importanti che la nostra piattaforma intende supportare coinvolgono dispositivi mobili ed embedded con risorse limitate. Non possiamo presumere che questi dispositivi siano in grado di ospitare runtime Python; l'unica cosa che possiamo presumere a questo punto è che siano in grado di ospitare un runtime TensorFlow locale. Pertanto, un presupposto architettonico fondamentale che assumiamo 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 ultime best practice come l'utilizzo della modalità desiderosa. Tuttavia, il codice finale deve essere serializzabile (ad esempio, può essere racchiuso come una tf.function . per 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 segue attualmente 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 è contenuta in una funzione no-arg che restituisce un tff.learning.Model . Questa funzione viene quindi chiamata da TFF per garantire che tutti i componenti del modello siano serializzati. Inoltre, essendo un ambiente fortemente tipizzato, TFF richiederà un po' di metadati aggiuntivi, ad esempio una specifica del tipo di input del modello.

Aggregazione

Consigliamo vivamente alla maggior parte degli utenti di creare modelli utilizzando Keras, vedere la sezione Convertitori per Keras di seguito. Questi wrapper gestiscono automaticamente l'aggregazione degli aggiornamenti del modello e tutte le metriche definite per il modello. Tuttavia, può essere comunque utile capire come viene gestita l'aggregazione per un tff.learning.Model generale.

Ci sono sempre almeno due livelli di aggregazione nell'apprendimento federato: aggregazione locale su dispositivo e aggregazione cross-device (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 la perdita media, l'accuratezza e altre metriche), che il modello aggiornerà nuovamente localmente poiché itera 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 prima costruisce tf.Variable s per contenere aggregati, come il numero di lotti o il numero di esempi elaborati, la somma delle perdite per lotto o per esempio, ecc.

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

    • Infine, TFF invoca 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 metriche da esportare dal client. È qui che il tuo 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. Anche in questo caso, si applica sia ai parametri del modello (variabili), di cui viene calcolata la media tra i clienti, sia alle metriche esportate dal modello come risultato dell'aggregazione locale.

    L'esecuzione dell'aggregazione a questo livello è responsabilità di TFF. Come 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 insieme di parametri del modello (durante l'addestramento) e un nuovo insieme 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 di metadati è rappresentato dall'interfaccia tff.learning.Model , 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 riportare, in modo corrispondente. Il TensorFlow costruito con questi metodi deve essere serializzabile, come discusso in precedenza.

  • La proprietà input_spec , così come le 3 proprietà che restituiscono sottoinsiemi delle variabili addestrabili, non addestrabili e locali rappresentano i metadati. TFF usa queste informazioni per determinare come connettere parti del tuo modello agli algoritmi di ottimizzazione federati e per definire firme di tipo interne per aiutare a verificare la correttezza del sistema costruito (in modo che il tuo modello non possa essere istanziato su dati che non corrispondono a quanto il modello è pensato per consumare).

Inoltre, l'interfaccia astratta tff.learning.Model 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. I metric_finalizers e report_local_unfinalized_metrics() verranno utilizzati insieme per creare un aggregatore di metriche cross-client durante la definizione dei processi di addestramento federati o dei calcoli di valutazione. Ad esempio, un semplice aggregatore tff.learning.metrics.sum_then_finalize prima somma i valori delle metriche non finalizzate dai client, quindi chiama le funzioni del finalizzatore sul server.

Puoi trovare esempi su come definire il tuo tff.learning.Model 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 hai un modello Keras, puoi fare affidamento su tff.learning.from_keras_model per costruire un tff.learning.Model .

Nota che TFF vuole comunque che tu fornisca un costruttore, una funzione del modello senza argomenti come la seguente:

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

Oltre al modello stesso, fornisci un batch 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 al momento della creazione del TensorFlow da serializzare).

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

Costruttori di calcolo federati

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

Presupposti architettonici

Esecuzione

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

  • Compila : TFF prima compila algoritmi di apprendimento federati 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 .

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

Un calcolo federato generato dall'API di apprendimento federato di TFF, ad esempio un algoritmo di addestramento che utilizza la media federata del modello o una valutazione federata, include una serie di elementi, in particolare:

  • Una forma serializzata del codice del modello e un codice TensorFlow aggiuntivo costruito dal framework Federated Learning per guidare il ciclo di addestramento/valutazione del modello (come la creazione di ottimizzatori, l'applicazione di aggiornamenti del modello, l'iterazione su tf.data.Dataset s 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 come questa comunicazione distribuita è intercalata 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 usare l'API di apprendimento federato non dovrai preoccuparti dei dettagli di questa rappresentazione. I calcoli sono rappresentati nel tuo codice Python come oggetti di tipo tff.Computation , che per la maggior parte puoi trattare come opachi Python callable s.

Nei tutorial, invocherai quei 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, in gruppi di dispositivi che eseguono Android o in cluster in un data center. Anche in questo caso, la principale conseguenza di ciò sono forti ipotesi sulla serializzazione . In particolare, quando si invoca uno dei metodi build_... descritti di seguito, il calcolo viene completamente serializzato.

Stato di modellazione

TFF è un ambiente di programmazione funzionale, ma molti processi di interesse nell'apprendimento federato sono stateful. Ad esempio, un ciclo di addestramento che coinvolge più cicli di calcolo della media del modello federato è un esempio di ciò che potremmo classificare come processo con stato . In questo processo, lo stato che evolve da round a round include l'insieme dei 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 viene lo stato iniziale (altrimenti non possiamo avviare il processo). Questo viene acquisito 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 del builder che generano calcoli federati per la formazione e la valutazione federate. Due esempi notevoli includono:

Set di dati

Presupposti architettonici

Selezione del cliente

Nel tipico scenario di apprendimento federato, abbiamo una vasta popolazione di potenzialmente 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, questo può essere limitato ai client che sono collegato a una fonte di alimentazione, non su una rete a consumo, e altrimenti inattivo). In genere, l'insieme di clienti disponibili a partecipare alla formazione o alla valutazione è al di fuori del 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 possono essere campionati casualmente .

La conseguenza chiave di ciò è che i calcoli federati, per progettazione, sono espressi in un modo che è ignaro dell'esatto insieme di partecipanti; tutta l'elaborazione è espressa come operazioni aggregate su un gruppo astratto di client anonimi e quel gruppo potrebbe variare da un ciclo di formazione all'altro. L'effettivo legame del calcolo con i partecipanti concreti, e quindi con i dati concreti che immettono 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 al seguente:

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 il 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. Quei tf.data.Dataset s possono essere alimentati direttamente come input per i calcoli federati generati in modalità desiderosa.

Va notato che la capacità di accedere alle identità dei clienti è una caratteristica fornita solo dai set di dati per l'uso nelle simulazioni, in cui potrebbe essere necessaria la capacità di allenarsi 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 un sottoinsieme specifico di client sono stati selezionati come input, ad esempio in una chiamata a tff.templates.IterativeProcess.next , le identità dei client non vengono più visualizzate in esso.

Set di dati disponibili

Abbiamo dedicato lo spazio dei nomi tff.simulation.datasets ai set di dati che implementano l'interfaccia tff.simulation.datasets.ClientData per l'uso nelle simulazioni e lo abbiamo inserito con i set di dati per supportare la classificazione delle immagini e le esercitazioni sulla generazione del testo . Vorremmo incoraggiarti a contribuire con i tuoi set di dati alla piattaforma.