close menu

סיכום תחרות: Tweet Sentiment Extraction בקאגל

המדריך עלה כפוסט של ים פלג בקבוצת Machine & Deep Learning Israel

כבר הרבה זמן שאני מחפש בעית שפה "להשתפשף עליה" בשביל ללמוד יותר טוב את התחום.
אז אחרי הפסד מטופש בARC (הגשה ששווה מדליית כסף באיחור של חמש דקות) נכנסתי לי לקאגל וגיליתי שרצה תחרות NLP ואני בדיוק תופס אותה בשבועיים האחרונים שלה.
התחרות: Tweet Sentiment Extraction.
על תחילת התחרות: לקחתי את כל הדאטה, זרקתי אותו לgoogle translate, תרגמתי אותו לרוסית, צרפתית, גרמנית, ספרדית -> חזרה לאנגלית.
יופי! עכשיו יש לי יותר דאטה מכולם ואני אפילו לא דובר אף אחת מהשפות. אז בלי לחשוב יותר מידי, אימנתי רוברטה (roBERTa) והגשתי: מדליית כסף.
עכשיו אפשר ללכת לקרוא את החוקים ולהבין על מה התחרות בכלל.

על התחרות:
הבעיה על פניו נראית פשוטה: נותנים לנו משפט, אומרים לנו מראש האם הסנטימנט שלו חיובי או שלילי ומבקשים מאיתנו "למרקר" את החלקים במשפט שגרמו לסנטימנט להיות חיובי או שלילי. המטריקה היא Jaccard. הגיוני ומריח שאפשר "לקמבן" את המטריקה.
מיותר לציין: אנשים לא כותבים אנגלית תקנית בטוויטר. הדאטה סופר מלוכלך ומפוצץ בסלנג.
משפטים המכילים because ו cuz או XOXO נפוצים מאד.
כנ"ל אימוג'ים. בכל מקום אימוג'ים.
התיוג עצמו של הדאטה היה ברמה נמוכה מאד (אגיע לזה), לאמן על כל הבלאגן הזה מודל == ללמוד את הפאשלות של המתייגים.
לפני שאתחיל להרחיב עד כמה הבעיה הזאת קשוחה, הניסוי הראשון שהרצתי (בעיקר מתוך עניין): Unsupervised! לקחתי roBERTa ואימנתי אותו (או אותה? רוברטה! איזה שטויות!) לחזות את הSentiment, הרצתי GradCAM והשתמשתי בגרדיאנטים בתור הפרדיקציה.
אמנם לא תוצאה ששווה מדליה אבל התוצאה היתה מרשימה! אותי זה הפתיע!
התחלתי את התחרות כמו שאתם מדמיינים, אימנתי את כל הטרנספורמרים על כל הטוקנייזרים כדי לבדוק ביצועים: אני מזכיר, אני רוצה לדעת בעצמי מה עובד הכי טובה!
התחלתי לחטט במודלים של "פרצוף מחבק" ופשוט הרצתי את כולם: for i in transformers: תתאמן!
אימנתי:
  • Bert
  • GPT
  • Transformer XL
  • GPT-2
  • XLM
  • XLNet
  • RoBERTa
  • DistilBERT
  • CTRL
  • CamemBERT
  • ALBERT
  • XLM-RoBERTa
  • FlauBERT
  • Bart
  • T5
  • ELECTRA
  • DialoGPT
  • Reformer
  • MarianMT
  • Longformer
  • Linformer (בעקבות דיונים כאן בקבוצה)
חלק מהם לא בנוים למשימה הזאת אז פשוט טענתי אותם: חתכתי מהם את "הבשר" עם הטרנספורמרים ועשיתי FineTuning לבעיה.
אמ;לק ביצועים:
roberta-base > bert-base > bert-large > xlnet-base > roberta-large
אני מנחש שזה בגלל Overfitting של roBERTa Large לדאטה.
חלקכם בשלב זה לא מבינים על מה אני מדבר בכלל חוץ מזה שלכולם קוראים ברט, אלברט, רוברט, רוברטה, אלברטו, ברטיסלבה, ויברטור, הילברט…
מה העניין עם כל משחקי המילים וBERT ?
אנסה להסביר..

סיכום טרנספורמרים

מה זה אטנשן? מה זה טרנספורמר? מה זה BERT?

אטנשן – שיטה שנמצאת בכל מקום במודלים מודרניים של למידה עמוקה. אבל מה זה?
אישית, כשניסיתי ללמוד בעצמי איך עובדים הטרנספורמרים נתקלתי בבלאגן אחד גדול, כל פוסט וכל מאמר המדבר על טרנספורמרים היה מלא עד אפס מקום בטריקים ומאות מושגים שונים ומשונים. חלקם מעורבבים בבדיחות ומשחקי מילים עם "Bert", מה שרק מחמיר את הקושי להבין את הנושא.
אטנשן הוא טריק שסייע בשיפור הביצועים של מודלי שפה מודרניים – טרנספורמרים.
נתחיל בכך שנראה את המודל כקופסה שחורה אחת. למשל: לתרגום, המודל לוקח משפט בשפה אחת, ומוציא משפט אחד מתורגם לשפה אחרת.
הטרנספורמר מורכב מרכיב קידוד, רכיב פענוח וקשרים ביניהם.
רכיב הקידוד הוא ערמת אנקודרים אחד על השני. (במאמר המקורי היו שישה מקודדים). רכיב הפענוח הוא ערמת מפענחים בגודל זהה.
המקודדים כולם זהים במבנה (ובכל זאת הם לא חולקים משקולות). כל מקודד מחולק לשתי שכבות:
כניסות המקודד זורמות תחילה דרך שכבת Self Attention – שכבה המסייעת למקודד להסתכל על מילים אחרות במשפט הקלט כשהוא מקודד מילה ספציפית. נסתכל מקרוב מקרוב על אטנשן עצמי בהמשך הפוסט.את התוצאה מזינים לשכבת Fully Connected. כאן יש טריק: אותה שכבת FC רצה על כל מילה בנפרד! לא על כולן ביחד. (בקרס: TimeDistributed(Dense)).
למפענח יש גם את שתי השכבות הללו, אך ביניהן גם שכבת אטנשן שעוזרת למפענח להתמקד בחלקים רלוונטיים במשפט הקלט (בדומה למה שעושה אטנשן במודלים seq2seq).כפי שקורה ביישומי NLP באופן כללי, אנו מתחילים בהפיכת כל מילת קלט לווקטור באמצעות אמבדינגס.
כל מילה מקבלת ווקטור אמבדינגס בגודל 512. בגרסה הפשוטה ביותר: כל מילה מיוצגת על ידי וקטור One-Hot (הכל אפסים חוץ מאינדקס אחד ספציפי שבו יש 1) והאמבדינגס הוא פשוט הכפלה (dot) של וקטור המילה במטריצת משקולות נלמדת. מהאורתוגונליות של OneHot, המילים עצמן מקבלות על ידי ההכפלה יצוגים בלתי תלוים.
בBert, האמבדינגס קורה רק במקודד התחתון ביותר. אז: הפשטה לכל המקודדים: הם מקבלים רשימת וקטורים כל אחד בגודל 512 – במקודד הראשון הוא יהיה האמבדיגנס של המילה, אך במקודדים אחרים זה יהיה הפלט של המקודד שנמצא ישירות לפני. הגודל של רשימה זו הוא hyperparameter שאנחנו יכולים להגדיר – בעיקרון זה יהיה אורך המשפט הארוך ביותר בסט האימון שלנו. לאחר קידוד המילים ברצף הקלט, כל אחת מהן זורמת בכל אחת משתי השכבות של המקודד.
כאן אנו מתחילים לראות מאפיין מפתח של טרנספורמרים, והוא שהמילה בכל מיקום זורמת בנתיב משלה (!!) בקודד. יש תלות בין נתיבים אלה בשכבת האטנשן. עם זאת, בשכבת הFC אין תלות, (TimeDistributed). כפי שכבר הזכרתי, מקודד מקבל רשימה של וקטורים כקלט. הוא מעבד רשימה זו על ידי העברת וקטורים אלה לשכבת 'אטנשן עצמי', אז לFC, ואז שולח את הפלט כלפי מעלה לקודד הבא.
עוד פעם: המילה בכל עמדה עוברת תהליך של אטנשן עצמי. ואז, כל אחד מהם עובר דרך שכבת FC – אותה שכבה בדיוק כשכל וקטור זורם דרכה בנפרד.
מה זה אטנשן?
לא להתבאס עלי בבקשה כי אני זורק את המושג "אטנשן עצמי" כאילו זה מושג שכולם צריכים להכיר. לקח לי אישית הרבה זמן להבין "מה הקטע" שלו ומעולם לא נתקלתי במשהו דומה עד שקראתי את המאמר Attention is All You Need.
נניח שהמשפט הבא הוא משפט קלט שאנחנו רוצים לתרגם:
"החיה לא חצתה את הרחוב מכיוון שהיא הייתה עייפה מדי"
מה הכוונה ב"זה "במשפט זה? האם הכוונה לרחוב או לבהמה? זו שאלה פשוטה לאדם, אבל לא פשוט לאלגוריתם.
כאשר המודל מעבד את המילה "זה", אטנשן עצמי מאפשרת לו לקשר "זה" ל"חיה ".
כאשר המודל מעבד כל מילה (כל מיקום ברצף הקלט), התייחסות עצמית מאפשרת לו להסתכל על עמדות אחרות ברצף הקלט ולחפש רמזים שיכולים להוביל לקידוד טוב יותר למילה זו. בדומה לRNNs, שמירה על מצב נסתר מאפשרת ל- RNN לשלב את יצוג של מילים / וקטורים קודמים שעובדו עם המילה הנוכחית המעובדת. אז אטנשן עצמי היא שיטה דומה כדי ללמוד את "היצוג" של מילים רלוונטיות אחרות לזו שאנו מעבדים כעת. אבל, וזה אבל גדול: זה לא סתם FC בין כל המילים לכל המילים – זאת רשת שלמה בין כל מילה לכל מילה.
מימוש במציאות: השלב הראשון בחישוב הוא יצירת שלושה ווקטורים מכל אחד מקטורי הקלט של המקודד.
אז עבור כל מילה, אנו יוצרים וקטור שאילתה, וקטור מפתח ווקטור ערך.
וקטורים אלו נוצרים על ידי הכפלת האמבדינגס בשלוש מטריצות שנוצאו בתהליך האימון [קסם. זה לא מעניין אתכם כרגע].
הווקטורים החדשים הללו קטנים יותר בממדים מהווקטור המוטמע. הממדיות שלהם היא 64, בעוד שלקטורי הכניסה / פלט המקודדים והמקודדים יש ממד של 512. הם לא צריכים להיות קטנים יותר, זו בחירה בארכיטקטורה כדי להפוך את החישוב של אטנשן רב-ראשית (לרוב) קבוע.
הכפלת x1 במטריצת המשקל WQ מייצרת q1, וקטור "השאילתה" המשויך למילה זו.
בסופו של דבר אנו יוצרים "שאילתה", "מפתח" ו"ערך" של כל מילה במשפט הקלט.
כמה נחמד מצידי לפתוח את הפוסט במרמור על עודף המושגים ואז להשתמש בהם בעצמי.
הרשו לי לתקן:
מה הם הווקטורים "שאילתה", "מפתח" ו"ערך"?
הם סתם שמות. הפשטות שימושיות לחשיבה על אטנשן. ספקולציות ל"איך זה עובד". השלב השני בחישוב האטנשן הוא חישוב ציון. נניח שאנחנו מחשבים את האטנשן של המילה הראשונה במשפט כלשהו, עלינו לדרג כל מילה במשפט הקלט כנגד מילה זו. הציון קובע כמה פוקוס צריך לרכז בחלקים אחרים במשפט הקלט כאשר אנו מקודדים את המילה.
הציון מחושב על ידי dot של וקטור השאילתה עם וקטור המפתח של המילה המתאימה שאנו מדרגים. אם אנו מעבדים את האטנשן העצמי של המילה במיקום מספר 1, הציון הראשון יהיה תוצר הנקודה של q1 ו- k1. הציון השני יהיה תוצר הנקודה של q1 ו- k2.
השלבים הבאים הם חלוקת הציונים בשורש הריבועי של הממד של וקטורי המפתח: בשביל שיפועים יציבים יותר – אין קסם. אחרי זה זורקים הכל לsoftmax. ציון softmax זה קובע עד כמה כל מילה אחרת תבוא לידי ביטוי בקידוד המילה במיקום זה.
בשלב הבא: מכפילים כל וקטור ערך בציון הsoftmax. האינטואיציה כאן היא לשמור ערכי המילים בהן אנו רוצים להתמקד, ולקטין את המילים לא רלוונטיות (על ידי הכפלתן במספרים זעירים כמו 0.001 למשל שנלמדו באטנשן).
השלב האחרון הוא לסכום את הוקטורים המשוקללים. זה מייצר את התוצאה של האטנשן העצמי במיקום זה.
והנה הטריק: רק במיקום זה!! כל מה שנשאר לעשות הוא לעשות את אותו החישוב בדיוק לכל אחת המילים אחרות.
להלן האנטנשן של BERT:
def scaled_dot_product_attention(q, k, v, mask):
w = batch_dot(q, k)
w = w / K.sqrt(K.cast(list(v.shape)[-1], K.floatx()))
w = mask * w + (1.0 – mask) * -np.inf
w = K.softmax(w)
return batch_dot(w, v)
"אטנשן מרובה ראשים", מה זה?
כדי לחדד עוד יותר את האטנשן העצמי, נוסף אליו מנגנון המכונה אטנשן "רב-ראשי". אנלוגיה לא רעה למנגנון (לדעתי): פילטרים ברשתות קונבולוציה, יש כמה מהם שרצים במקביל על אותו הקלט.
הרעיון של "Multi Head" משפר ביצועים בשני אופנים:
  • הוא מרחיב את יכולת המודל להתמקד בעמדות שונות. יהיה מועיל אם נתרגם משפט כמו "החיה לא חצתה את הכביש מכיוון שהיא הייתה עייפה מדי", היינו רוצים לדעת לאיזו מילה "היא" מתייחסת. למרות שבעברית "היא" לא מתייחסת לרחוב. אולי היתי צריך לחשוב על דוגמה טובה יותר, אבל הבנתם.
  • הוא נותן לאטנשן "תת מרחבים לייצוג".
כפי שנראה בהמשך, עם אטנשן מרובת ראשים יש לנו לא רק אחת, אלא מספר קבוצות של מטריצות משקל של שאילתה / מפתח / ערך (בטרנספורמר משתמשים בשמונה ראשי אטנשן, כך שבסופו של דבר אנו מכילים שמונה סטים לכל קידוד / מפענח). כל אחת מהסטים הללו מאותחלת באופן אקראי. לאחר האימונים, כל קבוצה משמשת לאמבדינגס של הקלט (או וקטורים מקודדים / מפענחים) לתת-דומיין שונה בייצוג.
באטנשן מרובת ראשים אנו מקפידים על וקטורי משקל Q / K / V נפרדים עבור כל ראש וכתוצאה מכך מטריצות Q / K / V שונות. אז בדיוק כפי שעשינו בעבר, אנו מכפילים את X במטריצות WQ / WK / WV כדי לייצר מטריצות Q / K / V. אם אנו מבצעים את אותו חישוב של אטנשן עצמי שתיארנו לעיל, אנו נשארים בסופו של דבר עם שמונה מטריצות Z שונות.
בעיה: שכבת הFC קדימה אינה מצפה לשמונה מטריצות – היא מצפה למטריצה ​​אחת (וקטור לכל מילה). אז אנחנו צריכים דרך להפוך את שמונת המטריצות אלה למטריצה ​​אחת. איך עושים זאת? אנו משרשרים את המטריצות ואז מכפילים על ידי מטריצת משקולות נוספת WO.
זה בערך הכל. הנה:
def split_heads(x, n, k):
return K.permute_dimensions(K.reshape(x, list(x.shape)[:-1] + [n, list(x.shape)[-1] // n]), [0, 2, 3, 1] if k else [0, 2, 1, 3])
def heads_merge(x):
return (lambda new_x: K.reshape(new_x, list(new_x.shape)[:-2] + [np.prod(list(new_x.shape)[-2:])]))(K.permute_dimensions(x, [0, 2, 1, 3]))
def multihead_attention(x, mask, n_head, n_state):
_q, _k, _v = x[:, :, :n_state], x[:, :, n_state:2 * n_state], x[:, :, -n_state:]
q = split_heads(_q, n_head)
k = split_heads(_k, n_head, k=True)
v = split_heads(_v, n_head)
a = scaled_dot_product_attention(q, k, v, mask)
return merge_heads(a)
וכמו שבטח שמתם לב, Multi head הוא קונספט. אפשר להריץ Multi Head על כל דבר.
פרט אחד בארכיטקטורה של המקודד שעלינו להזכיר לפני שנמשיך הלאה, הוא שלכל שכבת משנה (אטנשן עצמי, FC) בכל מקודד יש residual סביבו, ואחריו Layer Normalization. אלו אמנם קונספטים חשובים (ובהחלט משפרים את הרשת) אבל לא אכנס אליהם עכשיו.
שכבות האטנשן העצמי במפענח פועלות בצורה מעט שונה מזו שבמקודד:
במפענח מותר לשכבת האטנשן לטפל רק במיקומים קודמים ברצף הפלט. זה נעשה על ידי mask לעמדות העתידיות (קובעים אותן ל- inf) לפני הSoftmax בחישוב.
שכבת האטנשן של המפענח עובדת ממש כמו אטנשן עצמי מרובה-ראש, היא יוצרת את מטריצת השאילתות שלה מהשכבה שמתחתיה, אבל לוקחת את מטריצת המפתחות וערכים מהפלט של המקודדים. מכאן כבר אפשר לחבר את הטרנספורמר לכל שכבה או רשת שרק נרצה.
אימונים
כעת, לאחר שסקרנו את כל תהליך העיבוד בטרנספטורמר, כדאי להביט באינטואיציה של האימון.
טכניקת האימון הפשוטה ביותר היא Masked Language Modeling: MLM – נזרוק לרשת משפטים, נסתיר מילה אחת (או כמה) בכל משפט ונבקש ממנה לשחזר את המשפט.
התהליך נעשה כמו בAuto Encoder, הקלט הוא המשפט המוסתר והפלט הוא המשפט המלא. לי אישית כל זה מזכיר באינטואיציה קצת את Word2Vec. רק מרובה-ראש.
טוקנייזרים
מילים מגיעות באותיות, רשתות נוירונים עובדות עם מספרים. הפתרון: טוקנייזרים:
אוצר המילים של הפלט של המודל שלנו נוצר בשלב העיבוד המוקדם עוד לפני שאנחנו מתחילים להתאמן.
ברגע שאנו מגדירים את אוצר המילים שלנו, נוכל להשתמש בווקטור באותו רוחב כדי לציין כל מילה באוצר המילים שלנו. זה ידוע גם כOne Hot Encoding.
אני חייב להודות שהתחום כל כך בילבל אותי עד כדי שלי אישית לקח כמה חודשים טובים לעשות סדר ולהגיע למצב שאני באמת מבין מה עשו בכל המאמרים.
אותי בעיקר בילבל שלכל המושגים יש את אותו השם ולכל טריק הכי הכי קטן נתנו שם, דוגמה: Position Embeddings בBERT: להעביר וקטור אינדקסים דרך Cos ולהכפיל ובקטור עצמו כדי לתת משמעות שונה למילים המגיעות בתחילת המשפט אל מול מילים הנמצאות בסוף המשפט. אם נעשה את אותו הדבר אבל רק למילים המגיעות לפני המילה הנוכחית אז זה נקרא: Relative positional encoding (עשו את זה בXLNet).
לדעתי אפשר לחלק את כל השיפורים בכל המאמרים לכמה קטגוריות עיקריות:
  • טוקנייזר
  • ארכיטקטורה
  • שיטת אימון
  • דאטהסט
  • "למי יש יותר גדול [GPU כמובן]" – זה חלק מהתחום כיום.
רגע לפני שנחזור לדבר על התחרות:
אני נהנה להרוס – למחוק חלקים ממאמרים ולראות בעצמי האם הם נחוצים או לא: עשיתי את זה גם לטרנספורמרים.
בכל מקרה, את BERT אנחנו כבר מכירים: כל מה שקראתם עד עכשיו מגיע מBERT קלאסי.
נעבור על חלק מהטרנספורמרים האחרים (סיננתי מראש טריקים יותר מידי ספציפיים):
טריקים בGPT-2:
  • שיטת אימון: Causal Language Modeling (CLM) – במקום להשלים Masking: מקבל חלק ממשפט -> צריך לחזות את המילה הבאה בכל משפט.
  • טוקנייזר: byte pair encoding(BPE) – אני מפשט קצת אבל בגדול: עוברים על כל זוגות האותיות ומחפשים זוגות המופיעים בתדירות גבוהה. לאחר מכן עוברים על כל הזוגות ומחפשים רביעיות.. המוטיבציה: לאחד יצוג מילים כמו: low ו lower. שברמת המילה יקבלו יצוג שונה וברמת האותיות קשה ללמוד.
טריקים בTransformer-XL:
  • כל טרנספורמר שתאמנו יפשל יותר ככל שהמשפטים יהיו ארוכים יותר: הרעיון פה הוא ליצור אחד שפחות רגיש לאורך המשפט.
  • טריק: Positional Encoding רלטיבי: מסתכלים על מילה ספציפית, מעבירים את האינדקסים של שאר המילים ביחס אליה דרך sin או cos או שניהם.
  • הוא אחד המודלים היחידים שאין בארכיטקטורה שלהם הגבלה מובנית לאורך המשפט.
טריקים בXLM:
  • המודל מאומן על כמה שפות במקביל, משתמש בBytePair ובאימון שלו (לפי מה שאני מבין) מכניסים משפט בשפה אחת ונותנים לו להשלים את הMask בשפה אחרת. אני מזכיר: הוא משתמש בBytePair כדי שיהיו יותר טוקנים משותפים בין השפות.
  • עוד טריק: הוא מקבל ID משורשר למשפט של "באיזו שפה" המשפט.
טריקים בXLNet:
  • הרבה יותר מידי. ניסינו פעם כמה חברים מהקבוצה לרשום על לוח מחיק את כל הטריקים ברשת ונגמר הלוח. לא אתחיל אפילו.
  • הטענה המרכזית היא שMasking לא מכריח את המודל ללמוד את המשמעות של כל המילים במשפט, לדוגמה: הביטוי "New York" אם יכנס אל המודל כ "___ New", בסבירות גבוהה מאוד תהיה מילה אחרת (מספיקה רק אחת) המרמזת על העיר וממנה אפשר לשנן שצריך להשלים את "New York". תוך כדי התעלמות ממשמעות הביטוי.
  • התיקון: נבחר Subset רנדומלי של מילים מסביב למילה החסרה [תוך שמירה על סדר] ונשתמש בהן כדי לחזות את כל המשפט כולל המילים החסרות.
אני רק רוצה לציין שלא ראיתי בעיה אחת שהרשת הזאת מגיעה להיות SOTA עליה במציאות (המציאות שלי: כשאני מאמן) אבל זו רשת שקשה לאמן ויכול להיות שיש פוטנציאל לא מנוצל בשיטה.
טריקים בroBERTa:
  • המודל נחשב הGO-TO בקאגל, עובד מצוין מהקופסה על הרבה בעיות במכה.
  • השינוים בו ביחס לBERT הם בעיקר hyperparameters, העיפו את הNSM ואימנו עם Batchים ענקיים וLR ענקיים. (זה הגיוני, כשיש משפטים ארוכים ואנחנו מחפשים תופעה קטנה שנגרמת ממספר מילים בודדות: הרבה רעש בגרדיאנט. באצ' גדול יותר ממצע את הרעשים)
  • הם משתמשים בBytePairs, מאמנים תמיד על אותו גודל משפט, מאמנים עם AdamWarmup עם מספר איטרציות אתחול ועל הדרך הוסיפו טריק קטן לאמבדינגס כדי לעזור לנו לעשות fine-tuning.
בשפה פשוטה: לקחו את BERT, עשו ממנו קאגל, יצא SOTA בהכל.
טריקים בELECTRA:
  • הרעיון הוא להשתמש בGAN, גנרטור שיבחר מילים ספציפיות במשפט ויחליף אותן במילים רנדומליות ודיסקרימינטור (המודל הסופי שלנו) שיתקן את המשפט.
  • נחשב היום הSOTA בהכל, לא הצלחתי לעקוף איתו את roBERTa אבל הרעיון הכללי עובד טוב גם במודלים אחרים.
טריקים בALBERT:
  • כדי להקטין את ברט, שינו את המימדים הפנימיים של השכבות והוסיפו Shared Weights בין כל הבלוקים, העיפו את הDropOut (בתירוץ שיש להם יותר דאטה), הוסיפו sentence swapping objective. בגרסאות הגדולות הוא אחד לאחד BERT או BERT-Large.
טריקים בStructBERT:
  • רנדומלים מערבבים שלשות מילים במשפט ונותנים למודל לתקן אותן. שיפור ניכר ביחס לBERT וגם ביחס לroBERTa. לא היו מספיק כאלו Pretrained כדי שאוכל לנסות אותם בתחרות.
טריקים בBART:
  • שיטת Pretraining חדשה: מסתירים חלקים שלמים (כמה מילים) עם Mask ורנדומלית גם דוחפים Masking Token בין מילים צמודות במשפט: הרעיון הוא להכריח את המודל ללמוד האם כל Masking באמת מסתיר חלק מהמשפט או לא. לטענתם המודל מגיע לSOTA על הרבה בעיות. לא יצא לי לראות זאת בעצמי אבל חשוב לציין שאין הרבה מודלים כאלו מאומנים וזהו אולי הסיבה.
טריקים בLongformer:
  • טרנספורמרים מפשלים במשפטים ארוכים כי Self Attention גדל ריבועית באורך הקלט הרעיון הוא לפרמל מחדש את האטנשן שיהיה לינארי באורך הקלט. השיטה פשוטה: חלון – כל מילה מקבלת רפרזנטציה רק ממילים הנמצאות במרחק לינארי w ממנה [כשw היפרפרמטר]. בשביל מידע גלובלי במשפט משתמשים בעוד שכבת אטנשן [משקולות נפרדות] ממילים נבחרות במשפט לn מילים נבחרות במשפט. איזו מילה הולכת לאיזו שכבה נקבע ידנית. סיבוכיות: O(n x m).
טריקים בLinformer:
  • טרנספורמרים מפשלים במשפטים ארוכים כי Self Attention גדל ריבועית באורך הקלט הרעיון הוא לפרמל מחדש את האטנשן שיהיה לינארי באורך הקלט. אטנשן הוא Low rank – אפשר לקרב את האטנשן על ידי SVD. אבל SVD זה כבד חישובית אז נקרב את SVD של אטנשן.
עברית: מוכיחים ואז מפרמלים קירוב לאטנשן שגדל לינארית באורך הקלט – בדקו רק על דאטהסטים קטנים אבל מאורך משפט מסוים הם הSOTA עליהם [עוקפים roBERTa].
מדריך פרקטי
קיבלתי הרבה מחמאות ושאלות פרקטיות בפרטי.
א. תודה, אתם מחממים לי את הלב אבל בבקשה לא לקחת את מה שעשיתי פה יותר מידי ברצינות – בסופו של יום לא ניצחתי את התחרות.
ב. להלן מדריך קצרצר כדי שגם אתם תוכלו להנות מכל הטוב הזה!
המדריך מדגים רק Transfer Learning על מנת לא להעמיס, אלו המעוניינים בPretraining בעצמם [MLM, XLM וכו'] מוזמנים לפנות אלי בפרטי ואעזור להם. אישית בשביל התחרות השתמשתי בhuggingface – ספריה פשוטה המממשת את כל הטרנספורמרים גם בטנזורפלו וגם בפייטורצ'. חשוב לציין: אישית השתמשתי בטנזורפלו [בשביל קרס] אבל הספריה תומכת בצורה מושלמת בשניהם אבל יותר חשוב: במעבר ביניהם: אפשר לטעון משקולות שאומנו בפייטורצ' למודל טנזורפלו ולהפך! זאת הפעם הראשונה שאני רואה כזה דבר. כן ירבו!
לאורך התחרות הורדתי וניסיתי מודלים שאומנו בשתי החבילות והכל עבר חלק. על מנת לעשות את זה בעצמם, הוסיפו את הפרמטר: from_pytorch=True למודל שלכם. זהו.
מילה נוספת על MinimalIsAllYouNeed שלי לפני שאמשיך: זה ניסיון שלי "לעשות את הhuggingface" לפני שהיה huggingface. הספריה בשלב ניסויי ולמרות שהיא תומכת בכך, לא היתי משתמש בה עם משקולות pretrained. הרעיון הכללי בספריה הוא לרדד את ארכיטקטורות המודלים עצמם לכמה שפחות קוד. המטרה המקורית היתה מחקר ארכיטקטורות טרנספורמרים.
מכאן, אמשיך עם huggingface:
כמו שאמרנו, ישנם כמה חלקים עיקריים בעבודה עם מודלי שפה מודרניים:
אימון מקדים:
הזכרנו את:
MLM – Masked Language Modeling – מכניסים משפט עם מילים חסרות, מאמנים לשחזר את המשפט המלא.
XLM – מכניסים משפט או משפטים בכמה שפות + טוקן מיוחד המסמן את השפה, מאמנים MLM לשחזר בין השפות.
נוסיף:
Causal Language Modeling – CLM – כמו MLM אבל החיזוי הוא רק ל"המשך" המשפט במקום למילים החסרות בכל המשפט. בפועל המודלים יוצאים חזקים יותר למשימות יצירת טקסט כי המשימה מזכירה יותר יצירת טקסט.
Translation Language Modeling – TLM – כמו MLM אבל החיזוי מתבצע על משפטים משתי שפות במקביל. [Concat של שני משפטים עם אותה המשמעות]
המודלים בhuggingface מגיעים עם קונבנציית שמות פשוטה: שיטתאימון-מודל-דאטה.
לדוגמה: אם נרצה להשתמש בroBERTa המאומן XLM, נשתמש במודל "XLM-roBERTa".
דאטה באימון מקדים:
עיבוד שפה הוא תחום רחב. מחיזוי סנטימנט [שלילי \ חיובי] במשפטים, דרך תרגום ,מענה על שאלות ועד ליצירת טקסטים שלמים: מודלים המאומנים לבעיות מסוימות יהיו טובים לpretraining לבעיות מסוימות.
בעיות שפה נפוצות:
  • language-modeling
  • text-classification דאטהסטים נפוצים: GLUE, XNLI
  • token-classification דאטהסטים נפוצים: CoNLL NER
  • multiple-choice דאטהסטים נפוצים: SWAG, RACE, ARC
  • question-answering דאטהסטים נפוצים: SQuAD
  • summarization דאטהסטים נפוצים: CNN/Daily Mail
  • translation דאטהסטים נפוצים: WMT
  • adversarial דאטהסטים נפוצים: HANS
שוב, קונבנציית השמות היא: שיטתאימון-מודל-דאטה – לכן, אם נרצה לדוגמה מודל roBERTa שאומן לענות על שאלות בכמה שפות מדאטהסאט SQuAD, נשתמש במודל XLM-roBERTa-SQuAD.
המודלים עצמם:
המודלים בתחום מגיעים בכמה גדלים, וכמה תצורות. רובם המוחלט בקונבנציית שמות:
small, base, large.
ובחירה אחרונה שעלינו לבצע: האם המודל שלנו התאמן על טקסט המגיע רק באותיות קטנות או שהוא תומך גם באותיות גדולות? קונבנציית השמות: cased, uncased
בתחרות אישית השתמשתי בכמה מודלים וכמה תצורות באנסמבל כשאחד מהם היה xlm-roberta-cased-large-suqad. השמות היו אינפורמטיביים וזה הקל על העבודה.
קוד:
בhuggingface יש מחלקות לכל ארכיטקטורה נתמכת והמחלקות מגיעות בכמה תצורות [למשל: ללא ראש קלסיפיקציה או עם שני ראשי BERT הקלאסי].
אדגים שימוש במחלקה אחת פשוטה, את שאר השימושים תמצאו בתיעוד המצויין של החבילה:
from transformers import TFRobertaModel
model = TFRobertaModel.from_pretrained('roberta-base')
וזהו.
מכאן יש לכם model בקרס, עליו אתם יכולים להרכיב אילו שכבות שתרצו, לקמפל [model.compile('categorical_crossentropy', 'adam')] ולהריץ model.fit, model.predict.
טוקנייזרים:
כבר הזכרנו שלכל מאמר יש שיטת קידוד משל עצמו, חשוב לשים לב שהמקודד עצמו מכיל מידע מהדטה עליו הוא אומן והמודל בונה על כך. אם נרצה להשתמש במודל שאומן מראש נאלץ להשתמש במקודד איתו הוא אומן. קוד:
from transformers import RobertaTokenizer
tokenizer = RobertaTokenizer.from_pretrained('roberta-base')
זהו.
מכאן יש לנו אובייקט שכדי לקודד איתו משפט נשתמש בtokenizer.encode וכדי לפענח איתו משפט מהמודל נשתמש בtokenizer.decode.
חשוב באותה הנשימה לציין את החבילה: tokenizers, בחבילה זו יש את כל הטוקנייזרים ללא תלות במאמרים בהם הם פורסמו. כולם תומכים בטעינה מhuggingface וגם בfine_tuning ולכן אם נרצה למשל לטעון tokenizer שאומן "רגיל" ולהוסיף לו tokens המאומנים BytePair נשתמש בtokenizers.ByteLevelBPETokenizer.
עשיתי זאת בתחרות וזה עבד מצוין.
לכל שאר הטענות, שאלות: תיעוד החבילה: https://huggingface.co/transformers/
איפה מוצאים מודלים מאומנים?
הפרוייקט פתוח לגמרי והמודלים מאומנים על ידי כל הקהילה מכל העולם. ישנם גם מודלים בעברית.
שוב, כדי להשתמש בהם: העתיקו את הכתובת של המודל המעניין אתכם לתוך from_pretrained והוא מוכן לשימוש.

חזרה לתחרות

אחרי ברוטפורס מודלים והיפרפרמטרים התקבעתי על roBERTa, על GPT-2 (לא לדאוג. חכו.) וXLNet (למרות הביצועים, רציני שונות) התחלתי לאמן אנסמבל.
בשלב הזה אשמח לתרץ את הכשלון שלי בתחרות מראש: בחודש וחצי האחרונים נלחמתי מלחמה אלימה עם טנזורפלו כמו שחלקכם ראיתם בקבוצה של הQ&A. היא הסתיימה בכניעה מוחלטת שלו ובPR פאצ' לבאג בפייתון עצמו. למרות הנצחון, היה נורא ואיום. טנזורפלו נלחם בי באומץ וגזל ממני זמן יקר בתחרות (שגם ככה היתה שבועיים לסיום כשהצטרפתי).
הסטאפ באימון היה פשוט: שני "ענפים" למודל, האחד חוזה את "תחילת המירקור" והשני חוזה את "סוף המירקור"
אימנתי RoBERTa-base-squad2, RoBERTa-large-squad2, DistilRoBERTa-base, XLNet-base-cased והגשתי: לא הלך.
עברתי לאמן עם נייטרוס (מהתחרות הקודמת, זוכרים?) ועם random learning rate וrandom batch-size: נייטרוס אופטימייזר "אגרסיבי", הוא מעדכן משקולות רק בשיפור על הval set אז הרשתי לעצמי להתפרע – שיפר תוצאות!
הוספתי לכל אחד מהמודלים רשת CNN קטנה בסוף הטרנספורמר כי הבעיה "הריחה" כמו חיפוש תבניות: שיפר תוצאות!
המשכתי והלכתי צעד קדימה: הוספתי את כל WaveNet בסוף כל טרנספורמר ואימנתי לסירוגין או את WaveNet או את הטרנספורמר End2End: שיפר תוצאות!
אני מנחש שבשלב הזה מגיע לי הכבוד להמציא למודל שם שהוא משחק מילים עם BERT, זה ממש קל:

סייברט – cyBERT.

אימנתי אנסמבל חדש: CyBERT-base-squad2, CyBERT-large-squad2, DistilCyBERT-base, XLCybBERTNet-base-cased ומצאתי את עצמי עם…
כלום.
כלום?
לפני כמה ימים היתי בטופ של הטבלה, מה קרה?!
הלכתי לחקור את הDiscussions: מסתבר שאף אחד לא מדבר על טרנספורמרים. כולם כולם מדברים על איזה Magic Feature שיש בדאטה ונותנים רמזים מעורפלים היכן הוא נמצא.
אני משתתף בתחרויות האלה בשביל ללמוד, זה נחמד לקמבן את הלידרבורד (בדאטה-האק זה היה מצחיק!) אבל חוץ מללחוץ לי על האגו אין לי הרבה ערך בזה.
עזבתי את הDiscussion והחלטתי שאני ממשיך בשלי כי אני רוצה לנצח את ה"Magic" הזה שלהם עם מודל טוב כמו שצריך.
קצת Error Analysis: גיליתי שהמודל טועה במספר מקומות:
  • כדאי לא להעיף "רווחים" עודפים: אנחנו עובדים פה על טוויטר, אנשים מדברים בסלנג ורווחים רבים הם צורת ביטוי.
  • המודל מתקשה להבין אימוג'ים: אימנתי MLM שהמאסקינג רק על האימוג'ים: זה היה ממש כיף!! בשפה הכי פשוטה אימנתי מודל להוסיף אימוג'ים לכל טקסט! ניסיתי אותו גם על הדאטה מToxic Comments והוא בהפתעה מוחלטת אמר את דעתו על גרמניה הנאצית. עם אימוג'ים. (זה מה שיש בדאטה..)
  • שמתי לב למשהו מעצבן: אני מקבל ניקוד גרוע במקומות שהמודל צודק בהם: לדוגמה: המודל מוציא "!!" אבל בGT יש "!!!" – אני מתחיל להבין על איזה Magic כולם מדברים. That's awesome!!! –> s awesome!
  • השתמשתי ב label smoothing, תוספת ביצועים חינם. הרצתי ברוטפורס ומצאתי את הכמות האופטימלית.
  • הוספתי Decay learning rate, שיפור חינם.
  • הוספתי כמה אפוקים על הטסט לכל מודל בסוף האימון – מצאתי את מספר האפוקים על ידי ברוטפורס על הטבלה: אימנתי המון והגשתי את כולם עד שמצאתי סט-אפ יציב.
  • השתמשתי בבאצ'ים מאוזנים בין הPositive לNegative סנטימנט וזה שיפר הרבה מאד את התוצאה.
  • מצאתי את הדאטהסט המלא (קאגל, לא?) והיו בו הרבה יותר labels, אימנתי pretraining עליהם לכל המודלים והגשתי: שיפר תוצאות בענק.
  • המשכתי עם הגישה הזאת והרמתי אימון MLM לכל המודלים על כל הדאטה (כולל הtest), הוא רץ ברקע כל הזמן (שבוע רצוף בערך) כשלכל מודל יש GPU משלו עם 12GB, את אלו שלא נכנסים ב12GB קימבנתי עם TFLite: אין יותר דרך לשנות את המודל או להוציא את המשקולות אבל אפשר עדיין להשתמש בו.
  • ניסיתי להשתמש בMixed Precision אבל שום דבר בטנזורפלו לא עובד. ירדתי מזה.
  • תיקנתי דברים כאלה: "Ġ" ידנית בלי לחשוב.
  • שיניתי את הלוס לJaccard-Soft Labels, מסתבר שגם הפתרון המנצח עשה בדיוק את אותו הדבר: בגלל שCross Entropy לא מאפטם Jaccard ישירות אז קודם כל חישבתי Jaccard עם Label Smoothing על המילים ואז על הlabelים החדשים חשבתי KL divergence ביניהם לGT: הלוס הספציפי הזה הוא אחד הטריקים שהכי שיפר את הרשת שלי. ניסיתי קודם Dice וSoftIOU ושניהם לא עבדו.
גיליתי כמה דברים מעניינים בדאטה:
  • – יש � בדאטה. תודה באמת.
  • – הבעיה עם ה!!! קיימת גם עם …
  • – אנשים בטוויטר חותכים מילים באמצע: במשפט אחד היה "LOL. It's not goo" ובאחד היה " It's not amazi at all!"
  • – לפעמים המתייגים הגדילו ראש ותיקנו את המילה בתיוג (אני צריך להחזיר ממש טקסט כoutput, זה לא "בדיוק" למרקר).
הפתרון:
אוגמנטציות בNLP
לא מצאתי חבילה נוחה לאוגמטצניות טקסט, כתבתי בעצמי אחת ועשיתי אינטגרציה למודל בקרס מהתחרות הקודמת שיודע לקבל אוגמנטציות מובנה בזמן האימון.
אוגמנטציות בזמן אימון:
  • – החלפת synonyms רנדומלית על ידי מילון
  • – החלפה רנדומלית של משפט במשפט מתורגם בגוגל טרנסלייט לשפה אחרת וחזרה
  • – מחיקה של punctuation רנדומלית (לא "פשוט עשיתי" את זה כי הדאטה מלוכלך)
  • – תיקון correct_spelling עם מילון רנדומלית.
  • – מחיקה של HTMLים ולינקים רנדומלית (בחלקם היה מידע, ניסיתי גם סתם למחוק).
  • – להעיף stopwords
  • – להעיף מספרים
  • – לשנות מילים מCapital לlower והפוך
  • – ערבוב שלשות מילים, זוגות מילים
  • – שכפול מילים רנדומלי
  • – שכפול אותיות רנדומלי
  • – מחיקה רנדומלית של אותיות
  • – מחיקה רנדומלית של מילים
  • – מחיקת האשתגים
  • – הוספה רנדומלית של אימוג'ים חיוביים או שלילים ביחס לסנטימנט (תייגתי את האימוג'ים בעצמי, זה לא היה קשה!)
  • – הוספתי גם MixUp על ידי "שזירה" של מילים ממשפטים שונים אחת אחרי השניה לסירוגין, שיפר קצת אבל הגדיל את הזמן האימון בהרבה.
  • – הוספתי CutOut בסעיפים הקודמים.
  • – הוספתי CutMix: מילים ממשפט אחד בתוך משפט אחר רנדומלית.
לCyBERT הוספתי "כניסה" חדשה לדאטה טבלאי על ידי אינטגרציה עם TabNET. בשביל פיצ'רים טבלאיים חילצתי לכל מודל את האמבדינגס של המשפט ממודל אחר ובנוסף הוספתי TFIDF וCount Vectorizer.
עוד טריק שעזר לתוצאות היה להוסיף לכל משפט טוקן מיוחד שאומר מה הסנטימנט שלו בדאטה. לבסוף הוספתי עוד מודל קטן אחרי כל המודלים שעובד Char-Level והוא pre-trained מאפס MLM אצלי.
התפקיד שלו היה "לתקן" את הפרדיקציות של המודל (כמו !! או !!!).
הטריק האחרון שלי:
מכירים את זה שאתם יושבים במסעדה ואין לכם כוח לקרוא את התפריט? הפתרון ממש פשוט, מבקשים מהמלצר שיזמין לכם "משהו סבבה".
אז מימשתי חבילת מודלים כזאת:
sababa_models.py – מודלים שהם בתכלס "סבבה" כל הזמן
היא עובדת בצורה פשוטה: הצטברו לי כמויות אדירות של היפרפרמטרים לכל מיני מודלים מהברוטפורסים שאני מריץ כל שני וחמישי.
לקחתי את הטובים ביניהם (בלי לחשוב, רק sort), הרצתי אותם על כמה דאטהסטים כדי להיות בטוח שהם לא Overfitting לדאטה, סיננתי את הטובים ופשוט זרקתי את כולם לקובץ אחד.
אז מעכשיו כשיש בעיה חדשה ואין לי כוח לחשוב על מודל, אני פשוט קורא ל "SababaModel" והוא מסדר אותי עם "מודל סבבה".
עשיתי את המתבקש: חילצתי אמבדיגנס מהרשתות ואימנתי "אנסמבל סבבה" על האמבדינגס!
הוצאתי מכל הטרנספורמרים אמבדינגס לכל הדאטה בכל השפות ויצרתי לכל טרנספורמר "דאטהסט" חדש של כל הדאטה כשהוא מקודד.
לכל אחד מהדאטהסטים האלו אימנתי בWhile True "מודל סבבה" רנדומלי. לא שמרתי לוגים אז לצערי אני לא יכול לבדוק כמה מודלים הגשתי מכל סוג, אני רק יודע שהיו שם הרבה LighGBM, CatBoost, XGBoost, Keras-FC, TabNet, EntityEmbeddings, CNN, RNN.
שום דבר מזה לא שיפר תוצאות.
וכאן זה כבר התחיל לעצבן כי בדיונים כולם דיברו על איך הם מוצאים חוקים ידניים ש"מקבמנים" את התוצאות של המודל וכולם רק משתמשים בroBERTa Base.
הבנתי אתכם.

הגיע הזמן לאמן GPT-3.

באנסמבל.
מימשתי את GPT-3
תהנו לכם עם חשבון החשמל.
רגע לפני שאתם משתגעים, אימנתי GPT-3 Small. אין לו 176 מיליארד פרמטרים. אבל רק מהסיבה שיש הגבלה על גודל המודל בתחרות הזאת בקאגל. אחרת היתי מנסה בשביל הAchievement.
נשארו רק 24 שעות לסוף התחרות: עם כל הכבוד לי, אני לא יכול לאמן GPT-3 ב24 שעות.
אבל חשדתי שהTPUs של גוגל כן!
עשיתי פעם מנוי לקולאב פרו ושכחתי ממנו, זמן מצוין להשתמש בו.
העלתי הכל לקולאב והתחלתי להעמיס ברוטפורס מודלים על הTPUs: כמה שיותר מודלים, כמה שיותר pretrained שונים עם כמה שיותר היפרפרמטרים שונים.
חשבתי לעצמי, מעניין מה יקרה אם אאמן במולטיפרוססינג על TPUs.. כמו MultiGPU רק שהמחברת רצה על TPU, עד כמה זה אסור?
בשביל להריץ את זה היתי צריך לממש בעצמי את הTraining Loop של קרס מחדש עם GradientTape של טנזורפלו.
לא נהנתי מהתהליך אבל הגעתי יחסית מהר למצב שאני יכול לאמן על Multi TPU כמו הMulti GPU המובנה שיש בטנזורפלו.
הוספתי Mixed Precision עם bfloat ובצורה הזאת הצלחתי להוריד את זמן האימון של GPT-3 Small לשעתיים.
אימנתי 6 מודלים במקביל: אחד בקולאב, אחד בקאגל (Interactive), עוד אחד בקאגל בCommit ועוד שלושה אצלי על MultiGPU.
אני לא מעריץ יותר מידי גדול של הענן כי בסופו של דבר זה ממש מוציא את כל הכיף שהGPU לא נמצא פיסית ליידי. היה נחמד אם גוגל היו מוכרים TPUs בKSP.
אבל מסתבר שהמחברות בקולאב לא בנויות לברוטפוסטים. אני לא מבין מדוע. מפה לשם, כדי שהברוטפורס ישאר בחיים נאלצתי לעשות Restart וPlay בכל איטרציה ולהשגיח שהן בחיים, מידי פעם גם להזיז את העכבר.
ממש Human in the loop.היתי ער כל הלילה ועשיתי ריסטארטים למחברת בכל איטרציה.
את התחרות סיימתי כשאני רואה איך השעה 03:00 – שעת ההגשות עוברת לה אבל האנסמבל שלי רק ב25% Upload…
כל המנצחים קימבנו את המטריקה עם כל מיני חוקים שלא התעמקתי בהם עד עכשיו.
המנצח מנצח גם השתמש בWaveNet בתוך הטרנספורמר אבל בצורה פשוטה יותר ממני, יכול להיות שבמציאות המודל שלי חזק יותר. לא היה לי זמן לבדוק.
מקורות:
  • HuggingFace: https://huggingface.co/transformers/
  • The Illustrated Transformer – Jay Alammar: http://jalammar.github.io/illustrated-transformer/
  • MinimalIsAllYouNeed: https://github.com/ypeleg/MinimalIsAllYouNeed
  • BERT (Google) – Pre-training of Deep Bidirectional Transformers for Language Understanding by Jacob Devlin, Ming-Wei Chang, Kenton Lee and Kristina Toutanova.
  • GPT (OpenAI) – Improving Language Understanding by Generative Pre-Training by Alec Radford, Karthik Narasimhan, Tim Salimans and Ilya Sutskever.
  • GPT-2 (OpenAI) – Language Models are Unsupervised Multitask Learners by Alec Radford*, Jeffrey Wu*, Rewon Child, David Luan, Dario Amodei** and Ilya Sutskever**.
  • Transformer-XL (Google/CMU) – Transformer-XL: Attentive Language Models Beyond a Fixed-Length Context by Zihang Dai*, Zhilin Yang*, Yiming Yang, Jaime Carbonell, Quoc V. Le, Ruslan Salakhutdinov.
  • XLNet (from Google/CMU) – ​XLNet: Generalized Autoregressive Pretraining for Language Understanding by Zhilin Yang*, Zihang Dai*, Yiming Yang, Jaime Carbonell, Ruslan Salakhutdinov, Quoc V. Le.
  • XLM (from Facebook) – Cross-lingual Language Model Pretraining by Guillaume Lample and Alexis Conneau.
  • RoBERTa (from Facebook) – a Robustly Optimized BERT Pretraining Approach by Yinhan Liu, Myle Ott, Naman Goyal, Jingfei Du, Mandar Joshi, Danqi Chen, Omer Levy, Mike Lewis, Luke Zettlemoyer, Veselin Stoyanov.
  • DistilBERT (from HuggingFace) – DistilBERT, a distilled version of BERT: smaller, faster, cheaper and lighter by Victor Sanh, Lysandre Debut and Thomas Wolf. The same method has been applied to compress GPT2 into DistilGPT2.
  • CTRL (from Salesforce)- CTRL: A Conditional Transformer Language Model for Controllable Generation by Nitish Shirish Keskar*, Bryan McCann*, Lav R. Varshney, Caiming Xiong and Richard Socher.
  • CamemBERT (from FAIR, Inria, Sorbonne Université) – CamemBERT: a Tasty French Language Model by Louis Martin, Benjamin Muller, Pedro Javier Ortiz Suarez, Yoann Dupont, Laurent Romary, Eric Villemonte de la Clergerie, Djame Seddah, and Benoît Sagot.
  • ALBERT (from Google Research) – ALBERT: A Lite BERT for Self-supervised Learning of Language Representations by Zhenzhong Lan, Mingda Chen, Sebastian Goodman, Kevin Gimpel, Piyush Sharma, Radu Soricut.
  • XLM-RoBERTa (from Facebook AI) – Unsupervised Cross-lingual Representation Learning at Scale by Alexis Conneau*, Kartikay Khandelwal*, Naman Goyal, Vishrav Chaudhary, Guillaume Wenzek, Francisco Guzmán, Edouard Grave, Myle Ott, Luke Zettlemoyer and Veselin Stoyanov.
  • FlauBERT (from CNRS) – FlauBERT: Unsupervised Language Model Pre-training for French by Hang Le, Loïc Vial, Jibril Frej, Vincent Segonne, Maximin Coavoux, Benjamin Lecouteux, Alexandre Allauzen, Benoît Crabbé, Laurent Besacier, Didier Schwab.
עוד בנושא: