braintrace 0.2.3__tar.gz → 0.2.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {braintrace-0.2.3 → braintrace-0.2.5}/PKG-INFO +45 -3
- {braintrace-0.2.3 → braintrace-0.2.5}/README.md +42 -1
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/__init__.py +41 -11
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/__init___test.py +60 -30
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/__init__.py +21 -10
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/_common.py +99 -141
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/_common_test.py +0 -25
- braintrace-0.2.5/braintrace/_algorithm/axes.py +663 -0
- braintrace-0.2.5/braintrace/_algorithm/axes_test.py +497 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/base.py +88 -13
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/base_test.py +2 -2
- braintrace-0.2.5/braintrace/_algorithm/d_rtrl.py +107 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/d_rtrl_test.py +1 -1
- braintrace-0.2.5/braintrace/_algorithm/dni.py +668 -0
- braintrace-0.2.5/braintrace/_algorithm/dni_test.py +1004 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/e_prop.py +76 -95
- braintrace-0.2.5/braintrace/_algorithm/e_prop_test.py +445 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/graph_executor.py +39 -8
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/graph_executor_test.py +22 -1
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/io_dim_vjp.py +388 -147
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/io_dim_vjp_test.py +92 -4
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/ostl.py +82 -16
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/ostl_test.py +115 -0
- braintrace-0.2.5/braintrace/_algorithm/param_dim_vjp.py +1496 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/param_dim_vjp_test.py +412 -3
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/pp_prop.py +34 -4
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/pp_prop_test.py +9 -4
- braintrace-0.2.5/braintrace/_algorithm/random_projection_vjp.py +701 -0
- braintrace-0.2.5/braintrace/_algorithm/random_projection_vjp_test.py +412 -0
- braintrace-0.2.5/braintrace/_algorithm/sequence.py +575 -0
- braintrace-0.2.5/braintrace/_algorithm/sequence_test.py +1534 -0
- braintrace-0.2.5/braintrace/_algorithm/snap_n.py +221 -0
- braintrace-0.2.5/braintrace/_algorithm/snap_n_test.py +1289 -0
- braintrace-0.2.5/braintrace/_algorithm/tests/approx_correctness_test.py +308 -0
- braintrace-0.2.5/braintrace/_algorithm/tests/axis_acceptance_test.py +520 -0
- braintrace-0.2.5/braintrace/_algorithm/tests/axis_discrimination_test.py +111 -0
- braintrace-0.2.5/braintrace/_algorithm/tests/axis_golden_test.py +337 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/tests/conv_vmap_correctness_test.py +11 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/tests/diagnostic_exploration_test.py +2 -2
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/tests/exact_correctness_test.py +75 -71
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/tests/public_api_test.py +17 -3
- braintrace-0.2.5/braintrace/_algorithm/tests/scan_descent_support_test.py +353 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/tests/scan_fusion_test.py +2 -2
- braintrace-0.2.5/braintrace/_algorithm/tests/snn_model_correctness_test.py +136 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/tests/transform_correctness_test.py +3 -82
- braintrace-0.2.5/braintrace/_algorithm/tests/while_support_test.py +256 -0
- braintrace-0.2.5/braintrace/_algorithm/three_factor.py +200 -0
- braintrace-0.2.5/braintrace/_algorithm/three_factor_test.py +651 -0
- braintrace-0.2.5/braintrace/_algorithm/uoro.py +181 -0
- braintrace-0.2.5/braintrace/_algorithm/uoro_test.py +912 -0
- braintrace-0.2.5/braintrace/_algorithm/vjp_base.py +1908 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/vjp_base_test.py +493 -28
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/vjp_graph_executor.py +190 -21
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/vjp_graph_executor_test.py +57 -0
- braintrace-0.2.5/braintrace/_compatible_imports.py +148 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compatible_imports_test.py +60 -1
- braintrace-0.2.5/braintrace/_compile.py +396 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compile_test.py +37 -9
- braintrace-0.2.5/braintrace/_compiler/__init__.py +133 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/base.py +105 -17
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/base_test.py +178 -3
- braintrace-0.2.5/braintrace/_compiler/canonicalize.py +1266 -0
- braintrace-0.2.5/braintrace/_compiler/canonicalize_test.py +1701 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/diagnostics.py +52 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/diagnostics_test.py +10 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/graph.py +225 -27
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/graph_test.py +157 -1
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/hid_param_op.py +225 -96
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/hid_param_op_test.py +1 -1
- braintrace-0.2.5/braintrace/_compiler/hidden_group.py +2285 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/hidden_group_test.py +872 -2
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/hidden_pertubation.py +262 -74
- braintrace-0.2.5/braintrace/_compiler/hidden_pertubation_test.py +508 -0
- braintrace-0.2.5/braintrace/_compiler/jaxpr_graph.py +319 -0
- braintrace-0.2.5/braintrace/_compiler/jaxpr_graph_test.py +320 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/module_info.py +119 -32
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/module_info_test.py +30 -1
- braintrace-0.2.5/braintrace/_compiler/position_graph.py +636 -0
- braintrace-0.2.5/braintrace/_compiler/position_graph_test.py +604 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/report.py +2 -2
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/report_test.py +1 -1
- braintrace-0.2.5/braintrace/_compiler/scan_descent.py +597 -0
- braintrace-0.2.5/braintrace/_compiler/scan_descent_test.py +485 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/tests/compiler_oracle_test.py +1 -1
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/tests/compiler_property_test.py +1 -1
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_grad_exponential.py +0 -5
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_input_data.py +69 -39
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_legacy/_ops.py +35 -35
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_legacy/_params.py +28 -21
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_misc.py +57 -4
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_misc_test.py +53 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_op/__init__.py +42 -3
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_op/_primitive.py +91 -13
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_op/_primitive_test.py +160 -17
- braintrace-0.2.5/braintrace/_op/_registries.py +496 -0
- braintrace-0.2.5/braintrace/_op/_registries_test.py +342 -0
- braintrace-0.2.5/braintrace/_op/conv.py +927 -0
- braintrace-0.2.5/braintrace/_op/conv_test.py +1042 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_op/dense.py +177 -15
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_op/dense_test.py +227 -32
- braintrace-0.2.5/braintrace/_op/einsum.py +371 -0
- braintrace-0.2.5/braintrace/_op/einsum_test.py +496 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_op/elemwise.py +129 -27
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_op/elemwise_test.py +98 -7
- braintrace-0.2.5/braintrace/_op/embedding.py +292 -0
- braintrace-0.2.5/braintrace/_op/embedding_test.py +379 -0
- braintrace-0.2.5/braintrace/_op/grouped.py +464 -0
- braintrace-0.2.5/braintrace/_op/grouped_test.py +496 -0
- braintrace-0.2.5/braintrace/_op/lora.py +696 -0
- braintrace-0.2.5/braintrace/_op/lora_test.py +749 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_op/op_rule_oracle_test.py +15 -9
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_op/sparse.py +188 -27
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_op/sparse_test.py +294 -26
- braintrace-0.2.3/braintrace/_state_managment.py → braintrace-0.2.5/braintrace/_state_management.py +2 -10
- braintrace-0.2.3/braintrace/_state_managment_test.py → braintrace-0.2.5/braintrace/_state_management_test.py +1 -1
- braintrace-0.2.5/braintrace/_testing/__init__.py +50 -0
- braintrace-0.2.5/braintrace/_testing/oracle.py +779 -0
- braintrace-0.2.5/braintrace/_testing/oracle_models.py +1227 -0
- braintrace-0.2.5/braintrace/_testing/oracle_models_test.py +348 -0
- braintrace-0.2.5/braintrace/_testing/oracle_test.py +807 -0
- {braintrace-0.2.3/braintrace/_compiler → braintrace-0.2.5/braintrace/_testing}/scenario_catalog.py +326 -3
- {braintrace-0.2.3/braintrace/_compiler → braintrace-0.2.5/braintrace/_testing}/scenario_catalog_test.py +462 -11
- braintrace-0.2.5/braintrace/_typing_test.py +295 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_version.py +1 -1
- braintrace-0.2.5/braintrace/_version_test.py +170 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/nn/__init__.py +55 -29
- braintrace-0.2.5/braintrace/nn/__init___test.py +248 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/nn/_conv.py +41 -3
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/nn/_conv_test.py +67 -0
- braintrace-0.2.5/braintrace/nn/_embedding.py +288 -0
- braintrace-0.2.5/braintrace/nn/_embedding_test.py +186 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/nn/_linear.py +148 -7
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/nn/_linear_test.py +48 -4
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/nn/_readout.py +3 -1
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/nn/_rnn.py +6 -1
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/nn/_rnn_test.py +57 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace.egg-info/PKG-INFO +45 -3
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace.egg-info/SOURCES.txt +51 -16
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace.egg-info/requires.txt +2 -1
- {braintrace-0.2.3 → braintrace-0.2.5}/pyproject.toml +99 -11
- braintrace-0.2.5/setup.py +136 -0
- braintrace-0.2.3/braintrace/_algorithm/d_rtrl.py +0 -58
- braintrace-0.2.3/braintrace/_algorithm/e_prop_test.py +0 -218
- braintrace-0.2.3/braintrace/_algorithm/oracle.py +0 -222
- braintrace-0.2.3/braintrace/_algorithm/oracle_models.py +0 -195
- braintrace-0.2.3/braintrace/_algorithm/oracle_test.py +0 -175
- braintrace-0.2.3/braintrace/_algorithm/osttp.py +0 -208
- braintrace-0.2.3/braintrace/_algorithm/osttp_test.py +0 -200
- braintrace-0.2.3/braintrace/_algorithm/otpe.py +0 -386
- braintrace-0.2.3/braintrace/_algorithm/otpe_test.py +0 -215
- braintrace-0.2.3/braintrace/_algorithm/ottt.py +0 -262
- braintrace-0.2.3/braintrace/_algorithm/ottt_test.py +0 -209
- braintrace-0.2.3/braintrace/_algorithm/param_dim_vjp.py +0 -892
- braintrace-0.2.3/braintrace/_algorithm/tests/approx_correctness_test.py +0 -323
- braintrace-0.2.3/braintrace/_algorithm/vjp_base.py +0 -789
- braintrace-0.2.3/braintrace/_compatible_imports.py +0 -58
- braintrace-0.2.3/braintrace/_compile.py +0 -302
- braintrace-0.2.3/braintrace/_compiler/__init__.py +0 -56
- braintrace-0.2.3/braintrace/_compiler/hidden_group.py +0 -1335
- braintrace-0.2.3/braintrace/_compiler/hidden_pertubation_test.py +0 -126
- braintrace-0.2.3/braintrace/_docs_examples_test.py +0 -247
- braintrace-0.2.3/braintrace/_op/_registries.py +0 -206
- braintrace-0.2.3/braintrace/_op/_registries_test.py +0 -177
- braintrace-0.2.3/braintrace/_op/conv.py +0 -607
- braintrace-0.2.3/braintrace/_op/conv_test.py +0 -571
- braintrace-0.2.3/braintrace/_op/lora.py +0 -475
- braintrace-0.2.3/braintrace/_op/lora_test.py +0 -442
- {braintrace-0.2.3 → braintrace-0.2.5}/LICENSE +0 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_algorithm/tests/cross_check_test.py +0 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_compiler/tests/cell_relation_guardrail_test.py +0 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_grad_exponential_test.py +0 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_input_data_test.py +0 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_legacy/__init__.py +0 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_legacy/_ops_test.py +0 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_legacy/_params_test.py +0 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_op/op_rule_oracle.py +0 -0
- /braintrace-0.2.3/braintrace/_compiler/model4test.py → /braintrace-0.2.5/braintrace/_testing/compiler_models.py +0 -0
- /braintrace-0.2.3/braintrace/_etrace_model_test.py → /braintrace-0.2.5/braintrace/_testing/models.py +0 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/_typing.py +0 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/nn/_readout_test.py +0 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace/py.typed +0 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace.egg-info/dependency_links.txt +0 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/braintrace.egg-info/top_level.txt +0 -0
- {braintrace-0.2.3 → braintrace-0.2.5}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: braintrace
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.5
|
|
4
4
|
Summary: Enabling Scalable Online Learning for Brain Dynamics.
|
|
5
5
|
Author-email: BrainTrace Developers <chao.brain@qq.com>
|
|
6
6
|
License: Apache-2.0 license
|
|
@@ -26,9 +26,10 @@ Classifier: Topic :: Software Development :: Libraries
|
|
|
26
26
|
Requires-Python: >=3.11
|
|
27
27
|
Description-Content-Type: text/markdown
|
|
28
28
|
License-File: LICENSE
|
|
29
|
+
Requires-Dist: jax>=0.8.0
|
|
29
30
|
Requires-Dist: brainstate>=0.5.2
|
|
30
31
|
Requires-Dist: brainunit
|
|
31
|
-
Requires-Dist: brainevent
|
|
32
|
+
Requires-Dist: brainevent>=0.1.2
|
|
32
33
|
Requires-Dist: brainpy.state
|
|
33
34
|
Requires-Dist: braintools
|
|
34
35
|
Provides-Extra: cpu
|
|
@@ -74,7 +75,7 @@ It has been integrated into our establishing [brain modeling ecosystem](https://
|
|
|
74
75
|
|
|
75
76
|
## Installation
|
|
76
77
|
|
|
77
|
-
``braintrace``
|
|
78
|
+
``braintrace`` requires Python 3.11 or newer and supports Linux, macOS, and Windows. You can install ``braintrace`` via pip:
|
|
78
79
|
|
|
79
80
|
```bash
|
|
80
81
|
pip install braintrace --upgrade
|
|
@@ -86,6 +87,47 @@ Alternatively, you can install `BrainX`, which bundles `braintrace` with other c
|
|
|
86
87
|
pip install BrainX -U
|
|
87
88
|
```
|
|
88
89
|
|
|
90
|
+
## Quickstart
|
|
91
|
+
|
|
92
|
+
Mark the trainable operations with an ETP primitive (here, via `braintrace.nn`
|
|
93
|
+
layers, which use them internally), then compile the model into a learner and
|
|
94
|
+
drive a sequence. There is no scan to write and no special parameter class —
|
|
95
|
+
weights stay plain `brainstate.ParamState`.
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
import brainstate
|
|
99
|
+
import jax.numpy as jnp
|
|
100
|
+
import braintrace
|
|
101
|
+
|
|
102
|
+
class GRUNet(brainstate.nn.Module):
|
|
103
|
+
def __init__(self, n_in, n_rec, n_out):
|
|
104
|
+
super().__init__()
|
|
105
|
+
self.rnn = braintrace.nn.GRUCell(n_in, n_rec)
|
|
106
|
+
self.out = braintrace.nn.Linear(n_rec, n_out)
|
|
107
|
+
|
|
108
|
+
def update(self, x):
|
|
109
|
+
return self.out(self.rnn(x))
|
|
110
|
+
|
|
111
|
+
model = GRUNet(3, 8, 1)
|
|
112
|
+
|
|
113
|
+
# One call: initialise states, compile the eligibility-trace graph,
|
|
114
|
+
# return a ready learner.
|
|
115
|
+
learner = braintrace.compile(model, braintrace.D_RTRL, jnp.zeros((1, 3)), batch_size=1)
|
|
116
|
+
|
|
117
|
+
def step_loss(x, y):
|
|
118
|
+
return jnp.mean((learner(x) - y) ** 2)
|
|
119
|
+
|
|
120
|
+
xs = brainstate.random.randn(100, 1, 3) # (time, batch, features)
|
|
121
|
+
ys = brainstate.random.randn(100, 1, 1)
|
|
122
|
+
|
|
123
|
+
# Drives the sequence and accumulates online gradients -- O(1) memory in T.
|
|
124
|
+
grads, losses = learner.etrace_grad(xs, ys, step_fn=step_loss, return_value=True)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Swap `braintrace.D_RTRL` for `pp_prop`, `SnAp`, `UORO`, `ThreeFactor`, `DNI`,
|
|
128
|
+
`EProp`, the OSTL variants, or an explicit `braintrace.ETraceConfig` to change
|
|
129
|
+
the learning rule; nothing else in the snippet changes.
|
|
130
|
+
|
|
89
131
|
## Documentation
|
|
90
132
|
|
|
91
133
|
The official documentation is hosted on Read the Docs: [https://brainx.chaobrain.com/braintrace](https://brainx.chaobrain.com/braintrace)
|
|
@@ -19,7 +19,7 @@ It has been integrated into our establishing [brain modeling ecosystem](https://
|
|
|
19
19
|
|
|
20
20
|
## Installation
|
|
21
21
|
|
|
22
|
-
``braintrace``
|
|
22
|
+
``braintrace`` requires Python 3.11 or newer and supports Linux, macOS, and Windows. You can install ``braintrace`` via pip:
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
25
|
pip install braintrace --upgrade
|
|
@@ -31,6 +31,47 @@ Alternatively, you can install `BrainX`, which bundles `braintrace` with other c
|
|
|
31
31
|
pip install BrainX -U
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
+
## Quickstart
|
|
35
|
+
|
|
36
|
+
Mark the trainable operations with an ETP primitive (here, via `braintrace.nn`
|
|
37
|
+
layers, which use them internally), then compile the model into a learner and
|
|
38
|
+
drive a sequence. There is no scan to write and no special parameter class —
|
|
39
|
+
weights stay plain `brainstate.ParamState`.
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
import brainstate
|
|
43
|
+
import jax.numpy as jnp
|
|
44
|
+
import braintrace
|
|
45
|
+
|
|
46
|
+
class GRUNet(brainstate.nn.Module):
|
|
47
|
+
def __init__(self, n_in, n_rec, n_out):
|
|
48
|
+
super().__init__()
|
|
49
|
+
self.rnn = braintrace.nn.GRUCell(n_in, n_rec)
|
|
50
|
+
self.out = braintrace.nn.Linear(n_rec, n_out)
|
|
51
|
+
|
|
52
|
+
def update(self, x):
|
|
53
|
+
return self.out(self.rnn(x))
|
|
54
|
+
|
|
55
|
+
model = GRUNet(3, 8, 1)
|
|
56
|
+
|
|
57
|
+
# One call: initialise states, compile the eligibility-trace graph,
|
|
58
|
+
# return a ready learner.
|
|
59
|
+
learner = braintrace.compile(model, braintrace.D_RTRL, jnp.zeros((1, 3)), batch_size=1)
|
|
60
|
+
|
|
61
|
+
def step_loss(x, y):
|
|
62
|
+
return jnp.mean((learner(x) - y) ** 2)
|
|
63
|
+
|
|
64
|
+
xs = brainstate.random.randn(100, 1, 3) # (time, batch, features)
|
|
65
|
+
ys = brainstate.random.randn(100, 1, 1)
|
|
66
|
+
|
|
67
|
+
# Drives the sequence and accumulates online gradients -- O(1) memory in T.
|
|
68
|
+
grads, losses = learner.etrace_grad(xs, ys, step_fn=step_loss, return_value=True)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Swap `braintrace.D_RTRL` for `pp_prop`, `SnAp`, `UORO`, `ThreeFactor`, `DNI`,
|
|
72
|
+
`EProp`, the OSTL variants, or an explicit `braintrace.ETraceConfig` to change
|
|
73
|
+
the learning rule; nothing else in the snippet changes.
|
|
74
|
+
|
|
34
75
|
## Documentation
|
|
35
76
|
|
|
36
77
|
The official documentation is hosted on Read the Docs: [https://brainx.chaobrain.com/braintrace](https://brainx.chaobrain.com/braintrace)
|
|
@@ -41,8 +41,10 @@ downward:
|
|
|
41
41
|
hidden->weight / hidden->hidden Jacobian computations.
|
|
42
42
|
4. **Algorithms** — online-learning orchestrators: the exact algorithms
|
|
43
43
|
:class:`D_RTRL` / :func:`pp_prop` / :class:`ES_D_RTRL`, and the SNN family
|
|
44
|
-
:class:`EProp`, :class:`OSTLRecurrent`, :class:`OSTLFeedforward
|
|
45
|
-
|
|
44
|
+
:class:`EProp`, :class:`OSTLRecurrent`, :class:`OSTLFeedforward`. Every one
|
|
45
|
+
of them carries the two sequence drivers of
|
|
46
|
+
:class:`SequenceDriverMixin` — ``etrace_grad`` and ``etrace_evolve`` — so a
|
|
47
|
+
caller never writes the per-step gradient-accumulation loop by hand.
|
|
46
48
|
|
|
47
49
|
The :mod:`braintrace.nn` subpackage provides ready-made ETP-wired layers
|
|
48
50
|
(linear maps, convolutions, recurrent cells, read-outs).
|
|
@@ -50,7 +52,13 @@ The :mod:`braintrace.nn` subpackage provides ready-made ETP-wired layers
|
|
|
50
52
|
Notes
|
|
51
53
|
-----
|
|
52
54
|
The convenience entry point :func:`compile` wraps a model together with an
|
|
53
|
-
algorithm into a single trainable object and is the recommended starting point
|
|
55
|
+
algorithm into a single trainable object and is the recommended starting point:
|
|
56
|
+
one call replaces ``init_all_states`` + algorithm construction +
|
|
57
|
+
``compile_graph`` (+ the vmap wrapper, with ``vmap=True``). The object it
|
|
58
|
+
returns drives a sequence with :meth:`~SequenceDriverMixin.etrace_grad`
|
|
59
|
+
(accumulate online gradients under a loss) or
|
|
60
|
+
:meth:`~SequenceDriverMixin.etrace_evolve` (advance hidden state and the
|
|
61
|
+
eligibility trace with no loss).
|
|
54
62
|
The ``braintrace.MatMulOp`` / ``ETraceParam`` style names from the v0.1.x API
|
|
55
63
|
are deprecated shims served lazily with a :class:`DeprecationWarning`; new code
|
|
56
64
|
should mark parameters by routing them through ETP ops instead.
|
|
@@ -73,9 +81,12 @@ from typing import TYPE_CHECKING, Any
|
|
|
73
81
|
from . import nn
|
|
74
82
|
from ._compile import compile
|
|
75
83
|
from ._algorithm import (
|
|
84
|
+
ETraceConfig,
|
|
76
85
|
ETraceAlgorithm,
|
|
77
86
|
EligibilityTrace,
|
|
78
87
|
ETraceGraphExecutor,
|
|
88
|
+
ETraceVmap,
|
|
89
|
+
SequenceDriverMixin,
|
|
79
90
|
ETraceVjpAlgorithm,
|
|
80
91
|
ETraceVjpGraphExecutor,
|
|
81
92
|
ParamDimVjpAlgorithm,
|
|
@@ -83,17 +94,21 @@ from ._algorithm import (
|
|
|
83
94
|
pp_prop,
|
|
84
95
|
ES_D_RTRL,
|
|
85
96
|
IODimVjpAlgorithm,
|
|
97
|
+
SnAp,
|
|
98
|
+
RandomProjectionVjpAlgorithm,
|
|
99
|
+
UORO,
|
|
100
|
+
ThreeFactor,
|
|
101
|
+
DNI,
|
|
102
|
+
SyntheticGradient,
|
|
103
|
+
train_synthetic_gradient,
|
|
86
104
|
EProp,
|
|
87
105
|
OSTLRecurrent,
|
|
88
106
|
OSTLFeedforward,
|
|
89
|
-
OTPE,
|
|
90
|
-
OTTT,
|
|
91
|
-
OSTTP,
|
|
92
107
|
FixedRandomFeedback,
|
|
93
108
|
KappaFilter,
|
|
94
|
-
PresynapticTrace,
|
|
95
109
|
)
|
|
96
110
|
from ._compiler import (
|
|
111
|
+
ControlFlowPolicy,
|
|
97
112
|
ETraceGraph,
|
|
98
113
|
compile_etrace_graph,
|
|
99
114
|
HiddenParamOpRelation,
|
|
@@ -115,6 +130,9 @@ from ._compiler import (
|
|
|
115
130
|
from ._op import (
|
|
116
131
|
ETPPrimitive,
|
|
117
132
|
matmul,
|
|
133
|
+
grouped_matmul,
|
|
134
|
+
embedding,
|
|
135
|
+
einsum,
|
|
118
136
|
element_wise,
|
|
119
137
|
conv,
|
|
120
138
|
sparse_matmul,
|
|
@@ -152,9 +170,14 @@ __all__ = [
|
|
|
152
170
|
'__version__',
|
|
153
171
|
'__version_info__',
|
|
154
172
|
|
|
173
|
+
# learning-rule axes
|
|
174
|
+
'ETraceConfig',
|
|
175
|
+
|
|
155
176
|
# algorithms
|
|
156
177
|
'ETraceAlgorithm',
|
|
157
178
|
'EligibilityTrace',
|
|
179
|
+
'ETraceVmap',
|
|
180
|
+
'SequenceDriverMixin',
|
|
158
181
|
'ETraceVjpAlgorithm',
|
|
159
182
|
'ETraceVjpGraphExecutor',
|
|
160
183
|
'ParamDimVjpAlgorithm',
|
|
@@ -162,12 +185,22 @@ __all__ = [
|
|
|
162
185
|
'pp_prop',
|
|
163
186
|
'ES_D_RTRL',
|
|
164
187
|
'IODimVjpAlgorithm',
|
|
188
|
+
'SnAp',
|
|
189
|
+
'RandomProjectionVjpAlgorithm',
|
|
190
|
+
'UORO',
|
|
191
|
+
'ThreeFactor',
|
|
192
|
+
'DNI',
|
|
193
|
+
'SyntheticGradient',
|
|
194
|
+
'train_synthetic_gradient',
|
|
165
195
|
|
|
166
196
|
# one-call entry point
|
|
167
197
|
'compile',
|
|
168
198
|
|
|
169
199
|
# ETP primitives (user API)
|
|
170
200
|
'matmul',
|
|
201
|
+
'grouped_matmul',
|
|
202
|
+
'embedding',
|
|
203
|
+
'einsum',
|
|
171
204
|
'element_wise',
|
|
172
205
|
'conv',
|
|
173
206
|
'sparse_matmul',
|
|
@@ -185,6 +218,7 @@ __all__ = [
|
|
|
185
218
|
'ETraceGraphExecutor',
|
|
186
219
|
|
|
187
220
|
# compiler
|
|
221
|
+
'ControlFlowPolicy',
|
|
188
222
|
'ETraceGraph',
|
|
189
223
|
'compile_etrace_graph',
|
|
190
224
|
'HiddenGroup',
|
|
@@ -212,12 +246,8 @@ __all__ = [
|
|
|
212
246
|
'EProp',
|
|
213
247
|
'OSTLRecurrent',
|
|
214
248
|
'OSTLFeedforward',
|
|
215
|
-
'OTPE',
|
|
216
|
-
'OTTT',
|
|
217
|
-
'OSTTP',
|
|
218
249
|
'FixedRandomFeedback',
|
|
219
250
|
'KappaFilter',
|
|
220
|
-
'PresynapticTrace',
|
|
221
251
|
|
|
222
252
|
# errors
|
|
223
253
|
'NotSupportedError',
|
|
@@ -33,7 +33,7 @@ import pytest
|
|
|
33
33
|
|
|
34
34
|
import braintrace
|
|
35
35
|
import braintrace._legacy as legacy
|
|
36
|
-
from braintrace.
|
|
36
|
+
from braintrace._testing.oracle_models import tanh_rnn
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
# ===========================================================================
|
|
@@ -71,6 +71,10 @@ def _algo_constructors():
|
|
|
71
71
|
'EProp': lambda m: braintrace.EProp(m),
|
|
72
72
|
'OSTLRecurrent': lambda m: braintrace.OSTLRecurrent(m),
|
|
73
73
|
'OSTLFeedforward': lambda m: braintrace.OSTLFeedforward(m, decay_or_rank=0.9),
|
|
74
|
+
'SnAp': lambda m: braintrace.SnAp(m, n=1),
|
|
75
|
+
'UORO': lambda m: braintrace.UORO(m),
|
|
76
|
+
# `modulatory` has no fallback: a standing modulator is required.
|
|
77
|
+
'ThreeFactor': lambda m: braintrace.ThreeFactor(m, modulator=0.5),
|
|
74
78
|
}
|
|
75
79
|
|
|
76
80
|
|
|
@@ -87,33 +91,30 @@ def test_algorithm_is_usable_end_to_end(name):
|
|
|
87
91
|
assert bool(jnp.all(jnp.isfinite(y)))
|
|
88
92
|
|
|
89
93
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
model = tanh_rnn(seed=0).factory()
|
|
94
|
+
def test_dni_is_usable_end_to_end():
|
|
95
|
+
# DNI is the one preset whose second collaborator is sized from the compiled
|
|
96
|
+
# graph, so it cannot join the shared map above: build, compile, then attach.
|
|
97
|
+
model = tanh_rnn(n_in=3, n_rec=4, seed=0).factory()
|
|
94
98
|
brainstate.nn.init_all_states(model, batch_size=1)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
model = tanh_rnn(seed=0).factory()
|
|
105
|
-
brainstate.nn.init_all_states(model, batch_size=1)
|
|
106
|
-
algo = ctor(model)
|
|
107
|
-
assert algo is not None
|
|
99
|
+
algo = braintrace.DNI(model)
|
|
100
|
+
x0 = jnp.ones((3,), dtype='float32')
|
|
101
|
+
algo.compile_graph(x0)
|
|
102
|
+
algo.init_etrace_state()
|
|
103
|
+
algo.attach_synthesizer(
|
|
104
|
+
braintrace.SyntheticGradient(algo.group_signal_shapes()))
|
|
105
|
+
y = algo(x0)
|
|
106
|
+
assert y.shape == (1, 4)
|
|
107
|
+
assert bool(jnp.all(jnp.isfinite(y)))
|
|
108
108
|
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
assert
|
|
110
|
+
@pytest.mark.parametrize('name', ['UORO', 'ThreeFactor', 'DNI',
|
|
111
|
+
'SyntheticGradient', 'train_synthetic_gradient',
|
|
112
|
+
'RandomProjectionVjpAlgorithm'])
|
|
113
|
+
def test_p4_symbols_are_exported_from_both_all_lists(name):
|
|
114
|
+
from braintrace import _algorithm
|
|
115
|
+
assert name in braintrace.__all__, f'{name} missing from braintrace.__all__'
|
|
116
|
+
assert name in _algorithm.__all__, f'{name} missing from _algorithm.__all__'
|
|
117
|
+
assert getattr(braintrace, name) is getattr(_algorithm, name)
|
|
117
118
|
|
|
118
119
|
|
|
119
120
|
# --- Task 4: dynamic weight assignment raises NotSupportedError --------------
|
|
@@ -148,7 +149,14 @@ def test_weight_used_inside_scan_raises_not_implemented():
|
|
|
148
149
|
within a control-flow op. Previously (F-SCAN-WEIGHT) the message construction
|
|
149
150
|
indexed the hidden-path map with the weight var and a KeyError escaped instead;
|
|
150
151
|
the message now renders the weight variable directly, so the intended
|
|
151
|
-
NotImplementedError surfaces.
|
|
152
|
+
NotImplementedError surfaces.
|
|
153
|
+
|
|
154
|
+
Since Phase 2 canonicalization, statically short scans are unrolled at
|
|
155
|
+
extraction time instead of erroring, so this uses a length above
|
|
156
|
+
``ControlFlowPolicy.scan_unroll_limit`` to reach the unsupported-op path
|
|
157
|
+
(after a SCAN_UNROLL_SKIPPED warning). Since Phase 4, structured scan
|
|
158
|
+
descent handles over-limit ETP scans by default, so this pins the
|
|
159
|
+
opt-out path via ``ControlFlowPolicy(scan_descent='off')``."""
|
|
152
160
|
|
|
153
161
|
class ScanModel(brainstate.nn.Module):
|
|
154
162
|
def __init__(self):
|
|
@@ -160,15 +168,17 @@ def test_weight_used_inside_scan_raises_not_implemented():
|
|
|
160
168
|
def update(self, x):
|
|
161
169
|
def body(carry, _):
|
|
162
170
|
return braintrace.matmul(carry, self.w.value), None # weight inside scan
|
|
163
|
-
out, _ = jax.lax.scan(body, self.h.value, xs=None, length=
|
|
171
|
+
out, _ = jax.lax.scan(body, self.h.value, xs=None, length=64)
|
|
164
172
|
self.h.value = jax.nn.tanh(out)
|
|
165
173
|
return self.h.value
|
|
166
174
|
|
|
167
175
|
model = ScanModel()
|
|
168
176
|
brainstate.nn.init_all_states(model, batch_size=1)
|
|
169
|
-
algo = braintrace.D_RTRL(
|
|
177
|
+
algo = braintrace.D_RTRL(
|
|
178
|
+
model, control_flow=braintrace.ControlFlowPolicy(scan_descent='off'))
|
|
170
179
|
with pytest.raises(NotImplementedError):
|
|
171
|
-
|
|
180
|
+
with pytest.warns(UserWarning, match='NOT unrolled'):
|
|
181
|
+
algo.compile_graph(jnp.ones((1, 4), dtype='float32'))
|
|
172
182
|
|
|
173
183
|
|
|
174
184
|
# --- Task 6: legacy + nn deprecations emit DeprecationWarning ----------------
|
|
@@ -191,6 +201,14 @@ def test_nn_forwarded_name_warns():
|
|
|
191
201
|
_ = nn.LayerNorm
|
|
192
202
|
|
|
193
203
|
|
|
204
|
+
def test_nn_forwarded_state_name_warns_and_resolves():
|
|
205
|
+
import brainpy.state
|
|
206
|
+
import braintrace.nn as nn
|
|
207
|
+
with pytest.warns(DeprecationWarning):
|
|
208
|
+
forwarded = nn.LIF
|
|
209
|
+
assert forwarded is brainpy.state.LIF
|
|
210
|
+
|
|
211
|
+
|
|
194
212
|
def test_nn_unknown_name_raises_attribute_error():
|
|
195
213
|
import braintrace.nn as nn
|
|
196
214
|
with pytest.raises(AttributeError):
|
|
@@ -217,8 +235,20 @@ def test_iodim_lives_in_io_dim_vjp_module():
|
|
|
217
235
|
def test_expected_rnn_cells_exist():
|
|
218
236
|
import braintrace.nn as nn
|
|
219
237
|
for cell in ('ValinaRNNCell', 'GRUCell', 'MGUCell', 'LSTMCell', 'URLSTMCell',
|
|
220
|
-
'MinimalRNNCell', 'MiniGRU', 'MiniLSTM', 'LRUCell'):
|
|
238
|
+
'MinimalRNNCell', 'MiniGRU', 'MiniLSTM', 'LRUCell', 'CFNCell'):
|
|
221
239
|
assert hasattr(nn, cell), f"missing cell: {cell}"
|
|
240
|
+
assert cell in nn.__all__, f"cell not in __all__: {cell}"
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def test_nn_dir_advertises_deprecated_forwards():
|
|
244
|
+
# ``braintrace.nn.__getattr__`` forwards ~50 names to brainstate.nn /
|
|
245
|
+
# brainpy.state. Without ``__dir__`` none of them is discoverable, so the
|
|
246
|
+
# forwarding is invisible to tab-completion and to ``dir()``-based tooling.
|
|
247
|
+
import braintrace.nn as nn
|
|
248
|
+
names = dir(nn)
|
|
249
|
+
assert 'ReLU' in names # forwarded to brainstate.nn
|
|
250
|
+
assert 'LIF' in names # forwarded to brainpy.state
|
|
251
|
+
assert set(nn.__all__).issubset(names)
|
|
222
252
|
|
|
223
253
|
|
|
224
254
|
# ===========================================================================
|
|
@@ -17,32 +17,40 @@
|
|
|
17
17
|
|
|
18
18
|
Groups the core ETrace infrastructure (``ETraceAlgorithm``, ``EligibilityTrace``,
|
|
19
19
|
``ETraceGraphExecutor``), VJP-based algorithms (D-RTRL, pp_prop / ES-D-RTRL),
|
|
20
|
-
and paper-faithful SNN algorithms (EProp, OSTLRecurrent, OSTLFeedforward
|
|
21
|
-
OTTT, OSTTP).
|
|
20
|
+
and paper-faithful SNN algorithms (EProp, OSTLRecurrent, OSTLFeedforward).
|
|
22
21
|
"""
|
|
23
22
|
|
|
24
23
|
from __future__ import annotations
|
|
25
24
|
|
|
26
|
-
from ._common import FixedRandomFeedback, KappaFilter
|
|
25
|
+
from ._common import FixedRandomFeedback, KappaFilter
|
|
26
|
+
from .axes import ETraceConfig
|
|
27
27
|
from .base import ETraceAlgorithm, EligibilityTrace
|
|
28
28
|
from .d_rtrl import D_RTRL
|
|
29
29
|
from .e_prop import EProp
|
|
30
30
|
from .graph_executor import ETraceGraphExecutor
|
|
31
31
|
from .ostl import OSTLFeedforward, OSTLRecurrent
|
|
32
|
-
from .osttp import OSTTP
|
|
33
|
-
from .otpe import OTPE
|
|
34
|
-
from .ottt import OTTT
|
|
35
32
|
from .io_dim_vjp import IODimVjpAlgorithm
|
|
36
33
|
from .param_dim_vjp import ParamDimVjpAlgorithm
|
|
34
|
+
from .random_projection_vjp import RandomProjectionVjpAlgorithm
|
|
37
35
|
from .pp_prop import ES_D_RTRL, pp_prop # ES_D_RTRL: back-compat alias
|
|
36
|
+
from .sequence import ETraceVmap, SequenceDriverMixin
|
|
37
|
+
from .snap_n import SnAp
|
|
38
|
+
from .dni import DNI, SyntheticGradient, train_synthetic_gradient
|
|
39
|
+
from .three_factor import ThreeFactor
|
|
40
|
+
from .uoro import UORO
|
|
38
41
|
from .vjp_base import ETraceVjpAlgorithm
|
|
39
42
|
from .vjp_graph_executor import ETraceVjpGraphExecutor
|
|
40
43
|
|
|
41
44
|
__all__ = [
|
|
45
|
+
# axes
|
|
46
|
+
'ETraceConfig',
|
|
42
47
|
# core
|
|
43
48
|
'ETraceAlgorithm',
|
|
44
49
|
'EligibilityTrace',
|
|
45
50
|
'ETraceGraphExecutor',
|
|
51
|
+
# sequence drivers
|
|
52
|
+
'ETraceVmap',
|
|
53
|
+
'SequenceDriverMixin',
|
|
46
54
|
# VJP
|
|
47
55
|
'ETraceVjpAlgorithm',
|
|
48
56
|
'ETraceVjpGraphExecutor',
|
|
@@ -51,14 +59,17 @@ __all__ = [
|
|
|
51
59
|
'pp_prop',
|
|
52
60
|
'ES_D_RTRL',
|
|
53
61
|
'IODimVjpAlgorithm',
|
|
62
|
+
'SnAp',
|
|
63
|
+
'RandomProjectionVjpAlgorithm',
|
|
64
|
+
'UORO',
|
|
65
|
+
'ThreeFactor',
|
|
66
|
+
'DNI',
|
|
67
|
+
'SyntheticGradient',
|
|
68
|
+
'train_synthetic_gradient',
|
|
54
69
|
# SNN
|
|
55
70
|
'EProp',
|
|
56
71
|
'OSTLRecurrent',
|
|
57
72
|
'OSTLFeedforward',
|
|
58
|
-
'OTPE',
|
|
59
|
-
'OTTT',
|
|
60
|
-
'OSTTP',
|
|
61
73
|
'FixedRandomFeedback',
|
|
62
74
|
'KappaFilter',
|
|
63
|
-
'PresynapticTrace',
|
|
64
75
|
]
|