Назад
129

YOLO history (Part 3)

129

Введение

Здесь можно почитать о том, как начиналась наша серия статей 🙂
  • Part 1. Мы познакомились с архитектурой Yolo, ее уникальностью, сильными и слабыми сторонами YOLOv1.
  • Part 2. Мы узнали о новых трюках YOLOv2 и о том, как авторы смогли обучить модель предсказывать более 9000 классов.

“Sometimes you just kinda phone it in for a year, you know?” — а так начинается третья статья про YOLO.

Уже по первому предложению нам становится понятен тон повествования — автор общается с нами, как с другом. Почему вместо сухой научной статьи мы читаем эмоциональный текст? Дело в том, что это заключительная часть YOLO, в написании которой принимал участие ее создатель — Джозаф Редмон. Это своего рода отчет, подведение итогов полуторагодовой работы сообщества и его личных наработок, а еще исправление ошибок предыдущих версий.

А сейчас давайте посмотрим на то, что авторы и сообщество предложили нам на этот раз.

YOLOv3 (YOLOv3: An Incremental Improvement)

Как и в предыдущих статьях, изменения затронули всю архитектуру:

  • модель в основании архитектуры стала больше, вместо Darknet-19 используется Darknet-53, FPS немного просел, зато качество значительно выросло;
  • детекционная голова теперь имеет три выхода, каждый предсказывает объекты разного размера;
  • модель научилась решать задачу мультиклассификации (multilabel classification), или, как ее еще называют, “многометочной” классификации.

От Darknet-19 к Darknet-53

Первым делом авторы решили повысить точность модели, отвечающей за извлечение признаков из входного изображения (или feature extractor’a). Для удобства мы будем называть ее базовой моделью. С целью повышения точности этой модели авторы придумали специальную архитектуру — что-то между небольшим Darknet-19, который использовался в YOLOv2, и громоздкими ResNet’ами со 101 и более слоями. Больше всего Darknet-53 похожа на ResNet-52: в ней примерно столько же слоев, плюс конволюции только 3х3 и 1х1.

Рисунок 1. Архитектура Darknet-53. Каждый Convolutional на рисунке — последовательность из Conv2d (1×1 or 3×3) → batch norm → LeakyReLU

Главное отличие Darknet-53 от ResNet-52 — качество. На ImageNet’е Darknet-53 показал результат где-то между ResNet-101 и ResNet-152 (хотя он меньше первой в 2 раза и меньше второй в 3 раза!). А еще, несмотря на размер, Darknet-53 способна работать в 78 FPS. Такая точная и быстрая модель в основании — это именно то, что нужно!

Добавление шеи в архитектуру

Авторы вдохновились архитектурой Feature Pyramid Network (FPN) и решили добавить neck (шею) после базовой модели. Теперь модель все больше напоминает скелет человека, ведь у нее есть и шея, и голова 🙂

Добавление шеи позволило улучшить распознавание объектов любого размера и хорошо отделять их друг от друга. В результате получилась следующая архитектура:

Рисунок 2. Архитектура детекционной головы YOLOv3

Фактически neck — это все, кроме двух конволюционных слоев перед выходами модели. О выходах будет подробнее сказано ниже.

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

Про модель мы теперь уже все знаем, давайте познакомимся с выходами:

  1. Первый выход расположен сразу после базовой модели. Перед ним делается несколько конволюций для достижения правильного количества фичей и размера выходного тензора. К фичам мы еще вернемся, а сейчас сосредоточимся на размерах тензора. Представим, что на вход подается картинка размером 416х416. Тогда на выходе размер тензора будет 13х13, то есть итоговое изображение уменьшится в 32 раза. Для этого выхода рецептивное поле (или receptive field, термин из первой статьи) покроет обширную часть входного изображения, следовательно, выходу будет проще искать большие объекты.
  2. Затем берутся фичи из промежуточного слоя базовой модели (оранжевая стрелочка) и конкатенируются с текущей картой фичей. Чтобы тензоры совпали по размерам, текущие фичи увеличиваются в 2 раза с помощью операции upsampling. Трюк с использованием фичей из промежуточного слоя позволяет модели учитывать простые признаки, выделенные на ранних слоях, для обнаружения объектов меньшего размера (ведь на ранних слоях рецептивное поле значительно меньше). Для второго выхода был выбран слой из середины модели, поэтому он больше нацелен на поиск объектов среднего размера. Итоговый размер выходного тензора — 26х26, значит, исходное изображение уменьшится в 16 раз.
  3. Перед последним выходом процедура с увеличением карты фичей и добавлением признаков практически полностью повторяется, только промежуточный слой берется ближе ко входу модели. В результате третий выход имеет размер 52х52. И он отвечает за… самые маленькие объекты!

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

Можно попробовать посчитать самостоятельно, а потом заглянуть сюда 🙂

Для начала вспомним количество ббоксов в предыдущих версиях:

  • YOLOv1 — 98 ббоксов (7х7 — размер выходного тензора, в каждой ячейке 2 ббокса → 7*7*2 = 98).
  • YOLOv2 — 845 ббоксов (13х13 — размер выходного тензора, 5 анкеров для каждой ячейки → 13*13*5 = 845).

А теперь сделаем то же самое для YOLOv3. Мы знаем, что у модели 3 выхода размером 13х13, 26х26, 52х52 и 3 анкера для каждой ячейки. Таким образом, итоговое число ббоксов будет: (13*13 + 26*26 + 52*52)*3 = 10647.

В целом прослеживается тенденция увеличения количества ббоксов между версиями примерно в 10 раз.

А теперь мы поговорим об информации, которая на этот раз содержится в фичах.

Разбираем фичи по кусочкам

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

Информация о размерах ббоксов перекочевала из YOLOv2 без изменений. И координаты центра, и ширина, и высота предсказываются в формате смещений (освежить воспоминания можно вот тут, секция “предсказания положения ббоксов”).

Confidence score VS objectness score

В YOLOv2 параметр, отвечающий за уверенность нахождения центра объекта в текущей ячейке, назывался confidence score. В YOLOv3 его переименовали в objectness score. Фактически это тот же самый параметр, но с другим определением и лоссом. Objectness score должен быть равен 1 для ббокса, который больше пересекается с истинным ббоксом, чем все остальные предсказанные ббоксы. А лосс функция теперь — бинарная кросс-энтропия вместо квадратичного лосса, который был в YOLOv1 и YOLOv2.

Мультилейбл классификация

Еще подверглись изменениям фичи, отвечающие за принадлежность к классу. Раньше это были вероятности (все числа от 0 до 1, в сумме дающие 1) — выходы модели, пропущенные через софтмакс. В YOLOv3 авторы решили расширить возможности модели и добавить мультилейбл классификацию. Это такой тип классификации, при котором одному объекту подходит несколько лейблов. Например, картинка девушки — это и woman, и person.

Для достижения такого эффекта авторы убрали софтмакс и использовали сигмоиду для каждого выхода независимо. Таким образом, все значения фичей ограничились от 0 до 1. Далее выбирался трешхолд (обычно 0.5). Все фичи больше этого значения — лейблы для заданного ббокса.

В итоге количество фичей для датасета COCO с 80 классами равняется (4+1+80)*3 = 255.

Обучение

Авторы обучали модель с помощью ее тренировки на разных размерах, как это было в YOLOv2. Еще они делали много аугментаций данных. Кроме того, авторы сильно улучшили лосс функцию. Теперь задача классификации стала решаться за счет использования классификационных лосов, а не с помощью уменьшения квадратичного функционала:

Рисунок 3. Лосс функция для обучения YOLOv3

Часть про координаты, ширину и высоту не изменялась со времен YOLOv1. Поэтому ее разбор мы здесь опустим.

Напоминание нотации

Фигурная единица — это индикаторная функция, которая принимает значение 1 при наличии в \( i \)-ой ячейке какого-либо объекта и значение 0 при его отсутствии. Соответственно, \( 1^{obj}{ij} \) — часть лосса, которая участвует только при наличии объекта в ячейке \( ij \), а *\( 1^{noobj}{ij} \)* — при отсутствии объекта.

\( \lambda_{coord}=5 \) — вес для ячеек с объектами, \( \lambda_{noobj}=0.5 \) — вес для ячеек без объектов.

\( p_i(c) \) — исходная из разметки вероятность того, что в \( i \)-ой ячейке объект имеет класс \( c \). Она принимает значение 0 для неправильных классов и 1 для правильных.

\( \hat{p}_i(c) \) — предсказанная моделью вероятность того, что в \( i \)-ой ячейке объект имеет класс \( c \)

Objectness score

Для определения вероятности наличия центра объекта в ячейке \( ij \) мы считаем кросс-энтропию между предсказанной уверенностью модели и истинным значением (1 — для ячеек с центром объекта и 0 — для пустых).

Мультилейбл классификация

Здесь авторы также отказались от квадратичного лосса, который был в YOLOv1 и YOLOv2, и пришли к бинарной кросс-энтропии. Важно отметить: тут лосс считается по каждому из классов независимо.

Итоги

  1. На этот раз модель не смогла обогнать существующие детекторы. RetinaNet оказалась точнее, но в разы медленнее. YOLOv3 работала немного хуже, зато почти в 4 раза быстрее!
  2. Изменение детекционной головы позволило победить проблему маленьких объектов, однако по сравнению с другими решениями, YOLOv3 проседает в детекции средних и больших объектов.
  3. Итоги в цифрах: \( AP_{50} \) для YOLOv3 — 57.9 против 44.0 у YOLOv2. Для сравнения: у лучшей модели RetinaNet-ResNeXt-101-FPN скор составляет 61.1.
Рисунок 4. Результаты работы YOLOv3 на датасете COCO в сравнении с другими моделями на метрике

Забавный факт: автор решил не перерисовывать график результатов, а просто добавить YOLOv3 на график из другой работы про focal loss (он даже ссылку на нее оставил). Кроме того, в процессе сравнения они нашли баг в загрузке данных, исправление которого добавило модели около 2 mAP.

Заключение

YOLOv3 завершает трилогию статей о детекторах в реальном времени. Она подводит итог многолетней работы Джозафа Редмона над архитектурой YOLO. За это время ему удалось создать один из самых быстрых и известных детекторов современности.

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

Ссылки

Телеграм-канал

DeepSchool

Короткие посты по теории ML/DL, полезные
библиотеки и фреймворки, вопросы с собеседований
и советы, которые помогут в работе

Открыть Телеграм

Увидели ошибку?

Напишите нам в Telegram!