Простой пример реализации CNN можно найти в моем репозитории: https://github.com/mbaghou/machine_learning/blob/master/neural-network-examples/

Что такое сверточные нейронные сети и почему они важны?

Сверточные нейронные сети (ConvNets или CNN) — это категория нейронных сетей, которые доказали свою эффективность в таких областях, как распознавание и классификация изображений. ConvNets успешно распознают лица, объекты и дорожные знаки, а также улучшают зрение роботов и беспилотных автомобилей.

На Рис. 1 выше ConvNet может распознавать сцены, и система может предлагать соответствующие подписи («футболист бьет футбольный мяч»), в то время как Рис. 2 показывает пример использования ConvNet для распознавания повседневных предметов, людей и животных. В последнее время ConvNets также были эффективны в нескольких задачах обработки естественного языка (например, в классификации предложений).

Таким образом, ConvNets сегодня являются важным инструментом для большинства специалистов по машинному обучению. Однако понимание ConvNets и обучение их использованию в первый раз иногда может быть пугающим опытом. Основная цель этого сообщения в блоге — развить понимание того, как сверточные нейронные сети работают с изображениями.

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

Архитектура LeNet (1990-е)

LeNet была одной из самых первых сверточных нейронных сетей, которые помогли продвинуть область глубокого обучения. Эта новаторская работа Яна Лекуна была названа LeNet5 после многих предыдущих успешных итераций с 1988 года [3]. В то время архитектура LeNet использовалась в основном для задач распознавания символов, таких как чтение почтовых индексов, цифр и т. д.

Ниже мы разовьем интуитивное представление о том, как архитектура LeNet учится распознавать изображения. В последние годы было предложено несколько новых архитектур, которые являются улучшениями по сравнению с LeNet, но все они используют основные концепции LeNet, и их относительно легче понять, если у вас есть четкое представление о первой.

Сверточная нейронная сеть на рис. 3 похожа по архитектуре на исходную LeNet и классифицирует входное изображение по четырем категориям: собака, кошка, лодка или птица (исходная LeNet использовалась в основном для задач распознавания символов). . Как видно из рисунка выше, при получении изображения лодки в качестве входных данных сеть правильно присваивает самую высокую вероятность для лодки (0,94) среди всех четырех категорий. Сумма всех вероятностей в выходном слое должна быть равна единице (поясняется далее в этом посте).

В ConvNet есть четыре основных операции, показанные на Рис. 3 выше:

  1. свертка
  2. Нелинейность (ReLU)
  3. Объединение или субвыборка
  4. Классификация (полностью связанный слой)

Эти операции являются основными строительными блоками каждой сверточной нейронной сети, поэтому понимание того, как они работают, является важным шагом на пути к правильному пониманию сверточных сетей. Ниже мы попытаемся понять интуицию, стоящую за каждой из этих операций.

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

По сути, каждое изображение можно представить в виде матрицы значений пикселей.

Канал — общепринятый термин, используемый для обозначения определенного компонента изображения. Изображение со стандартной цифровой камеры будет иметь три канала — красный, зеленый и синий — вы можете представить их как три 2d-матрицы, наложенные друг на друга (по одной для каждого цвета), каждая из которых имеет значения пикселей в диапазоне от 0 до 255.

С другой стороны, изображение в оттенках серого имеет только один канал. Для целей этого поста мы будем рассматривать только изображения в градациях серого, поэтому у нас будет одна 2D-матрица, представляющая изображение. Значение каждого пикселя в матрице будет варьироваться от 0 до 255 — ноль указывает на черный цвет, а 255 — на белый.

Шаг свертки

ConvNets получили свое название от оператора свертки. Основной целью Convolution в случае ConvNet является извлечение признаков из входного изображения. Свертка сохраняет пространственные отношения между пикселями, изучая особенности изображения, используя маленькие квадраты входных данных. Мы не будем здесь вдаваться в математические подробности свертки, а попытаемся понять, как она работает с изображениями.

Как мы обсуждали выше, каждое изображение можно рассматривать как матрицу значений пикселей. Рассмотрим изображение 5 x 5, значения пикселей которого равны только 0 и 1 (обратите внимание, что для изображения в градациях серого значения пикселей варьируются от 0 до 255, зеленая матрица ниже — это особый случай, когда значения пикселей равны только 0 и 1):

Кроме того, рассмотрим еще одну матрицу 3 x 3, как показано ниже:

Затем свертка изображения 5 x 5 и матрицы 3 x 3 может быть вычислена, как показано на анимации на Рис. 5 ниже:

Найдите минутку, чтобы понять, как выполняются приведенные выше вычисления. Мы перемещаем оранжевую матрицу поверх нашего исходного изображения (зеленого) на 1 пиксель (также называемого «шагом») и для каждой позиции мы вычисляем поэлементное умножение (между двумя матрицами) и суммируем результаты умножения, чтобы получить окончательное целое число, которое образует один элемент выходной матрицы (розовый). Обратите внимание, что матрица 3×3 «видит» только часть входного изображения на каждом шаге.

В терминологии CNN матрица 3 × 3 называется «фильтром», «ядром» или «детектором признаков», а матрица, сформированная путем скольжения фильтра по изображению и вычисления скалярного произведения, называется «Свернутая функция», «Карта активации» или «Карта функций». Важно отметить, что фильтры действуют как детекторы признаков исходного входного изображения.

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

В таблице ниже мы можем увидеть эффекты свертки приведенного выше изображения с различными фильтрами. Как показано, мы можем выполнять такие операции, как Обнаружение краев, Резкость и Размытие, просто изменяя числовые значения нашей матрицы фильтров перед операцией свертки [8] — это означает, что разные фильтры могут обнаруживать разные функции изображения, например края, изгибы и т. д.

Еще один хороший способ понять операцию свертки — посмотреть на анимацию на рис. 6 ниже:

Фильтр (с красным контуром) скользит по входному изображению (операция свертки) для создания карты объектов. Свертка другого фильтра (с зеленым контуром) над тем же изображением дает другую карту объектов, как показано. Важно отметить, что операция свертки фиксирует локальные зависимости в исходном образе. Также обратите внимание, как эти два разных фильтра создают разные карты объектов из одного и того же исходного изображения. Помните, что изображение и два фильтра выше — это просто числовые матрицы, как мы уже обсуждали выше.

На практике CNN изучает значения этих фильтров самостоятельно в процессе обучения (хотя нам по-прежнему необходимо указать такие параметры, как количество фильтров, размер фильтра, архитектура сети и т. д., прежде чем тренировочный процесс). Чем больше у нас фильтров, тем больше признаков изображения извлекается и тем лучше наша сеть распознает закономерности в невидимых изображениях.

Размер карты признаков (свернутого признака) контролируется тремя параметрами [4], которые нам нужно определить перед выполнением шага свертки:

  • Глубина. Глубина соответствует количеству фильтров, которые мы используем для операции свертки. В сети, показанной на рис. 7, мы выполняем свертку исходного изображения лодки с использованием трех разных фильтров, в результате чего создаются три разные карты объектов, как показано на рисунке. Вы можете думать об этих трех картах объектов как о сложенных двухмерных матрицах, поэтому «глубина» карты объектов будет равна трем.

Рисунок 7

  • Шаг.Шаг — этоколичество пикселей, на которое мы перемещаем матрицу фильтра по входной матрице. Когда шаг равен 1, мы перемещаем фильтры по одному пикселю за раз. Когда шаг равен 2, фильтры прыгают на 2 пикселя за раз, когда мы перемещаем их. Наличие большего шага приведет к получению меньших карт характеристик.
  • Заполнение нулями. Иногда бывает удобно дополнить входную матрицу нулями вокруг границы, чтобы мы могли применить фильтр к граничным элементам нашей матрицы входного изображения. Приятной особенностью заполнения нулями является то, что оно позволяет нам контролировать размер карт объектов. Добавление нуля также называется широкой сверткой, а отсутствие заполнения нулями будет узкой сверткой. Это было ясно объяснено в [14].

Знакомство с нелинейностью (ReLU)

Дополнительная операция под названием ReLU использовалась после каждой операции свертки на рис. 3 выше. ReLU расшифровывается как Rectified Linear Unit и представляет собой нелинейную операцию. Его выход определяется:

Рисунок 8: операция ReLU

ReLU — это поэлементная операция (применяется к пикселю) и заменяет все отрицательные значения пикселей на карте объектов на ноль. Цель ReLU — ввести нелинейность в нашу ConvNet, поскольку большинство реальных данных, которые мы хотели бы, чтобы наша ConvNet изучала, были бы нелинейными (свертка — это линейная операция — поэлементное матричное умножение и сложение, поэтому мы учитывать нелинейность, вводя нелинейную функцию, такую ​​как ReLU).

Работу ReLU можно ясно понять из Рис. 9 ниже. На нем показана операция ReLU, примененная к одной из карт объектов, полученных на рисунке 6 выше. Выходная карта объектов здесь также называется «исправленной» картой объектов.

Рисунок 9: Работа ReLU. Источник [10]

Другие нелинейные функции, такие как tanh или sigmoid, также можно использовать вместо ReLU, но было обнаружено, что ReLU работает лучше в большинстве ситуаций.

Шаг объединения

Пространственное объединение (также называемое субдискретизацией или субдискретизацией) уменьшает размерность каждой карты объектов, но сохраняет наиболее важную информацию. Пространственное объединение может быть разных типов: Максимальное, Среднее, Сумма и т.д.

В случае Max Pooling мы определяем пространственную окрестность (например, окно 2 × 2) и берем самый большой элемент из исправленной карты объектов в этом окне. Вместо того, чтобы брать самый большой элемент, мы могли бы также взять среднее значение (среднее объединение) или сумму всех элементов в этом окне. На практике было показано, что Max Pooling работает лучше.

Рисунок 10 показывает пример операции Max Pooling на карте Rectified Feature (полученной после операции свертки + ReLU) с использованием окна 2×2.

Рисунок 10: Максимальное объединение. Источник [4]

Мы сдвигаем наше окно 2 x 2 на 2 ячейки (также называемое «шагом») и берем максимальное значение в каждой области. Как показано на Рис. 10, это уменьшает размерность нашей карты объектов.

В сети, показанной на Рис. 11, операция объединения применяется отдельно к каждой карте объектов (обратите внимание, что благодаря этому мы получаем три выходные карты из трех входных карт).

Рисунок 11: Объединение, примененное к исправленным картам объектов

Рисунок 12 показывает влияние объединения на исправленную карту объектов, которую мы получили после операции ReLU на рисунке 9 выше.

Рисунок 12: Объединение. Источник [10]

Функция объединения состоит в постепенном уменьшении пространственного размера входного представления [4]. В частности, объединение

  • делает входные представления (размер объекта) меньше и более управляемым
  • уменьшает количество параметров и вычислений в сети, поэтому контроль переобучения [4]
  • делает сеть инвариантной к небольшим преобразованиям, искажениям и переводам во входном изображении (небольшое искажение во входе не изменит выход Пулинга — так как мы берем максимальное/среднее значение в локальной окрестности).
  • помогает нам прийти к почти масштабно-инвариантному представлению нашего изображения (точный термин — эквивариантный). Это очень мощно, поскольку мы можем обнаруживать объекты на изображении независимо от того, где они расположены (подробнее см. [18] и [19]).

История до сих пор

Рисунок 13

До сих пор мы видели, как работают Convolution, ReLU и Pooling. Важно понимать, что эти слои являются основными строительными блоками любой CNN. Как показано на рисунке 13, у нас есть два набора слоев свертки, ReLU и объединения — второй слой свертки выполняет свертку на выходе первого слоя объединения с использованием шести фильтров для создания в общей сложности шести карт объектов. . Затем ReLU применяется индивидуально ко всем этим шести картам функций. Затем мы выполняем операцию Max Pooling отдельно для каждой из шести исправленных карт объектов.

Вместе эти слои извлекают полезные функции из изображений, вносят нелинейность в нашу сеть и уменьшают размерность функций, стремясь сделать функции несколько эквивалентными для масштабирования и перевода [18].

Выход 2-го уровня пула действует как вход для полностью подключенного уровня, который мы обсудим в следующем разделе.

Полностью подключенный слой

Слой Fully Connected — это традиционный многослойный персептрон, который использует функцию активации softmax в выходном слое (также можно использовать другие классификаторы, такие как SVM, но в этом посте мы будем придерживаться softmax). Термин полностью связанный подразумевает, что каждый нейрон в предыдущем слое связан с каждым нейроном в следующем слое. Я рекомендую прочитать этот пост, если вы не знакомы с многослойными персептронами.

Выходные данные сверточных слоев и слоев объединения представляют высокоуровневые функции входного изображения. Целью слоя Fully Connected является использование этих функций для классификации входного изображения по различным классам на основе набора обучающих данных. Например, задача классификации изображений, которую мы решили выполнить, имеет четыре возможных результата, как показано на Рис. 14 ниже (обратите внимание, что на Рис. 14 не показаны связи между узлами в полностью подключенном слое).

Рисунок 14: Полностью подключенный уровень — каждый узел подключен к каждому другому узлу на соседнем уровне.

Помимо классификации, добавление полносвязного слоя также является (обычно) дешевым способом изучения нелинейных комбинаций этих функций. Большинство признаков из сверточных слоев и слоев объединения могут быть хороши для задачи классификации, но комбинации этих признаков могут быть еще лучше [11].

Сумма выходных вероятностей из полносвязного слоя равна 1. Это обеспечивается использованием Softmax в качестве функции активации в выходном слое полносвязного слоя. Функция Softmax берет вектор произвольных действительных оценок и сжимает его в вектор значений от нуля до единицы, сумма которых равна единице.

Собираем все вместе — обучение с использованием обратного распространения

Как обсуждалось выше, слои Convolution + Pooling действуют как средства извлечения признаков из входного изображения, а слой Fully Connected действует как классификатор.

Обратите внимание, что на Рисунке 15 ниже, поскольку входным изображением является лодка, целевая вероятность равна 1 для класса лодки и 0 для остальных трех классов, т. е.

  • Входное изображение = лодка
  • Целевой вектор = [0, 0, 1, 0]

Рисунок 15: Обучение ConvNet

Общий процесс обучения сверточной сети можно резюмировать следующим образом:

  • Шаг 1. Мы инициализируем все фильтры и параметры/веса случайными значениями.
  • Шаг 2.Сеть берет обучающее изображение в качестве входных данных, проходит этап прямого распространения (свертка, ReLU и операции объединения вместе с прямым распространением в слое Fully Connected) и находит выходные вероятности для каждого класса.
  • Допустим, выходные вероятности для изображения лодки выше [0,2, 0,4, 0,1, 0,3]
  • Поскольку веса для первого обучающего примера назначаются случайным образом, выходные вероятности также являются случайными.
  • Шаг 3. Рассчитайте общую ошибку на выходном слое (сумма по всем 4 классам).
  • Общая ошибка = ∑ ½ (целевая вероятность — выходная вероятность) ²
  • Шаг 4. Используйте обратное распространение для вычисления градиентов ошибки по отношению ко всем весам в сети и используйте градиентный спуск для обновления всех значений фильтра / веса и значения параметров для минимизации ошибки вывода.
  • Веса корректируются пропорционально их вкладу в общую ошибку.
  • Когда то же самое изображение вводится снова, выходные вероятности теперь могут быть [0,1, 0,1, 0,7, 0,1], что ближе к целевому вектору [0, 0, 1, 0].
  • Это означает, что сеть научилась правильно классифицировать это конкретное изображение, регулируя его веса/фильтры таким образом, чтобы уменьшить ошибку вывода.
  • Такие параметры, как количество фильтров, размеры фильтров, архитектура сети и т. д., были зафиксированы до шага 1 и не меняются в процессе обучения — обновляются только значения матрицы фильтров и веса соединений.
  • Шаг 5. Повторите шаги 2–4 со всеми изображениями в тренировочном наборе.

Вышеупомянутые шаги обучают ConvNet — по сути это означает, что все веса и параметры ConvNet теперь оптимизированы для правильной классификации изображений из обучающего набора.

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

Примечание 1. Описанные выше шаги были чрезмерно упрощены, и математические детали были исключены, чтобы обеспечить интуитивное понимание процесса обучения. См. [4] и [12] для математической формулировки и полного понимания.

Примечание 2. В приведенном выше примере мы использовали два набора чередующихся слоев свертки и объединения. Обратите внимание, однако, что эти операции могут повторяться любое количество раз в одной ConvNet. Фактически, некоторые из самых эффективных ConvNet сегодня имеют десятки слоев свертки и объединения! Кроме того, нет необходимости иметь слой пула после каждого сверточного слоя. Как видно на рисунке 16 ниже, мы можем последовательно выполнять несколько операций Convolution + ReLU, прежде чем выполнять операцию объединения. Также обратите внимание, как каждый уровень ConvNet визуализируется на рисунке 16 ниже.

Рисунок 16: Источник [4]

Визуализация сверточных нейронных сетей

В целом, чем больше у нас шагов свертки, тем более сложные функции сможет научиться распознавать наша сеть. Например, в классификации изображений ConvNet может научиться обнаруживать края необработанных пикселей в первом слое, затем использовать края для обнаружения простых форм во втором слое, а затем использовать эти формы для сдерживания функций более высокого уровня, таких как формы лица. в более высоких слоях [14]. Это продемонстрировано на Рисунке 17 ниже — эти функции были изучены с использованием Сверточной сети глубокого убеждения, и рисунок включен здесь только для демонстрации идеи (это только пример: сверточные фильтры в реальной жизни могут обнаруживать объекты, которые не имеют никакого значения для человека).

Рисунок 17: Изученные функции из сверточной сети глубокого убеждения. Источник [21]

Адам Харли создал удивительные визуализации сверточной нейронной сети, обученной на базе данных рукописных цифр MNIST [13]. Я настоятельно рекомендую поиграться с этим, чтобы понять детали работы CNN.

Ниже мы увидим, как сеть работает для входа «8». Обратите внимание, что визуализация на Рис. 18 не показывает операцию ReLU отдельно.

Рисунок 18: Визуализация ConvNet, обученной рукописным цифрам. Источник [13]

Входное изображение содержит 1024 пикселя (изображение 32 x 32), а первый слой свертки (слой свертки 1) формируется путем свертки шести уникальных фильтров 5 × 5 (шаг 1) с входным изображением. Как видно, использование шести различных фильтров дает карту объектов с глубиной шесть.

За сверточным слоем 1 следует слой объединения 1, который выполняет максимальное объединение 2 × 2 (с шагом 2) отдельно по шести картам объектов в слое свертки 1. Вы можете навести указатель мыши на любой пиксель в слое объединения и наблюдать 2 x 2, он формируется на предыдущем слое свертки (показано на рис. 19). Вы заметите, что пиксель с максимальным значением (самый яркий) в сетке 2 x 2 попадает в слой объединения.

Рисунок 19: Визуализация операции объединения. Источник [13]

За уровнем объединения 1 следуют шестнадцать сверточных фильтров 5 × 5 (шаг 1), которые выполняют операцию свертки. Затем следует уровень объединения 2, который выполняет максимальное объединение 2 × 2 (с шагом 2). Эти два уровня используют те же концепции, что и описанные выше.

Затем у нас есть три полносвязных (FC) слоя. Есть:

  • 120 нейронов в первом слое FC
  • 100 нейронов во втором слое FC
  • 10 нейронов в третьем слое FC, соответствующем 10 цифрам, также называемым выходным слоем.

Обратите внимание, как на Рис. 20 каждый из 10 узлов в выходном слое подключен ко всем 100 узлам во втором полностью подключенном слое (отсюда и название «Полностью подключенный»).

Также обратите внимание, что единственная светлая вершина в выходном слое соответствует «8» — это означает, что сеть правильно классифицирует нашу рукописную цифру (более яркая вершина означает, что выход из нее выше, т. е. 8 имеет наибольшую вероятность среди всех остальных цифр). ).

Рисунок 20: Визуализация кобылок, связанных слоев. Источник [13]

3d версия этой же визуализации доступна здесь.

Другие архитектуры ConvNet

Сверточные нейронные сети существуют с начала 1990-х годов. Выше мы обсуждали LeNet, котораябыла одной из самых первых сверточных нейронных сетей. Некоторые другие влиятельные архитектуры перечислены ниже [3] [4].

  • LeNet (1990-е годы): уже упоминалось в этой статье.
  • С 1990-х по 2012 год. В период с конца 1990-х до начала 2010-х сверточная нейронная сеть находилась в стадии инкубации. По мере того как становилось доступно все больше и больше данных и вычислительных мощностей, задачи, которые могли решать сверточные нейронные сети, становились все более и более интересными.
  • AlexNet (2012 г.) — в 2012 г. Алекс Крижевский (и другие) выпустил AlexNet, который был более глубокой и более широкой версией LeNet и с большим отрывом выиграл сложный конкурс ImageNet Large Scale Visual Recognition Challenge. (ILSVRC) в 2012 году. Это был значительный прорыв по сравнению с предыдущими подходами, и нынешнее широкое применение CNN можно отнести к этой работе.
  • ZF Net (2013 г.) — победителем ILSVRC 2013 стала сверточная сеть от Мэтью Зейлера и Роба Фергуса. Он стал известен как ZFNet (сокращение от Zeiler & Fergus Net). Это было улучшение AlexNet за счет настройки гиперпараметров архитектуры.
  • GoogLeNet (2014 г.) —победителем ILSVRC 2014 стала сверточная сеть от Szegedy et al. от Google. Его основным вкладом стала разработка начального модуля, который значительно сократил количество параметров в сети (4 млн по сравнению с AlexNet с 60 млн).
  • VGGNet (2014 г.) — второе место в ILSVRC 2014 г. заняла сеть, которая стала известна как VGGNet. Его основной вклад заключался в том, что он показал, что глубина сети (количество слоев) является критическим компонентом для хорошей производительности.
  • ResNets (2015 г.) —Residual Network, разработанная Kaiming He (и другими), стала победителем ILSVRC 2015. ResNets в настоящее время являются самыми современными моделями сверточных нейронных сетей и являются выбором по умолчанию для использование ConvNets на практике (по состоянию на май 2016 г.).
  • DenseNet (август 2016 г.) —Недавно опубликованная Гао Хуаном (и другими) плотно связанная сверточная сеть имеет каждый уровень, непосредственно связанный с каждым другим уровнем с прямой связью. Было показано, что DenseNet обеспечивает значительные улучшения по сравнению с предыдущими современными архитектурами в пяти высококонкурентных тестовых задачах распознавания объектов. Ознакомьтесь с реализацией Torch здесь.

Вывод

В этом посте я попытался простыми словами объяснить основные концепции сверточных нейронных сетей. Есть несколько деталей, которые я упростил / пропустил, но, надеюсь, этот пост дал вам некоторое представление о том, как они работают.

Этот пост изначально был вдохновлен Понимание сверточных нейронных сетей для НЛП Денни Бритца (которую я бы рекомендовал прочитать), и ряд объяснений здесь основан на этом посте. Для более глубокого понимания некоторых из этих концепций я рекомендую вам ознакомиться с примечаниями из Стэнфордского курса по ConvNets, а также с другими превосходными ресурсами, упомянутыми в разделе Ссылки ниже. Если у вас возникли проблемы с пониманием любой из вышеперечисленных концепций или у вас есть вопросы/предложения, не стесняйтесь оставлять комментарии ниже.