Spaces:
Sleeping
Sleeping
| """Reusable utility to compare regression models side by side. | |
| Imported by both ``train.py`` and the EDA notebook to avoid duplication. | |
| """ | |
| from __future__ import annotations | |
| from dataclasses import dataclass | |
| from typing import Iterable | |
| import numpy as np | |
| import pandas as pd | |
| from sklearn.base import RegressorMixin | |
| from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score | |
| from sklearn.model_selection import KFold, cross_val_score | |
| from sklearn.pipeline import Pipeline | |
| class ModelResult: | |
| name: str | |
| mae: float | |
| rmse: float | |
| r2: float | |
| cv_mae_mean: float | None = None | |
| cv_mae_std: float | None = None | |
| def evaluate_pipeline( | |
| name: str, | |
| pipe: Pipeline, | |
| X_train: pd.DataFrame, | |
| y_train: pd.Series, | |
| X_test: pd.DataFrame, | |
| y_test: pd.Series, | |
| cv_folds: int | None = 5, | |
| ) -> ModelResult: | |
| pipe.fit(X_train, y_train) | |
| pred = pipe.predict(X_test) | |
| mae = float(mean_absolute_error(y_test, pred)) | |
| rmse = float(np.sqrt(mean_squared_error(y_test, pred))) | |
| r2 = float(r2_score(y_test, pred)) | |
| cv_mean = cv_std = None | |
| if cv_folds and cv_folds > 1: | |
| kf = KFold(n_splits=cv_folds, shuffle=True, random_state=42) | |
| scores = -cross_val_score( | |
| pipe, X_train, y_train, scoring="neg_mean_absolute_error", cv=kf, n_jobs=-1 | |
| ) | |
| cv_mean = float(scores.mean()) | |
| cv_std = float(scores.std()) | |
| return ModelResult(name, mae, rmse, r2, cv_mean, cv_std) | |
| def results_to_dataframe(results: Iterable[ModelResult]) -> pd.DataFrame: | |
| return pd.DataFrame( | |
| [ | |
| { | |
| "model": r.name, | |
| "MAE": r.mae, | |
| "RMSE": r.rmse, | |
| "R2": r.r2, | |
| "CV_MAE_mean": r.cv_mae_mean, | |
| "CV_MAE_std": r.cv_mae_std, | |
| } | |
| for r in results | |
| ] | |
| ).sort_values("MAE") | |