Neural Mastery
← Practice
2D Max Pooling Backward Pass Gradient Routermedium

2D Max Pooling Backward Pass Gradient Router

medium Neural Networks by Hand 20 min

NumPy allowed · plain Python earns 10 bonus points

Gradient descent step 1/4

Loss moves downhill

The update rule changes the parameters on each step.
Open lesson →
01parameters
02prediction
03loss
04gradient
θ = 4.000loss = 16.000∂L/∂θ = 8.000

θ ← θ − 0.14 · ∂L/∂θ

Route backpropagated errors solely to the active argmax elements that contributed to downstream pooling activations.

Task

Implement max_pool2d_backward(...). Initialize grad_input to zeros with shape (H_in, W_in). For each pooling window (i, j), find the index (max_r, max_c) corresponding to the maximum value in input_map[i*stride : i*stride+pool_size, j*stride : j*stride+pool_size]. (If multiple elements tie, pick the first in row-major order). Add grad_output[i][j] to grad_input[max_r][max_c]. Round all elements in grad_input to 4 decimal places.

Function Signature

max_pool2d_backward(input_map: list[list[float]], grad_output: list[list[float]], pool_size: int = 2, stride: int = 2) -> list[list[float]]

Examples

Example 1: 4x4 input 2x2 max pool stride 2
Input: input_map = [[1, 3, 2, 4], [5, 2, 8, 6], [3, 7, 1, 5], [2, 4, 9, 0]] grad_output = [[1.5, 2.5], [3.5, 4.5]] pool_size = 2 stride = 2
Output: [[0, 0, 0, 0], [1.5, 0, 2.5, 0], [0, 3.5, 0, 0], [0, 0, 4.5, 0]]
Example 2: 2x2 input 2x2 pool stride 2 single grad
Input: input_map = [[10, 20], [15, 5]] grad_output = [[1]] pool_size = 2 stride = 2
Output: [[0, 1], [0, 0]]
Example 3: Overlapping pool stride 1 routing
Input: input_map = [[1, 5, 2], [3, 4, 1]] grad_output = [[1, 2]] pool_size = 2 stride = 1
Output: [[0, 3, 0], [0, 0, 0]]

Constraints

  • 2 <= H_in, W_in <= 128
  • pool_size >= 1
  • stride >= 1
Python3Saved ✓
def max_pool2d_backward(input_map: list[list[float]], grad_output: list[list[float]], pool_size: int = 2, stride: int = 2) -> list[list[float]]:
"""Route upstream gradients back to the argmax positions of a max pooling layer.

Args:
input_map: 2D list of shape (H_in, W_in).
grad_output: 2D list of upstream gradients of shape (H_out, W_out).
pool_size: Pooling window spatial dimension.
stride: Pooling stride.

Returns:
2D list of shape (H_in, W_in) with routed gradients rounded to 4 decimals.
"""
pass

Case 1: 4x4 input 2x2 max pool stride 2
Input: input_map = [[1, 3, 2, 4], [5, 2, 8, 6], [3, 7, 1, 5], [2, 4, 9, 0]] grad_output = [[1.5, 2.5], [3.5, 4.5]] pool_size = 2 stride = 2
Expected: [[0, 0, 0, 0], [1.5, 0, 2.5, 0], [0, 3.5, 0, 0], [0, 0, 4.5, 0]]
Case 2: 2x2 input 2x2 pool stride 2 single grad
Input: input_map = [[10, 20], [15, 5]] grad_output = [[1]] pool_size = 2 stride = 2
Expected: [[0, 1], [0, 0]]
Case 3: Overlapping pool stride 1 routing
Input: input_map = [[1, 5, 2], [3, 4, 1]] grad_output = [[1, 2]] pool_size = 2 stride = 1
Expected: [[0, 3, 0], [0, 0, 0]]