Termination condition
Last edited
Fact-checked
In review queue
Sources
19 citations
Revision
v6 · 3,210 words
Fact-checks are independent of edits: a reviewer re-verifies the article against its sources and stamps the date. How we verify
See also: Machine learning terms
A termination condition, also called a stopping criterion, convergence criterion, or halting condition, is a rule that decides when an iterative algorithm should stop running. In machine learning, termination conditions appear in almost every iterative procedure: gradient-based optimization, tree induction, clustering, reinforcement learning episodes, evolutionary search, Markov chain Monte Carlo, and the token-by-token decoding loop of a large language model. The choice of stopping rule directly shapes how long training takes, how well a model generalizes, and whether results are reproducible from one run to the next. Because the rule is often the difference between an underfit and an overfit model, it is best treated as an explicit hyperparameter rather than an afterthought.
Most real systems combine several conditions rather than relying on a single rule. A typical training script will stop when whichever comes first: the maximum number of epochs is reached, validation loss has not improved for a fixed patience window, or a wall-clock budget runs out. Combining a hard upper bound with an early-exit rule keeps the procedure both safe (it always terminates) and efficient (it does not burn compute past the point where the model has stopped improving).
Why do termination conditions matter?
A badly chosen stopping rule has three concrete consequences. First, training too long invites overfitting: the model begins to memorize noise in the training set and validation accuracy starts to fall even while training loss keeps dropping [2]. Second, training too long wastes compute, which is a real cost when a single experiment can occupy GPUs for hours or days. Third, vague or undocumented stopping rules make experiments hard to reproduce; a paper that says "we trained until convergence" without specifying the criterion leaves a key hyperparameter implicit.
A sensible default in most deep learning workflows is to use both a maximum epoch count and a patience-based early stopping rule on a held-out validation set, then save the best checkpoint encountered along the way [1]. This pattern shows up in nearly every modern training framework.
Categories of termination conditions
Different algorithm families have their own conventions. The table below summarizes the most common stopping criteria across optimization paradigms.
| Paradigm | Common termination conditions | Typical implementation |
|---|---|---|
| First-order optimization | Gradient norm below tolerance, loss change below tolerance, max iterations | tol, max_iter, ` |
| Neural network training | Max epochs, validation metric plateau, time budget, learning rate floor | EarlyStopping callback, max_epochs |
| Decision tree induction | Max depth, min samples per leaf or split, min impurity decrease, max leaf nodes | Pre-pruning hyperparameters |
| Clustering | Centroid movement below tolerance, max iterations, inertia change | K-means tol and max_iter |
| Genetic algorithms | Generation count, fitness plateau, diversity collapse | Stagnation window |
| Reinforcement learning | Terminal state reached, max steps per episode, total environment steps budget | terminated / truncated flags |
| Bandits and active learning | Sample budget exhausted, confidence interval width below threshold | Pulls allocated, posterior shrinkage |
| MCMC | Burn-in length plus convergence diagnostics, fixed sample count | R-hat below threshold, ESS target |
| LLM decoding | EOS token, custom stop sequence, max tokens, time budget | stop, max_tokens parameters |
Gradient-based optimization
For smooth optimization with gradient descent or its variants, the classical termination rule is to stop when the gradient norm drops below a small tolerance: stop when . This reflects the first-order optimality condition, since at a stationary point the gradient is zero. Practical implementations usually compute the 2-norm of the gradient vector, although the infinity norm (largest absolute component) is sometimes preferred for high-dimensional problems where it gives a per-coordinate guarantee. Checking the gradient norm adds essentially no overhead, because the gradient computed at the end of one iteration is already needed at the start of the next.
Other common rules include stopping when the change in loss between iterations falls below a tolerance, when the change in parameters falls below a tolerance, or when a maximum iteration count is reached. SciPy's scipy.optimize.minimize exposes gtol (gradient-norm tolerance), ftol (function-value tolerance), xtol (step-size tolerance), and maxiter parameters that map directly onto these criteria [18]. For stochastic gradient descent the gradient norm is a noisy estimator and is rarely used directly; practitioners instead monitor a smoothed running loss or a held-out validation metric.
For strongly convex problems, gradient descent needs roughly iterations to reach gradient norm below , and iterations to reach loss within of the optimum, depending on conditioning [13]. These bounds are mostly used to choose a reasonable max_iter value rather than as live stopping rules.
Early stopping for neural networks
In neural network training the dominant stopping rule is early stopping with a patience parameter. After each epoch (or every fixed number of steps) the model is evaluated on a validation set; training continues as long as the monitored metric keeps improving and stops once it has failed to improve for patience consecutive epochs. The original systematic study of this idea is Lutz Prechelt's 1998 paper "Automatic early stopping using cross validation: quantifying the criteria," published in Neural Networks, which evaluated 14 automatic stopping criteria drawn from three classes across 12 classification and approximation tasks using multi-layer perceptrons trained with RPROP [1]. Its central finding, in the paper's own words, is that "slower stopping criteria allow for small improvements in generalization (in the order of 4%), but cost about a factor of 4 longer in training time" [1].
Early stopping doubles as an implicit regularizer. By halting before the parameters drift far from initialization, it has roughly the same effect as L2 weight decay in the linear-regression case, a result derived in detail in Goodfellow, Bengio, and Courville's Deep Learning (2016) [2]. The framework-level controls are similar across libraries, although the parameter names differ.
| Framework | API | Key parameters |
|---|---|---|
| Keras | keras.callbacks.EarlyStopping | monitor, patience, min_delta, mode, restore_best_weights, baseline, start_from_epoch |
| PyTorch Lightning | lightning.pytorch.callbacks.EarlyStopping | monitor, patience, min_delta, mode, check_finite, stopping_threshold, divergence_threshold |
| scikit-learn (MLP, SGDClassifier) | constructor flag early_stopping=True | validation_fraction, n_iter_no_change, tol |
| XGBoost | early_stopping_rounds argument to fit or train | rounds without improvement on the eval set |
| LightGBM | early_stopping_round parameter (alias early_stopping_rounds, n_iter_no_change) | rounds without improvement on a validation metric |
A common subtlety in Keras is that restore_best_weights=True only restores weights when the patience criterion actually fires; if training hits max_epochs first, the final weights are kept rather than the best ones [3]. Practitioners often add a ModelCheckpoint callback alongside EarlyStopping to ensure the best weights are written to disk regardless of which condition stopped training. Other frameworks fold extra guards into the same callback: PyTorch Lightning's EarlyStopping can also halt on an absolute stopping_threshold (stop once the metric is good enough) or bail out on a divergence_threshold (stop if the metric gets catastrophically worse) [4]. Gradient-boosting libraries follow the same pattern: XGBoost uses early_stopping_rounds [7] and LightGBM uses early_stopping_round [8], each halting when a validation metric fails to improve for a set number of boosting rounds.
Decision trees
Decision trees build top-down by recursively partitioning the data, and the termination condition controls when a node is declared a leaf. scikit-learn's DecisionTreeClassifier and DecisionTreeRegressor expose several pre-pruning parameters that act as stopping conditions: max_depth caps the depth of every branch, min_samples_split requires a minimum number of samples in a node before it can be split, min_samples_leaf enforces a minimum size for any resulting leaf, min_impurity_decrease requires that a split reduce impurity by at least a given amount, and max_leaf_nodes caps the total number of leaves [6]. Setting these too loose produces a tree that overfits; setting them too tight produces an underfit tree that misses real structure.
Post-pruning techniques such as cost-complexity pruning, exposed in scikit-learn through the ccp_alpha parameter, take a different approach: the tree is grown to its full size and then pruned back according to a complexity penalty [6]. Here the termination condition during growth is essentially "stop when the data in a node is pure or nearly so," with the regularization happening afterward.
Clustering
Iterative clustering algorithms typically alternate between assignment and update steps and need a rule for when to stop iterating. scikit-learn's KMeans uses two: tol, the relative tolerance with respect to the Frobenius norm of the difference in centroid positions between consecutive iterations (default 1e-4), and max_iter, the maximum number of iterations per run (default 300) [5]. Iteration stops as soon as either condition is met. Expectation-maximization for Gaussian mixture models, hierarchical clustering, and DBSCAN-style algorithms have analogous criteria, usually expressed as a tolerance on parameter changes plus a maximum iteration count.
Genetic algorithms and evolutionary search
Evolutionary algorithms run for a fixed number of generations or until some stagnation criterion fires. The most common stopping rules are a maximum generation count, a target fitness threshold, and a stagnation window: stop if the best fitness has not improved by more than over the last generations. Some implementations also monitor population diversity and stop when it collapses below a threshold, which usually signals premature convergence to a local optimum. Production genetic algorithm frameworks typically combine a hard generation cap with stagnation detection so that easy problems finish quickly while hard ones still receive a fixed compute budget.
Reinforcement learning: terminated versus truncated
In reinforcement learning the word "termination" has a precise technical meaning that differs from supervised training. Following Sutton and Barto's formulation, an agent's interaction with the environment breaks into episodes, and each episode ends in a special state called the terminal state, followed by a reset to a standard starting state [15]. Each episode in a Markov decision process therefore ends in one of two ways. The agent reaches a terminal state, where no further rewards accrue (the game is won or lost, the robot has fallen, the goal is reached) and which is formally modeled as an absorbing state that transitions only to itself with reward zero [15]. Alternatively, the episode is truncated by an external time limit even though the underlying process could continue indefinitely.
From Gymnasium version 0.26 onward, the Step API returns both cases explicitly, and step() now returns five values, (observation, reward, terminated, truncated, info), in place of the single combined done flag used in earlier versions of OpenAI Gym [10]. That combined flag was deprecated because it conflated the two cases and caused subtle bugs in bootstrapping. As the Farama Foundation explains, "using done uniformly would result in an incorrect loss function" [17]. The reason is that the two cases imply different Bellman targets: "when an episode ends due to termination we don't bootstrap, when it ends due to truncation, we bootstrap" [9]. When an episode terminates, the value of the next state is zero by definition, so the update uses only the immediate reward. When it is truncated, the next state still has a meaningful value, so bootstrapping should continue.
Treating truncation as termination teaches the agent that any reward collected before the time limit is effectively free, which produces myopic and unstable policies. Pardo et al. (2018) analyze this directly: they argue that terminations caused by time limits should not be treated as environment-defined terminal states but should instead be bootstrapped, an approach they call partial-episode bootstrapping, and they demonstrate improved performance and stability on continuous-control benchmarks such as MuJoCo's HalfCheetah [16].
| Episode end type | Cause | Bellman target | Gymnasium return value |
|---|---|---|---|
| Termination | Goal reached, agent died, environment-defined terminal state | (no bootstrap) | terminated=True, truncated=False |
| Truncation | Time limit, external cutoff, wrapper such as TimeLimit | (still bootstrap) | terminated=False, truncated=True |
| Ongoing | Neither condition met | both False |
Beyond per-episode termination, RL training itself has a higher-level termination condition. This is usually a total environment-step budget (often hundreds of millions of steps for Atari benchmarks or billions for large-scale robotics), a fixed number of policy update epochs, or a target performance level on a held-out evaluation suite.
Bandits and sequential decision-making
Multi-armed bandit algorithms sample arms until either a fixed sample budget runs out or the algorithm becomes confident enough to commit to one arm. Best-arm-identification procedures stop when the confidence interval around the leading arm's estimated value separates from the others by more than a target margin. Active learning and Bayesian optimization use analogous rules, stopping when the expected improvement from another query falls below a threshold or when a labeling budget is reached.
Markov chain Monte Carlo
MCMC samplers do not converge to a single answer; they generate samples from a target distribution. The termination problem is therefore split into two parts. A burn-in phase discards initial samples that depend too strongly on the starting point. After burn-in, the chain runs until enough effectively independent samples have been collected. Convergence diagnostics such as the Gelman-Rubin statistic R-hat (introduced in Gelman and Rubin 1992) compare the variance within and across multiple chains; values close to 1 indicate the chains have mixed [11]. Vehtari et al. (2021) improved the statistic with rank normalization and folding, and recommend the stricter threshold of R-hat below 1.01 (the traditional 1.1 cutoff is usually too optimistic) together with a bulk effective sample size (ESS) above 400 for stable posterior summaries [12]. A common operational rule is therefore to declare convergence only when R-hat for every parameter of interest is below 1.01 and ESS clears that target.
Language model inference: when does generation stop?
For large language models the training termination story is unusual. Modern LLMs are typically trained for a fixed number of optimizer steps consuming a planned token budget (often in the trillions of tokens) rather than to convergence in the classical sense. Training rarely runs until the loss flattens, both because the loss continues to improve slowly long after diminishing returns set in and because compute, not convergence, is the binding constraint.
At inference time, generation is governed by a different set of stopping rules. The model itself emits an end-of-sequence (EOS) token that the runtime treats as a stop signal. Users can supply additional stop strings that abort generation when matched in the output stream; the OpenAI API allows up to 4 such sequences [14]. A max_tokens parameter caps the worst-case length, and many production deployments add a wall-clock deadline so that a single slow request does not block other traffic.
Reasoning models that perform extended internal deliberation add a further termination condition on the hidden reasoning phase itself. Anthropic's Claude historically exposed this as a budget_tokens cap on extended thinking: a hard ceiling on how many internal reasoning tokens the model may spend, required to be strictly smaller than max_tokens, before it must commit to a final answer [19]. Newer Claude models (Opus 4.7 and later) replace the fixed budget with adaptive thinking, in which the model decides how much to think and the caller instead sets a coarse effort level (low, medium, high, or max); OpenAI's o-series reasoning models expose an analogous reasoning-effort control alongside a max_completion_tokens limit [19][14].
Best practices and common pitfalls
The most reliable approach is to combine multiple termination conditions and to pick the one that fires first. A typical recipe for supervised learning looks like this: a maximum epoch count high enough that the model reaches its best validation score; a patience-based early stopping rule on a sensible validation metric; a save-best-checkpoint mechanism so the best weights are recoverable; and a wall-clock budget as a final safety net.
A few mistakes show up over and over. Stopping too early produces an underfit model and is often caused by a patience value that does not account for noise in the validation curve. Stopping too late wastes compute and risks overfitting; this is the failure mode when only max_iter is used without any improvement check. Choosing the wrong validation metric is subtle: optimizing F1 while monitoring loss can stop training at the wrong epoch when the two are not perfectly aligned. Reusing the validation set for both early stopping and final reporting inflates the reported score, so a separate held-out test set should be evaluated only after training has stopped.
For RL, the single largest source of bugs is conflating termination and truncation. Always honor the distinction in the Bellman update [9][16]. For LLM inference, forgetting to set max_tokens (or setting it too high) is the standard way to discover that the model can talk forever. For MCMC, declaring convergence based on a single chain's apparent stationarity is a classic trap; always run multiple chains and check R-hat across them [12].
Finally, log the termination condition that actually fired. Knowing whether a run stopped because it converged, ran out of patience, hit the iteration cap, or was interrupted manually is essential for diagnosing what went wrong and for reproducing the experiment later.
Explain like I'm 5 (ELI5)
When a computer is learning from data, it keeps practicing over and over. A termination condition is just a rule that tells the computer when to stop practicing. Maybe it stops after a set number of practice rounds, or when its scores on a quiz stop getting better, or when a timer runs out. Picking a good rule matters: if the computer stops too soon, it will not have learned enough; if it keeps practicing forever, it will start memorizing the practice questions instead of understanding the topic, and it will also burn through a lot of electricity for no reason.
References
- Prechelt, L. (1998). "Automatic early stopping using cross validation: quantifying the criteria." *Neural Networks*, 11(4), 761-767. https://doi.org/10.1016/S0893-6080(98)00010-0 ↩
- Goodfellow, I., Bengio, Y., and Courville, A. (2016). *Deep Learning*. MIT Press, Chapter 7 (Regularization for Deep Learning). https://www.deeplearningbook.org/ ↩
- Keras documentation. "EarlyStopping callback." https://keras.io/api/callbacks/early_stopping/ ↩
- PyTorch Lightning documentation. "EarlyStopping." https://lightning.ai/docs/pytorch/stable/api/lightning.pytorch.callbacks.EarlyStopping.html ↩
- scikit-learn documentation. "KMeans." https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html ↩
- scikit-learn documentation. "DecisionTreeClassifier." https://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html ↩
- XGBoost documentation. "Python API: early stopping." https://xgboost.readthedocs.io/en/stable/python/python_intro.html ↩
- LightGBM documentation. "lightgbm.early_stopping." https://lightgbm.readthedocs.io/en/latest/pythonapi/lightgbm.early_stopping.html ↩
- Farama Foundation. "Gymnasium: Handling Time Limits." https://gymnasium.farama.org/tutorials/gymnasium_basics/handling_time_limits/ ↩
- Towers, M., et al. (2024). "Gymnasium: A Standardized Interface for Reinforcement Learning Environments." *arXiv:2407.17032.* https://arxiv.org/abs/2407.17032 ↩
- Gelman, A., and Rubin, D. B. (1992). "Inference from Iterative Simulation Using Multiple Sequences." *Statistical Science*, 7(4), 457-472. https://doi.org/10.1214/ss/1177011136 ↩
- Vehtari, A., Gelman, A., Simpson, D., Carpenter, B., and Bürkner, P. C. (2021). "Rank-Normalization, Folding, and Localization: An Improved R-hat for Assessing Convergence of MCMC." *Bayesian Analysis*, 16(2), 667-718. https://doi.org/10.1214/20-BA1221 ↩
- Nocedal, J., and Wright, S. J. (2006). *Numerical Optimization*, 2nd edition. Springer, chapters on convergence theory. https://doi.org/10.1007/978-0-387-40065-5 ↩
- OpenAI API reference. "Chat Completions: stop, max_tokens." https://platform.openai.com/docs/api-reference/chat/create ↩
- Sutton, R. S., and Barto, A. G. (2018). *Reinforcement Learning: An Introduction*, 2nd edition. MIT Press, Chapter 3 (Finite Markov Decision Processes), Section 3.4 on episodic and continuing tasks and terminal states. http://incompleteideas.net/book/the-book-2nd.html ↩
- Pardo, F., Tavakoli, A., Levdik, V., and Kormushev, P. (2018). "Time Limits in Reinforcement Learning." *Proceedings of the 35th International Conference on Machine Learning (ICML)*, PMLR 80. arXiv:1712.00378. https://arxiv.org/abs/1712.00378 ↩
- Farama Foundation. "Deep Dive: Gymnasium Terminated / Truncated Step API." https://farama.org/Gymnasium-Terminated-Truncated-Step-API ↩
- SciPy documentation. "scipy.optimize.minimize." https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html ↩
- Anthropic. "Extended thinking" and "Adaptive thinking." Claude Developer Platform documentation. https://platform.claude.com/docs/en/build-with-claude/extended-thinking ↩
Improve this article
Add missing citations, update stale details, or suggest a clearer explanation. Every suggestion is reviewed for sourcing before it goes live.
5 revisions by 1 contributors · full history