liveBook · Manning

Pointwise convolution

As explained in Math and Architectures of Deep Learning

A convolution with a one-by-one kernel that mixes channels at each spatial location and can reduce dimensionality.

A pointwise convolution uses a 1 × 1 kernel to transform the channels at each spatial location without using a wider spatial neighborhood. Its main architectural roles are reducing channel dimensionality and aligning feature-map shapes for later computation. section 11.2.2 section 11.2.3

Use pointwise convolutions to:

  • Reduce input channels before expensive 3 × 3 or 5 × 5 convolutions, sharply lowering their parameter cost. section 11.2.2
  • Project a feature map after pooling so its output channels fit the concatenated Inception representation. section 11.2.2
  • Match residual-branch resolution and channel count when a shortcut changes spatial size or doubles features. section 11.2.3

Dimensionality-reduced Inception branch

An Inception branch can apply a 1 × 1 convolution first, then a 3 × 3 or 5 × 5 convolution. The first operation reduces the incoming channel count, making the spatial convolution substantially cheaper while preserving the feature-map resolution. section 11.2.2

Residual shortcut projection

When a residual block halves spatial resolution with stride 2 and doubles the number of features, a 1 × 1 convolution with stride 2 transforms the shortcut so it can be added to the main branch. section 11.2.3

Listing 11.7 PyTorch code for a dimensionality reduced Inception block
class Inceptionv1Module(nn.Module):
    def __init__(self, in_channels, num_1x1=64,
                 reduce_3x3=96, num_3x3=128,
                 reduce_5x5=16, num_5x5=32,
                 pool_proj=32):
        super(Inceptionv1Module, self).__init__()

        self.branch1x1 = torch.nn.Sequential(
                        nn.Conv2d(               #1
                            in_channels, num_1x1,
                            kernel_size=1, bias=False),
                        nn.BatchNorm2d(num_1x1, eps=0.001),
                        nn.ReLU(inplace=True))

        self.branch3x3_1 = torch.nn.Sequential( #2
                        nn.Conv2d(
                            in_channels, reduce_3x3,
                            kernel_size=1, bias=False),
                        nn.BatchNorm2d(reduce_3x3, eps=0.001),
                        nn.ReLU(inplace=True))

        self.branch3x3_2 = torch.nn.Sequential(  #3
                        nn.Conv2d(
                            reduce_3x3, num_3x3,
                            kernel_size=3, padding=1, bias=False),
                        nn.BatchNorm2d(num_3x3, eps=0.001),
                        nn.ReLU(inplace=True))

        self.branch5x5_1 = torch.nn.Sequential(  #4
                        nn.Conv2d(
                            in_channels, reduce_5x5,
                            kernel_size=5, padding=2, bias=False),
                        nn.BatchNorm2d(reduce_5x5, eps=0.001),
                        nn.ReLU(inplace=True))
        self.branch5x5_2 = torch.nn.Sequential(  #5
                        nn.Conv2d(
                            reduce_5x5, num_5x5,
                            kernel_size=5, padding=2, bias=False),
                        nn.BatchNorm2d(num_5x5, eps=0.001),
                        nn.ReLU(inplace=True))

        self.pool = torch.nn.Sequential(         #6
                        torch.nn.MaxPool2d(
                            kernel_size=3, stride=1, padding=1),
                        nn.Conv2d(
                            in_channels, pool_proj,
                            kernel_size=1, bias=False),
                        nn.BatchNorm2d(pool_proj, eps=0.001),
                        nn.ReLU(inplace=True))


    def forward(self, x):
        conv1x1 = self.branch1x1(x)
        conv3x3 = self.branch3x3_2(self.branch3x3_1((x)))
        conv5x5 = self.branch5x5_2(self.branch5x5_1((x)))
        pool_out = self.pool(x)
        out = torch.cat(                         #7
            [conv1x1, conv3x3, conv5x5, pool_out], 1)
        return out

Inspect the PyTorch dimensionality-reduced Inception implementation, where 1 × 1 convolutions precede the 3 × 3 and 5 × 5 branches. section 11.2.2

How Math and Architectures of Deep Learning covers it

How deep it goes
Explains architectural roles and PyTorch placement, but defers detailed parameter-count derivations and kernel-level internals.
Examples
Uses reduced-channel Inception branches and stride-2 ResNet shortcut projections as concrete architectural examples.
What it assumes
Assumes convolutional feature maps, channels, pooling, strides, and residual addition while grounding usage in image-classification architectures.
What you can do after
Apply it via PyTorch to reduce channels in convolutional branches or align residual shortcut dimensions.
How it connects
Connects pointwise convolution to Inception modules, ResNet shortcuts, feature maps, pooling, channel reduction, and skip connections.

Also explained in

Compare how 2 books explain pointwise convolution →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Math and Architectures of Deep Learning. The section links point to the parts of the book it draws on.