M12 · Model deployment, serving, and optimization12-0325 min read
Lesson 86 of 106 · Module 13 of 14 · Week 6
Threads:The measurement threadThe infrastructure threadThe efficiency thread
Reading Loss Curves: Diagnosing a Training Run from Its Graph
A loss curve plots the model's error against training steps, and reading it means comparing two lines: training loss and validation loss. Both falling and converging is healthy; training loss falling while validation loss rises is overfitting; both flat and high is underfitting or a broken learning rate; a sudden spike to NaN is numerical divergence. The gap between the two curves — not the absolute value of either — is the diagnostic signal.
What a loss curve is and what its two lines mean
A loss function returns a single number measuring how wrong the model's predictions are on a batch of data. For language models that number is almost always cross-entropy — the negative log probability the model assigned to the tokens that actually appeared, averaged per token. 01-05 derives it. Lower is better, zero is perfect, and the value is on a log scale in disguise, which is why a drop from 3.0 to 2.0 is an enormous improvement and a drop from 0.30 to 0.29 is often noise.
Two lines get plotted:
- Training loss is computed on the batches the optimizer is currently learning from. It is measured while the weights are being updated, so it is a running commentary on data the model is actively memorizing. It is expected to fall.
- Validation loss is computed periodically on a held-out split the optimizer never sees, with the model in evaluation mode and gradients off. It is the estimate of generalization. It is the line that matters.
The distinction is the whole reason 01-07 insists on three splits. Training loss measures fit; validation loss measures fit to unseen data of the same kind; the test set, touched once at the end, measures whether your validation-driven decisions themselves overfitted. A curve plotting only training loss is close to uninformative for diagnosis — it will descend beautifully while the model rots.
Three related quantities show up on the same dashboards and should not be confused:
| Quantity | What it is | Where it lives |
|---|---|---|
| Training loss | Cross-entropy on the current training batches, during updates | Logged every step; noisy |
| Validation loss | Cross-entropy on a held-out split, no updates | Logged every N steps; smooth |
| Perplexity | exp(cross-entropy), a monotone transform | Same information, friendlier units — see 09-02 |
| Task metric | BLEU, ROUGE, exact match, faithfulness, accuracy | The thing you actually care about; can move opposite to loss |
That last row is the most important caveat in the lesson. Loss and task quality usually agree, and sometimes they diverge — a model can have slightly worse validation loss and better downstream behaviour, or vice versa. Loss is a proxy. It is a fast, free, high-resolution proxy that you read every run, and it is not the acceptance criterion. The acceptance criterion is your eval set.
How to read the shapes: a diagnostic method
L1 — Intuition: four questions, asked in order
Every loss-curve diagnosis reduces to four questions, and asking them in this order stops you from misreading the graph:
- Is there a NaN or an explosion? If loss went to
nan,inf, or jumped by orders of magnitude, stop. Nothing else in the graph means anything. This is a numerical failure, not a learning failure. - Is the training loss going down at all? If not, the problem is upstream of generalization — a learning rate near zero, a frozen graph, a broken data pipeline, a label bug.
- Are the two lines converging or diverging? Converging and both falling: healthy. Diverging with validation rising: overfitting. Both flat at a high value: underfitting.
- Where is the validation minimum? That step, not the last step, is the checkpoint you want.
L2 — Mechanism: the canonical shapes and what causes each
| Shape | Training loss | Validation loss | Diagnosis | First action |
|---|---|---|---|---|
| Healthy convergence | Falls, then flattens | Falls, then flattens just above training | Working as intended | Stop when validation flattens; keep the best checkpoint |
| Classic overfitting | Keeps falling toward zero | Falls, reaches a minimum, then rises | Model is memorizing the training set | Early stopping at the minimum; more data; regularization; fewer epochs |
| Underfitting | Falls a little then flattens high | Tracks training, also flat and high | Insufficient capacity, too few steps, or LR too small | Train longer, raise LR, increase capacity, reduce regularization |
| Learning rate too high | Noisy, plateaus early at a poor value, or oscillates | Same, erratic | Steps overshoot the minimum repeatedly | Lower LR; add warmup; check gradient clipping |
| Learning rate too low | Descends in a nearly straight, very shallow line | Same | Progress is real but glacial | Raise LR; use a schedule with warmup then decay |
| Divergence to NaN | Spikes vertically then nan | Undefined afterwards | Numerical overflow, exploding gradients, or bad data | Gradient clipping; lower LR; check FP16 loss scaling; find the bad batch |
| Loss spikes with recovery | Occasional sharp spike, then returns to trend | Largely unaffected | A pathological batch, or an aggressive LR under FP16 | Often tolerable; clip gradients, inspect the batch, consider BF16 |
| Step-function drops | Sudden drop at regular intervals | Follows | Epoch boundary — the model is seeing repeated data | Expected with few epochs; a large drop at epoch 2 hints at memorization |
| Validation below training | Above validation | Below training | Usually an artifact: dropout active in training but off in eval, or an easier validation split | Not a bug per se; verify the split and the eval mode |
| Flat from step zero | No movement at all | No movement | LR is 0, parameters frozen, gradients not flowing, or the loss is detached | Check that the optimizer sees the parameters and requires_grad is set |
| Erratic validation, smooth training | Smooth | Jumps around between evaluations | Validation split too small | Enlarge the validation split; evaluate less often but on more data |
Why overfitting produces that shape. Early in training the model learns structure that is genuinely present in the language — grammar, common facts, the shape of the task. Those patterns generalize, so both curves fall together. Later, once the general structure is exhausted, the cheapest remaining way to reduce training loss is to memorize idiosyncrasies of the specific training examples. Those idiosyncrasies do not appear in the validation split, so memorizing them lowers training loss and raises validation loss. The minimum of the validation curve is the moment the marginal pattern being learned stops generalizing.
The train–validation gap as a number. Report it explicitly: gap = validation_loss - training_loss. A small, stable gap is healthy. A gap that grows monotonically is overfitting in progress even if validation loss has not yet turned upward — a growing gap is the early warning and the upturn is the late one. The gap's absolute size is domain-dependent and not comparable across tasks; its trend is what you read.
Early stopping is the operational response: track validation loss, keep the best-so-far checkpoint, and stop when it has failed to improve for a set number of evaluations (the patience). Two implementation details cause real bugs. First, you must save the best checkpoint, not the last one — stopping without checkpointing throws away the model you were trying to keep. Second, patience must be measured in evaluations, and if you evaluate rarely you will overshoot the minimum by a lot.
L3 — Fine-tuning curves, LLM-specific reading, and what loss cannot tell you
Fine-tuning curves look different from pretraining curves and get misread constantly.
Pretraining runs one pass, or barely more, over an enormous corpus. Training loss and validation loss stay close because the model never sees an example twice — there is little to memorize. The curve is a long, smooth, slowly flattening descent, and the interesting features are learning-rate warmup at the start, occasional loss spikes, and the shape of the decay schedule.
Supervised fine-tuning runs several passes over a small dataset. Overfitting is the default outcome, not an exception. It is entirely normal for validation loss to reach its minimum inside the first epoch and rise thereafter, and the practical consequence is that fine-tuning is usually a 1-to-3-epoch activity, not a 20-epoch one. If your fine-tune's validation minimum is at step 200 of 5,000, the correct read is not "training failed" — it is "you needed 200 steps, and you now have the checkpoint."
Catastrophic forgetting is the failure that loss curves conceal. Fine-tuning loss on your new task can fall beautifully while the model quietly loses general capability it had before, because your validation split contains only the new task. The loss curve is blind to this by construction. The only detection is an eval slice that covers the old capabilities — the argument 11-03 makes at length.
LoRA and PEFT curves. With only adapter parameters trainable, the effective capacity is much smaller, so the curve typically descends less far and overfits more slowly. Loss values are not comparable between a LoRA run and a full fine-tune of the same model; compare each against its own baseline and against the eval set.
Mixed-precision artifacts. A BF16 run often shows a marginally noisier curve than FP32, which is expected from the reduced mantissa and is not a defect — 12-01 explains why. An FP16 run that produces repeated skipped steps or a sudden NaN is a loss-scaling problem, and BF16 is the standard remedy. When comparing two runs, precision mode belongs in the experiment record alongside seed and library version, because a curve difference caused by TF32 being enabled in one run is an infuriating thing to debug.
Distributed-training artifacts. In data-parallel training the loss you log is typically the loss on one rank's local batch unless you explicitly reduce across ranks; a curve that looks noisier than expected may simply be under-averaged. And the effective batch size is per_device_batch × devices × gradient_accumulation_steps, so a run that "changed nothing but the GPU count" changed the effective batch size and therefore the appropriate learning rate. 12-04 covers the synchronization that makes this true.
What a loss curve cannot tell you: whether the model is factually accurate, whether it hallucinates, whether it is safe, whether it produces valid JSON, whether it forgot something, whether it is biased, or whether it will be fast enough. Every one of those needs a separate instrument. Loss tells you whether optimization worked. It is necessary and nowhere near sufficient.
Overfitting vs underfitting vs divergence: the comparison table
| Overfitting | Underfitting | Divergence | |
|---|---|---|---|
| Training loss | Very low, still falling | High, flat | Spikes to inf/NaN |
| Validation loss | Rose after a minimum | High, flat, tracks training | Undefined |
| Train–val gap | Large and growing | Small (both bad) | n/a |
| Root cause | Too much capacity or too many epochs for the data | Too little capacity, too few steps, LR too small, over-regularized | Numerical instability, exploding gradients, bad data |
| Bias/variance framing | High variance | High bias | Neither — a broken run |
| Standard fixes | Early stopping, more/better data, dropout, weight decay, fewer epochs, smaller adapter rank | Train longer, higher LR, more capacity, less regularization, better features | Gradient clipping, lower LR, warmup, BF16 instead of FP16, find the offending batch |
| What it looks like at deployment | Great demo on known inputs, weak on real traffic | Uniformly mediocre | No usable checkpoint |
| Detected by | The gap, and the validation upturn | The absolute level of both curves | The spike |
And the two adjacent shapes that are frequently mistaken for pathologies:
| Observed | Sounds like | Actually is |
|---|---|---|
| Validation loss below training loss | "Impossible, something is broken" | Dropout and other regularization are active during training and disabled during evaluation, so the training number is measured under harder conditions. Also occurs when the validation split happens to be easier |
| Sharp drops at fixed intervals | "Learning-rate schedule bug" | Epoch boundaries. The model is seeing the same data again |
| Loss plateaus for a long stretch, then falls | "Stuck, kill the run" | Sometimes real — a long plateau followed by progress is a known phenomenon. Judge on validation, not vibes |
| Noisy training loss, smooth validation loss | "Validation is broken" | Training loss is per-batch and therefore noisy; validation loss is averaged over the whole split and therefore smooth |
Worked example: reading a fine-tuning run step by step
A constructed scenario. You are fine-tuning a 7B instruction model on 4,000 support-ticket summarization examples. Configuration: 3 epochs, per-device batch 4, gradient accumulation 4, 2 GPUs, BF16, LR 2e-5 with 30 warmup steps and cosine decay. Validation split: 400 held-out examples, evaluated every 50 steps.
Step 1 — how many steps is this run?
effective batch = 4 (per device) × 4 (accumulation) × 2 (GPUs) = 32 examples per step
steps per epoch = 4000 / 32 = 125 steps
total steps = 125 × 3 = 375 steps
evaluations = 375 / 50 = 7 evaluations (plus step 0)
Seven validation points across the whole run. That is the first finding, and it is a design flaw: with a validation minimum somewhere in a 375-step run, evaluating every 50 steps localizes it only to ±50 steps. For a short run, evaluate every 25 steps or every 10% of total steps, whichever is finer.
Step 2 — the logged numbers. Constructed, illustrative:
| Step | Training loss | Validation loss | Gap |
|---|---|---|---|
| 0 | 2.41 | 2.38 | −0.03 |
| 50 | 1.62 | 1.55 | −0.07 |
| 100 | 1.28 | 1.31 | +0.03 |
| 150 | 1.05 | 1.24 | +0.19 |
| 200 | 0.81 | 1.27 | +0.46 |
| 250 | 0.58 | 1.36 | +0.78 |
| 300 | 0.39 | 1.49 | +1.10 |
| 375 | 0.26 | 1.63 | +1.37 |
Step 3 — the diagnosis, using the four questions.
- No NaN, no explosion. The run is numerically sound.
- Training loss fell from 2.41 to 0.26. Optimization is working; the learning rate is not broken.
- The lines diverge from step 100 onward and the gap grows monotonically from +0.03 to +1.37. Textbook overfitting.
- Validation minimum is at step 150, value 1.24 — barely into epoch 2 of a 3-epoch run.
Step 4 — what to do about it. Deploy the step-150 checkpoint, not the step-375 one. If checkpointing was set to "last only," you have thrown the good model away and must re-run — which is why save_best and a validation-loss-driven checkpoint selection are non-negotiable configuration, not niceties.
Step 5 — quantify the mistake you almost made. The final-step model has training loss 0.26 and validation loss 1.63. The best model has validation loss 1.24. In perplexity terms:
best checkpoint: exp(1.24) ≈ 3.46
final checkpoint: exp(1.63) ≈ 5.10
The final checkpoint is roughly 47% worse in perplexity than the one you had at step 150, despite its training loss looking six times better. Anyone reading only training loss would have concluded the opposite. This is the single most valuable habit the lesson teaches.
Step 6 — the change for the next run. Three epochs was 2.5 times too many for 4,000 examples at this learning rate. Set epochs to 1–2, evaluate every 25 steps, enable early stopping with patience 2 evaluations, and keep the best checkpoint by validation loss. If the minimum lands even earlier next time, the dataset is smaller than the model's appetite and the fix is more or better data, or a lower-capacity adaptation such as a smaller LoRA rank.
Step 7 — the step loss does not close the case. Validation loss says step 150. Your eval set (01-08, 09-01) may disagree slightly, and where they disagree the eval set wins, because it measures the behaviour you promised and loss measures a proxy. Run the eval on the two or three best checkpoints and pick on the metric you shipped against.
Decision table: the symptom, the likely cause, and the next action
| Symptom in the graph | Most likely cause | Do this next |
|---|---|---|
| Validation loss turns upward while training keeps falling | Overfitting | Early stopping at the minimum; reduce epochs; add data or regularization |
| Gap grows but validation has not turned yet | Overfitting beginning | Prepare to stop; do not increase epochs |
| Both curves flat and high from the start | LR ≈ 0, frozen parameters, or gradients not flowing | Verify the optimizer's parameter list, requires_grad, and that the loss is connected to the graph |
| Both curves flat and high after an initial drop | Underfitting or LR too small | Raise LR, train longer, increase capacity or adapter rank, reduce regularization |
| Training loss oscillates wildly, never settles | LR too high | Lower LR by 3–10×; add warmup; clip gradients |
| Loss goes to NaN | Overflow / exploding gradients / bad batch | Clip gradients, lower LR, switch FP16 → BF16, locate and inspect the batch |
| One large spike, then recovery to trend | A pathological batch, or FP16 loss-scale adjustment | Usually tolerable; clip gradients and inspect the batch |
| Validation loss jumps erratically between evaluations | Validation split too small | Enlarge the split; that noise is sampling error, not model behaviour |
| Validation loss below training loss consistently | Dropout on in training, off in eval; or easier validation split | Verify eval mode and split construction; often benign |
| Sharp drop exactly at each epoch boundary | Model is re-seeing data | Expected; a big drop suggests memorization has started |
| Training loss identical across two runs that differ | The change did not take effect | Check the config actually loaded; check seeds; check that both runs read the same data |
| Loss improves but the eval set does not | Loss/metric divergence, or catastrophic forgetting | Trust the eval set; add slices covering prior capabilities (11-03) |
| Curve looks fine, production quality is poor | Validation split does not resemble production | Rebuild the split from real traffic; this is a data problem, not a training problem |
Why reading loss curves is on the NCA-GENL exam
Loss curves sit at the intersection of several official objectives: 4.5 (monitor the functioning of data collection, experiments, and other software processes), 1.5 and 1.1 (ML fundamentals and assisting with evaluation of model performance and reliability), and the data-analysis objectives on creating and interpreting visualizations to convey results (2.4, 2.5). Learning curves are one of the named chart types a candidate is expected to be able to read, and the train-versus-validation gap is the canonical over/underfitting diagnostic in the ML-fundamentals material.
The exam asks this as symptom-to-diagnosis matching, which is exactly how this lesson is built. Typical phrasings:
- "A model's training loss continues to decrease while its validation loss increases. What is happening?" — overfitting.
- "Which technique directly addresses the situation above?" — early stopping (also: more data, regularization, fewer epochs).
- "Both training and validation loss plateau at a high value. What does this indicate?" — underfitting / insufficient capacity or training.
- "Which chart type shows model performance against training progress?" — a line chart / learning curve, per
08-04. - "A training run's loss becomes NaN. Which is the most likely cause?" — exploding gradients or numerical overflow; remedy is gradient clipping or a lower learning rate.
- "Why must validation loss, not training loss, drive checkpoint selection?" — training loss measures fit to data the model is memorizing and cannot estimate generalization.
- "What does the gap between training and validation loss measure?" — the degree of overfitting / the variance component of error.
Distractor families:
| Distractor | Why it is wrong |
|---|---|
| "Rising validation loss means the learning rate is too low" | A too-low LR produces a slow descent, not a divergence between the curves |
| "Overfitting is fixed by training longer" | Training longer is the cause; the fix is stopping earlier or changing the data/regularization |
| "Underfitting is fixed by adding dropout" | Dropout is regularization, which makes underfitting worse. It treats overfitting |
| "A low training loss proves the model is good" | It proves the model fits the training set. Generalization is measured on held-out data |
| "Validation loss below training loss indicates data leakage" | Usually it indicates dropout being active in training and off in evaluation, or an easier split. Leakage typically shows up as an implausibly low validation loss with a suspiciously small gap |
| "Loss and task accuracy always move together" | They usually correlate and can diverge. The eval set is the acceptance criterion |
| "Early stopping means killing the run" | It means selecting the best-validation checkpoint, which requires having saved it |
Common mistakes when reading loss curves
| Mistake | Symptom | Cause | Fix |
|---|---|---|---|
| Plotting training loss only | Confident deployment of an overfitted model | No held-out curve to compare against | Always plot both lines; log the gap as its own series |
| Saving only the last checkpoint | The best model is gone and the run must be repeated | Checkpoint policy set to "latest" | Save best-by-validation-loss and keep the last as well |
| Evaluating too infrequently | Validation minimum localized only to ±N steps | Eval interval set for a long run and reused for a short one | Evaluate every 5–10% of total steps |
| Validation split too small | Erratic validation curve read as model instability | Sampling noise dominates | Enlarge the split; 09-09 covers how small is too small |
| Comparing loss values across different models or tokenizers | Nonsense conclusions | Cross-entropy is per token and depends on the tokenizer's vocabulary | Compare each run against its own baseline; compare models on task metrics |
| Reading a fine-tuning curve with pretraining expectations | "Overfitting after one epoch means the run failed" | Fine-tuning on small data overfits by default | Expect the minimum early; plan for 1–3 epochs |
| Ignoring effective batch size when scaling GPUs | Same LR behaves differently after adding devices | Effective batch = per-device × devices × accumulation | Record effective batch; re-tune LR when it changes |
| Treating a BF16 run's extra noise as a bug | Time lost chasing nothing | Reduced mantissa adds small numerical noise | Compare like precision to like; record the precision mode |
| Concluding a model is healthy because the curve is clean | Capability regressions ship undetected | Loss cannot see forgetting, hallucination, format compliance, or safety | Gate on the eval set with slices for prior capabilities |
| Not logging LR alongside loss | A schedule bug looks like a model problem | The learning-rate curve is missing from the dashboard | Log LR, gradient norm, and loss on the same timeline |
| Dropping the run because of a single spike | Wasted GPU hours | Isolated spikes often self-correct | Clip gradients, watch the next 100 steps, then decide |
What does it mean when validation loss increases while training loss decreases?
It means the model is overfitting: it is still reducing error on the examples it is being updated on, but the patterns it is now learning are specific to those examples and do not transfer to held-out data. The step at which validation loss reached its minimum is the point at which the last generalizing pattern was learned; everything after that is memorization. The fixes, in order of how often they are the right one: stop at the minimum and deploy that checkpoint (early stopping), reduce the number of epochs on the next run, get more or more diverse training data, add regularization such as dropout or weight decay, or reduce the trainable capacity — for LoRA, a smaller rank. Training longer is not a fix; training longer is the mechanism producing the problem.
What is the difference between training loss and validation loss?
Training loss is computed on the batches the optimizer is currently learning from, while the weights are being updated and with regularization such as dropout active. Validation loss is computed periodically on a held-out split the optimizer never touches, in evaluation mode with regularization disabled and gradients off. The consequence is that training loss measures fit and validation loss estimates generalization. Two practical corollaries: training loss is noisy because it is a per-batch number while validation loss is smooth because it is averaged over a whole split; and validation loss can legitimately sit below training loss, because dropout makes the training measurement harder than the evaluation measurement. Checkpoint selection, early stopping, and hyperparameter decisions must all be driven by validation loss. The test set stays sealed until the end so that it can audit the decisions validation loss drove.
How do you tell overfitting from underfitting on a loss curve?
Look at the gap and the level. Overfitting shows a large and growing gap: training loss low and still falling, validation loss having bottomed out and turned upward. Underfitting shows a small gap at a high level: both curves flat, close together, and disappointing. The mnemonic is that overfitting is a divergence problem and underfitting is an altitude problem. In bias–variance language, underfitting is high bias and overfitting is high variance, and the remedies are opposite — underfitting wants more capacity, more steps, a higher learning rate, and less regularization, while overfitting wants fewer steps, more data, and more regularization. Applying an overfitting remedy to an underfitting curve makes it strictly worse, which is why naming the shape correctly before acting is the entire skill.
Why did my training loss become NaN?
Because a number in the forward or backward pass exceeded the representable range of its dtype, or a division or logarithm hit an invalid input, and the resulting inf or nan propagated through the graph. The usual triggers, in rough order of frequency: a learning rate high enough that a single step blows up the weights; exploding gradients in a deep stack with no clipping; FP16's narrow exponent range overflowing where loss scaling is misconfigured or absent; and a genuinely pathological training example — an empty target, a corrupted record, a label out of vocabulary range. The remedies map one to one: clip gradient norms, lower the learning rate and add warmup, switch from FP16 to BF16 so the exponent range matches FP32's (12-01), and locate the offending batch by logging batch indices and re-running deterministically. Once loss is nan, weights are usually corrupted beyond recovery, so restart from the last good checkpoint rather than hoping the run heals.
What is early stopping and how do you choose the patience?
Early stopping monitors validation loss and terminates training when it has not improved for a set number of consecutive evaluations — that count is the patience. Its purpose is to select the checkpoint at the validation minimum rather than the one at the end of a fixed epoch budget, which makes it both a regularization technique and a compute saving. Choosing patience is a trade-off between two failure modes: too small and normal evaluation-to-evaluation noise stops a run that was still improving; too large and you burn compute past the minimum. Two or three evaluations is a common starting point, with the crucial condition that your evaluation interval is fine enough that a few evaluations is a small fraction of the run. And the detail that causes real incidents: early stopping is useless unless the best checkpoint was actually saved. "Stop when validation stops improving" and "keep the model from before it stopped improving" are two separate configuration settings, and only the second one gives you an artifact.
Can a loss curve tell you the model is production-ready?
No, and treating it as if it can is the most consequential misreading in this lesson. A loss curve certifies that optimization behaved: the numbers were stable, the model fit the data, and generalization did not collapse. It says nothing about factual accuracy, hallucination rate, output-format compliance, latency, safety, bias, or whether the model retained capabilities it had before fine-tuning. Catastrophic forgetting is invisible to a validation split that contains only the new task. Format regressions are invisible to cross-entropy. The correct pipeline is: read the loss curve to select candidate checkpoints, then run the frozen eval set with per-slice reporting on those candidates, then decide. The loss curve narrows the field; the eval set makes the call. 12-14 extends the same logic past deployment, where the instrument that validated the build becomes the instrument that detects its decay.
Glossary recap: the training-diagnosis terms this lesson introduced
| Term | Definition |
|---|---|
| Loss curve | Loss plotted against training progress; the primary diagnostic chart of a training run |
| Training loss | Cross-entropy on the batches currently being learned from, with regularization active |
| Validation loss | Cross-entropy on a held-out split, in eval mode with no gradient updates; the generalization estimate |
| Train–validation gap | validation_loss − training_loss; its growth is the early signal of overfitting |
| Overfitting | Training loss falling while validation loss rises; high variance; memorization of training idiosyncrasies |
| Underfitting | Both curves flat at a high value; high bias; insufficient capacity, steps, or learning rate |
| Divergence | Loss spiking to inf or NaN; a numerical failure, not a learning failure |
| Early stopping | Halting training when validation loss stops improving, after a patience window, and keeping the best checkpoint |
| Patience | The number of consecutive non-improving evaluations tolerated before stopping |
| Perplexity | exp(cross-entropy); the same information in more interpretable units |
| Learning-rate warmup | Ramping the LR up over the first steps to avoid early instability |
| Gradient clipping | Capping the gradient norm to prevent an exploding update |
| Effective batch size | per_device_batch × devices × gradient_accumulation_steps; changes when the hardware changes |
| Epoch boundary artifact | A step-like drop in training loss when the model begins a second pass over the same data |
| Loss/metric divergence | The case where validation loss and the downstream task metric disagree; the eval set governs |
Key takeaways on reading loss curves
- Read two lines, not one. A single training-loss curve cannot diagnose anything about generalization.
- Ask four questions in order: NaN? Is training loss falling? Are the lines converging or diverging? Where is the validation minimum?
- Overfitting = growing gap plus a validation upturn. Underfitting = small gap at a high level. Divergence = a spike to NaN.
- The gap's trend is the early warning; the validation upturn is the late one.
- The validation minimum is the checkpoint you deploy. Save best-by-validation, not last.
- Fine-tuning on small data overfits by default. Expect the minimum inside the first or second epoch and plan for 1–3 epochs.
- Validation loss below training loss is usually dropout, not a bug.
- Cross-entropy values are not comparable across tokenizers or model families. Compare each run to its own baseline.
- Effective batch size changes when you add GPUs or gradient accumulation, and the learning rate has to follow.
- Loss is a proxy. It cannot see forgetting, hallucination, format compliance, safety, or latency. The frozen eval set is the acceptance criterion.
Next: 12-04 takes up the machinery hiding behind that "× devices" term in the effective-batch formula. When a model trains on more than one GPU, every device computes gradients on different data — and unless those gradients are synchronized into a single averaged update, the replicas silently drift into different models. AllReduce and NCCL are how that synchronization happens.