7.2. מה שינתה למידת המכונה

מודול התמונה נושא קומץ שיטות זיהוי מורשתfind_features() עבור זיהוי פנים מבוסס Haar-cascade, find_eye() עבור מאתר האישונים הקבוע, find_hog() עבור סיכומי כיוון מפל (gradient), והנתיבים find_keypoints() ו־find_lbp() עבור נקודות מפתח שרירותיות. כולן עדיין עובדות; כולן הוחלפו על ידי צינור למידת המכונה.

7.2.1. הפיצול הקלאסי: סיכומים מתוכננים ביד, החלטות נלמדות

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

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

  • find_features() מסכמת חלון של התמונה על ידי חיבור הבהירות בתוך כמה מלבנים והשוואת הסכומים. מתכונות המלבנים נבחרו מכיוון שפני אדם מציגים ניגודי בהיר־מול־כהה אמינים: גבות מול לחיים, ארובות עיניים מול מצח, אף מול העור שסביבו.

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

  • find_lbp() מסכמת את הסביבה של כל פיקסל על ידי קידוד אילו מהפיקסלים שסביבו בהירים יותר ואילו כהים יותר. הקידוד נבחר מכיוון שתבניות הבהיר־מ־ / כהה־מ־ הללו לוכדות את המרקם של משטח באופן בלתי תלוי בתאורה הכוללת.

  • find_keypoints() מוצאת נקודות פינה בתמונה ומתארת את האזור סביב כל פינה באופן שנשאר זהה כאשר הפינה מסובבת. סכמת הפינה־והסיבוב נבחרה מכיוון שאותן פינות מופיעות מחדש כאשר סצנה נצפית מזווית שונה.

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

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

7.2.2. מה שינו רשתות הנוירונים

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

השינוי בשאלה מי מתכנן מה הוא מוחלט:

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

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

  • האדם מספק נתוני אימון מתויגים – מספיק דוגמאות של המטרה ומספיק דוגמאות של לא־מטרות כדי שלתהליך האימון יהיה ממה ללמוד.

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

7.2.3. הרכבה עם מודול התמונה

צינורות רשת נוירונים עדיין קולטים דרך אותם ממשקי API של חיישן, מציירים תוצאות דרך אותם פרימיטיבים draw_rectangle() ו־draw_circle(), ומגדירים את היקף העבודה דרך אותם אזורי עניין (ROI) (x, y, w, h). צינור טיפוסי קולט פריים, אופציונלית מוצא מטרה גסה עם מזהה קלאסי כמו find_blobs() ומעביר את התיבה התוחמת שלו אל ההסקה כ־ROI, מריץ את ההסקה, ומסמן את הזיהויים המוחזרים בחזרה אל הפריים המקורי. הפרימיטיבים הקלאסיים הם המצע; הרשת היא השלב החדש באמצע.