فهم الاكتشاف من الطرف إلى الطرف (End-to-End) في YOLO26 من Ultralytics

مقدمة

إذا كنت تقوم بالترقية إلى YOLO26 من نموذج أقدم مثل YOLOv8 أو YOLO11، فإن أحد أكبر التغييرات التي ستلاحظها هو إزالة كبت غير الأعظم (NMS). تنتج نماذج YOLO التقليدية آلاف التوقعات المتداخلة التي تحتاج إلى خطوة معالجة لاحقة منفصلة باستخدام NMS للتصفية وصولاً إلى الاكتشافات النهائية. وهذا يضيف زمن انتقال، ويعقد رسوم بيانية للتصدير، ويمكن أن يعمل بشكل غير متسق عبر منصات الأجهزة المختلفة.

يتبع YOLO26 نهجاً مختلفاً. فهو يخرج الاكتشافات النهائية مباشرة من النموذج، ولا يتطلب أي تصفية خارجية. يُعرف هذا بـ اكتشاف الكائنات من الطرف إلى الطرف، وهو مفعل افتراضياً في جميع نماذج YOLO26. النتيجة هي خط أنابيب نشر أبسط، وزمن انتقال أقل، وأداء استدلال أسرع بنسبة تصل إلى 43% على وحدات المعالجة المركزية (CPUs).

يرشدك هذا الدليل عبر ما تغير، وما إذا كنت بحاجة إلى تحديث الكود الخاص بك، وتنسيقات التصدير التي تدعم الاستدلال من الطرف إلى الطرف، وكيفية الانتقال بسلاسة من نماذج YOLO الأقدم.

لإلقاء نظرة أعمق على الدافع وراء هذا التحول المعماري، راجع مدونة Ultralytics حول سبب إزالة YOLO26 لـ NMS وكيف يغير ذلك النشر.

ملخص سريع
  • هل تستخدم Ultralytics API أو CLI؟ لا حاجة لإجراء أي تغييرات، فقط استبدل اسم النموذج الخاص بك بـ yolo26n.pt.
  • هل تستخدم كود استدلال مخصص (مثل ONNX Runtime أو TensorRT، إلخ)؟ قم بتحديث المعالجة اللاحقة لديك، حيث أصبح مخرج الاكتشاف الآن (N, 300, 6) بتنسيق xyxy، ولا يتطلب NMS. المهام الأخرى تضيف بيانات إضافية (معاملات القناع، أو النقاط الرئيسية، أو الزاوية).
  • هل تقوم بالتصدير؟ تدعم معظم التنسيقات المخرجات من الطرف إلى الطرف بشكل أصلي. ومع ذلك، تعود بعض التنسيقات (NCNN، وRKNN، وPaddlePaddle، وExecuTorch، وIMX، وEdge TPU) تلقائياً إلى المخرجات التقليدية بسبب قيود المشغل غير المدعومة (مثل torch.topk).

كيف يعمل الاكتشاف من الطرف إلى الطرف

يستخدم YOLO26 معمارية ثنائية الرأس أثناء التدريب. يتشارك كلا الرأسين نفس العمود الفقري (Backbone) والرقبة (Neck)، لكنهما ينتجان المخرجات بطرق مختلفة:

الرأسالغرضمخرج الاكتشافالمعالجة اللاحقة
واحد لواحد (افتراضي)استدلال من الطرف إلى الطرف(N, 300, 6)عتبة الثقة فقط
واحد لكثيرمخرج YOLO التقليدي(N, nc + 4, 8400)يتطلب NMS

الأشكال المذكورة أعلاه خاصة بـ الاكتشاف. المهام الأخرى تمد مخرج الواحد لواحد ببيانات إضافية لكل اكتشاف:

المهمةمخرج من الطرف إلى الطرفبيانات إضافية
الكشف(N, 300, 6)
التقسيم(N, 300, 6 + nm) + proto (N, nm, H, W)nm معاملات القناع (افتراضي 32)
الوضعية(N, 300, 57)17 نقطة رئيسية × 3 (x, y, الرؤية)
OBB(N, 300, 7)زاوية الدوران

أثناء التدريب، يعمل كلا الرأسين في وقت واحد، حيث يوفر رأس الواحد لكثير إشارة تعلم أغنى، بينما يتعلم رأس الواحد لواحد إنتاج توقعات نظيفة وغير متداخلة. أثناء الاستدلال والتصدير، يكون رأس الواحد لواحد هو النشط فقط افتراضياً، حيث ينتج ما يصل إلى 300 اكتشاف لكل صورة بتنسيق [x1, y1, x2, y2, confidence, class_id].

عند استدعاء model.fuse()، فإنه يقوم بدمج طبقات Conv + BatchNorm لاستدلال أسرع، وفي نماذج الطرف إلى الطرف، يزيل أيضاً رأس الواحد لكثير، مما يقلل من حجم النموذج وعدد العمليات الحسابية (FLOPs). لمزيد من التفاصيل حول المعمارية ثنائية الرأس، راجع صفحة نموذج YOLO26.

هل أحتاج إلى تغيير الكود الخاص بي؟

استخدام Ultralytics Python API أو CLI

لا حاجة لإجراء أي تغييرات. إذا كنت تستخدم Ultralytics Python API القياسية أو CLI، فإن كل شيء يعمل تلقائياً، حيث تتعامل جميع عمليات التنبؤ والتحقق والتصدير مع نماذج الطرف إلى الطرف خارج الصندوق.

لا توجد تغييرات مطلوبة في الكود مع Ultralytics API
from ultralytics import YOLO

# Load a YOLO26 model
model = YOLO("yolo26n.pt")

# Predict — no NMS step, no code changes
results = model.predict("image.jpg")

استخدام كود استدلال مخصص

نعم، تنسيق المخرجات مختلف. إذا كنت قد كتبت منطق معالجة لاحقة مخصصاً لـ YOLOv8 أو YOLO11 (على سبيل المثال، عند تشغيل الاستدلال باستخدام ONNX Runtime أو TensorRT)، فستحتاج إلى تحديثه للتعامل مع شكل المخرجات الجديد:

YOLOv8 / YOLO11YOLO26 (من الطرف إلى الطرف)
مخرج الاكتشاف(N, nc + 4, 8400)(N, 300, 6)
تنسيق الصندوق (Box)xywh (مركز x، مركز y، العرض، الارتفاع)xyxy (أعلى يسار x، أعلى يسار y، أسفل يمين x، أسفل يمين y)
التخطيطإحداثيات الصندوق + درجات الفئات لكل مرساة (anchor)[x1, y1, x2, y2, conf, class_id]
NMS مطلوبنعملا
المعالجة اللاحقةNMS + مرشح الثقةمرشح الثقة فقط

بالنسبة لمهام التقسيم، والوضعية، وOBB، يضيف YOLO26 بيانات خاصة بالمهمة لكل اكتشاف، راجع جدول أشكال المخرجات أعلاه.

حيث N هو حجم الدفعة وnc هو عدد الفئات (مثل 80 لـ COCO).

مع نماذج الطرف إلى الطرف، تصبح المعالجة اللاحقة أبسط بكثير، على سبيل المثال، عند استخدام ONNX Runtime:

import onnxruntime as ort

# Load and run the exported end-to-end model
session = ort.InferenceSession("yolo26n.onnx")
output = session.run(None, {session.get_inputs()[0].name: input_tensor})

# End-to-end output: (batch, 300, 6) → [x1, y1, x2, y2, confidence, class_id]
detections = output[0][0]  # first image in batch
detections = detections[detections[:, 4] > conf_threshold]  # confidence filter — that's it!

التبديل إلى رأس الواحد لكثير

إذا كنت بحاجة إلى تنسيق مخرجات YOLO التقليدي (على سبيل المثال، لإعادة استخدام كود المعالجة اللاحقة المستند إلى NMS الموجود)، يمكنك التبديل إلى رأس الواحد لكثير في أي وقت عن طريق ضبط end2end=False:

استخدام رأس الواحد لكثير لمخرجات تقليدية مستندة إلى NMS
from ultralytics import YOLO

model = YOLO("yolo26n.pt")

# Prediction with NMS (traditional behavior)
results = model.predict("image.jpg", end2end=False)

# Validation with NMS
metrics = model.val(data="coco.yaml", end2end=False)

# Export without end-to-end
model.export(format="onnx", end2end=False)

توافق تنسيق التصدير

تدعم معظم تنسيقات التصدير الاستدلال من الطرف إلى الطرف خارج الصندوق، بما في ذلك ONNX، وTensorRT، وCoreML، وOpenVINO، وTFLite، وTF.js، وMNN.

التنسيقات التالية لا تدعم الطرف إلى الطرف وتعود تلقائياً إلى رأس الواحد لكثير: NCNN، وRKNN، وPaddlePaddle، وExecuTorch، وIMX، وEdge TPU.

ماذا يحدث عندما لا يكون الطرف إلى الطرف مدعوماً

عند التصدير إلى أحد هذه التنسيقات، يقوم Ultralytics بالتبديل تلقائياً إلى رأس الواحد لكثير ويسجل تحذيراً، ولا حاجة لتدخل يدوي. هذا يعني أنك ستحتاج إلى NMS في خط أنابيب الاستدلال الخاص بك لهذه التنسيقات، تماماً كما هو الحال مع YOLOv8 أو YOLO11.

TensorRT + INT8

يدعم TensorRT الطرف إلى الطرف، لكنه يتم تعطيله تلقائياً عند التصدير باستخدام int8=True على TensorRT ≤10.3.0.

مقايضات الدقة والسرعة

يوفر الاكتشاف من الطرف إلى الطرف فوائد نشر كبيرة مع تأثير ضئيل على الدقة:

المقياسمن الطرف إلى الطرف (افتراضي)واحد لكثير + NMS (end2end=False)
سرعة الاستدلال على CPUأسرع بنسبة تصل إلى 43%الأساس (Baseline)
تأثير mAP~0.5 mAP أقلتساوي أو تتجاوز YOLO11
المعالجة اللاحقةمرشح الثقة فقطخط أنابيب NMS كامل
تعقيد النشربسيطيتطلب تنفيذ NMS

بالنسبة لمعظم تطبيقات العالم الحقيقي، يكون فرق ~0.5 mAP ضئيلاً، خاصة عند مراعاة مكاسب السرعة والبساطة. إذا كانت الدقة القصوى هي أولويتك القصوى، يمكنك دائماً العودة إلى رأس الواحد لكثير باستخدام end2end=False.

راجع مقاييس أداء YOLO26 للحصول على معايير تفصيلية عبر جميع أحجام النماذج (n, s, m, l, x).

الترحيل من YOLOv8 أو YOLO11

إذا كنت تقوم بترقية مشروع موجود إلى YOLO26، فإليك قائمة مرجعية سريعة لضمان انتقال سلس:

  • مستخدمو Ultralytics API / CLI: لا حاجة لإجراء أي تغييرات، فقط قم بتحديث اسم النموذج إلى yolo26n.pt (أو yolo26n-seg.pt، yolo26n-pose.pt، yolo26n-obb.pt)
  • كود المعالجة اللاحقة المخصص: قم بالتحديث للتعامل مع أشكال المخرجات الجديدة، (N, 300, 6) للاكتشاف، بالإضافة إلى بيانات خاصة بالمهمة لـ التقسيم، والوضعية، وOBB. لاحظ أيضاً تغيير تنسيق الصندوق من xywh إلى xyxy
  • خطوط أنابيب التصدير: تحقق من قسم توافق التنسيق أعلاه للتنسيق المستهدف الخاص بك
  • TensorRT + INT8: تحقق من أن إصدار TensorRT الخاص بك >10.3.0 لدعم الطرف إلى الطرف
  • تصديرات FP16: إذا كنت بحاجة إلى جميع المخرجات بتنسيق FP16، فقم بالتصدير باستخدام end2end=False، راجع لماذا يظل output0 بتنسيق FP32 عند التصدير مع half=True وend2end=True
  • iOS / CoreML: يتم دعم الطرف إلى الطرف بالكامل. إذا كنت بحاجة إلى دعم معاينة Xcode، فاستخدم end2end=False مع nms=True
  • أجهزة الحافة (NCNN, RKNN): تعود هذه التنسيقات تلقائياً إلى الواحد لكثير، لذا قم بتضمين NMS في خط الأنابيب الخاص بك على الجهاز

الأسئلة الشائعة

هل يمكنني استخدام end2end=True وnms=True معاً؟

لا. هذه الخيارات متبادلة بشكل حصري. إذا قمت بضبط nms=True على نموذج طرف إلى طرف أثناء التصدير، فسيتم إجباره تلقائياً على nms=False مع تحذير. يتعامل رأس الطرف إلى الطرف بالفعل مع تصفية التكرارات داخلياً، لذا فإن NMS الخارجية غير ضرورية.

ومع ذلك، فإن end2end=False مدمجاً مع nms=True هو تكوين صالح، حيث يقوم بدمج NMS التقليدي في رسم التصدير. يمكن أن يكون هذا مفيداً لتصديرات CoreML لأنه يتيح لك استخدام وظيفة المعاينة في Xcode مع نموذج الاكتشاف مباشرة.

ما الذي يتحكم فيه معلم max_det في نماذج الطرف إلى الطرف؟

يحدد معلم max_det (الافتراضي: 300) الحد الأقصى لعدد الاكتشافات التي يمكن لرأس الواحد لواحد إخراجها لكل صورة. يمكنك تعديله في وقت الاستدلال أو التصدير:

model.predict("image.jpg", max_det=100)  # fewer detections, slightly faster
model.export(format="onnx", max_det=500)  # more detections for dense scenes

لاحظ أنه تم تدريب نقاط فحص YOLO26 الافتراضية مع max_det=300. على الرغم من أنه يمكنك زيادة هذه القيمة، فقد تم تحسين رأس الواحد لواحد أثناء التدريب لإنتاج ما يصل إلى 300 اكتشاف نظيف، لذا قد تكون الاكتشافات التي تتجاوز هذا الحد أقل جودة. إذا كنت بحاجة إلى أكثر من 300 اكتشاف لكل صورة، ففكر في إعادة التدريب بقيمة max_det أعلى.

نموذج ONNX الذي قمت بتصديره يخرج (1, 300, 6) - هل هذا صحيح؟

نعم، هذا هو تنسيق مخرجات الطرف إلى الطرف المتوقع للاكتشاف: حجم دفعة قدره 1، وما يصل إلى 300 اكتشاف، كل منها بـ 6 قيم [x1, y1, x2, y2, confidence, class_id]. ببساطة قم بالتصفية حسب عتبة الثقة وانتهيت، لا حاجة لـ NMS.

بالنسبة للمهام الأخرى، يختلف شكل المخرجات:

المهمةشكل المخرجالوصف
كشف(1, 300, 6)[x1, y1, x2, y2, conf, class_id]
Segmentation(1, 300, 38) + (1, 32, 160, 160)6 قيم للصندوق + 32 معامل قناع، بالإضافة إلى موتر قناع أولي (prototype mask tensor)
Pose(1, 300, 57)6 قيم للصندوق + 17 نقطة رئيسية × 3 (x، y، الرؤية)
OBB(1, 300, 7)6 قيم للصندوق + 1 زاوية دوران

كيف أتحقق مما إذا كان النموذج المصدر الخاص بي شاملاً (end-to-end)؟

يمكنك التحقق باستخدام Ultralytics Python API أو عن طريق فحص بيانات تعريف نموذج ONNX المصدر مباشرةً:

تحقق مما إذا كان النموذج شاملاً (end-to-end)
from ultralytics import YOLO

model = YOLO("yolo26n.onnx")
model.predict(verbose=False)  # run predict to setup predictor first
print(model.predictor.model.end2end)  # True if end-to-end is enabled

بدلاً من ذلك، تحقق من شكل المخرجات — نماذج الكشف الشاملة (end-to-end) تخرج (1, 300, 6)، بينما تخرج النماذج التقليدية (1, nc + 4, 8400). لأشكال المهام الأخرى، راجع الأسئلة الشائعة حول أشكال المخرجات.

هل يتم دعم الكشف الشامل (end-to-end) لمهام التجزئة، وتقدير الوضع، و OBB؟

نعم. جميع متغيرات مهام YOLO26 — الكشف، والتجزئة، وتقدير الوضع، وكشف الكائنات الموجهة (OBB) — تدعم الاستنتاج الشامل (end-to-end) افتراضياً. يتوفر أيضاً خيار الرجوع end2end=False عبر جميع المهام.

كل مهمة تمد مخرجات الكشف الأساسية ببيانات خاصة بالمهمة:

المهمةالنموذجمخرج من الطرف إلى الطرف
كشفyolo26n.pt(N, 300, 6)
Segmentationyolo26n-seg.pt(N, 300, 38) + proto (N, 32, 160, 160)
Poseyolo26n-pose.pt(N, 300, 57)
OBByolo26n-obb.pt(N, 300, 7)

التعليقات