Partecipa al simposio Women in ML il 7 dicembre Registrati ora

Piattaforma e ambiente

Mantieni tutto organizzato con le raccolte Salva e classifica i contenuti in base alle tue preferenze.

TensorFlow.js funziona nel browser e in Node.js e in entrambe le piattaforme sono disponibili molte diverse configurazioni. Ogni piattaforma ha un insieme unico 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 diretta all'API TensorFlow o l'esecuzione con le implementazioni della CPU vanilla più lente.

Ambienti

Quando viene eseguito un programma TensorFlow.js, la configurazione specifica viene chiamata ambiente. L'ambiente è composto da un unico back-end globale e da un set di flag che controllano le funzionalità a grana fine 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. Il più delle volte, TensorFlow.js sceglierà automaticamente il miglior backend per te dato l'ambiente attuale. Tuttavia, a volte è importante sapere quale backend viene utilizzato e come cambiarlo.

Per trovare quale backend stai utilizzando:

console.log(tf.getBackend());

Se vuoi cambiare manualmente il back-end:

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 vanilla. I tensori sono archiviati 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 risultante tf.Tensor 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 chiami x.data() o x.array() , i valori si risolveranno quando il calcolo sarà effettivamente completato. Ciò rende importante utilizzare i metodi asincroni x.data() e x.array() sulle loro controparti sincrone x.dataSync() e x.arraySync() per evitare di bloccare il thread dell'interfaccia utente mentre il calcolo è completato.

Gestione della memoria

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

Per distruggere la memoria di un tf.Tensor , puoi usare il metodo dispose() :

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

È molto comune concatenare più operazioni 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 metodo tf.tidy() che pulisce tutti i tf.Tensor che non vengono restituiti da una funzione dopo l'esecuzione, in modo simile al modo in cui le variabili locali vengono ripulite 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 texture in virgola mobile a 16 bit. Tuttavia, la maggior parte dei modelli di machine learning viene addestrata con attivazioni e pesi in virgola mobile a 32 bit. Ciò può causare problemi di precisione durante il porting di un modello per un dispositivo mobile poiché i numeri mobili a 16 bit possono rappresentare solo numeri nell'intervallo [0.000000059605, 65504] . Ciò significa che dovresti fare attenzione che i pesi e le attivazioni nel tuo modello non superino questo intervallo. Per verificare se il dispositivo supporta trame a 32 bit, controlla il valore di tf.ENV.getBool('WEBGL_RENDER_FLOAT32_CAPABLE') , se questo è falso, il dispositivo supporta solo trame in virgola mobile a 16 bit. Puoi usare tf.ENV.getBool('WEBGL_RENDER_FLOAT32_ENABLED') per verificare se TensorFlow.js sta attualmente utilizzando trame a 32 bit.

Compilazione di shader e caricamenti di texture

TensorFlow.js esegue operazioni sulla GPU eseguendo i 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 vita 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 viene creato un tf.Tensor , non carichiamo immediatamente i dati sulla GPU, ma conserviamo i dati sulla CPU fino a quando tf.Tensor viene utilizzato in un'operazione. Se il tf.Tensor viene utilizzato una seconda volta, i dati sono già sulla GPU, quindi non ci sono costi di caricamento. 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 Tensor di input della stessa forma prima che vengano utilizzati 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 TensorFlow di Node.js

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 backend WebGL, le operazioni restituiscono tf.Tensor s in modo 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) bloccherà il thread dell'interfaccia utente.

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

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

backend WASM

TensorFlow.js fornisce un backend WebAssembly ( wasm ), che offre accelerazione della CPU e può essere utilizzato come alternativa ai backend con accelerazione CPU ( cpu ) e WebGL ( webgl ) di vaniglia JavaScript. Per usarlo:

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

Se il tuo server sta servendo il file .wasm su un percorso diverso o un nome diverso, usa setWasmPath prima di inizializzare il back-end. Per ulteriori informazioni, vedere la sezione "Utilizzo dei bundler" nel README:

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. Una destinazione di compilazione per l'esecuzione sul Web. WASM è supportato da Chrome, Safari, Firefox ed Edge dal 2017 ed è supportato dal 90% dei dispositivi in ​​tutto il mondo.

Prestazione

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

Contro JavaScript : i binari WASM sono generalmente molto più veloci dei bundle JavaScript per il caricamento, l'analisi e l'esecuzione da parte dei browser. JavaScript è tipizzato dinamicamente e Garbage Collector, che può causare rallentamenti in fase di esecuzione.

Contro WebGL : WebGL è più veloce di WASM per la maggior parte dei modelli, ma per i modelli piccoli WASM può superare WebGL a causa dei costi generali fissi di esecuzione degli 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 a 32 bit portatile, che offre parità di precisione su tutti i dispositivi. WebGL, d'altra parte, è specifico dell'hardware e diversi dispositivi possono avere una precisione variabile (ad esempio, fallback a float a 16 bit sui 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 domanda computazionale

In generale, WASM è una buona scelta quando i modelli sono più piccoli o ti interessano dispositivi di fascia bassa che non hanno il supporto WebGL (estensione OES_texture_float ) o hanno GPU meno potenti. Il grafico seguente mostra i tempi di inferenza (a partire da TensorFlow.js 1.5.2) in Chrome su un MacBook Pro 2018 per 5 dei nostri modelli ufficialmente supportati sui backend WebGL, WASM e 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
Rete mobile v2 37 ms 94 ms 923,6 ms 13 MB

La tabella sopra mostra che WASM è 10-30 volte più veloce del normale backend CPU JS su tutti i modelli e competitivo con WebGL per modelli più piccoli come BlazeFace , che è leggero (400 KB), ma ha un numero decente di operazioni (~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 varieranno a seconda del tuo 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 principale per l'implementazione di modelli pre-addestrati, lo sviluppo del back-end WASM darà la priorità all'inferenza rispetto al supporto della formazione . Visualizza un elenco aggiornato delle operazioni supportate in WASM e facci sapere se il tuo modello ha un'operazione non supportata. Per i modelli di addestramento, si consiglia di utilizzare il backend Node (TensorFlow C++) o il backend WebGL.

back-end della CPU

Il backend della CPU, 'cpu', è il backend meno performante, tuttavia è il più semplice. Le operazioni sono tutte implementate in JavaScript vanilla, il 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(): abilita la modalità di produzione, che rimuoverà la convalida del modello, i controlli NaN e altri controlli di correttezza a favore delle prestazioni.
  • tf.enableDebugMode() : abilita la modalità di debug, che registrerà sulla console ogni operazione eseguita, nonché informazioni sulle prestazioni di runtime come footprint di memoria e tempo di esecuzione totale del kernel. Nota che questo rallenterà notevolmente la tua applicazione, non usarlo in produzione.