Ultralytics YOLO27: Встать в лист ожидания.
Get Started
Обучи первую модель YOLO·Развёртывание·Урок 10/10
Урокначинающий

Экспорт для развёртывания

Экспортируй best.pt в ONNX, OpenVINO, TensorRT, CoreML, LiteRT или QNN, а затем докажи, что экспортированная модель совпадает с моделью PyTorch, прежде чем запускать её в production.

Для работы твоей модели best.pt нужны Python и PyTorch, которых обычно нет на телефонах, в браузерах, на Jetson и производственных серверах. Режим Export одним вызовом преобразует модель в автономный файл для этих сред выполнения. Но сам факт успешной загрузки экспорта ещё не означает, что он работает правильно, а небрежное сравнение может создать впечатление, что корректный экспорт сломан, или скрыть проблему в некорректном.

В этом уроке ты экспортируешь модель таблеток в ONNX, запустишь её через тот же API YOLO, докажешь совпадение с PyTorch по рамкам и валидационной метрике mAP при одинаковых настройках и выберешь формат для своей целевой платформы: ONNX, OpenVINO, TensorRT, CoreML, LiteRT или QNN.

Результат

Ты умеешь экспортировать обученную модель в подходящий для целевой платформы развёртывания формат и доказывать с помощью проверки соответствия и валидации, что экспорт совпадает с best.pt.

Ускоренное прохождение
Если ты уже освоился, вот краткая версия.
  1. yolo export model=runs/detect/pills_v1/weights/best.pt format=onnx — начни с него.

  2. OpenVINO — для CPU Intel; TensorRT — для GPU NVIDIA и Jetson; CoreML — для Apple; LiteRT — для Android; QNN — для NPU Snapdragon.

  3. Сравни .pt и экспорт на одном изображении с помощью rect=False со стороны .pt.

  4. Проведи валидацию обеих моделей с параметром imgsz, использованным при обучении; значения mAP50-95 должны совпасть.

Практические занятия

Пример: экспорт в ONNX#

Вкладка экспорта моделей на платформе Ultralytics со списком форматов для развёртывания, включая ONNX, TensorRT, CoreML и OpenVINO

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): 4 значения рамки плюс оценка класса для 2 100 кандидатов на рамки; по умолчанию NMS выполняется вне графа.
  • 9.3 MB: файл ONNX хранит веса FP32, поэтому он больше, чем .pt с FP16.
  • Predict: / Validate:: готовые команды для экспортированного файла с уже заданным правильным imgsz.

Большинство задач решается несколькими аргументами; остальные перечислены в руководстве по интеграции ONNX.

АргументПо умолчаниюДля чего использовать
imgszРазмер при обученииЭкспорт с другим фиксированным размером входных данных, например imgsz=640
dynamicFalseПринимать изображения разных размеров вместо одного фиксированного
quantizeНе требуется (FP32)16 — для весов FP16 (yolo26n.onnx уменьшает размер с 9.5 MB до 4.8 MB); 8 — для INT8, если формат его поддерживает
nmsНе требуетсяnms=True встраивает NMS в граф, поэтому среда выполнения возвращает готовые рамки

Пример: проверь, что экспорт совпадает с исходной моделью#

Класс YOLO также загружает экспортированные файлы, поэтому код предсказания из предыдущего примера работает без изменений. Сравни оба файла на одном и том же валидационном изображении:

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 на целевом устройстве, чтобы знать реальную производительность до запуска в production.

Выбери формат для целевой платформы#

Жизненный цикл на платформе Ultralytics: разметка с помощью интеллектуальной аннотации SAM, обучение на облачных GPU и развёртывание в глобальных регионах с логотипами партнёров по интеграции

Целевой показательФорматПримечания
Универсальный вариант по умолчанию: серверы и настольные компьютеры под Linux, Windows и MaconnxONNX Runtime на CPU или GPU; экспорт, который быстрее всего проверить
Графические процессоры NVIDIA и Jetsonengine (TensorRT)Максимальная скорость на NVIDIA; экспортируй на устройстве. См. Оптимизация с TensorRT
Процессоры и встроенные графические процессоры IntelopenvinoРеальный прирост скорости на CPU благодаря ядрам Intel. См. OpenVINO на CPU
Приложения для iPhone, iPad и MaccoremlНативное решение; использует Apple Neural Engine
Android и другие мобильные или встраиваемые устройстваlitertДля мобильных устройств рекомендуется INT8
NPU SnapdragonqnnУскорение Hexagon HTP; по умолчанию используются веса INT8 и 16-битные активации; выбери архитектуру HTP с помощью name
Веб-браузерonnx с ONNX Runtime WebНебольшие модели — вполне практичный вариант: 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")  # CPU / встроенный графический процессор Intel
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")  # NPU Qualcomm Snapdragon (HTP v73); выполни калибровку на собственных данных

Каждый экспорт сохраняет файлы рядом с весами: best.onnx, best_openvino_model/, best.engine и так далее. Начни с ONNX, даже если в итоге выберешь другой формат: его быстрее всего проверить, и он служит входным форматом для нескольких других цепочек инструментов. В руководстве по вариантам развёртывания сравниваются все форматы, а в разделе Выбор целевой платформы описан процесс выбора.

Квантование модели позволяет уменьшить размер и увеличить скорость за счёт точности. FP16 (quantize=16) уменьшает размер файла вдвое почти без потери точности. INT8 (quantize=8) ещё компактнее и быстрее, но требует калибровочных изображений — репрезентативных кадров, на которых экспорт подбирает диапазоны значений; Ultralytics рекомендует использовать не менее 300 изображений. Перед выпуском всегда проверяй модель INT8: потери могут быть как незначительными, так и существенными — в зависимости от модели и набора для калибровки.

Избегай этих ошибок#

Сравнение разных входных данных

Симптом: модель .pt обнаруживает 35 таблеток на Frame_144.jpg, а ONNX-файл — 25, и кажется, что экспорт работает неправильно. Причина: PyTorch во время инференса дополняет каждое изображение до минимального прямоугольника, размеры которого кратны шагу (192×320 для этих кадров с соотношением сторон 16:9), тогда как статическая модель ONNX всегда принимает квадрат 320×320. Различия во входных данных приводят к различиям в детекциях с низкой уверенностью. Решение: при сравнении передай rect=False модели .pt, как в parity.py.

Статический экспорт игнорирует твой imgsz

Симптом: ты передаёшь imgsz=640 в best.onnx, но в журнале по-прежнему указано 320x320. Причина: у статического экспорта один размер входных данных, заданный при экспорте. Решение: экспортируй модель с размером, который будешь использовать (imgsz=640), или экспортируй её с dynamic=True.

Движки TensorRT зависят от устройства

Движок .engine, созданный на A100, не запустится на Jetson Orin и может перестать работать после обновления TensorRT. Выполняй экспорт на целевом устройстве, используя ту версию TensorRT, с которой он будет работать. ONNX переносим, а движки — нет.

При INT8-калибровке по умолчанию используется COCO8

Если при экспорте в INT8 не указать data, Ultralytics выдаст предупреждение и выполнит калибровку на образцах COCO8 по умолчанию — восьми изображениях, совсем не похожих на изображения твоих таблеток. Передай собственный набор: model.export(format="litert", quantize=8, data="my_dataset/data.yaml").

Модель развёрнута#

Теперь у тебя есть обученная модель best.pt, результаты валидации для сравнения с базовым уровнем, файл экспорта для среды выполнения и подтверждение того, что экспорт соответствует исходной модели. Это полный цикл — данные, обучение, валидация, экспорт, развёртывание — и производственные команды выполняют его по расписанию. В курсе Ultralytics YOLO в производственной среде рассматриваются дальнейшие шаги после проверки экспорта: оптимизированные среды выполнения, конвейеры отслеживания, обслуживание нескольких потоков и мониторинг.

Попробовать

Экспортируй модель pills_v1/weights/best.pt в ONNX, затем запусти parity.py и val_export.py. Повторно запусти parity.py без rect=False и зафиксируй, как изменится количество .pt. Предоставь четыре результата: совпавшее количество детекций, максимальную разницу между рамками, два значения 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 количество детекций совпадает, а максимальная разница между рамками меньше 1 px.

  • При одинаковых настройках значения mAP50-95 для ONNX и .pt совпадают; ты также указал целевой формат и обосновал выбор.

Показать решение
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
Что дальше

Курс завершён — пройди итоговый тест, чтобы получить сертификат Обучи свою первую модель YOLO, а затем продолжи обучение на курсе Ultralytics YOLO в производственной среде.

Войди, чтобы сохранять прогресс