YOLO history (Part 5)
Введение
Погружение в дивный мир YOLO-семейства 😎
- Part 1. Знакомимся с архитектурой Yolo, её уникальностью, сильными и слабыми сторонами YOLOv1.
- Part 2. Рассказываем о трюках YOLOv2 и о том, как авторы смогли обучить модель предсказывать более 9000 классов.
- Part 3. Подробно рассматриваем нововведения от создателя архитектуры YOLO — Джозафа Редмона.
- Part 4. Разбираемся со внушительным числом аббревиатур, которые появились в новой версии YOLO после ухода Джозафа.
Развитие YOLO проходило гладко за все время существования семейства YOLO. Каждая следующая версия имела новые фишки, которые позволяли повышать планку как по скорости инференса, так и по итоговому качеству среди real-time детекторов. Даже смена авторов не помешала двигаться вперед, и YOLOv4 была достаточно тепло принята сообществом.
Извините за спойлер нашей статьи, но так не могло продолжаться вечно 🙂
Рояль в кустах
Статья про YOLOv4 появилась на архиве 23 апреля 2020 года. И, примерно через месяц, компания Ultralytics выпустила новую версию — YOLOv5! 31 мая они открыли репозиторий c моделями YOLOv5 в 4-х модификациях: s(7M), m(25.2M), l(61M) и x(123M). В скобочках указано количество параметров, для сравнения у YOLOv4 ~ 64M. Сообщество немного удивилось: неужели теперь новые версии архитектур будут выходить каждую неделю?
Однако все было не так просто. В этот же день в репозитории открылось скромное issue под названием The project should not be named yolov5! (Этот проект не должен называться yolov5). Кажется, это плохой знак, когда одно из первых issue в репозитории начинает оспаривать его имя… Так и случилось: следующие несколько недель научное сообщество (и не только) активно обсуждало, что это за модель такая, в чем разница с предыдущими моделями, и достойна ли она называться YOLOv5. У такой реакции было несколько причин:
1. Снова поменялись авторы. Если Алексей Бочковский (автор YOLOv4) имел прямое отношение к Джозафу Редмону (автору первых 3-х моделей), то Ultralytics не были широко известны. Однако их CEO, Гленн Джохер (Glenn Jocher), был упомянут в статье YOLOv4 за изобретение mosaic augmentations, также о нем хорошо отзывался Алексей:
@glenn-jocher did a lot for the development and improvements of Yolo and showed a lot of ideas, he created at least 2 very good repositories on Pytorch. Thus, he gave Yolo a long life outside of Darknet. All this hype around the Yolov5 was not raised by him.
Вольный перевод
Гленн много занимался разработкой и улучшением Yolo, был автором множества идей и создал как минимум 2 очень хороших репозитория Pytorch Поэтому он подарил Yolo долгую жизнь за пределами дакрнета. Не он поднял шумиху вокруг Yolov5.
2. Ultralytics не выпустили статьи с описанием модели, как делали все предыдущие авторы. Они обещали сделать статью до конца 2020 года:
Our current goal is to continue internal R&D throughout the remainder of 2020, and hopefully open source and publish at least a short synopsis of this to Arxiv by the end of the year.
Вольный перевод
Наша текущая цель — продолжить внутренние исследования до конца 2020 года и, будем надеяться, выложить в опенсорс и выпустить хотя бы краткий обзор в Arxiv к концу года.
Но статьи нет до сих пор 😢
Более того, в плане архитектуры новая модель практически не отличалась от YOLOv4. Единственное отличие: она была переписана на торч.
- Первоначальные метрики были плохо посчитаны. На релизе значения метрик не воспроизводились, а масло в огонь подлили ребята из roboflow со статьей YOLOv5 is here, где сделали абсолютно корявые расчеты (позже они выпустили новую статью, но лучше не стало).
Мнение Алексея Бочковского про автора статьи от roboflow
Основная дискуссия о YOLOv5 развернулась в двух issue на гитхабе. Первая в репозитории YOLOv5: о воспроизводимости результатов. Вторая в репозитории darknet: о валидности новой модели, воспроизводимости результатов и методах расчета итоговых метрик. На самом деле это любопытное обсуждение о том, как правильно сравнивать качество разных моделей, очень советую почитать на досуге 🙂
Несмотря на негативную реакцию комьюнити, Ultralytics достойно выдержали удар и провели предметную дискуссию с другими исследователями. В итоге, оказалось, что новая модель показывает качество ниже и работает медленнее, чем YOLOv4:
Казалось бы, вопрос можно закрывать, YOLOv5 — скам, расходимся.
Но у Ultralytics были свои планы: они убрали заявления о том, что YOLOv5 SOTA, исправили баги, добились воспроизводимости результатов, а также пообещали, что будут улучшать качество модели в будущем. Но главное — ребята сделали супер удобную экосистему, в которой была возможность обучать модели с нуля или брать претрейн модели для своих целей. Вероятно, именно этот аспект позволил так сильно прокачать YOLO и восстановить репутацию компании.
Что касается названия, авторы придерживались хитрой тактики: Ultralytics никогда не спорили, что именно их реализация должна называться YOLOv5 и утверждали, что готовы рассмотреть новые варианты названий, но не вступали в обсуждение нейминга. Вскоре шумиха улеглась, и название осталось при них.
YOLOv5 Reborn
Хоть Ultralytics и не выпустили статью с описанием архитектуры, в одном они не обманули: они продолжили усиленно работать над YOLOv5 и постепенно улучшать ее качество. Практически за 2 года (последний релиз, затрагивающий качество детекционной модели был 22 февраля 2022 года) YOLOv5 сделала огромный скачок вперед как по качеству, так и по скорости относительно первой версии.
нужно сравнивать с колонкой Speed V100 b32,
так как измерения делались на V100 с батчсайзом 32
Видно, что и скорость, и качество моделей заметно выросло. А еще модели стали немного меньше. Если сравнивать текущую версию со статьей YOLOv4, где \( AP^{test} \) = 43.0% и \( AP_{50} \) = 64.9%, можно сделать вывод: предыдущая версия работает значительно хуже. Напомню, YOLOv4 содержала ~64М параметров, то есть что-то среднее между l и х версиями. Эту теорию подтверждает и зоопарк моделей, который содержит разные вариации YOLOv4 из статьи (правда, там сломались все ссылки на веса).
Однако актуальная реализация YOLOv4 на torch, которая использует много трюков, придуманных в Ultralytics, показывает сравнимое, а в некоторых версиях даже лучшее качество, чем YOLOv5:
На Рисунке 4 YOLOv4 — исходная модель из статьи, а версии с припиской pacsp основаны на YOLOv4-CSP, архитектуре, представленной в следующей статье Алексея Бочковского “Scaled-YOLOv4: Scaling Cross Stage Partial Network”, которая вышла 22 февраля 2021 года. Мы не будем подробно разбирать эту версию YOLO, но ее важно упомянуть, ведь многие наработки этой статьи нашли применение в современных версиях YOLOv5.
Помимо YOLOv4-CSP в статье Scaled-YOLOv4 рассказывается о том, как можно увеличить архитектуру YOLO для эффективного обучения на больших (1280 пикселей) изображениях и выше. Такие модели обычно имеют приписку P5, P6 или P7. В репозитории Ultralytics они идут с припиской 6, например, YOLOv5l6.
Экосистема YOLOv5
Несмотря на отсутствие значительной разницы в качестве, YOLOv5 и сегодня остается одной из самых популярных open-source моделей. Почему? А все дело в экосистеме: если хотите практически не вставая с дивана сделать хорошую модельку, решающую задачу детекции (и instance segmentation в последнем релизе), то у Ultralytics все готово. Есть описание, как подготовить данные и обучить собственную модель с нуля, их модели можно удобно конвертировать практически в любые форматы, есть связки с самыми популярными сервисами для мониторинга (clearml, comet) и еще куча всего (за рекламу нам, кстати, не платили 😉).
MLOps и CICD
Немаловажным фактором при обучении моделей является среда, в которой они обучаются. Чтобы за этим следить, в экосистему были добавлены следующие вещи:
- Добавили в репозиторий прекомит хуки, проверку текущих версий библиотек;
- Добавили возможность конфигурировать архитектуру с помощью yaml на базе библиотеки kindle;
- Добавили автоматическое отображение статистик датасета и проверки на дубликаты, координаты, лишние классы и тд;
- Добавили wandb логирование и возможность просматривать ббоксы на итерациях обучения.
Как на официальном сайте, так и в интернете есть куча гайдов, как использовать модели Ultralytics практически для любых задач, поэтому мы на этом останавливаться не будем. В статье мы разберем устройство YOLOv5 и отличия модели от предыдущей версии.
Разбираем YOLOv5 по кусочкам
Глобально в YOLOv5 произошли следующие изменения:
- Замена CSP блока на С3 блок;
- Замена промежуточных блоков на С3 блоки;
- Замена SPP блока на SPPF;
- Замена функций активации во всей сети на silu (в некоторых источниках называется swish).
CSP vs C3
Давайте вспомним, как выглядели CSP блоки в YOLOv4:
С3 блок получается удалением одной конволюции 1х1 из CSP блока. Но на самом деле в YOLOv5 есть 2 типа С3 блоков:
Как мы убедимся далее, C3-skip используется только в бекбоне, а C3 — во всех остальных местах. Главное, на что стоит обратить внимание — количество параметров внутри C3 блока не делится пополам, как это делалось в C3-skip блоке. C3-skip — обозначение, придуманное нами для большей наглядности, которое нигде в литературе не используется.
Переход к C3 блоку позволил немного уменьшить все модели, при этом не потерять в качестве у всех моделей, кроме YOLOv5s (mAP до 37.0, после 36.8).
YOLOv4 vs YOLOv5 structure
Давайте посмотрим на итоговые архитектуры YOLOv4 и v5. Для примера возьмем YOLOv5l — это средняя версия, которая чуть меньше YOLOv4 (47.8M vs 64M параметров).
При сравнении архитектур видно: небольшие изменения коснулись как бекбона, CSPDarknet53, так и всей остальной части сети. В бекбоуне все CSP Residual блоки были заменены на С3-skip блоки. В шее модели все последовательные конволюции из YOLOv4 были заменены на C3 блоки, которые позволяют значительно уменьшить итоговое количество параметров в сети. Похожую замену (одиночные конволюции на CSP блоки) сделали авторы в Scaled-YOLOv4 при создании YOLOv4-CSP, о которой мы говорили выше. Более того, в статье есть вывод точного количества параметров, которое можно уменьшить таким образом. Но самое главное — эта замена значительно повышает итоговое качество!
SPP vs SPPF
Из предыдущей статьи мы знаем, что SPP слой выглядит следующим образом:
То есть к текущим фичам последовательно применяются MaxPooling’и разного размера и в итоге конкатенируются в один большой вектор фичей.
SPPF (Spatial Pyramid Pooling Fast) — это чисто инженерное изменение, переиспользование MaxPooling’а с маленьким ядром для представления MaxPooling’ов с бОльшим ядром. В коде будет выглядеть примерно так:
# Псевдокод для SPPF блока. Пример для блока SPP с 3мя ядрами: 5, 9 и 13.
def sppf(x):
cv1 = Conv(c_in, c_in//2, 1, 1) # conv, bn, silu, ks 1x1
cv2 = Conv(c_in//2, c_out, 1, 1) # conv, bn, silu, ks 1x1
maxpool = MaxPool(kernel_size=5)
x = cv1(x)
m_5 = maxpool(x)
m_9 = maxpool(m_5)
m_13 = maxpool(m_9)
return cv2(concatenate([x, m_5, m_9, m_13]))
SPP (и SPPF) можно рассматривать как разновидность CSP блока. Первый элемент в блоке — конволюция, уменьшающая число параметров в 2 раза. Далее происходит разделение на несколько веток: первая — Skip Connection, остальные — MaxPooling’и. После соединяем фичи обратно и делаем конволюцию, чтобы восстановить количество параметров.
Реализацию SPPF можно посмотреть по ссылке — тык.
Обучение
При обучении авторы использовали множество аугментаций:
- Mosaic augmentation;
- Аффинные преобразования и HSV;
- Горизонтальные флипы;
- MixUp.
Также переиспользовали множество трюков для обучения, которые в каком-то виде были у YOLOv4, например, Cosine learning rate scheduler и оптимальный набор гиперпараметров, подобранный с помощью генетического алгоритма.
И ещё новые наработки:
- Добавили возможность оптимизировать априорные размеры анкерных ббоксов для кастомных датасетов и назвали это AutoAnchor;
- Exponential Moving Average (EMA) — метод, в котором при обучении происходит усреднение параметров за последние несколько итераций. Это нужно для стабилизации тренировочного процесса;
- Mixed Precision Training — метод, в котором операции при обучении выполняются в половинной точности (например, во float16), что позволяет уменьшить затраты по памяти и ускорить обучение, иногда жертвуя точностью.
Расчет лосса
В пятой версии архитектуры Ultralytics использовали схожий с предыдущими версиями лосс, но с небольшими изменениями. Общая формула записывается следующим образом:
\( L = \lambda_1L_{cls} + \lambda_2L_{obj} + \lambda_3L_{loc} \), где
\( L_{cls} \) — классификационный лосс, представляющий собой Бинарную кросс-энтропию.
\( L_{obj} \) — objectness лосс, отвечающий за наличие объекта в конкретной части изображения. Несмотря на то, что он представлен кросс энтропией, как раньше, в YOLOv5 он считается немного по-другому.
В следующем разделе мы узнаем, что в расчете лосса не будут участвовать предсказания без объектов (для них лейбл 0). Использоваться будут только позитивные пары anchor-target, то есть пары, которые прошли порог матчинга. Для ранжирования предсказаний по качеству используется IoU (или CIoU) между предсказанием и таргетом. Если интересно, вот код — тык.
\( L_{loc} \) — локализационный лосс, отвечающий за расположение объекта относительно ячейки выходного тензора. Также, как в YOLOv4, это CIoU лосс. Порядок предсказания ббокса также не поменялся.
Так как разные выходы модели отвечают за разные по размеру объекты, авторы решили дополнительно перевзвешивать Objectness лосс для каждого выхода модели. По дефолту он выглядит следующим образом:
\( L_{obj} = 4*L_{obj}^{small} + 1*L_{obj}^{medium} + 0.4*L_{obj}^{large} \)
Дополнительно в репозитории есть возможность перебалансировать изначальные веса относительно значения лосса для каждого из выходов:
balance = [4, 1, 0.4]
# для каждого из выходов модели перебалансируем веса на основе
# посчитанного лосса
for i in range(3):
balance[i] = balance[i] * 0.9999 + 0.0001 / Lobj[i]
Совмещение истинных ббоксов (Ground Truth) с соответствующими им якорями
Так как на каждой итерации формируется новая мозайка, набор случайных картинок после аугментаций, необходимо на каждой итерации формировать новый набор anchor (target, на основе которых будет считаться лосс). Обычно такие тонкости не освещаются в литературе, но вопросы начинают возникать при работе руками. Поэтому считаем нужным об этом рассказать.
Нам дано: набор истинных ббоксов (ground truth, GT) и якоря, соответствующие каждой ячейке выходного тензора.
Нужно: для каждого истинного ббокса понять, какие якоря будут учитываться при расчете лосса.
Для этого авторы считают несколько соотношений:
\( r_w = \frac{w_{gt}}{w_{at}}; \ r_h=\frac{h_{gt}}{h_{at}} \), где
\( w_{gt} \) — ширина истинного ббокса, \( w_{at} \) — ширина якоря,
\( h_{gt} \) — высота истинного ббокса, \( h_{at} \) — высота якоря.
Затем выбирается максимальное соотношение из всех возможных:
\( r^{max}_w=max(r_w, 1/r_w); \ r^{max}_h=max(r_h, 1/r_h) \\ r^{max}=max(r^{max}_w, r^{max}_h). \)
Решение об учете якоря принимается на основе сравнения итогового соотношения с трешхолдом \( r^{max}<anchor_t \):
Важно отметить: параметр \( anchor_t \) влияет на количество позитивных примеров при обучении. Так он напрямую влияет на Precision и Recall нейронной сети. Чем больше \( anchor_t \) , тем больше якорей будет использоваться для предсказания ббоксов и участвовать в расчете лосса. Это даст нам большую полноту предсказаний, с одной стороны, но и просадку в Precision — с другой, ведь многие ббоксы будут плохо пересекаться с истинным ббоксом (например, при IOU в 0.7 такие предикты будут считаться False Positive). Если уменьшить \( anchor_t \) — может произойти ситуация, когда только один якорь будет подходить к конкретному таргету. Это позволит получить более точные ббоксы, но также и увеличит сложность обучения, так как позитивных примеров станет меньше.
Граничные условия:
0 будут учитываться в лоссе для всех ячеек, пересечение которых с ббоксом больше заданного порога.
В данном случае это левый верхний угол всех закрашенных ячеек
Итоги
- Несмотря на изначальные проблемы с качеством и скоростью новой архитектуры, Ultralytics смогли вывести модель на новый уровень, улушив mAP примерно на 6%!
- Авторы смогли сделать весомый вклад в развитие YOLO-семейства и реализовать целую экосистему вокруг своей модели.
Заключение
Выпуском YOLOv5 команда Ultralytics доказала: не всегда нужно придумывать звездолет, чтобы сделать архитектуру, которой будет пользоваться весь мир. Зачастую достаточно создать хорошую экосистему и улучшить модель по мере появления новых решений. Интересно, кто сделает следующую версию YOLO и как ее встретит сообщество? Совсем скоро расскажем в нашем канале 🙂
Ссылки
- https://github.com/ultralytics/yolov5/issues/2 — тред про название в Ultralytics;
- https://github.com/ultralytics/yolov5/issues/6 — тред про воспроизводимость результатов в Ultralytics;
- https://github.com/AlexeyAB/darknet/issues/5920 — тред в Darknet;
- https://github.com/WongKinYiu/CrossStagePartialNetworks/issues/32 — исходное сравнение качества YOLOv4 и YOLOv5;
- https://arxiv.org/abs/2011.08036 — Scaled YOLOv4.