پلت فرم و محیط

TensorFlow.js در مرورگر و Node.js کار می‌کند، و در هر دو پلتفرم پیکربندی‌های مختلف زیادی وجود دارد. هر پلتفرم دارای مجموعه ای منحصر به فرد از ملاحظات است که بر نحوه توسعه برنامه ها تأثیر می گذارد.

در مرورگر، TensorFlow.js از دستگاه های تلفن همراه و همچنین دستگاه های دسکتاپ پشتیبانی می کند. هر دستگاه دارای مجموعه خاصی از محدودیت ها است، مانند WebGL API های موجود، که به طور خودکار برای شما تعیین و پیکربندی می شوند.

در Node.js، TensorFlow.js از اتصال مستقیم به TensorFlow API یا اجرای با اجرای کندتر CPU vanilla پشتیبانی می کند.

محیط ها

هنگامی که یک برنامه TensorFlow.js اجرا می شود، پیکربندی خاص محیط نامیده می شود. محیط از یک باطن جهانی و همچنین مجموعه‌ای از پرچم‌ها تشکیل شده است که ویژگی‌های ظریف TensorFlow.js را کنترل می‌کنند.

Backends

TensorFlow.js از چندین پشتیبان مختلف پشتیبانی می کند که ذخیره سازی تانسور و عملیات ریاضی را اجرا می کند. در هر زمان معین، تنها یک باطن فعال است. بیشتر اوقات، TensorFlow.js با توجه به محیط فعلی، به طور خودکار بهترین باطن را برای شما انتخاب می کند. با این حال، گاهی اوقات مهم است که بدانید از کدام backend استفاده می شود و چگونه آن را تغییر دهید.

برای یافتن پشتیبان مورد استفاده:

console.log(tf.getBackend());

اگر می خواهید به صورت دستی backend را تغییر دهید:

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

باطن WebGL

Backend WebGL، 'webgl'، در حال حاضر قدرتمندترین باطن برای مرورگر است. این بک‌اند تا 100 برابر سریع‌تر از باطن CPU وانیلی است. تانسورها به عنوان بافت های WebGL ذخیره می شوند و عملیات ریاضی در سایه زن های WebGL پیاده سازی می شوند. در اینجا چند نکته مفید وجود دارد که هنگام استفاده از این باطن باید بدانید: \

از مسدود کردن رشته رابط کاربری خودداری کنید

هنگامی که یک عملیات فراخوانی می شود، مانند tf.matMul(a, b)، tf.Tensor حاصل به طور همزمان برگردانده می شود، اما محاسبه ضرب ماتریس ممکن است هنوز آماده نباشد. این بدان معنی است که tf.Tensor بازگشتی فقط یک دسته برای محاسبه است. وقتی x.data() یا x.array() را فراخوانی می کنید، زمانی که محاسبات واقعاً کامل شد، مقادیر حل می شوند. این امر استفاده از متدهای x.data() و x.array() ناهمزمان را بر روی همتایان همگام خود x.dataSync() و x.arraySync() برای جلوگیری از مسدود شدن رشته رابط کاربری در حین تکمیل محاسبات مهم می کند.

مدیریت حافظه

یکی از اخطارها هنگام استفاده از WebGL، نیاز به مدیریت صریح حافظه است. WebGLTextures، جایی که داده‌های Tensor در نهایت ذخیره می‌شوند، به‌طور خودکار زباله‌ای توسط مرورگر جمع‌آوری نمی‌شوند.

برای از بین بردن حافظه یک tf.Tensor می توانید از متد dispose() استفاده کنید:

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

زنجیره ای کردن چندین عملیات با هم در یک برنامه بسیار رایج است. نگه داشتن ارجاع به همه متغیرهای میانی برای از بین بردن آنها می تواند خوانایی کد را کاهش دهد. برای حل این مشکل، TensorFlow.js یک متد tf.tidy() ارائه می‌کند که تمام tf.Tensor هایی را که پس از اجرای یک تابع برگردانده نمی‌شوند، پاک می‌کند، مشابه روشی که متغیرهای محلی هنگام اجرای یک تابع پاک می‌شوند:

const a = tf.tensor([[1, 2], [3, 4]]);
const y = tf.tidy(() => {
  const result = a.square().log().neg();
  return result;
});
دقت، درستی

در دستگاه های تلفن همراه، WebGL ممکن است فقط از بافت های ممیز شناور 16 بیتی پشتیبانی کند. با این حال، بیشتر مدل‌های یادگیری ماشین با وزنه‌ها و فعال‌سازی‌های ممیز شناور ۳۲ بیتی آموزش داده می‌شوند. این می تواند هنگام انتقال یک مدل برای یک دستگاه تلفن همراه مشکلاتی در دقت ایجاد کند زیرا اعداد شناور 16 بیتی فقط می توانند اعدادی را در محدوده [0.000000059605, 65504] نشان دهند. این به این معنی است که باید مراقب باشید که وزن ها و فعال سازی ها در مدل شما از این محدوده فراتر نرود. برای بررسی اینکه آیا دستگاه از بافت‌های 32 بیتی پشتیبانی می‌کند، مقدار tf.ENV.getBool('WEBGL_RENDER_FLOAT32_CAPABLE') را بررسی کنید، اگر این نادرست است، دستگاه فقط از بافت‌های ممیز شناور 16 بیتی پشتیبانی می‌کند. می‌توانید tf.ENV.getBool('WEBGL_RENDER_FLOAT32_ENABLED') برای بررسی اینکه آیا TensorFlow.js در حال حاضر از بافت‌های 32 بیتی استفاده می‌کند استفاده کنید.

تلفیقی Shader و بارگذاری بافت

TensorFlow.js با اجرای برنامه های سایه زن WebGL عملیات روی GPU را اجرا می کند. هنگامی که کاربر درخواست اجرای عملیاتی را می‌کند، این سایه‌زن‌ها با تنبلی جمع‌آوری و کامپایل می‌شوند. کامپایل کردن یک سایه زن روی CPU روی رشته اصلی اتفاق می افتد و می تواند کند باشد. TensorFlow.js سایه‌بان‌های کامپایل‌شده را به‌طور خودکار کش می‌کند، و دومین فراخوانی را با همان عملیات با تانسورهای ورودی و خروجی هم‌شکل بسیار سریع‌تر انجام می‌دهد. به طور معمول، برنامه های TensorFlow.js چندین بار در طول عمر برنامه از عملیات مشابه استفاده می کنند، بنابراین عبور دوم از یک مدل یادگیری ماشین بسیار سریعتر است.

TensorFlow.js همچنین داده های tf.Tensor را به عنوان WebGLTextures ذخیره می کند. وقتی یک tf.Tensor ایجاد می‌شود، ما بلافاصله داده‌ها را در GPU آپلود نمی‌کنیم، بلکه داده‌ها را تا زمانی که tf.Tensor در یک عملیات استفاده شود، روی CPU نگه می‌داریم. اگر tf.Tensor برای بار دوم استفاده شود، داده ها از قبل روی GPU هستند، بنابراین هزینه آپلود وجود ندارد. در یک مدل یادگیری ماشین معمولی، این بدان معناست که وزن‌ها در طول اولین پیش‌بینی از طریق مدل بارگذاری می‌شوند و عبور دوم از مدل بسیار سریع‌تر خواهد بود.

اگر به عملکرد اولین پیش‌بینی از طریق مدل یا کد TensorFlow.js اهمیت می‌دهید، توصیه می‌کنیم قبل از استفاده از داده‌های واقعی، مدل را با عبور دادن یک تانسور ورودی به همان شکل گرم کنید.

مثلا:

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);

Node.js TensorFlow باطن

در باطن TensorFlow Node.js، 'node'، TensorFlow C API برای تسریع عملیات استفاده می شود. این از شتاب سخت افزاری موجود دستگاه، مانند CUDA، در صورت وجود استفاده می کند.

در این باطن، درست مانند باطن WebGL، عملیات tf.Tensor به صورت همزمان برمی گردد. با این حال، بر خلاف باطن WebGL، این عملیات قبل از بازگرداندن تانسور کامل می شود. این بدان معنی است که تماس با tf.matMul(a, b) رشته رابط کاربری را مسدود می کند.

به همین دلیل، اگر قصد استفاده از آن را در یک برنامه تولیدی دارید، باید TensorFlow.js را در موضوعات کارگر اجرا کنید تا رشته اصلی مسدود نشود.

برای اطلاعات بیشتر در مورد Node.js، این راهنما را ببینید.

باطن WASM

TensorFlow.js یک Backend WebAssembly ( wasm ) ارائه می دهد که شتاب CPU را ارائه می دهد و می تواند به عنوان جایگزینی برای CPU وانیلی جاوا اسکریپت ( cpu ) و WebGL accelerated ( webgl ) استفاده شود. برای استفاده از آن:

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

اگر سرور شما فایل .wasm را در مسیر دیگری یا نام دیگری ارائه می‌کند، قبل از اینکه Backend را مقداردهی کنید، از setWasmPath استفاده کنید. برای اطلاعات بیشتر به بخش «استفاده از بسته‌ها» در README مراجعه کنید:

import {setWasmPath} from '@tensorflow/tfjs-backend-wasm';
setWasmPath(yourCustomPath);
tf.setBackend('wasm');
tf.ready().then(() => {...});
چرا WASM؟

WASM در سال 2015 به عنوان یک فرمت باینری مبتنی بر وب جدید معرفی شد و برنامه های نوشته شده با جاوا اسکریپت، C، C++ و غیره را به عنوان یک هدف کامپایل برای اجرا در وب ارائه می کند. WASM از سال 2017 توسط کروم، سافاری، فایرفاکس و اج پشتیبانی می‌شود و 90 درصد دستگاه‌ها در سراسر جهان از آن پشتیبانی می‌کنند.

کارایی

WASM از کتابخانه XNNPACK برای اجرای بهینه اپراتورهای شبکه عصبی استفاده می کند.

در مقابل جاوا اسکریپت : باینری‌های WASM معمولاً سریع‌تر از بسته‌های جاوا اسکریپت برای بارگیری، تجزیه و اجرا توسط مرورگرها هستند. جاوا اسکریپت به صورت پویا تایپ می شود و زباله جمع آوری می شود که می تواند باعث کاهش سرعت در زمان اجرا شود.

در مقابل WebGL : WebGL برای اکثر مدل‌ها سریع‌تر از WASM است، اما برای مدل‌های کوچک، WASM به دلیل هزینه‌های سربار ثابت اجرای سایه‌زن‌های WebGL می‌تواند از WebGL بهتر عمل کند. بخش "چه زمانی باید از WASM استفاده کنم" در زیر به بحث اکتشافی برای تصمیم گیری می پردازد.

قابلیت حمل و پایداری

WASM دارای محاسبات شناور 32 بیتی قابل حمل است که برابری دقیقی را در همه دستگاه ها ارائه می دهد. از سوی دیگر، WebGL مخصوص سخت افزار است و دستگاه های مختلف می توانند دقت متفاوتی داشته باشند (مثلاً به شناورهای ۱۶ بیتی در دستگاه های iOS).

مانند WebGL، WASM به طور رسمی توسط تمام مرورگرهای اصلی پشتیبانی می شود. برخلاف WebGL، WASM می تواند در Node.js اجرا شود و در سمت سرور بدون نیاز به کامپایل کتابخانه های بومی استفاده شود.

چه زمانی باید از WASM استفاده کنم؟

اندازه مدل و تقاضای محاسباتی

به طور کلی، WASM انتخاب خوبی است زمانی که مدل‌ها کوچک‌تر هستند یا به دستگاه‌های رده پایین‌تری که فاقد پشتیبانی WebGL (پسوند OES_texture_float ) هستند یا پردازنده‌های گرافیکی قدرتمندتری دارند اهمیت می‌دهید. نمودار زیر زمان های استنتاج (از TensorFlow.js 1.5.2) را در Chrome در مک بوک پرو 2018 برای 5 مدل از مدل های پشتیبانی شده رسمی ما در پشتیبان های WebGL، WASM و CPU نشان می دهد:

مدل های کوچکتر

مدل WebGL WASM CPU حافظه
BlazeFace 22.5 میلی‌ثانیه 15.6 میلی‌ثانیه 315.2 میلی‌ثانیه .4 مگابایت
فیس مش 19.3 میلی‌ثانیه 19.2 میلی‌ثانیه 335 میلی‌ثانیه 2.8 مگابایت

مدل های بزرگتر

مدل WebGL WASM CPU حافظه
PoseNet 42.5 میلی‌ثانیه 173.9 میلی‌ثانیه 1514.7 میلی‌ثانیه 4.5 مگابایت
BodyPix 77 میلی‌ثانیه 188.4 میلی‌ثانیه 2683 میلی‌ثانیه 4.6 مگابایت
MobileNet نسخه 2 37 میلی‌ثانیه 94 میلی‌ثانیه 923.6 میلی‌ثانیه 13 مگابایت

جدول بالا نشان می‌دهد که WASM 10 تا 30 برابر سریع‌تر از باطن CPU ساده JS در بین مدل‌ها است و با WebGL برای مدل‌های کوچک‌تری مانند BlazeFace که سبک وزن (400 کیلوبایت) است، اما تعداد عملیات مناسب (~140) دارد، قابل رقابت است. با توجه به اینکه برنامه های WebGL هزینه سربار ثابتی برای هر اجرای عملیات دارند، این توضیح می دهد که چرا مدل هایی مانند BlazeFace در WASM سریعتر هستند.

این نتایج بسته به دستگاه شما متفاوت خواهد بود. بهترین راه برای تعیین اینکه آیا WASM برای برنامه شما مناسب است یا خیر این است که آن را در باطن های مختلف ما آزمایش کنید.

استنتاج در مقابل آموزش

برای پرداختن به کاربرد اولیه برای استقرار مدل‌های از پیش آموزش‌دیده، توسعه باطن WASM استنتاج را بر پشتیبانی آموزشی اولویت می‌دهد. فهرست به‌روزی از عملیات‌های پشتیبانی‌شده در WASM را ببینید و اگر مدل شما عملیات پشتیبانی‌نشده دارد ، به ما اطلاع دهید . برای مدل‌های آموزشی، توصیه می‌کنیم از Node (TensorFlow C++) یا Backend WebGL استفاده کنید.

باطن CPU

باطن CPU، 'cpu'، کمترین عملکرد را دارد، با این حال ساده ترین است. همه عملیات ها در جاوا اسکریپت وانیلی پیاده سازی می شوند که باعث می شود کمتر موازی شوند. آنها همچنین رشته UI را مسدود می کنند.

این باطن می تواند برای آزمایش یا در دستگاه هایی که WebGL در دسترس نیست بسیار مفید باشد.

پرچم ها

TensorFlow.js دارای مجموعه ای از پرچم های محیطی است که به طور خودکار ارزیابی می شوند و بهترین پیکربندی را در پلتفرم فعلی تعیین می کنند. این پرچم ها بیشتر داخلی هستند، اما چند پرچم جهانی را می توان با API عمومی کنترل کرد.

  • tf.enableProdMode(): حالت تولید را فعال می کند که اعتبار مدل، بررسی های NaN و سایر بررسی های صحت را به نفع عملکرد حذف می کند.
  • tf.enableDebugMode() : حالت اشکال زدایی را فعال می کند، که هر عملیاتی که اجرا می شود و همچنین اطلاعات عملکرد زمان اجرا مانند ردپای حافظه و کل زمان اجرای هسته را به کنسول وارد می کند. توجه داشته باشید که این کار سرعت برنامه شما را بسیار کند می کند، از این در تولید استفاده نکنید.