Concepts / Leaf Nodes and the Computation Graph

Leaf Nodes and the Computation Graph

Calling .backward on the loss computes gradients for the leaf nodes of the graph, so you do not need to derive them by hand.

  • Programming

Why You Rarely Compute Gradients by Hand

Up to this point, gradients have been computed by calling the grad function directly. That approach is useful for experimenting, for debugging, and for showing the underlying ideas. In practice, though, PyTorch offers a higher-level tool that does the work for you. This article starts with the code that uses that tool and then explains what happens when the code runs.

Imagine a loss value that has already been computed from a model's parameters, where the parameters w1 and b are tensors. A short program calls backward on the loss and then prints the gradients that PyTorch stored for two of those parameters. Notice that the program never writes a derivative formula. The only calculus step in it is the single call to backward. The calculus is still happening underneath; you simply no longer write it out yourself.

What do you think happens?

Before backward() has been called on the loss, what does the .grad attribute of the parameter w1 hold?

Reveal answer
Answer:

No gradient has been computed for w1 yet, so there is no gradient value to read from its .grad attribute.

Gradients are stored in each leaf tensor's .grad attribute when backward runs. Until that call happens, the gradient has not been computed, so there is nothing to read.

Following the Gradient Back from the Loss

The forward pass builds a computation graph: the loss was produced by a sequence of operations, and each operation links its inputs to its output. Calling backward on the loss starts at the loss and traverses that graph in reverse. The traversal reaches the leaf nodes, which are the tensors the graph was built from, such as the parameters w1 and b. Gradients are computed for all of these leaf nodes at once.

lossresult of forward passbackward()called on the losscomputation graphtraversed in reversew1leaf nodew1.gradgradient stored herebleaf nodeb.gradgradient stored herecalltraversesreaches leafreaches leafgradient receivedgradient received
After the forward pass builds the graph, the gradient travels backward from the loss, through the graph, and lands on each leaf tensor, where it is stored in that tensor's .grad attribute.

Read the diagram from top to bottom. The path starts at the loss, and the backward call moves through the graph until it reaches the leaf nodes. Each leaf node receives its gradient, and that gradient becomes available through the matching .grad attribute. The parameters w1 and b are the places where the values finally land. You do not have to follow the chain of calculus steps yourself; the traversal handles it.

Leaf Nodes Versus Intermediate Results

Definition

A leaf node is a tensor that the graph was built from, such as a parameter like w1 or b, rather than a value produced by an intermediate operation. Intermediate results are the values created along the way during the forward pass.

The distinction matters because the important detail is which tensors receive gradients. Calling backward on the loss computes gradients for the leaf nodes. The intermediate results sit between the leaves and the loss, and the gradients you read come from the leaves. This is why you read gradients from parameters like w1 and b and not from every value that appeared during the computation.

Tensor roleWhere it comes fromDoes it receive a .grad from backward on the loss?
Leaf node (for example w1 or b)A tensor the graph was built fromYes, gradients are computed for it
Intermediate resultA value produced by an intermediate operation in the forward passNot the target of the stored gradients described here

Leaf nodes versus intermediate results in the computation graph

The .grad Attribute Before and After backward

Each leaf tensor has its own .grad attribute, and that is where its gradient is stored. The gradient for a given parameter is looked up directly from that parameter. Before backward runs, the attribute holds no computed gradient. After backward finishes, the attribute holds the gradient that PyTorch computed for that leaf.

w1.gradno gradient computed yetw1.gradgradient value storedb.gradno gradient computed yetb.gradgradient value storedbackward()backward()
What the .grad attribute of w1 contains before and after the backward call on the loss.

The source output shows one gradient value for w1 and one for b. Those are the values you read from the two .grad attributes after the backward call. Reading them is the only step you perform; the computation was done when backward ran.

Layers of a Multilayer Perceptron

The source moves from gradients to a concrete network that PyTorch is often used to build: the multilayer perceptron. A multilayer perceptron is a fully connected neural network with multiple hidden layers between its input and output layers. Fully connected means that the units in one layer connect to the units in the next layer.

Input layerreceives the input valuesHidden layer 1fully connected to inputHidden layer 2fully connected to layer 1Output layerproduces the network outputconnects toconnects toconnects to
Data moves from the input layer, through two hidden layers, to the output layer. Each layer's units connect to the units of the next layer.

The source illustrates this structure with two hidden layers. Each node in its drawing stands for one unit in its layer, and the drawing uses very few nodes per layer so the structure is easy to see. The input layer is where data enters, the hidden layers sit between input and output, and the output layer is where the network produces its result. The source does not specify exactly which layer each named parameter such as w1 or b belongs to, so this article does not assign them to specific layers.

Checking Gradients When One Is Missing

When a gradient is missing or unexpected, the source suggests checking three things: the call order, whether the tensor is a leaf node, and which loss was differentiated.

  • Common mistake

    Reading .grad before calling backward

    Why it fails

    The gradient is stored in .grad only when backward runs, so reading earlier gives you no computed value.

    Do this instead

    Call backward on the loss first, then read the .grad attribute.

  • Common mistake

    Expecting a gradient from a tensor that is not a leaf node

    Why it fails

    Calling backward computes gradients for the leaf nodes of the graph, not for every intermediate result.

    Do this instead

    Check whether the tensor is a leaf node such as a parameter like w1 or b before looking for its gradient.

  • Common mistake

    Differentiating a different loss than the one you intended

    Why it fails

    The gradients stored in .grad come from the loss that backward was called on.

    Do this instead

    Confirm that backward was called on the loss you meant to optimize.

Predicting Which Gradients Appear

EASY

A loss is computed from parameters w1 and b, and an intermediate result is created along the way during the forward pass. After calling backward on the loss, which tensors should have a gradient value in their .grad attribute, and where would you look to read each one?

Hints
  • Ask which tensors are leaf nodes of the graph.
  • Remember where gradients are stored: in each leaf tensor's .grad attribute.

Key Takeaways

  • Calling backward on the loss computes gradients for the leaf nodes of the computation graph, so you do not need to derive them by hand.
  • A leaf node is a tensor the graph was built from, such as w1 or b; gradients are stored in each leaf tensor's .grad attribute, which is where you read them.
  • Before backward runs, the .grad attributes hold no computed gradient; after it finishes, the leaf tensors' .grad attributes hold their gradients.
  • A multilayer perceptron is a fully connected network with hidden layers between its input and output layers.
  • When a gradient is missing, check the call order, whether the tensor is a leaf node, and which loss was differentiated.

Related concepts

More concepts starting with L