← All posts

Foundations

Post 2 of 15

Loss functions and gradient descent

Posts in this series · 15

In the first Foundations post we built a tiny network, ran it forward, and used backpropagation to find how much each weight affected the output. That left two questions open. Affected what, exactly? And once we know, what do we do with it?

The answer to the first is the loss: one number that says how wrong the network is. The answer to the second is gradient descent: take a small step in the direction that makes the loss smaller, then repeat. Almost every model you have heard of, from image classifiers to the speech models in Pocket TTS, is trained this way.

Why we need one number

Imagine teaching a child to throw a ball into a bucket. After each throw you could say many things: “too far”, “a bit left”, “nice arc”. But if you had to give a single score, you would probably say how far from the bucket the ball landed. One number. Smaller is better.

A network is the same. It makes thousands of predictions, each a little right or wrong. To improve it, we need to squash all of that into one number called the loss (also called the cost or the objective). Why one? Because “better” only makes sense when you can compare. With one number, every change to the weights is either an improvement (loss went down) or not.

The loss has two jobs:

  1. Score. It says how bad the current predictions are.
  2. Steer. It must change smoothly as the weights change, so that we can ask “if I nudge this weight a little, does the loss go up or down?” That question is the gradient, and backpropagation from post 1 is how we answer it.

Choosing a loss is choosing what “wrong” means. The next two sections show that different choices really do lead to different answers.

Losses for numbers: squared and absolute error

Suppose the network predicts a number, like tomorrow’s temperature or the price of a house. We call the true answer the target yy and the network’s guess the prediction y^\hat{y} (read “y hat”).

Mean squared error

In one sentence: square each miss, then average.

MSE=1n∑i=1n(y^i−yi)2\text{MSE} = \frac{1}{n} \sum_{i=1}^{n} (\hat{y}_i - y_i)^2

MSE stands for mean squared error. Everyday picture: a fine that grows fast. Miss by 1, pay 1. Miss by 2, pay 4. Miss by 10, pay 100. Big mistakes are punished far more than small ones.

Worked example. Targets 3,53, 5; predictions 4,24, 2. Misses are 4−3=14 - 3 = 1 and 2−5=−32 - 5 = -3. Squares are 11 and 99. Average: (1+9)/2=(1 + 9) / 2 = 5.

If the second prediction moved from 2 to 4, its miss would shrink to −1-1, its square to 11, and the MSE to (1+1)/2=(1 + 1)/2 = 1. Fixing the big miss helped a lot, because it was squared.

Mean absolute error

In one sentence: drop the sign of each miss, then average.

MAE=1n∑i=1n∣y^i−yi∣\text{MAE} = \frac{1}{n} \sum_{i=1}^{n} \lvert \hat{y}_i - y_i \rvert

The bars ∣⋅∣\lvert \cdot \rvert mean “absolute value”: throw away the minus sign. MAE stands for mean absolute error. Everyday picture: a flat fee per unit of distance. Miss by 10, pay 10.

Same example: ∣1∣=1\lvert 1 \rvert = 1, ∣−3∣=3\lvert -3 \rvert = 3, average 2.

Outliers: where the two disagree

Here is the clearest way to see the difference. Suppose the network is very simple: it must give the same guess cc for every example. The targets are 2,3,4,152, 3, 4, 15. The 15 is an outlier, a value far from the rest (maybe a typo).

Check at c=6c = 6: squared misses are 16,9,4,8116, 9, 4, 81, MSE =110/4== 110/4 = 27.5. At c=3.5c = 3.5: squared misses 2.25,0.25,0.25,132.252.25, 0.25, 0.25, 132.25, MSE =135/4== 135/4 = 33.75, worse, so MSE prefers 6. For MAE, at c=3.5c = 3.5 the misses are 1.5,0.5,0.5,11.51.5, 0.5, 0.5, 11.5, MAE == 3.5; at c=6c = 6 they are 4,3,2,94, 3, 2, 9, MAE == 4.5, so MAE prefers 3.5.

Neither is “right”. MSE says “never be very wrong about anything”; MAE says “be right about most things”. If the 15 is a typo, MAE is the safer choice. If it is real and costly to miss, MSE is.

The steering job matters too. The slope of the squared miss (y^−y)2(\hat{y} - y)^2 with respect to y^\hat{y} is 2(y^−y)2(\hat{y} - y): big misses push hard, small misses push gently, so steps naturally shrink near the answer. The slope of ∣y^−y∣\lvert \hat{y} - y \rvert is just +1+1 or −1-1: the same push whether you are off by 0.01 or by 100. We will see why that matters when we take steps.

Squared error, absolute error and cross-entropy, each with its value and slope
Show
Figure 1. Three ways to score a miss. Drag the prediction and watch each loss and its slope. Squared error is gentle near the target and harsh far away; absolute error is a V; cross-entropy shoots up as the probability of the right answer falls to zero.

Losses for choices: probabilities and cross-entropy

Many tasks are not “predict a number” but “pick one of several options”: is this picture a cat, a dog or a bird? This is called classification, and each option is a class.

Turning scores into probabilities with softmax

The last layer of a classifier outputs one raw score per class. These scores are called logits. They can be any number, negative or positive, and they do not add up to anything in particular. We want probabilities instead: numbers between 0 and 1 that add up to 1.

In one sentence: softmax makes every score positive with eze^{z}, then divides by the total so they add to 1.

pk=ezk∑j=1Kezjp_k = \frac{e^{z_k}}{\sum_{j=1}^{K} e^{z_j}}

Everyday picture: sharing sweets. Each class gets a pile of sweets whose size is eits scoree^{\text{its score}}, then we report each pile as a share of all the sweets. A score one higher means a pile about 2.7 times bigger.

Worked example. Cat, dog, bird with logits z=(2,1,0)z = (2, 1, 0).

What changes if a number changes? Add the same amount to every logit, say (12,11,10)(12, 11, 10), and the probabilities do not move at all: every pile is multiplied by the same e10e^{10}. Only the differences between logits matter. Widen the gaps, say (4,2,0)(4, 2, 0), and the top class takes almost everything: 0.867,0.117,0.0160.867, 0.117, 0.016.

The name “softmax” comes from Bridle (1990): it is a soft version of “pick the maximum”.

Surprise, and why the loss is minus log

Now the true answer is “cat”. How should we score the probabilities 0.665,0.245,0.0900.665, 0.245, 0.090?

Think about surprise. If you were sure it would rain (p=1p = 1) and it rains, you are not surprised at all. If you gave rain a 1 in 100 chance and it rains, you are very surprised. A good measure of surprise should:

The one function that does all three is −log⁡p-\log p. (The third rule is the key one: log⁡(a×b)=log⁡a+log⁡b\log(a \times b) = \log a + \log b, so probabilities that multiply become surprises that add.) This idea comes from Claude Shannon’s 1948 paper that founded information theory. We use the natural log, ln⁡\ln.

Probability given to what happenedSurprise −ln⁡p-\ln p
10
0.50.693
0.12.303
0.014.605

Each time the probability shrinks by a factor of 10, the surprise grows by the same 2.303.

Cross-entropy loss is simply: the surprise the network feels at the right answer.

LCE=−∑k=1Kykln⁡pkL_{\text{CE}} = -\sum_{k=1}^{K} y_k \ln p_k

Worked example. True class cat, pcat=0.665p_{\text{cat}} = 0.665: loss =−ln⁡0.665≈= -\ln 0.665 \approx 0.408. If the true class were bird, pbird=0.090p_{\text{bird}} = 0.090: loss =−ln⁡0.090≈= -\ln 0.090 \approx 2.408. Confidently wrong costs a lot.

Why not just use squared error on the probabilities? You could, but cross-entropy punishes confident mistakes much harder (it goes to infinity as ptrue→0p_{\text{true}} \to 0, while squared error tops out at 1), and, as the next part shows, it gives a beautifully simple gradient.

The neat gradient: p minus y

We want to know: if I nudge logit zkz_k up a little, how does the loss change? Working through the chain rule from post 1 for softmax followed by cross-entropy, almost everything cancels and leaves:

∂LCE∂zk=pk−yk\frac{\partial L_{\text{CE}}}{\partial z_k} = p_k - y_k

In plain words: the push on each logit is “what you predicted minus what was true”.

Worked example with z=(2,1,0)z = (2, 1, 0), true class cat, y=(1,0,0)y = (1, 0, 0):

The three numbers add to zero. And notice: when the network is already right and sure (pcatp_{\text{cat}} near 1), every push is near 0, so it stops changing what already works.

Here is the short reason, for two classes. With logits z1,z2z_1, z_2, p1=ez1/(ez1+ez2)p_1 = e^{z_1}/(e^{z_1} + e^{z_2}). If class 1 is true, L=−ln⁡p1=−z1+ln⁡(ez1+ez2)L = -\ln p_1 = -z_1 + \ln(e^{z_1} + e^{z_2}). The slope of −z1-z_1 with respect to z1z_1 is −1-1; the slope of ln⁡(ez1+ez2)\ln(e^{z_1} + e^{z_2}) is ez1/(ez1+ez2)=p1e^{z_1}/(e^{z_1} + e^{z_2}) = p_1. Together: p1−1=p1−y1p_1 - 1 = p_1 - y_1. The same two lines work for any number of classes.

Logits become probabilities, a loss and a gradient, one column at a time
True class
Shift every logit
Figure 2. Softmax and cross-entropy, one operation at a time. Move the logits or pick a different true class; every number below updates. Add the same amount to all three logits and see that nothing changes.

The loss landscape

Now put the network’s weights on the map. Every possible setting of the weights gives one loss value. If the network had just two weights, we could draw this as a hilly terrain: east-west is weight 1, north-south is weight 2, and the height of the ground is the loss. Training means finding a low valley.

Real networks have millions of weights, so the terrain has millions of directions we cannot draw. But the picture still works: at any spot, the ground slopes some way, and we want to walk downhill.

The catch is that we are walking in thick fog. We cannot see the whole terrain. We can only feel the slope right under our feet. That is exactly what backpropagation gives us.

The gradient: the steepest-uphill arrow

In one sentence: the gradient lists, for each weight, how fast the loss rises when you nudge that weight.

∇L(w)=(∂L∂w1,∂L∂w2,…)\nabla L(\mathbf{w}) = \left( \frac{\partial L}{\partial w_1}, \frac{\partial L}{\partial w_2}, \ldots \right)

Taken together, these slopes form an arrow that points in the steepest uphill direction, and its length says how steep. So to go down, we walk the opposite way.

Worked example. On the bowl L=w12+4w22L = w_1^2 + 4 w_2^2, the slopes are 2w12 w_1 and 8w28 w_2. At the point (4,1)(4, 1) the gradient is (8,8)(8, 8): the ground rises just as fast eastward as northward. At (1,1)(1, 1) it is (2,8)(2, 8): much steeper northward, because the 4w224 w_2^2 term makes the bowl narrow in that direction.

Gradient descent in one dimension

In one sentence: move each weight a small step against its slope, then repeat.

wnew=w−η dLdww_{\text{new}} = w - \eta \, \frac{dL}{dw}

Everyday picture: walking down a hill in fog by feel. Where it is steep, you take a bigger stride; where it is nearly flat, a small shuffle.

The method is old: Augustin-Louis Cauchy described it in 1847.

Worked example. The loss is L(w)=(w−3)2L(w) = (w - 3)^2, a bowl with its bottom at w=3w = 3. Its slope is 2(w−3)2(w - 3). Start at w=0w = 0 with η=0.1\eta = 0.1.

StepwwLoss (w−3)2(w-3)^2Slope 2(w−3)2(w-3)Update
009−60−0.1×(−6)=0.60 - 0.1 \times (-6) = 0.6
10.65.76−4.80.6−0.1×(−4.8)=1.080.6 - 0.1 \times (-4.8) = 1.08
21.083.6864−3.841.08−0.1×(−3.84)=1.4641.08 - 0.1 \times (-3.84) = 1.464
31.4642.3593−3.0721.464+0.3072=1.77121.464 + 0.3072 = 1.7712

Look at the distance to the bottom: 3,2.4,1.92,1.536,…3, 2.4, 1.92, 1.536, \ldots Each step multiplies it by 0.8. Here is why. The update is w−0.1×2(w−3)w - 0.1 \times 2(w - 3), so the new distance is (w−3)−0.2(w−3)=0.8(w−3)(w - 3) - 0.2(w - 3) = 0.8(w - 3). In general, on this bowl, every step multiplies the distance by 1−2η1 - 2\eta. Keep that number in mind; the whole learning-rate section follows from it.

Also notice the steps shrink on their own (0.6, then 0.48, then 0.384) even though η\eta is fixed, because the slope shrinks near the bottom. With absolute error, whose slope is always ±1\pm 1, the step would stay η\eta forever and hop back and forth across the bottom.

A ball on the curve (w − 3)² stepping downhill, with each update written out
Figure 3. One step of gradient descent at a time. Each press measures the slope, multiplies by the learning rate, and moves the ball. Each update takes three presses: feel the slope, scale it, step. Change the start or the learning rate and the numbers update.

Gradient descent in two dimensions

With two weights we do exactly the same thing, once per weight, at the same time.

Take L=w12+4w22L = w_1^2 + 4 w_2^2, start at (4,1)(4, 1), η=0.1\eta = 0.1. The slopes are (2w1,8w2)(2 w_1, 8 w_2).

Per step, w1w_1 is multiplied by 1−2η=0.81 - 2\eta = 0.8 and w2w_2 by 1−8η=0.21 - 8\eta = 0.2. The steep direction is fixed almost at once; the gentle direction crawls. That is the typical shape of real training: quick progress at first, then a long slow slide along a valley floor.

Now try η=0.2\eta = 0.2. The factors become 0.60.6 and 1−1.6=−0.61 - 1.6 = -0.6. The minus sign means w2w_2 flips side each step: (4,1)→(2.4,−0.6)→(1.44,0.36)→(0.864,−0.216)(4, 1) \to (2.4, -0.6) \to (1.44, 0.36) \to (0.864, -0.216). The path zigzags across the narrow valley. Push to η=0.25\eta = 0.25 and w2w_2‘s factor is exactly −1-1: it bounces between 11 and −1-1 forever. The narrowest direction sets the speed limit for every direction.

Contour lines of a stretched bowl with gradient descent steps drawn on it
Start
Figure 4. Walking downhill on a map. Click anywhere to start. The red arrow is the gradient (uphill); the step goes the other way. Raise the learning rate to 0.2 and watch the zigzag.

The learning rate

The learning rate is the most important number you choose in training. On our 1-D bowl L=(w−3)2L = (w - 3)^2, each step multiplies the distance to the bottom by 1−2η1 - 2\eta. That single factor sorts every learning rate into one of five cases. Start at w=0w = 0 (distance 3) each time.

η\etaFactor 1−2η1 - 2\etaww after steps 1, 2, 3What happens
0.010.980.06, 0.1188, 0.1764Too small: crawls; after 100 steps still 0.4 away
0.40.22.4, 2.88, 2.976Just right: within 0.024 after 3 steps
0.503, 3, 3Lands exactly in one step (only on a perfect bowl)
1.0−16, 0, 6Bounces forever between 0 and 6
1.1−1.26.6, −1.32, 8.184Too large: diverges, distance 3, 3.6, 4.32, 5.18, …

Check the “after 100 steps” claim: 3×0.98100≈3×0.133≈3 \times 0.98^{100} \approx 3 \times 0.133 \approx 0.40.

And the divergence: at η=1.1\eta = 1.1, losses go 9,12.96,18.66,26.879, 12.96, 18.66, 26.87, each step 1.44 times worse (1.221.2^2). In real training this is the dreaded loss that shoots to “NaN” (not a number) after a few hundred steps.

The rule: as long as the factor’s size is below 1, that is 0<η<10 < \eta < 1 here, we get closer. In general the limit depends on how curved the steepest direction is, which is why the 2-D bowl’s narrow direction set a tighter limit of 0.250.25. Real networks do not tell you their curvature, so people try a few rates and watch the loss. Post 3 covers methods (momentum, Adam, schedules) that make this choice much less fragile.

The same bowl descended with three learning rates side by side
Right panel presets
Figure 5. A learning-rate race. Same bowl, same start, three step sizes. One crawls, one arrives, one flies off the chart.

Full-batch, stochastic and mini-batch

So far the loss was one formula. In real training it is an average over the training data: the loss on example 1, plus on example 2, and so on, divided by nn. The true gradient is therefore an average of per-example gradients, and computing it means running every example through the network. With a million examples, that is a million forward and backward passes for one step.

There are three ways to handle this.

A toy you can follow. We want one point w=(w1,w2)\mathbf{w} = (w_1, w_2) that is close to four data points: A (2,0)(2, 0), B (4,2)(4, 2), C (2,4)(2, 4), D (0,2)(0, 2). The loss for one point is its squared distance ∣w−point∣2\lvert \mathbf{w} - \text{point} \rvert^2; the full loss is the average over four. The best w\mathbf{w} is the centre, (2,2)(2, 2), where the loss is 4 (every point is 2 away, squared is 4). It cannot reach 0, because no single spot sits on all four points.

The gradient of one point’s loss is 2(w−point)2(\mathbf{w} - \text{point}). With η=0.25\eta = 0.25, the update w−0.25×2(w−target)\mathbf{w} - 0.25 \times 2(\mathbf{w} - \text{target}) simply moves halfway towards the target. That makes every step easy:

The noise is not only a cost. It can shake the weights out of small dents in the terrain, and it means the weights never settle perfectly; with a fixed learning rate, SGD keeps jittering around the bottom. That is one reason learning rates are usually lowered as training goes on.

Three paths towards the centre of four points: full batch, one example at a time, and two at a time
Data order
Figure 6. Same landscape, three ways to estimate the slope. The data order is fixed (B, D, A, C, and mini-batches B + A then D + C) so the numbers match the text; “Reshuffle” draws new orders.

Valleys, saddles and plateaus

Our bowls had one bottom. Real loss landscapes are messier.

For big networks, saddles and plateaus are thought to be a bigger nuisance than bad local minima: Dauphin and colleagues (2014) argued that in very many dimensions, most zero-slope points are saddles, since it is unlikely that the surface curves upward in every one of millions of directions at once.

Worked saddle. L=w12−w22L = w_1^2 - w_2^2: a valley along w1w_1, a hump along w2w_2. Slopes are (2w1,−2w2)(2 w_1, -2 w_2). With η=0.25\eta = 0.25, each step multiplies w1w_1 by 1−0.5=0.51 - 0.5 = 0.5 and w2w_2 by 1+0.5=1.51 + 0.5 = 1.5.

That tiny 0.01 is exactly what the noise from mini-batches provides for free.

Two balls on a saddle: one with no sideways nudge stays stuck, one with a tiny nudge rolls away
Mini-batch noise
Figure 7. Stuck on a saddle, and escaping it. A nudge of 0.01 is enough, but it takes several steps to show. Turn on “Add noise each step” to give both balls small random kicks, like mini-batch noise.

Convexity in simple terms

Some landscapes are guaranteed to be easy. A function is convex if, whenever you stretch a straight string between any two points on its surface, the string never dips below the surface. A bowl is convex; an egg carton is not.

Why care? On a convex landscape, every dip is the lowest point. There are no false valleys and no saddles, so gradient descent with a small enough learning rate always reaches the bottom.

Quick check with the string. On L=(w−3)2L = (w - 3)^2, take w=0w = 0 (height 9) and w=6w = 6 (height 9). The string’s midpoint is at height 9 above w=3w = 3, and the curve there is at 0. String above curve: fine. On L=w12−w22L = w_1^2 - w_2^2, along the w2w_2 direction take w2=−1w_2 = -1 and w2=1w_2 = 1 (both height −1-1). The string’s middle is at −1-1, but the surface at w2=0w_2 = 0 is at 00, above the string. Not convex.

Mean squared error on a model that is a straight line in its weights (linear regression) is convex, and so is cross-entropy on a single softmax layer (logistic regression). As soon as we stack layers with nonlinear activations, as in post 1, convexity is lost. Deep learning trains on non-convex landscapes anyway, and it works far better in practice than the theory promises.

What to remember

Try it yourself

Sources