Экспорт для развёртывания
Экспортируй 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.
Практические занятия
Пример: экспорт в ONNX#

yolo export model=runs/detect/pills_v1/weights/best.pt format=onnxPyTorch: 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 |
dynamic | False | Принимать изображения разных размеров вместо одного фиксированного |
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.
Выбери формат для целевой платформы#

| Целевой показатель | Формат | Примечания |
|---|---|---|
| Универсальный вариант по умолчанию: серверы и настольные компьютеры под Linux, Windows и Mac | onnx | ONNX Runtime на CPU или GPU; экспорт, который быстрее всего проверить |
| Графические процессоры NVIDIA и Jetson | engine (TensorRT) | Максимальная скорость на NVIDIA; экспортируй на устройстве. См. Оптимизация с TensorRT |
| Процессоры и встроенные графические процессоры Intel | openvino | Реальный прирост скорости на CPU благодаря ядрам Intel. См. OpenVINO на CPU |
| Приложения для iPhone, iPad и Mac | coreml | Нативное решение; использует Apple Neural Engine |
| Android и другие мобильные или встраиваемые устройства | litert | Для мобильных устройств рекомендуется INT8 |
| NPU Snapdragon | qnn | Ускорение 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=640 в best.onnx, но в журнале по-прежнему указано 320x320. Причина: у статического экспорта один размер входных данных, заданный при экспорте. Решение: экспортируй модель с размером, который будешь использовать (imgsz=640), или экспортируй её с dynamic=True.
Движок .engine, созданный на A100, не запустится на Jetson Orin и может перестать работать после обновления TensorRT. Выполняй экспорт на целевом устройстве, используя ту версию TensorRT, с которой он будет работать. ONNX переносим, а движки — нет.
Если при экспорте в INT8 не указать data, Ultralytics выдаст предупреждение и выполнит калибровку на образцах COCO8 по умолчанию — восьми изображениях, совсем не похожих на изображения твоих таблеток. Передай собственный набор: model.export(format="litert", quantize=8, data="my_dataset/data.yaml").
Модель развёрнута#
Теперь у тебя есть обученная модель best.pt, результаты валидации для сравнения с базовым уровнем, файл экспорта для среды выполнения и подтверждение того, что экспорт соответствует исходной модели. Это полный цикл — данные, обучение, валидация, экспорт, развёртывание — и производственные команды выполняют его по расписанию. В курсе Ultralytics YOLO в производственной среде рассматриваются дальнейшие шаги после проверки экспорта: оптимизированные среды выполнения, конвейеры отслеживания, обслуживание нескольких потоков и мониторинг.
Показать решение
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