summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--THEORY.md32
-rw-r--r--experiments/verify_theory.py37
2 files changed, 69 insertions, 0 deletions
diff --git a/THEORY.md b/THEORY.md
index d82e171..146621f 100644
--- a/THEORY.md
+++ b/THEORY.md
@@ -313,6 +313,35 @@ the observations are fixed. RRM needs one extra local Q prediction convolution
per mirror event, which is charged separately. It remains inherited local
weight estimation, not SDIL novelty.
+### Reciprocal Kolen--Pollack dynamics as the stable inherited substrate
+
+The modified Kolen--Pollack comparator does not estimate a moving weight from
+intermittent probes. Corresponding forward and reciprocal synapses independently
+form the same local activity correlation `C_t` on every task update. With
+matched momentum `mu`, decay `lambda`, and rate `eta`, their difference state
+obeys
+
+```text
+M_(t+1) = mu M_t - lambda D_t,
+D_(t+1) = D_t + eta M_(t+1),
+D_t = Q_t - W_t, M_t = mQ_t - mW_t.
+```
+
+The task correlation cancels exactly; with no momentum this reduces to
+`D_(t+1)=(1-eta lambda)D_t`. Exact symmetry is an invariant for the matched
+momentum system, and the executable audit obtains zero difference after two
+updates. The readout follows the same identity after applying this codebase's
+feedback sign convention `R=-W_out^T`. Each reciprocal correlation is
+recomputed from its own local activity pair; neither path reads the other
+weight or update.
+
+Mixed apical traffic does not change that invariant. If `u_l` is raw,
+norm-matched raw, or innovation, both corresponding synapses consume the same
+local parent activity and `u_l`, hence independently form equal `C_t`. The
+traffic/predictor mechanism can therefore be ablated without silently changing
+the credit-substrate tracking rule. Reciprocal KP and its stability are prior
+art; only a load-bearing neutral innovation can contribute SDIL evidence.
+
## 2. What is sufficient for a descent step
Flatten all forward parameters into `theta`, let `p = grad L(theta)`, and let
@@ -517,6 +546,9 @@ work `S_l=sum_{j>l} F_j`.
| BP | forward + reverse | exact transposed Jacobians | ordinary supervised loss | about one reverse pass | saved activations / graph |
| FA | forward + reverse-like serial feedback | fixed random feedback | ordinary loss | `O(F)` feedback work | activations + feedback states |
| convolutional hierarchical FA | forward + residual-DAG feedback | independent random 3x3 feedback tensors; exact parameter-free shortcut graph | ordinary loss | one feedback convolution per non-stem forward convolution (`0.988x` forward MACs at ResNet-20, plus local correlations) | hidden feedback maps + forward caches |
+| normalized / residual response mirror | hierarchical task pass plus intermittent local probe-response events | learned Q/R from local parent-child observations; no task-loss query | ordinary loss only | per mirror event: forward response + local correlation; RRM also predicts the response through Q | task caches plus one probe/response set |
+| reciprocal Kolen--Pollack | hierarchical task pass; forward and reciprocal correlations every update | separate plastic Q/R; equal local activity products and matched optimizer/decay | ordinary loss only | forward local correlation + feedback propagation + a separately recomputed reciprocal correlation (`1.326x` matched BP MACs in KP-1) | task caches plus feedback fields and reciprocal optimizer state |
+| KP + somato-dendritic innovation | KP plus neutral predictor warmup/update | same reciprocal Q/R; per-unit affine neutral predictor | ordinary loss only | KP affine work plus explicitly reported traffic/predictor elementwise operations and two charged diagnostic-prefix forwards | KP state plus raw/innovation fields and `2U` predictor parameters |
| DFA | forward + direct feedback | fixed random output maps | ordinary loss | `O(sum_l d_l d_out)` | activations + feedback states |
| learned NP, simultaneous | ordinary forward; one duplicate clean plus `2K` noisy full forwards every `e` batches | learned direct maps; no weight transport | `2KB/e` per ordinary batch | `(1+2K)F/e` | up to `2KB` noisy examples in the vectorized implementation |
| learned NP, layerwise | ordinary forward; clean baseline plus antithetic suffix replays | learned direct maps | `(1+2KH)B/e` | `(F + 2K sum_l S_l)/e`, quadratic in depth for balanced layers | serial suffix replay, no `2K` batch expansion |
diff --git a/experiments/verify_theory.py b/experiments/verify_theory.py
index 8054b0d..cc9b6c3 100644
--- a/experiments/verify_theory.py
+++ b/experiments/verify_theory.py
@@ -221,6 +221,42 @@ def check_intermittent_feedback_tracking():
assert abs(abs(error) - expected_endpoint) < 1e-15
+def check_kolen_pollack_difference_dynamics():
+ rng = np.random.default_rng(601)
+ eta = 0.07
+ momentum = 0.9
+ decay = 1e-3
+ forward = rng.normal(size=(7, 5))
+ reciprocal = rng.normal(size=(7, 5))
+ forward_momentum = rng.normal(size=(7, 5))
+ reciprocal_momentum = rng.normal(size=(7, 5))
+ maximum_error = 0.0
+ for _ in range(40):
+ # Both paths independently obtain the same local activity product.
+ correlation = rng.normal(size=(7, 5))
+ difference = reciprocal - forward
+ momentum_difference = reciprocal_momentum - forward_momentum
+ predicted_momentum_difference = (
+ momentum * momentum_difference - decay * difference)
+ predicted_difference = difference + eta * predicted_momentum_difference
+
+ forward_momentum = (momentum * forward_momentum
+ + correlation - decay * forward)
+ reciprocal_momentum = (momentum * reciprocal_momentum
+ + correlation - decay * reciprocal)
+ forward = forward + eta * forward_momentum
+ reciprocal = reciprocal + eta * reciprocal_momentum
+ maximum_error = max(
+ maximum_error,
+ float(np.abs((reciprocal_momentum - forward_momentum)
+ - predicted_momentum_difference).max()),
+ float(np.abs((reciprocal - forward)
+ - predicted_difference).max()))
+ print("\nKOLEN-POLLACK DIFFERENCE DYNAMICS")
+ print(f"task-correlation cancellation error={maximum_error:.3e}")
+ assert maximum_error < 3e-15
+
+
def main():
check_simultaneous_variance()
check_sigma_bias()
@@ -229,6 +265,7 @@ def main():
check_predictor_timescale()
check_innovation_identification()
check_intermittent_feedback_tracking()
+ check_kolen_pollack_difference_dynamics()
print("\nALL THEORY CHECKS PASSED")