Skip to content

← Autograd Mechanics step 2 of 8

Medium Primitives

The gradient from last time

x = torch.ones(3, requires_grad=True)

(x * 2).sum().backward()
x.grad                        # [2., 2., 2.]

(x * 2).sum().backward()
x.grad                        # [4., 4., 4.]

backward adds into .grad. It does not replace it. Run a second step without clearing and the gradient is the sum of both.

Why accumulation is the default

Because it is what lets a batch be split:

optimizer.zero_grad()
for micro in split(batch):
    model(micro).mean().backward()     # each adds into p.grad
optimizer.step()

Four micro-batches produce the same gradient as one batch four times the size, using a quarter of the activation memory. If backward replaced instead of adding, this would silently train on only the last micro-batch, which is the failure mode from the memory track wearing its real clothes.

It is also what makes multi-head losses work: call backward on each loss and the gradients sum, which is what adding the losses would have done.

Clearing it

optimizer.zero_grad()                     # sets grads to None by default now
x.grad = None

None rather than zero_(): a None gradient releases the buffer, and the first backward after it allocates a fresh one. Zeroing keeps a full-size tensor per parameter alive for no reason. Modern PyTorch defaults set_to_none=True for exactly this.

It also makes “no gradient was computed” distinguishable from “the gradient was zero”, which matters when debugging a parameter that is not moving.

The bug in the wild

Forgetting zero_grad does not raise. It trains, badly: every step’s gradient carries every earlier step, so the effective learning rate grows without bound and the loss diverges after a few hundred iterations. It looks like a learning-rate problem and is not.

Your task

def grads_per_step(x: torch.Tensor, steps: int) -> list

Run steps independent backward passes of (x * 2).sum(), and return the gradient after each one. Each entry must be that step’s gradient alone, not a running total.