Quick Answer

Overfitting is when a model learns the noise and quirks of your specific training examples instead of the actual underlying pattern, so it scores great on data it has already seen and falls apart on anything new. You can see it directly in numbers: training error keeps dropping while validation error stops improving and then gets worse. The fix is never to train longer — it's reducing model complexity relative to your data, adding regularization, or getting more or cleaner data.

What Overfitting Really Is

Every model is trying to learn a general pattern from a limited sample of examples. Overfitting happens when the model has enough flexibility to also learn the specific noise in that sample — the random measurement error, the coincidental correlations that exist in your 500 rows but wouldn't exist in the next 500 — and treats that noise as if it were signal worth predicting from. The result is a model that reproduces its training data almost perfectly and a real-world pattern almost not at all.

This is why training accuracy is close to useless as a standalone number. A model can hit 99.9% on its training set purely by memorizing it, the way a student who memorizes last year's exact exam paper will ace that paper and then fail a new one covering the same material with different questions. The number that actually matters is performance on data the model did not see during training — a validation set, held out before any training happens and never touched during it, used purely to check whether the model generalizes.

The gap between training performance and validation performance is the diagnostic. A small, stable gap is healthy. A gap that keeps widening as training continues is overfitting happening in real time, and it's directly observable if you're actually tracking both numbers instead of just the one that looks good.

Watching Overfitting Happen, in Real Numbers

Here's overfitting produced on purpose, so you can see the actual shape of it. Eighteen noisy training points were generated from a sine wave, and polynomials of increasing degree were fit to them — a higher degree means a more flexible curve with more parameters to tune, exactly analogous to a bigger neural network having more capacity than a smaller one:

model = make_pipeline(PolynomialFeatures(degree=d), LinearRegression())
model.fit(X_train, y_train)
train_mse = mean_squared_error(y_train, model.predict(X_train))
val_mse = mean_squared_error(y_test, model.predict(X_test))

The real measured mean squared error at each degree, with 18 training points and 12 held-out validation points:

degree     1      2      3      5      9     12     15     18
train   0.220  0.216  0.087  0.060  0.051  0.040  0.041  0.039
val     0.266  0.307  0.088  0.120  0.380  0.319  0.370  0.259

Read across the training row and it only goes down — a degree-18 polynomial has enough free parameters to bend through nearly every training point, so of course its training error is the lowest. Read across the validation row and the story is completely different: it improves right alongside training error up through degree 3 (0.088, the best point on the whole table), then gets dramatically worse from degree 5 onward, spiking to 0.380 at degree 9 and staying bad all the way to degree 18. Past degree 3, the model wasn't getting better at the real pattern anymore — it was getting better at memorizing 18 specific noisy points, at the direct cost of everything else. That crossover, where training error keeps falling but validation error turns and climbs, is the single clearest signature of overfitting there is.

Why Models Overfit

Three factors interact to cause this, and the polynomial example makes all three concrete. Capacity relative to data size is the biggest one — a degree-18 polynomial has 19 coefficients to fit against only 18 training points, which is enough freedom to pass through every single point exactly if it wanted to, noise included. The same model with 1,800 training points instead of 18 would struggle much more to overfit, because fitting the noise in 1,800 different points simultaneously is a far harder trick than fitting the noise in 18.

Noise in the data is the raw material overfitting consumes — if the training labels were noise-free, there'd be nothing for a flexible model to memorize beyond the true pattern, and higher capacity would just mean a more accurate fit. Real data always has some noise, whether from measurement error, human labeling inconsistency, or genuine randomness in what's being predicted, which is exactly why capacity has to be matched to it rather than maximized.

Training duration matters for the same reason in iterative models like neural networks: early in training, a network is learning the coarse, generalizable pattern; if you keep training well past that point without regularization, it starts using its remaining capacity to chip away at the last bit of training error by fitting individual noisy examples, which is functionally the same failure mode as the polynomial climbing to degree 18.

Detecting Overfitting in Your Own Project

The practical version of the diagnosis above is simple to set up and easy to skip under deadline pressure, which is exactly why it gets skipped. Split your data into training, validation, and test sets before you touch any hyperparameters — validation is for tuning decisions like model complexity, and test is a final, untouched check you only look at once, at the very end, so it stays an honest measure of generalization rather than something you've indirectly tuned against.

Plot a learning curve — training and validation error at increasing amounts of training (more epochs, or more data) — rather than reading off a single final number. The shape of the curve tells you things a single snapshot can't: whether the gap between the two lines is stable or widening, and whether validation error has an inflection point where it stops improving, exactly like the degree-3-to-degree-9 transition in the table above.

For smaller datasets, k-fold cross-validation — splitting the data into k parts, training on k-1 of them and validating on the held-out part, rotating which part is held out — gives a more reliable estimate than a single train/validation split, because a single split can accidentally be unrepresentative, especially with limited data. It costs more compute (you're training k models instead of one) but removes a real source of noise in your evaluation itself.

Fixing It: Regularization, in Real Numbers

Regularization is a direct, mechanical fix: it adds a penalty to the loss function for large weight values, which discourages the model from using its full capacity to chase individual noisy points, without reducing the model's raw complexity (its degree, its layer sizes) at all. Applying Ridge regression, which penalizes the sum of squared weights, to the same overfit degree-9 polynomial from above, sweeping the penalty strength (alpha):

model = make_pipeline(PolynomialFeatures(degree=9), StandardScaler(), Ridge(alpha=alpha))
alpha      0.0    0.0001   0.001    0.01     0.1      1.0
train    0.037    0.063    0.066    0.074    0.101    0.129
val      0.251    0.127    0.114    0.101    0.118    0.133

With no regularization (alpha = 0), validation error is 0.251 — badly overfit, matching the earlier table. As the penalty increases, validation error drops sharply, bottoming out at 0.101 around alpha = 0.01, then starts climbing again by alpha = 1.0 as the penalty becomes strong enough to also block the model from fitting the real pattern, not just the noise. Notice training error rises the entire time — regularization makes the training fit deliberately worse, which is exactly the trade being made: giving up some training accuracy specifically to gain validation accuracy, which is the only accuracy that predicts real-world behavior.

The same underlying idea shows up under different names depending on the model type: L1/L2 weight penalties in linear models and neural networks, dropout in neural networks (randomly disabling a fraction of neurons during each training step so no single neuron can be relied on too heavily), early stopping (halting training once validation error stops improving, even if training error is still falling), pruning in decision trees, and simply choosing a smaller or simpler model when the data doesn't justify a larger one.

The Other Failure Mode: Underfitting

The same table that shows overfitting also shows its opposite. At degree 1 and degree 2, training error is 0.220 and 0.216 — both high, and both close to their corresponding validation errors of 0.266 and 0.307. That's underfitting: the model is too simple to capture even the pattern in the data it's training on, so it does about equally poorly on both sets, just poorly across the board rather than well on one and badly on the other.

The diagnostic difference matters because the fix is the opposite direction. A large train-validation gap with good training performance points toward reducing complexity or adding regularization. Uniformly bad performance on both sets points toward the model needing more capacity, better features, or a fundamentally different approach — throwing regularization at an underfit model only makes it worse, since it already isn't using the capacity it has.

A Practical Checklist Before You Ship a Model

  • Hold out validation and test data before touching any hyperparameters — never let the model or your tuning decisions see the test set until the very end.
  • Track and plot both training and validation error throughout training, not just a single final accuracy number.
  • Start with a simple model and add complexity only as the data justifies it, rather than starting large and hoping regularization cleans it up.
  • Use cross-validation for model-selection decisions on smaller datasets, where a single split can mislead you.
  • If you see a big train-validation gap, reach for regularization, more data, or a simpler model — not more training time, which usually makes the gap worse, not better.
  • Re-check validation performance after any pipeline change, including ones that seem unrelated to the model itself, like a change in how features are computed — data leakage from training into validation is a common, quiet way to make overfitting invisible until production.

Frequently Asked Questions

What's the difference between overfitting and underfitting? Overfitting shows a large gap between training and validation performance, with training much better than validation. Underfitting shows both training and validation performance roughly equally poor, because the model is too simple to capture even the training pattern.
Does more data always fix overfitting? It usually helps a lot, since it becomes harder for a model to memorize noise across more examples, but it isn't guaranteed alone — if the new data has the same noise characteristics or if there's a deeper issue like data leakage, more data won't fully solve it. It typically needs to be combined with appropriate model capacity and regularization.
Does a high training accuracy always mean overfitting? No, not by itself. High training accuracy only signals overfitting when validation accuracy is meaningfully lower. If both are high and close together, the model is simply performing well and generalizing correctly.
What is early stopping? It's a regularization technique for iteratively trained models like neural networks where you monitor validation error during training and stop as soon as it stops improving, even if training error is still decreasing, rather than training for a fixed number of epochs regardless.
Is overfitting only a deep learning problem? No. It affects any sufficiently flexible model, including polynomial regression, decision trees, and k-nearest-neighbors with a small k. The example in this post uses plain polynomial regression specifically to show that the mechanism has nothing to do with neural networks in particular.