Spaces:
Sleeping
Sleeping
| """src/training/metrics.py — Shared metric computation utilities.""" | |
| from __future__ import annotations | |
| import numpy as np | |
| from sklearn.metrics import ( | |
| roc_auc_score, f1_score, accuracy_score, | |
| precision_score, recall_score, average_precision_score, | |
| roc_curve, | |
| ) | |
| def compute_auc(y_true: list, y_scores: list) -> float: | |
| if len(set(y_true)) < 2: | |
| return 0.5 | |
| return float(roc_auc_score(y_true, y_scores)) | |
| def compute_eer(y_true: list, y_scores: list) -> float: | |
| if len(set(y_true)) < 2: | |
| return 0.5 | |
| fpr, tpr, _ = roc_curve(y_true, y_scores) | |
| idx = int(np.argmin(np.abs(fpr - (1 - tpr)))) | |
| return float(fpr[idx]) | |
| def optimal_threshold(y_true: list, y_scores: list) -> float: | |
| """Threshold that maximises F1 on the provided set.""" | |
| from sklearn.metrics import precision_recall_curve | |
| precision, recall, thresholds = precision_recall_curve(y_true, y_scores) | |
| f1 = 2 * precision * recall / (precision + recall + 1e-8) | |
| best = int(np.argmax(f1[:-1])) | |
| return float(thresholds[best]) | |
| def compute_all( | |
| y_true: list, | |
| y_scores: list, | |
| threshold: float = 0.5, | |
| ) -> dict: | |
| y_pred = (np.array(y_scores) >= threshold).astype(int) | |
| return { | |
| "auc": compute_auc(y_true, y_scores), | |
| "auc_pr": float(average_precision_score(y_true, y_scores)) if len(set(y_true)) > 1 else 0.5, | |
| "eer": compute_eer(y_true, y_scores), | |
| "f1": float(f1_score(y_true, y_pred, zero_division=0)), | |
| "accuracy": float(accuracy_score(y_true, y_pred)), | |
| "precision": float(precision_score(y_true, y_pred, zero_division=0)), | |
| "recall": float(recall_score(y_true, y_pred, zero_division=0)), | |
| "threshold": threshold, | |
| } | |