AvgPool2D

Description

Info

Parent class: Pool2D

Derived classes: -

This module implements the operation of two-dimensional average pooling. For a detailed theoretical description, see Pool2D.

For an input tensor of shape (N, C, H_{in}, W_{in}) and an output tensor of shape (N, C, H_{out}, W_{out}) the operation is performed as follows (we consider the i-th element of the batch, the j-th map of the output tensor):

out(N_i, C_j, h, w) = \frac{1}{k_hk_w}\sum_{m=0}^{k_h-1}\sum_{n=0}^{k_w-1}(input(N_i, C_j, stride_h \times h + m, stride_w \times w + n))

where

N - size of the batch;
C - size of the batch;
H - size of the maps in height;
W - size of the maps in height;
stride_h, stride_w - pooling stride along the height and the width of the maps, respectively;
k_h, k_w - size of the pool window in height and width, respectively.

Initializing

def __init__(self, size=2, stride=2, pad=0, includePad=True, name=None):

Parameters

Parameter Parameter Description Default
size Union[int, tuple] Kernel size 2
stride Union[int, tuple] Pooling stride 2
pad Union[int, tuple] Padding of the input maps 0
includePad bool Flag for including the edge filling values when calculating the average value True
name str Layer name None

Explanations

size - possible to specify either a single size of the pooling window, in which case it will be square, or a tuple (size_h, size_w), where size_h is the height of the pooling window and size_w is its width.


stride - possible to specify either a single value of the pooling stride along the height and the width of the maps, or a tuple (stride_h, stride_w), where stride_h is the value of the stride along the map height, and stride_w – along its width.


pad - possible to specify either a single padding value for all sides of the map, or a tuple (pad_h, pad_w), where pad_h is the padding value on each side along the image height, and pad_w - along the width. The possibility of creating an asymmetric padding (filling with additional elements on only one side of the tensor) is not provided for this module, please use Pad2D;


includePad - if the pad parameter was set to nonzero and new elements were added to the original tensor along the edges, then when includePad is set, their values will also affect the result of the pooling operation.

Examples


Basic pooling example


Necessary imports.

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

Info

gpuarray is required to properly place the tensor in the GPU.

Let us set the tensor parameters so that we can clearly demonstrate the operation of the module.

>>> 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.]]]]

Let us initialize the module with standard parameters (size=2, stride=2, pad=0, includePad=True):

>>> pool = AvgPool2D()
>>> pool(data)
[[[[ 3.5  5.5  7.5]
   [15.5 17.5 19.5]
   [27.5 29.5 31.5]]]]

size parameter


Let us leave all parameters the same except size size:

>>> pool = AvgPool2D(size=4)
>>> pool(data)
[[[[10.5 12.5]
   [22.5 24.5]]]]
The size parameter can be set different for the height and the width of the map:
>>> pool = AvgPool2D(size=(4, 2))
>>> pool(data)
[[[[ 9.5 11.5 13.5]
   [21.5 23.5 25.5]]]]


stride parameter


Let us set the stride value to 1:

>>> pool = AvgPool2D(stride=1)
>>> pool(data)
[[[[ 3.5  4.5  5.5  6.5  7.5]
   [ 9.5 10.5 11.5 12.5 13.5]
   [15.5 16.5 17.5 18.5 19.5]
   [21.5 22.5 23.5 24.5 25.5]
   [27.5 28.5 29.5 30.5 31.5]]]]

The stride parameter can also be set different for the height and the width of the map:

>>> pool = AvgPool2D(stride=(1, 3))
>>> pool(data)
[[[[ 3.5  6.5]
   [ 9.5 12.5]
   [15.5 18.5]
   [21.5 24.5]
   [27.5 30.5]]]]

Now let us change both stride and size:

>>> pool = AvgPool2D(size=4, stride=4)
>>> pool(data)

[[[[10.5]]]]

In the output tensor, only one element was obtained, since the remaining elements of the input tensor could not form subtensors that were no smaller than the pooling window, which is why they were ignored.


pad parameter


To include the ignored items from the previous example, let us initialize the padding:

>>> pool = AvgPool2D(size=4, stride=4, pad=1)
>>> pool(data)
[[[[ 3.9375  5.625 ]
   [14.0625 15.75  ]]]]
Please note that the padding in the module is always symmetrical - one new element (row or column) was added on each side of the original tensor, i.e. after padding it looks as follows:
[[[[ 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.]]]]

The pad parameter can also be set different for the height and the width of the map. For example, pad=(0, 2), then:

[[[[ 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.]]]]


includePad parameter


In previous examples, the includePad parameter remained the same as the default, i.e. peripheral elements of padding were included in the calculations. Now let us see what happens if you unset this flag for the last example:

>>> pool = AvgPool2D(size=4, stride=4, pad=1, includePad=False)
>>> pool(data)
[[[[ 7. 10.]
   [25. 28.]]]]
As you can see, the pooling window took into account the presence of additional elements, but they were not included in the calculation of the average value of the subtensor.