NeuronCanvas
Neural Networks
Training a Network

Gradients and Gradient Descent

What a gradient is and how repeatedly stepping downhill trains every weight in a network.

Step 01 - The break

One number, two completely different runs

Same network, same data, same code. One number changed, and it did this.

lr = 0.35 lr = 1.10
2.400 loss 5.760 2.400 loss 5.760
0.720 loss 0.518 -2.880 loss 8.294
0.216 loss 0.047 3.456 loss 11.944
0.065 loss 0.004 -4.147 loss 17.199
0.019 loss 0.000 4.977 loss 24.767
0.006 loss 0.000 -5.972 loss 35.664
one of these is training. the other is the same code, one number different.

The number that changed is not a weight and not a data point. It is not part of the network at all. This page is about what it is and why it has that much power.

Step 02 - Before this page
Before this page - 2 pages, both immediately before this one2
Step 03 - The stage

Take a step. Then take four more. Then drag the learning rate somewhere else and press Reset and do it again. Find, by experiment, the largest value that still gets to the bottom.

Preview frame from the "Gradients and Gradient Descent" animation0:14

What this animation shows

A ball sits partway up a parabola (loss(x) = x^2) and takes a series of discrete steps, each one rolling it further downhill, leaving a fading trail of ghost positions behind it. The ball's steps get smaller as it nears the bottom, and it settles at the minimum and turns green. This is gradient descent in miniature: repeatedly stepping in the downhill direction until you reach the lowest point.

This curve is the loss - height is how wrong the network is for a given weight value. Each step nudges the weight downhill. Faded circles are the last few positions, so you can see whether the ball is settling down or flying farther out.

weight = 2.400
gradient = 4.800
loss = 5.760
steps taken = 0
A ball resting on a curved loss landscape, rolling toward the lowest point as gradient descent takes steps, with a fading trail showing recent positions.
Step 04 - One question first

The ball is at x = 2.4 and the slope under it is 4.8. To go downhill, does the next step add 4.8 to x or subtract it?

  • aAdd - the slope is positive, so go that way
  • bSubtract - the slope points uphill
  • cNeither, it depends which side of the bowl you are on
Commit to a guess, then open this

Subtract. The slope always points in the direction the loss increases, in every dimension at once, so going downhill always means moving against it. At x = 2.4 the slope is +4.8 and the step is negative. At x = −2.4 the slope is −4.8 and the step is positive. You never have to check which side you are on; the sign of the gradient has already checked for you. That is why the update rule has a minus sign in it and why it needs no if statement, and it is the single most-asked question on this page.

Step 05 - Plain explanation

Picture the loss as a landscape and a weight as a ball resting somewhere on that landscape - its height is how wrong the network currently is. The slope of the ground directly under the ball is called the gradient. Repeatedly nudging the ball a little in the downhill direction is gradient descent - it’s how every weight in a network gets better over time.

So far that has nudged one number. A network has thousands, sometimes billions, and each one has its own answer to “if I nudge you, how much does the loss change?” A gradient is nothing more than the whole collection of those answers, one per parameter, written down as a list.

Each entry is called a partial derivative, and “partial” just means you nudge one parameter while holding every other one perfectly still. Nudge w₁ alone, measure the loss change, write it down. Put w₁ back. Nudge w₂ alone, measure, write it down. The resulting list is the gradient.

Two pieces of shorthand, because everything from here on uses them. The entry for a parameter w is written dL/dw, said “d L by d w”, and it means precisely the nudge-and-measure number: how much the loss L changes per unit change in w. And lr is the learning rate, the fraction of that measured slope you actually move.

The list has a useful property that makes it worth calling a single object: read as a direction in the space of all the parameters at once, the gradient points in the direction of steepest increase of the loss. That is why the update rule has a minus sign in it. You want the loss to go down, the gradient points up, so you step against it. Every “why is there a minus sign there” question about training has that as its answer. It is also checkable, and rung 4 checks it.

Descending in fog

You cannot see the valley. You can feel the ground under one boot. Slide the boot around: whichever way it drops fastest is the downhill direction, and you step that way and repeat. The gradient is that slide, done once per parameter instead of once per boot. The learning rate is your stride length, and the argument about stride length is the argument this page is really about.

Where it breaks downA real hillwalker can see fifty metres ahead in patchy fog. Gradient descent sees precisely zero distance ahead; it only ever knows the tilt at the exact point it is standing.

Step 06 - The depth ladder
WordsA list of tilts, one per parameterWhat a gradient is, in one sentence, plus why the update subtracts it.Rung 01

The loss is a landscape. A weight is a ball on it. The height of the ground is how wrong the network currently is, and the slope of the ground directly under the ball is the gradient. Step downhill, repeatedly, and the network gets better.

With more than one parameter there is no single slope, so there is a list of them, one per parameter. Each entry is a partial derivative: nudge that one parameter, hold every other one perfectly still, and write down how much the loss moved. Do that once per parameter and the list you end up with is the gradient.

Read as a direction rather than as a list, the gradient points in the direction of steepest increase of the loss. You want the loss to go down. The gradient points up. So you step against it, and that is the whole of the minus sign.

NumbersThree descents, worked by handOne parameter, then two, with every intermediate value printed.Rung 02

Take the simplest possible loss landscape, loss(x) = x². Its slope at any point turns out to be 2x, but rather than trusting a formula out of nowhere, check it the honest, no-calculus way: nudge x by a tiny amount and see how much the output moves.

f(3) = 9
f(3.001) = 9.006001
slope ~ (9.006001 - 9) / 0.001 = 6.001 ~ 2 * 3 = 6.000 ok

That’s the honest, no-calculus definition of a derivative: how much the output changes for a tiny change in input, divided by that tiny change. Notice the answer came out to 6.001, not exactly 6 - the smaller the nudge, the closer this gets to the true slope; shrinking the nudge all the way toward zero is what calculus calls the derivative. This is the same trick already used to verify the derivative table on the activation-functions page, and it’ll come back once more on the output-activations page, so it’s worth having solid here.

One gradient descent step is just x_new = x − lr·gradient(x). Worked example: starting at x=2.4 with lr=0.35, the gradient is 2×2.4=4.8, so the next value is 2.4 − 0.35×4.8 = 0.72, much closer to the bottom (x=0) already.

Now the gradient of an actual loss with respect to two actual parameters, computed by hand. This is the same kind of network the loss functions page left off with, now taken the rest of the way: ŷ = w·x + b with w = 0.50 (positive, so blue on a diagram) and b = 0.00, on two training points. The loss is the average half-squared error, this site’s convention, which is why every gradient below comes out without a stray factor of 2 in it.

Worked example - a two-entry gradient, three steps, lr = 0.1
data: (x=1.0, y=1.0) and (x=2.0, y=3.0)
step 1 w = 0.500000 b = 0.000000
predictions: 0.500000 and 1.000000 errors: -0.500000 and -2.000000
loss = ( 0.5 * 0.25 + 0.5 * 4.0 ) / 2 = 1.062500
dL/dw = mean(e * x) = ( -0.500000 * 1.0 + -2.000000 * 2.0 ) / 2 = -2.250000
dL/db = mean(e) = ( -0.500000 + -2.000000 ) / 2 = -1.250000
gradient = ( -2.250000, -1.250000 )
length = sqrt( 2.250000^2 + 1.250000^2 ) = sqrt( 6.625000 ) = 2.573908
w -> 0.500000 - 0.1 * (-2.250000) = 0.725000
b -> 0.000000 - 0.1 * (-1.250000) = 0.125000
step 2 w = 0.725000 b = 0.125000
loss = 0.513281
gradient = ( -1.500000, -0.787500 ), length = 1.694154
w -> 0.875000 b -> 0.203750
step 3 w = 0.875000 b = 0.203750
loss = 0.275210
gradient = ( -1.006875, -0.483750 ), length = 1.117055
w -> 0.975688 b -> 0.252125
loss: 1.062500 -> 0.513281 -> 0.275210, and the gradient’s length
shrinks 2.573908 -> 1.694154 -> 1.117055 as the ground flattens

Three things to take from that. Both entries of the gradient were negative, so both parameters went up, and they went up by different amounts, because w had the steeper slope. Nobody decided that; it fell out of the arithmetic.

The “length” line is worth reading twice, because it is the first place on this site where two numbers get combined into one. It is the ordinary distance formula: square each entry, add, take the square root. That single number is how big the whole gradient is, ignoring which direction it points, and it is shrinking, which is what “approaching a minimum” looks like numerically: the ground under the ball is getting flatter. At an exact minimum, every entry of the gradient is 0, the length is 0, and the updates stop by themselves. This same quantity comes back on the vanishing gradients page under its other name, the norm, where clipping is defined in terms of it.

And look at how dL/dw got built: (−0.500000×1.0 + −2.000000×2.0) / 2. The second example contributed −4.0 of the −4.5 total, 89% of the whole signal, because its error was four times as large and its input was twice as large. Each example’s vote is weighted by its own error and its own input. Nothing about that is specific to this loss; it is what “the gradient of an average” means, and it is why one badly-fit example with a large input can dominate a whole batch.

PictureSix learning rates on one curveThe learning-rate claims, checked, and the same six runs on screen.Rung 03

Below about lr=0.5, the ball glides smoothly to the bottom. At exactly lr=0.5 it reaches the bottom in a single step. Between 0.5 and 1 it overshoots past the bottom and bounces to the other side, but each bounce is smaller than the last. At exactly lr=1, it bounces forever at the same distance, never settling and never escaping. Above lr=1, it overshoots farther every single step. Those claims are checkable, so here they are checked. Starting from x=2.4 on loss(x) = x², one step is x ← x − lr·2x = x·(1 − 2·lr). The whole behaviour is decided by that one multiplier.

Worked example - the same start, six learning rates, six steps each
lr = 0.10 multiplier +0.80 2.400 -> 1.920 -> 1.536 -> 1.229 -> 0.983 -> 0.786 -> 0.629
glides in, same sign every step, never overshoots
lr = 0.35 multiplier +0.30 2.400 -> 0.720 -> 0.216 -> 0.0648 -> 0.01944 -> 0.005832 -> 0.00175
glides in much faster
lr = 0.50 multiplier 0.00 2.400 -> 0.000-> 0 -> 0 -> 0 -> 0 -> 0
lands exactly on the bottom in one step and stays
lr = 0.90 multiplier -0.802.400 -> -1.920 -> 1.536 -> -1.229 -> 0.983 -> -0.786 -> 0.629
overshoots and alternates sign, but each swing is smaller
lr = 1.00 multiplier -1.00 2.400 -> -2.400 -> 2.400 -> -2.400 -> 2.400 -> -2.400 -> 2.400
bounces forever, never settles, never escapes
lr = 1.10 multiplier -1.20 2.400 -> -2.880 -> 3.456 -> -4.147 -> 4.977 -> -5.972 -> 7.166
every swing is larger than the last, this is divergence

The rule behind all six rows: the step converges when |1 − 2·lr| < 1, which for this landscape means lr < 1. The bars in |…| mean “ignore the sign”, so a multiplier of −0.80 counts as 0.80 and shrinks the number it multiplies, while −1.20 counts as 1.20 and grows it. The 2 in that expression is how sharply bends, its curvature: the slope of is 2x, which gains 2 for every 1 you move sideways, and a bowl whose slope changes faster means a smaller maximum safe learning rate. That is not a quirk of this toy function, it is the constraint that decides learning rates in real training, and it returns with real numbers on the optimizers page.

Every row of that table is a setting of the slider in Figure 02, and the fading trail is the row drawn. At lr = 0.10 the trail is a line of dots marching one way. At lr = 0.90 the dots alternate left and right of the bottom, each one closer in. At lr = 1.00 there are only ever two dots, because the ball visits exactly two places forever. Above 1.00 the trail runs off the edge of the frame and the ball sticks against it - at that point stop reading the picture and read the weight number underneath, which keeps going.

EquationThe update rule, and why it points that wayFive directions, the same step size, and the one that wins.Rung 04

One gradient descent step is x_new = x − lr·gradient(x), where lr controls how big a step to take.

The claim that the gradient points in the direction of steepest increase is the one the minus sign rests on, so here it is checked rather than asserted. Stand at the same starting point, w = 0.500000, b = 0.000000, where the loss is 1.062500. Move exactly the same distance, 0.1, in five different directions and see what the loss does. Each direction is written as “how much of the step goes into w, how much into b”, scaled so the total distance moved is 0.1 every time.

Worked example - same start, same step size 0.1, five directions
gradient here = ( -2.250000, -1.250000 ), length 2.573908
so “straight downhill” as a direction is ( 2.250000, 1.250000 ) / 2.573908
= ( 0.874157, 0.485643 )
direction lands at new loss change
straight down the gradient (+0.874157, +0.485643) w 0.587416 b 0.048564 0.822208 -0.240292
equal parts w and b (+0.707107, +0.707107) w 0.570711 b 0.070711 0.831263 -0.231237
w only (+1.000000, 0.000000) w 0.600000 b 0.000000 0.850000 -0.212500
b only ( 0.000000, +1.000000) w 0.500000 b 0.100000 0.942500 -0.120000
straight up the gradient (-0.874157, -0.485643) w 0.412584 b -0.048564 1.336990 +0.274490

Every direction with a downhill component lowers the loss, and the one built from the gradient lowers it the most: 0.240292 against 0.231237 for the nearest competitor, and more than twice what moving b alone achieves. Turn the direction around and it becomes the single fastest way to make the loss worse, which is the same fact stated from the other side. That is what “steepest” means, and it is why the update subtracts the gradient instead of adding it.

General caseA million parameters, and where this stops workingSame arithmetic, longer list, and the two ways the friendly picture lies.Rung 05

Nothing about the five-direction check depends on the loss being squared error or on there being two parameters; with a million parameters the arithmetic is the same and only the list is longer.

Two honest limitations, because the picture above is deliberately friendly.

has exactly one minimum and gradient descent cannot fail to find it. A real loss landscape has many. It can have local minima, dips that are not the deepest dip available, and far more commonly it has saddle points, places that slope down in some directions and up in others, where the gradient is near zero in every direction and progress stalls without the loss being anywhere near as low as it could get. In very high-dimensional networks saddle points are the more serious of the two, simply because a point needs to curve upward in every one of a million directions at once to be a true local minimum, and that is rare. Most of what optimizers do beyond plain gradient descent is about getting through flat and awkward regions faster.

And nothing here says when to stop. Gradient descent has no built-in finish line; the gradient shrinks toward zero but never quite arrives. In practice you stop after a fixed number of steps, or when the loss stops improving, or when a separate held-out score stops improving, which is early stopping.

Step 07 - Why this and not that

Why this and not that

Why not just solve for the minimum? We know the formula.

For you can, and the answer is x = 0. For a network you cannot: there is no closed-form solution for where a million-parameter non-linear loss is smallest, and even for the cases where linear algebra could do it, inverting a million-by-million matrix is far more expensive than taking a few thousand cheap steps.

Why a fixed step size rather than jumping straight to the bottom?

Because the gradient only tells you the tilt where you are standing, not how far the bottom is. The size of the gradient is a hint about that, which is why plain gradient descent takes big steps far out and small steps near the bottom for free. Methods that do try to estimate the distance exist - they use the curvature, the rate at which the tilt changes - and they are usually too expensive for networks this size.

Why is 6.001 acceptable? That is not 6.

It is the honest answer to the question we actually asked, which was “how much does the output move for a nudge of 0.001”. Shrink the nudge to 0.0001 and you get 6.0001. The derivative is what that sequence approaches, not any one member of it. Real autodiff does not do this arithmetic at all; it applies exact formulas that someone derived once by taking that limit properly.

If the gradient is zero, is training finished?

It means training has stopped, which is not the same thing. A zero gradient happens at the bottom of a bowl, at the top of a hill, and at a saddle point, and in a high-dimensional network the saddle point is by far the most likely of the three.

Everyone says gradient descent finds the global minimum. Does it?

No, and it mostly does not matter. Large networks have vast numbers of local minima and, empirically, most of the reachable ones are about equally good. The failures that hurt in practice are flat regions and badly scaled directions, which is what the next page’s optimizers exist for.

Name origins
Gradient
From Latin gradus, a step, via the 19th-century engineering sense of a road’s gradient: how much you climb per unit you travel. Same meaning, more dimensions.
Descent
Because you go down. It is named after the direction of travel, not the mechanism, which is why the mirror-image procedure for maximising something is called gradient ascent and is otherwise identical.
A “curly d”, written that way purely to distinguish a partial derivative (nudge one thing, hold the rest still) from an ordinary one (there is only one thing). It is read “partial”, or often just “d”.
η
The Greek letter eta, the near-universal symbol for a learning rate in papers. There is no story: it was a free letter. Code almost always calls it lr instead.
Learning rate
It is the fraction of the measured slope you actually move. Not a speed, not a percentage of anything else, and nothing in it is per second.
Saddle point
From the shape of a horse’s saddle: curving down along the horse and up across it, so the flat point in the middle is a minimum in one direction and a maximum in the other.
Step 08 - Where people go wrong

This curve is the loss - height is how wrong the network is for a given weight value. Each step nudges the weight downhill. Faded circles are the last few positions, so you can see whether the ball is settling down or flying farther out.

weight = 2.400
gradient = 4.800
loss = 5.760
steps taken = 0
A ball resting on a curved loss landscape, rolling toward the lowest point as gradient descent takes steps, with a fading trail showing recent positions.
Step 09 - Practice
  1. 01
    Reach the bottom in exactly one step.
    Hint

    One step is x ← x·(1 − 2·lr). What value of lr makes the multiplier zero?

    Answer

    lr = 0.50. The multiplier is 1 − 2×0.5 = 0, so any starting point lands on exactly 0.000 in one step and stays there. This is a property of this bowl, not a good learning rate: it works because the slope of is exactly 2x, and the moment the landscape is anything else, 0.5 is no longer special.

  2. 02
    Find the largest learning rate the slider offers that still converges, and the smallest that does not.
    Hint

    Try 0.95, then 1.00, then 1.05. Watch whether each swing is smaller than the last or larger.

    Answer

    Everything below 1.00 converges; 1.00 itself bounces forever; anything above diverges. At lr = 0.99 the multiplier is −0.98, so each swing keeps 98% of the last - it converges, agonisingly. At lr = 1.01 the multiplier is −1.02 and each swing is 2% larger, so it diverges, slowly at first. The boundary is exact and it is |1 − 2·lr| = 1.

  3. 03
    Set lr = 0.10 and take five steps. Without touching the widget again, predict the weight after step six, then check.
    Hint

    Every step multiplies the weight by the same fixed number.

    Answer

    1.417 × 0.80 = 1.134. The multiplier is 1 − 2×0.10 = 0.80, unchanged at every step, which is why this run is exactly predictable. That predictability is precisely what stops the moment the landscape is not a parabola - which is every real network.

  4. 04
    Make the loss get worse on every step without exceeding lr = 0.40.
    Hint

    There is a preset in the block above that does this. What is it doing to the update?

    Answer

    Flip the sign of the update - x ← x + lr·g instead of x ← x − lr·g (the “gradient ascent by accident” preset, at lr = 0.35). The multiplier becomes 1 + 0.70 = 1.70 and the loss rises smoothly: 5.760 → 16.646 → 48.108 → 139.03. Note that it never oscillates. A smooth climb is the fingerprint of a sign error; an alternating climb is the fingerprint of a learning rate that is too large. Two different bugs, two different pictures.

  5. 05
    Argue from the widget alone why the safe learning rate for a different bowl would be a different number.
    Hint

    Where does the 2 in the multiplier (1 − 2·lr) come from?

    Answer

    From the slope of being 2x, which gains 2 for every 1 you move sideways. That 2 is the curvature. For a bowl 5x² the slope is 10x, the multiplier is (1 − 10·lr), and the run diverges above lr = 0.20 rather than 1.00 - five times sharper bowl, five times smaller safe learning rate. The optimizers page picks this up with a two-dimensional valley where one direction is 20 times steeper than the other, and the safe rate for the whole run is set by the steepest direction alone.

Step 10 - Seen in the wild
  • Every PyTorch runThe two lines loss.backward() and optimizer.step() are this page: the first computes the list of tilts, the second moves every parameter against it by the learning rate. Everything else in a training script is scaffolding around those two calls.
  • Learning-rate findingThe single most common first move when a real training run fails is to sweep the learning rate over powers of ten and plot the loss after a few hundred steps. The shape people are looking for on that plot is exactly the six-row table in rung 3.
Step 11 - Memory anchor

The gradient is the tilt of the floor under your feet, and the minus sign is you choosing to walk downhill.

Everything else on this page is an argument about how big a step to take.

Step 12 - The next break

This page took one step at a time, on a bowl with one minimum, using the exact gradient of the whole dataset. Every one of those three is a luxury a real run does not have. The exact gradient means running every training example through the network before touching a single weight. One shared learning rate means the steepest direction in the whole network sets the speed limit for every other direction. And a single smooth bowl is the one landscape where plain gradient descent cannot be beaten - which is exactly why the next page can show it losing.

Optimizers