این یک راهنمای LiteRT.js سرتاسر است که فرآیند تبدیل یک مدل PyTorch برای اجرا در مرورگر با شتاب WebGPU را پوشش میدهد. این مثال از ResNet18 برای مدل ویژن و از TensorFlow.js برای پیش و پس پردازش استفاده می کند.
راهنما مراحل زیر را پوشش خواهد داد:
- با استفاده از AI Edge Torch مدل PyTorch خود را به LiteRT تبدیل کنید.
- بسته LiteRT را به برنامه وب خود اضافه کنید.
- مدل را بارگذاری کنید.
- منطق قبل و بعد از پردازش را بنویسید.
تبدیل به LiteRT
از نوت بوک PyTorch Converter برای تبدیل یک مدل PyTorch به فرمت مناسب .tflite
استفاده کنید. برای راهنمایی عمیق در مورد انواع خطاهایی که ممکن است با آنها روبرو شوید و نحوه رفع آنها، به مبدل مشعل AI Edge README مراجعه کنید.
مدل شما باید با torch.export.export
سازگار باشد، به این معنی که باید با TorchDynamo قابل صادرات باشد. بنابراین، نباید هیچ شاخه شرطی پایتون که به مقادیر زمان اجرا در تانسورها بستگی دارد، داشته باشد. اگر خطاهای زیر را در حین torch.export.export
مشاهده کردید، مدل شما با torch.export.export
قابل صادرات نیست. مدل شما همچنین نباید دارای ابعاد ورودی یا خروجی دینامیکی بر روی تانسورهای خود باشد. این شامل ابعاد دسته ای است.
همچنین می توانید با یک مدل PyTorch سازگار با TensorRT یا ONNX قابل صادرات شروع کنید:
یک نسخه سازگار با TensorRT از یک مدل میتواند نقطه شروع خوبی باشد، زیرا برخی از انواع تبدیلهای TensorRT نیز به مدلهایی نیاز دارند که TorchDynamo قابل صادرات باشند. اگر از هر گونه عملیات NVIDIA / CUDA در مدل استفاده می کنید، باید آنها را با عملیات استاندارد PyTorch جایگزین کنید.
یک مدل PyTorch قابل صادرات با ONNX میتواند نقطه شروع خوبی باشد، اگرچه برخی از مدلهای ONNX از TorchScript به جای TorchDynamo برای صادرات استفاده میکنند، در این صورت ممکن است مدل قابل صادرات TorchDynamo نباشد (اگرچه احتمالاً از کد مدل اصلی نزدیکتر است).
برای اطلاعات بیشتر، تبدیل مدلهای PyTorch به LiteRT را ببینید.
بسته LiteRT را اضافه کنید
بسته @litertjs/core
را از npm نصب کنید:
npm install @litertjs/core
بسته را وارد کنید و فایلهای 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/`);
مدل را بارگذاری کنید
LiteRT.js و ابزارهای تبدیل LiteRT-TFJS را وارد و مقداردهی اولیه کنید. همچنین باید TensorFlow.js را وارد کنید تا تانسورها را به 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();
مدل LiteRT تبدیل شده را بارگیری کنید:
const model = await loadAndCompile('path_to_model.tflite', {
accelerator: 'webgpu', // or 'wasm'
});
خط لوله مدل را بنویسید
منطق قبل و بعد از پردازش را بنویسید که مدل را به برنامه شما متصل می کند. استفاده از TensorFlow.js برای پردازش قبل و بعد توصیه میشود، اما اگر در TensorFlow.js نوشته نشده است، میتوانید await tensor.data
فراخوانی کنید تا مقدار را بهعنوان یک ArrayBuffer دریافت کنید یا await tensor.array
تا یک آرایه JS ساختاریافته را دریافت کنید.
در زیر نمونه ای از خط لوله سرتاسر برای 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);
}
تست و عیب یابی
به بخش های زیر در مورد روش های آزمایش برنامه خود و رسیدگی به خطاها مراجعه کنید.
تست با ورودی های جعلی
پس از بارگذاری یک مدل، ایده خوبی است که ابتدا مدل را با ورودی های جعلی تست کنید. قبل از اینکه وقت خود را صرف نوشتن منطق پردازش قبل و بعد برای خط لوله مدل خود کنید، هر گونه خطای زمان اجرا را تشخیص می دهد. برای بررسی این موضوع، می توانید از تستر مدل LiteRT.js استفاده کنید یا آن را به صورت دستی آزمایش کنید.
تستر مدل LiteRT.js
تستر مدل LiteRT.js مدل شما را روی GPU و CPU با استفاده از ورودی های تصادفی اجرا می کند تا تأیید کند که مدل به درستی روی GPU اجرا می شود. موارد زیر را بررسی می کند:
- اینکه آیا انواع داده های ورودی و خروجی پشتیبانی می شوند.
- اینکه آیا همه عملیات در GPU در دسترس هستند یا خیر.
- خروجی های GPU چقدر با خروجی های CPU مرجع مطابقت دارند.
- عملکرد استنتاج GPU
برای اجرای تستر مدل LiteRT.js، npm i @litertjs/model-tester
و سپس npx model-tester
را اجرا کنید. یک تب مرورگر را برای شما باز می کند تا مدل خود را اجرا کنید.
تست مدل دستی
اگر ترجیح می دهید به جای استفاده از تستر مدل LiteRT.js ( @litertjs/model-tester
) مدل را به صورت دستی آزمایش کنید، می توانید ورودی های جعلی ایجاد کنید و مدل را با runWithTfjsTensors
اجرا کنید.
برای تولید ورودی های جعلی، باید نام و شکل تانسورهای ورودی را بدانید. این موارد را می توان با LiteRT.js با فراخوانی model.getInputDetails
یا model.getOutputDetails
پیدا کرد. یک راه ساده برای یافتن آنها، تعیین یک نقطه شکست پس از ایجاد مدل است. یا از Model Explorer استفاده کنید.
هنگامی که اشکال و نام های ورودی و خروجی را شناختید، می توانید مدل را با ورودی جعلی تست کنید. این اطمینان را ایجاد می کند که مدل قبل از نوشتن بقیه خط لوله یادگیری ماشین اجرا می شود. این آزمایش میکند که همه عملیات مدل پشتیبانی میشوند. به عنوان مثال:
// 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);
انواع خطا
برخی از مدلهای LiteRT ممکن است توسط LiteRT.js پشتیبانی نشوند. خطاها معمولاً در این دسته قرار می گیرند:
- عدم تطابق شکل : یک باگ شناخته شده که فقط بر GPU تأثیر می گذارد.
- عملیات پشتیبانی نمی شود : زمان اجرا از عملیاتی در مدل پشتیبانی نمی کند. پشتیبانی WebGPU نسبت به CPU پوشش محدودتری دارد، بنابراین اگر این خطا را در GPU مشاهده کردید، ممکن است بتوانید مدل را روی CPU اجرا کنید.
- نوع تانسور پشتیبانی نشده : LiteRT.js فقط از تانسورهای int32 و float32 برای ورودی ها و خروجی های مدل پشتیبانی می کند.
- مدل خیلی بزرگ : LiteRT.js در اندازه مدل هایی که می تواند بارگیری کند محدود است.
عملیات پشتیبانی نمی شود
این نشان می دهد که backend مورد استفاده یکی از عملیات های مدل را پشتیبانی نمی کند. شما باید مدل اصلی PyTorch را بازنویسی کنید تا از این عملیات جلوگیری کنید و دوباره آن را تبدیل کنید، یا ممکن است بتوانید مدل را روی CPU اجرا کنید.
در مورد BROADCAST_TO
، این ممکن است با یکسان کردن ابعاد دسته ای برای هر تانسور ورودی مدل حل شود. موارد دیگر ممکن است پیچیده تر باشند.
نوع تانسور پشتیبانی نشده
LiteRT.js فقط از تانسورهای int32 و float32 برای ورودی ها و خروجی های مدل پشتیبانی می کند.
مدل خیلی بزرگ
این معمولاً به صورت فراخوانی Aborted()
یا عدم تخصیص حافظه در زمان بارگذاری مدل ظاهر میشود. LiteRT.js از نظر اندازه مدلهایی که میتواند بارگذاری کند محدود است، بنابراین اگر این را میبینید، ممکن است مدل شما خیلی بزرگ باشد. می توانید وزن ها را با کوانتایزر ai-edge کوانتیزه کنید، اما محاسبات را روی float32 یا float16 نگه دارید و ورودی ها و خروجی ها را به صورت float32 یا int32 مدل کنید.