Overfitting and Training Length
Fine-tuning is driven by one training call. Reading that call line by line tells you what the run is designed to do before you see a single result.
Try it: Training a Keras-Style Model: History and Early Stopping
The Keras workflow on a tiny dense network: stack Dense layers (the summary counts units * (inputs + 1) parameters per layer), compile with an optimizer, loss and accuracy metric, fit for a number of epochs in mini-batches with validation data, and read the history. Training loss keeps falling while validation loss reaches its lowest point and then rises: the model starts to overfit, and EarlyStopping with patience can stop there and restore the best weights.
How it works
- Build a Sequential stack of Dense layers ending in Dense(1, sigmoid); each layer has units * (inputs + 1) weights and biases, initialised Glorot-uniform with zero biases.
- compile(): mini-batch SGD with the chosen learning rate, binary cross-entropy (or mean squared error) loss, and accuracy (prediction > 0.5) as the metric.
- fit(): each epoch walks the training set in batches of batch_size; every batch runs a forward pass, backpropagates the mean batch loss and updates every weight .
- After each epoch the history records the epoch's training loss and accuracy (batch-weighted average of values seen during the epoch) and the val_loss and val_accuracy on the held-out validation points.
- EarlyStopping(monitor="val_loss", patience) keeps the best val_loss; after patience epochs with no improvement it stops training, and restore_best_weights puts back the weights of the best epoch.
- evaluate() reports loss and accuracy on the validation data with the final weights.
Default run (153 steps): Sequential([Dense(16, "relu"), Dense(16, "relu"), Dense(1, "sigmoid")]) on inputs of shape (2,). model.summary(): dense 16 * (2 + 1) = 48; dense_1 16 * (16 + 1) = 272; dense_2 1 * (16 + 1) = 17; total 337 trainable parameters, initialised with Glorot uniform (biases 0). … model.evaluate(x_val, y_val) with the weights from epoch 150: loss 1.2082, accuracy 0.75. Training loss went 0.6964 -> 0.0194. Stopping at epoch 32 would have given val_loss 0.5272 and val_accuracy 0.775.
Simplified: A toy re-implementation in TypeScript, not Keras or TensorFlow: 2 input features, at most 3 hidden layers of up to 32 units, a seeded 2-D dataset (inside/outside a circle with label noise; 40 validation points), plain SGD without momentum, shuffle=False so batch order is fixed, float64 arithmetic, and binary cross-entropy computed from the output logit (same value as on probabilities, without clipping). The results match an independent NumPy implementation of the same procedure, not a real Keras run.
Loading the simulation…
Why the Training Call Matters
A pre-trained language model already knows a great deal about language, but it has not yet learned to follow the kind of instructions you care about. Fine-tuning closes that gap by adjusting the pre-trained model so that it fits a specific task or dataset. In this article the task is concrete: the model is trained on instruction data until it can convert an active sentence into its passive voice counterpart.
By the time training starts, the model and its data loaders are already prepared. What remains is a single training call that wires everything together. Because that call is where fine-tuning actually happens, it is the best place to begin. Treat it as a checklist of decisions: which optimizer updates the weights, how many passes over the data to make, how often to check progress, and what to ask the model to generate along the way.
Fine-tuning is driven by one training call. Reading that call line by line tells you what the run is designed to do before you see a single result.
Reading the Optimizer Line
Start by reading the optimizer line. It creates an AdamW optimizer over the model's parameters, which means the optimizer is the component that will update the model during training. Two of its settings are stated explicitly: the learning rate is 0.00005 and the weight decay is 0.1. Those two numbers, together with the optimizer choice, make up the optimizer configuration for this fine-tuning run.
What the Optimizer Settings Control
The optimizer is the part of the run that changes the model. Because it is created over the model's parameters, every update during training is applied to those parameters. The learning rate of 0.00005 and the weight decay of 0.1 are the two settings the source states for this run, so they are the numbers to record when you later compare runs or explain a result. The source does not ask you to memorize how each setting works internally; what it asks is that you know which setting belongs to which role in the call.
Setting the Shape of the Run
The remaining arguments of the training call decide the shape of the run. The number of epochs is set to 2. The evaluation frequency is 5, and the evaluation iteration count is also 5, so the run checks its progress at regular intervals rather than only at the end. The call also receives a starting context, built by formatting the first validation instruction, which the model uses to generate a response while training is underway. The tokenizer is passed in so that text can be encoded and decoded during this process.
The call also returns three things that you will read afterward: a list of training losses, a list of validation losses, and a count of tokens seen. The script records the start and end time around the call and reports the elapsed minutes. Timing does not change what the model learns, but it is useful when you compare runs.
Predicting the Loss Curves
Before you look at the output of the run, decide what a healthy result would look like. You have the configuration in front of you: two epochs, evaluation every five iterations, and two loss curves that the run will produce. Commit to an answer first, because the reasoning you do now is what makes the output meaningful when it arrives.
What do you think happens?
Across the two epochs, what should the training loss and the validation loss do if the run is healthy?
Reveal answer
Both fall consistently
In this run both values decrease consistently across the two epochs, which the source reads as evidence that the model is learning effectively within two epochs.
Reading Training and Validation Loss Together
Two kinds of loss are tracked. The training loss is computed on the data the model is learning from. The validation loss is computed on held-out instruction examples. The source bases its evaluation on both, and this is the central reading skill for the run: a model whose training loss falls while its validation loss does not is not doing what you want. Watching only the training loss would hide that problem.
The source says the direction and consistency of the change matter most. A single lower number at one checkpoint is weaker evidence than a sequence of values that keeps falling as training continues. So when you read the output, look at the whole pair of curves: do both move down together from one checkpoint to the next, or does one of them stop following the other?
Overfitting is the pattern in which the model fits the training examples so closely that it generalizes less well. Divergence between the two losses, with training loss still falling and validation loss not following, is the signal to look for.
Checking the Generated Responses
The training call sends a starting context built from the first validation instruction, and the responses generated at the end of each epoch let you see the model's behavior directly. This is the most readable check in the whole run, because you can compare the model's answer against what the task asked for: did the model turn the active sentence into a passive one?
Judging a run from its losses and its responses
A run has finished. Both loss sequences fall steadily across the two epochs, and the response generated at the end of epoch 2 is a correct passive-voice rewrite of the instruction's sentence. Did the run succeed?
- 1Check the loss direction
Both the training and validation losses decrease consistently, so the model is not showing the divergence that signals overfitting.
- 2Check the consistency
The decrease holds across the sequence of checkpoints, which is stronger evidence than a single lower value.
- 3Check the generated response
The response matches what the task asked for, so the numbers and the behavior agree.
- 4Combine the evidence
Both signals point the same way, which is the pattern the source describes as success for this run.
The run succeeded. Two epochs were sufficient, and there is no evidence that a third epoch is needed.
Deciding When to Stop Training
The configuration uses exactly two epochs, and the source explains why that choice is reasonable. Because the losses keep decreasing and the responses are correct within those two passes, there is no need to add a third epoch. Epoch count is therefore a decision to make from results, not a number to keep because it appeared in an earlier run.
Finding Where a Run Goes Wrong
When a run departs from expectation, check three things in a fixed order: the configuration, the loss metrics, and the generated outputs. Each check narrows where the problem could be, and the decision after each check tells you what to look at next.
Mistakes When Judging a Run
Common mistake Judging the run by the training loss alone
What it looks likeThe training loss falls steadily, so the run is declared a success without looking at the validation loss.
Why it failsThe source treats the training loss as only half of the evidence. A model whose training loss falls while its validation loss does not is not doing what you want.
Do this insteadRead both losses together and check whether they keep moving in the same direction.
Common mistake Trusting a single lower value at one checkpoint
What it looks likeOne checkpoint shows a lower loss, so the run is treated as improving.
Why it failsThe source says a single lower number is weaker evidence than a sequence of values that keeps falling.
Do this insteadLook at the trend across all checkpoints in the run.
Common mistake Adding epochs out of habit
What it looks likeA third epoch is added because more training seems like it should help.
Why it failsThe source says adding more training without evidence can lead to overfitting.
Do this insteadDecide the epoch count from the results of the current run.
Common mistake Skipping the generated responses
What it looks likeOnly the loss numbers are read, and the outputs are never compared with the task.
Why it failsLosses are indirect; the responses show directly whether the model converts active sentences to passive voice.
Do this insteadCompare the response generated at the end of each epoch against the instruction.
Practice: Reviewing a Training Call
A colleague shares a fine-tuning call that uses AdamW, a learning rate of 0.00005, a weight decay of 0.1, two epochs, and evaluation every five iterations. They report that training loss fell across both epochs, but they did not record validation loss. Using the diagnostic order from this article, what would you check first, what would you ask them to add, and what would you need to see before calling the run successful?
Hints
- Start with the configuration: confirm which settings are present and which are missing.
- A decrease in training loss alone is not enough evidence.
- The generated responses give a direct check against the task.
Summary of a Training Run
- 1Fine-tuning adjusts a pre-trained model to a specific task, and a single training call sets the optimizer, epoch count, and evaluation settings.
- 2The optimizer updates the model's parameters; this run uses AdamW with a learning rate of 0.00005 and a weight decay of 0.1.
- 3Read training and validation loss together, looking at the consistent direction across checkpoints; divergence between them signals overfitting.
- 4Confirm success by combining the loss pattern with inspection of the generated responses, and decide the epoch count from results rather than habit.
At a glance
- Fine-tuning adjusts a pre-trained model to a specific task, and a single training call sets the optimizer, epoch count, and evaluation settings.
- The optimizer updates the model's parameters; this run uses AdamW with a learning rate of 0.00005 and a weight decay of 0.1.
- Read training and validation loss together, looking at the consistent direction across checkpoints; divergence between them signals overfitting.
- Confirm success by combining the loss pattern with inspection of the generated responses, and decide the epoch count from results rather than habit.