Tìm hiểu về End-to-End Detection trong Ultralytics YOLO26#
Các model theo phong cách phát hiện của YOLO26 — detection, segmentation, pose và OBB — mặc định không có NMS: chúng xuất ra các kết quả phát hiện cuối cùng trực tiếp từ model, không cần bước hậu xử lý Non-Maximum Suppression (NMS). Các model đời đầu như YOLOv8 và YOLO11 tạo ra hàng ngàn dự đoán chồng chéo mà một bước NMS riêng biệt phải lọc bớt, điều này làm tăng độ trễ, phức tạp hóa đồ thị xuất file và có thể hoạt động không đồng nhất trên các nền tảng phần cứng.
Điều này được gọi là phát hiện đối tượng đầu cuối (end-to-end) và tính năng này được bật theo mặc định. Kết quả là một pipeline triển khai đơn giản hơn và độ trễ thấp hơn — YOLO26n chạy nhanh hơn tới 43% so với YOLO11n trên suy luận CPU ONNX (Intel Xeon CPU @ 2.00 GHz).
Hướng dẫn này sẽ giúp bạn nắm bắt những thay đổi, liệu bạn có cần cập nhật code của mình không, những định dạng xuất nào hỗ trợ end-to-end inference và cách di chuyển mượt mà từ các model YOLO cũ hơn.
Để tìm hiểu sâu hơn về động lực đằng sau sự thay đổi kiến trúc này, hãy xem bài viết blog của Ultralytics về lý do YOLO26 loại bỏ NMS.
- Bạn đang sử dụng Ultralytics API hoặc CLI? Không cần thay đổi gì — chỉ cần đổi tên model thành
yolo26n.pt. - Bạn đang sử dụng code suy luận tùy chỉnh (ONNX Runtime, TensorRT, v.v.)? Hãy cập nhật phần hậu xử lý của bạn — đầu ra phát hiện bây giờ là
(N, 300, 6)ở định dạngxyxy, không cần NMS. Các tác vụ khác sẽ đính kèm thêm dữ liệu (hệ số mặt nạ, điểm khóa hoặc góc). - Đang xuất file? Hầu hết các định dạng giữ lại đầu ra end-to-end một cách nguyên bản; một số ít quay lại đầu ra truyền thống và quá trình lượng tử hóa có thể vô hiệu hóa tính năng này — hãy xem Khả năng tương thích định dạng xuất.
Cách thức hoạt động của End-to-End Detection#
YOLO26 sử dụng kiến trúc hai đầu (dual-head architecture) trong quá trình training. Cả hai đầu đều chia sẻ chung phần backbone và neck, nhưng tạo ra các đầu ra theo những cách khác nhau:
| Head | Mục đích | Đầu ra phát hiện | Hậu xử lý |
|---|---|---|---|
| One-to-One (mặc định) | End-to-end inference | (N, 300, 6) | Chỉ ngưỡng tin cậy (Confidence threshold) |
| One-to-Many | Đầu ra YOLO truyền thống | (N, nc + 4, 8400) | Yêu cầu NMS |
Các hình dạng trên dành cho detection, trong đó N là batch size, nc là số lượng lớp (ví dụ: 80 cho COCO), và số lượng anchor 8400 là giá trị tại imgsz=640. Các tác vụ khác mở rộng đầu ra một--một với dữ liệu bổ sung cho mỗi lần phát hiện:
| Tác vụ | End-to-End Output | Dữ liệu bổ sung |
|---|---|---|
| Phát hiện | (N, 300, 6) | — |
| Phân đoạn Cá thể | (N, 300, 6 + nm) + proto (N, nm, H, W) | hệ số mặt nạ nm (mặc định là 32) |
| Pose | (N, 300, 57) | 17 keypoints × 3 (x, y, độ hiển thị) |
| OBB | (N, 300, 7) | Góc xoay |
Trong quá trình training, cả hai đầu chạy đồng thời — đầu one-to-many cung cấp tín hiệu học tập phong phú hơn, trong khi đầu one-to-one học cách tạo ra các dự đoán sạch, không chồng chéo. Trong quá trình inference và export, chỉ có đầu one-to-one hoạt động mặc định, tạo ra tối đa 300 phát hiện mỗi ảnh theo định dạng [x1, y1, x2, y2, confidence, class_id].
Khi bạn gọi model.fuse(), nó sẽ gộp các lớp Conv + BatchNorm để suy luận nhanh hơn và trên các model end-to-end, cũng sẽ loại bỏ đầu one-to-many — giúp giảm kích thước model và số lượng FLOP. Để biết thêm chi tiết về kiến trúc hai đầu, hãy xem trang model YOLO26.
Tôi có cần thay đổi code của mình không?#
Sử dụng Ultralytics Python API hoặc CLI#
Không cần thay đổi gì. Nếu bạn sử dụng Ultralytics Python API hoặc CLI tiêu chuẩn, mọi thứ sẽ hoạt động tự động — prediction, validation và export đều xử lý các model end-to-end ngay khi thiết lập.
from ultralytics import YOLO
# Load a YOLO26 model
model = YOLO("yolo26n.pt")
# Predict — no NMS step, no code changes
results = model.predict("image.jpg")Sử dụng Custom Inference Code#
Có, định dạng đầu ra đã thay đổi. Nếu bạn đã viết logic hậu xử lý tùy chỉnh cho YOLOv8 hoặc YOLO11 (ví dụ: khi chạy suy luận với ONNX Runtime hoặc TensorRT), bạn sẽ cần cập nhật nó để xử lý hình dạng đầu ra mới:
| YOLOv8 / YOLO11 | YOLO26 (end-to-end) | |
|---|---|---|
| Đầu ra phát hiện | (N, nc + 4, 8400) | (N, 300, 6) |
| Định dạng Box | xywh (tâm x, tâm y, chiều rộng, chiều cao) | xyxy (x góc trên bên trái, y góc trên bên trái, x góc dưới bên phải, y góc dưới bên phải) |
| Bố cục | Tọa độ Box + điểm số class trên mỗi anchor | [x1, y1, x2, y2, conf, class_id] |
| Yêu cầu NMS | Có | Không |
| Hậu xử lý | NMS + lọc độ tin cậy | Chỉ lọc độ tin cậy |
Đối với các tác vụ segmentation, pose và OBB, YOLO26 đính kèm dữ liệu riêng của từng tác vụ vào mỗi phát hiện — hãy xem bảng hình dạng đầu ra.
Với các model end-to-end, quá trình hậu xử lý trở nên đơn giản hơn nhiều — ví dụ, khi sử dụng 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] > 0.25] # confidence filter, no NMSChuyển sang Head One-to-Many#
Nếu bạn cần định dạng đầu ra YOLO truyền thống (ví dụ: để tái sử dụng code hậu xử lý dựa trên NMS hiện có), bạn có thể chuyển sang đầu one-to-many khi nó khả dụng bằng cách thiết lập 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)Khả năng tương thích định dạng xuất#
Hầu hết các định dạng xuất đều hỗ trợ suy luận end-to-end ngay lập tức, bao gồm ONNX, TensorRT, CoreML, OpenVINO, LiteRT và MNN.
Các định dạng sau không hỗ trợ end-to-end và sẽ tự động chuyển về đầu one-to-many: NCNN, RKNN, PaddlePaddle, ExecuTorch, IMX, Edge TPU và Qualcomm QNN.
Đối với Hailo, trình xuất chọn đường dẫn đầu ra từ phần đầu đã tải thay vì từ một đối số, vì vậy end2end sẽ bị từ chối nếu được truyền: một model phát hiện YOLO26 mặc định giữ lại các đầu ra một--một không có NMS, trong khi một checkpoint có phần đầu đã là end2end=False sẽ biên dịch đường dẫn truyền thống với HailoRT NMS.
Đánh đổi giữa độ chính xác và tốc độ#
Phát hiện end-to-end mang lại những lợi ích triển khai đáng kể với tác động tối thiểu đến độ chính xác:
| Chỉ số | End-to-End (mặc định) | One-to-Many + NMS (end2end=False) |
|---|---|---|
| COCO mAPval | Thấp hơn 0.6-0.8 | Baseline |
| Hậu xử lý | Chỉ lọc độ tin cậy | Pipeline NMS đầy đủ |
| Độ phức tạp khi triển khai | Tối thiểu | Yêu cầu triển khai NMS |
Trên năm tỷ lệ phát hiện, phần đầu một--một tiêu tốn 0.6-0.8 mAP trên COCO — từ 40.9 xuống 40.1 đối với YOLO26n và từ 57.5 xuống 56.9 đối với YOLO26x — đổi lại là loại bỏ hoàn toàn quá trình NMS. Nếu độ chính xác tối đa là ưu tiên của bạn, hãy quay lại phần đầu một-nhiều với end2end=False.
Xem các chỉ số hiệu suất YOLO26 để biết các benchmark chi tiết trên tất cả các kích thước model (n, s, m, l, x).
Di chuyển từ YOLOv8 hoặc YOLO11#
Nếu bạn đang nâng cấp một dự án hiện có lên YOLO26:
- Người dùng Ultralytics API / CLI: Không cần thay đổi — chỉ cần cập nhật tên model thành
yolo26n.pt(hoặcyolo26n-seg.pt,yolo26n-pose.pt,yolo26n-obb.pt) - Code hậu xử lý tùy chỉnh: Cập nhật để xử lý các hình dạng đầu ra mới —
(N, 300, 6)cho detection, cộng với dữ liệu cụ thể theo tác vụ cho segmentation, pose và OBB. Cũng lưu ý sự thay đổi định dạng box từxywhsangxyxy - Pipeline xuất: Kiểm tra phần khả năng tương thích định dạng cho định dạng mục tiêu của bạn
- TensorRT dưới 8.5.0: tính năng end-to-end bị tắt ở mọi độ chính xác — hãy nâng cấp TensorRT lên 8.5.0 hoặc mới hơn để giữ lại tính năng này
- Các bản xuất đã lượng tử hóa: TensorRT 10.3.0 với
quantize=8trên JetPack 6 và LiteRT vớiquantize=8hoặcquantize="w8a16", tự động vô hiệu hóa end-to-end — hãy xuất ở độ chính xác cao hơn để giữ lại tính năng này - Xuất FP16: Nếu bạn cần tất cả các đầu ra ở định dạng FP16, hãy xuất với
end2end=False— xem lý do output0 giữ nguyên FP32 - iOS / CoreML: Tính năng end-to-end được hỗ trợ hoàn toàn. Nếu bạn cần hỗ trợ Xcode Preview, hãy sử dụng
end2end=Falsevớinms=True - Thiết bị Edge (NCNN, RKNN): Các định dạng này tự động quay lại one-to-many, vì vậy hãy bao gồm NMS trong pipeline trên thiết bị của bạn
Kết luận#
Phát hiện end-to-end là mặc định trong YOLO26 và không cần thay đổi code nếu bạn sử dụng Ultralytics Python API hoặc CLI. Chỉ các pipeline hậu xử lý tùy chỉnh mới cần cập nhật để đọc đầu ra (N, 300, 6) mới và loại bỏ bước NMS — ngoại trừ các định dạng xuất quay về đầu ra one-to-many (như NCNN và RKNN), vốn vẫn yêu cầu NMS trên thiết bị. Để biết các benchmark chi tiết về tốc độ và độ chính xác trên tất cả các kích thước model, hãy xem trang model YOLO26, và để xem toàn bộ các tùy chọn và định dạng xuất, hãy tham khảo tài liệu Export mode.
Câu hỏi thường gặp#
Không. Các tùy chọn này loại trừ lẫn nhau. Nếu bạn thiết lập
nms=Truetrên một model end-to-end trong quá trình export, nó sẽ tự động bị ép buộc thànhnms=Falsekèm theo cảnh báo. Đầu end-to-end đã tự xử lý việc lọc các mục trùng lặp ở bên trong, vì vậy NMS bên ngoài là không cần thiết.Tuy nhiên,
end2end=Falsekết hợp vớinms=Truelà một cấu hình hợp lệ — nó tích hợp sẵn NMS truyền thống vào đồ thị xuất. Điều này có thể hữu ích cho việc xuất CoreML vì nó cho phép bạn sử dụng trực tiếp tính năng Preview trong Xcode với model detection.Tham số
max_det(mặc định: 300) thiết lập số lượng phát hiện tối đa được trả về trên mỗi ảnh. Bạn có thể điều chỉnh nó tại thời điểm suy luận hoặc xuất:model.predict("image.jpg", max_det=100) # fewer detections model.export(format="onnx", max_det=500) # more detections for dense scenesGiá trị này được tích hợp sẵn vào đồ thị đã xuất dưới dạng top-k của phần đầu, vì vậy
max_det=500làm rộng tensor đầu ra lên tới(1, 500, 6), được giới hạn bởi số lượng anchor.Đúng vậy, đó là định dạng đầu ra end-to-end dự kiến cho việc phát hiện: batch size bằng 1, tối đa 300 kết quả phát hiện, mỗi kết quả có 6 giá trị
[x1, y1, x2, y2, confidence, class_id]. Chỉ cần lọc theo ngưỡng độ tin cậy — không cần NMS.Đối với các tác vụ khác, hình dạng đầu ra sẽ khác:
Tác vụ Hình dạng đầu ra Mô tả Detection (1, 300, 6)[x1, y1, x2, y2, conf, class_id]Segmentation (1, 300, 38)+(1, 32, 160, 160)6 giá trị khung hình + 32 hệ số mặt nạ, cộng với một tensor mặt nạ nguyên mẫu Pose (1, 300, 57)6 giá trị khung hình + 17 điểm đặc trưng × 3 (x, y, khả năng hiển thị) OBB (1, 300, 7)6 giá trị khung hình + 1 góc xoay Bạn có thể kiểm tra từ Ultralytics Python API hoặc từ metadata của model ONNX đã xuất:
Kiểm tra xem mô hình có phải là end-to-end khôngfrom 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 enabledHai bước kiểm tra trả lời cho các câu hỏi khác nhau: metadata của ONNX ghi lại phần đầu đã được xuất, trong khi
predictor.model.end2endbáo cáo rằng đầu ra của backend đã được hậu xử lý và không cần NMS bên ngoài. Chúng không khớp đối với một model được xuất bằngend2end=False, nms=True, sử dụng phần đầu một-nhiều nhưng tích hợp NMS vào đồ thị và cũng xuất ra(1, 300, 6)— do đó, chỉ riêng cờ hoặc hình dạng đầu ra không thể xác định được phần đầu. Đối với các hình dạng tác vụ khác, hãy xem FAQ về hình dạng đầu ra.Có. Các biến thể tác vụ theo phong cách phát hiện của YOLO26 — detection, instance segmentation, pose estimation và oriented object detection (OBB) — đều hỗ trợ suy luận end-to-end theo mặc định. Cơ chế dự phòng
end2end=Falsecũng khả dụng trên các tác vụ này.Mỗi tác vụ mở rộng đầu ra phát hiện cơ sở với dữ liệu cụ thể theo tác vụ; hình dạng đầu ra của
yolo26n.pt,yolo26n-seg.pt,yolo26n-pose.ptvàyolo26n-obb.ptđược liệt kê trong Cách hoạt động của Phát hiện Đầu cuối.