Transfer Learning
Transfer learning starts from a model pretrained on a huge dataset (ImageNet) and fine-tunes it on your task. Saves compute, beats from-scratch on small datasets, ships in production.
Keras transfer learning, freeze + fine-tune
EXAMPLE
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, callbacks
from tensorflow.keras.applications import EfficientNetV2B0
from tensorflow.keras.applications.efficientnet_v2 import preprocess_input
# 1) Data — image folders by class
img_size = (224, 224)
batch = 32
train_ds = keras.utils.image_dataset_from_directory(
'data/train',
image_size=img_size, batch_size=batch,
label_mode='categorical', shuffle=True,
)
val_ds = keras.utils.image_dataset_from_directory(
'data/val', image_size=img_size, batch_size=batch, label_mode='categorical'
)
num_classes = len(train_ds.class_names)
# 2) Data augmentation pipeline
aug = keras.Sequential([
layers.RandomFlip('horizontal'),
layers.RandomRotation(0.1),
layers.RandomZoom(0.1),
layers.RandomContrast(0.1),
])
# 3) Build — base + custom head
inputs = keras.Input(shape=img_size + (3,))
x = aug(inputs)
x = preprocess_input(x) # net-specific preprocessing
base = EfficientNetV2B0(
include_top=False,
weights='imagenet',
input_tensor=x,
pooling='avg',
)
base.trainable = False # FREEZE first
x = layers.Dropout(0.3)(base.output)
outputs = layers.Dense(num_classes, activation='softmax')(x)
model = keras.Model(inputs, outputs)
# 4) PHASE 1 — train the head only (fast, no overfit on a frozen base)
model.compile(
optimizer=keras.optimizers.AdamW(1e-3),
loss='categorical_crossentropy',
metrics=['accuracy'],
)
cbs = [
callbacks.EarlyStopping(monitor='val_accuracy', patience=5, restore_best_weights=True),
callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=3),
callbacks.ModelCheckpoint('best.keras', save_best_only=True, monitor='val_accuracy'),
]
model.fit(train_ds, validation_data=val_ds, epochs=10, callbacks=cbs)
# 5) PHASE 2 — unfreeze part of the base, fine-tune with a LOW learning rate
base.trainable = True
# Optionally unfreeze only the top N blocks
for layer in base.layers[:-30]:
layer.trainable = False
model.compile(
optimizer=keras.optimizers.AdamW(1e-5), # MUCH lower than phase 1
loss='categorical_crossentropy',
metrics=['accuracy'],
)
model.fit(train_ds, validation_data=val_ds, epochs=20, callbacks=cbs)
# 6) Save + load
model.save('classifier.keras')
restored = keras.models.load_model('classifier.keras')
# 7) Predict on a new image
img = tf.io.decode_jpeg(tf.io.read_file('test.jpg'))
img = tf.image.resize(img, img_size)
batch = tf.expand_dims(img, 0)
probs = model.predict(batch)
label = train_ds.class_names[probs.argmax()]
confidence = probs.max()
print(label, confidence)
# 8) Other strong pretrained options
# Vision:
# EfficientNetV2B0/L (224-300px)
# ConvNeXt-Tiny (highest accuracy/perf today)
# ResNet50V2 (classic, reliable)
# MobileNetV3 (edge devices)
# Text:
# keras-nlp / Hugging Face Transformers — BERT, DistilBERT, RoBERTa
# Audio:
# YAMNet (sounds), Whisper (speech) — usually via TF Hub or HF
# 9) When transfer learning shines
# - Small datasets (< 10k labelled images per class)
# - Limited compute (laptop GPU)
# - Adjacent task to the pretraining domain (ImageNet → product photos)
# 10) When it falls flat
# - Drastically different domain (medical X-rays, satellite imagery) — still helps but need more fine-tuning
# - Tiny model + huge novel dataset — might be cheaper from scratch
# - You need feature interpretability that the base hides
# 11) Tips
# - Keep image preprocessing IDENTICAL to what the base was pretrained on
# - Phase-1 LR ~1e-3, Phase-2 LR ~1e-5 (the 100x ratio is the rule of thumb)
# - Unfreeze only the top blocks; lower layers learn generic features
# - Watch for batch-norm: setting trainable=False keeps stats frozen; some tasks need stats updated
Why it matters
The two-phase recipe (freeze head, then unfreeze + low LR) is what makes transfer learning practical. Skip phase 2 for simple tasks; do both when you have enough data and accuracy still has room to grow.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
from tensorflow.keras.applications import EfficientNetB0 base = EfficientNetB0(include_top=False, weights='imagenet', input_shape=(224,224,3)) base.trainable = False out = layers.Dense(n_classes, activation='softmax')(layers.GlobalAveragePooling2D()(base.output)) model = Model(base.input, out)Try it Yourself »
Exercise
Freeze the backbone before fine-tuning.
base.
= False
Nine letters.
Discussion
Loading…