Before you start
Implement 2-D max pooling over a single channel image.
Slide a pool_size by pool_size window across the input with the given
stride and take the maximum inside each window. No padding, so windows that
would run off the edge are simply not taken:
out_h = (H - pool_size) // stride + 1
out_w = (W - pool_size) // stride + 1
Return an array of shape (out_h, out_w).
Pooling shrinks the feature map, which cuts the compute for every layer after it, and it buys a little translation invariance: shifting the input by one pixel often leaves the pooled output unchanged. Max specifically keeps the strongest activation in each neighbourhood, which is the "did this feature fire anywhere around here" signal.
If the input is smaller than the window, return an empty (0, 0) array.
def max_pool_2d(x, pool_size, stride):
Input
x = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]])
max_pool_2d(x, pool_size=2, stride=2)
Output
array([[ 6., 8.],
[14., 16.]])
Reasoning
With a 2 by 2 window and stride 2, the input splits into four blocks. The largest value in each block is 6, 8, 14 and 16.
(0, 0) array.Check runs the visible cases against a fresh kernel. Submit runs the hidden ones too.
⇧↵run cell