배포를 위한 내보내기
best.pt를 ONNX, OpenVINO, TensorRT, CoreML, LiteRT 또는 QNN으로 내보낸 다음, 배포 전에 내보낸 모델과 PyTorch 모델이 일치하는지 확인합니다.
best.pt을 실행하려면 Python과 PyTorch가 필요하지만, 휴대폰, 브라우저, Jetson, 프로덕션 서버에는 보통 해당 환경이 설치되어 있지 않습니다. Export 모드는 한 번의 호출로 해당 런타임에서 사용할 수 있는 독립 실행형 파일로 모델을 변환합니다. 다만 파일이 로드된다고 해서 결과가 반드시 올바른 것은 아니며, 부주의하게 비교하면 올바른 내보내기 결과를 잘못된 것으로 판단하거나 잘못된 결과를 놓칠 수 있습니다.
이 강의에서는 알약 모델을 ONNX로 내보내고, 동일한 YOLO API로 실행하고, 설정을 맞춘 상태에서 박스와 검증 mAP를 비교해 PyTorch와 일치하는지 확인합니다. 또한 대상 환경에 맞는 형식을 선택합니다: ONNX, OpenVINO, TensorRT, CoreML, LiteRT 또는 QNN.
실습형
예제: ONNX로 내보내기#

yolo export model=runs/detect/pills_v1/weights/best.pt format=onnxPyTorch: starting from 'runs/detect/pills_v1/weights/best.pt' with input shape (1, 3, 320, 320) BCHW and output shape(s) (1, 5, 2100) (5.2 MB)
ONNX: export success ✅ 0.9s, saved as 'runs/detect/pills_v1/weights/best.onnx' (9.3 MB)
Predict: yolo predict task=detect model=runs/detect/pills_v1/weights/best.onnx imgsz=320
Validate: yolo val task=detect model=runs/detect/pills_v1/weights/best.onnx imgsz=320 data=my_dataset/data.yaml각 줄의 의미:
input shape (1, 3, 320, 320): 이미지 하나, 컬러 채널 3개, 고정 크기 320×320 정사각형입니다. 학습 시 사용한imgsz이 파일에 내장되어 있습니다.output shape(s) (1, 5, 2100): 후보 박스 2,100개마다 박스 값 4개와 클래스 점수 1개를 출력합니다. 기본적으로 NMS는 그래프 외부에서 실행됩니다.9.3 MB: ONNX 파일은 FP32 가중치를 저장하므로 FP16.pt보다 용량이 큽니다.Predict:/Validate:: 내보낸 파일에 바로 사용할 수 있는 명령이며, 올바른imgsz가 이미 지정되어 있습니다.
몇 가지 인수만으로 대부분의 요구 사항을 처리할 수 있습니다. 나머지는 ONNX 통합 가이드에서 확인하세요.
| 인수 | 기본값 | 용도 |
|---|---|---|
imgsz | 학습 크기 | 다른 고정 입력 크기로 내보냅니다(예: imgsz=640). |
dynamic | False | 고정된 하나의 형태 대신 가변 입력 크기를 허용합니다. |
quantize | 없음(FP32) | FP16 가중치에는 16을 사용합니다(yolo26n.onnx은 9.5MB에서 4.8MB로 줄어듭니다). 해당 형식에서 지원하는 경우 INT8에는 8를 사용합니다. |
nms | 없음 | nms=True은 그래프에 NMS를 포함하므로 런타임에서 최종 박스를 반환합니다. |
예제: 내보낸 모델이 일치하는지 확인#
YOLO 클래스는 내보낸 파일도 로드하므로 앞서 작성한 predict 코드를 수정 없이 사용할 수 있습니다. 동일한 검증 이미지에서 두 파일을 비교합니다:
from ultralytics import YOLO
image = "my_dataset/images/val/Frame_144.jpg"
pt = YOLO("runs/detect/pills_v1/weights/best.pt")(image, rect=False, verbose=False)[0] # square input, like ONNX
onnx = YOLO("runs/detect/pills_v1/weights/best.onnx")(image, verbose=False)[0]
print(f"pt: {len(pt.boxes)} pills, mean conf {pt.boxes.conf.mean():.3f}")
print(f"onnx: {len(onnx.boxes)} pills, mean conf {onnx.boxes.conf.mean():.3f}")
print(f"max box difference: {(pt.boxes.xyxy - onnx.boxes.xyxy).abs().max():.4f} px")pt: 25 pills, mean conf 0.870
onnx: 25 pills, mean conf 0.870
max box difference: 0.0002 px개수와 신뢰도가 같고, 박스도 픽셀 일부 수준까지 동일합니다. 이제 더 강력한 검사인 전체 데이터 분할의 검증을 수행합니다:
from ultralytics import YOLO
pt = YOLO("runs/detect/pills_v1/weights/best.pt").val(data="my_dataset/data.yaml", rect=False, verbose=False)
onnx = YOLO("runs/detect/pills_v1/weights/best.onnx").val(data="my_dataset/data.yaml", verbose=False)
print(f".pt mAP50-95 {pt.box.map:.4f}")
print(f".onnx mAP50-95 {onnx.box.map:.4f}").pt mAP50-95 0.6570
.onnx mAP50-95 0.6570동일합니다. (.pt 파일의 기본 사각형 검증 점수는 0.659입니다. 이는 내보내기 때문이 아니라 입력 패딩에 따른 작은 차이입니다.)
결과가 일치하면 대상 기기에서 yolo benchmark로 실행 시간을 측정해 배포 전에 실제 속도를 확인합니다.
대상 환경에 맞는 형식 선택#

| 목표 | 형식 | 참고 사항 |
|---|---|---|
| 범용 기본 형식: Linux, Windows, Mac을 사용하는 서버와 데스크톱 | onnx | CPU 또는 GPU에서 ONNX Runtime을 사용합니다. 검증을 가장 빠르게 수행할 수 있는 내보내기 형식입니다. |
| NVIDIA GPU 및 Jetson | engine (TensorRT) | NVIDIA에서 가장 빠르며, 장치에서 내보냅니다. TensorRT로 최적화를 참조하세요. |
| Intel CPU 및 iGPU | openvino | Intel 커널을 사용하면 CPU 속도가 실제로 향상됩니다. CPU에서의 OpenVINO를 참조하세요. |
| iPhone, iPad 및 Mac 앱 | coreml | 네이티브 방식이며 Apple Neural Engine을 사용합니다. |
| Android 및 기타 모바일 또는 임베디드 장치 | litert | 모바일에는 INT8을 권장합니다. |
| Snapdragon NPU | qnn | Hexagon HTP 가속을 지원하며, 기본적으로 16비트 활성화와 함께 INT8 가중치를 사용합니다. name으로 HTP 아키텍처를 선택하세요. |
| 웹 브라우저 | ONNX Runtime Web을 사용하는 onnx | 더 작은 모델도 충분히 사용할 수 있습니다: n 및 s |
from ultralytics import YOLO
model = YOLO("runs/detect/pills_v1/weights/best.pt")
model.export(format="onnx") # 크로스 플랫폼: ONNX Runtime
model.export(format="openvino") # Intel CPU / iGPU
model.export(format="engine", quantize=16) # NVIDIA TensorRT, FP16 (대상 GPU에서 실행)
model.export(format="coreml") # Apple iOS / macOS
model.export(format="litert", quantize=8, data="my_dataset/data.yaml") # Android / 엣지, INT8
model.export(format="qnn", name="73", data="my_dataset/data.yaml") # Qualcomm Snapdragon NPU (HTP v73); 자체 데이터로 보정하세요각 내보내기 파일은 가중치 파일과 같은 위치에 저장됩니다: best.onnx, best_openvino_model/, best.engine 등입니다. 최종적으로 다른 형식을 사용하더라도 먼저 ONNX를 사용해 보세요. 검증이 가장 빠르고 여러 다른 도구 체인에서 입력으로 사용되기 때문입니다. 배포 옵션 가이드에서는 모든 형식을 비교하고, 배포 대상 선택에서는 선택 과정을 안내합니다.
모델 양자화는 정밀도를 낮춰 크기와 속도를 개선합니다. FP16 (quantize=16)은 정확도를 거의 그대로 유지하면서 파일 크기를 절반으로 줄입니다. INT8 (quantize=8)은 크기가 더 작고 속도도 더 빠르지만, 보정 이미지가 필요합니다. 보정 이미지는 내보내기 과정에서 값의 범위를 선택하기 위해 사용하는 대표 프레임입니다. Ultralytics는 최소 300장을 권장합니다. INT8 모델은 배포 전에 반드시 검증하세요. 정확도 손실은 모델과 보정 데이터 세트에 따라 미미할 수도, 클 수도 있습니다.
이런 실수는 피하세요#
증상: .pt 모델은 Frame_144.jpg에서 알약 35개를 찾지만 ONNX 파일은 25개를 찾아 내보내기가 잘못된 것처럼 보입니다. 원인: PyTorch 추론은 각 이미지를 스트라이드에 맞는 최소 크기의 직사각형(이 16:9 프레임에서는 192×320)으로 패딩하지만, 정적 ONNX 모델은 항상 320×320 정사각형을 입력으로 사용합니다. 입력이 다르면 낮은 신뢰도의 탐지 결과도 달라집니다. 해결 방법: parity.py처럼 비교할 때 .pt 모델에 rect=False를 전달하세요.
증상: best.onnx에 imgsz=640을 전달했는데 로그에는 여전히 320x320라고 표시됩니다. 원인: 정적 내보내기 모델은 내보낼 때 설정한 입력 크기 하나만 사용합니다. 해결 방법: 실행할 크기(imgsz=640)로 내보내거나 dynamic=True를 사용해 내보내세요.
A100에서 빌드한 .engine은 Jetson Orin에서 실행되지 않으며 TensorRT를 업그레이드하면 작동하지 않을 수도 있습니다. 실제로 실행할 TensorRT 버전을 사용해 대상 장치에서 내보내세요. ONNX는 이식할 수 있지만 엔진은 그렇지 않습니다.
INT8 내보내기에서 data을 생략하면 Ultralytics가 경고를 표시한 다음 기본 COCO8 샘플(여러분의 알약과 전혀 닮지 않은 이미지 8장)로 보정합니다. 직접 준비한 데이터를 전달하세요: model.export(format="litert", quantize=8, data="my_dataset/data.yaml").
배포 완료#
이제 학습된 best.pt, 기준 모델과 비교할 수 있는 검증 결과, 런타임용 내보내기 파일, 내보낸 모델이 원본과 일치한다는 증거를 갖추었습니다. 데이터 준비, 학습, 검증, 내보내기, 배포라는 전체 과정을 완료한 것입니다. 프로덕션 팀은 이 과정을 일정에 따라 실행합니다. Ultralytics YOLO in Production에서는 검증된 내보내기 파일을 바탕으로 최적화된 런타임, 추적 파이프라인, 다중 스트림 서빙 및 모니터링을 다룹니다.
정답 보기
from ultralytics import YOLO
# Train
model = YOLO("yolo26n.pt")
model.train(data="my_dataset/data.yaml", epochs=10, imgsz=320, name="pills_e2e")
# Validate
metrics = model.val()
print(f"mAP50-95 = {metrics.box.map:.3f}") # 0.659
# Export
model.export(format="onnx")parity.py: pt 25 pills, onnx 25 pills, max box difference 0.0002 px
without rect: pt 35 pills (192x320 input) vs onnx 25 (320x320): input mismatch, not an export bug
val_export.py: .pt 0.6570, .onnx 0.6570
Target: Intel laptop CPU -> openvino, for faster CPU inference than ONNX Runtime