כתיבת פעולות מותאמות אישית, גרעינים והדרגות ב-TensorFlow.js

סקירה כללית

מדריך זה מתאר את המנגנונים להגדרת פעולות מותאמות אישית (ops), ליבות והדרגות ב- TensorFlow.js. מטרתו היא לספק סקירה כללית של המושגים העיקריים והפניות לקוד המדגימות את המושגים בפעולה.

למי מיועד המדריך הזה?

זהו מדריך מתקדם למדי הנוגע בחלק הפנימי של TensorFlow.js, הוא עשוי להיות שימושי במיוחד עבור קבוצות האנשים הבאות:

  • משתמשים מתקדמים של TensorFlow.js המעוניינים בהתאמה אישית של התנהגות של פעולות מתמטיות שונות (למשל חוקרים עוקפים יישומי גרדיאנט קיימים או משתמשים שצריכים לתקן פונקציונליות חסרה בספרייה)
  • משתמשים בונים ספריות שמרחיבות את TensorFlow.js (למשל ספריית אלגברה לינארית כללית שנבנתה על גבי הפרימיטיבים של TensorFlow.js או קצה אחורי חדש של TensorFlow.js).
  • משתמשים המעוניינים לתרום אופציות חדשות ל-tensorflow.js שרוצים לקבל סקירה כללית של אופן הפעולה של המנגנונים הללו.

זה אינו מדריך לשימוש כללי ב- TensorFlow.js שכן הוא נכנס למנגנוני הטמעה פנימיים. אינך צריך להבין את המנגנונים הללו כדי להשתמש ב- TensorFlow.js

אתה צריך להיות נוח (או מוכן לנסות) לקרוא את קוד המקור של TensorFlow.js כדי להפיק את מירב השימוש במדריך זה.

טרמינולוגיה

עבור מדריך זה כמה מונחי מפתח שימושיים לתיאור מראש.

פעולות (Ops) - פעולה מתמטית על טנסור אחד או יותר שמייצרת טנסור אחד או יותר כפלט. אופציות הן קוד 'ברמה גבוהה' ויכולות להשתמש באופציות אחרות כדי להגדיר את ההיגיון שלהן.

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

Gradient / GradFunc - ההגדרה של 'מצב אחורה' של op/kernel שמחשבת את הנגזרת של פונקציה זו ביחס לקלט כלשהו. מעברי צבע הם קוד 'ברמה גבוהה' (לא ספציפי לקצה האחורי) ויכולים לקרוא לאופציות או גרעינים אחרים.

Kernel Registry - מפה מ-tuple (שם ליבה, שם אחורי) למימוש ליבה.

Gradient Registry - מפה משם ליבה למימוש גרדיאנט .

ארגון קוד

פעולות והדרגות מוגדרות ב- tfjs-core .

הגרעינים הם ספציפיים ל-backend ומוגדרים בתיקיות ה-backend המתאימות (למשל tfjs-backend-cpu ).

אין צורך להגדיר פעולות מותאמות אישית, גרעינים והדרגות בתוך החבילות הללו. אבל לרוב ישתמש בסמלים דומים ביישום שלהם.

הטמעת אופציות מותאמות אישית

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

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

הטמעת גרעינים מותאמים אישית

יישומי ליבה ספציפיים לקצה האחורי מאפשרים הטמעה אופטימלית של ההיגיון עבור פעולה נתונה. ליבות מופעלות על ידי ops הקורא tf.engine().runKernel() . יישומי ליבה מוגדרים על ידי ארבעה דברים

  • שם גרעין.
  • הקצה האחורי בו הליבה מיושם.
  • קלט: ארגומנטים טנסור לפונקציית הליבה.
  • תכונות: ארגומנטים שאינם טנסור לפונקציית הליבה.

הנה דוגמה ליישום ליבה . המוסכמות המשמשות ליישום הינן ספציפיות ל-backend ומובנות בצורה הטובה ביותר מהתבוננות ביישום ובתיעוד של כל backend.

בדרך כלל הגרעינים פועלים ברמה נמוכה יותר מהטנסורים ובמקום זאת קוראים וכותבים ישירות לזיכרון שבסופו של דבר ייעטף בטנסורים על ידי tfjs-core.

לאחר יישום ליבה ניתן לרשום אותו עם TensorFlow.js באמצעות פונקציית registerKernel מ-tfjs-core. אתה יכול לרשום ליבה עבור כל קצה אחורי שאתה רוצה שהקרנל יעבוד בו. לאחר הרישום ניתן להפעיל את הקרנל באמצעות tf.engine().runKernel(...) ו-TensorFlow.js ידאג לשלוח למימוש ב- הקצה האחורי הפעיל הנוכחי.

הטמעת מעברי צבע מותאמים אישית

מעברי צבע מוגדרים בדרך כלל עבור ליבה נתונה (מזוהה באותו שם ליבה המשמש בקריאה ל- tf.engine().runKernel(...) ). זה מאפשר ל-tfjs-core להשתמש ברישום כדי לחפש הגדרות גרדיאנט עבור כל ליבה בזמן ריצה.

הטמעת מעברי צבע מותאמים אישית שימושיים עבור:

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

אתה יכול לראות דוגמאות של יישומי שיפוע כאן .

לאחר שיישמת שיפוע עבור קריאה נתונה ניתן לרשום אותו עם TensorFlow.js באמצעות פונקציית registerGradient מ-tfjs-core.

הגישה הנוספת להטמעת מעברי צבע מותאמים אישית שעוקפת את רישום הגרדיאנט (וכך מאפשרת לחשב גרדיאנטים עבור פונקציות שרירותיות בדרכים שרירותיות היא שימוש ב-tf.customGrad .

הנה דוגמה לאופ בספרייה של שימוש ב-customGrad