Demo: Does a Convolution Really Move with Its Input?
A shared convolutional kernel is shift equivariant, but the boundary rule is part of that statement. The setup creates a small image, a detector for horizontal changes in intensity, and a circular shift.
import numpy as npimport matplotlib.pyplot as pltimport torchimport torch.nn.functional as Fplt.style.use("../figure_style.mplstyle")image = torch.zeros(1, 1, 32, 32)image[:, :, 5:14, 2:10] =1.0for i inrange(10, 25): image[:, :, i, i] =0.7kernel = torch.tensor([[-1.0, 0.0, 1.0], [-2.0, 0.0, 2.0], [-1.0, 0.0, 1.0]]).reshape(1, 1, 3, 3)shift = (0, -6) # vertical and horizontal displacement; change this pairshifted_image = torch.roll(image, shifts=shift, dims=(-2, -1))print("Image shape:", tuple(image.shape[-2:]), "shift:", shift)
Image shape: (32, 32) shift: (0, -6)
Question: When Do Shifting and Convolving Commute?
We compare two orders: convolve a shifted image, or shift the convolution of the original image. Circular padding wraps both the image and its neighborhoods. Zero padding instead introduces a special outside value at the boundary. Predict where the two comparisons can differ.
Largest circular-padding error: 0.00e+00
Largest zero-padding error: 4.00e+00
Answer. With circular padding, shifting and convolving commute up to floating-point precision. With zero padding, the equality fails where the wrapped shift changes which neighborhoods meet the image boundary.
Convolution provides equivariance relative to a specified boundary convention. Pooling, stride, and later nonlinear decisions can weaken the end-to-end symmetry further.