From 7b6cdfb9656d3b59edae442c99ba3412ecc32cfc Mon Sep 17 00:00:00 2001 From: YurenHao0426 Date: Wed, 22 Jul 2026 05:00:28 -0500 Subject: sdil: add feedback-first apical calibration --- experiments/smoke.py | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'experiments/smoke.py') diff --git a/experiments/smoke.py b/experiments/smoke.py index a49e4c6..9971800 100644 --- a/experiments/smoke.py +++ b/experiments/smoke.py @@ -6,7 +6,7 @@ import sys import torch sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) -from sdil.core import (SDILNet, SDILConfig, sdil_step, +from sdil.core import (SDILNet, SDILConfig, apical_calibration_step, sdil_step, node_perturbation_targets, simultaneous_node_perturbation_targets, neutral_p_update, teaching_signal) from sdil.baselines import dfa_config @@ -188,6 +188,33 @@ def check_direct_node_perturbation(): print("CHECK0f direct node perturbation: exact q update; A untouched") +def check_feedback_first_calibration(): + """A-only calibration must leave the entire forward network unchanged.""" + torch.manual_seed(23) + x = torch.randn(32, 5) + y = torch.randint(0, 3, (32,)) + yoh = onehot(y, 3) + net = SDILNet([5, 7, 7, 3], act="relu", device="cpu", seed=11, + residual=True, vectorizer_mode="context_gated") + weights_before = [weight.clone() for weight in net.W] + biases_before = [bias.clone() for bias in net.b] + apical_before = [weight.clone() for weight in net.A] + gates_before = [weight.clone() for weight in net.A_gate] + cfg = SDILConfig(eta_A=0.02, learn_A=True, learn_P=True, + pert_ndirs=1, pert_mode="simultaneous") + apical_calibration_step( + net, x, y, yoh, cfg, pert_mode="simultaneous", pert_ndirs=2) + assert all(torch.equal(before, after) + for before, after in zip(weights_before, net.W)) + assert all(torch.equal(before, after) + for before, after in zip(biases_before, net.b)) + assert any(not torch.equal(before, after) + for before, after in zip(apical_before, net.A)) + assert any(not torch.equal(before, after) + for before, after in zip(gates_before, net.A_gate)) + print("CHECK0g feedback-first calibration: A changed; W/readout frozen") + + def main(): torch.manual_seed(0) dev = "cpu" @@ -197,6 +224,7 @@ def main(): check_traffic_seed_isolation() check_state_conditioned_vectorizers() check_direct_node_perturbation() + check_feedback_first_calibration() print("loading MNIST subset...") tr, te, n_in, n_out = get_dataset("mnist", batch_size=128, device=dev) xb, yb = next(iter(tr)) -- cgit v1.2.3