איך אפשר לנפות באגים ולשפר את האופטימיזציה?
סיכום: אם המודל נתקל בקשיים באופטימיזציה, חשוב לפתור אותם לפני שמנסים לבצע פעולות אחרות. אבחון ותיקון של כשלים באימון הוא תחום מחקר פעיל.
![תרשים שמשווה בין Standard WideResNet ל-Stride 1x1 WideResNet.
ציר ה-y הוא שיעור שגיאות הבדיקה וציר ה-X הוא שיעור הלמידה הבסיסי.
ב-Standard WideResNet יש ירידה הדרגתית ב- TestErrorRate
ככל שקצב הלמידה הבסיסי עולה. לעומת זאת, ב-Stride WideResNet
יש תנודות משמעותיות ככל ששיעור הלמידה הבסיסי עולה.](https://developers.google.cn/static/machine-learning/guides/deep-learning-tuning-playbook/images/stride_instability.png?authuser=8&hl=he)
שימו לב לנקודות הבאות לגבי איור 4:
- שינוי השלבים לא פוגע בביצועים בקצבי למידה נמוכים.
- שיעורי למידה גבוהים כבר לא מאומנים היטב בגלל חוסר היציבות.
- החלה של 1,000 שלבים של הכנה לקראת הלמידה פותרת את התופעה הספציפית של חוסר היציבות, ומאפשרת אימון יציב עם קצב למידה מקסימלי של 0.1.
זיהוי עומסי עבודה לא יציבים
עומס עבודה מסוים הופך לבלתי יציב אם קצב הלמידה גדול מדי. חוסר יציבות היא בעיה רק כשהיא מאלצת אתכם להשתמש בקצב למידה קטן מדי. כדאי להבחין בין לפחות שני סוגים של חוסר יציבות באימון:
- חוסר יציבות באתחול או בתחילת האימון.
- אי יציבות פתאומית באמצע האימון.
אתם יכולים לנקוט גישה שיטתית לזיהוי בעיות יציבות בעומס העבודה על ידי ביצוע הפעולות הבאות:
- מסרוקים את שיעורי הלמידה ומוצאים את שיעור הלמידה הטוב ביותר*.
- תארו את עקומות אובדן האימונים של שיעורי הלמידה קצת מעל רמת ה-lr*.
- אם שיעורי הלמידה > lr* מראים חוסר יציבות של אובדן (אובדן לא גדל בתקופת האימון), תיקון חוסר היציבות בדרך כלל משפר את האימון.
רשמו את הנורמה L2 של ההדרגתיות המלאה במהלך האימון, כי ערכים חריגים יכולים לגרום לחוסר יציבות כוזבת באמצע האימון. המידע הזה יכול ליידע את מידת האגרסיביות של חיתוך הדרגתיים או עדכוני משקל.
הערה: בחלק מהמודלים מופיעה אי-יציבות בשלב מוקדם מאוד, ובעקבותיה מתבצע שחזור, שמוביל לאימון איטי אך יציב. לוחות זמנים נפוצים להערכה עלולים לפספס את הבעיות האלה, כי הם לא מבצעים הערכה בתדירות גבוהה מספיק.
כדי לבדוק זאת, אפשר לאמן ריצה מקוצרת של כ-500 צעדים באמצעות lr = 2 * current best
, אבל לבצע הערכה של כל שלב.
![שני גרפים: ציר ה-X בשני התרשימים הוא Global Step וציר ה-y של שני התרשימים הוא Train אובדן הרכבת. שני התרשימים משווים מצב המרה של
(2,2) לשלב המרה של (1,1). בתרשים הראשון מוצגות הערכות
לכל 1,000 שלבים. בתרשים הראשון הזה, שני מדדי ההמרות מציגים
ירידה יציבה הדרגתית עם יותר שלבים גלובליים. בתרשים השני
מוצגות הערכות תכופות ב-25 השלבים הראשונים. בתרשים השני, צעד ההמרה (2,2) מציג תנודות חדות בפסילת הרכבת
בשלבים הגלובליים הראשונים לפני שירד
ב-20 צעדים גלובליים באופן עקבי. מדד ההמרה של (1,1) מציג
אובדן רכבת נמוך באופן עקבי אחרי השלב הגלובלי הראשון.](https://developers.google.cn/static/machine-learning/guides/deep-learning-tuning-playbook/images/more_frequent_evals.png?authuser=8&hl=he)
תיקונים אפשריים לדפוסים נפוצים של חוסר יציבות
כדאי לשקול את הפתרונות הבאים לדפוסי אי יציבות נפוצים:
- החלת חימום על קצב הלמידה. השיטה הזו מתאימה במיוחד לחוסר יציבות באימון בשלב מוקדם.
- החלת חיתוך הדרגתי. המצב הזה טוב לאי-יציבות באימון מוקדם ובאמצע, ועשוי לתקן כמה הפעלות שגויות שלא ניתן לבצע בתקופת החימום.
- אפשר לנסות אופטימיזציה חדשה. לפעמים אדם יכול להתמודד עם אי-יציבות שלא יכולה להתמודד עם מומנטום. זהו תחום מחקר פעיל.
- ודאו שאתם משתמשים בשיטות המומלצות ובאתחולים הטובים ביותר של ארכיטקטורת המודלים שלכם (בהמשך מופיעות דוגמאות). מוסיפים חיבורים שיוריים ונורמליזציה אם המודל לא מכיל אותם.
- צריך לנרמל כפעולה האחרונה לפני השיוריה. לדוגמה:
x + Norm(f(x))
. לתשומת ליבך,Norm(x + f(x))
עלול לגרום לבעיות. - כדאי לנסות לאתחל ל-0 את ההסתעפויות הנותרות. (ראו ReZero הוא כל מה שצריך: שילוב מהיר בעומק גדול.)
- להנמיך את קצב הלמידה. זה מוצא אחרון.
הכנה של קצב הלמידה
![שני גרפים המדגימים את אותו ניסוי. בתרשים הראשון,
ציר ה-X מייצג 'שלב גלובלי' וציר ה-y הוא 'אבדן הרכבת'. נתוני ההכנה לקצב הלמידה נמוכים,
וכתוצאה מכך, אובדן הרכבת היה מאוד לא יציב.
עם נתוני ההכנה של שיעורי הלמידה הגבוהים יותר, אובדן הרכבת
היה הרבה יותר יציב.](https://developers.google.cn/static/machine-learning/guides/deep-learning-tuning-playbook/images/instability_during_warmup.png?authuser=8&hl=he)
מתי להפעיל הכנה של שיעור ההכנה לשיעור הלמידה
![תרשים של אובדן אנטרופיה בקבוצת האימות (ציר ה-y) לעומת
שיעור הלמידה הבסיסית (ציר ה-x). בתרשים מוצגים שישה ניסויים אפשריים,
שלכולם יש קצב למידה בסיסי נמוך יחסית. אובדן
האימות יורד ככל ששיעור הלמידה הבסיסי עולה, ואז מגיע לנקודה נמוכה
לפני תחילת העלייה. בתרשים מוצגים גם ארבעה ניסויים
שאינם מעשיים, שלכולם יש שיעור גבוה יחסית של למידת בסיס.](https://developers.google.cn/static/machine-learning/guides/deep-learning-tuning-playbook/images/axis_model_with_instability.png?authuser=8&hl=he)
![תרשים של אובדן אנטרופיה בערכת האימון (ציר ה-y) לעומת
שלב גלובלי (ציר ה-x). האובדן יורד מהר מאוד בשלבים הראשונים הגלובליים
הראשוניים. לאחר מכן, האובדן עולה באופן דרמטי כ-10,000 צעדים. לאחר מכן,
הירידה יורדת בהדרגה כ-15,000 צעדים.](https://developers.google.cn/static/machine-learning/guides/deep-learning-tuning-playbook/images/loss_model_with_instability.png?authuser=8&hl=he)
באיור 7א מוצגת תרשים של ציר היפר-פרמטר, שמציין שמודל החווה אי-יציבות באופטימיזציה, מפני שקצב הלמידה הטוב ביותר נמצא ממש על הקצה של חוסר היציבות.
איור 7ב מראה איך אפשר לבדוק זאת שוב על ידי בחינת אובדן האימון של מודל שאומן עם קצב למידה שגדול פי 5 או 10 מהשיא הזה. אם בתרשים מוצגת עלייה פתאומית בהפסד לאחר ירידה יציבה (למשל, בשלב של כ-10 אלף באיור שלמעלה), סביר להניח שהמודל יסבול מחוסר יציבות באופטימיזציה.
איך להחיל הכנה של שיעור ההכנה לשיעור הלמידה
![תרשים של אובדן האימות בשלב 76619 (ציר ה-y) לעומת שיעור הלמידה הבסיסית (ציר ה-x). התרשים משווה בין התוצאות של ארבעה מצבים שונים ב-LayerNorm Transformer ב-WMT14 EN-De. חימום
קצב הלמידה הפחית את אובדן האימות בקצבי למידה נמוכים יותר.](https://developers.google.cn/static/machine-learning/guides/deep-learning-tuning-playbook/images/beneficial_effect_warmup.png?authuser=8&hl=he)
הפונקציה unstable_base_learning_rate
תהיה קצב הלמידה שבו המודל הופך לבלתי יציב, באמצעות התהליך הקודם.
תרגול החימום כרוך בהכנה של לוח זמנים לקצב הלמידה, שמגביר את קצב הלמידה מ-0 ל-base_learning_rate
יציבה מסוימת שגדולה לפחות מ-unstable_base_learning_rate
בסדר גודל אחד.
ברירת המחדל היא לנסות base_learning_rate
בגודל 10xunstable_base_learning_rate
. עם זאת, אפשר להריץ את כל התהליך שוב בסכום כמו 100x unstable_base_learning_rate
. לוח הזמנים הספציפי הוא:
- צריך להגדיל את הערך מ-0 ל-base_learning_rate ב-warup_steps.
- אימון בקצב קבוע עבור post_warmup_steps.
המטרה היא למצוא את המספר הקצר ביותר של warmup_steps
שנותן לכם גישה לשיעורי שיא גבוהים בהרבה מאשר unstable_base_learning_rate
.
לכן עבור כל base_learning_rate
, צריך לכוון את warmup_steps
ואת post_warmup_steps
. בדרך כלל אפשר להגדיר את post_warmup_steps
לערך 2*warmup_steps
.
אפשר לכוונן את החימום בנפרד מלוח זמנים קיים לדעיכה. צריך לנקות את warmup_steps
בסדר גודל שונה. לדוגמה, במחקר לדוגמה אפשר לנסות את [10, 1000, 10,000, 100,000]
. הנקודה הגדולה ביותר האפשרית לא יכולה להיות יותר מ-10% מה-max_train_steps
.
אחרי שיוצרים warmup_steps
שלא מפוצץ את האימון בbase_learning_rate
, צריך להחיל אותו במודל הבסיס.
בעיקרון, כדאי להוסיף את לוח הזמנים הזה ללוח הזמנים הקיים ולהשתמש בבחירת נקודת הביקורת האופטימלית שתיארנו למעלה כדי להשוות את הניסוי הזה לניסוי הבסיסי. לדוגמה, אם במקור היו לנו 10,000 max_train_steps
וביצענו warmup_steps
עבור 1,000 שלבים, תהליך האימון החדש היה אמור לפעול במשך 11,000 שלבים בסך הכול.
אם נדרשים warmup_steps
ארוכים לאימון יציב (יותר מ-5% מתוך max_train_steps
), יכול להיות שתצטרכו להגדיל את המספר max_train_steps
כדי להביא בחשבון את העובדה הזו.
אין באמת ערך "אופייני" בכל הטווח של עומסי העבודה. במודלים מסוימים דרושות רק 100 שלבים, ואילו במודלים אחרים (במיוחד טרנספורמרים) צריך להשתמש ב-40,000 ומעלה.
חיתוך הדרגתי
![תרשים של נורמה Grad l2 (ציר ה-y) לעומת שלב גלובלי (ציר ה-x). אימון
הנורמה 'הטיפוסי' של ההדרגה לא היה יציב מאוד בשלבים הגלובליים המוקדמים. סף קליפ היה אגרסיבי מדי גרם לירידה
בקצב הלמידה והאימון האט. סף טוב יותר לקליפ
(ממש מעל לנורמת ההדרגתיות הטיפוסית) ייצב את האימון בשלב מוקדם.](https://developers.google.cn/static/machine-learning/guides/deep-learning-tuning-playbook/images/gradient_clipping.png?authuser=8&hl=he)
השימוש בחיתוך הדרגתי הוא שימושי ביותר כאשר מתרחשות בעיות חמורות או חריגות בהדרגה. חיתוך הדרגתי יכול לפתור כל אחת מהבעיות הבאות:
- חוסר יציבות באימון מוקדם (נורמה גדולה של שיפוע מוקדם)
- אי יציבות באימון באמצע (עליות חדות בהדרגה באמצע האימון).
לפעמים, תקופות חימום ממושכות יותר יכולות לתקן בעיות יציבות שלא קורות. לפרטים נוספים, אפשר לקרוא את המאמר חימום לקצב הלמידה.
🤖 מה לגבי חיתוך קטעים במהלך החימום?
ערכי הסף האידאליים לקליפ הם בדיוק מעל לנורמת ההדרגתיות ה "אופיינית".
הנה דוגמה לאופן שבו ניתן לבצע חיתוך הדרגתי:
- אם הנורמה של ההדרגתיות $\left | g\right |$ גדולה יותר מסף החיתוך בהדרגתיות $\lambda$, אז צריך לבצע ${g}'= \lambda\times \frac{g}{\left | g\right |}$ כאשר ${g}'$ הוא ההדרגתיות החדשה.
תעדו את הנורמה של ההדרגתיות הלא מוצמדת במהלך האימון. כברירת מחדל, יוצרים:
- תרשים של נורמה הדרגתית לעומת שלב
- היסטוגרמה של נורמות הדרגתיות שנצברו בכל השלבים
בחר סף חיתוך הדרגתי המבוסס על האחוזון ה-90 של נורמות הדרגתיות. הסף תלוי בעומס עבודה, אבל 90% היא נקודת התחלה טובה. אם לא עובדת 90%, אפשר לכוונן את הסף הזה.
🤖 מה לגבי אסטרטגיית הסתגלות?
אם ניסיתם לבצע חיתוך הדרגתי ועדיין יש בעיות של חוסר יציבות, תוכלו לנסות לעשות זאת יותר. כלומר, תוכלו להקטין את הסף.
חיתוך הדרגתי אגרסיבי מאוד (כלומר, יותר מ-50% מהעדכונים נחתכים), הוא במהותו דרך מוזרה להפחתת קצב הלמידה. אם אתם משתמשים בגזירים אגרסיביים במיוחד, סביר להניח שעדיף פשוט להוריד את קצב הלמידה.
למה קוראים לקצב הלמידה ולפרמטרים אחרים של אופטימיזציה היפר-פרמטרים? הם לא פרמטרים של התפלגות קודמת.
למונח 'היפר-פרמטר' יש משמעות מדויקת בלמידת מכונה בייס, ולכן ההתייחסות לקצב הלמידה ולרוב הפרמטרים האחרים של למידה עמוקה שניתן לכוונן היא 'היפר-פרמטרים' היא שימוש לרעה בטרמינולוגיה. אנחנו מעדיפים להשתמש במונח 'מטא-פרמטר' לציון שיעורי למידה, פרמטרים ארכיטקטוניים וכל שאר הדברים שניתן לכוונן במסגרת למידה עמוקה (Deep Learning). הסיבה לכך היא שמטא-פרמטר מונע את האפשרות לבלבול שמקורו בשימוש לרעה במילה "היפר-פרמטר". הבלבול הזה צפוי במיוחד כאשר מדברים על אופטימיזציה בייסיאנית, שבה למודלים של פני השטח של התשובה ההסתברותית יש היפר-פרמטרים אמיתיים משלהם.
לרוע המזל, על אף שעשוי לבלבל, המונח 'היפר-פרמטר' הפך לנפוץ מאוד בקהילת הלמידה העמוקה. לכן, במסמך הזה, שמיועד לקהל רחב שכולל הרבה אנשים שסביר להניח שלא יהיו מודעים לבלבול הזה, בחרנו לתרום למקור אחד של בלבול בתחום, בתקווה למנוע בלבול נוסף. עם זאת, יכול להיות שנקבל החלטה שונה כשנפרסם מאמר מחקר, ונעודד אחרים להשתמש במקום זאת ב"מטא-פרמטר" ברוב ההקשרים.
למה לא ניתן לכוונן את גודל האצווה כדי לשפר ישירות את הביצועים של קבוצת האימות?
שינוי גודל האצווה בלי לשנות פרטים אחרים בצינור עיבוד הנתונים משפיע לעיתים קרובות על הביצועים של קבוצת האימות. עם זאת, ההבדל בביצועים של קבוצת האימות בין שני גדלים של אצוות בדרך כלל נעלם אם מתבצעת אופטימיזציה בנפרד של צינור עיבוד הנתונים לכל גודל אצווה.
ההיפר-פרמטרים שיש להם הכי הרבה אינטראקציה עם גודל האצווה, ולכן הכי חשוב לבצע כוונון נפרד לכל גודל אצווה, הם ההיפר-פרמטרים של האופטימיזציה (לדוגמה, קצב למידה, מומנטום) וההיפר-פרמטרים של הרגולציה. קבוצות קטנות יותר מייצרות יותר רעש לאלגוריתם האימון כתוצאה מהשונות של המדגם. לרעש הזה יכולה להיות אפקט הרגולרי. לכן, אצוות גדולות יותר עשויות להוביל יותר להתאמה לעומס, ולפעמים יהיה צורך לבצע רדרציה חזקה יותר או שיטות נוספות ליישור. בנוסף, יכול להיות שתצטרכו לשנות את מספר שלבי האימון כשמשנים את גודל האצווה.
כשמביאים בחשבון את כל ההשפעות האלה, אין ראיות משכנעות לכך שגודל האצווה משפיע על ביצועי האימות המקסימליים שאפשר להשיג. לפרטים נוספים, ראו Shallue et al. 2018.
מהם כללי העדכון לכל האלגוריתמים הפופולריים של האופטימיזציה?
בקטע הזה מפורטים כללי עדכונים לכמה אלגוריתמים נפוצים של אופטימיזציה.
ירידה סטוכסטית בשיפוע (SGD)
\[\theta_{t+1} = \theta_{t} - \eta_t \nabla \mathcal{l}(\theta_t)\]
$\eta_t$ הוא קצב הלמידה בשלב $t$.
מומנטום
\[v_0 = 0\]
\[v_{t+1} = \gamma v_{t} + \nabla \mathcal{l}(\theta_t)\]
\[\theta_{t+1} = \theta_{t} - \eta_t v_{t+1}\]
$\eta_t$ הוא קצב הלמידה בשלב $t$, ו-$\gamma$ הוא מקדם התנע.
נסטרוב
\[v_0 = 0\]
\[v_{t+1} = \gamma v_{t} + \nabla \mathcal{l}(\theta_t)\]
\[\theta_{t+1} = \theta_{t} - \eta_t ( \gamma v_{t+1} + \nabla \mathcal{l}(\theta_{t}) )\]
$\eta_t$ הוא קצב הלמידה בשלב $t$, ו-$\gamma$ הוא מקדם התנע.
RMSProp
\[v_0 = 1 \text{, } m_0 = 0\]
\[v_{t+1} = \rho v_{t} + (1 - \rho) \nabla \mathcal{l}(\theta_t)^2\]
\[m_{t+1} = \gamma m_{t} + \frac{\eta_t}{\sqrt{v_{t+1} + \epsilon}}\nabla \mathcal{l}(\theta_t)\]
\[\theta_{t+1} = \theta_{t} - m_{t+1}\]
ADAM
\[m_0 = 0 \text{, } v_0 = 0\]
\[m_{t+1} = \beta_1 m_{t} + (1 - \beta_1) \nabla \mathcal{l} (\theta_t)\]
\[v_{t+1} = \beta_2 v_{t} + (1 - \beta_2) \nabla \mathcal{l}(\theta_t)^2\]
\[b_{t+1} = \frac{\sqrt{1 - \beta_2^{t+1}}}{1 - \beta_1^{t+1}}\]
\[\theta_{t+1} = \theta_{t} - \alpha_t \frac{m_{t+1}}{\sqrt{v_{t+1}} + \epsilon} b_{t+1}\]
נדאם
\[m_0 = 0 \text{, } v_0 = 0\]
\[m_{t+1} = \beta_1 m_{t} + (1 - \beta_1) \nabla \mathcal{l} (\theta_t)\]
\[v_{t+1} = \beta_2 v_{t} + (1 - \beta_2) \nabla \mathcal{l} (\theta_t)^2\]
\[b_{t+1} = \frac{\sqrt{1 - \beta_2^{t+1}}}{1 - \beta_1^{t+1}}\]
\[\theta_{t+1} = \theta_{t} - \alpha_t \frac{\beta_1 m_{t+1} + (1 - \beta_1) \nabla \mathcal{l} (\theta_t)}{\sqrt{v_{t+1}} + \epsilon} b_{t+1}\]