שימוש במעבדי TPU של Coral Edge כדי להריץ מודלים של TFlite ב-Node עם TensorFlow.js

1. מבוא

54e81d02971f53e8.png

העדכון האחרון: 11 באפריל 2022

ב-Codelab הזה תלמדו איך לאמן מודל לסיווג תמונות באמצעות Teachable Machine, ומפעילים פתרונות חכמים עם האצת חומרה של Coral באמצעות TensorFlow.js, ספרייה חזקה וגמישה של למידת מכונה ל-JavaScript. אתם יוצרים אפליקציית Electron שמציגה תמונות ממצלמת אינטרנט ומסווגת אותן באמצעות Coral Edge TPU. גרסה פעילה מלאה של ה-Codelab הזה זמינה במאגר sig-tfjs GitHub.

האם צריך מכשיר Coral?

לא. אפשר לנסות את ה-codelab הזה בלי מכשיר Coral ועדיין לקבל ביצועים טובים במחשב שולחני באמצעות מאיץ WebNN.

מה תפַתחו

ב-Codelab הזה, תבנו אפליקציית Electron שמסווגת תמונות. האפליקציה שלכם:

  • מסווג תמונות ממצלמת האינטרנט לקטגוריות שהוגדרו במודל שאומן.
  • משתמש במאיץ Coral כדי לשפר את הביצועים, אם יש כזה.
  • משתמש ב-WebNN כדי לשפר את הביצועים, אם הפלטפורמה שלכם תומכת בכך.

מה תלמדו

  • איך להתקין ולהגדיר את חבילת ה-NPM‏ tfjs-tflite-node כדי להריץ מודלים של TFLite ב-Node.js.
  • איך מתקינים את ספריית זמן הריצה של Edge TPU כדי להריץ מודלים במכשיר Coral.
  • איך מאיצים את ההסקה של המודל באמצעות Coral edge TPU.
  • איך להאיץ את ההסקה של מודלים באמצעות WebNN.

ה-Codelab הזה מתמקד ב-TFLite ב-Node.js. מושגים ובלוקים של קוד שלא רלוונטיים מוצגים בקצרה, ואתם יכולים פשוט להעתיק ולהדביק אותם.

מה תצטרכו

כדי להשלים את ה-Codelab הזה, תצטרכו:

  • מחשב עם מצלמת אינטרנט.
  • ל-Coral, מומלץ להשתמש ב-Raspberry Pi עם Raspberry Pi OS (64-bit) with desktop.
  • ל-WebNN, מומלץ להשתמש במחשב Intel x86-64 עם Ubuntu 20.04 או Windows 10.
  • גרסה של Node.js שגדולה מ-12 או שווה לה.
  • ידע ב-JavaScript.
  • (מומלץ) Coral USB Accelerator להאצת המודל.

2. להגדרה

קבלת הקוד

ריכזנו את כל הקוד שדרוש לפרויקט הזה במאגר Git. כדי להתחיל, מעתיקים את הקוד ופותחים אותו בסביבת הפיתוח המועדפת. ב-codelab הזה מומלץ להשתמש ב-Raspberry Pi עם Raspberry Pi OS (64-bit) עם שולחן עבודה. כך קל לחבר מאיץ Coral.

מומלץ מאוד: שימוש ב-Git כדי לשכפל את המאגר ב-Raspberry Pi

כדי לקבל את הקוד, פותחים חלון טרמינל חדש ומשכפלים את המאגר:

git clone https://github.com/tensorflow/sig-tfjs.git

כל הקבצים שצריך לערוך בסדנת התכנות נמצאים בספרייה tfjs-tflite-node-codelab (בתוך sig-tfjs). בספרייה הזו תמצאו ספריות משנה בשמות starter_code,‏ cpu_inference_working,‏ coral_inference_working ו-webnn_inference_working. אלה נקודות ביקורת לשלבים של ה-codelab הזה.

בין הקבצים האחרים במאגר נמצאים חבילות ה-NPM ש-tfjs-tflite-node-codelab תלוי בהן. לא תצטרכו לערוך את הקבצים האלה, אבל תצטרכו להריץ חלק מהבדיקות שלהם כדי לוודא שהסביבה שלכם מוגדרת בצורה נכונה.

התקנה של ספריית זמן הריצה של Edge TPU

כדי להשתמש במכשירי Coral, צריך להתקין את ספריית זמן הריצה של Edge TPU. כדי להתקין אותו, פועלים לפי ההוראות לפלטפורמה שלכם.

ב-Linux / Raspberry Pi

ב-Linux, הספרייה זמינה מ-PPA של Google כחבילת Debian, ‏ libedgetpu1-std, לארכיטקטורות x86-64 ו-Armv8 (64 ביט). אם המעבד שלכם משתמש בארכיטקטורה אחרת, תצטרכו לקמפל אותו מהמקור.

מריצים את הפקודה הזו כדי להוסיף את Coral PPA של Google ולהתקין את ספריית Edge TPU Runtime.

# None of this is needed on Coral boards
# This repo is needed for almost all packages below
echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | sudo tee /etc/apt/sources.list.d/coral-edgetpu.list
# This repo is needed for only python3-coral-cloudiot and python3-coral-enviro
echo "deb https://packages.cloud.google.com/apt coral-cloud-stable main" | sudo tee /etc/apt/sources.list.d/coral-cloud.list

curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -

sudo apt-get update
sudo apt-get install libedgetpu1-std

ב-Windows / מערכות הפעלה אחרות

קובצי הפעלה בינאריים שעברו הידור מראש זמינים לגרסאות x86-64 של MacOS ו-Windows, ואפשר להתקין אותם על ידי הרצת הסקריפט install.sh או install.bat בארכיון אחרי ההורדה.

הפעלה מחדש של המכשיר

אחרי שמתקינים את Edge TPU Runtime, מפעילים מחדש את המכשיר כדי להפעיל את כלל Coral Udev החדש שהתווסף על ידי תוכנת ההתקנה.

אימות הזיהוי של מכשיר Coral

כדי לוודא שמכשיר Coral מזוהה ופועל, מריצים את בדיקות השילוב עבור חבילת coral-tflite-delegate. החבילה הזו נמצאת בספריית השורש של המאגר. כדי להריץ את בדיקות השילוב, מחברים את מאיץ Coral ומריצים את הפקודות האלה בספרייה של החבילה:

npx yarn
npx yarn build-deps
npx yarn test-integration

הפלט אמור להיראות כך:

yarn run v1.22.17
$ yarn build && yarn test-integration-dev
$ tsc
$ jasmine --config=jasmine-integration.json
Platform node has already been set. Overwriting the platform with node.
Randomized with seed 78904
Started

============================
Hi there 👋. Looks like you are running TensorFlow.js in Node.js. To speed things up dramatically, install our node backend, which binds to TensorFlow C++, by running npm i @tensorflow/tfjs-node, or npm i @tensorflow/tfjs-node-gpu if you have CUDA. Then call require('@tensorflow/tfjs-node'); (-gpu suffix for CUDA) at the start of your program. Visit https://github.com/tensorflow/tfjs-node for more details.
============================
WARNING: converting 'int32' to 'uint8'
.


1 spec, 0 failures
Finished in 2.777 seconds
Randomized with seed 78904 (jasmine --random=true --seed=78904)
Done in 6.36s.

אין צורך להתקין את @tensorflow/tfjs-node, כמו שמופיע ביומני הרישום, כי תפעילו את המודל ב-TFLite.

אם הפלט מכיל Encountered unresolved custom op: edgetpu-custom-op, סימן שמכשיר Coral לא זוהה. מוודאים שהתקנתם את ספריית זמן הריצה של edge TPU וחיברתם את מכשיר Coral למחשב. אפשר גם להיעזר במדריך תחילת העבודה של Coral כדי לבדוק את גרסת Python של Coral bindings. אם גרסת Python פועלת אבל הבדיקות האלה עדיין נכשלות, אפשר לשלוח לנו דוח על באג.

הרצת הקוד לתחילת הדרך

עכשיו אפשר להריץ את קוד לתחילת הדרך. כדי להתחיל, פועלים לפי השלבים הבאים.

  1. עוברים לספרייה starter_code בספרייה tfjs-tflite-node-codelab.
  2. מריצים את הפקודה npm install כדי להתקין יחסי תלות.
  3. מריצים את הפקודה npm start כדי להפעיל את הפרויקט. אפליקציה שמציגה פיד וידאו ממצלמת האינטרנט של המחשב אמורה להיפתח.

מהי נקודת ההתחלה שלנו?

נקודת ההתחלה שלנו היא אפליקציית מצלמה בסיסית של Electron שנועדה לשימוש ב-Codelab הזה. הקוד פושט כדי להציג את המושגים ב-Codelab, ואין בו טיפול בשגיאות. אם תבחרו להשתמש מחדש בקוד באפליקציה שנמצאת בשלב הייצור, הקפידו לטפל בכל השגיאות ולבדוק את כל הקוד באופן מלא.

אפליקציית Electron בסיסית עם פיד פעיל ממצלמת המכשיר.

היכרות עם הקוד לתחילת הדרך

יש הרבה קבצים בקוד לתחילת הדרך הזה, אבל הקובץ היחיד שצריך לערוך הוא renderer.js. הוא קובע מה יוצג בדף, כולל פיד הווידאו ורכיבי ה-HTML, וזה המקום שבו מוסיפים את מודל הלמידה החישובית לאפליקציה. בין הקבצים האחרים יש קובץ index.html, אבל כל מה שהוא עושה זה לטעון את הקובץ renderer.js. יש גם קובץ main.js, שהוא נקודת הכניסה ל-Electron. הוא שולט במחזור החיים של האפליקציה, כולל מה להציג כשהיא נפתחת ומה לעשות כשהיא נסגרת, אבל לא תצטרכו לבצע בו שינויים.

פתיחת כלי לניפוי באגים

יכול להיות שתצטרכו לנפות באגים באפליקציה במהלך העבודה עם ה-Codelab הזה. האפליקציה הזו מבוססת על Electron, ולכן יש בה כלי לניפוי באגים ב-Chrome. ברוב הפלטפורמות, אפשר לפתוח אותו באמצעות Ctrl + Shift + i. לוחצים על הכרטיסייה Console כדי לראות את היומנים והודעות השגיאה מהאפליקציה.

אין כאן עוד הרבה מה לגלות, אז בואו נתחיל לאמן את מסווג התמונות.

3. אימון מסווג תמונות

בקטע הזה, תאמנו גרסאות של TFLite ו-Coral של מודל סיווג תמונות בהתאמה אישית.

אימון המסווג

מסווג תמונות מקבל תמונות קלט ומקצה להן תוויות. ב-codelab הזה, תשתמשו ב-Teachable Machine כדי לאמן מודל בדפדפן. כדי להאיץ את ההדרכה של הקטע הזה, אפשר להשתמש במחשב נייח או במחשב נייד במקום ב-Raspberry Pi, אבל תצטרכו להעתיק את הקבצים שיתקבלו ל-Pi.

עכשיו אפשר לאמן מודל. אם אתם לא בטוחים איזה סוג מודל לאמן, מודל קל לאימון הוא גלאי אנשים, שמזהה רק אם יש אדם בפריים.

  1. פותחים את דף ההדרכה של Teachable Machine בכרטיסייה חדשה.
  2. בוחרים באפשרות פרויקט תמונה ואז באפשרות מודל תמונה רגיל.
  3. מוסיפים תמונות לדוגמה לכל כיתה. הדרך הקלה ביותר לעשות זאת היא באמצעות הקלט ממצלמת האינטרנט. אפשר גם לשנות את השמות של הכיתות.
  4. אחרי שאוספים מספיק נתונים לכל כיתה (בדרך כלל מספיקות 50 דוגמאות), לוחצים על Train Model (אימון המודל).

אחרי שהאימון של המודל יסתיים, תוצג תצוגה מקדימה של הפלט של המודל.

מודל עובר אימון על תמונות משתי קטגוריות,

אפשר לנסות לתת למודל קלטים שונים. אם אתם מוצאים קלט שסווג בצורה שגויה, אתם יכולים להוסיף אותו לנתוני האימון ולאמן מחדש את המודל.

  1. כשמרוצים מרמת הדיוק של המודל, לוחצים על ייצוא המודל. תצטרכו להוריד שתי גרסאות נפרדות של המודל.
  2. מייצאים את המודל כמודל TensorFlow Lite Floating point. הקובץ converted_tflite.zip יורד. שפועל במעבד.
  3. מייצאים את המודל כמודל Tensorflow Lite EdgeTPU. תתבצע הורדה של קובץ בשם converted_edgetpu.zip שפועל ב-Coral Edge TPU.

4. הפעלת מודל ה-CPU באפליקציה

אחרי שמאמנים מודל, צריך להוסיף אותו לאפליקציה. בסיום הקטע הזה, האפליקציה תוכל להפעיל את המודל באמצעות המעבד של המכשיר.

הוספת קובץ המודל לאפליקציה

מבטלים את הדחיסה של קובץ המודל converted_tflite.zip שהורדתם כשאימנתם את המסווג. יש שני קבצים בארכיון. ‫model_uquant.tflite הוא מודל TFLite שנשמר, כולל גרף המודל והמשקלים. ‫labels.txt מכיל את התוויות שקריאות לבני אדם של הכיתות שהמודל חוזה. ממקמים את שני הקבצים ב- modeldirectory.

התקנת יחסי תלות

כדי לטעון מודל ולבצע עיבוד מקדים של נתוני הקלט, צריך כמה תלויות מ-TensorFlow.js:

  • tfjs-tflite-node: חבילת TensorFlow.js להרצת מודלים של TFLite ב-Node.js.
  • @tensorflow/tfjs: החבילה הראשית של TensorFlow.js.

החבילה @tensorflow/tfjs כבר מותקנת, אבל צריך להתקין את tfjs-tflite-node באמצעות הפקודה הבאה:

npm install --save tfjs-tflite-node

אחרי שמתקינים אותו, מוסיפים אותו לאפליקציה בחלק העליון של renderer.js:

CODELAB חלק 1: ייבוא של tfjs-tflite-node.

const {loadTFLiteModel} = require('tfjs-tflite-node');

טעינת המודל

עכשיו אפשר לטעון את המודל. ‫tfjs-tflite-node מספק את הפונקציה loadTFLiteModel כדי לעשות את זה. הוא יכול לטעון מודלים מנתיב קובץ, מ-ArrayBuffer או מכתובת URL של TFHub. כדי לטעון את המודל ואת המשקלים שלו, מוסיפים את הקוד הבא לפונקציה main:

CODELAB part 1: Load the model here.

const modelPath = './model/model_unquant.tflite';
const model = await loadTFLiteModel(modelPath);
const labels = fs.readFileSync('./model/labels.txt', 'utf8')
      .split('\n');

הפעלת המודל

הפעלת המודל מתבצעת בשלושה שלבים. קודם כול, שולפים ומעבדים מראש פריים קלט ממצלמת האינטרנט. אחר כך מריצים את המודל על הפריים הזה ומקבלים חיזוי. לאחר מכן, מציגים את התחזית בדף.

עיבוד מראש של הקלט ממצלמת האינטרנט

בשלב הזה, מצלמת האינטרנט היא רק רכיב HTML, והפריימים שמוצגים בה לא זמינים לקובץ JavaScript renderer.js. כדי לשלוף פריימים ממצלמת האינטרנט, TensorFlow.js מספקת את tf.data.webcam, שכוללת את השיטה capture() שקל להשתמש בה כדי לצלם פריימים מהמצלמה.

כדי להשתמש בו, צריך להוסיף את קוד ההגדרה הזה אל main():

CODELAB part 1: Set up tf.data.webcam here.

const tensorCam = await tf.data.webcam(webcam);

לאחר מכן, כדי לצלם תמונה בכל פריים, מוסיפים את הקוד הבא ל-run():

CODELAB part 1: Capture webcam frames here.

const image = await tensorCam.capture();

צריך גם לבצע עיבוד מקדים לכל פריים כדי שיהיה תואם למודל. למודל שבו משתמשים ב-Codelab הזה יש צורת קלט [1, 224, 224, 3], ולכן הוא מצפה לתמונה בפורמט RGB בגודל 224 על 224 פיקסלים. הפונקציה tensorCam.capture() מחזירה צורה של [224, 224, 3], ולכן צריך להוסיף מימד נוסף לחלק הקדמי של הטנסור באמצעות tf.expandDims. בנוסף, מודל ה-CPU מצפה לקלט Float32 בין ‎-1 ל-1, אבל מצלמת האינטרנט מתעדת ערכים מ-0 עד 255. אפשר לחלק את טנסור הקלט ב-127 כדי לשנות את הטווח שלו מ-[0, 255] ל-[0, ‎~2] ואז להחסיר 1 כדי לקבל את הטווח הרצוי [‎-1, ‎~1]. כדי לעשות את זה, מוסיפים את השורות האלה ל-tf.tidy() בפונקציה run():

CODELAB חלק 1: עיבוד מראש של פריימים ממצלמת אינטרנט

const expanded = tf.expandDims(image, 0);
const divided = tf.div(expanded, tf.scalar(127));
const normalized = tf.sub(divided, tf.scalar(1));

חשוב להשליך טנסורים אחרי השימוש בהם. ‫tf.tidy() עושה את זה באופן אוטומטי לקוד שכלול בקריאה החוזרת שלו, אבל הוא לא תומך בפונקציות אסינכרוניות. תצטרכו להשמיד באופן ידני את טנסור התמונה שיצרתם קודם לכן באמצעות קריאה לשיטה dispose() שלו.

CODELAB part 1: Dispose webcam frames here.

image.dispose();

הפעלת המודל והצגת התוצאות

כדי להריץ את המודל על הקלט שעבר עיבוד מראש, קוראים ל-model.predict() על הטנזור המנורמל. הפונקציה מחזירה טנסור חד-ממדי שמכיל את ההסתברות החזויה של כל תווית. כדי לקבל את הסיכוי באחוזים של כל תווית, מכפילים את ההסתברות ב-100 ומשתמשים בפונקציה showPrediction שכלולה בקוד לתחילת הדרך כדי להציג את התחזית של המודל על המסך.

הקוד הזה משתמש גם ב-stats.js כדי למדוד את משך הזמן שלוקח לחיזוי, על ידי הצבת קריאות ל-stats.begin ול-stats.end סביב model.predict.

CODELAB part 1: Run the model and display the results here.

stats.begin();
const prediction = model.predict(normalized);
stats.end();
const percentage = tf.mul(prediction, tf.scalar(100));
showPrediction(percentage.dataSync(), labels);

מריצים שוב את האפליקציה עם yarn start, ואמורים לראות את הסיווגים מהמודל.

מודל ה-CPU של TFLite פועל באפליקציית Electron. הוא מסווג תמונות ממצלמת האינטרנט ומציג את ערכי הביטחון לכל סיווג למטה.

ביצועים

בשלב הזה, המודל פועל במעבד. זה בסדר למחשבים נייחים ולרוב המחשבים הניידים, אבל יכול להיות שזה לא רצוי אם מריצים את הפקודה ב-Raspberry Pi או במכשיר אחר עם צריכת חשמל נמוכה. ב-Raspberry Pi 4, סביר להניח שתראו בסביבות 10 FPS, יכול להיות שזה לא מספיק מהר לחלק מהאפליקציות. כדי לשפר את הביצועים בלי להשתמש במחשב מהיר יותר, אפשר להשתמש בסיליקון ספציפי לאפליקציה בצורה של Coral Edge TPU.

5. הפעלת מודל Coral באפליקציה

אם אין לכם מכשיר Coral, אתם יכולים לדלג על הקטע הזה.

השלב הזה ב-codelab מבוסס על הקוד שכתבתם בקטע הקודם, אבל אם אתם רוצים להתחיל מחדש, אתם יכולים להשתמש בנקודת הבדיקה cpu_inference_working.

השלבים להרצת מודל Coral כמעט זהים לשלבים להרצת מודל CPU. ההבדל העיקרי הוא פורמט המודל. מכיוון ש-Coral תומך רק בטנסורים מסוג uint8, המודל עובר קוונטיזציה. ההגדרה הזו משפיעה על טנסורי הקלט שמועברים למודל ועל טנסורי הפלט שהמודל מחזיר. הבדל נוסף הוא שצריך לקמפל מודלים באמצעות קומפיילר Edge TPU כדי להריץ אותם ב-Coral TPU. השלב הזה כבר בוצע ב-TeachableMachine, אבל אפשר ללמוד איך לבצע אותו במודלים אחרים בתיעוד של Coral.

הוספת קובץ המודל של Coral לאפליקציה

מבטלים את הדחיסה של קובץ המודל converted_edgetpu.zip שהורדתם כשאימנתם את המסווג. הארכיון כולל שני קבצים. ‫model_edgetpu.tflite הוא מודל TFLite שנשמר, כולל גרף המודל והמשקלים. ‫labels.txt מכיל את התוויות שקריאות לבני אדם של הכיתות שהמודל חוזה. ממקמים את קובץ המודל בספרייה coral_model.

התקנת יחסי תלות

כדי להריץ מודלים של Coral, צריך את ספריית זמן הריצה של Edge TPU. לפני שממשיכים, חשוב לוודא שהאפליקציה מותקנת בהתאם להוראות ההגדרה.

הגישה למכשירי Coral היא באמצעות TFLite delegates. כדי לגשת אליהם מ-JavaScript, מתקינים את חבילת coral-tflite-delegate:

npm install --save coral-tflite-delegate

לאחר מכן, מייבאים את הנציג על ידי הוספת השורה הבאה לראש הקובץ renderer.js:

CODELAB part 2: Import the delegate here.

const {CoralDelegate} = require('coral-tflite-delegate');

טעינת המודל

עכשיו אפשר לטעון את מודל Coral. הפעולה הזו מתבצעת באותו אופן כמו במודל CPU, רק שעכשיו מעבירים אפשרויות לפונקציה loadTFLiteModel כדי לטעון את Coral delegate.

CODELAB part 2: Load the delegate model here.

const coralModelPath = './coral_model/model_edgetpu.tflite';
const options = {delegates: [new CoralDelegate()]};
const coralModel = await loadTFLiteModel(coralModelPath, options);

אין צורך לטעון את התוויות כי הן זהות לאלה של מודל ה-CPU.

הוספת לחצן למעבר בין CPU ל-Coral

מוסיפים את מודל Coral לצד מודל ה-CPU שהוספתם בקטע הקודם. אם מריצים את שניהם בו-זמנית, קשה לראות את ההבדלים בביצועים, ולכן יש לחצן מעבר שמאפשר לעבור בין ביצוע ב-Coral לבין ביצוע במעבד.

מוסיפים את הכפתור עם הקוד הזה:

CODELAB part 2: Create the delegate button here.

let useCoralDelegate = false;
const toggleCoralButton = document.createElement('button');
function toggleCoral() {
  useCoralDelegate = !useCoralDelegate;
  toggleCoralButton.innerText = useCoralDelegate
      ? 'Using Coral. Press to switch to CPU.'
      : 'Using CPU. Press to switch to Coral.';
}
toggleCoralButton.addEventListener('click', toggleCoral);
toggleCoral();
document.body.appendChild(toggleCoralButton);

בואו נשתמש בתנאי הזה בפונקציה run(). אם הערך של useCoralDelegate הוא false, צריך להפעיל את הגרסה של ה-CPU. אחרת, הוא מריץ את גרסת Coral (אבל כרגע הוא לא יעשה כלום). עוטפים את הקוד מהרצת מודל ה-CPU במשפט if. שימו לב: הטנזור expanded לא נכלל במשפט התנאי if כי נעשה בו שימוש במודל Coral.

CODELAB part 2: Check whether to use the delegate here.

// NOTE: Don't just copy-paste this code into the app.
// You'll need to edit the code from the CPU section.
const expanded = tf.expandDims(image, 0);
if (useCoralDelegate) {
  // CODELAB part 2: Run Coral prediction here.
} else {
  const divided = tf.div(expanded, tf.scalar(127));
  const normalized = tf.sub(divided, tf.scalar(1));
  stats.begin();
  const prediction = model.predict(normalized);
  stats.end();
  const percentage = tf.mul(prediction, tf.scalar(100));
  showPrediction(percentage.dataSync(), labels);
}

הפעלת המודל

גרסת Coral של המודל מצפה לטנסורים מסוג uint8 מ-0 עד 255, ולכן אין צורך לנרמל את הקלט שלה. עם זאת, הפלט הוא גם טנסור uint8 בטווח 0 עד 255. לפני שהערך מוצג, צריך להמיר אותו למספר עשרוני בין 0 ל-100.

‫CODELAB חלק 2: הפעלת חיזוי של Coral כאן. (זה חלק מקטע הקוד שלמעלה)

stats.begin();
const prediction = coralModel.predict(expanded);
stats.end();
const percentage = tf.div(tf.mul(prediction, tf.scalar(100)), tf.scalar(255));
showPrediction(percentage.dataSync(), labels);

מריצים שוב את האפליקציה עם yarn start, והיא אמורה להציג סיווגים ממאיץ Coral.

מודלי ה-CPU וה-Coral פועלים באפליקציה אחד בכל פעם, ויש כפתור למעבר ביניהם. דגם המעבד מגיע לכ-20 פריימים לשנייה, ודגם Coral מגיע לכ-45 פריימים לשנייה.

אפשר לעבור בין מסקנות של Coral לבין מסקנות של מעבד (CPU) בלחיצה על הלחצן. יכול להיות שתבחינו בדירוגי מהימנות פחות מדויקים במודל Coral בהשוואה למודל המעבד (CPU), ובדרך כלל הם מסתיימים במספר עשרוני זוגי. הירידה ברמת הדיוק היא תוצאה של הפעלת מודל שעבר קוונטיזציה ב-Coral. בדרך כלל זה לא משנה בפועל, אבל כדאי לזכור את זה.

הערה לגבי ביצועים

קצב הפריימים שאתם רואים כולל עיבוד מקדים ועיבוד שלאחר מכן, ולכן הוא לא מייצג את היכולות של חומרת Coral. כדי לקבל מושג טוב יותר לגבי הביצועים, אפשר ללחוץ על מד ה-FPS עד שמוצג זמן האחזור (באלפיות השנייה), שמודד רק את הקריאה ל-model.predict. עם זאת, המדידה הזו עדיין כוללת את הזמן שנדרש להעברת טנסורים לקישורי C מקוריים של TFLite ואז למכשיר Coral, ולכן היא לא מדויקת לחלוטין. כדי לקבל נקודות השוואה מדויקות יותר של ביצועים שנכתבו ב-C++, אפשר לעיין בדף נקודות ההשוואה של EdgeTPU.

חשוב לציין גם שהסרטון צולם במחשב נייד ולא ב-Raspberry Pi, ולכן יכול להיות שתראו ערך FPS שונה.

האצת העיבוד המקדים של Coral

במקרים מסוימים, אפשר להחליף את ה-backends של TFJS כדי לזרז את העיבוד המקדים. ה-Backend שמוגדר כברירת מחדל הוא WebGL, שמתאים לפעולות גדולות שאפשר לבצע במקביל, אבל האפליקציה הזו לא מבצעת הרבה פעולות כאלה בשלב העיבוד המקדים (הפעולה היחידה שהיא משתמשת בה היא expandDims, שלא מתבצעת במקביל). כדי להימנע מהשהייה הנוספת שנוצרת בהעברת טנסורים אל ה-GPU וממנו, אפשר לעבור ל-backend של המעבד (CPU). לשם כך, מוסיפים את השורה הזו אחרי שורות הייבוא בחלק העליון של הקובץ.

tf.setBackend(cpu');

השינוי הזה משפיע גם על העיבוד המקדים של מודל ה-CPU של TFLite, שהוא מקביל, ולכן המודל פועל הרבה יותר לאט.

6. האצת מודל המעבד באמצעות WebNN

אם אין לכם מאיץ Coral, או אם אתם רוצים לנסות דרך אחרת להאצת המודל, אתם יכולים להשתמש בנציג WebNN TFLite. הנציג הזה משתמש בחומרה של למידת מכונה שמוטמעת במעבדי Intel כדי להאיץ את הסקת המודל באמצעות ערכת הכלים OpenVINO. לכן, יש לו דרישות נוספות שלא נכללו בקטע ההגדרה של ה-codelab הזה, ותצטרכו להתקין את ערכת הכלים OpenVINO. לפני שממשיכים, חשוב לבדוק את ההגדרה שלכם בהשוואה לפלטפורמות של מערכות היעד שנתמכות. שימו לב שהנציג של WebNN עדיין לא תומך ב-macOS.

התקנת ערכת הכלים OpenVINO

ערכת הכלים OpenVINO משתמשת בחומרה של למידת מכונה שמוטמעת במעבדי Intel כדי להאיץ את המודלים. אפשר להוריד גרסה שעברה קומפילציה מראש מ-Intel או לבנות אותה ממקור. יש כמה דרכים להתקין את OpenVINO, אבל לצורך ה-Codelab הזה מומלץ להשתמש בסקריפט ההתקנה ל-Windows או ל-Linux. חשוב להתקין את גרסת זמן הריצה 2021.4.2 LTS, כי יכול להיות שגרסאות אחרות לא יהיו תואמות. אחרי שמריצים את קובץ ההתקנה, צריך להגדיר את משתני הסביבה של המעטפת כמו שמתואר בהוראות ההתקנה ל-Linux או ל-Windows ( פתרון קבוע), או על ידי הרצת הפקודה setupvars.sh (Linux) או setupvars.bat (Windows) שנמצאת בספרייה webnn-tflite-delegate.

אימות הפעולה של WebNN Delegate

כדי לוודא שההעברה של WebNN פועלת כמו שצריך, מריצים את בדיקות השילוב של חבילת webnn-tflite-delegate שנמצאת בספריית השורש של המאגר. כדי להריץ את בדיקות השילוב, מריצים את הפקודות הבאות בספרייה של החבילה:

# In webnn-tflite-delegate/
npx yarn
npx yarn test-integration

הפלט אמור להיראות כך:

WebNN delegate: WebNN device set to 0.
INFO: Created TensorFlow Lite WebNN delegate for device Default and power Default.

============================
Hi there 👋. Looks like you are running TensorFlow.js in Node.js. To speed things up dramatically, install our node backend, which binds to TensorFlow C++, by running npm i @tensorflow/tfjs-node, or npm i @tensorflow/tfjs-node-gpu if you have CUDA. Then call require('@tensorflow/tfjs-node'); (-gpu suffix for CUDA) at the start of your program. Visit https://github.com/tensorflow/tfjs-node for more details.
============================
label: wine bottle
score:  0.934505045413971
.


1 spec, 0 failures
Finished in 0.446 seconds
Randomized with seed 58441 (jasmine --random=true --seed=58441)
Done in 8.07s.

אם מופיע פלט כמו זה, סימן שיש שגיאת הגדרה:

Platform node has already been set. Overwriting the platform with node.
Randomized with seed 05938
Started
error Command failed with exit code 3221225477.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

הפלט הזה כנראה מצביע על כך שלא הגדרתם את משתני הסביבה של OpenVINO. בשלב הזה, אפשר להגדיר אותן על ידי הפעלת הפקודה setupvars.sh (Linux) או setupvars.bat (Windows), אבל כדאי להגדיר אותן באופן קבוע באמצעות ההוראות ל-Linux או ל-Windows ( פתרון קבוע). אם אתם משתמשים ב-Windows, ה

setupvars.bat

הפקודה לא תומכת ב-Git bash, לכן חשוב להריץ אותה ופקודות אחרות מתוך ה-Codelab הזה דרך שורת הפקודה של Windows.

התקנת WebNN Delegate

אחרי שמתקינים את OpenVINO, אפשר להשתמש ב-WebNN כדי להאיץ את מודל ה-CPU. הקטע הזה ב-codelab מתבסס על הקוד שכתבתם בקטע 'הפעלת מודל CPU באפליקציה'. אפשר להשתמש בקוד שכתבתם בשלב הזה, אבל אם כבר השלמתם את הקטע בנושא Coral, השתמשו בנקודת הבדיקה cpu_inference_working כדי להתחיל מחדש.

החלק של Node.js ב-WebNN delegate מופץ ב-npmjs. כדי להתקין אותו, מריצים את הפקודה הבאה:

npm install --save webnn-tflite-delegate

לאחר מכן, מייבאים את הנציג על ידי הוספת השורה הבאה לראש הקובץ renderer.js:

CODELAB part 2: Import the delegate here.

const {WebNNDelegate, WebNNDevice} = require('webnn-tflite-delegate');

הנציג WebNN תומך בהרצה במעבד (CPU) או ב-GPU. האפשרות WebNNDevice מאפשרת לבחור באיזה מהם להשתמש.

טעינת המודל

עכשיו אפשר לטעון את המודל עם ההרשאה WebNN מופעלת. ב-Coral, היה צריך לטעון קובץ מודל אחר, אבל WebNN תומך באותו פורמט מודל כמו TFLite. כדי להפעיל את WebNNDelegate, מוסיפים אותו לרשימת הנציגים שמועברים למודל:

CODELAB part 2: Load the delegate model here.

let webnnModel = await loadTFLiteModel(modelPath, {
  delegates: [new WebNNDelegate({webnnDevice: WebNNDevice.DEFAULT})],
});

אין צורך לטעון מחדש את התוויות כי זה אותו מודל.

הוספת כפתור למעבר בין TfLite CPU לבין WebNN

עכשיו, אחרי שהגרסה של המודל ב-WebNN מוכנה, מוסיפים לחצן למעבר בין WebNN לבין TfLite CPU inference. אם מפעילים את שניהם בו-זמנית, קשה לראות את ההבדלים בביצועים.

מוסיפים את הלחצן עם הקוד הזה (שימו לב שעדיין לא תהיה אפשרות להחליף מודלים):

CODELAB part 2: Create the delegate button here.

let useWebNNDelegate = false;
const divElem = document.createElement('div');
const toggleWebNNButton = document.createElement('button');
function toggleWebNN() {
  useWebNNDelegate = !useWebNNDelegate;
  toggleWebNNButton.innerHTML = useWebNNDelegate
      ? 'Using WebNN. Press to switch to TFLite CPU.'
      : 'Using TFLite CPU. Press to switch to WebNN.';
  divElem.hidden = useWebNNDelegate ? false : true;
}

toggleWebNNButton.addEventListener('click', toggleWebNN);
toggleWebNN();
document.body.appendChild(toggleWebNNButton);
document.body.appendChild(divElem);

הקוד הזה מוסיף גם רכיב div שמשמש להגדרת WebNN בקטע הבא.

הוספת תפריט נפתח למעבר בין מכשירי WebNN

‫WebNN תומך בהרצה במעבד וב-GPU, לכן כדאי להוסיף תפריט נפתח כדי לעבור ביניהם. מוסיפים את הקוד הזה אחרי הקוד שיוצר את הלחצן:

// Create elements for WebNN device selection
divElem.innerHTML = '<br/>WebNN Device: ';
const selectElem = document.createElement('select');
divElem.appendChild(selectElem);

const webnnDevices = ['Default', 'GPU', 'CPU'];
// append the options
for (let i = 0; i < webnnDevices.length; i++) {
  var optionElem = document.createElement('option');
  optionElem.value = i;
  optionElem.text = webnnDevices[i];
  selectElem.appendChild(optionElem);
}

עכשיו, אם מריצים את האפליקציה, רואים תפריט נפתח עם האפשרויות Default,‏ GPU ו-CPU. אם תבחרו באחת מהאפשרויות האלה, לא יקרה שום דבר כי התפריט הנפתח עדיין לא מחובר. באפליקציה מוצג תפריט נפתח שבו אפשר לבחור את מכשיר WebNN מתוך האפשרויות &#39;ברירת מחדל&#39;, &#39;GPU&#39; או &#39;CPU&#39;.

איך משנים את המכשיר באמצעות התפריט הנפתח

כדי לקשר את התפריט הנפתח כך שישנה את המכשיר שבו נעשה שימוש ב-WebNN, מוסיפים listener לאירוע change של רכיב בורר התפריט הנפתח. כשהערך שנבחר משתנה, צריך ליצור מחדש את מודל WebNN עם מכשיר WebNN תואם שנבחר באפשרויות ההקצאה.

מוסיפים את הקוד הבא אחרי הקוד שהוסיף את התפריט הנפתח:

selectElem.addEventListener('change', async () => {
  let webnnDevice;
  switch(selectElem.value) {
    case '1':
      webnnDevice = WebNNDevice.GPU;
      break;
    case '2':
      webnnDevice = WebNNDevice.CPU;
      break;
    default:
      webnnDevice = WebNNDevice.DEFAULT;
      break;
  }
  webnnModel = await loadTFLiteModel(modelPath, {
    delegates: [new WebNNDelegate({webnnDevice})],
  });
});

בעקבות השינוי הזה, בכל פעם שמשנים את התפריט הנפתח, נוצר מודל חדש עם ההגדרות הנכונות. עכשיו הגיע הזמן לחבר את מודל WebNN ולהשתמש בו להסקת מסקנות.

הפעלת מודל WebNN

מודל WebNN מוכן לשימוש, אבל הלחצן למעבר בין WebNN לבין TfLite CPU עדיין לא מחליף את המודל. כדי להחליף את המודל, קודם צריך לשנות את השם של המשתנה model מהקטע הראשון של ה-codelab, שבו טענתם את מודל ה-CPU של TfLite.

שנה את השורה הבאה...

const model = await loadTFLiteModel(modelPath);

...כדי שיתאים לשורה הזו.

const cpuModel = await loadTFLiteModel(modelPath);

אחרי שמשנים את השם של המשתנה model ל-cpuModel, מוסיפים אותו לפונקציה run כדי לבחור את המודל הנכון בהתאם למצב הכפתור:

CODELAB part 2: Check whether to use the delegate here.

let model;
if (useWebNNDelegate) {
  model = webnnModel;
} else {
  model = cpuModel;
}

עכשיו, כשמריצים את האפליקציה, הכפתור עובר בין TfLite CPU לבין WebNN. מודל ה-CPU של TFLite ומודלי ה-CPU וה-GPU של WebNN פועלים באפליקציה. כשמודל WebNN אחד פעיל, אפשר לעבור בין המודלים באמצעות תפריט נפתח. דגם המעבד (CPU) מגיע ל-15 FPS בערך, ודגם המעבד (CPU) של WebNN מגיע ל-40 FPS בערך.

אם יש לכם כרטיס גרפי משולב של Intel, אתם יכולים גם לעבור בין הסקה של WebNN CPU לבין הסקה של WebNN GPU.

הערה לגבי ביצועים

קצב הפריימים שאתם רואים כולל עיבוד מקדים ועיבוד שלאחר מכן, ולכן הוא לא מייצג את היכולות של WebNN. כדי לקבל מושג טוב יותר לגבי הביצועים, אפשר ללחוץ על מד ה-FPS עד שמוצג זמן האחזור (באלפיות השנייה), שמודד רק את הקריאה ל-model.predict. עם זאת, המדידה הזו עדיין כוללת את הזמן שנדרש להעברת טנסורים ל-TFLite native C bindings, ולכן היא לא מדויקת לחלוטין.

7. מזל טוב

מעולה! סיימתם את הפרויקט הראשון שלכם ב-Coral או ב-WebNN באמצעות tfjs-tflite-node ב-Electron.

כדאי לנסות את התכונה ולבדוק אותה על מגוון תמונות. אפשר גם לאמן מודל חדש ב-TeachableMachine כדי לסווג משהו שונה לחלוטין.

סיכום

ב-codelab הזה למדתם:

  • איך מתקינים ומגדירים את חבילת ה-npm‏ tfjs-tflite-node כדי להריץ מודלים של TFLite ב-Node.js.
  • איך מתקינים את ספריית זמן הריצה של Edge TPU כדי להריץ מודלים במכשיר Coral.
  • איך מאיצים את ההסקה של המודל באמצעות Coral edge TPU.
  • איך להאיץ את ההסקה של מודלים באמצעות WebNN.

מה השלב הבא?

עכשיו שיש לכם בסיס עבודה להתחיל ממנו, אילו רעיונות יצירתיים תוכלו להעלות כדי להרחיב את מודל למידת המכונה הזה לתרחיש שימוש בעולם האמיתי שאתם עשויים לעבוד עליו? אולי תוכלו ליצור מהפכה בתחום שבו אתם עובדים באמצעות הסקה מהירה ובמחיר סביר, או אולי תוכלו לשנות טוסטר כך שהוא יפסיק לקלות כשהלחם נראה בדיוק כמו שצריך. האפשרויות הן אינסופיות.

כדי להעמיק את הידע וללמוד איך TeachableMachine אימן את המודל שבו השתמשתם, כדאי לעיין ב-codelab בנושא Transfer Learning. אם אתם מחפשים מודלים אחרים שפועלים עם Coral, כמו זיהוי דיבור והערכת תנוחה, כדאי לעיין בכתובת coral.ai/models. בנוסף, אפשר למצוא גרסאות של המודלים האלה ועוד הרבה מודלים אחרים שמתאימים למעבד ב-TensorFlow Hub.

שיתוף התוצרים עם Google

אתם יכולים בקלות להרחיב את מה שיצרתם היום גם לתרחישי שימוש יצירתיים אחרים, ואנחנו ממליצים לכם לחשוב מחוץ לקופסה ולהמשיך ליצור.

אל תשכחו לתייג אותנו ברשתות החברתיות באמצעות ההאשטאג #MadeWithTFJS כדי לקבל הזדמנות שהפרויקט שלכם יוצג בבלוג של TensorFlow או אפילו באירועים עתידיים. נשמח לראות מה יצא לך ליצור.

אתרים שכדאי לבדוק