Link to this sectionUltralytics를 사용하여 Non-YOLO PyTorch 모델을 내보내는 방법#
PyTorch 모델을 프로덕션 환경에 배포하려면 일반적으로 대상마다 다른 익스포터를 사용해야 합니다. ONNX에는 torch.onnx.export, Apple 기기에는 coremltools, TensorFlow에는 onnx2tf, NCNN에는 pnnx 등을 사용해야 합니다. 각 도구는 자체 API, 의존성 설정 문제, 출력 규칙을 가지고 있습니다.
Ultralytics ships standalone export utilities that wrap multiple backends behind one consistent interface. You can export any torch.nn.Module, including timm image models, torchvision classifiers and detectors, or your own custom architectures, to ONNX, TorchScript, OpenVINO, CoreML, NCNN, PaddlePaddle, MNN, ExecuTorch, and TensorFlow SavedModel without learning each backend separately.
Link to this sectionNon-YOLO 내보내기에 Ultralytics를 사용하는 이유는 무엇인가요?#
- 10가지 형식을 지원하는 하나의 API: 12가지 서로 다른 호출 규칙 대신 단 하나의 규칙만 학습하면 됩니다.
- 공유 유틸리티 인터페이스: 내보내기 도우미는
ultralytics.utils.export하위에 위치하므로, 백엔드 패키지가 설치되면 여러 형식에 걸쳐 동일한 호출 패턴을 사용할 수 있습니다. - YOLO 내보내기와 동일한 코드 경로: 모든 Ultralytics YOLO 내보내기를 수행하는 도우미와 동일한 도우미가 사용됩니다.
- FP16 및 INT8 양자화: 이를 지원하는 형식(OpenVINO, CoreML, MNN, NCNN)에 대해 기본적으로 내장되어 있습니다.
- CPU 환경 지원: 내보내기 단계 자체에는 GPU가 필요하지 않으므로 로컬 노트북 환경에서도 실행할 수 있습니다.
Link to this section빠른 시작#
The fastest path is a two-line export to ONNX with no YOLO code and no setup beyond pip install ultralytics onnx timm:
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")Link to this section지원되는 내보내기 형식#
torch2* 함수는 표준 torch.nn.Module과 예시 입력 텐서를 인자로 받습니다. MNN, TF SavedModel, TF Frozen Graph는 중간 ONNX 또는 Keras 아티팩트를 거칩니다. 어느 경우든 YOLO 관련 속성이 별도로 필요하지 않습니다.
| 형식 | 함수 | 설치 | 출력 |
|---|---|---|---|
| ONNX | torch2onnx() | pip install onnx | .onnx 파일 |
| TorchScript | torch2torchscript() | PyTorch에 포함됨 | .torchscript 파일 |
| OpenVINO | torch2openvino() | pip install openvino | _openvino_model/ 디렉토리 |
| CoreML | torch2coreml() | pip install coremltools | .mlpackage |
| TF SavedModel | onnx2saved_model() | 상세 요구 사항은 아래 참조 | _saved_model/ 디렉토리 |
| TF Frozen Graph | keras2pb() | 상세 요구 사항은 아래 참조 | .pb 파일 |
| NCNN | torch2ncnn() | pip install ncnn pnnx | _ncnn_model/ 디렉토리 |
| MNN | onnx2mnn() | pip install MNN | .mnn 파일 |
| PaddlePaddle | torch2paddle() | pip install paddlepaddle x2paddle | _paddle_model/ 디렉토리 |
| ExecuTorch | torch2executorch() | pip install executorch | _executorch_model/ 디렉토리 |
MNN, TF SavedModel 및 TF Frozen Graph 내보내기는 중간 단계로 ONNX를 거칩니다. 먼저 ONNX로 내보낸 다음 변환하십시오.
일부 내보내기 함수는 선택적으로 metadata 딕셔너리를 인자로 받습니다(예: torch2torchscript(..., metadata={"author": "me"})). 형식이 지원하는 경우 내보낸 아티팩트에 사용자 정의 키-값 쌍을 포함할 수 있습니다.
Link to this section단계별 예제#
아래의 모든 예제는 timm의 사전 학습된 ResNet-18 모델을 평가 모드(evaluation mode)로 설정하여 동일한 환경에서 수행합니다:
import timm
import torch
model = timm.create_model("resnet18", pretrained=True).eval()
im = torch.randn(1, 3, 224, 224)Dropout, batch normalization 및 기타 학습 전용 레이어는 추론 중에 다르게 동작합니다. .eval()을 생략하면 올바르지 않은 출력을 가진 모델이 내보내집니다.
Link to this sectionONNX로 내보내기#
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 인수를 사용하여 이를 재정의할 수 있습니다.
Link to this sectionTorchScript로 내보내기#
추가 의존성이 필요하지 않습니다. 내부적으로 torch.jit.trace를 사용합니다.
from ultralytics.utils.export import torch2torchscript
torch2torchscript(model, im, output_file="resnet18.torchscript")Link to this sectionOpenVINO로 내보내기#
from ultralytics.utils.export import torch2openvino
ov_model = torch2openvino(model, im, output_dir="resnet18_openvino_model")디렉토리에는 고정된 이름의 model.xml 및 model.bin 쌍이 포함됩니다:
resnet18_openvino_model/
├── model.xml
└── model.bin동적 입력 형태를 위해 dynamic=True, FP16을 위해 half=True, 또는 INT8 양자화를 위해 int8=True를 전달하십시오. INT8은 추가로 calibration_dataset 인수가 필요합니다.
openvino>=2024.0.0(macOS 15.4+에서는 >=2025.2.0) 및 torch>=2.1이 필요합니다.
Link to this sectionCoreML로 내보내기#
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, output_file="resnet18.mlpackage")분류 모델의 경우, 분류 헤드를 CoreML 모델에 추가하려면 클래스 이름 목록을 classifier_names에 전달하십시오.
coremltools>=9.0, torch>=1.11, numpy<=2.3.5가 필요합니다. Windows는 지원되지 않습니다.
coremltools>=9.0은 macOS 및 Linux용 Python 3.103.13 버전의 휠을 제공합니다. 더 최신 Python 버전에서는 네이티브 C 확장이 로드되지 않습니다. CoreML 내보내기에는 Python 3.103.13을 사용하십시오.
Link to this sectionTensorFlow 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.0onnx2tf>=1.26.3,<1.29.0tf_keras<=2.19.0sng4onnx>=1.0.1onnx_graphsurgeon>=0.3.26(--extra-index-url https://pypi.ngc.nvidia.com과 함께 설치)- macOS에서는
ai-edge-litert>=1.2.0,<1.4.0(다른 플랫폼에서는ai-edge-litert>=1.2.0) onnxslim>=0.1.71onnx>=1.12.0,<2.0.0protobuf>=5
Link to this sectionTensorFlow Frozen Graph로 내보내기#
위에서 언급한 SavedModel 내보내기 단계에 이어, 반환된 Keras 모델을 고정된 .pb 그래프로 변환합니다:
from pathlib import Path
from ultralytics.utils.export import keras2pb
keras2pb(keras_model, output_file=Path("resnet18_saved_model/resnet18.pb"))Link to this sectionNCNN으로 내보내기#
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.pytorch2ncnn()은 처음 사용할 때 ncnn과 pnnx가 있는지 확인합니다.
Link to this sectionMNN으로 내보내기#
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에 대해 half=True, INT8 양자화에 대해 int8=True를 지원합니다. MNN>=2.9.6 및 torch>=1.10이 필요합니다.
Link to this sectionPaddlePaddle로 내보내기#
from ultralytics.utils.export import torch2paddle
torch2paddle(model, im, output_dir="resnet18_paddle_model")디렉토리에는 PaddlePaddle 모델 및 매개변수 파일이 포함됩니다:
resnet18_paddle_model/
├── model.pdmodel
└── model.pdiparamsx2paddle 및 플랫폼에 맞는 올바른 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에서는 지원되지 않습니다.
Link to this sectionExecuTorch로 내보내기#
from ultralytics.utils.export import torch2executorch
torch2executorch(model, im, output_dir="resnet18_executorch_model")내보낸 .pte 파일은 출력 디렉터리 내에 저장됩니다:
resnet18_executorch_model/
└── model.ptetorch>=2.9.0 및 호환되는 ExecuTorch 런타임(pip install executorch)이 필요합니다. 런타임 사용법은 ExecuTorch 통합을 참조하십시오.
Link to this section내보낸 모델 검증#
After exporting, verify numerical parity with the original PyTorch model before shipping. A quick smoke test with ONNXBackend from ultralytics.nn.backends compares outputs and flags tracing or quantization errors early:
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}") # should be < 1e-5FP32 내보내기의 경우, 최대 절대 오차는 1e-5 미만이어야 합니다. 더 큰 차이가 발생하면 지원되지 않는 연산, 잘못된 입력 형상, 또는 eval 모드가 아닌 모델일 수 있습니다. FP16 및 INT8 내보내기는 허용 오차가 더 큽니다. 무작위 텐서 대신 실제 데이터로 검증하십시오.
다른 런타임의 경우, 입력 텐서 이름이 다를 수 있습니다. 예를 들어, OpenVINO는 모델의 순방향 인수 이름(일반적으로 일반 모델의 경우 x)을 사용하는 반면, torch2onnx는 기본적으로 "images"를 사용합니다.
Link to this section알려진 제한 사항#
- 다중 입력 지원이 균일하지 않음:
torch2onnx및torch2openvino는 다중 입력 모델에 대해 예제 텐서의 튜플 또는 리스트를 허용합니다.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 전용 형식: Axelera 및 Sony IMX500 내보내기는 YOLO 전용 모델 속성이 필요하며 일반 모델에는 사용할 수 없습니다.
- 플랫폼별 형식: TensorRT는 NVIDIA GPU가 필요합니다. RKNN은
rknn-toolkit2SDK(Linux 전용)가 필요합니다. Edge TPU는edgetpu_compiler바이너리(Linux 전용)가 필요합니다.
Link to this sectionFAQ#
Link to this sectionUltralytics로 어떤 모델을 내보낼 수 있습니까?#
모든 torch.nn.Module이 가능합니다. 여기에는 timm, torchvision 또는 기타 커스텀 PyTorch 모델이 포함됩니다. 모델은 내보내기 전에 평가 모드(model.eval())여야 합니다. ONNX 및 OpenVINO는 다중 입력 모델을 위한 예제 텐서 튜플을 추가로 허용합니다.
Link to this sectionGPU 없이 작동하는 내보내기 형식은 무엇입니까?#
지원되는 모든 형식(TorchScript, ONNX, OpenVINO, CoreML, TF SavedModel, TF Frozen Graph, NCNN, PaddlePaddle, MNN, ExecuTorch)은 CPU에서 내보낼 수 있습니다. 내보내기 과정 자체에는 GPU가 필요하지 않습니다. TensorRT만이 유일하게 NVIDIA GPU를 요구하는 형식입니다.
Link to this section어떤 Ultralytics 버전이 필요합니까?#
Use Ultralytics >=8.4.38, which includes the ultralytics.utils.export module and the standardized output_file/output_dir arguments.
Link to this sectiontorchvision 모델을 iOS 배포를 위해 CoreML로 내보낼 수 있습니까?#
Yes. torchvision classifiers, detectors, and segmentation models export to .mlpackage via torch2coreml. For image classification models, pass a list of class names to classifier_names to bake in a classification head. Run the export on macOS or Linux. CoreML is not supported on Windows. See the CoreML integration for iOS deployment details.
Link to this section내보낸 모델을 INT8 또는 FP16으로 양자화할 수 있습니까?#
Yes, for several formats. Pass half=True for FP16 or int8=True for INT8 when exporting to OpenVINO, CoreML, MNN, or NCNN. INT8 in OpenVINO additionally requires a calibration_dataset argument for post-training quantization. See each format's integration page for quantization trade-offs.