close menu

איך באמת מודלים לומדים לייצר תמונות מטקסט? (חלק א')

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

בנוסף, על הדרך: התבקשתי אתמול בתגובות להסביר איך עובד הסיפור הזה של למידת יצוגים שמאפשר חיפוש דוגמאות "דומות".

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

לקרוא מימין לשמאל: "מלך" – "גבר" + "אישה" = "מלכה"

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

אז איך הגענו מתרגילי חשבון פשוטים ליצירת תמונות?
.
.
  • המשימה: לגרום למודל "לקרב" דוגמאות זהות ו"להרחיק" דוגמאות שונות.
  • מוטיבציה: כי די נו. איזה מגניב זה!
.
.

למידת ניגודים – Contrastive Learning

המטרה העיקרית של למידת ניגוד היא ללמוד מרחב נסתר בו דוגמאות דומות קרובות אחת לשניה ודוגמאות שונות רחוקות אחת מהשניה. ישנן שיטות רבות ללמידת יצוגים מנוגדים אבל המטרה העיקרית זהה: ללמוד לתרגם דוגמאות אל מרחב כלשהו בו הדוגמאות הדומות קרובות והשונות רחוקות.
ממטרה זו קל להסיק כי הדרך הפשוטה ביותר תהיה לאמן מודל על זוגות דוגמאות כך שדוגמאות דומות יסווגו כקרובות ודוגמאות שונות יסווגו כרחוקות.
הלוס: לוס ניגודי – Contrastive Loss
הלוס הקלאסי לבעיה זו הוא הלוס הניגודי – כמו שאמרנו: נרצה שדוגמאות מאותה המחלקה יתקרבו ודוגמאות ממחלקה שונה יתרחקו ולכן הלוס יהיה "למנמם (מלשון מינימום) את המרחק בין הדוגמאות אם הן מאותה מחלקה ולמקסם את המרחק אם הן ממחלקות שונות"
שיפור: לוס שלישיות – Triplet Loss
שיפור פשוט לשיטה זו הוא במקום ללמוד האם זוגות שייכים לאותה המחלקה, נלמד האם כל אחד מהם בנפרד שייך למחלקה של דוגמה אחרת. כלומר: בכל שלב נבחר דוגמה וביחס אליה נשאל זוגות "מי מהם שייך לאותה המחלקה כמוה?"

למה זה משפר בכלל? כי עכשיו יש לנו יותר אינפורמציה! לא רק שאנחנו מקרבים את הקרובים, אנחנו לומדים את ההבדל בין הקרובים לרחוקים (כי בכל שלשה יש לנו גם זוג לקרב וגם זוג להרחיק).

שימו לב שיש כאן הנחה לא קלה שאנחנו יודעים לדגום טוב את השלשות הללו.
לוס מרובע
ישנה גם כמובן גרסה מרובעת של הלוס (איך לא?) המחשבת בכל שלב שני זוגות חיוביים ושלילים. לא ניסיתי.
לוס N-זוגות
אפשר להמשיך ולהגזים את השיטה הזו ולבנות לוסים שלוקחים בחשבון כמה השוואות שרק נרצה. אנחנו לא הראשונים [1] שחשבנו על זה. זה עובד טוב אבל באופן כללי זה בדרך כלל לא נדרש.
לוס Nearest Neighbors
בעבודה מעניינת [2] לא מזמן, הוצג טריק פשוט המרכך את היצוגים הנלמדים: לגזור דרך הsoftmax ולהוסיף טמפרטורה בזמן האימון. טריק משנה לגמרי את היצוג הנלמד בתוך הרשת ומחליק את המרחב אליו הרשת מטילה את הדוגמאות. במאמר עצמו ישנה תמונה יפה מאד של אינטרפולציה בין דוגמאות (לא דרך הרשת! בין הדוגמאות באימון) וניתן לראות בבירור שהרשת תופסת הבדלים עדינים מאד בין דוגמאות האימון בצורה שהיתה קשה מאד לפני כן.
רעיון: נבלגן את הדאטה בעצמנו!
במקום להסתמך על דוגמאות מתויגות, נוכל לבלגן או להרעיש בעצמנו [3] את הדאטה ולאמן את המודל עם לוס ניגודי כך נגרום למודל להבין לעומק את הדאטה וזאת עוד לפני שאנחנו בכלל משתמשים בו על הדוגמאות האמיתיות! נוכל אפילו להרעיש את הדוגמאות בצורות "הגיוניות" למשל אם אנחנו מתעסקים בתמונות: לסובב אותן! או אם אנחנו מתעסקים בטקסט: אותיות קטנות\גדולות!
זה נשמע קל ופשוט!
.
כך גם אני חשבתי.
.
בלשון עבר.
.
.
כמה נקודות חשובות שבלעדיהן כלום לא יעבוד:
  • תגזימו עם האוגמנטציות: אין כזה דבר קשה מידי, זה גם ככה לא הדאטה אמיתי שלכם: סובבו את התמונות ומתחו אותן לכל הכיוונים כמה שאתם יכולים. אולי יקח למודל שלכם זמן להתחיל ללמוד אבל זה עדיף מאשר אוברפיטינג (כי מודל שלמד "להעתיק" את הקלט לא יכול להתאושש)
  • באצ' בגודל כמה שיותר גדול: אני לא אוהב את זה בכלל [4] אבל ספציפית כאן (ו. רק. כאן.) זה מתבקש: באצ' כמה שיותר גדול. הלמידה כאן קשה ורועשת מאד ואנו נרצה שהמודל ילמד מעדכונים כמה שיותר חלקים ונקיים. מיצוע העדכונים על גבי הרבה דוגמאות היא הדרך לנקות מהן רעשים.
  • למידה אקטיבית, שזה אומר: לבחור דוגמאות בצורה חכמה תוך כדי האימון לפי הטעויות של המודל.
למידה אקטיבית – Hard Negative Mining
הינו רוצים לבחור למודל דוגמאות בצורה כזו שהוא ילמד הכי טוב – אלו שיהיו לו הקשות ביותר.
אם יש בידינו תיוגים, הינו רוצים לבחור למשל זוגות בעלי תיוג שונה שהמודל חושב שצריכים להיות קרובים. קל למדוד ולבדוק תנאים אלו.
למידה אקטיבית קשה – Online Hard Negative Mining (OHEM)
כשמדברים על בייסלין יש בגדול שתי גישות עיקריות ללמידה אקטיבית:
  • ללמוד רגיל – לעדכן רק מה שהכי קשה
אין הרבה מה להסביר, אנו לומדים רגיל ומעדכנים את המודל רק על פי הדוגמאות שהיו עבורו הקשות ביותר באותו הבאצ' (או בתוך אותה הדוגמה אם הדוגמה ממימד גבוה כמו תמונה או טקסט ארוך). זה כמובן מאריך את זמן האימון ומוסיף היפרפרמטר שקשה לאפטם (כמה אחוז מההכי קשים לקחת) אבל בהחלט עובד ובדרך כלל מביא את המודלים להיות מדוייקים ביותר
  • בכל באצ' – להריץ את המודל ולבחור את הדוגמאות בהן הכי יטעה
זה כמובן לוקח הרבה יותר זמן כי בכל שלב אנו צריכים להפעיל את המודל על כל הדאטה אבל זו דרך מצוינת לסחוט מהמודל עוד קצת דיוק (למשל אחרי שהוא כבר מאומן רגיל). [בSimCLR זה מה שעושים]
אפשר כמובן לשחק עם כל הרעיונות האלו בכל מידי דרכים כמו לבחור שלשות עם הדוגמה החיובית הקלה ביותר והשלילית הקשה ביותר [5] וקל להמשיך לחשוב על טריקים בסגנון.
  • ממליץ לשחק עם זה אם דיוק מודלים חשוב לכם.
להרחיק דוגמאות בכוח: ArcFace
נתבונן בשכבה הלינארית האחרונה ברשת סיווג
אם נוריד ממנה את הBias כל מה שהיא תעשה הוא כפל מטריצות פשוט ביצוג הנסתר ברשת. כלומר, לכל יצוג אנו מחשבים כפל בינו לבין וקטורי עמודה ממשוקלים לכל אחת מהמחלקות. אז אם למשל היצוגים היו וקטורים באורך 1, המכפלה הזו זהה לחישוב מרחק קוסינוס ועם וקטורי יחידה המרחק הוא הזוית בניהם. לכן, מכיוון שהפלט כרגע הוא קוסינוס זוית, נוכל להפעיל arccos ולקבל את הזוויות בפועל. מכאן, אנו מוסיפים קבוע כלשהו ליצוג הרשת במחלקה הנכונה שעל הרשת לייצר ובכך הקשה על הרשת ללמוד בדיוק את המחלקה אותה היא היתה רוצה לחזות. לאחר מכן נחשב חזרה קוסינוס ועל הביטוי הסופי נחשב על הלוס.
לכן, על מנת ללמוד יצוג הרשת כבר לא מסוגלת ללמוד "להיות לא בטוחה" (כי הפרענו לה בדיוק במחלקה הזו על ידי הוספת הקבוע) ועליה לבסוף להחזיר ערך גדול אף יותר מכל שאר הערכים על מנת לא לטעותץ
ובעולם האמיתי..

יצוג במודלי שפה

נתמקד עכשיו במודלי שפה, איך עושים את כל זה במודלים שלומדים טקסט?
בניגוד לתמונות, אי אפשר "לסובב" טקסטים. נצטרך למצוא שיטות אחרות "לבלגן" את הטקסטים שלנו על מנת ללמד את המודל איך נראים קטעי טקסט (בלי לפגוע במשמעות).
הרעשות פשוטות
לפני שמתחילים עם דברים חכמים: קל מאד לבלגן טקסטים בשיטות דביליות לחלוטין: הוספת רווחים\ירידות שורה, החלפת אותיות באותיות קרובות במקלדת (טעויות הקלדה), מחיקת מילים, אותיות גדולות\קטנות..
כמעט ואין קטעי קוד באינטרנט שמתעסקים בנושא (למה?) ואלו שכן מתיימרים לנסות לעשות זאת מסובכים, שבורים ואיטיים. אני ממליץ לכם לממש בעצמם אם אתם מעוניינים בהרעשות מסוג זה.
הרעשות מתאמות שפה
אפשר להרעיש משפטים בהתאם למשמעות שלהם [6] על ידי שימוש בכמה היוריסטיקות פשוטות:
  • החלפת מילים למילים נרדפות על ידי מילון
  • הכנסה אקראית של מילים נרדפות למילים כלשהן במיקומים הקרובים אליהן לטקסט
  • החלפה אקראית בין זוגות מילים בטקסט
  • מחיקה אקראית של מילים מהטקסט
אפשר כמובן גם למתוח שיטה זו ולהתביית בכוונה על מילים מעניינות למחיקה ובלגון כמו תאריכים, שמות אנשים או באופן כללי "דברים מעניינים". אותם קל מאד למצוא בשיטות קלאסיות של עיבוד שפה.
הרעשות על ידי מודלים
כמובן שאם בידנו יש מודל שפה (ויש בידינו די הרבה מודלי שפה כיום) נוכל להשתמש בו על מנת להחליף מילים רנדומליות בטקסט. כמעט כל מודלי השפה המודרנים (ברט, רוברטה..) אומנו לשחזר מילים לתוך טקסט כשבכל שלב מילה ספציפית הוסתרה מהם. אפשר להשתמש במודלים מסוג זה בצורה פשוטה ביותר על מנת להחליף מילים רנדומליות במשפט ובכל להשתמש באינפורמציה הנמצאת בתוכם כדי לחזק את ביצועי המודל שלנו.
אפשר גם כמובן ללכת שלב אחד קדימה ולהשתמש במודל שמנסח מחדש את המשפט כולו (למהל המודל parrot paraphraser שבנוי במיוחד בשביל זה: https://huggingface.co/prithivida/parrot_paraphraser_on_T5).
טריק פשוט: גוגל טרנסלייט.
טריק פשוט לניסוח מחדש הוא כמובן לזרוק את המשפטים לגוגל טרנסלייט ולתרגם אותם לשפה אחרת ואז מיד לתרגם אותם בחזרה. הטריק שקול לשימוש במודל לניסוח מחדש רק שהמודל הוא המודל שיש בגוגל טרנסלייט.
  • שיטה זו נקראת בשפה המקצועית: Back-translation
הרעשות בתוך הרשת:
מכיוון שמטריצת היצוג של טקסט תלת מימדית (אורך טקסט, טוקן, מימד היצוג) ניתן להרעיש אותה [7] על ידי Dropout מיוחד הבנוי מ"קו" אפסים לאורך אותה המטריצה, כך נקבל כמה הרעשות מיוחדות:
  • הסתרת טוקנים ספציפים
  • הסתרת חלקים ארוכים מהטקסט
  • הסתרת פיצ'רים מהרשת
כל אחת מהרעשות אלו יכולה לעזור לרשת ללמוד יצוגים בצורה איכותית יותר.
שימוש בDropout פשוט:
ישנה גם השיטה הפשוטה יותר [8] של פשוט שימוש בDroput גבוה ולמידה על סמך אותו המשפט לעצמו כשבכל פעם מופעל רעש כבד בתוך הרשת.
האימון של Sentence-BERT
מסתבר שברט הקלאסי לא עובד ממש בלמידת יצוגי משפטים. הבעיה הכללית היא שהוא מתיחס שונה מאד למילים בהתאם לשכיחות שלהן בדאטה בזמן האימון. מאד הגיוני כשמטרת האימון היא לשחזר מילים.
לכן הוצע שיפור לאימון ברט [9]: Sentence Bert מודל שאומן במיוחד ללמוד יצוגי טקסט, ההבדל הגדול הוא שבמקום להשתמש בלמידת MLM (הסתרת מילים ואימון לשחזר את אותן המילים המוסתרות) השתמשו בלמידת ניגוד על פני כמה דאטהסטים במקביל (כך שיש גם תיוגים). במאמר גם נבדקו מספר שיטות שונות לבנית הרשת ואני ממליץ למתעניינים בנושא לעבור עליו.
ישנן עוד כל מיני שיטות שונות ומשונות ללמוד יצוגי טקסט כמו ללמוד האם שני משפטים שייכים לאותה הפסקה או האם משפט שייך לפסקה מסויימת אבל בגדול כמו בכל בעיה אחרת: בדקו על הדאטה שלכם מה עובד הכי טוב.
אם מדידת מרחקי טקסט חשובה לכם, אני ממליץ לכם להציץ [10] בחבילה Sentence Transformers בה אומנו מספר רב של מודלי שפה שונים על טקסט באותן השיטות.
היצוגים של OpenAI
גם לOpenAI יש שירות יצוגי טקסט, היו איתו כמה דרמות בשנה האחרונה, התוצאות הראשוניות היו מאכזבות:
באותה התקופה שוחררו מספר מודלים חדשים לSentence Embeddings שעקפו את ביצועי המודלים של OpenAI, בנוסף שימוש ביצוגים היה יקר במיוחד [יצוגים שעלות מכונה בענן היכולה לייצרם עלו דולר בודד, עלו אצל OpenAI עשרות אלפי דולרים]
לא מזמן שוחרר שירות מעודכן ליצוגי OpenAI שחזר להיות הState Of The Art ובנוסף חתך את עלויות השירות בכ90%.
לא יצא לי לבדוק את השירות אבל ממה שנשמע ברחבי האינטרנט, כנראה שהוא מוצלח מאד.

לא ידועים פרטים על המודלים בשירות וכיצד הם אומנו.

יצוג תמונות

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

אוגמנטציות: הרעשות שאינן משנות את תוכן התמונה – למשל: לסובב אותה.

שיטות בסיסיות:
ישנן דרכים רבות לשנות תמונה תוך שמירה על התוכן שלה. אנו יכולים להשתמש בכל אחת מהדרכים הבאות או בהרכבה של כמה מהן:
  • חיתוך אקראי
  • שינוי גודל
  • עיוותי צבע
  • טשטושי גאוס
  • היפוכים
איך משלבים אוגמנטציות?
אפשר פשוט לרנדם אוגמנטציות: לסובב ואז למתוח.. להפוך ואז להחשיך..
זה עובד. אבל זה לא מגיע לתוצאות הכי הכי טובות.
ישנן דרכים מתוחכמות יותר לשלב בין אוגמנטציות שונות.
  • ללמוד איך לשלב מהדאטה [11] (AutoAugment) לבחור סדר אוגמנטציות (גזירה, סיבוב, היפוך..) על מנת לסווג את התמונה בצורה הטובה ביותר
  • ללמוד חופשי מהדאטה זה קשה, מסתבר שמספיק אבל ללמוד רק פרמטר אחד (RandAugment) "עצימות" של כמה אוגמנטציות במקביל על מנת לקבל תוצאות דומות
  • אפשר גם לנסות ללמוד עם אלגוריתם גנטי [13] אילו אוגמנטציות כדאי לשלב
  • או אפילו למדוד KL בין הדוגמאות [14] על מנת לבחור אוגמנטציות
אוגמנטציות שילוב בין תמונות
אפשר גם לשלב בין כמה תמונות לצורך הרעשה, שיטות אלו חזקות במיוחד ופשוטות מאד!
  • הפשוטה ביותר: MixUP – "לוקחים חתול, מדביקים עליו "קצת כלב שקוף"" – שילוב תמונות באמצעות הדבקה שקופה של אחת על השניה

חשוב גם למשקל את משתנה המטרה בהתאם

  • הפשוטה ביותר 2: CutMix – חותכים חלק מתמונה אחת ומדביקים בתוך אחרת.

שיפור: מציאת חלקים מעניינים על ידי היוריסטיקות כאלו ואחרות

ישנן מספר שיפורים לשיטות אלו אבל הן עובדות מצוין כמו שהן. ממליץ.
אימון ניגודיות בתמונות:
הרעיון מאד פשוט: נרעיש תמונה אחת ונלמד את המודל שמדובר באותה התמונה, השיטה מאד מפורסמת ונראת SimCLR והיא עובדת מצוין. כמובן כמו שצוין למעלה, היא עובדת רק אם הבאצ' גדול מספיק כך שהמודל רואה גם תמונות שאינן דומות וגם תמונות הדומות אחת לשניה.
שיפור: לימוד קורלציה במרחב הנסתר
שיפור לשיטה זו (Barlow Twins) משתמש באותה התמונה מורעשת בכמה הרעשות שונות ולומד על הCross Correlation בין היצוגים. הרעיון הכללי הוא שלא רק נרצה שהיצוגים יהיו זהים, גם נרצה להחליש את כל הרעש סביבם. רעיון זה מאד דומה לCLIP, אליו נגיע בעוד רגע.

גם טקסט וגם תמונה – CLIP

הרעיון הוא פשוט: אם יש לנו תמונות הצמודות לטקסט המתאר אותן, נקח מלא תמונות. נקח מלא טקסט. נכניס את הכל לתוך הרשת ונחשב לכל הזוגות (טקסט תמונה) לוס במקביל כך שכל הזוגות הנכונים ילמדו 1 וכל הזוגות הלא נכונים ילמדו 0.

זה שונה מלמידה פשוטה.

אימון CLIP הוביל ליצוג מוצלח במיוחד גם של יצוג הטקסט וגם של יצוג התמונה במודל [אפשר להפריד בניהם לאחר האימון] וCLIP הוא אחת מאבני הדרך החשובות ביותר בדרך ליצירת תמונות מטקסט.
ההמשך יגיע בחלק ב'..
רפרנסים:
[2] – לוס שכנים קרובים: https://arxiv.org/pdf/1902.01889.pdf
[3] – להרעיש בעצמנו את הדאטה: SimCLR כאן: https://lilianweng.github.io/…/2021-05-31-contrastive/…
[4] – מי שמאמין לא מפחד! כי הבאצ' שלו תמיד בודד! באצ' בגודל 1 או הביתה! בניגוד למה שכולם אומרים: באצ' כמה שיותר קטן בתחילת האימון יוביל אתכם לתוצאות הטובות ביותר! יש לזה מחיר כמובן והמחיר הוא זמן החישוב. בכל מדריך היום כתוב להגדיל את הבאצ' כמה שרק אפשר כי זה חוסך בזמן. אין לי שום בעיה עם הטענה הזו אבל חשוב לדעת (ואף אחד כמעט לא יודע) שעל הזמן הזה אתם משלמים בדיוק של המודל! אז לא "להגדיל כמה שיותר". במקום: "לקחת בחשבון ולתעדף זמן אימון מול דיוק המודל" ומכאן עשו את השיקולים שלכם בהתאם לסיטואציה הספציפית שלכם. וכן, אני באמת מאמן הרבה מודלים עם באצ' בגודל 1!
[5] – הדוגמה החיובית הקלה ביותר והשלילית הקשה ביותר: https://openaccess.thecvf.com/…/Xuan_Improved…
[6] – היוריסטיקות פשוטות להרעשת טקסט: https://arxiv.org/abs/1901.11196
[7] – הרעשות בתוך הרשת: https://arxiv.org/abs/2009.13818
[8] – שימוש בDroput פשוט בשיטת SimSCE כאן: https://arxiv.org/abs/2104.08821
[9] – אימון ברט במיוחד ללמידת יצוג טקסט: https://arxiv.org/abs/1908.10084
[10] – החבילה Sentence Transformers כאן: https://huggingface.co/sentence-transformers
[11] – ללמוד לשלב אוגמנטציות מהדאטה – AutoAugment כאן: https://lilianweng.github.io/…/2019-05-05-domain…/…
[12] – מספיק ללמוד פרמטר עצימות בודד: RandAugment כאן: https://arxiv.org/abs/1909.13719
[13] – ללמוד אוגמנטציות עם אלגוריתם גנטי: https://arxiv.org/abs/1905.05393
[14] – למדוד KL לצורך אוגמנטציות: https://arxiv.org/abs/1904.12848
[15] – אותה דוגמה, מורעשת כמה פעמים – SimCLR כאן: https://arxiv.org/abs/2002.05709
[16] – לימוד על סמך קורלציה, כאן:https://arxiv.org/abs/2103.03230
[17] – גם טקסט וגם תמונה – CLIP כאן: https://arxiv.org/abs/2103.00020
עוד בנושא: