Buckets:
| # /// script | |
| # requires-python = ">=3.10" | |
| # dependencies = ["numpy", "scipy", "torch"] | |
| # /// | |
| """Claim 6 GPU-scaled audit — uniform coverage of the OFUL-style confidence sets | |
| (paper Eqs. (4)-(5) + Lemma B.2) with thousands of Monte-Carlo replications. | |
| Batched over M replications in torch (float64). Designs are sequences of | |
| transport plans produced by batched log-domain Sinkhorn on random / adaptively | |
| chosen (estimate-dependent) costs. Verifies | |
| P( theta* in C_t(delta) for ALL t <= T ) >= 1 - delta/2 | |
| and the controls (width/4, noise 4x) that break the theorem's conditions. | |
| Writes results JSON to --out (mounted bucket path inside a HF Job). | |
| """ | |
| import argparse | |
| import json | |
| import math | |
| import os | |
| import sys | |
| import time | |
| import numpy as np | |
| import torch | |
| # ---- minimal instance construction (self-contained; mirrors botlib) -------- | |
| def trig_features_1d(u, n_feats): | |
| feats = np.empty((n_feats, len(u))) | |
| freqs = np.empty(n_feats) | |
| for m in range(n_feats): | |
| if m == 0: | |
| feats[m] = 1.0; freqs[m] = 0 | |
| else: | |
| k = (m + 1) // 2 | |
| ph = 2 * np.pi * k * u | |
| feats[m] = np.cos(ph) if (m % 2 == 1) else np.sin(ph) | |
| freqs[m] = k | |
| return feats, freqs | |
| def build_instance(K, Kp, seed): | |
| rng = np.random.default_rng(seed) | |
| x = np.sort(rng.uniform(0.02, 0.98, K)) + rng.normal(0, 1e-3, K) | |
| y = np.sort(rng.uniform(0.02, 0.98, Kp)) + rng.normal(0, 1e-3, Kp) | |
| mu = rng.dirichlet(np.full(K, 5.0)); mu = np.maximum(mu, 1e-3); mu /= mu.sum() | |
| nu = rng.dirichlet(np.full(Kp, 5.0)); nu = np.maximum(nu, 1e-3); nu /= nu.sum() | |
| rho = np.outer(mu, nu).ravel() | |
| N = K * Kp | |
| fx, frx = trig_features_1d(x, 2 * K + 3) | |
| fy, fry = trig_features_1d(y, 2 * Kp + 3) | |
| pairs = [(m1, m2) for m1 in range(len(fx)) for m2 in range(len(fy))] | |
| pairs.sort(key=lambda p: (max(frx[p[0]], fry[p[1]]), frx[p[0]] + fry[p[1]], p[0] + p[1], p)) | |
| cands = np.asarray([np.outer(fx[m1], fy[m2]).ravel() for (m1, m2) in pairs]) | |
| B = [] | |
| for f in cands: | |
| g = f.astype(float).copy() | |
| for _ in range(2): | |
| if B: | |
| Bm = np.asarray(B) | |
| g = g - Bm.T @ (Bm @ (rho * g)) | |
| nrm = np.sqrt(g @ (rho * g)) | |
| if nrm > 1e-8: | |
| B.append(g / nrm) | |
| if len(B) == N: | |
| break | |
| B = np.asarray(B) | |
| X, Y = np.meshgrid(x, y, indexing="ij") | |
| cost = np.cos(2 * np.pi * (X - Y)) + 0.5 * np.sin(2 * np.pi * X) * np.cos(4 * np.pi * Y) + 0.3 * X * Y | |
| theta_star = B @ (rho * cost.ravel()) | |
| return dict(mu=mu, nu=nu, rho=rho, B=B, cost=cost, theta_star=theta_star, K=K, Kp=Kp, N=N) | |
| def batched_sinkhorn(mu, nu, M, eps, n_iter=60): | |
| """Batched log-domain Sinkhorn. M: (B,K,K'), eps: scalar or (B,1,1).""" | |
| B = M.shape[0] | |
| logmu = torch.log(mu)[None, :, None] # (1,K,1) | |
| lognu = torch.log(nu)[None, None, :] # (1,1,K') | |
| f = torch.zeros(M.shape[0], M.shape[1], 1, dtype=M.dtype, device=M.device) | |
| g = torch.zeros(M.shape[0], 1, M.shape[2], dtype=M.dtype, device=M.device) | |
| for _ in range(n_iter): | |
| f = -eps * torch.logsumexp((g - M) / eps + lognu, dim=2, keepdim=True) | |
| g = -eps * torch.logsumexp((f - M) / eps + logmu, dim=1, keepdim=True) | |
| P = torch.exp((f + g - M) / eps + logmu + lognu) | |
| P = torch.clamp(P, min=0) | |
| P = P / P.sum(dim=(1, 2), keepdim=True) | |
| return P | |
| def run_variant(inst, M_reps, T, sigma, delta, lam, Cbar, seed, device, | |
| beta_scale=1.0, sigma_run=None, adaptive=False, dtype=torch.float64): | |
| torch.manual_seed(seed) | |
| K, Kp, N = inst["K"], inst["Kp"], inst["N"] | |
| sig_run = sigma if sigma_run is None else sigma_run | |
| mu = torch.tensor(inst["mu"], dtype=dtype, device=device) | |
| nu = torch.tensor(inst["nu"], dtype=dtype, device=device) | |
| Bmat = torch.tensor(inst["B"], dtype=dtype, device=device) # (N,N) | |
| th_star = torch.tensor(inst["theta_star"], dtype=dtype, device=device) # (N,) | |
| A = torch.zeros(M_reps, N, N, dtype=dtype, device=device) | |
| Vinv = torch.eye(N, dtype=dtype, device=device).expand(M_reps, N, N).clone() / lam | |
| bvec = torch.zeros(M_reps, N, dtype=dtype, device=device) | |
| ld = torch.zeros(M_reps, dtype=dtype, device=device) # logdet(I + lam^-1 A_t) | |
| covered = torch.ones(M_reps, dtype=torch.bool, device=device) | |
| min_slack = torch.full((M_reps,), float("inf"), dtype=dtype, device=device) | |
| theta_hat = torch.zeros(M_reps, N, dtype=dtype, device=device) | |
| log_const = math.log(4.0 / delta ** 2) | |
| cov_curve = [] | |
| for t in range(1, T + 1): | |
| if adaptive and t > 5: | |
| base = torch.einsum("kn,mk->mn", Bmat, theta_hat) # (M,N) func values | |
| cmat = base.reshape(M_reps, K, Kp) + 0.3 * torch.randn(M_reps, K, Kp, dtype=dtype, device=device) | |
| else: | |
| cmat = torch.randn(M_reps, K, Kp, dtype=dtype, device=device) | |
| eps = torch.rand(M_reps, 1, 1, dtype=dtype, device=device) * 0.45 + 0.05 | |
| P = batched_sinkhorn(mu, nu, cmat, eps) | |
| a = torch.einsum("nz,mz->mn", Bmat, P.reshape(M_reps, N)) # (M,N) | |
| Cfb = a @ th_star + sig_run * torch.randn(M_reps, dtype=dtype, device=device) | |
| w = torch.einsum("mij,mj->mi", Vinv, a) | |
| s = 1.0 + (a * w).sum(1) | |
| ld = ld + torch.log(s) | |
| Vinv = Vinv - torch.einsum("mi,mj->mij", w, w) / s[:, None, None] | |
| A = A + torch.einsum("mi,mj->mij", a, a) | |
| bvec = bvec + a * Cfb[:, None] | |
| theta_hat = torch.einsum("mij,mj->mi", Vinv, bvec) | |
| d = th_star[None, :] - theta_hat | |
| Vd = lam * d + torch.einsum("mij,mj->mi", A, d) | |
| dist = torch.sqrt(torch.clamp((d * Vd).sum(1), min=0)) | |
| beta = beta_scale * (sigma * torch.sqrt(torch.clamp(ld + log_const, min=0)) + math.sqrt(lam) * Cbar) | |
| covered &= dist <= beta | |
| min_slack = torch.minimum(min_slack, beta - dist) | |
| if t in (1, 2, 5, 10, 20, 50, 100, 200, 400, 600, 800, T): | |
| cov_curve.append((t, float(covered.float().mean()))) | |
| return { | |
| "uniform_coverage": float(covered.float().mean()), | |
| "mean_min_slack": float(min_slack.mean()), | |
| "coverage_curve": cov_curve, | |
| } | |
| def main(): | |
| ap = argparse.ArgumentParser() | |
| ap.add_argument("--out", default="results") | |
| ap.add_argument("--reps", type=int, default=4096) | |
| ap.add_argument("--T", type=int, default=800) | |
| ap.add_argument("--K", type=int, default=8) | |
| args = ap.parse_args() | |
| device = "cuda" if torch.cuda.is_available() else "cpu" | |
| print(f"device={device} torch={torch.__version__} reps={args.reps} T={args.T}") | |
| t0 = time.time() | |
| sigma, delta, lam = 0.1, 0.2, 1.0 | |
| inst = build_instance(args.K, args.K, seed=1000) | |
| Cbar = 1.1 * float(np.linalg.norm(inst["theta_star"])) | |
| res = {"config": dict(K=args.K, N=inst["N"], T=args.T, reps=args.reps, | |
| sigma=sigma, delta=delta, lam=lam, device=device), | |
| "target_uniform_coverage": 1 - delta / 2} | |
| variants = { | |
| "random_correct": dict(), | |
| "adaptive_perturbed": dict(adaptive=True), | |
| "control_beta_quarter": dict(beta_scale=0.25), | |
| "control_noise_4x": dict(sigma_run=4 * sigma), | |
| } | |
| for name, kw in variants.items(): | |
| r = run_variant(inst, args.reps, args.T, sigma, delta, lam, Cbar, | |
| seed=hash(name) % 2 ** 31, device=device, **kw) | |
| res[name] = r | |
| print(f"[{name}] uniform_coverage={r['uniform_coverage']:.4f} " | |
| f"mean_min_slack={r['mean_min_slack']:.3f}", flush=True) | |
| res["wall_seconds"] = time.time() - t0 | |
| os.makedirs(args.out, exist_ok=True) | |
| path = os.path.join(args.out, "claim6_gpu.json") | |
| with open(path, "w") as f: | |
| json.dump(res, f, indent=2) | |
| print(f"saved {path} ({res['wall_seconds']:.0f}s)") | |
| if __name__ == "__main__": | |
| main() | |
Xet Storage Details
- Size:
- 7.83 kB
- Xet hash:
- 3b7ca3f1573de51009f03e89f1201d3c0ed7bb882ac69eac7dcf3fe422b1f0f1
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.