Сверточная нейронная сеть OverFeat
OverFeat - модель сверточной нейронной сети, описанная в [1], которая предназначена для того, чтобы одновременно (т.е. одной сетью) решать три задачи: детектировать объект, классифицировать его и уточнять положение на снимке (detection, recognition, and localization).
Стандартно сверточная сеть для классификации объектов тренируется на наборе картинок, на каждой из которых есть ровно один объект, он расположен в центре и занимает практически всю картинку. После тренировки мы получаем сеть, которую можем использовать и для детектирования объектов, используя стандартный подход скользящего окна (sliding window) на разных масштабах входного снимка. При этом кроме “точного” окна с объектом мы дополнительно получим множество окон, содержащих только какую-то часть объекта. Эта часть иногда позволяет хорошо классифицировать объект (например, в качестве такой части мы можем получить голову собаки, по которой мы классифицируем объект как “собака”). Такая избыточность полезна для решения задачи классификации, но скорее мешает при решении задач детекции и уточнении положения объекта на снимке. В статье предлагается перетренировывать последнии слои классификационной сети, чтобы дополнительно получать ограничивающий прямоугольник (bounding box) объекта.
Схема классификационной сети
Сеть для классификации выглядит примерно вот так:
На самом деле, есть четыре версии работы [1] на arXiv, плюс в работе рассматриваются два варианта сети. На рисунке схема “accurate” сети, описанной вот здесь. Мы просто зафиксируем пока такую схему сети, для удобства дальнейшего рассуждения, но в реальной работе количество каналов в слоях и размеры сверточных ядер могут несколько варьироваться, в конечном итоге для выделения особенностей (features) изображения можно взять ту сеть, которая больше подходит для конкретной задачи, нас же интересует принцип.
Тренировка классификатора
Сеть тренируется на тренировочном наборе ImageNet 2012. Картинки масштабируются таким образом, чтобы меньшая сторона изображения получилась равной 256 пикселям, затем из полученного изображения случайным образом вырезаются картинки размером 221 х 221 (5 штук на каждое изображение + горизонтально отраженные), все это собирается в минибатчи и запускается в сеть.
Классификация
Важно понимать, что часть нейронной сети до первого полносвязного слоя (FC7) может применяться к изображению почти любого размера (исключая слишком маленькие изображения). Исходя из конфигурации сети, исходное изображение разбивается на квадраты размера 221 x 221 с шагом 36 по пространственным координатам, каждый такой квадрат генерирует 1024 х 5 х 5 карту особенностей подаваемую на вход классификатора (слои FC7 - FC8 - FC9). Откуда берётся размер 221 x 221 понятно - это размер входа сети, которую мы тренировали. Шаг 36 = 2 х 3 х 2 х 3 - это перемноженные страйды слоёв Conv1, MaxPool1, MaxPool2, MaxPool6.
Важно понимать, что на вход классификатора мы не можем подать что-то по размеру отличное от того, на что этот классификатор натренирован (в данном случае 1024 x 5 x 5).
Предположим, что у нас есть изображение размера 442 х 442, на котором изображен объект, который мы намерены классифицировать. Самый простой способ - это масштабировать изображение к размеру входа натренированной сети (в нашем случае 221 x 221), прогнать его через сеть и получить отклик классификатора. Однако, возможно объект не занимает изображение целиком и уменьшая изображение в два раза мы рискуем усложнить работу классификатора.
Второй вариант: прогнать сверточную часть сети на изображении без масштабирования и получить большую карту особенностей. Теперь двигаясь по ней с шагом 1 и выбирая квадраты 5 x 5 классифицировать их, и получить вероятность для каждого из 1000 классов, для каждого поля размера 221 x 221 на исходном изображении (с шагом 36). А затем каким-то образом объединить полученную классификацию (выбрать максимум, усреднить и выбрать максимум - вариантов достаточно). Единственная оставшаяся проблема, заключается в том, что 36 слишком крупный шаг, который может привести к неправильной классификации из-за неудачного выравнивания объекта внутри той части изображения, которую сеть преобразует в карту особенностей и подаст на вход классификатору.
Авторы предлагают следующее:
-
на карте, полученной от слоя Conv6 применить MaxPool6 (с ядром 3 х 3 и страйдом 3 х 3, т.е. не перекрывающиеся квадраты) девять раз, сдвигая начальную точку на слое Conv6 на шаг 0, 1, 2 по каждой из координат
-
таким образом мы получим девять карт с выхода слоя MaxPool6.
-
для каждой из девяти карт применяем классификатор (на вход классификатора подаем 1024 х 5 х 5)
-
объединяем результаты классификаторов со всех девяти карт “перемешивая” их естественным образом по пространственным координатам.
Таким образом, мы получаем отклик для квадрата 221 х 221, сдвигаемого уже с шагом 12 по вертикали и горизонтали.
Разберем на примере:
Пример
Пусть на вход сети мы подаём изображение размера 245 х 245, тогда на выходе слоя Conv6 мы получим карту особенностей размера 17 х 17 (с 1024 каналами).
слой выход 3 x 245 x 245 Conv1 96 x 120 x 120 MaxPool1 96 x 40 x 40 Conv2 256 x 34 x 34 MaxPool2 256 x 17 x 17 Conv3 512 x 17 x 17 Conv4 512 x 17 x 17 Conv5 1024 x 17 x 17 Conv6 1024 x 17 x 17 На этой карте мы применяем MaxPool6 (т.е. maxpool на квадратах 3 x 3 без перекрытия) девять раз, сдвигаясь на (0, 0), (1, 0), …, (2, 2), получая таким образом девять карт 5 x 5, которые подаём на вход классификатора, с выхода которого наконец получаем 3 х 3 = 9 наборов вероятностей для 1000 классов.
В одномерном варианте это выглядит так:
Такой подход можно применять не только к исходному, но и к отмасштабированному изображению. Авторы предлагают 6 размеров изображения (фактически 6 масштабов), дополнительно к 221 x 221. На самом деле здесь все зависит от задачи и понимания размеров объектов на изображениях тренировочного и рабочего наборов. В статье авторы сравнивают результаты для нескольких вариантов выбора размеров изображения (масштаба).
Чтобы улучшить классификацию, авторы предлагают натренировать 7 нейронных сетей (с одинаковой структурой, но разной начальной инициализацией при тренировке) и затем результат классификации определять “голосованием” этих сетей.
Локализация
Чтобы, дополнительно к классификации, решить задачу локализации и получить прямоугольник объекта на изображении, заменим три последних полносвязных слоя, реализующие классификатор, на три слоя, которые будут решать задачу регрессии и выдавать четыре координаты прямоугольника объекта (т.е. координаты левого, верхнего, правого и нижнего ребер прямоугольника) для каждого класса.
Для тренировки веса́ всех слоёв до MaxPool6 включительно замораживаются (мы их натренировали, когда тренировали классификатор). А веса́ последних трех слоев, решающих задачу регрессии тренируются, используя $l_2$ функцию потерь между предсказанными и реальными значениями координат ребер ограничивающего прямоугольника. Функция потерь считается только для случая, когда выход последнего слоя соответствует полю на входном изображении пересекающемуся с объектом минимум на 50%. Чтобы, при использовании сети, оценка от предсказателей, которые “плохо видят объект”, не вносила ошибки в конечный результат. Так же для тренировки используются разные масштабы картинок, это позволяет получать более точные результаты предсказания прямоугольников объектов.
При работе применяется тот же приём, что и в случае с классификацией для уменьшения шага хождения по исходному изображению с 36 до 12 пикселей.
Итак, для нескольких масштабов, мы получили некоторое множество предсказаний для класса объекта на изображении. Так же для каждого масштаба, окна внутри изображения и класса получили предсказание ограничивающего прямоугольника объекта. Далее надо объединить все эти предсказания и получить один или несколько прямоугольников с соответсвующими классами объектов в них. Прежде чем перейти к рассмотрению алгоритма, который бы решил данную задачу, введём некоторые обозначения. Обозначим $O(b)$ - центр прямоугольника $b$ и определим расстояние между прямоугольниками $b_1, b_2$ как:
\[\rho(b_1, b_2) = d(O(b_1), O(b_1 \cap b_2)) + d(O(b_2), O(b_1 \cap b_2))\]здесь $d(\cdot, \cdot)$ обычное евклидово расстояние между точками на плоскости.
Определим операцию слияния двух прямоугольников $b_1, b_2$. Пусть прямоугольники заданы координатами своих ребер $b_1 = (l_{b_1}, t_{b_1}, r_{b_1}, b_{b_1})$, $b_2 = (l_{b_2}, t_{b_2}, r_{b_2}, b_{b_2})$, тогда:
\[merge(b_1, b_2) = \left( \frac {(l_{b_1} + l_{b_2})} 2, \frac {(t_{b_1} + t_{b_2})} 2, \frac {(r_{b_1} + r_{b_2})} 2, \frac {(b_{b_1} + b_{b_2})} 2 \right)\]Для слияния набора прямоугольников, в статье предлагается следующий алгоритм (я его переписал в силу своего понимания):
Жадная стратегия слияния
Для каждого масштаба проходим по всем возможным окнам классификатора (как писали выше это окна размера 221 x 221 и проходятся они с шагом 36 или 12).
Для каждого окна выбираем класс с максимальным откликом от классификатора. Так же, для данного окна и данного класса, используя вариант сети решающий задачу регресии, получаем ограничивающий прямоугольник. Таким образом, для каждого масштаба мы собираем список троек <класс, отклик, прямоугольник>. Проходя по всем масштабам собираем общий список (при этом приводим координаты прямоугольника к единому масштабу). Выбираем k классов с максимальным откликом (или с максимальным средним откликом) и удаляем из списка тройки, соответствующие классам не попавшим в k топовых.
Теперь для каждого из выбранных k классов проделываем следущее:
-
Обозначим $B$ множество пар <отклик, прямоугольник> для данного класса.
-
Повторяем следующую процедуру слияния:
-
По всем парам элементов из $B$ найдем пару с минимальным расстоянием между прямоугольниками:
\((\hat b_1, \hat b_2 ) = {\rm argmin}_{b_1 \neq b_2 \in B} \{\rho(b_1, b_2)\}\) -
Если расстояние $\rho(\hat b_1, \hat b_2 )$ между прямоугольниками, больше порога $t$ - заканчиваем работу.
-
Если расстояние между прямоугольниками меньше порога $t$, то удаляем эти прямоугольники из множества $B$ и добавляем в множество $B$ прямоугольник $\hat b = merge(\hat b_1, \hat b_2 )$. При этом отклик нового прямоугольника мы считаем как сумму откликов двух исходных прямоугольников.
Детектирование
Детектирование тренируется аналогично классификации, но при этом обрабатывается всё изображение (сверточные слои от входного размера не зависят). В отличии от задачи локализации при этом необходимо тренировать случай, отсутствия какого бы то ни было объекта. Т.е. к 1000 исходных классов добавляется еще класс негативов. Обычно, начальный набор негативных примеров для тренировки выбирают случайным образом, а затем уже частично натренированной сетью набирают более сложные негативные примеры на которых сеть ошибается и применяют процедуру bootstraping-а, т.е. добавляют эти сложные негативы в тренировочный набор. Авторы предлагают собирать сложные негативы “на лету” выбирая ошибки на тренировочных картинках, либо случайно, либо наиболее часто повторяющиеся. При том, что начальная тренировка части сети, отвечающей за выделение особенностей (слои до MaxPool6) уже к этому моменту проведена в рамках решения задачи классификации, дотренировка сети для детектирования обычно не слишком затратна по времени.
Литература
- P. Sermanet, D. Eigen, X. Zhang, M. Mathieu, R. Fergus, and Y. LeCun, “Overfeat: Integrated recognition, localization and detection using convolutional networks,” arXiv:1312.6229, 2013