🧭 Business Decision Classifier — Logistic Regression Live
A logistic regression boundary bends to separate two outcome classes as gradient descent runs — watch weights update and the decision line move, point by point.
About the Business Decision Classifier
Logistic regression is the workhorse behind an enormous share of real business classifiers — churn prediction, credit approval, fraud flags, lead scoring. It takes a weighted sum of input features, z = w1·x1 + w2·x2 + b, and squashes it through the sigmoid function to output a probability that a customer belongs to the positive class. Training means adjusting w1, w2 and b with gradient descent so that binary cross-entropy loss, averaged over the dataset, keeps falling.
This simulation trains a live two-feature logistic regression model on a synthetic business dataset: "customer engagement score" on one axis and "support tickets filed" on the other, split into two outcome classes (high churn risk vs. low churn risk). Each training step draws a mini-batch, computes the gradient of the loss with respect to w1, w2 and b, and nudges the weights downhill. Watch the straight decision line rotate and slide into place, the shaded half-planes sharpen in confidence, and the loss curve fall as accuracy climbs.
Frequently Asked Questions
What is logistic regression?
Logistic regression is a linear classifier: it computes a weighted sum z = w1·x1 + w2·x2 + b of the input features, then passes z through the sigmoid function to produce p = σ(z), a probability in (0, 1) that the example belongs to class 1. A prediction is made by thresholding p, typically at 0.5. Despite the name, it is a classification method, not regression in the usual sense — "regression" refers to the underlying linear combination of weights.
Why use the sigmoid function specifically?
Sigmoid σ(z) = 1/(1 + e^(–z)) maps any real number to the open interval (0, 1), so its output can be read directly as a probability. It is smooth and differentiable everywhere, which gradient descent needs, and its derivative has the convenient closed form σ'(z) = σ(z)(1 – σ(z)), reused when computing the loss gradient. Its S-shape also means predictions near the decision boundary change smoothly rather than jumping discontinuously.
What does binary cross-entropy loss measure?
Binary cross-entropy is L = –[y·log(p) + (1–y)·log(1–p)], averaged over the batch. It heavily penalises confident wrong predictions — as p → 0 for a true label y = 1, the loss shoots toward infinity — while confident correct predictions cost almost nothing. For a fixed dataset, cross-entropy loss as a function of w1, w2, b is convex, so gradient descent has a single global minimum to aim for rather than getting trapped in local minima.
Why can't a linear boundary always separate the classes?
Because logistic regression's decision boundary — the set of points where p = 0.5 — is always exactly a straight line (w1·x + w2·y + b = 0), or a hyperplane in higher dimensions. When the two outcome classes genuinely overlap (as in the "Overlapping" preset) or the true separating pattern is curved or non-linear, no choice of w1, w2, b can push the loss to zero. Training still converges — it finds the single straight line that minimises total cross-entropy — it just can't achieve perfect accuracy on data that isn't linearly separable.
What happens if the learning rate is too high or too low?
The learning rate η scales every gradient step: w ← w – η·∂L/∂w. Because the cross-entropy loss surface for logistic regression is a smooth convex bowl, too large an η causes updates to overshoot the minimum, making the loss curve oscillate or diverge instead of settling. Too small an η makes each step barely move the weights, so training crawls toward convergence and wastes far more steps than necessary — though, unlike in deep networks, it will eventually get there since there is only one minimum to find.
What gradients does gradient descent actually compute here?
For each training example, the error term is e = p – y (predicted probability minus true label). The gradients are ∂L/∂w1 = e·x, ∂L/∂w2 = e·y, and ∂L/∂b = e, averaged across the mini-batch. These fall directly out of applying the chain rule through the log-loss and the sigmoid — the same mechanics as backpropagation, just for a network with no hidden layers. Each update step subtracts η times these averaged gradients from w1, w2 and b.
How is the decision boundary and shaded region visualised?
Every pixel of the plot corresponds to a hypothetical (engagement score, support tickets) pair. A forward pass computes the model's predicted probability p at that point; the pixel is tinted red if p < 0.5 (predicted high risk) or blue if p ≥ 0.5 (predicted low risk), with opacity scaled to |p – 0.5| × 2 so confidently-classified regions look vivid and the area near the boundary fades out. The solid line traces exactly where p = 0.5 — the linear decision boundary itself.
Why are there three dataset presets?
"Separable" places the two clusters far apart with low variance, so a line can achieve near-100% accuracy — useful for watching clean, fast convergence. "Overlapping" moves the clusters closer with more spread, so some points will always sit on the wrong side of any straight line — showing the loss plateauing above zero, which is expected and correct behaviour, not a bug. "Noisy" keeps the separable layout but randomly flips roughly 12% of labels, mimicking real-world label noise and showing how a few mislabelled points can permanently limit achievable accuracy.
A logistic regression boundary bends to separate two outcome classes as gradient descent runs — watch weights update point by point.
3D · Three.js / WebGL renderer · 60 FPS target · runs fully client-side, no install