הגדרת Feature Store למודלי ML: Feast, Redis ו-S3

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

היכולות שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1359
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1330
  • עיצוב לוגו לחברת B2B Advance
    עיצוב לוגו לחברת B2B Advance
    776
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1077
  • פיתוח לוגו חברת AIDER
    פיתוח לוגו חברת AIDER
    1022
  • פיתוח CRM עבור Chasseurs
    פיתוח CRM עבור Chasseurs
    1113

Feature store ל-ML: היכן נשברת הלמידה והאינפרנס

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

ההבדל בעיגול, באזור הזמן או ברגע חיתוך הנתונים מצטבר, ו-training-serving skew הופך מודל תקין למקור להתראות שווא.

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

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

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

מה נותן שכבת תכונות אחודה

שכבת תכונות אחודה מסירה את מקור הפערים העיקרי בפרויקטי ML: כאשר האנליטיקאי מחשב תכונות בשאילתה אחת, והמודל בפרודקשן מקבל אותן ממקור אחר. Feature store מקבע לוגיקת חישוב אחת ומפיץ אותה בשני מצבים — אופליין לאימון ואונליין לאינפרנס. בזכות זה התכונות בניסוי ובפרודקשן זהות ביט-לביט, ולא "בערך".

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

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

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

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

אחסון מקוון ואחסון לא־מקוון: מצבי עבודה

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

האחסון הלא־מקוון שומר היסטוריה על פני טווח ארוך ומספק אותה באצוות — עבור אימון, אימון מחדש וניתוח תקלות, שבהם חשובה השלמות ולא המהירות.

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

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

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

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

כיצד אנו מיישמים feature store: שלבי העבודה

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

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

לאחר מכן אנו בונים את התהליך כך שכל שלב יניב ארטיפקט שניתן לבדוק, ולא "השתפר".

  1. ביקורת מקורות. אנו אוספים רשימה של טבלאות, סטרימים וחילוצים חיצוניים, ומציינים בעלים, תדירות עדכון והשהיה בהופעת הנתונים. בפלט — מפת מקורות עם ציון אילו מהם מתאימים לאספקה מקוונת ואילו רק לעיבוד אצווה.
  2. סכמת מאפיינים. אנו מתארים ישויות, מפתחות וחתימות זמן, ומסכימים על מילון שמות אחיד. אנו קובעים אילו מאפיינים מחושבים מחדש בזרימה ואילו ממומשים לפי לוח זמנים.
  3. הגדרת המחסן. אנו מקימים שכבה לא-מקוונת לחיתוכים היסטוריים ושכבה מקוונת לאספקה מהירה ברגע הבקשה, ומגדירים סנכרון ביניהן. בנפרד אנו בודקים שבאימון המודל רואה את המאפיין בנקודת הזמן שבה הוא היה רלוונטי — אחרת נוצרת דליפת נתונים עתידיים.
  4. רישום וגרסאות. כל סט מאפיינים מקבל גרסה ובעלים; שינוי בסכמה אינו שובר מודלים שכבר עובדים, משום שהגרסה הישנה נשארת זמינה.
  5. בדיקה. אנו משווים ערכים מהשכבה המקוונת והלא-מקוונת על אותם מפתחות, מריצים שאילתות בקרה, מודדים את השהיית האספקה ואת שיעור המאפיינים שהגיעו ללא חוסרים.
  6. מסירה. אנו מעבירים לצוות נהלי עדכון, סכמת גישה וסדר הוספת מאפיינים חדשים, כדי שהעבודה תמשיך בלעדינו.

סדר עבודה כזה מסיר את הכאב העיקרי — אי-ההתאמה בין האימון לפרוד — והופך את המאפיינים לניתנים לשימוש חוזר: מודל חדש מתחבר לסטים מוכנים, ולא אוסף את החילוץ שלו מאפס.

מה הלקוח מקבל לידיו

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

  • קונפיגורציות Feature Store: תיאורים דקלרטיביים של ישויות, מקורות признаки ותצוגות признаки (feature views), מפורקים לפי סביבות dev/stage/prod עם פרמטרים של שכבות אחסון אופליין ואונליין.
  • סכמות נתונים: תיאור ישויות, סוגי признаки, מפתחות חיבור וחתימות זמן — עם ולידציה בכניסה, כך שפער בין אימון לאינפרנס נתפס בשלב הרישום ולא בפרודקשן.
  • מדיניות גישה: תפקידים לקריאה וכתיבה של признаки, הפרדה לפי צוותים ומודלים, כללים להנפקת מפתחות לאחסון אונליין ולשכבה אופליין.
  • נהלי עדכון: לוח זמנים למטריאליזציה של признаки, כללי חישוב מחדש בעת שינוי מקור, סדר הוצאת גרסאות מיושנות משימוש.
  • תיעוד: תרשים זרימת נתונים מהמקור ועד המודל, הוראות להוספת признак חדש, צ'ק-ליסט לשחרור גרסה וסדר חזרה לגרסה קודמת.
  • סקריפטים לפריסה ולמיגרציות: הקמת סביבה מאפס, העברת признаки קיימים, בדיקת שלמות לאחר עדכון.
  • ניטור והתראות: בקרת רעננות של признаки, שיעור ערכים חסרים ופערים בין ערכי אופליין לאונליין עם ספי הפעלה.

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

מקרה בוחן: צמצום הכנת הפיצ'רים הידנית פי שלושה

הלקוח — צוות פלטפורמת ML בחברת מוצר: עשרות מודלים של ניקוד והמלצות, אימון ב-Feast מעל S3, הגשה מקוונת דרך Redis. לפני הטמעת מאגר הפיצ'רים כל מדען נתונים הרכיב את מערך הפיצ'רים שלו ידנית: ייצוא מחנות הנתונים, ג'וינים בנוטבוקים, העברה ידנית לפרודקשן.

הכנת מערך אחד ארכה 3-4 ימים, ופער בין מדגם האימון למדגם המקוון צף כבר בפרודקשן — איכות המודל ירדה בלי אף שגיאה בלוגים.

מה שינו

אספו את כל הפיצ'רים לרישום אחיד: הגדרות הפיצ'רים, המקורות והבעלים מתוארים באופן דקלרטיבי, ולא מפוזרים בין סקריפטים. ערכים היסטוריים לאימון עוברים materialization ל-S3 לפי לוח זמנים, ערכים מקוונים נכתבים ל-Redis בכל אירוע — אותה לוגיקת חישוב משרתת גם את האימון וגם את האינפרנס.

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

מדדים לפני ואחרי

מדד לפני אחרי
הכנת מערך פיצ'רים 3-4 ימים יום אחד
שיעור הפעולות הידניות ~70% ~15%
פערי train/serving באופן קבוע מקרים בודדים
זמן מרעיון פיצ'ר עד פרודקשן שבועות ימים

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

מה זה נתן מבחינת יציבות

האפקט המרכזי — יכולת החיזוי של האינפרנס. המודל בפרודקשן רואה בדיוק את אותם פיצ'רים שעליהם התאמן, ולכן מדדי האיכות הפסיקו "לצוף" בין מהדורות.

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

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

במה שונה feature store ממאגר נתונים רגיל?

מאגר נתונים רגיל הוא מקום שבו הנתונים נמצאים. Feature store הוא שכבה שמבטיחה שאותם מאפיינים בדיוק יגיעו לאימון ולמסקנות (inference) באותה צורה.

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

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

Feature store מקבע את הגדרת המאפיין ואת גרסתו, ולכן אימון על חתך מלפני חודש הוא בר-שחזור, והפער בין הניסוי לפרודקשן נראה כ-diff, ולא כירידה במדדים כעבור שבוע.

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

אחרת המודל לומד על התפלגות אחת ופועל על אחרת — train/serve skew קלאסי, שבמאגר נתונים רגיל יש לתפוס אותו ידנית.

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

Feature store מוציא זאת לשכבה משותפת — מודל חדש מתחבר למאפיינים מוכנים, ולא בונה את הצינור שלו מאפס.

לכן feature store לא מחליף את מאגר הנתונים, אלא נבנה מעליו: S3 או האגם נשארים מקור ההיסטוריה, Redis — שכבה אונליין מהירה, ורישום המאפיינים (feature registry) מקשר את ההגדרות, הגרסאות והבעלים שלהם לחוזה אחד מנוהל.

ספקות טכניים נפוצים

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

האם מאגר התכונות ישתלב בסטאק הנוכחי שלנו?

Feast פועל מעל מקורות נתונים קיימים ואינו דורש להעביר אותם. שכבת ה-offline קוראת מאחסון קבצים (תואם S3) או מאחסון טבלאי, ושכבת ה-online — מ-Redis. האימון והאינפרנס לוקחים תכונות מאותה הגדרה, ולכן הפער ביניהם נעלם מעצם הבנייה. אם יש לכם כבר Spark או ויטרינות dbt, הם נשארים המקור, ו-Feast הופך לשכבת הגישה.

כיצד מתבצעת ההגירה מאיסוף תכונות ידני?

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

מה עם התמיכה והעדכון?

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

כיצד זה משתלב עם צינור האימון?

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

בואו נדון במשימה שלכם

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

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

מה תקבלו בסיכום השיחה:

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

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

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