TensorFlow
custom estimator
early stopping
train_and_evaluate
machine learning

TensorFlow 1.10 custom estimator early stopping with train_and_evaluate

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

In TensorFlow 1.10, the usual way to combine a custom estimator with early stopping is to attach a stopping hook to the TrainSpec used by train_and_evaluate. The important detail is that early stopping is driven by evaluation results written during the evaluation phase, so your monitored metric must exist in the estimator's eval output.

train_and_evaluate Does Not Stop by Itself

tf.estimator.train_and_evaluate coordinates alternating training and evaluation, but it does not automatically stop when validation metrics stall. You have to add that behavior explicitly.

For TensorFlow 1.10-era estimator workflows, the standard approach is an early-stopping hook such as tf.contrib.estimator.stop_if_no_decrease_hook.

Your Custom Estimator Must Expose Eval Metrics

The model function for a custom estimator should return an EstimatorSpec with:

  • 'loss'
  • 'train_op'
  • 'eval_metric_ops'

A minimal custom estimator model function might look like this:

python
1import tensorflow as tf
2
3
4def model_fn(features, labels, mode, params):
5    x = features["x"]
6    logits = tf.layers.dense(x, 1)
7    predictions = tf.squeeze(logits, axis=1)
8    loss = tf.losses.mean_squared_error(labels, predictions)
9
10    if mode == tf.estimator.ModeKeys.TRAIN:
11        optimizer = tf.train.AdamOptimizer(0.001)
12        train_op = optimizer.minimize(loss, global_step=tf.train.get_global_step())
13        return tf.estimator.EstimatorSpec(mode=mode, loss=loss, train_op=train_op)
14
15    mae = tf.metrics.mean_absolute_error(labels, predictions)
16    return tf.estimator.EstimatorSpec(
17        mode=mode,
18        loss=loss,
19        eval_metric_ops={"mae": mae},
20    )

That mae metric can now be monitored by an early-stopping hook.

Add the Stop Hook to the TrainSpec

In TensorFlow 1.10, a common pattern is:

python
1estimator = tf.estimator.Estimator(model_fn=model_fn, model_dir="/tmp/model")
2
3early_stop = tf.contrib.estimator.stop_if_no_decrease_hook(
4    estimator=estimator,
5    metric_name="loss",
6    max_steps_without_decrease=1000,
7    min_steps=1000,
8    run_every_steps=100,
9)
10
11train_spec = tf.estimator.TrainSpec(
12    input_fn=train_input_fn,
13    max_steps=100000,
14    hooks=[early_stop],
15)
16
17eval_spec = tf.estimator.EvalSpec(
18    input_fn=eval_input_fn,
19    steps=100,
20    throttle_secs=30,
21)
22
23tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec)

This tells training to stop after the monitored metric stops decreasing for the configured number of steps.

Choose the Metric Carefully

You can monitor built-in eval loss, or one of your custom metrics from eval_metric_ops. For example, if lower MAE is what matters, monitor mae instead of loss.

The key rule is simple: the metric name must exactly match what the evaluation phase writes. If the hook watches a metric that does not exist, early stopping will not behave the way you expect.

min_steps and run_every_steps Matter

Two parameters are especially important:

  • 'min_steps prevents premature stopping before the model has had a chance to learn anything'
  • 'run_every_steps controls how often the stopping condition is checked'

If min_steps is too small, noisy validation metrics can stop training too early. If run_every_steps is too large, early stopping becomes sluggish and wastes training work.

Why This Works with Custom Estimators

The estimator does not need special early-stopping logic inside model_fn. That logic sits outside the model in the training hook. Your job inside the custom estimator is simply to expose stable evaluation metrics and make sure train_and_evaluate is actually running evaluations often enough to provide signal.

Common Pitfalls

  • Monitoring a metric name that is not present in eval_metric_ops.
  • Forgetting that early stopping depends on evaluation runs, not only on training steps.
  • Setting min_steps so low that early noise stops training prematurely.
  • Putting the hook in the wrong place instead of attaching it to TrainSpec.
  • Expecting TensorFlow 1.x estimator hooks to behave exactly like modern Keras callbacks.

Summary

  • In TensorFlow 1.10, early stopping with train_and_evaluate is typically done with a stopping hook on the TrainSpec.
  • Your custom estimator must expose the metric you want to monitor during evaluation.
  • 'loss is the simplest metric to monitor, but custom eval metrics can work too.'
  • 'min_steps and evaluation frequency strongly affect the stopping behavior.'
  • The model function defines metrics; the early-stopping hook decides when training ends.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.