Convolutional Neural Networks
Convolutional neural networks, or CNNs, are among the most influential architectures in deep learning. Although their ideas are mathematically rooted in linear algebra, their design reflects a simple principle: images should be processed according to their spatial structure. A dense network treats every pixel as an unrelated input, whereas a CNN learns how neighboring values form meaningful visual patterns such as edges, textures, and shapes.
Consider a color image with a resolution of (224 \times 224). It contains (224 \times 224 \times 3 = 150{,}528) input values. If every one of these values were connected to a hidden layer with 1,000 neurons, the first layer alone would require more than 150 million parameters. Such a model would be expensive to train, difficult to optimize, and highly vulnerable to overfitting.
CNNs address this problem with two central mechanisms:
- Local connectivity: Each neuron examines only a small region of the input rather than the entire image.
- Weight sharing: The same convolutional filter is reused at every spatial position.
Together, these mechanisms allow a CNN to learn a feature detector once and then apply it anywhere in an image. A filter trained to recognize a horizontal edge can therefore detect that edge in the upper-left corner, the center, or the lower-right corner.
How a Convolution Works
A convolutional layer contains a set of learnable filters. Each filter has a small spatial size, such as (3 \times 3) or (5 \times 5), and spans every input channel. The filter slides across the input feature map. At each location, it performs an element-wise multiplication with the corresponding input region, sums the results, and adds a bias.
The result is an output feature map containing the locations where the learned pattern appears. Multiple filters produce multiple output channels, allowing one layer to detect several types of features simultaneously. Early convolutional layers often respond to basic elements such as edges and color contrasts, while deeper layers combine them into textures, object parts, and complete objects.
Several hyperparameters control the operation:
- Kernel size determines the area visible to each filter. Smaller kernels are common in modern architectures because stacking many layers can gradually expand the receptive field.
- Stride specifies how far a filter moves between calculations. A stride greater than one reduces the spatial resolution of the output.
- Padding adds values around the input border. For a filter of size (k), padding of (\lfloor k/2 \rfloor) can preserve the spatial dimensions when the stride is one.
- Input and output channels determine how many feature maps participate in the operation.
For a two-dimensional convolution, the output width and height can be calculated as
[
O = \left\lfloor \frac{I + 2P - K}{S} \right\rfloor + 1,
]
where (I) is the input size, (P) is the padding, (K) is the kernel size, and (S) is the stride.
The Main Building Blocks
Convolutional Layers
Convolutional layers perform feature extraction. Their filters are normally optimized through gradient-based training rather than designed manually. A network may use dozens or hundreds of filters in a single layer, with each filter specializing in a different visual pattern.
Activation Functions
Convolution is a linear operation, so a nonlinear activation is needed to represent complex relationships. The rectified linear unit, or ReLU, is the most widely used choice:
[
\operatorname{ReLU}(x) = \max(0, x).
]
ReLU is computationally inexpensive and generally trains more effectively than saturating activation functions. Other options include Leaky ReLU, GELU, and sigmoid or softmax functions at the output.
Pooling and Downsampling
Pooling reduces the height and width of feature maps. Max pooling keeps the largest value in each local window, while average pooling uses the mean. Downsampling lowers computational cost and limits the model’s sensitivity to small changes in position.
Modern networks do not always rely on explicit pooling layers. Strided convolutions and global average pooling can perform similar functions, and architectures such as ResNet often preserve spatial resolution for longer before reducing it.
Normalization and Residual Connections
Batch normalization is frequently placed after a convolution and before an activation. It stabilizes training by normalizing intermediate activations and often makes optimization faster.
Residual connections provide another important improvement. Instead of requiring a block to learn an entire transformation, the block learns a residual update:
[
y = F(x) + x.
]
This shortcut gives gradients a direct path through the network, making it much easier to train very deep models.
Classification Heads
After feature extraction, a classification network converts its output into predictions. A conventional head flattens the feature maps and passes them through fully connected layers. Many contemporary designs instead use global average pooling, which collapses each channel to a single value before the final classifier. This can dramatically reduce the number of parameters and help limit overfitting.
A Simple CNN in PyTorch
The following model provides a compact example for MNIST digit classification. It uses two convolutional blocks followed by a fully connected classification head.
import torch
import torch.nn as nn
class SimpleCNN(nn.Module):
def __init__(self):
super().__init__()
self.features = nn.Sequential(
# Block 1: 1 input channel, 16 output channels
nn.Conv2d(
in_channels=1,
out_channels=16,
kernel_size=3,
stride=1,
padding=1
),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
# Block 2: 16 input channels, 32 output channels
nn.Conv2d(
in_channels=16,
out_channels=32,
kernel_size=3,
stride=1,
padding=1
),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2)
)
self.classifier = nn.Sequential(
nn.Flatten(),
nn.Linear(32 * 7 * 7, 128),
nn.ReLU(inplace=True),
nn.Linear(128, 10)
)
def forward(self, x):
x = self.features(x)
return self.classifier(x)
model = SimpleCNN()
print(model)
The MNIST images are (28 \times 28) pixels with one channel. The first pooling operation reduces them to (14 \times 14), and the second reduces them to (7 \times 7). The final linear layer produces ten logits, one for each digit class. When training with PyTorch’s CrossEntropyLoss, the model outputs raw logits directly because the loss function performs the necessary log-softmax calculation internally.
Why CNNs Remain Powerful
The effectiveness of a CNN comes from the combination of sparse connectivity, shared weights, hierarchical feature learning, and spatial downsampling. These properties give CNNs a useful balance between expressive power and computational efficiency. They can learn a filter once and recognize the same feature across an entire image, making them naturally suited to classification, object detection, segmentation, image retrieval, and medical imaging.
The architecture has evolved considerably since LeNet introduced the basic convolutional design. AlexNet demonstrated the potential of deep CNNs on large-scale image datasets, VGG emphasized uniform stacks of small convolutional blocks, and ResNet made very deep networks practical through residual connections. More recent systems combine convolutional backbones with attention mechanisms, normalization techniques, and carefully designed training strategies.
Understanding CNNs therefore requires more than memorizing layer types. The essential concepts are how filters detect spatial patterns, how weight sharing supports parameter efficiency, how deeper layers build hierarchical representations, and how architectural choices affect accuracy, speed, and generalization. These ideas form a foundation for modern computer vision and for many other applications that process data with meaningful spatial or local structure.