~/blog
Logistic Regression: Math Intuition
You're a loan officer who just learned that linear regression can't produce valid probabilities for classification. The fix is a function called the sigmoid — but the story doesn't end there. Once you replace the linear output with , you need a new loss function (MSE doesn't work for probabilities), a new way to interpret the coefficients (log-odds rather than raw scores), and a gradient that connects all the pieces. Each piece has a formula, and each formula has a concrete number attached to it.
This post traces the full path from raw score to gradient update on six loan applications. Every formula lands on a specific number from this dataset — nothing is symbolic.
What Logistic Regression Does
Logistic regression takes a linear score and passes it through the sigmoid function to produce a probability. The coefficients are interpreted in log-odds: a unit change in a feature multiplies the odds of the outcome by . The loss function — binary cross-entropy — penalizes wrong confidence, not wrong predictions. And the gradient of this loss with respect to the weights has exactly the same form as linear regression's gradient, but with probabilities in place of raw predictions.
The Plan — Four Steps from Linear Score to Gradient Update
We'll start with a single linear score and convert it to a probability using the sigmoid. We'll reinterpret that probability as log-odds to understand what the coefficients mean. We'll compute the cross-entropy loss to see why MSE is wrong. And finally we'll run one gradient descent step to see how the weights update. Each step is computed on the same six samples.
Anchor dataset: Loan default prediction (6 samples for hand-trace clarity).
import numpy as np
X = np.array([25, 32, 45, 75, 95, 110]).reshape(-1, 1)
y = np.array([1, 1, 1, 0, 0, 0])
# Weights after fitting (used for trace — not starting weights):
# w₀ = 8.12, w₁ = -0.094Step 1: Linear Score → Sigmoid → Probability
The raw linear score is computed the same way as in linear regression:
The sigmoid function converts this to a probability:
The model predicts , which is the probability of default given income.
Trace for all 6 samples with , :
| Income | Predicted | |||
|---|---|---|---|---|
| 25 | 8.12 − 2.35 = 5.77 | = 0.997 | 1 | 1 ✓ |
| 32 | 8.12 − 3.01 = 5.11 | = 0.994 | 1 | 1 ✓ |
| 45 | 8.12 − 4.23 = 3.89 | = 0.980 | 1 | 1 ✓ |
| 75 | 8.12 − 7.05 = 1.07 | = 0.745 | 1 | 0 ✗ |
| 95 | 8.12 − 8.93 = −0.81 | = 0.307 | 0 | 0 ✓ |
| 110 | 8.12 − 10.34 = −2.22 | = 0.098 | 0 | 0 ✓ |
At decision threshold 0.5: income = 75 gives — predicted as default (wrong). These weights are illustrative; the true MLE solution would correctly separate this dataset.
Green dots are correctly classified; the red dot at income=75k sits above the 0.5 line but is a non-defaulter (y=0). The S-shape ensures all outputs stay within (0, 1).
✓ Step 1 complete. The linear score ranges from 5.77 (income=25k) to −2.22 (income=110k). After sigmoid, each maps to a valid probability in . The S-shaped curve guarantees that no input produces an output outside the probability range.
Step 2: Log-Odds (Logit) Interpretation
The ratio of default probability to non-default probability is the odds:
Taking the log of odds recovers the linear score exactly:
The log-odds (logit) is linear in the features. This means logistic regression is a linear model — it draws a straight boundary in feature space — just applied to log-odds rather than probability directly.
Log-odds trace for 3 anchor samples:
| Income | Odds | |||
|---|---|---|---|---|
| 25 | 0.997 | 0.003 | 332.3 | ✓ |
| 75 | 0.745 | 0.255 | 2.92 | ✓ |
| 110 | 0.098 | 0.902 | 0.109 | ✓ |
Interpreting : Each additional $1k in income changes the log-odds of default by . In odds terms, it multiplies the odds of default by:
A 9% reduction in the odds of default for each $1k of additional income.
Log-odds is linear in income. The boundary income (z=0) is where the line crosses zero — every sample to the left has positive log-odds (predicted default), every sample to the right has negative log-odds (predicted no default).
✓ Step 2 complete. The log-odds equals the linear score : . Each additional e^{-0.094} = 0.91$ — a 9% reduction per unit. Logistic regression IS a linear model in log-odds space.
Step 3: Binary Cross-Entropy Loss
Why not MSE? Consider predicting with (correct, very confident). MSE loss = — nearly zero. Now predict with (correct, barely). MSE = . The nearly-random prediction is penalized 250,000× more than the confident correct one — backward.
Binary cross-entropy (BCE) penalizes wrong confidence, not wrong predictions:
Three cases:
- Correct and confident: , → (tiny)
- Correct and unconfident: , → (meaningful signal)
- Wrong and confident: , → (large penalty, → )
Per-sample loss for the 6-sample anchor:
| Income | |||
|---|---|---|---|
| 25 | 1 | 0.997 | |
| 32 | 1 | 0.994 | |
| 45 | 1 | 0.980 | |
| 75 | 0 | 0.745 | |
| 95 | 0 | 0.307 | |
| 110 | 0 | 0.098 | |
| Avg loss |
The sample at income=75 dominates the loss (1.367) because the model is confidently wrong: it predicts (likely default) for a non-defaulter. This is exactly where gradient descent will push the decision boundary.
Left panel (): loss approaches infinity as (confidently wrong). Right panel (): loss approaches infinity as . In both cases, confident correct predictions have loss near zero.
✓ Step 3 complete. Binary cross-entropy penalizes wrong confidence, not wrong predictions. The sample at income=75k dominates the total loss (1.367 of 0.311 average) because the model is confidently wrong — exactly where the gradient needs to push hardest.
Step 4: Gradient Descent Update
The total cost over samples:
The gradients work out elegantly — the same form as linear regression but with sigmoid probabilities:
One gradient step from , , :
With all weights zero: for every sample, so .
Prediction errors :
| Income | |||
|---|---|---|---|
| 25 | 0.5 | 1 | −0.5 |
| 32 | 0.5 | 1 | −0.5 |
| 45 | 0.5 | 1 | −0.5 |
| 75 | 0.5 | 0 | +0.5 |
| 95 | 0.5 | 0 | +0.5 |
| 110 | 0.5 | 0 | +0.5 |
Computing gradients:
Weight updates:
The gradient is zero because the dataset is balanced (3 defaulters, 3 non-defaulters) — symmetry cancels. The gradient is positive (14.83) because higher incomes are associated with non-default (), so the gradient pushes negative — exactly right. After this one step, the model already knows to decrease as income increases.
Before (flat line): all probabilities = 0.5, model has no information. After one step: the curve tilts — low income → higher P(default), high income → lower P(default). The direction is correct on step one.
✓ Step 4 complete. From with all , one gradient step gives . The negative already knows that higher income should decrease default probability — correct direction from a single update.
Key Formulas Reference
| Step | Formula | Purpose |
|---|---|---|
| Linear score | Raw activation | |
| Sigmoid | Maps probability | |
| Log-odds | Linear interpretation | |
| Per-sample loss | Penalizes wrong confidence | |
| Gradient | Same form as linear regression |
Related Concepts
The BCE gradient has exactly the same structure as the OLS gradient for linear regression — the only difference is (from sigmoid) instead of (from the linear prediction). This is not a coincidence: both emerge from the chain rule applied through the output activation. Understanding this post requires comfort with the chain rule and what makes a function convex. It unlocks regularization (appending to adds to each gradient), multiclass softmax (the same BCE structure generalizes to classes), and neural network training (replace sigmoid with other activations, BCE becomes cross-entropy over softmax output).
Honest Limitations
At initialization , every sample has . Gradient descent is guaranteed to find the global minimum because BCE is convex in the weights — the loss surface has no local minima. This property disappears the moment you stack layers: a two-layer network with sigmoid activations is no longer convex. A second limitation: MLE for logistic regression does not have a finite solution when the data is perfectly linearly separable. The weights diverge toward infinity, trying to push all probabilities to exactly 0 or 1. sklearn's default L2 regularization (C=1.0) prevents divergence by adding a penalty, but it changes the optimization from pure MLE to a penalized version — the resulting weights are biased toward zero.
Test Your Understanding
-
The gradient at initialization because the dataset is balanced. If you added one more defaulter (making 4 defaulters, 3 non-defaulters), what sign would have, and what does that mean for 's update?
-
At income=75, the loss is 1.367 — the largest single-sample loss. After one gradient step (), compute the new for income=75 and the new . Did the loss for this sample decrease?
-
The gradient of BCE with respect to weights has the form — identical in structure to the linear regression gradient. Why does the same form emerge from a completely different loss function?
-
At (the approximate fitted weights), the decision boundary (income where ) is at . Compute this boundary income value. Does it match your intuition from the data?
-
The log-odds interpretation says each $1k income multiplies the odds of default by . If income doubles from 50 to 100, what is the ratio of the odds at 100 to the odds at 50?