YOLO history. Part 7
- Введение
- YOLOv7: Trainable bag-of-freebies sets new state-of-the-art for real-time object detectors (
- Efficient Layer Aggregation Network (ELAN)
- Extended Efficient Layer Aggregation Network (E-ELAN)
- Auxiliary head + Coarse-to-Fine Label Assignment
- YOLOv7. Общая схема
- YOLOv7. Результаты
- YOLOv9: Learning What You Want to Learn Using Programmable Gradient Information (
- Generalized ELAN
- Programmable Gradient Information
- Auxiliary Reversible Branch
- Multi-level Auxiliary Information
- YOLOv9. Общий вид
- YOLOv9. Обучение
- YOLOv9. Результаты
- Заключение
- Полезные ссылки
Введение
Погружение в дивный мир YOLO-семейства 😎
Part 1. Знакомимся с архитектурой YOLO, её уникальностью, сильными и слабыми сторонами YOLOv1.
Part 2. Рассказываем о трюках YOLOv2 и о том, как авторы смогли обучить модель предсказывать более 9000 классов.
Part 3. Подробно рассматриваем нововведения от создателя архитектуры YOLO — Джозафа Редмона.
Part 4. Разбираемся со внушительным числом аббревиатур, которые появились в новой версии YOLO после ухода Джозафа.
Part 5. Отвечаем на вопрос: в чём разница между 4-ой и 5-ой версиями YOLO.
Part 6. Узнаем, как сделать современный anchor-free детектор, и почему YOLOv7 вышла позже YOLOv6.
В развитии YOLO-семейства участвовало очень много исследователей. Научное сообщество улучшает его как за счёт новых номерных версий, так и с помощью моделей, не получивших порядкового номера. При этом, можно выделить две самые активные группы исследователей — Ultralytics и команда Алексея Бочковского, а также исследователи из Тайваньского Института IIS (Institute of Information Science).
Обе группы внесли огромный вклад в развитие моделей: Ultralytics создала качественную экосистему для всего семейства YOLO, а исследователи из IIS улучшили теоретическую составляющую, оптимизируя структуру модели и подходы к обучению. Каждая группа сейчас выпустила по 3 номерные части YOLO. Мы ранее познакомились с YOLOv5 (Ultralytics) и YOLOv4 (IIS), а сегодня поговорим о двух других архитектурах от IIS: YOLOv7 и YOLOv9. А в следующей части мы разберём модели от Ultralytics и сможем полноценно сравнить подходы двух групп 😎
Почему мы разбираем YOLOv7 и YOLOv9 вместе? Всё просто: это модели, выпущенные одной группой, и YOLOv9 является прямым продолжением 7-ой части.
YOLOv7: Trainable bag-of-freebies sets new state-of-the-art for real-time object detectors (arxiv)
В этой номерной версии авторы предложили два нововведения:
- использование E-ELAN блоков для эффективного масштабирования размера архитектуры и избавления от затухания градиентов;
- добавление вспомогательных голов (Auxiliary Head) во время обучения модели для более стабильного потока градиентов.
Перед тем, как мы поговорим о новом блоке, давайте узнаем, зачем нужно было его придумывать. Сделаем шаг назад и разбёремся сначала с ELAN-блоком.
Efficient Layer Aggregation Network (ELAN)
В качестве базового блока для новой модели авторы использовали идею из предыдущей статьи — YOLOR. Они исследовали способы контроля градиентного потока (gradient path), который показывает, насколько эффективно градиенты проходят от функции потерь к самым ранним слоям.
Самый простой способ увеличить градиентный поток — использовать скип-коннекшены. Но тут есть проблема: при неаккуратном применении скипов длина пути, по которому градиент проходит от выхода к какому-либо слою, может варьироваться хаотично. Например, до одних слоёв градиент может доходить за два шага (через скипы), а до других — за десять. Такой дисбаланс приводит к тому, что сеть будет обучаться неравномерно: одни слои будут обучаться слишком быстро, а другие — почти не получат сигнал.
Чтобы такого не происходило, авторы решили контролировать самый короткий и самый длинный градиентные пути (the shortest and longest gradient path).
Для этого они придумали блок, который назвали ELAN (см. Рисунок 1).
Идея: давайте построим блок так, чтобы в нём было несколько параллельных путей с разным количеством конволюций, значит, с разной длиной градиентного пути: короткие (1-2 конволюции), длинные (4-6). И самое важное — в конце все пути конкатенируются в один вектор и прогоняются через конволюцию 1х1 для выравнивания числа каналов.

В итоге короткие пути будут обучаться быстро, длинные — устойчиво, а общая конволюция 1х1 будет балансировать общий градиентный поток.
💡 Примечание: также, как и в CSP-блоках из YOLOv4, в самом начале блока фичи разделяются на 2 независимые группы по с каналов в каждой.
Главная проблема ELAN-блока — он плохо масштабируется, поскольку при увеличении модели в глубину необходимо добавлять новые конволюции внутри блока:

А при таком способе масштабирования градиентный поток у больших моделей может быть нестабильным, так как разница между коротким и длинным градиентными путями становится слишком большой.
Extended Efficient Layer Aggregation Network (E-ELAN)
E-ELAN был придуман, чтобы решить проблему с масштабированием модели за счёт групповых свёрток и более разнообразных ветвлений внутри блока.
Верхняя часть блока практически полностью совпадает с ELAN-блоком. Сначала мы разделяем фичи на 2 части по 2c каналов в каждой. Затем к каждому из наборов применяем групповые конволюции с 2-мя группами в каждой.
Нотацию 3×3, 2c, 2c, 2 можно расшифровать как:
- 3х3 — размер свёртки;
- 2с, 2с — количество входных и выходных каналов;
- 2 — количество групп.

То есть вход делится на 2 группы по с каналов, затем каждая группа обрабатывается независимо, и на выходе две группы собираются обратно.
Понять схему с групповыми свёртками может быть не так просто, поэтому есть картинка с эквивалентной реализацией через обычные свёрточные слои:

В конце блока также применяется конволюция, которая выравнивает количество каналов у выходного набора фичей, чтобы не раздувать сеть в ширину.
Auxiliary head + Coarse-to-Fine Label Assignment
Следующим нововведением стал способ обучения модели. Авторы решили использовать метод Deep supervision, известный ещё со времен GoogleNet. Это одна из первых больших свёрточных моделей, у которой было 3 выхода и для нормального обучения которой нужно было обучать каждый из них.
Адаптируя подход Deep supervision к задаче детекции, авторы YOLOv7 предложили следующее: в процессе обучения модели добавлять вспомогательные головы к предыдущим слоям в шее и обучать модель, считая лосс и пуская градиенты как из основной головы, так и через промежуточные слои. Используя такой подход, авторы позволили ранним слоям получать больше сигнала.

Чёрными блоками на картинке схематично показана архитектура сети backbone + PAN. Основные выходы модели названы Lead Head, а вспомогательные — Auxiliary или Aux Head. Таким образом, в процессе обучения мы получаем сразу два набора выходов. Сейчас у вас могли возникнуть такие вопросы, как: «А чем отличаются эти выходы? Как обучать столько голов?». Давайте разберёмся со всем по порядку 🙂
Для начала поговорим о главном отличии между выходами — они используют разные лейблы при обучении.
Идея: чтобы увеличить объём градиентов для сети, будем использовать менее строгие условия для поиска лейблов для Aux головы, а для lead головы — строгие условия, как и в других архитектурах. А для обучения модели лоссы будем учитывать с разным весом:
\(Loss = lead + 0.25 * aux\) .
Пока оставим за скобками понятие «строгость условий» и поговорим о том, как именно авторы решают задачу сопоставления предсказаний и разметки для обоих выходов. Для этого они используют выходы lead-головы как основу для матчинга, а затем распределяют лейблы между лоссами. Такой подход получил название Coarse-to-fine lead head guided label assigner.

Основное отличие между головами в процессе обучения заключается в количестве предсказаний, которые будут считаться положительными и, соответственно, учитываться в расчёте локализационной части лосса для каждого таргета (объекта).
Перед тем, как мы поговорим о способе назначения положительных предсказаний для выходов, давайте поймём, что предсказывает модель.
Тык, чтобы узнать, как получаются выходы модели
Традиционно YOLOv7 считается безъякорным детектором, но это не совсем так. В обычной YOLOv7 используются якоря как начальные приближения ббоксов, а сеть предсказывает смещения, как раньше. Итоговые предсказания считаются по следующим формулам: \begin{aligned}b_x & =\sigma\left(t_x\right) * 2-0.5+c_x \\b_y & =\sigma\left(t_y\right) * 2-0.5+c_y \\b_w & =\left(\sigma\left(t_w\right) * 2\right)^2 * p_w \\b_h & =\left(\sigma\left(t_h\right) * 2\right)^2 * p_h\end{aligned}
где \(t_x, t_y, t_w, t_h\) — предсказанные смещения для центра ббокса, ширины и высоты;
\(b_x, b_y, b_w, b_h\)— размеры предсказанного ббокса;
\(c_x, c_y\) — координаты цетра ячейки, для которой делается предсказание;
\(p_w, p_h\) — ширина и высота якоря, к которому применяются смещения.
Для каждого пикселя на выходной фичемапе по дефолту определено 3 якоря. Также помимо смещений для каждого якоря предсказываются objectness score и вероятности принадлежности к каждому из классов. Фактически основные модели YOLOv7 остаются anchor-based. Есть несколько anchor-free реализаций, например, YOLOv7-u6, которая использует decoupled TAL head, как в YOLOv6. В статьях anchor-free YOLOv7 обозначается как YOLOv7… AF, где вместо троеточия стоит размер модели.
Хорошо, с этим разобрались! Теперь узнаем, в чём отличие матчинга для lead и aux голов. В качестве основного алгоритма матчинга выступает SimOTA.
Simplified Optimal Transport Assignment (SimOTA)
Традиционно алгоритм состоит из следующих шагов:
- Фильтрация кандидатов Выбираем кандидатов, центр которых лежит внутри (или рядом) с центром таргет ббокса (GT). Кандидат — либо предсказания, либо якоря. В нашем случае это якоря.
- Вычисление матрицы стоимостей (Cost Matrix) Для каждого кандидата и GT считается стоимость сопоставления: cost = class loss + \(\lambda\) bbox loss
- Top-k Matching Для каждого GT выбирается Top-K кандидатов с наименьшим cost. Они считаются положительными. Только положительные кандидаты будут вносить вклад в регрессионную часть лосса, которая отвечает за сопоставление GT ббоксов и предсказаний.
Кандидаты, для которых не нашлось GT, будут считаться негативными. И будут только в objectness лоссе.
В YOLOv7 к традиционному алгоритму SimOTA добавляется ещё один шаг: перед фильтрацией кандидатов по положению считается соотношение сторон между GT-боксами и якорями. Если якорь отличается от порога больше, чем на заданный трешхолд, он исключается из рассмотрения. Таким образом, авторы ещё сильнее ускоряют обучение, убирая заведомо “неподходящие” якоря.
Для lead головы Top-k выбирается равное 3-м, то есть в процессе обучения мы будем выбирать для каждого GT-бокса 3 пикселя в качестве «положительных», а для aux головы — 5.

YOLOv7. Общая схема
Итак, мы разобрались со всеми нововведениями, упомянутыми в статье. Теперь давайте посмотрим на всю архитектуру целиком:

На рисунке выше видно, что глобальных изменений немного. Давайте перечислим основные:
- Использование нового блока E-ELAN. На картинке показан обычный ELAN-блок, так как не во всех моделях YOLOv7 используется E-ELAN. Точнее, в большинстве реализаций из официального репозитория применяют именно ELAN-блок.
- Несколько усложнённых блоков, например, знакомый нам по YOLOv5 SPPF-блок превратился в SPPFCSPBlock. Он сохранил изначальную идею, к нему просто добавили CSP-блок 🙂
- Блок со страшным названием — MaxPoolAndStrideConvBlock — между стейджами бекбоуна для разнообразия receptive field при понижении пространственной размерности.
- ImplicitA и ImplicitM — Implicit слои, которые были вдохновлены DenceNet’ом. Их можно интерпретировать как механизмы внимания, которые перевзвешивают фичи посредством добавления к ним обучаемого тензора:
ImplicitA(x) = x + A, где A — обучаемый тензор;ImplicitM(x) = x + M, где M — обучаемый тензор.
- Репараметризация. Авторы использовали её как отдельные блоки, так и вместо конволюций в E-ELAN. RepVGG похож на блок из YOLOv6, но без скип-конекшена. Авторы утверждали, что без него градиенты будут более разнообразные, поэтому его и убрали.
- Итоговая модель получается с использованием EMA (Exponential Moving Average), который означает, что во время обучения мы содержим 2 копии модели:
- Обычная модель со стандартным обновлением весов;
- EMA-модель, веса которой плавно обновляются в процессе обучения. Фактически мы считаем экспоненциальное скользящее среднее от весов первой модели.
- Стандартный лосс из трёх частей:
- локализационный лосс — CIoU;
- классификационный лосс — BCE или FocalLoss;
- Objectness score — BCE.
YOLOv7. Результаты
В итоге авторы получили хороший детектор, который работал на уровне SOTA-архитектур на COCO. Также они представили семейство моделей, в котором содержатся самые разнообразные версии YOLOv7:
| Название | Расшифровка | Особенности | Качество (\(AP_{test}\)) |
|---|---|---|---|
| YOLOv7 | Базовая модель | Anchor-based, обучалась без aux-head и репараметризации | 51.4 |
| YOLOv7 — Tiny | Легковесная модель | Оптимизированная версия под real-time | 38.7 |
| YOLOv7-X | Самая большая модель | Очень большая модель, которая тестировалась на картинках 640х640 | 53.1 |
| YOLOv7-W6 | Wide, 6 stages | Широкий бекбоун, используются aux head | 54.9 |
| YOLOv7-E6 | Efficient, 6 stages | Увеличена и глубина, и ширина, Efficient head, RepConv, aux head | 56 |
| YOLOv7-D6 | Depth, 6 stages | Сеть увеличена в глубину, но не обязательно в ширину | 56.6 |
| YOLOv7-E6E | Efficient ++, 6 stages | Как E6, только с репараметризацией и другой головой | 56.8 |
Она не была лучшей по качеству, так как вышедшие уже тогда Swin-трансформеры показывали высокие результаты, YOLOv7 была значительно быстрее (56 FPS на V100 YOLOv6-E6 против 9.2 у Swin).
- «6 stages» показывают глубину бекбоуна, а также косвенно указывают на количество голов. У моделей с цифрой 6 обычно 3 головы, а у моделей с цифрой 7 — 4 головы.
- Все модели с припиской -6 и обучались, и тестировались на изображениях большего разрешения (1280х1280), в отличие от обычных моделей, которые тестировались на изображениях 640х640.
YOLOv9: Learning What You Want to Learn Using Programmable Gradient Information (arxiv)
Новая модель вышла через 2 года после выхода YOLOv7 и YOLOv6, и через год после предыдущей модели YOLOv8, в феврале 2024 года. В этой части авторы решили продолжить экспериментировать как с форматом основного блока, так и с идеей обучения модели с помощью вспомогательных архитектур, как было с Auxiliary head.
Давайте поговорим об изменениях в привычном порядке:
- сначала посмотрим, как изменился основной блок, который теперь называется GELAN и представляет собой изменённый ELAN-блок;
- затем рассмотрим дополнительные структуры, которые помогали обучаться основной модели. В статье такой подход называется Programmable Gradient Information.
Generalized ELAN
В этот раз авторы не стали придумывать сложную архитектуру блока, а пошли в сторону обобщения. Они попытались объединить идеи из CSPNet и ELAN. CSP помогает модели хорошо обучаться и при этом имеет мало параметров, что уменьшает время инференса, а ELAN может контролировать поток градиентов. Объединяя два подхода, авторы получают блок, способный контролировать поток градиентов и иметь оптимальную (с точки зрения числа параметров) конфигурацию. В итоге получается блок, внутрь которого можно вставлять другие блоки! Чтобы ты мог обучать один блок, пока обучаешь другой😃

Разберём работу блока в самом простом случае: как и раньше, первой операцией происходит разделение фичей на 2 независимые группы. Затем к одной из групп последовательно применяется выбранный блок (обычно это CSP). После результаты всех блоков объединяются и проходят через свёртку 1х1 для выравнивания каналов.
В более сложных реализациях вместо transition можно ставить другие операции, например, 1х1 конволюции и др.
Programmable Gradient Information
В этой части авторы продолжают обращаться к использованию подхода Deep supervision из YOLOv7, только заходят с другой стороны. Они пытаются придумать, как обойти проблему потери информации при прохождении данных через многочисленные слои нейронной сети. Эта проблема известна как «информационное горлышко» (information bottleneck). Она может привести к искажению градиентов и, как следствие, к снижению точности модели.
В статье авторы приводят пример, как может теряться информация на изображении по мере прохождения по сети:

Мы видим, что PlainNet практически полностью теряет всю информацию после 50-го слоя. ResNet сильно размывает изображение, а вот CSP и GELAN передают данные почти без потери информации. У нас возникло много вопросов на счет такого способа сравнения блоков. Если у вас так же есть сомнения, будем ждать ваши размышления в комментариях!🙂
Помимо основного блока авторы придумали два вспомогательных метода, которые также нацелены на уменьшение потери информации при обучении модели, — Auxiliary Reversible Branch и Multi-level Auxiliary Information. Прежде, чем подробно их разобрать, давайте посмотрим на картинку:

Мы видим, что Auxiliary Reversible Branch дублирует основной бекбоун и добавляется в шею модели, а Multi-level Auxiliary Information применяется к последним блокам бекбоуна.
Auxiliary Reversible Branch
Эта ветка, в первую очередь, помогает нормально толкать градиенты при увеличении сети. Авторы утверждают, что информация, проходящая через бекбоун, и часть шеи 100% будет подвержена проблеме information bottleneck’a. Чтобы сеть всё-таки обучалась, авторы предложили использовать структуру, дающую надёжные градиенты.
Как они гарантируют надёжность? Вводят понятие «обратимой» модели (reversible). Сейчас будет чуть-чуть формул, не пугайтесь 🙂 Они нужны, чтобы понять идею «обратимости».
Если функция \(\mathbb{r}\) является обратным преобразованием функции \(\nu\), она называется обратимой функцией:
\(X = \nu(\mathbb{r}(X))\), где X — входные данные, а \(\mathbb{r}\) и \(\nu\) — обратные друг другу функции.
Использование таких функций позволит не терять информации:
\(I(X,X) = I(X, \mathbb{r}(X)) = I(X, \nu(\mathbb{r}(X)))\), где \(I\) — взаимная информация (mutual information).
Таким образом, мы можем последовательно применять обратимые функции без потери информации.
В статье авторы предлагают добавить параллельную ветку, состоящую из «обратимых» операций, которая затем соединится с шеей модели для смешения признаков. Утверждается, что на этапе обучения вспомогательная ветвь генерирует надёжные градиенты, потому что сохраняет всю полезную информацию.
На бумаге звучит хорошо, но как это сделать в реальности? В статье авторы не объясняют, из каких именно слоёв состоит «обратимая» ветвь. И в исходном коде, на первый взгляд, нет ARB-ветви. Несколько хинтов, описывающих ARB, можно найти в issues (ссылка на issue, код блоков). В итоге, как минимум один обратимый блок всё-таки есть:
- CBFuse — блок, объединяющий информацию из вспомогательной ветви с блоками основной сети.
Как и где именно он используется в сети, мы узнаем чуть позже. А пока перейдём к следующей ветке 🙂
Multi-level Auxiliary Information
Deep supervision подход, который мы обсуждали в YOLOv7, имеет один серьёзный недостаток.
В FPN и PAN-based архитектурах мы предполагаем, что разные головы будут обнаруживать объекты разного размера. Deep supervision ещё больше помогает доталкивать градиенты от отдельных голов.
Но тут возникает противоречие: используя архитектурную особенность PAN + aux head для выхода с низкоуровневыми фичами, мы отдельно учим низкоуровневые фичи (shallow features) находить маленькие объекты, помечая остальное пространство как фон. Однако из таких фичей нельзя получить хорошие высокоуровневые фичи (deep features), необходимые для обнаружения объектов разного размера.
В 9й версии, авторы решили это противоречие следующим образом: для получения более информативных фичей на ранних слоях, они добавляют aux сеть. За счет этого в архитектуру сети получается добавить несколько дополнительных путей градиентов от входа к слоям бекбоуна, что положительно сказывается на обучении архитектуры с большим количеством слоев и блоков.
Таким образом, благодаря aux сети, бекбоун больше не будет «забывать» информацию о фичах с разного уровня, а будет получать агрегированные градиенты, содержащие информацию о всех типах объектов.
Поздравляю, мы закончили с теоретической частью! 😎 Давайте теперь посмотрим, как же выглядит эта «вспомогательная» сеть (в статье она называется «интеграционной»).
YOLOv9. Общий вид
Давайте рассмотрим, как выглядит YOLOv9 вместе со вспомогательной сетью, которая называется Auxiliary:

Фактически мы обучаем сразу 2 модели: основную и вспомогательную. Но вспомогательная модель гораздо проще. В ней значительно меньше свёрточных блоков, зато много блоков, объединяющих признаки с разных уровней.
Остановимся на блоках с рисунка выше:
- основной блок в архитектуре RepNCSPELAN — GELAN блок с CSP блоками внутри;
- ADown — блок для уменьшения пространственной размерности за счёт конволюций со страйдом и пуллингов, он сильно похож на MaxPoolAndStrideConvBlock из YOLOv7;
- CBLinear — блок, фактически состоящий из одной конволюции 3х3, но имеющий важное архитектурное назначение: он разделяет фичи на независимые потоки, которые затем отправляются на разные уровни CBFuse, что приводит к эффективному распространению градиентов. Именно этот блок позволяет смешивать признаки со всех выходов.
На самом деле это только одна из вариаций вспомогательной архитектуры. Авторы экспериментировали с различными походами, даже брали Auxiliary Head из YOLOv7, которая, кстати, показала неплохие результаты.
На картинке объединены Auxiliary Reversible Branch и Multi-level Auxiliary Information в одну Auxiliary модель. В данном случае ARB представлена с помощью CBFuse блоков, которые могут быть обратимыми. Они выступают в роли агрегаторов информации, полученной с разных уровней исходного бекбоуна.
YOLOv9. Обучение
Теперь — пара слов про обучение модели. Идея такая же, как и в YOLOv7: вспомогательная часть участвует в общем лоссе с меньшим весом (0.25). При этом, все модели используют независимый алгоритм матчинга предсказаний с одинаковыми параметрами. YOLOv9 anchor-free детектор, поэтому для матчинга используется TAL — алгоритм, знакомый нам из YOLOv6.
За обучение модели отвечает трёхсоставной лосс:
- CIoU для регрессии;
- BCE для классов;
- Distribution Focal Loss (DFL).
Если первые два нам хорошо знакомы, то последний встречается впервые.
В Distribution Focal Loss традиционный подход регрессии координат заменяется на предсказание распределения вероятностей положения границ ббокса.
Для каждой координаты ббокса (их обычно 4) делаем следующие шаги в алгоритме:
- Диапазон значений разбивается на дискретные бины, и сеть предсказывает вероятность истинного размера для каждого бина.
- Обучается за счёт максимизации вероятности истинного значения координаты. То есть чем ближе предсказание к истинному значению, тем ниже лосс.
- Итоговое предсказание — математическое ожидание по предсказанному распределению.
Итоговый лосс взвешивается следующим образом:
\(L = 7.5 * L_{CIoU} + 0.5 * L_{BCE} + 1.5 * L_{dfl}\)
YOLOv9. Результаты
В итоге авторам удалось создать точную модель, которая способна работать на SOTA-уровне, с малым числом параметров за счёт обучения с помощью PGI. Малого количества параметров удалось добиться через отбрасывание вспомогательных сетей на инференсе.
Благородя этому авторы уменьшили количество параметров на 49% в сравнении с YOLOv8, при этом увеличили качество на 0.6% по метрике AP.
Вдохновившись успехами YOLOv8, авторы решили обучить модель на другие задачи. Вместе с детекцией они сразу выпустили сегментационную модель. А затем добавили и другие задачи. В ветке yolov9u (ссылка) есть модели для следующих задач:
- instance segmentation;
- oriented object detection;
- pose estimation;
- image classification;
- transformer-based object detection.
Заключение
Итак, сегодня мы познакомились с двумя новыми представителями семейства YOLO — YOLOv7 и YOLOv9. Эти архитектуры демонстрируют идею: иногда бывает полезно добавить вспомогательную сеть, которая может решить проблемы в основной архитектуре.
В следующей части мы с вами поговорим о двух моделях от Ultralytics (YOLOv8 и v11), поэтому оставайтесь с нами! 🙂
Полезные ссылки

