cnn

ייצור דאטה טבלאי ע”י שימוש ב- Conditional Tabular GAN

מיועד ל- מתחילים (כתבה קצת טכנית)

נכתב על ידי yuval schreiber

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

דאטה טבלאי

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

הגדרת הבעיה- נניח דאטה טבלאי T שמכיל Nd עמודות בדידות ו-Nc עמודות רציפות, המטרה הינה לאמן מחולל G ללמוד לייצר דאטה טבלאי סינתטי מ-T שיקרא Tsyn
כדי להעריך את ביצועי המחולל מפצלים את T לאימון ומבחן, ובוחנים שני היבטים:

  1. התאמת הנתונים ב- Tsyn להתפלגות הנתונים ב- Ttrain
  2. השוואת מודל סיווג/רגרסיה מאומן על Tsyn עם מודל מאומן על Ttrain, מבחינת ביצועים על Ttest

GANGenerative Adversarial Network

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

התאמות שנעשות ב-CTGAN

השימוש ב-GAN רגיל לייצור דאטה טבלאי יוצר שתי בעיות שההתאמות ב-CTGAN באות לפתור:

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

לכל משתנה רציף תחילה מתאימים VGM (variational Gaussian mixture model), GM רגיל מנסה למצוא את k הגאוסיאנים שמייצגים הכי טוב את הנתונים דרך שימוש ב-EM, לעומת זאת VGM-ים יכולים להחליט מהו ה-k הכי מתאים לנתונים דרך סף משקולות.
לאחר שנמצאו k (בדוגמה מעלה k=3) ההתפלגויות שממדלות הכי טוב את המשתנה הרציף (בדוגמה מעלה עמודה i), מעריכים את ההסתברויות (בדוגמה מעלה ρ1,ρ23) להשתייכות הדגימה (בדוגמה מעלה j) לכל אחת מההתפלגויות, מהן דוגמים את ההתפלגות הנבחרת (מסומנת ב- β), ואז מייצגים את ערך הדגימה בתוך ההתפלגות שלה (כמה היא חשובה בתוך הגאוסיאן שלה) ע״י שימוש ב-α , כאשר η הינו השכיח ו-φ הינה סטיית התקן של ההתפלגות.
כעת עבור כל דגימה המודל יקבל במקום הערכים הרציפים,שרשור של α ו-β  של כל העמודות הרציפות, עם וקטורי האחד חם של העמודות הבדידות.

2. דגימה הוגנת של משתנים בדידים– באימון GAN רעש הקלט מיוצר מהתפלגות פריורית (לרוב גאוסיאנית מרובת משתנים), דגימה זו עבור משתנים בדידים עשויה להחמיץ מידע על התפלגותם ולשמר את חוסר האיזון בדאטה, נרצה לבצע דגימה מחדש בדרך שמאפשרת דגימה שווה בין ערכים דיסקרטיים שונים בזמן האימון, ושחזור ההתפלגות האמיתית בזמן המבחן.
הפתרון המוצע מורכב מ-3 אלמנטי מפתח:
a. וקטור מותנה– וקטור אשר מכיל מידע על המשתנים הבדידים, ומשתמשים בו כדי לכפות על המחולל לייצר דגימות משתנים בדידים עם התפלגות דומה לנתוני האימון.
הוקטור מכיל שרשור של כל וקטורי אחד חם של העמודות הבדידות, כך שכל הערכים הינם 0 מלבד קטגוריה אחת מאחת העמודות הבדידות, והוא מאלץ את המחולל לייצר דגימה מקטגוריה נבחרת זו.
b. הפסד המחולל– כדי לוודא שהאילוץ אכן מתקיים מענישים את פונקציית ההפסד של המחולל ע”י הוספת CE בין החלק של העמודה בה יש 1 בוקטור המותנה, לחלק של אותה עמודה בדגימה המיוצרת.
c. אימון לפי דגימה– דוגם את התנאים לפיהם נוצר הוקטור המותנה, כך שההתפלגויות הנוצרות ע”י המחולל יתאימו להתפלגויות המשתנים הבדידים בנתוני האימון.
אימון לפי דגימה מתבצע כך:

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

קוד
חבילת פייתון רלוונטית והסבר על אופן השימוש בה

קישורים רלוונטיים

One Hot Encoding
EM
CTGAN

Posted by yuval schreiber in deep

מערכת לזיהוי דובר מבוססת למידה עמוקה

מיועד ל- מתחילים (כתבה קצת טכנית)

נכתב על ידי bar madar

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

מוטיבציה

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

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

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

הגדרת הבעיה

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

את בעיית זיהוי הדובר מקובל לחלק ל2 תתי בעיות:

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

* אימות דובר –בהינתן קטע דיבור של דובר לא ידוע וטענה לזהות הדובר בקטע עבור דובר מוכר למערכת, יש להחליט האם הטענה נכונה או שלא. במילים אחרות, בהינתן 2 קטעי דיבור (של דובר לא ידוע ושלא דובר מוכר) על המערכת להחליט האם 2 הקטעים שייכים לאותו דובר.

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

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

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

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

מערכת לזיהוי דובר מבוססת למידה עמוקה

מערכת לזיהוי דובר מבוססת למידה עמוקהממומשת על ידי חיבור של חמשת השלבים הבאים:

1. הוצאת פיצ’רים לדאטה הגולמי.

2. אימון מודל רשת נוירונים לסיווג דוברים מקבוצה סגורה.

3. הוצאת ווקטור זהות לכל דובר “נרשם למערכת” או “מועמד” על ידי למידת מעבר מהמודל שאימנו בשלב הקודם.

4. הוצאת תוצאת תאימות עבור 2 קטעי דיבור.

5. קבלת החלטה.

ניתן לראות את סכימת המערכת הבסיסית באיור הבא:

כעת, נעבור לחלק המעניין בו נסביר על כל שלב במערכת, ולאחריו תדעו איך ניתן לזהות דובר בעזרת למידה עמוקה 🙂

1. הוצאת פיצ’רים

בשלב הראשון, יש לבצע ווקטוריזציה וניקוי לדאטה הגולמי (קטעי אודיו).

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

להוצאת הפיצ’רים נשתמש באלגוריתם ה(MFCC(Mel Frequency Cepstrum Coefficient אשר נפוץ מאוד גם בעולם זיהוי הדיבור. הייחודיות באלגוריתם זה היא העבודה במרחב התדר של האות וההתחקות אחר הדרך הפיזיולוגית בה האוזן האנושית מדגישה את מנעד התדרים ע”י שימוש בסולם MEL  (מתייחס לתדר או גובה הצליל הנשמעים על ידי האוזן האנושית ביחס לערכים הנמדדים בפועל. לבני האדם הרבה יותר קל להבחין בשינויים קטנים בגובה הצליל בתדרים נמוכים)

לאלגוריתם הMFCC מספר שלבים:

1. אות הדיבור הרציף נדגם ונחתך לפריימים נחפפים בעלי גודל זהה.

2. על כל פריים, מופעלת התמרת פורייה דיסקרטית (Discrete Fourrier Transform) ומחושבת האנרגיה בספקטרום התדרי לקבלת ייצוג האות בתחום התדר.

3. הייצוג התדרי של הפריימים עובר דרך פילטר חלונות ((hamming אשר מכווצים ומורחבים לפי סולם MEL. מספר החלונות שנבחר, יהיה מספר הפיצ’רים שנקבל עבור כל פריים.

4. קבלת פיצ’רי הMFCC תהיה על ידי הפעלת התמרת קוסינוס בדידה (Discrete Cosine Transform) על ווקטורי הפיצ’רים, שנועדה לייצר דה-קורלציה בין הפיצ’רים בווקטור.

לאחר הוצאת הפיצ’רים עבור כל פריים, מתבצע סינון פריימים שבהם אין דיבור (Voice Activity Detection).

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

2. אימון מודל לסיווג דוברים מקבוצה סגורה

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

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

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

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

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

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

המודל המסווג בנוי מ3 חלקים:

1. שכבות ייצוג פריים (frame-level)– לחלק הזה ייכנסו סדרות של פיצ’רים המייצגים את הפריימים שמרכיבים את קטע הדיבור. במאמר https://www.danielpovey.com/files/2018_icassp_xvectors.pdf שהציג לראשונה את שיטת ה x-vector שהפכה לSOTA בתחום, נעשה שימוש בארכיטקטורת Time Delay Neural Network (מופיעה באיור) שהיא אימפלמנטציה של רשת קונבולוציה חד מימדית, כאשר הקלט לרשת הוא שרשור של פריים במקום ה-t, יחד עם מספר קבוע של פריימים עוקבים ואוחרים לו. בכל שכבה יש קונטקסט קבוע בין הייצוגים של הפריימים (ניתן להתייחס אל זה כאל פילטר בגודל ספציפי) וככל שמעמיקים ברשת ככה הקונטקסט גדל (ניתן לראות בתמונה את הקווים האדומים שמסמנים את הקונטקסט בכל שכבה). בצורה הזאת, אנחנו גם מרוויחים ניצול מיטבי של המידע עבור כל פריים וגם מתאפשר חישוב בצורה יעילה (מבלי לחשב קשרים בין פריימים רחוקים ללא קורלציה).

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

2. שכבה חשובה מאוד במודל המסווג שלנו היא שכבת ה”איגום” (pooling layer). מכיוון שהמערכת צריכה לעבוד עם קטעי דיבור באורכים שונים, יש צורך בשכבת מעבר משלב ייצוג הפריים לשלב ייצוג ה”קטע” (segment-level).

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

דוגמא פשוטה לשכבה כזאת היא שכבת איגום סטטיסטית שמחשבת פרמטרים סטטיסטים (תוחלת וסטיית תקן)  עבור כל הפריימים השייכים לקטע ולכן המוצא שלה יהיה תלוי במימד השכבה שבקצה הרשת ולא בכמות הפריימים. שכבות איגום חכמות יותר יכולות לשלב attention על מנת לחשב ממוצע משוקלל חכם בין כל הפריימים או שכבת Learnable Dictionary Encoding שלומדת פרמטרי קידוד יחד עם מילון מובנה עבור כל פריים על מנת להוציא את הייצוג המיטבי לקטע.

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

3. חילוץ ווקטור זהות דובר מהמודל המסווג

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

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

4. תוצאת תאימות עבור 2 קטעי דיבור

השלב הרביעי בתהליך מתחיל לאחר שכבר חילצנו ווקטורי זהות דובר עבור 2 קטעי דיבור, וכעת יש להשוות ביניהם, או במילים אחרות להוציא להם תוצאת תאימות (similarity score).

תוצאת התאימות המתאימה ביותר למקרה שלנו היא יחס הlikelihood בין 2 היפותזות:

* H_0– 2 קטעי הדיבור שייכים לאותו הדובר

* H_1– 2 קטעי הדיבור שייכים לדוברים שונים

כאשר x_1,x_2 מסמלים את ווקטורי הזהות שחולצו ל 2 קטעי הדיבור. ניתן לראות שהתוצאה נעה בין 1 (קטעים זהים) ל 0.

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

אבל במצב הריאלי, כאשר אין מספיק דאטה ברשותנו, נרצה להשתמש במודל סטטיסטי חכם אשר מאומן ע”י צמדים של קטעי דיבור בעלי תיוג של שייכות לאותו דובר. מודל הPLDA(Probability Linear Discriminant Analysis) עושה שימוש במטריצות הפיזור של בתוך הקלאס ומחוץ לקלאס

(between-class and within-class scatter matrix), אשר מחושבות ע”י צמדי קטעי האימונים, ומגדיר משתנה חבוי שהוא משתנה הקלאס שיוגדר להיות משתנה אקראי גאוסי (רציף לעומת הבדיד במודל הGMM). בעזרת משתנים אלו, מודל הPLDA ממדל את ההסתברות לדובר כלשהו וגם את ההסתברות המותנת של קטע דיבור בהנתן דובר כלשהו. בעזרת התפלגויות אלה, ונוסחאת ההסברות השלמה, ניתן עבור 2 קטעי דיבור, לחשב את תוצאת התאימות ביניהם.

בהסבר הקצרצר כאן חסכתי לכם את הפיתוחים המתמטיים של המודל, אבל מידע נוסף למתעניינים נמצא בקישור הבא: https://link.springer.com/content/pdf/10.1007/11744085_41.pdf

קבלת החלטה

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

בעולם זיהוי הדובר קיימות 2 שגיאות:

* שגיאת קבלה (False Alarm)– כאשר 2 הקטעים שייכים לדוברים שונים אבל המערכת מחליטה שהם שייכים לאותו הדובר

* שגיאת דחייה (False reject)– כאשר 2 הקטעים שייכים לאותו דובר אבל המערכת מחליטה שהם שייכים לדוברים שונים

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

הערכת ביצועי המערכת

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

על מנת למדוד את ביצועי מערכת זיהוי הדובר, נשתמש בדאטה אבלואציה ובכלי גרפי שנקרא Detection Error Tradeoff Curve.

דאטה האבלואציה יורכב מצמדי “מבחן” של קטעי דיבור, ותיוג האם הם שייכים לאותו דובר או לא (target \ non-target). בגרף, הצירים מייצגים את יחסי שגיאות המערכת עבור סט אבלואציה של צמדי קטעי קול המתוייגיםכtarget  או non-target.

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

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

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

בגרף הבא, ניתן לראות השוואה בין 4 מערכות שונות שנבדקו על אותו דאטה סט, הנקודות על הגרפים הן נקודות הEER:

לסיכום

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

אם לאחר קריאת הכתבה צצות לכם שאלות או שתרצו הרחבה נוספת בנושאים קשורים, מוזמנים לכתוב לי במייל ואשמח לנסות לעזור (-:

Barmadar13@gmail.com

linkedin.com/in/bar-madar-838b15160

Posted by bar madar in deep

מהו Variational AutoEncoders?

מיועד ל- מטיבי לכת (כתבה מאוד טכנית)

נכתב על ידי avraham raviv

כדי להבין היטב את אופן הפעולה של Variational Autoencoders (VAE), נדבר מעט על הורדת מימדים, לאחר מכן נסביר מהו Autoencoders, כיצד הוא עובד ומה החסרונות שלו, ומשם נעבור ל-VAE.

Dimensionality Reduction

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

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

תהליך האימון הוא דו שלבי: דאטה x\in R^{n} עובר דרך encoder, ולאחריו מתקבל e(x)\in R^{m} , כאשר m<n לאחר מכן התוצאה מוכנסת ל-decoder בכדי להחזיר אותה למימד המקורי, ולבסוף מתקבל d(e(x)) \in R^{^{n}} אם לאחר התהליך מתקיים x=d(e(x)) אז למעשה לא נאבד שום מידע בתהליך, אך אם לעומת זאת x\neq d(e(x)) אז מידע מסוים אבד עקב הורדת המימד ולא היה ניתן לשחזר אותו במלואו בפענוח. באופן אינטואיטיבי, אם אנו מצליחים לשחזר את הקלט המקורי מהייצוג של במימד נמוך בדיוק טוב מספיק, כנראה שהייצוג במימד נמוך הצליח להפיק את הפיצ’רים המשמעותיים של הדאטה המקורי.

 

איור 1. ארכיטקטורת encoder ו-decoder.

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

(e^{*},d^{*})=\underset{(e,d)\in ExD}{argmin}\epsilon (x,d(e(x)))

כאשר \epsilon (x,d(e(x))) הוא שגיאת השחזור שבין הדאטה המקורי לבין הדאטה המשוחזר.

אחת השיטות השימושיות להורדת מימד שאפשר להסתכל עליה בצורה הזו היא Principal Components Analysis (PCA). בשיטה זו מטילים (בצורה לינארית) דאטה ממימד n למימד m על ידי מציאת בסיס אורתוגונלי במרחב ה-m מימדי בו המרחק האוקלידי בין הדאטה המקורי לדאטה המשוחזר מהייצוג החדש הוא מינימלי.

איור 2. דוגמא להורדת מימד בשיטת PCA.

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

Autoencoders (AE)

ניתן לקחת את המבנה של ה- encoder-decoder המתואר בפרק הקודם ולהשתמש ברשת נוירונים עבור בניית הייצוג החדש ועבור השחזור. מבנה זה נקרא Autoencoder:

איור 3. Autoencoder – שימוש ברשתות נוירונים עבור הורדת המימד והשחזור.

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

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

איור 4. דוגמא לשימוש ב-Autoencoder.

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

Variational AutoEncoders (VAE)

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

כדי להתמודד עם בעיה זו, ניתן להשתמש ב-Variational AutoEncoders (VAE). בשונה מ-AE שלוקח דאטה ובונה לו ייצוג ממימד נמוך, VAE קובע התפלגות פריורית למרחב הלטנטי z – למשל התפלגות נורמלית עם תוחלת 0 ומטריצת  II covariance. בהינתן התפלגות זו, ה-encoder מאמן רשת המקבלת דאטה x ומוציאה פרמטרים של התפלגות פוסטריורית z|x , מתוך מטרה למזער כמה שניתן את ההפרש בין ההתפלגויות z ו- z|x . לאחר מכן דוגמים וקטורים מההתפלגות הפוסטריורית z|x (הנתונה על ידי הפרמטרים המחושבים ב-encoder), ומעבירים אותם דרך ה-decoder כדי לייצר פרמטרים של ההתפלגות z|x . חשוב להבהיר שאם הדאטה המקורי הוא תמונה המורכבת מאוסף של פיקסלים, אזי במוצא יתקבל x|z לכל פיקסל בנפרד ומההתפלגות הזו דוגמים נקודה והיא תהיה ערך הפיקסל בתמונה המשוחזרת. באופן הזה, הלמידה דואגת לא רק להורדת המימד, אלא גם להתפלגות המושרית על המרחב הלטנטי. כאשר ההתפלגות המותנית במוצא x|z טובה, קרי קרובה להתפלגות המקורית של x, ניתן בעזרתה גם ליצור דוגמאות חדשות, ובעצם מתקבל מודל גנרטיבי. כאמור, ה-encoder מנסה לייצג את הדאטה המקורי באמצעות התפלגות במימד נמוך יותר, למשל התפלגות נורמלית עם תוחלת ומטריצת covariance:z\sim p(z|x)=N(\mu _{z},\sigma _{x})

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

 

איור 5. ארכיטקטורה של VAE.

לאחר שהוצג המבנה הכללי של VAE, ניתן לתאר את תהליך הלמידה, ולשם כך נפריד בשלב זה בין שני החלקים של ה-VAE. ה-encoder מאמן רשת שמקבלת דוגמאות מסט האימון, ומנסה להפיק מהן פרמטרים של התפלגות  הקרובים כמה שניתן להתפלגות פריורית , שכאמור נקבעה מראש. מההתפלגות הנלמדת הזו דוגמים וקטורים חדשים ומעבירים ל-decoder. ה- decoderמבצע את הפעולה ההפוכה – לוקח וקטור שנדגם מהמרחב הלטנטי , ומייצר באמצעותו דוגמא חדשה הדומה לדאטה המקורי. תהליך האימון יהיה כזה שימזער את השגיאה של שני חלקי ה-VAE – גם  שבמוצא יהיה כמה שיותר קרוב ל- המקורי, וגם ההתפלגות  תהיה כמה שיותר קרובה להתפלגות הפריורית z. נתאר באופן פורמלי את בעיית האופטימיזציה ש-VAE מנסה לפתור. נסמן את הווקטורים של המרחב הלטנטי ב-z, את הפרמטרים של ה-decoder ב-\theta , ואת הפרמטרים של ה-encoder ב-\lambda. כדי למצוא את הפרמטרים האופטימליים של שתי הרשתות, נרצה להביא למקסימום את p(\widehat{x}=x;\theta) , כלומר למקסם את הנראות המרבית של סט האימון תחת \theta . כיוון שפונקציית log מונוטונית, נוכל לקחת את לוג ההסתברות:

L(\theta)=log(p(x;\theta ))

אם נביא למקסימום את הביטוי הזה, נקבל את ה- \theta האופטימלי. כיוון שלא ניתן לחשב במפורש את p(x;\theta ) , יש להשתמש בקירוב. נניח וה -encoder הוא בעל התפלגות מסוימת q(z;\lambda ) (מה ההסתברות לקבל את z בהינתן x  בכניסה). כעת ניתן לחלק ולהכפיל את L(\theta )ב – q(z;\lambda ):

log[p(x;\theta )]=log \underset{z}{\Sigma}p(x,z;\theta )=log\underset{z}{\Sigma}q(z;\lambda )\frac{p(x,z;\theta)}{q(z;\lambda)}\geqslant \underset{z}{\Sigma}q(z;\lambda)log\frac{p(x,z_{i};\theta)}{q(z;\lambda)}

כאשר אי השוויון האחרון נובע מאי-שוויון ינסן, והביטוי שמימין לאי השיוויון נקרא Evidence Lower BOund ELBO(\theta,\lambda). ניתן להוכיח שההפרש בין ה-ELBO לבין הערך שלפני הקירוב הוא המרחק בין שתי ההתפלגויות p(z|x),q(z) , והוא נקרא Kullback–Leibler divergence ומסומן ב- D_{KL}:

log[p(x;\theta)]=ELBO(\theta,\lambda)+D_{KL}(q(z;\lambda)||p(z|x;\theta))

אם שתי ההתפלגויות זהות, אזי מרחק D_{KL} ביניהן הוא 0 ומתקבל שוויון: log[p(x;\theta)]=ELBO(\theta,\lambda) . כזכור, אנחנו מחפשים למקסם את פונקציית המחיר log[p(x;\theta)] , וכעת בעזרת הקירוב ניתן לרשום:

L(\theta)=log[p(x;\theta)]\geqslant ELBO(\theta,\lambda)

\rightarrow \theta_{ML}=arg\underset{\theta}{max}L(\theta)=arg\underset{\theta}{max}\underset{\lambda}{max}ELBO(\theta,\lambda)

כעת ניתן בעזרת שיטת GD למצוא את האופטימום של הביטוי, וממנו להפיק את הפרמטרים האופטימליים של ה-encoder ושל ה-decoder. נפתח יותר את ה-ELBO(\theta,\lambda) עבור VAE, ביחס לשתי התפלגויות: p(x|z;\theta) – ההסתברות ש-decoder עם סט פרמטרים \theta יוציא x  בהינתן z. q(z|x;\lambda) – ההסתברות ש-encoder עם סט פרמטרים \lambda יוציא את z_{i} בהינתן x בכניסה לפי הגדרה:

ELBO(\theta, \lambda)=\underset{z}{\Sigma}q(z|x;\lambda)log[p(x,z;\theta)]-\underset{z}{\Sigma}q(z|x;\lambda)log[q(z|x;\lambda)

את הביטוי log[p(x,z;\theta)] ניתן לפתוח לפי בייס:

p(x,z)=p(x|z)\cdot p(z)

={\underset{z }{\sum}}q(z|x;\lambda)(log[p(x|z;\theta)]+log[p(z;\theta))])-{\underset{z }{\sum}}q(z|x;\lambda)log[q(z|x;\lambda)]

={\underset{z }{\sum}}q(z|x;\lambda)(log[p(x|z;\theta)]-{\underset{z }{\sum}}q(z|x;\lambda)(log[q(z|x;\lambda)]-log[p(z;\theta)])

={\underset{z }{\sum}}q(z|x;\lambda)(log[p(x|z;\theta)]-{\underset{z }{\sum}}q(z|x;\lambda)\frac{log[q(z|x;\lambda]}{log[p(z;\theta]}])

הביטוי השני לפי הגדרה שווה ל-D_{KL}(q(z|x;\lambda)||p(z;\theta)), לכן מתקבל:

=\underset{z}{\sum}q(z|x;\lambda)log[p(x|z;\theta)]-D_{KL}(q(z|x;\lambda)||p(z))

הביטוי הראשון הוא בדיוק התוחלת של log[p(x|z;\theta)]. תחת ההנחה ש-z מתפלג נורמלית, ניתן לרשום:

=E_{q(z|x;\lambda)}logN(x;\mu_{\theta}(z),\sigma_{\theta}(z))-D_{kl}(N(\mu_{\lambda}(x),\sigma_{\lambda}(x))||N(0,I)))

כדי לחשב את התוחלת ניתן פשוט לדגום דוגמאות מההתפלגות z|x\sim N(\mu_{\theta}(x),\sigma_{\theta}(x))) ולקבל:

E_{q(z|x;\lambda)}logN(x;\mu_{\theta}(z),\sigma_\theta(z))\approx logN(x;\mu_{\theta}(z),\sigma_{\theta}(z))

ועבור הביטוי השני יש נוסחה סגורה:

D_{KL}(N(\mu,\sigma^{2})||N(0,I))=\frac{1}{2}(\mu^2+\sigma^2-log \sigma^2)

כעת משיש בידינו נוסחה לחישוב פונקציית המחיר, נוכל לבצע את תהליך הלמידה. יש לשים לב שפונקציית המחיר המקורית הייתה תלויה רק ב-\theta, , אך באופן שפיתחנו אותה היא למעשה דואגת גם למזעור ההפרש בין הכניסה למוצא, וגם למזעור ההפרש בין ההתפלגות הפריורית z לבין ההתפלגות z|x שבמוצא ה-encoder.

איור 6. תהליך הלמידה של VAE.

כאשר נתון סט דוגמאות , ניתן להעביר כל דוגמא x_{t} ב-encoder ולקבל עבורה את \mu _{\lambda },\sigma _{\lambda }. לאחר מכן דוגמים וקטור לטנטי z מההתפלגות עם פרמטרים, מעבירים אותו ב-decoder ומקבלים את \inline \mu _{\theta},\sigma _{\theta}. לאחר התהליך ניתן להציב את הפרמטרים המתקבלים ב-ELBO ולחשב את ה-Loss. ניתן לשים לב שה-ELBO מורכב משני איברים – האיבר הראשון מחשב את היחס בין הדוגמא שבכניסה לבין ההתפלגות שמתקבלת במוצא, והאיבר השני מבצע רגולריזציה להתפלגות הפריורית במרחב הלטנטי. הרגולריזציה גורמת לכך שההתפלגות במרחב הלטנטי z|x תהיה קרובה עד כמה שניתן להתפלגות הפריורית z. אם ההתפלגות במרחב הלטנטי קרובה להתפלגות הפריורית, אז ניתן בעזרת ה-decoder ליצור דוגמאות חדשות, ובמובן הזה ה-VAE הוא מודל גנרטיבי.

הדגימה של z מההתפלגות במרחב הלטנטי יוצרת קושי בחישוב הגרדיאנט של ה-ELBO, לכן בדרך כלל מבצעים Reparameterization trick – דוגמים z_{0} מהתפלגות נורמלית סטנדרטית, ואז כדי לקבל את z משתמשים בפרמטרים של ה-encoder:

z=z_{0}\sigma _{\lambda}(x)+\mu _{\lambda }(x)

.forward-backwardבגישה הזו כל התהליך נהיה דטרמיניסטי – מגרילים מראש z_{0} ואז רק נשאר לחשב באופן סכמתי את ה

 

Reference:

https://towardsdatascience.com/understanding-variational-autoencoders-vaes-f70510919f73

 

Posted by avraham raviv in deep

אתגר רפאל–פתרון בלמידת חיזוקים End-to-End

מיועד ל- מתחילים (כתבה קצת טכנית)

נכתב על ידי binyamin manela

הקדמה על האתגר:

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

המטרה במשחק היא להגן על שתי ערים מרקטות המשוגרות אליהן בעזרת משגר יירוט (ראה Figure 1).

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

בכל צעד ניתן לבצע אחת מ4 פעולות:

  1. לא לעשות כלום
  2. להזיז קצת את המיירט עם כיוון השעון
  3. להזיז קצת את המיירט נגד כיוון השעון
  4. לירות טיל יירוט

הניקוד במשחק הוא כדלקמן: בעת פגיעת רקטה בעיר יורדות 15 נקודות. בעת פגיעת רקטה בשטח פתוח יורדת נקודה אחת. יירוט מוצלח של רקטה מעניק ארבע נקודותובכל ירי של טיל יירוט יורדת נקודה אחת. לאחר כל צעד הסביבה מחזירה את סך הניקוד שנצבר עד כה (score).

המשחק מכיל מספר אתגרים מרכזיים:

  1. הdynamics של המשחק מורכבים לאלגוריתם hand-coded
  2. ה state space של המשחק לא קבוע– כמות הרקטות וטילי היירוט משתנה כל הזמן.
  3. Sparse reward– הסיכוי לירי מוצלח קטן משמעותית מהסיכוי לפספס. כלומר, סביר שהסוכן ילמד מהר שעדיף להימנע מירי.
  4. Reward assigning– גם במקרה והסוכן ירה נכון, התגמול על ירי מוצלח מגיע רק בדיעבד ויהיה לסוכן קשה להבין מה גרם לאותו משוב חיובי. בנוסף, פגיעה של רקטה בעיר גוררת תגמול שלילי גדול באופן מידי, ותגרום לסוכן לחשוב שהוא עשה משהו רע בצעד שלפני הפגיעה (פצצה עוינת=רקטה, טיל כיפת ברזל=טיל).

פתרון Model Free

בכדי להימנע מהגדרות מדוייקות של המערכת, החלטתי לאמן את הסוכן ע”י reinforcement learning. לצורך כך, השתמשתי באלגוריתם PPO עם מימוש הזה. הגדרתי סבב של למידה (cycle) כ10 episodes (10000 תצפיות) ואז למידה עליהם של 10 epochs. לצורך נוחות, בניתי wrapper למשחק כך שהסביבה תתפקד כמו סביבת RL סטנדרטית. את התגמול הגדרתי להיות השינוי בscore. לצורך האימון יצרתי שתי סביבות:Train env ו Test_env.

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

ייצוג רקטות וטילים

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

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

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

של 40X100 פיקסלים (כל פיקסל מתאר גודל של 100X100 מטר) ומתארת את המצב הנוכחי של המערכת מבחינת רקטות / טילים בהתאמה (ראה figure 2).

בכל רגע נתון החזקתי את שלושת המפות האחרונות של הסביבה (כל מפה בchannel אחר) על מנת לאפשר הבנה של המהירות והתאוצה. כלומר, המצב של הרקטות והטילים תואר על ידי שני tensors בגודל של 40X100X3. מעכשיו אקרא לטנזוריםהאלה ‘תמונת רקטות’ ו’תמונת טילים’. כפי שציינתי, הניתוח של שתי התמונות דומה מבחינת כישורים שהרשת צריכה לפתח. לפיכך, בניתי רשת CNNאחת אליה הזנתי את תמונת הרקטות ותמונת הטילים בנפרד.

לאחר העיבוד של התמונות עם רשת הCNN, הכנסתי את הפלט של שתי התמונות לשכבת Dense עם אקטיבצייתtanh שאמורה להוציא עיבוד מוכן של מיקומי הרקטות והטילים ולפלט זה הצמדתי גם את שאר הקלט. מאחר והממדים של שאר הקלטים קבועים (מיקום הערים, זווית המיירט והמשתנה שמודיע האם ניתן לירות), אין בעיה להכניס אותו ללא עיבוד (מלבד נרמול של הערכים לטווח [1,1-]). את כל הקלט המעובד העברתי בשכבת Dense אחת. הפלט של השכבה מתאר את המצב הכולל של המערכת ואותו הזנתי לרשתות הactorוהcritic-. היתרון של שיטה זו היא שבעקבות שיתוף המשקלים (ומאחר ורשת הCNN צריכה לעשות עבודה דומה עבור שתי התמונות), הרשתות אמורות ללמוד מהר יותר. את הגרפים של רשת הActor וה-CNN ניתן לראות בfigure3.

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

החלטתי להימנע משילוב של רשת CNN באלגוריתם הRL. הבעיה קשה מספיק גם ככה, הלמידה של הייצוג כנראה “שברה” את הסוכן. החלטתי להשתמש בvariational auto-encoder(VAE) ללמוד ייצוג יעיל של המפות (תזכורת – מפה היא המצב הנוכחי של הטילים/רקטות). אימנתי את הVAE על 150K מפות של הסביבה (75K מפות של רקטות ו 75K של טילים) והגדרתי את המימד של ווקטור הייצוג להיות בגודל 100. כלומר, הVAE צריך היה ללמוד לייצג תמונה של 40X100X1 כווקטור עם 100 מימדים ולשחזר ממנו את התמונה המקורית. הניסיון הראשון לא הצליח. מאחר והרוב מוחלט של הפיקסלים הם 0, הVAE התכנס לאופטימום לוקאלי בו הוא פשוט מחזיר תמונה ריקה ונמנע לחלוטין מלנסות ולהגדיר איפה יש טילים. בכדי לתקן זאת, החלטתי לייצג את המצב כheat-map סביב הטילים והרקטות. גם כאן, יצרתי מפה נפרדת לטילים ולרקטות (ראה figure 4).

בכדי ליצור את ה heat-maps פשוט הרצתי את המפות המקוריות שיצרתי דרך קונבולוציה עם פילטרים קבועים של מטריצת אחדות בגדלים [7,5,3,1] וstrides=1, וסכמתי את התוצאות. כל קונבולוציה כזו יוצרת ריבוע של אחדות סביב הטיל בגודל מתאים וסכימה שלהם יוצרת פירמידה

סביב הטיל. כעת, לאחר אימון, הVAE הצליח לייצר ייצוג לא רע של הטילים (ראה Figure 4,5).

אחרי שאימנתי את הVAE, החלפתי את שכבות הCNN בשכבת Dense פשוטה. שכבה זו מקבלת מקבץ של שלושה ווקטורים באורך 100 (שוב, הייצוג של המערכת לאורך 3 [1]timesteps) ומצמצמת אותם לווקטור של 128 מימדים. השתמשתי בשכבה זו עבור הרקטות והטילים בנפרד. את הפלט איחדתי לווקטור של 256 מימדים, והזנתי לעוד שכבת Dense עם אקטיבצייתtanh ופלט של 128 מימדים שמתאר את כל המצב של המערכת מבחינת רקטות וטילים. שאר הרשתות נשארו כמקודם (איור 2). גם כעת הביצועים לא היו מדהימים, אבל לפחות יש לי מסגרת לריצות. כעת הגיע הזמן לחשוב קצת יותר במונחים של למידת חיזוקים ואיך להקל על הסוכן.

Sparse Rewards

הסיכוי שירי של הסוכן יוביל למשוב חיובי הוא די נמוך. לפיכך, הסוכן לומד בשלב מוקדם שירי זו פעולה לא משתלמת, ונמנע ממנה לחלוטין. על מנת לתקן את הרושם הזה, החלטתי להשתמש בשיטה של Curriculum learning. בסביבה שסופקה על ידי רפאל יש פרמטר בשם prox_radius (פרמטר זה מגדיר את המרחק הנדרש בין הטיל לרקטה על מנת שהרקטה תתפוצץ כשהערך המקורי עומד על 150 מטר). על ידי שינוי של ערך זה, אני יכול להקל או להקשות על הסוכן. על מנת ללמד את הסוכן שירי זה דבר חיובי, אני מתחיל את האימון עם prox_radius=2000. רדיוס כל כך גדול מלמד את הסוכן שלירות זה דבר חיובי, אך לא מלמד אותו לכוון. על מנת לתקן את זה, כל פעם שהסוכן מגיע לרמת ביצועים מסויימת (אני הגדרתי את הגבול להיות score ממוצע גדול מ0 על פני 10 episodes) אני מכפיל את הרדיוס בפאקטור דעיכה (0.9) עד שהרדיוס יגיע חזרה ל150. שינוי כזה הוא חוקי כי לאחר הלמידה, הסוכן יכול לשחק בסביבה המקורית ללא שינוי.

Reward Assigning

פונקציית התגמול הישירה (השינוי בscore) לא כל כך יעילה, כי מאוד קשה לסוכן לדעת איזו פעולה אחראית לכל תגמול (גם חיובי וגם שלילי), מאחר והתגמול על ירי מוצלח מגיע רק לאחר מספר צעדים ומוצמד לפעולה שלא השפיעה עליו כלל. בנוסף, גם העונש על פגיעה בעיר הוא לא אינפורמטיבי, מאחר והוא מוצמד לפעולה שלא יכלה למנוע אותה. לפיכך, החלטתי לעצב פונקציית תגמול משלי (גם זה שינוי חוקי, מאחר ובמהלך הtest אין כלל התייחסות לתגמול). הוספתי לאובייקט world רשימה בשם reward שנבנתה במהלך הפרק ובסוף (לאחר 1000 צעדים) הוחזרה לסוכן. השינוי הראשון והבסיסי ביותר היה להכניס את התגמול על יירוט מוצלח לreward של הstep בו הטיל נורה. בכדי לעשות זאת, הוספתי לכל טיל שדה נוסף בו שמרתי את הצעד בו הוא נורה ובמידה והיה יירוט, עידכנתי את רשימת הrewards בindex המתאים.

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

בעיה נוספת שהיתה היא המגבלות על הירי. הסוכן יכול לירות רקטה רק אחת לכל 8 צעדים (הטעינה לוקחת 3 שניות). מאחר ואין לסוכן שום אינדיקציה מתי הוא יכול לירות ומתי לא, זה מוסיף variance לvalue שהסוכן מנסה ללמוד. ההגדרה במשחק היא מאוד מדוייקת ואין שום סיבה למנוע את הידע הזה מהסוכן. לצורך כך הגדרתי קלט נוסף –can_shoot, ששווה 1 אם הסוכן יכול לירות (עברו 7 צעדים מאז הירי האחרון) ו0 אחרת. היתרון של קלט כזה הוא שהוא מוריד את האקראיות מבחינת הסוכן ומאפשר אומדן מדוייק יותר של התוצאה של פעולות.

[1]על מנת להגביר את ההבדל בין הווקטורים, החלטתי לא להשתמש במצבים עוקבים, אלא בקפיצות של 3 time-steps. כלומר, הזנתי את הווקטור של המצב הנוכחי, לפני 3 צעדים ולפני 6 צעדים.

_______________________________

[1]על מנת להגביר את ההבדל בין הווקטורים, החלטתי לא להשתמש במצבים עוקבים, אלא בקפיצות של 3 time-steps. כלומר, הזנתי את הווקטור של המצב הנוכחי, לפני 3 צעדים ולפני 6 צעדים.

עם זאת, עדיין הסוכן לא למד מספיק טוב. הסוכן תמיד קיבל ציון גבוה באזור ה300 בשני הסבבים הראשונים של אימון בהם רדיוס הפגיעה עמד על 2000 ו 1800 (אחרי הכל, הוא יירט כמעט את כל הרקטות), אבל אחרי בערך שני סבבי למידה הוא ירד באופן מידי לאזור ה-500. הפעלתי את הrender וגיליתי שהסוכן פשוט מחליט משום מה להימנע לחלוטין מירי. אחרי כמה ניסויים גיליתי שאם אני הופך את הloss של הactor ואומר לו למזער את ה advantage, הסוכן דווקא מצליח לא רע בכלל ומגיע עד לרדיוס של בערך 400 עם ציונים גבוהים (50-100 ומעלה) ואז מתחיל להיכשל. פה חשדתי.

אחרי בערך 45 דקות של בהייה בתקרה, חשיבה ב over-clocking ודמיון אישי מודרך בו אני מנסה לראות את העולם מנקודת מבטו של הסוכן, הגעתי להארה!

 

PPO לא אוהב Curriculum Learning!!!!!

כן, אני יודע, זה קצת הלם, אבל תכלס זה הגיוני. אם רוצים לעבוד עם PPO (ולצורך העניין, כל אלגוריתם שמבוסס על Advantage) ביחד עם Curriculum learning, צריך לעשות את זה מאוד בזהירות. אני אסביר – הactor מחליט אילו פעולות לתעדף על ידי השאלה האם הם הניבו תוצאה טובה מהמצופה או לא. אם הcritic התאמן בעולם פשוט יותר בו קל יותר לקבל משוב גבוה (כמו עולם בו הרדיוס של הטילים גדול יותר וקל לפגוע ברקטות), הוא יגיד לactor שהצפי גדול יותר ממה שהוא אמור להיות, ולפיכך נקבל שהadvantageעל ירי יהיה כמעט תמיד שלילי. ככל שפעולה היתה מתגמלת יותר בעולם הקודם, כך צפויה לcritic אכזבה חמורה יותר. הcritic התאכזב מאוד מהתוצאה של ירי וגרם לactor להימנע ממנו לחלוטין. כשחושבים על זה, זה לא כל כך מפתיע. כמו שאומרים, “כגודל הצפייה, כך גודל האכזבה” ולכן גם נרמול של הAdvantage  לא עזר כאן (האכזבה מירי היתה גדולה מהאכזבה מהימנעות מירי).

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

עם זאת, הסוכן עדיין התקשה להגיע לרדיוס האמיתי (150) של הבעיה ונתקע באזור ה200.

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

פה אמרתי נואש, לאור העובדה שנשארו רק כמה שעות לתחרות.

אם היה לי עוד כמה ימים, השיפורים העיקריים שהייתי בודק היו:

  1. כמובן, חיפוש מימוש אחר.
  2. שיפור של הרפרזנטציה. אולי אימון נוסף של הVAE על יותר נתונים עם פחות תלות בניהם. הכנסתי לסט שלי רק תמונה אחת כל 50 timesteps מפוצלת ל3 מפות), אבל בדיעבד קלטתי שתמונת המצב מכילה 3 מפות עוקבות, מה שיצר סטים מאוד דומים אחד לשני. הייתי מתקן את זה ומכניס רק את המצב הנוכחי של המערכת במקום את 3 המצבים האחרונים.

בנוסף, אני חושב שבעתיד אבחן 2 כיוונים נוספים “בשביל הספורט”. דבר ראשון, הייתי רוצה להחליף את הרפרזנטציה בשכבה של Deep sets. כלומר, להכניס כל אחד מהטילים לרשת קטנה (שכבה או שתיים) עם output של נניח 50 נוירונים ואז לאחד את הפלט של כל הטילים בעזרת max pooling (או משהו בסגנון) על כל אחד מהממדים.

כיוון נוסף הוא לעזוב את הפתרון של end2end. יכול להיות מעניין לפצל את הבעיה ל2 סוכנים שונים:

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

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

לסיכום, היה לא קל, מתסכל ואפילו מייאש לעיתים, אבל כחוק, RL זה פשוט תענוג!

 

אם מישהו מעוניין בפרטים נוספים / קוד, שידבר איתי בפרטי 😊  0526429005

Posted by binyamin manela in deep

איך מתקינים מה שצריך עבור Deep Learning עם Anaconda ?

מיועד ל- מתחילים (כתבה קצת טכנית)

נכתב על ידי תמיר נווה

הדרך הכי נוחה ונטולת התקנות לפתח Machine Learning & Deep Learning זה השירות Colab שהינו שירות חינמי של גוגל שמספק מחשב עם GPU לכל דורש והוא מאוד מומלץ למשחקים וללימודים. כשרוצים לפתח משהו קצת יותר גדול ומורכב המגבלות של Colab באות לידי ביטוי: זמן מוגבל של סשן, חוסר יכולת לשים break points על הקוד, החרדות שהקוד שלי יושב בשרתי גוגל (ולפעמים בפרויקטים בטחוניים בכלל אין לנו חיבור לרשת החיצונית) וכו’…

אז אנחנו רוצים לפתח קוד שממש יישב אצלנו, על המחשב שלנו ואנחנו מאוד חוששים מההתקנות המייגעות… (קצת בצדק…)

אם יש GPU צריך להתקין Cuda ואם חלילה אין תאימות בין הגירסאות נבין את זה אחרי המתנה של שעות התקנה שירדו לטימיון, אם בטעות בחרנו פייתון 32bits פתאום נגלה את זה אחרי שכבר סיימנו את ההתקנה כי איזשהיא package  לא מתאימה, ועוד ועוד צרות מייגעות…

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

מהן סביבות עבודה ?

בפייתון ולרוב באופן כללי בעולם הקוד הפתוח אין גורם אחד שאחראי ומנהל את הפיתוח של כל החבילות (packages) או מרכיבי הקוד למיניהם. ולכן נוצרות בעיות תאימות. מה שקורה זה שעובדים על איזשהוא פרויקט שמבוסס על קוד שמשתמש בחבילתNumpy  (למשל) בגירסה ישנה ואז רוצים להוריד קוד חדש יותר שמתבסס על חבילת Numpy בגירסה חדשה יותר. על מנת שנוכל להריץ על אותו המחשב את שתי הפרויקטים החדש והישן עלינו להחזיק גם גירסאות Numpy חדשה וישנה וזה מתאפשר ע”י אחזקה של שתי סביבות שונות. בכל סביבה ניתן להתקין התקנות שלא ישפיעו על סביבה אחרת. וכל פרויקט שנרצה להריץ נצטרך לבחור באיזו סביבה הוא ירוץ.

אז למעשה סביבה היא תיקייה בה נשמרים כל החבילות בגירסותיהן השונות עם המפרש (Python interpreter)  שמאפשר להריץ קוד פייתון. גם למפרש יש הרי גירסאות שונות ואפשר להחזיק סביבת פייתון 2 וסביבת פייתון 3 במקביל.

מה עושים שלב אחרי שלב ?

מורידים Anaconda מהקישור הבא:

https://www.anaconda.com/distribution/

אחרי שמתקינים נוצר לנו Anacoda Prompt שזה כמו ה Command line הרגיל רק שמשמאל ל path הנוכחי מופיע בסוגריים שם הסביבה הנוכחית (ברירת המחדל הינה base):

אם רוצים לקבל את רשימת הסביבות הקיימות רושמים:

conda info –envs

ומקבלים (מה שיש אצלי כרגע):

אם רוצים לעבור לסביבה אחרת:

ניתן לראות ששם הסביבה הנוכחית השתנה ל (tf_gpu).

אם רוצים לקבל את רשימת החבילות המותקנות בסביבה הנוכחית:

conda list

ואם רוצים ליצור סביבה חדשה:

conda create –name XXX

ואז כל התקנה שנעשה תישמר בסביבה הנוכחית.

התקנה חדשה תיעשה ע”י

conda install XXX

או גם בדרך המוכרת:

pip install XXX

מחיקת סביבה:

conda remove –name old_name –all

שינוי שם של סביבה אי אפשר, אבל אפשר לשכפל בשם אחר ואז למחוק:

conda create –name new_name –clone old_name

conda remove –name old_name –all

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

conda create –offline –name $NAME

 

אז לאחר שהתקנו Anaconda ויצרנו סביבה והתקנו בה את החבילות שאנחנו רוצים (למשל TensorFlow, Keras, Numpy)

השלב הבא הוא לבחור סביבת פיתוח (IDE) ולקשר אותה לסביבות העבודה אותם יצרנו ב Anaconda.

אז אדגים זאת על Pycharm, ראשית נתקין את גירסת ה-Community החינמית: (או הגירסה המקצועית בתשלום)

https://www.jetbrains.com/pycharm/download/#section=windows

אחרי שהתקנו נלחץ על new project  ובעקרון נוכל להתחיל לכתוב קוד. אבל כפי שהסברנו יש לשייך סביבה לפרויקט או במילים אחרות להחליט איזה מפרש (python interpreter) על חבילותיו השונות נרצה שיריץ את הקוד שלנו ?

אז סביבה כבר הגדרנו בAnaconda Prompt  ומה שנותר זה להגדיר ל PyCharm היכן יושבת הסביבה שהגדרנו מקודם. אז נלך ל Settings שם מצד שמאל נראה Project: project_name (אצלי שם הפרויקט הוא desktop)

ונלחץ על Project Interpreter:

ואז על Add ז”א הוספת סביבת עבודה:

פה נבחר סביבת Anaconda  קיימת ונזין את מיקום ה Interpreter כפי שהופיע לנו כשבנינו את הסביבה ב Anaconda Prompt (ואם שכחנו אפשר לכתו where python ב anaconda prompt  בכדי לקבל זאת שוב)

ורצוי לשים וי על Make available to all projects כדי שהסביבה הזו תהיה מוכרת לכל פרויקט עתידי גם.

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

תחת Run-Edit Configuration נבחר סביבת עבודה לפרויקט שלנו מתוך הסביבות הקיימות (אותן הגדרנו בעבר):

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

Posted by תמיר נווה in deep

צעד קטן לאדם צעד גדול להתכנסות

מיועד ל- מטיבי לכת (כתבה מאוד טכנית)

נכתב על ידי Ayelet Sapirshtein

“המסע הארוך ביותר נפתח בצעד הלא נכון”. (צ’ארלס כריסטופר מארק)

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

מהי אופטימיזציה למזעור פונקציית ההפסד (loss function) ?

פונקציית המחיר משמעותה עד כמה המודל שלנו צודק. ככל שהערך של פונקציית ההפסד (loss) נמוכה יותר, כך המודל “צודק” יותר. מודל “צודק” משמעו מודל שהפרדיקציה במוצאו קרובה ל Ground Truth, התוצאה שאמורה להיות בהתאם לתיוגים. למשל במודל סיווג בינארי לדואר (דואר זבל=1 דואר רגיל=0) עד כמה הציון שהמודל נותן קרוב ל1 בהינתן דואר זבל ו0 בהינתן מייל רגיל.

 לכל אורך אימון המודל מטרתינו לעדכן את המשקלים (המשתנים הפנימיים של המודל) ככה שהפרדיקציה שלו תהיה קרובה יותר ל Ground Truth וזאת אנו עושים ע”י כך שגוזרים את פונקציית המחיר (מחשבים gradient) ביחס למשקלי המודל. הנגזרת מלמדת אותנו על ההתנהגות (עליה\ירידה) של הפונקציה אותה גוזרים. כיוון הגרדיאנט בנקודה מצביע על הכיוון בו הפונקציה עולה ובכיוון הנגדי יורדת מהנקודה בה אנחנו נמצאים. מטרה תהליך האימון היא למצוא ערך מינימום של פונקציית ההפסד ולשם כך משתמשים בשיטות אופטימיזציה.

Gradient Descent

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

לדוגמה לחישוב Gradient descent עבור מודל רגרסיה לינארית n מימדית:

עבור קלט וקטור x, וקטור y שהינו ה Ground Truth (התחזית הרצויה) ו θ

וקטור הפרמטרים של מודל הרגרסייה.

ההיפותזה של התחזית עבור קלט x נראית כך:

h_0(x)=\sum_{j=0}^n\theta_jx_j

h_0 מייצגת את התחזית עבור דוגמא x

בהינתן m דגימות פונקצית ההפסד תראה כך:

J_{train}(\theta )=\frac{1}{2m}\sum _{i=1}^m\left ( h_{\theta}\left ( x^{(i)}\right )-y^{(i)} \right )^2

הגרדיאנט: 

\frac{1}{m}\sum _{i=1}^m\left ( h_{\theta}\left ( x^{(i)}\right )-y^{(i)} \right )x_j^{(i)}

הוא פרמטר המייצג את גודל הצעד שנלקח בצעד העדכון learning rate

עבור learning rate נקבל שצעד העדכון הייה:

\theta_j-\alpha\frac{1}{m}\sum _{i=1}^m\left ( h_{\theta}\left ( x^{(i)}\right )-y^{(i)} \right )x_j^{(i)}

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

בפועל חישוב הגרדיאנט לפי כל סט האימון (גודל batch ענקי) לוקחת זמן רב ולא ישים מבחינה חישובית. לעומת זאת SGD=Stochastic Gradient Descent, היא שיטה לפיה עוברים בלולאה מספר פעמים (כמספר ה-epochs) על סט האימון, ובכל איטרציה במקום לחשב את הגרדיאנט לפי כל סט האימון, מחשבים את הגרדיאנט לפי הדוגמא הנוכחית. (זהו למעשה batch בגודל אחד)

כדי לגרום לגרדיאנטים להיות פחות תנודתיים, במקום לחשב גרדיאנט לפי קלט יחיד, מחשבים לפי קבוצה קטנה של קלטים, שיטה זו נקראת Mini Batch Gradient Descent.

מקור 

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

ללא קשר לגודל ה Batch לשיטת ה-SGD יש לא מעט בעיות:

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

  1. התכנסות למינימום מקומי ולנקודות אוכף. כאשר SGD מגיע למינימום מקומי, או נקודת אוכף הגרדיאנט שווה ל0 וSGD יעצר. במימד גבוה זו סיטואציה שכיחה, למעשה הרבה יותר ממינימום מקומי. מסיבה זו הבעיה העיקרית היא עם נקודות אוכף ופחות עם מינימום מקומי. בעיה זו נוצרת גם בסביבת נקודת האוכף, שבה גרדיאנט מאוד קטן, וזו בעיה גדולה.מקור
  2. כיוון הגרדיאנט עלול לסבול מרעשים בעקבות העבודה עם mini batch, לדגימות חריגות (outliers) ב-Batch יכולה להיות השפעה חזקה.למרבה המזל יש אסטרטגייה פשוטה שעובדת טוב ברוב המקרים כדי להתמודד עם בעיית תנודתיות הגרדיאנטים והעצירה בנקודות אוכף.

    הוספת מומנטום ל-SGD

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

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

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

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

 

מקור

לרוב בוחרים את rho להיות 0.9 או 0.99.

שיטת אופטימיזציה שנועדה כדי להתמודד עם הזיגזוג שנוצר כתוצאה מהמקרה בו גרדיאנט משתנה בעוצמה שונה בכיוונים שונים היא AdaGrad.

AdaGrad

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

מה יקרה כתוצאה מהחילוק בהנחה שיש לנו קואורדינטה אחת שהנגזרת הכיוונית שלה תמיד קטנה קואורדינטה אחרת שהנגזרת הכיוונית שלה תמיד גדולה?

מקור

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

מה קורה לAdaGrad לאורך תהליך האימון כאשר סכום הריבועים הולך וגדל?

גודל הצעדים (learning rate) יקטן לאורך הזמן, כי אנחנו ממשיכים להגדיל את סכום הריבועים. במקרה הקמור (convex) , שיש בו מובטח מינימום יחיד, התיאוריה אומרת שזה למעשה ממש טוב. כי במקרה הזה כאשר מתקרבים למינימום רוצים לעשות צעדים קטנים יותר כדי לא להחמיץ את המינימום. לעומת זאת המקרה הלא קמור זה קצת בעייתי. כי אנחנו עלולים להיתקע בנקודת אוכף. בפרקטיקה AdaGrad לא כל כך שימושי בגלל הנטייה שלו להיתקע.

יש וריאציה קלה לAdaGrad שמתמודדת עם הבעיה הזו הנקראת RMSProp

RMSProp

באלגוריתם הזה במקום לתת לסכום הריבועים לגדול לאורך האלגוריתם, אנחנו מאפשרים לסכום ריבועי הגרדיאנטים לקטון. ב-RMSProp , אחרי שאנחנו מחשבים את הגרדיאנטים שלנו, אנחנו לוקחים את הערכה הנוכחית שלנו של ריבועי הגרדיאנטים, מכפילים אותה בקצב הדעיכה,לרוב 0.9 או 0.99, ומוסיפים לו 1 פחות קצב הדעיכה כפול ריבוע הגרדיאנט הנוכחי.

מקור

הקורא הדקדקן שישווה בין Ada-Grad לבין RMSProp יבחין שאם נחליף במשוואות של RMSProp את הממוצע המשוכלל לפי פרמטרdecay_rate לסכום, כלומר להחליף את decay_rate ב-1 ואת 1-decay_rate ב-1 נקבל בדיוק את AdaGrad.

RMSProp שומר על המאפיין הנחמד של Ada-Grad להאיץ מהירות לאורך כיוון אחד ולהאט אותה בכיוון אחר, מבלי הבעיה של תמיד להאט.

ניתן לראות ש RMSProp לא עושה overshoot והוא נע בכיוון יחסית שווה לאורך כל המימדים.

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

למה לא גם וגם ? ? ?

Adam

משלב את השיטות הקדמות Momentum+ AdaGrad

מקור

אבל בצורה הזו הוא סובל מבעיה בצעדים הראשונים. המומנט השני מאותחל ל-0, אחרי איטרציה בודדת המומנט השני המומנט השני עדיין ממש קרוב ל-0 בהנחה ש bata1 שווה ל-0.9 או 0.99. אז כאשר נבצע חילוק במומנט השני, זה יגרום לכך שנבצע צעד מאוד גדול על ההתחלה. כדי לפתור את הבעיה הזו הוסיפו לAdam שינוי קטן. 

מקור

המשתנים first_unbias ו second_unbias מתנהגים כמו המומנט הראשון והשני. כאשר t גדול וכאשר t קטן, השינוי של ה-unbias מקטין את first_unbias ו second_unbias ביחס למומנטים, אבל היות ובחישוב x אנחנו מפעילים שורש על second_unbias, נראה שיחס הגדלים בין המונה למכנה קטן, וכך גם צעדי ההתחלה.

פרמטרים מומלצים לAdam: bata1=0.9, bata2=0.999 ,learning_rate=1e-3

מה החסרונות של Adam וכיצד מתמודדים איתם?

למרות שAdam הוא אחד משיטות האופטימיזציה השימושיות ביותר כיום, הוא סובל מ 2 בעיות עיקריות:

  1.  האימון הראשוני של Adam לא יציב, בגלל שבתחילת האימון יש מעט נקודות לחישוב הממוצע עבור המומנט השני. צעדים גדולים מבוססים על מידע מועט ורועש יכולים לגרום להשתקעות בנקודת מינימום מקומית או אוכף. בעיה המשותפת לרוב אלגוריתמי אופטימיזציה.
  2. המודל המתקבל לא מכליל בצורה טובה (נוטה ל overfitting) ביחס לSGD עם מומנטום.

דרך אחת להתמודד עם הבעיה הראשונה היא להתחיל לאמן בקצב נמוך, וכאשר המודל מתגבר על בעיית ההתייצבות הראשוניות, להגביר את הקצב. שיטה זו נקראת learning rate warm-up. חסרונה של השיטה הוא שמידת החימום הנדרש אינה ידועה ומשתנה מערך נתונים למערך נתונים. 

במקום שנגדיר בעצמנו את הפרמטרים עבור ה-warm-up ניתן להשתמש ב-RAdam .RAdam הוא אלגוריתם חדש שמחליף את ה-warm-up ב-Adam ולא מצריך הגדרת פרמטרים עבור תקופת החימום. חוקרים שפתחו את RAdam מצאו כי בעית ההתיצבות הראשונית נגרמת כתוצאה משונות לקויה ב-learning rate האדפטיבי כתוצאה מכמות הנתונים המוגבלת בתחילת האימון. הדרך בה (Rectified Adam)-RAdam פותר את הבעיה היא על ידי תיקון (Rectified) השונות של ה-learning rate האדפטיבי על סמך הגרדיאנטים.

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

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

איך בוחרים learning rate?

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

מקור 

לא חייבים לדבוק באותו learning rate לאורך כל האימון. מומלץ לרוב להקטין את ה-learning rate לאורך האימון ובכך לשלב בין היתרונות של קצב לימוד מהיר ואיטי. הקטנת ה -learning rate מקובלת לרוב בשימוש ב-SGD ופחות באלגוריתמים אדפטיבים שבהם שינוי ה-learning rate כבר נמצא באלגוריתם. בנוסף learning rate נמוך בתחילת האימון, warm-up, יכול להועיל, כפי שציינו קודם.

LookAhead

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

מתוך מאמר LookAhead

 

במה משתמשים בפועל?

נכון להיום השיטות הנפוצות ביותר הם Adam שמתכנס מהר ו-SGD עם מומנטום ו-learning rate decay משמש בדרך כלל עבור SOTA אבל דורש fine tuning. בין השיטות החדישות היום שנותנות תוצאות טובות ניתן למצוא את Ranger אופטימיזר שמשלב את RAdam עם LookAhead. כל אחד מהם מטפל בהיבטים שונים של אופטימיזציה. RAdam מייצב אימונים ההתחלתיים, ו-LookAhead מייצב את האימונים הבאים, מבצע אקספלורציה מזרז את תהליך ההתכנסות.

ספרו לנו בתגובות באילו שיטות אופטימיזציה אתם משתמשים, ומה עבד לכם טוב?

שאלות אפשריות לראיונות עבודה:

איך עובד backpropagation?

אילו שיטות אופטימיזציה לאימון רשתות אתה מכיר? ‍

כיצד משתמשים ב-SGD לאימוני רשת עצבית? ‍

מה היתרונות בשימוש במיני באצ’ים ב-gradient descent?

איך עובד Adam? מה ההבדל העיקרי בינו לבין SGD? ‍

למה לעיתים קרובות ל-Adam יש לוס נמוך יותר אבל SGD נותן תוצאות יותר טובות על ה-test ?
‍מה זה learning rate?

מה קורה כשה-learning rate גדול מדי? קטן מדי?

מה עדיף learning rate קבוע או משתנה לאורך האימון?

איך מחליטים מתי להפסיק לאמן רשת עצבית? 

מה זה model checkpointing?

חומר נוסף:

Gradient Descent Intuition Andrew Ng

Stochastic Gradient Descent  Andrew Ng 

cs231n Stanford Lecture 7

Ranger

Posted by Ayelet Sapirshtein in deep

5 שאלות על פונקציות אקטיבציה שעלולות להופיע בראיון העבודה הבא שלך

מיועד ל- מתחילים (כתבה קצת טכנית)

נכתב על ידי Ayelet Sapirshtein

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

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

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

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

z^{[1]}=W^{[1]}x+b^{[1]}

נשתמש בפונקציית הזהות בתור פונקציית אקטיבציה:

a^{[1]}=id\left ( z^{[1]} \right )=W^{[1]}x+b^{[1]}

נחשב את האקטיבציה של השכבה הבאה: 

z^{[2]}=W^{[2]}a^{[1]}+b^{[2]}

\inline a^{[2]}&=id\left ( \right z^{[2]})=W^{[2]}a^{[1]}+b^{[2]} =W^{[2]}\left ( W^{[1]}x+b^{[1]}\right )+b^{[2]} =\left (W^{[2]}W^{[1]}\right )x+\left ( W^{[2]}b^{[1]}+b^{[2]} \right )=\acute{W}x+\acute{b}

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

פונקציית האקטיבציה הראשונה שהייתה בשימוש ברשתות הייתה סיגמואיד 

סיגמואיד:

 

הסיגמואיד מכווץ את המספרים לטווח של [0,1] . הוא היה פופולרי בעבר בשל הדמיון לפעולת אקטיבציה במוח האנושי. לפונקציית סיגמואיד יש כמה חסרונות בולטים בתור פונקציית אקטיבציה.

Saturation (רוויה)- הרוויה הורגת את הגרדיאנט. כאשר השיפוע מתיישר הגרדיאנט שואף ל-0 ולכן פעפוע לאחור לא יוכל לעדכן את המשקלים.

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

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

חישוב האקספוננט לוקח זמן רב 

כדי לפתור את הבעייה שנוצרה מכך שסיגמואיד לא ממורכז סביב ה-0 עברו להשתמש בפונקציית tanh.

(טנגנס היפרבולי) tanh

 tanh מתנהגת כמו סיגמואיד שעבר הזזה והכפלה בקבוע. גרסה אחרת של tanh נראית כך: tanh(x)=2\sigma(x)-1. tanh ממורכזת סביב ה-0 מכווץ את המספרים לטווח של [1,1-].

Saturation (רוויה)-  בדומה לסיגמואיד tanh סובל מבעייה של דעיכת גרדיאנטים (vanishing gradient) בגלל רוויה.

חישוב tanh לוקח זמן רב 

כיום tanh שימושי בעיקר עבור רשתות rnn.

ReLU

AlexNet הייתה הרשת הראשונה שהחליפה את פונקציית האקטיבציה ל-ReLU, וגרמה לרשת להתכנס פי 6 יותר מהר.

ReLU מהיר לחישוב ביחס לסיגמואיד ו-tanh.

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

 

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

Leaky ReLU

מאוד דומה ל-relu אבל הגרדיאנט שלו לא מתאפס כאשר x<0. מבחינה פרקטית, אין קונצנזוס שהוא נותן תוצאות טובות יותר, יש מאמרים לכאן ולשם.

Maxout

לא נכנסת לסטורציה אבל מכפילה את מספר המשקלים ברשת, במקום w יש לנו עכשיו w1 וw2. מסיבה זו היא לא פרקטית

ELU

 

חישוב אקספוננט לוקח זמן רב.

 ELU ו-MaxOut נמצאים בשימוש רק לעיתים רחוקות, מפני שאין עדיות חד משמעיות שהן עובדות טוב יותר מReLU והן יותר יקרות מבחינה חישובית. נראה שאין עדויות חד משמעיות לכך שפונקציות שלא מגיעת לרוויה כמו ELU ,MaxOut או Leaky ReLU משפרות תוצאות, אז נשאלת השאלה איך בכל זאת נוכל למנוע מנוירונים למות?

מה אפשר לעשות כדי למנוע מנוירונים ברשת למות ?

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

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

עם זאת בחירת learning rate נמוך מדי יאט את קצב ההתכנסות.
דרכים נוספות כדי למנוע מנוירונים למות הן pruning או dropout, ו-batch normalization.

מתכוננים לראיונות עבודה? ענו על השאלות הבאות בנושא:

  1. מדוע אנחנו זקוקים לפונקציות אקטיבציה?
  2. כתוב את פונקציית סיגמואיד ושרטט אותה?
  3. מה הנגזרת של פונקציית סיגמואיד?
  4. מה הבעיות בשימוש בפונקציית סיגמואיד בתור פונקציית אקטיבציה?
  5. מה גורם לתופעת ה vanishing gradient ברשתות, ובאילו דרכים אפשר להתמודד איתה?

כתבו את תשובותיכם בתגובות וקבלו מאיתנו פידבק. תפגיזו בראיונות!

מקורות:

046003, Spring 2019 טכניון
cs231n_2019  7 מצגת

Activation Functions (C1W3L06)

Why Non-linear Activation Functions (C1W3L07)

Lecture 0204 Gradient descent in practice II: Learning rate

 

 

Posted by Ayelet Sapirshtein in deep

סדר בניהול הריצות Machine Learning

מיועד ל- מתחילים (כתבה קצת טכנית)

נכתב על ידי תמיר נווה

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

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

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

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

מהו Neptune

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

כמובן שהכל מגובה ומאובטח.

איך משתמשים ?

ראשית נרשמים כאן ומקבליםtoken  אישי, מגדירים את ה token כמשתנה מערכת:


NEPTUNE_API_TOKEN=”…”

ואז הגישה יכולה להיות מ R או פייתון, אדגים עם פייתון.

מתקינים:


pip install neptune-client

ואז מכניסים לקוד שלכם את שלושת שורות הקוד הבאות:

 

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

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

לצורך כך הוסיפו שורות שכאלו:

neptune.send_metric(‘Variable I want to store’,var1)

neptune.send_image(‘Image I want to see while training’,img1)

כשהקוד ירוץ תתווסף שורה לרשימת ה experiments ב dashboard של Neptune עם כל המאפיינים:

התגיות מועילות כי בעוד חודש שנשכח למשל שבדקנו איך dropout הישפיע על הביצועים נחפש את כל הריצות עם התגית הזו, עוד שנה שננסה להיזכר מה הייתה הריצה הכי טובה עם מודל ה Xception למשל נחפש תגיות (שאנחנו כתבנו בשורת ה  neptune.create_experiment עם המילים best, xception)

גישה לתמונות ולגרפים

כדי לראות את נתוני הריצה נלחץ על ה experiment  הרצוי ושם כל אלמנט ששלחנו יוצג (משתנים\תמונות\גרפים וכו’). לחיצה על כל אחד תציג אותו:

השוואות בין ריצות

כשנרצה להשוות בין משתנים כלשהם מריצות שונות נסמן את הריצות הרצויות מהרשימה ונלחץ על compare.

מה שנקבל זה גרפים של המשתנים ששלחנו וכל ריצה תהיה בצבע אחר:

לסיכום

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

Posted by תמיר נווה in deep

הסבר למתחילים על העברת לימוד -Transfer Learning

מיועד ל- כל אחד (כתבה לא טכנית)

נכתב על ידי Ron Jacobson

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

  • בניית מודל מאפס
  • שימוש במודל קיים ומאומן כדי להיעזר במשקלים שלו. (Transfer Learning)

במאמר זה נתמקד באפשרות השניה.

ישנם מספר מודלים אשר יכולים לעזור לנו לבצע העברת לימוד (Transfer Learning) או כיוונון סופי (Fine-Tuning) בצורה טובה ויעילה.

מהי העברת למידה?

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

איך זה עובד?

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

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

המודל למעשה יהיה בארכיטקטורה הבאה:

 

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

מדוע משתמשים בהעברת למידה?

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

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

כלומר, למעשה נחסוך בשתי דרכים:

1: הקטנת הדאטה הנדרש – לא יהיה צורך במערך אימונים גדול במיוחד.

2: הקטנת הכוח החישובי הנדרש. היות ואנו משתמשים במשקולות אשר אומנו מראש ונותר רק ללמוד את המשקולות של השכבות האחרונות.

מתי כדאי להשתמש בהעברת למידה?

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

בדרך כלל כדאי להשתמש בהעברת למידה כאשר:

(א) אין ברשותך מספיק נתוני אימון מתוייגים כדי לאמן את הרשת שלך מאפס

(ב) כבר קיימת רשת אשר אומנה מראש על משימה דומה, ובד”כ על כמויות אדירות של נתונים.

(ג) מקרה נוסף שבו השימוש יהיה מתאים הוא כאשר למשימה 1 ולמשימה 2 יש את אותו קלט. (למשל תמונה באותו הגודל)

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

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

אילו מודלים יעזרו לנו בהעברת הלמידה?

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

מודל VGG16

VGG16 פורסם בשנת 2014 והוא אחד מסוגי הרשתות הפשוטות ביותר (בין ארכיטקטורות ה – CNN האחרות שהיו בתחרות Imagenet). רשת זו מכילה סה”כ 16 שכבות מתוכם 13 שכבות קונבלוציה ו 3 שכבות Dense לצורך הסיווג. מספר הפילטרים בשכבות בקונבלוציה הולכים וגדלים  בעוד המימדים הגיאומטריים הולכים וקטנים.

החסרונות של ארכיטקטורה זו הינם:

  1. שלב האימון הינו איטי יחסית
  2. התהליך מייצר מודל גדול מאוד.

הארכיטקטורה של VGG16 ניראת כך:

https://www.semanticscholar.org/paper/Face-Recognition-across-Time-Lapse-Using-Neural-Khiyari-Wechsler/1c147261f5ab1b8ee0a54021a3168fa191096df8

באם נבחר להשתמש במודל זה, אנו נבצע את הצעדים הבאים כדי לממש את VGG16:

  • נייבא את האפליקיישן של VGG16 מ- applications
  • נוסיף את המשקולות השמורים לארכיטקטורה (weights = ‘ImageNet’)
  • נשתמש במודל כדי לבצע תחזיות
  • אציין כי קיימת רשת דומה מאוד בשם VGG19 אשר מכילה מאפיינים דומים למה שתואר לעיל.

מודל InceptionNets

רשת הידועה גם בשם “GoogleNet“. המורכבת מסה”כ 22 שכבות והייתה המודל המנצח בתחרות ImageNet של שנת 2014.

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

מודלים אלו משתמשים בקונבלוציות בגדלים שונים כדי ליצור Feature-Map מגוון.

בנוסף, הם גם מכילים קונבלוציה של 1X1 כדי לבצע הפחתת מימדים.

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

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

https://arxiv.org/pdf/1409.4842.pdf

והארכיטקטורה השלמה ניראת כך:

https://arxiv.org/pdf/1409.4842.pdf

 

 

מודל Resnets

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

עם זאת, לאחר יציאת מודל Resnet התברר כי הדבר לא ממש מדויק. להלן הבעיות עם רשתות שהן עמוקות יותר:

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

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

כפי שמופיע באיור להלן:

https://towardsdatascience.com/an-overview-of-resnet-and-its-variants-5281e2f56035

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

באמצעות בלוקים שיוריים ברשת, ניתן לבנות רשתות בכל עומק שהוא תחת ההבנה כי שכבות חדשות למעשה מסייעות ללמוד תבניות חדשות בנתוני הקלט. מחברי המאמר יצרו ארכיטקטורת רשת עצבית עם 152 שכבות. הסוגים השונים של Resnets כגון Resnet34, Resnet50, Resnet101 הפיקו את הפתרונות עם דיוק גבוה מאוד בתחרויות Imagenet.

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

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

לסיכום

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

Posted by Ron Jacobson in deep

ערוכים לזה: עריכת וידאו בעזרת AI

מיועד ל- מתחילים (כתבה קצת טכנית)

נכתב על ידי Ayelet Sapirshtein

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

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

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

להלן דוגמה של וידאו מקורי ומשעמם באורך 1:25 (הלקוח מאגר וידאוים לבעיית התימצות: tvsum)

ולהלן הוידאו המתומצת שלו באורך 12 שניות כפלט מאלגוריתם הזה (רק שיניתי אותו בזה שהחלפתי את הרשת שמקודדים איתה את הפריימים inception v3 במקוםinception v1)

איך קובעים את מידת החשיבות של פריים?

חשיבות הפריימים היא דבר סובייקטיבי. בלמידה מונחית (supervised), למידה מבוססת מידע מתויג, משתמשים בדירוג אנושי. עבור כל סרטון מבקשים ממספר אנשים לסווג כל פריים למעניין או לא מעניין, ממצעים את הדירוגים ומקבלים ציון שמייצג את רמת העניין של הפריים. אם פריים מסויים עניין 7 מתוך 10 אנשים הוא יקבל ציון 0.7. כך מייצרים את המידע המתוייג.

איך יוצרים רשת שמדרגת את החשיבות של כל פריים?

בניגוד לתמונה, רמת העניין של פריים תלויה ברצף הפריימים ומיקומו בתוך הוידאו. בשביל לתת ביטוי למיקום הפריים ברצף, משתמשים ברשתות נוירונים ממשפחת (Recurrent Neural Network (RNN או Self-Attention אשר נועדו לפענח מידע סדרתי. רשתות אלו יכולות לקבל מידע סדרתי בכל אורך, לצורך עניינינו סרטונים עם מספר פריימים שונה. בנוסף לכך הן כוללות מרכיב של זיכרון – כך שהרשת “יודעת להתחשב” בהיסטוריה.

רשת RNN בסיסית

תודה ל https://en.wikipedia.org/wiki/Recurrent_neural_network#/media/File:Recurrent_neural_network_unfold.svg

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

Xt הוא הקלט ה-t ברצף הזמן, במקרה שלנו הפריים ה -t

ht הוא מצב נסתר (hidden state) בזמן t, ה”זיכרון” של הרשת. ht מחושב על סמך המצב הנסתר הקודם (ht-1) והקלט בשלב הנוכחי (Xt).

ot הפלט של זמן t, במקרה שלנו התחזית של הרשת לגבי כמה מעניין הפריים ה-t.

בעיות זיכרון

הכנסת וידאו שלם לרשת RNN זה דבר כבד! נדרש לשם כך זיכרון רב. על מנת לפתור את הבעיה משתמשים בשתי טכניקות:

  1. Down-Sampling לסרטון. במקום להתחשב ב-30 פריימים לשנייה אפשר להסתכל רק על 2, תחת ההנחה שאין הבדל גדול בין פריימים עוקבים.
  2. במקום לקחת את הפריימים עצמם, מתמצתים את המידע שנמצא בתמונה. דבר זה מתבצע על ידי הוצאת מאפיינים בעזרת רשתות קונבולוציה (CNN) שאומנו למטרות סיווג תמונות (כגון VGG, GoogLeNet, ResNet)

איך שומרים על רציפות הסרטון?
אחת הדרכים לתמצת סרטון מתחילה בלבקש מהמשתמש את אורך הסיכום הדרוש. לאחר מכן, מחלקים את הוידאו למקטעים בצורה חכמה על ידי אלגוריתם למציאת נק’ שינוי סצנה (למשל Kernel Temporal Segmentation). נקודות השינוי ישמשו להגדרת הסוף וההתחלה של כל מקטע. במקום שהאלגוריתם יבחר באופן נפרד כל פריים, הוא בוחר אילו מקטעים לקחת. באופן זה נשמרת הרציפות בסרטון המקוצר.

איך בוחרים אילו מקטעים לקחת? (בעיית תרמיל הגב)

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

בעייה זו שקולה לבעייה מפורסמת מאוד במדעי המחשב שנקראת בעיית תרמיל הגב (Knapsack problem) .

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

בעייה זו מוגדרת כבעייה np-קשה, עם זאת, כאשר משקלי כל הפריטים שלמים, ניתן לפתור אותה בעזרת תכנון דינאמי בסיבוכיות זמן (O(Wn, כאשר W הוא המשקל המירבי שניתן לסחוב ו-n כמות הפריטים. במקרה שלנו המשקלים הם מספר הפריימים בכל מקטע, כלומר מספרים שלמים.

איך אומדים את טיב הסרטון?

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

Recall = TP/(TP+FN)

 וב-

Precision = TP/(TP+FP)

כאשר TP=True Positive זה כשהאלגוריתם חזה שהקטע מעניין וצדק

ו FN=False Negative זה כשהאלגוריתם חזה שהקטע לא מעניין וטעה

ו FP=False Positive זה כשהאלגוריתם חזה שהקטע מעניין וטעה.

תודה ל https://en.wikipedia.org/wiki/F1_score#/media/File:Precisionrecall.svg

 מדד  F-score  מוגדר באופן הבא:

סיכום

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

  1. מייצגים כל פריים על ידי וקטור פיצ’רים, באמצעות רשת קונבולוציה.
  2. מחלקים את הוידאו לסצנות באמצעות אלגוריתם למציאת נק’ שינוי המקבל כקלט את וקטורי הפיצ’רים של הפריימים
  3. מורידים את ה-(fps (frame per second של הסרטון
  4. מכניסים את וקטורי הפיצ’רים לרשת מבוססת RNN שמחזירה את החשיבות של כל פריים.
  5. משתמשים בתכנון דינאמי לבעיית תרמיל הגב בשביל לבחור אילו מקטעים להכניס לסרט המקוצר בהתאם להגבלת אורך שהגדרנו.

הפוסט מבוסס ברובו על האלגוריתם המוצע במאמר Summarizing Videos with Attention שמבצע למידה מונחית (supervised)

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

קישורים

Posted by Ayelet Sapirshtein in deep

Dataloop – המזון של תעשיית ה AI

המרואיין: ערן שלמה (CEO)

כמה אנשי פיתוח ? איך מחולקים ?

שמונה אנשי פיתוח, מחולקים לשני Front End לארבע Back End  לאחד  SDKואלגוריתמאי. ונשמח לשמוע מאנשי FrontEnd ואלגוריתמיקה.

רקע

אנחנו בונים AI שעוזר לייצר את המזון או האנרגיה לתעשיית ה AI (שהוא הרי Data מתוייג).

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

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

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

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

אנחנו מקבלים מחברות שמתעסקות ב Computer Vision מאגרי תמונות ומספקת Training Sets (ז”א תמונות מתוייגות) ואם צריך גם מודלים מאומנים.

 

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

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

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

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

מהם המוצרים בחברה ?

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

המערכת שלנו מכילה דאטאבייסים עם המון מטה-דאטא. ז”א לא רק את התמונות והתיוגים אלא גם נתונים על עבודת התיוג לכל תמונה. (משך התעכבות, תנועות עכבר, וכו…)

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

 

אילו חלקים במוצר מצריכים אלגוריתמיקה ?

אנו חברה שלא רק מנהלת את תהליך התיוג של ה Data בפלטפורמת תוכנה נוחה אלא גם אנו מאמנים מודלים משלנו שיעזרו בניהול תהליך התיוג:

מודל שיחזה טעויות תיוג

לרוב לצוותים הללו יש איש  QA שעובר מדגמית (ביחס של 1:10) והוא יקר יותר.אנחנו מאמנים מודל להיות QA שמציע ל QA האנושי הצעות שיותר סביר שבעלות טעות ובכך לחסוך את זמן העבודה שלו.

למשל יש עשרת אלפים מלבנים של כלב\חתול שאתה בוטח בהם (כי עליהם עבר האיש QA) ובתשעים אלף אחרים אינך בוטח.אנו מאמנים מסווג לארבע מחלקות:Good/Bad Dog Annotation, Good/Bad Cat Annotation. בכדי לאמן מודל כזה ביעילות אנו עושים אוגמנטציות למשל ע”י הזזה של המלבן מדוגמאות שאתה בטוח לגביהן בכדי לקבל דוגמא של Bad Dog/Cat.

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

מודל שיחזה עלות תיוג

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

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

מודל שייעל את התיוג

 

 

אימון מודלים כדי שיציעו הצעות למתייגים כדי לייעל את התהליך. למשל אולי המודל כבר מצליח 80% במשימתו אז נשתמש בו וזה יחסוך זמן תיוג.

מה עובד לכם טוב ?

גילינו דבר מעניין:

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

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

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

מה מאתגר אתכם ?

יצרת שפה משותפת בין בני אדם למכונות שתמנע המון קשיי תקשורת

בעיות שפתרתם בדרך יצירתית ?

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

מהם אתגרי העתיד ?

בעתיד נאפשר ללקוחות לבנות Pipelnes של מודלים שלנו או של הלקוח שיכולים לעשות את החישו

בים אצלנו וכך הלקוח לא יצטרך לנהל שרתים.

Posted by תמיר נווה in companies

ניהול צי של רחפני צילום – vHive

המרואיין: תומר דניאל (CTO)

כמה אנשי פיתוח ? איך מחולקים ?

אנחנו סטארט אפ קטן וצומח, כרגע כל הפיתוח מונה 7 מהנדסים, מהם שניים עוסקים באלגוריתמים והשאר מפתחים מנוסים בתחומם – Back End, מובייל ו-Web. אנחנו עובדים במתודולוגית Agile בספרינטים מוכווני לקוח ומחשבה רבה על איכות.

מהם המוצרים בחברה ?

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

אילו חלקים במוצר מצריכים אלגוריתמיקה ?

המוצר שלנו עתיר באלגוריתמיקה; אנחנו מפתחים אלגוריתמים גיאומטרים לתכנון והטסה של סקרי צילום אווירי מרובי רחפנים, תוך שימוש באלגוריתמי אופטימיזציה למציאת פתרון אופטימלי במהירות תחת מספר רב של אילוצים  ממספר גדול של קונפיגורציות על בסיס constraint based programming וב mixed integer programming בו האתגר הוא התכנסות מהירה.

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

מה עובד לכם טוב ? (דוגמאות לאלגוריתמים)

לדוגמא, לצורך יצירת מודל תלת מימדי מדויק נדרש לעגן את התמונות במרחב בדיוק גבוה. לשם כך מניחים בשטח אובייקטים הנקראים Ground Control Points שהמיקום שלהם ידוע ברמת דיוק גבוהה. בתהליך יצירת המודל התלת מימדי נדרש לסמן את האובייקטים בתמונות. בנינו אלגוריתם מבוסס DL, שמזהה את האובייקטים בתמונות (מבוסס על Faster R-CNN) ומאפשר לחסוך מהמשתמש שעות רבות של תיוג התמונות ולקבל מודל תלת מימדי איכותי.

מה מאתגר אתכם ?

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

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

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

בעיות שפתרתם בדרך יצירתית ?

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

ספר על משימת איסוף ה DB אצלכם ? (מי עושה ? מי בודק ? מי מתייג ? מי מנהל ?)

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

מהם אתגרי העתיד ?

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

Posted by תמיר נווה in companies

רשתות סיאמיות – להצליח איפה שדיפ לרנינג נכשל – חלק א

מיועד ל- מתחילים (כתבה קצת טכנית)

נכתב על ידי thebeancounter

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

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

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

מה עושים כשאין מספיק DATA ?

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

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

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

רשתות סיאמיות

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

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

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

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

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

דוגמית קוד

להלן דוגמה ממומשת מעל tf.keras

המימוש פשוט, וכמו כל מימוש פשוט של רעיון מחקרי מורכב – הוא לא עובד טוב (שאף אחד לא יספר לכם אחרת) מדובר ברשת פשוטה, המקבלת שתי דוגמאות MNIST בתור קלט

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

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

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

כנסו לריפו הזה כדי לראות את כל הקוד של המאמר.

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

 

 

 

 

 

 

Posted by thebeancounter in deep

TensorFlow 2 –מה נשתנה ?

מיועד ל- מתחילים (כתבה קצת טכנית)

נכתב על ידי Moti Gadian

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

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

לפי האתר הרשמי של גוגל (tensorflow.org) פורסם שבגרסה החדשה, גוגל שמה לה למטרה מספר דברים מרכזיים:

  • להקל על המתכנתים את החיים
  • להפוך את צורת הכתיבה ליותר “פייתונית” (פחות להתעסק עם גרף האופרציות)
  • להוסיף יותר תמיכה ב High Level .
  • להוסיף ולשפר כלים למחקר
  • לעשות סדר בכל תתי הספריות והמודולים הרשמיים וגם באלו של הקהילה (Contrib)
  • תמיכה חזקה בכל מה שקשור לפרודקשיין בכל פלטפורמה.

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

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

tensorflow models

https://medium.com/tensorflow/whats-coming-in-tensorflow-2-0-d3663832e9b8

לפי האתר הרשמי של גוגל חלוקת המודולים תהיה ברורה מאוד:

  1. מודולים וספריות של אימון
  2. מודולים וספריות של פרודקשיין (או גם “פריסת המודל” ושימושו בפועל באפליקציות )

מודלים שהיו מחוץ לסקופ הנ”ל או שהיו בקטגוריה משלהם- יצורפו לאחת משתי הקטגוריות. כמו כן מודולים לא רשמיים שכבר “התנפחו” ויצאו מכלל שליטה יפסיקו להיות נתמכים רשמית ע”י גוגל, מודולים לא רשמיים שנהיו פופולריים מאוד יאוחדו רשמית עם Tensorflow.

מה עם קצת קוד ??

אז לחלק שמעניין את כולנו – קוד.

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

גוגל הפכה רשמית את מצב ברירת המחדל שלה ל Eager מאשר Graph – עד עכשיו כדי להגדיר מודל היינו צריכים להגדיר את האופרציות, המשתנים, והקבועים שלנו מראש ואז להריץ פעולות ע”י שימוש ב Session. אם היינו רוצים להריץ פעולות ישירות ללא הידור מקדים של הגרף היינו צריכים להפעיל מצב מיוחד ע”י הפקודה tf.enable_eager_execution  , כעת מצב זה הינו מצב ברירת המחדל, מצב זה בעצם מאפשר לכתוב פעולות בקונוטציה של פונקציות בפייתון ולהריץ אותם ישירות.

(ניתן לקרוא הכל בפרוטרוט בבלוג הרשמי באנגלית כאן)

Tensorflow בגרסה החדשה דוחפת יותר לכיוון של שימוש בספריית המעטפת Keras ע”י הוספת תמיכה בשלושה סוגי קונסטרוקציות:

  • Sequential Model– בנייה של מודל בצורה סדרתית שכבה על שכבה.

Sequential Model

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

Functional API

  • Model Subclassing– מצב זה הינו די חדש לגרסה 2.0 בו בעצם ניתן “לדרוס” (או לבצע ירושה לחובבי ה OOP) את מבנה המודל הכללי של Keras אך לשמור על ההתנהגות שלנו וכך בעצם ליצור מודלים הרבה יותר מורכבים אשר יכולים להכיל כל מיני אופרציות סף שלTensorflow עצמה.

Model Subclassing

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

חידושים בתחום הProduction

  • Distribution Strategiesאסטרטגיות ותצורות הפצה מובנות מראש של אופרציות באימון מפוצל (אימון שמתחלק בין כמה וכמה מחשבים או כרטיסי GPU) ללא צורך בשינוי הקוד או התאמתו לאימון מרובה.
  • Tensorflow Serving מודול המאפשר “הגשה” של רשתות (מודלים) בכל סביבה שהיא (שרת או ענן) לצורך ביצוע קריאות אל המודל וקבלת תשובה ללא התעסקות עם קונפיגורציות מסובכות.
  • Tensorflow Lite מודול המאפשר הגשה של רשתות על מכשירים דלי כוח חישובי כגון סמארטפונים, מכשירי ,IOTוכדו’.
  • jsמודול המאפשר הגשה של רשתות ע”י דפדפן פשוט בשפת Javascript.

 

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

מקווה שנהניתם… מוזמנים להגיב לשאול שאלות או לבקש בקשות לפוסטים ספציפיים בתגובות 😊

Posted by Moti Gadian in deep

למידה עמוקה על גרפים

מיועד ל- מטיבי לכת (כתבה מאוד טכנית)

נכתב על ידי Ori Cohen

מהם גרפים והיכן הם מופיעים

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

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

תודה ל https://commons.wikimedia.org/wiki/User:R%C3%B6mert

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

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

למידה עקיפה

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

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

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

למידה מתוך מבנה הגרף

למידה מתוך מאפיינים שבנויים ידנית, למרות הצלחתה היחסית, לא יכולה להיות השיטה הטובה ביותר. דוגמה לתהליך מסוג זה אנחנו יכולים לראות בהתפתחות הלמידה העמוקה על תמונות. בעבר הרחוק (בערך עד 2012) מעבר לשימוש ברשתות נוירונים רגילות (Feed-Forward Networks), הדרך היחידה לשפר למידה על תמונות הייתה ע”י שינויים ידניים שנעשו לתמונות, בין אם שינויים לתמונות שהוכנסו ללמידה ובין אם פיצ’רים שחושבו על התמונות והוכנסו לרשתות בנוסף לתמונות עצמן. קפיצת המדרגה הגדולה בלמידה על תמונות הייתה כאשר הכניסו למשחק רשתות שיודעות גם ללמוד את הפיצ’רים האופטימליים עבור הנתונים, רשתות שכיום ידועות בשם רשתות קונבולוציה.

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

https://arxiv.org/pdf/1311.2901.pdf

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

מטריצת השכנויות של גרף הינה מטריצה בה אם ישנה קשת בין קודקודים  ו- אז בשורה ה- בעמודה ה- נכניס את משקל הקשת ביניהם (או 1 אם הגרף שלנו לא ממושקל).

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

קונבולוציות על גרפים Graph Convolutional Network

בשנת 2017 הוציאו שניים מהמוחות המבריקים ביותר בתחום למידת המכונה על גרפים, תומס קיפף ומקס וולינג, את אחד מהמאמרים בעלי ההשפעה הרחבה ביותר בתחום, Semi-Supervised Classification with Graph Convolutional Networks. במאמר זה הציגו לראשונה השניים את מה שהם כינו “רשתות קונבולוציה על גרפים”, רשתות שיכולות ללמוד תבניות בין קודקודים שונים באופן דומה לקונבולוציות על תמונות. השניים הציעו את המבנה הבא לשכבה אחת ברשת שלהם:

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

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

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

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

תוצאות

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

במאמר, מציגים את רשת בעל שתי שכבות שמצליחה ללמוד את החלוקה שמוצגת בצד ימין מתוך 5% מהתוויות בלבד (על Cora dataset שהינו מאגר נתונים במבנה גרף של מאמרים מדעיים וקשרי ציטוטים ביניהם). למעשה, הרשת הצליחה לזהות קודקודים (ז”א מאמרים מדעיים) דומים והניחה שהם מקבלים סיווג דומה למעט הקודקודים עליהם היה לה מידע.

לקוח מ https://arxiv.org/pdf/1609.02907.pdf

במאמר משווים הכותבים את המאמר שלהם לשש מהשיטות הקיימות לסיווג של קודקודים:

https://arxiv.org/pdf/1609.02907.pdf

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

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

קישורים

 

 

Posted by Ori Cohen in deep

ניווט בתוך הסימפונות – BodyVision

המרואיין: דימה סזגנוב (VP R&D)

רקע

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

כמה אנשי פיתוח ? איך מחולקים ?

שני צוותי פיתוח 5-6 אנשים כל אחד. הצוותים הם feature teams – מאורגנים סביב יכולות במוצר וגם full stack במובן שהצוות מסוגל לסגור feature קצה לקצה, כולל איפיון, אלגורימים, bench tests, אינטגרציה, UI\UX, בדיקות תוכנה. הרכב הצוותים מאוד דינאמי ומשתנה לפעמים כל ספרינט.

מהם המוצרים בחברה ?

לחברה שני מוצרים:

LungVision System – הינה מערכת דימות שמאפשרת ניווט בתוך הראות ע”י הכוונה של רופא לאיזור העניין ומיקום הכלים באופן מדויק. זה נעשה באמצעות fusion  בין תמונות מסוגים שונים בזמן אמת.

LungVision Tool – הינו כלי מכני, או קטטר, שמאפשר גישה פיזית לכל נקודה בתוך הראות.

אילו חלקים במוצר מצריכים אלגוריתמיקה ?

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

משמעות ה Fusion הינה רגיסטרציה (ע”י מציאת פיצ’רים תואמים) בין תמונות ממקורות שונים. (CT,xray,… )

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

מה עובד לכם טוב ?

אנחנו מצליחים לחבר את צוות הפיתוח לשטח ולמשתמשים באופן יום יומי.

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

אחת הבעיות למשל שאנו פותרים כדי לתכנן את הפרוצדורה היא לזהות את נתיבי האוויר שבריאות. אנו עושים סגמנטציה על סריקת ה CT ומשתמשים הן באלגוריתם קלאסי מבוסס Gradient Vector Flow והן בגישות למידה עמוקה כמו U-Net ובפרט בגירסה מתקדמת של U-Net המתאימה למקרה שלנו.

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

מה מאתגר אתכם ?

איזון בין השקעה במחקר (לטווח ארוך) לבין פיתוח (לטווח קצר)

תשתית – זמן אימון, יכולת לדבג, אירגון דאטה, העברת ידע, הדרכת צוות.

בעיות שפתרתם בדרך יצירתית ?

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

ספר על משימת איסוף ה DB אצלכם ? (מי עושה ? מי בודק ? מי מתייג ? מי מנהל ?)

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

מהם אתגרי העתיד ?

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

Scale-up של המוצר והתאמתו לקהל רחב של משתמשים – המוצר צריך להיות אמין ואינטואיטיבי לשימוש.

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

 

Posted by תמיר נווה in companies

איפה יש חניה פנויה ? Parkam

המרואיין: עופר חסון (CTO)

רקע

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

מציאת החניה הפנויה מבוססת על ניתוח בזמן אמת של צילום של הרחובות או החניונים ואופטימיזציה של ניווט מרובה משתמשים.

כמה אנשי פיתוח ? איך מחולקים ?

אנשי הפיתוח בחברה מחולקים לשלוש קבוצות: צוות פיתוח מובייל (אנדרואיד ו-iOS), צוות Datascience, וצוות הליבה (Backend, Server, Frontend).

מהם המוצרים בחברה ?

1) אפליקציית ניווט לציבור הרחב.

2) ממשק בקרה לבעלי חניונים/עיריות.

3) API לאינטגרציה עבור לקוחות שכבר יש להם מערכת בקרה קיימת.

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

אילו חלקים במוצר מצריכים אלגוריתמיקה ?

חלק ראשון: עיבוד התמונה (Deep Learning) למטרת זיהוי חניה תפוסה/פנויה.

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

פיתחנו ארכיטקטורות Light Weight משלנו מבוססות Shufflenet בשילוב עם Squeeze-and-Excitation Networks.

כמו כן, אנו עוסקים בהבנת סצינה באמצעות  Semantic Segmentation ו- Object Detection כדי לעזור למיפוי להיות יותר אוטומטי.

חלק שני:הניווט

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

מה עובד לכם טוב ?

בהקשר של הצד ההנדסי, העבודה ב -Scale, הניהול של ה- Data והתיוג, בנינו  Pipelines אוטומטיים שעובדים יפה.

פיתחנו כלים שמאפשרים לכל צוות לעבוד בצורה עצמאית כולל Pipeline מלא עד העלאה ל Production, דבר זה גם מייעל את העבודה וגם נותן תחושת אחריות לצוותים.

הרשת שפיתחנו נותנת תוצאות מדהימות!

מה מאתגר אתכם ?

קשיים של העולם האמיתי: מצלמות מתלכלכות, זזות וכו’.

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

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

בעיות שפתרתם בדרך יצירתית ?

לבעיית זיהוי הרכב: האם זה אותו רכב או לא ? לקחנו אלגוריתם מתחום ה- Audio של זיהוי דוברים והשמשנו אותו לבעיה שלנו וזה עובד לנו טוב!

ספר על משימת איסוף ה-DBאצלכם ? (מי עושה ? מי בודק ? מי מתייג ? מי מנהל ?)

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

כשהם מסיימים זה עובר אוטומטית לצוות ה-Datascience שלנו לואלידציה.

ה-Flow שפיתחנו הוא אוטומטי ועובד ביעילות.

מהם אתגרי העתיד ?

עולם החניה מעלה הרבה דרישות, חלקן מורכבות וחלקן מיידיות עבורנו.

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

מודל DeViSE – משלב הבנת שפה עם הבנת תמונה

מיועד ל- מתחילים (כתבה קצת טכנית)

נכתב על ידי Nadavpo

כשהתחלתי להיכנס לעולם הלמידה העמוקה, טיפסתי באותם השלבים שאני מאמין שרובנו טיפסנו בהם (ואם לא, אני ממליץ בחום על הספר האלקטרוני החינמי של Michael Nielsen בתור התחלה): רשת עם שכבת FC נסתרת אחת, רשת עמוקה, היפר פרמטרים, שכבות קונבולוציה, AlexNet,  VGG, Inception וכו’.

גם אני נשבתי בקסם רשתות הנוירונים – היכולת להגיע לביצועים מרהיבים באמצעות מספר שורות קוד (ומספר גדול יותר של שעות אימון וקינפוג, אבל ניחא), היו מדע בדיוני בעיניי. עם זאת, יש דבר שמציק לי לאורך כל הדרך והוא ההבנה בכל פעם מחדש שרשתות לא באמת מבינות מה הן עושות. עכשיו תגידו “בוקר טוב, אלה בסך הכל תוכנות מחשב, למה שיבינו משהו?”. אני יודע אני יודע, אך עם זאת כולנו מכירים את התיאוריה והרעיון שבבסיס רשתות הנוירונים והוא שהן כביכול מחקות את פעולת המוח, ואם זה אכן כך אז איך הן יכולות לעשות לנו כאלה בושות? לעיתים נראה שאין כל קשר בין מה שאנו מצפים מהרשת (ה-ground truth) לבין מה שהרשת ביצעה בפועל. אז נכון, לפעמים אני גם לא מבין את הקשר של מעשים מסוימים של בני אדם לבין המציאות ומבחינה זאת הרשתות האלו דווקא בסדר גמור, אבל לא על זה אני  מדבר. 

תיאור מילולי של קטגורית התמונות

לצורך הסקופ הזה אני רוצה להתעניין בשאלה איך ניתן לגרום לרשת לסווג קטגוריות שאליהן היא לא נחשפה מעולם או נחשפה רק פעם אחת (zero\one shot detection למתעניינים) על ידי תיאור מילולי בלבד של הקטגוריות? או איך ניתן לגרום לרשת לכך שגם כאשר היא תטעה בסיווג של תמונה, התוצאה תהיה בעלת קשר סמנטי לאמת?

מענה הגון לשאלות אלה יקרב אותנו קצת יותר לחיקוי של דרך החשיבה האנושית.

בארכיטקטורות המוכרות, אלה הכוללות שכבות קונבולוציה, pooling layers ולבסוף שכבת softmax קשה לגרום לרשת להצליח במשימות האלו. בכל תהליך האימון הרשתות מקבלות פידבק של כמה הן רחוקות מהאמת האחת והיחידה (ה-one hot encoding), אין כל דרך להבין קשר בין קטגוריות שונות. במילים אחרות, המימד של תגיות התמונות (ה-labels) מורכב מוקטורים אורתוגונליים חסרי כל קשר אחד עם השני ולכן לא ניתן להעריך כמה חמור דומה לסוס למשל. דוגמה נוספת היא מקרה שבו המאגר שעליו התאמנה הרשת לא מכיל תמונות של זברות אך בזמן שימוש ברשת, לאחר גמר האימון, נרצה לנסות לסווג תמונות של זברות. ב-VGG למשל זה לא יהיה אפשרי.

רשתות המבוססות על embedding vectors פותרות בדיוק בעיות כאלו. לצורך העניין נתמקד במאמר המציג רשת בשם DeVise.

רשת זו בנויה משתי רשתות נפרדות. הרשת הראשונה מבצעת את תהליך ה-word2vec ומאומנת על מסד נתונים טקסטואלי גדול ככל האפשר (ויקיפדיה במקרה שלנו), ואילו החלק השני יהיה CNN להוצאת מידע חזותי מהתמונה כאשר שכבת ה-softmax הוסרה ממנו, מעין transfer learning, במקרה שלנו רשת ה-CNN הינה ה-AlexNet (בכל זאת מאמר מ-2013).

המחשת מבנה הרשת. בצד שמאל רשת CNN, בצד ימין מודל skip-gram ובאמצע שילוב של שניהם כפי שמתבצע בתהליך האימון. (לקוח מ DeViSE: A Deep Visual-Semantic Embedding Model)

מה הקשר בין word2vec לבין AlexNet אתם שואלים?

פה טמון הסוד. בשלב האימון תג (label) התמונה נכנס לתוך רשת ה-word2vec ומקודד לוקטור במימד 500 או 1000 שאותו ניתן למקם כנקודה במרחב רב ממדי, וכעת נקבל שתגים מאותה הקטגוריה ימוקמו סמוכים האחד לשני (בנוסף נקבל גם קשרים דומים בין תגים עם אותו הקשר – למשל וקטור המחבר בין כלב לכלבלב יהיה דומה מאד לזה המחבר בין חתול וחתלתול – אבל זה נושא לפוסט אחר). במקביל, התמונה עצמה נכנסת ל-CNN כאשר במוצא ה-CNN ישנו וקטור באותו המימד של ה-word2vec. את שני המוצאים האלו מכניסים לפונקציית המחיר (זכרו שכעת התג מיוצג על ידי 500, או 1000, מספרים ולא רק על ידי אחד והמון אפסים כמו ב-one hot encoding) המשלבת אבחנה בין כמה קרוב היה הוקטור במוצא ה-CNN לוקטור לוקטור המתאים לתג התמונה ובנוסף אבחנה כמה רחוק היה הוקטור במוצא ה-CNN משאר הוקטורים שנלמדו במודל ה-skip-gram. בשלב ה-test נכנסת תמונה לרשת והתיוג יהיה זה בעל ה-embedding vector (הוקטור מה-word2vec) הקרוב ביותר לזה שיצא מרשת ה-CNN. שיטה זאת מאפשרת לנו לנצל את המידע הסמנטי מהמרחב הטקסטואלי לשימוש במרחב החזותי על ידי כך שאנו מלמדים את רשת ה-CNN לספק וקטורים קרובים מבחינה מרחבית לתמונות בעלות תיוג עם קשר סמנטי. בכך גם כאשר הרשת שלנו תשגה בתיוג התמונה, ישנו סיכוי גבוה לכך שלטעות יהיה קשר סמנטי לאובייקט שבתמונה.

דוגמה למרחב טקסטואלי על פי קטגוריות שנוצר בארכיטקטורת skip-gram ובו ניתן לראות מקבצים של דוגמאות אימון על פי קטגוריה (לקוח מ DeViSE: A Deep Visual-Semantic Embedding Model)

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

תוצאות הרשת היו קרובות לאלו שהושגו עם ה-CNN בלבד, אך ככל שבוחנים יותר תיוגים עבור כל תמונת מבחן (משמע, לא בודקים האם הרשת צדקה רק על ידי בדיקת התג שהיה הכי קרוב לוקטור שהופק בזמן המבחן, אלא בודקים את ה-2,3 ואפילו 20 הוקטורים הקרובים ביותר) רשת ה-DeVise השיגה תוצאות קצת יותר טובות מה-CNN המקורית. אומנם לא נראה שיפור בתוצאות אך לפחות לעניות דעתי הכיוון שהוצג במאמר בהחלט מקרב אותנו עוד קצת לכיוון של רשתות ש”מבינות”  קצת יותר את העולם הויזואלי שסביבן.

Posted by Nadavpo in deep

ניתוח תלת מימד של CT לצורך ניבוי סרטן ריאות

מיועד ל- מתחילים (כתבה קצת טכנית)

נכתב על ידי תמיר נווה

בכתבה זו אספר על בעיית עיבוד סריקות CT (שהינן תמונות תלת מימדיות) ובפרט אספר על תחרות ה-Kaggle לזיהוי סרטן ריאות: Data Sciense Bowl 2017 ועל הפתרונות המנצחים בתחרות זו מתוך ה-1972 צוותים שהשתתפו בתחרות.

האלגוריתם שזכה מקום ראשון (של צוות grt123 בתוצאה של loss=0.39975) נמצא כאן וכמובן הוציאו על זה מאמר.

תיאור הבעיה

מאגר הנתונים הנתון באתגר הינו מעל אלף Dicoms (סטנדרט של תמונות\סרטונים רפואיים) של סריקות CT תלת מימדיות של חלל החזה של אנשים בסיכון גבוה לסרטן ריאה.

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

בעיה מסוג זה מקוטלגת כ- MultipleInstance Learning, שהינה אופיינית לעולם המדיקל ונחשבת קשה. זו בעיה בה יש כמה מופעים שונים של ארוע\אוביקט כלשהוא (הגושים במקרה שלנו) וכל אחד מהם לבדו לא בהכרח מעיד על פרדיקציה חיובית. ז”א מדובר בחיזוי תופעה שיכולה להתקיים בכמה אופנים שונים.

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

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

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

אז בואו קצת נבין איך זה נראה. מראה הגושים יכול להיות מאוד שונה ממקרה למקרה:

לקוח מ Evaluate the Malignancy of Pulmonary Nodules Using the 3D Deep Leaky Noisy-or Network

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

סריקת ה-CT מכילה הרבה יותר מידע מתמונת חתך בודדת כפי שניתן לראות בסרטון הבא של תמונת CT תלת מימדית: (למעשה מנפישים אותה כתלות בכל אחד משלושה צירים)

על ה-DB

המידע שיש ב Dicom הינו צילום תלת מימדי וניתן להתייחס ולהציג אותו בעצם כמו סרטון שחור לבן (המיוצג ע”י מטריצה תלת מימדית או בהכללה טנזור). כאשר ציר הזמן הוא אחד מצירי העומק של סריקת ה-CT.

כל מכונת סריקה מייצרת סריקה בקצב דגימה שונה בציר העומק ולכן המרווח בין זוג תמונות חתך עוקבות (slice thickness) הוא שונה. וזו תופעה איתה יש להתמודד (בשלב העיבוד המקדים Pre-Processing).

הגושים (Nodules) אותם יש לחפש הינם בגודל טיפוסי של 1x1x1 סמ”ר  בעוד סריקת CT ממוצעת הינה בגודל 30x30x40 סמ”ר ולכן מדובר בחיפוש מחט בערימת שחת. אם נשווה לעולם היותר מוכר (לי) של דו מימד, זה כמו לחפש אוביקט בעל שטח של בערך 30 פיקסלים (ז”א בערך 5×5 פיקסלים) בתמונה בגודל 1000×1000. התיוג של ה DB מבוסס על שקלול אבחנות של כמה רופאים.

הרחבת DB תלת מימדי (Augmentation)

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

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

תמונה דו מימדית ניתן לסובב ארבע פעמים בתשעים מעלות, ולעשות אותו הדבר עם תמונת המראה שלה, ובכך להכפיל פי שמונה את ה-DB מבלי להיכנס לסיבוכים כמו הרעשה, הוספת תאורה, סיבוב בזוויות לא ישרות וכו’… לתמונות תלת מימדיות ניתן להפעיל את אותו העקרון ולהרחיב את המאגר פי 48.

אם יש בקוביה גוש, גם יהיה גוש בכל אחת מה 48 סיבובים\היפוכים שלה:

תודה ל Дейка2

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

על הפתרון שזכה במקום הראשון

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

עיבוד מקדים (Pre-Processing)

לפני השלב הראשון יש כמו תמיד עיבוד מקדים שמטרתו לייצר אחידות בין הסריקות ולהסיר את כל מה שמחוץ לריאות. העיבוד המקדים כולל המרת התמונות ל- (Hounsfield Scale=HU) שהינו נירמול רמות הצבע כמקובל בסריקות CT, המרה לתמונה בינארית (לפי סף) ומחיקת כל מה שאינו בתוך ה- Connected Component  העיקרי בתמונה (שהינו הריאות). כמו כן פעולות מורפולוגיות בכדי ליצור מסיכה (mask) שבעזרתה ניקח מהתמונה המקורית רק את אזור הריאות.

שלב ראשון – גילוי מועמדים

השלב הראשון ממומש באמצעות מה שהכותבים מכנים N-Net = Nodule Net שהינה רשת 3D RPN מבוססת U-Net אשר מחזירה מלבנים (Bounding Boxes) סביב הגושים עם סף גילוי נמוך כדי לקבל כמה שיותר מועמדים גם אם אינם משמעותיים להחלטה הסופית. רשת זו מאמנים עם הרבה אוגמנטציות (Augmentation) של היפוכים (Flips), סיבובים, שינויי גודל והזזות קטנות. אגב, על רשת ה U-Net ניתן לקרוא בבלוג זה כאן.

בשלב השני לוקחים את חמשת הגושים החשודים ביותר שאותרו בשלב הראשון ובאמצעות אלגוריתםLeaky noisy-or model (יוסבר בהמשך) מחשבים פרדיקציה לקיום המחלה. אלגוריתם זה מניח שיש “זליגה” קלה של הסתברות לקיום האירוע (המחלה) גם אם אין אף תופעה (גוש) המרמז על כך.

חפיפה בין המודלים

לכל אחד מהשלבים (הראשון והשני) יש מודל אחר. האחד מחזיר מלבנים והשני מסווג קיום או אי קיום סרטן (Detection & Classification) והאימון מתבצע לסירוגין בין שני המודלים (Epoch לזה ו Epoch לזה) כאשר עיקר המשקולות של שתי המודלים משותפים. שיטה זו עוזרת למנוע Overfitting (שהרי מקטינה את כמות המשקלים לאימון).

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

לקוח מ Evaluate the Malignancy of Pulmonary Nodules Using the 3D Deep Leaky Noisy-or Network

חלק עליון בתרשים (a):

לוקחים את החלק המרכזי (Crop בגודל 96x96x96) מתמונת הגוש (הקוביה) שיצא מהשלב הראשון מזינים אותו לרשת ה N-Net (המודל הראשון) ולוקחים את השכבת הקונבולוציה האחרונה שלו כפיצ’ר בגודל 24x24x24x128 ממנו לוקחים רק את המרכז בגודל 2x2x2x128 עושים עליו max-pooling ונשארים עם פיצ’ר וקטור בגודל 128 לכל גוש מועמד.

חלק תחתון בתרשים (b):

ומשם עוד Fully-connected, Max-pooling, Sigmoid activation בכדי להגיע לפרדיקציה הסופית (המשקללת את המידע מחמשת הפיצ’רים של הגושים העיקריים).

שלב שני – שיקלול הנתונים של כל גוש (Leaky Noisy-or Method)

השיקלול יכול להיות Max Pooling אבל אז אין קשר בין המידע של כל גוש. כי הרי סריקה עם שני גושים שמנבאים סרטן ב 50% תביא לתוצאה סופית של 50% (המקסימום בין 50 ל 50 הוא 50) אבל סביר שרופא שינתח סריקה כזו יחליט שיש סבירות גבוה מ 50% לסרטן.

שיקלול שכן לוקח בחשבון את סך הפרדיקציות מכל גוש הינו Noisy-Or ההופכי למכפלת ההסתברויות של העדר סרטן: (ההסתברות שהראשון מעיד על סרטן או שהשני או שהשלישי…)

אך מה קורה אם גוש ממאיר ביותר התפספס בגילוי בשלב הראשון ?

לצורך כך משתמשים במודל ה- Leaky Noisy-or method שמניח שייתכן והפרדיקציה חיובית על אף שאף גוש לא ניבא זאת. הפרמטר Pd נלמד גם כן בשלב האימון. (ז”א הוא תלוי תמונה ולא תלוי גוש)

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

באימון המודלים משתמשים בין השאר ב Gradient clipping וב- Batch normalization.

על הפתרון שזכה במקום השני

לאלגוריתם (ולצוות) שלקח את המקום השני בתחרות יש שתי כתבות מפורטות של כל אחד מהמפתחים  Daniel Hammackו Julian de Wit.

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

גם פה נעשה עיבוד מקדים שמייצר אחידות בין הסריקות. לכל סריקה לעשות Rescale כך שכל Voxel  (פיקסל תלת מימדי) שלה ייצג גודל של 1mmx1mmx1mm. (גודל זה נקבע באמצעות ניסוי וטעייה כפשרה בין דיוק תוצאות לזמני חישוב)

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

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

מה שהם עשו זה השתמשו במאגר נתונים המקורי שממנו נגזר המאגר של התחרות שנקרא LIDC-IDRI שמכיל בנוסף לסריקות ולגושים אותם איבחנו רופאים, גם מאפיינים אותם איבחנו הרופאים לכל גוש. למשל גודל, מידת הממאירות, חיספוס וכו’… מידע זה שהוסר מהמאגר שבתחרות היווה נקודת מפתח להצלחה.

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

לקוח מ 2nd place solution for the 2017 national datascience bowl

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

טכניקת אימון אותה שווה להזכיר בה הם השתמשו נקראת Curriculum Learning. הרעיון הוא קודם לאמן דגימות קטנות ופשוטות ואז לאמן עם הדוגמאות הקשות. גישה זו אינטואיטיבית לנו הלומדים האנושיים כי תמיד הורגלנו ללמוד את הפשוט (כיתה א’) ואז כשזה מוטמע במוחנו, ללמוד את הנושאים היותר מסובכים (כיתה ב’ וכו’…). לפי התיאור שלהם הם קודם אימנו עם קוביות בגודל 32x32x32 ואז אימנו עם קוביות בגודל 64x64x64.

קישורים

  1. למי שמחפש מאגרי נתונים ובעיות בתחום הרפואי חייבים להכיר את: Grand-Challenges
  2. LUNA16  הינה תחרות לזיהוי גושים (Nodules) בכמעט אלף תמונות CT
  3. מאגר LIDC-IDRI בתחום סרטן הריאות
  4. MicroDicom – כלי חינמי מומלץ לראות Dicoms

Posted by תמיר נווה in deep

למידת מכונה? לא לגאונים בלבד

מיועד ל- מתחילים (כתבה קצת טכנית)

נכתב על ידי Moti Gadian

תמיד חלמת ללמוד Machine Learning  או  Deep Learning  אבל נבהלת מכל הנוסחאות? , חיפשת דוגמאות קוד והתבלבלת מכל המושגים הטכניים? חושב שהנושא של למידת מכונה מיועד רק למתמטיקאים או מדענים? זה בדיוק המאמר בשבילך!

תחום ה Deep Learning צבר תאוצה בשנים האחרונות, וכולם רוצים לקחת חלק בטכנולוגיה הזו.

היום כאשר הנושא נכנס לתודעה ורואים את מיטב החברות הגדולות ( Google , Facebook ועוד) מפתחות ספריות או  Frameworks בינה מלאכותית  – כמעט כל מפתח יכול להתחיל לבנות מודל בסיסי בכמה שורות קוד פשוטות.

במאמר זה נתייחס לספרייה Keras (למרות שהיא יותר קרובה להיות Framework) שהינה ספרייה עילית לבניית מודלי בינה מלאכותית או בשמם המדעי Neural Networks .

ככלל, הFlow  של תהליך Deep Learning מורכב מ-3 חלקים עיקריים:

  1. הכנת המידע   (Data)
  2. הגדרת מודל
  3. בניית המודל
  4. אימון של המודל – הזנת
  5. המידע אליו והפעלת האלגוריתמים
  6. חיזוי (Prediction)  – שימוש במודל ובחינה שלו

לאחר שהתהליך הושלם והשגנו אחוז גבוה של דיוק (ההסתברות שהמודל שלנו יחזיר תשובות נכונות),

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

מוכנים? אז בואו נתחיל!

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

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

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

המבנה הפשוט של רשת נוירונים מורכב מ-3 חלקים (שכבות) :

  • קלט
  • שכבות ביניים (hidden) עליהם מבוצעים החישובים
  • פלט

די עם ההקדמות תן לכתוב קוד!

את הקוד שלנו אנחנו נכתוב ב Python שהיא השפה הכי פופולארית לכתיבת מודלים.

שלב ראשון – התקנת הספריות:

פתחו את הטרמינל (שורת הפקודה) והקלידו את הפקודה הבאה

Pip install tensorflow

חכו כמה דק’ עד שהספרייה תתוקן.

(אנחנו בעצם מתקינים את הספריהTensorflow  מבית Google אולם Keras  כבר כלול בה כשכבת אבסטרקציה)

שלב 2  –  הכנת ה Data

אנו נעזר ב data שכבר הוכן ונוקה עבורנו לצורכי למידה באדיבות  Keras אנו נשתמש בDataset שנקרא Mnist, זה בעצם אוסף של תמונות שחור לבן המכילות ספרות בכתב יד.

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

שימו לב שחילקנו את הdata  שלנו שלני חלקים:

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

שלב 3 – בניית המודל , קונפיגורציה והזנת המידע (אימון)

שלב 4  – מדידת ביצועים

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

בסוף הריצה אנו אמורים לקבל משהו דומה לזה:

evaluation result: loss(0.10702921551428735) | accuracy(0.9663)

זהוו !! – כל הכבוד בניתם את המודל הראשון שלכם.

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

Posted by Moti Gadian in deep

טנזורים או נקודות במרחב ? סקירת מאמרים על ענני נקודות בלמידה עמוקה

מיועד ל- מתחילים (כתבה קצת טכנית)

נכתב על ידי Yizhak Ben-Shabat

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

הקדמה

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

  • רשתות קונבולוציה
  • נתונים – מאגרי תמונות עצומים הפכו לזמינים ופתוחים לכולם.
  • כוח חישוב

הזמינות של מידע תלת מימדי מתחילה לגדול בקצב מסחרר. בין אם מדובר בחלקי תיב”ם (CAD תכנון וייצור באמצעות מחשב) שתוכננו על ידי אדם או על מידע שנסרק על ידי חיישן LiDAR או מצלמת עומק (RGBD) – ענני נקודות נמצאים בכל מקום !

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

אתגרים

מסתבר שהמעבר לא כל כך פשוט. אחלק את האתגרים לשני סוגים עיקריים : אתגרים “חדשים” שקשורים לתהליך הלמידה ואתגרים ” ישנים” שקשורים לאופי המידע השונה.

אתגרי רשתות הנוירונים:

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

אתגרי אופי הנתונים:

  • מידע חסר: העצמים הסרוקים בדרך כלל מוסתרים בחלקם ולכן חלק מהמידע חסר
  • רעש: כל החיישנים רועשים. יש מספר סוגים של רעש הכוללים פרטורבציות (לכל נקודה סרוקה יש הסתברות מסויימת להמצא סביב הנקודה האמיתית בתוך ספרה בעלת רדיוס בגודל מסויים) ונקודות חריגות outliers (נקודה המופיעה במיקום אקראי במרחב).
  • סיבובים: לאותו האוביקט יהיה ענן נקודות שונה אם הוא באוריינטציה שונה אפילו אם נסרקו בו אותם הנקודות, למשל ענני נקודות של מכונית שפונה ימינה או שמאלה.
  • ההרחבה ה”מיידית” להפעלת למידה עמוקה על ענני נקודות היא להעביר את הענן לייצוג נפחי (ווקסלים), ז”א איפה שאין דגימה שמים אפס ואיפה שיש דגימה שמים אחד. כך, נוכל לאמן רשת קונבולוציה עם פילטרים תלת מימדיים ולהימנע מכל האתגרים שקשורים לרשתות נוירונים על ענני נקודות (סריג הווקסלים פותר את בעיית המידע הלא סדור, ההמרה לווקסלים פותרת את בעיית הפרמוטציות ומספר הווקסלים קבוע ומוגדר מראש). אולם, לגישה זו יש חסרונות משמעותיים. ייצוג נפחי הופך להיות גדול מאד, מהר מאד. למשל, עבור תמונה אופיינית בגודל 256×256= 65536 פיקסלים נוסיף את מימד הנפח ונקבל 256X256X256=16777216 ווקסלים. זה הרבה מאד מידע (אפילו לכרטיסים גראפיים חדשים שכמות הזיכרון בהם גדל מאד בשנים האחרונות). מלבד גודל הזיכרון לאחסון, המשמעות של נתונים רבים כל כך היא זמן עיבוד איטי מאד. לכן, בהרבה מקרים “מתפשרים” ולוקחים רזולוציה נפחית נמוכה יותר (בחלק מהשיטות 64X64X64) שעולה לנו במחיר של שגיאת קוואנטיזציה.

אזזזזזזזזזזזזזזזזזזז, הפיתרון הרצוי לעיבוד ענני נקודות באמצעות למידה עמוקה צריך לעבוד בצורה ישירה על הנקודות.

הדטסט

כמו בכל בעיה בתחום הראייה הממוחשבת, אם ברצוננו להוכיח ששיטה עובדת, צריך להראות את זה על אמות מידה (Benchmark) מקובל בתחום.

אני אתמקד ב ModelNet40 מבית היוצר של פרינסטון. הוא מכיל 12311 מודלי תיבם עם 40 קטגוריות של אובייקטים (מטוסים, שולחנות, צמחים וכ’) ומיוצג על ידי רשתות משולשים Triangle mesh (קירוב של משטח חלק על ידי אוסף של מישורים הנפוץ בעולם הגראפיקה). מחלקים את הסט ל9843 מודלים לאימון ו 0135 לבדיקה. ביצעתי קצת ויזואליזציות של הדטסט עם קוד הגיטהאב שפותח עבור שיטת PointNet (תודה לצ’ארלס)

קטגוריות מדטסט ModelNet40

סקר ספרות

בפוסט הזה אסקור 3 שיטות שמבצעות למידה ישירות על ענני נקודות.

אבל שניה לפני זה אני רוצה להראות גרף עמודות המסכם מספר שיטות עדכניות (נכון לתחילת 2018) ובאיזה סוג נתונים כל אחת משתמשת. אפשר לראות שב-2015 רוב השיטות עבדו על תמונות דו מימדיות של אובייקט תלת מימדי שצולמו ממספר נקודות מבט שונות (Multi-View), ב-2016 מספר גדול יותר של שיטות השתמשו בייצוג נפחי עם PointNet החלוצה שהתחילה לעבוד על ענני נקודות ושב-2017 חלה עליה בשיטות המנסות לעבוד ישירות על ענני נקודות.

פרסומים אחרים לסיווג תלת מימדי (דיוק, שנה וסוג הנתונים)

PointNet – CVPR 2017

המאמר פורסם ב arXiv בסוף 2016 ומיד משך תשומת לב רבה. הגישה לפיתרון פשוטה מאד והם הציגו הסברים תיאורטיים למה היא עובדת טוב. הם אימנו פרספטרון רק שכבתי (MLP) על כל נקודה בנפרד (עם משקלים משותפים בין הנקודות השונות). כל נקודה “הוטלה” למרחב ממימד 1024. אחר כך פתרו את בעיית סדר הנקודות על ידי הפעלת פונקציה סימטרית (מקסימום) על כל הנקודות. התוצאה היא ווקטור באורך 1024 שניתן להתייחס אליו כמתאר (פיצ’ר) גלובאלי לכל ענן נקודות. את המתאר הזה הם הזינו למסווג לא לינארי (רשת fully connected). הם גם פתרו את בעיית הרוטציה על ידי הוספת תת רשת קטנה (T-net). תת הרשת הזו לומדת לשערך מטריצת טרנספורמציה על הנקודות (3×3) ועל מתארים ממימד ביניים (64×64). לקרוא לרשת זו “תת רשת” זה קצת מטעה כי כי גודלה קרוב לגודל הרשת הראשית. בנוסף, בגלל העלייה המשמעותית במספר הפרמטרים הם הוסיפו לפונקציית המחיר אילוץ שגורם למטריצת הטרנספורמציה לשאוף לארותוגונליות.

הם גם עשו סגמנטציה לחלקים עם רשת דומה מאד.

והם גם עשו סגמנטציה סמנטית על סצנות.

והם גם עשו שיערוך נורמאלים.

עבודה מדהימה! אני מאד ממליץ לקרוא (או אפילו לצפות בסרטון המצגת)

התוצאה שלהם עם ModelNet40 היתה 89.2% דיוק.

תודה ל https://arxiv.org/pdf/1612.00593.pdf

Cite: Charles R. Qi, Hao Su, Kaichun Mo, and Leonidas J. Guibas. Pointnet: Deep learning on point sets for 3d classication and segmentation. In The IEEE Conference on Computer Vision and Pattern Recognition (CVPR), July 2017.

הקוד זמין בגיטהאב: PointNet code 

Deep Sets – NIPS2017 ICLR2017

החבר’ה האלה מ CMU פרסמו את העבודה הזאת מספר שבועות לפני PointNet. הרעיון הכללי מאד דומה (לא לוקח צד בויכוח מי חשב עליו קודם). המיקוד של המאמר הזה הוא ייצור שכבה שמקבילה לקונבולוציה שפועלת על סטים (סט של נקודות במקרה שלנו) שנקראת שכבת ה”שקילות לפרמוטציות” ( permutation equivariance = PE) שזמן החישוב שלה הוא לינארי ביחס לגודל הסט. הם טוענים ששכבת ה PE היא הצורה הטובה לשיתוף משקלים למטרה זו. הניסויים מראים ביצועים משופרים לסיווג ענני נקודות (90%).

הם גם עושים חיזוי לסכום ספרות MNIST.

הם גם עושים זיהוי אנומליות בסטים.

עבודה מאד מעניינת, מאד ממליץ לקרוא למי שיותר מוכוון תיאוריות בשיטות למידה.

Cite: Ravanbakhsh, Siamak, Jeff Schneider, and Barnabas Poczos. “Deep learning with sets and point clouds.” arXiv preprint arXiv:1611.04500 (2016).

Zaheer, M., Kottur, S., Ravanbakhsh, S., Poczos, B., Salakhutdinov, R. R., & Smola, A. J. (2017). Deep sets. In Advances in Neural Information Processing Systems (pp. 3394-3404).

הקוד זמין בגיטהאב: Deep sets code

Pointnet++ – NIPS 2017

כשקראתי לראשונה את PointNet היה דבר אחד שמאד הטריד אותי – למה הם לא משתמשים בשכנויות מקומיות ? אז, אני מניח שזה הטריד גם אותם כי לא עבר זמן רב והם הוציאו לאויר העולם את PointNet++. זאת למעשה גירסה הירארכית של המקור. לכל שכבה יש שלושה תתי שלבים : דגימה, איסוף ופינטנוט (pointnetting). בשלב הראשון, הם בוחרים מרכזים, בשלב השני הם יוצרים אוסף של תתי עננים מקומיים מהשכנים של כל מרכז (ברדיוס נתון). לאחר מכן הם מזינים אותם לפוינטנט ומקבלים ייצוג מסדר גבוהה של תת הקבוצה. לאחר מכן הם חוזרים על התהלים (דוגמים מרכזים, מוצאים שכנים, ומריצים פוינטנט על הייצוג ממימד גבוהה יותר כדי לקבל ייצוג ממימד גבוהה עוד יותר). הם ביצעו שימוש ב3 שכבות כאלה (3 רמות הירארכיה). הם גם בחנו מספר שיטות איסוף על מנת להתגבר על בעיות הקשורות לצפיפות ענן הנקודות (בעיות שקיימות כשמשתמשים בכל חיישן תלת מימדי = נקודות צפופות קרוב לחיישן ודלילות רחוק מהחיישן). הם השיגו שיפור על המקור עם דיוק של 90.7% על ModelNet40 (שיפור גבוה יותר התקבל כשהשתמשו בווקטורי הנורמל לכל נקודה).

תודה ל https://arxiv.org/pdf/1706.02413.pdf


Cite: Charles R Qi, Li Yi, Hao Su, and Leonidas J Guibas. Pointnet++: Deep hierarchical feature learning on point sets in a metric space. arXiv preprint arXiv:1706.02413, 2017

Kd-Network – ICCV 2017

המאמר הזה משתמש במבנה הנתונים הידוע Kd-tree כדי ליצור סדר בענן הנקודות. לאחר הכנסת הענן למבנה, הם לומדים משקלים לכל צומת בעץ (שמייצגת חלוקה של המרחב בציר מסויים). המשקלים משותפים לכל ציר בכל רמה בודדת בעץ (כל הירוקים בתמונה למטה יש משקלים משותפים כי כולם מחלקים את המרחב בציר x). הם בחנו תת חלוקה ראנדומאלית ודטרמיניסטית של המרחב ומדווחים שהגישה הראנדומלית עובדת טוב יותר. הם מדווחים גם על מספר חסרונות. הגישה רגישה לסיבוב (כי רוטציה משנה את מבנה העץ) ורעש (במידה והוא משנה את מבנה העץ). אני מצאתי חיסרון נוסף – מספר הנקודות: לכל קלט בעל מספר נקודות שונה צריך לבצע דגימה מחדש למספר הנקודות שעליו הרשת אומנה או לחלופין לאמן רשת חדשה שתתאים למספר הנקודות הנתון.

הם מדווחים דיוק של 90.6% עבור 1024 נקודות בענן (עץ בעומק 10) ודיוק של 91.8 עבור ~32K נקודות (עץ בעומק 15) על ModelNet40.

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

הם גם עשו סגמנטציה לחלקים ו Shape Retrieval.

תודה ל https://arxiv.org/pdf/1704.01222.pdf

Cite: Roman Klokov and Victor Lempitsky. Escape from cells: Deep kd-networks for the recognition of 3d point cloud models. arXiv preprint arXiv:1704.01222, 2017.

סיכום

בקהילת הvision, התוצאות הסופיות מאד חשובות ולכן ריכזתי אותן כאן בטבלה:

אפשר לראות שהתוצאות יחסית קרובות אחת לשניה ויש הרבה השפעות של פרמטרים וגורמים שונים. לכן, אני מוצא עניין רב בהבנה של אופן הפעולה של כל שיטה. PointNet ואחותה הגדולה PointNet++ עושים שימוש בפונקציות סימטריות כדי לפתור את בעיית הסדר בעוד שKd-Network עושה שימוש בעץ Kd. העץ גם פתר את בעיית הסדר בעוד שבפוינטים הפרספטרון אומן על כל נקודה בנפרד.

אני פיתחתי שיטה משלי (יחד עם המנחים שלי בטכניון כמובן) תוצרת כחול לבן לפתרון הבעיה הנקראת 3DmFV-Net. ארחיב עליה בפוסט הבא. למי שאין סבלנות מוזמן לקרוא את המאמר, להיכנס לפוסט המסביר על השיטה בבלוג שלי, לצפות בסרטון היוטיוב בנושא ולהשתמש בקוד. השיטה פורסמה בכנס 2018 IROS ובעיתון Robotics and Aautomation Letters.

Posted by Yizhak Ben-Shabat

AdaNet – איך לומדים איך ללמוד

מיועד ל- מתחילים (כתבה קצת טכנית)

נכתב על ידי Ori Cohen

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

אופטימיזציה של מודלים

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

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

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

כלומר, כמו כל בעיה שעליה אנו עובדים במדעי הנתונים – אם אנחנו לא יודעים לפתור את הבעיה ננסה להשתמש בלמידת מכונה כדי לפתור אותה…

למידת מכונה מאפטמת (מיטיבה) למידת מכונה

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

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

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

ע”י שילוב מודלים קטנים, AdaNet יכולה ללמוד מודלים גדולים ומורכבים בצורה אופטימלית.


לקוח מ introducing-adanet-fast-and-flexible

ניתן לראות באנימציה איך באופן אדפטיבי יש גדילה של שילוב של מודלים, בכל איטרציה בהתאם למדידת פונקציית המחיר המשולבת (ensembled loss function) לכל מועמד האלגוריתם בוחר את המועמד הטוב ביותר להמשיך איתו לאיטרציה הבאה. באיטרציות הבאות הרשתות הכחולות מוקפאות ורק הרשתות הצהובות מאומנות.

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

תוצאות מדווחות

התוצאות של מודל זה מרשימות במיוחד. ע”י שימוש ברשתות נוירונים פשוטות (Fully-connected feed forward) המערכת הצליחה ללמוד מודלים שמשתווים, או אפילו עולים עליהם בביצועיהם, בדר”כ ע”י שימוש בפחות פרמטרים מהמודלים הטובים ביותר שבנויות מאותו סוג רשת.

לדוגמה, על CIFAR-10, אוסף סטנדרטי לזיהוי תמונות, הצליחה המערכת שלהם יותר מהמערכות הקיימות. (להזכירכם, המודלים היחידים שהושווה הם מודלים שמכילים שכבות מלאות בלבד, תוצאות אלו לא מייצגות את המודלים הטובים ביותר שקיימים בשוק).

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

אחזור ואדגיש כי מערכת זו גמישה במיוחד וניתן להשתמש בה על מנת לבנות מודלים מכל סוג המורכבים ממגוון רחב של שכבות (כגון CNN, RNN וכו’). כותבי המאמר בחרו שלא לעשות זאת על מנת לפשט את התהליך.

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

צלילה קלה לקוד

 עבור המעוניינים, את הקוד המלא למערכת (כולל הוראות התקנה ודוגמות) ניתן למצוא ב- https://github.com/tensorflow/adanet .

ניתן להתקין בקלות:

$ pip install adanet

ולהשתמש בזה (כקופסה שחורה) גם די בפשטות:

head = tf.contrib.estimator.multi_class_head(10)

estimator = adanet.Estimator(
    head=head,
    subnetwork_generator=CNNGenerator(),
    max_iteration_steps=max_iteration_steps,
    evaluator=adanet.Evaluator(
        input_fn=adanet_input_fn,
        steps=None),
    adanet_loss_decay=.99)

כאשר head מגדיר שכבת ה-softmax במוצא הרשת המשולבת. (למשל 10 מחלקות)

CNNGenerator הינה ירושה של המחלקה adanet.subnetwork.Generator שמחזירה כמה רשתות מועמדות לכל איטרציה ומבוססת על מחלקה שיורשת מ-adanet.subnetwork.Builder

ההפעלה עצמה מתבצעת ע”י קריאה ל-

tf.estimator.train_and_evaluate()

למעשה, גם את הקופסה השחורה הזו ניתן להבין די בקלות, במיוחד עבור אלו שמכירים High level APIs כדוגמת Keras. הממשק Estimator מתפקד כמו כל פונקציית fit אחרת, ומתאים את הפרמטרים בהתאם לפונקצית המחיר, שבמקרה זה ניתנת בפרמטר evaluator. הייחוד בקריאה זו לממשק הוא שאנו נותנים לרשת לבחור את תתי הרשתות בצורה דינמית מתוך האופציות שאנו מספקים בפונקציה subnetwork_generator. למי שמעוניין, ממשק זה נמצא בשימוש גם באופן כללי ב- Tensorflow וניתן ללמוד עליו כאן.

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

Posted by Ori Cohen

למידה לא מונחית לשערוך עומק לתמונה – Unsupervised Learning for Depth Estimation

מיועד ל- כל אחד (כתבה לא טכנית)

נכתב על ידי TzviLederer

תחומים במערכות לומדות

נהוג לחלק את עולם ה-machine learning לשלושה תחומים – למידה מונחית (supervised learning), למידה לא-מונחית (unsupervised learning) ולמידה בעזרת חיזוקים (reinforcement learning). ההבדל הבסיסי בין התחומים הוא סוג המידע בו משתמשים. בלמידה מונחית יש לנו גישה למידע מתוייג, למשל במטלה של זיהוי וסיווג אובייקטים בדרך כלל אנו מחזיקים בתמונות מתוייגות (בין אם מדובר בתיוג של כל התמונה, Bounding box, תמונות סגמנטציה וכדו’). למידה לא מונחית היא למידה בעזרת מידע ללא תיוג, הוצאת תובנות או מידע שלא נגיש לנו בעזרת הרבה מידע אך ללא ידע מקדים עליו. דוגמה קלאסית לזה היא אישכול (clustering) של וקטורים, כלומר חלוקה של דגימות לקבוצות בעלות משמעות (למשל חלוקה של כתבות באתר חדשות לפי נושאים בצורה אוטומטית). למידה באמצעות חיזוקים היא למידה של קבלת החלטות נכונה כאשר המשוב יכול להגיע גם באיחור, כלומר יכול להיות שיעבור זמן עד שנדע האם צדקנו בקבלת ההחלטות שלנו או לא. דוגמאות קלאסיות לאתגרים בתחום זה הם אלגוריתם המשחק במשחק מחשב, בו השחקן יכול לבחור בכל שלב איך לפעול אך לעיתים הוא ידע אם קבלת ההחלטות שלו הייתה נכונה רק בשלב מאוחר יותר (אם ינצח את השלב או יפסיד בו).

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

תמונות סטריאו

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

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

לקוח מ https://stackoverflow.com/questions/17607312/difference-between-disparity-map-and-disparity-image-in-stereo-matching

רשת בלתי מונחית (Unsupervised) לחישוב עומק

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

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

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

סיכום

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

מאמר בנושא:

https://arxiv.org/pdf/1609.03677.pdf

Posted by TzviLederer

Transfer Learning – הכללת ידע

מיועד ל- כל אחד (כתבה לא טכנית)

נכתב על ידי tomer peled

מוטיבציה

למידה עמוקה (Deep Learning) שינתה את העולם בעזרת מפגש של טכנולוגיה ותיקה (Neural Networks) שהחלה בשנות החמישים והבשלה של תנאים: כח מחשוב, כמויות גדולות של Data זמין וסטנדרטיזציה של שיטות עבודה – Benchmarks סטנדרטים, קוד פתוח. אך כמויות גדולות של Data רלוונטי לא בהכרח זמינות עבור כל בעיה.

למרבית המזל קרוב מאד לפריצת התחום של למידה עמוקה, התברר גם שזמינות כמויות גדולות של Data אינה הכרחית בהרבה מקרים, מאחר ש TransferLearning (המרת למידה) התגלתה כיעילה במיוחד להרחבת מרחב הפתרונות של למידה עמוקה.

הגדרה

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

Transfer Learning

בשני מאמרים פורצי דרך [5], [4] הוכח שרשת שלמדה לפתור בעייה מסוימת – למשל סיווג תמונות מ 1000 קטגוריות המצויות ב ImageNet, יכולה בתהליך פשוט של Fine Tuning לעבור התאמה  לפתרון בעיה אחרת כגון סיווג אנשים (שלא מופיעים כקטגוריה ב ImageNet), מוצרים מחנות מכוונת או סיווג סצינות.

למעשה רוב העבודה שנעשית היום בלמידה עמוקה מבוססת על Tranfer-Learning ומאפשרת לחסוך לימוד על חומרה מרובת GPU במשך שבועות כמו שנעשה על ImageNet.

למה זה עובד ?

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

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

אז איך עושים את זה ?

תהליך ה Transfer Learning כולל לימוד מחדש של שכבת ההחלטה (סיווג או רגרסיה), תוך הקפאת (Trainable= 0, Freeze)  הלימוד בשאר השכבות. ולעיתים לאחר מכן גם לימוד של השכבות העליונות בקצב לימוד (Learning Rate) נמוך.

  • הדרך הפשוטה ביותר – ולעיתים זה כל מה שנידרש היא להשתמש ברשת מאומנת מראש על בעיה אחרת כגון ImageNet כ feature-extractor (מחלץ תכונות) ולאמן מסווג למשל Linear-SVM או SoftMax התכונות שחולצו מהתמונות שלנו.
  • הרחבה אפשרית לשיפור ביצועים נקראת כוונון עדין fine-tuning. כלומר התאמה קטנה של המשקלות בשאר הרשת.
    • מקובל להקפיא את הלימוד בשכבות הנמוכות של הרשת. מאחר שההכללה בלימוד על בסיס נתונים גדול כ Image-Net טובה מההכללה שתתקבל על סט תמונות קטן ומגוון פחות וכן ה features בשכבות אלו מבטאים אבסטרקציה כגילוי שפות וכתמים המשותפים לכלל הבעיות.
    • את השכבות העליונות ברשת מאמנים בקצב לימוד (Learning-rate) נמוך על מנת לשמור על השפעה קטנה.
    • לעיתים מאמנים בו זמנית את השכבות העליונות ברשת בקצב נמוך ואת המסווג בקצב גבוה יותר.

מקורות


Posted by tomer peled in deep

מיני-פרויקט בלמידה חיזוקית (Reinforcement Learning)

מיועד ל- מתחילים (כתבה קצת טכנית)

נכתב על ידי תמיר נווה

אז אחרי שבניתי את הרובוט הזה (ראו את התמונה בעמוד הראשי של כל הכתבות) אני רוצה להכניס לו קצת בינה ודעת…

מטרתי הייתה ללמוד ולהתנסות ב Reinforcement Learning כי זה תחום מאוד מסקרן, בטח אחרי כל משחקי האטארי המפוצחים ע”י אלגוריתם (חודשים של התמכרות כשהייתי בן שבע 🙂 מעניין איך המחשב משחק בזה ? ? ?)

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

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

קצת טרמינולוגית RL

תודה ל https://becominghuman.ai/the-very-basics-of-reinforcement-learning-154f28a79071

State = מצב בו נמצא הסוכן (סך המידע הגלוי לו על הסביבה שלו). אפשר שמצבים יחשבו כראשוניים או כסופיים (ז”א תחילת\סוף משחק). במקרה של המשחק המתואר, מצב הינו: מיקומו של הסוכן על לוח המשבצות, מיקומו של הכדור על לוח המשבצות, ומשתנה בינארי שמשמעותו אם הכדור מוחזק ע”י הסוכן או לא.

Action = פעולה אותה יכול הסוכן לעשות בכל מצב. הפעולה תעביר אותו למצב חדש או תשאיר אותו בנוכחי. במקרה של המשחק המתואר זה ערך מספרי בדיד בין 1 ל-5: מעלה, מטה, ימינה, שמאלה, הרם.

Episode = אפיזודה\משחק שלם. ז”א שרשרת של מעברים ממצב ראשוני כלשהוא למצב סופי כלשהוא. במקרה של המשחק המתואר זה שרשרת המצבים מתחילת המשחק עד שהכדור מוחזק ע”י הסוכן והסוכן מגיע למשבצות האדומות.

Reward = תגמול אותו מקבל הסוכן כתוצאה מצמד (פעולה, מצב קודם). במקרה של המשחק המתואר החלטתי לתת תגמול גבוה  במקרה של נצחון, תגמול נמוך במקרה של הגעה של הסוכן למיקום הכדור והרמתו. ערכי התגמולים הם פרמטרים איתם שיחקתי (למשל בקוד כפי שתוכלו לראות זה כרגע 20, 5). כמו כן שיחקתי עם אפשרות לתת תגמול שלילי (ז”א עונש) על כל תור שחולף. שיטה זו בעצם גורמת לסוכן להתאמן על לנצח מהר ולא סתם לנצח. כי בכל תור בו עשה פעולה מיותרת הוא משלם מחיר…

π=Policy = מדיניות לפיה מחליט הסוכן איזו פעולה לבחור בכל מצב. למעשה פונקציה המקבלת מצב ומחזירה פעולה. בקוד תוכלו לראות שתי גישות אותן ניסיתי (ε-Greedy או Softmax Action Selection).

Return=G = סכום התגמולים שנתקבלו החל מצמד (פעולה, מצב) ועד לסיומה של האפיזודה

Quality=Q = טבלת הערך לכל צמד (פעולה, מצב). מחושב למשל כממוצע של כל ה-G שנתקבלו עבור על צמד (פעולה, מצב). המשמעות הינה כמה מוצלחת הפעולה הזו בהינתן המצב הזה?

Value=V = טבלת הערך לכל מצב. (לעיתים משתמשים ב V ולעיתים ב Q) המשמעות הינה עד כמה כדאי להימצא במצב הזה ? (מבחינת אפשרויות לנצחון)

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

אילו יש בידינו (בידי הסוכן) את הערכים האופטימליים לכל מצב\פעולה אז ישנן מדינויות  (Policies) לפעול כמו ε-greedy או softmax action selection. הרחבה על נושא זה תמצאו בכתבה הזו.

בכתבה זו נעסוק במספר שיטות לעידכון פונקציות הערך Q או V.

שיטת מונטה קרלו

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

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

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

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

שיטת Q-Learning

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

הערך Q עבור בחירת פעולה מסויימת At במצב מסויים St (בזמן\תור t) הינו הערך שהיה ועוד קומבינציה לינארית בין התגמול שנתקבל מפעולה זו לבין הערך הגבוה ביותר שניתן לקבל בעבור המצב הבא. (ע”י השוואה בין כל הפעולות האפשריות מהמצב החדש)

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

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

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

שיטת Deep Q-Learning

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

גם כאן ניתן לפעול לפי מדיניות כלשהיא, למשל ε-Greedy או Softmax Action Selection או כל מדיניות אחרת שמשתמשת ב Q שהרשת מספקת לכל מצב. ואת הלימוד (back propagate) של הרשת מבצעים באופן דומה ל Q Learning, תוך כדי המשחק. התהליך כולו (עליו חוזרים לאורך אפיסודות\משחקים רבים) נראה כך:

  • מזינים את המצב הנוכחי לרשת ומקבלים וקטור q1 (ערך לכל פעולה אפשרית). הפעלת זו של הרשת הינה רק קדימה ז”א ללא אימון BackPropagation.
  • בוחרים פעולה ומשחקים אותה (או בעלת הערך הגבוה ממה שיצא ברשת או אקראי תלוי במדיניות)
  • מזינים את המצב הנוכחי (שהוא החדש) לרשת ומקבלים וקטור q2 (זו שוב הפעלת הרשת קדימה ז”א ללא אימון עדיין)
  • בונים וקטור פרדיקציה (שישמש לשלב האימון) באופן הבא:

לוקחים את הווקטור q1 כאשר מחליפים בו את האלמנט של הפעולה בה בחרנו ושמים שם ערך חדש לפי נוסחת ה- Q-Learning:

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

האינטואיציה לכך: מצב ייחשב מוצלח אם ניתן להגיע ממנו למצב מוצלח אחר. (כמו במשחק השחמט: אומרים “שח” כי זה מצב ממנו ניתן לנצח בתור הבא)

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

כשאימנתי לפי שיטה זו היו דרושים יותר משחקי אימון (מאשר בשיטת Q-Learning) כדי להגיע להצלחה, אני מניח שזה מכיוון שזה קצת overkill לבעיה. היתרון הגדול בשימוש ב CNN לבעיות כאלו הם כשהמצב (state) הינו תמונה (כמו במשחקי אטארי) ולא וקטור או מטריצה (תמציתית) המתארת את המצב הנוכחי במשחק. במקרים שהמצב הוא תמונה, לתחזק טבלת ערכים לכל מצב אינו ריאלי.

טיפים לניפוי הקוד

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

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

  • חישוב והצגה של גרף של כמות האיטרציות כפונקציה של מספר האפיזודות (המשחקים) אליהן אומן הסוכן אמור להיות גרף יורד. מדד זה סיפק לי מידע אם אני בכיוון הנכון בכל הרצה. במילים אחרות: ככל שהסוכן מתאמן יותר, הוא אמור לנצח יותר מהר במשחק.
  • להשוות ביצועים של סוכן שמתנהג בצורה אקראית לגמרי (כמה תורות בממוצע ינצח במשחק ?) לעומת מודל מאומן.
  • לייצר ויזואליזציה של המשחק (זה מומלץ בכל domain), לאפשר לי משחק אינטראקטיבי (ז”א שאוכל לשחק כנגדו) שיגרום לי להבין מה בכל זאת למד המודל. למשל למד אסטרטגיות כאלו שמביאות אותו לפעולות מחזוריות ולכן לתקיעות. בכל צעד שהמודל “משחק” להציג את השיקולים שלו (ז”א את ערכי ה Q  לאותו המצב)
  • להתחיל במקרה פשוט ולאט לאט לסבך אותו (זה גם מומלץ בכל domain). במקרה זה התחלתי בלוח פשוט ביותר של 2×2 כאשר מצב הפתיחה קבוע. ואז מצב פתיחה אקראי, ואז הגדלת גודל לוח המשחק, וכו’

הסבר על הקוד

את הקוד תמצאו ב GitHub שלי !

Solve_game.py זהו הקוד הראשי שפותר את המשחק לפי כל אחת מהשיטות (זה הקוד שיש להריץ).

Game.py המחלקה המממשת את המשחק עצמו, מאפשרת לאתחל משחק לפי פרמטרים שונים, להקליט משחק, לשחק (לא משנה אם אדם או אלגוריתם), להציג לוח משחק ועוד… שימו לב למטודה state_as_tensor שמחזירה את מצב המשחק כטנזור בגודל nxnx2. כאשר n הוא גודל לוח המשבצות וערוץ אחד עבור מיקום הסוכן והערוץ השני עבור מיקום הכדור ומצבו (מוחזק או לא מוחזק ע”י הסוכן)

interactive_play.py מאפשר למשתמש (אנושי) לשחק במשחק

policies.py מאפשר מדיניות משחק: אפסילון החמדן (Greedy Epsilon) או Softmax Selection. בפרט שליטה על דעיכת הפרמטר אפסילון (ε).

Deep_Q_learning.py מימוש שיטת Deep-Q Learning כמוסבר מעלה.

tabular_learning.py מימוש שיטות מונטה קרלו או Q-Learning כמוסבר מעלה.

לסיכום

מאוד התרגשתי כשראיתי את הסוכן המאומן שלי משחק בעצמו במשחק ומנצח מהר, ז”א ללא צעדים מיותרים!

ראו סרטון שמדגים את תהליך הלמידה: (בהתחלה משחק אקראי וככל שמתקדם האימון משחק יותר ויותר בהגיון):


השלב הבא של הפרויקט הוא לעבוד עם משתנה מצב תמונה (ז”א אוסף פיקסלים) ואז לבחון ביצועים. כמו כן לחפש דרכים איך להקטין את משך האימון ולממש Double Q-Learning.

אשמח לשאלות ופידבקים!

Posted by תמיר נווה in deep