Logistic regression and softmax classification
Turning a linear score into a probability — and why that is a neuron
Logistic regression is the simplest classifier worth understanding deeply, and it is secretly a one-layer neural network with a sigmoid or softmax output. Its loss — cross-entropy derived from a Bernoulli likelihood — is the loss of every classifier and every language model in this path (4.3 Loss functions catalog, 7.6 Decoder-only: GPT and autoregressive generation), and its gradient is the gradient that flows out of every softmax layer (4.4 Backpropagation, fully derived).
You'll be able to
- Explain why a sigmoid of a linear score is the right model for a binary probability, via log-odds
- Derive binary cross-entropy as the negative log-likelihood of a Bernoulli model
- Derive the gradient Xᵀ(p̂ − y)/n and explain why there is no closed form but the problem is convex
- Generalize to softmax regression for K classes and state its gradient
- Choose decision thresholds under class imbalance and judge whether predicted probabilities are calibrated
- Recognize logistic regression as nn.Linear + sigmoid and implement it in NumPy and PyTorch
Key ideas
- Logistic regression models the log-odds as a linear function: log(p/(1−p)) = wᵀx + b, so the decision boundary p = 0.5 is a hyperplane.
- Binary cross-entropy is the negative log-likelihood of a Bernoulli model; wrong-and-confident predictions are punished without bound.
- The gradient at the logit is p − y, so ∇J = Xᵀ(p̂ − y)/n — the same 'features × errors' form as linear regression.
Show 5 more key ideas
- No closed form, but the loss is convex (Hessian XᵀSX ⪰ 0), so gradient descent or Newton/IRLS finds the global optimum; separable data need L2 regularization.
- Softmax regression generalizes to K classes with p_c = e^{z_c}/Σ e^{z_k}, loss −log p_y and gradient p − y_onehot; it is shift-invariant.
- A threshold is a decision, not part of the model; move it with costs and class imbalance, and check calibration with reliability diagrams.
- Logistic/softmax regression is nn.Linear plus sigmoid/softmax — a one-layer neural network; every classifier head and LM output layer is one.
- Compute the loss from logits (log(1 + e^{−z})) rather than from probabilities to avoid log(0).
Suggested path through this lesson
Why not regress on the label?
If labels are you could fit a line to them, but a line predicts values below 0 and above 1, and far-away points drag it around even when they are already classified correctly. What you want is a model of the probability that stays in and whose loss stops caring about a point once it is confidently right. Logistic regression is the minimal such model.
Sigmoid and log-odds
Keep the linear score and squash it with the sigmoid (logistic function):
Inverting it explains the model: . The log-odds (logit) is linear in the features, so each unit increase in multiplies the odds by — that is how you interpret a coefficient. The decision boundary is , a hyperplane: logistic regression is a linear classifier; the nonlinearity only shapes the probabilities around that plane. In the demo, set the hidden layer to zero and you are looking at exactly this boundary; add a hidden layer and you will see what one more layer buys (4.1 From perceptron to MLP; universal approximation).
The loss: cross-entropy from a Bernoulli likelihood
Model each label as a coin flip with probability : . The likelihood of the dataset is the product over , and its negative log is the binary cross-entropy (1.9 Information theory: entropy, cross-entropy and KL divergence):
Each term is the surprise of the true label under the model: predicting for a positive costs ; predicting for it costs . The loss is unbounded above, which is why wrong-and-confident is punished so hard, and why numerically you compute it from the logit as for (the "with logits" losses in 2.4 PyTorch I: tensors, autograd and the training loop) rather than from , which can round to exactly 0 or 1.
The gradient (and why it looks familiar)
Differentiate one term with respect to : . Multiply by :
The messy pieces cancel to the cleanest possible result: the error signal at the logit is prediction minus truth. Chain through and stack over examples:
Compare 3.2 Linear regression: linear regression's gradient was . Same shape — "features times errors" — with the prediction passed through a sigmoid. This is not a coincidence: both losses are negative log-likelihoods of exponential-family models, and for all of them the gradient is .
There is no closed form because depends on nonlinearly, so we iterate. But the problem is convex: the Hessian is with , which is positive semidefinite (1.3 Eigen-things, SVD and low rank), so gradient descent, or Newton's method (called iteratively reweighted least squares here, and what scikit-learn's default solver approximates) reaches the global optimum. One caveat: if the classes are perfectly separable, the likelihood keeps improving as and the weights diverge; this is why every practical implementation adds a small L2 penalty by default (3.6 Regularization and generalization; scikit-learn's C is ).
Worked example
Let , , and one example with label .
- Logit: .
- Probability: .
- Loss: .
- Error signal: . Gradient w.r.t. : ; w.r.t. : .
- One gradient step with : , ; new logit , new . The step increased the probability of the correct label, as it must.
Many classes: softmax regression
For classes compute scores () and normalize with the softmax:
Softmax is shift-invariant ( gives the same probabilities — subtract the max for stability, 2.2 NumPy and vectorized thinking), reduces to the sigmoid when , and its gradient has the same beautiful form: (1.5 Multivariable and matrix calculus derives it). Every classifier head and the output layer of every language model is softmax regression on learned features; the vocabulary of a GPT is a -way softmax (7.6 Decoder-only: GPT and autoregressive generation).
Thresholds, imbalance and calibration
The output is a probability; turning it into a decision requires a threshold, and is just the default that minimizes 0–1 error when the classes and costs are balanced. If missing a fraud case costs 50× a false alarm, lower the threshold; if positives are 1% of the data, a model can be useful at thresholds far from 0.5. Sweep thresholds and read precision/recall or the ROC curve (3.5 Evaluating models: metrics, validation and the bias–variance trade-off). For heavy imbalance, class weights (reweighting terms in ) or resampling shift the fit; thresholds shift the decision. A separate question is calibration: among examples with , are about 80% positive? Logistic regression is usually well calibrated because it optimizes the likelihood directly; trees and modern neural networks often are not (3.9 Ensembles: bagging, random forests and gradient boosting, 4.3 Loss functions catalog), and the standard fix — Platt scaling — is a logistic regression fitted on the model's scores. Reliability diagrams and the Brier score / log loss measure it.
import numpy as np
def sigmoid(z): return 1 / (1 + np.exp(-z))
def train_logreg(X, y, lr=0.1, steps=5000, l2=1e-3):
w, b = np.zeros(X.shape[1]), 0.0
for _ in range(steps):
p = sigmoid(X @ w + b)
gw = X.T @ (p - y) / len(y) + l2 * w
gb = (p - y).mean()
w -= lr * gw; b -= lr * gb
return w, b
In PyTorch this is nn.Linear(d, 1) with BCEWithLogitsLoss, or nn.Linear(d, K) with CrossEntropyLoss (2.4 PyTorch I: tensors, autograd and the training loop) — a one-layer network. Insert nn.Linear(d, h) and a ReLU before it and you have a multilayer perceptron (4.1 From perceptron to MLP; universal approximation).
Where this shows up later
- The sigmoid and softmax are the output activations of 4.2 Activation functions; cross-entropy is the loss of 4.3 Loss functions catalog; the gradient starts every backward pass in 4.4 Backpropagation, fully derived.
- Softmax over a vocabulary is how a language model predicts the next token — 6.2 Classical NLP and n-gram language models, 7.6 Decoder-only: GPT and autoregressive generation; temperature scaling of the same softmax is decoding — 8.5 Decoding and sampling.
- Logistic regression on frozen features is the linear probe of 5.8 Self-supervised and contrastive learning and 8.11 Interpretability: what is happening inside; the Bradley–Terry reward model of RLHF is logistic regression on preference pairs — 8.3 Alignment: RLHF, PPO, DPO, GRPO and Constitutional AI.
- Thresholds, imbalance and calibration are evaluated formally in 3.5 Evaluating models: metrics, validation and the bias–variance trade-off.
Common pitfalls (5)
- Reading accuracy at threshold 0.5 on imbalanced data; a 99%-negative dataset gives 99% accuracy to a model that predicts nothing.
- Fitting unregularized logistic regression on separable data and watching the weights blow up.
- Applying a sigmoid and then passing probabilities to a 'with logits' loss (double squashing).
- Interpreting coefficients as probability changes; they are changes in log-odds (multiply odds by e^{w_j}).
- Assuming any model's probabilities are calibrated; trees and neural nets usually need Platt or temperature scaling.
Recap: all 8 key points
- Logistic regression models the log-odds as a linear function: log(p/(1−p)) = wᵀx + b, so the decision boundary p = 0.5 is a hyperplane.
- Binary cross-entropy is the negative log-likelihood of a Bernoulli model; wrong-and-confident predictions are punished without bound.
- The gradient at the logit is p − y, so ∇J = Xᵀ(p̂ − y)/n — the same 'features × errors' form as linear regression.
- No closed form, but the loss is convex (Hessian XᵀSX ⪰ 0), so gradient descent or Newton/IRLS finds the global optimum; separable data need L2 regularization.
- Softmax regression generalizes to K classes with p_c = e^{z_c}/Σ e^{z_k}, loss −log p_y and gradient p − y_onehot; it is shift-invariant.
- A threshold is a decision, not part of the model; move it with costs and class imbalance, and check calibration with reliability diagrams.
- Logistic/softmax regression is nn.Linear plus sigmoid/softmax — a one-layer neural network; every classifier head and LM output layer is one.
- Compute the loss from logits (log(1 + e^{−z})) rather than from probabilities to avoid log(0).
Watch
Why the S-curve, what the coefficients mean, and how it differs from linear regression.
Read
Try it live
Interactive demo
runs in your browserExercises
- Reproduce the worked example, then take ten steps
With , , , , compute , the loss and the gradient by hand. Then code ten gradient steps with and print after each. Expected: increases monotonically toward 1.
- From scratch vs scikit-learn
Train the NumPy
train_logregabove on scikit-learn's breast-cancer data (standardized, 80/20 split). Compare coefficients and accuracy withLogisticRegression(C=1000). Expected: near-identical coefficients and ≥95% accuracy; then setl2=0on a separable toy dataset and watch grow without bound. - Threshold sweep
On an imbalanced dataset (e.g., downsample positives to 5%), sweep thresholds from 0.05 to 0.95 and plot precision, recall and F1. Expected: the F1-maximizing threshold is well below 0.5; explain why.
- Calibration check
Bin predicted probabilities into deciles and plot the empirical positive rate per bin (a reliability diagram) for logistic regression and for a random forest on the same data. Expected: logistic regression lies near the diagonal; the forest is typically squeezed toward 0.5. Fit Platt scaling on the forest's scores and re-plot.
Quiz
Flashcards
These cards are now in your spaced-repetition queue. Review all due cards →