Machine Learning
TensorFlow
Gradient Descent
Batch Processing
Neural Networks

TensorFlow average gradients over several batches

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

Averaging gradients over several mini-batches is usually called gradient accumulation. It allows you to simulate a larger effective batch size when device memory cannot hold that batch at once. Done correctly, it improves training stability for some workloads, but incorrect scaling or reset logic can quietly break optimization.

Core Sections

Why Gradient Accumulation Is Used

Suppose your model converges better with effective batch size of 256, but your GPU fits only 64 samples. You can process four batches, accumulate gradients, average them, then apply one optimizer step.

Effective batch size formula:

  • per-step batch size times accumulation steps

Example:

  • 64 times 4 equals 256 effective batch size

This keeps memory usage near batch size 64 while updating as if using 256.

Basic TensorFlow 2 Training Loop

A clear custom loop in eager mode:

python
1import tensorflow as tf
2
3model = tf.keras.Sequential([
4    tf.keras.layers.Dense(64, activation="relu"),
5    tf.keras.layers.Dense(1)
6])
7
8optimizer = tf.keras.optimizers.Adam(1e-3)
9loss_fn = tf.keras.losses.MeanSquaredError()
10acc_steps = 4
11
12@tf.function
13def train_epoch(dataset):
14    accum = [tf.zeros_like(v) for v in model.trainable_variables]
15    step = 0
16
17    for x, y in dataset:
18        with tf.GradientTape() as tape:
19            pred = model(x, training=True)
20            loss = loss_fn(y, pred) / tf.cast(acc_steps, tf.float32)
21
22        grads = tape.gradient(loss, model.trainable_variables)
23        accum = [a + g for a, g in zip(accum, grads)]
24        step += 1
25
26        if step % acc_steps == 0:
27            optimizer.apply_gradients(zip(accum, model.trainable_variables))
28            accum = [tf.zeros_like(v) for v in model.trainable_variables]
29
30    # handle remainder batches
31    if step % acc_steps != 0:
32        optimizer.apply_gradients(zip(accum, model.trainable_variables))

Key points:

  • divide loss by accumulation steps
  • reset accumulators after apply
  • apply remainder at epoch end

Integrating with Model.fit

If you prefer fit, override train_step in a subclassed model.

python
1class AccumModel(tf.keras.Model):
2    def __init__(self, acc_steps=4, **kwargs):
3        super().__init__(**kwargs)
4        self.acc_steps = acc_steps
5        self.accum_step_counter = tf.Variable(0, trainable=False, dtype=tf.int64)
6        self.accum_grads = []
7
8    def compile(self, optimizer, loss_fn):
9        super().compile()
10        self.optimizer = optimizer
11        self.loss_fn = loss_fn
12
13    def build(self, input_shape):
14        super().build(input_shape)
15        self.accum_grads = [tf.Variable(tf.zeros_like(v), trainable=False) for v in self.trainable_variables]
16
17    def train_step(self, data):
18        x, y = data
19        with tf.GradientTape() as tape:
20            y_pred = self(x, training=True)
21            loss = self.loss_fn(y, y_pred) / tf.cast(self.acc_steps, tf.float32)
22
23        grads = tape.gradient(loss, self.trainable_variables)
24        for a, g in zip(self.accum_grads, grads):
25            a.assign_add(g)
26
27        self.accum_step_counter.assign_add(1)
28
29        if tf.equal(self.accum_step_counter % self.acc_steps, 0):
30            self.optimizer.apply_gradients(zip(self.accum_grads, self.trainable_variables))
31            for a in self.accum_grads:
32                a.assign(tf.zeros_like(a))
33
34        return {"loss": loss * tf.cast(self.acc_steps, tf.float32)}

This pattern keeps high-level training APIs while controlling update cadence.

Learning Rate and Optimizer Behavior

Accumulation changes update frequency, so learning rate may need tuning. Some teams scale learning rate with effective batch size, but this is workload dependent.

Test with:

  • same effective batch size true large batch baseline
  • accumulated batch variant
  • learning rate sweep

Also inspect optimizer state behavior, especially for adaptive optimizers.

Mixed Precision and Distributed Setup Notes

With mixed precision, gradient scaling and unscaling order matters. In distributed training, accumulation can be done per replica or after cross-replica reduction depending on strategy.

Start with single-device correctness first, then extend to distributed configuration.

Monitoring and Debugging

Track both mini-batch loss and update-step loss so training curves are interpretable. Add checks for NaN gradients before apply.

python
for g in grads:
    tf.debugging.check_numerics(g, "gradient contains invalid values")

Silent accumulation bugs are easier to catch with explicit counters and metric logging.

Common Pitfalls

  • Forgetting to divide loss by accumulation steps and applying oversized updates.
  • Resetting accumulators at wrong time and mixing gradients across update windows.
  • Ignoring remainder batches at epoch end and dropping training signal.
  • Assuming accumulation exactly equals true large-batch behavior in all optimizers.
  • Tuning learning rate for one update cadence and reusing it blindly after accumulation changes.

Summary

  • Gradient accumulation emulates larger batch training with lower memory demand.
  • Correct implementation requires scaling, reset, and remainder handling discipline.
  • Custom loops are easiest to verify, while train_step override keeps fit workflow.
  • Learning rate and optimizer dynamics should be revalidated after introducing accumulation.
  • Add explicit metrics and checks to catch silent training logic mistakes.

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.