A model makes a prediction, and a loss function measures how far that prediction is from the desired output. Backpropagation works backward from that loss to find how changing each model parameter would change it. Those gradients guide parameter updates intended to reduce the loss. section 5.2 section 5.5
PyTorch’s autograd handles the derivative calculations. Set `requires_grad=True` on a parameter tensor, compute a loss from it, and call `loss.backward()`. PyTorch records the differentiable operations used to produce the loss, traverses that computation graph in reverse, and places the resulting derivatives in the parameter tensor’s `.grad` attribute. section 5.5.1
Get gradients for a two-parameter model
With input `t_u` and target `t_c`, define `model(t_u, w, b)` as `w * t_u + b` and let `loss_fn` return mean squared error. Then run `params = torch.tensor([1.0, 0.0], requires_grad=True)`, `loss = loss_fn(model(t_u, *params), t_c)`, and `loss.backward()`. Now `params.grad` contains one loss derivative for each parameter; in the worked calculation it is `tensor([4517.2969, 82.6000])`. Calling `backward()` computes gradients—it does not itself update `params`. section 5.5.1
A training loop uses those gradients in this order:
- Clear gradients left from earlier backward calls, using `params.grad.zero_()` for the manual update or `optimizer.zero_grad()` with an optimizer. Backward calls accumulate gradients rather than replace them. section 5.5.1 section 5.5.5
- Run the model, calculate the training loss, and call `train_loss.backward()`. section 5.5.5
- Update the parameters, either manually inside `torch.no_grad()` or with `optimizer.step()`. Then repeat with a new forward pass and loss. section 5.5.1 section 5.5.5
Keep validation separate: call `backward()` on the training loss, not the validation loss. The two losses have separate computation graphs, but their graphs share parameters; backpropagating both would add validation gradients to the same parameters. Validation can run inside `torch.no_grad()` so its graph is not created. section 5.5.5
# In[9]:
def training_loop(n_epochs, learning_rate, params, t_u, t_c):
for epoch in range(1, n_epochs + 1):
if params.grad is not None: #1
params.grad.zero_()
t_p = model(t_u, *params)
loss = loss_fn(t_p, t_c)
loss.backward()
with torch.no_grad(): #2
params -= learning_rate * params.grad
if epoch % 500 == 0:
print('Epoch %d, Loss %f' % (epoch, float(loss)))
return params
The complete manual training loop shows gradient clearing, the forward and backward passes, and a parameter update outside gradient tracking. section 5.5.1
The same backward step matters in data-parallel training. Each device computes gradients from its own data shard; gradients must be aggregated before the optimizer step so the model copies do not diverge. section 16.3
















