HiddenPerturbation#
- class braintrace.HiddenPerturbation#
The hidden-perturbation information.
Hidden perturbation adds a perturbation variable to each hidden state in the jaxpr and replaces the hidden states with the perturbed states:
\[h^t = f(x) \;\Rightarrow\; h^t = f(x) + \mathrm{perturb\_var},\]where \(h\) is the hidden state, \(f\) is the function, \(x\) is the input, and \(\mathrm{perturb\_var}\) is the perturbation variable.
- Variables:
perturb_vars (sequence of Var) – The perturbation variables.
perturb_hidden_paths (sequence of Path) – The hidden-state paths that are perturbed.
perturb_hidden_states (sequence of brainstate.HiddenState) – The hidden states that are perturbed.
perturb_jaxpr (ClosedJaxpr) – The perturbed jaxpr.
See also
add_hidden_perturbation_in_moduleBuild perturbations directly from a model.
Notes
Internally a new variable \(\hat{h}^t = f(x)\) is defined and an extra equation \(h^t = \hat{h}^t + \mathrm{perturb\_var}\) is added. The perturbation lets the hidden-state gradient be read off the perturbation variable
\[\frac{\partial L^t}{\partial h^t} = \frac{\partial L^t}{\partial \mathrm{perturb\_var}}.\]Examples
>>> import brainstate >>> import braintrace >>> gru = braintrace.nn.GRUCell(3, 4) >>> _ = brainstate.nn.init_all_states(gru) >>> inputs = brainstate.random.randn(3) >>> hidden_perturb = braintrace.add_hidden_perturbation_in_module(gru, inputs) >>> isinstance(hidden_perturb, braintrace.HiddenPerturbation) True
- static __new__(_cls, perturb_vars, perturb_hidden_paths, perturb_hidden_states, perturb_jaxpr)#
Create new instance of HiddenPerturbation(perturb_vars, perturb_hidden_paths, perturb_hidden_states, perturb_jaxpr)
- dict()#
Return this perturbation’s named fields as a plain dictionary.
- Returns:
dict – An ordered mapping from field name to value, as produced by the underlying
typing.NamedTuple.
- eval_jaxpr(inputs, perturb_data)#
Evaluate the perturbed jaxpr.
- Parameters:
inputs (sequence of jax.Array) – The flat input values of the original jaxpr.
perturb_data (sequence of jax.Array) – The perturbation values, one per entry of
perturb_vars.
- Returns:
sequence of jax.Array – The outputs of the perturbed jaxpr.
- init_perturb_data()#
Initialize the perturbation data to zeros.
- Returns:
sequence of jax.Array – One zero array per perturbation variable, matching its shape and dtype.
- perturb_data_to_hidden_group_data(perturb_data, hidden_groups)#
Convert the perturbation data to per-hidden-group data.
- Parameters:
perturb_data (sequence of jax.Array) – The perturbation values, one per entry of
perturb_vars.hidden_groups (sequence of HiddenGroup) – The hidden groups to map the perturbation data onto.
- Returns:
sequence of jax.Array – One concatenated perturbation array per hidden group.
- Raises:
ValueError – If
perturb_datadoes not have the same length asperturb_vars, or if a hidden group needs a path that was not perturbed.
Notes
Both guards are
if ... raiserather thanassertso thatpython -Ocannot strip them. The mapping from paths to perturbation data is positional (zip(perturb_hidden_paths, perturb_data)), so a length disagreement silently re-attributes every cotangent past the mismatch; and a group asking for an unperturbed path used to surface as a bareKeyErrornaming a path tuple and nothing else. Both checks read only Python-level lengths and dict keys, never array data.
- perturb_hidden_paths#
Alias for field number 1
- perturb_hidden_states#
Alias for field number 2
- perturb_jaxpr#
Alias for field number 3
- perturb_vars#
Alias for field number 0
- HiddenPerturbation.__init__()#