Вступление

В этой статье я объясню, как 2D свертки реализованы как умножение матриц. Это объяснение основано на примечаниях сверточных нейронных сетей CS231n для визуального распознавания (модуль 2). Я предполагаю, что читатель знаком с концепцией операции свертки в контексте глубокой нейронной сети. Если нет, то в этом репо есть отчет и отличные анимации, объясняющие, что такое свертки. Код для воспроизведения вычислений в этой статье можно скачать здесь.

Объяснение

Маленький пример

Предположим, у нас есть одноканальное изображение размером 4 x 4, X, и его значения в пикселях следующие:

Далее предположим, что мы определяем двумерную свертку со следующими свойствами:

Это означает, что будет 9 фрагментов изображения 2 x 2, которые будут поэлементно умножены на матрицу W, например:

Эти фрагменты изображения могут быть представлены как 4-мерные векторы-столбцы и объединены в единую матрицу 4 x 9, P, например:

Обратите внимание, что i-й столбец матрицы P на самом деле является i-м фрагментом изображения в векторной форме столбца.

Матрица весов для сверточного слоя, W, может быть сведена к 4-мерному вектору-строке, K, следующим образом:

Чтобы выполнить свертку, мы сначала умножаем матрицу K на P, чтобы получить 9-мерный вектор-строку (матрица 1 x 9), который дает нам:

Затем мы изменяем результат K P на правильную форму, которая представляет собой матрицу 3 x 3 x 1 (размер канала последний). Размер канала равен 1, потому что мы установили выходные фильтры на 1. Высота и ширина равны 3, потому что согласно примечаниям CS231n:

Это означает, что результат свертки:

Это проверяет, выполняем ли мы свертку с использованием встроенных функций PyTorch (подробности см. В этих статьях, сопровождающих код).

Большой пример

Пример в предыдущем разделе предполагает одно изображение, а количество выходных каналов свертки равно 1. Что изменится, если мы ослабим эти предположения?

Предположим, что наш вход для свертки - это изображение 4 x 4 с 3 каналами со следующими значениями пикселей:

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

Обратите внимание, что каждый выходной фильтр будет иметь собственное ядро ​​(поэтому в этом примере у нас 2 ядра), а канал каждого ядра равен 3 (поскольку входное изображение имеет 3 канала).

Поскольку мы по-прежнему свертываем ядро ​​2 x 2 на изображении 4 x 4 с нулевым заполнением и шагом 1, количество участков изображения по-прежнему равно 9. Однако матрица участков изображения, P , будет иначе. Более конкретно, i-й столбец P будет объединением значений 1-го, 2-го и 3-го каналов (как вектор-столбец), соответствующих фрагменту изображения i. P теперь будет матрицей 12 x 9. Строк 12, потому что каждый патч изображения имеет 3 канала, а каждый канал - 4 элемента, поскольку мы установили размер ядра 2 x 2. Вот как выглядит P:

Что касается W, каждое ядро ​​будет сглажено в вектор-строку и последовательно соединено, чтобы сформировать матрицу 2 x 12, K. i-я строка K - это объединение значений 1-го, 2-го и 3-го каналов (в виде вектора-строки), соответствующих i-му ядру. Вот как будет выглядеть K:

Теперь осталось только выполнить матричное умножение K P и придать ей правильную форму. Правильная форма - это матрица 3 x 3 x 2 (размер канала последний). Вот результат умножения:

И вот результат после преобразования его в матрицу 3 x 3 x 2:

Это снова проверяет, выполняем ли мы свертку с использованием встроенных функций PyTorch (подробности см. В сопроводительном коде этой статьи).

И что?

Зачем нам нужно выражать двумерные свертки в терминах умножения матриц? Помимо эффективной реализации, подходящей для работы на графическом процессоре, знание этого подхода позволит нам рассуждать о поведении глубокой сверточной нейронной сети. Например, He et. al. (2015) выразили двумерные свертки в терминах умножения матриц, что позволило им применить свойства случайных матриц / векторов, чтобы отстаивать лучшую процедуру инициализации весов.

Заключение

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

Приложение

1D свертка

Метод, описанный в этой статье, также распространяется на одномерные свертки.

Например, предположим, что ваш вход представляет собой 3-канальный 12-мерный вектор, например:

Если мы установим для нашей одномерной свертки следующие параметры:

  • размер ядра: 1 х 4
  • выходные каналы: 2
  • шаг: 2
  • заполнение: 0
  • смещение: 0

Тогда параметры в операции свертки, W, будут тензором с формой (2, 3, 1, 4). Зададим W следующие значения:

Основываясь на параметрах операции свертки, матрица фрагментов «изображения» P будет иметь форму (12, 5) (5 фрагментов изображения, где каждый фрагмент изображения является 12-мерным вектором, поскольку patch имеет 4 элемента по 3 каналам) и будет выглядеть так:

Затем мы сглаживаем W, чтобы получить K, имеющий форму (2, 12), поскольку имеется 2 ядра, и каждое ядро ​​состоит из 12 элементов. Вот как выглядит K:

Теперь мы можем умножить K на P, что дает:

Наконец, мы изменяем K P до правильной формы, которая, согласно формуле, является «изображением» с формой (1, 5). Это означает, что результатом этой свертки является тензор с формой (2, 1, 5), поскольку мы устанавливаем выходные каналы на 2. Вот как выглядит окончательный результат:

Что, как и ожидалось, проверяет, должны ли мы выполнять свертку с использованием встроенных функций PyTorch.

использованная литература

Руководство по сверточной арифметике для глубокого обучения; Дюмулен и Визен. 2018 г.

Углубляясь в выпрямители: превосходя человеческий уровень по классификации ImageNet; Он и др. al. 2015 г.