YOLO Vision 2026:

Ultralytics를 사용하여 비 YOLO PyTorch 모델을 내보내는 방법#

Ultralytics는 단일한 일관된 인터페이스 뒤에서 여러 백엔드를 래핑하는 독립형 내보내기 유틸리티를 ultralytics.utils.export를 통해 제공합니다. 각 백엔드를 따로 배우지 않고도 timm 이미지 모델, torchvision 분류기 및 감지기, 또는 사용자 정의 아키텍처를 포함한 모든 torch.nn.ModuleONNX, TorchScript, OpenVINO, CoreML, NCNN, PaddlePaddle, MNN, ExecuTorch, TensorFlow SavedModel으로 내보낼 수 있습니다.

PyTorch 모델을 프로덕션에 배포하는 것은 대개 대상마다 다른 내보내기 도구를 저글링해야 함을 의미합니다. ONNX용 torch.onnx.export, Apple 기기용 coremltools, TensorFlow용 onnx2tf, NCNN용 pnnx 등이 그렇습니다. 각 도구는 고유한 API, 종속성 특이성, 출력 규칙을 가지고 있습니다. 이러한 유틸리티는 이를 단일 호출 패턴으로 압축합니다.

비 YOLO 모델 내보내기에 Ultralytics를 사용해야 하는 이유는 무엇입니까?#

  • 10개 형식에 걸친 단일 API: 수십 개의 호출 규칙 대신 하나의 호출 규칙만 배우면 됩니다.
  • 공유 유틸리티 서피스: 내보내기 도우미는 ultralytics.utils.export에 위치하므로, 백엔드 패키지가 설치되면 형식 전반에 걸쳐 동일한 호출 패턴을 유지할 수 있습니다.
  • YOLO 내보내기와 동일한 코드 경로: Ultralytics YOLO 내보내기를 구동하는 것과 동일한 도우미가 사용됩니다.
  • FP16 및 INT8 양자화 지원(OpenVINO, CoreML, MNN, NCNN)이 내장되어 있습니다.
  • CPU에서 작동: 내보내기 단계 자체에 GPU가 필요하지 않으므로 모든 노트북에서 로컬로 실행할 수 있습니다.

빠른 시작#

가장 빠른 방법은 YOLO 코드 없이, 그리고 pip install ultralytics onnx timm 외의 다른 설정 없이 두 줄의 코드로 ONNX에 내보내는 것입니다:

import timm
import torch

from ultralytics.utils.export import torch2onnx

model = timm.create_model("resnet18", pretrained=True).eval()
torch2onnx(model, torch.randn(1, 3, 224, 224), output_file="resnet18.onnx")

지원되는 내보내기 형식#

torch2* 함수는 표준 torch.nn.Module과 예제 입력 텐서를 취합니다. MNN, TF SavedModel, TF Frozen Graph는 중간 ONNX 또는 Keras 아티팩트를 거칩니다. 두 경우 모두 YOLO 관련 속성이 필요하지 않습니다.

형식함수설치출력
ONNXtorch2onnx()pip install onnx.onnx 파일
TorchScripttorch2torchscript()PyTorch에 포함됨.torchscript 파일
OpenVINOtorch2openvino()pip install openvino_openvino_model/ 디렉토리
CoreMLtorch2coreml()pip install coremltools.mlpackage
TF SavedModelonnx2saved_model()아래의 상세 요구사항 참조_saved_model/ 디렉토리
TF Frozen Graphkeras2pb()아래의 상세 요구사항 참조.pb 파일
NCNNtorch2ncnn()pip install ncnn pnnx_ncnn_model/ 디렉토리
MNNonnx2mnn()pip install MNN.mnn 파일
PaddlePaddletorch2paddle()pip install paddlepaddle x2paddle_paddle_model/ 디렉토리
ExecuTorchtorch2executorch()pip install executorch_executorch_model/ 디렉토리
중간 형식으로서의 ONNX

MNN, TF SavedModel, TF Frozen Graph 내보내기는 중간 단계로 ONNX를 거칩니다. 먼저 ONNX로 내보낸 후 변환하세요.

메타데이터 임베딩

여러 내보내기 함수는 형식이 지원하는 경우 내보낸 아티팩트에 사용자 정의 키-값 쌍을 임베드하는 선택적 metadata 사전(예: torch2torchscript(..., metadata={"author": "me"}))을 허용합니다.

단계별 예시#

아래의 모든 예시는 동일한 설정을 사용하며, 평가 모드(evaluation mode)인 timm의 사전 훈련된 ResNet-18을 사용합니다:

import timm
import torch

model = timm.create_model("resnet18", pretrained=True).eval()
im = torch.randn(1, 3, 224, 224)
내보내기 전 항상 `model.eval()`을 호출하십시오

드롭아웃, 배치 정규화 및 기타 학습 전용 레이어는 추론 중에 다르게 동작합니다. .eval()을 건너뛰면 잘못된 출력을 가진 내보내기가 생성됩니다.

ONNX로 내보내기#

from ultralytics.utils.export import torch2onnx

torch2onnx(model, im, output_file="resnet18.onnx")

동적 배치 크기의 경우 dynamic 사전을 전달하세요:

torch2onnx(model, im, output_file="resnet18_dyn.onnx", dynamic={"images": {0: "batch_size"}})

기본 opset은 14이고 기본 입력 이름은 "images"입니다. opset, input_names, output_names 인수를 사용하여 재정의할 수 있습니다.

TorchScript로 내보내기#

추가 종속성이 필요하지 않습니다. 내부적으로 torch.jit.trace을 사용합니다.

from ultralytics.utils.export import torch2torchscript

torch2torchscript(model, im, output_file="resnet18.torchscript")

OpenVINO로 내보내기#

from ultralytics.utils.export import torch2openvino

ov_model = torch2openvino(model, im, output_dir="resnet18_openvino_model")

디렉토리에는 고정 이름의 model.xmlmodel.bin 쌍이 포함되어 있습니다:

resnet18_openvino_model/
├── model.xml
└── model.bin

동적 입력 형태의 경우 dynamic=True, FP16의 경우 quantize=16, INT8 양자화의 경우 quantize=8를 전달하세요. INT8에는 추가로 calibration_dataset 인수가 필요합니다.

openvino>=2024.0.0(또는 macOS 15.4+의 경우 >=2025.2.0)과 torch>=2.1가 필요합니다.

CoreML로 내보내기#

import coremltools as ct

from ultralytics.utils.export import torch2coreml

inputs = [ct.TensorType("input", shape=(1, 3, 224, 224))]
ct_model = torch2coreml(model, inputs, im, classifier_names=None, output_file="resnet18.mlpackage")

분류 모델의 경우, CoreML 모델에 분류 헤드를 추가하려면 클래스 이름 목록을 classifier_names에 전달하세요.

coremltools>=9.0, torch>=1.11, numpy<=2.3.5가 필요합니다. Windows에서는 지원되지 않습니다.

`BlobWriter not loaded` 오류

coremltools>=9.0은 macOS 및 Linux용 Python 3.10–3.13 휠을 제공합니다. 최신 Python 버전에서는 네이티브 C extensions 로드가 실패합니다. CoreML 내보내기에는 Python 3.10–3.13을 사용하세요.

TensorFlow SavedModel로 내보내기#

TF SavedModel 내보내기는 중간 단계로 ONNX를 거칩니다:

from ultralytics.utils.export import onnx2saved_model, torch2onnx

torch2onnx(model, im, output_file="resnet18.onnx")
keras_model = onnx2saved_model("resnet18.onnx", output_dir="resnet18_saved_model")

이 함수는 Keras 모델을 반환하며 출력 디렉토리 내에 TFLite 파일(.tflite)도 생성합니다:

resnet18_saved_model/
├── saved_model.pb
├── variables/
├── resnet18_float32.tflite
├── resnet18_float16.tflite
└── resnet18_int8.tflite

요구 사항:

  • tensorflow>=2.0.0,<=2.19.0
  • onnx2tf>=1.26.3,<1.29.0
  • tf_keras<=2.19.0
  • sng4onnx>=1.0.1
  • onnx_graphsurgeon>=0.3.26
  • macOS의 ai-edge-litert>=1.2.0,<1.4.0 (기타 플랫폼의 경우 ai-edge-litert>=1.2.0)
  • onnxslim>=0.1.82
  • onnx>=1.12.0,<2.0.0
  • protobuf>=5

TensorFlow Frozen Graph로 내보내기#

위의 SavedModel 내보내기에 이어, 반환된 keras_model을 고정된 .pb 그래프로 변환합니다:

from pathlib import Path

from ultralytics.utils.export import keras2pb

keras2pb(keras_model, output_file=Path("resnet18_saved_model/resnet18.pb"))

NCNN으로 내보내기#

from ultralytics.utils.export import torch2ncnn

torch2ncnn(model, im, output_dir="resnet18_ncnn_model")

디렉터리에는 고정된 이름의 param 및 bin 파일과 Python 래퍼가 포함되어 있습니다:

resnet18_ncnn_model/
├── model.ncnn.param
├── model.ncnn.bin
└── model_ncnn.py

torch2ncnn()은 첫 사용 시 ncnnpnnx를 확인합니다.

MNN으로 내보내기#

MNN 내보내기는 입력으로 ONNX 파일이 필요합니다. 먼저 ONNX로 내보낸 후 변환하십시오:

from ultralytics.utils.export import onnx2mnn, torch2onnx

torch2onnx(model, im, output_file="resnet18.onnx")
onnx2mnn("resnet18.onnx", output_file="resnet18.mnn")

FP16용 quantize=16과 INT8 양자화용 quantize=8을 지원합니다. MNN>=2.9.6torch>=1.10이 필요합니다.

PaddlePaddle로 내보내기#

from ultralytics.utils.export import torch2paddle

torch2paddle(model, im, output_dir="resnet18_paddle_model")

디렉터리에는 PaddlePaddle 모델 및 매개변수 파일이 포함되어 있습니다:

resnet18_paddle_model/
├── model.pdmodel
└── model.pdiparams

x2paddle과 플랫폼에 맞는 PaddlePaddle 배포판이 필요합니다:

  • CUDA상의 paddlepaddle-gpu>=3.0.0,<3.3.0
  • ARM64 CPU상의 paddlepaddle==3.0.0
  • 기타 CPU상의 paddlepaddle>=3.0.0,<3.3.0

NVIDIA Jetson에서는 지원되지 않습니다.

ExecuTorch로 내보내기#

from ultralytics.utils.export import torch2executorch

torch2executorch(model, im, output_dir="resnet18_executorch_model")

내보낸 .pte 파일은 출력 디렉토리 내에 저장됩니다:

resnet18_executorch_model/
└── model.pte

torch>=2.9.0과 일치하는 ExecuTorch 런타임(pip install executorch)이 필요합니다. 런타임 사용법은 ExecuTorch 통합을 참조하세요.

내보낸 모델 검증#

내보내기가 완료된 후 배포하기 전에 원래 PyTorch 모델과의 수치적 일치성을 확인하십시오. ultralytics.nn.backendsONNXBackend을 사용한 빠른 스모크 테스트는 출력을 비교하고 트레이싱 또는 양자화 오류를 조기에 감지합니다:

import numpy as np
import timm
import torch

from ultralytics.nn.backends import ONNXBackend

model = timm.create_model("resnet18", pretrained=True).eval()
im = torch.randn(1, 3, 224, 224)
with torch.no_grad():
    pytorch_output = model(im).numpy()

onnx_model = ONNXBackend("resnet18.onnx", device=torch.device("cpu"))
onnx_output = onnx_model(im)[0]

diff = np.abs(pytorch_output - onnx_output).max()
print(f"Max difference: {diff:.6f}")  # typically ~1e-5, well under 1e-4 for FP32
예상 오차

FP32 내보내기의 경우, 최대 절대 오차는 일반적으로 1e-5 정도이며 1e-4보다 훨씬 아래로 유지되어야 합니다. 더 큰 차이는 지원되지 않는 연산, 잘못된 입력 형태, 또는 eval 모드가 아닌 모델을 가리킵니다. FP16 및 INT8 내보내기는 더 느슨한 허용 오차를 가집니다. 임의의 텐서 대신 실제 데이터로 검증하세요.

다른 런타임의 경우 입력 텐서 이름이 다를 수 있습니다. 예를 들어 OpenVINO는 모델의 forward 인수 이름을 사용하고(일반 모델의 경우 대개 x), torch2onnx은 기본적으로 "images"가 됩니다.

알려진 제한 사항#

  • 다중 입력 지원은 불균일합니다: torch2onnxtorch2openvino은 여러 입력이 있는 모델에 대해 튜플 또는 예제 텐서 리스트를 허용합니다. torch2torchscript, torch2coreml, torch2ncnn, torch2paddle, torch2executorch은 단일 입력 텐서를 가정합니다.
  • ExecuTorch에는 flatc이 필요합니다: ExecuTorch 런타임은 FlatBuffers 컴파일러가 필요합니다. macOS에서는 brew install flatbuffers, Ubuntu에서는 apt install flatbuffers-compiler로 설치하세요.
  • Ultralytics를 통한 추론 불가: 내보낸 비-YOLO 모델은 추론을 위해 YOLO()을 통해 다시 로드할 수 없습니다. 각 형식의 네이티브 런타임(ONNX Runtime, OpenVINO Runtime 등)을 사용하세요.
  • YOLO 전용 형식: AxeleraSony IMX500 내보내기는 YOLO 전용 모델 속성이 필요하며 일반 모델에는 사용할 수 없습니다.
  • 플랫폼 전용 형식: TensorRT에는 NVIDIA GPU가 필요합니다. RKNN에는 rknn-toolkit2 SDK(Linux 전용)가 필요합니다. Edge TPU에는 edgetpu_compiler 바이너리(Linux 전용)가 필요합니다.

결론#

이러한 유틸리티는 하나의 일관된 API를 통해 일반 torch.nn.Module에서 배포 준비가 완료된 ONNX, OpenVINO, CoreML, TensorFlow 또는 모바일 런타임 아티팩트로 모든 PyTorch 모델을 변환합니다. 대상 하드웨어와 일치하는 형식을 선택하고, 원래 모델에 대해 수치적 일치성을 확인한 후, 런타임별 배포 단계에 맞는 통합 가이드를 따르세요.

FAQ#

  • 모든 torch.nn.Module. 여기에는 timm, torchvision 또는 모든 사용자 정의 PyTorch 모델의 모델이 포함됩니다. 모델은 내보내기 전에 평가 모드(model.eval())여야 합니다. ONNX와 OpenVINO는 다중 입력 모델에 대한 예제 텐서 튜플을 추가로 허용합니다.

  • 지원되는 모든 형식(TorchScript, ONNX, OpenVINO, CoreML, TF SavedModel, TF Frozen Graph, NCNN, PaddlePaddle, MNN, ExecuTorch)은 CPU에서 내보낼 수 있습니다. 내보내기 프로세스 자체에는 GPU가 필요하지 않습니다. TensorRT만이 유일하게 NVIDIA GPU를 요구하는 형식입니다.

  • Ultralytics >=8.4.38을 사용하세요. 여기에는 ultralytics.utils.export 모듈과 표준화된 output_file/output_dir 인수가 포함됩니다.

  • 네. torchvision 분류기, 감지기 및 분할 모델은 torch2coreml을 통해 .mlpackage으로 내보내집니다. 이미지 분류 모델의 경우, 분류 헤드를 포함하려면 클래스 이름 목록을 classifier_names에 전달하십시오. macOS 또는 Linux에서 내보내기를 실행하십시오. Windows에서는 CoreML이 지원되지 않습니다. iOS 배포 세부 정보는 CoreML integration을 참조하십시오.

  • 네, 여러 형식에 대해 가능합니다. OpenVINO, CoreML, MNN 또는 NCNN으로 내보낼 때 FP16의 경우 quantize=16을 전달하고 INT8의 경우 quantize=8을 전달하십시오. OpenVINO의 INT8은 post-training quantization을 위해 calibration_dataset 인수를 추가로 요구합니다. 양자화 트레이드오프에 대해서는 각 형식의 통합 페이지를 참조하십시오.

  • 원래 PyTorch 모델과 내보낸 모델을 동일한 입력에서 실행한 다음 출력을 비교합니다. 일치하는 백엔드로 내보낸 파일을 로드하고(예: ONNX의 경우 ONNXBackend) 최대 절대 오차를 확인합니다. FP32 내보내기의 경우 일반적으로 1e-5 정도이며 1e-4보다 훨씬 아래로 유지되어야 합니다. 더 큰 간격은 지원되지 않는 연산, 잘못된 입력 형태, 또는 eval 모드가 아닌 모델을 가리킵니다. 실행 가능한 예제는 내보낸 모델 확인하기를 참조하세요.

댓글