Softmax for Multi-Class Output
Softmax turns raw scores into a probability distribution for multi-class classification, and its clean gradient with cross-entropy.
The obvious way to turn three scores into three probabilities
Divide each score by the sum of the scores. It costs nothing and it obviously adds to 1.
All three of those sum to exactly 1, which was the only property the method was built for, and none of the last two are probabilities.
Before this page - 4 pages4
Output Activations
logits, the task-to-activation decision table, and the multi-class head this page opens upLoss Functions
cross-entropy, which this page pairs with softmax rather than redefinesThe Single Neuron
e as a fixed number, which is the whole mechanism on this pageLayers and the Forward Pass
the rain network, which produces the three logits in rung 2 rather than having them handed over
Three sliders, three bars. Push one up and watch the other two fall without your touching them, which is the property this whole page is about.
The sliders move in steps of 0.01, so nudging one after loading a preset will round it. Reload the preset to get the exact logits back.
0:13What this animation shows
Three bars, labeled class A, B, and C, start at heights 0.66, 0.24, and 0.10 with those values captioned above each bar, and "sums to 1.00" beneath. The bars then redistribute, with class B growing to become the dominant bar while the others shrink, and the values update and still sum to 1.00. This is softmax in action: turning a set of raw scores into a genuine probability distribution across classes.
Bars always sum to 100% - raising one steals mass from the others.
The second button loads the three logits the rain network produced for dry, drizzle and downpour. The widget's own labels say cat, dog and bird, and they are not being renamed: read the first slider as dry, the second as drizzle and the third as downpour while that preset is loaded.
Set all three logits to the same number. Any number you like. Before you look at the bars: what are the three probabilities? Then add 1.00 to all three and look again.
Commit to a guess, then open this
Exactly 33.3% each, whatever number you chose. And after adding 1.00 to all three, still exactly 33.3% each.
That is not a rounding coincidence. Adding the same constant to every logit multiplies every exponential by the same e^c, in the numerator and in the denominator, where it cancels exactly. Only the differences between logits ever matter. The absolute level carries no information at all.
That fact looks like trivia and is load-bearing twice over. It is why one of the three output biases is redundant and could be pinned at zero forever. And it is what makes the single most important line in every real softmax implementation legal, which rung 5 gets to.
Softmax turns unbounded scores into competing shares. It does it in two steps, and the first one is the interesting one: run every score through e^x, which makes every number positive without disturbing which is largest, then divide each result by their total, which makes them add to exactly 1. The consequence is that these outputs are not independent. Raising one score lowers every other probability automatically, because there is one hundred percent to distribute and it is always fully distributed.
Election night
Raw vote counts become percentages by dividing by the total, which is exactly the method that failed at the top of this page, and it works there for one reason: you cannot cast a negative vote. Scores out of a network can be negative, so softmax does one thing first: it runs every score through e^x, which turns any number, however negative, into a positive one without changing who is ahead of whom. Then it divides. And it has a consequence a returning officer would recognise: nobody's share can go up without somebody else's going down, because there is exactly one hundred percent to hand out.
Where it breaks downvotes are counted once and stop moving. A network's logits keep changing during training, so the shares are being redistributed at every step.
WordsWhat we're asking for, and why the obvious idea failsThree requirements stated before any formula, then the divide-by-the-total idea taken apart.Rung 01
Sigmoid answers a yes/no question. "Cat, dog, or bird?" needs a probability distribution spread across several options at once, not an independent yes/no per option. Softmaxdoes exactly that: e to the power of one class's score, divided by the sum of e to the power of every class's score.
Before the formula, the requirements. You have three raw scores out of the last layer, one per class, and you want three probabilities. Whatever turns one into the other has to satisfy three things:
- Every output is positive. There is no such thing as a -12% chance.
- The outputs add up to exactly 1. If exactly one of the three classes is true, the confidence has to be fully distributed among them with nothing left over.
- A bigger score gives a bigger probability. If the network scored "cat" above "dog", the cat probability must come out above the dog probability. The ordering must survive.
Why not just divide by the total?
The block at the top of this page, taken apart. Divide each score by the sum of all the scores. It costs nothing and it obviously sums to 1. On (2.0, 1.0, 0.1) it gives (0.645161, 0.322581, 0.032258), which looks fine. On (2.0, -1.0, 0.1) it gives (1.818182, -0.909091, 0.090909): still sums to 1, and complete nonsense, a probability of 181.8% and a probability of -90.9%. Requirement 1 is broken. And on (1.0, -1.0, 0.0) the sum is exactly 0 and the method divides by zero.
Both failures come from the same source: raw scores can be negative, and the fix has to be something that turns any number, however negative, into a positive one, without breaking the ordering. e^x does exactly that. It is positive for every input without exception (e^-1000 is a very small positive number, never zero and never negative), and it is strictly increasing, so a bigger score always produces a bigger e^score. Requirements 1 and 3 are satisfied by the exponential itself; requirement 2 is satisfied by dividing by the sum afterwards.
Watch it fix the broken case:
Three genuine probabilities, ordering preserved, no division by zero possible because a sum of positive numbers is always positive.
There is a cost, and it is worth naming. Exponentials grow fast, so softmax exaggerates differences. A logit gap of 1.0 becomes a probability ratio of e^1 = 2.718, so "cat scored one point higher than dog" becomes "cat is 2.7 times more likely than dog". That amplification is deliberate and it is where the "soft max" name comes from: the function is a smoothed version of "pick the largest and give it everything".
NumbersFrom two inputs to three probabilities, with no gapsThe whole chain, input to loss to gradient, plus the shift-invariance check.Rung 02
Worked example - logits z=[2.0, 1.0, 0.1] for cat/dog/bird: e²=7.389056, e¹=2.718282, e^0.1=1.105171, summing to 11.212509. Dividing each by that sum gives p=(0.659001, 0.242433, 0.098566), which sums to 1.000000, a genuine probability distribution.
Where the three logits come from
This page has been handing you three numbers. Here is a network producing them, so the chain from input to probability is unbroken. Same small rain network as the rest of this module: two inputs, two tanh hidden neurons, now with three output neurons instead of one, because there are three classes.
Read the gradient signs. The two wrong classes get positivegradients, meaning "push these logits down". The correct class gets a negativegradient, meaning "push this logit up". And the sizes are exactly how wrong each one was. dry was already at 2.3%, so its correction is tiny at 0.022533. drizzle at 14.7% gets a firmer shove at 0.146623. Softmax with cross-entropy gives you a correction proportional to the error and nothing else, which is the whole reason this pairing is standard.
One arithmetic check on that gradient: the three components sum to 0.022533 + 0.146623 - 0.169156, which is 0.000000. That is not a coincidence and it happens every time. The probabilities sum to 1, the one-hot label sums to 1, so p - y always sums to 0. Softmax cannot raise one logit without lowering the others; the gradient enforces the same coupling the forward pass has. (The printed six-decimal values happen to cancel perfectly here. They will not always, and if you run this check on other numbers and land on 0.000001 rather than 0.000000 that is the rounding, not a broken gradient. The reason just given is the proof; the addition is only a spot check.)
Shifting every logit changes nothing
Add the same number to all the logits and the probabilities do not move. Not approximately, exactly.
The reason is one line of algebra. Multiplying every exponential by the same constant e^-c multiplies the numerator and the denominator by e^-c, and it cancels. Only the differences between logits ever matter. The absolute level is meaningless, which is another way of saying one of the three output biases is redundant: you could pin it at zero forever and lose nothing at all.
PictureWhat the exponential actually does to three numbersThe failing case from the top of the page, drawn before and after e^x.Rung 03
The bars on the stage figure are the probabilities and they always fill the track exactly. That is not a drawing convention, it is the constraint: raising one bar takes width from the others, because there is one track and it is full.
Drag the third slider up on its own and watch the first two shrink without your touching them. Nothing about the first two classes changed. Their scores are identical. Their shares fell because somebody else's share rose.
The top panel is the three raw scores from the break at the top of this page, one of which hangs below the axis. Dividing by the total at that point produces a negative share, and if the three happened to sum to zero it produces nothing at all. The bottom panel is the same three numbers after e^x: every bar is now above the axis, and the ranking strip under each panel is identical, first, third, second, before and after. That is requirement 1 fixed with requirement 3 left untouched, which is exactly what the exponential was chosen for.
EquationThe formula and its gradientThe formula, an honest note about why it is not derived line by line, and a finite-nudge check of the result.Rung 04
This next result is one of the least obvious "nice" identities in this subject. Unlike the sigmoid case on the output-activations page, walking through every step here requires tracking how changing one logit shifts every output probability at once, since softmax ties all the outputs together. We're going to state the result and confirm it numerically, rather than derive it line by line.
Here's a genuine independent check, not a restatement of the formula: nudge just the "cat" logit by 0.001 (z=[2.001, 1.0, 0.1]), recompute softmax and the cross-entropy loss for the true class cat, and measure the change. The measured slope comes out to ≈−0.3409; the predictedgradient, p_cat−1 = 0.659−1 = −0.3410, matches to three decimal places, the same small gap you'd expect from the earlier finite-nudge check, not a coincidence. The general rule, holding for every class at once, is ∂L/∂zᵢ = pᵢ−yᵢ - for this example, the full gradient is [−0.341, 0.242, 0.099].
General caseSoftmax as it is actually implemented and usedThe max-subtraction trick, softmax over two classes, temperature, and when you can skip softmax entirely.Rung 05
Why every real implementation subtracts the maximum
Shift invariance is not a curiosity. It is what makes softmax computable.
e^x overflows fast. In standard 32-bit floating point the largest representable number is about 3.4 * 10^38, and e^88 is already 1.65 * 10^38, so e^89 overflows to infinity. Logits in the tens are routine, and it does not take much beyond that to cross the line, so the naive formula produces inf / inf, which a computer reports as NaN(short for "Not a Number", the value it returns when it has been asked for something undefined). NaN then propagates through the rest of the model, poisoning every number it touches, and destroys the run.
Subtracting the maximum makes the largest shifted logit exactly 0, so the largest exponential is exactly e^0 = 1 and nothing can ever overflow. The smallest ones may underflow to 0, which is harmless: they were negligible anyway, and the sum still contains that guaranteed 1, so the denominator can never be zero.
Confirm on the page's own numbers that the trick changes nothing:
This is also the concrete reason the previous page's gotcha exists. When PyTorch's CrossEntropyLoss takes raw logits rather than probabilities, it can do this subtraction and combine the log with the exp internally, cancelling them algebraically instead of computing both. Hand it probabilities and you have already thrown away the numbers it needed.
Softmax over two classes is sigmoid
The last two pages have presented sigmoid and softmax as two different tools. They are the same tool.
Since only logit differences matter, a two-class softmax has one meaningful number in it, the gap between the two logits, and softmax of (z, 0) reduces algebraically to 1 / (1 + e^-z), which is sigmoid. Verify it on any pair with the same gap:
So binary classification with a sigmoid is not a special case that happens to work. It is softmax with the redundant second logit removed, and using one output instead of two saves a parameter that could never have meant anything.
Temperature
One knob, worth knowing because you have already used it. Divide every logit by a number T before applying softmax.
Small T divides the logits by a small number, which spreads them further apart, which the exponential amplifies further still: the top class approaches 100% and the rest approach 0. Large T squeezes the logits together and the distribution flattens toward equal probabilities for everything. In the limits, Tapproaching 0 gives a hard "always pick the winner" and T approaching infinity gives a coin flip among all classes.
The ordering never changes at any temperature, because dividing by a positive number preserves order. Only the confidence changes. This is the same "temperature" setting on every text-generation interface you have used: low temperature makes a model pick its favourite word almost every time, high temperature lets less likely words through.
At inference, you often don't need softmax at all
During training you need the probabilities, because cross-entropy is defined on them. At prediction time, if all you want is "which class", you can skip softmax entirely.
The predicted class is argmax, meaning "the position of the largest number". And since e^x is strictly increasing and dividing by the same positive sum preserves order, the largest logit is always the largest probability. In our example the largest logit is downpour at 1.875071 and the largest probability is downpour at 0.830844. This holds always, not usually.
So a deployed classifier that only reports a label can read the answer straight off the logits. You need softmax when you need to report a confidence, when you need to thresholdon one ("only act if above 90%"), or when you need to compare probabilities across examples. If you only need the label, the extra step buys nothing.
Why this and not that
Why exponentiate rather than just divide by the total?
Because logits can be negative, and dividing by the total then produces negative "probabilities" and can divide by zero. e^x is the cheapest function that is positive for every input and strictly increasing, so it fixes the sign without disturbing the ranking. Step 1 and rung 1 show both failures.
Why not subtract the minimum first, then divide?
It does fix the negatives, and it breaks two other things. It changes the ratios between scores in a way that depends on the smallest score, so an irrelevant fourth class with a very low score would silently change the relative probabilities of the other three. And when all the scores are equal it makes them all zero and divides by zero anyway.
Why subtract the maximum rather than the mean?
Because the maximum is the only choice that guarantees the largest shifted logit is exactly 0, so the largest exponential is exactly 1 and overflow is impossible. Subtracting the mean shrinks the numbers, usually enough, and offers no guarantee.
Why is one of the biases redundant?
Because only differences matter. Adding a constant to all three logits changes nothing, so one of the three output biases can be pinned at zero forever with no loss of expressiveness at all. This is not a trick worth doing in practice; it is a fact worth knowing when a parameter count does not add up.
Why not use softmax for a multi-label problem?
Because the sum-to-one constraint is a claim that exactly one option is true. On a photo that is outdoor and also contains people, that claim is false, and softmax will make the two labels compete for confidence they should each hold independently. The previous page has the arithmetic.
If argmax is all I need, why compute softmax at all?
Only when you need a confidence to report, a threshold to compare against, or probabilities comparable across examples. If you need a label, the largest logit already is the answer, always, not usually.
- softmax
- "soft" means a smoothed version of a hard operation, the same prefix as softplus on the modern-activations page. "Max" is the hard operation being smoothed. And the name is arguably wrong: what it smooths is not max, which returns the largest value, but argmax, which returns which one was largest, and softmax's output is a smoothed indicator of which. Some papers call it softargmax for this reason. The wrong name won.
- temperature
- borrowed directly from statistical physics, where the Boltzmann distribution gives the probability of a state with energy E as proportional to e^(-E / kT), and T there is literally a temperature. Softmax with a temperature is the same expression with logits in place of negative energies. High temperature means a system flitting between states; low temperature means it settles into the lowest one. The metaphor is exact, not decorative.
- one-hot
- from digital electronics, where a one-hot bus is one on which exactly one line is energised at a time.
- argmax
- "the argument at which the maximum occurs", meaning the input position rather than the output value.
- logit
- defined on the previous page and unchanged: the log-odds, the inverse of sigmoid, the number before the squash.
- NaN
- "Not a Number", the value floating-point arithmetic returns when asked for something undefined, such as infinity divided by infinity. Its defining property is that it contaminates: anything computed from a NaN is a NaN.
- categorical
- in categorical cross-entropy: because the label is one of k categories rather than a yes or no.
- What is happening
- Softmax's constraint is a claim that exactly one option is true, and here it is false. The three logits loaded are a photo tagger's, for outdoor / night / people; the widget's own labels still read cat / dog / bird, so read the three sliders in that order.
- Fix
- Give each label its own sigmoid and its own binary cross-entropy term, and add the losses. Nothing about the network body changes.
- Watch for
- Read independently, the three sigmoids give
0.768525,0.377541and0.880797, summing to2.026863, which is correct and should not sum to 1. The bars on screen, softmax over the identical three logits, read0.293408,0.053601,0.652991. Outdoor fell from 76.9% to 29.3%, not because the evidence changed but because it had to give room to "people".
- What is happening
- The framework applied softmax inside its loss and you applied it before handing the values over, so a set of probabilities got treated as a set of logits.
- Fix
- Hand the loss the raw logits.
CrossEntropyLossapplies softmax itself and expects to be the only one that does. - Watch for
- The probabilities
0.659001,0.242433,0.098566fed back in as logits: the bars read0.448377,0.295617,0.256006. The distribution has gone from 65.9 / 24.2 / 9.9 to 44.8 / 29.6 / 25.6. Softmax is not idempotent; applying it a second time flattens everything toward equal, and a third time flattens it further.
- What is happening
- Only the differences between logits carry information. The absolute level is meaningless, which is rung 2's shift invariance seen from the other side.
- Fix
- Track the gaps, or track the probabilities. A logit on its own says nothing without the others beside it.
- Watch for
- This preset loads
(5.0, 4.0, 3.1), where every logit is more than double the stage's first preset, and the bars read65.9%,24.2%,9.9%- identical to six decimals. Two networks with wildly different logit scales are the same classifier.
- What is happening
- Every other logit is in the denominator. Softmax is the one activation in this module that couples its outputs.
- Fix
- Read the whole vector, never one entry. If you need genuinely independent outputs, you needed independent sigmoids, which is mistake 1.
- Watch for
- Only the third logit moved, from 0.1 to 4.0. Cat's logit is still exactly 2.0 and cat's probability has fallen from
65.9%to11.4%. Every activation on the previous three pages would have left cat completely alone.
- What is happening
- The index of the correct class does not match the index of the output unit. Nothing about this is detectable from the loss curve, because the loss is falling correctly toward the wrong target.
- Fix
- Check the label mapping against the output ordering once, by hand, on a single example whose class you know. It is a five-minute check that no metric will do for you.
- Watch for
- The logits say the model is confident about cat at
65.9%, and the correct class is set to bird. The loss reads2.317029, which is a loss you would only see from a badly broken model, and the gradient will now push the cat logit down and the bird logit up. Train on this and the model will dutifully learn to predict bird for cats.
- 01Make all three classes exactly equally likely, then find a second, completely different way to do it.
Hint
The Socratic question above is the whole answer.Answer
Any three equal logits:
(0, 0, 0)gives 33.3% each, and so does(5, 5, 5), and so does(-3, -3, -3). The absolute level never mattered. - 02Make cat exactly twice as likely as dog.
Hint
The ratio of two probabilities is e^(difference of their logits), so you want a difference whose exponential is 2.Answer
A gap of
ln(2) = 0.693147, for example cat at 2.00 and dog at 1.31, which gives a ratio ofe^0.69 = 1.993716, close enough to see on the bars. Bird's logit does not matter at all: it changes both probabilities by the same factor, so it cannot change their ratio. - 03Find two logit triples that are visibly different on the sliders and produce identical bars.
Hint
Shift, don't tilt.Answer
Any pair differing by a constant:
z = ( 2.0, 1.0, 0.1) -> p = (0.659001, 0.242433, 0.098566)z = ( 0.0, -1.0, -1.9) -> p = (0.659001, 0.242433, 0.098566)This is shift invariance, and it is what makes the max-subtraction trick in rung 5 legal rather than merely convenient.
- 04With cat as the correct class and dog and bird left at 1.0 and 0.1, find the smallest cat logit that keeps the loss under 0.50.
Hint
A loss below 0.50 means p_cat above e^-0.5.Answer
About
1.78.e^-0.5 = 0.606531, so you needp_catabove that, and the crossing is at a cat logit of1.7740, giving a loss of exactly0.50. At 1.78 the probability is0.607984and the loss is0.497607. - 05Hardest. Show that raising the correct class's logit by 1.0 and lowering one wrong class's logit by 1.0 are not the same operation, even though both increase the gap by 1.
Hint
There are three logits, and only two of them are involved in either move.Answer
start z = (2.0, 1.0, 0.1)raise cat z = (3.0, 1.0, 0.1) -> p = (0.840083, 0.113693, 0.046224)lower dog z = (2.0, 0.0, 0.1) -> p = (0.778268, 0.105327, 0.116405)Different, and notice bird: it went down in the first case and up in the second, without being touched in either. Only the full pattern of differences decides anything, and a move that changes one gap always changes the others too. This is the coupling from mistake 4, stated as an exercise.
- The temperature sliderThe one in every chat interface you have used is the T on this page, dividing the model's logits before softmax. Turn it down and the model picks its top token nearly every time; turn it up and less likely tokens get through.
- Your photo app's taggerThe other place you meet softmax daily is the last layer of every object and face tagger, where the 97% printed under the label is one number out of a set that was forced to add up to a hundred.
Softmax is one cake, cut by exponentials.
Nobody gets a negative slice, the slices always finish the cake, and a one-point lead in score is a 2.7-times bigger piece. Only the gaps between the scores decide anything: add a hundred to everybody and not one crumb moves.
Everything in this module has been one network, hand-set, on one example, with you doing the arithmetic. Nothing on any of these pages has learned anything: every weight you have seen was chosen by a person so the numbers would come out readable. The playground is where those nine numbers stop being yours.
And the honest limit of the whole module. A fully connected network of the kind you have been reading treats a 28-by-28 image as 784 unrelated numbers, with no idea at all that two neighbouring pixels have anything to do with each other. Everything you have learned still holds exactly. It is simply not enough for a picture, and the fix has its own module.