πŸ“š Study Notes / Home / Neural Nets / Session 11
Session 11 Β· Transfer Learning & Applications

Standing on the shoulders of giant models

In Session 10 we built powerful CNN architectures. But training one from scratch needs millions of images and weeks of GPU time β€” luxuries you probably don't have. This session is the good news: you can borrow a model someone else trained and adapt it to your own task in an afternoon. Then we'll tour what CNNs do beyond "what's in this picture?" β€” drawing boxes around objects, colouring every pixel, recognising faces, reading X-rays, and even generating brand-new images. As always, we start each topic with a tiny story, then build up the real detail with code and diagrams.

⏱ 18 min readπŸ“– 4 topics

1 Transfer learning β€” borrowing a trained brain


Explain like I'm 5

Imagine someone spent ten years learning to draw β€” they got really good at hands, faces, light, and shadow. Now you want to learn to draw cartoon cats. Do you start from scratch with a crayon? No! You ask that expert to teach you, and because they already know edges, curves, and shapes, you only need to show them a few cats and they pick it up fast. Transfer learning is exactly this: take a model that already learned to "see," and teach it your new thing with just a little practice.

In Session 10 we saw that training a deep CNN like ResNet on a giant dataset takes enormous data and compute. Transfer learning is the trick of reusing a model that was already pre-trained on a big dataset and adapting it to your own, usually much smaller, task.

The standard pre-training dataset: ImageNet

The most common starting point is a model pre-trained on ImageNet β€” a dataset of about 1.2 million labelled images across 1,000 categories (dogs, cars, mushrooms, guitars…). A model that has learned to tell those 1,000 classes apart has, as a side effect, learned to recognise an enormous vocabulary of visual patterns. We reuse that.

Why early features are general

Recall from Session 10 that a CNN learns features in layers, and they get more abstract the deeper you go. This is the key insight that makes transfer learning work:

Layer depthWhat it learnsHow task-specific?
Early layersEdges, colours, simple textures, gradients.Very general β€” every image task needs these. An edge is an edge whether it's a cat or an X-ray.
Middle layersCorners, blobs, repeating patterns, simple parts (an eye, a wheel).Fairly general β€” reusable across many tasks.
Late layersWhole-object concepts ("this looks like a dog's face").Very specific to the original task's classes.
The big idea

The early layers of any vision model learn the same generic building blocks β€” edges and textures. Those are exactly what your new task needs too. So instead of relearning "what is an edge" from scratch, you keep the borrowed early layers and only retrain the task-specific end.

This isn't just hand-waving β€” Yosinski et al. (2014) measured it directly, showing that features in the first layers transfer almost perfectly between tasks, while the last layers are specialised and transfer poorly. The deeper you go, the less general the features.

Two flavours: feature extraction vs fine-tuning

There are two main ways to do transfer learning, differing in how much of the borrowed model you let change.

Feature extractionFine-tuning
IdeaFreeze the pre-trained layers; use them as a fixed "feature factory." Train only a new head.Start from pre-trained weights, but let some (or all) of them keep learning on your data.
What's trainableOnly the new final classifier layer(s).The new head plus some upper layers of the backbone.
Best whenSmall dataset, or your task is similar to ImageNet.Larger dataset, or your task differs a lot from ImageNet.
Speed / riskFast, little risk of overfitting.Slower; can overfit on tiny datasets, so use a small learning rate.
The two words to remember

We call the borrowed network (minus its final classifier) the backbone or feature extractor. The small new piece you bolt on for your task is the head. Transfer learning = keep the backbone, replace the head.

A simple recipe for choosing

πŸͺΆ
Small + similar
Freeze backbone, train head only
β†’
πŸ“¦
Big + similar
Fine-tune a few top layers
β†’
🌍
Big + different
Fine-tune most layers, low LR
Worked example β€” pretrained ResNet for your own classes

Say you want to classify 5 kinds of flowers with only ~2,000 photos. Far too few to train a deep CNN from scratch. Here's the standard PyTorch pattern using a ResNet-18 pre-trained on ImageNet. The whole trick is in two lines: freeze the backbone, then replace the final layer so it outputs 5 classes instead of 1,000.

import torch
import torch.nn as nn
from torchvision import models

# 1. Load a model pre-trained on ImageNet
model = models.resnet18(weights=models.ResNet18_Weights.DEFAULT)

# 2. FEATURE EXTRACTION: freeze every borrowed parameter
for param in model.parameters():
    param.requires_grad = False

# 3. Replace the head. resnet18's classifier is `model.fc`,
#    a Linear(512 -> 1000). Swap in a fresh Linear(512 -> 5).
#    New layers default to requires_grad=True, so ONLY these train.
num_features = model.fc.in_features         # 512
model.fc = nn.Linear(num_features, 5)   # 5 flower classes

# 4. Only the new head's params reach the optimizer
optimizer = torch.optim.Adam(model.fc.parameters(), lr=1e-3)
criterion = nn.CrossEntropyLoss()

# 5. Train as usual β€” but it's fast: few params, few epochs.
for images, labels in train_loader:
    optimizer.zero_grad()
    loss = criterion(model(images), labels)
    loss.backward()
    optimizer.step()

To switch from feature extraction to fine-tuning, you'd simply set requires_grad = True on the top layers too and pass their parameters to the optimizer with a small learning rate (e.g. 1e-5), so the precious pre-trained weights only nudge gently rather than getting wrecked.

Two gotchas

1. Match the preprocessing. A pretrained model expects inputs normalised exactly how it was trained (ImageNet's mean/std, a specific input size like 224Γ—224). Feed it raw differently scaled images and accuracy tanks. 2. Don't fine-tune with a big learning rate β€” you'll blow away the very knowledge you borrowed. Always go gentle when unfreezing.

Recap Transfer learning reuses a model pre-trained on a big dataset (usually ImageNet) for your smaller task. It works because early layers learn general features (edges, textures) that every vision task needs. Feature extraction freezes the backbone and trains only a new head; fine-tuning also lets upper layers keep learning at a small learning rate. In PyTorch: load a pretrained model, freeze its params, and replace model.fc with a fresh layer sized to your number of classes.

2 Object detection β€” not just "what," but "where"


Explain like I'm 5

Classification is like asking "Is there a dog in this photo?" and getting a yes/no. Object detection is like handing a friend a highlighter and saying "draw a box around every dog, every cat, and every person, and label each box." Now you don't just know what's in the picture β€” you know where each thing is and how many there are.

So far our CNNs answered "which single class is this image?" Object detection goes further: it finds multiple objects in one image and, for each, predicts both a class label and a bounding box β€” a rectangle (x, y, width, height) that frames the object.

🏷️
Classification
"This is a cat"
β†’
πŸ“
Localization
"…and it's right here" (1 box)
β†’
🎯
Detection
Many objects, each boxed + labelled

Two families of detectors

Almost every detector falls into one of two camps, trading accuracy vs speed.

Two-stage (R-CNN family)One-stage (YOLO, SSD)
How it worksStage 1: propose regions that might hold an object. Stage 2: classify + refine each box.Look once: a single network predicts all boxes and classes directly across a grid.
MembersR-CNN β†’ Fast R-CNN β†’ Faster R-CNN.YOLO ("You Only Look Once"), SSD ("Single Shot Detector").
SpeedSlower β€” two passes.Fast β€” real-time (great for video, robots, self-driving).
AccuracyHistorically a bit higher, especially small objects.Very competitive now, and far faster.
How the R-CNN family evolved

R-CNN ran a CNN on ~2,000 cropped region proposals β€” accurate but painfully slow. Fast R-CNN ran the CNN once over the whole image and shared the features. Faster R-CNN added a learned Region Proposal Network so even the "where to look" step became a neural net. Each step made it faster.

The YOLO idea, in one breath

YOLO divides the image into a grid. Each grid cell predicts a few boxes, the class in them, and a confidence score β€” all in one forward pass. That's why it's fast enough to run on live video. It's the go-to when latency matters.

How do we measure "is this box correct?" β€” IoU

A predicted box is rarely pixel-perfect. IoU (Intersection over Union) measures overlap between the predicted box and the true box:

IoU = area(overlap)  /  area(union)
  • IoU = 1.0 β€” perfect overlap (boxes identical).
  • IoU = 0 β€” no overlap at all.
  • A common rule: a detection "counts as correct" if its IoU with a true box is β‰₯ 0.5.
Worked example β€” computing IoU

Say the true box is the square from (0,0) to (10,10) β€” area 100. The predicted box is (5,0) to (15,10) β€” also area 100. They overlap in the strip (5,0)–(10,10), area = 5Γ—10 = 50.

Union = 100 + 100 βˆ’ 50 = 150. So IoU = 50 / 150 β‰ˆ 0.33 β€” below 0.5, so this prediction would not count as a correct detection.

def iou(boxA, boxB):  # boxes as (x1, y1, x2, y2)
    # intersection rectangle
    xi1, yi1 = max(boxA[0], boxB[0]), max(boxA[1], boxB[1])
    xi2, yi2 = min(boxA[2], boxB[2]), min(boxA[3], boxB[3])
    inter = max(0, xi2 - xi1) * max(0, yi2 - yi1)
    areaA = (boxA[2]-boxA[0]) * (boxA[3]-boxA[1])
    areaB = (boxB[2]-boxB[0]) * (boxB[3]-boxB[1])
    return inter / (areaA + areaB - inter)   # overlap / union

Scoring a whole detector β€” mAP

To grade a detector across a whole dataset we use mAP (mean Average Precision). At a high level: for each class you plot how precise (few false boxes) and how complete (found all objects) the detector is, summarise that curve into one number called Average Precision, then average it across all classes. Higher mAP = better detector. You'll see scores like "mAP@0.5" meaning "AP computed using the IoU β‰₯ 0.5 rule."

Why one extra cleanup step is needed

Detectors often fire several overlapping boxes on the same object. A step called Non-Maximum Suppression (NMS) keeps the highest-confidence box and deletes its near-duplicates (those with high IoU to it). Without NMS you'd "detect" the same dog five times.

Recap Object detection finds multiple objects, giving each a class label and a bounding box. Two-stage detectors (R-CNN β†’ Fast β†’ Faster) propose regions then classify them β€” accurate but slower. One-stage detectors (YOLO, SSD) predict everything in a single pass β€” fast, real-time. We measure box quality with IoU (overlap Γ· union), grade a whole model with mAP, and clean up duplicate boxes with NMS.

3 Segmentation β€” labelling every single pixel


Explain like I'm 5

A bounding box is a rough rectangle around an object β€” it includes a lot of background in the corners. Segmentation is like giving the picture to a careful kid with coloured crayons and saying "colour every road pixel grey, every car pixel blue, every tree pixel green." No rectangles β€” you trace the exact shape of everything. That's pixel-level labelling.

Detection gives you boxes; segmentation goes finer and assigns a label to every pixel. There are two important kinds:

TypeWhat it doesThree dogs in a photo β†’
Semantic segmentationLabels each pixel by class. All dogs are just "dog."One big "dog" coloured region (they're not told apart).
Instance segmentationLabels each pixel and separates individual objects.Three separately coloured dogs: dog-1, dog-2, dog-3.

The encoder–decoder shape (and U-Net)

Classification CNNs keep shrinking the image down to a tiny feature map, then output one label. But segmentation needs an output that's the same size as the input (one label per pixel). So we use an encoder–decoder architecture: first squeeze the image down to learn what's there, then expand it back up to recover where exactly.

πŸ–ΌοΈ
Input
Full image
β†’
πŸ”»
Encoder
Downsample: learn "what"
β†’
πŸ”Ί
Decoder
Upsample: recover "where"
β†’
🎨
Output
Per-pixel label map

The classic example is U-Net (Ronneberger et al., 2015), born in medical imaging. Drawn out, it makes a U shape: the encoder going down the left, the decoder climbing the right. Its signature trick is skip connections that hand the sharp, high-resolution details from each encoder level straight across to the matching decoder level β€” so fine edges aren't lost during the squeeze.

  input
    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ skip ───────────────┐
    β–Ό  β”‚                                      β–Ό
 [enc1] ──────────── skip ──────────────► [dec1] ─► output map
    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€ skip ────────┐              β–²
    β–Ό  β”‚                       β–Ό             β”‚
 [enc2] ──── skip ────► [dec2]β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    β”‚                      β–²
    β–Ό                      β”‚
 [enc3] ──────────────► [dec3]
    β”‚                      β–²
    └──── bottleneck β”€β”€β”€β”€β”€β”€β”˜
   (encoder down)     (decoder up)
            the "U" shape
What is "upsampling"?

The decoder has to grow a small feature map back to full resolution. It does this with operations like transposed convolution (sometimes loosely called "deconvolution") or simple interpolation followed by a normal conv. Think of it as the reverse of the pooling that shrank the image on the way down.

Instance segmentation: Mask R-CNN

For instance segmentation, the most famous model is Mask R-CNN (He et al., 2017). The idea is beautifully simple: take Faster R-CNN (the two-stage detector from Topic 2) and add a third output branch that, for each detected box, predicts a small binary mask β€” a per-pixel "object / not object" map inside that box.

πŸ“¦
Detect box
Faster R-CNN finds objects
β†’
🏷️
Classify
What is it?
β†’
🎭
+ Mask branch
Per-pixel shape inside the box
Worked example β€” running Mask R-CNN in PyTorch

torchvision ships a Mask R-CNN pre-trained on the COCO dataset. With transfer learning (Topic 1!) you load it and run instance segmentation in a few lines:

import torch
from torchvision.models.detection import maskrcnn_resnet50_fpn

# Pretrained on COCO (80 everyday object classes)
model = maskrcnn_resnet50_fpn(weights="DEFAULT")
model.eval()                              # inference mode

with torch.no_grad():
    out = model([image_tensor])[0]   # one image in, dict out

# out["boxes"]  -> bounding boxes  (N, 4)
# out["labels"] -> class id per object
# out["scores"] -> confidence per object
# out["masks"]  -> per-pixel masks (N, 1, H, W)
keep = out["scores"] > 0.7      # keep confident detections

Notice the output bundles boxes + labels + masks together β€” that's detection and segmentation in one model. To adapt it to your own classes, you'd replace its box and mask heads (exactly the transfer-learning move from Topic 1) and fine-tune.

Recap Segmentation labels every pixel. Semantic segmentation labels by class (all dogs = "dog"); instance segmentation also separates each object (dog-1, dog-2…). The standard architecture is an encoder–decoder that squeezes the image then expands it back to full size; U-Net adds skip connections to keep fine detail and rules medical imaging. Mask R-CNN does instance segmentation by adding a per-object mask branch onto Faster R-CNN.

4 A tour of other computer-vision applications


Explain like I'm 5

Once a machine can "see" β€” finding edges, shapes, and objects β€” you can point that skill at almost anything. Unlock your phone with your face, let a game read your dance moves, help a doctor spot something on an X-ray, or even ask a computer to paint a picture that never existed. Same CNN superpowers, aimed at different jobs.

The same convolutional machinery β€” often via transfer learning from a big pretrained backbone β€” powers a huge range of real applications. Here's a quick guided tour of four major areas.

Face recognition

The trick here isn't to classify "which of 1,000 fixed people is this" β€” you can't retrain every time a new person joins. Instead, a CNN turns each face into an embedding: a vector of numbers where the same person's faces sit close together and different people sit far apart (recall embeddings give similar things similar codes). Recognition then becomes "is this new face's vector close to a stored one?"

Example

Phone face-unlock stores one embedding of your face at setup. Each unlock attempt is embedded and compared by distance β€” close enough β†’ unlock. Models like FaceNet are trained with a triplet loss that explicitly pulls same-person faces together and pushes different-person faces apart.

Pose estimation

Pose estimation locates a person's keypoints β€” joints like elbows, knees, wrists, and shoulders β€” and connects them into a stick-figure skeleton. The model predicts a heatmap for each joint (where is it most likely?), then links them up.

Example

This powers fitness apps that count your squats, motion capture in films, sign-language reading, and gesture controls. OpenPose and the keypoint variant of Mask R-CNN are well-known examples.

Medical imaging

CNNs (and U-Net especially, from Topic 3) read X-rays, CT and MRI scans, and microscope slides β€” detecting tumours, segmenting organs, or flagging fractures. The encoder–decoder shape is ideal because doctors often need the exact outline of a region, not just a box.

Why this needs extra care

Medical data is scarce and privacy-sensitive, so transfer learning is essential β€” you rarely have millions of labelled scans. And mistakes carry real-world cost, so these models assist clinicians rather than replace them, and demand careful validation.

Generative vision

Generative models don't classify images β€” they create them. Two families dominate: GANs (Generative Adversarial Networks), where a "generator" tries to fool a "discriminator" that judges real vs fake, and diffusion models, which learn to turn random noise into an image step by step (the engine behind tools like Stable Diffusion).

Example

Text-to-image tools ("a cat astronaut, oil painting"), photo super-resolution, removing objects from photos, and style transfer are all generative vision. We won't go deep here β€” generative models get their own treatment later β€” but know they share the same convolutional roots.

The common thread

Every application above reuses the same idea: a CNN backbone that has learned to see, adapted with a task-specific head β€” classification, boxes, masks, keypoints, embeddings, or pixel generation. Master the backbone-plus-head pattern and the whole field opens up.

Recap CNNs reach far beyond classification: face recognition uses embeddings so matching is a distance check; pose estimation finds body keypoints via heatmaps; medical imaging leans on U-Net segmentation and transfer learning; and generative vision (GANs, diffusion) creates brand-new images. All of them are the same "see-then-head" recipe pointed at a different goal.

β˜… Putting it all together


This session was about using the CNNs you built in Session 10 β€” not training from scratch, and not just classifying. Here's the one-paragraph story connecting all four topics:

Because a CNN's early layers learn general features (edges, textures) and only its late layers are task-specific, you can transfer-learn: take a model pre-trained on ImageNet, keep the backbone, and swap in a new head β€” freezing for feature extraction or gently unfreezing for fine-tuning. That same backbone-plus-head recipe scales up: bolt on a detection head and you get object detection (two-stage R-CNN vs one-stage YOLO/SSD), scored with IoU and mAP; bolt on an encoder–decoder (U-Net) and you get pixel-level segmentation; add a mask branch (Mask R-CNN) and you separate every instance. Point that "see-then-head" machinery anywhere and you get face recognition, pose estimation, medical imaging, and generative vision. Next session we leave images behind and learn to model sequences with RNNs.

Quick self-check

Why do the early layers of a CNN transfer well to a new task?

Because they learn generic, low-level features β€” edges, colours, simple textures β€” that almost every vision task needs. Only the late layers are specialised to the original task's classes.

What's the difference between feature extraction and fine-tuning?

Feature extraction freezes the pretrained backbone and trains only a new head. Fine-tuning also lets some/all backbone layers keep learning (at a small learning rate). Use extraction for small or similar datasets; fine-tuning for larger or more different ones.

In transfer learning code, why do we replace model.fc?

The pretrained final layer outputs the original 1,000 ImageNet classes. We swap it for a fresh Linear layer sized to our number of classes, and (for feature extraction) it's the only part that trains.

One-stage vs two-stage detectors β€” which is faster and why?

One-stage (YOLO, SSD) is faster because it predicts all boxes and classes in a single forward pass. Two-stage (R-CNN family) first proposes regions, then classifies them β€” two passes, slower but historically a touch more accurate.

What does IoU measure, and what's a typical "correct" threshold?

IoU = area of overlap Γ· area of union between a predicted and true box. It ranges 0 (no overlap) to 1 (perfect). A detection is commonly counted correct at IoU β‰₯ 0.5.

Semantic vs instance segmentation β€” three dogs in one photo?

Semantic segmentation paints all three as one "dog" region. Instance segmentation separates them into dog-1, dog-2, dog-3. Mask R-CNN does the instance version.

Why does U-Net use skip connections?

The encoder loses fine spatial detail as it downsamples. Skip connections pass the high-resolution features straight from each encoder level to the matching decoder level, so sharp edges and precise locations are recovered in the output.

πŸ“š References & Further Reading


Class material

  • SST Deep Learning handout (Session 11) β€” your course handout for this session.

Papers, docs & deep dives