PyTorch represents image data as (N, C, H, W): batch, channels, height, width. (The other major convention is NHWC, used by TensorFlow and CoreML — be ready to permute when you cross frameworks.)
nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0) learns out_channels filters of shape (kernel_size, kernel_size, in_channels), slides each over the input, and produces out_channels feature maps. The output spatial size follows the standard formula: out = (in + 2*padding - kernel) / stride + 1.
The variants you'll actually use
Conv2d — 2D conv. Default for images.
Conv1d — 1D conv. Useful for sequences (audio waveforms, character-level text, time series).
ConvTranspose2d — "deconvolution" for upsampling. The decoder of a U-Net, the generator of a DCGAN.
Depthwise separable convs — built by combining Conv2d(groups=in_channels) + Conv2d(1x1). The trick that makes MobileNet / EfficientNet efficient.
The padding shorthand
PyTorch added padding='same' as a string in 1.10+, which keeps spatial dims unchanged for stride=1. It's the convenient version of "compute the right padding by hand" that everyone used to write. Use it when you don't have a specific reason to drop spatial dims.
Build a small ResNet-style block: Conv2d(64, 64, 3, padding=1) → BatchNorm → ReLU → Conv2d(64, 64, 3, padding=1) → BatchNorm, then add the input back (skip connection) before a final ReLU. Verify it preserves spatial dims and channel count.
Progress
Progress is local-only — sign in to sync across devices.