Conv3D¶
Описание¶
Этот модуль выполняет операцию трехмерной свёртки. Для более полной информации см. ConvND.
Для входного тензора с размерами (N, C_{in}, D_{in}, H_{in}, W_{in}) и выходного с размерами (N, C_{out}, D_{out}, H_{out}, W_{out}) операция проводится следующим образом (рассматриваем i-й элемент батча и j-ую карту выходного тензора):
где
N - размер батча;
C - количество карт в тензоре;
D - размер карты тензора по глубине;
H - размер карты тензора по высоте;
W - размер карты тензора по ширине;
bias - тензор смещений слоя свёртки, имеет размеры (1, C_{out}, 1, 1);
weight - тензор весов слоя свёртки, имеет размеры (C_{out}, C_{in}, size_h, size_w);
\star - оператор взаимной корреляции.
Инициализация¶
def __init__(self, inmaps, outmaps, size, stride=1, pad=0, dilation=1, wscale=1.0, useBias=True, name=None,
initscheme=None, empty=False, groups=1):
Параметры
Параметр | Возможные типы | Описание | По умолчанию |
---|---|---|---|
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 |
Пояснения
Info
Для вышерассмотренных входного (N, C_{in}, D_{in}, H_{in}, W_{in}) и выходного (N, C_{out}, D_{out}, H_{out}, W_{out}) тензоров существует зависимость между их размерами: \begin{equation} D_{out} = \frac{D_{in} + 2pad_d - dil_d(size_d - 1) - 1}{stride_d} + 1 \end{equation} \begin{equation} H_{out} = \frac{H_{in} + 2pad_h - dil_h(size_h - 1) - 1}{stride_h} + 1 \end{equation} \begin{equation} W_{out} = \frac{W_{in} + 2pad_w - dil_w(size_w - 1) - 1}{stride_w} + 1 \end{equation}
size
- фильтры всегда равносторонние, т.е. (size_d, size_h, size_w)
, где size_d == size_h == size_w
;
stride
- возможна передача как единой величины шага свёртки вдоль всех осей карт, так и tuple вида (stride_d, stride_h, stride_w)
, где stride_h
- величина шага свёртки вдоль глубины карты, stride_h
- величина шага свёртки вдоль высоты карты, а stride_w
- вдоль ширины;
pad
- возможна передача как единой величины отступа для всех сторон карт, так и tuple вида (pad_d, pad_h, pad_w)
, где pad_d
- величина отступа с каждой стороны вдоль глубины карты, pad_h
- вдоль высоты карты, а pad_w
- вдоль ширины. Возможности создания асимметричного паддинга (заполнение дополнительными элементами только с одной стороны тензора) для данного модуля не предусмотрено;
dilation
- возможна передача как единой величины разрежения для всех сторон ядра свёртки, так и tuple вида (dil_d, dil_h, dil_w)
, где dil_d
- величина разрежения фильтра вдоль глубины карты, dil_h
- величина разрежения фильтра вдоль высоты карты, dil_w
- вдоль ширины;
groups
- количество групп, на которое разбивается множество карт для того, чтобы быть свернуто независимо друг от друга.
Общее правило звучит так (при этом надо учитывать, что значения параметров inmaps
и outmaps
должны целочисленно делиться на значение параметра groups
): из каждых \frac{inmaps}{groups} входных карт формируются \frac{outmaps}{groups} выходных карт. То есть, можно сказать, мы проводим groups
независимых свёрток. Частные случаи:
- если
groups=1
, то каждая выходная карта взаимодействует со всеми входными картами, то есть происходит обычная свёртка; - если
inmaps
==outmaps
==groups
, то происходит depthwise свёртка - из каждой входной карты формируется одна выходная (см. подробности в теории ConvND).
Таким образом, для получения полноценного Depthwise Separable Convolution блока необходимо разместить подряд два библиотечных слоя свёртки:
- один depthwise с параметрами
inmaps
==outmaps
==groups
; - один pointwise с ядром размера 1.
Примеры¶
Базовый пример свёртки¶
Необходимые импорты.
>>> import numpy as np
>>> from PuzzleLib.Backend import gpuarray
>>> from PuzzleLib.Modules import Conv3D
>>> from PuzzleLib.Variable import Variable
Info
gpuarray
необходим для правильного размещения тензора на GPU
Для данного модуля примеры даны в упрощённом варианте. Для более наглядного представления можно взглянуть на примеры Conv2D.
>>> batchsize, inmaps, d, h, w = 1, 1, 6, 6, 6
>>> outsize = 2
>>> data = gpuarray.to_gpu(np.random.randn(batchsize, inmaps, d, h, w).astype(np.float32))
Инициализируем модуль со стандартными параметрами (stride=1
, pad=0
, dilation=1
, groups=1
):
>>> conv = Conv3D(inmaps=inmaps, outmaps=outsize, size=2)
>>> conv(data)
Оставим все параметры такими же, кроме size
:
>>> conv = Conv3D(inmaps=inmaps, outmaps=outsize, size=4)
>>> conv(data)
Параметр size
можно задавать разным для каждой оси карты:
>>> conv = Conv3D(inmaps=inmaps, outmaps=outsize, size=(2, 4, 2))
>>> conv(data)
Параметры stride
и pad
также можно задавать разным для каждой оси карты:
>>> conv = Conv3D(inmaps=inmaps, outmaps=outsize, size=4, stride=(1, 4, 4), pad=(0, 1, 1))
>>> conv(data)
Как и говорилось ранее, если параметр имеет разные значения для разных осей, то все эти значения должны быть переданы явно. Следующий пример вызовет ошибку:
>>> conv = Conv3D(inmaps=inmaps, outmaps=outsize, size=2, stride=(1, 3))
>>> conv(data)