ConvND

Описание

Info

Родительский класс: Module

Производные классы: Conv1D, Conv2D, Conv3D

Общая информация

Этот модуль выполняет операцию n-мерной свёртки.

Свертка в общих словах - операция над парой тензоров D и B, результатом которой является тензор C=D∗B, причём тензор D является субтензором некоего тензора A. Каждый элемент результата вычисляется как скалярное произведение тензора B и субтензора A такого же размера (от положения A зависит положение вычисленного элемента в результате).

Лучше всего это продемонстрировано на рисунке 1 (см. параметр "Шаг свёртки").

Для входного тензора с размерами (N, C_{in}, Dims_{in}) и выходного с размерами (N, C_{out}, Dims_{out}) операция проводится следующим образом (рассматриваем i-й элемент батча и j-ую карту выходного тензора):

out_i(C_{out_j}) = bias(C_{out_j}) + \sum_{k=0}^{C_{in} - 1}weight(C_{out_j}, k) \star input_i(k)

где

N - размер батча;
C - количество карт в тензоре;
Dims - вектор размеров карты тензора по каждому измерению (например, (H, W) для двумерных карт);
bias - тензор смещений слоя свёртки;
weight - тензор весов слоя свёртки;
\star - оператор взаимной корреляции.

Параметры операции

Операцию свертки характеризуют следующие параметры и объекты:


Ядро свёртки size


Если посмотреть на вышеприведенное определение, то ядро свертки - это тензор B. Ядро свертки характеризуется своим размером, формой и набором значений своих элементов. Для свёрточных слоёв нейронной сети набор значений элементов ядра - это веса, которые являются обучаемым параметром.

Important

В рамках данной библиотеки форма ядер свёртки всегда равносторонняя, т.е. квадрат для двумерной свёртки и куб для трёхмерной.


Шаг свёртки stride


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

Работа свёртки при разном шаге хорошо продемонстрирована на рисунках 1 и 2 (на примере двумерной свёртки):

Обычная двумерная свёртка
Рисунок 1. Двумерная свёртка (size=3, stride=1)

Двумерная свёртка с увеличенным шагом
Рисунок 2. Двумерная свёртка (size=3, stride=2)


Паддинг pad


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

Двумерная свёртка с получением тензора того же размера
Рисунок 3. Двумерная свёртка карты размера 5 (size=3, stride=1, pad=1)

Другой причиной может стать желание избежать потери граничных элементов карт при определенных наборах остальных параметров. На рисунке 4 представлена ситуация, когда элементы не были потеряны: без паддинга последние граничные 2 столбца и строки не были бы задействованы при получении выходного тензора.

Ассиметричная двумерная свёртка
Рисунок 4. Двумерная свёртка карты размера 6 (size=3, stride=2, pad=1)

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


Разрежение dilation


Параметр разрежения определяет количество раз, в которое будет увеличен размер ядра свертки. При этом элементы ядра удаляются друг от друга в заданное число раз, а образовавшиеся пустые значения заполняются нулями.

Разреженная свёртка
Рисунок 5. Разреженная свёртка с разными степенями разрежения: dilation=1, dilation=2 и dilation=4

При применении разрежения экспоненциально растет размер рецептивного поля (receptive field). Для первого изображения оно равно 3х3, для второго уже 7х7, для третьего - 15х15.

Другой пример разреженной свёртки представлен на рисунке 6:

Разреженная свёртка (анимация)
Рисунок 6. Разреженная свёртка карты размера 7 (size=3, stride=1, dilation=1)

Приятным свойством применения этой техники является то, что она дешева с точки зрения вычислений. То есть мы используем свертки гораздо большей размерности, увеличиваем поля чувствительности, имея возможность отслеживать более глобальные признаки - но не добавляем при этом нагрузки на железо.


Количество связей входных и выходных карт groups


Техника использования групп при операции свертки в англоязычной литературе называется Depthwise Convolution, которая является частью техники Depthwise Separable Convolution.

Depthwise Separable Convolution разбивает процесс вычисления свертки на две части: depthwise свертка и pointwise свертка. Рассмотрим технику на примере двумерной свёртки.

На первом этапе в результате свертки получается тензор без изменения глубины: мы используем ядра свертки глубины 1 и размера size в количестве, равном количеству входных карт, и применяем каждое такое ядро отдельно к каждой карте соответственно.

depthwise_conv.png
Рисунок 7. Depthwise свёртка карты размера 12 (size=5, stride=1)

На втором этапе применяется точечное ядро для получения желаемого количества выходных карт (на рисунке количество выходных карт 256):

pointwise2
Рисунок 8. Pointwise свёртка карты размера 8 (size=1, stride=1)

То есть, можно сказать, что мы провели замену одного свёрточного слоя с весами (C_{out}, C_{in}, size, size) на две свёртки: depthwise (C, 1, size, size) и затем pointwise (C_{out}, C, 1, 1), где

C_{out} - количество выходных карт тензора;
C_{in} - количество входных карт тензора;
C - промежуточное количество карт, равное C_{in};
size - размер ядра.

Info

В рамках этой библиотеки depthwise свертка осуществляется варьированием параметра groups. Для более подробной информации см. примеры классов наследников.

Данная техника позволяет значительно уменьшить количество вычислений.

Дополнительные источники

  • Детальное описание операции свертки и сверточных нейронных сетей: ссылка;
  • Подробный разбор техники паддинга: ссылка;
  • Статья по разреженным свёрткам: ссылка;
  • Разбор Depthwise convolution на английском: ссылка;
  • Разбор Depthwise convolution на русском: ссылка.

Инициализация

def __init__(self, nd, inmaps, outmaps, size, stride=1, pad=0, dilation=1, wscale=1.0, useBias=True, name=None,
                 initscheme=None, empty=False, groups=1):

Параметры

Параметр Возможные типы Описание По умолчанию
nd int Размерность операции. -
inmaps int Количество карт во входном тензоре. -
outmaps int Количество карт в выходном тензоре. -
size int Размер ядра свёртки. -
stride Union[int, tuple] Шаг свёртки. 1
pad Union[int, tuple] Паддинг карт. 0
dilation Union[int, tuple] Разрежение окна свёртки. 1
wscale float Дисперсия случайных весов слоя. 1.0
useBias bool Использовать или нет вектор смещений. True
initscheme Union[tuple, str] Указывает схему инициализации весов слоя (см. createTensorWithScheme). None -> ("xavier_uniform", "in")
name str Имя слоя. None
empty bool Инициализировать ли матрицу весов и смещений. False
groups int На сколько групп разбиваются карты для раздельной обработки. 1

Пояснения

См. классы потомки.