Виды 2D сверток

Виды 2D сверток

DeepSchool

Автор: Александр Лекомцев

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

Пару слов про размерность

Относительно размерности используют свертки трёх типов — 1D, 2D, 3D. И хотя чаще всего используют двумерные, у других вариантов тоже есть свои применения. Например, 1D свёртки используют в анализе сигналов или текстов, а 3D - для работы с облаками точек. В этой статье мы рассмотрим разные виды 2D сверток, но эти идеи можно адаптировать и для других размерностей. Кроме того, не будем останавливаться отдельно на свёртках с разной шириной и высотой, большинство свёрток ниже легко дополняется этим под специфическую задачу.

1x1

Свёртки 1x1 (они же pointwise convolutions) — это обычные свёртки в один пиксель. Они работают только с одним числом в ширину и высоту, но со всеми каналами тензора. С их помощью можно изменить число каналов перед дорогими свёртками 3x3. А так как количество умножений растет квадратично с длиной свертки, разница получается заметной. Получается, благодаря сверткам 1х1 мы можем дешево изменить количество каналов и добавить больше нелинейности (если поставим в конце функцию активации).

Ещё одна интересная деталь — свёртки 1x1 идентичны полносвязному слою, поскольку каждый элемент в канале умножается на единственный вес и после они складываются. Вот такое необычное обобщение.

Рисунок 1. К карте признаков (голубым) применяется единственная свёртка 1x1 (оранжевым), на выходе получаем новую карту признаков (зелёным).

Transposed

В некоторых архитектурах encoder-decoder можно встретить транспонированные свертки. Если обычные свертки без заполнения уменьшают карту признаков в ширину и высоту, то транспонированные наоборот, увеличивают.

Как этого добиться? Для начала создадим промежуточные тензоры (нижний ряд на Рисунке 2), умножая каждое число во входной карте на ядро. Потом заполним пустые позиции нулями и сложим получившиеся тензоры. Размер стороны тензора на выходе = размер входной карты + размер ядра - 1. Если непонятно, то лучше посмотреть видео с визуализацией :)

Рисунок 2. Транспонированная свёртка с шагом 1

А что если мы добавим шаг? Тут всё тоже довольно просто. Шаг мы добавляем не к перемещению ядра по входу, а к перемещению по заполняемым значениям в промежуточных картах признаков, как на Рисунке 3

Рисунок 3. Транспонированная свёртка с шагом 2

Dilated

Свёртки создавали исходя из идеи о локальности признаков. То есть подразумевали, что информативные признаки находятся рядом. Но что делать, если признаки недостаточно близко для стандартных свёрток 3x3? Одно из решений — взять свертку побольше. Но мы помним, что количество умножений растет квадратично с длиной стороны свертки. Значит больше свертка = больше вычислений.

Расширить сворачиваемую область без повышения вычислительной сложности могут dilated (они же atrous) convolutions. Вместо того чтобы сворачивать соседние пиксели, они пропускают несколько из них между сворачиваемыми. Dilation — это параметр, равный количеству пропускаемых пикселей. Чем он больше, тем больше рецептивное поле свёртки, но и выше вероятность потерять полезные мелкие признаки. При dilation равным размеру изображения, мы уже получим свёртку 1x1, которая вообще не связывает между собой соседние пиксели.

Рисунок 4. Dilated convolution при dilation равном (a) 1, (b) 2, (c) 3.

Spatially Separable

Идея берет свое начало из классической обработки изображений. Ядро свертки представлено матрицей. Матрицу можно представить как произведение двух векторов. Два вектора занимают меньше памяти, чем матрица, да и число операций становится меньше. Схема работы с таким разложением на Рисунке 5.

Рисунок 5. Последовательное применение двух свёрток 3x1, 1x3 вместо одной 3x3

Проблема этого способа в том, что не все матрицы представимы в таком формате. Перемножая векторы, мы будем получать матрицы неполного ранга. Например, на Рисунке 6 видно, что первый столбец, умноженный на d/c даст второй, а значит они линейно зависимы и ранг равен единице для матрицы 2x2.

Рисунок 6. Умножение векторов для получения матрицы

Depthwise Separable

Совмещает сразу несколько идей из уже упомянутых. Сначала разделим свёртку по каналам и применим к каждому каналу отдельно. Это называется просто depthwise convolution.

Рисунок 7. Depthwise convolution.


Затем мы конкатенируем полученные карты и прогоняем их через 1x1 свёртки, увеличивая глубину.

Рисунок 8. Применяем 256 свёрток 1x1 к конкатенированному результату с Рисунка 7.

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

Grouped

Суть grouped convolution прекрасно видна на Рисунке 9. Мы разделяем нашу карту на 2 группы, применяем свертку к каждой отдельно и соединяем. Таким образом мы опять уменьшаем число умножений, но что ещё важнее, теперь умножение каждой группы можно проводить независимо! Эта идея была использована ещё в AlexNet, но только в ResNeXt исследовали возможность повышения качества с помощью групповой свертки.

Рисунок 9. Grouped convolution (GConv).

Эту же идею продолжает shuffled grouped convolution — в которых после свертки еще и перемешивают каналы как на Рисунке 10.

Рисунок 10. Две GConv последовательно применяются к разным вариантам каналов. В (а) каналы не перемешиваются, (b) каналы перемешиваются

Deformable

И заканчиваем мы на очень необычной свертке, которая продолжает идеи dilated convolution. В деформируемой свертке кроме самого ядра обучается положение чисел, на которые будет умножение. Что позволяет учить свёртки абсолютно любой формы, сильно ослабляя предположение о локальности фичей.

Рисунок 11. Отдельная свертка (conv) извлекает карту смещений (offset field), благодаря которым другая свертка выбирает ячейки для умножения (offsets).


Report Page