๐ŸŽ“ A1Learner
๐Ÿ”

PyTorch Receptive Fields

A receptive field is the patch of the original input that one output cell can see. Stacked convolutions grow that patch layer by layer.

One layer

Start from a field of one cell. A 3 by 3 kernel adds one cell on each side.

field = 1
field += 3 - 1
print(field)

Two layers

A second 3 by 3 conv adds one more cell on each side. The running total reaches 5.

field = 1
for _ in range(2):
    field += 3 - 1
print(field)

Three layers

A third conv grows the field to 7. The closing program measures these sizes with gradients, and the counts match.

field = 1
for _ in range(3):
    field += 3 - 1
print(field)

Example

import torch
from torch import nn

torch.manual_seed(0)


def field_size(depth):
    layers = []
    for _ in range(depth):
        conv = nn.Conv2d(1, 1, kernel_size=3, padding=1, bias=False)
        with torch.no_grad():
            conv.weight.fill_(1.0)
        layers.append(conv)
    model = nn.Sequential(*layers)
    image = torch.rand(1, 1, 16, 16, requires_grad=True)
    out = model(image)
    centre = out[0, 0, 8, 8]
    centre.backward()
    mask = image.grad[0, 0] != 0
    height = int(mask.any(dim=1).sum())
    width = int(mask.any(dim=0).sum())
    return height, width


for depth in (1, 2, 3):
    height, width = field_size(depth)
    print(f"{depth} stacked conv: receptive field {height} x {width}")

Key points

  • Receptive field: the input patch that can change one output cell
  • One 3 by 3 conv gives each output cell a 3 by 3 field
  • Each extra 3 by 3 conv adds one cell to each side of the field
  • Use stacked small kernels to see a wide patch with few weights
  • A deeper stack lets each cell judge a larger part of the image

In this example, field_size builds a stack of 3 by 3 convs with every weight set to one. Padding 1 keeps the map at 16 by 16, so the centre cell is easy to pick. The program takes the centre output cell and calls backward on it. The input gradient is non-zero only inside the patch that cell can see. Counting its non-zero rows and columns gives the field size. Depths 1, 2, and 3 print fields of 3, 5, and 7.

Note

Stride and pooling grow the field faster than stride-1 convs

Try it Yourself

Edit the code, then press Run.

Running is simulated ยท Python Playground

Exercise

How large is the receptive field after two stacked 3 by 3 convs with stride 1?