הגדרת DVC: היכן נשברת יכולת השחזור של מודלים
תמונה מאלפת: המודל מציג איכות טובה בבדיקה, מעלים אותו לאוויר, וכעבור חודש אותה תוצאה כבר אינה חוזרת. הקוד במאגר לא השתנה, אך מערך הנתונים שעליו אימנו נדרס — חלק מהתיוג תוקן, חלק מהייצוא הוחלף, חלק מהקבצים נמחקו. אין לאן לחזור: אף אחד לא ניהל בקרת שינויים בנתונים, ואין עם מה להשוות את המשקלים הישנים.
הסיבה אינה במודל, אלא בכך שהקוד והנתונים חיים לפי כללים שונים. הקוד עובר סקירה, יש לו היסטוריה ונקודות חזרה, והנתונים נמצאים בתיקייה ברשת או באחסון אובייקטים, שבו ייצוא חדש מוחק את הקודם.
אימון המודלים מופעל "על מה שיש עכשיו", והקשר בין גרסת הנתונים למטריקה שהתקבלה נשמר רק בזיכרון של המהנדס או בשם התיקייה.
המחיר של סכמה כזאת — פערים בתוצאות ואובדן יכולת השחזור של ניסויים. המהנדס מבזבז ימים על ניסיונות לחזור על הרצה קודמת, משווה מטריקות שאין להשוות, והוויכוח "מה השתנה" עובר להתכתבות. כשצריך להחזיר עדכון כושל לאחור, מתברר שאין מה להחזיר.
הגדרת DVC סוגרת בדיוק את הפער הזה: ניהול גרסאות של מערכי נתונים ותצורות, קישור משקלי המודל לתמונת מצב מסוימת של הנתונים וחזרה צפויה מראש על ההרצה. בהמשך — כיצד זה בנוי והיכן זה נשבר לרוב.
מה נותן ניהול גרסאות של נתונים ומודלים בעבודה
ניהול גרסאות של נתונים ומשקלים סוגר סוג צר אך יקר של בעיות: פער בין מה שעליו אימנו את המודל לבין מה שנמצא כרגע באחסון. כל עוד מערך הנתונים וארטיפקט האימון חיים בנפרד, כל הרצה חוזרת היא לוטו: המטריקות מתפצלות, ואת הסיבה מחפשים ימים.
DVC קושר את מערך הנתונים, התצורה והמשקלים לקומיט אחד, ולכן מצב הניסוי משוחזר לפי מזהה, ולא לפי זיכרון המהנדס.
האפקט המדיד הראשון — שיעור ההרצות הניתנות לשחזור. הנתונים ממוענים לפי האש של התוכן, ולא לפי נתיב במערכת הקבצים, ולכן קומיט אחד נותן מטריקות תואמות גם במחשב המפתח וגם בשרת האימון.
ניתוח תקלה מתחיל במזהה הגרסה, ולא בסקר בצוות: הפער בין הרצות יורד מ"כל שנייה" למקרים בודדים.
האפקט השני — זמן. שלבים שלא השתנו אינם מחושבים מחדש: הכנת הנתונים, האימון והאימות נשמרים במטמון לפי האשים של הקלט, והרצה חוזרת מעלה ארטיפקטים מוכנים במקום מחזור מלא. גם בניית הסביבה מפסיקה להיות ידנית — התלויות והפרמטרים מקובעים בתצורה, ומהנדס חדש מקבל סביבת עבודה בפקודה אחת.
השלישי — היסטוריית גרסאות של מודלים וחזרה לגרסה קודמת. המשקלים מקושרים למצב מסוים של הנתונים, ולכן חזרה לריליס קודם היא החלפת מצביע, ולא אימון מחדש. סוג השגיאה "בפרודקשן יש מודל שאומן על נתונים אחרים" נעלם: אי-התאמה בין נתונים למשקלים נראית עוד לפני העלאה לאוויר.
אפשרויות אחסון גרסאות: השוואת גישות
מקום אחסון הגרסאות קובע באיזו מהירות הצוות חוזר למערך הנתונים הקודם ומה יקרה כששני מהנדסים עורכים תיוג בו-זמנית. נבחן ארבע אפשרויות שנתקלות בהן במציאות בפרויקטים, ואת המגבלות שלהן.
| אפשרות | מתי מתאימה | מגבלות אחסון |
|---|---|---|
| דיסקים מקומיים | ניסוי בודד על נפח קטן | הגרסאות לא עוזבות את המחשב: עמית לא ישחזר את ההרצה, חזרה לאחר התקנה מחדש אינה אפשרית |
| דיסק רשת משותף | צוות קטן ברשת אחת, עריכות נתונים נדירות | אין נעילות ובדיקת שלמות, קונפליקטים נפתרים ידנית, קריאה של קבצים גדולים נחלשת |
| אחסון אובייקטים | תרחיש עבודה: מערכי נתונים גדולים, עשרות גרסאות, צוות מבוזר | נדרשים מפתחות גישה ומדיניות מחזור חיים; בלעדיהם נפח הגרסאות גדל ללא שליטה |
| מרשם מודלים | ארטיפקטים שיוצאים לפרודקשן: משקלים, מטא-נתונים, מטריקות | שומר מודלים, אך אינו מחליף אחסון של נתוני גלם ודגימות ביניים |
מה אנחנו מביאים בחשבון בבחירה
בפועל משלבים בין האפשרויות האלה: אחסון אובייקטים הופך למקום הראשי לנתונים, מרשם המודלים — לנקודת הוצאה של גרסאות לפרודקשן, ודיסק הרשת נשאר מטמון להאצת הקריאה.
המגבלה המרכזית כאן אינה מהירות הכתיבה, אלא יכולת החיזוי: גרסה צריכה להשתחזר לפי מזהה, ולא לפי שם קובץ עם תאריך בשם — אחרת החזרה הופכת לחיפוש אחר העותק הנכון ביד.
הגדרת DVC שלב אחר שלב: מביקורת עד מסירה
סדר השלבים כאן אינו פורמליות: אם מתחילים מאחסון, אבל לא מסכימים על סכמה, המאגר מתמלא בעותקים של מערכי נתונים, ואף אחד כבר לא יגיד איזו גרסת נתונים מתאימה לאיזה קומיט. לכן הולכים מביקורת לנהלים.
- ביקורת התהליך הנוכחי. מפרקים מה כבר נמצא ב-Git, אילו מערכי נתונים ומשקלים חיים מחוץ למאגר, באיזו תדירות הם משתנים וכמה מקום תופסים. מתעדים צווארי בקבוק: העברה ידנית של ארטיפקטים, דגימות ביניים שאבדו, הרצות אימון שאינן ניתנות לשחזור.
- סכמת ניהול גרסאות. מגדירים מה נלקח לשליטה — נתוני גלם, חתכי ביניים, תצורות אימון, משקלי מודלים — ולפי אילו כללים גרסת נתונים מקושרת לקומיט ולתג.
- חיבור האחסון. מגדירים אחסון מרוחק, מחלקים גישה לפי תפקידים, מפעילים מטמון מקומי כדי שייצוא חוזר לא יריץ שוב ושוב את אותם קבצים, וקובעים מדיניות אחסון לגרסאות ישנות.
- תיאור שלבים בני שחזור. שלבי הכנת הנתונים והאימון מתוארים באופן הצהרתי: כל ניסוי קודם עולה בפקודה אחת, ולא משחזור מהזיכרון.
- אוטומציה של בדיקות. סכומי ביקורת מאותתים על שינוי בנתונים, ובאינטגרציה רציפה מגדירים בנייה והשוואת מטריקות: תוצאה שנחלשה לא עוברת לענף הראשי.
- מסירה לצוות. מוסרים נהלים, הוראות לתרחישים אמיתיים ואחראי על האחסון. לאחר מכן הצוות בעצמו מנהל גרסאות לנתונים וחוזר לגרסה הרצויה ללא תמיכה חיצונית.
מה הלקוח מקבל לידיים: תצורות ונהלים
מוסרים לא רק קבצי עבודה, אלא גם כל מה שהצוות שלכם צריך לעבודה עצמאית עם גרסאות נתונים ומודלים. הרכב החבילה מסכמים בהתחלה, ובקבלה בודקים לפיו, ולא לפי הזיכרון.
- קבצי תצורה של הצינור: תיאור שלבי הכנת הנתונים, האימון וההערכה — חזרה על ניסוי מופעלת בפקודה אחת, ולא נבנית ידנית.
- סכמות אחסון: מפה של היכן נמצאים מערכי הנתונים, המטריקות ומשקלי המודלים, מה מנוהל בגרסאות ומה משוחזר מהמטמון.
- הגדרות אחסון: חיבור אחסון מרוחק ומטמון, חלוקת נתיבים לפי מערכי נתונים וגרסאות, כללי פינוי אובייקטים מיושנים.
- מדיניות גישה: תפקידי מהנדסים, אנליסטים וקבלנים, הפרדת הרשאות קריאה וכתיבה, סדר הוצאת מפתחות ושלילתם.
- נהלי עבודה עם גרסאות: מתי נפתח ענף ניסוי, כיצד מודל מועבר לפרודקשן וכיצד מתבצעת חזרה לאחור.
- תיעוד: מבנה המאגר, הוראות לחיבור משתתף חדש ולשחזור סביבת עבודה מאפס.
- רשימת בדיקה לקבלה: תרחישים שאנחנו מריצים במסירה — שחזור אימון, חזרה לגרסה קודמת, מתן גישה למהנדס חדש.
החבילה נשארת בקונטור שלכם: תלויות חיצוניות מפורטות ברשימה נפרדת, כדי ששום דבר לא יישאר מחוצה לו.
מקרה בוחן: קיצרנו את זמן שחזור התוצאות
מה היה לפני
פרויקט — אימון מודלים על נתונים שמתעדכנים כל שבוע. עשרות ניסויים חיו "איך שיצא": דגימות על הדיסק, משקלים ליד הקוד, פרמטרי הרצה — בהערות של המבצע.
הרצה חוזרת של אימון ארכה 6–8 שעות: להעלות סביבה, למצוא את גרסת הנתונים הנכונה, להרכיב את התצורה מחדש. ב-6 מתוך 10 מקרים המטריקות היו שונות מההרצה הקודמת, וחזרה לאחור של מודל חייבה הרכבה ידנית של חצי יום.
מה השתנה
גרסאות של דגימות ושל משקלים הועברו מתיקיית העבודה לאחסון נפרד, במאגר נשארו רק מצביעים אליהן. קובץ תצורה אחד מתאר את ההרצה כולה: חלוקת הדגימות, עיבוד מקדים, סדר השלבים.
הגדרנו את DVC כך שהרצה חוזרת מושכת את אותם נתונים ומשחזרת את הסביבה, וחזרה לגרסה קודמת היא החלפת מצביע, ולא הרכבה ידנית.
| מדד | לפני | אחרי |
|---|---|---|
| הרצה חוזרת של אימון | 6–8 שעות של הרכבה ידנית | כ-15 דקות |
| שיעור הרצות עם מטריקות תואמות | 4 מתוך 10 | 10 מתוך 10 |
| חזרה לגרסת מודל קודמת | חצי יום של הרכבה ידנית מחדש | דקות, הנתונים נמשכים אוטומטית |
תוצאת הפרויקט: הניסוי הפסיק להיות חד-פעמי — אפשר לחזור עליו ולהגן עליו. חזרות לגרסאות קודמות יצאו מקטגוריית הפעולות המסוכנות: המצב הקודם משוחזר במדויק, יחד עם הנתונים והסביבה.
במה שונה ניהול גרסאות של נתונים מניהול גרסאות של קוד?
קוד ונתונים משתנים בדרכים שונות, וההבדל הזה קובע את כל השאר. תיקון בקוד — כמה שורות טקסט, ולכן מערכת ניהול הגרסאות שומרת רק את ההבדל בין מצבים סמוכים. מערך נתונים — קובץ בינארי של עשרות גיגה-בייט, וההבדל בין שני ייצואים כמעט תמיד דומה לנפח המלא.
לכן מערך נתונים לא שמים באותו מאגר של הקוד: השוואה שורה-שורה עבורו אינה קיימת, הדלתא לא מחושבת, וכל קומיט מכפיל את גודל האחסון. מודלים מתנהגים באותו אופן — אין טעם להשוות אותם שורה-שורה, אבל יש טעם לקשור אותם לנתונים ולפרמטרים שעליהם אומנו.
עבור נתונים, למאגר נכנסים קבצי מצביע עם סכום ביקורת, והמערכים והמשקלים עצמם — לאחסון אובייקטים; כך בנויה הגדרת DVC. התאמת גרסאות נבדקת לפי סכום ביקורת: אותו מערך נותן אותו מזהה, וחזרה לשילוב הרצוי של נתונים ומודל מתבצעת בפקודת סנכרון אחת.
קריטריון ההתאמה של התוצאות גם הוא שונה. לקוד מספיק שבדיקות יעברו על אותה רוויזיה; עבור מודל חשוב שהמטריקה תשתחזר על מערך קבוע עם אותם פרמטרי אימון. אם לפחות אחד משלושת המרכיבים — נתונים, קוד, פרמטרים — אינו מקובע, תוצאת האימון מפסיקה להיות ניתנת לחזרה.
ספקות טכניים: נפחים, אחסון, הרשאות גישה
שאלות הנדסיות לפני הגדרת ניהול גרסאות הן כמעט תמיד אותן שאלות: נפח נתונים גדול, כמה צוותים עם הרשאות שונות, תהליך אימון שכבר עובד. DVC בנוי כך שבמאגר נשארים רק קבצי מצביע, והארטיפקטים עצמם חיים באחסון נפרד.
להלן תשובות למה שבדרך כלל מבררים לפני תחילת העבודה. אם המקרה שלכם אינו ברשימה, נבחן אותו בנפרד.
מערך הנתונים לא נכנס למאגר — מה אז?
ב-git נכנסים רק מצביעים עם סכומי ביקורת, והנתונים ומשקלי המודלים עוברים לאחסון אובייקטים. המאגר נשאר קל, הגרסה הרצויה נמשכת בפקודה אחת, דגימות תכופות נשמרות במטמון מקומי. ניקוי גרסאות ישנות מוגדר באמצעות מדיניות אחסון.
כיצד לחלק גישה לנתונים ולמודלים?
ההרשאות ניתנות ברמת האחסון: תפקידים לקריאה, כתיבה ומחיקה, מפתחות נפרדים לבנייה שירותית ולמהנדסים. מפתחות אינם נשמרים במאגר — רק הפניות למשתני סביבה. פניות לארטיפקטים נשארות בלוגים, ולכן רואים מי ומתי הוריד גרסה.
אצלנו כבר פרוס ניהול גרסאות ויש תהליך אימון משלו. נצטרך לשבור אותו?
לא — ניהול הגרסאות נבנה מעל התיקיות והסקריפטים הקיימים: הנתונים מאונדקסים כפי שהם, האימון מופעל בדרך הרגילה. גרסת הנתונים נרשמת באותו קומיט של קוד האימון, ולכן יכולת השחזור מופיעה בלי לכתוב מחדש את התהליך. המעבר מתבצע בשלבים, עם אפשרות חזרה לסכמה המקורית.
נדון במשימה: מאיפה להתחיל ניהול גרסאות
כדי לחזור עם הערכת נפח ותוכנית עבודה, עלינו לדון במשימה באופן ענייני — לפי התהליך הנוכחי שלכם בעבודה עם נתונים ומודלים. חלק מהתשובות אפשר לתת בקירוב, ואת השאר נדייק בעצמנו בניתוח המאגר והאחסון.
- היכן נמצאים כעת הנתונים והמודלים: דיסקים מקומיים, ספריות רשת, אחסון אובייקטים — ומה הנפח עם קצב הגידול בחודש.
- מה נחשב לארטיפקט: משקלי מודלים, מטריקות אימון, תצורות, דגימות מוכנות — ואילו מהם דרושים בפרודקשן.
- כמה מהנדסים עובדים עם מערך נתונים אחד והאם דרושים חלוקת הרשאות וכללי סקירת שינויים.
- כיצד בנוי מחזור האימון הנוכחי: סקריפטים, מחברות, אורקסטרטור, שלבים ידניים — היכן ניהול הגרסאות ישתלב, ומה יצטרך להיכתב מחדש.
- דרישות לאחסון ארטיפקטים: קונטור חיצוני או פנימי, מדיניות אחסון ומחיקה, גישה מרשת חיצונית.
- מה כבר קיים בתשתית: מאגר עם היסטוריית שינויים, שרת בנייה שבו מופעלים אימונים.
מהתשובות האלה מתגבש סדר ההתחלה: ביקורת האחסון הנוכחי, סכמת ענפים ותגים, הגדרת אחסון מרוחק, העברת מערכים קיימים, נהלי עבודה לצוות. אלה הם נתוני הקלט של הפרויקט — בלעדיהם הערכת הנפח תהיה בקירוב. תארו את המשימה בצורה נוחה, ונחזור עם הערכה ותוכנית עבודה.







