House Price Regression
Estimate sale price from size, bedrooms, and age. Lower is better: predicting the training mean scores an MSE of 2879.57.
Lower is better. Scored on 15 held-out rows.
Dataset
x: feature 1 · y: feature 2
Each dot is one training row: feature 1 against feature 2, coloured by class.
What this lab teaches
Solve a four-unknown least-squares system by hand - intercept plus three features - and beat the training-mean predictor on MSE.
The split in numbers
There are 30 training rows and 15 hidden rows. The features are house size (roughly 830 to 3000), bedrooms (1 to 5), and age (0 to 37), and the targets are prices in the 140 to 360 range. Predicting the training mean costs MSE 2879.57 on the hidden rows, which is the recorded baseline, and the target is 400.
The fitted surface
Ordinary least squares gives price = 33.46 + 0.0969*size + 10.78*bedrooms - 0.385*age. On the hidden 15 rows that scores MSE about 283 with R-squared 0.90, comfortably inside the target. The training residual standard deviation is about 12.7, so part of the price is genuinely noisy; do not expect a perfect fit, just a far better one than the mean.
Assembling the system
Prepend a constant 1 column to the features, build the 4x4 normal equations (X-transpose X) theta = X-transpose y, and solve with Gaussian elimination. The matrix diagonal holds n, the sums of squares of each feature, and the off-diagonals hold pairwise feature sums - all computable in one pass over the 30 rows with plain Python loops.
Common pitfalls
- Fitting on unscaled features and then evaluating with a different scaling. Age spans 37 while size spans about 2000, so a scale change that touches only one column silently shifts the intercept and slope.
- Reading the first coefficient as a feature weight. The design matrix's first column is the constant 1, so theta[0] is the intercept; mixing up the column order of bedrooms and age flips their weights.
- Dividing by a zero or near-zero pivot during elimination without a fallback, which happens whenever a candidate column has no variance in the rows you keep.
Rules of the run
- Define predict(train_X, train_y, test_X) and return exactly one value per test row.
- Pure Python or numpy both run; no external data or network access.
- Return a numeric prediction for every test row.
Hint
Least squares has a closed form: solve the normal equations (X-transpose X) theta = X-transpose y.
Reference solution
Revealing doesn't affect your record — but try the hint first.