Module Assessment
Overview
This assessment brings together everything you have learned in module 11: fitting ordinary least squares regression, diagnosing residuals, adding polynomial features, applying Ridge and Lasso regularization, and selecting a final model using cross-validation and systematic hyperparameter search. You will work with the California Housing dataset — the same dataset used throughout the module — and walk through a complete regression workflow from baseline to regularized model, culminating in a justified recommendation.
Learning Objectives
By the end of this assessment, you will have demonstrated the ability to:
- Train and evaluate linear regression models using appropriate metrics.
- Apply polynomial features and regularization to improve model performance.
- Use cross-validation and GridSearchCV to tune hyperparameters without data leakage.
- Interpret residual plots and select the best model with justification.
Starter Code
Complete the assessment using this Colaboratory notebook.
The Dataset
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, cross_val_score
from sklearn.linear_model import LinearRegression, Ridge, Lasso, RidgeCV, LassoCV
from sklearn.preprocessing import PolynomialFeatures, StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.metrics import mean_absolute_error, root_mean_squared_error, r2_score
housing = fetch_california_housing(as_frame=True)
X = housing.data
y = housing.target
print(X.shape)
print(X.head())
Output:
(20640, 8)
MedInc HouseAge AveRooms AveBedrms Population AveOccup Latitude Longitude
0 8.3252 41.0 6.984127 1.023810 322.0 2.555556 37.88 -122.23
1 8.3014 21.0 6.238137 0.971880 2401.0 2.109842 37.86 -122.22
...
Columns: MedInc, HouseAge, AveRooms, AveBedrms, Population, AveOccup, Latitude, Longitude
Target: MedHouseVal — median house value in $100,000s (e.g., a value of 2.5 means $250,000)
Coding Assessment
Practice the concepts from this module using this notebook. After completing all tasks, save your notebook to GitHub and submit the link for grading.
Task 1: Baseline Model
Load the California Housing dataset, create an 80/20 train/test split with random_state=42, and train a LinearRegression model on all 8 features. Report MAE, RMSE, and R² on the test set.
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
lr = LinearRegression()
lr.fit(X_train, y_train)
y_pred = lr.predict(X_test)
mae = mean_absolute_error(y_test, y_pred)
rmse = root_mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"MAE: {mae:.4f}")
print(f"RMSE: {rmse:.4f}")
print(f"R²: {r2:.4f}")
Record your results — you will use them as the baseline in Task 5.
Task 2: Residual Analysis
Using the predictions from Task 1, generate two diagnostic plots and write a brief interpretation.
Plot 1 — Residuals vs. Predicted Values:
residuals = y_test - y_pred
plt.figure(figsize=(8, 5))
plt.scatter(y_pred, residuals, alpha=0.3, s=10)
plt.axhline(0, color="red", linewidth=1.5)
plt.xlabel("Predicted Value ($100k)")
plt.ylabel("Residual")
plt.title("Residuals vs. Predicted Values")
plt.tight_layout()
plt.show()
Plot 2 — Histogram of Residuals:
plt.figure(figsize=(7, 4))
plt.hist(residuals, bins=60, edgecolor="white")
plt.xlabel("Residual")
plt.ylabel("Count")
plt.title("Distribution of Residuals")
plt.tight_layout()
plt.show()
After generating both plots, write 2 sentences in a markdown cell addressing:
- Do the residuals appear normally distributed and centered near zero?
- Is there any pattern in the residuals vs. predicted plot that suggests the linear model's assumptions may be violated?
Task 3: Polynomial Features + Ridge
Build a Pipeline that combines PolynomialFeatures(degree=2) with a StandardScaler and Ridge regression. Tune the regularization strength using RidgeCV.
from sklearn.linear_model import RidgeCV
alphas = np.logspace(-2, 3, 20)
poly_ridge = Pipeline([
("poly", PolynomialFeatures(degree=2, include_bias=False)),
("scaler", StandardScaler()),
("model", RidgeCV(alphas=alphas, cv=5)),
])
poly_ridge.fit(X_train, y_train)
best_alpha = poly_ridge.named_steps["model"].alpha_
print(f"Best alpha selected by RidgeCV: {best_alpha:.4f}")
# Cross-validated RMSE on training data
cv_scores = cross_val_score(
poly_ridge, X_train, y_train,
cv=5, scoring="neg_root_mean_squared_error"
)
cv_rmse = -cv_scores.mean()
print(f"CV RMSE (5-fold, train): {cv_rmse:.4f}")
# Test RMSE
y_pred_ridge = poly_ridge.predict(X_test)
test_rmse = root_mean_squared_error(y_test, y_pred_ridge)
print(f"Test RMSE: {test_rmse:.4f}")
Compare the test RMSE from this pipeline to your Task 1 baseline. Does adding polynomial features and regularization improve performance?
Task 4: Lasso for Feature Selection
Fit a Lasso model with alpha=0.01 (after scaling). Identify which of the 8 original features receive non-zero coefficients, and how many are zeroed out.
lasso_pipe = Pipeline([
("scaler", StandardScaler()),
("model", Lasso(alpha=0.01, max_iter=5000)),
])
lasso_pipe.fit(X_train, y_train)
coefs = pd.Series(
lasso_pipe.named_steps["model"].coef_,
index=X.columns
)
print("Lasso coefficients:")
print(coefs)
print(f"\nFeatures zeroed out: {(coefs == 0).sum()}")
print(f"Features retained: {(coefs != 0).sum()}")
y_pred_lasso = lasso_pipe.predict(X_test)
lasso_rmse = root_mean_squared_error(y_test, y_pred_lasso)
lasso_r2 = r2_score(y_test, y_pred_lasso)
print(f"\nLasso Test RMSE: {lasso_rmse:.4f}")
print(f"Lasso Test R²: {lasso_r2:.4f}")
Note: With alpha=0.01 on the California Housing data, Lasso typically retains most features. Increase alpha to observe more aggressive feature elimination.
Task 5: Model Comparison Table
Fill in the following table with your results from Tasks 1, 3, and 4. For cross-validated RMSE on the linear regression baseline, use cross_val_score with scoring="neg_root_mean_squared_error" and 5-fold CV.
| Model | CV RMSE | Test RMSE | Test R² |
|---|---|---|---|
| Linear Regression | |||
| Polynomial (deg=2) + Ridge | |||
| Lasso (alpha=0.01) |
Which model achieves the lowest test RMSE? Does that same model also achieve the highest R²?
Task 6: Recommendation
In a markdown cell, write 2–3 sentences justifying which model you would deploy based on your results. Cite at least two specific metrics from your comparison table. Consider both predictive accuracy and the practical implications of model complexity.
Grading Rubric
| Task | Points | Criteria |
|---|---|---|
| Task 1: Baseline model | 15 | Correct train/test split; LinearRegression fitted and evaluated; MAE, RMSE, and R² reported |
| Task 2: Residual analysis | 20 | Both plots generated; markdown interpretation addresses normality and any fan-shaped or curved pattern |
| Task 3: Polynomial + Ridge | 20 | Pipeline constructed correctly; RidgeCV used to select alpha; CV RMSE and test RMSE reported and compared to baseline |
| Task 4: Lasso feature selection | 15 | Lasso fitted inside a scaling pipeline; zero-coefficient features identified and counted; test RMSE reported |
| Task 5: Comparison table | 15 | All three rows filled with correct values from prior tasks |
| Task 6: Recommendation | 15 | Recommendation cites specific metrics; reasoning addresses accuracy-complexity trade-off |
| Total | 100 |