diff options
| -rw-r--r-- | THEORY.md | 32 | ||||
| -rw-r--r-- | experiments/verify_theory.py | 37 |
2 files changed, 69 insertions, 0 deletions
@@ -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") |
