Gradient Accumulation with Custom model.fit in TF.Keras?
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.
Introduction
Gradient accumulation lets you simulate a larger effective batch size by summing gradients across several smaller mini-batches before applying an optimizer step. In TF.Keras, the clean way to do this while still using model.fit() is not to rewrite the whole training loop, but to override train_step in a custom Model subclass.
Why Override train_step Instead of Replacing fit
model.fit() already handles callbacks, metrics, validation, progress bars, distribution strategy integration, and data iteration. If you replace it entirely, you throw away a lot of useful framework behavior.
Overriding train_step gives you control over one batch update while keeping the rest of the Keras training stack. That is usually the right level for gradient accumulation.
A Working Pattern
The model below accumulates gradients for accum_steps mini-batches and applies them only when the accumulation counter reaches that value. For clarity, this version uses eager execution during training.
The important detail is dividing the loss by the accumulation step count before computing gradients. Without that scaling, each optimizer update would be too large.
Effective Batch Size
If your physical mini-batch size is 4 and accum_steps is 4, the effective batch size is 16. That is the main point of the technique: you can mimic larger-batch training without fitting all samples in memory at once.
This is especially useful for large models, long sequences, or high-resolution inputs where the real bottleneck is memory rather than compute.
Metrics and Update Timing
Metrics usually update every mini-batch, not only when gradients are applied. That is fine, but you should remember that the displayed metric count and the optimizer step count are no longer the same thing.
This matters when scheduling learning rates or logging per-step information. If your schedule assumes one optimizer step per batch, you need to adapt it to the accumulation interval.
About Current TensorFlow Optimizers
In current TensorFlow and Keras releases, some optimizers expose built-in gradient accumulation options. When that is available and matches your needs, it is simpler than custom code. The custom train_step approach is still valuable when you need full control, want optimizer-independent behavior, or need to combine accumulation with custom loss logic.
Common Pitfalls
The biggest pitfall is forgetting to divide the loss by the accumulation step count before computing gradients. That changes optimization dynamics and usually destabilizes training.
Another mistake is failing to reset the accumulator tensors after applying gradients. If the old values stay around, the next update includes stale gradients.
Developers also overlook the final partial accumulation at the end of an epoch. If the batch count is not divisible by accum_steps, you may want logic to flush the remaining gradients instead of dropping them.
Finally, be careful with schedules, logging, and callbacks that assume one optimizer update per batch. Gradient accumulation changes that assumption.
Summary
- In TF.Keras, the clean way to add gradient accumulation while keeping
model.fit()is to overridetrain_step. - Accumulate gradients across several mini-batches and apply them only at the chosen interval.
- Scale the loss before gradient calculation so the effective update matches the intended batch size.
- Reset accumulator tensors after each optimizer step.
- Watch out for learning-rate schedules and end-of-epoch remainder batches, because accumulation changes the meaning of a training step.
Related reading
- Gradient Accumulation with Custom model.fit in TF.Keras?
- Gradient Descent vs Adagrad vs Momentum in TensorFlow
- Graph disconnected cannot obtain value for tensor Tensor
- Graph optimizations on a tensorflow serveable created using tf.Estimator
- Gradient clipping appears to choke on None
- Gradient descent convergence How to decide convergence?
- GridSearch for an estimator inside a OneVsRestClassifier
- Guided Back-propagation in TensorFlow
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack 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.