File size: 2,671 Bytes
d9ca01e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
"""

Evaluation metrics for anomaly detection performance.



Computes accuracy, precision, recall, F1-score, and AUC-ROC.

"""

import numpy as np
from typing import Optional, List
from sklearn.metrics import (
    accuracy_score,
    precision_score,
    recall_score,
    f1_score,
    roc_auc_score,
    confusion_matrix,
    classification_report,
)


class MetricsCalculator:
    """Calculates all evaluation metrics for binary classification."""

    @staticmethod
    def compute_all(

        y_true: list | np.ndarray,

        y_pred: list | np.ndarray,

        y_scores: Optional[list | np.ndarray] = None,

    ) -> dict:
        """

        Compute all metrics.



        Args:

            y_true:   Ground-truth labels (0 = normal, 1 = abnormal).

            y_pred:   Predicted labels.

            y_scores: Predicted probabilities for the positive class

                      (required for AUC-ROC).



        Returns:

            Dictionary of metric_name → value.

        """
        y_true = np.asarray(y_true)
        y_pred = np.asarray(y_pred)

        metrics = {
            "accuracy": accuracy_score(y_true, y_pred),
            "precision": precision_score(y_true, y_pred, zero_division=0),
            "recall": recall_score(y_true, y_pred, zero_division=0),
            "f1_score": f1_score(y_true, y_pred, zero_division=0),
        }

        if y_scores is not None and len(np.unique(y_true)) > 1:
            metrics["auc_roc"] = roc_auc_score(y_true, y_scores)

        return metrics

    @staticmethod
    def get_confusion_matrix(

        y_true: list | np.ndarray,

        y_pred: list | np.ndarray,

    ) -> np.ndarray:
        """Return confusion matrix as a 2×2 numpy array."""
        return confusion_matrix(y_true, y_pred)

    @staticmethod
    def get_classification_report(

        y_true: list | np.ndarray,

        y_pred: list | np.ndarray,

        target_names: list = None,

    ) -> str:
        """Return a formatted classification report."""
        if target_names is None:
            target_names = ["Normal", "Abnormal"]
        return classification_report(
            y_true, y_pred, target_names=target_names, zero_division=0
        )

    @staticmethod
    def format_metrics(metrics: dict) -> str:
        """Pretty-print metrics to a formatted string."""
        lines = []
        for name, value in metrics.items():
            if isinstance(value, float):
                lines.append(f"  {name:>15s}: {value:.4f}")
            else:
                lines.append(f"  {name:>15s}: {value}")
        return "\n".join(lines)