Normal equation closed-form solution
Overview
The normal equation provides an analytical closed-form solution to linear regression by directly computing the optimal parameters without iterative optimization. Unlike gradient descent, it solves for in a single step using matrix calculus.

Think of it like finding the lowest point in a valley: instead of taking many small steps downhill (gradient descent), we use calculus to jump straight to the bottom in one leap.
The Derivation (From First Principles)
Step 1: Set Up the Cost Function
For linear regression with training examples and features:
The cost function (Mean Squared Error) is:
Why ? The cancels with the derivative of the square (makes calculus cleaner), and normalizes across different dataset sizes.
Step 2: Vectorize Using Matrix Notation
Let's construct the design matrix (dimensions: ):
Why the column of 1's? That's the feature that multiplies (the intercept/bias term).
The parameter vector and target vector :
Now all predictions in one shot: gives a vector of predictions.
The cost function becomes:
Why this form? The squared error sum is exactly the dot product of the error vector with itself: .
Step 3: Take the Gradient and Set to Zero
To minimize , we need .
Expanding the quadratic:
Why this expansion? We use with and .
Taking the gradient with respect to (using matrix calculus rules):
Why these terms?
- when is symmetric
- Constants vanish
Setting the gradient to zero:
Step 4: Solve for
Why is it called "normal"? In linear algebra, "normal" means perpendicular. At the optimum, the residual vector is orthogonal (normal) to the column space of . This is the least squares solution.
Important caveat on the pseudoinverse: When has full column rank (i.e., is invertible), the matrix equals the Moore-Penrose pseudoinverse , giving the unique least squares solution. When is rank-deficient (singular ), this formula breaks down, and the pseudoinverse must be computed via a more general method such as SVD (Singular Value Decomposition). In that case there are infinitely many least squares solutions, and returns the one with minimum norm.
Worked Examples
Step 1: Construct and
Why this structure? First column is all 1's for , second column is the values.
Step 2: Compute
Why this multiplication? Each element is the dot product of row from with column from .
Step 3: Compute
Step 4: Invert
For a 2×2 matrix , the inverse is .
Why compute the determinant? It's , which ensures the matrix is invertible.
Step 5: Compute
Result: ,
The fitted line is .
| 1 | 3 | 7 |
| 2 | 4 | 10 |
| 3 | 5 | 13 |
Step 1: Design matrix
Why three columns? Column 0 is for , column 1 for (feature ), column 2 for (feature ).
Step 2:
Step 3:
Why these numbers? Row 1: . Row 2: . Row 3: .
Step 4: STOP — check invertibility first!
Look carefully at the feature columns: notice that for every row. This means column 2 of equals column 1 plus (column of 1's):
The columns are linearly dependent, so is rank-deficient (). Therefore is singular — its determinant is and it cannot be inverted. The plain normal equation formula does not apply here.
Why this matters: Because the features are redundant, there is no unique . There are infinitely many exact solutions.
Step 5: Solve correctly. The relationship is exactly linear ( is one valid fit), so a perfect (zero-error) fit exists. For example:
But because , we can trade weight between the parameters. Another exact solution:
wait — let's keep the constraint honest. Any satisfying that reproduces the targets works. The clean way to see it: substitute into the model:
Only the combinations and are determined; the individual values are free. The data requires and (matching ), giving infinitely many .
The correct tool: Use the SVD-based pseudoinverse (), which returns the minimum-norm solution among these infinitely many, or remove the redundant feature and solve a well-posed 2-parameter problem.
Lesson: Always check the rank of before blindly inverting .
When to Use (and When Not to Use)
When to use normal equation:
- features (matrix inversion is tractable)
- Small to medium datasets ()
- Need exact solution without tuning hyperparameters
- No regularization needed
When to use gradient descent:
- (e.g., image features, text features)
- Very large (big data scenarios)
- Online learning (data arrives in streams)
- Need regularization (Lasso/Ridge) or other constraints
The mistake: Applying the normal equation when is singular (non-invertible)—exactly what happens in Example 2 above.
Why it feels right: The formula looks simple—just plug in your data!
What goes wrong:
- When (more features than examples): system is under-determined
- When features are linearly dependent (multicollinearity):
- Example: including both "price in dollars" and "price in cents" as separate features
The fix:
- Remove redundant features (check correlation matrix / rank)
- Use regularization (Ridge regression adds to make invertible)
- Use the SVD-based pseudoinverse (numpy's
pinvorlstsqhandles singular matrices gracefully and returns the minimum-norm solution) - Collect more data if
The mistake: Computing the normal equation without feature normalization.
Why it feels right: The normal equation is analytical—scaling shouldn't matter mathematically.
What actually happens:
- Numerical instability in matrix inversion when features have vastly different scales
- becomes ill-conditioned (small changes cause huge errors)
- Example: feature 1 is "age" (20-80), feature 2 is "income" (20,000-200,000)
The fix: Standardize features: before applying the normal equation.
Implementation Considerations
Instead of explicitly computing , use:
- QR decomposition: , then solve
- SVD (Singular Value Decomposition): Handles near-singular and rank-deficient matrices robustly (and defines the true pseudoinverse)
- Cholesky decomposition: Faster for positive definite
Why? Direct matrix inversion is numerically unstable and computationally expensive. These methods avoid inversion while solving the same system.
import numpy as np
# Bad: explicit inversion (fails if X^T X is singular)
theta_bad = np.linalg.inv(X.T @ X) @ X.T @ y
# Good: use solve (uses LU decomposition internally)
theta_good = np.linalg.solve(X.T @ X, X.T @ y)
# Best: use lstsq (uses SVD, handles singular/rank-deficient matrices)
theta_best = np.linalg.lstsq(X, y, rcond=None)[0]Recall Feynman Explanation (Explain to a 12-year-old)
Imagine you're trying to draw the best straight line through some points on a graph. You could guess a line, measure how far each point is from it, adjust a little bit, and keep doing this until you can't improve anymore (that's gradient descent—lots of little adjustments).
But there's a clever shortcut! Using math, you can calculate the PERFECT line in one go without any guessing. It's like having a magic formula that looks at ALL your points at once and figures out exactly where the line should be.
The "normal equation" is that magic formula. You organize all your data points into a special grid (matrix), do some multiplying and dividing with these grids, and out pops the answer—the exact best line!
The catch? This magic formula gets really slow when you have TONS of data or LOTS of different measurements (features). For small problems, it's the fastest way. For huge problems, you're better off with the "guess-and-adjust" method. And watch out: if two of your measurements are secretly the same thing in disguise (like measuring height in inches AND in centimeters), the magic formula gets confused and can't give one answer—there are infinitely many! You have to throw away the duplicate first.
"The Transpose Times, Inverse Times, Transpose Y"
Or think: "X-Transpose-X gets inverted, then X-Transpose-y gets inserted"
Visual: → the "sandwiched inverse" pattern.
Connections
- Linear Regression Fundamentals — the problem this solves
- Gradient Descent — the iterative alternative
- Ridge Regression — adds to handle non-invertibility
- Moore-Penrose Pseudoinverse — generalized inverse for singular matrices (via SVD)
- QR Decomposition — numerically stable way to solve least squares
- Feature Scaling — preprocessing to avoid numerical issues
- Polynomial Regression — still uses normal equation with transformed features
- Underdetermined vs Overdetermined Systems — when unique solutions exist
#flashcards/
Concept Map
Hinglish (regional understanding)
Intuition Hinglish mein samjho
Hinglish (regional understanding)
Intuition Hinglish mein samjho
Dekho, is note ka core idea bahut simple hai. Jab hum linear regression karte hain, toh humara goal hota hai woh best-fit line dhundhna jo error ko minimum kare. Ab error ko minimize karne ke do tareeke hain — ek toh gradient descent, jisme hum thode-thode steps le kar dheere-dheere neeche valley ke bottom tak jaate hain. Lekin normal equation ek shortcut deta hai — ye ek hi baar mein, ek single formula se seedha optimal parameters nikaal deta hai. Iska matlab hai koi iteration nahi, koi learning rate tune karne ka jhanjhat nahi, bas ek matrix calculation aur kaam khatam.
Ye kaam isliye karta hai kyunki linear regression ka cost function ek quadratic (bowl-shaped) function hota hai — ek katore jaisa. Aur katore ke sabse neeche wale point pe slope zero hoti hai. Toh agar hum gradient ko zero set kar dein aur solve karein, toh humein seedha wahi lowest point mil jaata hai jahan error minimum hai. Isi ko algebra mein solve karke woh famous formula banta hai: . Yahan hamara design matrix hai jisme sab features rakhe hain, aur woh 1's ka column intercept (bias) term ke liye hota hai.
Ab ye why-matters kyun hai? Kyunki jab tumhara dataset chhota ya medium size ka ho aur features zyada na hon, tab normal equation gradient descent se kaafi tez aur accurate hota hai — no tuning, no guessing. Lekin ek dhyan dene wali baat — jab features bahut zyada ho jaate hain, tab ka inverse nikaalna computationally mehenga ho jaata hai, aur tab gradient descent better rehta hai. Toh ye samajhna zaroori hai ki dono methods kab-kab use hote hain — ye concept tumhare machine learning foundation ko strong banata hai.