מדוע בדיקות A/B של מודלי ML נכשלות בפרודקשן
הכשל היקר ביותר בבדיקות A/B של מודלי ML אינו נפילת השירות, אלא תשובה בטוחה ממודל לא נכון. ברג'יסטרי נמצאת הגרסה הנכונה, אבל את המאפיינים בכניסה אוסף קוד אחר, ספרי העזר מתעדכנים בנפרד, ופער גרסאות המודל בין הסביבות צף שבועות לאחר ההרצה.
השבר השני — מטריקות. בדיקת מודלים בפרודקשן משווה בין קבוצת ביקורת לניסוי על חתכים שונים: בסביבה אחת חלון האגרגציה רחב יותר, באחרת החריגים מסוננים אחרת. מטריקות לא יציבות יוצרות פיזור גדול מהאפקט של המודל עצמו, והניסוי נסגר לפי רעש ולא לפי תוצאה.
השלישי — חוסר יכולת לשחזר. כעבור חודש איש כבר לא ישחזר אילו מאפיינים, גרסאות ספרי עזר וספים עמדו ברגע המדידה. גם כאשר גרסאות הארטיפקטים מתועדות ב-MLflow, ברג'יסטרי נשמר המודל, ולא ההקשר המלא של הרצתו — אין במה להשוות ניסויים בדיעבד.
והרביעי — החזרה לאחור של המודל. אם הארטיפקט הקודם לא נשמר יחד עם הקונפיגורציה, החזרה הופכת לבנייה ידנית תחת לחץ: האיכות צונחת ממש עכשיו, והשחזור אורך שעות. מחיר העיכוב נמדד בשיעור ההחלטות הפגומות עבור המשתמש בזמן הזה.
נפרק כיצד זה נסגר: גרסאות בלתי משתנות של המודל והמאפיינים, שכבה אחודה לחישוב מטריקות עבור שתי הסביבות, והחזרה לאחור בפעולה אחת.
אפקטים מדידים: השהיה, החזרות לאחור, שיעור בדיקות ידניות
סביבה מנוהלת משנה את המחזור עצמו: ההשערה נבדקת על קבוצת ביקורת וקבוצת ניסוי לפני שהגרסה יוצאת לכל הקהל. החלפת חלק התעבורה הופכת לפעולה בהגדרות הניסוי, ולא לריליס נפרד, ולכן הזמן מהשערה ועד העלאה של המודל מתקצר מימים לשעות — את התיאומים מחליף נוהל.
שיעור ההצלבות הידניות יורד מאותה סיבה: מטריקות מחושבות על אותו חתך מסומן עבור שתי הקבוצות, המובהקות של האפקט נבדקת אוטומטית, והאנליסט מסתכל רק על סגמנטים שנויים במחלוקת. מה שדרש קודם ייצוא יומי ואיחוד טבלאות ידני הופך לדוח שמתעדכן מעצמו.
בנפרד נעלם סוג הכשלים היקר ביותר: דעיכה „שקטה“ בסגמנט צר והעלאה של גרסה שאומנה על חתך מיושן. מטריקת איכות עם סף עוצרת את הפריסה ומחזירה את הגרסה הקודמת אוטומטית — זמן השחזור נמדד בדקות, והשבתה בגלל טעות מפסיקה להיות אירוע לכל היום.
MLflow בתכנית הזו אחראי על יכולת השחזור: כל גרסת מודל מקושרת לפרמטרים, לנתונים ולמטריקה, ולכן ניתן לבדוק מחדש את תוצאת הניסוי, והחזרה לאחור היא החלפה לגרסה קודמת מקובעת, ולא בנייה מחדש. האפקט של הניסוי הופך למדיד לפני ההעלאה, ולא לאחר האירוע.
אפשרויות פריסה: הרצת צל, קנרית, מדורגת
מצב ההפצה נבחר לא לפי נוחות, אלא לפי איזה חלק מהתעבורה מותר לתת למודל החדש וכמה יקרה טעות בבקשה חיה. הרצת צל עונה על השאלה „האם המודל החדש מתלכד עם הנוכחי“, פריסה קנרית — „האם המוצר לא מדרדר אצל משתמשים אמיתיים“, ופריסה מדורגת — „איזו מהגרסאות מנצחת לפי המטריקה“.
מגבלות המצבים נתקלות בניתוב הבקשות ובאופן איסוף המטריקות. כל עוד המטריקה לא מקושרת לגרסת המודל ולקוהורטה, כל השוואה בין גישות הופכת לאוסף ניחושים.
| מצב | מתי מתאים | מגבלות |
|---|---|---|
| הרצת צל | העברת לוגיקה למודל חדש, בדיקת איכות על תעבורה אמיתית בלי להשפיע על התשובה | הגרסה לא משפיעה על הפלט, ולכן מטריקות מוצר עבורה לא נאספות; נדרשת סביבה מכפילה ורזרבה במשאבים |
| פריסה קנרית | המודל כבר אומן, אבל נדרשת הגנה מפני דעיכה בבקשות חיות | דורשת החזרה לאחור אוטומטית וסימון מטריקות לפי קוהורטות; על חלק קטן מהתעבורה הסטטיסטיקה נאספת לאט |
| הפצה מדורגת | נדרשת בדיקת אפקט לפי סגמנטים והשוואת גרסאות עם הצטברות נתונים | נמשכת יותר זמן; בלי בקרת אחידות הקבוצות ההשוואה מאבדת משמעות |
בפועל משלבים בין המצבים: הרצת צל כאשרור כניסה לתעבורה חיה, פריסה קנרית כביטוח, והפצה מדורגת כדרך לאסוף סטטיסטיקה לפי סגמנטים.
שלבי יישום: מביקורת ועד מסירה לתפעול
סדר העבודה נבנה כך שטעות בתכנית תהיה גלויה לפני הרצה על תעבורה אמיתית, ולא אחרי שבוע של ניתוח מטריקות. כל שלב מסתיים בארטיפקט שניתן לבדוק — אז ההפעלה לא הופכת ל„הפעלנו ונראה“.
-
ביקורת תכנית הניסוי. בודקים איזו מטריקה נחשבת ליעד, היכן ובאיזה נפח תעבורה היא נאספת, והאם יש מספיק תצפיות כדי להבחין בין גרסאות. בודקים אם הקבוצות לא חופפות לניסויים אחרים שרצים ושאין הטיה באופן שבו אירועים נכנסים למאגר.
-
סימון תעבורה. קובעים את יחידת הרנדומיזציה — משתמש, סשן או בקשה — ואת שיטת הקיבוע: אותו מאפיין נותן קבוצה יציבה בביקורים חוזרים. מקבעים את חלק התעבורה לניסוי ואת כללי ההחרגה, כדי שבדיקות שירות לא ייכנסו להשוואה.
-
הגדרת הסביבה. פורסים שירות השוואה: הוא מקבל בקשה, מנתב אותה לגרסת המודל הנכונה, וכותב ללוג את התחזית ואת סמן הגרסה. מצב צל מאפשר להריץ גרסה חדשה על תעבורה חיה בלי להשפיע על התשובה למשתמש.
-
בדיקות בקרה. מריצים בדיקת A/A לאחידות הקבוצות, מצליבים את התפלגות המאפיינים בין הענפים, בודקים התנהגות כשאחת הגרסאות נכשלת וכששירות ההשוואה לא זמין. את המטריקה בשני הענפים מחשבים לפי אותו כלל — אחרת ההבדל יהיה בחישוב, ולא במודל.
-
מסירה לתפעול. מוסרים לצוות נוהל הפעלה ועצירה, תיאור החזרה לאחור, דשבורד עם מטריקות והגדרות התראות. מתעדים את הסימון ואת קונפיגורציית הסביבה, כדי שהניסוי הבא יופעל בלעדינו.
ארטיפקטי מסירה: תרשימים, מדיניות גישה, נהלים
אחרי מסירת הסביבה נשאר לצוות הלקוח סט ארטיפקטים שלפיו ניתן להפעיל בדיקות A/B חדשות באופן עצמאי — בלי לשחזר לוגיקה מהודעות ומזיכרון של מהנדסים. להלן רשימת מה שמוסרים ולמה כל מסמך נחוץ בעבודה.
- קונפיגורציות הסביבה. קבצי פריסה ופרמטרי סביבות: סביבת בדיקה וסביבת פרודקשן נבדלות רק בערכים, ולכן גרסת מודל חדשה עולה בהעתקת קונפיגורציה, ולא בבנייה מחדש.
- תרשימי זרימת נתונים. המסלול מהבקשה ועד כתיבת המטריקה: היכן נקלטת הגרסה, כיצד מחושבת מטריקת היעד, היכן נפרדות הדגימות. לפי התרשים מהנדס חדש מבין את הסביבה בתוך שעה.
- מדיניות גישה. הפרדת תפקידים: מי משנה את חלק התעבורה לגרסה, מי עוצר את הבדיקה, למי נגישים הלוגים הגולמיים. אי אפשר לשבור את הניסוי בשינוי מקרי.
- נוהל הניסוי. שלבים חובה: השערה, מטריקת יעד, נפח דגימה מינימלי, קריטריון עצירה וסדר החזרה למודל הביקורת.
- תבנית דוח. טופס אחיד לתיעוד התוצאה: גרסאות המודלים המושווים, תקופה, מטריקות לפי קבוצות, מסקנה והחלטה — להמשיך, לשפר או לסגור.
- הוראות והדרכה. סקירה של הסביבה עם צוות הלקוח ותזכורות קצרות לפעולות טיפוסיות: הפעלת בדיקה, עצירה, החזרה לאחור, קריאת דוח, הוספת מטריקה חדשה.
סט כזה מסיר את התלות בקבלן חיצוני: שינויים בסביבה מוכנסים לפי כללים מתועדים, ולא לפי הסכמות בעל פה. נדון במשימה — נחזור עם תכנית עבודה והרכב ארטיפקטים לסביבה שלכם.
מקרה בוחן: הסרנו פער גרסאות בין הסביבה לפרודקשן
הלקוח העלה כמה מודלים בחודש, וסביבת האימון והפרודקשן חיו חיים נפרדים. ארטיפקטים הועברו בסקריפטים, מאפיינים נבנו מחדש ביד, ופער גרסאות בין הסביבות צף כבר בתעבורה חיה. העלאה עיוורת בלי פילוח קהל לא אפשרה להבחין בדעיכה לפני שמטריקות המוצר נפלו.
לפני הבנייה מחדש, שתיים-שלוש הצלבות ידניות בשבוע גזלו מהמהנדס כחצי יום, השחזור אחרי אירוע נמשך יותר משעה, והחזרה לאחור הייתה צריכה להיות מופעלת ידנית בכמעט רבע מההעלאות.
מה שינו
שתי הסביבות אוחדו לרג'יסטרי מודלים אחד ב-MLflow: גרסה, סט מאפיינים ואיכות על מדגם ביקורת מקושרים לארטיפקט אחד, והמעבר לפרודקשן עובר רק דרך בדיקה אוטומטית של המניפסט. את ההעלאה העברנו לפילוח תעבורה 5/95 עם החזרה לאחור אוטומטית לפי מטריקה מרכזית, במקום החלפה עיוורת של המודל כולו. החלטות מתועדות יחד עם הגרסה, ולכן ניתוח תקלה מתחיל מתמונה מוכנה, ולא מהצלבת לוגים ידנית.
אחרי רבעון ההצלבות הידניות הצטמצמו לבדיקה מתוכננת אחת, פערי גרסאות בין הסביבה לפרודקשן לא שוחזרו אף פעם, והשחזור ארך דקות: החזרה לאחור פעלה מעצמה לפי הסף. שיעור המסלולים המכוסים בבדיקות אוטומטיות לפני העלאה עלה משליש לתשע עשיריות.
מה לעשות אם המודל כבר בפרודקשן ואין סימון?
היעדר סימון לניסוי חוסם לא את השוואת הגרסאות, אלא את היעדר מתג מנוהל ביניהן. אם המודל כבר בפרודקשן, קודם מפרידים אותו מקוד השירות: גרסת המודל והפרמטרים שלה צריכים להיות מוזרקים מהקונפיגורציה, ולא להיות תפורים לתוך הקריאה. לאחר מכן בכניסה לשירות מופיעה שכבה דקה של ניתוב, שמחליטה לפי מאפיין אחד של הבקשה איזו גרסה תטפל בה.
כל עוד אין סימון, נשענים על אותות עקיפים: לוגים של החלטות, תגובת משתמשים, שיעור תיקונים ידניים אחרי תשובת המודל, התפלגות התחזיות לפי מחלקות והזזה של התפלגות זו בזמן.
זה מספיק כדי לתפוס דעיכה ופער גרסאות, וסט מלא של דוגמאות בדיקה נוצר מאוחר יותר — כבר לפי זרם הבקשות האמיתיות שנאסף.
| אפשרות | מתי מתאים | מגבלות |
|---|---|---|
| מצב צל | אסור להסתכן באיכות התשובה למשתמש | שתי גרסאות מחושבות במקביל, נדרשת רזרבת כוח |
| הפעלה קנרית | צריך לתפוס מהר כשל ברור על חלק קטן מהתעבורה | מראה תקלות, אבל כמעט לא מבדילה באיכות |
| A/B לפי חלק תעבורה | המטריקה מדידה ונצברת בתוך ימים, ולא חודשים | דורשת התפלגות יציבה של בקשות בין הקבוצות |
המעבר נעשה הדרגתי: יחידות אחוזים של תעבורה לגרסה חדשה, המתנה על החלק שנבחר, ואז צעד למעלה. בכל צעד משווים את אותם אותות שנאספו לפני ההפעלה, ומחזיקים החזרה לאחור מוכנה — החזרת גרסה לפי קונפיגורציה, בלי בנייה מחדש ובלי עצירת השירות.
מיגרציה בלי עצירה נוצרת בדיוק מזה: הניתוב חי בנפרד מהמודל, ולכן החלפת גרסה אורכת שניות ולא מפסיקה עיבוד בקשות.
סף העצירה נקבע מראש ובגדלים מדידים: ירידה במטריקת היעד, עלייה בשיעור השגיאות, פער התפלגויות מעל המותר. אם הסף נחצה — התעבורה חוזרת לגרסה הקודמת אוטומטית, ולא לפי שיחת טלפון של התורן.
ספקות טכניים נפוצים של לקוחות ומהנדסים
ספקות בשלב הזה הם בדרך כלל טכניים: האם יש מספיק נתונים, האם עונתיות מעוותת את התמונה, מה לעשות עם שינויים מקבילים בכללים ובמודל. להלן תשובות קצרות על איך אנחנו סוגרים את הנקודות האלה בסימון הניסוי.
האם יש מספיק תעבורה למטריקות מהימנות?
לא סופרים תעבורה כוללת, אלא את מספר אירועי היעד בכל קבוצה. גודל מדגם מינימלי קובעים לפני ההתחלה — לפי האפקט הצפוי ופיזור המטריקה. אם אירועים פחותים, מצרים את המטריקה או מאריכים את חלון התצפית, ולא מתאימים את הבדיקה למספר יפה.
האם עונתיות תעוות את התמונה?
החלוקה נעשית לפי מזהה משתמש יציב, ולכן שתי הקבוצות נופלות לאותם ימים, מבצעים ושעות שיא. ההשוואה נעשית במקביל באותו חלון, ואת התוצאה בודקים מחדש בתקופות סמוכות — אפקט שנשמר רק בשבוע אחד לא נכנס למסקנות.
מה לעשות אם הכללים והמודל משתנים בו-זמנית?
ניסוי אחד — שינוי אחד. אם משנים את שניהם בבת אחת, אי אפשר להפריד את האפקט: לא ברור מה נתן את העלייה ומה אכל אותה. מפצלים את השינויים לשלבים עוקבים או מתכננים תכנית עם בדיקת השפעה משותפת, כדי להעריך את התרומה של כל גורם.
למי נגישות התוצאות ומה עם אבטחת נתונים?
דוחות נצפים לפי תפקידים: לצוות המוצר — חתכים לפי סגמנטים ומטריקות, למהנדסים — אירועים במאגר לצורך ניתוח. נתונים אישיים לא נכנסים לדיווח, מזהים עוברים פסידונימיזציה, והייצוא מוגבל במדיניות גישה ומתועד בלוג.
נדון במשימה: איך נתחיל לעבוד על הסביבה
כדי שסביבת בדיקות A/B של מודלים לא תהפוך לשרשרת תיקונים, מתחילים בסקירה של מה שכבר עובד. מכם — גישה לריפוזיטורי התשתית, לתכנית הנוכחית של העלאת מודלים לפרודקשן ולהייצוא לפי מטריקת היעד מתקופות קודמות: בלי זה אי אפשר לחשב את גודל הקבוצות ומשך חלון התצפית.
סדר הצעדים הראשונים:
- מתארים את המסלול הנוכחי של המודל: היכן נשמרות הגרסאות, מי מחליף תעבורה ביניהן, מה כבר מתועד בלוג;
- מקבעים את מטריקת היעד ואת מטריקות המגבלה, שאסור להן לרדת בשום תוצאה של הבדיקה;
- בוחרים יחידת רנדומיזציה — לקוח, סשן או בקשה — ואת השיטה לקשר אותה לקבוצה, כדי שמשתמש לא ידלג בין הגרסאות;
- מתאמים תכנית חישוב: חלקי תעבורה, אפקט מובהק מינימלי, קריטריון עצירה מוקדמת;
- מתכננים החזרה לאחור: בפקודה אחת כל התעבורה חוזרת למודל הביקורת בתוך דקות ספורות;
- מוסיפים תצפית על דריפט של נתוני הקלט ועל פער התפלגויות בין הקבוצות;
- מסמנים את היקף העבודה: היכן נדרשים שינויים בקוד ההעלאה והיכן די בקונפיגורציה.
לפי תוצאות הסקירה נחזור עם הערכה ותכנית: הרכב השלבים, לוחות זמנים לכל אחד, תחום האחריות של הצוות שלנו ושל שלכם. הצעד הבא — תארו את המשימה, ואנחנו נתאם סקירה.







