Python · Course navigation

Logistic regression for classification

Turn a linear score into a probability with the sigmoid and train it by gradient descent on log loss.

On this page
Before you start

Linear regression and gradient descent.

  • Turn a linear score into a probability with the sigmoid and train it by gradient descent on log loss.
  • Predict the sample output and explain the state changes.
  • Complete the practice task and check the boundary cases.

The concept

Despite its name, logistic regression is a classification method. It computes a linear score z = w·x + b and passes it through the sigmoid function σ(z) = 1 / (1 + e⁻ᶻ), which maps any number to a value between 0 and 1 that is read as the probability of the positive class. A prediction is positive when that probability is at least 0.5, which happens exactly when z >= 0.

The model is trained by minimizing the log loss (binary cross-entropy), which punishes confident wrong predictions heavily. Its gradient has the same pleasant shape as in linear regression: ∂L/∂w = average of (σ(z) − y)·x. The decision boundary, where the probability is 0.5, is at x = −b / w for one feature.

The data below are separable: every example with x <= 3 is class 0 and every example with x >= 4 is class 1. The trained model classifies all six correctly and places the boundary near 3.47, in the gap between 3 and 4. The exact position within the gap depends on how long training runs. For separable data, the unregularized weights would grow forever as training continues, so practical implementations add a regularization penalty or stop early.

Code example

Python
import math

xs = [1, 2, 3, 4, 5, 6]
labels = [0, 0, 0, 1, 1, 1]


def sigmoid(z):
    return 1 / (1 + math.exp(-z))


w = b = 0.0
for _ in range(3000):
    grad_w = sum((sigmoid(w * x + b) - y) * x for x, y in zip(xs, labels)) / len(xs)
    grad_b = sum((sigmoid(w * x + b) - y) for x, y in zip(xs, labels)) / len(xs)
    w -= 0.5 * grad_w
    b -= 0.5 * grad_b

predictions = [1 if sigmoid(w * x + b) >= 0.5 else 0 for x in xs]
print(predictions == labels)
print(round(sigmoid(w * 2 + b), 3), round(sigmoid(w * 3.5 + b), 3), round(sigmoid(w * 5 + b), 3))
print(round(-b / w, 2))
Output
True
0.001 0.537 0.999
3.47

Follow the code

Open the walkthrough to inspect the example one step at a time.

Show guided walkthrough
Guided walkthroughReady
1import math
2
3xs = [1, 2, 3, 4, 5, 6]
4labels = [0, 0, 0, 1, 1, 1]
5
6
7def sigmoid(z):
8 return 1 / (1 + math.exp(-z))
9
10
11w = b = 0.0
12for _ in range(3000):
13 grad_w = sum((sigmoid(w * x + b) - y) * x for x, y in zip(xs, labels)) / len(xs)
14 grad_b = sum((sigmoid(w * x + b) - y) for x, y in zip(xs, labels)) / len(xs)
15 w -= 0.5 * grad_w
16 b -= 0.5 * grad_b
17
18predictions = [1 if sigmoid(w * x + b) >= 0.5 else 0 for x in xs]
19print(predictions == labels)
20print(round(sigmoid(w * 2 + b), 3), round(sigmoid(w * 3.5 + b), 3), round(sigmoid(w * 5 + b), 3))
21print(round(-b / w, 2))

Follow the example

Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.

View the complete dry-run table
Prepared trace of the published program. Some rows group repeated iterations.
Step / lineWhat happensState after stepOutput so far
The sigmoid squashes any score into (0, 1), so the output can be read as a probability.—
—
The log-loss gradient: prediction minus label, weighted by the input.—
—
After training, all six examples are classified correctly.—
True
Probability of class 1: near 0 at x = 2, about one half in the gap at 3.5, near 1 at x = 5.—
True
0.001 0.537 0.999
The decision boundary is where w·x + b = 0, at x ≈ 3.47.—
True
0.001 0.537 0.999
3.47

Behind the scenes

How Python processes this code

Python runs this source through its interpreter. It creates objects for values and resolves names as each statement runs.

Cost and common mistakes

Each training step costs O(n) for n examples (O(n·d) with d features), the same as linear regression.

  • Logistic regression produces a probability, not a certainty. Use a threshold appropriate to the costs of errors, not always 0.5.
  • On perfectly separable data the weights keep growing, making the probabilities extreme. Use regularization.
  • The model is linear in its inputs, so a single logistic regression cannot separate classes that need a curved boundary without feature engineering.

Try it yourself

Roughly what probability does the model give for x = 3.47?

Reveal answer and reasoning

About 0.5, because that is the decision boundary where w·x + b = 0 and σ(0) = 0.5.

Further reading