summaryrefslogtreecommitdiff
path: root/experiments
diff options
context:
space:
mode:
authorYurenHao0426 <Blackhao0426@gmail.com>2026-07-21 14:25:48 -0500
committerYurenHao0426 <Blackhao0426@gmail.com>2026-07-21 14:25:48 -0500
commitf058f1e792d7b2c99fbb4f555fe12c052177846b (patch)
tree6d26f9789dbf27d5b1ec8fcf5d853cee21bf62f9 /experiments
parent5f3a0ce2b9fdc445882dc2cb9d8547132a7b3748 (diff)
figures: lock claim-critical training protocols
Diffstat (limited to 'experiments')
-rw-r--r--experiments/plot_main_figures.py45
1 files changed, 38 insertions, 7 deletions
diff --git a/experiments/plot_main_figures.py b/experiments/plot_main_figures.py
index 7b17b2c..9005caa 100644
--- a/experiments/plot_main_figures.py
+++ b/experiments/plot_main_figures.py
@@ -99,15 +99,31 @@ def require_scaling_protocol(rows):
for key, expected in (("dataset", "cifar10"), ("width", 64),
("epochs", 5), ("batch_size", 128),
("act", "tanh"), ("residual", 1),
- ("device", "cuda")):
+ ("momentum", 0.9), ("device", "cuda")):
require_value(errors, row, key, args.get(key), expected)
name = method(row)
require_value(errors, row, "depth", args.get("depth"),
args.get("depth") if args.get("depth") in DEPTHS else "one of " + repr(DEPTHS))
require_value(errors, row, "eta", args.get("eta"), 0.02 if name == "SDIL" else 0.05)
+ if name == "FA":
+ for key, expected in (("train_examples", 0), ("max_batches", 0),
+ ("feedback_scale", 1),
+ ("canonical_preprocess", 1)):
+ require_value(errors, row, key, args.get(key), expected)
+ else:
+ for key, expected in (("max_steps", 0), ("w_scale", 1),
+ ("n_in", 3072)):
+ require_value(errors, row, key, args.get(key), expected)
if name == "SDIL":
- require_value(errors, row, "pert_mode", args.get("pert_mode"), "simultaneous")
- require_value(errors, row, "pert_ndirs", args.get("pert_ndirs"), 16)
+ for key, expected in (
+ ("eta_A", 0.02), ("eta_P", 0.002), ("pert_sigma", 0.01),
+ ("pert_every", 4), ("pert_mode", "simultaneous"),
+ ("pert_ndirs", 16), ("use_residual", 1), ("learn_A", 1),
+ ("learn_P", 1), ("p_neutral", 1), ("p_warmup_steps", 200),
+ ("p_warmup_eta", 0.05), ("nuis_rho", 0),
+ ("predictor_mode", "diagonal"), ("normalize_delta", 0),
+ ("settle_steps", 0), ("kappa", 0), ("feedback", "error")):
+ require_value(errors, row, key, args.get(key), expected)
if errors:
raise RuntimeError("mixed CIFAR scaling protocols:\n" + "\n".join(errors))
@@ -131,6 +147,9 @@ def require_ep_protocol(groups):
if name == "EP":
require_value(errors, row, "batch_size", args.get("batch_size"), 20)
require_value(errors, row, "ep_persistent", args.get("ep_persistent"), 1)
+ require_value(errors, row, "ep_dt", args.get("ep_dt"), 0.5)
+ require_value(errors, row, "canonical_preprocess",
+ args.get("canonical_preprocess"), 1)
resolved = row.get("resolved_protocol", {})
for key in ("beta", "free_steps", "nudge_steps", "learning_rates"):
require_value(errors, row, f"resolved_protocol.{key}",
@@ -142,9 +161,20 @@ def require_ep_protocol(groups):
require_value(errors, row, "act", args.get("act"), "tanh")
require_value(errors, row, "residual", args.get("residual"), 0)
require_value(errors, row, "eta", args.get("eta"), 0.05)
+ require_value(errors, row, "momentum", args.get("momentum"), 0.9)
+ require_value(errors, row, "max_steps", args.get("max_steps"), 0)
if name == "SDIL":
- require_value(errors, row, "pert_mode", args.get("pert_mode"), "simultaneous")
- require_value(errors, row, "pert_ndirs", args.get("pert_ndirs"), 16)
+ for key, expected in (
+ ("eta_A", 0.02), ("eta_P", 0.002),
+ ("pert_sigma", 0.01), ("pert_every", 4),
+ ("pert_mode", "simultaneous"), ("pert_ndirs", 16),
+ ("use_residual", 1), ("learn_A", 1), ("learn_P", 1),
+ ("p_neutral", 1), ("p_warmup_steps", 200),
+ ("p_warmup_eta", 0.05), ("nuis_rho", 0),
+ ("predictor_mode", "diagonal"), ("normalize_delta", 0),
+ ("settle_steps", 0), ("kappa", 0),
+ ("feedback", "error")):
+ require_value(errors, row, key, args.get(key), expected)
if errors:
raise RuntimeError("mixed exact-EP protocols:\n" + "\n".join(errors))
@@ -481,8 +511,9 @@ GTX 1080. **a,** CIFAR-10 test accuracy versus wall time for width-64 residual M
five epochs. The black line is the mean-based nondominated frontier among local-learning methods.
BP is a nonlocal reference and is excluded from frontier construction. Labels give hidden depth.
**b,** SDIL versus canonical equilibrium propagation (EP) on exact 784–500–10 (d1) and
-784–500–500–10 (d2) forward architectures, the same first 50,000 MNIST training examples, and the
-same epoch counts. EP retains its published raw-pixel, hard-sigmoid energy dynamics and relaxation
+784–500–500–10 (d2) forward architectures and the same first 50,000 MNIST training examples.
+Within each matched architecture, every method uses the same budget: 25 epochs for d1 and 60 epochs
+for d2. EP retains its published raw-pixel, hard-sigmoid energy dynamics and relaxation
schedule; SDIL retains its z-scored, tanh feedforward dynamics. Thus architecture, examples, and
epochs are matched, but preprocessing and state dynamics are intentionally method-native.