Softmax and temperature
In one line
Softmax turns scores into probabilities that sum to one; temperature decides how sure those probabilities sound, and calibration makes them honest.
Prefer small steps? Guided mode walks through the same ideas one at a time.
Why it exists
A classifier ends with one number per label. Picking the largest is easy, and for a demo that is enough. Production needs a second decision: is the largest one large enough to act on, or should this input go to a human?
That second decision needs a number with a meaning — "the model is 80% sure, and when it says 80% it is right about 80% of the time". Raw scores do not have that meaning. Softmax gives them the right shape, and temperature, chosen against labelled data, gives them the right size. Skip either and every threshold you set downstream is a guess.
Scores rank, they do not promise#
Whatever produces the scores — against a prototype per label, or the of a small classification head on an — the output has the same limits. The numbers put the labels in order. They do not sum to one, they are not bounded the same way across models, and their absolute size means little.
Take a support ticket that scores 0.58 against Billing and 0.40 against Account. Billing ranks first; that part is reliable. But swap the encoder and the same ticket might score 0.81 and 0.77, with the same order and a very different-looking gap. Neither pair is a probability. Reading 0.58 as "58% likely" is the same mistake as comparing timestamps from two machines whose clocks were never synced: the ordering within one source holds, and the values across sources mean nothing.
Temperature: how sure the numbers sound#
is a single number, , that every score is divided by before softmax. At nothing changes. Below one, gaps grow and the winner's share rises; above one, gaps shrink and shares drift toward even. It is the same knob a chat model exposes for sampling, used here for a different purpose: to set confidence rather than variety.
Temperature never changes the winner — dividing every score by the same positive number keeps the order — so it cannot make a classifier more accurate. What it changes is the claim. At the ticket's 0.18 gap becomes 9, and Billing gets about 99.99%. Same ranking, a far stronger promise.
The right is the one that makes the promise true. That property is : among all predictions stated at about 80%, about 80% should be correct. You find it by measurement. Hold out a the model never trained on, try a range of values, and for each one compare stated confidence with observed accuracy, band by band. Keep the where they agree. Then a threshold on that number can decide whether to answer or to fall back to .
The math
Softmax with temperature, for label out of with score :
With two labels only the gap matters. For the ticket, , and at :
When you only have probabilities, not scores, temperature still applies: take the log, divide by , exponentiate and renormalise. The first three steps collapse into a power:
So at , probabilities of 0.7 and 0.3 become 0.49 and 0.09, which renormalise to about 0.84 and 0.16.
Worked example
Two tickets, two labels, a confidence threshold of 80%. Scores are cosine similarities to each label's prototype. The numbers are illustrative.
Billing Account gap
ticket 1 "charged twice" 0.58 0.40 0.18
ticket 2 "update my card" 0.50 0.45 0.05
Read at three temperatures, the Billing share for each:
tau = 1 tau = 0.1 tau = 0.02
ticket 1 54% 86% 99.99%
ticket 2 51% 62% 92%
At the model never clears 80%, so everything goes to a human and the classifier does no work. At both tickets clear it, including ticket 2, where the model barely leans at all. At ticket 1 is answered and ticket 2 is routed to a person — which is the behaviour you wanted, but only the validation set can tell you that 0.1 is the right value.
Suppose it does: across held-out tickets, the ones stated at about 85% were right about 84% of the time at , and the ones stated at 99% were right only about 80% of the time at . The first is calibrated; the second is a model promising far more than it delivers. The winner was Billing in every column. Only the decision to answer changed.
Gotchas
-
Reading raw similarity as a percentage. A cosine of 0.9 is an angle, not a chance, and its meaning shifts between encoders. Only a calibrated output can be read as "90% sure", and only for the model and data it was calibrated on.
-
Choosing temperature by feel. A low makes outputs look decisive and demos look good. It also turns slight leans into 99% claims, and a confident wrong answer is the most expensive kind. Fit on a validation set and refit it when the encoder, the labels or the traffic change.
-
Forgetting to renormalise. for one label, or without dividing by the new total, is not a probability. Everything downstream — a threshold, a blend of two scorers — silently inherits the error.
-
Comparing top-label shares across tasks. The winner's share falls as the number of labels grows: 54% with two labels can be the same lean as 8% with fourteen. Set thresholds per task, from that task's validation data, never borrowed from another model.
Mental model
Think of a health-check score behind a load balancer. For choosing the best backend, any score works as long as it ranks them — that is softmax on raw scores. For deciding whether to send traffic at all, the score has to mean "the probability this request succeeds", measured against real outcomes, the way an SLO is. Temperature is the calibration that turns the first kind of number into the second. Ranking decides what; calibrated confidence decides whether.
In practice
Problem statements that lean on this topic. Rated by the phase that makes them land.
A spam filter and a chatbot are not the same kind of thing
The word "AI" covers two products with opposite shapes — one has a right answer and one has better and worse ones — and the shape decides everything downstream.
no prerequisites · 4 min · #framing #classification #evals
Routing tickets with the wrong kind of model
A large chat model can sort tickets into queues, at two hundred times the cost of a small classifier that does it better — because the output is a label, not a sentence.
after phase 1 · 4 min · #classification #cost #architecture
The same question gave two different answers
The randomness in a model's output is a setting, not a property; for anything you will compare, test or parse, it should be switched off — and knowing where it lives is the whole trick.
after phase 2 · 3 min · #testing #evals #debugging
Done reading?
Nothing marks itself complete. Say so only when you could explain this to someone else.
This topic has 3 subtopics.
Roadmap · 6 steps and a recapshow
Raw scores are not probabilities
A classifier ends with one score per label. Say a support ticket scores 0.58 against Billing and 0.40 against Account.
Those numbers put the labels in order, and that is all they do. They are not required to sum to 1. Their size depends on the model: swap the encoder and the same ticket might score 0.81 and 0.77. The order held; the values did not.
So a raw score can pick a winner. It cannot tell you how sure to be.
Still confused? Isn't a score of 0.9 already 90%?
Only if something made it so. A number reads as a probability when two things hold: all labels' values sum to 1, and a stated 90% comes true about 90% of the time. Raw scores have neither property. The next steps add them, one at a time.
The pattern
Compare scores only within the system that produced them, like timestamps from one clock.
Softmax: scores become shares
Take three scores: 2, 1 and 0.
Raise (about 2.718) to each one: 7.39, 2.72 and 1.00.
Add them up: 11.11.
Divide each by that total: about 67%, 24% and 9%.
That is . Every share is positive, the shares sum to 100%, and the order is the same as the scores' order. A gap of 1 between two scores became a ratio of about 2.7 between their shares: turns differences into ratios.
Still confused? Why e to the score, rather than just dividing each score by the total?
Scores can be zero or negative, and dividing 2 and −1 by their total gives nonsense. is always positive. It also makes shares depend only on the gaps between scores: add 10 to every score and the shares stay 67%, 24% and 9%.
The pattern
Normalise by the total, so each share is relative to the alternatives, like request counts turned into traffic percentages.
Close scores stay close
Back to the ticket: Billing 0.58, Account 0.40.
is about 1.79 and about 1.49. Divide by their total and Billing gets about 54%, Account about 46%.
Billing still wins, but the model is barely leaning. That is the honest reading of these scores. Cosine scores between texts sit in a narrow band, so their gaps are small, and softmax on a small gap gives near-even shares.
Nothing is wrong with the arithmetic. This scale was simply never meant to be read as confidence.
Still confused? What happens with 14 labels instead of 2?
The shares spread thinner. With a winner at 0.58 and thirteen others near 0.40, softmax gives the winner about 8%, even though it clearly ranks first. A low top share is normal with many labels, which is why confidence bars are set per task, never borrowed from another one.
The pattern
Keep "which one" and "how sure" as separate questions; a correct ranking can carry weak confidence.
Temperature: stretching the gaps
is one number, (tau). Every score is divided by it before softmax.
At nothing changes. A smaller makes gaps bigger. At , the 0.18 gap between Billing and Account becomes , and softmax gives Billing about 99.99%.
Same ticket, same winner, a far stronger claim. A larger does the opposite: gaps shrink and shares drift toward even.
Chat models expose the same knob to vary their wording. Here it sets confidence instead.
Still confused? Does temperature ever change the winner?
No. Dividing every score by the same positive number keeps their order, so the top label stays on top. Only the share it gets changes.
The pattern
A scale factor never changes an order, only how strongly the order is stated.
Choosing τ: make 80% mean 80%
Pick with data, not by feel.
Take a : labelled examples the model was not trained on. For each candidate , gather the predictions stated at about 80% and check how many were right.
If only 60% were right, the model is overconfident: raise . If 95% were, it is underconfident: lower . Keep the value where stated and observed agree across the range, not just at 80%.
That agreement is called .
Still confused? People say calibrated scores are "on a comparable scale". What does that mean?
That an 80% from this model and an 80% from another both come true about 80% of the time. That shared meaning is what later lets you blend two scorers, or set one confidence bar for both.
Still confused? How much validation data is enough?
Enough that each confidence band holds a few dozen predictions. With fewer, the observed rate in a band swings too much to tune against. Module D covers how much it swings.
The pattern
Treat a confidence number as a contract and test it against outcomes, the way you test an SLO.
Temperature on probabilities you already have
Sometimes you only get probabilities, not scores: a service returns 70% and 30%. You can still apply temperature.
Take the log to get back to scores, divide by , raise again, then divide by the new total. The first three moves collapse into one power:
With the power is 2: 70% and 30% become 0.49 and 0.09, which renormalise to about 84% and 16%.
Still confused? Does it still sum to 100%?
Not straight after the power: 0.49 + 0.09 = 0.58. Dividing by that total is what makes it a distribution again. Skip it and every threshold downstream is off.
The pattern
Apply a knob in the space it was defined in, then convert back.
Recap
Raw scores rank labels; they do not promise anything. turns them into shares that sum to 100%, using so that gaps become ratios. Close scores give close shares, and that is the honest reading.
divides the scores before softmax. It stretches or squeezes the confidence without ever touching the ranking. Choose it on a , so that 80% comes true about 80% of the time — that is . Then a confidence bar on that number can decide whether to answer at all, or to pass the input to a person.
Ranking decides what. Calibrated confidence decides whether.
Patterns from each step
- Compare scores only within the system that produced them, like timestamps from one clock.
- Normalise by the total, so each share is relative to the alternatives, like request counts turned into traffic percentages.
- Keep "which one" and "how sure" as separate questions; a correct ranking can carry weak confidence.
- A scale factor never changes an order, only how strongly the order is stated.
- Treat a confidence number as a contract and test it against outcomes, the way you test an SLO.
- Apply a knob in the space it was defined in, then convert back.