Lesson 14
Checkpoints, inference, and responsible model reuse
Introduction
Four small classifier predictions contain three correct answers and one error, so accuracy is 0.75. Inspecting the wrong example matters before saving, loading, or fine-tuning the model for another task.
- Learning goal
Evaluate, save, restore, and carefully fine-tune a PyTorch model while reporting prediction errors and important limitations.
- Before you start
PyTorch modules, data splits, logits, class predictions, evaluation mode, and optimization.
Lesson plan
- Evaluate a classifier with aggregate accuracy and inspect individual prediction errors.
- Save configuration and learned state, reload them, and confirm matching outputs.
- Fine-tune selected parameters carefully and state data, metric, and reuse risks.
Why model use is more than one prediction
A trained model is only one part of a working system. Input preparation, tokenizer version, label meanings, evaluation data, and saved settings all affect the result. A model can run without an error while still producing wrong answers because its inputs were normalized differently or its class IDs were reversed.
Start from a model card or project documentation. Record what data the model expects, what task it was trained for, its limits, and its license. For text models, use the exact tokenizer and vocabulary that belong to the checkpoint. For image models, match resizing and normalization rules.
Practical terms
state_dictA dictionary mapping parameter names to tensors.Evaluate a small classifier
model.eval() switches layers such as dropout and batch normalization to evaluation behavior. It does not disable gradient recording. torch.no_grad() disables that recording for the enclosed operations and saves memory. Use both for ordinary evaluation.
Predict first: each fixed weight row selects one input feature. For [3,1], the logits are [3,1], so class 0 wins. Trace the other two rows before reading the printed predictions.
import torch
from torch import nn
model = nn.Linear(2, 2)
with torch.no_grad():
model.weight.copy_(torch.tensor([[1.0, 0.0], [0.0, 1.0]]))
model.bias.zero_()
features = torch.tensor([[3.0, 1.0],
[0.0, 2.0],
[4.0, 1.0]])
labels = torch.tensor([0, 1, 0])
model.eval()
with torch.no_grad():
logits = model(features)
predictions = logits.argmax(dim=1)
accuracy = (predictions == labels).float().mean()
print(predictions.tolist())
print(accuracy.item())
# Expected:
# [0, 1, 0]
# 1.0
Accuracy is useful when classes are balanced and every error has similar cost. It can hide poor results on a rare class. Depending on the task, also inspect a confusion matrix, precision, recall, F1, calibration, or examples of failures. Measure against a simple baseline so that “high” has context.
Save and restore state
Saving a state_dict is usually clearer and more portable than saving a whole Python model object. To resume training exactly, save model state, optimizer state, the current epoch or step, and important configuration. Recreate the same architecture before loading its parameters.
A successful load message is not enough. Run the same fixed input through the original and restored models in evaluation mode. Equal outputs check the architecture and parameter transfer together.
import tempfile
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
with tempfile.TemporaryDirectory() as directory:
path = directory + "/checkpoint.pt"
torch.save({
"model": model.state_dict(),
"optimizer": optimizer.state_dict(),
"epoch": 3,
}, path)
restored_model = nn.Linear(2, 2)
restored_optimizer = torch.optim.SGD(
restored_model.parameters(), lr=0.01
)
checkpoint = torch.load(path, weights_only=True)
restored_model.load_state_dict(checkpoint["model"])
restored_optimizer.load_state_dict(checkpoint["optimizer"])
restored_model.eval()
with torch.no_grad():
same = torch.equal(model(features), restored_model(features))
print(checkpoint["epoch"]) # Expected: 3
print(same) # Expected: True
A checkpoint does not automatically save the tokenizer, label mapping, random seeds, package versions, or model constructor arguments. Store these beside the checkpoint in a small configuration file or a documented experiment directory. Only load checkpoint files from sources you trust.
Fine-tune carefully
Fine-tuning starts from useful pretrained parameters instead of random values. Use a smaller learning rate than you might use from scratch, keep a validation split, and compare with a frozen-feature baseline. You can freeze a layer by setting its parameters' requires_grad to false, then give the optimizer only trainable parameters.
feature_layer = nn.Linear(4, 8)
classifier = nn.Linear(8, 2)
for parameter in feature_layer.parameters():
parameter.requires_grad = False
trainable = [
parameter
for parameter in list(feature_layer.parameters())
+ list(classifier.parameters())
if parameter.requires_grad
]
print(len(trainable)) # Expected: 2 (classifier weight and bias)
Common pitfalls
model.eval()does not disable gradients; use no-grad or inference mode too.- Do not evaluate repeatedly on the final test set while choosing settings.
- Match the checkpoint architecture, tokenizer, preprocessing, and label map.
- Save optimizer state if training must resume, not only model weights.
- Inspect performance across important groups and failure types, not only one average score.
Try it
A three-class model predicts [0,2,2,1] for labels [0,1,2,1]. Calculate accuracy. Which example is wrong, and why is looking at it useful?
Reveal the worked answer
predictions = torch.tensor([0, 2, 2, 1])
labels = torch.tensor([0, 1, 2, 1])
correct = predictions == labels
print(correct.tolist()) # [True, False, True, True]
print(correct.float().mean().item()) # Expected: 0.75
The second example is wrong: class 2 was predicted instead of class 1. Examining errors can reveal ambiguous data, a label problem, missing training examples, or a systematic model weakness that one number cannot explain.
Recap
Reliable model use requires matching preprocessing, explicit evaluation, and reproducible saving. Use evaluation mode plus disabled gradients for inference. Save state dictionaries and enough configuration to rebuild the run. Fine-tune with held-out validation data and inspect failures as well as aggregate metrics. A model is ready only when its behavior is understood for the intended task.
References: PyTorch save/load tutorial and PyTorch no_grad documentation.