SabaPivot's picture
download
raw
8.62 kB
"""Poster figures from the claim JSON outputs. CPU, matplotlib Agg."""
import json
import sys
import numpy as np
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
OUT = "/home/ubuntu/samuel/sgmcmc-uq-repro/outputs"
FIG = "/home/ubuntu/samuel/sgmcmc-uq-repro/figs"
ACC, ACC2, EMPH, GREY = "#0E6E5C", "#7BC4B4", "#C9782A", "#7A7A7A"
plt.rcParams.update(
{
"font.size": 13,
"axes.spines.top": False,
"axes.spines.right": False,
"axes.linewidth": 1.1,
"figure.dpi": 170,
"savefig.bbox": "tight",
}
)
def J(n):
return json.load(open(f"{OUT}/{n}"))
# ---------------------------------------------------------------- fig 1 ----
c1 = J("claim1_thm41.json")
lam = np.array([r["lam"] for r in c1["sweep"]])
err = np.array([r["rel_cov_err"] for r in c1["sweep"]])
se = np.array([r["rel_cov_err_se"] for r in c1["sweep"]])
sd = np.array([r["rel_sd_err"] for r in c1["sweep"]])
fig, ax = plt.subplots(figsize=(6.4, 4.6))
ax.errorbar(
lam,
err,
yerr=se,
marker="o",
color=ACC,
lw=2.2,
ms=7,
capsize=3,
label=r"$\|\Sigma_\theta-\Sigma_\psi\|_F/\|\Sigma_\theta\|_F$",
)
ax.plot(
lam,
sd,
marker="s",
color=ACC2,
lw=2.0,
ms=6,
ls="--",
label=r"$\max_d\,|\sigma_{\theta,d}-\sigma_{\psi,d}|/\sigma_{\theta,d}$",
)
k = err[0] / np.sqrt(lam[0])
ax.plot(
lam,
k * np.sqrt(lam),
color=EMPH,
lw=2.4,
ls=":",
label=r"theorem rate $C_v\lambda^{1/2}$ (anchored at $\lambda_{\min}$)",
)
ax.set_xscale("log")
ax.set_yscale("log")
ax.set_xlabel(r"step size $\lambda$")
ax.set_ylabel("relative error")
ax.set_title(
f"Thm 4.1: fitted exponent {c1['fitted_exponent_cov']:.2f} " r"$\geq 1/2$",
fontsize=13,
)
ax.legend(fontsize=10, frameon=False, loc="upper left")
ax.grid(alpha=0.25, which="both")
fig.savefig(f"{FIG}/claim1_thm41.png")
plt.close(fig)
# ---------------------------------------------------------------- fig 2 ----
c3 = J("claim3_w2.json")
fig, axs = plt.subplots(1, 2, figsize=(10.4, 4.3))
L = c3["lambda_sweep"]
x = np.array([r["lam"] for r in L])
u = np.array([r["w2_coupling_upper"] for r in L])
lo = np.array([r["w2_marginal_lower"] for r in L])
axs[0].fill_between(x, lo, u, color=ACC2, alpha=0.45, label="$W_2$ bracket")
axs[0].plot(x, u, "o-", color=ACC, lw=2.2, ms=6, label="synchronous coupling (upper)")
axs[0].plot(x, u[0] * (x / x[0]), ls=":", color=EMPH, lw=2.4, label=r"slope $1$")
axs[0].set_xscale("log")
axs[0].set_yscale("log")
axs[0].set_xlabel(r"$\lambda$ ($B=16$)")
axs[0].set_ylabel(r"$W_2(\pi_\theta,\pi_\psi)$")
axs[0].set_title(
f"fitted {c3['fitted_exponent_lambda']:.3f} (predicted 1)", fontsize=12
)
Bs = c3["batch_sweep"]
xb = np.array([r["B"] for r in Bs])
ub = np.array([r["w2_coupling_upper"] for r in Bs])
lob = np.array([r["w2_marginal_lower"] for r in Bs])
axs[1].fill_between(xb, lob, ub, color=ACC2, alpha=0.45)
axs[1].plot(xb, ub, "o-", color=ACC, lw=2.2, ms=6)
axs[1].plot(
xb, ub[0] * (xb / xb[0]) ** -1.0, ls=":", color=EMPH, lw=2.4, label=r"slope $-1$"
)
axs[1].set_xscale("log")
axs[1].set_yscale("log")
axs[1].set_xlabel(r"batch size $B$ ($\lambda=0.05$)")
axs[1].set_title(f"fitted {c3['fitted_exponent_B']:.3f} (predicted $-1$)", fontsize=12)
for a in axs:
a.grid(alpha=0.25, which="both")
a.legend(fontsize=10, frameon=False)
fig.suptitle(r"Cor 4.6: $W_2(\pi_\theta,\pi_\psi)\leq A\lambda/B$", fontsize=14)
fig.savefig(f"{FIG}/claim3_w2.png")
plt.close(fig)
# ---------------------------------------------------------------- fig 3 ----
c5 = J("claim5_boston.json")
rows = [r for r in c5["results"] if r["loss"] == "log" and "cov_err_median" in r]
meth = ["CT", "LR+WS", "DQ+const", "DQ+exact", "DQ+exact-cf"]
paper = {
("CT", 16): 0.247,
("CT", 50): 0.589,
("LR+WS", 16): 9.23e8,
("LR+WS", 50): 1.40e7,
("DQ+exact", 16): 0.337,
("DQ+exact", 50): 0.352,
("DQ+exact-cf", 16): 0.337,
("DQ+exact-cf", 50): 0.352,
}
fig, ax = plt.subplots(figsize=(8.2, 4.4))
w = 0.36
xs = np.arange(len(meth))
for j, B in enumerate([16, 50]):
vals = []
for mth in meth:
r = [q for q in rows if q["method"] == mth and q["B"] == B][0]
v = r["cov_err_median"]
vals.append(v if np.isfinite(v) else 1e12)
ax.bar(
xs + (j - 0.5) * w,
vals,
w,
color=[ACC, ACC2][j],
label=f"reproduced, $B={B}$",
edgecolor="white",
)
for j, B in enumerate([16, 50]):
for i, mth in enumerate(meth):
if (mth, B) in paper:
ax.plot(
[xs[i] + (j - 0.5) * w - w / 2, xs[i] + (j - 0.5) * w + w / 2],
[paper[(mth, B)]] * 2,
color=EMPH,
lw=2.6,
label="paper Table 3" if (i == 0 and j == 0) else None,
)
ax.set_yscale("log")
ax.set_xticks(xs)
ax.set_xticklabels(
["CT", "LR+WS", "DQ+const", "DQ+exact\n(root solve)", "DQ+exact\n(closed form)"],
fontsize=10,
)
ax.axhline(1.0, color=GREY, lw=1, ls="--")
ax.set_ylabel(r"$\|\hat S-S_\star\|_F/\|S_\star\|_F$ (median of 30)")
ax.set_title(
"Table 3, Boston housing, log loss (bars: this reproduction; "
"orange rules: paper)",
fontsize=12,
)
ax.legend(fontsize=10, frameon=False, ncol=2)
ax.grid(alpha=0.25, axis="y", which="both")
fig.savefig(f"{FIG}/claim5_boston.png")
plt.close(fig)
# ---------------------------------------------------------------- fig 4 ----
c6 = J("claim6_propB1.json")
g = c6["grid"]
ks = sorted(set(r["kappa"] for r in g))
def agg(key):
return [np.median([r[key] for r in g if r["kappa"] == kk]) for kk in ks]
fig, ax = plt.subplots(figsize=(6.6, 4.4))
kk = np.array(ks)
kk_p = np.where(kk == 0, 3e-8, kk)
ax.plot(
kk_p,
np.maximum(agg("B3_resid_SGD"), 1e-17),
"o-",
color=ACC,
lw=2.2,
ms=7,
label=r"Eq. (B.3), SGD ($\beta=\infty$)",
)
ax.plot(
kk_p,
np.maximum(agg("B3_resid_SGLD_paper"), 1e-17),
"s-",
color=EMPH,
lw=2.4,
ms=7,
label=r"Eq. (B.3) as printed, SGLD ($\beta=N$)",
)
ax.plot(
kk_p,
np.maximum(agg("B3_resid_SGLD_corrected"), 1e-17),
"^--",
color=ACC2,
lw=2.2,
ms=7,
label="corrected temperature term, SGLD",
)
ax.set_xscale("log")
ax.set_yscale("log")
ax.set_xlabel(r"momentum $\kappa$ ($\kappa=0$ plotted at the left edge)")
ax.set_ylabel("relative residual of Eq. (B.3)")
ax.axhline(1e-14, color=GREY, lw=1, ls=":")
ax.text(4e-8, 2.5e-14, "machine precision", fontsize=9, color=GREY)
ax.set_title(
"Prop B.1: exact for SGD and as $\\kappa\\to0$; the SGLD\n"
"temperature term is wrong for $\\kappa>0$",
fontsize=12,
)
ax.legend(fontsize=9.5, frameon=False, loc="center left")
ax.grid(alpha=0.25, which="both")
fig.savefig(f"{FIG}/claim6_propB1.png")
plt.close(fig)
# ---------------------------------------------------------------- fig 5 ----
c2 = J("claim2_thm43.json")
c4 = J("claim4_alg1.json")
fig, axs = plt.subplots(1, 2, figsize=(10.4, 4.2))
labels = [
"empirical MC\n(1.8M grads)",
"exact finite-domain\n(156 configs)",
"exhaustive minibatch\nenumeration",
]
vals = [
max(r["rel_err_formula_vs_MC"] for r in c2["T1_empirical_mc"]),
c2["T2_exact_finite_domain"]["worst_rel_err"],
max(r["rel_err"] for r in c2["T3_exhaustive"]),
]
axs[0].bar(range(3), vals, color=[ACC2, ACC, ACC], edgecolor="white")
axs[0].set_yscale("log")
axs[0].set_xticks(range(3))
axs[0].set_xticklabels(labels, fontsize=9.5)
axs[0].axhline(1e-14, color=GREY, ls=":", lw=1)
axs[0].set_ylabel("worst relative error of Eq. (12)")
axs[0].set_title("Thm 4.3 verification", fontsize=12)
axs[0].grid(alpha=0.25, axis="y", which="both")
s2 = [r for r in c4["stage2"] if r["B"] in (16, 200)]
mm = ["CT", "LR+WS", "DQ+const", "DQ+exact"]
for j, B in enumerate([16, 200]):
v = [
max(
[q for q in s2 if q["method"] == m and q["B"] == B][0][
"exact_proxy_cov_vs_target"
],
1e-16,
)
for m in mm
]
axs[1].bar(
np.arange(4) + (j - 0.5) * 0.36,
v,
0.36,
color=[ACC, ACC2][j],
label=f"$B={B}$",
edgecolor="white",
)
axs[1].set_yscale("log")
axs[1].set_xticks(range(4))
axs[1].set_xticklabels(mm, fontsize=10)
axs[1].set_ylabel(r"$\|\Sigma_\psi(\Lambda)-\hat S\|_F/\|\hat S\|_F$")
axs[1].set_title(
"Alg 1 stage 2: does the tuned $\\Lambda$ hit the target?", fontsize=12
)
axs[1].legend(fontsize=10, frameon=False)
axs[1].grid(alpha=0.25, axis="y", which="both")
fig.savefig(f"{FIG}/claim24_alg1.png")
plt.close(fig)
print("figures written to", FIG)

Xet Storage Details

Size:
8.62 kB
·
Xet hash:
666dbb32cd789e2692c1a02180938f99988fdd723b2892d366284b9ee2c16e53

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