RandomProjectionVjpAlgorithm#
- class braintrace.RandomProjectionVjpAlgorithm#
Rank-1 random-projection eligibility trace — the UORO engine.
Per hidden group
gthe influence of parameterjon hidden unitu = (position, state)is carried by one rank-1 pair\[\tilde\varepsilon_g[j, u] \approx \tilde s_g[u] \, \tilde\theta_g[j]\]with \(\tilde s_g\) shaped
(*varshape, num_state)and \(\tilde\theta_g\) parameter-shaped — no hidden axis, no trailing state axis. One \(\tilde s\) per group; one \(\tilde\theta\) per(group, ParamState path), so a weight consumed by two relations of one group keeps a single parameter factor and the two projections are summed into it.With \(\nu_g\) a Rademacher draw of \(\tilde s_g\)’s shape and \(J_f\) the instantaneous term, the step is
\[\begin{split}\mathrm{proj}_g &= \nu_g^\top J_f \\ \rho_0 &= \sqrt{(\|\tilde\theta_g\| + \epsilon) / (\|D_g \tilde s_g\| + \epsilon)} \\ \rho_1 &= \sqrt{(\|\mathrm{proj}_g\| + \epsilon) / (\|\nu_g\| + \epsilon)} \\ \tilde s_g &\leftarrow \rho_0 (D_g \tilde s_g) + \rho_1 \nu_g \\ \tilde\theta_g &\leftarrow \tilde\theta_g / \rho_0 + \mathrm{proj}_g / \rho_1\end{split}\]and the gradient contributed at a window boundary is \(\sum_g (\text{signal}_g \cdot \tilde s_g)\, \tilde\theta_g\) — a scalar per group times a parameter-shaped array.
Unbiased for what. Conditionally on earlier draws, the updated outer product is
a b^T + c d^T + (rho0/rho1) a d^T + (rho1/rho0) c b^Twitha = D s_tilde,b = theta_tilde,c = nu,d = nu^T J_f. The first term isD eps_tilde(rho0cancels), the second isnu nu^T J_f, and the two cross terms are odd in the current draw whilerho1is even, so any negation-symmetric draw law withE[nu nu^T] == IgivesE[eps_tilde_new] == D eps_tilde + J_fexactly. Induction over time then gives an unbiased estimate of the exact within-group influence recursion that the compiled transition defines.That is the whole claim, and it is narrower than “unbiased”. Three approximations are untouched:
cross-group coupling — the compiler splits hidden states into groups and drops inter-group terms; one factor pair per group cannot carry them;
the instantaneous term’s tail —
dfcomes from a single all-ones JVP of they -> hiddenmap, exact only for a position-preserving elementwise tail (finding F-31);each primitive’s own solve regime — the projector is built from the framework’s own per-primitive rules, so it inherits them exactly.
On a single-group model with a position-preserving elementwise tail — the class where that recursion is itself exact — this is therefore unbiased for BPTT. Elsewhere it is unbiased for the block-local recursion and biased against BPTT, like every other coordinate in this repository. It is not restricted to that class.
Memory, honestly. The carrier is
|theta| + B * P * Selements againstB * |theta| * Sfor the anchored per-parameter trace: ontanh_rnn(3, 4)that is 20 against 16. UORO is not a memory win over the anchored trace — it is a bias win at comparable carrier size, and a memory win against saturated SnAp-n (64) or the full influence matrix (64), which is what unbiasedness would otherwise cost. AndO(|theta| + P S)describes carrier storage, not peak memory: the full transition Jacobian is anO((P S)^2)transient per step (follow-up F-32 tracks a matrix-freeD @ sproduct). The fused stepper keeps that transient per-step rather than stacked over the window.- Parameters:
model (brainstate.nn.Module) – The one-step model.
name (str, optional) – Node name.
vjp_method (str, optional) –
'single-step'or'multi-step'. Default'multi-step': the chunked finite-window path requires it, and it is the path the estimator is validated on.fast_solve (bool, optional) – Whether registered closed-form kernels may be used when building the projector. Default
True.control_flow (ControlFlowPolicy, optional) – Control-flow canonicalization policy.
config (ETraceConfig, optional) – The learning-rule coordinate. Must have
trace_factorization='random_projection'.projection_key (int or jax.Array, optional) – Seed for the projection stream. Default
42.reset_statere-derives the stream from it, so a reset run repeats bit-for-bit.projection_eps (float, optional) – Guard added to every norm before the ratio. Default
1e-12. At the first step both factors are zero, so both ratios are0/0; withprojection_eps=0the carrier is NaN at every window length. Because the guard perturbs the normalisers, the exactness pins carry a tolerance above float64 epsilon — seeuoro_test.py.random_feedback_key (jax.Array, optional) – Passed through to the base class for
learning_signal='random_feedback'.snap_max_jacobian_elements (int, optional) – Passed through; unused at
recurrence_scope='coupled'.
See also
braintrace.UOROthe preset that fixes the coordinate.
braintrace.SnApthe deterministic scale whose saturating end this estimates.
- get_etrace_of(weight)#
The parameter-side factors associated with weight.
- Parameters:
weight (brainstate.ParamState or Path) – The weight whose factors are requested.
- Returns:
dict –
{(group index, path): theta_tilde}for that weight.- Raises:
ValueError – If the weight has no random-projection factor.
- init_etrace_state(*args, **kwargs)#
Allocate the rank-1 factors, the projection key and the step counter.
- reset_state(batch_size=None, **kwargs)#
Reset the factors, the step counter and the projection stream.
The stream is re-derived from
projection_keyrather than advanced, so a reset run reproduces the previous one bit-for-bit.
- RandomProjectionVjpAlgorithm.__init__(model, name=None, vjp_method='multi-step', fast_solve=True, control_flow=None, config=None, projection_key=42, projection_eps=1e-12, random_feedback_key=None, snap_max_jacobian_elements=16777216)#