"""Doğruluk ve kalibrasyon ölçüleri (yalnızca numpy).""" import numpy as np def ece(conf, correct, bins=15): conf, correct = np.asarray(conf, float), np.asarray(correct, float) edges = np.linspace(0, 1, bins + 1) out = 0.0 for lo, hi in zip(edges[:-1], edges[1:]): m = (conf > lo) & (conf <= hi) if lo > 0 else (conf >= lo) & (conf <= hi) if m.any(): out += m.mean() * abs(conf[m].mean() - correct[m].mean()) return float(out) def brier(conf, correct): conf, correct = np.asarray(conf, float), np.asarray(correct, float) return float(np.mean((conf - correct) ** 2)) def auroc(conf, correct): """Güvenin doğru/yanlışı ayırma gücü (Mann-Whitney).""" conf, correct = np.asarray(conf, float), np.asarray(correct, bool) pos, neg = conf[correct], conf[~correct] if len(pos) == 0 or len(neg) == 0: return float("nan") order = np.argsort(np.concatenate([pos, neg]), kind="mergesort") ranks = np.empty(len(order)) allv = np.concatenate([pos, neg])[order] i = 0 r = np.empty(len(order)) while i < len(allv): j = i while j + 1 < len(allv) and allv[j + 1] == allv[i]: j += 1 r[i:j + 1] = (i + j) / 2 + 1 i = j + 1 ranks[order] = r return float((ranks[:len(pos)].sum() - len(pos) * (len(pos) + 1) / 2) / (len(pos) * len(neg))) def risk_coverage(conf, correct, coverages=(1.0, 0.8, 0.6, 0.4, 0.2)): """En emin olduğu adımların %c'sinde doğruluk.""" conf, correct = np.asarray(conf, float), np.asarray(correct, float) order = np.argsort(-conf, kind="stable") out = {} for c in coverages: k = max(1, int(round(c * len(order)))) out[f"acc@{int(c * 100)}%"] = float(correct[order[:k]].mean()) return out def bootstrap_ci(correct, n=1000, seed=0): correct = np.asarray(correct, float) rng = np.random.default_rng(seed) means = [correct[rng.integers(0, len(correct), len(correct))].mean() for _ in range(n)] return float(np.percentile(means, 2.5)), float(np.percentile(means, 97.5)) def summarize(conf, correct): d = {"n": int(len(correct)), "acc": float(np.mean(correct)), "acc_ci95": bootstrap_ci(correct), "ece": ece(conf, correct), "brier": brier(conf, correct), "auroc": auroc(conf, correct)} d.update(risk_coverage(conf, correct)) return d