DEEP LEARNING / 4. CNNS

Convolutional Neural Networks

Exploiting spatial structure — the vision backbone


EXPLANATION

CNNs exploit a key property of images: nearby pixels are related. Instead of connecting every pixel to every neuron (expensive, ignores structure), convolution slides a small filter across the image, detecting features wherever they appear.

Three key ideas:
• Local connectivity → filter sees small patch at a time (spatial locality)
• Weight sharing    → same filter used everywhere (translation invariance)
• Pooling           → progressively reduce spatial size, increase receptive field

CNN architecture pattern:
[Conv → BN → ReLU] × N → Flatten → Linear → Output

Each conv block doubles channels and halves spatial size. The network goes from (H×W×3) raw pixels to (1×1×C) deep feature vectors.

DATA FLOW

Input image: (224 × 224 × 3)
        ↓  Conv(64, 3×3) + BN + ReLU
  (224 × 224 × 64)
        ↓  MaxPool(2×2)
  (112 × 112 × 64)
        ↓  Conv(128, 3×3) + BN + ReLU
  (112 × 112 × 128)
        ↓  MaxPool(2×2)
  (56 × 56 × 128)
        ↓  ... deeper layers ...
  (7 × 7 × 512)
        ↓  Global Average Pool
  (512,)
        ↓  Linear(512 → num_classes)
  (num_classes,)

CODE

PYTHON
1import torch
2import torch.nn as nn
3
4# ── Convolution intuition ─────────────────────────────────────────
5conv = nn.Conv2d(
6 in_channels=3, # RGB
7 out_channels=64, # learn 64 different filters
8 kernel_size=3, # 3×3 filter
9 padding=1, # same padding: output size = input size
10 stride=1,
11)
12x = torch.randn(8, 3, 224, 224) # batch=8, C=3, H=224, W=224
13out = conv(x)
14print(f"Input: {x.shape}") # (8, 3, 224, 224)
15print(f"Output: {out.shape}") # (8, 64, 224, 224)
16
17# ── Conv block (the repeating unit) ──────────────────────────────
18class ConvBlock(nn.Module):
19 def __init__(self, in_c, out_c, stride=1):
20 super().__init__()
21 self.block = nn.Sequential(
22 nn.Conv2d(in_c, out_c, 3, stride=stride, padding=1, bias=False),
23 nn.BatchNorm2d(out_c),
24 nn.ReLU(inplace=True),
25 )
26 def forward(self, x):
27 return self.block(x)
28
29# ── Simple CNN for image classification ───────────────────────────
30class SimpleCNN(nn.Module):
31 def __init__(self, num_classes=10):
32 super().__init__()
33 self.features = nn.Sequential(
34 ConvBlock(3, 64, stride=1), # (B, 64, 224, 224)
35 nn.MaxPool2d(2), # (B, 64, 112, 112)
36 ConvBlock(64, 128, stride=1), # (B, 128, 112, 112)
37 nn.MaxPool2d(2), # (B, 128, 56, 56)
38 ConvBlock(128, 256, stride=2), # (B, 256, 28, 28)
39 ConvBlock(256, 512, stride=2), # (B, 512, 14, 14)
40 )
41 self.head = nn.Sequential(
42 nn.AdaptiveAvgPool2d(1), # (B, 512, 1, 1)
43 nn.Flatten(), # (B, 512)
44 nn.Linear(512, num_classes),
45 )
46
47 def forward(self, x):
48 return self.head(self.features(x))
49
50model = SimpleCNN(num_classes=10)
51x = torch.randn(4, 3, 224, 224)
52out = model(x)
53print(f"Output: {out.shape}") # (4, 10)
54
55total = sum(p.numel() for p in model.parameters())
56print(f"Parameters: {total:,}")
← PREV3. OptimizersNEXT →5. RNNs & LSTMs