MaxPool2D¶
Описание¶
Этот модуль реализует операцию двумерного максимизирующего пулинга (двумерного максимизирующего объединения). Подробное теоретическое описание см. в Pool2D.
Для входного тензора с размерами (N, C, H_{in}, W_{in}) и выходного с размерами (N, C, H_{out}, W_{out}) операция проводится следующим образом (рассматриваем i-й элемент батча, j-ую карту выходного тензора):
где
N - размер батча;
C - количество карт в тензоре;
H - размер карт по высоте;
W - размер карт по ширине;
stride_h, stride_w - шаг пулинга вдоль высоты и ширины карт соответственно;
k_h, k_w - размер окна пулинга по высоте и ширине соответственно.
Инициализация¶
def __init__(self, size=2, stride=2, pad=0, useMask=False, name=None):
Параметры
Параметр | Возможные типы | Описание | По умолчанию |
---|---|---|---|
size | Union[int, tuple] | Размер ядра. | 2 |
stride | Union[int, tuple] | Шаг пулинга. | 2 |
pad | Union[int, tuple] | Паддинг входных карт. | 0 |
useMask | bool | Сохранять ли тензор с индексами максимумов. | False |
name | str | Имя слоя. | None |
Пояснения
size
- возможна передача как единого размера окна пулинга, в таком случае оно будет квадратным, так и tuple вида (size_h, size_w)
, где size_h
- высота окна пулинга, а size_w
- его ширина;
stride
- возможна передача как единой величины шага пулинга по высоте и ширине карт, так и tuple вида (stride_h, stride_w)
, где stride_h
- величина шага пулинга вдоль высоты карты, а stride_w
- вдоль ширины;
pad
- возможна передача как единой величины отсупа для всех сторон карт, так и tuple вида (pad_h, pad_w)
, где pad_h
- величина отступа с каждой стороны вдоль высоты картинки, а pad_w
- вдоль ширины. Возможности создания асимметричного паддинга (заполнение дополнительными элементами только с одной стороны тензора) для данного модуля не предусмотрено, используйте Pad2D.
Примеры¶
Базовый пример пулинга¶
Необходимые импорты.
>>> import numpy as np
>>> from PuzzleLib.Backend import gpuarray
>>> from PuzzleLib.Modules import MaxPool2D
Info
gpuarray
необходим для правильного размещения тензора на GPU
Зададим параметры тензора, чтобы можно было наглядно продемонстрировать работу модуля.
>>> batchsize, maps, h, w = 1, 1, 6, 6
>>> data = gpuarray.to_gpu(np.arange(batchsize * maps * h * w).reshape((batchsize, maps, h, w)).astype(np.float32))
>>> data
[[[[ 0. 1. 2. 3. 4. 5.]
[ 6. 7. 8. 9. 10. 11.]
[12. 13. 14. 15. 16. 17.]
[18. 19. 20. 21. 22. 23.]
[24. 25. 26. 27. 28. 29.]
[30. 31. 32. 33. 34. 35.]]]]
Инициализируем модуль со стандартными параметрами (size=2
, stride=2
, pad=0
, useMask=False
):
>>> avgpool = MaxPool2D()
>>> avgpool(data)
[[[[ 7. 9. 11.]
[19. 21. 23.]
[31. 33. 35.]]]]
Параметр size¶
Оставим все параметры такими же, кроме size
:
>>> pool = MaxPool2D(size=4)
>>> pool(data)
[[[[21. 23.]
[33. 35.]]]]
size
можно задавать разным для высоты и ширины карты:
>>> pool = MaxPool2D(size=(4, 2))
>>> pool(data)
[[[[19. 21. 23.]
[31. 33. 35.]]]]
Параметр stride¶
Установим значение stride
равным 1:
>>> pool = MaxPool2D(stride=1)
>>> pool(data)
[[[[ 7. 8. 9. 10. 11.]
[13. 14. 15. 16. 17.]
[19. 20. 21. 22. 23.]
[25. 26. 27. 28. 29.]
[31. 32. 33. 34. 35.]]]]
Параметр stride
также можно задавать разным для высоты и ширины карты:
>>> pool = MaxPool2D(stride=(1, 3))
>>> pool(data)
[[[[ 7. 10.]
[13. 16.]
[19. 22.]
[25. 28.]
[31. 34.]]]]
Изменим теперь и stride
, и size
:
>>> pool = MaxPool2D(size=4, stride=4)
>>> pool(data)
[[[[21.]]]]
В выходном тензоре получился всего один элемент, так как оставшиеся элементы входного тензора не могли образовать субтензоры, которые по размеру были бы не меньше окна пулинга, из-за чего они были проигнорированы.
Параметр pad¶
Чтобы включить проигнорированные элементы из предыдущего примера, инициализируем паддинг:
>>> pool = MaxPool2D(size=4, stride=4, pad=1)
>>> pool(data)
[[[[14. 17.]
[32. 35.]]]]
[[[[ 0. 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 1. 2. 3. 4. 5. 0.]
[ 0. 6. 7. 8. 9. 10. 11. 0.]
[ 0. 12. 13. 14. 15. 16. 17. 0.]
[ 0. 18. 19. 20. 21. 22. 23. 0.]
[ 0. 24. 25. 26. 27. 28. 29. 0.]
[ 0. 30. 31. 32. 33. 34. 35. 0.]
[ 0. 0. 0. 0. 0. 0. 0. 0.]]]]
Параметр pad
также можно задавать разным для высоты и ширины карты. Например pad=(0, 2)
, тогда:
[[[[ 0. 0. 0. 1. 2. 3. 4. 5. 0. 0.]
[ 0. 0. 6. 7. 8. 9. 10. 11. 0. 0.]
[ 0. 0. 12. 13. 14. 15. 16. 17. 0. 0.]
[ 0. 0. 18. 19. 20. 21. 22. 23. 0. 0.]
[ 0. 0. 24. 25. 26. 27. 28. 29. 0. 0.]
[ 0. 0. 30. 31. 32. 33. 34. 35. 0. 0.]]]]
Параметр useMask¶
Параметр useMask
отвечает за то, будет ли сохранён тензор индексов максимальных элементов. Чтобы продемонстрировать его работу, переинициализируем тензор данных:
>>> data = gpuarray.to_gpu(np.random.randint(low=0, high=9, size=(batchsize, maps, insize)).astype(np.float32))
>>> print(data)
[[[[4. 5. 7. 8. 3. 1.]
[7. 7. 4. 0. 7. 7.]
[2. 1. 2. 1. 0. 4.]
[6. 8. 5. 5. 1. 1.]
[1. 2. 5. 8. 4. 4.]
[6. 0. 2. 6. 8. 5.]]]]
>>> pool = MaxPool2D(useMask=True)
>>> pool(data)
[[[[7. 8. 7.]
[8. 5. 4.]
[6. 8. 8.]]]]
>>> print(pool.mask)
[[[[ 6 3 10]
[19 20 17]
[30 27 34]]]]
>>> maps = 2
>>> data = gpuarray.to_gpu(np.random.randint(low=0, high=9, size=(batchsize, maps, insize)).astype(np.float32))
>>> print(data)
[[[[3. 3. 8. 6. 4. 3.]
[2. 7. 0. 2. 6. 4.]
[1. 5. 4. 7. 2. 8.]
[7. 6. 8. 4. 7. 0.]
[4. 0. 8. 1. 5. 3.]
[0. 6. 8. 2. 3. 4.]]
[[7. 4. 6. 7. 1. 4.]
[6. 5. 5. 1. 5. 7.]
[3. 7. 3. 6. 2. 7.]
[2. 8. 7. 3. 5. 5.]
[4. 8. 2. 1. 4. 1.]
[2. 7. 3. 1. 4. 0.]]]]
>>> pool = MaxPool2D(useMask=True)
>>> pool(data)
[[[[7. 8. 6.]
[7. 8. 8.]
[6. 8. 5.]]
[[7. 7. 7.]
[8. 7. 7.]
[8. 3. 4.]]]]
>>> print(pool.mask)
[[[[ 7 2 10]
[18 20 17]
[31 26 28]]
[[ 0 3 11]
[19 20 17]
[25 32 28]]]]
>>> print(pool.mask.shape)
(1, 2, 3, 3)