summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYurenHao0426 <Blackhao0426@gmail.com>2026-07-22 13:35:13 -0500
committerYurenHao0426 <Blackhao0426@gmail.com>2026-07-22 13:35:13 -0500
commit37cf78b7f696c9eedc0745ebdaa656bff0ab2f81 (patch)
tree37bef77b388614e404703dba305f232bed5423bb
parent0db651ac83608ea8f5b94950a391da22f076a142 (diff)
protocol: freeze normalized mirror baseline funnel
-rw-r--r--MIRROR_BASELINE.md86
-rw-r--r--README.md2
-rw-r--r--experiments/analyze_mirror_causal_capture.py149
-rw-r--r--experiments/mirror_causal_capture_screen.py54
4 files changed, 291 insertions, 0 deletions
diff --git a/MIRROR_BASELINE.md b/MIRROR_BASELINE.md
new file mode 100644
index 0000000..c7ad348
--- /dev/null
+++ b/MIRROR_BASELINE.md
@@ -0,0 +1,86 @@
+# Normalized response-mirror baseline protocol
+
+## Status and attribution
+
+This protocol was frozen before observing any CIFAR-prefix response-mirror
+alignment or accuracy endpoint. A mechanics-only pilot on synthetic Gaussian
+images was used to choose the bounded mirror-rate grid; it did not load the
+frozen CIFAR development split or evaluate validation/test accuracy.
+
+The method is an inherited strong baseline, not SDIL novelty. It is a
+normalized, bias-blocked local system-identification variant of Akrout et al.'s
+[weight mirror](https://proceedings.neurips.cc/paper_files/paper/2019/file/f387624df552cea2f369918c5e1e12bc-Paper.pdf).
+Gaussian parent probes pass through ordinary local forward synapses and a
+separate update receives only the probe and child preactivation response. The
+local correlation estimates the forward kernel; Q/R track that estimate by an
+exponential delta rule. The task-error path remains the audited hierarchical
+FA residual DAG.
+
+Any BP-like scale obtained here belongs to weight estimation. It can raise the
+bar SDIL must beat but cannot raise SDIL novelty or rescue failed Oral-A-v1.
+Only a later, separately frozen demonstration that somato-dendritic innovation
+is load-bearing on top of this path can improve the paper-level claim.
+
+## WM-0: mechanics gate
+
+Before endpoints, the smoke suite must show:
+
+- one 16-probe local observation has mean feedback/forward cosine above 0.985
+ and minimum cosine above 0.95 on a deterministic tiny ResNet;
+- every feedback/forward norm ratio is in `[0.90, 1.10]`;
+- after observations are fixed, changing all forward parameters changes the
+ feedback update by exactly zero;
+- all hierarchical-gradient and convolutional local-update audits remain
+ green.
+
+The gate passed at mean/min cosine `0.988701/0.966066`, norm ratios
+`[0.953729,1.044368]`, and update independence error exactly zero.
+
+## WM-1: frozen-forward CIFAR causal-capture gate
+
+Use seed-0 ResNet-20, random feedback scale 1, the first 10,000 examples of the
+frozen development split, batch 128 for the diagnostic graph, and the fixed
+64-example training-prefix exact-gradient audit. Forward weights, readout,
+BatchNorm state, and affine parameters remain bitwise fixed.
+
+Record one fixed-HFA reference. For each `eta_M in {0.03, 0.1, 0.3}`, run 20
+local mirror observations with convolutional probe batch 1, Gaussian noise
+standard deviation 1, and mirror seed 3000. No task loss or label is consumed
+by mirroring; the final alignment audit alone uses labels. Select maximum
+early-third alignment, then all-layer alignment, then lower rate.
+
+WM-1 passes only if all four records are finite and selected WM:
+
+1. reaches early-third teaching alignment at least `0.40`;
+2. reaches all-layer alignment at least `0.50`;
+3. reaches mean feedback/forward cosine at least `0.85`;
+4. keeps every feedback/forward norm ratio in `[0.5, 1.5]`;
+5. records zero logical task-loss queries during mirror learning.
+
+No mirror batch, step count, noise scale, rate, covariance estimator, or
+per-layer schedule is added after observation.
+
+## WM-2: bounded short accuracy gate
+
+Only a WM-1 pass opens a matched 10k-example, 20-epoch ResNet-20 validation
+screen. Copy A2b data, augmentation, batch 128, cosine schedule, no warmup,
+momentum 0.9, weight decay `1e-4`, and output LR 0.1. Cross hidden LR
+`{0.03,0.1}`. Use the selected mirror rate, 20 mirror warmup observations,
+then one batch-1 mirror observation every 16 task updates. Select validation
+accuracy, then lower total MACs/rate.
+
+Advance only if both runs are finite, selected WM reaches at least 65%, stays
+within 10 points of BP's matched 74.94%, retains early alignment at least 0.30,
+uses zero task-loss queries for feedback learning, and costs no more than 1.15x
+matched BP estimated MACs. Failure closes the baseline without tuning.
+
+## WM-3: full validation baseline
+
+Only a WM-2 pass opens one 200-epoch seed-0 validation run on all 45,000
+development-training examples. Copy its selected hidden rate, mirror settings,
+output LR 0.1, and the A1 step drops at epochs 100/150. No recovery branch is
+allowed. A finite endpoint at least 88% with early alignment at least 0.30 and
+cost at most 1.15x BP is considered a strong inherited baseline. It does not
+authorize test access; it instead opens design of a hierarchical innovation
+intervention on the same frozen recipe.
+
diff --git a/README.md b/README.md
index ca15bc4..bf3ce6a 100644
--- a/README.md
+++ b/README.md
@@ -138,6 +138,8 @@ high finite-sample kernel recovery and that changing forward parameters after
observation cannot affect the update. Any scale obtained this way is credited
to the weight-mirror baseline until innovation residualization is shown to be
load-bearing on top of it.
+`MIRROR_BASELINE.md` freezes that comparator's CIFAR-prefix capture, short
+accuracy, and conditional full-validation gates.
The subsequent V3 mechanism estimates the required A/G matrix statistics
directly by perturbing the vectorizer parameter subspace. It remains
diff --git a/experiments/analyze_mirror_causal_capture.py b/experiments/analyze_mirror_causal_capture.py
new file mode 100644
index 0000000..4347385
--- /dev/null
+++ b/experiments/analyze_mirror_causal_capture.py
@@ -0,0 +1,149 @@
+#!/usr/bin/env python3
+"""Audit and gate normalized response-mirror causal capture."""
+import argparse
+import glob
+import json
+import math
+import os
+
+
+SPLIT_HASH = "8328b206a97c420e49e54e3eca4abe3274c4756b084355784ea3fb8059e4515b"
+RATES = (0.03, 0.1, 0.3)
+
+
+def load(path):
+ with open(path) as handle:
+ record = json.load(handle)
+ args = record["args"]
+ mode = args.get("mode")
+ if mode not in ("hfa", "wm"):
+ raise ValueError(f"{path}: unexpected method")
+ expected = {
+ "depth": 20, "width": 16, "seed": 0, "loader_seed": 0,
+ "epochs": 0, "train_limit": 10000, "val_examples": 5000,
+ "split_seed": 2027, "eval_split": "validation", "eval_every": 0,
+ "normalization": "batchnorm", "a_scale": 1.0,
+ "alignment_probe": 64, "mirror_batch_size": 1,
+ "mirror_noise_std": 1.0, "mirror_seed": 3000,
+ }
+ for key, value in expected.items():
+ if args.get(key) != value:
+ raise ValueError(f"{path}: {key} drift")
+ expected_steps = 0 if mode == "hfa" else 20
+ if args.get("mirror_warmup_steps") != expected_steps:
+ raise ValueError(f"{path}: mirror warmup drift")
+ if mode == "wm" and float(args["mirror_eta"]) not in RATES:
+ raise ValueError(f"{path}: unregistered mirror rate")
+ if record["provenance"]["git_tracked_dirty"]:
+ raise ValueError(f"tracked-dirty result: {path}")
+ if record["split"]["validation_index_sha256"] != SPLIT_HASH:
+ raise ValueError(f"split drift: {path}")
+ if record["evaluation_protocol"]["test_evaluations"]:
+ raise ValueError(f"test touched: {path}")
+ expected_space = None if mode == "hfa" else "local_parent_child_response"
+ if record.get("calibration_metric_space") != expected_space:
+ raise ValueError(f"metric-space drift: {path}")
+ diagnostics = record["diagnostics"]
+ values = diagnostics["teaching_negative_gradient_cosine"]
+ early_count = max(1, len(values) // 3)
+ norm_ratios = diagnostics["feedback_forward_norm_ratio"]
+ feedback_cosines = diagnostics["feedback_forward_cosine"]
+ metrics = {
+ "early_third_alignment": sum(values[:early_count]) / early_count,
+ "all_layer_alignment": sum(values) / len(values),
+ "mean_feedback_forward_cosine": (
+ sum(feedback_cosines) / len(feedback_cosines)),
+ "min_feedback_forward_norm_ratio": min(norm_ratios),
+ "max_feedback_forward_norm_ratio": max(norm_ratios),
+ }
+ if mode == "wm":
+ warmup = record.get("mirror_warmup", {}).get("mean")
+ if warmup is None:
+ raise ValueError(f"missing mirror aggregate: {path}")
+ metrics.update({
+ "mean_mirror_update_rms": warmup["mirror_update_rms"],
+ "mean_mirror_estimate_rms": warmup["mirror_estimate_rms"],
+ })
+ finite = (bool(record["final"]["finite"])
+ and all(math.isfinite(value) for value in metrics.values()))
+ return {
+ "path": path, "mode": mode,
+ "mirror_eta": (None if mode == "hfa" else float(args["mirror_eta"])),
+ "metrics": metrics, "finite": finite,
+ "logical_batch_loss_queries": int(
+ record["work"]["logical_batch_loss_queries"]),
+ "mirror_events": int(record["counters"]["mirror_events"]),
+ "total_macs": int(record["work"]["total_macs_estimate"]),
+ "source_commit": record["provenance"]["git_commit"],
+ }
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--input", default="results/mirror_causal_capture")
+ parser.add_argument(
+ "--out", default="results/mirror_causal_capture_gate.json")
+ args = parser.parse_args()
+ rows = [load(path) for path in sorted(
+ glob.glob(os.path.join(args.input, "*.json")))]
+ references = [row for row in rows if row["mode"] == "hfa"]
+ candidates = [row for row in rows if row["mode"] == "wm"]
+ if len(references) != 1 or len(candidates) != len(RATES):
+ raise ValueError("incomplete WM-1 method grid")
+ if {row["mirror_eta"] for row in candidates} != set(RATES):
+ raise ValueError("incomplete WM-1 rate grid")
+ if len({row["source_commit"] for row in rows}) != 1:
+ raise ValueError("WM-1 source commits differ")
+ eligible = [row for row in candidates if row["finite"]]
+ eligible.sort(key=lambda row: (
+ -row["metrics"]["early_third_alignment"],
+ -row["metrics"]["all_layer_alignment"], row["mirror_eta"]))
+ selected = eligible[0] if eligible else None
+ checks = {
+ "all_four_records_finite": all(row["finite"] for row in rows),
+ "candidate_selected": selected is not None,
+ }
+ if selected is None:
+ checks.update({
+ "early_third_at_least_0.40": False,
+ "all_layer_at_least_0.50": False,
+ "mean_feedback_forward_cosine_at_least_0.85": False,
+ "feedback_norm_ratios_in_0.5_to_1.5": False,
+ "zero_task_loss_queries": False,
+ })
+ else:
+ metrics = selected["metrics"]
+ checks.update({
+ "early_third_at_least_0.40": (
+ metrics["early_third_alignment"] >= 0.40),
+ "all_layer_at_least_0.50": (
+ metrics["all_layer_alignment"] >= 0.50),
+ "mean_feedback_forward_cosine_at_least_0.85": (
+ metrics["mean_feedback_forward_cosine"] >= 0.85),
+ "feedback_norm_ratios_in_0.5_to_1.5": (
+ metrics["min_feedback_forward_norm_ratio"] >= 0.5
+ and metrics["max_feedback_forward_norm_ratio"] <= 1.5),
+ "zero_task_loss_queries": (
+ all(row["logical_batch_loss_queries"] == 0 for row in rows)),
+ })
+ output = {
+ "protocol": "normalized_response_mirror_capture_v1",
+ "status": "passed" if all(checks.values()) else "failed",
+ "checks": checks, "rows": rows, "matched_fixed_hfa": references[0],
+ "selected_wm": selected, "confirmation_test_seeds_touched": False,
+ "review_score_before": 5, "review_score_after": 5,
+ "score_change_rule": "inherited baseline capture cannot raise score",
+ }
+ os.makedirs(os.path.dirname(os.path.abspath(args.out)), exist_ok=True)
+ with open(args.out, "w") as handle:
+ json.dump(output, handle, indent=2, sort_keys=True)
+ handle.write("\n")
+ print(json.dumps({
+ "status": output["status"], "checks": checks,
+ "reference": references[0], "selected_wm": selected,
+ }, indent=2))
+
+
+if __name__ == "__main__":
+ main()
+
diff --git a/experiments/mirror_causal_capture_screen.py b/experiments/mirror_causal_capture_screen.py
new file mode 100644
index 0000000..1bf516a
--- /dev/null
+++ b/experiments/mirror_causal_capture_screen.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python3
+"""Run a shard of the frozen normalized response-mirror capture screen."""
+import argparse
+import os
+import subprocess
+import sys
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--device", default="cuda")
+ parser.add_argument("--shard_index", type=int, default=0)
+ parser.add_argument("--num_shards", type=int, default=1)
+ parser.add_argument("--dry_run", action="store_true")
+ args = parser.parse_args()
+ if not 0 <= args.shard_index < args.num_shards:
+ raise ValueError("invalid shard index")
+ common = [
+ sys.executable, "experiments/conv_run.py", "--device", args.device,
+ "--depth", "20", "--width", "16", "--seed", "0",
+ "--loader_seed", "0", "--batch_size", "128", "--epochs", "0",
+ "--train_limit", "10000", "--val_examples", "5000",
+ "--split_seed", "2027", "--eval_split", "validation",
+ "--eval_every", "0", "--augment_train", "1", "--lr", "0.1",
+ "--output_lr", "0.1", "--lr_schedule", "constant",
+ "--warmup_epochs", "0", "--momentum", "0.9",
+ "--weight_decay", "1e-4", "--normalization", "batchnorm",
+ "--a_scale", "1", "--alignment_probe", "64",
+ "--mirror_batch_size", "1", "--mirror_noise_std", "1",
+ "--mirror_seed", "3000",
+ ]
+ jobs = [("fixed_hfa", common + [
+ "--mode", "hfa", "--out",
+ "results/mirror_causal_capture/fixed_hfa.json",
+ ])]
+ for rate in (0.03, 0.1, 0.3):
+ tag = f"wm_etaM{rate}"
+ jobs.append((tag, common + [
+ "--mode", "wm", "--mirror_eta", str(rate),
+ "--mirror_warmup_steps", "20", "--out",
+ f"results/mirror_causal_capture/{tag}.json",
+ ]))
+ os.makedirs("results/mirror_causal_capture", exist_ok=True)
+ for index, (tag, command) in enumerate(jobs):
+ if index % args.num_shards != args.shard_index:
+ continue
+ print(tag, " ".join(command), flush=True)
+ if not args.dry_run:
+ subprocess.run(command, check=True)
+
+
+if __name__ == "__main__":
+ main()
+