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
outmaps = 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=outmaps, size=2)
print(conv(data))
Оставим все параметры такими же, кроме size
:
conv = Conv3D(inmaps=inmaps, outmaps=outmaps, size=4)
print(conv(data))
Параметр size
можно задавать разным для каждой оси карты:
conv = Conv3D(inmaps=inmaps, outmaps=outmaps, size=(2, 4, 2))
print(conv(data))
Параметры stride
и pad
также можно задавать разным для каждой оси карты:
conv = Conv3D(inmaps=inmaps, outmaps=outmaps, size=4, stride=(1, 4, 4), pad=(0, 1, 1))
print(conv(data))
Как и говорилось ранее, если параметр имеет разные значения для разных осей, то все эти значения должны быть переданы явно. Следующий пример вызовет ошибку:
conv = Conv3D(inmaps=inmaps, outmaps=outmaps, size=2, stride=(1, 3))
print(conv(data))