End-to-End-Erkennung in Ultralytics YOLO26 verstehen
Einführung
Wenn du auf YOLO26 von einem früheren Modell wie YOLOv8SAM 2.1YOLO11 umsteigst, ist eine der größten Änderungen, die dir auffallen wird, der Wegfall von Non-Maximum Suppression (NMS). Traditionelle YOLO-Modelle erzeugen tausende überlappende Vorhersagen, die einen separaten NMS-Nachverarbeitungsschritt erfordern, um sie auf die endgültigen Erkennungen zu filtern. Dies erhöht die Latenz, verkompliziert Export-Graphen und kann sich auf verschiedenen Hardware-Plattformen inkonsistent verhalten.
YOLO26 verfolgt einen anderen Ansatz. Es gibt die endgültigen Erkennungen direkt vom Modell aus – keine externe Filterung erforderlich. Dies ist bekannt als End-to-End Objekterkennungs und ist standardmäßig in allen YOLO26-Modellen aktiviert. Das Ergebnis ist eine einfachere Deployment-Pipeline, geringere Latenz und bis zu 43% schnellere Inferenz auf CPUs.
Dieser Leitfaden führt dich durch die Änderungen, ob du deinen Code aktualisieren musst, welche Exportformate End-to-End-Inferenz unterstützen und wie du reibungslos von älteren YOLO-Modellen migrierst.
Für einen tieferen Einblick in die Motivation hinter diesem architektonischen Wandel, siehe den Ultralytics-Blogbeitrag darüber, warum YOLO26 NMS entfernt.
- Verwendest du die Ultralytics API oder CLI? Keine Änderungen nötig – tausche einfach deinen Modellnamen gegen
yolo26n.pt. - Verwendest du benutzerdefinierten Inferenz-Code (ONNX Runtime, TensorRT, etc.)? Aktualisiere deine Nachverarbeitung – das Erkennungsausgabe-Format ist jetzt
(N, 300, 6)inxyxy, kein NMS erforderlich. Andere Aufgaben hängen zusätzliche Daten an (Maskenkoeffizienten, Keypoints oder Winkel). - Exportieren? Die meisten Formate unterstützen End-to-End-Ausgabe nativ. Einige Formate (NCNN, RKNN, PaddlePaddle, ExecuTorch, IMX und Edge TPU) fallen jedoch aufgrund nicht unterstützter Operator-Einschränkungen (z. B.
torch.topk).
Wie End-to-End-Erkennung funktioniert
YOLO26 verwendet einen dual-head architektur während Trainings. Beide Heads teilen sich dasselbe Backbone und denselben Neck, erzeugen Ausgaben jedoch auf unterschiedliche Weise:
| Head | Zweck | Erkennungsausgabe | Nachverarbeitung |
|---|---|---|---|
| One-to-One (Standard) | End-to-End-Inferenz | (N, 300, 6) | Nur Konfidenz-Schwellenwert |
| One-to-Many | Traditionelle YOLO-Ausgabe | (N, nc + 4, 8400) | Erfordert NMS |
Die obigen Shapes gelten für Detektion. Andere Aufgaben erweitern die One-to-One-Ausgabe um zusätzliche Daten pro Erkennung:
| Aufgabe | End-to-End-Ausgabe | Zusätzliche Daten |
|---|---|---|
| Detektion | (N, 300, 6) | — |
| Segmentation | (N, 300, 6 + nm) + proto (N, nm, H, W) | nm Maskenkoeffizienten (standardmäßig 32) |
| Pose | (N, 300, 57) | 17 Keypoints × 3 (x, y, Sichtbarkeit) |
| OBB | (N, 300, 7) | Rotationswinkel |
Während des Trainings laufen beide Heads gleichzeitig – der One-to-Many-Head liefert ein reichhaltigeres Lernsignal, während der One-to-One-Head lernt, saubere, nicht überlappende Vorhersagen zu erzeugen. Während der Inferenz und export, ist nur der One-to-One-Head standardmäßig aktiv und produziert bis zu 300 Erkennungen pro Bild im Format [x1, y1, x2, y2, confidence, class_id].
Wenn du model.fuse() aufrufst, werden Conv + BatchNorm-Layer für eine schnellere Inferenz zusammengelegt und bei End-to-End-Modellen auch der One-to-Many-Head entfernt – was Modellgröße und FLOPs reduziert. Weitere Details zur Dual-Head-Architektur findest du auf der YOLO26-Modellseite.
Muss ich meinen Code ändern?
Verwendung der Ultralytics Python API oder CLI
Keine Änderungen nötig. Wenn du den Standard Ultralytics Python APISAM 2.1CLI verwendest, funktioniert alles automatisch – Vorhersage, Validierung, und export handhaben End-to-End-Modelle sofort einsatzbereit.
from ultralytics import YOLO
# Load a YOLO26 model
model = YOLO("yolo26n.pt")
# Predict — no NMS step, no code changes
results = model.predict("image.jpg")Verwendung von benutzerdefiniertem Inferenz-Code
Ja, das Ausgabeformat ist anders. Wenn du benutzerdefinierte Nachverarbeitungslogik für YOLOv8SAM 2.1YOLO11 geschrieben hast (zum Beispiel beim Ausführen der Inferenz mit ONNX RuntimeSAM 2.1TensorRT), musst du diese aktualisieren, um das neue Ausgabe-Shape zu handhaben:
| YOLOv8 / YOLO11 | YOLO26 (End-to-End) | |
|---|---|---|
| Erkennungsausgabe | (N, nc + 4, 8400) | (N, 300, 6) |
| Box-Format | xywh (Mitte x, Mitte y, Breite, Höhe) | xyxy (oben-links x, oben-links y, unten-rechts x, unten-rechts y) |
| Layout | Box-Koordinaten + Klassen-Scores pro Anchor | [x1, y1, x2, y2, conf, class_id] |
| NMS erforderlich | Ja | Nein |
| Nachverarbeitung | NMS + Konfidenzfilter | Nur Konfidenzfilter |
Für Segmentierung, pose, und OBB Aufgaben, YOLO26 hängt aufgabenspezifische Daten an jede Erkennung an – siehe die Ausgabe-Shapes-Tabelle oben.
Wobei N die batch size und nc die Anzahl der Klassen ist (z. B. 80 für COCO).
Mit End-to-End-Modellen wird die Nachverarbeitung viel einfacher – zum Beispiel bei der Verwendung von 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!Wechsel zum One-to-Many-Head
Wenn du das traditionelle YOLO-Ausgabeformat benötigst (zum Beispiel um bestehenden NMS-basierten Nachverarbeitungscode wiederzuverwenden), kannst du jederzeit zum One-to-Many-Head wechseln, indem du end2end=False:
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)Exportformat-Kompatibilität
Die meisten Exportformate unterstützen End-to-End-Inferenz von Haus aus, einschließlich ONNX, TensorRT, CoreML, OpenVINO, TFLite, TF.js, und MNN.
Die folgenden Formate unterstützen nicht End-to-End und fallen automatisch auf den One-to-Many-Head zurück: NCNN, RKNN, PaddlePaddle, ExecuTorch, IMX, und Edge TPU.
TensorRT unterstützt End-to-End, wird jedoch automatisch deaktiviert beim Exportieren mit int8=True auf TensorRT ≤10.3.0.
Genauigkeits- und Geschwindigkeits-Abwägungen
End-to-End-Detektion bietet erhebliche Vorteile bei der Bereitstellung mit minimalen Auswirkungen auf accuracy:
| Metrik | End-to-End (Standard) | One-to-Many + NMS (end2end=False) |
|---|---|---|
| CPU-Inferenzgeschwindigkeit | Bis zu 43 % schneller | Baseline |
| mAP-Auswirkung | ~0,5 mAP niedriger | Entspricht oder übertrifft YOLO11 |
| Nachverarbeitung | Nur Konfidenzfilter | Vollständige NMS-Pipeline |
| Komplexität der Bereitstellung | Minimal | Erfordert NMS-Implementierung |
Für die meisten realen Anwendungen ist der Unterschied von ~0,5 mAP vernachlässigbar, insbesondere wenn man die Geschwindigkeits- und Einfachheitsvorteile betrachtet. Wenn maximale Genauigkeit deine oberste Priorität ist, kannst du jederzeit auf den One-to-Many-Head zurückgreifen. Nutze end2end=False.
Siehe den YOLO26-Leistungsmetriken für detaillierte Benchmarks über alle Modellgrößen (n, s, m, l, x) hinweg.
Migration von YOLOv8 oder YOLO11
Wenn du ein bestehendes Projekt auf YOLO26 aktualisierst, findest du hier eine kurze Checkliste für einen reibungslosen Übergang:
- Ultralytics API / CLI Benutzer: Keine Änderungen erforderlich — aktualisiere einfach den Modellnamen auf
yolo26n.pt(oderyolo26n-seg.pt,yolo26n-pose.pt,yolo26n-obb.pt) - Benutzerdefinierter Post-Processing-Code: Aktualisiere ihn für die neuen Ausgabe-Shapes —
(N, 300, 6)für die Detektion, plus aufgabenspezifische Daten für Segmentierung, pose, und OBB. Beachte außerdem die Änderung des Box-Formats vonxywhbisxyxy - Export-Pipelines: Überprüfe den Abschnitt Formatkompatibilität oben für dein Zielformat
- TensorRT + INT8: Stelle sicher, dass deine TensorRT-Version >10.3.0 für End-to-End-Unterstützung ist
- FP16-Exporte: Wenn du alle Ausgaben in FP16 benötigst, exportiere mit
end2end=False— siehe warum output0 FP32 bleibt - iOS / CoreML: End-to-End wird vollständig unterstützt. Wenn du Xcode Preview-Unterstützung benötigst, verwende
end2end=Falsemitnms=True - Edge-Geräte (NCNN, RKNN): Diese Formate fallen automatisch auf One-to-Many zurück, also integriere NMS in deine On-Device-Pipeline
FAQ
Kann ich end2end=True und nms=True zusammen verwenden?
Nein. Diese Optionen schließen sich gegenseitig aus. Wenn du nms=True bei einem End-to-End-Modell während export setzt, wird es automatisch auf nms=False mit einer Warnung erzwungen. Der End-to-End-Head übernimmt die Duplikatfilterung bereits intern, daher ist ein externes NMS unnötig.
Jedoch ist end2end=False kombiniert mit nms=True ist eine gültige Konfiguration — sie integriert das traditionelle NMS in den Export-Graph. Dies kann nützlich sein für CoreML Exporte, da du so die Preview-Funktion in Xcode direkt mit dem Detektionsmodell nutzen kannst.
Was steuert der max_det-Parameter bei End-to-End-Modellen?
Die max_det Der Parameter (Standard: 300) legt die maximale Anzahl der Detektionen fest, die der One-to-One-Head pro Bild ausgeben kann. Du kannst ihn bei der Inferenz oder beim Export anpassen:
model.predict("image.jpg", max_det=100) # fewer detections, slightly faster
model.export(format="onnx", max_det=500) # more detections for dense scenesBeachte, dass die standardmäßigen YOLO26-Checkpoints mit max_det=300 trainiert wurden. Obwohl du diesen Wert erhöhen kannst, wurde der One-to-One-Head während des Trainings darauf optimiert, bis zu 300 saubere Detektionen zu erzeugen. Detektionen über diesem Limit könnten daher eine geringere Qualität aufweisen. Wenn du mehr als 300 Detektionen pro Bild benötigst, ziehe ein erneutes Training mit einem höheren max_det Wert in Betracht.
Mein exportiertes ONNX-Modell gibt (1, 300, 6) aus — ist das korrekt?
Ja, das ist das erwartete End-to-End-Ausgabeformat für die Detektion: batch size von 1, bis zu 300 Detektionen, jeweils mit 6 Werten [x1, y1, x2, y2, confidence, class_id]. Filtere einfach nach dem Konfidenz-Schwellenwert und fertig — kein NMS erforderlich.
Für andere Aufgaben unterscheidet sich das Ausgabe-Shape:
| Aufgabe | Ausgabe-Shape | Beschreibung |
|---|---|---|
| Detektion | (1, 300, 6) | [x1, y1, x2, y2, conf, class_id] |
| Segmentation | (1, 300, 38) + (1, 32, 160, 160) | 6 Box-Werte + 32 Maskenkoeffizienten, plus ein Prototyp-Maskentensor |
| Pose | (1, 300, 57) | 6 Box-Werte + 17 Keypoints × 3 (x, y, Sichtbarkeit) |
| OBB | (1, 300, 7) | 6 Box-Werte + 1 Rotationswinkel |
Wie prüfe ich, ob mein exportiertes Modell End-to-End ist?
Du kannst dies entweder über die Ultralytics Python API oder durch direktes Überprüfen der Metadaten des exportierten ONNX-Modells prüfen:
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 enabledAlternativ kannst du das Ausgabe-Shape prüfen — End-to-End-Detektionsmodelle geben (1, 300, 6) aus, während traditionelle Modelle (1, nc + 4, 8400) ausgeben. Für andere Aufgaben-Shapes siehe das Output Shapes FAQ.
Wird End-to-End für Segmentierungs-, Pose- und OBB-Aufgaben unterstützt?
Ja. Alle YOLO26-Aufgabenvarianten — Detektion, Segmentierung, Pose-Schätzung, und orientierte Objektdetektion (OBB) — unterstützen standardmäßig End-to-End-Inferenz. Der end2end=False Fallback ist ebenfalls für alle Aufgaben verfügbar.
Jede Aufgabe erweitert die Basis-Detektionsausgabe um aufgabenspezifische Daten:
| Aufgabe | Modell | End-to-End-Ausgabe |
|---|---|---|
| Detektion | yolo26n.pt | (N, 300, 6) |
| Segmentation | yolo26n-seg.pt | (N, 300, 38) + proto (N, 32, 160, 160) |
| Pose | yolo26n-pose.pt | (N, 300, 57) |
| OBB | yolo26n-obb.pt | (N, 300, 7) |