Predict Housing Prices with Linear Regression

Train a linear regression model to predict California housing prices.

Introduction

30 Second Summary

Housing prices seem unpredictable, but hidden patterns in data like income levels and location can reveal surprisingly accurate trends. What if you could teach a computer to spot those patterns for you?

In this project, you will build a machine learning model that predicts California housing prices using real data and linear regression.

What You'll Build

A Python notebook in Google Colab that loads the California Housing dataset, trains a linear regression model, and evaluates its predictions with industry-standard metrics.

By the end of this project, you'll have:

  • A trained linear regression model that predicts housing prices from real California data.
  • Scatter plot visualizations showing how features relate to price and how predictions compare to actual values.
  • Evaluation metrics (R-squared and Mean Squared Error) measuring your model's accuracy.
  • Secret Mission: Train a multi-feature model using all 8 features and compare its performance to your single-feature model.

Are there any prerequisites?

None. Google Colab runs in your browser with all required libraries pre-installed. You just need a Google account to get started.

Set Up Google Colab

Before you can train a machine learning model, you need a place to write and run Python code.

Google Colab is a free, browser-based notebook environment that comes with all the libraries you need pre-installed. No downloads, no terminal commands. You just open it and start coding.

In this step, get ready to:
  • Open Google Colab and create a new notebook.
  • Verify your Python environment by importing all required libraries.
  • Rename your notebook to keep things organized.
Open Google Colab and create a new notebook

Google Colab runs entirely in your browser. You just need a Google account to get started.

  • Open your browser and navigate to colab.research.google.com.
  • Sign in with your Google account if prompted.
  • Click New notebook in the bottom-left of the popup window.

A blank notebook opens with an empty code cell ready for you to type in.

What is Google Colab?

Google Colab is a free Jupyter notebook environment hosted by Google. It gives you a Python runtime with popular data science libraries already installed.

Each notebook is made up of "cells" that you run one at a time. This makes it easy to experiment with code in small pieces.

Import the required libraries

Your notebook needs access to several Python libraries for data handling, visualization, and machine learning. Google Colab comes with all of them pre-installed, so you just need to import them.

  • Click inside the empty code cell in your notebook and paste the following code:
# California Housing Price Prediction with Linear Regression
# Run this code in Google Colab (one cell at a time or all together)

# Step 1: Import libraries
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score

What does this code do?

Each import brings in a library that handles a specific job in your ML pipeline:

  • numpy handles numerical operations on arrays of data.
  • pandas loads and organizes data into tables called DataFrames.
  • matplotlib creates charts and visualizations.
  • sklearn (scikit-learn) provides the dataset, the model, and the evaluation tools.
  • Run the cell by clicking the Play button on the left side of the cell, or press Shift+Enter.
  • Wait a few seconds for Colab to connect to a runtime. You should see a green checkmark appear next to the cell with no error messages.

Seeing an error after running the cell?

If you see a ModuleNotFoundError, make sure you are using Google Colab (not a local Jupyter notebook). All required libraries are pre-installed on Colab.

If the cell shows a spinning icon for more than 30 seconds, click Runtime in the top menu, then Reconnect. Try running the cell again.

Help me fix my import errors in Google Colab.

Rename your notebook

A descriptive name makes your notebook easy to find later in Google Drive.

  • Click on the notebook title at the top-left of the page (it says Untitled0.ipynb by default).
  • Replace the text with California Housing Linear Regression and press Enter.

Your notebook title updates immediately. The file saves automatically to your Google Drive.

✔️ Awesome, I've got everything!

Great. Double check you've saved your notebook and your imports ran without errors.

ⓧ I'd like to double check the full code

Here is the complete code you should have in your first cell:

# California Housing Price Prediction with Linear Regression
# Run this code in Google Colab (one cell at a time or all together)

# Step 1: Import libraries
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score

Your environment is ready. Next up, you'll load a real dataset of California housing prices and start exploring what the data looks like.

Load and Explore the Dataset

Your notebook is set up and all libraries are imported. Now it's time to bring in the actual data.

The California Housing dataset contains 20,640 real samples from the 1990 U.S. Census. You'll load it, explore its structure, and create your first visualization to spot patterns before training a model.

In this step, get ready to:
  • Load the California Housing dataset into a pandas DataFrame.
  • Examine the dataset's shape, features, and summary statistics.
  • Visualize the relationship between median income and house value.
Load the dataset and examine its structure

Before building any model, you need to understand what data you're working with. Loading the dataset and printing its properties tells you how many samples exist, what features are available, and what values look like.

  • Load the California Housing dataset and print its key properties by adding this code in a new cell:
# Step 2: Load and explore the dataset
housing = fetch_california_housing(as_frame=True)
df = housing.frame

print("Dataset shape:", df.shape)
print("\nFeature names:", housing.feature_names)
print("\nFirst 5 rows:")
print(df.head())
print("\nSummary statistics:")
print(df.describe())

What does this code do?

  • fetch_california_housing(as_frame=True) downloads the dataset and returns it as a pandas DataFrame instead of a NumPy array.
  • housing.frame gives you the full DataFrame including both the 8 input features and the target column.
  • df.shape shows the number of rows and columns.
  • df.describe() prints summary statistics (mean, standard deviation, min, max) for every column.
  • Run the cell by clicking the play button on the left side of the cell, or by pressing Shift+Enter.
  • You should see the dataset shape printed as (20640, 9), a list of 8 feature names, a table showing the first 5 rows, and a full summary statistics table.

What is MedHouseVal?

The target column MedHouseVal is the median house value for each census block group. Values are in units of $100,000, so a value of 2.5 means $250,000.

The dataset caps at 5.0 ($500,000). You'll see this show up as a horizontal cluster of points in the scatter plot next.

Not seeing any output?

  • Make sure you ran the imports cell (from Step 1) before this cell. Colab cells must run in order.
  • Check that this code is in a new cell, not appended to the bottom of the imports cell. Click + Code in the toolbar to add a fresh cell.
  • help me debug why my Colab cell isn't producing output
Create an exploratory scatter plot

Before training a model, it helps to visualize the data. A scatter plot reveals whether a clear relationship exists between a feature and the target price.

  • Create a scatter plot of median income vs. house value by adding this code in a new cell:
# Scatter plot: Median Income vs. House Value
plt.figure(figsize=(10, 6))
plt.scatter(df['MedInc'], df['MedHouseVal'], alpha=0.3, s=10)
plt.xlabel('Median Income (tens of thousands)')
plt.ylabel('Median House Value ($100,000s)')
plt.title('Median Income vs. House Value')
plt.show()

What does this code do?

  • plt.figure(figsize=(10, 6)) creates a 10-by-6 inch chart canvas.
  • plt.scatter() plots each of the 20,640 data points as a dot. alpha=0.3 makes dots semi-transparent so overlapping areas appear darker. s=10 keeps dots small.
  • The x-axis shows MedInc (median income in tens of thousands of dollars) and the y-axis shows MedHouseVal (median house value in units of $100,000).
  • Run the cell by pressing Shift+Enter.
  • You should see a scatter plot with a clear upward trend. Higher median incomes cluster with higher house values. You'll also notice a horizontal band of points capped at 5.0 along the top.

Why start with MedInc?

MedInc (median income) has the strongest correlation with house value in this dataset. That clear upward trend you see in the plot is exactly what linear regression tries to capture with a straight line.

Don't see a chart?

  • Make sure plt.show() is the last line in the cell. Without it, Colab may not render the plot.
  • Verify you ran the previous cell first so that df exists. If you see a NameError, go back and run the loading cell.
  • help me debug why my matplotlib scatter plot isn't showing in Colab

✔️ Awesome, I've got everything!

Great. Double check you've saved your notebook (Colab auto-saves, but you can press Ctrl+S or Cmd+S to be sure).

ⓧ I'd like to double check the full code

Here's everything your notebook should contain so far, across all cells:

# California Housing Price Prediction with Linear Regression
# Run this code in Google Colab (one cell at a time or all together)

# Step 1: Import libraries
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score

# Step 2: Load and explore the dataset
housing = fetch_california_housing(as_frame=True)
df = housing.frame

print("Dataset shape:", df.shape)
print("\nFeature names:", housing.feature_names)
print("\nFirst 5 rows:")
print(df.head())
print("\nSummary statistics:")
print(df.describe())

# Scatter plot: Median Income vs. House Value
plt.figure(figsize=(10, 6))
plt.scatter(df['MedInc'], df['MedHouseVal'], alpha=0.3, s=10)
plt.xlabel('Median Income (tens of thousands)')
plt.ylabel('Median House Value ($100,000s)')
plt.title('Median Income vs. House Value')
plt.show()

You've loaded 20,640 real housing samples and confirmed that median income has a clear relationship with price. Next up, you'll split this data into training and testing sets so you can teach a model on one portion and measure how well it predicts on the other.

Prepare the Data for Training

Your scatter plot revealed a clear upward trend between median income and house values. Now you need to transform this raw data into a format that a machine learning model can actually learn from.

This means selecting which column the model uses as input, defining what it should predict, and splitting the data so you can test how well the model performs on data it has never seen.

In this step, get ready to:
  • Separate features (X) from the target variable (y).
  • Split data into training (80%) and test (20%) sets.
  • Confirm the split by printing the shapes of each set.
Separate features from the target

Every machine learning model needs two things: input data (called features) and the answer it should learn to predict (called the target).

You saw from the scatter plot that MedInc (median income) has the strongest relationship with house prices. You will use this single column as your feature for the first model.

What is feature selection?

Feature selection is choosing which columns from your data to feed into the model. Starting with one strong feature makes it easy to visualize and understand the model's behaviour.

The target is the column you want to predict. Here, that is MedHouseVal (median house value in units of $100,000).

Split into training and test sets

A model that memorizes all its data is useless on new, unseen data. Train/test splitting holds back a portion of the data so you can measure how well the model generalises.

  • Create a new code cell in your notebook and add the following code to select your feature, split the data, and print the resulting shapes:
# Step 3: Prepare data for training
X = df[['MedInc']]  # Single feature (2D DataFrame)
y = df['MedHouseVal']  # Target variable

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

print(f"Training set: X_train {X_train.shape}, y_train {y_train.shape}")
print(f"Test set: X_test {X_test.shape}, y_test {y_test.shape}")

What does this code do?

X = df[['MedInc']] selects the median income column as a 2D DataFrame. The double brackets keep it as a DataFrame (not a Series), which is the shape scikit-learn expects for input features.

y = df['MedHouseVal'] extracts the target column as a simple Series of values to predict.

train_test_split randomly shuffles and divides the data. test_size=0.2 reserves 20% for testing. random_state=42 locks the shuffle so you get the same split every time you run the cell.

  • Run the cell by pressing Shift+Enter.
  • You should see output showing the training set shapes as (16512, 1) and (16512,), and the test set shapes as (4128, 1) and (4128,).

What do these shapes mean?

The training set has 16,512 samples (80% of 20,640). The test set has 4,128 samples (20%). The 1 in the X shapes means you have one feature column (MedInc).

Your model will learn patterns from the training data, and you will measure its accuracy on the test data it has never seen.

Seeing a NameError?

If you see NameError: name 'df' is not defined, make sure you ran the cells from Step 2 first. Colab needs each cell executed in order so variables exist in memory.

If you see NameError: name 'train_test_split' is not defined, go back and run the first cell that imports your libraries.

Help me fix my NameError in Google Colab

✔️ Awesome, I've got everything!

Great. Double check you see the correct shapes in your cell output, then move on to the next step.

ⓧ I'd like to double check the full code

Here is the full notebook code up to this point. Compare your cells against this:

# California Housing Price Prediction with Linear Regression
# Run this code in Google Colab (one cell at a time or all together)

# Step 1: Import libraries
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score

# Step 2: Load and explore the dataset
housing = fetch_california_housing(as_frame=True)
df = housing.frame

print("Dataset shape:", df.shape)
print("\nFeature names:", housing.feature_names)
print("\nFirst 5 rows:")
print(df.head())
print("\nSummary statistics:")
print(df.describe())

# Scatter plot: Median Income vs. House Value
plt.figure(figsize=(10, 6))
plt.scatter(df['MedInc'], df['MedHouseVal'], alpha=0.3, s=10)
plt.xlabel('Median Income (tens of thousands)')
plt.ylabel('Median House Value ($100,000s)')
plt.title('Median Income vs. House Value')
plt.show()

# Step 3: Prepare data for training
X = df[['MedInc']]  # Single feature (2D DataFrame)
y = df['MedHouseVal']  # Target variable

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

print(f"Training set: X_train {X_train.shape}, y_train {y_train.shape}")
print(f"Test set: X_test {X_test.shape}, y_test {y_test.shape}")

Your data is shaped and split. Next up, you will feed the training data into a linear regression model and see how well it predicts housing prices.

Train and Evaluate the Model

Your data is split into training and test sets. Now comes the exciting part: training a model that learns the relationship between income and housing prices.

In this step, you will create a linear regression model, fit it to your training data, and measure how well it predicts prices on data it has never seen.

In this step, get ready to:
  • Train a LinearRegression model on the training data.
  • Evaluate predictions using Mean Squared Error and R-squared.
  • Visualize predicted vs. actual housing prices with a scatter plot.
Train the model and evaluate predictions

Linear regression finds the straight line that best fits your training data. Once trained, the model uses that line to predict housing prices for new data points it has never seen before.

  • Create a new code cell in your Colab notebook and paste the following code:
# Step 4: Train and evaluate the model
model = LinearRegression()
model.fit(X_train, y_train)

y_pred = model.predict(X_test)

mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)

print(f"\nModel Results:")
print(f"Coefficient (slope): {model.coef_[0]:.4f}")
print(f"Intercept: {model.intercept_:.4f}")
print(f"Mean Squared Error: {mse:.4f}")
print(f"R-squared Score: {r2:.4f}")

What does this code do?

This code creates a linear regression model, trains it, and measures its accuracy.

  • LinearRegression() creates a fresh model instance. model.fit(X_train, y_train) teaches it the relationship between income and price using the training data.
  • model.predict(X_test) generates price predictions for the test set (data the model has never seen).
  • mean_squared_error measures how far off predictions are on average (lower is better). r2_score measures how much of the price variation the model explains (closer to 1.0 is better).
  • model.coef_[0] is the slope (how much price increases per unit of income). model.intercept_ is the baseline price when income is zero.
  • Run the cell by pressing the play button or Shift+Enter.
  • You should see printed output showing the coefficient, intercept, MSE, and R-squared values. Your R-squared score should be around 0.47, meaning median income alone explains about 47% of the variation in housing prices.

What does an R-squared of 0.47 mean?

An R-squared of 0.47 means your single-feature model explains 47% of the variation in housing prices. The remaining 53% is influenced by other factors like location, house age, and number of rooms.

This is a reasonable result for one feature. The Secret Mission later shows how adding all 8 features improves this score significantly.

Seeing a NameError?

If you see an error mentioning an undefined variable like X_train or LinearRegression, make sure you ran all the previous cells in order. Colab cells must be executed sequentially.

help me fix a NameError in my Google Colab notebook for linear regression

Visualize predicted vs. actual values

Numbers alone do not tell the full story. A scatter plot comparing predicted prices to actual prices makes it easy to see where the model does well and where it struggles.

  • Create a new code cell below your previous one and paste this visualization code:
# Visualization: Actual vs. Predicted
plt.figure(figsize=(10, 6))
plt.scatter(y_test, y_pred, alpha=0.3, s=10)
plt.plot([0, 5], [0, 5], 'r--', linewidth=2, label='Perfect Prediction')
plt.xlabel('Actual House Value ($100,000s)')
plt.ylabel('Predicted House Value ($100,000s)')
plt.title('Actual vs. Predicted House Values')
plt.legend()
plt.show()

What does this chart show?

Each dot represents one house from the test set. The x-axis shows the actual price. The y-axis shows what the model predicted.

The red dashed line represents perfect prediction (where predicted equals actual). Points close to this line are accurate predictions. Points far from it are where the model missed. You will notice the model struggles with very expensive houses because there are fewer examples of them in the training data.

  • Run the cell by pressing the play button or Shift+Enter.
  • You should see a scatter plot with blue dots clustered around the red dashed diagonal line. The title reads "Actual vs. Predicted House Values" and the legend shows "Perfect Prediction".

Don't see the scatter plot?

Make sure plt.show() is included at the end of the cell. Also confirm that the previous cell (where you trained the model and created y_pred) ran successfully before this one.

help me troubleshoot my matplotlib scatter plot not displaying

✔️ Awesome, I've got everything!

Great. Double check you have both the printed metrics and the scatter plot visible in your notebook.

ⓧ I'd like to double check the full code

Here is the complete notebook code from start to finish. Compare it against what you have in your Colab notebook.

# California Housing Price Prediction with Linear Regression
# Run this code in Google Colab (one cell at a time or all together)

# Step 1: Import libraries
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score

# Step 2: Load and explore the dataset
housing = fetch_california_housing(as_frame=True)
df = housing.frame

print("Dataset shape:", df.shape)
print("\nFeature names:", housing.feature_names)
print("\nFirst 5 rows:")
print(df.head())
print("\nSummary statistics:")
print(df.describe())

# Scatter plot: Median Income vs. House Value
plt.figure(figsize=(10, 6))
plt.scatter(df['MedInc'], df['MedHouseVal'], alpha=0.3, s=10)
plt.xlabel('Median Income (tens of thousands)')
plt.ylabel('Median House Value ($100,000s)')
plt.title('Median Income vs. House Value')
plt.show()

# Step 3: Prepare data for training
X = df[['MedInc']]  # Single feature (2D DataFrame)
y = df['MedHouseVal']  # Target variable

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

print(f"Training set: X_train {X_train.shape}, y_train {y_train.shape}")
print(f"Test set: X_test {X_test.shape}, y_test {y_test.shape}")

# Step 4: Train and evaluate the model
model = LinearRegression()
model.fit(X_train, y_train)

y_pred = model.predict(X_test)

mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)

print(f"\nModel Results:")
print(f"Coefficient (slope): {model.coef_[0]:.4f}")
print(f"Intercept: {model.intercept_:.4f}")
print(f"Mean Squared Error: {mse:.4f}")
print(f"R-squared Score: {r2:.4f}")

# Visualization: Actual vs. Predicted
plt.figure(figsize=(10, 6))
plt.scatter(y_test, y_pred, alpha=0.3, s=10)
plt.plot([0, 5], [0, 5], 'r--', linewidth=2, label='Perfect Prediction')
plt.xlabel('Actual House Value ($100,000s)')
plt.ylabel('Predicted House Value ($100,000s)')
plt.title('Actual vs. Predicted House Values')
plt.legend()
plt.show()

Secret mission

Train a Multi-Feature Model

Your single-feature model uses only median income to predict housing prices. But the dataset has 8 features. What happens when you give the model more information to work with?

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely in Google Colab, so there are no ongoing costs or cloud resources to worry about. Decide whether to keep your notebook, or delete it entirely.

Resources you used:

  • Google Colab notebook (stored in your Google Drive).

Keep everything running

No action needed. Choose this if you want to revisit your notebook, experiment with different features, or reference your code later.

  • Your notebook stays in Google Drive under the Colab Notebooks folder.
  • You can reopen it anytime at colab.research.google.com.

Pause - I'll come back to this later

Google Colab automatically disconnects idle runtimes, so there is nothing to pause manually. Your notebook is already saved in Google Drive and ready to reopen whenever you return.

  • If your runtime is still connected, click Runtime in the top menu, then Disconnect and delete runtime.
  • This frees up any memory the session was using. Your code and outputs remain saved in the notebook file.

Delete - I don't want to use this again

Remove the notebook entirely from your Google Drive.

  • In Google Colab, click File in the top menu.
  • Click Move to trash.
  • To permanently delete it, open Google Drive, click Trash in the left sidebar, right-click your notebook file, and select Delete forever.

Nice Work!

Nice Work!

You just built your first machine learning model! You loaded real-world data, explored it visually, trained a linear regression, and evaluated your predictions with industry-standard metrics.

You've learned how to:

  • Loaded and explored the California Housing dataset using pandas and matplotlib scatter plots to understand feature relationships.
  • Trained a LinearRegression model on an 80/20 train/test split and made predictions on unseen data.
  • Evaluated model performance using R-squared and Mean Squared Error, then visualized predicted vs. actual house values.
  • Trained a multi-feature model using all 8 features and compared its performance to the single-feature version.

Ready to quiz yourself?