🌏 中文版
Video status: Videos included. Video source and notes
Edition: based on MIT 6.7960 Fall 2024 OCW (OCW Lec 02, How to Train a Neural Net, taught by Sara Beery). This post is written from the official OCW transcript and slides. The transcript has no timestamps, so references point to content rather than times.
The Question This Lecture Answers
Anyone who has written PyTorch has called loss.backward(), but many cannot say why it is affordable: how does one backward sweep through a network with hundreds of millions of parameters return a gradient for every one of them?
Lecture 2 of MIT 6.7960 gives a plain answer. Sara Beery says in class that backpropagation is "basically an efficiency trick": once you expand the chain rule, the gradient expressions for different layers share a long common factor, and backprop computes that factor once.
After this post you should be able to:
- Say why a given loss landscape is hard to train on, and which remedy applies.
- Write the forward, backward and weight-update equations for a linear layer and the backward rule for ReLU, with the shape of every quantity.
- Compute gradients by hand on any directed acyclic graph, including shared parameters.
Prerequisites are the chain rule and matrix multiplication. The lecture assumes you have seen the multilayer perceptron from Lecture 1.
Gradient Descent, SGD and Momentum
Training searches for parameters that minimize the total loss over the training set. There are only three things we can do with : evaluate it, evaluate its gradient, and evaluate its Hessian. In practice we almost always stop at the first two, which is first-order optimization:
is the learning rate. When the landscape is not convex, the point you reach may be only a local minimum, and you usually do not know how far it is from the global one.
With millions or billions of examples, a gradient over all the data is too slow, so we approximate it with the gradient over a small batch. That is stochastic gradient descent (SGD). A batch size of 1 updates after every example; a batch size equal to the dataset is ordinary gradient descent.
The trade-offs Beery lists:
| Advantages | Faster; small batches already approximate the full gradient; the noise is an implicit regularizer that can bounce you out of local minima |
| Disadvantages | High variance, unstable updates |
She adds an observation from her own experiments: the more imbalanced the classes, the less stable SGD is. A rare class can be absent for several batches in a row, and when it appears it shifts the gradient sharply.
Momentum biases each step toward the direction of the previous one, the way a heavy object gains speed rolling downhill. Its strength is a hyperparameter. In the classroom demo, momentum 0 rolls steadily to the minimum; 0.5 gets there in about half the steps; too much overshoots and oscillates, and ends up slower. For intuition she recommends Gabriel Goh's interactive 2017 article Why Momentum Really Works.
Six Loss Landscapes: Differentiable Does Not Mean Trainable
The lecture shows six one-dimensional loss landscapes and asks three questions. The answers separate "differentiable" from "easy to optimize":
- Which are differentiable? Only the smooth bowl and the nearly flat one.
- Which have defined gradients in PyTorch? All of them. Autograd gives a directional derivative even next to a discontinuity.
- Which are hard to optimize? This is the question that matters.
| Landscape | Problem | Remedy given in class |
|---|---|---|
| Multiple local minima | Where you end depends on where you start | Try several random seeds; the variance across seeds itself tells you how unstable the landscape is |
| Two plateaus with a jump between them (zero gradient) | The gradient is 0 everywhere and completely uninformative; the low-loss part is never reached | Evolution strategies; the slides show them minimizing this function |
| Nearly flat (vanishing gradient) | Progress is very slow and batch noise dominates the signal | No dedicated remedy given in class; in Q&A evolution strategies are said to maybe help |
| Steeper toward the minimum (exploding gradient) | One step throws you far away, so you never land on the minimum | Gradient clipping |
Evolution strategies ignore the gradient. They sample small normally distributed perturbations around the current parameters and move toward the perturbations with lower loss, so they can still move where the gradient is uninformative. Gradient clipping is more direct: if the gradient magnitude exceeds a cap , scale it back to . Beery calls it "a useful and commonly used hack." An example of my own: the gradient is with magnitude 50; scaling by overall magnitude with a cap of gives , same direction, smaller step. The formula on the slide clips each component instead, which turns the same gradient into and changes its direction.
A student follows up on differentiability in PyTorch (the question is incomplete in the transcript). Her answer is that being able to compute a gradient does not make it useful; on a flat landscape the gradient you compute is simply 0.
Three Properties of Activation Functions
Continuous, differentiable and smooth: each of these might make optimization easier, though none is required. ReLU is continuous everywhere and differentiable almost everywhere, but it has a kink at 0, so it is not smooth. GELU is , where is the cumulative distribution function of the standard normal, and it satisfies all three.
Beery is careful not to say GELU is always better. Her claim is that we do not yet know, experimentally or theoretically, which properties training needs, but the trend does move toward functions that satisfy all three.
Computation Graphs and the Forward Pass
A computation graph draws a model as a graph: each node is a functional transformation and each edge carries data. Deep learning deals almost entirely with directed acyclic graphs (DAGs), and assumes every node is differentiable.
A two-layer multilayer perceptron is a chain:
flowchart TB
X["Input x"] --> L1["Linear W1"]
L1 --> R["ReLU"]
R --> L2["Linear W2"]
L2 --> J["Loss J"]
In the forward pass each node takes its input and its own parameters, produces an output, and hands it to the next node until the loss comes out.
Backprop: Compute the Shared Part Once
To update layer 1 you need ; to update layer 2 you need . Expand both with the chain rule and the long stretch running back from the loss is identical; only the last factor differs.
Backprop passes that shared quantity from the output end to the input end once. Each layer tracks two things:
- : the derivative of the layer's output with respect to its input (or its parameters), determined by the layer's function.
- : the gradient of the loss with respect to the layer's output, a row vector passed back from later layers.
There is one recurrence: gradient in = gradient out × this layer's .
Get the Shapes Right First
The lecture pauses for a matrix calculus refresher, because shapes are where backprop most often goes wrong:
- If is an column vector and is a scalar, is a row vector.
- If is an vector, is an Jacobian.
- For the chain rule , with lengths , , : () () ().
Three Equations for a Linear Layer
For a linear layer everything comes out clean:
| Equation | Why | |
|---|---|---|
| Forward | Multiply by the weight matrix | |
| Backward | Because | |
| Weight gradient | Only output depends on , and its derivative with respect to is |
So the weight gradient is the outer product of the layer's input and the gradient coming back. Written with column-vector gradients, the backward equation becomes : forward multiplies by , backward by .
ReLU Becomes a Gate on the Way Back
On the backward pass ReLU is not ReLU again. It becomes a diagonal matrix with 1 where the forward input was positive and 0 elsewhere. Units that were zeroed on the way forward do not pass gradient on the way back.
Two consequences follow:
- The whole backward pass is linear, including the ReLU step. Beery relays an intuition from "Phil" (presumably co-instructor Phillip Isola): a first-order approximation fits a plane to the curved loss landscape and moves along it, so it has to be linear.
- The backward pass needs intermediate values from the forward pass. A student points out that this makes the two passes asymmetric: going forward only, you can discard a layer's output once the next layer is computed, but to go backward you must keep them all. Beery confirms it: to compute backprop efficiently you have to save the intermediate representations.
When It Is Not a Chain: Merging and Branching
Real networks share weights, split or concatenate data, and attach multiple heads and objectives; they are not chains. Extending everything above to an arbitrary DAG takes only two more operations:
| Forward | Backward |
|---|---|
| Merge (add, concatenate, and so on): several inputs become one | Route each part of the gradient back to the input it belongs to |
| Branch: one output goes to several places | Sum the gradients coming back from the branches |
Parameter sharing is a special case of branching: one set of parameters is sent to several places, so its gradient is the sum of the gradients from each use.
A shared-parameter example, worked (written for this post). Let , where the same is used twice, with and .
- Forward: , , .
- Gradient from the outer use: .
- Gradient from the inner use: pass back through the outer multiplication (times ), then through tanh (times ), then multiply by the input , giving .
- Add the two: .
Either one alone underestimates it. This is what the branching rule looks like for a shared parameter.
One Update by Hand: The Exercise at the End of the Slides
The slides end with an exercise the lecture had no time for, though slides 74–80 include a step-by-step solution. The presentation and notation below are this post's own, and both the intermediate values and the final weights were compared with that solution.
Setup: two input nodes (1, 2), two tanh hidden nodes (3, 4), one linear output node (5), no bias terms.
| Weight | ||||||
|---|---|---|---|---|---|---|
| Initial | 1 | −3 | 0.2 | 1 | 1 | −1 |
There is one training example: , , target . The problem says Euclidean loss, and the solution slides use the form ; the learning rate is 0.2.
Forward
- ,
- ,
Backward. The gradient at the output is .
The output layer is linear, so its weight gradient is input times the gradient coming back:
The gradient passes back through the output layer (multiply by the weight) and then through tanh (multiply by ):
(The slide solution writes as −0.1186, truncated to four digits; rounded it is −0.1187.)
The first-layer weight gradients are again input times the gradient coming back:
- ,
- ,
Update ( gradient)
| Weight | ||||||
|---|---|---|---|---|---|---|
| Updated | 1.0237 | −2.9976 | 0.1658 | 0.9966 | 1.0226 | −0.9891 |
| Slide answer (two digits) | 1.02 | −3.0 | 0.17 | 1.0 | 1.02 | −0.99 |
Run the forward pass again with the new weights: the output moves from 0.3131 to 0.3768 and the loss drops from 0.0175 to 0.0076.
The thing to notice is that is computed once and reused by all six weight gradients, while and are each computed once and reused by two. That is the "compute the shared part once" from the opening.
The slides write the learning rate as and note that this is because their update uses a plus sign. This post uses the minus-sign convention, so the learning rate is a positive 0.2; the two are equivalent.
Differentiable Programming: Weights Are Not the Only Thing You Can Optimize
The last part steps back. Deep nets are popular for two reasons: they are differentiable and therefore easy to optimize, and they are compositional, like building blocks. General models with these two properties came to be called differentiable programming.
Beery cites Andrej Karpathy's Software 2.0: in traditional software a person writes the program; in Software 2.0 a person defines a space of possible programs and data optimizes within it. Real systems are hybrids, with some nodes hard-coded by people (image normalization values, for example) and some "written" by backprop. Neural Module Networks is the example from class: the parser that reads the question might not be learned at all, while the CNN that recognizes objects might be updated from training data.
Because the whole graph is differentiable, you can take any scalar cost and optimize any node or edge with respect to it. Hold the weights fixed and optimize the input instead, and you get several well-known applications:
- Feature visualization: find the image that maximizes the "cat" output neuron to see what the model considers most cat-like (see Feature Visualization). DeepDream is the same idea.
- Steering image generation with CLIP: CLIP's text and image encoders and the image generator are all frozen; only the generator's input vector is optimized so that the generated image lands closest to the text prompt in CLIP space.
One practical detail from class: optimizing the logit before the softmax is more stable than optimizing the probability after it. The cheapest way to raise one class's probability is often to push the other classes down, not to make the image look more like that class.
Common Misunderstandings
- "Backprop is an optimization algorithm." It is not. It only computes gradients; SGD, Adam and other optimizers are what use them to update parameters.
- "Adam is just momentum." The lecture mentions Adam in one sentence as a popular example with momentum. Adam also rescales each parameter's step adaptively by gradient magnitude, which this lecture does not cover; see the Optimization Overview in this series.
- "PyTorch can differentiate it, so it will train." Being able to compute a gradient and the gradient carrying signal are different things.
Check Yourself
- A linear layer has a matrix . What is the shape of the incoming ? What are the shapes of and the weight gradient? Answer: is ; is ; the weight gradient has the shape of , .
- In the exercise above, replace node 3 with ReLU. What is ? Answer: , so the gate is 1 and . If were negative, and neither nor would update on this step.
- Change the shared-parameter example above to (with still 0.5). What is ? Answer: , , . The outer use gives and the inner use gives , for a total of 1.1816. One gradient per use, then add: that is the branching rule.
- Late in training the loss curve suddenly shows huge spikes. Which tool from this lecture do you try first? Answer: gradient clipping. A spike usually means one step's gradient was too large and threw the parameters far away.
Lecture Video Source
Rechecked against the live MIT OCW Fall 2024 gallery on 2026-10-13: the lecture number matches and the video is public and embeddable. Lecture numbering and topics follow OCW.
Original video: MIT 6.7960 Fall 2024 — Lec 02. How to Train a Neural Net
Course and recording links:
Checked: 2026-10-13.
Content check: verified against the video transcript (2026-10-13): read the full official OCW transcript and the slides. The transcript has no timestamps and the audio was not replayed for this post. The closing exercise is not explained in class; the working here was compared with the step-by-step solution on slides 74–80. The two small examples on gradient clipping and a shared parameter are this post's own.
References
- MIT 6.7960 Fall 2024 OCW course home
- Lec 02 official transcript (PDF)
- Lecture 2: How to Train a Neural Net slides
- Gabriel Goh, Why Momentum Really Works (Distill, 2017)
- Hendrycks & Gimpel, Gaussian Error Linear Units (GELUs)
- Andreas et al., Neural Module Networks
- Andrej Karpathy, Software 2.0
- Olah et al., Feature Visualization (Distill, 2017)
- Google Research, Inceptionism: Going Deeper into Neural Networks
- OpenAI, CLIP: Connecting text and images
Loading...