YOLO history (Part 4)
- Введение
- YOLOv4 (
- Backbone’s bag-of-specials
- Cross Stage Partial (CSP) block
- Mish
- Backbone’s bag-of-freebies
- Mosaic augmentation
- CutMix
- DropBlock
- Class label smoothing
- Detector’s bag-of-specials
- Detector’s neck
- Spatial Pyramid Pooling (
- Spatial Attention Module (
- Изменения выходных фичей (Eliminate grid sensitivity)
- Изменения постпроцессинга, или
- Detector’s bag-of-freebies
- Cross mini-Batch Normalization (
- Обучение
- Другие изменения
- Итоги
- Заключение
- Ссылки
Введение
Здесь можно почитать о том, как начиналась наша серия статей 🙂
- Part 1. Мы познакомились с архитектурой YOLO, ее уникальностью, сильными и слабыми сторонами YOLOv1.
- Part 2. Узнали о новых трюках YOLOv2 и о том, как авторы смогли обучить модель предсказывать более 9000 классов.
- Part 3. Детально рассмотрели последние изменения создателя архитектуры YOLO — Джозафа Редмона.
Итак, Джозаф Редмон сообщает о прекращении работы над YOLO (по идеологическим соображениям), но не выступает против ее развития другими. После этой новости целых два года мир не увидит новой версии архитектуры. А в апреле 2020, в разгар ковида, Алексей Бочковский и группа исследователей из Тайваня выпустят новую версию YOLO.
Возникает закономерный вопрос: почему именно эти авторы? На самом деле, имя Алексея здесь появляется не случайно. Он много лет активно участвовал в развитии darknet-фреймворка (на нем написаны предыдущие YOLO), а еще создал программу для разметки с целью наиболее легкого обучения YOLOv2/v3.
Джозаф прокомментировал выход статьи:
Поэтому несмотря на смену авторов, YOLOv4 — каноничное продолжение семейства. Более того, новая архитектура полностью соответствует философии YOLO — это небольшая и быстрая модель на darknet’e, которая за один проход решает задачу детекции.
YOLOv4 (YOLOv4: Optimal Speed and Accuracy of Object Detection)
Уже с первых строк чувствуется серьезный подход авторов и их желание использовать самые топовые решения в индустрии на момент 2020 года. Сегодня нас ждет много аббревиатур, но мы с ними разберемся вместе 🙂
Изменения коснулись и архитектуры, и самого подхода к обучению и постпроцессингу. Следовательно, авторы вводят два понятия:
- Bag-of-freebies — набор методов для увеличения точности модели за счет усложнения обучения (и без влияния на скорость инференса). К таким методам относятся, например, аугментации, изменение лосса, шедулерры.
- Bag-of-specials — набор методов для увеличения точности модели за счет небольшого уменьшения скорости инференса. Это изменения в архитектуре и методы постпроцессинга.
В статье авторы экспериментируют с широким набором аугментаций и блоков. Мы сосредоточимся только на тех методах, которые повысили итоговое качество модели:
Первый столбец таблицы показывает трюки для создания и обучении бекбоуна, второй — для YOLOv4.
Backbone’s bag-of-specials
Давайте начнем распутывать клубок под названием YOLOv4 с устройства бекбоуна.
В луших традициях YOLO, в качестве бекбоуна была выбрана обновленная версия Darknet53 — CSPDarknet53. Авторы экспериментировали также с CSPResNeXt50 и EfficientNet-B3, но Darknet их победил.
Основные отличия CSPDarknet53 от Darknet53:
- использование Cross Stage Partial блоков вместо residual блоков;
- замена активации LeakyRelu на Mish.
Cross Stage Partial (CSP) block
Для начала напомним, как выглядит Darknet53:
Для улучшения качества авторы заимствовали из статьи CSPNet идею разделения фич на 2 группы и использования сверток только к одной из этих групп (правая ветка на рисунке 4). Ко второй части применяется конволюция 1х1 для выравнивания числа каналов. Затем 2 группы фичей снова конкатенируются вместе. Итоговый блок выглядит так:
Основная идея — такое устройство блока позволяет градиентам выучивать разную информацию, следовательно, ускорять процесс обучения.
В зависимости от места в сети количество CSP Res Unit-ов меняется.
Mish
Mish — это ReLU-подобная активация с непрерывной производной в районе нуля.
Математически она записывается следующим образом:
По словам авторов, замена функции активации значительно повысила точность как бекбоуна, так и детектора.
Backbone’s bag-of-freebies
Как и раньше, бекбоун обучали решать задачу классификации на ImageNet. Ради хорошего качества авторы перепробовали много трюков. Интересный факт: модель с наилучшим качеством классификации не смогла показать тот же результат в задаче детекции.
Самой лучшей классификационной моделью стала CSPResNeXt50, но среди детекторов выиграл CSPDarknet50.
Для обучения оптимального бекбоуна использовали mosaic augmentation, CutMix, DropBlock, class label smoothing. Давайте разбираться со всем по порядку 🙂
Mosaic augmentation
Основная идея аугментации — случайное совмещение 4-х картинок из датасета. Она должна научить сеть распознавать объекты без опоры на контекст. Выглядит это вот так:
Для таких картинок также меняется лейбл. При задаче классификации его изменение прямо пропорционально доле объекта каждого из классов в кадре.
Примерные лейблы для картинки выше:
labels = {
"anemone_fish": 0.2,
"ice_bear": 0.25,
"african_elephant": 0.35,
"lemon": 0.2
}
Эта аугментация применяется и в задаче детекции. Тогда для каждого из объектов или частей объектов ббокс будет уменьшен пропорционально объекту. Кроме того, авторы ввели пороговое значение, отвечающее за изменение соотношения сторон. Все ббоксы, соотношение сторон которых изменилось больше, чем на порог, удалятся.
CutMix
Идея аугментации — замена некоторой части картинки на другую картинку. Например, замена головы собаки на голову кошки, как на рисунке ниже. Такой подход также позволяет модели избежать переобучения под контекст.
Как и в случае с mosaic augmentation, лейблы заменяются пропорционально долям классов на изображении. Для примера выше итоговые лейблы будут выглядить таким образом:
labels = {
"dog": 0.6,
"cat": 0.4
}
DropBlock
Это своего рода dropout для конволюционных слоев. Поскольку в сверточных сетях есть большая пространственная корреляция, зануление случайных одиночных фичей никак не повлияет на обобщающую способность слоя. Например, на центральном изображении (рисунок 9) видно, как после зануления фичей важная пространственная информация о наличии собаки в кадре сохраняется. DropBlock, в свою очередь, позволяет занулить целые области фичей. Это побуждает модель искать новый контекст, на который можно опереться.
Class label smoothing
Class label smoothing — метод, который уменьшит переобучение модели за счет сглаживания лейблов.
На практике он заменит единицу у правильного класса в векторе лейблов на меньшее значение, например, на 0.9. Тогда из вектора labels = [0.0, 0.0, 0.0, 1.0, 0.0]
получится вектор smoothed_labels = [0.0, 0.0, 0.0, 0.9, 0.0]
.
Это поможет избежать наличия больших весов при обучении модели: теперь нет необходимости выдавать большие значения на выходе, чтобы приблизить softmax к единице (как это было в случае с обычными лейблами).
Detector’s bag-of-specials
Также как и в YOLOv3, детектор YOLOv4 можно разделить на 3 части:
- Бекбоун — CSPDarknet53.
- Шея (neck) на основе модифицированной версии Path Aggregation Network (PAN) с использованием Spatial Pyramid Pooling layer’a (SPP) и Spatial Attention Module (SAM).
- Голова (head) из YOLOv3 (3 выходных тензора разного размера).
Detector’s neck
Архитектура YOLOv3 построена на основе Feature Pyramid Network. Ее основная идея — создание UNet-образной модели со скипконекшеннами и несколькими головами. Схематично это выглядит так:
То есть сначала мы сжимаем изображение и увеличиваем количество фичей, а затем разжимаем его, добавляем фичи из начальных слоев и передаем результат на выход.
Эта структура позволяет использовать простые фичи из первых слоев сети на последних слоях. Выходные слои получают более разнообразный набор фичей, что повышает качество итоговой детекции. Однако в такой архитектуре выход с наименьшим пространственным размером(13х13) не будет дополнительно обогащен информацией с более ранних слоев. Так как чтобы добраться до этого выхода, фичи должны пройти через всю сеть (а это больше сотни слоев!) и скипконекшены в этом случае не помогут.
PAN пытается решить данную проблему за счет добавления дополнительного потока обогащения признаков:
За счет первого скипконекшена на первый выход теперь повлияют как фичи, которые прошли через всю сеть, так и фичи с ранних слоев. Это поможет сети лучше обобщать информацию. Сейчас от входа до первого выхода всего 10 слоев!
Авторы YOLOv4 использовали модифицированную реализацию PAN — вместо операции сложения в блоке аггрегации (блок “С” на рисунке 11) авторы применили конкатенацию.
Spatial Pyramid Pooling (SPP)
Этот слой сети находится сразу после CSPDarknet53. Схематично его можно представить следующим образом:
То есть к исходному набору фичей одновременно применяется несколько max pooling слоев с паддингом для сохранения изначального размера. Затем итоговые фичи конкатенируются обратно.
Идея этого слоя — получить глобальный контекст всего изображения. Ведь после бекбоуна рецептивное поле (receptive field) все еще не будет покрывать изображение целиком. В YOLO использовались пуллинги размером 13, 9 и 5.
Spatial Attention Module (SAM)
Авторы не обошли стороной и популярный на тот момент механизм внимания. Они взяли SAM за основу, убрали операции пуллинга и оставили один конволюционный слой:
После применения сигмойды значение фичей ограничится между 0 и 1, поэтому его можно воспринимать как степень важности каждой отдельно взятой фичи в исходном наборе.
Идея слоя — перевзвешивать карту фичей для выделения самых важных признаков и зануления неважных. Особенность механизма внимания в YOLO: для каждой фичи в исходном наборе подбирается уникальный вес, а не один вес для пространственного вектора фичей, как обычно.
Изменения выходных фичей (Eliminate grid sensitivity)
Итак, нам осталось поговорить о выходе сети. В статье авторы сообщают, что используют подход из YOLOv3 без изменений. На самом деле, это не совсем так. Они нашли крайний случай, где этот подход работает плохо. Давайте вспомним предыдущие части, чтобы понять суть проблемы.
На выходе из сети мы получаем около 10 тысяч векторов длиной 255 (при условии 3-х якорей на каждый выход сети: формально 3х(5+C), где C — количество классов, C=80 для COCO). Каждый вектор хранит в себе информацию о размерах ббокса, вероятность нахождения в текущей ячейке центра объекта и вероятность принадлежности к классам. Во второй части наших статей мы рассказывали, что размеры ббокса хранятся в виде смещений по формуле:
\( b_x=\sigma(t_x)+c_x\\ b_y=\sigma(t_y)+c_y\\ b_w=p_we^{t_w}\\ b_h=p_he^{t_h}\\ \)
- где \( t_x, t_y, t_w, t_h \) — предсказания модели
- \( c_x,c_y \) — координаты левого верхнего угла ячейки
- \( p_w, p_h \) — априорные значения высоты и ширины анкера
- \( \sigma \) — сигмойда
- \( b_w, \ b_h \) — размеры ббокса
- \( b_x, \ b_y \) — координаты центра ббокса соответственно
Подход работает плохо, если истинная координата центра находится на границе ячейки, то есть \( b_x = c_x \) или \( b_x = c_x + 1 \). Поскольку \( t_x \) должен принимать либо большое отрицательное значение, либо большое положительное. Другими словами, это крайние случаи, когда нам нужно либо занулить сигмойду, либо приблизить ее к единице.
Для решения проблемы авторы выполняют следующие операции: сначала определяют константу больше 1. Она называется scale_x_y
в конфиге YOLO. Итоговые размеры ббокса считаются следующим образом (для х и у одинаково):
\( b_x = (\sigma(t_x) * S — \frac{S-1}{2}) + c_x \)
\( b_y = (\sigma(t_y) * S — \frac{S-1}{2}) + c_y \)
\( b_w=p_w*(\sigma(t_w) * S)^2 \)
\( b_h=p_h*(\sigma(t_h) * S)^2 \), где S — та самая константа.
Изменения постпроцессинга, или DIoU-NMS
Вместо Non Maximum Suppression (NMS) как раньше, авторы решили использовать его улучшенную версию — Distance-IoU Non Maximum Suppression.
Главное отличие DIoU-NMS от NMS: применение Distance IoU вместо IoU.
Если IoU считает долю пересечения между ббоксами, DIoU еще учитывает расстояние между центрами ббоксов.
Формально это выглядит следующим образом:
\( IoU = \frac{B \cap B^{gt}}{B \cup B^{gt}}; \quad DIoU = IoU — \frac{\rho^2(b,\ b^{gt})}{c^2} \)
- где \( B \) — предсказанный ббокс
- \( B^{gt} \) — истинный ббокс
- \( \rho \) — евклидово расстояние между координатами центров предсказанного (\( b \)) и истинного (\( b_{gt} \)) ббоксов (красная линия на рисунке 15)
- \( с \) — длина диагонали минимального прямоугольника (синия линия на рисунке 15), покрывающего два ббокса
В результате DIoU-NMS выглядит так:
Здесь \( R_{DIoU}(M, B_i) = \frac{\rho^2(b,\ b^{gt})}{c^2} \), где \( s_i \) — уверенность, предсказанная для ббокса, а \( \varepsilon \) — трешхолд из NMS.
Тут \( M \) — ббокс c наибольшим скором, \( B_i \) — ббокс-кандидат на удаление.
Запись выше означает, что все ббоксы, DIoU которых будет больше трешхолда, удалятся.
Таким образом, добавленное расстояние позволит не удалять ббоксы, которые сильно пересекаются, но имеют большое расстояние между центрами. Это означает, что ббоксы соответствуют разным объектам на картинке.
Detector’s bag-of-freebies
Для обучения детектора авторы использовали очень много трюков: от аугментаций (Mosaic, Self-Adversarial Training) и регуляризаций (DropBlock) до особого подхода к работе с ббоксами (Eliminate grid sensitivity, Multiple anchors for single gt) и обучению сети (CIoU-loss, CmBN, Cosine annealing scheduler). Но обо всем по порядку 🙂
Для обучения детектора использовалась аугментация Self-Adversarial Training. Сначала мы делаем обычный форвард: пропускаем изображение через сеть, считаем лосс и градиенты. Затем посчитанные градиенты применяем к изображению так, чтобы максимально ухудшить предсказание сети (это еще называется self adversarial attack). На последнем этапе снова отправляем изображение в модель, считаем лосс и градиенты, а веса модели обновляются. Такая аугментация помогает модели генерализовать предсказания и избежать переобучения.
Cross mini-Batch Normalization (CmBN)
При обучении на батчах большого размера обычно используют процедуру gradient accumulation: разбивают большой батч на несколько мини-батчей, для которых поочередно делается forward модели. Затем полученные градиенты аггрегируются и применяются к модели. Обычная батч-нормализация в таком случае будет считать статистики по каждому отдельному мини-батчу, следовательно, статистики получатся очень шумными (мини-батчи маленькие по определению). CmBN же предлагает накапливать статистики следующим образом:
На картинке выше представлен пример для 4-х мини-батчей. Нам важны индексы над accumulate BN
. На первом мини-батче статистики считаются (и применяются) только по первому мини-батчу (обозначение t_3). На втором — уже по двум мини-батчам (t_3 и t_2). На следующем — по трем и так далее.
Обучение
Авторы обучили модель с помощью тренировки на разных размерах, как и в предыдущих версиях YOLO. Но они изменили лосс функцию для обработки ббоксов. Во-первых, авторы заменили квадратичный лосс, который использовался в YOLOv3 на CIoU-loss.
Мы уже разобрали выше IoU и DIoU. CIoU — модификация DIoU, которая плюсом к расстоянию между центрами учитывает соотношение сторон ббоков. Формально CIoU считается следующим образом:
\( CIoU = IoU — \frac{\rho^2(b,\ b^{gt})}{c^2} — \alpha \upsilon, \text{ где } \alpha = \frac{\upsilon}{(1-IoU) + \upsilon} \)
По словам авторов, \( \upsilon \) отвечает за консистентность соотношения сторон ббоксов:
\( \upsilon = \frac{4}{\pi^2}(arctan\frac{w^{gt}}{h_{gt}} — arctan\frac{w}{h})^2 \)
Где \( {w^{gt}}\text{ и }{h^{gt}} \) — ширина и высота истинного ббокса, а \( w \text{ и } h \) — предсказанного.
Поскольку мы хотим минимизировать функцию потерь, CIoU лосс будет записываться таким образом:
\( \mathcal{L}_{CIoU} = 1 — IoU + \frac{\rho^2(b,\ b^{gt})}{c^2} + \alpha \upsilon \)
В остальном численный расчет лосса не изменился (подробнее про него можно почитать в предыдущей части).
Другие изменения
Помимо всех вышеперечисленных трюков авторы использовали и другие:
- Сosine annealing scheduler — шедулер для изменения лернинг рейта у оптимизатора. Авторы не применяли restart, то есть learning rate постепенно уменьшался со старта обучения и до самого конца:
- Подбор гиперпараметров для сети с помощью эволюционных алгоритмов (фактически они случайным образом выбирали несколько наборов параметров для обучения модели, а затем выбирали лучшие из моделей и переобучали их).
- Использование нескольких якорей для одного истинного ббокса при расчете лосса. Так как из-за особенностей якорныых методов детекции, для целевого объекта может подходить несколько якорей, поэтому в YOLOv4 используется подход при котором в лоссе могут учитываться несколько позитиынвх пар якорь — целевой объект. Формирование таких пар определяется по следующему критерию:
IoU (truth, anchor) > IoU threshold
.
Итоги
- Авторы смогли сохранить философию YOLO и внести огромный вклад в развитие этого семейства.
- Они переосмыслили модель YOLO, что позволило достичь топ 1 качества в задаче детекции на MS COCO среди real-time моделей.
- Итоги в цифрах: \( AP_{50} \) у YOLOv4 = 64.9% против 55.3% у YOLOv3 для моделей с FPS ≥ 30.
Интересный факт: практически во всех реализациях YOLOv4 вы не найдете SAM блоков перед выходами. Его нет даже в конфиге, который авторы приложили в статье на медиуме. Если вы знаете причины — поделитесь своим мнением в комментариях 😊
Заключение
С выходом YOLOv4 Алексей и команда доказали, что семейство real-time моделей может развиваться без участия Джозафа Редмона. YOLOv4 — модель, которая идет в ногу со временем и использует самые современные (на 2020 год) решения в области (от новых блоков и аттеншенов до использования другого лосса и постпроцессинга).
Интересно, что же придумают исследователи, чтобы побить качество данной модели? Об этом мы узнаем в следующих частях серии ☺️
Ссылки
- YOLOv4: https://arxiv.org/abs/2004.10934
- Подробный пост на медиуме от авторов: https://jonathan-hui.medium.com/yolov4-c9901eaa8e61
- Архитектура сети в netron: https://netron.app/?url=https%3A%2F%2Fraw.githubusercontent.com%2FAlexeyAB%2Fdarknet%2Fmaster%2Fcfg%2Fyolov4-csp.cfg
- PAN: https://arxiv.org/abs/1803.01534
- SPP: https://arxiv.org/abs/1406.4729v4
- SAM: https://arxiv.org/abs/1807.06521v2
- DIoU-NMS: https://arxiv.org/abs/1911.08287v1
- CmBN: https://arxiv.org/pdf/2002.05712.pdf.