Ultralytics YOLO27: 대기자 명단에 등록하세요.
Get Started
첫 YOLO 모델 학습하기·배포·레슨 10/10
강의초급

배포를 위한 내보내기

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.

학습 성과

학습된 모델을 배포 대상에 적합한 형식으로 내보내고, 동일 조건의 패리티 검사와 검증을 통해 내보낸 모델이 best.pt과 일치하는지 확인할 수 있습니다.

속성 과정
이미 사용법을 알고 계신다면, 간단히 요약해 드리겠습니다.
  1. yolo export model=runs/detect/pills_v1/weights/best.pt format=onnx — 여기서 시작합니다.

  2. Intel CPU에는 OpenVINO, NVIDIA GPU 및 Jetson에는 TensorRT, Apple 기기에는 CoreML, Android에는 LiteRT, Snapdragon NPU에는 QNN을 사용합니다.

  3. 같은 이미지에서 .pt과 내보낸 모델을 비교합니다. .pt 측에서 rect=False을 사용합니다.

  4. 두 모델을 학습 시 imgsz에서 검증합니다. mAP50-95가 일치해야 합니다.

실습형

예제: ONNX로 내보내기#

ONNX, TensorRT, CoreML, OpenVINO 등의 배포 형식이 나열된 Ultralytics Platform 모델 내보내기 탭

yolo export model=runs/detect/pills_v1/weights/best.pt format=onnx
PyTorch: 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).
dynamicFalse고정된 하나의 형태 대신 가변 입력 크기를 허용합니다.
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로 실행 시간을 측정해 배포 전에 실제 속도를 확인합니다.

대상 환경에 맞는 형식 선택#

Ultralytics Platform 라이프사이클: SAM 스마트 주석으로 주석을 추가하고, 클라우드 GPU에서 학습하며, 통합 파트너 로고와 함께 전 세계 리전에 배포합니다

목표형식참고 사항
범용 기본 형식: Linux, Windows, Mac을 사용하는 서버와 데스크톱onnxCPU 또는 GPU에서 ONNX Runtime을 사용합니다. 검증을 가장 빠르게 수행할 수 있는 내보내기 형식입니다.
NVIDIA GPU 및 Jetsonengine (TensorRT)NVIDIA에서 가장 빠르며, 장치에서 내보냅니다. TensorRT로 최적화를 참조하세요.
Intel CPU 및 iGPUopenvinoIntel 커널을 사용하면 CPU 속도가 실제로 향상됩니다. CPU에서의 OpenVINO를 참조하세요.
iPhone, iPad 및 Mac 앱coreml네이티브 방식이며 Apple Neural Engine을 사용합니다.
Android 및 기타 모바일 또는 임베디드 장치litert모바일에는 INT8을 권장합니다.
Snapdragon NPUqnnHexagon 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를 전달하세요.

정적 내보내기 모델은 imgsz를 무시함

증상: best.onnx에 imgsz=640을 전달했는데 로그에는 여전히 320x320라고 표시됩니다. 원인: 정적 내보내기 모델은 내보낼 때 설정한 입력 크기 하나만 사용합니다. 해결 방법: 실행할 크기(imgsz=640)로 내보내거나 dynamic=True를 사용해 내보내세요.

TensorRT 엔진은 장치별로 다름

A100에서 빌드한 .engine은 Jetson Orin에서 실행되지 않으며 TensorRT를 업그레이드하면 작동하지 않을 수도 있습니다. 실제로 실행할 TensorRT 버전을 사용해 대상 장치에서 내보내세요. ONNX는 이식할 수 있지만 엔진은 그렇지 않습니다.

별도 지정하지 않으면 INT8은 COCO8로 보정됨

INT8 내보내기에서 data을 생략하면 Ultralytics가 경고를 표시한 다음 기본 COCO8 샘플(여러분의 알약과 전혀 닮지 않은 이미지 8장)로 보정합니다. 직접 준비한 데이터를 전달하세요: model.export(format="litert", quantize=8, data="my_dataset/data.yaml").

배포 완료#

이제 학습된 best.pt, 기준 모델과 비교할 수 있는 검증 결과, 런타임용 내보내기 파일, 내보낸 모델이 원본과 일치한다는 증거를 갖추었습니다. 데이터 준비, 학습, 검증, 내보내기, 배포라는 전체 과정을 완료한 것입니다. 프로덕션 팀은 이 과정을 일정에 따라 실행합니다. Ultralytics YOLO in Production에서는 검증된 내보내기 파일을 바탕으로 최적화된 런타임, 추적 파이프라인, 다중 스트림 서빙 및 모니터링을 다룹니다.

사용해 보기

pills_v1/weights/best.pt을 ONNX로 내보낸 다음 parity.py과 val_export.py를 실행하세요. rect=False 없이 parity.py을 다시 실행하고 .pt 수가 어떻게 바뀌는지 기록하세요. 다음 네 가지 결과를 제출하세요: 일치하는 detection 수, 최대 박스 차이, 두 개의 mAP50-95 값, 실제 배포 대상에 필요한 형식과 그 이유를 설명하는 한 줄.

커밋
git add -A && git commit -m "feat(deploy): exported best.pt to onnx for production runtime"
완료 조건
다음 조건을 모두 충족하면 레슨을 완료한 것입니다.
  • runs/detect/pills_v1/weights/best.onnx이 존재하며 YOLO()을 통해 예측을 수행합니다.

  • rect=False을 사용하면 detection 수가 일치하고 최대 박스 차이가 1px 미만입니다.

  • 동일한 설정에서 ONNX와 .pt의 검증 mAP50-95가 일치하며, 선택한 대상 형식과 그 이유를 설명했습니다.

정답 보기
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
다음 단계

과정을 완료했습니다. 최종 퀴즈를 풀고 Train your first YOLO model 수료증을 받은 다음, Ultralytics YOLO in Production을 계속 학습하세요.