|
16 | 16 | ) |
17 | 17 |
|
18 | 18 | from cybench.datasets.dataset import Dataset |
19 | | -from cybench.evaluation.eval import evaluate_predictions |
| 19 | +from cybench.evaluation.eval import evaluate_predictions, get_default_metrics |
20 | 20 | from cybench.models.naive_models import AverageYieldModel |
21 | 21 | from cybench.models.trend_models import TrendModel |
22 | 22 | from cybench.models.sklearn_models import SklearnRidge, SklearnRandomForest |
@@ -252,55 +252,76 @@ def get_prediction_residuals(run_name: str, model_names: dict) -> pd.DataFrame: |
252 | 252 | return df_all |
253 | 253 |
|
254 | 254 |
|
| 255 | +def _prepare_targets_preds(df_yr, model_name, y_loc_mean=None, residual=False): |
| 256 | + """Prepare y_true and y_pred, optionally using residuals.""" |
| 257 | + y_true = df_yr[KEY_TARGET].values |
| 258 | + y_pred = df_yr[model_name].values |
| 259 | + |
| 260 | + if residual and y_loc_mean is not None: |
| 261 | + y_true = y_true - df_yr[KEY_LOC].map(y_loc_mean) |
| 262 | + y_pred = y_pred - df_yr[KEY_LOC].map(y_loc_mean) |
| 263 | + |
| 264 | + return y_true, y_pred |
| 265 | + |
| 266 | + |
255 | 267 | def compute_metrics( |
256 | 268 | run_name: str, |
257 | 269 | model_names: list = None, |
| 270 | + residual: bool = False, |
258 | 271 | ) -> pd.DataFrame: |
259 | 272 | """ |
260 | 273 | Compute evaluation metrics on saved predictions. |
| 274 | +
|
261 | 275 | Args: |
262 | | - run_name (str): The name of the run. Will be used to store log files and model results |
263 | | - model_names (list) : names of models |
| 276 | + run_name (str): The name of the run. Will be used to store log files and model results. |
| 277 | + model_names (list): Names of models to evaluate. If None, all model columns are used. |
| 278 | + residual (bool): If True, compute metrics on residuals (values adjusted per location). |
264 | 279 |
|
265 | 280 | Returns: |
266 | | - a pd.DataFrame containing evaluation metrics |
| 281 | + pd.DataFrame containing evaluation metrics |
267 | 282 | """ |
268 | 283 | df_all = load_results(run_name) |
269 | 284 | if df_all.empty: |
270 | 285 | return pd.DataFrame(columns=[KEY_COUNTRY, "model", KEY_YEAR]) |
271 | 286 |
|
272 | 287 | rows = [] |
273 | 288 | country_codes = df_all[KEY_COUNTRY].unique() |
| 289 | + |
274 | 290 | for cn in country_codes: |
275 | 291 | df_cn = df_all[df_all[KEY_COUNTRY] == cn] |
276 | 292 | all_years = sorted(df_cn[KEY_YEAR].unique()) |
| 293 | + |
| 294 | + # Precompute location means for residuals |
| 295 | + y_loc_mean = df_cn.groupby(KEY_LOC)[KEY_TARGET].mean() if residual else None |
| 296 | + |
277 | 297 | for yr in all_years: |
278 | 298 | df_yr = df_cn[df_cn[KEY_YEAR] == yr] |
279 | | - y_true = df_yr[KEY_TARGET].values |
| 299 | + |
280 | 300 | if model_names is None: |
281 | 301 | model_names = [ |
282 | | - c |
283 | | - for c in df_yr.columns |
| 302 | + c for c in df_yr.columns |
284 | 303 | if c not in [KEY_COUNTRY, KEY_LOC, KEY_YEAR, KEY_TARGET] |
285 | 304 | ] |
286 | 305 |
|
287 | 306 | for model_name in model_names: |
288 | | - metrics = evaluate_predictions(y_true, df_yr[model_name].values) |
| 307 | + y_true, y_pred = _prepare_targets_preds(df_yr, model_name, y_loc_mean, residual) |
| 308 | + |
| 309 | + # Select metrics based on residual mode |
| 310 | + metrics_to_use = get_default_metrics(residual=residual) |
| 311 | + metrics = evaluate_predictions(y_true, y_pred, metrics=metrics_to_use) |
| 312 | + |
289 | 313 | metrics_row = { |
290 | 314 | KEY_COUNTRY: cn, |
291 | 315 | "model": model_name, |
292 | 316 | KEY_YEAR: yr, |
| 317 | + **metrics |
293 | 318 | } |
294 | | - |
295 | | - for metric_name, value in metrics.items(): |
296 | | - metrics_row[metric_name] = value |
297 | | - |
298 | 319 | rows.append(metrics_row) |
299 | 320 |
|
300 | | - df_all = pd.DataFrame(rows) |
301 | | - df_all.set_index([KEY_COUNTRY, "model", KEY_YEAR], inplace=True) |
| 321 | + df_out = pd.DataFrame(rows) |
| 322 | + df_out.set_index([KEY_COUNTRY, "model", KEY_YEAR], inplace=True) |
302 | 323 |
|
303 | | - return df_all |
| 324 | + return df_out |
304 | 325 |
|
305 | 326 |
|
306 | 327 | def run_benchmark_on_all_data(): |
|
0 commit comments