Baselines and Choosing a Model
Freeze, fine-tune, or train from scratch?
With a pretrained model available, the real choice is how much of it to retrain — and the answer follows from your data size and how far your task sits from the model's old one.
- 8 min read
- 3 reading levels
- Published
On this page 5
One lesson, three depths. Pick the one that fits you today — you can switch any time.
Beginner — No maths. Plain English.
When a pretrained model exists, the decision is not whether to use it but how much of it to retrain: none, some, or all.
A restaurant hiring a cook does not teach them to hold a knife. An experienced cook arrives knowing heat, timing, and knife work — the restaurant teaches only its own menu. Training from scratch would mean hiring someone who has never cooked and starting with "this is an onion".
A pretrained model is the experienced cook: a network someone else trained on a mountain of general data. Your decision is how much retraining the new job needs.
Why it exists
Training a big model from nothing needs data and compute most teams will never have. Pretrained models turned that from a wall into a choice: start from knowledge, adapt what you must.
But "adapt" has a dial, and each setting costs differently:
- Retrain nothing extra: fast, cheap, safe — and limited.
- Retrain a little: the middle path, most common in practice.
- Retrain everything: powerful, hungry, and able to destroy what it inherited.
How it works
Three settings of the dial, and the two questions that choose between them:
FREEZE keep the whole cook, teach only the menu card
→ tiny data (hundreds of examples), similar task
FINE-TUNE let the cook adjust their late habits to your kitchen
(partly) → medium data (thousands), task somewhat different
SCRATCH hire a beginner, teach everything
→ huge data, or a task so alien the old skills mislead
question 1: how much labelled data do you have?
question 2: how far is your task from what the model knew?Retraining everything on little data carries a danger. The model overwrites its general knowledge with your handful of examples. It is like a cook forgetting knife skills to memorise five recipes. Small data plus full retraining is the classic self-inflicted wound.
A real example you have seen
Voice assistants adapt to your accent without relearning the language. Phone cameras that recognise your face did not relearn what faces are. Both are frozen general knowledge with a thin personal layer trained on top — the dial at its first setting.
Remember this
- The choice is a dial: freeze, fine-tune partly, or train from scratch.
- Less data → freeze more. More distant task → retrain more.
- Full retraining on small data destroys inherited knowledge — the classic mistake.
What to learn next
- Transfer learning in PyTorch — the full training-loop mechanics.
- LoRA — the parameter-efficient third setting of the dial.
- Buying accuracy with size, and when to stop — choosing the pretrained model's size itself.
Developer — Code and libraries.
Setup
pip install torch torchvisionOutputs verified with torch 2.5.1 and torchvision 0.20, CPU.
The dial, in parameter counts
The mechanics of all three strategies are requires_grad flags. This runs download-free; swapping in real pretrained weights is a one-argument change.
import torch
from torchvision import models
# weights=None keeps this download-free. For the real thing use
# weights="IMAGENET1K_V1", a one-time ~45 MB download.
net = models.resnet18(weights=None)
net.fc = torch.nn.Linear(net.fc.in_features, 5) # our task: 5 classes
def trainable(m):
return sum(p.numel() for p in m.parameters() if p.requires_grad)
total = sum(p.numel() for p in net.parameters())
print(f"total parameters: {total:,}")
# Strategy 1: freeze everything, train the new head only.
for p in net.parameters():
p.requires_grad = False
for p in net.fc.parameters():
p.requires_grad = True
print(f"head only: {trainable(net):,} trainable")
# Strategy 2: also unfreeze the last residual stage.
for p in net.layer4.parameters():
p.requires_grad = True
print(f"last stage + head: {trainable(net):,} trainable")
# Strategy 3: fine-tune everything.
for p in net.parameters():
p.requires_grad = True
print(f"full fine-tune: {trainable(net):,} trainable")
# The optimizer should only ever see what is trainable.
frozen_setup = [p for p in net.parameters() if p.requires_grad]
opt = torch.optim.AdamW(frozen_setup, lr=1e-4)
print(f"parameter tensors handed to the optimizer: {len(frozen_setup)}")total parameters: 11,179,077 head only: 2,565 trainable last stage + head: 8,396,293 trainable full fine-tune: 11,179,077 trainable parameter tensors handed to the optimizer: 62
The walkthrough
2,565 versus 11 million. Head-only training touches 0.02% of the network — which is why it works with a few hundred labelled images and finishes in minutes on CPU. The other 99.98% acts as a fixed feature extractor.
layer4 is the "late habits" of the analogy. Early convolution layers hold generic edges and textures that transfer almost anywhere; late layers hold task-specific combinations. Unfreezing from the back forward is the standard middle path, and the parameter jump — 2.5k to 8.4M — shows why it needs thousands of examples, not hundreds.
The optimizer line is the practical bug-catcher. Handing net.parameters() wholesale to the optimizer while relying on requires_grad works, but filtering explicitly documents intent and enables tricks like per-layer learning rates.
Two rates when fine-tuning fully: new head at a normal rate, inherited body at a tenth of it. The body already knows things; big steps make it forget.
Common mistakes
Full fine-tuning on 500 examples. The network happily memorises your 500 and shreds its general features doing so — catastrophic forgetting in miniature. Freeze first; unfreeze only if the frozen version demonstrably plateaus.
Forgetting the preprocessing contract. Pretrained weights assume the exact normalisation of their pretraining (for ImageNet models: specific per-channel means and stds). Feed differently scaled pixels and accuracy quietly craters with no error message.
Leaving BatchNorm in training mode with tiny batches. Frozen backbones with unfrozen BatchNorm statistics silently adapt to your little dataset and destabilise. Call .eval() on frozen sections or freeze the norm layers explicitly — details in BatchNorm in PyTorch.
Comparing strategies at one data size. The ranking flips with data volume — the entire point. If you can, plot all three against 10%, 50%, 100% of your data; the crossing points tell you what to do when more data arrives.
Try it yourself
Print the trainable-parameter count when you unfreeze layer3 as well. Then, using the ~45 MB figure for resnet18's weights, estimate download plus disk cost for resnet50 (~98 MB) — and answer: for a 400-image dataset of five product types, which dial setting do you pick, and why?
What to learn next
- Transfer learning in PyTorch — the full training-loop mechanics.
- LoRA — the parameter-efficient third setting of the dial.
- Buying accuracy with size, and when to stop — choosing the pretrained model's size itself.
Researcher — Mathematics and papers.
What transfers, and from where
Yosinski et al. (2014), How transferable are features in deep neural networks? (NeurIPS), quantified layer-wise transferability with splice experiments: early layers are general, late layers specific, and transfer benefit degrades with task distance. Two additional effects they isolated: fragile co-adaptation when splitting mid-network, and a persistent generalisation boost from transferred initialisations even after long fine-tuning.
Follow-ups refined the picture:
- Kornblith et al. (2019), Do Better ImageNet Models Transfer Better? (CVPR) — largely yes, with correlation to ImageNet accuracy, but with diminishing and task-dependent returns.
- Raghu et al. (2019), Transfusion (NeurIPS) — for medical imaging, transfer's benefit is often re-use of low-level statistics and better initialisation scale, not high-level features; sometimes a smaller scratch model matches.
- He, Girshick, Dollár (2019), Rethinking ImageNet Pre-training (ICCV) — with enough target data and training time, scratch matches pretraining on COCO; pretraining mainly buys speed of convergence, not final accuracy, when data is plentiful. This is the "SCRATCH" arm's empirical backing.
Formal view: hypothesis transfer and forgetting
Fine-tuning is regularised estimation around the source solution $\theta_0$. Explicitly: $\min_\theta \mathcal{L}_{\text{target}}(\theta) + \lambda \lVert \theta - \theta_0 \rVert^2$ recovers the intuition that a small learning rate and early stopping keep $\theta$ near $\theta_0$ — an implicit prior whose strength should scale inversely with target-data size. Catastrophic forgetting (McCloskey & Cohen, 1989; measured for modern nets in Kirkpatrick et al., 2017, EWC, PNAS) is the failure of this prior under aggressive updates: EWC's Fisher-weighted penalty $\sum_i F_i (\theta_i - \theta_{0,i})^2$ formalises "protect the weights that mattered".
Parameter-efficient fine-tuning
The freeze/fine-tune dichotomy has a modern third axis: adapt through low-dimensional additions while freezing the base — adapters (Houlsby et al., 2019, ICML), and LoRA (Hu et al., 2021): $\Delta W = BA$ with rank $r \ll \min(d_{in}, d_{out})$, training ~0.1–1% of parameters to near-full fine-tuning quality in LLMs. The same data-size logic applies, shifted: PEFT methods extend the "small data" regime upward because their capacity is bounded by construction. Linear probing then fine-tuning (Kumar et al., 2022, Fine-Tuning Can Distort Pretrained Features, ICLR) sequences the dial: fit the head first so full fine-tuning starts from a non-destructive gradient field — theoretical support for "freeze first, unfreeze if it plateaus".
Decision summary from the literature
Data size and domain gap remain the two load-bearing variables. Small n, small gap → freeze (linear probe). Small n, large gap → probe-then-partial-tune, or reconsider the source model. Large n, small gap → full fine-tune at low LR. Large n, large gap → fine-tune fully; scratch becomes competitive as n grows (He et al., 2019).
What to learn next
- Transfer learning in PyTorch — the full training-loop mechanics.
- LoRA — the parameter-efficient third setting of the dial.
- Buying accuracy with size, and when to stop — choosing the pretrained model's size itself.