TensorFlow.js פועל בדפדפן וב-Node.js, ובשתי הפלטפורמות קיימות תצורות זמינות רבות ושונות. לכל פלטפורמה יש מערך שיקולים ייחודי שישפיע על אופן פיתוח האפליקציות.
בדפדפן, TensorFlow.js תומך במכשירים ניידים כמו גם במכשירים שולחניים. לכל מכשיר יש קבוצה מסוימת של אילוצים, כמו ממשקי API זמינים של WebGL, שנקבעים ומוגדרים עבורך באופן אוטומטי.
ב-Node.js, TensorFlow.js תומך בקישור ישירות לממשק ה-API של TensorFlow או בריצה עם יישומי מעבד וניל איטיים יותר.
סביבות
כאשר מופעלת תוכנית TensorFlow.js, התצורה הספציפית נקראת הסביבה. הסביבה מורכבת מגב עולמי יחיד וכן מערך דגלים השולטים בתכונות עדינות של TensorFlow.js.
קצוות אחוריים
TensorFlow.js תומכים במספר קצה אחוריים שונים המיישמים אחסון טנזור ופעולות מתמטיות. בכל זמן נתון, רק אחורי אחד פעיל. לרוב, TensorFlow.js יבחר אוטומטית את הקצה האחורי הטוב ביותר עבורך בהתחשב בסביבה הנוכחית. עם זאת, לפעמים חשוב לדעת באיזה backend נעשה שימוש וכיצד להחליף אותו.
כדי למצוא באיזה קצה אחורי אתה משתמש:
console.log(tf.getBackend());
אם אתה רוצה לשנות ידנית את הקצה האחורי:
tf.setBackend('cpu');
console.log(tf.getBackend());
WebGL אחורי
ה-WebGL backend, 'webgl', הוא כרגע ה-backend החזק ביותר עבור הדפדפן. הקצה האחורי הזה מהיר עד פי 100 מהקצה האחורי של מעבד וניל. טנסורים מאוחסנים כמרקמי WebGL ופעולות מתמטיות מיושמות בהצללות WebGL. הנה כמה דברים שימושיים שכדאי לדעת בעת שימוש ב-backend זה: \
הימנע מחסימת שרשור ממשק המשתמש
כאשר נקראת פעולה, כמו tf.matMul(a,b), ה-tf.Tensor המתקבל מוחזר באופן סינכרוני, אולם ייתכן שחישוב הכפל המטריצה לא באמת מוכן עדיין. זה אומר שה-tf.Tensor שהוחזר הוא רק ידית לחישוב. כאשר אתה קורא ל- x.data()
או x.array()
, הערכים ייפתרו כאשר החישוב יסתיים בפועל. זה חשוב להשתמש בשיטות האסינכרוניות x.data()
ו- x.array()
על פני מקבילותיהן הסינכרוניות x.dataSync()
ו- x.arraySync()
כדי להימנע מחסימת חוט ממשק המשתמש בזמן השלמת החישוב.
ניהול זיכרון
אזהרה אחת בעת שימוש ב-WebGL backend היא הצורך בניהול זיכרון מפורש. WebGLTextures, שזה המקום שבו נתוני Tensor מאוחסנים בסופו של דבר, אינם זבל שנאסף אוטומטית על ידי הדפדפן.
כדי להרוס את הזיכרון של tf.Tensor
, אתה יכול להשתמש בשיטת dispose()
:
const a = tf.tensor([[1, 2], [3, 4]]);
a.dispose();
מקובל מאוד לשרשר מספר פעולות יחד באפליקציה. החזקת הפניה לכל משתני הביניים כדי להיפטר מהם יכולה להפחית את קריאות הקוד. כדי לפתור בעיה זו, TensorFlow.js מספקת שיטה tf.tidy()
אשר מנקה את כל tf.Tensor
s שאינם מוחזרים על ידי פונקציה לאחר ביצועה, בדומה לאופן שבו משתנים מקומיים מנקים כאשר פונקציה מבוצעת:
const a = tf.tensor([[1, 2], [3, 4]]);
const y = tf.tidy(() => {
const result = a.square().log().neg();
return result;
});
דִיוּק
במכשירים ניידים, WebGL עשוי לתמוך רק בטקסטורות של נקודה צפה של 16 סיביות. עם זאת, רוב דגמי למידת המכונה מאומנים עם משקולות והפעלה של נקודה צפה של 32 סיביות. זה יכול לגרום לבעיות דיוק בעת העברה של דגם למכשיר נייד שכן מספרים צפים של 16 סיביות יכולים לייצג רק מספרים בטווח [0.000000059605, 65504]
. זה אומר שאתה צריך להיזהר שהמשקלים וההפעלה בדגם שלך לא יחרגו מטווח זה. כדי לבדוק אם ההתקן תומך בטקסטורות של 32 סיביות, בדוק את הערך של tf.ENV.getBool('WEBGL_RENDER_FLOAT32_CAPABLE')
, אם זה שקרי אז המכשיר תומך רק בטקסטורות של 16 סיביות של נקודה צפה. אתה יכול להשתמש ב- tf.ENV.getBool('WEBGL_RENDER_FLOAT32_ENABLED')
כדי לבדוק אם TensorFlow.js משתמש כעת בטקסטורות של 32 סיביות.
אוסף הצללה והעלאות טקסטורות
TensorFlow.js מבצע פעולות ב-GPU על ידי הפעלת תוכניות הצללה של WebGL. הצללות אלו מורכבות ומקובלות בעצלתיים כאשר המשתמש מבקש לבצע פעולה. הקומפילציה של הצללה מתרחשת ב-CPU בשרשור הראשי ויכולה להיות איטית. TensorFlow.js יאחסן את ההצללות הקומפיליות באופן אוטומטי, מה שהופך את הקריאה השנייה לאותה פעולה עם טנסורי קלט ופלט מאותה צורה למהירה הרבה יותר. בדרך כלל, יישומי TensorFlow.js ישתמשו באותן פעולות מספר פעמים במהלך חיי האפליקציה, כך שהמעבר השני במודל למידת מכונה הוא הרבה יותר מהיר.
TensorFlow.js מאחסן גם נתוני tf.Tensor כ-WebGLTextures. כאשר נוצר tf.Tensor
, אנו לא מעלים מיד נתונים ל-GPU, אלא אנו שומרים את הנתונים על ה-CPU עד שה- tf.Tensor
ישמש בפעולה. אם נעשה שימוש שני ב- tf.Tensor
, הנתונים כבר נמצאים ב-GPU כך שאין עלות העלאה. במודל למידת מכונה טיפוסית, המשמעות היא שמשקולות מועלות במהלך החיזוי הראשון דרך המודל והמעבר השני במודל יהיה הרבה יותר מהיר.
אם אכפת לך מהביצועים של החיזוי הראשון דרך המודל שלך או קוד TensorFlow.js, אנו ממליצים לחמם את המודל על ידי העברת Tensor קלט מאותה צורה לפני השימוש בנתונים אמיתיים.
לְדוּגמָה:
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 backend
ב-TensorFlow Node.js, 'node', ה-API של TensorFlow C משמש להאצת פעולות. זה ישתמש בהאצת החומרה הזמינה של המכונה, כמו CUDA, אם זמינה.
ב-backend זה, בדיוק כמו ב-WebGL, הפעולות מחזירות tf.Tensor
s באופן סינכרוני. עם זאת, בניגוד ל-WebGL backend, הפעולה הושלמה לפני שמחזירים את הטנזור. המשמעות היא שקריאה ל- tf.matMul(a, b)
תחסום את שרשור ה-UI.
מסיבה זו, אם אתה מתכוון להשתמש בזה ביישום ייצור, עליך להפעיל את TensorFlow.js בשרשורי עובדים כדי לא לחסום את השרשור הראשי.
למידע נוסף על Node.js, עיין במדריך זה.
אחורי WASM
TensorFlow.js מספק קצה אחורי של WebAssembly ( wasm
), המציע האצת מעבד וניתן להשתמש בו כחלופה ל-Vanilla JavaScript CPU ( cpu
) ו-WebGL מואצת ( webgl
). כדי להשתמש בו:
// Set the backend to WASM and wait for the module to be ready.
tf.setBackend('wasm');
tf.ready().then(() => {...});
אם השרת שלך מגיש את קובץ .wasm
בנתיב אחר או בשם אחר, השתמש ב- setWasmPath
לפני שאתה מאתחל את הקצה העורפי. עיין בסעיף "שימוש בחבילות" ב-README למידע נוסף:
import {setWasmPath} from '@tensorflow/tfjs-backend-wasm';
setWasmPath(yourCustomPath);
tf.setBackend('wasm');
tf.ready().then(() => {...});
למה WASM?
WASM הוצג בשנת 2015 כפורמט בינארי חדש מבוסס אינטרנט, המספק תוכניות הכתובות ב-JavaScript, C, C++ וכו', יעד הידור להפעלה באינטרנט. WASM נתמך על ידי Chrome, Safari, Firefox ו-Edge מאז 2017, ונתמך על ידי 90% מהמכשירים ברחבי העולם.
ביצועים
הקצה האחורי של WASM ממנף את ספריית XNNPACK ליישום מיטבי של מפעילי רשתות עצביות.
לעומת JavaScript : קבצים בינאריים של WASM הם בדרך כלל הרבה יותר מהירים מחבילות JavaScript עבור דפדפנים לטעינה, לנתח ולבצע. JavaScript מוקלד באופן דינמי ונאסף אשפה, מה שעלול לגרום להאטות בזמן ריצה.
לעומת WebGL : WebGL מהיר יותר מ-WASM עבור רוב הדגמים, אך עבור דגמים זעירים WASM יכול להעלות על WebGL עקב עלויות התקורה הקבועות של ביצוע הצללות WebGL. הסעיף "מתי עלי להשתמש ב-WASM" להלן דן בהיוריסטיקה לקבלת החלטה זו.
ניידות ויציבות
ל-WASM יש אריתמטיקה ציפה ניידת של 32 סיביות, המציעה שוויון דיוק בכל המכשירים. WebGL, לעומת זאת, הוא ספציפי לחומרה ומכשירים שונים יכולים להיות בעלי דיוק משתנה (לדוגמה, חזרה לציפים של 16 סיביות במכשירי iOS).
כמו WebGL, WASM נתמך רשמית על ידי כל הדפדפנים הגדולים. בניגוד ל-WebGL, WASM יכול לרוץ ב-Node.js, ולשמש בצד השרת ללא כל צורך להדר ספריות מקוריות.
מתי עלי להשתמש ב-WASM?
גודל דגם וביקוש חישובי
באופן כללי, WASM היא בחירה טובה כאשר הדגמים קטנים יותר או אם אכפת לך ממכשירים ברמה נמוכה יותר שאין להם תמיכה ב-WebGL (סיומת OES_texture_float
) או שיש להם GPUs פחות חזקים. התרשים שלהלן מציג זמני מסקנות (נכון ל-TensorFlow.js 1.5.2) ב-Chrome ב-MacBook Pro משנת 2018 עבור 5 מהדגמים הנתמכים רשמית שלנו על פני WebGL, WASM ו-CPU:
דגמים קטנים יותר
דֶגֶם | WebGL | WASM | מעבד | זֵכֶר |
---|---|---|---|---|
BlazeFace | 22.5 אלפיות השנייה | 15.6 אלפיות השנייה | 315.2 אלפיות השנייה | .4 MB |
FaceMesh | 19.3 אלפיות השנייה | 19.2 אלפיות השנייה | 335 אלפיות השנייה | 2.8 מגה-בייט |
דגמים גדולים יותר
דֶגֶם | WebGL | WASM | מעבד | זֵכֶר |
---|---|---|---|---|
PoseNet | 42.5 אלפיות השנייה | 173.9 אלפיות השנייה | 1514.7 אלפיות השנייה | 4.5 מגה-בייט |
BodyPix | 77 אלפיות השנייה | 188.4 אלפיות השנייה | 2683 אלפיות השנייה | 4.6 מגה-בייט |
MobileNet v2 | 37 אלפיות השנייה | 94 אלפיות השנייה | 923.6 אלפיות השנייה | 13 מגה-בייט |
הטבלה שלמעלה מראה ש-WASM מהיר פי 10-30 מה-JS המעבד האחורי הרגיל בדגמים, ותחרותי עם WebGL עבור דגמים קטנים יותר כמו BlazeFace , שהוא קל משקל (400KB), אך עם זאת יש לו מספר הגון של פעולות (~140). בהתחשב בכך שלתוכניות WebGL יש עלות תקורה קבועה לכל ביצוע פעולה, זה מסביר מדוע מודלים כמו BlazeFace מהירים יותר ב-WASM.
תוצאות אלו ישתנו בהתאם למכשיר שלך. הדרך הטובה ביותר לקבוע אם WASM מתאים ליישום שלך היא לבדוק אותו בקצה האחורי השונים שלנו.
הסקה מול אימון
כדי לתת מענה למקרה השימוש העיקרי לפריסה של מודלים מאומנים מראש, הפיתוח האחורי של WASM ייתן עדיפות להסקה על פני תמיכה באימון . ראה רשימה עדכנית של פעולות נתמכות ב-WASM ודווח לנו אם לדגם שלך יש הפעלה לא נתמכת. עבור דגמי אימון, אנו ממליצים להשתמש ב-Node (TensorFlow C++) או ב-WebGL backend.
קצה אחורי של מעבד
ה-CPU, 'cpu', הוא הקצה האחורי הכי פחות בעל ביצועים, אולם הוא הפשוט ביותר. כל הפעולות מיושמות ב-vanilla JavaScript, מה שהופך אותן פחות ניתנות להקבילה. הם גם חוסמים את שרשור ה-UI.
הקצה האחורי הזה יכול להיות שימושי מאוד לבדיקות, או במכשירים שבהם WebGL אינו זמין.
דגלים
ל- TensorFlow.js יש קבוצה של דגלי סביבה המוערכים באופן אוטומטי וקובעים את התצורה הטובה ביותר בפלטפורמה הנוכחית. דגלים אלו הם לרוב פנימיים, אך ניתן לשלוט בכמה דגלים גלובליים באמצעות API ציבורי.
-
tf.enableProdMode():
מאפשר מצב ייצור, שיסיר את אימות המודל, בדיקות NaN ובדיקות נכונות אחרות לטובת ביצועים. -
tf.enableDebugMode()
: מאפשר מצב ניפוי באגים, שירשם למסוף כל פעולה שתבוצע, כמו גם מידע על ביצועי זמן ריצה כמו טביעת זיכרון וזמן ביצוע הליבה הכולל. שים לב שזה יאט מאוד את היישום שלך, אל תשתמש בזה בייצור.