abhi6168 commited on
Commit
0c8b6aa
·
verified ·
1 Parent(s): bc8ec11

Upload folder using huggingface_hub

Browse files
eval/__init__.py ADDED
File without changes
eval/__pycache__/__init__.cpython-314.pyc ADDED
Binary file (167 Bytes). View file
 
eval/__pycache__/metrics.cpython-314.pyc ADDED
Binary file (6.42 kB). View file
 
eval/metrics.py ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Calibration + accuracy metrics shared by every eval path (encoder, decoder-LoRA,
3
+ and later the cascade). Implements exactly what PRD.md Section 5.3/8.1 commits
4
+ to reporting: accuracy, multi-class Brier score, and ECE (equal-mass binning,
5
+ the standard that avoids the equal-width-binning pitfall on skewed confidence
6
+ distributions most models produce).
7
+ """
8
+
9
+ import numpy as np
10
+
11
+
12
+ def accuracy(probs: np.ndarray, labels: np.ndarray) -> float:
13
+ preds = probs.argmax(axis=-1)
14
+ return float((preds == labels).mean())
15
+
16
+
17
+ def brier_score(probs: np.ndarray, labels: np.ndarray, n_classes: int) -> float:
18
+ """Multi-class Brier score: mean squared error between predicted probs and one-hot labels."""
19
+ one_hot = np.zeros_like(probs)
20
+ one_hot[np.arange(len(labels)), labels] = 1.0
21
+ return float(np.mean(np.sum((probs - one_hot) ** 2, axis=-1)))
22
+
23
+
24
+ def expected_calibration_error(probs: np.ndarray, labels: np.ndarray, n_bins: int = 15) -> float:
25
+ """
26
+ ECE using the *confidence of the predicted class* against equal-mass bins
27
+ (sorted-then-split), which is more robust than equal-width bins when a
28
+ model's confidence distribution is heavily skewed toward high confidence
29
+ (the common case post-fine-tuning) — equal-width bins would leave most
30
+ bins near-empty and the ECE estimate noisy.
31
+ """
32
+ confidences = probs.max(axis=-1)
33
+ preds = probs.argmax(axis=-1)
34
+ correct = (preds == labels).astype(np.float64)
35
+
36
+ order = np.argsort(confidences)
37
+ confidences, correct = confidences[order], correct[order]
38
+
39
+ n = len(confidences)
40
+ bin_edges = np.linspace(0, n, n_bins + 1).astype(int)
41
+
42
+ ece = 0.0
43
+ for i in range(n_bins):
44
+ lo, hi = bin_edges[i], bin_edges[i + 1]
45
+ if hi <= lo:
46
+ continue
47
+ bin_conf = confidences[lo:hi].mean()
48
+ bin_acc = correct[lo:hi].mean()
49
+ weight = (hi - lo) / n
50
+ ece += weight * abs(bin_conf - bin_acc)
51
+ return float(ece)
52
+
53
+
54
+ def fit_temperature(logits: np.ndarray, labels: np.ndarray, max_iter: int = 200, lr: float = 0.01) -> float:
55
+ """
56
+ Post-hoc temperature scaling (Guo et al. 2017): find scalar T minimizing
57
+ NLL of softmax(logits / T) on a held-out calibration split. Single
58
+ parameter, convex in log(T), optimized here with plain gradient descent
59
+ to avoid pulling in torch/scipy-specific optimizers for a 1D problem.
60
+ """
61
+ log_t = 0.0 # T starts at 1.0
62
+ labels = labels.astype(np.int64)
63
+ n = len(labels)
64
+ idx = np.arange(n)
65
+
66
+ def grad_at(log_t_val):
67
+ t = np.exp(log_t_val)
68
+ scaled = logits / t
69
+ scaled -= scaled.max(axis=-1, keepdims=True)
70
+ exp_scaled = np.exp(scaled)
71
+ probs = exp_scaled / exp_scaled.sum(axis=-1, keepdims=True)
72
+
73
+ # d(NLL)/d(1/T) = mean(E_p[z] - z_true); d(1/T)/d(log T) = -1/T.
74
+ true_logit = logits[idx, labels]
75
+ expected_logit = (probs * logits).sum(axis=-1)
76
+ d_nll_d_invT = (expected_logit - true_logit).mean()
77
+ return d_nll_d_invT * (-1.0 / t)
78
+
79
+ for _ in range(max_iter):
80
+ log_t -= lr * grad_at(log_t)
81
+
82
+ return float(np.exp(log_t))
83
+
84
+
85
+ def full_report(probs: np.ndarray, labels: np.ndarray, n_classes: int) -> dict:
86
+ return {
87
+ "n": int(len(labels)),
88
+ "accuracy": accuracy(probs, labels),
89
+ "brier": brier_score(probs, labels, n_classes),
90
+ "ece": expected_calibration_error(probs, labels),
91
+ }