Вы загрузили датасет, запустили train.py с дефолтными параметрами и получили mAP 0.65. «Неплохо», - думаете вы. А потом видите в паблике, как кто-то на похожих данных выжимает 0.92. Разница не в магии, а в 69 часах экспериментов, которые я провел за последний месяц.
Это не очередной туториал «как запустить YOLO». Это разбор того, что происходит между первой и сотой эпохой обучения. Почему модель иногда учится, а иногда нет. Как гиперпараметры влияют не только на метрики, но и на то, будет ли ваша модель работать в продакшене через месяц.
Выбор YOLO в 2026 году: что актуально, а что уже музейный экспонат
На 28.01.2026 ситуация с YOLO выглядит так: есть официальная ветка Ultralytics (YOLOv8, YOLOv10), китайские форки (YOLOv6, YOLOv7) и куча экспериментальных версий. Если вы не занимаетесь исследованиями архитектур, берите YOLOv10 - последнюю стабильную версию от Ultralytics на текущую дату.
Я тестировал три версии на одном датасете с детекцией промышленных дефектов (похоже на задачу из нашей статьи «Как выжать максимум из YOLO для промышленного CV»). Результаты:
| Модель | mAP@0.5 | FPS (RTX 4090) | Память, ГБ | Мой вердикт |
|---|---|---|---|---|
| YOLOv8n | 0.71 | 245 | 1.2 | Для embedded |
| YOLOv10m | 0.83 | 142 | 3.8 | Баланс скорость/качество |
| YOLOv10x | 0.87 | 68 | 8.1 | Только если нужна максимальная точность |
YOLOv10 принес несколько важных изменений по сравнению с v8: улучшенная архитектура neck, лучшее разделение задач классификации и детекции, и что важно - стабильность обучения. В v8 иногда наблюдались «провалы» в лоссе после 50-й эпохи, в v10 это исправили.
Гиперпараметры, которые на самом деле влияют на результат
В документации YOLO около 50 гиперпараметров. Из них реально менять нужно 8-10. Остальные либо работают хорошо по умолчанию, либо требуют изменения только в специфичных случаях.
1 Learning rate: не верьте дефолтным значениям
lr0=0.01 - стандартное значение для YOLOv10. И оно почти всегда слишком большое. На практике я видел две ситуации:
- Маленький датасет (до 1000 изображений) - lr0=0.001
- Средний датасет (1-10к изображений) - lr0=0.005
- Крупный датасет (10к+) - можно пробовать 0.01
2 Аугментации: больше ≠ лучше
YOLOv10 по умолчанию включает mosaic, mixup, copy-paste аугментации. На бумаге это круто. На практике - может сломать обучение на специфичных данных.
# data.yaml - секция аугментаций
augmentations:
mosaic: 1.0 # иногда ставим 0.5 или 0.0
mixup: 0.2 # для маленьких датасетов лучше 0.0
copy_paste: 0.0 # почти всегда выключаем
hsv_h: 0.015
hsv_s: 0.7
hsv_v: 0.4
degrees: 0.0 # если объекты всегда в одной ориентации
translate: 0.2
scale: 0.9
shear: 0.0
Кейс из практики: детекция дефектов на печатных платах. Объекты - микротрещины, сколы. Mosaic аугментация создавала артефакты на стыках изображений, модель начинала детектить эти артефакты как дефекты. Решение - отключить mosaic.
3 Batch size: игра в угадайку с видеопамятью
Правило «чем больше batch, тем лучше» не работает для YOLO. Особенно для маленьких датасетов. Вот что я наблюдал:
| Batch size | mAP@0.5 | Время эпохи | Стабильность |
|---|---|---|---|
| 8 | 0.81 | 45 сек | Высокая |
| 16 | 0.83 | 32 сек | Средняя |
| 32 | 0.79 | 28 сек | Низкая |
| 64 | 0.75 | 25 сек | Очень низкая |
Оптимальный batch size для датасета в 5000 изображений - 16. Больше - модель начинает «забывать» детали. Меньше - обучение становится шумным.
Экспериментальная установка: как не потратить неделю впустую
Я провел 69 часов экспериментов. Из них 40 часов - на первые 10 экспериментов, потому что делал все неправильно. Вот как нужно организовать процесс:
Шаг 1: Базовый запуск с минимальными изменениями
# Не делайте так:
yolo train data=custom.yaml model=yolov10m.pt epochs=100 \
lr0=0.01 batch=16 mosaic=1.0 mixup=0.2 hsv_h=0.015 \
degrees=10.0 translate=0.2 scale=0.9 shear=0.0 \
patience=50 save_period=10 device=0 project=experiments
# Делайте так:
yolo train data=custom.yaml model=yolov10m.pt epochs=50 \
lr0=0.01 batch=16 \
project=baseline name=exp1
Зачем? Чтобы понять, как модель ведет себя на ваших данных «из коробки». Сохраняйте логи, смотрите на графики loss. Если baseline показывает mAP 0.6 - у вас либо плохие данные, либо сложная задача.
Шаг 2: Систематический перебор одного параметра
Не меняйте пять параметров одновременно. Не узнаете, что именно сработало. Мой скрипт для автоматизации:
import subprocess
import yaml
# Параметры для перебора
learning_rates = [0.001, 0.005, 0.01, 0.02]
batch_sizes = [8, 16, 32]
for lr in learning_rates:
for bs in batch_sizes:
exp_name = f"lr_{lr}_bs_{bs}"
cmd = [
"yolo", "train",
f"data=custom.yaml",
f"model=yolov10m.pt",
f"epochs=30", # Короткие прогоны сначала
f"lr0={lr}",
f"batch={bs}",
f"project=hyperparam_tuning",
f"name={exp_name}",
f"device=0",
"save=false", # Не сохраняем веса для каждого эксперимента
"val=true",
]
subprocess.run(cmd)
# Анализируем логи после каждого запуска
with open(f"hyperparam_tuning/{exp_name}/results.csv", 'r') as f:
# Парсим последнюю строку с метриками
pass
Шаг 3: Валидация на «сложных» данных
Создайте отдельный валидационный набор из 50-100 самых сложных примеров. Тех, где объекты маленькие, перекрываются, плохо освещены. Если модель работает на них - она будет работать везде.
Ошибка №1: использовать случайный сплит train/val. В реальности сложные случаи распределены неравномерно. Соберите hard cases вручную.
Метрики: почему mAP врет и как это исправить
mAP@0.5 - стандартная метрика для YOLO. И она абсолютно бесполезна для многих практических задач. Вспомните статью про промышленное CV - там даже 10% загрязнения было критично.
Что отслеживать вместо (или вместе с) mAP:
- Precision на IoU=0.1 - для задач, где важно не пропустить объект
- Recall по классам - если у вас классовый дисбаланс
- FPS на целевом железе - не на вашей RTX 4090, а на том устройстве, где будет работать модель
- Размер модели - для embedded систем
Мой скрипт для кастомных метрик:
import json
from pathlib import Path
def analyze_experiment(exp_path):
results = {
"mAP_50": 0,
"mAP_50_95": 0,
"precision_10": 0, # IoU=0.1
"recall_per_class": {},
"inference_time": 0,
"model_size_mb": 0
}
# Читаем результаты YOLO
results_file = Path(exp_path) / "results.csv"
if results_file.exists():
# Парсим CSV
pass
# Замеряем инференс
import time
import torch
from ultralytics import YOLO
model = YOLO(str(Path(exp_path) / "weights" / "best.pt"))
# Тест на 100 изображениях
times = []
for img_path in test_images[:100]:
start = time.time()
model(img_path, verbose=False)
times.append(time.time() - start)
results["inference_time"] = sum(times) / len(times)
results["fps"] = 1 / results["inference_time"]
# Сохраняем
with open(Path(exp_path) / "custom_metrics.json", 'w') as f:
json.dump(results, f, indent=2)
return results
Распространенные ошибки (я совершил их все)
Ошибка 1: Слишком много эпох
«Давайте обучу на 300 эпохах, чтобы наверняка». Результат - переобучение уже на 80-й эпохе, а вы тратите время и электричество. YOLOv10 сходится за 50-100 эпох для большинства датасетов. Используйте early stopping с patience=20.
Ошибка 2: Игнорирование class imbalance
В датасете 90% объектов - класс А, 10% - класс Б. Модель быстро научится детектить А, а Б будет игнорировать. Решение - взвешенная функция потерь или oversampling редких классов. В YOLOv10 есть параметр class_weights.
Ошибка 3: Неверный выбор IoU threshold для NMS
iou_thres=0.45 по умолчанию. Если у вас объекты расположены плотно (например, клетки на микрофотографии), уменьшайте до 0.3. Иначе модель будет подавлять правильные детекции.
Ошибка 4: Обучение на неочищенных данных
Перед обучением потратьте день на разметку. Посмотрите каждое изображение. Удалите дубликаты, исправьте кривые bounding boxes. Как в статье про разметку данных - качество данных важнее качества модели.
Мой чеклист перед запуском продакшена
- Проверили распределение размеров объектов в датасете. Если объекты мелкие (< 32x32 пикселей), увеличили imgsz с 640 до 1280.
- Создали hard validation set из 100 самых сложных случаев.
- Запустили 3-5 экспериментов с разными learning rates (0.001, 0.005, 0.01).
- Проверили метрики не только mAP@0.5, но и precision@0.1, recall по классам.
- Замерили FPS на целевом устройстве (не на GPU для обучения).
- Протестировали модель на данных, которых не было в тренировочном наборе (другое освещение, другой ракурс).
- Сохранили все гиперпараметры, seed, версии библиотек для воспроизводимости.
Что дальше: когда YOLO недостаточно
YOLO - отличный инструмент, но не серебряная пуля. В каких случаях стоит посмотреть на другие архитектуры:
- Очень мелкие объекты (< 16x16 пикселей) - посмотрите на YOLO-World или DETR
- Необходимость детектировать тысячи классов - EfficientDet или Cascade R-CNN
- Ограниченные ресурсы (мобильные устройства) - NanoDet, MobileDet
- Задачи сегментации - конечно, можно использовать YOLO segmentation, но для бинарной сегментации иногда лучше подходят специализированные архитектуры
Помните историю про распознавание жестов? Там YOLO был выбран не потому, что он лучший для жестов, а потому что нужна была реальная скорость. Всегда выбирайте инструмент под задачу, а не наоборот.
Самый важный вывод из 69 часов экспериментов: не существует «волшебных» гиперпараметров. Есть системный подход, внимательность к данным и готовность потратить время на анализ, а не на слепой перебор. Начните с простого, меняйте по одному параметру, документируйте все. И через неделю у вас будет не просто обученная модель, а понимание того, как она работает.
А если хотите углубиться в оптимизацию уже обученных моделей, посмотрите статью про pruning нейросетей - те же принципы работают и для компьютерного зрения.