Throughout, the adjoint of a node v is written vˉ and means "how much does the final scalar output change when v wiggles a little." The rule we keep applying is the reverse-mode update: for each edge u→v,
uˉ+=vˉ⋅∂u∂v,seed fˉ=1.
Here is a small computational graph for f=(x+y)⋅z. Name the nodes, name the operations on the edges, and confirm it is a DAG (no cycles).
Recall Solution
Nodes: the inputs x,y,z; the intermediate a=x+y; the output f=a⋅z.
Edge operations:
x→a and y→a: the add operation (a=x+y).
a→f and z→f: the multiply operation (f=a⋅z).
DAG? Every edge points strictly "forward" (input → intermediate → output). You can never return to a node you left, so there are no cycles. Directed + acyclic = DAG. ✓
For f=a⋅b, write down the two local derivatives∂a∂f and ∂b∂f — the numbers autograd stores on those edges.
Recall Solution
f=a⋅b is a product. Treat the other factor as a constant:
∂a∂f=b,∂b∂f=a.Why these matter: in the backward pass the multiply edge sends aˉ+=fˉ⋅b and bˉ+=fˉ⋅a. The multiply node literally "swaps" the values.
Function with a shared input: f=sin(x)⋅(x+y) at x=1,y=2. Notice x feeds two branches. Compute xˉ and yˉ by the backward pass, and show the accumulation explicitly.
Recall Solution
Break into primitives: b=sinx, a=x+y, f=b⋅a.
Forward:
b=sin1≈0.841471
a=1+2=3
f=0.841471⋅3=2.524413
Backward:
fˉ=1.
Multiply: bˉ=fˉ⋅a=3, aˉ=fˉ⋅b=0.841471.
Path through b=sinx: xˉ+=bˉ⋅cosx=3⋅cos1=3⋅0.540302=1.620907.
Path through a=x+y: xˉ+=aˉ⋅1=0.841471.
Accumulate:xˉ=1.620907+0.841471=2.462378.
yˉ=aˉ⋅1=0.841471.
Check against the closed form∂x∂f=cosx(x+y)+sinx:
=0.540302⋅3+0.841471=2.462378 ✓.
Explain, using this same graph, why reverse mode gives bothxˉ and yˉ in one backward pass, while forward mode would need one pass per input.
Recall Solution
Reverse mode seeds the single output (fˉ=1) and propagates sensitivities backward. Every input's adjoint drops out of that one sweep — here xˉ and yˉ both. Cost ∝ number of outputs (one).
Forward mode seeds one input's perturbation (e.g. x˙=1,y˙=0) and pushes it forward to see f˙=∂f/∂x. To also get ∂f/∂y you must re-seed (x˙=0,y˙=1) and run again. Cost ∝ number of inputs.
For a loss (one output, many weights), reverse mode wins massively. See Automatic differentiation (forward vs reverse mode).
Answers:∂L/∂w≈−0.147136,∂L/∂b≈−0.073568,∂L/∂x≈−0.036784.
Interpretation: all negative → increasing w,b,xdecreases the loss, so a Gradient descent step (which subtracts the gradient) would increase them. Makes sense: y^<t, we want z bigger.
Take one gradient-descent step on w with learning rate η=0.1, using wˉ from 4.1. Compute the new w.
Recall Solution
Update rule: w←w−ηwˉ.
wnew=0.5−0.1⋅(−0.147136)=0.5+0.0147136=0.5147136.w increased, exactly the direction that pushes y^ toward t=1. See Loss functions and Gradient descent.