TensorTau PathToAGI Mathematics of Change Level 02

Level 02 · Mathematics of Change · Chapter 022

Computational Graphs: Turning Formulas Into Data Flow

How can we break a complicated function into tiny local operations so that both the forward calculation and the backward flow of derivatives become mechanical?

Where We Are

Chapter 021 gave us the chain rule.

If

y=f(g(x)),y=f(g(x)),

then

dydx=dydgdgdx.\frac{dy}{dx} = \frac{dy}{dg}\frac{dg}{dx}.

That solves the mathematics of composition.

But a neural network is not a neat two-function composition.

It may contain millions of operations:

input
 → matrix multiply
 → bias add
 → activation
 → matrix multiply
 → activation
 → ...
 → prediction
 → loss

Writing one giant symbolic formula becomes impossible to reason about.

We need a representation that remembers what was computed from what.

That representation is a computational graph.


1. The Problem: One Formula Can Hide Many Operations

Consider

L=(wx+b−y)2.L=(wx+b-y)^2.

It looks like one expression.

But a computer cannot perform “the whole formula” in one magical step.

It performs small operations:

  1. multiply ww and xx,
  2. add bb,
  3. subtract yy,
  4. square the result.

Name the intermediate values:

a=wx,a=wx, z=a+b,z=a+b, e=z−y,e=z-y, L=e2.L=e^2.

Now the hidden structure is visible.


2. Draw the Forward Graph

w ──┐
    × ── a ──┐
x ──┘        + ── z ──┐
             b        - ── e ── square ── L
                      y

Every node is either:

  • an input/value,
  • an operation,
  • an intermediate result.

Every arrow means:

this value is used to compute that value.

The graph is a map of dependency.


3. Why Name Intermediate Values?

Suppose

w=2,x=3,b=1,y=10.w=2, \quad x=3, \quad b=1, \quad y=10.

Forward pass:

a=wx=2(3)=6,a=wx=2(3)=6, z=a+b=6+1=7,z=a+b=6+1=7, e=z−y=7−10=−3,e=z-y=7-10=-3, L=e2=9.L=e^2=9.

The graph lets us store these values:

a = 6
z = 7
e = -3
L = 9

Later the backward pass will reuse them.

This is exactly what autodiff systems do internally.


4. Local Derivatives

Each operation knows only its own derivative.

For multiplication

a=wx,a=wx,

local derivatives are

∂a∂w=x,\frac{\partial a}{\partial w}=x, ∂a∂x=w.\frac{\partial a}{\partial x}=w.

For addition

z=a+b,z=a+b, ∂z∂a=1,\frac{\partial z}{\partial a}=1, ∂z∂b=1.\frac{\partial z}{\partial b}=1.

For subtraction

e=z−y,e=z-y, ∂e∂z=1,\frac{\partial e}{\partial z}=1, ∂e∂y=−1.\frac{\partial e}{\partial y}=-1.

For squaring

L=e2,L=e^2, dLde=2e.\frac{dL}{de}=2e.

No node needs to understand the entire network.

Each node only knows its own small rule.


5. Backward Pass as Chain Rule on the Graph

Start from the loss.

A quantity always changes one-for-one with itself:

dLdL=1.\frac{dL}{dL}=1.

Now move backward.

At the square node:

dLde=2e.\frac{dL}{de}=2e.

With

e=−3,e=-3, dLde=−6.\frac{dL}{de}=-6.

At subtraction:

dLdz=dLderacdedz=(−6)(1)=−6.\frac{dL}{dz} = \frac{dL}{de} rac{de}{dz} =(-6)(1) =-6.

At addition:

dLda=dLdzracdzda=(−6)(1)=−6.\frac{dL}{da} = \frac{dL}{dz} rac{dz}{da} =(-6)(1) =-6.

Finally through multiplication:

dLdw=dLdaracdadw=(−6)(x).\frac{dL}{dw} = \frac{dL}{da} rac{da}{dw} =(-6)(x).

Since x=3x=3:

dLdw=−18\boxed{ \frac{dL}{dw}=-18 }

Exactly as expected.


6. The “Upstream × Local” Rule

At every node, the pattern is the same:

gradient passed backward=upstream gradient×local derivative\boxed{ \text{gradient passed backward} = \text{upstream gradient} \times \text{local derivative} }

For example, at

a=wx,a=wx,

if upstream gradient is

dLda,\frac{dL}{da},

then

dLdw=dLdadadw.\frac{dL}{dw} = \frac{dL}{da} \frac{da}{dw}.

This one pattern becomes the operational heart of backpropagation.


7. A Tempting Wrong Idea: Differentiate the Giant Formula Every Time

We could expand

L=(wx+b−y)2L=(wx+b-y)^2

and differentiate symbolically from scratch.

For a tiny expression, that is fine.

For a 100-layer network, it is disastrous.

Why?

Because the same intermediate calculations are reused throughout the network.

A computational graph exposes reuse and lets us apply small derivative rules locally.

A Tempting Wrong Idea

“Backpropagation means finding one enormous derivative formula for the whole network.”

No. Backpropagation is efficient because it avoids doing that. It reuses local derivatives and previously computed upstream gradients.


8. Branches: One Value Can Affect the Loss in Multiple Ways

Consider

f(x)=x2+x3.f(x)=x^2+x^3.

The input x branches into two paths:

       ┌─ square ─┐
x ─────┤          + ── f
       └─ cube ───┘

Derivative through first branch:

2x.2x.

Through second:

3x2.3x^2.

Total derivative:

dfdx=2x+3x2\boxed{ \frac{df}{dx}=2x+3x^2 }

When a value influences the output through multiple paths, contributions add.

This is crucial in real networks with branching, residual connections and parameter reuse.


9. Why Gradient Contributions Add at Branches

Suppose

y=u(x)+v(x).y=u(x)+v(x).

Then

dydx=dudx+racdvdx.\frac{dy}{dx} = \frac{du}{dx}+ rac{dv}{dx}.

If x affects loss through multiple downstream paths, total sensitivity is the sum of all path sensitivities.

This gives the graph rule:

multiply along a path; add across alternative paths.

That sentence is worth remembering.


10. Example With a Branch

Let

a=x2,a=x^2, b=3x,b=3x, y=a+b.y=a+b.

At x=2x=2:

Forward:

a=4,a=4, b=6,b=6, y=10.y=10.

Backward:

dyda=1,dydb=1.\frac{dy}{da}=1, \qquad \frac{dy}{db}=1.

Path through a:

1⋅dadx=1⋅2x=4.1\cdot\frac{da}{dx} =1\cdot2x =4.

Path through b:

1⋅dbdx=1⋅3=3.1\cdot\frac{db}{dx} =1\cdot3 =3.

Add:

dydx=4+3=7.\frac{dy}{dx}=4+3=7.

Direct derivative confirms:

ddx(x2+3x)=2x+3=7.\frac{d}{dx}(x^2+3x)=2x+3=7.

11. Topological Order

A graph has dependencies.

You cannot compute a node before its inputs exist.

So forward evaluation must respect dependency order.

For

x → a → c
 \→ b ↗

we must compute:

  1. x,
  2. a and b,
  3. c.

This is a topological ordering of a directed acyclic graph (DAG).

Backward propagation uses the reverse topological order.

That is not accidental.

To know a node’s total influence on loss, we must first know the gradients arriving from everything downstream.


12. Why Neural Computation Is Usually a DAG

During one ordinary feed-forward evaluation, values flow forward without cycles:

inputs → hidden values → outputs → loss

That creates a directed acyclic graph.

Recurrent networks may represent repeated-time computation, but when unrolled across a finite sequence they also form a DAG for differentiation.

Autodiff engines exploit this structure.


13. Computational Graph vs Neural-Network Architecture Diagram

These are related but not identical.

A high-level architecture diagram may show:

Linear → ReLU → Linear

A computational graph can be much more detailed:

x
↓
matmul W1
↓
add b1
↓
ReLU
↓
matmul W2
↓
add b2
↓
loss

And underneath matrix multiplication itself are many scalar multiplications and additions.

The level of detail depends on what derivative rules the system treats as primitive.


14. Scalar Graph vs Tensor Graph

For teaching, scalar graphs are easiest.

Real frameworks operate on tensors.

A node may represent

Z=XW+bZ=XW+b

rather than one scalar multiply.

Its backward rule returns tensor gradients:

dX,dW,db.dX, \quad dW, \quad db.

The conceptual graph is identical:

X ─┐
W ─┼─ Linear ─ Z
b ─┘

Only the local derivative rule becomes matrix calculus instead of scalar calculus.


15. Shape Check on the Graph

Suppose

X:(B,d),X:(B,d), W:(d,h),W:(d,h), b:(h,).b:(h,).

Then

Z=XW+bZ=XW+b

has shape

(B,h).(B,h).

If loss L is scalar, backward gradients must align with the quantities they belong to:

dL/dZ  → (B,h)
dL/dW  → (d,h)
dL/db  → (h,)
dL/dX  → (B,d)

Computational graphs are also shape-flow graphs.


16. Forward Values and Backward Gradients Are Different Things

At every graph node, keep two mental boxes.

Forward value

What numerical value did this operation produce?

Backward gradient

How sensitive is the final loss to this node’s value?

For node z:

forward:  z
backward: dL/dz

Confusing these is a common source of backprop mistakes.


17. Why We Cache Forward Values

Suppose

y=x2.y=x^2.

Backward rule needs

dydx=2x.\frac{dy}{dx}=2x.

So during backward, we need the original x.

For sigmoid or softmax, backward may also reuse forward outputs.

Frameworks therefore store enough intermediate information from the forward pass to compute backward efficiently.

This stored information consumes memory.

That is why training often needs much more memory than inference.


18. Memory vs Compute Tradeoff

If we store every intermediate activation, backward is fast but memory-heavy.

If we discard some and recompute them later, memory decreases but compute increases.

This tradeoff appears in techniques such as activation checkpointing.

Even advanced training systems are still negotiating the simple graph question:

Which forward values should I remember for backward?


19. Reverse-Mode Automatic Differentiation Preview

Suppose a function has millions of inputs/parameters but one scalar loss.

We want

∂L∂θ1,…,∂L∂θn.\frac{\partial L}{\partial\theta_1}, \ldots, \frac{\partial L}{\partial\theta_n}.

Reverse-mode autodiff starts from the one scalar output and propagates sensitivities backward through the graph.

This computes all parameter gradients efficiently in roughly a small multiple of the forward-pass work.

That is why reverse mode is ideal for neural-network training.


20. Forward-Mode vs Reverse-Mode Intuition

Imagine function

f:Rn→Rm.f:\mathbb R^n\to\mathbb R^m.

Forward mode

Track how one chosen input perturbation affects everything downstream.

Good when number of inputs is small.

Reverse mode

Start from one chosen output sensitivity and propagate backward to all inputs.

Good when outputs are few—especially scalar loss.

Deep learning usually has:

millions/billions of parameters → one scalar loss

So reverse mode is the natural fit.


21. A Full Scalar Graph by Hand

Use

x=2,w=3,b=1,y=8.x=2, \quad w=3, \quad b=1, \quad y=8.

Define

a=wx,a=wx, z=a+b,z=a+b, e=z−y,e=z-y, L=e2.L=e^2.

Forward

a=6,a=6, z=7,z=7, e=−1,e=-1, L=1.L=1.

Backward seed

dLdL=1.\frac{dL}{dL}=1.

Square

dLde=2e=−2.\frac{dL}{de}=2e=-2.

Subtract

dLdz=−2,\frac{dL}{dz}=-2, dLdy=(−2)(−1)=2.\frac{dL}{dy}=(-2)(-1)=2.

Add

dLda=−2,\frac{dL}{da}=-2, dLdb=−2.\frac{dL}{db}=-2.

Multiply

dLdw=(−2)x=−4,\frac{dL}{dw}=(-2)x=-4, dLdx=(−2)w=−6.\frac{dL}{dx}=(-2)w=-6.

One graph gives every local sensitivity we care about.


22. Verify the Final Gradients Directly

Original loss:

L=(wx+b−y)2.L=(wx+b-y)^2.

Differentiate directly:

∂L∂w=2(wx+b−y)x.\frac{\partial L}{\partial w} =2(wx+b-y)x.

At our values:

2(−1)(2)=−4.2(-1)(2)=-4.

Matches the graph.

Similarly:

∂L∂b=2(wx+b−y)=−2.\frac{\partial L}{\partial b} =2(wx+b-y)=-2.

Again matches.

The computational graph did not invent new calculus.

It organized the chain rule so we could apply it locally and systematically.


23. A Tempting Wrong Idea: Gradients “Move” Backward as Numbers Only

It is common to visualize gradients flowing backward like water.

Useful—but incomplete.

At every edge, the upstream sensitivity is transformed by the local derivative.

So backward propagation is not merely passing a number backward unchanged.

It is repeated multiplication, matrix multiplication, broadcasting reduction, masking, and accumulation according to local operation rules.

The graph tells us which rule applies where.


24. Stop-Gradient / Detach Intuition

Sometimes we intentionally do not want gradients to flow through one edge.

Conceptually, we cut that dependency for differentiation.

Frameworks expose operations such as detach or stop-gradient mechanisms.

Forward values can still be used, but backward sensitivity does not propagate through that path.

This is useful in many advanced algorithms.

The graph picture makes the idea immediately understandable: forward edge exists; derivative edge is blocked.


25. In-Place Mutation Can Break the Story

Suppose a backward rule needs an earlier forward value x.

If code overwrites x in place before backward, the graph may no longer have the information required to compute correct gradients.

Modern frameworks track such issues carefully.

This is why some in-place tensor operations interact badly with autograd.

Again, the underlying reason is not framework superstition.

The backward graph needs specific saved values.


26. Code: Tiny Manual Graph

x = 2.0
w = 3.0
b = 1.0
y = 8.0

# forward
a = w * x
z = a + b
e = z - y
loss = e ** 2

# backward
dloss_dloss = 1.0
dloss_de = dloss_dloss * (2 * e)
dloss_dz = dloss_de * 1.0
dloss_da = dloss_dz * 1.0
dloss_db = dloss_dz * 1.0
dloss_dw = dloss_da * x
dloss_dx = dloss_da * w

assert loss == 1.0
assert dloss_dw == -4.0
assert dloss_db == -2.0
assert dloss_dx == -6.0

This is backpropagation without a framework.


27. The Graph as a Debugging Tool

When a gradient is wrong, inspect the path.

Ask:

  1. What forward value entered this node?
  2. What local derivative should this operation have?
  3. What upstream gradient arrived?
  4. Were multiple downstream contributions added?
  5. Are tensor shapes compatible?
  6. Was a value broadcast in forward and therefore reduced in backward?

This turns “backprop feels magical” into local bookkeeping.


28. Machine-Learning Connection — Residual Networks

A residual block contains a skip path:

x ───────────────┐
│                + ── output
└→ F(x) ─────────┘

Backward gradients can travel through both paths.

Their contributions add at x.

The graph perspective makes the derivative structure obvious and helps explain why skip connections improve gradient flow.

We will return to this in Chapter 102.


29. Machine-Learning Connection — Shared Parameters

Suppose the same weight is used at several places in a model.

The graph contains multiple downstream paths from that parameter to the loss.

Its total gradient is the sum of contributions from every use.

This is common in:

  • recurrent networks,
  • convolution kernels,
  • tied embeddings,
  • repeated modules.

Parameter sharing therefore relies on gradient accumulation over graph branches.


30. History Lens — From Symbolic Differentiation to Automatic Differentiation

Automatic differentiation is distinct from both symbolic differentiation and numerical finite differences.

It exploits the fact that computer programs are compositions of elementary operations with known derivatives.

By recording those operations as a graph and systematically applying the chain rule, derivatives can be computed to machine precision with predictable cost.

Reverse-mode automatic differentiation became especially important for neural networks because one scalar objective depends on enormous numbers of parameters.

Backpropagation is the neural-network specialization of this broader idea.


31. Distinctions That Matter

PairDifference
formula vs computational graphcompact mathematical expression vs explicit dependency structure
forward value vs backward gradientcomputed quantity vs loss sensitivity to that quantity
local derivative vs total derivativeone operation’s rule vs all downstream effects
multiply along path vs add across pathschain rule vs branch accumulation
symbolic differentiation vs autodiffmanipulate formulas vs execute derivative rules on program operations
numerical differentiation vs autodiffapproximate via perturbations vs exact chain-rule propagation up to floating-point arithmetic
forward mode vs reverse modepropagate input tangent forward vs output sensitivity backward

32. What We Discovered

  1. Complex expressions can be decomposed into small operations.
  2. A computational graph records dependency between values.
  3. Forward pass computes and often stores intermediate values.
  4. Each operation needs only a local derivative rule.
  5. Backward pass repeatedly uses “upstream gradient × local derivative.”
  6. Gradients multiply along a path.
  7. Contributions add when a value reaches the loss through multiple paths.
  8. Forward uses topological order; reverse mode uses reverse topological order.
  9. Reverse-mode autodiff is ideal for many parameters and one scalar loss.
  10. Tensor computational graphs use the same logic with matrix/tensor local rules.
  11. Graph structure explains gradient accumulation, detach, activation memory and checkpointing.
  12. This graph machinery is the operational foundation of backpropagation and autograd.

33. One-Minute Explanation

A computational graph rewrites a complicated formula as a network of small operations. During the forward pass, values move from inputs toward the loss. During the backward pass, each node receives an upstream sensitivity, multiplies it by its local derivative, and passes the result toward its inputs. If one value affects the loss through multiple paths, those gradient contributions add. This is just the chain rule organized as a graph, but that organization is what makes automatic differentiation and backpropagation practical for enormous neural networks.


34. Mastery Check

  1. Draw a computational graph for (wx+b−y)2(wx+b-y)^2.
  2. What is the difference between a node’s forward value and backward gradient?
  3. Explain “upstream × local.”
  4. Why do gradient contributions add at branches?
  5. Why must forward execution respect topological order?
  6. Why does backward run in reverse dependency order?
  7. Why is reverse-mode autodiff a good fit for neural networks?
  8. What information may need to be cached during forward?
  9. Why can activation checkpointing trade compute for memory?
  10. How does parameter sharing affect gradient accumulation?
  11. How is autodiff different from finite-difference numerical differentiation?
  12. Why is a computational graph more useful than one giant symbolic derivative for deep networks?

🔭 Bridge to Chapter 023

We now know:

  • what a gradient is,
  • how the chain rule propagates sensitivity,
  • how a computational graph organizes the calculation.

But computing the gradient is not yet learning.

A gradient only tells us the local uphill direction.

We still need an update rule that repeatedly changes parameters and actually reduces loss.

How do we turn gradients into a learning algorithm?

That question leads to gradient descent.

Six ways to work the chapter, climbing from explaining it in your own words to investigating it like a researcher. Reading is not enough — this is where the chapter lands.

Level 1 — Explain It

  1. Explain a computational graph without using the words “autograd” or “backpropagation.”
  2. Why are intermediate values useful?
  3. What is the difference between a local derivative and a total derivative to the loss?
  4. Explain “multiply along paths, add across paths.”
  5. Why is reverse-mode differentiation a natural fit for a scalar loss with millions of parameters?

Level 2 — Calculate It

Use

a=wx,z=a+b,e=z−y,L=e2a=wx, \quad z=a+b, \quad e=z-y, \quad L=e^2

with

w=3
x=2
b=1
y=8

Calculate by hand:

  1. every forward value,
  2. dL/dedL/de,
  3. dL/dzdL/dz,
  4. dL/dadL/da,
  5. dL/dbdL/db,
  6. dL/dwdL/dw,
  7. dL/dxdL/dx.

Then differentiate the original compact formula directly and verify the results.

Level 3 — Draw It

Draw computational graphs for:

  1. y=x2+3xy=x^2+3x
  2. y=(a+b)cy=(a+b)c
  3. L=(wx+b−y)2L=(wx+b-y)^2
  4. y=ReLU⁡(wx+b)y=\operatorname{ReLU}(wx+b)

For every operation node, write its local derivative rule.

Level 4 — Branching

For

y=x2+x3,y=x^2+x^3,
  1. draw both paths from x to y,
  2. compute each path contribution,
  3. add them,
  4. verify against direct differentiation.

Explain exactly why adding is necessary.

Level 5 — Break It

A. Forget one branch

Intentionally backpropagate through only one path of x2+x3x^2+x^3. Compare the wrong gradient with the correct one.

B. Pass upstream gradient unchanged

At a squaring node, pretend the local derivative is 1. Show the incorrect result and explain what information was lost.

C. Wrong execution order

Try to compute a downstream node before one of its dependencies. Explain why topological ordering is not optional.

D. Destroy a cached value

Construct an example where the backward rule needs the original forward input. Overwrite it before backward and explain why the derivative cannot be reconstructed reliably.

Level 6 — Build a Tiny Scalar Graph Engine

Create a tiny Value class storing:

value
parents
local backward rule
grad

Support at least:

  • addition,
  • multiplication,
  • subtraction,
  • power of 2.

Requirements:

  1. build a topological ordering,
  2. run forward naturally through operator calls,
  3. seed final output gradient with 1,
  4. traverse in reverse topological order,
  5. accumulate gradients with += when branches meet.

Verify on

L=(wx+b−y)2.L=(wx+b-y)^2.

Investigation — Forward Mode vs Reverse Mode

Take a function with 20 scalar inputs and one scalar output.

Reason about how many separate derivative sweeps would be needed to obtain the complete gradient using:

  • one-input-at-a-time forward mode,
  • one-output reverse mode.

Then reverse the shape: one scalar input and 20 outputs.

Explain why the preferred mode changes with input/output dimensionality.

Tensor Shape Preview

Suppose

X: (32, 10)
W: (10, 64)
b: (64,)
Z = X @ W + b
loss: scalar

Predict:

Z       → ______
dL/dZ   → ______
dL/dW   → ______
dL/db   → ______
dL/dX   → ______

Do not derive the matrix formulas yet; just reason from what each gradient belongs to.

Mastery Gate

Do not continue until you can answer:

  • What does a computational graph record?
  • What is the forward pass?
  • What is the backward pass?
  • What does “upstream gradient × local derivative” mean?
  • Why do branches require gradient accumulation?
  • Why is reverse topological order required?
  • Why can training consume more memory than inference?
  • Why is reverse mode ideal for scalar-loss neural networks?
  • How does this representation prepare us for gradient descent, backpropagation and autograd?