Level-Adaptive Replay Memory / experiment.py

Failed on benchmark

Raw ⬇ ZIP
  1import json
  2import math
  3from pathlib import Path
  4import numpy as np
  5
  6SEED = 1268
  7
  8
  9def rho_curve(m, benefit=0.28, length=2.0, stale=0.0, onset=3, p0=0.04):
 10    val = p0 + benefit * (1.0 - math.exp(-m / length)) - stale * max(0, m - onset)
 11    return float(np.clip(val, 1e-5, 0.95))
 12
 13
 14def escape(rho, M):
 15    return 1.0 - (1.0 - rho) ** M
 16
 17
 18def math_verification():
 19    rng = np.random.default_rng(SEED)
 20    # Prediction 1: exact M-fold escape formula.
 21    rho = 0.173
 22    formula = []
 23    for M in [1, 2, 4, 8, 16, 32]:
 24        n = 120000
 25        observed = rng.binomial(n, escape(rho, M)) / n
 26        predicted = escape(rho, M)
 27        formula.append({"M": M, "predicted": predicted, "observed": float(observed),
 28                        "abs_error": float(abs(observed - predicted))})
 29
 30    # Prediction 2: monotone learning implies increasing memory improves escape.
 31    mono_r = [escape(rho_curve(m, benefit=.30, length=2.5, stale=0), 8)
 32              for m in range(1, 17)]
 33    monotone_fraction = float(np.mean(np.diff(mono_r) > 0))
 34
 35    # Prediction 3: staleness creates a finite optimum; more drift shifts it left.
 36    opt_rows = []
 37    for stale in [0.0, .005, .015, .03, .05, .08]:
 38        rs = [escape(rho_curve(m, benefit=.30, length=2.5, stale=stale), 8)
 39              for m in range(1, 17)]
 40        # Independent high-sample sweep gives an observed optimum.
 41        obs = []
 42        for m in range(1, 17):
 43            p_m = rho_curve(m, benefit=.30, length=2.5, stale=stale)
 44            rho_obs = rng.binomial(200000, p_m) / 200000
 45            obs.append(escape(rho_obs, 8))
 46        opt_rows.append({"stale": stale, "predicted_opt_m": int(np.argmax(rs) + 1),
 47                         "observed_opt_m": int(np.argmax(obs) + 1),
 48                         "best_r": float(max(rs)),
 49                         "observed_best_r": float(max(obs))})
 50    # Prediction 4: in the low-rho regime, r is approximately M*rho.
 51    scaling = []
 52    for M in [1, 2, 4, 8, 16]:
 53        r = escape(.002, M)
 54        scaling.append({"M": M, "r": r, "r_over_Mrho": r / (M * .002)})
 55    return {"formula_check": formula, "monotone_fraction": monotone_fraction,
 56            "stale_optima": opt_rows, "low_rho_scaling": scaling}
 57
 58
 59def run_controller(rng, rounds=80, M=8, tau=.025, probe_every=4, mmax=8,
 60                    benefit=.30, length=2.5, stale=.045, noise_n=48):
 61    m = 1
 62    total_escape = 0
 63    trajectory = []
 64    for t in range(rounds):
 65        # Production event uses exactly M proposals, matching fixed_run.
 66        p = rho_curve(m, benefit, length, stale)
 67        total_escape += int(np.any(rng.random(M) < p))
 68        # Independent validation samples estimate rho for adaptation.
 69        rho_hat = rng.binomial(noise_n, p) / noise_n
 70        r_hat = escape(rho_hat, M)
 71        if t % probe_every == 0:
 72            estimates = {m: r_hat}
 73            for neighbor in (m - 1, m + 1):
 74                if 1 <= neighbor <= mmax:
 75                    q = rho_curve(neighbor, benefit, length, stale)
 76                    qhat = rng.binomial(noise_n, q) / noise_n
 77                    estimates[neighbor] = escape(qhat, M)
 78            if m + 1 in estimates and estimates[m + 1] - estimates[m] > tau:
 79                m += 1
 80            elif m - 1 in estimates and estimates[m] - estimates[m - 1] > tau:
 81                m -= 1
 82        trajectory.append(m)
 83    return {"escapes": total_escape, "mean_m": float(np.mean(trajectory)),
 84            "final_m": trajectory[-1], "trajectory": trajectory}
 85
 86def fixed_run(rng, m, rounds=80, M=8, benefit=.30, length=2.5, stale=.045,
 87              noise_n=48):
 88    escapes = 0
 89    p = rho_curve(m, benefit, length, stale)
 90    for _ in range(rounds):
 91        rho_hat = rng.binomial(noise_n, p) / noise_n
 92        # Same estimated-proposal process and M-fold escape metric.
 93        escapes += int(rng.random() < escape(rho_hat, M))
 94    return escapes
 95
 96
 97def comparison():
 98    settings = {"rounds": 80, "M": 8, "stale": .045, "noise_n": 48}
 99    vals = {}
100    for m in [1, 2, 4, 8, 16]:
101        vals[str(m)] = fixed_run(np.random.default_rng(SEED + m), m, **settings)
102    adaptive = run_controller(np.random.default_rng(SEED + 100), mmax=8, tau=.025,
103                              probe_every=4, **settings)
104    return {"fixed_escapes": vals, "adaptive": {k: v for k, v in adaptive.items()
105                                                   if k != "trajectory"},
106            "adaptive_trajectory": adaptive["trajectory"]}
107
108
109def main():
110    report = {"seed": SEED, "math": math_verification(), "comparison": comparison()}
111    Path("results.json").write_text(json.dumps(report, indent=2))
112    print(json.dumps(report, indent=2))
113
114
115if __name__ == "__main__":
116    main()