Modelli salvati riutilizzabili

Introduzione

TensorFlow Hub ospita i SavedModel per TensorFlow 2, tra le altre risorse. Possono essere caricati in un programma Python con obj = hub.load(url) [ per saperne di più ]. L' obj restituito è il risultato di tf.saved_model.load() (consulta la guida ai SavedModel di TensorFlow). Questo oggetto può avere attributi arbitrari, che possono essere tf.functions, tf.Variables (inizializzate con i loro valori pre-addestrati), altre risorse e, ricorsivamente, altri oggetti simili.

Questa pagina descrive un'interfaccia che deve essere implementata obj caricato per poter essere riutilizzato in un programma Python di TensorFlow. I SavedModel che si conformano a questa interfaccia sono chiamati SavedModel riutilizzabili .

Riutilizzare significa costruire un modello più ampio attorno a obj , includendo la possibilità di perfezionarlo. Il perfezionamento consiste nell'ulteriore addestramento dei pesi presenti in obj caricato come parte del modello circostante. La funzione di perdita e l'ottimizzatore sono determinati dal modello circostante; obj definisce solo la mappatura delle attivazioni di input e output (il "passaggio in avanti"), eventualmente includendo tecniche come il dropout o la normalizzazione batch.

Il team di TensorFlow Hub raccomanda di implementare l'interfaccia Reusable SavedModel in tutti i SavedModel destinati a essere riutilizzati nel senso sopra descritto. Molte utility della libreria tensorflow_hub , in particolare hub.KerasLayer , richiedono che i SavedModel la implementino.

Relazione con SignatureDefs

Questa interfaccia, in termini di tf.functions e altre funzionalità di TF2, è separata dalle firme di SavedModel, disponibili fin da TF1 e tuttora utilizzate in TF2 per l'inferenza (ad esempio, per la distribuzione di SavedModel su TF Serving o TF Lite). Le firme per l'inferenza non sono sufficientemente espressive per supportare la messa a punto fine, e tf.function fornisce un'API Python più naturale ed espressiva per il modello riutilizzato.

Relazione con le librerie di modellazione

Un SavedModel riutilizzabile utilizza solo primitive di TensorFlow 2, indipendentemente da qualsiasi libreria di modellazione specifica come Keras o Sonnet. Ciò facilita il riutilizzo tra diverse librerie di modellazione, senza dipendenze dal codice originale della libreria di modellazione.

Sarà necessario un certo grado di adattamento per caricare i SavedModel riutilizzabili in una determinata libreria di modelli o per salvarli da essa. Per Keras, hub.KerasLayer si occupa del caricamento e il salvataggio integrato di Keras nel formato SavedModel è stato riprogettato per TF2 con l'obiettivo di fornire un superset di questa interfaccia (vedere la RFC di maggio 2019).

Relazione con le "API comuni di SavedModel" specifiche per le attività

La definizione dell'interfaccia in questa pagina consente un numero e un tipo qualsiasi di input e output. Le API Common SavedModel per TF Hub perfezionano questa interfaccia generale con convenzioni di utilizzo per attività specifiche, al fine di rendere i modelli facilmente intercambiabili.

Definizione dell'interfaccia

Attributi

Un SavedModel riutilizzabile è un SavedModel di TensorFlow 2 tale che obj = tf.saved_model.load(...) restituisce un oggetto che ha i seguenti attributi

  • __call__ . Obbligatorio. Una tf.function che implementa il calcolo del modello (il "passaggio in avanti") soggetto alla specifica seguente.

  • variables : Un elenco di oggetti tf.Variable, che elenca tutte le variabili utilizzate da qualsiasi possibile invocazione di __call__ , incluse sia quelle addestrabili che quelle non addestrabili.

    Questo elenco può essere omesso se vuoto.

  • trainable_variables : Un elenco di oggetti tf.Variable tali che v.trainable sia true per tutti gli elementi. Queste variabili devono essere un sottoinsieme di variables . Queste sono le variabili da addestrare durante il fine-tuning dell'oggetto. Il creatore di SavedModel può scegliere di omettere alcune variabili che erano originariamente addestrabili per indicare che queste non devono essere modificate durante il fine-tuning.

    Questo elenco può essere omesso se vuoto, in particolare se SavedModel non supporta la messa a punto fine.

  • regularization_losses : Un elenco di tf.functions, ognuna delle quali accetta zero input e restituisce un singolo tensore scalare float. Per la messa a punto, si consiglia all'utente di SavedModel di includerle come termini di regolarizzazione aggiuntivi nella funzione di perdita (nel caso più semplice, senza ulteriore scalatura). In genere, vengono utilizzate per rappresentare i regolarizzatori dei pesi. (Per mancanza di input, queste tf.functions non possono esprimere regolarizzatori di attività.)

    Questo elenco può essere omesso se vuoto, in particolare se SavedModel non supporta il fine-tuning o non desidera prescrivere la regolarizzazione dei pesi.

La funzione __call__

Un obj SavedModel ripristinato ha un attributo obj.__call__ che è una funzione tf.function ripristinata e consente di chiamare obj come segue.

Sinossi (pseudocodice):

outputs = obj(inputs, trainable=..., **kwargs)

Argomentazioni

Le argomentazioni sono le seguenti.

  • C'è un argomento posizionale obbligatorio con un batch di attivazioni di input del SavedModel. Il suo tipo è uno di

    • un singolo tensore per un singolo input,
    • un elenco di tensori per una sequenza ordinata di input senza nome,
    • un dizionario di tensori indicizzati da un particolare insieme di nomi di input.

    (Le future revisioni di questa interfaccia potrebbero consentire annidamenti più generali.) Il creatore di SavedModel sceglie uno di questi, nonché le forme e i tipi di dati del tensore. Ove utile, alcune dimensioni della forma dovrebbero essere indefinite (in particolare la dimensione del batch).

  • Potrebbe essere presente un argomento opzionale con parola chiave ` training che accetta un valore booleano Python, True o False . Il valore predefinito è False . Se il modello supporta il fine-tuning e se il suo calcolo differisce tra le due opzioni (ad esempio, come nel dropout e nella normalizzazione batch), tale distinzione viene implementata tramite questo argomento. In caso contrario, questo argomento potrebbe essere assente.

    Non è obbligatorio che __call__ accetti un argomento training con valori tensoriali. Spetta al chiamante utilizzare tf.cond() se necessario per la comunicazione tra di essi.

  • Il creatore di SavedModel può scegliere di accettare ulteriori kwargs opzionali con nomi specifici.

    • Per gli argomenti con valori tensoriali, il creatore di SavedModel definisce i tipi di dati e le forme consentiti. tf.function accetta un valore predefinito Python su un argomento tracciato con un input tf.TensorSpec. Tali argomenti possono essere utilizzati per consentire la personalizzazione degli iperparametri numerici coinvolti in __call__ (ad esempio, il tasso di dropout).

    • Per gli argomenti con valori Python, il creatore di SavedModel definisce i valori consentiti. Tali argomenti possono essere utilizzati come flag per effettuare scelte discrete nella funzione tracciata (ma attenzione all'esplosione combinatoria delle tracce).

La funzione __call__ ripristinata deve fornire tracce per tutte le combinazioni ammissibili di argomenti. L'inversione training tra True e False non deve modificare l'ammissibilità degli argomenti.

Risultato

Gli outputs della chiamata obj possono essere

  • un singolo tensore per un singolo output,
  • un elenco di tensori per una sequenza ordinata di output senza nome,
  • un dizionario di tensori indicizzati da un particolare insieme di nomi di output.

(Le future revisioni di questa interfaccia potrebbero consentire annidamenti più generali.) Il tipo di ritorno può variare a seconda dei parametri con valore Python. Ciò consente l'utilizzo di flag che producono output aggiuntivi. Il creatore di SavedModel definisce i tipi di dati e le forme di output e la loro dipendenza dagli input.

Funzioni richiamabili con nome

Un SavedModel riutilizzabile può fornire più parti del modello nel modo descritto sopra, inserendole in sotto-oggetti denominati, ad esempio obj.foo , obj.bar e così via. Ogni sotto-oggetto fornisce un metodo __call__ e attributi di supporto relativi alle variabili ecc. specifici per quella parte del modello. Nell'esempio precedente, ci sarebbero obj.foo.__call__ , obj.foo.variables e così via.

Si noti che questa interfaccia non copre l'approccio di aggiungere direttamente una tf.function come tf.foo .

Gli utenti di Reusable SavedModels devono gestire un solo livello di annidamento ( obj.bar , ma non obj.bar.baz ). (Le future revisioni di questa interfaccia potrebbero consentire annidamenti più profondi e potrebbero eliminare il requisito che l'oggetto di livello superiore sia a sua volta richiamabile.)

Osservazioni conclusive

Relazione con le API in-process

Questo documento descrive un'interfaccia di una classe Python composta da tipi primitivi come `tf.function` e `tf.Variable` che sopravvivono al processo di serializzazione tramite tf.saved_model.save() e tf.saved_model.load() . Tuttavia, l'interfaccia era già presente sull'oggetto originale passato a tf.saved_model.save() . L'adattamento a tale interfaccia consente lo scambio di parti del modello tra API di costruzione del modello all'interno di un singolo programma TensorFlow.