Link to this sectionКак экспортировать PyTorch-модели, отличные от YOLO, с помощью Ultralytics#
Развертывание моделей PyTorch в продакшене обычно означает необходимость жонглировать разными экспортерами для каждой целевой платформы: torch.onnx.export для ONNX, coremltools для устройств Apple, onnx2tf для TensorFlow, pnnx для NCNN и так далее. У каждого инструмента свой API, свои причуды в зависимостях и свои стандарты вывода.
Ultralytics предоставляет автономные утилиты экспорта, которые объединяют множество бэкендов под одним унифицированным интерфейсом. Ты можешь экспортировать любой torch.nn.Module, включая модели классификации timm, классификаторы и детекторы torchvision или свои собственные архитектуры в ONNX, TorchScript, OpenVINO, CoreML, NCNN, PaddlePaddle, MNN, ExecuTorch и TensorFlow SavedModel, не изучая каждый бэкенд по отдельности.
Link to this sectionПочему стоит использовать Ultralytics для экспорта не-YOLO моделей?#
- Один API для 10 форматов: выучи одну конвенцию вызова вместо дюжины.
- Общая поверхность утилит: вспомогательные функции экспорта находятся в
ultralytics.utils.export, поэтому, как только пакеты бэкендов установлены, ты можешь использовать один и тот же шаблон вызова для разных форматов. - Тот же путь кода, что и у экспорта YOLO: те же вспомогательные функции обеспечивают каждый экспорт Ultralytics YOLO.
- Встроенная квантование FP16 и INT8 для форматов, которые его поддерживают (OpenVINO, CoreML, MNN, NCNN).
- Работает на CPU: для самого процесса экспорта GPU не требуется, поэтому ты можешь запустить его локально на любом ноутбуке.
Link to this sectionБыстрый старт#
Самый быстрый путь — это экспорт в ONNX в две строки без кода YOLO и без настройки, помимо 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Пошаговые примеры#
Каждый пример ниже использует одну и ту же настройку: предобученную ResNet-18 из timm в режиме оценки (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 sectionЭкспорт в 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.
Link to this sectionЭкспорт в TorchScript#
Дополнительные зависимости не нужны. Под капотом используется torch.jit.trace.
from ultralytics.utils.export import torch2torchscript
torch2torchscript(model, im, output_file="resnet18.torchscript")Link to this sectionЭкспорт в OpenVINO#
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 для динамических входных форм, half=True для FP16 или int8=True для квантования INT8. Для INT8 дополнительно требуется аргумент calibration_dataset.
Требуется openvino>=2024.0.0 (или >=2025.2.0 на macOS 15.4+) и torch>=2.1.
Link to this sectionЭкспорт в 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, output_file="resnet18.mlpackage")Для моделей classification передай список имен классов в classifier_names, чтобы добавить заголовок классификации к модели CoreML.
Требуется coremltools>=9.0, torch>=1.11 и numpy<=2.3.5. Не поддерживается в Windows.
coremltools>=9.0 поставляет колеса для Python 3.10–3.13 на macOS и Linux. На новых версиях Python собственное расширение C не загружается. Используй Python 3.10–3.13 для экспорта в CoreML.
Link to this sectionЭкспорт в 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.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)ai-edge-litert>=1.2.0,<1.4.0на macOS (ai-edge-litert>=1.2.0на других платформах)onnxslim>=0.1.71onnx>=1.12.0,<2.0.0protobuf>=5
Link to this sectionЭкспорт в TensorFlow 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 sectionЭкспорт в 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.pytorch2ncnn() проверяет наличие ncnn и pnnx при первом использовании.
Link to this sectionЭкспорт в 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")Поддерживает half=True для FP16 и int8=True для квантования INT8. Требуется MNN>=2.9.6 и torch>=1.10.
Link to this sectionЭкспорт в 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 для твоей платформы:
paddlepaddle-gpu>=3.0.0,<3.3.0на CUDApaddlepaddle==3.0.0на ARM64 CPUpaddlepaddle>=3.0.0,<3.3.0на других процессорах
Не поддерживается на NVIDIA Jetson.
Link to this sectionЭкспорт в 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.
Link to this sectionПроверь свою экспортированную модель#
После экспорта перед развертыванием проверь численное соответствие с исходной моделью PyTorch. Быстрый дымовой тест с помощью ONNXBackend из ultralytics.nn.backends сравнивает выходные данные и позволяет заблаговременно выявить ошибки трассировки или квантования:
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-5Для экспорта в FP32 максимальная абсолютная разница должна быть менее 1e-5. Большие значения указывают на неподдерживаемые операции, некорректную форму входных данных или модель, не переведенную в режим оценки (eval mode). Для форматов FP16 и INT8 допуски мягче. Проверяй на реальных данных, а не на случайных тензорах.
Для других сред выполнения имя входного тензора может отличаться. OpenVINO, например, использует имя аргумента forward (обычно x для обычных моделей), тогда как torch2onnx по умолчанию использует "images".
Link to this sectionИзвестные ограничения#
- Поддержка нескольких входов неоднородна:
torch2onnxиtorch2openvinoпринимают кортеж или список тензоров-примеров для моделей с несколькими входами.torch2torchscript,torch2coreml,torch2ncnn,torch2paddleиtorch2executorchпредполагают наличие только одного входного тензора. - ExecuTorch требует
flatc: Среде выполнения ExecuTorch нужен компилятор FlatBuffers. Установи его с помощьюbrew install flatbuffersна macOS илиapt install flatbuffers-compilerна Ubuntu. - Без вывода через Ultralytics: Экспортированные модели, не относящиеся к YOLO, нельзя загрузить обратно через
YOLO()для инференса. Используй собственную среду выполнения для каждого формата (ONNX Runtime, OpenVINO Runtime и т. д.). - Форматы только для YOLO: Экспорт для Axelera и Sony IMX500 требует специфических атрибутов модели YOLO и недоступен для обычных моделей.
- Форматы, зависящие от платформы: TensorRT требует видеокарту NVIDIA. RKNN требует SDK
rknn-toolkit2(только Linux). Edge TPU требует бинарный файлedgetpu_compiler(только Linux).
Link to this sectionЧасто задаваемые вопросы (FAQ)#
Link to this sectionКакие модели я могу экспортировать с помощью Ultralytics?#
Любой torch.nn.Module. Сюда входят модели из timm, torchvision или любые пользовательские модели PyTorch. Перед экспортом модель должна быть переведена в режим оценки (model.eval()). ONNX и OpenVINO дополнительно принимают кортеж из тензоров-примеров для моделей с несколькими входами.
Link to this sectionКакие форматы экспорта работают без GPU?#
Все поддерживаемые форматы (TorchScript, ONNX, OpenVINO, CoreML, TF SavedModel, TF Frozen Graph, NCNN, PaddlePaddle, MNN, ExecuTorch) можно экспортировать на CPU. GPU для самого процесса экспорта не требуется. TensorRT — единственный формат, требующий видеокарту NVIDIA.
Link to this sectionКакая версия Ultralytics мне нужна?#
Используй Ultralytics >=8.4.38, которая включает модуль ultralytics.utils.export и стандартизированные аргументы output_file/output_dir.
Link to this sectionМогу ли я экспортировать модель torchvision в CoreML для развертывания на iOS?#
Да. Классификаторы, детекторы и модели сегментации torchvision экспортируются в .mlpackage через torch2coreml. Для моделей классификации изображений передай список имен классов в classifier_names, чтобы встроить заголовок классификации. Запускай экспорт на macOS или Linux. CoreML не поддерживается в Windows. Подробности развертывания на iOS см. в интеграции CoreML.
Link to this sectionМогу ли я квантовать свою экспортированную модель до INT8 или FP16?#
Да, для нескольких форматов. Передай half=True для FP16 или int8=True для INT8 при экспорте в OpenVINO, CoreML, MNN или NCNN. INT8 в OpenVINO дополнительно требует аргумент calibration_dataset для пост-тренировочного квантования. См. страницу интеграции каждого формата, чтобы узнать о компромиссах при квантовании.