Skip to content

← CNNs from Scratch step 6 of 15

Hard Primitives

Transposed Conv2d

A transposed convolution turns each input value into a weighted output patch. Patches can overlap, so their contributions must be added.

Implement transposed_conv2d(x, w, stride=1). This exercise uses no bias, padding or output padding, dilation 1, and a single group.

Inputs and output

  • x has shape (N, C_in, H, W): batch, input channels, height and width.
  • w has shape (C_in, C_out, kH, kW). The input-channel axis comes first.
  • stride is a positive integer used along both spatial axes.
  • All dimensions are positive. x and w share a floating-point dtype and device.

Return shape (N, C_out, H_out, W_out), preserving the input dtype and device, where:

H_out = (H - 1) * stride + kH
W_out = (W - 1) * stride + kW

Place and add the patches

Start with a zero output. For each example n, input channel ci and input position (i, j), multiply x[n, ci, i, j] by every output-channel kernel w[ci, co]. Place each resulting patch with its top-left corner at (i * stride, j * stride):

out[n, co, i * stride + a, j * stride + b] += x[n, ci, i, j] * w[ci, co, a, b]

Apply this for every output channel co and kernel position (a, b). Use w in its given spatial order. Add contributions from all input channels and positions; do not overwrite overlaps or mix batch examples.

For a single input channel containing one row [1, 2], a kernel with one row [1, 3], and stride 1, the patches are [1, 3] and [2, 6], offset by one position. Their sum is [1, 5, 6]. At stride 3, the result is [1, 3, 0, 2, 6]: positions reached by no patch stay zero.

Transposed convolution is often used to enlarge feature maps. It does not always enlarge them: a 1-by-1 kernel with stride 1 keeps the spatial shape. It applies the transpose of a convolution's linear map, not its inverse, so it does not generally recover the original input. You are implementing the forward operation here, not computing gradients.

Leave x and w unchanged.