SabaPivot's picture
download
raw
10 kB
"""Figures for the logbook / poster."""
import json
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
OUT = "/home/ubuntu/samuel/ulmc-kl-repro/outputs"
FIG = "/home/ubuntu/samuel/ulmc-kl-repro/figs"
ACC = "#1f6feb"
ACC2 = "#d2691e"
GREY = "#666666"
plt.rcParams.update(
{
"font.size": 9,
"axes.grid": True,
"grid.alpha": 0.25,
"figure.dpi": 160,
"savefig.bbox": "tight",
}
)
def L(name):
return json.load(open(f"{OUT}/{name}.json"))
sc = L("scaling2")
pr = L("prescription")
# ---------------------------------------------------------------- fig 1
fig, ax = plt.subplots(1, 3, figsize=(10.5, 3.1))
r = sc["ulmc"]["d_fixed_trH"]["rows"]
d = np.array([x["d"] for x in r], float)
N = np.array([x["N_eps"] for x in r], float)
ax[0].loglog(d, N / N[0], "o-", color=ACC, label="ULMC (measured)")
r2 = sc["rmd"]["d_fixed_trH"]["rows"]
d2 = np.array([x["d"] for x in r2], float)
N2 = np.array([x["N_eps"] for x in r2], float)
ax[0].loglog(d2, N2 / N2[0], "s-", color=ACC2, label="RMD (measured)")
ax[0].loglog(
d, np.ones_like(d), "--", color=GREY, label=r"dimension-free: $\propto tr(H)^{1/2}$"
)
ax[0].loglog(d, np.sqrt(d / d[0]), ":", color="crimson", label=r"$d^{1/2}$ bound")
ax[0].set_xlabel("dimension $d$ (tr(H)=10, $\\alpha$=0.01, $\\beta$=1 fixed)")
ax[0].set_ylabel("$N_\\epsilon$ / $N_\\epsilon(d{=}11)$")
ax[0].set_title("Claim 1: iterations vs $d$ at fixed tr(H)")
ax[0].legend(fontsize=6.5)
rc = sc["ulmc"]["d_control_H_eq_betaI"]["rows"]
dc = np.array([x["d"] for x in rc], float)
Nc = np.array([x["N_eps"] for x in rc], float)
ax[1].loglog(dc, Nc / Nc[0], "o-", color=ACC, label="ULMC, $H=\\beta I$")
ax[1].loglog(
dc,
np.sqrt(dc / dc[0]),
"--",
color=GREY,
label=r"$\propto tr(H)^{1/2}=(\beta d)^{1/2}$",
)
ax[1].set_xlabel("dimension $d$ (tr(H) = $\\beta d$ grows)")
ax[1].set_ylabel("$N_\\epsilon$ / $N_\\epsilon(d{=}10)$")
ax[1].set_title("Control: real $d$-dependence is detected")
ax[1].legend(fontsize=7)
bl = L("bias_law")["dimension_free_bias_bound"]
rat = [e["ratio"] for e in bl["examples"]]
ax[2].axhline(1.0, color="crimson", ls="--", lw=1.2, label="bound $h^2\\,tr(H)/256$")
ax[2].plot(range(len(rat)), rat, "o", color=ACC, ms=4)
ax[2].set_ylim(0, 1.15)
ax[2].set_xlabel("random spectra (200 sampled, $d \\leq 400$)")
ax[2].set_ylabel("bias / ($h^2$ tr(H)/256)")
ax[2].set_title(
f"exact ULMC bias law\nmax ratio {bl['max_ratio_bias_over_h2trH_div256']:.3f} $\\leq$ 1"
)
ax[2].legend(fontsize=7)
fig.tight_layout()
fig.savefig(f"{FIG}/fig1_dimension_free.png")
# ---------------------------------------------------------------- fig 2
fig, ax = plt.subplots(1, 3, figsize=(10.5, 3.1))
for i, (key, xl, pred_u, pred_r) in enumerate(
[
("eps", "$\\epsilon$", -1.0, -2 / 3),
("trH", "tr(H)", 0.5, 1 / 3),
("kappa", "$\\kappa$", 1.5, 1.0),
]
):
for sch, col, mk in (("ulmc", ACC, "o"), ("rmd", ACC2, "s")):
rr = sc[sch][key]["rows"]
x = np.array([q[key if key != "eps" else "eps"] for q in rr], float)
y = np.array([q["N_eps"] for q in rr], float)
Lc = np.array([q["L"] for q in rr], float)
e = sc[sch][key]["fit_exponent_log_corrected"]
ax[i].loglog(
x,
y / Lc,
mk + "-",
color=col,
ms=4,
label=f"{sch.upper()} fit {e:+.3f} (thm {sc[sch][key]['predicted']:+.3f})",
)
ax[i].set_xlabel(xl)
ax[i].set_ylabel("$N_\\epsilon\\,/\\,\\log$ factor")
ax[i].legend(fontsize=6.5)
ax[0].set_title("Claim 2/3: $\\epsilon$ exponent")
ax[1].set_title("tr(H) exponent")
ax[2].set_title("$\\kappa$ exponent (ULMC: 1.0 vs claimed 1.5)")
fig.tight_layout()
fig.savefig(f"{FIG}/fig2_exponents.png")
# ---------------------------------------------------------------- fig 3
fig, ax = plt.subplots(1, 2, figsize=(7.6, 3.1))
for sch, col, mk in (("ulmc", ACC, "o"), ("rmd", ACC2, "s")):
rr = pr[sch]["rows"]
k = np.array([q["kappa"] for q in rr], float)
sf = np.array([q["shortfall_factor"] for q in rr], float)
ax[0].loglog(
k,
sf,
mk + "-",
color=col,
ms=4,
label=f"{sch.upper()} (Thm {'4.3' if sch == 'ulmc' else '5.2'})",
)
ax[0].loglog(k, np.sqrt(k / k[0]), ":", color="crimson", label=r"$\kappa^{1/2}$")
ax[0].axhline(1, color=GREY, ls="--", lw=1)
ax[0].set_xlabel("$\\kappa$")
ax[0].set_ylabel("steps actually needed / steps prescribed")
ax[0].set_title("Theorem's own $(h,N)$ pairing")
ax[0].legend(fontsize=7)
for sch, col, mk, th in (("ulmc", ACC, "o", 0.5), ("rmd", ACC2, "s", 1.0)):
rr = pr[sch + "_simulated_time"]["rows"]
k = np.array([q["kappa"] for q in rr], float)
nh = np.array([q["Nh"] for q in rr], float)
e = pr[sch + "_simulated_time"]["Nh_exponent_in_kappa"]
ax[1].loglog(
k,
nh,
mk + "-",
color=col,
ms=4,
label=f"{sch.upper()} measured {e:.2f} (thm {th})",
)
ax[1].loglog(
k,
nh[0] * (k / k[0]) ** 0.5,
":",
color="crimson",
label="Thm 4.3 implies $\\kappa^{1/2}$",
)
ax[1].set_xlabel("$\\kappa$")
ax[1].set_ylabel("minimum simulated time $N h$")
ax[1].set_title("Required burn-in time")
ax[1].legend(fontsize=6.5)
fig.tight_layout()
fig.savefig(f"{FIG}/fig3_prescription.png")
# ---------------------------------------------------------------- fig 4
lm = L("lemma61")
fig, ax = plt.subplots(1, 2, figsize=(7.6, 3.1))
s = np.geomspace(1.02, 1e3, 400)
ax[0].semilogx(
s,
2 * s / (1 + s - np.log(s)),
color=ACC,
lw=1.8,
label="$E_\\mu[p^\\top H p]\\,/\\,(tr H+\\beta KL)$",
)
ax[0].axhline(1.0, color=GREY, ls="--", label="Lemma 6.1 as printed")
ax[0].axhline(
lm["C_star_closed_form"],
color="crimson",
ls="-.",
label="$C^*=2e^2/(e^2-1)=2.3130$",
)
ax[0].axvline(np.e**2, color="crimson", ls=":", lw=1)
ax[0].set_xlabel("momentum covariance $s$ of $\\mu$ ($H=\\beta I$)")
ax[0].set_ylabel("LHS / RHS")
ax[0].set_title("Claim 5: Lemma 6.1 violated for $s>1$")
ax[0].legend(fontsize=6.5)
rg = lm["random_gaussian_search"]
nq = lm["nonquadratic_nonconvex_V_quadrature"]
lbl = [
"Gaussian $\\mu$\ngradient",
"Gaussian $\\mu$\nmomentum",
"non-quadratic\nnon-convex $V$",
]
val = [rg["worst_ratio_gradient"], rg["worst_ratio_momentum"], nq["worst_ratio"]]
ax[1].bar(lbl, val, color=[ACC, ACC, ACC2], width=0.55)
ax[1].axhline(1.0, color=GREY, ls="--", label="printed constant 1")
ax[1].axhline(lm["C_star_closed_form"], color="crimson", ls="-.", label="$C^*$")
ax[1].set_ylabel("worst observed LHS/RHS")
ax[1].set_title("worst ratio found; none exceeds $C^*$")
ax[1].legend(fontsize=7)
fig.tight_layout()
fig.savefig(f"{FIG}/fig4_lemma61.png")
# ---------------------------------------------------------------- fig 5
try:
nqd = L("nonquadratic")
fig, ax = plt.subplots(1, 2, figsize=(7.6, 3.1))
b = nqd["bias_law_nonquadratic"]
for sch, col, mk in (
("ulmc", ACC, "o"),
("lmc", "crimson", "^"),
("composite", ACC2, "s"),
):
ax[0].loglog(
b[sch]["h"],
b[sch]["floor"],
mk + "-",
color=col,
ms=4,
label=f"{sch.upper()} slope {b[sch]['h_exponent']:.2f}",
)
ax[0].set_xlabel("step size $h$")
ax[0].set_ylabel("stationary KL bias (1 stiff coord.)")
ax[0].set_title("Non-quadratic $V$: ULMC $O(h^2)$ vs LMC $O(h)$")
ax[0].legend(fontsize=7)
hh = nqd["head_to_head_nonquadratic"]
rr = [r for r in hh["rows"] if r["ulmc"]["N_eps"]]
e = np.array([r["eps"] for r in rr])
for sch, col, mk in (
("ulmc", ACC, "o"),
("lmc", "crimson", "^"),
("composite", ACC2, "s"),
):
ax[1].loglog(
e,
[r[sch]["N_eps"] for r in rr],
mk + "-",
color=col,
ms=4,
label=f"{sch.upper()} slope {hh[sch + '_eps_exponent']:.2f}",
)
ax[1].set_xlabel("$\\epsilon$")
ax[1].set_ylabel("$N_\\epsilon$")
ax[1].set_title(
f"Claim 6: ridge-separable, tr(H)={hh['trH']:.0f} $\\ll$ "
f"$\\beta d$={hh['beta_times_d']:.0f}"
)
ax[1].legend(fontsize=7)
fig.tight_layout()
fig.savefig(f"{FIG}/fig5_composite.png")
except FileNotFoundError:
print("nonquadratic.json not ready")
# ---------------------------------------------------------------- fig 6
gc = L("genconvex")
fig, ax = plt.subplots(1, 2, figsize=(7.6, 3.1))
for sch, col, mk in (("ulmc", ACC, "o"), ("rmd", ACC2, "s")):
rr = gc[sch]["d_fixed_trH"]["rows"]
d = np.array([q["d"] for q in rr], float)
N = np.array([q["N_eps"] for q in rr], float)
ax[0].loglog(
d,
N / N[0],
mk + "-",
color=col,
ms=4,
label=f"{sch.upper()} exponent {gc[sch]['d_fixed_trH']['fit_exponent']:+.3f}",
)
ax[0].loglog(d, np.sqrt(d / d[0]), ":", color="crimson", label="$d^{1/2}$")
ax[0].axhline(1, color=GREY, ls="--")
ax[0].set_xlabel("dimension $d$ (tr(H)=6, $W$=3 fixed, $\\alpha\\to0$)")
ax[0].set_ylabel("$N_\\epsilon$ / $N_\\epsilon(d{=}20)$")
ax[0].set_title("Claim 4: dimension-free at $\\alpha\\to0$")
ax[0].legend(fontsize=7)
for sch, col, mk, p in (("ulmc", ACC, "o", -4.0), ("rmd", ACC2, "s", -3.0)):
rr = gc[sch]["eps"]["rows"]
e = np.array([q["eps"] for q in rr], float)
N = np.array([q["N_eps"] for q in rr], float)
ax[1].loglog(
e,
N,
mk + "-",
color=col,
ms=4,
label=f"{sch.upper()} measured {gc[sch]['eps']['fit_exponent']:.2f}",
)
ax[1].loglog(
e,
N[-1] * (e / e[-1]) ** p,
":",
color=col,
lw=1,
label=f"Thm bound $\\epsilon^{{{p:.0f}}}$",
)
ax[1].set_xlabel("$\\epsilon$")
ax[1].set_ylabel("$N_\\epsilon$")
ax[1].set_title("$\\alpha=0$ rate: bound holds, far from tight")
ax[1].legend(fontsize=6)
fig.tight_layout()
fig.savefig(f"{FIG}/fig6_genconvex.png")
print("figures written")

Xet Storage Details

Size:
10 kB
·
Xet hash:
1cc5064613589ace3030dc8941fe3246dae29a431f41f158bf802da009bf5958

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.