API di livelli TensorFlow.js per gli utenti Keras

Gli strati API di TensorFlow.js è modellato dopo Keras e ci sforziamo di rendere l'API Livelli come simile a Keras ragionevole date le differenze tra JavaScript e Python. Ciò semplifica la migrazione a TensorFlow.js Layers in JavaScript per gli utenti con esperienza nello sviluppo di modelli Keras in Python. Ad esempio, il seguente codice Keras si traduce in JavaScript:

# Python:
import keras
import numpy as np

# Build and compile model.
model = keras.Sequential()
model.add(keras.layers.Dense(units=1, input_shape=[1]))
model.compile(optimizer='sgd', loss='mean_squared_error')

# Generate some synthetic data for training.
xs = np.array([[1], [2], [3], [4]])
ys = np.array([[1], [3], [5], [7]])

# Train model with fit().
model.fit(xs, ys, epochs=1000)

# Run inference with predict().
print(model.predict(np.array([[5]])))
// JavaScript:
import * as tf from '@tensorlowjs/tfjs';

// Build and compile model.
const model = tf.sequential();
model.add(tf.layers.dense({units: 1, inputShape: [1]}));
model.compile({optimizer: 'sgd', loss: 'meanSquaredError'});

// Generate some synthetic data for training.
const xs = tf.tensor2d([[1], [2], [3], [4]], [4, 1]);
const ys = tf.tensor2d([[1], [3], [5], [7]], [4, 1]);

// Train model with fit().
await model.fit(xs, ys, {epochs: 1000});

// Run inference with predict().
model.predict(tf.tensor2d([[5]], [1, 1])).print();

Tuttavia, ci sono alcune differenze che vorremmo evidenziare e spiegare in questo documento. Una volta comprese queste differenze e la logica alla base, la migrazione da Python a JavaScript (o la migrazione nella direzione opposta) dovrebbe essere un'esperienza relativamente fluida.

I costruttori accettano oggetti JavaScript come configurazioni

Confrontare le seguenti righe Python e JavaScript da l'esempio precedente: entrambi creano un denso strato.

# Python:
keras.layers.Dense(units=1, inputShape=[1])
// JavaScript:
tf.layers.dense({units: 1, inputShape: [1]});

Le funzioni JavaScript non hanno un equivalente degli argomenti delle parole chiave nelle funzioni Python. Vogliamo evitare implementazione di opzioni costruttore come argomenti posizionali in JavaScript, che sarebbe particolarmente scomodo ricordare e utilizzare per i costruttori con un gran numero di argomenti a parola chiave (ad esempio, LSTM ). Questo è il motivo per cui utilizziamo oggetti di configurazione JavaScript. Tali oggetti forniscono lo stesso livello di invarianza posizionale e flessibilità degli argomenti delle parole chiave Python.

Alcuni metodi della classe del modello, ad esempio, Model.compile() , anche prendere un oggetto di configurazione JavaScript come ingresso. Tuttavia, tenere presente che Model.fit() , Model.evaluate() e Model.predict() sono leggermente diverse. Poiché questi metodo rimessa applicabilità x (arredamento) e y (etichette o target) dati come input; x ed y sono argomenti posizionali separano dall'oggetto configurazione conseguente che svolge il ruolo di argomenti a parola chiave. Per esempio:

// JavaScript:
await model.fit(xs, ys, {epochs: 1000});

Model.fit() è asincrono

Model.fit() è il metodo principale con cui gli utenti effettuano una formazione modello TensorFlow.js. Questo metodo può essere spesso di lunga durata, della durata di secondi o minuti. Pertanto, utilizziamo async caratteristica del linguaggio JavaScript, in modo che questa funzione può essere utilizzata in un modo che non blocca il thread principale dell'interfaccia utente durante l'esecuzione nel browser. Questo è simile ad altre funzioni potenzialmente esecuzione prolungata in JavaScript, come async recupero . Si noti che async è un costrutto che non esiste in Python. Mentre il fit() metodo Keras restituisce un oggetto di storia, la controparte del fit() metodo in JavaScript restituisce una promessa di Storia, che può essere await ed (come nell'esempio sopra) o utilizzato con il metodo allora ().

Nessun NumPy per TensorFlow.js

Utenti pitone KERAS utilizzano spesso NumPy per eseguire operazioni numeriche e matrice di base, come la generazione tensori 2D nell'esempio precedente.

# Python:
xs = np.array([[1], [2], [3], [4]])

In TensorFlow.js, questo tipo di operazioni numeriche di base vengono eseguite con il pacchetto stesso. Per esempio:

// JavaScript:
const xs = tf.tensor2d([[1], [2], [3], [4]], [4, 1]);

Il tf.* Namespace fornisce anche una serie di altre funzioni per le operazioni di matrice e algebra lineare come moltiplicazione matriciale. Vedere la documentazione di TensorFlow.js Nucleo per ulteriori informazioni.

Usa metodi di fabbrica, non costruttori

Questa riga in Python (dall'esempio sopra) è una chiamata al costruttore:

# Python:
model = keras.Sequential()

Se tradotta rigorosamente in JavaScript, la chiamata al costruttore equivalente sarebbe simile alla seguente:

// JavaScript:
const model = new tf.Sequential();  // !!! DON'T DO THIS !!!

Tuttavia, abbiamo deciso di non utilizzare i "nuovi" costruttori perché 1) la parola chiave "nuovo" renderebbe il codice più gonfio e 2) il "nuovo" costruttore è considerato una "parte negativa" di JavaScript: una potenziale trappola, in quanto è sostenuto in JavaScript: le parti buone . Per creare modelli e livelli in TensorFlow.js, chiami i metodi factory, che hanno nomi CamelCase inferiori, ad esempio:

// JavaScript:
const model = tf.sequential();

const layer = tf.layers.batchNormalization({axis: 1});

I valori della stringa di opzione sono LowerCamelCase, non snake_case

In JavaScript, è più comune caso d'uso di cammello per i nomi dei simboli (ad esempio, vedere la Guida di Google JavaScript Style ), in confronto con Python, dove caso serpente è comune (ad esempio, in Keras). Pertanto, abbiamo deciso di utilizzare LowerCamelCase per i valori stringa per le opzioni, tra cui le seguenti:

  • DataFormat, ad esempio, channelsFirst anziché channels_first
  • Inizializzatore, ad esempio, glorotNormal anziché glorot_normal
  • Perdita e metriche, ad esempio, meanSquaredError invece di mean_squared_error , categoricalCrossentropy invece di categorical_crossentropy .

Ad esempio, come nell'esempio sopra:

// JavaScript:
model.compile({optimizer: 'sgd', loss: 'meanSquaredError'});

Per quanto riguarda la serializzazione e la deserializzazione del modello, state tranquilli. Il meccanismo interno di TensorFlow.js garantisce che i casi snake negli oggetti JSON vengano gestiti correttamente, ad esempio durante il caricamento di modelli preaddestrati da Python Keras.

Esegui oggetti Layer con apply(), non chiamandoli come funzioni

In Keras, un oggetto Layer ha la __call__ metodo definito. Pertanto l'utente può invocare la logica del livello chiamando l'oggetto come una funzione, ad es.

# Python:
my_input = keras.Input(shape=[2, 4])
flatten = keras.layers.Flatten()

print(flatten(my_input).shape)

Questo zucchero di sintassi Python è implementato come metodo apply() in TensorFlow.js:

// JavaScript:
const myInput = tf.input({shape: [2, 4]});
const flatten = tf.layers.flatten();

console.log(flatten.apply(myInput).shape);

Layer.apply() supporta la valutazione imperativa (desiderosa) su tensori concreti

Attualmente, in Keras, il metodo chiamata può funzionare solo (Python) di tensorflow tf.Tensor oggetti (supponendo tensorflow backend), che sono simbolico e non tenere valori numerici reali. Questo è ciò che è mostrato nell'esempio nella sezione precedente. Tuttavia, in TensorFlow.js, il metodo apply() dei livelli può funzionare sia in modalità simbolica che imperativa. Se apply() viene richiamato con una SymbolicTensor (una stretta analogia tf.Tensor), il valore restituito sarà uno SymbolicTensor. Ciò accade in genere durante la creazione del modello. Ma se apply() viene richiamato con un valore effettivo di cemento Tensor, verrà restituito un concreto Tensor. Per esempio:

// JavaScript:
const flatten = tf.layers.flatten();

flatten.apply(tf.ones([2, 3, 4])).print();

Questa funzione ricorda (Python) di tensorflow Esecuzione Eager . Offre una maggiore interattività e possibilità di debug durante lo sviluppo del modello, oltre ad aprire le porte alla composizione di reti neurali dinamiche.

Gli ottimizzatori sono in corso. , non ottimizzatori.

In Keras, costruttori di oggetti Optimizer sono sotto i keras.optimizers.* Namespace. In TensorFlow.js Livelli, i metodi di fabbrica per ottimizzatori sono sotto il tf.train.* Namespace. Per esempio:

# Python:
my_sgd = keras.optimizers.sgd(lr=0.2)
// JavaScript:
const mySGD = tf.train.sgd({lr: 0.2});

loadLayersModel() viene caricato da un URL, non da un file HDF5

In Keras, i modelli sono di solito salvati come file HDF5 (.h5), che può essere successivamente caricato usando il keras.models.load_model() metodo. Il metodo prende un percorso al file .h5. La controparte di load_model() in TensorFlow.js è tf.loadLayersModel() . Dal momento che HDF5 non è un formato di file del browser-friendly, tf.loadLayersModel() prende un formato TensorFlow.js-specifica. tf.loadLayersModel() prende un file model.json come argomento di input. Il model.json può essere convertito da un file Keras HDF5 utilizzando il pacchetto tensorflowjs pip.

// JavaScript:
const model = await tf.loadLayersModel('https://foo.bar/model.json');

Si noti inoltre che tf.loadLayersModel() restituisce una Promise di tf.Model .

In generale, salvataggio e caricamento tf.Model s in TensorFlow.js viene fatto usando i tf.Model.save e tf.loadLayersModel metodi, rispettivamente. Abbiamo progettato queste API per essere simile a Salva e load_model API di Keras. Ma l'ambiente del browser è molto diverso dall'ambiente di backend su cui vengono eseguiti i framework di deep learning come Keras, in particolare nella serie di percorsi per la persistenza e la trasmissione dei dati. Quindi ci sono alcune differenze interessanti tra le API di salvataggio/caricamento in TensorFlow.js e in Keras. Vedi il nostro tutorial su Salvataggio e caricamento tf.Model per maggiori dettagli.

Usa fitDataset() per modelli di treni che utilizzano tf.data.Dataset oggetti

In tf.keras di Python tensorflow, un modello può essere addestrato utilizzando un set di dati oggetto. Il modello fit() metodo accetta direttamente un oggetto. Modello A TensorFlow.js può essere addestrato con l'equivalente JavaScript del Oggetti dataset così (si veda la documentazione delle API tf.data in TensorFlow.js ). Tuttavia, la formazione a differenza di Python, Dataset-based viene fatto attraverso un metodo dedicato, vale a dire fitDataset . Il fit () metodo è solo per la formazione del modello tensore-based.

Gestione della memoria di oggetti Layer e Model

TensorFlow.js viene eseguito su WebGL nel browser, dove i pesi degli oggetti Layer e Model sono supportati da trame WebGL. Tuttavia, WebGL non ha un supporto integrato per la raccolta dei rifiuti. Gli oggetti Layer e Model gestiscono internamente la memoria del tensore per l'utente durante le chiamate di inferenza e training. Ma consentono anche all'utente di smaltirli per liberare la memoria WebGL che occupano. Ciò è utile nei casi in cui vengono create e rilasciate molte istanze del modello all'interno di un singolo caricamento di pagina. Di disporre uno strato o un oggetto modello, utilizzare la dispose() metodo.