Определи спецификацию набора данных
До начала сбора данных спланируй сценарии, квоты, вариативность, крайние случаи и изображения фона, а затем соотнеси план с целевыми объёмами Ultralytics.
Команды без спецификации в итоге получают 5 000 хорошо освещённых дневных фотографий с одной камеры и модель, которая уже в первый день работы в эксплуатации не справляется с сумерками. Спецификация набора данных — это список необходимых изображений: каждый сценарий, который должна обрабатывать модель, количество изображений для него и редкие случаи, для которых нужно собрать дополнительные данные. На её составление уйдёт час, а её содержание определит, на что направить усилия по сбору данных.
Практические занятия
Место спецификации в процессе#
Спецификация связывает цель с камерой. Она определяет процесс сбора данных и служит документом, к которому ты возвращаешься, если первая модель не достигает целевого показателя:
Цикл возвращает тебя к спецификации, а не к настройкам обучения: недостижение целевого показателя обычно означает, что спецификация не охватила какой-то сценарий. В руководстве этапы проекта компьютерного зрения описан тот же жизненный цикл.
Запиши сценарии отдельными строками#
Сценарий — это сочетание условий съёмки, которое должна обрабатывать модель. Строки с квотами помогают увидеть пробелы ещё до того, как кто-нибудь возьмёт в руки камеру:
| Сценарий | Камеры | Места | Время суток | Условие | Квота | Примечания |
|---|---|---|---|---|---|---|
| dock-day | cam-1 — cam-4 | сектора A–C | 08:00–17:00 | любое | 1,200 | часы пиковой загрузки |
| dock-night | cam-1 — cam-4 | сектора A–C | 22:00–04:00 | любое | 400 | натриевое освещение, меньше людей |
| loading-rain | cam-2, cam-3 | сектор B | любое | только дождь | 200 | редкий, но критичный случай |
| штабель | любое | любое | любое | поддоны в штабеле выше 2 уровней | 150 | скрывает людей за собой |
| Фон | любое | любое | любое | пустой док | 150 | нет объектов, нет меток |
Если сценарий нельзя описать, он не попадёт в обучающие данные — и именно на нём модель даст сбой в эксплуатации.
Соотнеси спецификацию с целевыми объёмами#
В рекомендациях Ultralytics по достижению наилучших результатов обучения приведены практические ориентиры для эксплуатации:
| Целевой показатель | Рекомендация |
|---|---|
| Изображения на класс | ≥ 1,500 |
| Размеченные экземпляры на класс | ≥ 10,000 |
| Фоновые изображения (без меток) | 0–10% набора данных; в COCO — около 1% |
| Разнообразие | Разное время суток, сезоны, погода, освещение, углы съёмки, источники данных и камеры |
Это ориентиры для модели, готовой к эксплуатации. Для первых экспериментов достаточно нескольких сотен размеченных объектов на класс, а первая модель поможет быстрее всего понять, для каких сценариев нужно собрать больше данных. Чтобы выяснить, насколько набор данных не дотягивает до ориентира, подсчитай его объём. Этот скрипт можно запустить на COCO128 — срезе COCO из 128 изображений, который загружается автоматически:
from collections import Counter
from pathlib import Path
from ultralytics.data.utils import IMG_FORMATS, check_det_dataset, img2label_paths
IMAGES_PER_CLASS, INSTANCES_PER_CLASS = 1500, 10_000 # Ultralytics production targets
data = check_det_dataset("coco128.yaml") # downloads COCO128 (~7 MB) on first run; swap in your data YAML
images = [p for p in Path(data["train"]).rglob("*.*") if p.suffix[1:].lower() in IMG_FORMATS]
image_count, instance_count, background = Counter(), Counter(), 0
for label in map(Path, img2label_paths([str(p) for p in images])):
classes = [int(r.split()[0]) for r in label.read_text().splitlines() if r.strip()] if label.exists() else []
instance_count.update(classes)
image_count.update(set(classes))
background += not classes
print(f"{len(images)} images, {background} background ({background / len(images):.0%}, target 0-10%)")
print(f"{'class':>12} {'images':>7} {'instances':>10} {'of target':>10}")
ranked = instance_count.most_common()
for cls, n in ranked[:3] + ranked[-3:]: # best and worst covered classes
coverage = min(image_count[cls] / IMAGES_PER_CLASS, n / INSTANCES_PER_CLASS)
print(f"{data['names'][cls]:>12} {image_count[cls]:>7} {n:>10} {coverage:>10.1%}")
never_labeled = [name for i, name in data["names"].items() if i not in instance_count]
print(f"{len(never_labeled)} classes in names with zero labels: {never_labeled[:4]} ...")128 images, 2 background (2%, target 0-10%)
class images instances of target
person 61 254 2.5%
car 12 46 0.5%
cup 10 36 0.4%
bear 1 1 0.0%
banana 1 1 0.0%
skis 1 1 0.0%
9 classes in names with zero labels: ['fire hydrant', 'parking meter', 'sheep', 'cow'] ...Как это читать:
- Покрытие — меньшее из соотношения числа изображений и соотношения числа экземпляров, поскольку классу нужны оба показателя. Даже у
person, класса с наилучшим покрытием, этот показатель составляет всего 2,5% от целевого объёма для эксплуатации. - Классы с одним экземпляром (
bear,banana,skis) невозможно ни выучить, ни оценить. В своём наборе данных либо собери для них дополнительные примеры, либо исключи их из v1. - Классы без меток перечислены в YAML, но ни разу не размечены. Модель всё равно тратит ресурсы на их предсказание. Удали их из
namesили собери для них данные до начала обучения.
Охвати факторы вариативности#

В одном кадре уже есть люди на переднем и дальнем плане, велосипеды, собака и автомобили. В настоящей спецификации нужно целенаправленно предусмотреть такое разнообразие. Для каждого фактора укажи, охватывает ли его спецификация и почему он не применим; пустые строки обозначают сценарии, с которыми ты столкнёшься уже в эксплуатации:
| Измерение | Примеры |
|---|---|
| Время | День, ночь, рассвет, сумерки |
| Погода | Солнце, облачность, дождь, туман, снег |
| Освещение | Яркое, тусклое, блики, резкие тени, смешанное освещение |
| Камера | Модель, объектив, высота установки, поле зрения |
| География | Объекты, города, страны |
| Люди и операторы | Смены, команды, униформа, средства защиты |
| Варианты продукта | Артикулы, версии упаковки, цвета |
| Размер объекта | Близко и крупно, на среднем расстоянии, далеко и мелко |
| Перекрытие | Без перекрытия, частичное, сильное, за стеклом |
| Состояние оборудования | Грязные или запотевшие объективы, повреждённые поддоны, стёртая разметка на полу |
Разнообразие важнее объёма: 1 500 изображений, распределённых по этим строкам, ценнее 5 000 снимков с одной камеры в полдень.
Запланируй фоновые изображения и граничные случаи#
Фоновые изображения — это кадры без размеченных объектов, например пустая погрузочная площадка. Они учат модель распознавать отсутствие объектов и снижают число ложноположительных срабатываний.
В формате Ultralytics YOLO изображение фона — это просто изображение с пустым файлом меток или вообще без такого файла. При сканировании обучающая процедура учитывает оба варианта (… 1200 images, 90 backgrounds, 0 corrupt). Перед первой эпохой сверь это число со своей целевой долей 0–10%.
Граничные случаи — это сильное перекрытие, объекты, обрезанные краем кадра, необычная ориентация, сложенные друг на друга объекты и похожие объекты, например мачта погрузчика рядом со стальной колонной. Выдели для каждого отдельную строку квоты.
Если человек за штабелем поддонов появляется в одном кадре из 200, то в наборе данных, собранном с естественной частотой, будет около 7 таких кадров из 1 500 — слишком мало для обучения. Намеренно увеличивай долю редких случаев: их квоты должны быть намного выше, чем их доля в реальных видеозаписях.
Невозможно заранее предусмотреть все сценарии. Подготовь достаточно точную спецификацию, быстро обучи первую модель и используй её ошибки, чтобы выявить упущенные сценарии.
Показать решение
Квоты рассчитываются по целевому числу экземпляров, а не только по числу изображений. Предположим, что на парковке нужно считать объекты двух классов, а на пилотных видеозаписях в среднем 3 автомобиля и 0,5 грузовика на изображение:
| Класс | Экземпляров на изображение | Изображений для 10 000 экземпляров | Изображений для минимального объёма в 1 500 | План |
|---|---|---|---|---|
car | 3.0 | ≈ 3,300 | 1,500 | 3 300 изображений |
truck | 0.5 | ≈ 20,000 | 1,500 | Целевой сбор у въезда на погрузочную площадку, где грузовики встречаются в 10 раз чаще |
Обычных видеозаписей достаточно для автомобилей. Для грузовиков потребовалось бы 20 000 случайных изображений, поэтому в спецификацию добавляют отдельный сценарий (въезд на погрузочную площадку, будни с 06:00 до 10:00), а не собирают в шесть раз больше всего. Добавь строку для фона — около 5% (пустая парковка ночью) — и строки для граничных случаев: снегопокров и грузовики, частично выходящие за край кадра.