Meet YOLO26: next-gen vision AI.

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, не требуются.

ФорматФункцияУстановкаРезультат
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"})), который внедряет пользовательские пары ключ-значение в экспортированный артефакт, если формат это поддерживает.

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)
Всегда вызывай `model.eval()` перед экспортом

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.

Ошибка `BlobWriter not loaded`

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.0
  • onnx2tf>=1.26.3,<1.29.0
  • tf_keras<=2.19.0
  • sng4onnx>=1.0.1
  • onnx_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.71
  • onnx>=1.12.0,<2.0.0
  • protobuf>=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.py

torch2ncnn() проверяет наличие 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 на CUDA
  • paddlepaddle==3.0.0 на ARM64 CPU
  • paddlepaddle>=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 для пост-тренировочного квантования. См. страницу интеграции каждого формата, чтобы узнать о компромиссах при квантовании.

Комментарии