Piattaforma e ambiente

TensorFlow.js funziona nel browser e in Node.js e in entrambe le piattaforme sono disponibili molte diverse configurazioni. Ogni piattaforma ha una serie unica di considerazioni che influenzeranno il modo in cui le applicazioni vengono sviluppate.

Nel browser, TensorFlow.js supporta dispositivi mobili e dispositivi desktop. Ogni dispositivo ha una serie specifica di vincoli, come le API WebGL disponibili, che vengono determinate e configurate automaticamente per te.

In Node.js, TensorFlow.js supporta l'associazione direttamente all'API TensorFlow o l'esecuzione con le implementazioni CPU vanilla più lente.

ambienti

Quando viene eseguito un programma TensorFlow.js, la configurazione specifica è denominata ambiente. L'ambiente è composto da un singolo backend globale e da un set di flag che controllano le funzionalità dettagliate di TensorFlow.js.

backend

TensorFlow.js supporta più backend diversi che implementano l'archiviazione del tensore e le operazioni matematiche. In un dato momento, è attivo un solo backend. La maggior parte delle volte, TensorFlow.js sceglierà automaticamente il miglior backend per te dato l'ambiente corrente. Tuttavia, a volte è importante sapere quale backend viene utilizzato e come cambiarlo.

Per trovare quale backend stai utilizzando:

console.log(tf.getBackend());

Se vuoi modificare manualmente il backend:

tf.setBackend('cpu');
console.log(tf.getBackend());

Backend WebGL

Il backend WebGL, 'webgl', è attualmente il backend più potente per il browser. Questo backend è fino a 100 volte più veloce del backend della CPU vaniglia. I tensori sono memorizzati come trame WebGL e le operazioni matematiche sono implementate negli shader WebGL. Ecco alcune cose utili da sapere quando si utilizza questo backend: \

Evita di bloccare il thread dell'interfaccia utente

Quando viene chiamata un'operazione, come tf.matMul(a, b), il tf.Tensor risultante viene restituito in modo sincrono, tuttavia il calcolo della moltiplicazione della matrice potrebbe non essere ancora pronto. Ciò significa che il tf.Tensor restituito è solo un handle per il calcolo. Quando si chiama x.data() o x.array() , i valori si risolvono quando il calcolo realmente effettuati. Ciò rende importante utilizzare la asincrono x.data() e x.array() metodi sopra le loro controparti sincroni x.dataSync() e x.arraySync() per evitare il blocco thread UI mentre il completamento del calcolo.

Gestione della memoria

Un avvertimento quando si utilizza il backend WebGL è la necessità di una gestione esplicita della memoria. WebGLTextures, che è il luogo in cui vengono archiviati i dati di Tensor, non vengono automaticamente raccolti immondizia dal browser.

Per distruggere la memoria di un tf.Tensor , è possibile utilizzare la dispose() Metodo:

const a = tf.tensor([[1, 2], [3, 4]]);
a.dispose();

È molto comune concatenare più operazioni insieme in un'applicazione. Tenere un riferimento a tutte le variabili intermedie per eliminarle può ridurre la leggibilità del codice. Per risolvere questo problema, TensorFlow.js fornisce un tf.tidy() metodo che pulisce tutto tf.Tensor s non restituiti da una funzione dopo l'esecuzione di esso, simile al modo in cui le variabili locali vengono eliminati quando viene eseguita una funzione:

const a = tf.tensor([[1, 2], [3, 4]]);
const y = tf.tidy(() => {
  const result = a.square().log().neg();
  return result;
});
Precisione

Sui dispositivi mobili, WebGL potrebbe supportare solo trame in virgola mobile a 16 bit. Tuttavia, la maggior parte dei modelli di machine learning viene addestrata con pesi e attivazioni in virgola mobile a 32 bit. Ciò può causare problemi di precisione quando porting un modello per un dispositivo mobile come numeri galleggianti 16 bit possono rappresentare solo numeri nell'intervallo [0.000000059605, 65504] . Ciò significa che dovresti stare attento che i pesi e le attivazioni nel tuo modello non superino questo intervallo. Per verificare se le texture supportati dal dispositivo 32 bit, controllare il valore della tf.ENV.getBool('WEBGL_RENDER_FLOAT32_CAPABLE') , se questo è falso allora il dispositivo supporta solo 16 texture bit floating point. È possibile utilizzare tf.ENV.getBool('WEBGL_RENDER_FLOAT32_ENABLED') per verificare se TensorFlow.js sta attualmente utilizzando 32 bit texture.

Compilazione di shader e caricamenti di texture

TensorFlow.js esegue operazioni sulla GPU eseguendo programmi shader WebGL. Questi shader vengono assemblati e compilati pigramente quando l'utente chiede di eseguire un'operazione. La compilazione di uno shader avviene sulla CPU sul thread principale e può essere lenta. TensorFlow.js memorizzerà automaticamente nella cache gli shader compilati, rendendo molto più veloce la seconda chiamata alla stessa operazione con tensori di input e output della stessa forma. In genere, le applicazioni TensorFlow.js utilizzeranno le stesse operazioni più volte durante la durata dell'applicazione, quindi il secondo passaggio attraverso un modello di apprendimento automatico è molto più veloce.

TensorFlow.js memorizza anche i dati tf.Tensor come WebGLTextures. Quando un tf.Tensor si crea, non carichiamo immediatamente i dati alla GPU, invece osserviamo i dati sulla CPU fino a quando il tf.Tensor viene utilizzato in un'operazione. Se il tf.Tensor viene utilizzata una seconda volta, i dati sono già sulla GPU quindi non c'è alcun costo di upload. In un tipico modello di machine learning, ciò significa che i pesi vengono caricati durante la prima previsione attraverso il modello e il secondo passaggio attraverso il modello sarà molto più veloce.

Se ti interessano le prestazioni della prima previsione tramite il tuo modello o il codice TensorFlow.js, ti consigliamo di riscaldare il modello passando un tensore di input della stessa forma prima di utilizzare i dati reali.

Per esempio:

const model = await tf.loadLayersModel(modelUrl);

// Warmup the model before using real data.
const warmupResult = model.predict(tf.zeros(inputShape));
warmupResult.dataSync();
warmupResult.dispose();

// The second predict() will be much faster
const result = model.predict(userData);

Backend Node.js TensorFlow

Nel backend TensorFlow Node.js, 'node', l'API TensorFlow C viene utilizzata per accelerare le operazioni. Questo utilizzerà l'accelerazione hardware disponibile della macchina, come CUDA, se disponibile.

In questo backend, proprio come il back-end WebGL, operazioni restituiscono tf.Tensor s sincrono. Tuttavia, a differenza del backend WebGL, l'operazione viene completata prima di recuperare il tensore. Ciò significa che una chiamata a tf.matMul(a, b) blocca il thread UI.

Per questo motivo, se si intende utilizzarlo in un'applicazione di produzione, è necessario eseguire TensorFlow.js nei thread di lavoro per non bloccare il thread principale.

Per ulteriori informazioni su Node.js, consulta questa guida.

backend WASM

TensorFlow.js fornisce un backend WebAssembly ( wasm ), che l'accelerazione offerte CPU e può essere usato come alternativa alla vaniglia JavaScript CPU ( cpu ) e WebGL accelerato ( webgl ) backend. Per usarlo:

// Set the backend to WASM and wait for the module to be ready.
tf.setBackend('wasm');
tf.ready().then(() => {...});

Se il server sta scontando il .wasm file su un percorso diverso o un nome diverso, l'uso setWasmPath prima di inizializzare il backend. Vedere la "Uso Fardellatrici" sezione nel README per maggiori informazioni:

import {setWasmPath} from '@tensorflow/tfjs-backend-wasm';
setWasmPath(yourCustomPath);
tf.setBackend('wasm');
tf.ready().then(() => {...});
Perché WASM?

Wasm è stato introdotto nel 2015 come un nuovo formato binario basato sul web, che fornisce programmi scritti in JavaScript, C, C ++, ecc un target di compilazione per l'esecuzione sul web. Wasm è stato supportato da Chrome, Safari, Firefox, ed Edge dal 2017, ed è supportato da 90% dei dispositivi in tutto il mondo.

Prestazione

Wasm backend sfrutta la libreria XNNPACK per l'implementazione ottimizzata degli operatori di rete neurale.

Versus JavaScript: binari wasm sono in genere molto più veloce di JavaScript fasci per i browser di caricare, analizzare ed eseguire. JavaScript viene digitato dinamicamente e viene eseguito il Garbage Collection, il che può causare rallentamenti in fase di esecuzione.

Versus WebGL: WebGL è più veloce di wasm per maggior parte dei modelli, ma per i piccoli modelli wasm può outperform WebGL a causa dei costi generali fissi di esecuzione shader WebGL. La sezione "Quando dovrei usare WASM" di seguito discute l'euristica per prendere questa decisione.

Portabilità e stabilità

WASM ha un'aritmetica mobile portatile a 32 bit, che offre parità di precisione su tutti i dispositivi. WebGL, d'altra parte, è specifico dell'hardware e dispositivi diversi possono avere una precisione variabile (ad esempio fallback a float a 16 bit su dispositivi iOS).

Come WebGL, WASM è ufficialmente supportato da tutti i principali browser. A differenza di WebGL, WASM può essere eseguito in Node.js ed essere utilizzato lato server senza la necessità di compilare librerie native.

Quando dovrei usare WASM?

Dimensioni del modello e richiesta computazionale

In generale, wasm è una buona scelta quando i modelli sono più piccoli o si preoccupano per i dispositivi di fascia più bassa che la mancanza di supporto WebGL ( OES_texture_float estensione) o che hanno GPU meno potenti. La tabella sottostante mostra l'inferenza volte (come di TensorFlow.js 1.5.2) in Chrome su un MacBook Pro 2018 per 5 dei nostri ufficialmente supportati modelli in tutto il WebGL, wasm, e backend CPU:

Modelli più piccoli

Modello WebGL WASM processore Memoria
BlazeFace 22,5 ms 15,6 ms 315,2 ms .4 MB
FaceMesh 19,3 ms 19,2 ms 335 ms 2,8 MB

Modelli più grandi

Modello WebGL WASM processore Memoria
PoseNet 42,5 ms 173,9 ms 1514,7 ms 4,5 MB
BodyPix 77 ms 188,4 ms 2683 ms 4.6 MB
MobileNet v2 37 ms 94 ms 923,6 ms 13 MB

La tabella qui sopra mostra che wasm è 10-30 volte più veloce rispetto alla pianura backend JS CPU attraverso modelli e competitivo con WebGL per i modelli più piccoli come BlazeFace , che è leggero (400KB), ma ha un numero decente di OPS (~ 140). Dato che i programmi WebGL hanno un costo fisso per l'esecuzione delle operazioni, questo spiega perché modelli come BlazeFace sono più veloci su WASM.

Questi risultati variano a seconda del dispositivo. Il modo migliore per determinare se WASM è adatto alla tua applicazione è testarlo sui nostri diversi backend.

Inferenza vs formazione

Per affrontare il caso d'uso primario per la distribuzione di modelli di pre-formazione, lo sviluppo backend wasm darà la priorità inferenza sovrallenamento supporto. Vedere un elenco aggiornato dei ops supportati in wasm e fateci sapere se il modello ha un op non supportato. Per i modelli di addestramento, si consiglia di utilizzare il backend Node (TensorFlow C++) o il backend WebGL.

Backend della CPU

Il backend della CPU, "cpu", è il backend meno performante, tuttavia è il più semplice. Le operazioni sono tutte implementate in JavaScript vanilla, che le rende meno parallelizzabili. Bloccano anche il thread dell'interfaccia utente.

Questo backend può essere molto utile per i test o su dispositivi in ​​cui WebGL non è disponibile.

bandiere

TensorFlow.js ha una serie di flag di ambiente che vengono valutati automaticamente e determinano la migliore configurazione nella piattaforma corrente. Questi flag sono per lo più interni, ma alcuni flag globali possono essere controllati con l'API pubblica.

  • tf.enableProdMode(): attiva la modalità di produzione, che rimuoverà la validazione dei modelli, i controlli Nan, e di altri controlli di correttezza a favore di prestazioni.
  • tf.enableDebugMode() : abilita la modalità di debug, che registrerà alla console ogni operazione che viene eseguita, così come le informazioni sulle prestazioni di runtime come occupazione di memoria e il tempo totale di esecuzione del kernel. Nota che questo rallenterà notevolmente la tua applicazione, non usarlo in produzione.