House Price Prediction
Download public House Prices train/test CSVs, clean mixed numeric/categorical features, train a log-price regression model, validate RMSLE, and create submission.csv.
Final deliverable: A complete Kaggle-style regression notebook that predicts SalePrice and writes submission.csv.
Dataset: House Prices public CSV mirror
The notebook downloads public train.csv and test.csv mirrors for the Kaggle House Prices problem. The target is SalePrice in train.csv.
- SalePrice: target house sale price in train.csv
- OverallQual, GrLivArea, GarageCars, TotalBsmtSF: strong numeric predictors
- Neighborhood, HouseStyle, Exterior, SaleCondition: categorical predictors
- Id: required identifier for submission.csv
Download House Prices Data
Download public train.csv and test.csv files without Kaggle credentials.
Run the public download cell and confirm train.csv and test.csv exist.
# Run this cell in Colab, Kaggle, or a local notebook.
# It downloads public dataset files directly, so you do not need Kaggle credentials.
from pathlib import Path
from urllib.request import urlretrieve
import zipfile
DATA_DIR = Path("data/house-prices")
DATA_DIR.mkdir(parents=True, exist_ok=True)
def find_file(name):
possible_roots = [DATA_DIR, Path("/kaggle/input")]
for root in possible_roots:
if root.exists():
matches = list(root.rglob(name))
if matches:
return matches[0]
raise FileNotFoundError(f"Could not find {name}. Run the dataset download cell first.")
files = {
"train.csv": "https://raw.githubusercontent.com/ankita1112/House-Prices-Advanced-Regression/master/train.csv",
"test.csv": "https://raw.githubusercontent.com/ankita1112/House-Prices-Advanced-Regression/master/test.csv"
}
for filename, url in files.items():
target = DATA_DIR / filename
if target.exists() and target.stat().st_size > 0:
print(f"already exists: {target}")
continue
print(f"downloading {filename} ...")
urlretrieve(url, target)
print(f"saved: {target}")
for zip_path in DATA_DIR.glob("*.zip"):
extract_dir = DATA_DIR / zip_path.stem
extract_dir.mkdir(exist_ok=True)
if any(extract_dir.iterdir()):
print(f"already extracted: {extract_dir}")
continue
with zipfile.ZipFile(zip_path, "r") as zf:
zf.extractall(extract_dir)
print(f"extracted: {zip_path} -> {extract_dir}")
print("Files:")
all_files = [path for path in sorted(DATA_DIR.rglob("*")) if path.is_file()]
for path in all_files[:40]:
print(path)
if len(all_files) > 40:
print(f"... {len(all_files) - 40} more files not shown")Show reference solution
# Run this cell in Colab, Kaggle, or a local notebook.
# It downloads public dataset files directly, so you do not need Kaggle credentials.
from pathlib import Path
from urllib.request import urlretrieve
import zipfile
DATA_DIR = Path("data/house-prices")
DATA_DIR.mkdir(parents=True, exist_ok=True)
def find_file(name):
possible_roots = [DATA_DIR, Path("/kaggle/input")]
for root in possible_roots:
if root.exists():
matches = list(root.rglob(name))
if matches:
return matches[0]
raise FileNotFoundError(f"Could not find {name}. Run the dataset download cell first.")
files = {
"train.csv": "https://raw.githubusercontent.com/ankita1112/House-Prices-Advanced-Regression/master/train.csv",
"test.csv": "https://raw.githubusercontent.com/ankita1112/House-Prices-Advanced-Regression/master/test.csv"
}
for filename, url in files.items():
target = DATA_DIR / filename
if target.exists() and target.stat().st_size > 0:
print(f"already exists: {target}")
continue
print(f"downloading {filename} ...")
urlretrieve(url, target)
print(f"saved: {target}")
for zip_path in DATA_DIR.glob("*.zip"):
extract_dir = DATA_DIR / zip_path.stem
extract_dir.mkdir(exist_ok=True)
if any(extract_dir.iterdir()):
print(f"already extracted: {extract_dir}")
continue
with zipfile.ZipFile(zip_path, "r") as zf:
zf.extractall(extract_dir)
print(f"extracted: {zip_path} -> {extract_dir}")
print("Files:")
all_files = [path for path in sorted(DATA_DIR.rglob("*")) if path.is_file()]
for path in all_files[:40]:
print(path)
if len(all_files) > 40:
print(f"... {len(all_files) - 40} more files not shown")The notebook owns its data setup, so the learner can run it in Colab, Kaggle, or locally without manually uploading files.
Load and Inspect House Prices
Read training and test files, inspect target distribution, and check missing values.
Load train.csv and test.csv, print shapes, inspect SalePrice, and list the most missing columns.
from pathlib import Path
import pandas as pd
possible_roots = [
Path("data/house-prices"),
Path("/kaggle/input"),
]
def find_file(name):
for root in possible_roots:
if root.exists():
matches = list(root.rglob(name))
if matches:
return matches[0]
raise FileNotFoundError(f"Could not find {name}. Run the dataset download/load cell first.")
train_path = find_file("train.csv")
df = pd.read_csv(train_path)
print(train_path)
print(df.shape)
df.head()
# Load test.csv
# Inspect SalePrice and missing valuesShow reference solution
from pathlib import Path
import pandas as pd
possible_roots = [
Path("data/house-prices"),
Path("/kaggle/input"),
]
def find_file(name):
for root in possible_roots:
if root.exists():
matches = list(root.rglob(name))
if matches:
return matches[0]
raise FileNotFoundError(f"Could not find {name}. Run the dataset download/load cell first.")
train_path = find_file("train.csv")
df = pd.read_csv(train_path)
print(train_path)
print(df.shape)
df.head()
import numpy as np
import matplotlib.pyplot as plt
test_df = pd.read_csv(find_file("test.csv"))
print("train:", df.shape)
print("test:", test_df.shape)
display(df[["Id", "SalePrice", "OverallQual", "GrLivArea", "Neighborhood"]].head())
display(df.isna().sum().sort_values(ascending=False).head(12))
df["SalePrice"].hist(bins=40)
plt.title("SalePrice distribution")
plt.xlabel("SalePrice")
plt.ylabel("Count")
plt.show()House prices are skewed, so predicting log price usually gives a better RMSLE-style model than predicting raw dollars directly.
Build a Preprocessing Pipeline
Handle numeric and categorical columns consistently for train, validation, and test.
Separate SalePrice, identify numeric/categorical columns, and build imputers plus one-hot encoding.
from sklearn.compose import ColumnTransformer from sklearn.impute import SimpleImputer from sklearn.pipeline import Pipeline from sklearn.preprocessing import OneHotEncoder # Separate target and feature columns # Build numeric and categorical preprocessing
Show reference solution
from sklearn.compose import ColumnTransformer
from sklearn.impute import SimpleImputer
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder
target = "SalePrice"
id_col = "Id"
X = df.drop(columns=[target])
y_log = np.log1p(df[target])
feature_cols = [col for col in X.columns if col != id_col]
numeric_features = X[feature_cols].select_dtypes(include=["number"]).columns.tolist()
categorical_features = X[feature_cols].select_dtypes(exclude=["number"]).columns.tolist()
numeric_pipeline = Pipeline([
("imputer", SimpleImputer(strategy="median")),
])
categorical_pipeline = Pipeline([
("imputer", SimpleImputer(strategy="most_frequent")),
("onehot", OneHotEncoder(handle_unknown="ignore", sparse_output=False)),
])
preprocess = ColumnTransformer([
("num", numeric_pipeline, numeric_features),
("cat", categorical_pipeline, categorical_features),
])
print(len(numeric_features), "numeric features")
print(len(categorical_features), "categorical features")The important part is consistency. The same preprocessing object is fitted on training data and reused on validation/test rows.
Train and Validate a Price Model
Fit a model on log SalePrice and validate with RMSLE-style error.
Split training rows, train a random forest pipeline, and evaluate RMSE on log price.
from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import mean_squared_error from sklearn.model_selection import train_test_split # Split train/validation # Train model on log price # Evaluate validation RMSLE
Show reference solution
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
X_train, X_val, y_train_log, y_val_log = train_test_split(
X[feature_cols], y_log, test_size=0.2, random_state=42
)
model = Pipeline([
("preprocess", preprocess),
("regressor", RandomForestRegressor(
n_estimators=350,
min_samples_leaf=2,
random_state=42,
n_jobs=-1,
)),
])
model.fit(X_train, y_train_log)
val_pred_log = model.predict(X_val)
rmsle_like = np.sqrt(mean_squared_error(y_val_log, val_pred_log))
print("validation RMSLE-style score:", round(rmsle_like, 4))Kaggle House Prices is scored on log error. Training on log1p(SalePrice) makes the validation metric match the competition better.
Analyze Errors
Inspect residuals and understand where the model struggles.
Convert log predictions back to prices and inspect actual vs predicted errors.
# Build an error analysis table # Plot actual vs predicted values
Show reference solution
actual_price = np.expm1(y_val_log)
predicted_price = np.expm1(val_pred_log).clip(0)
results = X_val.copy()
results["actual"] = actual_price
results["predicted"] = predicted_price
results["error"] = results["predicted"] - results["actual"]
display(results[["actual", "predicted", "error", "OverallQual", "GrLivArea"]].head())
plt.scatter(results["actual"], results["predicted"], alpha=0.35)
limit = max(results["actual"].max(), results["predicted"].max())
plt.plot([0, limit], [0, limit], color="red")
plt.xlabel("Actual SalePrice")
plt.ylabel("Predicted SalePrice")
plt.title("Actual vs Predicted House Price")
plt.show()Error analysis turns a metric into understanding. It helps identify overprediction, underprediction, and target range problems.
Write the Project Readout
Summarize the model, metric, limitations, and next improvements.
Write a short final readout a recruiter or interviewer could understand.
# Write your final readout in markdown: # - Dataset # - Baseline # - Best model # - Metric # - Biggest limitation # - Next improvement
Show reference solution
# Example readout: # I used the California Housing dataset to predict median house value from income, rooms, occupancy, and location features. # A linear regression baseline gave a simple reference point, while a random forest captured non-linear relationships better. # I evaluated with RMSE because the target is numeric and RMSE is interpretable in the target unit. # The biggest limitation is that the dataset is aggregated by block group, not individual houses. # Next I would add cross-validation, tune hyperparameters, and inspect location-driven errors more deeply.
Projects become portfolio-ready when you can explain the workflow, not just show code cells.
Create House Prices Submission
Train on all labeled rows, predict test rows, and save Id/SalePrice submission.csv.
Fit the final pipeline on all training data, predict test_df, convert from log price, and save submission.csv.
# Fit model on all train rows # Predict test rows # Save submission.csv
Show reference solution
model.fit(X[feature_cols], y_log)
test_pred_log = model.predict(test_df[feature_cols])
test_prices = np.expm1(test_pred_log).clip(0)
submission = pd.DataFrame({
"Id": test_df["Id"],
"SalePrice": test_prices,
})
submission.to_csv("submission.csv", index=False)
display(submission.head())
print("saved submission.csv", submission.shape)This is the file you can upload to the House Prices competition. The validation score tells you whether the notebook is sane before submission.