Вступление
В этой статье я объясню, как 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 г.