Ultralytics YOLO27: انضم إلى قائمة الانتظار.
Get Started
Ultralytics YOLO في بيئة الإنتاج·المعايرة والملاحظة·الدرس 8/9
الدرسمتوسط

قابلية الملاحظة والانحراف

سجّل المقاييس التي تكشف التراجع الصامت في الدقة، واختبر توزيعات الثقة للكشف عن الانحراف، ولا تطلق التنبيهات إلا عند ظهور مؤشرات تستدعي إجراءً.

قد تكون خدمة الرؤية عاملة وسريعة، لكنها تعطي نتائج خاطئة. قد تتحرك الكاميرا من موضعها، أو تتغير الإضاءة، أو يصل خط منتجات جديد، بينما يواصل النموذج إرجاع الصناديق وتظل جميع لوحات معلومات البنية التحتية خضراء. في هذا الدرس، أدى تعتيم مقطع لمحاكاة وقت الغسق إلى تغيير متوسط الثقة بمقدار 0.01 فقط، وهو تغير لا يظهر على الرسم البياني، لكن اختبار KS ثنائي العينة كشفه عند p = 0.007. ستبني هذا الاختبار وآلية التسجيل التي تمدّه بالبيانات.

النتيجة

أصدر مقاييس JSON لكل إطار، وشغّل اختبار انحراف KS بمقارنة النتائج بخط أساس الإطلاق، وتحقق من مجموعة محجوبة، وحدد تنبيهات يرتبط كل منها بإجراء محدد.

المسار السريع
إذا كنت تعرف الأساسيات بالفعل، فإليك النسخة المختصرة.
  1. لكل إطار: الكاميرا، وr.speed["inference"]، وعدد عمليات الكشف، ومتوسط الثقة، وقيم الثقة الخام.

  2. احفظ قيم الثقة عند الإطلاق بوصفها خط الأساس؛ وقارنها يوميًا باستخدام scipy.stats.ks_2samp.

  3. تحقق أسبوعيًا من مجموعة محجوبة ذات تسميات باستخدام yolo val؛ وأطلق تنبيهًا عند انخفاض mAP بأكثر من نقطة واحدة.

  4. أطلق التنبيهات فقط عند ظهور مؤشرات لها إجراء تالٍ موثق؛ واجعل كل ما عدا ذلك ضمن لوحة معلومات.

عملي

ثلاث طبقات من المؤشرات#

الطبقةالسؤالالمؤشرات
البنية التحتيةهل الخدمة تعمل وتواكب سرعة الإدخال؟زمن الاستجابة، ومعدل المعالجة، والإطارات المُسقطة، واستخدام CPU وGPU
سلوك النموذجهل يتصرف النموذج كما كان الأسبوع الماضي؟عمليات الكشف لكل إطار، ومتوسط الثقة، ومزيج الفئات، وأحجام الصناديق
دقة النموذجهل ما زال النموذج يعطي نتائج صحيحة؟mAP لمجموعة التحقق (مقاييس الأداء)، ومراجعة بشرية لعينات، ومعدل الإنذارات الكاذبة

تغطي معظم الفرق الطبقة الأولى بأدوات قياسية وتتوقف عندها. أما الطبقتان الثانية والثالثة فهما موضع الإخفاق الصامت لأنظمة الرؤية؛ ويغطي دليل مراقبة النماذج دورة الصيانة كاملة.

صفحة النشر في Ultralytics Platform ضمن علامة التبويب Logs، مع مرشحي Errors وAll فوق أسطر طلبات INFO مؤرخة لمراقبة الطلبات وطلبات العينة

إذا نشرت عبر Ultralytics Platform، فستوفر لك صفحة النشر طبقة البنية التحتية (الطلبات، ومعدل الأخطاء، وزمن الاستجابة P95) وسجلات الطلبات التي يمكنك تصفيتها لإظهار الأخطاء، كما هو موضح أعلاه؛ ويتناول درس مراقبة الصحة والدقة هذه الجوانب. أما طبقتا السلوك والدقة فعليك بناؤهما بنفسك، وهذا ما يفعله بقية هذا الدرس.

إصدار المقاييس لكل إطار#

يحتوي كل كائن Results على توقيتات وصناديق. اكتب سطر JSON واحدًا لكل إطار وأرسله إلى نظام المقاييس الذي تستخدمه:

import json
import time

from ultralytics import YOLO

model = YOLO("yolo26n.pt")
video = "https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4"
with open("metrics.jsonl", "w") as log:
    for r in model.predict(video, stream=True, verbose=False):
        conf = r.boxes.conf
        record = {
            "ts": time.time(),
            "camera": "lobby-1",
            "inference_ms": round(r.speed["inference"], 1),
            "detections": len(r.boxes),
            "mean_conf": round(conf.mean().item(), 3) if len(conf) else None,
            "confs": [round(c, 3) for c in conf.tolist()],  # ⁨القيم الخام لاختبار الانحراف⁩
        }
        log.write(json.dumps(record) + "\n")
print({k: v for k, v in record.items() if k != "confs"})
{'ts': 1792003254.33, 'camera': 'lobby-1', 'inference_ms': 34.7, 'detections': 22, 'mean_conf': 0.543}

الغرض من كل حقل:

  • inference_ms: أطلق تنبيهًا عندما تتجاوز قيمة p95 الحد المسموح به.
  • detections: يشير الانخفاض المفاجئ إلى ما يقارب الصفر عادةً إلى وجود كاميرا محجوبة أو معطّلة؛ أما الارتفاع الحاد فيشير إلى تغيّر المشهد أو إيجابيات كاذبة.
  • mean_conf: خط اتجاه سريع، لكنه تقريبي أكثر من اللازم لاكتشاف الانحراف بمفرده.
  • confs: التوزيع الكامل الذي يحتاج إليه اختبار الانحراف أدناه.

اختبر انحراف توزيعات الثقة#

يظهر انحراف البيانات في قيم الثقة قبل وقت طويل من تصنيف أي شخص لبيانات جديدة. اجمع قيم الثقة عند الإطلاق لتكون خط أساس، واجمع نافذة حديثة، ثم قارن التوزيعين باختبار كولموغوروف-سميرنوف ثنائي العينة (pip install scipy). يحاكي هذا البرنامج النصي وقت الغسق بتعتيم المقطع نفسه:

import cv2
import numpy as np
from scipy.stats import ks_2samp

from ultralytics import YOLO
from ultralytics.utils.downloads import safe_download

model = YOLO("yolo26n.pt")
video = str(safe_download("https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4"))

def confidences(darken=1.0):
    """Collect every detection confidence from the clip, optionally darkened to simulate dusk."""
    cap, out = cv2.VideoCapture(video), []
    while True:
        ok, frame = cap.read()
        if not ok:
            break
        out += model((frame * darken).astype(np.uint8), verbose=False)[0].boxes.conf.tolist()
    return np.array(out)

baseline = confidences()  # what "normal" looked like at launch
for name, recent in (("same scene", confidences()), ("dusk (35% brightness)", confidences(darken=0.35))):
    stat, p = ks_2samp(baseline, recent)
    print(f"{name:22s} n={len(recent):4d} mean_conf={recent.mean():.3f} KS={stat:.3f} p={p:.2g}")
same scene             n=1376 mean_conf=0.519 KS=0.000 p=1
dusk (35% brightness)  n=1337 mean_conf=0.508 KS=0.064 p=0.0068

اقرأها سطرًا سطرًا:

  • المشهد نفسه: تعطي التوزيعات المتطابقة إحصائية KS تساوي 0 وp = 1، وهذا هو الاختبار الضابط.
  • الغسق: 39 اكتشافًا أقل ومتوسط أقل بمقدار 0.011 فقط، وهو فرق لن يلاحظه أحد على رسم بياني. تبلغ إحصائية KS (أكبر فجوة بين التوزيعين التراكميين) 0.064، وتشير قيمة p = 0.0068 < 0.01 إلى أن التحول حقيقي.

تنبيه الانحراف سببٌ لفحص إطارات عيّنة، وليس دليلًا على الفشل. عندما يكون الانحراف حقيقيًا، اجمع إطارات من الكاميرات المتأثرة وصنّفها: يوضح دليل جمع البيانات وتعليقها ما ينبغي جمعه، ويوضح دليل الضبط الدقيق كيفية إعادة التدريب. وتُعد أحجام الصناديق (العرض × الارتفاع) مؤشرًا ثانيًا بسيطًا للانحراف: إذ تظهر تغييرات الحوامل والعدسات فيها أولًا.

تحقّق من مجموعة اختبار محجوبة أسبوعيًا#

تشير مؤشرات السلوك إلى حدوث تغيير؛ لكن التسميات وحدها تكشف ما إذا كانت الدقة قد تراجعت. احتفظ بمجموعة اختبار محجوبة تضم 200–500 صورة إنتاجية مصنفة، وتحقق من كل إصدار للنموذج، وكذلك كل أسبوع:

yolo val model=yolo26n.pt data=coco8.yaml > weekly_metrics.txt  # use your production model and holdout YAML

سجّل mAP50-95 وAP لكل فئة بمرور الوقت، وأطلق تنبيهًا عندما ينخفض mAP بأكثر من نقطة واحدة مقارنةً بالأسبوع السابق. السبب الأكثر شيوعًا هو استبدال نموذج كان من المفترض ألا يغيّر شيئًا؛ والسبب الثاني هو الانحراف. ويُظهر مصفوفة الالتباس على مجموعة الاختبار المحجوبة نفسها حالات التراجع لكل فئة بوضوح.

جودة النموذج بمرور الوقت: تظل الجودة مستقرة مع وصول بيانات جديدة مصنفة، ثم تتراجع بعد النقطة المتوقعة لبدء التراجع، مع طرح سؤال: هل نعيد التدريب الآن أم ننتظر

تجيب مجموعة الاختبار المحجوبة عن السؤال المطروح في هذا الرسم البياني. أعد التدريب عندما تُظهر المجموعة بدء تراجع الجودة، أو عندما تتوفر لديك بيانات جديدة مصنفة كافية من الظروف التي شهدت انحرافًا، لا وفق جدول زمني ثابت.

أطلق التنبيهات بناءً على الإجراءات، لا الأرقام#

المؤشرمتى يُطلق التنبيهالإجراء
p95 inference_msيتجاوز الحد المسموح به لأكثر من 3 دقائقوسّع نطاق الموارد أو انتقل إلى التصدير المحسّن
عدد الاكتشافات لكل إطارانخفاض بنسبة 50% أو أكثر لمدة 5 دقائقتحقق من بث الكاميرا، ثم من إصدار النموذج
الإطارات المفقودةتتجاوز نسبتها 5% لمدة 10 دقائقأضف سعة أو خفّض FPS لكل بث
اختبار KS للثقةp < 0.01 في النوافذ اليوميةراجع الإطارات، ثم شغّل التحقق على مجموعة الاختبار المحجوبة
mAP50-95 لمجموعة الاختبار المحجوبةانخفاض بأكثر من نقطة واحدة مقارنةً بالأسبوع السابقاجمع البيانات وصنّفها واضبط النموذج بدقة

مواطن الخلل#

مقارنة نوافذ غير متماثلة

العَرَض: يُطلق اختبار KS إنذارًا كل مساء وكل يوم اثنين. الحل: الدورات اليومية والأسبوعية تغيرات حقيقية في التوزيع. قارن حالات متماثلة (الكاميرات نفسها، والساعات نفسها، ويوم الأسبوع نفسه)، واستخدم نوافذ تضم آلاف عمليات الكشف.

مجموعة اختبار محجوبة قديمة

العَرَض: تبدو قيمة mAP لمجموعة الاختبار المحجوبة جيدة، بينما يبلغ المستخدمون عن حالات إخفاق. الحل: يجب أن تماثل مجموعة الاختبار المحجوبة بيئة الإنتاج الحالية. حدّثها كل ربع سنة بإطارات موسومة حديثًا من الكاميرات المهمة.

إذا لم يكن أحد سيتخذ إجراءً بناءً عليه، فلا ترسل تنبيهًا

يجب أن يتضمن كل تنبيه إجراءً تاليًا مكتوبًا. أما الإشارة التي تريد مراقبتها فحسب، فمكانها لوحة المعلومات لا نظام التنبيه.

جرّبه

أضف تسجيل JSON إلى مسار المعالجة وشغّله لمدة ساعة (أو على مقطع فيديو طويل). احتفظ بالنافذة الأولى بوصفها baseline.jsonl، ثم شغّل فحص KS الخاص بالحل على نافذة ثانية: في وقت مختلف من اليوم، أو من كاميرا مختلفة، أو على نسخة معتمة. قدّم إحصائية KS وقيمة p، بالإضافة إلى جدول التنبيهات الذي يحدد إجراءً لكل صف.

متى يُعدّ مكتملًا
تكون قد أتممت الدرس عند تحقق جميع الشروط التالية.
  • يكتب مسار المعالجة سطر JSON واحدًا لكل إطار، يتضمن زمن الاستجابة وعدد الاكتشافات ومتوسط الثقة وقيم الثقة الخام.

  • أجريت اختبار KS بين خط أساس ونافذة حديثة وسجلت الإحصائية وقيمة p.

  • لكل تنبيه حددته عتبة ومدة وإجراء تالٍ مكتوب.

عرض الحل

احتفظ بأول نافذة سليمة من مخرجات monitor.py بوصفها baseline.jsonl، ثم قارن بها كل نافذة جديدة:

import json

import numpy as np
from scipy.stats import ks_2samp

def load(path):
    """Flatten the per-frame 'confs' lists written by monitor.py."""
    with open(path) as f:
        return np.array([c for line in f for c in json.loads(line)["confs"]])

baseline, recent = load("baseline.jsonl"), load("metrics.jsonl")
stat, p = ks_2samp(baseline, recent)
print(f"KS={stat:.3f} p={p:.2g} -> {'review frames' if p < 0.01 else 'ok'}")
KS=0.000 p=1 -> ok

هذه هي النتيجة المتوقعة عندما يأتي الملفان من اللقطات نفسها. شغّل الاختبار يوميًا باستخدام مجدول، وأرسل الإحصائية وقيمة p إلى نظام المقاييس نفسه المستخدم لسجلات كل إطار، ووجّه review frames إلى شخص، لا إلى نظام النداء.

ما الخطوة التالية

الدرس الأخير: عندما تُظهر لوحات المعلومات أن زمن الاستجابة أو التكلفة يتجاوز الحد المسموح به، فأي إجراء ينبغي اتخاذه أولًا؟

سجّل الدخول لحفظ التقدم