A linear score, squashed by the sigmoid into a probability, cut by a threshold into a decision. Train a real classifier on draggable points, watch gradient descent chase the data, then trade false positives against false negatives with one slider.
Sign in to save progress
Three moves: score, squash, cut
Logistic classification is the smallest useful classifier and the template for the output layer of far bigger ones. It never predicts a class directly. It predicts a probability, and a separate threshold turns that probability into a decision.
1. Score linearly
z = w1 x1 + w2 x2 + b is just a weighted sum. Its sign says which side of a line the point is on; its size says how far from that line.
2. Squash with the sigmoid
p = 1 / (1 + e^-z) maps any score into (0, 1). Score 0 becomes p = 0.5, large positive scores approach 1, large negative scores approach 0. Distance from the line becomes confidence.
3. Cut with a threshold
Predict class 1 when p is at least t. The set of points where p = t is a straight line: the decision boundary. Training aims the line; the threshold slides it.
z = w1 * x1 + w2 * x2 + b linear score p = 1 / (1 + exp(-z)) sigmoid: probability of class 1 predict class 1 when p >= t the threshold t is YOUR choice, not the model's
This guide is the machine-learning view: fit by gradient descent, predict, decide. The same model has a statistics life as a GLM, where the interesting questions are about the coefficients themselves: log-odds interpretation, standard errors, significance. That view lives in the Logistic Regression guide. No coefficient inference here, only decisions.
Step 1: train it, for real, in your browser
The weights start at zero, where the model says p = 0.5 for everything and the loss is ln 2, about 0.6931. Each training step computes the true cross-entropy gradient over all visible points and walks downhill. Watch the loss fall and the score function take shape.
The objective the buttons minimize
L = mean cross-entropy + (0.002 / 2) * (w1^2 + w2^2)
Each button press runs real full-batch gradient descent (learning rate 1.5) on the 36 visible points. The small L2 penalty keeps the weights bounded when the classes are linearly separable; without it they would grow forever. Every number below is recomputed from the current weights after every step.
Gradient steps
0
train at least 150 to unlock the map
Cross-entropy loss
0.6931
0.6931 at step 0 (untrained, p = 0.5)
Learned score function
z = 0.00 x1 + 0.00 x2 + 0.00
p = sigmoid(z), updated live
Loss curve (Train button steps)
Step 2: move the data, slide the threshold
The map shows the model's probability at every location: blue where it bets on class 0, pink where it bets on class 1, dark where it is unsure. Drag a point across the boundary and gradient descent refits live. Then slide the threshold and watch the boundary translate while the confusion counts rebalance.
Drag any point, or Tab to a point and move it with the arrow keys. The model is untrained (w1 = w2 = b = 0), so p = 0.5 everywhere, the map is flat, and no boundary exists yet. Train it first.
Same trained weights, different cut: the threshold shifts the boundary to the score value logit(t) = 0.00, it never rotates it. Rotation comes only from retraining.
Confusion counts on the 36 points, recomputed live
| actual \ predicted | predicted 1 | predicted 0 |
|---|---|---|
| actual 1 | 18 TP | 0 FN |
| actual 0 | 18 FP | 0 TN |
Accuracy
50.0%
Precision
50.0%
Recall
100.0%
The model is untrained, so p = 0.5 for every point: at t up to 0.50 everything is predicted class 1, above it everything is class 0. These counts are real, they are just counts of a useless model.
Step 3: the cost question
You deploy this classifier as a spam filter: class 1 means spam and the message is deleted. A false positive (real mail deleted) is far more costly than a false negative (spam that slips through). Which way do you move the threshold?