1. סקירה כללית
בשיעור ה-Lab הזה תלמדו איך ליצור מסווג Keras. במקום לנסות להבין מה השילוב המושלם של שכבות רשת נוירונים לזיהוי פרחים, נשתמש קודם בטכניקה שנקראת 'למידת העברה' כדי להתאים מודל רב-עוצמה שאומן מראש למערך הנתונים שלנו.
שיעור ה-Lab הזה כולל את ההסברים התיאורטיים הדרושים על רשתות נוירונים, והוא נקודת התחלה טובה למפתחים שרוצים ללמוד על למידה עמוקה (Deep Learning).
שיעור ה-Lab הזה הוא חלק 2 בסדרה Keras on TPU. אפשר לבצע אותן בסדר הבא או בנפרד.
- פייפליינים במהירות TPU: tf.data.Dataset ו-TFRecords
- [THIS LAB] Your first Keras model, with transfer learning
- רשתות עצביות מתקפלות, עם Keras ויחידות TPU
- רשתות מתקפלות מודרניות, squeezenet, Xception, עם Keras ויחידות TPU

מה תלמדו
- כדי ליצור מסווג תמונות משלכם ב-Keras עם שכבת softmax ופונקציית הפסד cross-entropy
- כדי לרמות 😈, אפשר להשתמש בלמידת העברה במקום לבנות מודלים משלכם.
משוב
אם נתקלתם בבעיה כלשהי בשיעור ה-Lab הזה, נשמח לדעת. אפשר לשלוח משוב באמצעות בעיות ב-GitHub [ קישור למשוב].
2. מדריך למתחילים ב-Google Colaboratory
ב-Lab הזה נעשה שימוש ב-Google Collaboratory, ולא נדרשת הגדרה מצדכם. Colaboratory היא פלטפורמת מחברות אונליין למטרות חינוכיות. הוא מציע הדרכה בחינם בנושאי CPU, GPU ו-TPU.

אתם יכולים לפתוח את מחברת הדוגמה הזו ולהריץ כמה תאים כדי להכיר את Colaboratory.
בחירת TPU backend

בתפריט Colab, בוחרים באפשרות Runtime > Change runtime type (זמן ריצה > שינוי הסוג של זמן הריצה) ואז בוחרים באפשרות TPU. בשיעור ה-Lab הזה תשתמשו ב-TPU (Tensor Processing Unit) עוצמתי שמגובה באימון מואץ באמצעות חומרה. החיבור לסביבת זמן הריצה יתבצע אוטומטית בהרצה הראשונה, או שתוכלו להשתמש בלחצן 'חיבור' בפינה השמאלית העליונה.
הרצת Notebook

מריצים כל תא בנפרד על ידי לחיצה על תא והקשה על Shift-ENTER. אפשר גם להריץ את כל ה-notebook באמצעות סביבת זמן הריצה > הפעלת הכול.
תוכן העניינים

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

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

אם תבצעו אימות באמצעות חשבון מורשה, תוכלו לגשת ב-Colab לקטגוריות הפרטיות שלכם ב-Google Cloud Storage. קטע הקוד שלמעלה יפעיל תהליך אימות.
3. [INFO] סיווג רשתות נוירונים למתחילים
על קצה המזלג
אם אתם כבר מכירים את כל המונחים מודגשים בפסקה הבאה, אתם יכולים לעבור לתרגיל הבא. אם אתם רק מתחילים ללמוד על למידה עמוקה, אתם מוזמנים להמשיך לקרוא.
למודלים שנבנו כרצף של שכבות, Keras מציעה את Sequential API. לדוגמה, אפשר לכתוב ב-Keras מסווג תמונות שמשתמש בשלוש שכבות צפופות באופן הבא:
model = tf.keras.Sequential([
tf.keras.layers.Flatten(input_shape=[192, 192, 3]),
tf.keras.layers.Dense(500, activation="relu"),
tf.keras.layers.Dense(50, activation="relu"),
tf.keras.layers.Dense(5, activation='softmax') # classifying into 5 classes
])
# this configures the training of the model. Keras calls it "compiling" the model.
model.compile(
optimizer='adam',
loss= 'categorical_crossentropy',
metrics=['accuracy']) # % of correct answers
# train the model
model.fit(dataset, ... )

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

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

פונקציית ההפעלה הפופולרית ביותר נקראת RELU, קיצור של Rectified Linear Unit (יחידה ליניארית מתוקנת). זו פונקציה פשוטה מאוד, כפי שאפשר לראות בגרף שלמעלה.
הפעלת Softmax
הרשת שלמעלה מסתיימת בשכבה של 5 נוירונים כי אנחנו מסווגים פרחים ל-5 קטגוריות (ורד, צבעוני, שן הארי, חרצית וחמנייה). נוירונים בשכבות ביניים מופעלים באמצעות פונקציית ההפעלה הקלאסית RELU. עם זאת, בשכבה האחרונה אנחנו רוצים לחשב מספרים בין 0 ל-1 שמייצגים את ההסתברות לכך שהפרח הזה הוא ורד, צבעוני וכן הלאה. לשם כך, נשתמש בפונקציית הפעלה שנקראת softmax.
כדי להחיל softmax על וקטור, מחשבים את האקספוננט של כל רכיב ואז מבצעים נורמליזציה של הווקטור, בדרך כלל באמצעות נורמת L1 (סכום הערכים המוחלטים) כך שסכום הערכים יהיה 1 ואפשר יהיה לפרש אותם כהסתברויות.

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

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

חלוקה לקבוצות קטנות ומומנטום
אפשר לחשב את הגרדיאנט רק על תמונה לדוגמה אחת ולעדכן את המשקלים וההטיות באופן מיידי, אבל אם עושים את זה על קבוצה של 128 תמונות לדוגמה, מקבלים גרדיאנט שמייצג טוב יותר את האילוצים שמוטלים על ידי תמונות לדוגמה שונות, ולכן סביר להניח שהפתרון יתקבל מהר יותר. גודל המיני-batch הוא פרמטר שניתן להתאמה.
לטכניקה הזו, שנקראת לפעמים "ירידה סטוכסטית של גרדיאנט", יש יתרון פרגמטי נוסף: עבודה עם אצוות פירושה גם עבודה עם מטריצות גדולות יותר, ובדרך כלל קל יותר לבצע אופטימיזציה שלהן ב-GPU וב-TPU.
עם זאת, יכול להיות שההתכנסות תהיה קצת כאוטית, ואפילו תיפסק אם וקטור הגרדיאנט יהיה אפס. האם זה אומר שמצאנו מינימום? לא תמיד. רכיב של מעבר צבעים יכול להיות אפס במינימום או במקסימום. אם יש וקטור גרדיאנט עם מיליוני אלמנטים, וכולם אפסים, ההסתברות שכל אפס מתאים לנקודת מינימום ואף אחד מהם לא מתאים לנקודת מקסימום היא קטנה למדי. במרחב עם הרבה ממדים, נקודות אוכף הן די נפוצות ואנחנו לא רוצים לעצור בהן.

איור: נקודת אוכף. השיפוע הוא 0, אבל זה לא מינימום בכל הכיוונים. (Attribution של התמונה Wikimedia: By Nicoguaro - Own work, CC BY 3.0)
הפתרון הוא להוסיף לאלגוריתם האופטימיזציה תנופה מסוימת, כדי שהוא יוכל לעבור את נקודות האוכף בלי לעצור.
מילון מונחים
אצווה או אצווה קטנה: האימון מתבצע תמיד על אצוות של נתוני אימון ותוויות. כך האלגוריתם יכול להתכנס. המאפיין 'batch' הוא בדרך כלל המאפיין הראשון של טנסורים של נתונים. לדוגמה, טנסור בצורה [100, 192, 192, 3] מכיל 100 תמונות בגודל 192x192 פיקסלים עם שלושה ערכים לכל פיקסל (RGB).
פונקציית אובדן של אנטרופיה צולבת: פונקציית אובדן מיוחדת שמשמשת לעיתים קרובות בסיווגים.
שכבה צפופה: שכבה של נוירונים שבה כל נוירון מחובר לכל הנוירונים בשכבה הקודמת.
תכונות: הקלטים של רשת נוירונים נקראים לפעמים 'תכונות'. האומנות של בחירת החלקים של מערך נתונים (או שילובים של חלקים) שיוזנו לרשת נוירונים כדי לקבל חיזויים טובים נקראת 'הנדסת פיצ'רים (feature engineering)'.
תוויות: שם נוסף ל'סיווגים' או לתשובות נכונות בבעיית סיווג בפיקוח
קצב למידה: חלק מהשיפוע שלפיו המשקולות וההטיות מתעדכנים בכל איטרציה של לולאת האימון.
לוגיטים: הפלט של שכבת נוירונים לפני שמחילים את פונקציית ההפעלה נקרא 'לוגיטים'. המונח הזה מגיע מהפונקציה הלוגיסטית, שנקראת גם פונקציית סיגמואיד, שהייתה פונקציית ההפעלה הכי פופולרית. השם 'Neuron outputs before logistic function' (פלט של נוירון לפני פונקציה לוגיסטית) קוצר ל-'logits'.
loss: פונקציית השגיאה שמשווה בין התפוקות של רשת נוירונים לבין התשובות הנכונות
נוירון: מחשב את הסכום המשוקלל של הקלט שלו, מוסיף הטיה ומעביר את התוצאה דרך פונקציית הפעלה.
קידוד one-hot: מחלקה 3 מתוך 5 מקודדת כווקטור של 5 אלמנטים, כולם אפסים חוץ מהאלמנט השלישי שהוא 1.
relu: יחידה לינארית מתוקנת. פונקציית הפעלה פופולרית לנוירונים.
sigmoid: פונקציית הפעלה נוספת שהייתה פופולרית בעבר ועדיין שימושית במקרים מיוחדים.
softmax: פונקציית הפעלה מיוחדת שפועלת על וקטור, מגדילה את ההפרש בין הרכיב הגדול ביותר לבין כל שאר הרכיבים, וגם מבצעת נורמליזציה של הווקטור כך שהסכום שלו יהיה 1, כדי שאפשר יהיה לפרש אותו כווקטור של הסתברויות. משמש כשלב האחרון בסיווגים.
tensor: טנזור הוא כמו מטריצה, אבל עם מספר שרירותי של ממדים. טנסור חד-ממדי הוא וקטור. טנסור דו-ממדי הוא מטריצה. אחר כך אפשר ליצור טנסורים עם 3, 4, 5 או יותר מימדים.
4. למידה בהעברה
בבעיה של סיווג תמונות, שכבות צפופות כנראה לא יספיקו. צריך ללמוד על שכבות קונבולוציה ועל הדרכים הרבות שבהן אפשר לסדר אותן.
אבל אפשר גם לקצר את הדרך! אפשר להוריד רשתות נוירונים מתקפלות שאומנו באופן מלא. אפשר להסיר את השכבה האחרונה שלהם, את ראש הסיווג softmax, ולהחליף אותה בשכבה משלכם. כל המשקלים וההטיות שאומנו נשארים כמו שהם, ואתם מאמנים מחדש רק את שכבת ה-softmax שאתם מוסיפים. הטכניקה הזו נקראת 'למידת העברה', והיא פועלת כל עוד קבוצת הנתונים שעליה הרשת העצבית מאומנת מראש דומה מספיק לנתונים שלכם.
מעשי
צריך לפתוח את ה-notebook הבא, להריץ את התאים (Shift-ENTER) ולפעול לפי ההוראות בכל מקום שמופיעה התווית WORK REQUIRED.
Keras Flowers transfer learning (playground).ipynb
מידע נוסף
בעזרת למידת העברה, אתם נהנים גם מארכיטקטורות מתקדמות של רשתות נוירונים מתקפלות שפותחו על ידי חוקרים מובילים, וגם מאימון מוקדם על קבוצת נתונים עצומה של תמונות. במקרה שלנו, נשתמש בשיטת העברת הלמידה מרשת שאומנה על ImageNet, מסד נתונים של תמונות שמכיל הרבה צמחים וסצנות בחוץ, שקרובים מספיק לפרחים.

איור: שימוש ברשת נוירונים קונבולוציונית מורכבת, שכבר אומנה, כקופסה שחורה, ואימון מחדש רק של ראש הסיווג. זהו למידת העברה. בהמשך נראה איך הסידורים המורכבים האלה של שכבות קונבולוציה פועלים. בינתיים, זאת בעיה של מישהו אחר.
למידה של העברות ב-Keras
ב-Keras, אפשר ליצור מופע של מודל שעבר אימון מראש מתוך אוסף tf.keras.applications.*. לדוגמה, MobileNet V2 היא ארכיטקטורה טובה מאוד של רשת קונבולוציה, והגודל שלה סביר. אם בוחרים באפשרות include_top=False, מקבלים את המודל שאומן מראש בלי שכבת ה-softmax הסופית שלו, כדי שתוכלו להוסיף משלכם:
pretrained_model = tf.keras.applications.MobileNetV2(input_shape=[*IMAGE_SIZE, 3], include_top=False)
pretrained_model.trainable = False
model = tf.keras.Sequential([
pretrained_model,
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(5, activation='softmax')
])
שימו לב גם להגדרה pretrained_model.trainable = False. הוא מקפיא את המשקולות וההטיות של המודל שעבר אימון מראש, כך שאתם מאמנים רק את שכבת ה-softmax. בדרך כלל התהליך הזה כולל מספר קטן יחסית של משקלים, ואפשר לבצע אותו במהירות בלי להשתמש במערך נתונים גדול מאוד. עם זאת, אם יש לכם הרבה נתונים, למידת העברה יכולה לעבוד אפילו טוב יותר עם pretrained_model.trainable = True. המשקלים שאומנו מראש מספקים ערכים ראשוניים מצוינים, ועדיין אפשר להתאים אותם באמצעות האימון כדי שיתאימו יותר לבעיה שלכם.
לבסוף, שימו לב לשכבת Flatten() שנוספה לפני שכבת ה-softmax הצפופה. שכבות צפופות פועלות על וקטורים שטוחים של נתונים, אבל אנחנו לא יודעים אם זה מה שהמודל שאומן מראש מחזיר. לכן אנחנו צריכים לשטח את התמונה. בפרק הבא, כשנעמיק בארכיטקטורות של רשתות קונבולוציה, נסביר את פורמט הנתונים שמוחזר על ידי שכבות קונבולוציה.
הגישה הזו אמורה להניב רמת דיוק של כ-75%.
המוצר
מחברת הפתרון אתם יכולים להשתמש בו אם אתם נתקעים.
Keras Flowers transfer learning (solution).ipynb
מה נכלל
- 🤔 איך כותבים מסווג ב-Keras
- 🤓 מוגדר עם שכבת softmax אחרונה ועם הפסד אנטרופיה צולבת
- 😈 Transfer learning
- 🤔 אימון המודל הראשון
- 🧐 מעקב אחרי ההפסד והדיוק במהלך האימון
כדאי להקדיש רגע כדי לעבור על רשימת המשימות הבאה.
5. מעולה!
עכשיו אפשר לבנות מודל Keras. כדי ללמוד איך מרכיבים שכבות קונבולוציה, צריך להמשיך לשיעור ה-Lab הבא.
- פייפליינים במהירות TPU: tf.data.Dataset ו-TFRecords
- [THIS LAB] Your first Keras model, with transfer learning
- רשתות עצביות מתקפלות, עם Keras ויחידות TPU
- רשתות מתקפלות מודרניות, squeezenet, Xception, עם Keras ויחידות TPU
מעבדי TPU בפועל
מעבדי TPU ו-GPU זמינים ב-Cloud AI Platform:
- ב-Deep Learning VMs
- ב-AI Platform Notebooks
- במשימות של AI Platform Training
בסופו של דבר, נשמח לקבל משוב. נשמח לדעת אם משהו לא בסדר בשיעור ה-Lab הזה או אם יש לך רעיונות לשיפור. אפשר לשלוח משוב באמצעות בעיות ב-GitHub [ קישור למשוב].

|

