House Price Prediction¶
Predicting median house values across California census blocks is one of the most instructive regression problems in data science. It combines real geographic data, skewed distributions, correlated features, and a target variable with a known data quirk — a hard ceiling at $500,000. Every decision you make here maps directly to skills you will use in production regression work.
Learning Objectives¶
By completing this project you will be able to:
- Load and inspect a real-world regression dataset with no external downloads
- Identify and explain target variable ceiling effects and their impact on model evaluation
- Apply log transformations to skewed targets and features
- Engineer interaction features and geographic cluster features
- Compare linear models against tree-based ensemble models on regression tasks
- Evaluate regression models using MAE, RMSE, R², and MAPE
- Interpret feature importance and residual plots to diagnose model weaknesses
Prerequisites¶
- Week 02 Day 01 Part 2 — Regression Algorithms (Linear, Ridge, Lasso, tree-based regression)
- Week 02 Day 03 Part 1 — Feature Engineering (transformations, interactions, encoding)
- Week 02 Day 01 Part 1 — Scikit-learn workflow (train-test split, pipelines, cross-validation)
Skills Practiced¶
| Skill Area | Specific Techniques |
|---|---|
| EDA | Distribution analysis, correlation matrix, geographic scatter plots |
| Feature Engineering | Log transforms, interaction features, geographic clustering, outlier capping |
| Modelling | Linear Regression, Ridge, Random Forest, Gradient Boosting |
| Evaluation | MAE, RMSE, R², MAPE, residual plots, feature importance |
| Spatial Analysis | Latitude/longitude plots, spatial error mapping |
Project Structure¶
| File | What it covers |
|---|---|
README.md |
Project overview, objectives, dataset summary |
dataset-guide.md |
Column reference, data quirks, loading and inspecting the data |
eda.md |
Exploratory analysis — distributions, correlations, geographic patterns |
feature-engineering.md |
Outlier handling, interaction features, geographic features, scaling |
model-building.md |
Baseline through Gradient Boosting, hyperparameter tuning, model comparison |
evaluation.md |
Regression metrics, residual diagnostics, feature importance, spatial errors |
interview-questions.md |
Eight interview questions with model answers |
Dataset¶
California Housing from the 1990 census. Available directly from scikit-learn — no download required.
from sklearn.datasets import fetch_california_housing
import pandas as pd
housing = fetch_california_housing(as_frame=True)
df = housing.frame # 20,640 rows, 9 columns including target
print(df.shape) # (20640, 9)
print(df.columns.tolist())
# ['MedInc', 'HouseAge', 'AveRooms', 'AveBedrms', 'Population',
# 'AveOccup', 'Latitude', 'Longitude', 'MedHouseVal']
Column Reference¶
| Column | Description | Units |
|---|---|---|
MedInc |
Median household income in the block group | $10,000s |
HouseAge |
Median age of houses in the block group | Years |
AveRooms |
Average number of rooms per household | Rooms |
AveBedrms |
Average number of bedrooms per household | Bedrooms |
Population |
Total population of the block group | People |
AveOccup |
Average number of occupants per household | People |
Latitude |
Geographic latitude of the block group centroid | Degrees |
Longitude |
Geographic longitude of the block group centroid | Degrees |
MedHouseVal |
Target. Median house value in the block group | $100,000s |
The $500,000 Ceiling — Read This First¶
Warning
The target column MedHouseVal is capped at 5.0, which represents $500,000. Any block group where the true median value was above $500,000 is recorded as exactly 5.0. This creates an artificial spike in the distribution at the ceiling.
This matters in two ways. First, your model will be trained on truncated ground truth for the most expensive neighborhoods. Second, standard regression metrics (MAE, RMSE) will look better than they really are for high-value predictions, because the true values are hidden above 5.0.
You cannot fix this without additional data. You must understand it, report it, and account for it when interpreting your model's performance on high-value blocks.
# How many blocks are capped at the ceiling?
capped = (df['MedHouseVal'] == 5.0).sum()
print(f"Capped blocks: {capped} ({capped / len(df) * 100:.1f}%)")
# Capped blocks: 965 (4.7%)
Success
This is an intentionally messy, real-world dataset. No missing values, all numeric, and a known quirk that professional data scientists encounter regularly. It is the right place to learn regression end-to-end.