איך לאמן מודל שפה תותחופלצת?

-
מצאתם מודל שאומן מראש באנגלית.
-
היתם רוצים אותו דבר בעברית.
-
איך קוראים לקסם ש"מעביר אותו לעברית"?
שיטות פשוטות לאימון מודלי שפה חזקים:
שיטה ראשונה: Adaptive Fine Tuning
מודלי שפה גדולים מודרנים מכלילים מצוין לדוגמאות השונות באופן משמעותי מאלו שאומנו עליהן – הרבה יותר ממודלים ישנים יותר (Hendrycks et al., 2020), ובכל זאת: הם לא קסם. נתונים ששונים באופן מהותי מאלו שהם ראו: יעשו להם בעיות.
הרעיון בשיטה הוא שננסה לאמן את המודל Unsupervised לנתונים הדומים ביותר לנתונים החדשים שיש לנו ורק אז נאמן את המודל לבצע את המשימה הספציפית.
לדוגמה: אם יש בידנו למשל מודל המאומן לבצע משימות (Instruct) באנגלית, אבל הינו רוצים מודל Instruct בעברית. מה יקרה אם נקח את מודל האנגלית ונאמן אותו MLM (השלמת מילים חסרות) בעברית (ללא קשר ליכולת לבצע משימות בעברית).
אפשר "להעביר את הידע" בתוך המודל מאנגלית לעברית?
התשובה לכך היא:
"למרות שהתשובה היא 'כן אבל..'. זה נשמע כל כך יומרני ותלוש. אכתוב 'לא' ואז אכנס לפרטים למה ה'לא' הוא די 'כן אבל'"
לא.
התופעה לה אנו מנסים לגרום כן נצפה בעבר, מודלים שאומנו במספר שפות כן מכלילים ידע בין השפות.
הבעיה היא שזה מאד מוגבל ונזדקק להרבה מאד דאטה כדי לגרום לתופעה הזו להתרחש.
אז התשובה היא: "כן, זה אפשרי. צריך בשביל זה המון דאטה מאד מגוון ומודל חזק מאד וגם אז "לא מובטח" לנו כלום"
את אותו הקונספט אפשר להכליל לכמה סוגי אימונים שונים:
אימון מותאם תחום (Domain):
דוגמה: אם המודל המאומן אומן על ידי כתבות, ונתוני היעד הם גם כתבות חדשותיות, כוונון עדין מותאם לתחום יכלול התאמת המודל למאמרים חדשותיים נוספים.
אימון מותאם משימה (Instruction):
דוגמה: אם המודל המאומן אומן על משימות תרגום, ונתוני היעד הם גם משימת תרגום, כוונון עדין מותאם למשימות יכלול התאמת המודל על נתוני תרגום נוספים.
אימון מותאם לשפה (Language):
[אתם יודעים איך אומרים "שפה" באנגלית. למה רשמתי את זה?]
דוגמה: אם המודל המאומן אומן על טקסט באנגלית, ונתוני היעד למשל בעברית. לפני האימון לבצע את המשימה שמעניינת אותנו בעברית, נאמן "בכללי" בעברית Unsupervised ורק אז נשתמש במודל למשימה אותה רצינו לבצע.
שיטה שניה: בחירת דאטה לפי חשיבות – Importance Sampling
בחירת דאטה לפי חשיבות היא שיטה המנסה לגשר על הבדלים גדולים בהתפלגות בין סט האימון לסט הוולידציה – הרעיון פשוט: בחירת דוגמאות ספציפיות המתאימות יותר לדוגמאות בעולם האמיתי.
אם תבחר דוגמאות ספציפיות שדומות לטסט: נקבל אוברפיטינג!
לא מדויק: זה נכון שאם "פשוט נבחר" בלי להסתכל מה אנחנו עושים – נקבל אוברפיטינג. אבל באמצעות שיטה זו אנחנו יכולים לבחור באופן כללי דוגמאות "המתאימות" לתנאים מסוימים מבלי לציין במפורש לאיזו תנאים אנחנו מכוונים (אנחנו משתמשים במודל כדי לבחור דוגמאות).
שיטה זו בגרסתה הכללית יותר "Importance Sampling" שימושית ביותר ואני ממליץ לכולם ללכת לקרוא על רעיונות באיזור.
שיפור פשוט: Behavioural Fine-tuning
אם באימון אדפטיבי אנחנו משתמשים במודל שאומן מראש ומלמדים אותו את התפלגות הדאטה (ללא קשר להתפלגות הדאטה המתויג למשימה אותה נרצה לבצע).
שיפור פשוט וטריוויאלי יהיה: אם יש לנו דאטה ממשימות "קרובות אבל לא בדיוק", לדוגמה: משימות "לא קשורות" בעברית.
אם נאמן את המודל עליהן ורק אז נעבור "לפתור משימות" בעברית – נקבל מודל חזק ביותר.
מה ההבדל הגדול? למרות שMLM (וSiFT וElectra וכל השיטות באיזור..) עובדות מצוין בלימוד של מודלי שפה התפלגויות שונות ומשונות. יש להן חסרונות. חסרון בולט (מעבר לזה שהן לא מכוונות משימה) הוא שהן בדרך כלל עובדות על מילה בודדת אחת, מה שיוצר מודלים המתקשים עם שלילות, מילים מגדריות (עברית למשל) ובכללי "דברים קטנים" המשנים את כל משמעות המשפט כולו.
רשימת "דברים קטנים שדופקים מודלי שפה":
1. שלילות.
2. מילים מגדריות.
3. החלפת גוף ראשון <-> שני <-> שלישי
שיטה שלישית: מודלי שפה לעניים:
-
אתם יודעים מה יותר גרוע מלא להצליח לאמן מודל שפה גדול למשימה הספציפית?
-
כשאין כסף בכלל לאמן איזשהו מודל שפה גדול.
היה נחמד אם היתה שיטה שמאפשרת לקחת מודל שפה שמישהו עשיר אימן, לחתוך ממנו חלקים (בלי שידפק יותר מידי) ולאמן מודל שפה קטן וזול המחזיק בכוח דומה.
לפני כשבוע פרסמתי כאן פוסט על תופעה מעניינת הקימת במודלי שפה: "חצי מודל" עדיין יודע לדבר טוב.
אפשר לנצל תופעה זו ולאמן מודלי שפה קטנים הרבה יותר! פשוט: חותכים אותם באמצע. אכן יש פגיעה בביצועים אבל היא יחסית קטנה (לאחר אימון מלא).
עוד מעניין: שיטה שעובדת טוב במודלי שפה: Stochastic Depth – רק חלק מהשכבות נמצאות בכל צעד אימון. אנו יודעים שOpenAI משתמשים בשיטה זו באימון חלק מהמודלים. נכתב על כך במאמר של Whisper.
יש יותר טוב?
אדפטרים
תחום חם היום!
הרעיון פשוט: במקום לאמן את כל המודל (כי למי יש כסף לזה בכלל) נוסיף שכבות במיקומים אסטרטגים ונאמן רק אותן.
החידוש כאן הוא באסטרטגיה המשמשת לבנית ארכיטקטורת הרשת. אם פעם הינו מאמנים רשת (או כמה שכבות ברשת), כאן אנו מקפיאים את הרשת המקורית ומוסיפים שכבות מיוחדות שרק אותן נאמן.
שאלת השאלות: מה עם התוצאות.
אדפטרים מגיעים לתוצאות דומות בהרבה משימות. הם אמנם לא מושלמים אבל בהחלט כדאי לשקול אותם.
אדפטרים עם צוואר בקבוק – Bottleneck Adapters
הרעיון הפשוט ביותר: נוסיף במקביל לכל בלוק ברשת עוד בלוק BottleNeck (וגם Fully Connected) ונאמן רק אותו. כך אנו לא פוגעים ברשת מלכתחילה (כי אנחנו לומדים רק "להוסיף" ליצוג כל אחד מהבלוקים) וגם מאמנים חלק קטן מאד ברשת ביחס לאימון הרשת כולה.
היפרפרמטר החשוב ביותר בשיטה זו הוא "כמה מקטינים" את המימד בצוואר הבקבוק.
שוחררו כמה מאמרים המנסים ארכיטקטורות שונות לאדפרטרים:
-
למשל Houlsby et al. (2019) מציעים אדפטרים גם אחרי האטנשן וגם בלוק לינארי בכל שכבת אטנשן.
-
וגם Pfeiffer et al. (2020) מציעים אדפטרים רק אחרי הFF בבלוקים.
-
ובנוסף He et al. (2021) מציעים אדפטרים במקביל לשכבות הטרנספורמר המקורית.
אדפטר לאמבדינגס
אם אתם עוקבים אחרי מה שאני מפרסם אז בשלב זה כבר הבנתם שהשכבה ממנה מודלי שפה מקבלים את רוב כוחם בFine-Tuning היא האמבדינגדס (וגם הUnembeddings).
איך מוסיפים לה אדפטר?
במאמר MAD-X הכותבים (Pfeiffer et al., 2020) מציעים להוסיף אדפטר לאחר האמבדינגס ולהפוך אותו בUnembeddings.
למה לא להגדיל את המימד?
אנחנו יודעים כבר מלפני כחצי שנה (הרבה זמן בתחום) שמודלי שפה משתפרים משמעותית אם לפני הטקסט מוסיפים גם "וקטור עם רעש ממש ספציפי".
על Prefix Tuning
הטריק הזה נקרא Prefix Tuning ומגיעים לרעש הספציפי הזה בצורה פשוטה: מכניסים אל המודל את המשפט המקורי ואת התוצאה המבוקשת ומסתכלים מה הגרדיאנטים אומרים באיזור הקלט של ה"הוקטור הרנדומלי".
על ידי אופטימיזציה כזו מגיעים ל"צ'יט" שאם מוסיפים אותו לקלט מודלי השפה – הם פשוט משתפרים כי למידה עמוקה זה קסם.
את אותו הרעיון אפשר לממש גם באדפטרים: נוסיף "וקטור רנדום" נלמד בשרשור לפני יצוג המבדינגס של הטקסט וניתן לרשת ללמוד אותו לבד.
המאמר: Prefix Tuning (Li and Liang, 2021)
שיטה חשובה: Low-Rank Adaptation (LoRA)
-
כל כפל מטריצות במודל ℎ=𝑊0𝑥, אפשר לפרמטר מחדש (Reparametrize) כ פירוק ℎ=𝑊0𝑥+𝛼𝑟𝐵𝐴𝑥
-
כש, 𝐴∈ℝ𝑟×𝑘 ו- 𝐵∈ℝ𝑑×𝑟 מטריצות הפירוק ו- 𝑟, מימד נמוך יותר.
-
ואפשר להכליל את הרעיון הזה לכל איזור ברשת.
כל השיטות ביחד: (IA)^3
במאמר Infused Adapter by Inhibiting and Amplifying Inner Activations ((IA)^3) הכותבים משתמשים בכל השיטות ביחד כשהם מוסיפים אדפטרים נפרדים גם ליצוגי הKQV באטנשן.
– הם גם מוסיפים Gateים ועוד כל מיני טריקים אבל אני חושב שהבנתם את הרעיון.
מה עוד אפשר לעשות עם אדפטרים?
מלבד היתרון הברור של שיטה זו בחסכון בכוח העיבוד, לשיטה זו יש גם יתרונות נוספים.
אדפטרים כ"זכרון":
ברגע באדפטר מאומן למשימה ספציפית, מעכשיו אותו האדפטר הוא "החלק ברשת שיודע לפתור את המשימה".
וניתן לשחק עם יכולת זו.
למשל:
-
החלפת "הידע" ברשת בזמן הפעלת הרשת
-
שילוב בין אדפטרים מוביל לשילוב ידע בין משימות שונות.
יש עוד הרבה מאיפה שזה בא. המשך יבוא..