Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 18

Normal Equation for Linear Regression

Recommended resources

Hello! Let's dive into our next lesson on Linear Regression.

In the last few lessons, we've focused heavily on gradient descent—an iterative algorithm that takes many small steps to find the optimal model parameters. We saw how crucial things like the learning rate and feature scaling are to making it converge efficiently.

Today, we're going to explore a completely different approach. For the specific case of linear regression, there's a way to solve for the best parameters directly, in a single calculation, with no iterations needed. This is a powerful analytical method, and our goal for this lesson is to implement the normal equation to solve for linear regression coefficients directly.

1. From Iteration to a Direct Solution

Gradient descent is like walking down a hill blindfolded, taking small steps in the steepest direction until you reach the bottom. The Normal Equation, in contrast, is like using a mathematical formula to instantly calculate the exact coordinates of the lowest point on that hill.

The central idea comes from calculus. To find the minimum of a function, you can take its derivative with respect to the parameters, set the derivative to zero, and solve for the parameters. The Normal Equation is the result of performing this operation on the Mean Squared Error (MSE) cost function for linear regression.

Stanford CS229: Machine Learning - Linear Regression and Gradient Descent | Lecture 2 (Autumn 2018)

For an excellent conceptual introduction, let's turn to Andrew Ng's lecture on the topic. He explains the idea of using a non-iterative method to jump directly to the global optimum.

Watch the two short clips from 53:34 to 54:35 and from 01:01:31 to 01:03:23. Focus on his explanation of the high-level strategy: taking the derivative of the cost function J(θ), setting it to zero, and solving for θ.

As Professor Ng outlines, performing this derivation with matrix calculus gives us a beautiful, closed-form solution.


2. The Normal Equation Formula

The final result of that derivation is the Normal Equation:

This single line of linear algebra gives us the optimal parameter vector that minimizes the cost function. Let's break it down:

  • : The vector of model parameters we want to find (e.g., ).
  • : The vector of target values from our training data, with shape , where is the number of samples.
  • : This is the design matrix containing the input features. It has a very specific and important structure. For training samples and features, is an matrix. The crucial part is the first column of ones. This is how we account for the bias term (or intercept), , because . Forgetting this column is one of the most common implementation mistakes!
  • : The transpose of the design matrix.
  • : The inverse of the matrix product .
Gradient Descent vs Normal Equation Comparison
This diagram provides a great summary. Gradient descent (left) takes iterative steps, requiring a learning rate alpha. The Normal Equation (right) is an analytical solution that computes theta in one go.

3. Implementing the Normal Equation from Scratch

Now, let's translate this formula into Python code. Since you're proficient with NumPy, you'll see how elegantly its linear algebra capabilities map to this equation.

We'll follow a clear, practical demonstration.

Python Linear Regression with Normal Equation

The video 'Python Linear Regression with Normal Equation' by Raili Taylor provides a perfect, concise walkthrough of the entire implementation process. We'll follow her steps.

Watch this video from 00:29 to 13:19. It covers everything from generating data to making predictions. Pay close attention to these key parts: Data Generation (00:29 - 03:17): See how synthetic linear data is created. Adding the Bias Column (05:06 - 08:04): This is the most critical step, where she explains how to add the column of ones to create the design matrix X_b. Implementing the Formula (08:04 - 09:46): Watch how the equation is translated directly into NumPy code. Making Predictions (09:46 - 13:19): Understand how to use the resulting beta (our θ) vector to predict values for new data.

Let's consolidate those steps into our own code.

Step 1: Generate Data

First, we create some synthetic data to work with.

import numpy as np
import matplotlib.pyplot as plt

# Generate 100 data points
X = 2 * np.random.rand(100, 1)
# Linear equation: y = 4 + 3x + noise
y = 4 + 3 * X + np.random.randn(100, 1)

plt.scatter(X, y)
plt.xlabel("Feature (x)")
plt.ylabel("Target (y)")
plt.title("Synthetic Linear Data")
plt.grid(True)
plt.show()

Step 2: Construct the Design Matrix

This is where we add the column of ones to X for the bias term . We use np.c_, a handy NumPy tool for concatenating arrays column-wise.

# Add x0 = 1 to each instance
X_b = np.c_[np.ones((100, 1)), X]

# Let's inspect the first 5 rows
print("First 5 rows of X_b:")
print(X_b[:5])

You should see that the first column is all ones, and the second column contains our original feature values from X.

Test your understanding!

Given that X has a shape of (100, 1), what will be the shape of the matrix X_b.T @ X_b? Why is this resulting shape important for the next step of the calculation (taking the inverse)?

Show answer
  • X_b has shape (100, 2).
  • X_b.T (the transpose) has shape (2, 100).
  • The product X_b.T @ X_b will therefore have shape (2, 100) @ (100, 2), resulting in a (2, 2) matrix.

This is important because only square matrices can have an inverse. The product always results in a square matrix of shape , where is the number of features, allowing us to compute its inverse.

Step 3: Calculate using the Normal Equation

Now for the main event. We translate into a single line of NumPy.

# Calculate theta_best using the Normal Equation formula
theta_best = np.linalg.inv(X_b.T @ X_b) @ X_b.T @ y

print(f"Optimal theta values (theta_0, theta_1): {theta_best.ravel()}")

You should get values very close to our original parameters, [4, 3]. The small difference is due to the random noise we added to y.

Step 4: Make Predictions

With our optimal theta_best vector, we can now make predictions on new data points. Remember, we also have to add the bias term to our new data before predicting.

# Let's predict values for x=0 and x=2
X_new = np.array([[0], [2]])

# Add the bias term (column of ones) to our new data
X_new_b = np.c_[np.ones((2, 1)), X_new]

# Make predictions
y_predict = X_new_b @ theta_best

print(f"\nPredictions for x=0 and x=2:\n{y_predict}")

# Plot the regression line
plt.scatter(X, y)
plt.plot(X_new, y_predict, "r-", label="Predictions")
plt.xlabel("Feature (x)")
plt.ylabel("Target (y)")
plt.title("Linear Regression with Normal Equation")
plt.legend()
plt.grid(True)
plt.show()
Linear Regression using Normal Equation Plot
The final output should look similar to this plot, with the original data points and the red regression line calculated by our model passing through them.

Conclusion

Congratulations! You have successfully implemented a completely different method for training a linear regression model. Unlike the iterative process of gradient descent, the Normal Equation provides a direct, analytical solution.

Key Takeaways:

  • The Normal Equation is a closed-form formula, , that solves for the optimal linear regression parameters analytically.
  • It is a non-iterative method, meaning you don't need to choose a learning rate, worry about the number of iterations, or perform feature scaling.
  • A critical implementation step is adding a column of ones to the feature matrix X to create the design matrix X_b, which accounts for the bias/intercept term .
  • The core of the implementation relies on standard linear algebra operations: matrix transposition, multiplication, and inversion, which are efficiently handled by NumPy.

Preview of the Next Lesson:
The Normal Equation seems incredibly direct and convenient. This raises an obvious question: if we have this powerful tool, why did we spend so much time learning about gradient descent? In the next lesson, we will answer exactly that by exploring the computational and practical trade-offs between gradient descent and the Normal Equation, helping you understand when to use each method.