Sigmoid & Probability
The sigmoid turns a score into a number between 0 and 1. Whether that number is a probability is a fact about calibration on the deployment distribution, not about the function.
The problem, the obvious approach, and why it breaks
Every lesson starts where the work starts: someone has a problem, and the first model that comes to mind looks fine offline.
The model output is 0.8. Under what conditions does that mean 80%, and what do class weights, resampling and a changed base rate do to it?
A medical-billing company scores insurance claims for the chance of denial and shows the score to billing staff as "denial risk: 80%". Staff have started ignoring it because "the 80% ones mostly go through". The team lead asks whether the model is wrong or the number is.
The output of a sigmoid is between 0 and 1, so it is a probability. Balance the classes so the model learns the minority class, train, and show the output as a percentage.
Up-sampling positives to 50% teaches the model that denials are six times more common than they are. Every score is inflated; "80%" claims are denied far less often than 80%, and staff learn to distrust the number.
- Up-sampling positives to 50% teaches the model that denials are six times more common than they are. Every score is inflated; "80%" claims are denied far less often than 80%, and staff learn to distrust the number.
- The model was trained under one base rate and deployed under another. Even without resampling, the two payers with new rules have a denial rate the intercept never saw; their scores are systematically too low.
- The threshold for "pre-review" was set at 0.5 on the balanced training data, which corresponds to a much lower probability on the real distribution; the review queue is several times the size anyone planned.
- Nobody plotted a reliability curve, so the mismatch between "80%" and the observed frequency was discovered by staff intuition, months after launch (Calibration).
What is being predicted, and from what data
This domain leads with these two. A target nobody defined precisely is a label nobody can trust, and a dataset nobody can describe is a model nobody can debug.
- Predict whether a submitted claim will be denied by the payer. The label is the payer's denial response, which arrives in two to six weeks and is sometimes reversed on appeal (Label Quality).
- The score is consumed as a probability by a human deciding whether to pre-review a claim, so the *value* matters — 80% is a promise about a frequency, not just a rank.
- One example is one claim: payer, procedure codes, amount, provider, days since service, and prior denial rate for the payer–procedure pair.
- Denials are around 8% of claims. The training set was built with the positive class up-sampled to 50% because "the model needs balanced data".
- Two large payers changed their rules after the training window, and their denial rate is now well above the historical figure.
How it actually works
Precisely enough to predict its behaviour — not a framework API.
- The sigmoid is the inverse of the logit: if p = σ(z) then z = log(p / (1 − p)), the log-odds. A linear model in z is a model in which each feature adds a constant amount of log-odds; the intercept b is the log-odds when every feature is zero, and it absorbs the base rate.
- Training on data with base rate π′ instead of the true π shifts the fitted intercept by approximately log(π′/(1−π′)) − log(π/(1−π)). Class weighting has the same effect: weighting positives by k is equivalent, to first order, to adding log(k) to the intercept. The slope weights barely change; the whole score distribution slides.
- So a resampled or reweighted logistic regression is not miscalibrated in a mysterious way — it is calibrated to the *wrong prior*, by a known constant that can be subtracted back: z_corrected = z − log(k).
- Calibration is a property of the (model, population) pair. A model calibrated on last year's claims is calibrated on this year's only if the base rate and the feature–label relationship held; a payer rule change breaks it for that payer without touching the others (Concept Drift).
Log-odds, and where the base rate lives
Invert the sigmoid and the model is linear in log-odds: log(p/(1−p)) = w·x + b. Each feature adds or subtracts a fixed amount of log-odds; the intercept is the log-odds with every feature at zero, which after standardisation means "an average claim". The base rate of the training set therefore sits in b.
Change the base rate the model was trained on — by resampling, by class weights, or by the world moving — and b moves by the difference in log-odds while the slopes stay put. On a plot of the sigmoid this is a horizontal slide of the whole curve; every score changes, every ranking stays the same.
1import numpy as np2 3def logit(p):4 return np.log(p / (1 - p))5 6# trained with positives upsampled from pi_true=0.08 to pi_train=0.507pi_true, pi_train = 0.08, 0.508shift = logit(pi_train) - logit(pi_true) # ≈ log(1/0.087) ≈ 2.44 of log-odds9 10def corrected_probability(z_trained):11 # z_trained = w·x + b as fitted on the resampled data12 return 1 / (1 + np.exp(-(z_trained - shift)))13 14# sanity check on an honest held-out set:15# corrected_probability(z).mean() should be close to the observed denial rateThe correction is exact for a well-specified logistic regression and a good first-order fix otherwise. It does not repair a *bent* reliability curve; for that, fit a recalibration map on an honest held-out period.
A probability is a claim about the deployment population
"80% of the claims scored 0.8 are denied" is a statement about a population. The model learned it on last year's claims under last year's payer rules. It stays true this year only if the base rate and the feature–label relationship stayed put. Two payers changed their rules; for their claims the model's "80%" is a stale frequency and the staff are right to distrust it.
This is why calibration is checked on a held-out *later* period and per segment, and why it is monitored rather than certified. It is also why the honest display is sometimes a rank or a band: a rank survives an intercept shift, a percentage does not.
The base rate of denial on served claims, per payer, is close to what the (corrected) intercept encodes.
holds when Payer rules and the claim mix are stable; the correction for any resampling is applied in the serving path.
breaks when A payer changes its rules, the claim mix shifts towards a high-denial procedure, or a retrain on a resampled set is deployed without the correction.
respond If the reliability curve shifted, recalibrate the intercept on recent labels; if it bent, the relationship changed and a retrain is a candidate — with the per-payer plot as the evidence.
"Denial risk: 80%" — computed by a model trained at 50% prevalence and never checked on a later period. Staff learn within weeks that it is not 80%.
Either the intercept-corrected, recalibrated probability with a per-payer reliability check behind it, or "high / medium / low" derived from rank, which makes no frequency promise.
A displayed percentage is a promise a human will test against experience. If the promise cannot be kept on the deployment distribution, make a weaker promise that can.
When the number matters and when it does not
If the score only orders claims — review the riskiest fifty each morning — a constant shift changes nothing. If the score is multiplied by the claim amount to decide whether pre-review is worth its cost, the shift changes every decision. The consumer decides whether calibration is a requirement or a nicety.
The confusion matrix at the deployed threshold is the concrete version of this. Under the inflated scores the 0.5 threshold sat far down the real distribution, so the review queue contained many claims that were never at risk.
Illustrative counts. The false-positive column is what an intercept shifted by roughly two and a half units of log-odds looks like: the same ranking, the same denials caught, and a review queue nobody planned for. Correct the intercept and the queue shrinks without a single ranking changing.
How to build it
Most important first.
- Do not resample or reweight to "balance" a logistic regression unless you need to; the imbalance lives in the intercept and the model handles it. If you must, correct the intercept back or recalibrate on an unresampled held-out set.
- Check calibration on a held-out *later* period with a reliability curve, per payer, before displaying any score as a percentage (Calibration, Evaluation Slices).
- Display a probability only if it will be used as one — an expected-value decision, a human reading it as a frequency. If the consumer only needs a ranking or a queue, display a band or a rank (Prediction vs Decision).
- Choose the review threshold on the real distribution's costs, not at 0.5 on the training data (Threshold Selection).
- Monitor the mean predicted probability against the observed denial rate per payer as labels arrive; a gap is the earliest sign the prior moved.
What to measure
Which number actually maps to the decision — and which numbers look relevant and are not.
- The reliability curve: observed denial rate in each predicted-probability bin, on a held-out later period, per major payer. This is the number that answers "does 80% mean 80%".
- Mean predicted probability against observed base rate, weekly, per payer — a one-number calibration monitor that works as soon as labels arrive.
- Ranking metrics like ROC AUC look relevant and are completely unaffected by an intercept shift; a model can be perfectly ranked and lie about every percentage (ROC AUC).
What must stay true after deployment
The field this whole domain exists for. A model is a set of assumptions with weights attached; these are the ones a monitor or a test should be checking.
- The base rate of denial on the served claims, per payer, stays close to the base rate the intercept encodes — a monitor on observed rate against mean predicted probability checks it.
- The serving path uses the corrected score, with the same intercept adjustment the calibration check was run on; a contract test on a fixed claim can pin the exact output.
- Staff read the number as a frequency and act on it as such; if they have learned to ignore it, the model's calibration no longer matters and the display should change.
- Offline: reliability curve and expected calibration error on a held-out later period, per payer; the intercept correction checked by comparing mean predicted probability to the true base rate.
- Online: weekly observed denial rate against mean predicted probability, per payer, as decisions come back; the review-queue size against plan.
- Over time: recalibrate — not retrain — when only the base rate has moved; retrain when the reliability curve bends rather than shifts (Retraining as a Decision).
What can go wrong
- The intercept correction is applied in training but the serving code was copied from the balanced-data notebook and applies its own threshold to the uncorrected score.
- Calibration is checked globally and holds; the two payers with new rules are badly miscalibrated in opposite directions and cancel in the aggregate.
- The reliability curve is computed on the same period as training, which is leakage of the base rate; it looks fine and says nothing about deployment.
- Refusing to resample keeps the probabilities honest and can leave a very rare class with too little gradient signal in the slope weights; the fix is more positives or a different model, not a distorted prior.
- Per-payer calibration monitoring is one monitor per payer, each of which needs enough labelled claims to say anything, and the small payers never will.
- Recalibrating on a recent period gives an honest probability and burns that period's labels, which then cannot be used to evaluate the recalibrated model.
- "The output is between 0 and 1, so it is a probability." It is a sigmoid of a score. It is a probability of the deployment event only if a reliability curve on the deployment distribution says so.
- "We balanced the classes so the model learns the minority class." You told the model the minority class is six times more common than it is. The slopes are nearly the same; the intercept is off by log(6), and every displayed percentage with it.
- "ROC AUC is unchanged, so the model is fine." AUC is invariant to a constant shift in the scores. It cannot see that every percentage is wrong.
Where this applies
ML advice is stated as universal far more often than it is. These labels say what each claim is specific to — and where CONTESTED appears, the note gives the strongest form of the opposing view.
- MODEL-SPECIFICThe "reweighting shifts the intercept by log(k)" result is a property of logistic regression's log-loss objective; for tree ensembles and neural networks reweighting distorts scores in a way that is not a constant shift and needs a fitted recalibration (Calibration).
- DOMAIN-SPECIFICWhere the probability is shown to a human or fed into an expected-value calculation (medical, credit, insurance) calibration is the product; where the consumer is a top-k ranking (ads, recommendations) a miscalibrated but well-ordered score costs nothing until someone multiplies it by a value.
- SIMPLIFIEDThe 8% base rate, the 50% resampling and the "80%" display are illustrative; the intercept-shift mechanism is exact for logistic regression and approximate elsewhere.
Where the depth lives
This domain teaches the model and hands the rest off by name.
- — Probability theory — Bayes' rule is why the prior is an additive term in log-odds: log-odds posterior = log-odds prior + log likelihood ratio, and a linear model is a model of the likelihood ratio.