Ultralytics 의 종단 간 탐지 이해하기
소개
YOLO26 으로 이전 모델(예: YOLOv8 이나 YOLO11에서 YOLO26으로 업그레이드하는 경우, 가장 눈에 띄는 변화 중 하나는 Non-Maximum Suppression (NMS)의 제거입니다. 기존의 YOLO 수천 개의 중복 예측 결과를 생성하며, 이를 최종 탐지 결과로 필터링하기 위해 별도의 NMS 단계가 필요합니다. 이는 지연 시간을 증가시키고, 그래프 내보내기를 복잡하게 만들며, 서로 다른 하드웨어 플랫폼 간에 일관성 없는 동작을 보일 수 있습니다.
YOLO26은 다른 접근 방식을 취합니다. 이 모델은 외부 필터링 과정 없이 모델에서 직접 최종 탐지 결과를 출력합니다. 이를 ‘엔드투엔드 (end-to-end) 객체 탐지’라고 하며, 모든 YOLO26 모델에서 기본적으로 활성화되어 있습니다. 그 결과 배포 파이프라인이 간소화되고 지연 시간이 단축되며, CPU에서 추론 속도가 최대 43% 빨라집니다.
이 가이드에서는 변경된 사항, 코드 업데이트 필요 여부, 엔드투엔드 추론을 지원하는 내보내기 형식, 그리고 기존 YOLO 원활하게 마이그레이션하는 방법을 단계별로 안내합니다.
이러한 아키텍처 변경의 배경에 대해 더 자세히 알아보려면, YOLO26에서 NMS 제거한 이유를 다룬Ultralytics 게시물을 참고하시기 바랍니다.
간략한 요약
- Ultralytics 를 사용하시나요, 아니면 CLI 사용하시나요? 변경할 필요는 없습니다. 모델 이름만 다음과 같이 바꾸시면 됩니다.
yolo26n.pt. - 사용자 정의 추론 코드(ONNX , TensorRT 등)를 사용하고 계신가요? 후처리 기능을 업데이트하세요 — 이제 감지 결과가
(N, 300, 6)에서xyxy형식이며, NMS 하지 NMS . 다른 작업들은 추가 데이터(마스크 계수, 키포인트 또는 각도)를 덧붙입니다. - 내보내기 하시겠습니까? 대부분의 포맷은 기본적으로 엔드투엔드 출력을 지원합니다. 하지만 일부 포맷(NCNN, RKNN, PaddlePaddle, ExecuTorch, IMX, Edge TPU)은 지원되지 않는 연산자 제약 조건(예:
torch.topk)입니다.
종단 간 탐지 작동 원리
YOLO26은 훈련 과정에서 듀얼 헤드 아키텍처를 사용합니다. 두 헤드 모두 동일한 백본과 넥을 공유하지만, 출력을 생성하는 방식은 서로 다릅니다:
| 헤드 | 목적 | 감지 결과 | 후처리 |
|---|---|---|---|
| 일대일 (기본값) | 종단간 추론 | (N, 300, 6) | 신뢰 구간(하한값만) |
| 일대다 | 기존 YOLO | (N, nc + 4, 8400) | NMS 필요합니다 |
위의 도형들은 탐지용입니다. 다른 작업들은 탐지 결과마다 추가 데이터를 포함하여 일대일 출력을 확장합니다:
| 작업 | 전체 결과 | 추가 정보 |
|---|---|---|
| 객체 탐지 | (N, 300, 6) | — |
| Segmentation | (N, 300, 6 + nm) + 프로토 (N, nm, H, W) | nm 마스크 계수 (기본값 32) |
| 포즈 | (N, 300, 57) | 17개 키포인트 × 3 (x, y, 가시성) |
| OBB | (N, 300, 7) | 회전 각도 |
훈련 과정에서 두 헤드 모두 동시에 작동합니다. 일대다(one-to-many) 헤드는 더 풍부한 학습 신호를 제공하는 반면, 일대일(one-to-one) 헤드는 중복되지 않는 명확한 예측 결과를 도출하는 방법을 학습합니다. 훈련 과정에서 추론 및 export, 오직 일대일 지도 기본적으로 활성화되어 있으며, 이미지당 최대 300개의 탐지 결과를 다음 형식으로 생성합니다. [x1, y1, x2, y2, confidence, class_id].
전화를 걸면 model.fuse(), 이 모델은 더 빠른 추론을 위해 Conv 및 BatchNorm 레이어를 접어 처리하며, 엔드투엔드 모델의 경우 원-투-매니(one-to-many) 헤드를 제거하여 모델 크기와 FLOPs를 줄입니다. 듀얼 헤드 아키텍처에 대한 자세한 내용은 YOLO26 모델 페이지.
코드를 변경해야 하나요?
Ultralytics Python 또는 CLI 사용
변경할 필요가 없습니다. 표준 Ultralytics Python 를 사용하거나 CLI를 사용하시면 예측, 검증, 내보내기 등 모든 작업이 자동으로 처리되며, 모델 전체를 즉시 활용할 수 있습니다.
Ultralytics 를 사용할 때 코드 변경이 필요하지 않습니다
from ultralytics import YOLO
# Load a YOLO26 model
model = YOLO("yolo26n.pt")
# Predict — no NMS step, no code changes
results = model.predict("image.jpg")
yolo predict model=yolo26n.pt source=image.jpg
사용자 정의 추론 코드 사용
네, 출력 형식이 다릅니다. 만약 YOLOv8 또는 YOLO11 (예를 들어, ONNX 이나 TensorRT)을 사용하는 경우, 새로운 출력 형식을 처리할 수 있도록 업데이트해야 합니다:
| YOLOv8 YOLO11 | YOLO26 (종단간) | |
|---|---|---|
| 검출 출력 | (N, nc + 4, 8400) | (N, 300, 6) |
| 상자 형식 | xywh (중심 x, 중심 y, 너비, 높이) | xyxy (왼쪽 위 x, 왼쪽 위 y, 오른쪽 아래 x, 오른쪽 아래 y) |
| 레이아웃 | 앵커별 박스 좌표 및 클래스 점수 | [x1, y1, x2, y2, conf, class_id] |
| NMS | 예 | 아니요 |
| 후처리 | NMS 신뢰도 필터 | 신뢰도 필터만 |
분할, 자세, OBB 작업의 경우, YOLO26은 각 탐지 결과에 작업별 데이터를 추가합니다. 자세한 내용은 위의 출력 형상 표를 참조하십시오.
어디 N ~는 배치 크기 및 nc 는 수업 수입니다(예: 80은 COCO)입니다.
엔드투엔드 모델을 사용하면 후처리 과정이 훨씬 간단해집니다. 예를 들어, ONNX 사용할 때:
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 기반 후처리 코드를 재사용하려는 경우), 다음을 설정하여 언제든지 1대다(one-to-many) 헤드로 전환할 수 있습니다. 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)
yolo predict model=yolo26n.pt source=image.jpg end2end=False
yolo val model=yolo26n.pt data=coco.yaml end2end=False
yolo export model=yolo26n.pt format=onnx end2end=False
내보내기 형식 호환성
대부분의 내보내기 형식은 기본적으로 종단 간 추론을 지원하며, 여기에는 다음이 포함됩니다. ONNX, TensorRT, CoreML, OpenVINO, TFLite, TF.js 및 MNN.
다음 형식은 종단 간(end-to-end)을 지원하지 않으며, 자동으로 일대다(one-to-many) 헤드로 전환됩니다: NCNN, RKNN, PaddlePaddle, ExecuTorch, IMX 및 Edge TPU.
엔드투엔드(end-to-end)가 지원되지 않을 경우 어떻게 되나요?
이러한 형식 중 하나로 내보낼 때, Ultralytics 일대다 헤드로 전환하고 경고 메시지를 기록합니다. NMS 수동 작업은 필요하지 않습니다. 즉, YOLOv8 이나 YOLO11과 마찬가지로, 추론 파이프라인에 NMS가 필요하다는 뜻입니다.
TensorRT INT8
TensorRT 엔드투엔드를 지원하지만, 이는 자동 비활성화 다음으로 내보낼 때 int8=True TensorRT .3.0 TensorRT 버전에서
정확도와 속도의 상충 관계
종단 간 탐지 기능은 정확도에 미치는 영향을 최소화하면서도 배포 측면에서 상당한 이점을 제공합니다:
| 지표 | 종단 간 (기본값) | 일대다 + NMSend2end=False) |
|---|---|---|
| CPU 속도 | 최대 43% 더 빠름 | 기준선 |
| mAP | 약 0.5 mAP | YOLO11 동등하거나 그 이상 |
| 후처리 | 신뢰도 필터만 | 전체 NMS |
| 배포 복잡성 | 미니멀 | NMS 필요합니다 |
대부분의 실제 응용 분야에서, 약 0.5 mAP 차이는 미미하며, 특히 속도와 편의성 측면에서 얻는 이점을 고려하면 더욱 그렇습니다. 만약 최고의 정확도를 최우선으로 생각한다면, 언제든지 다음을 사용하여 일대다 헤드로 되돌릴 수 있습니다. end2end=False.
모든 모델 크기(n, s, m, l, x)에 대한 상세한 벤치마크 결과는 YOLO26 성능 지표를 참조하십시오.
YOLOv8 YOLO11에서 마이그레이션하기
기존 프로젝트를 YOLO26으로 업그레이드하는 경우, 원활한 전환을 위해 다음 체크리스트를 참고하시기 바랍니다:
- Ultralytics / CLI 여러분: 변경할 내용은 없습니다. 모델 이름만 다음과 같이 업데이트해 주세요.
yolo26n.pt(또는yolo26n-seg.pt,yolo26n-pose.pt,yolo26n-obb.pt) - 사용자 정의 후처리 코드: 새로운 출력 형식을 처리하기 위한 업데이트 —
(N, 300, 6)탐지를 위한 데이터와 더불어, 특정 작업을 위한 데이터 분할, pose및 OBB. 또한 상자 형식이xywh에서xyxy - 내보내기 파이프라인: 대상 형식에 대해서는 위의 ‘형식 호환성’ 섹션을 확인하십시오
- TensorRT INT8: 엔드투엔드 지원을 받으려면 TensorRT 10.3.0 이상인지 확인하십시오.
- FP16 내보내기: 모든 출력을 FP16 형식으로 내보내려면 다음 명령을 사용하여 내보내십시오.
end2end=False— 참조 왜 output0이 FP32로 유지되는가 - iOS CoreML: 엔드투엔드(End-to-end) 기능이 완벽하게 지원됩니다. Xcode Preview 지원이 필요한 경우 다음을 사용하십시오.
end2end=False와 함께nms=True - 엣지 디바이스(NCNN, RKNN): 이러한 형식은 자동으로 일대다(one-to-many) 방식으로 전환되므로, 온디바이스 NMS 포함시켜야 합니다.
FAQ
end2end=True와 nms=True를 함께 사용할 수 있나요?
아니요. 이 옵션들은 서로 배타적입니다. 만약 nms=True ~ 동안 종단간 모델에 따라 export, 그러면 자동으로 nms=False 단, 한 가지 주의할 점이 있습니다. 엔드투엔드 헤드는 이미 내부적으로 중복 필터링을 처리하므로, 별도의 NMS 필요하지 NMS .
그러나, end2end=False ~와 결합하여 nms=True 유효한 구성입니다. 이 구성은 기존 NMS 내보내기 그래프 NMS 통합합니다. 이는 다음과 같은 경우에 유용할 수 있습니다. CoreML 수출하는 이유는 감지 모델을 Xcode의 미리보기 기능과 직접 연동하여 사용할 수 있기 때문입니다.
엔드투엔드 모델에서 max_det 매개변수는 무엇을 제어하나요?
에 지정되어 있습니다. max_det 매개변수(기본값: 300)는 1:1 헤드(one-to-one head)가 이미지당 출력할 수 있는 최대 탐지 수를 설정합니다. 이 값은 추론 시 또는 내보내기 시에 조정할 수 있습니다:
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. 이 값을 높일 수는 있지만, 1대1 헤드는 훈련 과정에서 최대 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개의 마스크 계수, 그리고 프로토타입 마스크 tensor |
| 포즈 | (1, 300, 57) | 6개의 박스 값 + 17개의 키포인트 × 3 (x, y, 가시성) |
| OBB | (1, 300, 7) | 6개의 박스 값 + 1개의 회전 각도 |
내보낸 모델이 엔드투엔드 모델인지 어떻게 확인할 수 있나요?
Ultralytics Python 사용하거나 내보낸 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
import onnxruntime as ort
session = ort.InferenceSession("yolo26n.onnx")
metadata = session.get_modelmeta().custom_metadata_map
print(metadata.get("end2end")) # 'True' if end-to-end is enabled
또는 출력 형식을 확인해 보세요 — 종단간 탐지 모델은 (1, 300, 6)반면, 기존 모델들은 (1, nc + 4, 8400). 다른 작업 형태에 대해서는 출력 형상 FAQ.
세그멘테이션, 포즈 추정, OBB(최대 바운딩 박스) 작업에 대해 엔드투엔드(end-to-end) 방식이 지원되나요?
네. 모든 YOLO26 작업 변형 — 감지, 분할, 포즈 추정및 지향 객체 탐지(OBB) — 기본적으로 종단 간 추론을 지원합니다. end2end=False 폴백 기능은 모든 작업에서도 사용할 수 있습니다.
각 태스크는 기본 감지 결과에 해당 태스크 고유의 데이터를 추가합니다:
| 작업 | 모델 | 전체 결과 |
|---|---|---|
| 객체 탐지 | yolo26n.pt | (N, 300, 6) |
| Segmentation | yolo26n-seg.pt | (N, 300, 38) + 프로토 (N, 32, 160, 160) |
| 포즈 | yolo26n-pose.pt | (N, 300, 57) |
| OBB | yolo26n-obb.pt | (N, 300, 7) |