Inizia a utilizzare LiteRT.js

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:

  1. Converti il modello PyTorch in LiteRT utilizzando AI Edge Torch.
    1. Aggiungi il pacchetto LiteRT alla tua app web.
  2. Carica il modello.
  3. 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.