דגמים ושכבות

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

ב-TensorFlow.js יש שתי דרכים ליצור מודל למידת מכונה:

  1. באמצעות Layers API שבו אתה בונה מודל באמצעות שכבות .
  2. שימוש ב-Core API עם פעולות ברמה נמוכה יותר כגון tf.matMul() , tf.add() וכו'.

ראשית, נבחן את Layers API, שהוא API ברמה גבוהה יותר לבניית מודלים. לאחר מכן, נראה כיצד לבנות את אותו מודל באמצעות Core API.

יצירת מודלים עם Layers API

ישנן שתי דרכים ליצור מודל באמצעות Layers API: מודל רציף ומודל פונקציונלי . שני הסעיפים הבאים בוחנים כל סוג מקרוב יותר.

המודל הרציף

הסוג הנפוץ ביותר של מודל הוא מודל Sequential , שהוא ערימה לינארית של שכבות. אתה יכול ליצור מודל Sequential על ידי העברת רשימה של שכבות לפונקציה sequential() :

const model = tf.sequential({
 layers: [
   tf.layers.dense({inputShape: [784], units: 32, activation: 'relu'}),
   tf.layers.dense({units: 10, activation: 'softmax'}),
 ]
});

או באמצעות שיטת add() :

const model = tf.sequential();
model.add(tf.layers.dense({inputShape: [784], units: 32, activation: 'relu'}));
model.add(tf.layers.dense({units: 10, activation: 'softmax'}));

חשוב: השכבה הראשונה במודל צריכה inputShape . ודא שאתה לא כולל את גודל האצווה בעת מתן ה- inputShape . לדוגמה, אם אתה מתכנן להזין את טנסור המודל של הצורה [B, 784] , כאשר B יכול להיות כל גודל אצווה, ציין inputShape כ- [784] בעת יצירת המודל.

אתה יכול לגשת לשכבות של המודל דרך model.layers , וליתר דיוק model.inputLayers ו- model.outputLayers .

המודל הפונקציונלי

דרך נוספת ליצור LayersModel היא באמצעות הפונקציה tf.model() . ההבדל העיקרי בין tf.model() ל- tf.sequential() הוא ש- tf.model() מאפשר לך ליצור גרף שרירותי של שכבות, כל עוד אין להן מחזורים.

הנה קטע קוד שמגדיר את אותו מודל כמו לעיל באמצעות ה-API של tf.model() :

// Create an arbitrary graph of layers, by connecting them
// via the apply() method.
const input = tf.input({shape: [784]});
const dense1 = tf.layers.dense({units: 32, activation: 'relu'}).apply(input);
const dense2 = tf.layers.dense({units: 10, activation: 'softmax'}).apply(dense1);
const model = tf.model({inputs: input, outputs: dense2});

אנו קוראים apply() בכל שכבה על מנת לחבר אותה לפלט של שכבה אחרת. התוצאה של apply() במקרה זה היא SymbolicTensor , שמתנהג כמו Tensor אך ללא ערכים קונקרטיים.

שימו לב שבניגוד למודל הרציף, אנו יוצרים SymbolicTensor דרך tf.input() במקום לספק inputShape לשכבה הראשונה.

apply() יכול גם לתת לך Tensor בטון, אם תעביר אליו Tensor בטון:

const t = tf.tensor([-2, 1, 0, 5]);
const o = tf.layers.activation({activation: 'relu'}).apply(t);
o.print(); // [0, 1, 0, 5]

זה יכול להיות שימושי בעת בדיקת שכבות בבידוד וראיית הפלט שלהן.

בדיוק כמו במודל רציף, אתה יכול לגשת לשכבות של המודל דרך model.layers , וליתר דיוק model.inputLayers ו- model.outputLayers .

מַתַן תוֹקֵף

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

תקציר הדגם

קרא model.summary() כדי להדפיס סיכום שימושי של המודל, הכולל:

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

עבור הדגם שהגדרנו למעלה, נקבל את הפלט הבא בקונסולה:

שכבה (סוג) צורת פלט פראם מס'
צפוף_צפוף1 (צפוף) [null,32] 25120
dense_Dense2 (צפוף) [null,10] 330
סה"כ פרמים: 25450
פרמטרים ניתנים לאימון: 25450
פרמטרים שאינם ניתנים לאימון: 0

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

סדרה

אחד היתרונות העיקריים של שימוש ב- LayersModel על פני ה-API ברמה נמוכה יותר הוא היכולת לשמור ולטעון מודל. LayersModel יודע על:

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

כדי לשמור או לטעון מודל זה רק שורת קוד אחת:

const saveResult = await model.save('localstorage://my-model-1');
const model = await tf.loadLayersModel('localstorage://my-model-1');

הדוגמה למעלה שומרת את הדגם לאחסון מקומי בדפדפן. עיין model.save() documentation ובמדריך השמירה והטעינה כיצד לשמור במדיומים שונים (למשל אחסון קבצים, IndexedDB , הפעלת הורדת דפדפן וכו')

שכבות מותאמות אישית

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

class SquaredSumLayer extends tf.layers.Layer {
 constructor() {
   super({});
 }
 // In this case, the output is a scalar.
 computeOutputShape(inputShape) { return []; }

 // call() is where we do the computation.
 call(input, kwargs) { return input.square().sum();}

 // Every layer needs a unique name.
 getClassName() { return 'SquaredSum'; }
}

כדי לבדוק זאת, אנו יכולים לקרוא לשיטת apply() עם טנזור בטון:

const t = tf.tensor([-2, 1, 0, 5]);
const o = new SquaredSumLayer().apply(t);
o.print(); // prints 30

חשוב: אם אתה מוסיף שכבה מותאמת אישית, אתה מאבד את היכולת להרכיב מודל בסידרה.

יצירת מודלים עם Core API

בתחילת המדריך הזה, הזכרנו שיש שתי דרכים ליצור מודל למידת מכונה ב-TensorFlow.js.

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

ייתכן שתרצה להשתמש ב-Core API בכל פעם:

  • אתה צריך גמישות או שליטה מקסימלית.
  • אינך זקוק לסידרה, או שאתה יכול ליישם את היגיון ההסדרה שלך.

מודלים ב-Core API הם רק פונקציות שלוקחות Tensors אחד או יותר ומחזירות Tensor . אותו דגם כמו לעיל שנכתב באמצעות Core API נראה כך:

// The weights and biases for the two dense layers.
const w1 = tf.variable(tf.randomNormal([784, 32]));
const b1 = tf.variable(tf.randomNormal([32]));
const w2 = tf.variable(tf.randomNormal([32, 10]));
const b2 = tf.variable(tf.randomNormal([10]));

function model(x) {
  return x.matMul(w1).add(b1).relu().matMul(w2).add(b2).softmax();
}

שימו לב שב-Core API אנחנו אחראים על יצירה ואתחול של משקלי המודל. כל משקל מגובה Variable שמאותת ל-TensorFlow.js שהטנסורים הללו ניתנים ללמידה. אתה יכול ליצור Variable באמצעות tf.variable() ומעבר ב- Tensor קיים.

במדריך זה הכרת את הדרכים השונות ליצירת מודל באמצעות השכבות וה-Core API. לאחר מכן, עיין במדריך דגמי ההדרכה כיצד להכשיר דוגמנית.