Questa è una guida end-to-end di LiteRT.js che illustra il processo di conversione di un modello PyTorch da eseguire nel browser con l'accelerazione WebGPU. Questo esempio utilizza ResNet18 per il modello di visione e TensorFlow.js per il pre- e post-processing.
La guida illustrerà i seguenti passaggi:
- Converti il modello PyTorch in LiteRT utilizzando AI Edge
Torch.
- Aggiungi il pacchetto LiteRT alla tua app web.
- Carica il modello.
- Scrivi la logica di pre- e post-elaborazione.
Converti in LiteRT
Utilizza il notebook PyTorch Converter per convertire un modello PyTorch nel formato .tflite
appropriato. Per una guida
approfondita sui tipi di errori che potresti riscontrare e su come risolverli, consulta il file
README di AI
Edge Torch Converter.
Il modello deve essere compatibile con
torch.export.export
, il che
significa che deve essere esportabile con TorchDynamo. Pertanto, non deve avere
rami condizionali Python che dipendono dai valori di runtime all'interno dei tensori. Se
visualizzi i seguenti errori durante
torch.export.export
,
il modello non è esportabile con torch.export.export
. Inoltre, il modello non deve
avere dimensioni di input o output dinamiche sui tensori. Ciò include
la dimensione batch.
Puoi anche iniziare con un modello PyTorch compatibile con TensorRT o esportabile in ONNX:
Una versione di un modello compatibile con TensorRT può essere un buon punto di partenza, poiché alcuni tipi di conversioni TensorRT richiedono anche che i modelli siano esportabili con TorchDynamo. Se utilizzi operazioni NVIDIA / CUDA nel modello, dovrai sostituirle con operazioni PyTorch standard.
Un modello PyTorch esportabile in ONNX può essere un buon punto di partenza, anche se alcuni modelli ONNX utilizzano TorchScript anziché TorchDynamo per l'esportazione, nel qual caso il modello potrebbe non essere esportabile in TorchDynamo (anche se è probabilmente più vicino del codice del modello originale).
Per maggiori informazioni, consulta Convertire i modelli PyTorch in LiteRT.
Aggiungere il pacchetto LiteRT
Installa il pacchetto @litertjs/core
da npm:
npm install @litertjs/core
Importa il pacchetto e carica i relativi file Wasm:
import {loadLiteRt} from '@litertjs/core';
// They are located in node_modules/@litertjs/core/wasm/
// Serve them statically on your server.
await loadLiteRt(`your/path/to/wasm/`);
Carica il modello
Importa e inizializza LiteRT.js e le utilità di conversione LiteRT-TFJS. Devi anche importare TensorFlow.js per passare i tensori a LiteRT.js.
import {CompileOptions, loadAndCompile, loadLiteRt, setWebGpuDevice} from '@litertjs/core';
import {runWithTfjsTensors} from '@litertjs/tfjs-interop';
// TensorFlow.js imports
import * as tf from '@tensorflow/tfjs';
import '@tensorflow/tfjs-backend-webgpu'; // Only WebGPU is supported
import {WebGPUBackend} from '@tensorflow/tfjs-backend-webgpu';
async function main() {
// Initialize TensorFlow.js WebGPU backend
await tf.setBackend('webgpu');
// Initialize LiteRT.js's Wasm files
await loadLiteRt('your/path/to/wasm/');
// Make LiteRt use the same GPU device as TFJS (for tensor conversion)
const backend = tf.backend() as WebGPUBackend;
setWebGpuDevice(backend.device);
// ...
}
main();
Carica il modello LiteRT convertito:
const model = await loadAndCompile('path_to_model.tflite', {
accelerator: 'webgpu', // or 'wasm'
});
Scrivi la pipeline del modello
Scrivi la logica di pre-elaborazione e post-elaborazione che collega il modello alla tua app.
È consigliabile utilizzare TensorFlow.js per la pre-elaborazione e la post-elaborazione, ma se non è scritto in TensorFlow.js, puoi chiamare await
tensor.data
per ottenere il valore come ArrayBuffer o await
tensor.array
per ottenere un array JS strutturato.
Di seguito è riportato un esempio di pipeline end-to-end per ResNet18:
// Wrap in a tf.tidy call to automatically clean up intermediate TensorFlow.js tensors.
// (Note: tidy only supports synchronous functions).
const top5 = tf.tidy(() => {
// Get RGB data values from an image element and convert it to range [0, 1).
const image = tf.browser.fromPixels(dogs, 3).div(255);
// These preprocessing steps come from https://github.com/pytorch/vision/blob/main/torchvision/models/resnet.py#L315
// The mean and standard deviation for the image normalization come from https://github.com/pytorch/vision/blob/main/torchvision/transforms/_presets.py#L38
const imageData = image.resizeBilinear([224, 224])
.sub([0.485, 0.456, 0.406])
.div([0.229, 0.224, 0.225])
.reshape([1, 224, 224, 3])
.transpose([0, 3, 1, 2]);
// You can pass inputs as a single tensor, an array, or a JS Object
// where keys are the tensor names in the TFLite model.
// When passing an Object, the output is also an Object.
// Here, we're passing a single tensor, so the output is an array.
const probabilities = runWithTfjsTensors(model, imageData)[0];
// Get the top five classes.
return tf.topk(probabilities, 5);
});
const values = await top5.values.data();
const indices = await top5.indices.data();
top5.values.dispose(); // Clean up the tfjs tensors.
top5.indices.dispose();
// Print the top five classes.
const classes = ... // Class names are loaded from a JSON file in the demo.
for (let i = 0; i < 5; ++i) {
const text = `${classes[indices[i]]}: ${values[i]}`;
console.log(text);
}
Test e risoluzione dei problemi
Consulta le sezioni seguenti per scoprire come testare l'applicazione e gestire gli errori.
Test con input falsi
Dopo aver caricato un modello, è consigliabile testarlo prima con input falsi. In questo modo, verranno rilevati eventuali errori di runtime prima di dedicare tempo alla scrittura della logica di pre- e post-elaborazione per la pipeline del modello. Per verificarlo, puoi utilizzare lo strumento di test del modello LiteRT.js o testarlo manualmente.
Tester di modelli LiteRT.js
Il tester di modelli LiteRT.js esegue il modello su GPU e CPU utilizzando input casuali per verificare che il modello venga eseguito correttamente sulla GPU. Controlla quanto segue:
- Se i tipi di dati di input e output sono supportati.
- Indica se tutte le operazioni sono disponibili sulla GPU.
- Quanto corrispondono gli output della GPU agli output della CPU di riferimento.
- Le prestazioni dell'inferenza della GPU.
Per eseguire il tester del modello LiteRT.js, esegui npm i @litertjs/model-tester
e poi
npx model-tester
. Si aprirà una scheda del browser per eseguire il modello.
Test manuale del modello
Se preferisci testare manualmente il modello anziché utilizzare lo strumento di test
del modello LiteRT.js (@litertjs/model-tester
), puoi generare input falsi ed eseguire il
modello con runWithTfjsTensors
.
Per generare input falsi, devi conoscere i nomi e le forme dei tensori di input. Questi possono essere trovati con LiteRT.js chiamando model.getInputDetails
o
model.getOutputDetails
. Un modo semplice per trovarli è impostare un punto di interruzione dopo la creazione del modello. In alternativa, utilizza Esplorazione
modelli.
Una volta che conosci le forme e i nomi di input e output, puoi testare il modello con un input fittizio. In questo modo, avrai la certezza che il modello verrà eseguito prima di scrivere il resto della pipeline di machine learning. In questo modo si verifica che tutte le operazioni del modello siano supportate. Ad esempio:
// Imports, initialization, and model loading...
// Create fake inputs for the model
const fakeInputs = model.getInputDetails().map(
({shape, dtype}) => tf.ones(shape, dtype));
// Run the model
const outputs = runWithTfjsTensors(model, fakeInputs);
console.log(outputs);
Tipi di errore
Alcuni modelli LiteRT potrebbero non essere supportati da LiteRT.js. Gli errori rientrano in genere in queste categorie:
- Mancata corrispondenza della forma: un bug noto che interessa solo la GPU.
- Operazione non supportata: il runtime non supporta un'operazione nel modello. Il backend WebGPU ha una copertura più limitata rispetto alla CPU, quindi se visualizzi questo errore sulla GPU, potresti essere in grado di eseguire il modello sulla CPU.
- Tipo di tensore non supportato: LiteRT.js supporta solo tensori int32 e float32 per gli input e gli output del modello.
- Modello troppo grande: LiteRT.js è limitato nelle dimensioni dei modelli che può caricare.
Operazione non supportata
Ciò indica che il backend utilizzato non supporta una delle operazioni nel modello. Dovrai riscrivere il modello PyTorch originale per evitare questa operazione e riconvertirlo oppure potresti essere in grado di eseguire il modello sulla CPU.
Nel caso di BROADCAST_TO
, questo problema può essere risolto rendendo la dimensione batch
uguale per ogni tensore di input del modello. Altri casi potrebbero essere più
complicati.
Tipo di tensore non supportato
LiteRT.js supporta solo i tensori int32 e float32 per gli input e gli output del modello.
Modello troppo grande
In genere viene visualizzato come chiamata a Aborted()
o come errore di allocazione della memoria durante il caricamento del modello. LiteRT.js è limitato nelle dimensioni dei modelli che può caricare, quindi
se visualizzi questo messaggio, il tuo modello potrebbe essere troppo grande. Puoi provare a quantizzare i pesi con ai-edge-quantizer, ma mantieni i calcoli a float32 o float16 e gli input e gli output del modello come float32 o int32.