Оцени и подготовь к развёртыванию все задачи
Задай для каждой задачи собственную метрику приёмки для целевого размера развёртывания, проверь все задачи в одном цикле и экспортируй каждую в ONNX с проверенным предсказанием.
У каждой задачи своё определение правильного результата: перекрытие пикселей, сходство ключевых точек, IoU повёрнутых рамок, правильный класс top-1 или отношение глубин. Команды, которые используют для всех задач один и тот же чек-лист детекции, выпускают модели сегментации, проверенные по mAP рамок, и модели оценки позы, проверенные по рамкам, хотя именно рамки не являются целевым результатом. Кроме того, модель, прошедшая проверку, всё равно может дать сбой после экспорта: в этом уроке одни и те же веса модели оценки позы обнаруживают 5 человек при одном размере входного изображения и 3 — при другом, а расстояния модели глубины почти удваиваются.
Практические занятия
Одна метрика приёмки для каждой задачи#
| Задача | Метрика приёмки | Ключ results_dict | Атрибут Python | Что оценивается |
|---|---|---|---|---|
| сегментация | mask mAP50-95 | metrics/mAP50-95(M) | metrics.seg.map | IoU пикселей для каждого объекта |
| семантическая сегментация | mIoU (+ IoU для каждого класса) | metrics/mIoU | metrics.miou | IoU пикселей для каждого класса |
| оценка позы | pose mAP50-95 | metrics/mAP50-95(P) | metrics.pose.map | OKS |
| obb | OBB mAP50-95 | metrics/mAP50-95(B) | metrics.box.map | IoU повёрнутых рамок |
| классификация | точность top-1 | metrics/accuracy_top1 | metrics.top1 | правильный класс top-1 |
| глубина | δ1 (+ AbsRel) | metrics/delta1 | metrics.delta1 | доля пикселей, у которых истинная глубина отличается не более чем в 1,25 раза |
В руководстве по метрикам производительности объясняется каждая метрика. Запуски сегментации и оценки позы также показывают метрики рамок. Используй их для диагностики: разница между показателями рамок и масок указывает на качество контуров, — но рамки не являются целевым результатом. Рекомендации по анализу результатов детекции, например подбор порогов и построение матрицы ошибок, применимы и здесь; они приведены в разделе «Валидация и диагностика».
Проверь все задачи в одном цикле#
Режим Val принимает веса любой задачи при условии, что им соответствует набор данных, поэтому один цикл формирует показатели для таблицы релиза:
from ultralytics import YOLO
runs = {
"yolo26n-seg.pt": ("coco8-seg.yaml", "metrics/mAP50-95(M)"),
"yolo26n-sem.pt": ("cityscapes8.yaml", "metrics/mIoU"),
"yolo26n-pose.pt": ("coco8-pose.yaml", "metrics/mAP50-95(P)"),
"yolo26n-obb.pt": ("dota8.yaml", "metrics/mAP50-95(B)"),
"yolo26n-depth.pt": ("depth8.yaml", "metrics/delta1"),
}
for weights, (data, key) in runs.items():
metrics = YOLO(weights).val(data=data, device="cpu", plots=False, verbose=False)
print(f"{weights:17s} {key:22s} {metrics.results_dict[key]:.3f}")yolo26n-seg.pt metrics/mAP50-95(M) 0.538
yolo26n-sem.pt metrics/mIoU 0.610
yolo26n-pose.pt metrics/mAP50-95(P) 0.419
yolo26n-obb.pt metrics/mAP50-95(B) 0.857
yolo26n-depth.pt metrics/delta1 0.377Если явно не указать imgsz, каждая модель проходит валидацию при размере, на котором её обучали: 640 для сегментации и оценки позы, 768 для глубины, 1024 для семантической сегментации и OBB. Показатели этих предварительно обученных моделей выше результатов обучения с размером 320 пикселей, приведённых ранее в курсе: отчасти благодаря обучению, отчасти — разрешению. Четыре изображения для валидации позволяют лишь проверить, что всё работает; например, на странице задачи оценки глубины приводится δ1 на полном наборе NYU. Классификация намеренно не включена: проверь дообученный классификатор на собственных папках, как в уроке по классификации.
Одинаковые веса показывают разные результаты при разных значениях imgsz. Записывай imgsz рядом с каждым результатом, проводи валидацию при том размере, который будешь использовать при развертывании, и никогда не сравнивай результаты, измеренные при разных размерах.
Экспортируй все задачи#
Каждую задачу можно экспортировать в ONNX одним и тем же вызовом режима Export. Задача сохраняется в метаданных модели, поэтому YOLO("model.onnx") применяет нужную постобработку. Выбор среды выполнения, проверка паритета и настройка TensorRT или OpenVINO рассматриваются в разделе «Экспорт в ONNX (и проверка паритета)»; в этом цикле проверяется, что все задачи проходят полный цикл экспорта и повторной загрузки:
from ultralytics import YOLO
for weights in ["yolo26n-seg.pt", "yolo26n-sem.pt", "yolo26n-pose.pt", "yolo26n-obb.pt", "yolo26n-cls.pt", "yolo26n-depth.pt"]:
onnx_path = YOLO(weights).export(format="onnx", imgsz=320)
onnx_model = YOLO(onnx_path) # task comes from the ONNX metadata
result = onnx_model("https://ultralytics.com/images/bus.jpg", imgsz=320, verbose=False)[0]
print(f"{onnx_model.task:9s} {result.verbose()}")segment 4 persons, 1 bus,
semantic
pose 3 persons,
obb (no detections),
classify minibus 0.38, police_van 0.21, trolleybus 0.05, amphibian 0.05, bullet_train 0.03,
depth depth 4.67-26.91m,Все экспортированные модели загрузились повторно с правильным типом задачи. Три результата стоит проверить внимательнее:
- При размере 320 пикселей модель оценки позы обнаружила 3 человек, тогда как запуск PyTorch при размере 640 пикселей обнаружил 5.
- Модель глубины оценила расстояния как 4,7–26,9 м, тогда как те же веса при исходном размере 768 пикселей дали значения 2,1–14,9 м.
- OBB ничего не обнаружила на уличной фотографии — это правильное поведение для модели, обученной на аэрофотоснимках, а не ошибка экспорта.
PyTorch с imgsz=320 выдаёт те же показатели для оценки позы и глубины, что и ONNX, поэтому ни в одном из случаев нет ошибки экспорта: результат изменился из-за размера входного изображения. Экспортируй модель с тем значением imgsz, которое ты проверил. Для семантической сегментации нет сводной строки по объектам, поэтому проверь result.semantic_mask.
Сделай по одному предсказанию каждой экспортированной моделью на изображении, похожем на те, на которых она обучалась: у моделей COCO это должны быть уличные сцены, у OBB — аэрофотоснимки, а у моделей глубины — сцены в помещении или на улице с подходящим масштабом. Выполни эту проверку, прежде чем объявлять экспорт неисправным или отправлять его в рабочую среду.
Если ты реализуешь собственную постобработку, ниже приведены исходные выходы ONNX при imgsz=320 из журнала экспорта:
| Задача | Форма выходных данных ONNX | Содержимое |
|---|---|---|
| сегментация | (1, 116, 2100) и (1, 32, 80, 80) | рамки + 80 оценок классов + 32 коэффициента масок; прототипы масок |
| семантическая сегментация | (1, 320, 320) | карта классов; argmax уже включён в граф |
| оценка позы | (1, 56, 2100) | рамки + 1 оценка + значения 17 × 3 для ключевых точек |
| obb | (1, 20, 2100) | рамки + 15 оценок классов + 1 угол |
| классификация | (1, 1000) | вероятности классов |
| глубина | (1, 1, 320, 320) | глубина в метрах на пиксель |
На платформе Ultralytics на странице модели отображаются метрики для соответствующей задачи (например, mask mAP для модели сегментации), а на вкладке Export можно получить модель в тех же форматах:

ONNX — формат для обмена моделями: один экспортированный файл запускается в ONNX Runtime или конвертируется для других сред выполнения.

Чек-лист перед выпуском#
- Метрика приёмки из таблицы выше достигает целевого значения на отложенной выборке при размере развёртывания
imgsz. - Экспортированная модель повторно загружается с ожидаемым
taskи выдаёт те же предсказания, что и PyTorch, на фиксированном наборе изображений. - В коде для каждой задачи обрабатываются пустые результаты:
masks is None, отсутствие ключевых точек, отсутствие OBB. - Показатели для последующей обработки (площади, углы, расстояния, вероятности классов) записываются в журнал, чтобы отслеживать их изменения, как описано в разделе «Наблюдаемость и дрейф».
Если метрика приёмки не достигнута, «вернуться к данным» обычно означает использовать один из трёх способов:

Сначала исправь качество данных и процесс разметки: проверки меток из уроков 2 и 6 — самый простой способ начать. Меняй модель только после того, как приведёшь данные в порядок.
Показать решение
from ultralytics import YOLO
checks = {
"runs/segment/train/weights/best.pt": ("coco8-seg.yaml", "metrics/mAP50-95(M)", "https://ultralytics.com/images/bus.jpg"),
"runs/obb/train/weights/best.pt": ("dota8.yaml", "metrics/mAP50-95(B)", "https://ultralytics.com/images/boats.jpg"),
}
for weights, (data, key, image) in checks.items():
model = YOLO(weights)
gate = model.val(data=data, imgsz=320, plots=False, verbose=False).results_dict[key]
onnx_model = YOLO(model.export(format="onnx", imgsz=320))
result = onnx_model(image, imgsz=320, verbose=False)[0]
print(f"{onnx_model.task:8s} {key} @320 = {gate:.3f} | ONNX: {result.verbose()}")Замени пути runs/... на пути к папкам, выведенные при запусках обучения (Results saved to ...). Для запусков в одну эпоху из уроков 2 и 7:
segment metrics/mAP50-95(M) @320 = 0.377 | ONNX: 4 persons, 1 bus,
obb metrics/mAP50-95(B) @320 = 0.832 | ONNX: 185 ships, 3 harbors,| Модель | Метрика для принятия решения | Значение | imgsz | ONNX |
|---|---|---|---|---|
| сегментация | mask mAP50-95 | 0.377 | 320 | повторно загружается как segment, обнаруживает автобус и 4 человек |
| obb | OBB mAP50-95 | 0.832 | 320 | повторно загружается как obb, обнаруживает 185 кораблей и 3 гавани |
Для каждой проверки используется изображение из соответствующего домена: модель OBB получает аэрофотоснимок гавани, а не уличную сцену. Обе строки проходят проверку экспорта, но ни одна модель не готова к выпуску: обучение в течение одной эпохи на четырёх изображениях для валидации — это лишь проверка работоспособности, а не проверка по пороговому значению.