Training costs real time and money — its results shouldn’t evaporate when the Python process exits. This final unit of chapter 5 persists what we’ve built: first checkpointing our own model (with everything needed to resume training), then the chapter’s endgame — filling our architecture with OpenAI’s pretrained GPT-2 weights.
5.4 Saving and loading model weights
The right unit of persistence is the
state_dict state_dict PyTorch's name→tensor dictionary of a module's or optimizer's parameters, used with torch.save/load for checkpointing.
defined in ch. 5 — open in glossary
: a dictionary mapping each
parameter’s name (tok_emb.weight, trf_blocks.0.att.W_query.weight, …) to
its tensor. One subtlety matters: LLMs are trained with adaptive optimizers
like AdamW, which store additional state for every model
weight (moment estimates). To continue pretraining later, that state must
survive too:
torch.save({
"model_state_dict": model.state_dict(), #A
"optimizer_state_dict": optimizer.state_dict(), #B
},
"model_and_optimizer.pth"
) - #A All 163M learned parameters, by name. Enough on its own for inference-only use.
- #B AdamW's per-parameter statistics — without these, resumed training starts the optimizer cold and behaves differently from an uninterrupted run.
checkpoint = torch.load("model_and_optimizer.pth", weights_only=True) #A
model = GPTModel(GPT_CONFIG_124M) #B
model.load_state_dict(checkpoint["model_state_dict"])
optimizer = torch.optim.AdamW(model.parameters(), lr=0.0005, weight_decay=0.1)
optimizer.load_state_dict(checkpoint["optimizer_state_dict"]) #C
model.train() #D - #A weights_only=True restricts deserialization to plain tensors — the safe way to load files, refusing arbitrary pickled code.
- #B The state_dict carries only numbers: you must first re-create the architecture (the class + config), then pour the weights in. Names and shapes must match exactly.
- #C The optimizer is rebuilt over the fresh model's parameters, then its saved statistics are restored.
- #D Loading doesn't set the mode — switch to train() to continue pretraining (or eval() if you're here to generate).
Two dictionaries to preserve
The model's learned parameters AND the optimizer's adaptive state. Saving only the first is fine for inference; resuming TRAINING needs both.
The checkpoint round-trip: what goes into the .pth file and what has to happen — in order — to come back from it.
5.5 Loading pretrained weights from OpenAI
Pretraining an LLM on a large corpus is time- and resource-intensive —
chapter 1 put GPT-scale runs in the millions of dollars. The
alternative: load OpenAI’s openly published GPT-2 weights into the very
architecture we built. One catch: the published checkpoint (original
TensorFlow format) uses different tensor names and structure than our
GPTModel, so loading requires a custom mapping — matching each of OpenAI’s
tensors to the corresponding module of ours:
Thin ice, marked
The source notes cover §5.5 in a single sentence — “custom loading is required because the data-structure names differ” — so this page keeps to that scope. The full mapping code lives in the book’s repository; what matters for the journey: after loading, our hand-built model generates coherent English, and the fine-tuning chapters start from exactly these weights.5.6 Summary
- LLMs generate one token at a time; by default the highest-probability token wins — greedy decoding.
- Probabilistic sampling and temperature scaling let us influence the diversity and coherence of the output; top-k restricts the pool.
- Training and validation losses gauge generated-text quality during training; pretraining minimizes the training loss with a conventional cross-entropy objective and the AdamW optimizer.
- Pretraining a large model from scratch is expensive — loading openly available weights is the practical alternative.
Stage 2 complete
The model is built (ch2–4), trainable, measurable, and — via OpenAI’s weights — genuinely fluent. Everything from here on is specialization: chapter 6 fine-tunes this foundation into a spam classifier; chapter 7 teaches it to follow instructions.📝 Check yourself: saving, loading & borrowed weights
0 / 51.Why does the checkpoint save the OPTIMIZER's state_dict alongside the model's?
2.What exactly is a state_dict?
3.After loading a checkpoint to CONTINUE pretraining, the code calls model.train(). Why?
4.Why can't OpenAI's published GPT-2 weights be loaded with a plain load_state_dict call?
5.What's the payoff of loading OpenAI's pretrained weights instead of pretraining ourselves?