| from __future__ import annotations |
|
|
| from typing import List |
|
|
| import numpy as np |
| from sklearn.metrics import roc_auc_score |
| from sklearn.preprocessing import label_binarize |
|
|
|
|
| def compute_binary_auc( |
| y_true: np.ndarray, |
| y_scores: np.ndarray, |
| pos_label: str = None, |
| classes: List[str] = None, |
| ) -> float: |
| if len(np.unique(y_true)) < 2: |
| return 0.5 |
|
|
| try: |
| if len(classes) == 2: |
| pos = classes[1] if classes else pos_label |
| binary_true = (y_true == pos).astype(int) |
| return float(roc_auc_score(binary_true, y_scores[:, 1])) |
| else: |
| y_bin = label_binarize(y_true, classes=classes) |
| return float( |
| roc_auc_score(y_bin, y_scores, multi_class="ovr", average="macro") |
| ) |
| except Exception: |
| return 0.5 |
|
|
|
|
| def compute_uncertainty_entropy(proba: np.ndarray) -> float: |
| clipped = np.clip(proba, 1e-10, 1.0) |
| entropy = -np.sum(clipped * np.log(clipped), axis=1) |
| max_entropy = np.log(proba.shape[1]) |
| return float(np.mean(entropy / max_entropy)) if max_entropy > 0 else 0.0 |
|
|
|
|
| def per_sample_uncertainty(proba: np.ndarray) -> np.ndarray: |
| clipped = np.clip(proba, 1e-10, 1.0) |
| entropy = -np.sum(clipped * np.log(clipped), axis=1) |
| max_entropy = np.log(proba.shape[1]) |
| return (entropy / max_entropy) if max_entropy > 0 else entropy |
|
|
|
|
| def cosine_similarity_to_set( |
| embedding: np.ndarray, labeled_embeddings: np.ndarray |
| ) -> float: |
| if labeled_embeddings.shape[0] == 0: |
| return 0.0 |
| mean_labeled = labeled_embeddings.mean(axis=0) |
| norm_emb = np.linalg.norm(embedding) |
| norm_mean = np.linalg.norm(mean_labeled) |
| if norm_emb < 1e-10 or norm_mean < 1e-10: |
| return 0.0 |
| return float(np.dot(embedding, mean_labeled) / (norm_emb * norm_mean)) |
|
|
|
|
| def per_sample_diversity( |
| pool_embeddings: np.ndarray, labeled_embeddings: np.ndarray |
| ) -> np.ndarray: |
| if labeled_embeddings.shape[0] == 0: |
| return np.ones(pool_embeddings.shape[0]) |
| mean_labeled = labeled_embeddings.mean(axis=0) |
| pool_norms = np.linalg.norm(pool_embeddings, axis=1, keepdims=True) |
| mean_norm = np.linalg.norm(mean_labeled) |
| safe_pool_norms = np.where(pool_norms < 1e-10, 1.0, pool_norms) |
| safe_mean_norm = mean_norm if mean_norm > 1e-10 else 1.0 |
| cosines = pool_embeddings.dot(mean_labeled) / ( |
| safe_pool_norms.squeeze() * safe_mean_norm |
| ) |
| return 1.0 - np.clip(cosines, -1.0, 1.0) |
|
|
|
|
| def compute_mean_diversity_score( |
| pool_embeddings: np.ndarray, labeled_embeddings: np.ndarray |
| ) -> float: |
| scores = per_sample_diversity(pool_embeddings, labeled_embeddings) |
| return float(np.mean(scores)) |
|
|