Linear Regression with Gradient Descent - Supervised Learning
Implement Linear Regression with Gradient Descent in Python with NumPy. medium exercise with examples, hints, and instant feedback. No setup or signup required.
Linear Regression with Gradient Descent
Fit a one-feature linear model y ≈ w * x + b by running batch gradient descent on the mean squared error.
Background
Linear regression has a closed-form solution, but gradient descent is how almost every other model (and every neural network) is trained. Implementing it on the simplest model shows the full loop: predict, measure the loss, compute gradients, step.
Formula
Loss (mean squared error over the n samples):
J(w, b) = (1/n) * sum_i (y_pred_i - y_i)^2, y_pred_i = w * x_i + b
Gradients:
dJ/dw = (2/n) * sum_i (y_pred_i - y_i) * x_i
dJ/db = (2/n) * sum_i (y_pred_i - y_i)
Algorithm:
- Start from
w = 0,b = 0. - Repeat
iterationstimes: computey_predwith the currentw, b, compute both gradients, then update both parameters simultaneously:w -= learning_rate * dJ/dw,b -= learning_rate * dJ/db. - Return the final
(w, b).
Inputs
X: 1D float array of inputs, shape(n,)y: 1D float array of targets, shape(n,)learning_rate: step size (float, e.g. 0.01 to 0.1)iterations: number of full-batch updates (int)
Expected Return Format
A tuple (w, b) with both values rounded to 2 decimals.
Edge Cases and Conventions
- Use the exact update order above: the tests include a 10-iteration run, which checks the update rule itself, not just the optimum it converges to.
- Too large a learning rate makes the iterates diverge; the tests use stable values.
Constraints
- NumPy only; no
np.polyfitor closed-form least squares. Vectorise each step over the samples (one Python loop over iterations is expected).
Follow-up
- Derive the closed form
w = cov(x, y) / var(x),b = mean(y) - w * mean(x), and explain when gradient descent is still preferable. - Why does standardising
xlet you use a larger learning rate?
Examples
Input: linear_regression(np.array([1, 2, 3, 4]), np.array([2, 4, 6, 8]), 0.1, 1000) Output: (2.0, 0.0)
The data lie exactly on y = 2x, and 1000 steps are enough to converge.
Input: linear_regression(np.array([1, 2, 3, 4]), np.array([2, 4, 6, 8]), 0.01, 1) Output: (0.3, 0.1)
One step from (0, 0): dJ/dw = (2/4) * (-60) = -30 and dJ/db = (2/4) * (-20) = -10, so w = 0.3 and b = 0.1.
Practice in Python
import numpy as np
def linear_regression(X: np.ndarray, y: np.ndarray,
learning_rate: float = 0.01,
iterations: int = 1000) -> tuple:
"""
Train y = w * x + b with batch gradient descent on the MSE.
Args:
X: Input features, 1D array of shape (n,)
y: Target values, 1D array of shape (n,)
learning_rate: Step size for gradient descent
iterations: Number of full-batch updates
Returns:
Tuple (w, b), each rounded to 2 decimals
"""
# Initialize parameters
w = 0.0
b = 0.0
n = len(X)
# Your gradient descent implementation here
pass
return (round(w, 2), round(b, 2))
The interactive editor loads with Python and NumPy. Run your implementation against 6 tests, or use the progressive hints.