Skip to content

← Regression from Scratch step 4 of 4

Easy End-to-End

Logistic Regression From Scratch

Logistic regression uses a weighted sum of features to estimate the probability of class 1. Applying a sigmoid turns the score z into a probability: sigmoid(z) = 1 / (1 + exp(-z)).

In this exercise, train the weights using full-batch gradient descent. Every step uses all examples, and training stops after the requested number of steps.

Your task

Implement fit_logistic(x, y, lr, n_steps):

  • x is a floating-point feature matrix of shape (N, d), with N, d >= 1.
  • y has shape (N,) and contains labels 0 or 1.
  • lr is a nonnegative learning rate.
  • n_steps is a nonnegative integer.

Start with a zero weight vector of shape (d,). Repeat these operations exactly n_steps times:

p = sigmoid(x @ w)           # shape (N,)
grad = x.T @ (p - y) / N     # shape (d,)
w = w - lr * grad

Compute each gradient using the current weights, then update all weights together. Use these explicit operations rather than an optimizer or automatic differentiation. Return only the final weight vector, preserving the inputs. For zero steps, return zeros. With lr = 0, the weights also stay zero.

Why this update?

The training objective is mean binary cross-entropy:

loss = -mean(y * log(p) + (1 - y) * log(1 - p))

Its gradient with respect to the weights is x.T @ (p - y) / N. The division by N averages across examples. You do not need to compute or return the loss itself, and you should not multiply this gradient by another sigmoid derivative. The formula already accounts for it.

Intercept and example

Use x exactly as supplied. There is no separate bias parameter and your function must not add a column. When the caller supplies a column of ones, its weight acts as the intercept.

For x = [[1, 2], [1, -1], [1, 0]] and y = [1, 0, 1], the initial weights [0, 0] give probabilities [0.5, 0.5, 0.5]. The first gradient is [-1/6, -1/2]. With lr = 0.6, one step returns [0.1, 0.3]. The first weight is the intercept because this input already has a column of ones. Subsequent steps must recompute the probabilities.

A fixed number of steps does not guarantee convergence. Follow the given step count even if the weights are still changing.