ג.1 מהי למידת מכונה?
עד כה כתבנו תוכניות בדרך המוכרת: חשבנו על הבעיה, ניסחנו כללים וכתבנו אותם כקוד. כך בנינו את המשחקים בחלק הקודם, וכך המחשב עושה בדיוק מה שאמרנו לו. אבל יש בעיות שקשה מאוד לנסח עבורן כללים. נסו למשל לכתוב פונקציה שמקבלת תמונה ומחליטה אם יש בה חתול. אילו תנאים נבדוק? צבע? צורה של אוזניים? כל כלל שננסח יפול על חתול שמצולם מזווית אחרת. אנחנו, בני האדם, לא למדנו לזהות חתולים מתוך רשימת כללים; למדנו מתוך דוגמאות רבות.
זה בדיוק הרעיון של למידת מכונה — Machine Learning: במקום לכתוב את הכללים בעצמנו, בונים מערכת שלומדת אותם מדוגמאות או מניסיון. אנו מספקים למערכת נתונים, והיא מכוונת את עצמה עד שהיא מפיקה תשובות טובות. התוכנית שלנו אינה מכילה את הפתרון; היא מכילה את המנגנון שמוצא את הפתרון.
בפרק זה נבנה את התמונה הכללית לפני שניכנס לקוד. נראה היכן למידת מכונה ממוקמת בתוך הבינה המלאכותית, נכיר את רשתות הנוירונים שישמשו אותנו בהמשך, נבין מהו אימון ומדוע הוא חשוב, ונחבר את כל זה למטרה של הספר: בניית שחקן מחשב למשחקים. בסיום נציג את ספריית PyTorch שבה נממש את הרעיונות בפרקים הבאים.
בינה מלאכותית ולמידת מכונה
לפני שנגדיר למידת מכונה, נמקם אותה בתוך התחום הרחב שאליו היא שייכת.
בינה מלאכותית — Artificial Intelligence, או AI — היא תחום במדעי המחשב העוסק בפיתוח מערכות המחקות יכולות של אינטליגנציה אנושית.
השיעור וההרצאות באתר של גלעד מרקמן
חומרי הליווי: 1. מבוא והתקנה (עותק מקומי)
למידת מכונה היא תחום בתוך הבינה המלאכותית: הדרך שבה מערכת רוכשת את יכולותיה מתוך נתונים ולא מתוך כללים שנכתבו מראש. סוגי הלמידה נבדלים זה מזה לפי סוג המידע שהמערכת מקבלת בזמן הלמידה. נכיר שלושה סוגי למידה:
- למידה מונחית — Supervised Learning: לומדים מדוגמאות שהתשובה הרצויה עבורן ידועה.
- למידה בלתי מונחית — Unsupervised Learning: מחפשים מבנה בנתונים ללא תשובה נתונה לכל דוגמה.
- למידת חיזוק — Reinforcement Learning: לומדים מתוך פעולות והתגמולים שמתקבלים בעקבותיהן.
דוגמת החתולים שייכת ללמידה מונחית: לכל תמונה באוסף אנו יודעים אם יש בה חתול. בחלק זה של הספר נעסוק בעיקר בלמידה מונחית, ובחלק הבא נעבור ללמידת חיזוק, שבה שחקן המחשב ילמד מתוך המשחק עצמו.
למידה עמוקה — Deep Learning מבוססת על רשתות נוירונים בעלות כמה שכבות חישוב. רשתות כאלה יכולות לשמש בסוגי הלמידה השונים, וגם בלמידת חיזוק. לכן בתרשים יש חפיפה בין למידה עמוקה ללמידת חיזוק; החפיפה נקראת למידת חיזוק עמוקה.
מהו נוירון בביולוגיה?
הכלי המרכזי שבו נשתמש בספר הוא רשת נוירונים. השם לקוח מהביולוגיה, ולכן נתחיל שם, רק כדי להבין מהיכן הגיע הרעיון.
המוח בנוי מתאי עצב הנקראים נוירונים. התאים מחוברים זה לזה ומעבירים מידע באמצעות הקשרים ביניהם. המבנה הזה נתן השראה לרעיון של רשת נוירונים במחשב: יחידות רבות המחוברות זו לזו.
רשת נוירונים מלאכותית היא מודל מתמטי; היא אינה העתק של המוח. ההשראה הביולוגית עוזרת להבין את רעיון החיבורים, אך את החישוב עצמו נתאר באמצעות מספרים ופונקציות.
מהו נוירון ברשת נוירונים מלאכותית?
נעבור עתה מההשראה למודל המתמטי. נוירון מלאכותי הוא פונקציה המקבלת מספרים כקלט, מבצעת חישוב ומחזירה מספר כפלט. נסמן את הקלטים באות X, את המשקלים באות W ואת הפלט באות Y. לכל קלט מוצמד משקל, הקובע כיצד הוא משתתף בחישוב: משקל גדול פירושו שהקלט משפיע הרבה על התוצאה, משקל קרוב לאפס פירושו שהוא כמעט אינו משפיע.
החישוב מורכב משני שלבים:
- סכום משוקלל: מכפילים כל קלט במשקל שלו ומחברים את המכפלות. בשלושה קלטים נקבל X₁W₁ + X₂W₂ + X₃W₃. הכתיב המקוצר של הסכום הוא WᵀX.
- הפעלת פונקציית אקטיבציה: מפעילים על הסכום פונקציה לא לינארית המסומנת באות היוונית σ. הפלט הוא Y = σ(WᵀX). פונקציית האקטיבציה — Activation Function היא פונקציה פשוטה, כדוגמת פונקציה שמאפסת סכום שלילי ומשאירה סכום חיובי כמות שהוא; את הפונקציות המקובלות נכיר בהמשך.
המשקלים (W) הם הדבר החשוב ביותר בנוירון, ולכן נעצור עליהם רגע. הקלטים X מגיעים מבחוץ ואיננו שולטים בהם, ומבנה החישוב, סכום ואחריו פונקציית אקטיבציה, קבוע מראש. המשקלים, לעומת זאת, הם מספרים רגילים שאפשר לשנות בכל עת, וכל שינוי בהם משנה את הפלט: אם נגדיל את W₁, הקלט X₁ ישפיע יותר על התוצאה; אם נקטין אותו לאפס, הנוירון יתעלם מ־X₁ לחלוטין. אותו נוירון בדיוק, עם משקלים אחרים, מחשב פונקציה אחרת. זהו לב הרעיון של רשת נוירונים: הידע של הרשת אינו כתוב בקוד, אלא נמצא בערכי המשקלים, ואימון פירושו שינוי המשקלים באופן שיטתי עד שהרשת מפיקה את התשובות הרצויות. כשנדבר בהמשך על "רשת שלומדת", הכוונה תמיד למשקלים שמתעדכנים.
מהי רשת נוירונים?
נוירון יחיד יכול לחשב רק פונקציות פשוטות. כדי להגיע לחישובים מורכבים, כמו זיהוי חתול בתמונה, מחברים נוירונים רבים זה לזה. ברשת נוירונים מחברים כמה נוירונים מלאכותיים: הפלטים של נוירונים משמשים כקלטים לנוירונים הבאים. כך מתקבלת פונקציה המורכבת מחישובים קטנים, והתוצאה שלה תלויה במשקלים (W) שבחיבורים. הפלט הסופי יכול להיות מספר אחד או כמה מספרים.
בתרשים נראים שלושה חלקים:
- שכבת קלט — Input: הערכים המוזנים לרשת.
- שכבה חבויה — Hidden: נוירונים המבצעים חישובי ביניים.
- שכבת פלט — Output: הנוירונים המפיקים את תוצאת הרשת.
לדוגמה, בתרשים שלפנינו שני קלטים מזינים שני נוירונים. כל אחד מהם מחשב סכום משוקלל ומפעיל עליו אקטיבציה. שני הפלטים שלהם נכנסים לנוירון נוסף, שמפיק את התוצאה הסופית Y.
אימון רשת נוירונים
כעת יש לנו רשת שיודעת לבצע חישוב. אבל אילו משקלים (W) יגרמו לה להחזיר תשובה מועילה? עם משקלים אקראיים הרשת מפיקה מספרים חסרי משמעות; המבנה של הרשת לבדו אינו יודע דבר על חתולים. אימון הוא התהליך שבו משנים את המשקלים (W) בעזרת דוגמאות. כאן נמצא ההבדל המרכזי מהתכנות הרגיל: את המספרים הנכונים איננו כותבים בעצמנו, אלא נותנים לתהליך האימון למצוא אותם.
באימון המונחה המתואר כאן, לכל קלט ידועה גם התשובה הרצויה. מזינים את הקלט לרשת, משווים את הפלט לתשובה הרצויה ומשנים את המשקלים (W) כדי לשפר את התוצאה. ההפרש בין הפלט לתשובה הרצויה הוא מדד לטעות של הרשת, ומטרת האימון היא להקטין את הטעות הזו ככל האפשר. המבנה שהכרנו נשאר דרך החישוב; המספרים שבמשקלים (W) הם שמתעדכנים. כיצד יודעים לאיזה כיוון לשנות כל משקל? זו השאלה שבה יעסקו הפרקים הקרובים.
לדוגמה, נרצה לבנות רשת המקבלת תמונה ומחליטה אם מופיע בה חתול. הקלט הוא ערכי הפיקסלים של התמונה, והתשובה הרצויה היא ״חתול״ או ״לא חתול״.
נאסוף תמונות משני הסוגים, כאשר התשובה לכל תמונה ידועה לנו. נתחיל במשקלים אקראיים, נזין תמונות לרשת ונעדכן את המשקלים לפי התשובות הרצויות. לאורך האימון ננסה להביא את הרשת למצב שבו היא מזהה נכון את התמונות שבאוסף.
האם בכך סיימנו? לא. אם כל מה שהרשת יודעת הוא לענות נכון על תמונות האימון, לא הרווחנו הרבה: את התשובות לתמונות האלה ידענו ממילא. אנו רוצים שהרשת תזהה חתול גם בתמונה חדשה, שלא שימשה לאימון. היכולת להשתמש במה שנלמד מדוגמאות קודמות כדי לענות על קלט חדש נקראת הכללה; הצלחה בתמונות האימון לבדה אינה מבטיחה אותה. רשת יכולה "לשנן" את תמונות האימון ועדיין להיכשל בתמונה חדשה, ולכן נבדוק תמיד את הרשת גם על דוגמאות שלא ראתה.
רשת נוירונים במשחקים
איך כל זה קשור למשחקים שבנינו? בדוגמת החתולים הרשת מקבלת תמונה ומחזירה תשובה. במשחק נרצה להעריך עד כמה מצב מסוים טוב עבור השחקן: הרשת תקבל את מצב המשחק ותחזיר מספר שמבטא כמה המצב טוב. נשתמש בשלושה מושגים: מצב — State, פעולה — Action וערך — Value. פעולה משנה את מצב המשחק, והרשת יכולה לעזור להעריך את המצב שאליו נגיע.
אם נוכל להעריך היטב את המצבים שאליהם מובילות הפעולות האפשריות, נוכל להיעזר בערכים האלה בבחירת פעולה: נבחר את הפעולה שמובילה למצב בעל הערך הגבוה ביותר. אך מניין נשיג דוגמאות לאימון? במשחק אין לנו אוסף מוכן של מצבים עם "התשובה הנכונה" לכל אחד. בלמידת חיזוק אפשר לאמן את הרשת מתוך ניסיון המשחק עצמו: צעדים שבוצעו מספקים דוגמאות ללמידה, והתוצאות של המשחק אומרות לנו אילו צעדים היו טובים.
הגורם שבוחר את הפעולה נקרא סוכן — Agent. הוא פועל בתוך סביבה — Environment, ומקבל ממנה תצפיות ותגמולים. כך מתחברים הרעיון של רשת לומדת והמטרה של בניית שחקן במשחק.
ספריית PyTorch
רשת נוירונים ואימון הם, בסופו של דבר, הרבה מאוד פעולות חשבון על הרבה מאוד מספרים. אפשר לכתוב את כל זה בעצמנו ב־Python, אבל זה יהיה איטי ומסורבל. כדי לממש את הרעיונות האלה נשתמש ב־PyTorch, ספריית קוד פתוח ללמידת מכונה עם ממשק בשפת Python. היא מספקת רכיבים לבניית רשתות נוירונים וכלים לחישובים על מערכים הנקראים טנסורים — Tensors. היא מאפשרת גם חישובים באמצעות מעבד גרפי, GPU, שמבצע פעולות רבות במקביל ומאיץ מאוד את האימון.
בפרק הבא נכין את PyTorch לעבודה ב־Colab, ולאחר מכן נכיר את הטנסורים שעליהם יתבססו החישובים.