How to Implement Transfer Learning with Pre-Trained Models in AI For Beginners Computer Vision
Transfer learning in the AI For Beginners curriculum lets you repurpose ImageNet-trained models like MobileNetV2 or ResNet-18 for custom image classification by freezing the backbone, adding a new classification head, and optionally fine-tuning top layers.
The computer vision unit in Microsoft's AI-For-Beginners repository provides complete, runnable implementations in both TensorFlow/Keras and PyTorch. These lessons demonstrate how to solve the classic "cats vs. dogs" classification problem using pre-trained weights rather than training from scratch.
Why Transfer Learning Works for Small Datasets
Training deep neural networks requires millions of labeled images. Most practitioners don't have this data. Transfer learning bridges this gap by reusing features learned from large datasets (typically ImageNet's 1.2 million images) and adapting them to your specific task.
The AI For Beginners approach follows a proven two-phase pattern:
- Feature extraction — freeze the pre-trained backbone and train only the new classification head
- Fine-tuning — unfreeze select layers and continue training with reduced learning rates
This method achieves high accuracy with as few as 2,000 training images.
TensorFlow/Keras Implementation
The file lessons/4-ComputerVision/08-TransferLearning/TransferLearningTF.ipynb demonstrates transfer learning using Keras Applications.
Loading the Pre-Trained Backbone
import tensorflow as tf
from tensorflow import keras
from tfcv import load_cats_dogs_dataset, plot_results
# Load dataset
ds_train, ds_test = load_cats_dogs_dataset(batch_size=64)
# Load MobileNetV2 pre-trained on ImageNet
base = keras.applications.MobileNetV2(
weights='imagenet',
include_top=False, # exclude original classification head
input_shape=(224, 224, 3)
)
Setting include_top=False removes ImageNet's 1000-class output layer, allowing you to attach your own classifier.
Freezing and Building the Model
# Freeze all backbone layers
base.trainable = False
# Build new classification head
inputs = keras.Input(shape=(224, 224, 3))
x = keras.applications.mobilenet_v2.preprocess_input(inputs)
x = base(x, training=False) # run in inference mode (BatchNorm)
x = keras.layers.GlobalAveragePooling2D()(x)
outputs = keras.layers.Dense(2, activation='softmax')(x)
model = keras.Model(inputs, outputs)
The GlobalAveragePooling2D layer reduces spatial dimensions from (7, 7, 1280) to (1280), feeding directly into the 2-class output for cats vs. dogs.
Training and Fine-Tuning
# Phase 1: Train only the head
model.compile(
optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
history = model.fit(
ds_train,
validation_data=ds_test,
epochs=5
)
# Phase 2: Fine-tune top layers
base.trainable = True
model.compile(
optimizer=keras.optimizers.Adam(1e-5), # 100x smaller learning rate
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
fine_history = model.fit(
ds_train,
validation_data=ds_test,
epochs=3
)
The helper function plot_results(history) in tfcv.py generates visualization of training curves.
PyTorch Implementation
The equivalent PyTorch workflow appears in lessons/4-ComputerVision/08-TransferLearning/TransferLearningPyTorch.ipynb, using torchvision models.
Model Setup and Layer Freezing
import torch
import torchvision
from pytorchcv import load_cats_dogs_dataset, train, validate, plot_results
# Load dataset with custom loaders
dataset, train_loader, test_loader = load_cats_dogs_dataset()
# Load pre-trained ResNet-18
base = torchvision.models.resnet18(pretrained=True)
# Freeze all parameters
for param in base.parameters():
param.requires_grad = False
# Replace final FC layer for binary classification
num_ftrs = base.fc.in_features
base.fc = torch.nn.Linear(num_ftrs, 2)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
base = base.to(device)
Training Loop and Selective Unfreezing
# Phase 1: Train classification head only
hist = train(base, train_loader, test_loader, epochs=5, lr=0.001)
# Phase 2: Unfreeze last residual block (layer4) for fine-tuning
for name, param in base.named_parameters():
if "layer4" in name:
param.requires_grad = True
# Re-create optimizer with only trainable parameters
optimizer = torch.optim.Adam(
filter(lambda p: p.requires_grad, base.parameters()),
lr=1e-5
)
fine_hist = train(base, train_loader, test_loader,
optimizer=optimizer, epochs=3, lr=1e-5)
The train() and validate() functions in pytorchcv.py implement standard training loops with progress tracking and metric logging.
Key Architectural Differences: TensorFlow vs. PyTorch
| Aspect | TensorFlow/Keras | PyTorch |
|---|---|---|
| Pre-trained model loading | keras.applications.MobileNetV2(weights='imagenet', include_top=False) |
torchvision.models.resnet18(pretrained=True) |
| Freeze mechanism | base.trainable = False |
param.requires_grad = False for each parameter |
| Classification head | GlobalAveragePooling2D() → Dense(2, activation='softmax') |
AdaptiveAvgPool2d((1,1)) → replace fc layer |
| Training orchestration | model.fit() with callbacks |
Custom train() function in pytorchcv.py |
| Fine-tuning control | Unfreeze entire backbone: base.trainable = True |
Selective unfreeze by layer name: "layer4" in name |
Helper Functions and Utilities
The repository includes utility modules that abstract boilerplate code:
tfcv.py— dataset loading (load_cats_dogs_dataset), image preprocessing, and visualization (plot_results)pytorchcv.py— PyTorch dataset wrappers, training loops (train,validate), and metric plotting
These files let you focus on model architecture rather than data pipeline implementation.
Fine-Tuning Strategies
Both implementations demonstrate progressive unfreezing:
| Strategy | When to Use | Learning Rate |
|---|---|---|
| Head-only training | Very small datasets (< 1,000 images) | Standard (1e-3) |
| Top-block fine-tuning | Medium datasets, similar to ImageNet | Reduced (1e-4 to 1e-5) |
| Full fine-tuning | Large datasets, very different from ImageNet | Very low (1e-5 to 1e-6) |
The AI For Beginners notebooks use top-block fine-tuning as the default balanced approach.
Adapting to Your Own Dataset
Replace the backbone and adjust class count:
TensorFlow:
# Swap MobileNetV2 for EfficientNetB0
base = keras.applications.EfficientNetB0(
weights='imagenet',
include_top=False,
input_shape=(224, 224, 3)
)
# Change output classes
outputs = keras.layers.Dense(NUM_YOUR_CLASSES, activation='softmax')(x)
PyTorch:
# Swap ResNet-18 for DenseNet-121
base = torchvision.models.densenet121(pretrained=True)
# Replace classifier
base.classifier = torch.nn.Linear(base.classifier.in_features, NUM_YOUR_CLASSES)
Summary
- Transfer learning in AI For Beginners uses a consistent two-phase approach across TensorFlow and PyTorch implementations
- Freeze the backbone initially to preserve ImageNet features while training a new classification head
- Fine-tune selectively with reduced learning rates to adapt deeper layers to your specific data
- Key files:
TransferLearningTF.ipynb,TransferLearningPyTorch.ipynb,tfcv.py, andpytorchcv.pyinlessons/4-ComputerVision/08-TransferLearning/
Frequently Asked Questions
What pre-trained models does AI For Beginners recommend for beginners?
The official notebooks use MobileNetV2 (TensorFlow) and ResNet-18 (PyTorch) because they offer strong accuracy with moderate computational requirements. MobileNetV2 runs efficiently on CPU, making it ideal for educational environments without GPU access. Both models achieve >95% accuracy on the cats vs. dogs dataset after fine-tuning.
How does freezing layers work in practice?
Freezing prevents gradient updates from modifying pre-trained weights. In Keras, base.trainable = False sets all layer trainable attributes to False. In PyTorch, you set requires_grad=False on each parameter tensor. This ensures the backbone acts as a fixed feature extractor during initial training, preventing overfitting on small datasets.
When should I fine-tune versus just training the head?
Fine-tune when your dataset size exceeds ~1,000 images per class or when your target images differ significantly from ImageNet (medical imaging, satellite photos, industrial defects). If your data closely resembles natural photographs and you have limited samples, head-only training often suffices according to the patterns in pytorchcv.py and tfcv.py.
Can I use these patterns for multi-label classification?
Yes. Replace the final activation: use sigmoid instead of softmax in TensorFlow, or nn.BCEWithLogitsLoss in PyTorch. Change the output dimension to match your number of labels. The backbone feature extraction remains identical; only the classification head and loss function require modification.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →