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 over several smaller batches before applying an optimizer step. In TF.Keras, the cleanest way to keep model.fit while adding this behavior is to subclass keras.Model and override train_step.
Why Gradient Accumulation Helps
Suppose your GPU can only hold a batch size of 8, but you want the optimization behavior of batch size 32. You can process four micro-batches of 8, accumulate their gradients, and then update the weights once.
That gives an effective batch size of:
micro_batch_size * accumulation_steps
This is useful when:
- memory limits prevent a larger real batch
- training is noisy with very small batches
- you want to preserve the
fitAPI, callbacks, and metrics
Custom train_step Approach
The main idea is:
- compute gradients for each micro-batch
- add them into accumulation buffers
- apply the average or summed gradients every
Nsteps - reset the buffers
A compact implementation looks like this:
This keeps the familiar fit workflow.
Using It With fit
With batch_size=8 and accumulation_steps=4, the optimizer updates as if the effective batch were 32.
Important Detail: Final Partial Accumulation
If the epoch ends before the accumulation counter reaches the exact step boundary, you may have leftover gradients that were never applied. In production code, handle that carefully by flushing remaining accumulated gradients at epoch end or designing dataset size and step count so the remainder is acceptable.
Loss Scaling and Metrics
A common choice is to divide accumulated gradients by accumulation_steps before applying them. That keeps the update magnitude comparable to a real larger batch.
Metrics usually update every micro-batch, which is fine for most training dashboards. The main thing to be consistent about is the optimizer step schedule, not the UI frequency.
Distributed Training Considerations
Gradient accumulation is different from distributed data parallelism. If you later combine it with strategies such as tf.distribute.MirroredStrategy, think carefully about where gradients are already being reduced and how many samples each update truly represents.
Common Pitfalls
A common mistake is applying gradients every batch and still calling it gradient accumulation. If the optimizer steps every micro-batch, you are not accumulating.
Another mistake is forgetting to divide by accumulation_steps, which changes the effective learning rate.
Developers also often overlook the leftover-gradient case at the end of an epoch, which can silently skip updates.
Summary
- Gradient accumulation simulates a larger batch using smaller micro-batches.
- In TF.Keras, overriding
train_stepis the cleanest way to keepmodel.fit. - Accumulate gradients for
Nsteps, then apply them once. - Scale accumulated gradients if you want behavior closer to a true larger batch.
- Handle leftover gradients at epoch boundaries deliberately.
Related reading
- Gradient clipping appears to choke on None
- Guided Back-propagation in TensorFlow
- Heroku deploying Deep Learning model
- High bias convolutional neural network not improving with more layers/filters
- Gradient Descent vs Adagrad vs Momentum in TensorFlow
- Graph disconnected cannot obtain value for tensor Tensor
- Gradient descent convergence How to decide convergence?
- Gradient Descent for Linear Regression Exploding
.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.