We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
Per-Sample Gradients with vmap
Compute one gradient vector per training example, using the same weights for every example. Keep those gradients separate instead of averaging them.
Your task
Implement per_sample_grads(w, X, y) by composing automatic differentiation
with vmap. The floating-point inputs share a dtype and device:
- w has shape
(d,)and contains the shared weights. - X has shape
(batch, d), with one example per row. - y has shape
(batch,), with one scalar target per example.
For example i, the loss is (dot(w, X[i]) - y[i])**2. Return its gradient
with respect to w in row i of a (batch, d) tensor. Preserve dtype and
device and leave all inputs unchanged. Do not update the weights.
There is no factor of 1/2 and no division by batch size in this loss:
residual[i] = dot(w, X[i]) - y[i]
gradient[i, j] = 2 * residual[i] * X[i, j]
For w=[1, 0], X=[[2, 3], [4, 5]] and y=[0, 0], residuals are
[2, 4] and the result is [[8, 12], [32, 40]]. Returning their sum or
mean would lose the separate gradient for each example.
Share the weights, map the examples
Define a scalar loss_fn(w, xi, yi) for one example. Differentiate its first
argument, w, then map that gradient function across X and y:
- PyTorch: use
torch.func.grad(loss_fn)andtorch.func.vmap(grad_fn, in_dims=(None, 0, 0))(w, X, y). - JAX: use
jax.grad(loss_fn, argnums=0)andjax.vmap(grad_fn, in_axes=(None, 0, 0))(w, X, y).
None means the whole weight vector is shared; 0 selects one example and target along their leading axes. You do not need to expand w into repeated rows. This is vectorized computation, not a request to distribute work across devices.
In the diagram, each inner call receives a (3,) weight vector, a (3,)
example and a scalar target. Its (3,) gradient becomes one row of (8, 3).
[] denotes a scalar shape. The controls illustrate axis placement rather
than checking whether arbitrary choices make a valid loss function.
Loading visualization…
Understand the ideas behind this exercise. The Problem tab contains the exact implementation requirements.
Write a function for one example, then apply it to a batch
A vectorizing transformation applies a function across chosen input axes. Suppose
f(a, b) computes the dot product of two vectors. Mapping both inputs over axis
zero pairs row 0 with row 0, row 1 with row 1, and so on. It returns one scalar
per pair, not a matrix of all possible row pairs.
An input that is not mapped is shared across the batch. To compute one gradient per training example, share the model weights and map over the inputs and labels. Keep the resulting example axis if the task asks for per-example gradients.
For scalar weight w = 1 and loss (w*x - y)^2, the gradient is
2 * (w*x - y) * x. With examples (x, y) = (2, 0) and (3, 1), the gradients
are 8 and 12. Their mean is 10, but [8, 12] is the per-example result.
Specify the mapped axes
JAX calls the input-axis argument in_axes; PyTorch's vmap calls it in_dims.
These arguments distinguish batched inputs from shared inputs. See
JAX's vectorization guide
for examples.
Vectorization does not promise execution on multiple devices. It also does not make arbitrary mutation or Python side effects work independently for each example. Data-dependent output sizes can be a problem because the results need to fit into a batch. Keep output shapes consistent and follow the transformation's supported operations.
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.