We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Autograd Mechanics step 2 of 8
Clear gradients between independent backward passes
backward() adds to an existing .grad rather than replacing it. When each
pass should be independent, clear the previous gradient before the next pass.
import torch
x = torch.ones(3, requires_grad=True)
(x * 2).sum().backward()
print(x.grad.tolist()) # [2.0, 2.0, 2.0]
(x * 2).sum().backward()
print(x.grad.tolist()) # [4.0, 4.0, 4.0]
Each expression builds a new graph, so these are two separate backward passes.
The second result includes both contributions even though x has not changed.
When accumulation is intentional
Accumulation lets several losses contribute to one update. To reproduce the mean loss over equal-sized microbatches, divide each microbatch mean by the number of microbatches before calling backward. Otherwise, summing four means gives four times the full-batch mean gradient.
For unequal microbatch sizes, weight each mean by its share of the total examples. This equivalence assumes an additive per-example loss and consistent forward behavior; layers using batch statistics can change the result. Accumulation can reduce peak activation memory, but the saving is not a fixed fraction of total training memory.
If several losses share a graph, adding them and calling backward once is
often simplest. Separate backward calls may need retain_graph=True until
the last call so that required saved values remain available.
Clear gradients between independent passes
x.grad = None
# For parameters managed by an optimizer:
# optimizer.zero_grad(set_to_none=True)
Setting .grad to None removes that tensor's reference to the gradient
buffer. Zeroing an existing buffer is also valid, but keeps the buffer.
These choices can affect optimizer behavior: a parameter with no gradient may
be skipped, while one with a zero gradient may still receive momentum or
weight-decay updates.
Forgetting to clear gradients changes the update direction and magnitude. It can harm training, but does not imply a fixed effective learning rate or guaranteed divergence after a particular number of steps.
Your task
def grads_per_step(x: torch.Tensor, steps: int) -> list
The harness supplies a floating-point leaf tensor x with gradient tracking
enabled. Run steps independent backward passes of (x * 2).sum() and return
a list of gradient tensors, one per pass. Every entry should contain twos
with the same shape as x, rather than a running total.
For x = [1., 1.] and steps = 3, the returned values should be
[[2., 2.], [2., 2.], [2., 2.]].
Understand the ideas behind this exercise. The Problem tab contains the exact implementation requirements.
backward() adds to an existing .grad rather than replacing it. When each
pass should be independent, clear the previous gradient before the next pass.
import torch
x = torch.ones(3, requires_grad=True)
(x * 2).sum().backward()
print(x.grad.tolist()) # [2.0, 2.0, 2.0]
(x * 2).sum().backward()
print(x.grad.tolist()) # [4.0, 4.0, 4.0]
Each expression builds a new graph, so these are two separate backward passes.
The second result includes both contributions even though x has not changed.
When accumulation is intentional
Accumulation lets several losses contribute to one update. To reproduce the mean loss over equal-sized microbatches, divide each microbatch mean by the number of microbatches before calling backward. Otherwise, summing four means gives four times the full-batch mean gradient.
For unequal microbatch sizes, weight each mean by its share of the total examples. This equivalence assumes an additive per-example loss and consistent forward behavior; layers using batch statistics can change the result. Accumulation can reduce peak activation memory, but the saving is not a fixed fraction of total training memory.
If several losses share a graph, adding them and calling backward once is
often simplest. Separate backward calls may need retain_graph=True until
the last call so that required saved values remain available.
Clear gradients between independent passes
x.grad = None
# For parameters managed by an optimizer:
# optimizer.zero_grad(set_to_none=True)
Setting .grad to None removes that tensor's reference to the gradient
buffer. Zeroing an existing buffer is also valid, but keeps the buffer.
These choices can affect optimizer behavior: a parameter with no gradient may
be skipped, while one with a zero gradient may still receive momentum or
weight-decay updates.
Forgetting to clear gradients changes the update direction and magnitude. It can harm training, but does not imply a fixed effective learning rate or guaranteed divergence after a particular number of steps.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
PyTorch reference solution
Sign in to track your attempts toward unlocking the reference solution.