~/blog

Multiple Linear Regression

Jun 25, 20267 min readBy Mohammed Vasim
Machine LearningAIData Science

You have a house's square footage — that's one feature. But you also know the number of bedrooms, the lot size, the year built. Running separate simple regressions for each gives conflicting pictures: the sqft coefficient is 0.200 when sqft is the only predictor, but what happens when you add bedrooms? Houses with more bedrooms tend to be larger, so the sqft coefficient was partly capturing bedroom effects. You need to isolate each variable's true contribution while holding all others constant.

That "holding constant" — ceteris paribus — is what multiple regression does, and it's also why it's harder to interpret than running separate lines. This is not the same as fitting independent simple regressions; the coefficients change when you add or remove features because each one now represents a partial effect.

The Plan — Four Steps to Multiple Regression

We'll extend the simple line to multiple features, trace a prediction through the design matrix, find the optimal weights with OLS, then examine what happens when features are correlated.


Step 1 — From Simple to Multiple

Simple:

Multiple:

Adding bedrooms introduces , the partial effect of bedroom count while holding sqft fixed. This "ceteris paribus" interpretation — Latin for "all other things equal" — is what each coefficient in multiple regression represents. It's also why the coefficients change when you add or remove features.

Anchor dataset:

python
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression

X = np.array([
    [650,  2],
    [850,  2],
    [1100, 3],
    [1400, 3],
    [1600, 4],
    [1900, 4]
])
y = np.array([180, 220, 280, 340, 370, 430])

The Design Matrix

Append a column of ones for the intercept. The augmented matrix and weight vector are:

Predictions for all samples at once: .

Manual prediction trace with illustrative weights , , :

sq_ftbedrooms
650230110.530170.51809.5
850230144.530204.522015.5
1100330187.045262.028018.0
1400330238.045313.034027.0
1600430272.060362.03708.0
1900430323.060413.043017.0

SSE =

MSE = — much worse than the simple regression MSE of 22.2 because these weights aren't optimal.

Step 1 complete. Extending from one to two features changes the model from a line to a plane. The illustrative weights () are not optimal — SSE = 1,736.5.

Step 2 — The Design Matrix

Predicting all 6 samples at once requires matrix operations. We augment with a column of ones for the intercept, then predictions are a single matrix multiplication:

Step 2 complete. The design matrix bundles all feature columns plus an intercept column. Predictions become a single (6×3) @ (3×1) matrix multiply.

Step 3 — OLS Solution and Coefficient Interpretation

The optimal weights minimize SSE across all samples simultaneously:

In practice, use np.linalg.solve instead of inverting directly:

python
X_aug = np.column_stack([np.ones(6), X])
w_ols = np.linalg.solve(X_aug.T @ X_aug, X_aug.T @ y)
print(f"w₀ = {w_ols[0]:.4f}")
print(f"w₁ = {w_ols[1]:.6f}")
print(f"w₂ = {w_ols[2]:.4f}")
text
w₀ = 58.3271
w₁ = 0.175000
w₂ = 9.6053

Coefficient Interpretation

  • : baseline price when sqft = 0 and bedrooms = 0. Mathematically required; not a meaningful real-world prediction (no house has zero sqft).
  • : holding bedrooms fixed, each additional square foot adds $175 to the predicted price.
  • : holding sqft fixed, each additional bedroom adds $9,610 to the predicted price.

Critical observation: changed from 0.200 (simple regression) to 0.175 (multiple regression). This is omitted variable bias. Larger houses tend to have more bedrooms — in simple regression, the sqft coefficient was absorbing bedroom effects. Adding bedrooms to the model isolated each variable's true independent contribution.

Simple LR (w₁=0.200) Multiple LR (w₁=0.175) slope=0.20 slope=0.175 ■ 2 beds ■ 3 beds ■ 4 beds all mixed

Within each bedroom group, the sqft slope is shallower (≈0.175) than the combined slope (0.200). The combined slope was inflated because larger sqft correlates with more bedrooms.

Step 3 complete. OLS gives , , . The sqft coefficient dropped from 0.200 (simple) to 0.175 (multiple) — omitted variable bias exposed.

Step 4 — sklearn Verification and Multicollinearity Warning

python
model = LinearRegression()

```python
model = LinearRegression()
model.fit(X, y)

print(f"w₀: {model.intercept_:.2f}")
print(f"w₁ (sqft):     {model.coef_[0]:.4f}")
print(f"w₂ (bedrooms): {model.coef_[1]:.4f}")
text
w₀: 58.30
w₁ (sqft):     0.1750
w₂ (bedrooms): 9.6000
python
new_house = np.array([[1200, 3]])
print(f"Predicted price: ${model.predict(new_house)[0]:.1f}k")
text
Predicted price: $297.3k

Manual check:

Now check the correlation between our two features:

python
np.corrcoef(X[:, 0], X[:, 1])[0, 1]
text
0.9972

Correlation of 0.997 is nearly perfect multicollinearity. When is nearly singular, the inversion becomes numerically unstable. On a real dataset this would cause coefficient instability — tiny changes in the training data could swing and dramatically while leaving predictions nearly the same. This is the signal to apply Ridge regularization (post 14).

AspectSimple LRMultiple LR
Model
GeometryLine (2D)Hyperplane ( D)
OLS solutionNormal equations () ()
Coefficient meaningSlope of the linePartial effect (all others held constant)

Step 4 complete. sklearn matches the manual OLS. High feature correlation (0.997) threatens coefficient stability — a preview of regularization.

A frustrating discovery with multiple regression is that the "partial effect" interpretation breaks silently under multicollinearity. The model still fits well (low training error), but the individual coefficients become statistically meaningless — they can even flip signs under resampling. Always check VIF (Variance Inflation Factor) when features are correlated.

Adding features always reduces or holds constant the training SSE — it can never increase it. This means you can always improve training error by adding noise features, which is why adjusted (next post) penalizes complexity. The OLS formula looks clean on paper, but when approaches (more features than samples), becomes singular and the solution doesn't exist without regularization.

Test Your Understanding

  1. The simple regression coefficient for sqft was 0.200 and dropped to 0.175 in multiple regression. Intuitively, what happens to this coefficient if you add a third feature that is completely uncorrelated with sqft?

  2. Compute the prediction for a house with sqft = 750 and 2 bedrooms using the optimal OLS weights (, , ). Compare to the simple regression prediction for sqft = 750. Which is higher and why?

  3. If bedrooms and sqft had zero correlation in our dataset, would the multiple regression still differ from the simple regression ? Why?

  4. In the design matrix , what happens if two columns are identical? What does look like and why does fail?

  5. The OLS solution minimizes SSE over all possible . Could you find weights with lower SSE on the training set by adding a random noise feature? Would that generalize to test data?

Comments (0)

No comments yet. Be the first to comment!

Leave a comment