File size: 2,681 Bytes
e6afd7e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
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))