1. סקירה כללית
המדריך הזה עודכן ל-Tensorflow 2.2 !
ב-Codelab הזה תלמדו איך לפתח ולאמן רשת נוירונים שמזהה ספרות בכתב יד. בדרך, תשפרו את רשת הנוירונים ותשיגו 99% דיוק, וגם תגלו את הכלים בתחום שבו אנשי מקצוע מתחום הלמידה העמוקה משתמשים כדי לאמן את המודלים שלהם ביעילות.
ב-Codelab הזה נעשה שימוש במערך הנתונים MNIST, אוסף של 60,000 ספרות מתויגות, שהעסיק דורות של מומחי דוקטורט במשך כמעט שני עשורים. אפשר לפתור את הבעיה עם פחות מ-100 שורות של קוד Python או TensorFlow.
מה תלמדו
- מהי רשת נוירונים ואיך לאמן אותה
- איך בונים רשת נוירונים בסיסית בשכבה אחת באמצעות tf.keras
- איך מוסיפים עוד שכבות?
- איך להגדיר לוח זמנים לקצב הלמידה
- איך לבנות רשתות נוירונים קונבולוציה
- איך להשתמש בטכניקות של הרגולריזציה: נשירה, נירמול בכמות גדולה
- מה יותר מדי התאמה
למה תזדקק?
רק דפדפן. אפשר להעביר את הסדנה הזאת במלואה באמצעות Google Colaboratory.
משוב
נשמח לשמוע אם משהו השתבש בשיעור ה-Lab הזה או אם לדעתכם צריך לשפר אותו. אנחנו מטפלים במשוב דרך בעיות של GitHub [ feedback link].
2. התחלה מהירה של Google Colaboratory
בשיעור ה-Lab הזה נעשה שימוש ב-Google Colaboratory ולא נדרשת כל הגדרה מצידך. אפשר להריץ אותו מ-Chromebook. כדי להכיר את קובצי ה-notebook של Colab, צריך לפתוח את הקובץ שלמטה ולהפעיל את התאים.
הוראות נוספות מפורטות בהמשך:
בחירת הקצה העורפי של GPU
בתפריט Colab, בוחרים באפשרות סביבת זמן הריצה > צריך לשנות את הסוג של סביבת זמן הריצה ואז לבחור באפשרות GPU. החיבור לסביבת זמן הריצה יתבצע באופן אוטומטי בהפעלה הראשונה, או שאפשר להשתמש באפשרות Connect (התחברות) בפינה הימנית העליונה.
ביצוע Notebook
כדי להפעיל תאים בכל פעם, לוחצים על תא באמצעות מקש Shift-ENTER. אפשר גם להריץ את כל ה-notebook באמצעות סביבת זמן הריצה > הפעלה של הכול
תוכן העניינים
בכל המחברות יש תוכן עניינים. אפשר לפתוח אותו באמצעות החץ השחור שמימין.
תאים מוסתרים
בחלק מהתאים תוצג רק הכותרת שלהם. זוהי תכונת notebook ספציפית ל-Colab. אפשר ללחוץ עליהן לחיצה כפולה כדי לראות את הקוד שבפנים, אבל בדרך כלל זה לא מעניין במיוחד. בדרך כלל תומכים בפונקציות או בפונקציות חזותיות. עדיין צריך להריץ את התאים האלה כדי להגדיר את הפונקציות שבתוכה.
3. אימון רשת נוירונים
קודם נצפה ברכבת של רשת נוירונים. עליכם לפתוח את ה-notebook שלמטה ולעבור על כל התאים. לא לשים לב לקוד עדיין, נתחיל להסביר אותו מאוחר יותר.
בזמן שמפעילים את ה-notebook, מתמקדים ברכיבים החזותיים. הסברים מופיעים בהמשך.
נתוני אימון
יש לנו מערך נתונים של ספרות בכתב יד שתויגו כדי שנוכל לדעת מה כל תמונה מייצגת, כלומר מספר בין 0 ל-9. במחברת תראו קטע:
רשת הנוירונים שנבנה מסווגת את הספרות בכתב יד ב-10 המחלקות שלהן (0, .., 9). הוא עושה זאת על סמך פרמטרים פנימיים שנדרשים להם ערך נכון כדי שהסיווג יפעל כראוי. 'הערך הנכון' הזה נלמדת באמצעות תהליך אימון שדורש 'מערך נתונים ממותגים' עם תמונות והתשובות הנכונות שמשויכות אליהן.
איך אנחנו יכולים לדעת אם רשת הנוירונים המאומנת מניבה ביצועים טובים או לא? שימוש במערך הנתונים לאימון כדי לבדוק את הרשת הוא רמאות. הוא כבר ראה את מערך הנתונים הזה פעמים רבות במהלך האימון, והוא בהחלט הכי מוצלח בו. אנחנו זקוקים למערך נתונים מתויג נוסף, שמעולם לא נראה במהלך האימון, כדי להעריך את 'העולם האמיתי' לביצועי הרשת. הוא נקרא 'מערך נתונים של אימות'
הדרכה
עם התקדמות האימון, אצוות נתוני אימון אחת בכל פעם, הפרמטרים הפנימיים של המודל מתעדכנים והמודל משתפר בזיהוי הספרות בכתב יד. אפשר לראות אותו בתרשים האימון:
בצד ימין, רמת ה"דיוק" הוא פשוט אחוז הספרות שמזוהות בצורה נכונה. היא עולה ככל שהאימון מתקדם, וזה טוב.
בצד ימין אפשר לראות את "ההפסד". כדי להוביל את ההדרכה, נגדיר 'הפסד' שמייצג עד כמה המערכת מזהה את הספרות ומנסה לצמצם את הערך הזה. מה שאתם רואים כאן הוא שההפסד של האימון ושל נתוני האימות פוחת – וזה טוב. זה אומר שרשת הנוירונים לומדת.
ציר ה-X מייצג את מספר ה"תקופות" או איטרציות על כל מערך הנתונים.
חיזויים
אחרי אימון המודל, אנחנו יכולים להשתמש בו כדי לזהות ספרות בכתב יד. בתרשים הבא תוכלו לראות את רמת הביצועים ביחס למספר ספרות שעברו רינדור מגופנים מקומיים (שורה ראשונה), ולאחר מכן 10,000 ספרות במערך נתוני האימות. הכיתה החזויה מופיעה מתחת לכל ספרה, באדום אם היא שגויה.
כמו שאפשר לראות, המודל הראשוני לא טוב במיוחד אבל עדיין מזהה ספרות מסוימות בצורה נכונה. רמת הדיוק הסופית של האימות היא כ-90%, וזה לא כל כך גרוע ביחס למודל הפשטות שבו אנחנו מתחילים, אבל המשמעות היא שעדיין מחמיצים 1,000 ספרות אימות מתוך ה-10,000. מדובר בהרבה יותר אפשרויות, ולכן נראה שכל התשובות שגויות (אדום).
חיישנים
הנתונים מאוחסנים במטריצות. תמונה בגווני אפור בגודל 28x28 פיקסלים מתאימה למטריצה דו-ממדית של 28x28. אבל כדי ליצור תמונה צבעונית, אנחנו צריכים מידות נוספות. לכל פיקסל יש 3 ערכים של צבעים (אדום, ירוק, כחול), לכן יש צורך בטבלה תלת-ממדית עם מידות [28, 28, 3]. כדי לאחסן קבוצה של 128 תמונות צבעוניות, יש צורך בטבלה ארבע ממדית עם מימדים [128, 28, 28, 3].
הטבלאות הרב-ממדיות האלה נקראות "tensors", ורשימת המאפיינים שלהן היא הצורה שלהן.
4. [מידע]: רשתות נוירונים בשלב 101
בקצרה
אם כל המונחים המודגשים בפסקה הבאה כבר מוכרים לכם, תוכלו לעבור לתרגיל הבא. אם אתם רק מתחילים בתחום הלמידה העמוקה, אתם מוזמנים להמשיך לקרוא.
עבור מודלים שנוצרו כרצף של שכבות, Keras מציעה את Sequential API. לדוגמה, אפשר לכתוב ב-Keras מסווג תמונות שמשתמש בשלוש שכבות צפופות כך:
model = tf.keras.Sequential([
tf.keras.layers.Flatten(input_shape=[28, 28, 1]),
tf.keras.layers.Dense(200, activation="relu"),
tf.keras.layers.Dense(60, activation="relu"),
tf.keras.layers.Dense(10, activation='softmax') # classifying into 10 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, ... )
שכבה אחת צפופה
ספרות בכתב יד במערך הנתונים של MNIST הן תמונות בגווני אפור בגודל 28x28 פיקסלים. הגישה הפשוטה ביותר לסיווג שלהם היא להשתמש בפיקסלים 28x28=784 פיקסלים כקלט לרשת נוירונים עם שכבה אחת.
כל 'נוירון' ברשת נוירונים מבצע סכום משוקלל של כל ערכי הקלט שלו, ומוסיף קבוע שנקרא 'הטיה' ולאחר מכן מזינים את התוצאה באמצעות "פונקציית הפעלה" לא לינארית. "משקולות" ו"הטיות" הם פרמטרים שייקבעו באמצעות אימון. הם מופעלים עם ערכים אקראיים בהתחלה.
התמונה שלמעלה מייצגת רשת נוירונים בשכבה אחת עם 10 נוירונים מסוג פלט, כי אנחנו רוצים לסווג ספרות ל-10 מחלקות (0 עד 9).
עם כפל במטריצה
כך יכולה להיות שכבה של רשת נוירונים, שמעבדת אוסף של תמונות, על ידי הכפלה של מטריצה:
באמצעות העמודה הראשונה של המשקולות במטריצת המשקולות W, אנחנו מחשבים את הסכום המשוקלל של כל הפיקסלים בתמונה הראשונה. הסכום הזה תואם לנוירון הראשון. בעזרת העמודה השנייה של המשקולות, אנחנו עושים את אותו הדבר עבור הנויראון השני וכן הלאה, עד לנוירון העשירי. לאחר מכן אנחנו יכולים לחזור על הפעולה עבור 99 התמונות הנותרות. אם קוראים למטריצה X שמכילה את 100 התמונות שלנו, כל הסכומים המשוקללים של 10 הנוירונים, המחושבים ל-100 תמונות, הם פשוט X.W, הכפלה של המטריצה.
עכשיו כל נוירון צריך להוסיף את ההטייה שלו (קבוע). מכיוון שיש לנו 10 נוירונים, יש לנו 10 קבועי הטיה. נקרא לווקטור הזה של 10 ערכים B. צריך להוסיף אותו לכל שורה במטריצה שחושבה קודם לכן. קצת קסם שנקרא 'שידור' אנחנו נכתוב את זה עם סימן פלוס פשוט.
בסופו של דבר אנחנו מחילים פונקציית הפעלה, לדוגמה "softmax" (ראו הסבר בהמשך) ומשיגים את הנוסחה שמתארת רשת נוירונים עם שכבה אחת, המוחלת על 100 תמונות:
ב-Keras
עם ספריות של רשת נוירונים ברמה גבוהה כמו Keras, לא נצטרך ליישם את הנוסחה הזו. עם זאת, חשוב להבין ששכבה של רשת נוירונים היא קבוצה של כפל ותוספות. ב-Keras, שכבה צפופה תיכתב כך:
tf.keras.layers.Dense(10, activation='softmax')
ניתוח מעמיק
זה טריוויאלי לשרשר שכבות של רשת נוירונים. השכבה הראשונה מחשבת משקלים משוקללים של פיקסלים. השכבות הבאות מחשבות את הסכומים המשוקללים של תפוקות השכבות הקודמות.
ההבדל היחיד, מלבד מספר הנוירונים, יהיה הבחירה של פונקציית ההפעלה.
פונקציות הפעלה: relu, softmax ו-sigmoid
בדרך כלל צריך להשתמש ב-"relu" את פונקציית ההפעלה לכל השכבות חוץ מהאחרונה. השכבה האחרונה, במסווג, תשתמש ב-"softmax" הפעלה.
שוב, 'נוירון' מחשב סכום משוקלל של כל ערכי הקלט, מוסיף ערך שנקרא 'הטיה' ומזינה את התוצאה באמצעות פונקציית ההפעלה.
פונקציית ההפעלה הפופולרית ביותר נקראת "RELU" עבור יחידה לינארית שעברה תיקון. זוהי פונקציה פשוטה מאוד כפי שניתן לראות בתרשים שלמעלה.
פונקציית ההפעלה המסורתית ברשתות נוירונים הייתה sigmoid, אבל relu הוכח כי יש לו מאפייני שילוב טובים יותר כמעט בכל מקום, והוא מועדף כעת.
הפעלת Softmax לסיווג
בשכבה האחרונה של רשת הנוירונים שלנו יש 10 נוירונים כי אנחנו רוצים לסווג ספרות בכתב יד ל-10 מחלקות (0,.9). הפלט שלה צריך להיות 10 מספרים בין 0 ל-1 שמייצגים את ההסתברות שמספרה זו תהיה 0, 1, 2 וכן הלאה. לשם כך, בשכבה האחרונה נשתמש בפונקציית הפעלה שנקראת "softmax".
כדי להחיל softmax על וקטור, המערכת לוקחת את המעריכי של כל רכיב ואז מנרמלת את הווקטור, בדרך כלל על ידי חלוקתו ב-L1 שלו. נורמה (כלומר, סכום הערכים המוחלטים), כך שערכים מנורמלים מסתכמים ב-1 ויכולים להתפרש כהסתברויות.
הפלט של השכבה האחרונה, לפני ההפעלה, נקרא לפעמים "logits". אם הווקטור הזה הוא L = [L0, L1, L2, L3, L4, L5, L6, L7, L8, L9], אז:
הפסד חוצה-אנטרופיה
עכשיו, כשרשת הנוירונים שלנו מייצרת חיזויים מתמונות קלט, אנחנו צריכים למדוד עד כמה הן טובות, כלומר המרחק בין מה שהרשת אומרת לנו לבין התשובות הנכונות, שנקראות גם 'תוויות'. חשוב לזכור שיש לנו תוויות נכונות לכל התמונות במערך הנתונים.
כל מרחק מתאים, אבל כשמדובר בבעיות סיווג, המונח "מרחק בין אנטרופיה" נקרא היא היעילה ביותר. נקרא לשגיאה הזו 'הפסד' פונקציה:
ירידה הדרגתית
"אימון" רשת הנוירונים כוללת למעשה שימוש בתמונות ובתוויות לאימון כדי להתאים משקולות והטיות ולצמצם את פונקציית האובדן החוצה-אנטרופיה. כך זה עובד.
ה-cross-entropy הוא פונקציה של משקולות, הטיות, פיקסלים של תמונת האימון והסיווג הידוע שלה.
אם נחשב את הנגזרות החלקיות של ה-Cross-entropy ביחס לכל המשקולות ולכל ההטיות, נקבל 'הדרגתיות', המחושב עבור תמונה, תווית וערך נוכחי של משקולות והטיות. זכרו שיש לנו מיליוני משקולות והטיות, ולכן חישוב ההדרגתיות נשמע כמו עבודה רבה. לשמחתנו, TensorFlow עושה את זה בשבילנו. התכונה המתמטית של שיפוע הוא שהוא מצביע "למעלה". מכיוון שאנחנו רוצים להגיע למקום שבו ה-cross-entropy הוא נמוך, אנחנו הולכים בכיוון ההפוך. אנחנו מעדכנים את המשקל וההטיות לפי חלק מההדרגתיות. לאחר מכן אנחנו מבצעים את אותו הדבר שוב ושוב באמצעות הקבוצות הבאות של תמונות ותוויות לאימון, בלולאת אימון. אנו מקווים שזה מתכנס למקום שבו ה-cross-entropy הוא מינימלי, אם כי שום דבר לא מבטיח שהמינימום הזה ייחודי.
מיני-אצווה ומומנטום
ניתן לחשב את ההדרגתיות על תמונה אחת לדוגמה בלבד ולעדכן את המשקלים וההטיות באופן מיידי, אבל אם עושים זאת על קבוצה של, לדוגמה, 128 תמונות יוצר הדרגתי שמייצג טוב יותר את המגבלות שהוטלו על ידי תמונות לדוגמה שונות ולכן סביר להניח שהן יתמזגו מהר יותר אל הפתרון. גודל המיני-אצווה הוא פרמטר שניתן לשנות.
השיטה הזו, שלפעמים נקראת 'ירידה הדרגתית אקראית' יש יתרון נוסף פרגמטי יותר: עבודה עם אצוות פירושה גם עבודה עם מטריצות גדולות יותר, ובדרך כלל קל יותר לבצע אופטימיזציה שלהן במעבדי GPU ובמעבדי TPU.
עם זאת, ההתכנסות עדיין יכולה להיות קצת כאוטית והיא יכולה אפילו לעצור אם הווקטור ההדרגתי הוא אפסים. האם זה אומר שמצאנו ערך מינימום? לא תמיד. רכיב הדרגתי יכול להיות אפס במינימום או במקסימום. בווקטור הדרגתי שכולל מיליוני רכיבים, אם כולם אפסים, ההסתברות שכל אפסים תואמת למינימום ואף אחד מהם לנקודה מקסימלית לא די קטן. במגוון מימדים, נקודות אוכף הן נפוצות ולא רוצים לעצור בהן.
איור: נקודת אוכף. ההדרגתיות היא 0 אך הוא לא ערך מינימלי בכל הכיוונים. (קרדיט תמונה Wikimedia: By Nicoguaro – Own work, CC BY 3.0)
הפתרון הוא להוסיף קצת תנע לאלגוריתם האופטימיזציה כדי שהוא יוכל לשוט מעבר לנקודות האופל בלי לעצור.
מילון מונחים
אצווה או מיני-אצווה: האימון תמיד מתבצע על קבוצות של נתוני אימון ותוויות. הפעולה הזו עוזרת לאלגוריתם להתמזג. "האצווה" הוא בדרך כלל המימד הראשון של מזיני הנתונים. לדוגמה, Tensor של צורה [100, 192, 192, 3] מכיל 100 תמונות של 192x192 פיקסלים עם שלושה ערכים לכל פיקסל (RGB).
הפסד באנטרופיה אחת: פונקציית הפסד מיוחדת שמשמשת לעיתים קרובות במסווגים.
שכבה צפופה: שכבה של נוירונים שבה כל נוירונים מחובר לכל נוירונים בשכבה הקודמת.
תכונות: ערכי הקלט של רשת נוירונים נקראים לפעמים 'תכונות'. היכולת להבין אילו חלקים של מערך נתונים (או שילובי חלקים) להזין ברשת נוירונים כדי לקבל תחזיות טובות נקראת 'הנדסת תכונות'.
labels: שם אחר ל-"classes" או נכונות תשובות בעייתיות בסיווג בפיקוח
קצב למידה: החלק מתוך ההדרגתיות שבו מתעדכנים המשקולות וההטיות בכל איטרציה של לולאת האימון.
logits: הפלט של שכבת נוירונים לפני הפעלת פונקציית ההפעלה נקראים 'logits'. המונח מגיע מהפונקציה הלוגיסטית. נקרא גם "פונקציית sigmoid" שהיתה בעבר פונקציית ההפעלה הפופולרית ביותר. "פלט נוירונים לפני פונקציה לוגיסטית" קוצר ל-"logit".
loss (הפסד): פונקציית השגיאה שמשווה בין פלטי רשת נוירונים לתשובות הנכונות
neuron: מחשב את הסכום המשוקלל של הקלט, מוסיף הטיה ומזין את התוצאה באמצעות פונקציית הפעלה.
קידוד חם אחד: מחלקה 3 מתוך 5 מקודדת בתור וקטור של 5 רכיבים, כל אפסים חוץ מהאפס השלישי שהוא 1.
relu: יחידה לינארית מתוקנת. פונקציית הפעלה פופולרית לנוירונים.
sigmoid: פונקציית הפעלה נוספת שבעבר הייתה פופולרית ועדיין שימושית במקרים מיוחדים.
softmax: פונקציית הפעלה מיוחדת שפועלת על וקטור, מגדילה את ההפרש בין הרכיב הגדול ביותר לבין כל האחרים, וגם מנרמלת את הווקטור לסכום של 1 כדי שאפשר יהיה לפרש אותו כווקטור של הסתברויות. משמש כשלב האחרון במסווגים.
tensor: "tensor" דומה למטריצה, אבל עם מספר שרירותי של מאפיינים. טנזור חד-ממדי הוא וקטור. מפריד דו-ממדי הוא מטריצה. לאחר מכן יכולים להיות רכיבי Tensor עם 3, 4, 5 או יותר מאפיינים.
5. קדימה, מתחילים
נחזור למחברת המחקר והפעם נקרא את הקוד.
בואו נעבור על כל התאים ב-notebook הזה.
התא 'פרמטרים'
גודל האצווה, מספר תקופות האימון והמיקום של קובצי הנתונים מוגדרים כאן. קובצי נתונים מתארחים בקטגוריה של Google Cloud Storage (GCS), ולכן הכתובת שלהם מתחילה ב-gs://
ייבוא תא
כל ספריות Python הנדרשות מיובאות לכאן, כולל TensorFlow וגם matplotlib להמחשות.
התא "כלים להצגה חזותית [RUN ME]****"
התא הזה מכיל קוד תצוגה לא מעניין. כברירת מחדל הוא מכווץ, אבל אפשר ללחוץ עליו לחיצה כפולה כדי לפתוח אותו ולעיין בקוד.
תא "tf.data.Dataset: ניתוח קבצים והכנת מערכי נתונים של אימון ואימות"
התא הזה השתמש ב-API tf.data.Dataset כדי לטעון את מערך הנתונים של MNIST מקובצי הנתונים. אין צורך להקדיש יותר מדי זמן לתא הזה. אם אתם מתעניינים ב-API של tf.data.Dataset, תוכלו להיעזר במדריך הזה: צינורות נתונים במהירות TPU. בינתיים, הפרטים הבסיסיים הם:
תמונות ותוויות (תשובות נכונות) ממערך הנתונים של MNIST מאוחסנות ברשומות באורך קבוע ב-4 קבצים. ניתן לטעון את הקבצים באמצעות פונקציית הרשומה הקבועה הייעודית:
imagedataset = tf.data.FixedLengthRecordDataset(image_filename, 28*28, header_bytes=16)
עכשיו יש לנו מערך נתונים של בייטים של תמונות. צריך לפענח אותם לתמונות. לשם כך אנחנו מגדירים פונקציה. התמונה לא דחוסה, כך שהפונקציה לא צריכה לפענח שום דבר (decode_raw
בעצם לא עושה כלום). לאחר מכן התמונה מומרת לערכים של נקודה צפה (floating-point) בין 0 ל-1. נוכל לשנות אותה כאן כתמונה דו-ממדית, אבל למעשה נשאיר אותה כמערך פיקסלים בגודל 28*28 כי זה מה שצפוי לשכבה הראשונית שלנו.
def read_image(tf_bytestring):
image = tf.io.decode_raw(tf_bytestring, tf.uint8)
image = tf.cast(image, tf.float32)/256.0
image = tf.reshape(image, [28*28])
return image
אנחנו מחילים את הפונקציה הזו על מערך הנתונים באמצעות .map
ומקבלים מערך נתונים של תמונות:
imagedataset = imagedataset.map(read_image, num_parallel_calls=16)
אנחנו מבצעים קריאה ופענוח מאותו סוג בשביל תוויות, ואנחנו .zip
תמונות ותוויות יחד:
dataset = tf.data.Dataset.zip((imagedataset, labelsdataset))
עכשיו יש לנו מערך נתונים של זוגות (תמונה, תווית). זה מה שאנחנו מצפים מהמודל שלנו. אנחנו עדיין לא מוכנים להשתמש בו בפונקציית האימון:
dataset = dataset.cache()
dataset = dataset.shuffle(5000, reshuffle_each_iteration=True)
dataset = dataset.repeat()
dataset = dataset.batch(batch_size)
dataset = dataset.prefetch(tf.data.experimental.AUTOTUNE)
ה-API של tf.data.Dataset כולל את כל פונקציית השירות הדרושה להכנת מערכי נתונים:
.cache
שומר את מערך הנתונים ב-RAM במטמון. זהו מערך נתונים קטנטן ולכן הוא יעבוד. ההשמעה האקראית של .shuffle
גורמת למאגר נתונים זמני של 5,000 רכיבים. חשוב לסדר את נתוני האימון בצורה אקראית. הפונקציה .repeat
מחזירה את מערך הנתונים בלולאה. נעבור עליו אימונים מספר פעמים (כמה תקופות של זמן מערכת). .batch
משלבת מספר תמונות ותוויות לתוך קבוצת מיני-אצווה. לבסוף, .prefetch
יכול להשתמש במעבד (CPU) כדי להכין את האצווה הבאה בזמן אימון ה-GPU הנוכחי.
מערך הנתונים לאימות מוכן באופן דומה. עכשיו אנחנו מוכנים להגדיר מודל ולהשתמש במערך הנתונים הזה כדי לאמן אותו.
תא "Keras Model"
כל המודלים שלנו יהיו רצפים ישרים של שכבות, כדי שנוכל להשתמש בסגנון tf.keras.Sequential
כדי ליצור אותם. בהתחלה יש כאן שכבה אחת צפופה. יש בו 10 נוירונים כי אנחנו מסווגים ספרות בכתב יד ל-10 כיתות. הוא משתמש ב-"softmax" מפני שהיא השכבה האחרונה בסיווג.
מודל Keras גם צריך לדעת את הצורה של הקלט שלו. אפשר להשתמש במדיניות tf.keras.layers.Input
כדי להגדיר אותה. כאן, וקטורים של קלט הם וקטורים שטוחים של ערכי פיקסלים באורך 28*28.
model = tf.keras.Sequential(
[
tf.keras.layers.Input(shape=(28*28,)),
tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='sgd',
loss='categorical_crossentropy',
metrics=['accuracy'])
# print model layers
model.summary()
# utility callback that displays training curves
plot_training = PlotTraining(sample_rate=10, zoom=1)
הגדרת המודל מתבצעת ב-Keras באמצעות הפונקציה model.compile
. כאן אנחנו משתמשים בכלי האופטימיזציה הבסיסי 'sgd'
(Stochastic Gradient Descent). מודל סיווג דורש פונקציית אובדן חוצה-אנטרופיה, שנקראת 'categorical_crossentropy'
ב-Keras. לסיום, אנחנו מבקשים מהמודל לחשב את המדד 'accuracy'
, שהוא אחוז התמונות שסווגו בצורה נכונה.
Keras מציע את כלי השירות הנחמד מאוד model.summary()
שמדפיס את הפרטים של המודל שיצרתם. המדריך מהסוג הזה הוסיף את הכלי PlotTraining
(מוגדר בתא 'כלי עזר להמחשה'), שיוצגו בו עקומות אימון שונות במהלך האימון.
תא 'אימון ואימות של המודל'
כאן מתבצעת האימון, על ידי קריאה ל-model.fit
והעברת מערכי הנתונים של האימון והאימות. כברירת מחדל, Keras מריץ סבב אימות בסוף כל תקופה של זמן מערכת.
model.fit(training_dataset, steps_per_epoch=steps_per_epoch, epochs=EPOCHS,
validation_data=validation_dataset, validation_steps=1,
callbacks=[plot_training])
ב-Keras אפשר להוסיף התנהגויות מותאמות אישית במהלך האימון באמצעות קריאות חוזרות (callback). כך הטמענו בסדנה הזאת את תרשים האימון שמתעדכן באופן דינמי.
המחשה חזותית של חיזויים בתא
אחרי אימון המודל, נוכל לקבל ממנו חיזויים על ידי קריאה ל-model.predict()
:
probabilities = model.predict(font_digits, steps=1)
predicted_labels = np.argmax(probabilities, axis=1)
כאן הכנו קבוצה של ספרות מודפסות שעברו רינדור מגופנים מקומיים, למטרת בדיקה. חשוב לזכור שרשת הנוירונים מחזירה וקטור של 10 הסתברויות מה-softmax, כדי לקבל את התווית, אנחנו צריכים לגלות מהי הסבירות הגבוהה ביותר. np.argmax
מספריית numpy עושה את זה.
כדי להבין למה צריך את הפרמטר axis=1
, חשוב לזכור שעיבדנו מקבץ של 128 תמונות ולכן המודל מחזיר 128 וקטורים של הסתברויות. הצורה של הפרמטר img_tensor היא [128, 10]. אנחנו מחשבים את ערך ה-argmax על פני 10 ההסתברויות שהוחזרו לכל תמונה, כך ש-axis=1
(הציר הראשון הוא 0).
המודל הפשוט הזה כבר מזהה 90% מהספרות. לא רע, אבל עכשיו תשפר את הביצועים באופן משמעותי.
6. הוספת שכבות
כדי לשפר את דיוק הזיהוי, נוסיף עוד שכבות לרשת הנוירונים.
אנחנו משאירים את ה-softmax כפונקציית ההפעלה בשכבה האחרונה, כי זו הסיבה שהכי מתאימה לסיווג. בשכבות ביניים, נשתמש בפונקציית ההפעלה הקלאסית ביותר: sigmoid:
לדוגמה, המודל שלך יכול להיראות כך (אל תשכחו את הפסיקים, tf.keras.Sequential
לוקח רשימת שכבות שמופרדת בפסיקים):
model = tf.keras.Sequential(
[
tf.keras.layers.Input(shape=(28*28,)),
tf.keras.layers.Dense(200, activation='sigmoid'),
tf.keras.layers.Dense(60, activation='sigmoid'),
tf.keras.layers.Dense(10, activation='softmax')
])
עיון ב'סיכום' של המודל. הוא כולל עכשיו לפחות פי 10 פרמטרים. הוא אמור להיות פי 10 יותר טוב! אבל מסיבה כלשהי לא ...
נראה שהאובדן חמק גם הוא דרך הגג. משהו לא בדיוק בסדר.
7. טיפול מיוחד ברשתות עמוקות
בדיוק חוויתם רשתות נוירונים, כמו שאנשים נהגו לעצב אותן בשנות ה-80 וה-90. לא פלא שהם ויתרו על הרעיון, ועצרו את מה שנקרא 'חורף של AI'. ואכן, ככל שמוסיפים שכבות נוספות, כך גדל הסיכוי להתמזג עם רשתות נוירונים.
מסתבר שרשתות נוירונים עמוקות עם הרבה שכבות (20, 50, אפילו 100 היום) יכולות לעבוד ממש טוב, בתנאי שכמה טריקים מתמטיים מלוכלכים לגרום להן להתמזג. הגילוי של הטריקים הפשוטים האלה הוא אחת מהסיבות לחזרתיות של הלמידה העמוקה בעשור השני של המאה ה-20.
הפעלה של RELU
פונקציית ההפעלה sigmoid היא למעשה בעייתית ברשתות עמוקות. הוא דוחה את כל הערכים בין 0 ל-1 וכשאתם עושים זאת שוב ושוב, פלטי הנוירונים וההדרגתיות שלהם עלולים להיעלם לחלוטין. היא הוזכרה מסיבות היסטוריות, אבל ברשתות מודרניות נעשה שימוש ב-RELU (יחידה לינארית מוצפנת) שנראה כך:
מצד שני, ל-relu יש נגזרת של 1, לפחות בצד ימין. עם הפעלת RELU, גם אם ההדרגתיות המגיעות מתאי נוירונים מסוימים יכולות להיות אפס, תמיד יהיו אחרים שנותנים הדרגתי ברור שאינו אפס והאימון יכול להמשיך בקצב טוב.
כלי אופטימיזציה טוב יותר
במרחבים עם ממדים גבוהים מאוד כמו כאן — יש לנו 10,000 משקולות והטיות — "נקודות אוכף". בתדירות גבוהה. אלה נקודות שאינן נקודות מינימום מקומיות, אבל שבהן ההדרגתיות היא בכל זאת אפס והכלי לאופטימיזציה של הורדת ההדרגתיות נשאר תקוע שם. ב-TensorFlow יש מגוון רחב של כלי אופטימיזציה זמינים, כולל כאלה שעובדים עם כמות אינרציה ומשייטים בבטחה מעבר לנקודות אוכף.
אתחולים אקראיים
האומנות של אתחול הטיות של משקולות לפני אימון היא תחום מחקר בפני עצמו, שכולל מספר מאמרים שמתפרסמים בנושא. כאן אפשר לראות את כל האתחולים שזמינים ב-Keras. למרבה המזל, Keras עושה את הדבר הנכון כברירת מחדל ומשתמשת באתחול 'glorot_uniform'
, שהוא הטוב ביותר כמעט בכל המקרים.
אתם לא צריכים לעשות שום דבר, כי Keras כבר עושה את הדבר הנכון.
NaN ...
נוסחת ה-cross-entropy כוללת לוגריתם ו-Log(0) הוא Not מספר (NaN, קריסה מספרית אם אתם מעדיפים). האם הקלט לקרוס-אנטרופיה יכול להיות 0? הקלט מגיע מ-softmax, שהוא בעצם מעריכי מעריכי ומעריכי הוא אף פעם לא אפס. אז אנחנו בטוחים!
בטוח? בעולם המתמטיקה היפהפה, נהיה בטוחים, אבל בעולם המחשבים, exp(-150), שמיוצג בפורמט float32, הוא אפס כפי שהוא מקבל והקריסה חוצה-אנטרופיה.
למרבה המזל, גם כאן לא צריך לעשות שום דבר, כי Keras מטפל בעניין הזה ומחשב את ה-softmax ולאחר מכן את ה-Cross-entropy בצורה זהירה במיוחד כדי להבטיח יציבות מספרית ולהימנע מה-NaN האימה.
הצלחת?
עכשיו אתם אמורים להגיע לרמת דיוק של 97%. המטרה בסדנה הזו היא להגיע באופן משמעותי ליותר מ-99%, אז כדאי להמשיך.
אם נתקעת, הנה הפתרון בשלב הזה:
8. דעיכה לאורך קצב הלמידה
אולי אפשר לנסות להתאמן מהר יותר? שיעור הלמידה שמוגדר כברירת מחדל בכלי האופטימיזציה של Adam הוא 0.001. שננסה להגדיל אותו?
נראה שמעבר מהיר יותר לא עוזר הרבה, ומה קורה עם כל הרעש הזה?
עקומות האימון מאוד רועשות בוחנות את שתי עקומות האימות: הן קופצים למעלה ולמטה. זה אומר שאנחנו מתקדמים מהר מדי. אנחנו יכולים לחזור למהירות הקודמת שעשינו, אבל יש דרך טובה יותר.
הפתרון הטוב הוא להתחיל במהירות ולפרק את קצב הלמידה באופן אקספוננציאלי. ב-Keras, אפשר לעשות זאת באמצעות הקריאה החוזרת (callback) של tf.keras.callbacks.LearningRateScheduler
.
קוד שימושי להעתקה-הדבקה:
# lr decay function
def lr_decay(epoch):
return 0.01 * math.pow(0.6, epoch)
# lr schedule callback
lr_decay_callback = tf.keras.callbacks.LearningRateScheduler(lr_decay, verbose=True)
# important to see what you are doing
plot_learning_rate(lr_decay, EPOCHS)
לא לשכוח להשתמש בlr_decay_callback
שיצרת. הוספה שלו לרשימת הקריאה החוזרת ב-model.fit
:
model.fit(..., callbacks=[plot_training, lr_decay_callback])
ההשפעה של השינוי הקטן הזה היא נפלאה. אפשר לראות שרוב הרעש נעלם, ורמת הדיוק בבדיקה גבוהה מ-98% באופן ממושך.
9. נשירה, התאמת יתר
נראה שהמודל ממש מתכנס עכשיו. בואו ננסה להעמיק עוד יותר.
זה עוזר?
לא ממש, רמת הדיוק עדיין תקועה ב-98%, כדאי לבחון את אובדן האימות. הוא עולה! אלגוריתם הלמידה פועל על נתוני אימון בלבד ומייעל את אובדן האימון בהתאם. המערכת אף פעם לא רואה נתוני אימות, ולכן לא מפתיע שאחרי זמן מה העבודה כבר לא משפיעה על אובדן האימות, שמפסיק לצנוח ולפעמים גם חוזר שוב ושוב.
אין לכך השפעה מיידית על יכולות הזיהוי של המודל בפועל, אבל הדבר ימנע ממך לבצע חזרות רבות, ובדרך כלל זהו סימן לכך שלאימון כבר אין השפעה חיובית.
הניתוק הזה נקרא בדרך כלל 'התאמת יתר' וכשרואים אותה, אפשר לנסות ליישם טכניקת הרגולריזציה שנקראת "נשירה". טכניקת הנשירה מצלמת נוירונים אקראיים בכל איטרציה של אימון.
זה עבד?
הרעש מופיע שוב (באופן לא מפתיע, בהתאם לאופן שבו פועלת הנשירה). נראה שאובדן האימות כבר לא הולך ומתקרב, אבל באופן כללי הוא גבוה יותר מאשר ללא נטישה. ורמת הדיוק של האימות ירדה קצת. זו תוצאה די מאכזבת.
נראה שנטישה לא הייתה הפתרון הנכון, או אולי 'התאמה מוגזמת' הוא מושג מורכב יותר וחלק מהגורמים שלו לא מאפשרים 'נטישה' לתקן?
מה זה 'התאמת יתר'? התאמת יתר מתרחשת כשרשת נוירונים לומדת "רע", בדרך שמתאימה לדוגמאות האימון אבל לא כל כך טובה בנתונים מהעולם האמיתי. יש טכניקות להסתגלות, כמו נטישה, שיכולות לאלץ את התלמידים ללמוד בדרך טובה יותר, אבל גם להתאמה יתר יש שורשים עמוקים יותר.
התאמת יתר בסיסית מתרחשת כאשר לרשת נוירונים יש יותר מדי דרגות חופש לפתרון הבעיה הנדון. נניח שיש לנו כל כך הרבה נוירונים שהרשת יכולה לאחסן בהם את כל תמונות האימון שלנו, ואז לזהות אותם לפי התאמת דפוסים. זה ייכשל לגמרי בנתונים מהעולם האמיתי. רשת נוירונים צריכה להיות מוגבלת במידה מסוימת כדי שיהיה עליה לכלול את מה שהיא לומדת במהלך האימון.
אם יש לכם מעט מאוד נתוני אימון, גם רשת קטנה יכולה ללמוד אותם בעל פה ותראו "התאמת יתר". באופן כללי, תמיד צריכים הרבה נתונים כדי לאמן רשתות נוירונים.
לבסוף, אם ביצעתם את כל הפעולות בספר, התנסו בגדלים שונים של רשת כדי לוודא שדרגות החופש שלו מוגבלות, החילו נשירה מסוימת וביצעתם אימון על כמות גדולה של נתונים, יכול להיות שעדיין תיתקעו ברמת ביצוע שלא נראה ששום דבר יכול לשפר. המשמעות היא שרשת הנוירונים, בצורתה הנוכחית, לא יכולה לחלץ מידע נוסף מהנתונים, כמו במקרה שלנו כאן.
זוכרים איך אנחנו משתמשים בתמונות שלנו השטוחות לווקטור אחד? זה היה ממש רעיון גרוע. ספרות בכתב יד עשויות מצורות, ומחקנו את פרטי הצורה כששטחנו את הפיקסלים. עם זאת, יש סוג של רשת נוירונים שיכולה לנצל מידע על צורות: רשתות מתקפלות. בואו ננסה אותם.
אם נתקעת, הנה הפתרון בשלב הזה:
10. [מידע] רשתות קונבולוציה
בקצרה
אם כל המונחים המודגשים בפסקה הבאה כבר מוכרים לכם, תוכלו לעבור לתרגיל הבא. אם אתם רק מתחילים להשתמש ברשתות נוירונים קונבולוציה, כדאי לקרוא את המשך המאמר.
איור: סינון תמונה עם שני פילטרים עוקבים שמורכבים מ-48 x 4 x 48 משקולות לכל אחד מהם.
כך נראית רשת עצבית מתקפלת פשוטה ב-Keras:
model = tf.keras.Sequential([
tf.keras.layers.Reshape(input_shape=(28*28,), target_shape=(28, 28, 1)),
tf.keras.layers.Conv2D(kernel_size=3, filters=12, activation='relu'),
tf.keras.layers.Conv2D(kernel_size=6, filters=24, strides=2, activation='relu'),
tf.keras.layers.Conv2D(kernel_size=6, filters=32, strides=2, activation='relu'),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(10, activation='softmax')
])
בשכבה של רשת קונבולוציונית, "נוירון" אחד מציג סכום משוקלל של הפיקסלים שנמצאים בדיוק מעליו, באזור קטן בלבד של התמונה. הוא מוסיף הטיה ומזין את הסכום באמצעות פונקציית הפעלה, בדיוק כמו שנירון בשכבה רגילה וצפיפות. לאחר מכן הפעולה הזו חוזרת על עצמה בכל התמונה תוך שימוש באותם משקלים. זכרו שבשכבות צפופות, לכל נוירון יש משקולות משלו. כאן יש "תיקון" אחד המשקולות מחליקות על פני התמונה בשני הכיוונים ("קובולציה"). הפלט כולל ערכים רבים ככל האפשר בתמונה (מספר הפיקסלים בתמונה (עם זאת, יש צורך במרווח פנימי מסוים בקצוות). זו פעולת סינון. באיור שלמעלה נעשה שימוש במסנן של משקולות 4x4x3=48.
עם זאת, 48 משקולות לא מספיקות. כדי להוסיף עוד דרגות חופש, אנחנו חוזרים על אותה פעולה עם קבוצת משקולות חדשה. הפעולה הזו תפיק קבוצה חדשה של פלט מסננים. שנקרא 'ערוץ' של פלטים באנלוגיה עם הערוצים R,G,B בתמונת הקלט.
אפשר לסכם את שתי קבוצות המשקולות (או יותר) כטנזור אחד על ידי הוספת מאפיין חדש. מתקבלת הצורה הגנרית של חיישן המשקולות לשכבה קונבולוציה. מאחר שמספר ערוצי הקלט והפלט הם פרמטרים, אנחנו יכולים להתחיל ליצור מקבצים ולשרשר שכבות של שכבות קונבולוציה.
איור: רשת עצבית מתקפלת משנה 'קוביות' של נתונים ל"קוביות" אחרות של נתונים.
קיפולים (קונבולציות) ברצף, צבירה מקסימלית
אם מבצעים את הקונבולוציות בקצב של 2 או 3, אפשר גם לכווץ את קוביית הנתונים שמתקבלת בממדים האופקיים שלה. אפשר לעשות זאת ב-2 דרכים נפוצות:
- קונבולציה זזה: מסנן הזזה כמו למעלה, אבל עם צעדים >1
- קיבוץ מקסימלי: חלון הזזה שמבצע את הפעולה MAX (בדרך כלל בתיקונים בגודל 2x2, שחוזר על עצמו כל 2 פיקסלים)
איור: החלקת חלון המחשוב ב-3 פיקסלים תוביל לפחות ערכי פלט. קונבולוציות חדות או צבירה מקסימלית (מקסימום בחלון של 2x2 עם החלקה בצעד של 2) הן דרך לכווץ את קוביית הנתונים במידות האופקיות.
השכבה הסופית
אחרי השכבה הקונבולוציה האחרונה, הנתונים מופיעים בצורת "קובייה". יש שתי דרכים להזין אותו דרך השכבה האחרונה, צפיפות.
השיטה הראשונה היא לשטח את קוביית הנתונים לווקטור ולאחר מכן להזין אותה לשכבת ה-softmax. לפעמים אפשר אפילו להוסיף שכבה צפופה לפני שכבת הsoftmax. בדרך כלל המחיר הזה יקר מבחינת מספר המשקולות. שכבה צפופה בקצה רשת קונבולוציה יכולה להכיל יותר ממחצית מהמשקל של כל רשת הנוירונים.
במקום להשתמש בשכבה צפופה ויקרה, אנחנו יכולים גם לפצל את הנתונים הנכנסים ב"קובייה" לחלקים רבים ככל האפשר, יש ממוצע של הערכים שלהם ולהזין אותם באמצעות פונקציית הפעלה מסוג Softmax. בשיטה הזו של בניית ראש הסיווג, עולה 0 משקלים. ב-Keras יש שכבה לשם: tf.keras.layers.GlobalAveragePooling2D()
.
מעבר לקטע הבא כדי לבנות רשת קונבולוציונית לבעיה הרצויה.
11. רשת קונבולוציה
תן לנו לבנות רשת קונבולוציה לזיהוי ספרות בכתב יד. נשתמש בשלוש שכבות מורכבות בחלק העליון, שכבת הקריאה המסורתית מסוג softmax בחלק התחתון, ונחבר אותן לשכבה אחת שמחוברת באופן מלא:
שימו לב שהשכבה השנייה והשלישית הגיעו ממפלגת אחת לשניים, ולכן הן גורמות לירידה במספר ערכי הפלט מ-28x28 ל-14x14 ואז ל-7x7.
בואו נכתוב את קוד Keras.
נדרשת תשומת לב מיוחדת לפני השכבה הקונבולוציה הראשונה. אכן, מצפה ל'קובייה' תלת-ממדית של נתונים, אך עד כה מערך הנתונים שלנו הוגדר לשכבות צפופות וכל הפיקסלים של התמונות ישולבו בווקטור. עלינו לשנות אותן בחזרה לתמונות בגודל 28x28x1 (ערוץ אחד לתמונות בגווני אפור):
tf.keras.layers.Reshape(input_shape=(28*28,), target_shape=(28, 28, 1))
אפשר להשתמש בשורה הזו במקום בשכבה tf.keras.layers.Input
שאיתה הייתה לך עד עכשיו.
ב-Keras, התחביר של שכבת קונבולוציה שמופעלת על ידי 'relu' הוא:
tf.keras.layers.Conv2D(kernel_size=3, filters=12, padding='same', activation='relu')
עבור קונבולציה עם שורות, כתבו:
tf.keras.layers.Conv2D(kernel_size=6, filters=24, padding='same', activation='relu', strides=2)
כדי לשטח קוביית נתונים לווקטור כדי שניתן יהיה לצרוך אותו בשכבה צפופה:
tf.keras.layers.Flatten()
ובשכבה הדחוסה, התחביר לא השתנה:
tf.keras.layers.Dense(200, activation='relu')
האם המודל שלך פרץ את מחסום הדיוק של 99%? די קרוב... אבל כדאי לבחון את עקומת אובדן האימות. האם המכשיר הזה מצלצל בפעמון?
יש לבחון גם את החיזויים. לראשונה, תוכלו לראות שרוב 10,000 הספרות של הבדיקה מזוהות בצורה נכונה. נשארו רק כ-41⁄2 שורות של זיהוי שגוי (כ-110 ספרות מתוך 10,000)
אם נתקעת, הנה הפתרון בשלב הזה:
12. עזיבה חוזרת
באימון הקודם יש סימנים ברורים להתאמת יתר (ועדיין הוא לא עומד ברמת דיוק של 99%). האם כדאי לנסות שוב להפסיק לקבל הודעות?
איך היה?
נראה שההחלטה שהתקבלה עבדה עכשיו. אובדן האימות כבר לא הולך ומצטמצם, והדיוק הסופי אמור להיות הרבה יותר מ-99%. מעולה!
בפעם הראשונה שניסינו להחיל נשירה, חשבנו שהייתה לנו בעיית התאמה מוגזמת, כשלמעשה הבעיה הייתה בארכיטקטורה של רשת הנוירונים. לא יכולנו להתקדם רחוק יותר בלי שכבות קונבולוציה, ולא הייתה שום אפשרות נטישה לצורך כך.
הפעם, נראה שהתאמת יתר היא הגורם לבעיה והנטישה עזרה בפועל. חשוב לזכור שיש הרבה דברים שעלולים לגרום לניתוק בין העקומות של איבוד האימון ואובדן האימות, והאובדן של האימות הולך ומצטמצם. התאמת יתר (יותר מדי דרגות חופש, ניצול לרעה של הרשת) היא רק אחת מהן. אם מערך הנתונים קטן מדי או שהארכיטקטורה של רשת הנוירונים לא מתאימה, יכול להיות שתראו התנהגות דומה בעקומות האובדן, אבל נשירה לא תעזור.
13. נירמול בכמות גדולה
לסיום, ננסה להוסיף נירמול בכמות גדולה.
זו התיאוריה. בפועל, צריך לזכור כמה כללים:
בינתיים ננגן לפי הספר ונוסיף שכבה של נורמה באצווה בכל שכבה של רשת נוירונים מלבד האחרונה. אין להוסיף אותו לפונקציית ה-softmax בשכבת זרימת הנתונים. הכלי לא יועיל לשם.
# Modify each layer: remove the activation from the layer itself.
# Set use_bias=False since batch norm will play the role of biases.
tf.keras.layers.Conv2D(..., use_bias=False),
# Batch norm goes between the layer and its activation.
# The scale factor can be turned off for Relu activation.
tf.keras.layers.BatchNormalization(scale=False, center=True),
# Finish with the activation.
tf.keras.layers.Activation('relu'),
מה רמת הדיוק עכשיו?
עם קצת שינוי קטן (BATCH_SIZE=64, הפרמטר 'דעיכה' של קצב הלמידה 0.666, שיעור הנטישה בשכבה 0.3) וקצת מזל, אפשר להגיע ל-99.5%. שיעור הלמידה וההתאמות שבוצעו בהתאם ל'שיטות המומלצות' לשימוש בנורמה באצווה:
- נורמה באצווה עוזרת לרשתות נוירונים להתמזג ובדרך כלל מאפשרת לאמן מהר יותר.
- נורמה באצווה היא שיטה רגולרית. בדרך כלל תוכלו להפחית את כמות הנטישה שבה אתם משתמשים, או אפילו לא להשתמש בנטישה בכלל.
ה-notebook של הפתרון כולל הרצת אימון של 99.5%:
14. מאמנים את הענן בחומרה חזקה: AI Platform
גרסה מותאמת לענן של הקוד מופיעה בתיקיית mlengine ב-GitHub והוראות להרצה של הקוד ב-Google Cloud AI Platform. כדי להריץ את החלק הזה צריך ליצור חשבון Google Cloud ולהפעיל את החיוב. המשאבים הדרושים להשלמת שיעור ה-Lab צריכים להיות קטנים משני דולרים (בהנחה של שעה אחת של זמן אימון על GPU אחד). כדי להכין את החשבון:
- יוצרים פרויקט ב-Google Cloud Platform ( http://cloud.google.com/console).
- הפעלת החיוב.
- מתקינים את כלי שורת הפקודה של GCP ( GCP SDK כאן).
- יוצרים קטגוריה של Google Cloud Storage (צריך להזין את האזור
us-central1
). הוא ישמש להגדרת קוד האימון ולאחסון המודל המאומן. - הפעילו את ממשקי ה-API הנדרשים וביקשו את המכסות הנדרשות (מריצים את פקודת האימון פעם אחת), ומקבלים הודעות שגיאה שמסבירות מה להפעיל).
15. מעולה!
בניתם את רשת הנוירונים הראשונה שלכם ואימוןם אותה ברמת דיוק של 99%. הטכניקות שנלמדו בדרך לא ספציפיות למערך הנתונים של MNIST, אלא נפוצות מאוד בעבודה עם רשתות נוירונים. כמתנה לפרידה, הנה "פתקי הצוק" כרטיס לשיעור ה-Lab, בגרסה מצוירת. אפשר להשתמש בו כדי לזכור את מה שלמדתם:
השלבים הבאים
- אחרי שהרשתות מחוברות באופן מלא ורשתות מורכבות, כדאי לבחון רשתות נוירונים חוזרות.
- כדי להריץ את האימון או את המסקנות שלכם בענן בתשתית מבוזרת, Google Cloud מספק AI Platform.
- לבסוף, אנחנו אוהבים לקבל משוב. נשמח לשמוע אם משהו השתבש בשיעור ה-Lab הזה או אם לדעתכם צריך לשפר אותו. אנחנו מטפלים במשוב דרך בעיות של GitHub [ feedback link].
המחבר: מרטין גורנרטוויטר: @martin_gorner |
כל התמונות המצוירות שנמצאות בשיעור ה-Lab הזה: alexpokusay / 123RF תמונות ממאגר