MaxPool1D

Описание

Info

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

Производные классы: -

Этот модуль реализует операцию одномерного максимизирующего пулинга (одномерного максимизирующего объединения). Подробное теоретическое описание см. в Pool1D.

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

out(N_i, C_j, l) = \max\limits_{m=0..k-1}(input(N_i, C_j, stride \times l + m))

где

N - размер батча;
C - количество карт в тензоре;
L - размер последовательности;
stride - шаг пулинга;
k - размер окна пулинга.

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

def __init__(self, size=2, stride=2, pad=0, useMask=False, name=None):

Параметры

Параметр Возможные типы Описание По умолчанию
size int Размер ядра. 2
stride int Шаг пулинга. 2
pad int Паддинг входных карт. 0
useMask bool Сохранять ли тензор с индексами максимумов. False
name str Имя слоя. None

Пояснения

pad - возможна передача только единой величины отступа для всех сторон карт. Возможности создания асимметричного паддинга (заполнение дополнительными элементами только с одной стороны тензора) для данного модуля не предусмотрено, используйте Pad1D.

Примеры


Базовый пример пулинга


Необходимые импорты.

>>> import numpy as np
>>> from PuzzleLib.Backend import gpuarray
>>> from PuzzleLib.Modules import MaxPool1D

Info

gpuarray необходим для правильного размещения тензора на GPU

Зададим параметры тензора, чтобы можно было наглядно продемонстрировать работу модуля.

>>> batchsize, maps, insize = 1, 1, 10
>>> data = gpuarray.to_gpu(np.arange(batchsize * maps * insize).reshape((batchsize, maps, insize)).astype(np.float32))
>>> data

[[[0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]]]

Инициализируем модуль со стандартными параметрами (size=2, stride=2, pad=0, useMask=False):

>>> pool = MaxPool1D()
>>> pool(data)
[[[1. 3. 5. 7. 9.]]]

Параметр size


Оставим все параметры такими же, кроме size:

>>> pool = MaxPool1D(size=4)
>>> pool(data)
[[[3. 5. 7. 9.]]]

Параметр stride


Установим значение stride равным 1:

>>> pool = MaxPool1D(stride=1)
>>> pool(data)
[[[1. 2. 3. 4. 5. 6. 7. 8. 9.]]]

Изменим теперь и stride, и size:

>>> pool = MaxPool1D(size=4, stride=4)
>>> pool(data)
[[[3. 7.]]]

Как видно, последние два элемента исходного тензора не были включены в расчёты, так как субтензор из них был по размеру меньше окна пулинга.


Параметр pad


Чтобы включить последние элементы из предыдущего примера, инициализируем паддинг:

>>> pool = MaxPool1D(size=4, stride=4, pad=1)
>>> pool(data)
[[[2. 6. 9.]]]
Обратите внимание, что паддинг в модуле всегда симметричный - по одному новому элементу было добавлено с каждой стороны исходного тензора, т.е. его вид после паддинга:
[[[0. 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 0.]]]


Параметр useMask


Параметр useMask отвечает за то, будет ли сохранён тензор индексов максимальных элементов. Чтобы продемонстрировать его работу, переинициализируем тензор данных:

>>> data = gpuarray.to_gpu(np.random.randint(low=0, high=9, size=(batchsize, maps, insize)).astype(np.float32))
>>> print(data)
[[[5. 5. 5. 3. 6. 7. 6. 4. 7. 4.]]]
>>> pool = MaxPool1D(useMask=True)
>>> pool(data)
[[[5. 5. 7. 6. 7.]]]
>>> print(pool.mask)
[[[[0 2 5 6 8]]]]
Для каждого элемента батча и каждой карты индексы возвращаются отдельно:
>>> maps = 2
>>> data = gpuarray.to_gpu(np.random.randint(low=0, high=9, size=(batchsize, maps, insize)).astype(np.float32))
>>> print(data)
[[[1. 0. 6. 3. 8. 0. 5. 7. 2. 0.]
  [8. 0. 1. 6. 3. 7. 5. 7. 5. 6.]]]
>>> pool = MaxPool1D(useMask=True)
>>> pool(data)
[[[1. 6. 8. 7. 2.]
  [8. 6. 7. 7. 6.]]]
>>> print(pool.mask)
[[[[0 2 4 7 8]]
  [[0 3 5 7 9]]]]
>>> print(pool.mask.shape)
(1, 2, 1, 5)