7.15. כתיבת מעבד משלכם

כאשר הקטלוג אינו מכסה מודל – רשת מחקרית שמבנה הפלט שלה ייחודי, שינוי קטן בארכיטקטורה קיימת, טנזור שהפרשנות הסמנטית שלו ספציפית ליישום – היישום מספק מעבד-קצה משלו. הפרוטוקול פשוט: callable שמקבל (model, inputs, outputs) ומחזיר את כל שהיישום מצפה לו מ-predict().

מחלקה עם __call__ היא הצורה המקובלת:

class MyPostprocessor:
    def __init__(self, threshold=0.5):
        self.threshold = threshold

    def __call__(self, model, inputs, outputs):
        ...
        return result

גם פונקציה רגילה עובדת – המנוע בודק רק שהאובייקט הוא callable.

7.15.1. חיבור שלו פנימה

שתי נקודות חיבור. ארגומנט המילה-מפתח postprocess= של הבנאי קושר את ה-callable לכל קריאת predict() על המודל:

model = ml.Model("/rom/my_model.tflite",
                 postprocess=MyPostprocessor())

כדי לעקוף את הקישור עבור קריאה בודדת – להחליף מפענחים מבלי לטעון מחדש את המודל – העבירו callback= ל-predict ישירות:

result = model.predict([img], callback=MyOtherPostprocessor())

חתימת ה-callable זהה בכל אחד מהמקרים.

7.15.2. מה ה-callable מקבל

  • model – מופע ה-Model, שימושי עבור פרמטרי הקוונטיזציה (output_scale, output_zero_point, output_dtype) ומימדי הקלט (input_shape).

  • inputs – רשימת הקלטים שהיישום העביר ל-predict(). האיבר הראשון הוא בדרך כלל מופע ה-Normalization הקשור; המאפיין roi שלו הוא מה ש-NMS מצפה לו למיפוי מחדש של תיבות בחזרה לתמונה המקורית.

  • outputs – טנזורי הפלט הגולמיים כרשימה של אובייקטי ndarray, ב-dtype המקורי שלהם. פלטים מסוג float מגיעים כפי שהם; פלטים שלמים מגיעים מקוונטזים.

7.15.3. חשבון מקוונטז

כל המפענחים המובנים משתמשים באותם פונקציות עזר ב-ml.utils, ומפענח מותאם אישית בדרך כלל רוצה את אותו דפוס: quantize() מעלה סף float למרחב המקוונטז של המודל, threshold() מסנן מבלי לבטל קוונטיזציה של כל הטנזור, ו-dequantize() רץ פעם אחת על השורדים. sigmoid() ו-logit() זמינים עבור רשתות שערוצי הפלט שלהן הם לוגיטים טרום-sigmoid (גלאי MediaPipe הם המקרה הקנוני).

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

7.15.4. ערך החזרה

מה שה-callable מחזיר הוא מה ש-predict() מחזיר. עבור מפענחים שפולטים תיבות המוסכמה היא לדחוף מועמדים דרך NMS ולהחזיר את הרשימות שלו לכל מחלקה – צורת הקריאה ש-דיכוי לא-מקסימלי מתעד ושה-סקירה מודרכת של YOLOv8 בונה בהקשר. עבור כל דבר אחר, החזירו את כל שהיישום מוצא נוח: ndarray יחיד, מחרוזת תווית, tuple בצורת (class, score, embedding), מילון.