Convolutional Neural Networks
convolution Β· filters Β· pooling Β· stride Β· padding Β· ResNet Β· transfer learning
What Is a CNN?
A Convolutional Neural Network (CNN) is a deep learning architecture designed for grid-structured data (images, video, audio). It uses learnable filters to detect spatial patterns automatically β edges, textures, shapes, objects.
| Layer Type | Role |
|---|---|
| Conv2D | Detect local patterns using learned filters |
| Activation | Non-linearity β ReLU after each conv |
| BatchNorm | Normalize + stabilize training |
| Pooling | Downsample β reduce spatial size |
| Flatten | Convert 3D feature map β 1D vector |
| Dense | Classification or regression head |
Convolution Operation
A filter (kernel) slides over the input, computing dot products at each position to produce a feature map.
| Parameter | Effect |
|---|---|
| Filter size (F) | 3Γ3 most common; larger = bigger receptive field |
| Stride (S) | Step size. S=2 halves output size |
| Padding (P) | SAME keeps size; VALID shrinks output |
| # Filters | = # output channels / feature maps |
keras.layers.Conv2D( filters=32, # number of filters kernel_size=(3,3), # filter size strides=(1,1), # stride padding='same', # SAME or VALID activation='relu' # fused activation )
Pooling Layers
Pooling reduces spatial dimensions, decreasing computation and providing spatial invariance to small translations.
| Type | Operation | Use When |
|---|---|---|
| MaxPool | Take max in each window | Most common β preserves strongest activations |
| AvgPool | Average in each window | Smoother features; used in later layers |
| GlobalAvgPool | One average per channel | Replaces Flatten β fewer parameters |
| GlobalMaxPool | One max per channel | Compact feature extraction |
# Standard: 2Γ2 window, stride 2 keras.layers.MaxPooling2D(pool_size=(2,2)) # Global β removes spatial dims entirely keras.layers.GlobalAveragePooling2D() # Adaptive β specify output size (PyTorch) nn.AdaptiveAvgPool2d(output_size=(1,1))
Receptive Field & Feature Maps
The receptive field is the region of the input that a neuron in a deeper layer "sees". Deeper layers have larger receptive fields and detect more abstract features.
| Layer Depth | Detects | Receptive Field |
|---|---|---|
| Conv Layer 1 | Edges, gradients, colours | 3Γ3 β 7Γ7 |
| Conv Layer 2 | Corners, textures, curves | ~15Γ15 |
| Conv Layer 3 | Parts, patterns, shapes | ~31Γ31 |
| Conv Layer 4+ | Objects, faces, scenes | Full image |
Standard CNN Architecture Pattern
from tensorflow import keras model = keras.Sequential([ # Block 1 keras.layers.Conv2D(32, (3,3), padding='same', activation='relu', input_shape=(224,224,3)), keras.layers.BatchNormalization(), keras.layers.Conv2D(32, (3,3), padding='same', activation='relu'), keras.layers.MaxPooling2D((2,2)), keras.layers.Dropout(0.25), # Block 2 keras.layers.Conv2D(64, (3,3), padding='same', activation='relu'), keras.layers.BatchNormalization(), keras.layers.Conv2D(64, (3,3), padding='same', activation='relu'), keras.layers.MaxPooling2D((2,2)), keras.layers.Dropout(0.25), # Classifier head keras.layers.GlobalAveragePooling2D(), keras.layers.Dense(256, activation='relu'), keras.layers.Dropout(0.5), keras.layers.Dense(10, activation='softmax') ])
CNN Design Rules
- Double filters after each MaxPool: 32 β 64 β 128 β 256. Spatial size halves, depth doubles.
- Use 3Γ3 filters throughout. Two 3Γ3 layers have the same receptive field as one 5Γ5 but fewer parameters.
- BatchNorm after Conv, before activation (or after β both are common; before is theoretically cleaner).
- GlobalAvgPool instead of Flatten to reduce parameters and overfitting in the classifier head.
- Dropout 0.25 after pooling blocks, 0.5 before the final Dense.
- He initialization for all ReLU layers β set kernel_initializer='he_normal'.
Famous CNN Architectures
| Architecture | Year | Key Innovation | Top-1 (ImageNet) | Best For |
|---|---|---|---|---|
| LeNet-5 | 1998 | First successful CNN; conv + pool pattern | β | Digit recognition (MNIST) |
| AlexNet | 2012 | Deep CNN on GPU; ReLU; Dropout | 63.3% | Sparked deep learning revolution |
| VGG-16/19 | 2014 | All 3Γ3 filters; very deep (16β19 layers) | 74.5% | Feature extraction baseline |
| GoogLeNet | 2014 | Inception modules; 1Γ1 convolutions | 74.8% | Efficient multi-scale features |
| ResNet-50 | 2015 | Residual (skip) connections; very deep | 76.1% | General backbone; most popular |
| DenseNet | 2017 | Dense connections; every layer β all later | 77.2% | Feature reuse; medical imaging |
| MobileNetV2 | 2018 | Depthwise separable conv; lightweight | 72.0% | Mobile / edge deployment |
| EfficientNet-B0 | 2019 | Compound scaling (width+depth+resolution) | 77.1% | Best accuracy/efficiency trade-off |
| ConvNeXt | 2022 | Modernized ResNet; ViT-inspired design | 82.1% | Pure-CNN alternative to ViT |
Residual Connections (ResNet)
ResNet's key innovation: skip connections that add the input directly to the output of a stack of layers. This solves the vanishing gradient problem, enabling networks with 50β152+ layers.
def residual_block(x, filters): shortcut = x x = keras.layers.Conv2D(filters, (3,3), padding='same')(x) x = keras.layers.BatchNormalization()(x) x = keras.layers.Activation('relu')(x) x = keras.layers.Conv2D(filters, (3,3), padding='same')(x) x = keras.layers.BatchNormalization()(x) x = keras.layers.Add()([x, shortcut]) # skip! x = keras.layers.Activation('relu')(x) return x
1Γ1 Convolutions
A 1Γ1 conv applies a learned linear combination across channels at each spatial position β no spatial aggregation, pure channel mixing.
| Use Case | How |
|---|---|
| Channel reduction | 256 β 64 channels before expensive 3Γ3 conv (bottleneck) |
| Channel expansion | 64 β 256 after depthwise conv (MobileNet inverted residual) |
| Dimension matching | Match channels in skip connections |
| Pointwise mixing | Mix channel information without spatial context |
Transfer Learning
Reuse a model pretrained on a large dataset (ImageNet) as a feature extractor for a new task β dramatically reduces data and compute needs.
- Load pretrained base: EfficientNet, ResNet50, MobileNetV2 with include_top=False.
- Freeze base weights: base.trainable = False β only train new head.
- Add custom head: GlobalAvgPool β Dense β Softmax for your classes.
- Train head only for 5β10 epochs with higher LR (1e-3).
- Fine-tune: Unfreeze top layers of base, retrain with low LR (1e-5).
base = keras.applications.EfficientNetB0( include_top=False, weights='imagenet', input_shape=(224,224,3) ) base.trainable = False # freeze base x = keras.layers.GlobalAveragePooling2D()(base.output) x = keras.layers.Dense(128, activation='relu')(x) out = keras.layers.Dense(num_classes, activation='softmax')(x) model = keras.Model(base.input, out)
Fine-tuning Strategy
| Scenario | Strategy | LR |
|---|---|---|
| Small data, similar domain | Freeze all base; train head only | 1e-3 |
| Small data, different domain | Freeze early layers; unfreeze top 20% | 1e-4 |
| Large data, similar domain | Unfreeze all; fine-tune everything | 1e-4 |
| Large data, different domain | Train from scratch or fine-tune all | 1e-3 |
# After training head, unfreeze top layers base.trainable = True # Keep early layers frozen for layer in base.layers[:100]: layer.trainable = False # Recompile with much lower LR model.compile( optimizer=keras.optimizers.Adam(1e-5), loss='categorical_crossentropy' )
Data Augmentation
aug = keras.Sequential([ layers.RandomFlip("horizontal"), layers.RandomRotation(0.15), layers.RandomZoom(0.1), layers.RandomContrast(0.1), layers.RandomBrightness(0.1), layers.RandomTranslation(0.1, 0.1), ], name="augmentation")
| Technique | When to Use |
|---|---|
| Horizontal Flip | Natural images (not medical, text, digits) |
| Rotation Β±15Β° | Most tasks; use Β±90Β° for microscopy |
| CutOut / Erasing | Force model to use full image context |
| Mixup | Blend 2 images + labels; strong regularizer |
| CutMix | Paste crop of one image onto another |
| RandAugment | Automatic augmentation policy search |
Beyond Classification
| Task | Output | Key Models |
|---|---|---|
| Classification | Class label | ResNet, EfficientNet, VGG |
| Localization | Label + bounding box | ResNet + regression head |
| Object Detection | Multiple boxes + labels | YOLO, SSD, Faster R-CNN |
| Semantic Seg. | Class per pixel | U-Net, DeepLab, FCN |
| Instance Seg. | Mask per object instance | Mask R-CNN, SOLO |
| Pose Estimation | Keypoint locations | OpenPose, HRNet |
CNN Hyperparameters & Troubleshooting
Key Hyperparameters
| Param | Typical Values |
|---|---|
| Filter sizes | 3Γ3 (default), 5Γ5, 7Γ7 (first layer) |
| Num filters | 32β64β128β256 (doubling) |
| Stride | 1 (conv), 2 (downsample) |
| Padding | SAME (keeps size), VALID (shrinks) |
| Dropout | 0.25 (after pool), 0.5 (before dense) |
| Batch size | 32β128 for images |
| LR | 1e-3 (Adam), 1e-5 (fine-tune) |
Common Problems & Fixes
| Problem | Fix |
|---|---|
| High train acc, low val acc | More augmentation, dropout, L2 reg |
| Low train + val acc | More filters, more layers, longer training |
| Loss not decreasing | Lower LR, check normalization, fix data pipeline |
| Checkerboard artifacts | Use resize-conv instead of ConvTranspose |
| Very slow training | Use GPU, mixed precision, prefetch data |
| NaN loss | Lower LR, gradient clipping, check labels |
Input Preprocessing
# Scale to [0, 1] x = x / 255.0 # ImageNet normalization mean = [0.485,0.456,0.406] std = [0.229,0.224,0.225] x = (x - mean) / std # Keras built-in per model preprocess = keras.applications\ .efficientnet.preprocess_input x = preprocess(x)
CNN β Mastery Checklist
Core Concepts
- Explain how a filter slides over an image to produce a feature map
- Calculate output size using W_out = (WβF+2P)/S + 1
- Describe what MaxPool vs GlobalAvgPool does
- Explain what the receptive field is and how it grows
- Distinguish SAME vs VALID padding and their output sizes
- Count parameters in a Conv2D layer: FΒ²ΓC_inΓC_out + C_out
Architecture & Design
- Build a 3-block CNN in Keras with ConvβBNβReLUβPool
- Explain why residual connections help very deep networks
- Implement a residual block using the Functional API
- Explain what a 1Γ1 conv does and when to use it
- Compare EfficientNet, ResNet, and MobileNet trade-offs
- Choose the right architecture for mobile vs server deployment
Transfer Learning & Tuning
- Load EfficientNetB0 with include_top=False and add a custom head
- Freeze and unfreeze base layers correctly
- Apply the right LR for head training vs fine-tuning
- Apply 4+ image augmentation techniques appropriately
- Diagnose overfitting vs underfitting from learning curves
- Preprocess inputs correctly for a given pretrained backbone