diff --git a/src/evaluation/metrics.py b/src/evaluation/metrics.py index 2293c82..0180ca1 100644 --- a/src/evaluation/metrics.py +++ b/src/evaluation/metrics.py @@ -33,13 +33,17 @@ def expected_calibration_error(y_true, y_prob, n_bins: int = 10) -> float: def binary_metrics(y_true, y_prob, threshold: float = 0.5) -> dict: y_pred = (np.asarray(y_prob) >= threshold).astype(int) + precision = float(precision_score(y_true, y_pred, zero_division=0)) + recall = float(recall_score(y_true, y_pred, zero_division=0)) + f2 = (5.0 * precision * recall) / (4.0 * precision + recall + 1e-12) + return { "roc_auc": safe_auc(y_true, y_prob, "roc"), "pr_auc": safe_auc(y_true, y_prob, "pr"), "f1": float(f1_score(y_true, y_pred, zero_division=0)), - "f2": float((5 * precision_score(y_true, y_pred, zero_division=0) * recall_score(y_true, y_pred, zero_division=0)) / (4 * precision_score(y_true, y_pred, zero_division=0) + recall_score(y_true, y_pred, zero_division=0) + 1e-12)), - "precision": float(precision_score(y_true, y_pred, zero_division=0)), - "recall": float(recall_score(y_true, y_pred, zero_division=0)), + "f2": float(f2), + "precision": precision, + "recall": recall, "brier": float(brier_score_loss(y_true, y_prob)), "ece": expected_calibration_error(y_true, y_prob), } diff --git a/tests/test_binary_metrics_polish.py b/tests/test_binary_metrics_polish.py new file mode 100644 index 0000000..b5cf7d7 --- /dev/null +++ b/tests/test_binary_metrics_polish.py @@ -0,0 +1,19 @@ +"""Regression checks compatible with the project's lightweight test runner.""" + +from src.evaluation.metrics import binary_metrics + + +def test_f2_uses_reported_precision_and_recall() -> None: + cases = [ + ([0, 1, 1, 0], [0.1, 0.9, 0.4, 0.3], 1.0, 0.5), + ([0, 0, 1, 1], [0.8, 0.7, 0.2, 0.1], 0.0, 0.0), + ] + for labels, scores, expected_precision, expected_recall in cases: + result = binary_metrics(labels, scores, threshold=0.5) + assert abs(result["precision"] - expected_precision) < 1e-12 + assert abs(result["recall"] - expected_recall) < 1e-12 + expected_f2 = ( + 5.0 * expected_precision * expected_recall + / (4.0 * expected_precision + expected_recall + 1e-12) + ) + assert abs(result["f2"] - expected_f2) < 1e-12