Implement Overlapping Max Pooling. Unlike standard max pooling where stride equals kernel size, overlapping pooling uses a stride smaller than the kernel size, so pooling windows overlap.
import numpy as np
def overlapping_max_pool(x: np.ndarray, kernel_size: int = 3,
stride: int = 2) -> np.ndarray:
if x.ndim == 2:
H, W = x.shape
out_h = (H - kernel_size) // stride + 1
out_w = (W - kernel_size) // stride + 1
output = np.zeros((out_h, out_w))
for i in range(out_h):
for j in range(out_w):
h_start = i * stride
w_start = j * stride
region = x[h_start:h_start + kernel_size,
w_start:w_start + kernel_size]
output[i, j] = np.max(region)
return output
# 4D: (batch, channels, H, W)
batch, channels, H, W = x.shape
out_h = (H - kernel_size) // stride + 1
out_w = (W - kernel_size) // stride + 1
output = np.zeros((batch, channels, out_h, out_w))
for b in range(batch):
for c in range(channels):
for i in range(out_h):
for j in range(out_w):
h_start = i * stride
w_start = j * stride
region = x[b, c,
h_start:h_start + kernel_size,
w_start:w_start + kernel_size]
output[b, c, i, j] = np.max(region)
return outputout = (input_size - kernel_size) // stride + 1.