Updated results, hebrew, abstract, intro, etc.

This commit is contained in:
2026-08-30 06:57:52 +03:00
parent 24d6fac79c
commit 275e29bde0
13 changed files with 353 additions and 268 deletions
+96
View File
@@ -0,0 +1,96 @@
"""
ROC curve illustration for ROLL-AOC.
Shows how ROLL-AOC converts the single-threshold ROLL into AUC optimization:
- ROC curve traced by sweeping threshold τ
- 10 evenly-spaced FPR sample points (as ROLL evaluates in miniature)
- Green shaded region = AUC (area under curve, what we maximize)
- Red shaded region = AOC = 1 − AUC (area over curve, the loss we minimize)
- Vertical segments = per-threshold loss 1 − TPR(αᵢ), one per sampled FPR
Run from the thesis root:
nix develop --command python3 content/method/figures/roll_aoc_roc.py
"""
import numpy as np
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from scipy.stats import norm
OUT_DIR = "content/method/figures"
# --- Parameters (same distributions as roll_principle.py) ------------------
mu0, sig0 = 0.0, 1.00
mu1, sig1 = 1.5, 1.00
# --- ROC curve -------------------------------------------------------------
# Sweep τ from high to low → FPR rises from 0 to 1
tau_grid = np.linspace(norm.ppf(0.9999, mu0, sig0),
norm.ppf(0.0001, mu0, sig0), 3000)
fpr_curve = 1.0 - norm.cdf(tau_grid, mu0, sig0)
tpr_curve = 1.0 - norm.cdf(tau_grid, mu1, sig1)
# Pin endpoints so the fill covers the full unit square correctly
fpr_full = np.concatenate([[0.0], fpr_curve, [1.0]])
tpr_full = np.concatenate([[0.0], tpr_curve, [1.0]])
auc = float(np.trapezoid(tpr_full, fpr_full))
# --- 10 sample FPR points: αᵢ = i/11 for i = 1…10 ------------------------
n_samples = 10
alpha_s = np.array([(i / (n_samples + 1)) for i in range(1, n_samples + 1)])
tpr_s = np.interp(alpha_s, fpr_full, tpr_full)
# --- Palette (matches roll_principle.py) -----------------------------------
C_POS = "#CC6633" # ROC curve (positive-class colour)
C_GREEN = "#44AA77" # AUC fill
C_RED = "#BB3333" # AOC fill / vertical segments
C_DOT = "#333333" # sample dots
# ── Figure ─────────────────────────────────────────────────────────────────
fig, ax = plt.subplots(figsize=(4.8, 4.4))
# Random-classifier diagonal
ax.plot([0, 1], [0, 1], color="#AAAAAA", linestyle="--",
linewidth=0.9, zorder=1, label="Random classifier")
# AUC — green fill under ROC curve
ax.fill_between(fpr_full, 0, tpr_full,
color=C_GREEN, alpha=0.25, zorder=2,
label=rf"AUC $\approx$ {auc:.2f} (maximize)")
# AOC — red fill above ROC curve
ax.fill_between(fpr_full, tpr_full, 1.0,
color=C_RED, alpha=0.22, zorder=2,
label=r"AOC $= 1-\mathrm{AUC}$ (minimize)")
# ROC curve itself
ax.plot(fpr_full, tpr_full, color=C_POS, linewidth=2.0, zorder=3,
label="ROC curve")
# Per-threshold loss segments: vertical from TPR(αᵢ) up to 1
for a_i, t_i in zip(alpha_s, tpr_s):
ax.plot([a_i, a_i], [t_i, 1.0],
color=C_RED, linewidth=1.0, alpha=0.55, zorder=4)
# Sample dots on the ROC curve
ax.scatter(alpha_s, tpr_s,
color=C_DOT, s=35, zorder=5,
label=r"Sampled $\alpha_i$ (ROLL evaluations)")
# --- Axes / labels ---------------------------------------------------------
ax.set_xlabel(r"FPR $(\alpha)$", fontsize=9)
ax.set_ylabel(r"TPR", fontsize=9)
ax.set_xlim(0.0, 1.0)
ax.set_ylim(0.0, 1.0)
ax.set_aspect("equal")
ax.tick_params(labelsize=8)
ax.spines[["top", "right"]].set_visible(False)
ax.legend(fontsize=7.5, loc="lower right", framealpha=0.88)
fig.tight_layout()
fig.savefig(f"{OUT_DIR}/roll_aoc_roc.pdf", bbox_inches="tight")
fig.savefig(f"{OUT_DIR}/roll_aoc_roc.png", bbox_inches="tight", dpi=180)
print(f"Saved to {OUT_DIR}/roll_aoc_roc.{{pdf,png}}")
print(f"AUC = {auc:.4f} AOC = {1-auc:.4f}")