Building a CNN in Python
Press Next → or use ← → arrow keys
Why CNNs Were Born
The three ideas that make CNNs work: look at small patches, reuse one filter across the whole image, and stack layers so simple features combine into complex ones.
The Architecture — A Data Assembly Line
An image flows through stations that shrink it spatially while enriching it with channels, ending in class probabilities. Here's the network we'll build:
32×32 → 16×16 → 8×8 → 4×4 as pooling compresses; meanwhile filters climb 32 → 64 → 128. Then flatten and two dense layers turn features into a 10-way decision.
The Building Blocks
Every CNN is assembled from a handful of standard layers. Each has one job:
Conv → BatchNorm → ReLU → (Conv…) → Pool → Dropout, stacked into blocks, then a dense head. Learn this pattern and you can read almost any CNN.
The Dataset — CIFAR-10
60,000 tiny colour photos across 10 everyday classes — the classic proving ground for image models.
Normalising to [0, 1] (and using float32 for GPU speed) is the single most important preprocessing step — skip it and training may never converge.
Data Augmentation
Randomly transform each training image on the fly so the network sees endless variations — and learns features that survive real-world wobble.
Validation and test images stay untouched — you want to measure real-world performance, not performance on artificially varied pictures.
The Three Convolutional Blocks
Each block runs conv layers, normalises, pools, and drops out — doubling the filters as the spatial size halves:
| Block | Layers | Filters | Output |
|---|---|---|---|
| 1 | 2× Conv 3×3 + BN → Pool → Dropout 0.25 | 32 | 16×16×32 |
| 2 | 2× Conv 3×3 + BN → Pool → Dropout 0.25 | 64 | 8×8×64 |
| 3 | Conv 3×3 + BN → Pool → Dropout 0.25 | 128 | 4×4×128 |
Two stacked 3×3 layers cover the same 5×5 receptive field with fewer parameters and an extra ReLU in between — more expressive, cheaper. All use padding='same' and light L2.
The Classification Head
After the conv blocks, flatten the feature maps and let dense layers make the final decision:
Compile & Train Smartly
Pick the optimiser and loss, then let callbacks babysit the training run:
Loss: categorical cross-entropy
Metric: accuracy (for humans)
ReduceLROnPlateau — halve LR on a plateau
ModelCheckpoint — save the best model
EarlyStopping ends training once the validation loss stops improving, so you get the best model without wasting compute or overfitting.
The Model in Keras
One block, expressed in a handful of layers — repeat with more filters for the deeper blocks:
from tensorflow.keras import layers, models, regularizers
model = models.Sequential([
layers.Input((32, 32, 3)),
# Block 1
layers.Conv2D(32, 3, padding='same', activation='relu',
kernel_regularizer=regularizers.l2(1e-4)),
layers.BatchNormalization(),
layers.Conv2D(32, 3, padding='same', activation='relu'),
layers.MaxPooling2D(2),
layers.Dropout(0.25),
# ... Block 2 (64 filters), Block 3 (128 filters) ...
layers.Flatten(),
layers.Dense(512, activation='relu'),
layers.BatchNormalization(),
layers.Dropout(0.5),
layers.Dense(10, activation='softmax'),
])
model.compile(optimizer='adam', loss='categorical_crossentropy',
metrics=['accuracy'])
Keras' Sequential API stacks layers top to bottom. Swap the filter counts and you have blocks 2 and 3 — the pattern is deliberately repetitive.
Results on CIFAR-10
After training, the custom CNN reaches solid accuracy on held-out test images:
| Easiest classes (F1) | Hardest classes (F1) |
|---|---|
| Automobile 0.90 · Ship 0.88 · Horse 0.87 | Cat 0.62 · Bird 0.69 · Dog 0.69 |
Animals share fur, poses, and backgrounds, so they blur together. Vehicles have rigid, distinct shapes and separate cleanly. The confusion is in the data, not a bug.
Case Study — Pneumonia from X-Rays
With only ~5,900 chest X-rays, training from scratch is hopeless. Transfer learning with a pretrained VGG16 turns a tiny dataset into a strong diagnostic model.
Reading the Loss Curves
The training and validation loss curves are your dashboard. Learn to read them at a glance:
| Pattern | What you see | Fix |
|---|---|---|
| Healthy | Both losses fall together, small gap | Nothing — ship it |
| Overfitting | Train ↓ but val ↑ | More dropout / augmentation |
| Underfitting | Loss flat from epoch 1 | Bigger model, higher LR, add BatchNorm |
| Oscillating | Loss bounces wildly | Lower the learning rate |
Accuracy alone hides problems. The gap between train and val loss is what tells you whether to regularise more, train longer, or dial the learning rate.
Which Architecture When?
| Architecture | Best for | Data size |
|---|---|---|
| Custom CNN | Learning, full control | 50k–500k |
| VGG16 (transfer) | Medical, domain-specific | 1k–50k |
| ResNet50 | General vision | 10k+ |
| EfficientNet-B0 | Production, mobile | Any |
| Vision Transformer | Massive datasets | 1M+ |
Under 10k images? Reach for transfer learning. Learning the ropes? Build a custom CNN on CIFAR-10. Shipping to phones? EfficientNet. Have a million labelled images? A Vision Transformer.
7 Golden Rules for Building CNNs
Normalise, augment, stack conv blocks, regularise, and read the loss curves. From CIFAR-10 to a medical classifier, it's the same recipe — scaled to the problem.