С момента своего создания семейство моделей обнаружения объектов YOLO прошло долгий путь. YOLOv7 является самым последним дополнением к этому знаменитому семейству детекторов объектов с одним выстрелом на основе привязки. Он поставляется с множеством улучшений, которые включают в себя самую современную точность и скорость. В этой статье мы проведем точную настройку модели обнаружения объектов YOLOv7 на основе реального набора данных для обнаружения выбоин.

При сравнении с набором данных COCO крошечная модель YOLOv7 обеспечивает отображение более 35%, а модель YOLOv7 (обычная) обеспечивает отображение более 51%. Также не менее важно, чтобы мы получали хорошие результаты при точной настройке такой современной модели. По этой причине в этом сообщении в блоге мы проведем точную настройку YOLOv7 на основе реального набора данных для обнаружения выбоин.

Если вы совершенно новичок в YOLOv7, настоятельно рекомендуется ознакомиться со статьей YOLOv7 Object Detection Paper Объяснение и выводы. Эта вводная статья охватывает следующее.

1. Подробности об архитектуре YOLOv7

2. Обучающие эксперименты и результаты из статьи YOLOv7

3. Выполнение вывода с использованием YOLOv7 для обнаружения объектов

4. Выполнение вывода с использованием YOLOv7 для оценки позы человека

  1. Краткое описание набора данных для обнаружения выбоин

  2. Обучающие эксперименты, которые мы проведем

  3. Точная настройка YOLOv7 в наборе данных для обнаружения выбоин

    3.1. Крошечная модель YOLOv7 с фиксированным разрешением обучения

    3.2. Крошечная модель YOLOv7 с несколькими разрешениями

    3.3. Обучение с фиксированным разрешением YOLOv7

    3.4. Обучение YOLOv7 с несколькими разрешениями

  4. Выполнение вывода с использованием обученных моделей

    4.1. Вывод из видео

    4.2. Сравнение кадров в секунду

  5. Заключение

1. Краткое описание набора данных для обнаружения выбоин

В этом сообщении в блоге мы будем использовать набор данных для обнаружения выбоин, который представляет собой комбинацию двух наборов данных. Мы уже обсуждали детали набора данных в одном из предыдущих постов. Здесь мы рассмотрим некоторые важные моменты и внесенные нами изменения.

Набор данных состоит из изображений из двух разных источников. Они

После объединения набор данных теперь содержит:

  • 1265 обучающих изображений

  • 401 изображение проверки

  • 118 тестовых изображений

По сравнению с предыдущим постом об обучении выбоинам YOLOv4, набор данных в этом посте имеет небольшие различия в изображениях. Все изображения, высота которых превышала 1500 пикселей, были уменьшены в 0,3 раза. Это приводит все изображения к нормализованному разрешению почти с тем же коэффициентом.

Ниже приведены несколько аннотированных изображений из набора данных.

Изображения из набора данных обнаружения выбоин, которые мы будем использовать для точной настройки YOLOv7.
Изображения из набора данных обнаружения выбоин, которые мы будем использовать для точной настройки YOLOv7.

Набор данных содержит изображения с камер приборной панели автомобиля, а также фотографии, сделанные с портативных камер на дорогах.

2. Обучающие эксперименты, которые мы проведем

В этом сообщении в блоге мы проведем четыре обучающих эксперимента с использованием моделей YOLOv7.

  1. Мы начнем с точной настройки миниатюрной модели YOLOv7 с фиксированным разрешением.

  2. Затем мы перейдем к обучению миниатюрной модели YOLOv7 с использованием изображений с несколькими разрешениями.

  3. Далее мы будем обучать модель YOLOv7 изображениям с фиксированным разрешением.

  4. Наконец, мы будем обучать модель YOLOv7 на изображениях с несколькими разрешениями.

Мы подробно рассмотрим все настройки, параметры и модели обучения в соответствующих разделах обучения. Точная настройка модели YOLOv7 имеет свои особенности, которые требуют определенного внимания. Но мы подробно рассмотрим все моменты по мере прохождения разделов обучения модели.

3. Точная настройка YOLOv7 для набора данных обнаружения выбоин

Шаги обучения, которым мы будем следовать, предназначены для выполнения в записной книжке Jupyter. В разделе загрузки этого поста представлен блокнот Jupyter, который можно запустить одним щелчком мыши. Хотя здесь мы рассмотрим только части кода подготовки и обучения набора данных, Jupyter notebook также содержит код для визуализации данных, который вы можете использовать для углубленного изучения набора данных.

Если вы используете ОС Ubuntu, вы можете напрямую запустить ее локально, хотя для обучения моделей вам понадобится графический процессор. Если вы используете ОС Windows, вы можете запустить ноутбук на Colab, который уже предоставляет бесплатный графический процессор.

Примечание: При проведении обучающих экспериментов настоятельно рекомендуется использовать графический процессор. Обучающие эксперименты для этого сообщения в блоге проводились в среде Colab с использованием 16-гигабайтного графического процессора Tesla P100. Время обучения может варьироваться в зависимости от используемого графического процессора.

Начиная со следующего раздела, мы начнем с загрузки набора данных и настройки YOLOv7 для обучения. Затем мы перейдем к каждому из тренировочных экспериментов.

Загрузка и извлечение набора данных

Самый первый шаг - загрузить и подготовить набор данных и все файлы данных, которые нам понадобятся для обучения.

Следующая команда загружает набор данных

# Download the dataset.
!wget https://learnopencv.s3.us-west-2.amazonaws.com/pothole_dataset.zip

Давайте извлечем набор данных и посмотрим на его структуру каталогов.

# Extract the dataset.
!unzip -q pothole_dataset.zip
pothole_dataset/
├── images
│   ├── test [118 entries exceeds filelimit, not opening dir]
│   ├── train [1265 entries exceeds filelimit, not opening dir]
│   └── valid [401 entries exceeds filelimit, not opening dir]
└── labels
    ├── test [118 entries exceeds filelimit, not opening dir]
    ├── train [1265 entries exceeds filelimit, not opening dir]
    ├── valid [401 entries exceeds filelimit, not opening dir]

Для обучения YOLOv7 нам нужно, чтобы изображения и метки находились в приведенной выше структуре каталогов. Все изображения находятся в соответствующих каталогах, а все метки - в соответствующих каталогах labels. Каждое изображение имеет отдельный текстовый файл, содержащий метку класса и аннотации для каждого объекта в новой строке. Ниже приведен пример.

0 0.5497282608695652 0.5119565217391304 0.017934782608695653 0.005072463768115942
0 0.41032608695652173 0.5253623188405797 0.025 0.005797101449275362
0 0.30842391304347827 0.5282608695652173 0.014673913043478261 0.005797101449275362
0 0.1654891304347826 0.5224637681159421 0.027717391304347826 0.005797101449275362
0 0.10163043478260869 0.5286231884057971 0.01956521739130435 0.006521739130434782
0 0.07907608695652174 0.5293478260869565 0.01576086956521739 0.007971014492753623

Первое число - это метка класса. Поскольку у нас здесь только один класс, число равно 0. Остальное - координаты ограничивающей рамки в <x_center, y_center, width, height>формате. Все координаты ограничивающей рамки нормализуются в соответствии с размером изображения.

Клонирование репозитория YOLOv7

Следующим шагом является клонирование репозитория YOLOv7, чтобы мы могли получить доступ к кодовой базе для обучения моделей.

if not os.path.exists('yolov7'):
    !git clone https://github.com/WongKinYiu/yolov7.git
 
%cd yolov7
 
!pip install -r requirements.txt

В приведенном выше блоке кода мы клонируем репозиторий YOLOv7, если он еще не присутствует в текущем каталоге. Затем мы входим в каталог и устанавливаем требования.

Создание файла YAML Dataset

Как и во многих последних версиях YOLO, нам понадобится файл YAML dataset для обучения любой из моделей YOLOv7. Это .файл yaml содержит пути к наборам изображений, количество классов и имена классов.

Этот файл будет помещен в каталог yolov7/data.

%%writefile data/pothole.yaml
train: ../pothole_dataset/images/train
val: ../pothole_dataset/images/valid
test: ../pothole_dataset/images/test
 
# Classes
nc: 1  # number of classes
names: ['pothole']  # class names

Приведенный выше блок кода создает pothole.yamlфайл. Здесь содержатся пути к обучающему, проверяющему и тестовому изображению. Поскольку мы выполняем код в каталоге yolov7, пути указаны относительно этого каталога.

Если вы работали с YOLOv5, вы можете заметить, что структура файла YAML для YOLOv7 очень похожа на структуру файла YAML набора данных YOLOv5.

3.1 Обучение крошечной модели YOLOv7 с фиксированным разрешением

В этом разделе мы будем обучать модель YOLOv7-Tiny. Крошечная модель содержит чуть более 6 миллионов параметров. Для обучения модели мы будем использовать изображения с собственным базовым разрешением, которое составляет 640 × 640. Но прежде чем мы сможем начать обучение, есть несколько других деталей, о которых нам нужно позаботиться.

Сначала нам нужно загрузить модель YOLOv7-tiny.

# Download the Tiny model weights.
!wget https://github.com/WongKinYiu/yolov7/releases/download/v0.1/yolov7-tiny.pt

При этом будет загружена последняя версия модели YOLOv7-tiny, которая была предварительно обучена на наборе данных COCO.

Далее нам нужно настроить модель YOLOv7-tiny для обучения обнаружению выбоин. Внутри каталога есть несколько файлов конфигурации по умолчаниюyolov7/cfg/training/. Все они содержат конфигурацию модели. Нам нужно настроить yolov7-tiny.yamlфайл. Для этого мы создадим копию этого файла, переименуем его и соответствующим образом настроим.

Следующий блок кода создает yolov7_pothole-tiny.yamlфайл

%%writefile cfg/training/yolov7_pothole-tiny.yaml
# parameters
nc: 1  # number of classes
depth_multiple: 1.0  # model depth multiple
width_multiple: 1.0  # layer channel multiple
 
# anchors
anchors:
  - [10,13, 16,30, 33,23]  # P3/8
  - [30,61, 62,45, 59,119]  # P4/16
  - [116,90, 156,198, 373,326]  # P5/32
 
# yolov7-tiny backbone
backbone:
  # [from, number, module, args] c2, k=1, s=1, p=None, g=1, act=True
  [[-1, 1, Conv, [32, 3, 2, None, 1, nn.LeakyReLU(0.1)]],  # 0-P1/2 
  
  [-1, 1, Conv, [64, 3, 2, None, 1, nn.LeakyReLU(0.1)]],  # 1-P2/4   
  
  [-1, 1, Conv, [32, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-2, 1, Conv, [32, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-1, 1, Conv, [32, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-1, 1, Conv, [32, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  [[-1, -2, -3, -4], 1, Concat, [1]],
  [-1, 1, Conv, [64, 1, 1, None, 1, nn.LeakyReLU(0.1)]],  # 7
  
  [-1, 1, MP, []],  # 8-P3/8
  [-1, 1, Conv, [64, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-2, 1, Conv, [64, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-1, 1, Conv, [64, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-1, 1, Conv, [64, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  [[-1, -2, -3, -4], 1, Concat, [1]],
  [-1, 1, Conv, [128, 1, 1, None, 1, nn.LeakyReLU(0.1)]],  # 14
  
  [-1, 1, MP, []],  # 15-P4/16
  [-1, 1, Conv, [128, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-2, 1, Conv, [128, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-1, 1, Conv, [128, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-1, 1, Conv, [128, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  [[-1, -2, -3, -4], 1, Concat, [1]],
  [-1, 1, Conv, [256, 1, 1, None, 1, nn.LeakyReLU(0.1)]],  # 21
  
  [-1, 1, MP, []],  # 22-P5/32
  [-1, 1, Conv, [256, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-2, 1, Conv, [256, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-1, 1, Conv, [256, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-1, 1, Conv, [256, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  [[-1, -2, -3, -4], 1, Concat, [1]],
  [-1, 1, Conv, [512, 1, 1, None, 1, nn.LeakyReLU(0.1)]],  # 28
  ]
 
# yolov7-tiny head
head:
  [[-1, 1, Conv, [256, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-2, 1, Conv, [256, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-1, 1, SP, [5]],
  [-2, 1, SP, [9]],
  [-3, 1, SP, [13]],
  [[-1, -2, -3, -4], 1, Concat, [1]],
  [-1, 1, Conv, [256, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  [[-1, -7], 1, Concat, [1]],
  [-1, 1, Conv, [256, 1, 1, None, 1, nn.LeakyReLU(0.1)]],  # 37
  
  [-1, 1, Conv, [128, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-1, 1, nn.Upsample, [None, 2, 'nearest']],
  [21, 1, Conv, [128, 1, 1, None, 1, nn.LeakyReLU(0.1)]], # route backbone P4
  [[-1, -2], 1, Concat, [1]],
  
  [-1, 1, Conv, [64, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-2, 1, Conv, [64, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-1, 1, Conv, [64, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-1, 1, Conv, [64, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  [[-1, -2, -3, -4], 1, Concat, [1]],
  [-1, 1, Conv, [128, 1, 1, None, 1, nn.LeakyReLU(0.1)]],  # 47
  
  [-1, 1, Conv, [64, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-1, 1, nn.Upsample, [None, 2, 'nearest']],
  [14, 1, Conv, [64, 1, 1, None, 1, nn.LeakyReLU(0.1)]], # route backbone P3
  [[-1, -2], 1, Concat, [1]],
  
  [-1, 1, Conv, [32, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-2, 1, Conv, [32, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-1, 1, Conv, [32, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-1, 1, Conv, [32, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  [[-1, -2, -3, -4], 1, Concat, [1]],
  [-1, 1, Conv, [64, 1, 1, None, 1, nn.LeakyReLU(0.1)]],  # 57
  
  [-1, 1, Conv, [128, 3, 2, None, 1, nn.LeakyReLU(0.1)]],
  [[-1, 47], 1, Concat, [1]],
  
  [-1, 1, Conv, [64, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-2, 1, Conv, [64, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-1, 1, Conv, [64, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-1, 1, Conv, [64, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  [[-1, -2, -3, -4], 1, Concat, [1]],
  [-1, 1, Conv, [128, 1, 1, None, 1, nn.LeakyReLU(0.1)]],  # 65
  
  [-1, 1, Conv, [256, 3, 2, None, 1, nn.LeakyReLU(0.1)]],
  [[-1, 37], 1, Concat, [1]],
  
  [-1, 1, Conv, [128, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-2, 1, Conv, [128, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-1, 1, Conv, [128, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  [-1, 1, Conv, [128, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  [[-1, -2, -3, -4], 1, Concat, [1]],
  [-1, 1, Conv, [256, 1, 1, None, 1, nn.LeakyReLU(0.1)]],  # 73
      
  [57, 1, Conv, [128, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  [65, 1, Conv, [256, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  [73, 1, Conv, [512, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
 
  [[74,75,76], 1, IDetect, [nc, anchors]],   # Detect(P3, P4, P5)
  ]

Для нашей цели нам нужно только изменить количество классов (nc) на 1. Все остальные конфигурации остаются прежними. Мы также можем увидеть архитектуру модели для модели YOLOv7-tiny. Нам понадобится этот файл во время обучения, чтобы загрузить правильную архитектуру модели.

Выполнение обучающей команды

Далее мы выполним команду для обучения модели.

!python train.py --epochs 100 --workers 4 --device 0 --batch-size 32 \
--data data/pothole.yaml --img 640 640 --cfg cfg/training/yolov7_pothole-tiny.yaml \
--weights 'yolov7-tiny.pt' --name yolov7_tiny_pothole_fixed_res --hyp data/hyp.scratch.tiny.yaml

Давайте рассмотрим важные флаги в приведенной выше команде:

  • --device: Номер (идентификатор) графического процессора для обучения. Поскольку у нас только один графический процессор, значит, он равен 0.

  • --data: Это принимает путь к файлу YAML dataset.

  • --img: По умолчанию изображения будут изменены до разрешения 640 × 640 перед отправкой в сеть. Тем не менее, здесь мы указываем размер изображения.

  • --cfg: Это путь к файлу конфигурации модели, который необходим для загрузки архитектуры модели, которую мы создали незадолго до этого.

  • --weights: Этот флаг принимает путь к предварительно подготовленной модели.

  • --name: Все результаты обучения, проверки и тестирования по умолчанию сохраняются в подкаталогах внутри каталога runs. Мы можем указать имя этих подкаталогов, указав строковое имя из этого флага.

  • --hyp: Все модели в семействе YOLOv7 имеют различный набор параметров и гиперпараметров. К ним относятся скорость обучения, методы увеличения, а также интенсивность увеличения среди многих других гиперпараметров. Все они определены в их файлах гиперпараметров (файлах YAML) в каталоге yolov7/data. Здесь мы указываем путь к соответствующему файлу гиперпараметров YOLOv7-tiny model.

Другие флаги определяют количество эпох для обучения, размер пакета и количество рабочих. Вы можете настроить их в соответствии с используемым оборудованием. Здесь мы обучаем модель для 100 эпох.

Ниже приведены результаты после 100 эпох.

Epoch   gpu_mem       box       obj       cls     total    labels  img_size
    99/99     4.66G   0.02915   0.00714         0   0.03629        50       640: 100% 40/40 [01:38<00:00,  2.45s/it]
              Class      Images      Labels           P           R      mAP@.5  mAP@.5:.95: 100% 7/7 [00:12<00:00,  1.77s/it]
                all         401        1034       0.689       0.624        0.65       0.322

В наборе проверки у нас есть карта 0,65 при 0,5 IoU и 0,322 при 0,5: 0,95 IoU. Мы также можем проверить точность тестового набора, используя обученную модель, используя следующую команду

Результаты после точной настройки модели YOLOv7-tiny в наборе данных для обнаружения выбоин.
Результаты после точной настройки модели YOLOv7-tiny в наборе данных для обнаружения выбоин.

Учитывая, что мы обучили небольшую модель, это выглядит неплохо. Давайте рассмотрим

!python test.py --weights runs/train/yolov7_tiny_pothole_fixed_res/weights/best.pt --task test --data data/pothole.yaml
Class      Images      Labels           P           R      mAP@.5  mAP@.5:.95: 100% 4/4 [00:04<00:00,  1.09s/it]
                all         118         304        0.82       0.556        0.64       0.348

Мы получаем отображение 0,64 и 0,348 соответственно в тестовом наборе данных.

3.2 Обучение модели Tiny YOLOv7 с несколькими разрешениями

YOLOv7 также предоставляет возможность тренироваться с использованием изображений с несколькими разрешениями. В отличие от предыдущего обучающего эксперимента, где мы использовали фиксированное разрешение 640×640, размер изображений будет меняться каждые несколько партий.

При обучении с несколькими разрешениями нам нужно предоставить базовое разрешение (скажем, 640 × 640). Во время обучения размер изображений будет изменен до +-50%, если это базовое разрешение. Итак, для изображений размером 640 × 640 минимальное разрешение будет 320 × 320, а максимальное - 1280 × 1280. Как правило, это помогает обучить более надежную модель, особенно для случаев, когда у нас есть объекты меньшего размера, такие как этот набор данных. Но нам также нужно тренироваться дольше, поскольку набор данных становится намного сложнее из-за различных размеров.

Выполнение команды обучения

Нам просто нужно добавить один дополнительный флаг в команду обучения, чтобы обучить многомасштабную модель.

!python train.py --epochs 100 --workers 4 --device 0 --batch-size 32 \
--data data/pothole.yaml --img 640 640 --cfg cfg/training/yolov7_pothole-tiny.yaml \
--weights 'yolov7-tiny.pt' --name yolov7_tiny_pothole_multi_res --hyp data/hyp.scratch.tiny.yaml \
--multi-scale

Как вы можете видеть, все остается прежним, за исключением того, что мы добавляем флаг one –multi-scale для проведения обучения с несколькими разрешениями.

Ниже приведены результаты финальной эпохи.

Epoch   gpu_mem       box       obj       cls     total    labels  img_size
99/99     12.6G   0.03214   0.01051         0   0.04265        50       896
Class      Images      Labels           P           R      mAP@.5  mAP@.5:.95: 100% 7/7 [00:12<00:00,  1.77s/it]
all         401     0.757    0.5725    0.6255      0.31
Результаты точной настройки для YOLOv7 - крошечное обучение с несколькими разрешениями.
Результаты точной настройки для YOLOv7 - крошечное обучение с несколькими разрешениями.

Как вы можете заметить, есть еще несколько провалов по сравнению с обучением с фиксированным разрешением.

Кроме того, давайте проверим результаты теста.

!python test.py --weights runs/train/yolov7_tiny_pothole_multi_res/weights/best.pt --task test --data data/pothole.yaml
Class      Images      Labels           P           R      mAP@.5  mAP@.5:.95: 100% 4/4 [00:04<00:00,  1.04s/it]
                all         118         304       0.707       0.605       0.624       0.351

На этот раз у нас более низкая карта на 0,5 IoU. Это может быть связано с изменением размеров изображения во время обучения. Если мы будем тренироваться еще дольше, результаты будут еще лучше. Мы получим больше информации при выполнении вывода с использованием обученных моделей.

3.3 Обучение с фиксированным разрешением YOLOv7

Теперь мы начнем обучающие эксперименты с использованием обычной модели YOLOv7. Авторы называют это просто YOLOv7, и мы будем ссылаться на него, используя то же имя. Эта модель намного больше по сравнению с крошечной моделью, содержащей 37 миллионов параметров. Мы можем с уверенностью ожидать, что это даст лучшие результаты, чем предыдущие обучающие эксперименты.

Нам нужно будет выполнить несколько аналогичных настроек, которые мы сделали для модели tiny. Первым шагом является загрузка предварительно обученной модели YOLOv7.

!wget https://github.com/WongKinYiu/yolov7/releases/download/v0.1/yolov7_training.pt

Затем создайте файл конфигурации модели для пользовательского набора данных.

%%writefile cfg/training/yolov7_pothole.yaml
# parameters
nc: 1  # number of classes
depth_multiple: 1.0  # model depth multiple
width_multiple: 1.0  # layer channel multiple
 
# anchors
anchors:
  - [12,16, 19,36, 40,28]  # P3/8
  - [36,75, 76,55, 72,146]  # P4/16
  - [142,110, 192,243, 459,401]  # P5/32
 
# yolov7 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [32, 3, 1]],  # 0
  
  [-1, 1, Conv, [64, 3, 2]],  # 1-P1/2     
  [-1, 1, Conv, [64, 3, 1]],
  
  [-1, 1, Conv, [128, 3, 2]],  # 3-P2/4 
  [-1, 1, Conv, [64, 1, 1]],
  [-2, 1, Conv, [64, 1, 1]],
  [-1, 1, Conv, [64, 3, 1]],
  [-1, 1, Conv, [64, 3, 1]],
  [-1, 1, Conv, [64, 3, 1]],
  [-1, 1, Conv, [64, 3, 1]],
  [[-1, -3, -5, -6], 1, Concat, [1]],
  [-1, 1, Conv, [256, 1, 1]],  # 11
        
  [-1, 1, MP, []],
  [-1, 1, Conv, [128, 1, 1]],
  [-3, 1, Conv, [128, 1, 1]],
  [-1, 1, Conv, [128, 3, 2]],
  [[-1, -3], 1, Concat, [1]],  # 16-P3/8 
  [-1, 1, Conv, [128, 1, 1]],
  [-2, 1, Conv, [128, 1, 1]],
  [-1, 1, Conv, [128, 3, 1]],
  [-1, 1, Conv, [128, 3, 1]],
  [-1, 1, Conv, [128, 3, 1]],
  [-1, 1, Conv, [128, 3, 1]],
  [[-1, -3, -5, -6], 1, Concat, [1]],
  [-1, 1, Conv, [512, 1, 1]],  # 24
        
  [-1, 1, MP, []],
  [-1, 1, Conv, [256, 1, 1]],
  [-3, 1, Conv, [256, 1, 1]],
  [-1, 1, Conv, [256, 3, 2]],
  [[-1, -3], 1, Concat, [1]],  # 29-P4/16 
  [-1, 1, Conv, [256, 1, 1]],
  [-2, 1, Conv, [256, 1, 1]],
  [-1, 1, Conv, [256, 3, 1]],
  [-1, 1, Conv, [256, 3, 1]],
  [-1, 1, Conv, [256, 3, 1]],
  [-1, 1, Conv, [256, 3, 1]],
  [[-1, -3, -5, -6], 1, Concat, [1]],
  [-1, 1, Conv, [1024, 1, 1]],  # 37
        
  [-1, 1, MP, []],
  [-1, 1, Conv, [512, 1, 1]],
  [-3, 1, Conv, [512, 1, 1]],
  [-1, 1, Conv, [512, 3, 2]],
  [[-1, -3], 1, Concat, [1]],  # 42-P5/32 
  [-1, 1, Conv, [256, 1, 1]],
  [-2, 1, Conv, [256, 1, 1]],
  [-1, 1, Conv, [256, 3, 1]],
  [-1, 1, Conv, [256, 3, 1]],
  [-1, 1, Conv, [256, 3, 1]],
  [-1, 1, Conv, [256, 3, 1]],
  [[-1, -3, -5, -6], 1, Concat, [1]],
  [-1, 1, Conv, [1024, 1, 1]],  # 50
  ]
 
# yolov7 head
head:
  [[-1, 1, SPPCSPC, [512]], # 51
  
  [-1, 1, Conv, [256, 1, 1]],
  [-1, 1, nn.Upsample, [None, 2, 'nearest']],
  [37, 1, Conv, [256, 1, 1]], # route backbone P4
  [[-1, -2], 1, Concat, [1]],
  
  [-1, 1, Conv, [256, 1, 1]],
  [-2, 1, Conv, [256, 1, 1]],
  [-1, 1, Conv, [128, 3, 1]],
  [-1, 1, Conv, [128, 3, 1]],
  [-1, 1, Conv, [128, 3, 1]],
  [-1, 1, Conv, [128, 3, 1]],
  [[-1, -2, -3, -4, -5, -6], 1, Concat, [1]],
  [-1, 1, Conv, [256, 1, 1]], # 63
  
  [-1, 1, Conv, [128, 1, 1]],
  [-1, 1, nn.Upsample, [None, 2, 'nearest']],
  [24, 1, Conv, [128, 1, 1]], # route backbone P3
  [[-1, -2], 1, Concat, [1]],
  
  [-1, 1, Conv, [128, 1, 1]],
  [-2, 1, Conv, [128, 1, 1]],
  [-1, 1, Conv, [64, 3, 1]],
  [-1, 1, Conv, [64, 3, 1]],
  [-1, 1, Conv, [64, 3, 1]],
  [-1, 1, Conv, [64, 3, 1]],
  [[-1, -2, -3, -4, -5, -6], 1, Concat, [1]],
  [-1, 1, Conv, [128, 1, 1]], # 75
      
  [-1, 1, MP, []],
  [-1, 1, Conv, [128, 1, 1]],
  [-3, 1, Conv, [128, 1, 1]],
  [-1, 1, Conv, [128, 3, 2]],
  [[-1, -3, 63], 1, Concat, [1]],
  
  [-1, 1, Conv, [256, 1, 1]],
  [-2, 1, Conv, [256, 1, 1]],
  [-1, 1, Conv, [128, 3, 1]],
  [-1, 1, Conv, [128, 3, 1]],
  [-1, 1, Conv, [128, 3, 1]],
  [-1, 1, Conv, [128, 3, 1]],
  [[-1, -2, -3, -4, -5, -6], 1, Concat, [1]],
  [-1, 1, Conv, [256, 1, 1]], # 88
      
  [-1, 1, MP, []],
  [-1, 1, Conv, [256, 1, 1]],
  [-3, 1, Conv, [256, 1, 1]],
  [-1, 1, Conv, [256, 3, 2]],
  [[-1, -3, 51], 1, Concat, [1]],
  
  [-1, 1, Conv, [512, 1, 1]],
  [-2, 1, Conv, [512, 1, 1]],
  [-1, 1, Conv, [256, 3, 1]],
  [-1, 1, Conv, [256, 3, 1]],
  [-1, 1, Conv, [256, 3, 1]],
  [-1, 1, Conv, [256, 3, 1]],
  [[-1, -2, -3, -4, -5, -6], 1, Concat, [1]],
  [-1, 1, Conv, [512, 1, 1]], # 101
  
  [75, 1, RepConv, [256, 3, 1]],
  [88, 1, RepConv, [512, 3, 1]],
  [101, 1, RepConv, [1024, 3, 1]],
 
  [[102,103,104], 1, IDetect, [nc, anchors]],   # Detect(P3, P4, P5)
  ]

Из приведенного выше файла конфигурации ясно, что модель содержит больше слоев по сравнению с крошечной моделью.

Выполнение команды обучения

!python train.py --epochs 100 --workers 4 --device 0 --batch-size 16 --data data/pothole.yaml \
--img 640 640 --cfg cfg/training/yolov7_pothole.yaml --weights 'yolov7_training.pt' \
--name yolov7_pothole_fixed_res --hyp data/hyp.scratch.custom.yaml

Поскольку YOLOv7 - гораздо более крупная модель, мы используем пакет размером 16 для учета использования памяти графического процессора. Кроме этого, мы также соответствующим образом настраиваем флаги –weights, –name и –hyp.

Ниже показаны результаты после последней эпохи.

Epoch   gpu_mem       box       obj       cls     total    labels  img_size
    99/99     15.5G   0.02019  0.003874         0   0.02407        79       640: 100% 79/79 [01:33<00:00,  1.18s/it]
              Class      Images      Labels           P           R      mAP@.5  mAP@.5:.95: 100% 13/13 [00:10<00:00,  1.19it/s]
                all         401        1034       0.733        0.67       0.704       0.372

Мы получаем увеличение карты проверки более чем на 5% как при 0,5 IoU, так и при 0,5: 0,95 IoU.

Результаты после обучения модели YOLOv7 с использованием изображений с фиксированным разрешением.
Результаты после обучения модели YOLOv7 с использованием изображений с фиксированным разрешением.

Теперь давайте проверим результаты набора тестов.

!python test.py --weights runs/train/yolov7_pothole_fixed_res/weights/best.pt --task test --data data/pothole.yaml 
Class      Images      Labels           P           R      mAP@.5  mAP@.5:.95: 100% 4/4 [00:05<00:00,  1.36s/it]
                all         118         304       0.725       0.684       0.686       0.395

Мы получаем гораздо более высокие значения точности для тестового набора данных также при обучении более крупной модели.

3.4 Обучение YOLOv7 с несколькими разрешениями

Для заключительного обучающего эксперимента мы будем обучать модель YOLOv7 изображениям с несколькими разрешениями. В этом случае нам просто нужно добавить флаг –multi-scale и изменить название проекта.

!python train.py --epochs 100 --workers 4 --device 0 --batch-size 8 --data data/pothole.yaml \
--img 640 640 --cfg cfg/training/yolov7_pothole.yaml --weights 'yolov7_training.pt' \
--name yolov7_pothole_multi_res --hyp data/hyp.scratch.custom.yaml \
--multi-scale
Epoch   gpu_mem       box       obj       cls     total    labels  img_size
    99/99     12.4G   0.02644   0.00577         0   0.03221        36       576: 100% 158/158 [01:40<00:00,  1.57it/s]
              Class      Images      Labels           P           R      mAP@.5  mAP@.5:.95: 100% 26/26 [00:10<00:00,  2.39it/s]
                all         401        1034       0.753       0.645       0.708       0.369

Результаты кажутся почти такими же, как при обучении с фиксированным разрешением с немного более высокой картой на 0,5 IoU.

Результаты после обучения модели YOLOv7 с использованием изображений с несколькими разрешениями.
Результаты после обучения модели YOLOv7 с использованием изображений с несколькими разрешениями.

Следующий блок предназначен для выполнения теста с использованием новейшей обученной модели с несколькими разрешениями.

!python test.py --weights runs/train/yolov7_pothole_multi_res/weights/best.pt --task test --data data/pothole.yaml

Ниже приведены результаты.

Class      Images      Labels           P           R      mAP@.5  mAP@.5:.95: 100% 4/4 [00:04<00:00,  1.22s/it]
                all         118         304       0.757       0.615       0.685       0.395

Результаты здесь выглядят почти так же, как и в модели с фиксированным разрешением. Но мы можем ожидать, что обучение с несколькими разрешениями будет работать лучше, если мы будем тренироваться в течение большего количества эпох.

4. Выполнение вывода с использованием обученных моделей

У нас есть четыре обученные модели. Давайте сделаем выводы на основе этих видеороликов и проверим результаты. Для выполнения вывода мы скопировали обученные модели вместе с их соответствующими папками в клонированный каталог yolov7. Здесь мы запустим вывод и проверим выходные данные для каждой из обученных моделей.

Вы хотите знать, как YOLOv4 работает с набором данных для обнаружения выбоин? Посмотрите этот пост, где мы выполняем обнаружение выбоин с помощью YOLOv4 и Darknet.

4.1 Вывод из видео

Примечание: Все эксперименты с выводом были выполнены на графическом процессоре ноутбука GTX 1060 6GB.

Вы можете использовать ту же команду для выполнения вывода на видео по вашему выбору, изменив путь к видео.

Вывод с использованием моделей YOLOv7-Tiny

У нас есть пример видео, на котором мы можем выполнить вывод, используя следующую команду. Давайте сначала проверим использование обученной модели с фиксированным разрешением.

python detect.py --source ../../inference_data/video.mp4 --weights runs/train/yolov7_tiny_pothole_fixed_res/weights/best.pt --view-img

И следующую команду можно использовать для выполнения вывода с использованием обученной модели с несколькими разрешениями.

python detect.py --source ../../inference_data/video.mp4 --weights runs/train/yolov7_tiny_pothole_multi_res/weights/best.pt --view-img

Ниже приведен результат.

В верхней части показаны выходные данные миниатюрной модели с фиксированным разрешением, а в нижней - модели с несколькими разрешениями.

Крошечная модель с фиксированным разрешением работает хорошо. Но здесь мы видим много колебаний в обнаружениях. Это может быть связано с менее уверенным обнаружением.

Обнаружения с обученной моделью с несколькими разрешениями остаются почти такими же. Но мы можем видеть, что он может обнаружить несколько выбоин, которые находятся дальше в нескольких случаях по сравнению с обученной моделью с фиксированным разрешением.

Вывод с использованием моделей YOLOv7

Теперь давайте проверим результаты вывода обученных моделей YOLOv7 (большая модель). Начиная с обученной модели с фиксированным разрешением.

python detect.py --source ../../inference_data/video.mp4 --weights runs/train/yolov7_pothole_fixed_res/weights/best.pt --view-img

Следующая команда предназначена для вывода обученной модели с несколькими разрешениями.

python detect.py --source ../../inference_data/video.mp4 --weights runs/train/yolov7_pothole_multi_res/weights/best.pt --view-img

Эти результаты выглядят намного лучше. Выбоины, которые находятся далеко, обнаруживаются более уверенно с меньшими колебаниями в случае обученной модели с фиксированным разрешением YOLOv7.

Модель, обученная на изображениях с несколькими разрешениями, в некоторых случаях дает наилучшие результаты. Он способен обнаруживать выбоины, которые находятся намного дальше. Но мы также можем видеть несколько случаев сбоев (ложных срабатываний), когда модель обнаруживает разметку полосы движения как выбоины. Поскольку он был обучен на изображениях с несколькими разрешениями, возможно, еще большее обучение этой модели даст наилучшие результаты.

Больше сравнения выводов

В большинстве случаев при обучении с изображениями с несколькими разрешениями нам может потребоваться тренироваться дольше, чтобы получить хорошие результаты. Это необходимо, поскольку набор данных становится значительно сложнее из-за различных размеров изображений. Кроме того, модель может изучать больше изображений из-за различных функций.

По этой причине в этом разделе у нас есть результаты вывода для модели с фиксированным разрешением, которая обучалась в течение 100 эпох, и другой обученной модели с несколькими разрешениями, которая обучалась в течение 275 эпох. Результаты обнаружения были наложены друг на друга для упрощения сравнения.

Оранжевые ограничивающие рамки представляют обнаружения из обучения 100 эпох с фиксированным разрешением. А зеленые ограничивающие рамки взяты из обучения 275 эпох с несколькими разрешениями. Обе они являются моделями YOLOv7.

С одной стороны, совершенно очевидно, что модель, обученная на изображениях с фиксированным разрешением, обнаруживает выбоины, которые находятся немного дальше. Но у него также больше ложных срабатываний. С другой стороны, модель, обученная на изображениях с фиксированным разрешением, обнаруживает больше выбоин, имеет гораздо меньше ложных срабатываний, а также обнаруженные прямоугольники более ограничены вокруг выбоин.

Необходимо найти компромисс между обучением и получением наилучших результатов от обученных моделей с фиксированным разрешением и обученных моделей с несколькими разрешениями. В основном оно основано на варианте использования и наборе данных. Еще более важным является проведение нескольких экспериментов, чтобы выяснить, какие тренировочные настройки и модели работают лучше всего.

4.2. Сравнение кадров в секунду

Ниже приведен график, показывающий сравнение кадров в секунду и времени вывода (в миллисекундах) между различными моделями, для которых мы выполняли выводы в предыдущем разделе.

График, показывающий сравнение между FPS и временем вывода для разных моделей YOLOv7.
График, показывающий сравнение между FPS и временем вывода для разных моделей YOLOv7.

Вы можете получить разные результаты FPS и времени вывода в зависимости от оборудования, которое вы используете для вывода. Тем не менее, модели YOLOv7-tiny будут самыми быстрыми, независимо от того, были ли они обучены на изображениях с фиксированным разрешением или с несколькими разрешениями.

5. Заключение

В этом сообщении в блоге мы подробно рассказали о точной настройке модели YOLOv7. Мы выбрали пользовательский набор данных для обнаружения выбоин, что было довольно сложно. Затем мы обучили YOLOv7 и YOLOv7 - крошечные модели с фиксированными изображениями и изображениями с несколькими разрешениями. Мы также выполнили вывод с использованием обученных моделей, чтобы получить представление о результатах вывода в реальном времени при использовании моделей. Мы узнали, какие модели работают лучше по сравнению с другими.

Надеюсь, этот пост в блоге дал вам много информации и идей для проведения ваших собственных экспериментов по тонкой настройке YOLOv7. Поделитесь в разделе комментариев, если вам посчастливилось получить интересные результаты.

Код из статьи на github

Комментарии (6)


  1. iliketech
    22.11.2022 11:44
    +3

    О! Условно заливаем такой функционал в каждый авторегистратор, фиксируем по маршруту лужи, ямы. Отправляем данные на сервер. Обрабатываем. Показываем на интерактивной карте с фильтрацией.


    Далее мониторим самые очаги появления и анализируем причину их появления - среда, материалы, технология, нагрузки на покрытие.


    В этой же программе, на карте "дядя Больждедор с серьезными щщями на кожаном лице" из АДминистрации - назначает ремонт этого участка в режиме real-time-strategy, перетащив мышкой на место ремонта NPC в оранжевых жилетах. Если ремонты будут частыми, то "ТащMayor" сможет спросить у бухгалтерши "Тети Ячсмить" - о том, "в какую дыру постоянно тратятся деньги?"


    1. dimanosov007 Автор
      22.11.2022 12:05

      Отличная идея! надо ее предложить дяде.


    1. Javian
      22.11.2022 12:06
      +1

      На практике: Управляющая компания закупает уличные светодиодные светильники. Ставит - работают. Но чего-то дорого. Закупаем тоже самое, но без радиаторов. Ставит - перегорают через месяц. Ставим новые такие же - списываем деньги на обслуживание дома. Профит.


  1. s_f1
    22.11.2022 20:41
    +2

    Честно говоря, в шоке от видео. Что с дорогой? Будто в редакторе вырезали из российской промзоны и вставили в австралийский пригород.


  1. Mdm3
    23.11.2022 19:13
    +1

    Интересная статья. Спасибо.

    Не понял только, аугментацию оставляли или отключали?

    У меня yolov7 показала хуже результаты по точности и скорости инференса по сравнению с yolov5. Учил распознавать людей и лодки.


    1. dimanosov007 Автор
      24.11.2022 10:05

      Аугментацию они оставили вот есть в коде для обучения:

      --hyp data/hyp.scratch.tiny.yaml

      ну я сравнивал по детекции паспортов, там мне показалось как раз что YOLOv7 лучше справляется с задачей, да и обучение проходит быстрее