Download evaluation/protocol.py from thu-sail-lab/VETime: direct link, hf CLI and curl.
- Browser
- Download file 3.63 kB
-
https://huggingface.co/thu-sail-lab/VETime/resolve/main/evaluation/protocol.py
- Command line
-
hf download hf://thu-sail-lab/VETime/evaluation/protocol.py
-
curl -L -o protocol.py https://huggingface.co/thu-sail-lab/VETime/resolve/main/evaluation/protocol.py
3.63 kB
| """Fixed-prediction evaluation entry points for the published Test_TSB script.""" | |
| import numpy as np | |
| import torch | |
| from sklearn.metrics import precision_recall_fscore_support | |
| from .basic_metrics import basic_metricor, generate_curve, improved_cardinality_fn | |
| def get_metrics(score, labels, slidingWindow=100, pred=None, version="opt", thre=250): | |
| """Evaluate scores without selecting thresholds from ground-truth labels. | |
| Respect supplied predictions. Otherwise use mean(score) + 3 * std(score), | |
| matching Test_TSB.py. Remove labels == -1 before calibration and evaluation. | |
| Undefined ranking/event metrics are NaN, rather than a fabricated zero. | |
| """ | |
| score = np.asarray(score, dtype=float) | |
| labels = np.asarray(labels) | |
| if score.ndim != 1 or labels.shape != score.shape: | |
| raise ValueError("Scores and labels must be one-dimensional with equal lengths.") | |
| if pred is not None: | |
| pred = np.asarray(pred) | |
| if pred.shape != score.shape: | |
| raise ValueError("Predictions must have the same shape as scores.") | |
| valid = labels != -1 | |
| score, labels = score[valid], labels[valid] | |
| if not len(score) or not np.isfinite(score).all(): | |
| raise ValueError("At least one finite, unpadded score is required.") | |
| if not np.isin(labels, [0, 1]).all(): | |
| raise ValueError("Labels must be 0, 1, or -1 for padding.") | |
| labels = labels.astype(int) | |
| if pred is None: | |
| pred = score > (score.mean() + 3 * score.std()) | |
| else: | |
| pred = pred[valid] | |
| if not np.isin(pred, [0, 1]).all(): | |
| raise ValueError("Predictions must be binary.") | |
| pred = pred.astype(int, copy=True) | |
| if int(slidingWindow) != slidingWindow or slidingWindow < 1: | |
| raise ValueError("slidingWindow must be a positive integer.") | |
| grader = basic_metricor() | |
| precision, recall, f1, _ = precision_recall_fscore_support( | |
| labels, pred, average="binary", zero_division=0 | |
| ) | |
| adjusted = grader.adjustment(labels, pred.copy()) | |
| pa_p, pa_r, pa_f, _ = precision_recall_fscore_support( | |
| labels, adjusted, average="binary", zero_division=0 | |
| ) | |
| t_p, t_r = grader.ts_precision_and_recall( | |
| torch.as_tensor(labels), torch.as_tensor(pred), | |
| recall_cardinality_fn=improved_cardinality_fn, | |
| weighted_precision=True, | |
| ) | |
| t_f = 2 * t_p * t_r / (t_p + t_r) if t_p + t_r else 0.0 | |
| auc_roc = auc_pr = vus_roc = vus_pr = float("nan") | |
| if len(np.unique(labels)) == 2: | |
| auc_roc = grader.metric_ROC(labels, score) | |
| auc_pr = grader.metric_PR(labels, score) | |
| *_, vus_roc, vus_pr = generate_curve( | |
| labels, score, int(slidingWindow), version=version, thre=thre | |
| ) | |
| aff_f = aff_p = aff_r = float("nan") | |
| if labels.any(): | |
| if pred.any(): | |
| aff_f, aff_p, aff_r = grader.metric_Affiliation(labels, score, preds=pred) | |
| else: | |
| aff_f, aff_p, aff_r = 0.0, float("nan"), 0.0 | |
| return {key: float(value) for key, value in { | |
| "AUC-PR": auc_pr, "AUC-ROC": auc_roc, | |
| "VUS-PR": vus_pr, "VUS-ROC": vus_roc, | |
| "Standard-F1": f1, "Standard-Precision": precision, "Standard-Recall": recall, | |
| "PA-F1": pa_f, "PA-Precision": pa_p, "PA-Recall": pa_r, | |
| "Affiliation-F": aff_f, "Affiliation-P": aff_p, "Affiliation-R": aff_r, | |
| "F1_T": t_f, "Precision_T": t_p, "Recall_T": t_r, | |
| }.items()} | |
| def get_metrics_pred(score, labels, pred, slidingWindow=100): | |
| """Evaluate a fixed prediction vector through the same public protocol.""" | |
| return get_metrics(score, labels, slidingWindow=slidingWindow, pred=pred) | |