OpenReservoirComputing 0.1.3a0__tar.gz → 0.2.0__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.
- {openreservoircomputing-0.1.3a0/src/OpenReservoirComputing.egg-info → openreservoircomputing-0.2.0}/PKG-INFO +2 -2
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/README.md +1 -1
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/api/classifier.md +5 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/api/control.md +5 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/api/forecaster.md +5 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/examples/classification.ipynb +4 -4
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/examples/continuous_rc.ipynb +7 -7
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/examples/control.ipynb +5 -5
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/examples/ks.ipynb +1 -1
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0/docs}/examples/lorenz.ipynb +1 -1
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0/docs}/examples/rc_background.ipynb +16 -6
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/user-guide/drivers.md +9 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/user-guide/models.md +129 -8
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/user-guide/readouts.md +49 -14
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/examples/classification.ipynb +4 -4
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/examples/continuous_rc.ipynb +7 -7
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/examples/control.ipynb +5 -5
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/examples/ks.ipynb +1 -1
- openreservoircomputing-0.2.0/examples/lorenz.ipynb +264 -0
- openreservoircomputing-0.2.0/examples/rc_background.ipynb +420 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0/src/OpenReservoirComputing.egg-info}/PKG-INFO +2 -2
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/orc/classifier/__init__.py +2 -1
- openreservoircomputing-0.2.0/src/orc/classifier/train.py +152 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/orc/control/__init__.py +2 -1
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/orc/control/models.py +18 -0
- openreservoircomputing-0.2.0/src/orc/control/train.py +160 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/orc/drivers.py +40 -1
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/orc/embeddings.py +3 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/orc/forecaster/__init__.py +2 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/orc/forecaster/base.py +2 -24
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/orc/forecaster/train.py +112 -160
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/orc/readouts.py +186 -1
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/tests/classifier/test_classifier_models.py +96 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/tests/control/test_control_models.py +73 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/tests/forecaster/test_forecast_models.py +110 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/tests/test_readouts.py +174 -0
- openreservoircomputing-0.1.3a0/docs/examples/lorenz.ipynb +0 -256
- openreservoircomputing-0.1.3a0/docs/examples/rc_background.ipynb +0 -417
- openreservoircomputing-0.1.3a0/src/orc/classifier/train.py +0 -83
- openreservoircomputing-0.1.3a0/src/orc/control/train.py +0 -90
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/.github/CODEOWNERS +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/.github/workflows/docs.yml +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/.github/workflows/publish.yml +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/.github/workflows/tests.yml +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/.gitignore +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/LICENSE +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/api/data.md +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/api/drivers.md +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/api/embeddings.md +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/api/readouts.md +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/api/utils.md +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/contributing.md +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/examples/data_library.ipynb +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/getting-started/installation.md +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/getting-started/quickstart.md +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/imgs/ORC_logo_cropped.png +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/imgs/control_diagram.png +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/imgs/readme_example_forecast.png +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/index.md +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/javascripts/mathjax.js +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/stylesheets/extra.css +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/user-guide/data.md +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/user-guide/embeddings.md +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/user-guide/overview.md +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/examples/data_library.ipynb +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/imgs/ORC_logo_cropped.png +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/imgs/control_diagram.png +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/imgs/readme_example_forecast.png +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/mkdocs.yml +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/pyproject.toml +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/setup.cfg +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/OpenReservoirComputing.egg-info/SOURCES.txt +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/OpenReservoirComputing.egg-info/dependency_links.txt +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/OpenReservoirComputing.egg-info/requires.txt +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/OpenReservoirComputing.egg-info/top_level.txt +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/orc/__init__.py +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/orc/classifier/base.py +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/orc/classifier/models.py +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/orc/control/base.py +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/orc/data/__init__.py +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/orc/data/integrators.py +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/orc/forecaster/models.py +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/orc/utils/__init__.py +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/orc/utils/numerics.py +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/orc/utils/regressions.py +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/src/orc/utils/visualization.py +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/tests/data/test_integrators.py +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/tests/test_drivers.py +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/tests/test_embeddings.py +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/tests/utils/test_numerics.py +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/tests/utils/test_regressions.py +0 -0
- {openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/tests/utils/test_visualization.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: OpenReservoirComputing
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: GPU accelerated implementations of common RC architectures
|
|
5
5
|
Author-email: "Jan P. Williams" <jmpw1@uw.edu>, Dima Tretiak <dtretiak@uw.edu>
|
|
6
6
|
Maintainer-email: "Jan P. Williams" <jmpw1@uw.edu>
|
|
@@ -111,7 +111,7 @@ t_test = t[split_idx:]
|
|
|
111
111
|
|
|
112
112
|
# Initialize and train the ESN
|
|
113
113
|
esn = orc.forecaster.ESNForecaster(data_dim=3, res_dim=400)
|
|
114
|
-
esn, R = orc.forecaster.
|
|
114
|
+
esn, R = orc.forecaster.train_RCForecaster(esn, U_train)
|
|
115
115
|
|
|
116
116
|
# Forecast!
|
|
117
117
|
U_pred = esn.forecast(fcast_len=U_test.shape[0], res_state=R[-1]) # feed in the last reservoir state seen in training
|
|
@@ -52,7 +52,7 @@ t_test = t[split_idx:]
|
|
|
52
52
|
|
|
53
53
|
# Initialize and train the ESN
|
|
54
54
|
esn = orc.forecaster.ESNForecaster(data_dim=3, res_dim=400)
|
|
55
|
-
esn, R = orc.forecaster.
|
|
55
|
+
esn, R = orc.forecaster.train_RCForecaster(esn, U_train)
|
|
56
56
|
|
|
57
57
|
# Forecast!
|
|
58
58
|
U_pred = esn.forecast(fcast_len=U_test.shape[0], res_state=R[-1]) # feed in the last reservoir state seen in training
|
|
@@ -20,6 +20,11 @@ The `orc.classifier` subpackage provides reservoir computing models for time ser
|
|
|
20
20
|
|
|
21
21
|
## Training Functions
|
|
22
22
|
|
|
23
|
+
::: orc.classifier.train.train_RCClassifier
|
|
24
|
+
options:
|
|
25
|
+
show_root_heading: true
|
|
26
|
+
show_source: true
|
|
27
|
+
|
|
23
28
|
::: orc.classifier.train.train_ESNClassifier
|
|
24
29
|
options:
|
|
25
30
|
show_root_heading: true
|
|
@@ -20,6 +20,11 @@ The `orc.control` subpackage provides reservoir computing models for dynamical s
|
|
|
20
20
|
|
|
21
21
|
## Training Functions
|
|
22
22
|
|
|
23
|
+
::: orc.control.train.train_RCController
|
|
24
|
+
options:
|
|
25
|
+
show_root_heading: true
|
|
26
|
+
show_source: true
|
|
27
|
+
|
|
23
28
|
::: orc.control.train.train_ESNController
|
|
24
29
|
options:
|
|
25
30
|
show_root_heading: true
|
|
@@ -38,6 +38,11 @@ The `orc.forecaster` subpackage provides reservoir computing models for time ser
|
|
|
38
38
|
|
|
39
39
|
## Training Functions
|
|
40
40
|
|
|
41
|
+
::: orc.forecaster.train.train_RCForecaster
|
|
42
|
+
options:
|
|
43
|
+
show_root_heading: true
|
|
44
|
+
show_source: true
|
|
45
|
+
|
|
41
46
|
::: orc.forecaster.train.train_ESNForecaster
|
|
42
47
|
options:
|
|
43
48
|
show_root_heading: true
|
{openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/examples/classification.ipynb
RENAMED
|
@@ -207,7 +207,7 @@
|
|
|
207
207
|
}
|
|
208
208
|
],
|
|
209
209
|
"source": [
|
|
210
|
-
"trained_classifier = orc.classifier.
|
|
210
|
+
"trained_classifier = orc.classifier.train_RCClassifier(\n",
|
|
211
211
|
" classifier,\n",
|
|
212
212
|
" train_seqs=train_seqs,\n",
|
|
213
213
|
" labels=train_labels,\n",
|
|
@@ -245,7 +245,7 @@
|
|
|
245
245
|
"probs = jax.vmap(trained_classifier.classify)(train_seqs)\n",
|
|
246
246
|
"\n",
|
|
247
247
|
"\n",
|
|
248
|
-
"train_preds = jnp.
|
|
248
|
+
"train_preds = jnp.argmax(probs, axis=1)\n",
|
|
249
249
|
"train_acc = jnp.mean(train_preds == train_labels)\n",
|
|
250
250
|
"print(f\"Training accuracy: {train_acc:.1%}\")"
|
|
251
251
|
]
|
|
@@ -277,7 +277,7 @@
|
|
|
277
277
|
"source": [
|
|
278
278
|
"probs = jax.vmap(trained_classifier.classify)(test_seqs)\n",
|
|
279
279
|
"\n",
|
|
280
|
-
"test_preds = jnp.
|
|
280
|
+
"test_preds = jnp.argmax(probs, axis=1)\n",
|
|
281
281
|
"test_acc = jnp.mean(test_preds == test_labels)\n",
|
|
282
282
|
"print(f\"Test accuracy: {test_acc:.1%}\")"
|
|
283
283
|
]
|
|
@@ -356,7 +356,7 @@
|
|
|
356
356
|
" state_repr=\"mean\",\n",
|
|
357
357
|
")\n",
|
|
358
358
|
"\n",
|
|
359
|
-
"trained_mean = orc.classifier.
|
|
359
|
+
"trained_mean = orc.classifier.train_RCClassifier(\n",
|
|
360
360
|
" classifier_mean,\n",
|
|
361
361
|
" train_seqs=train_seqs,\n",
|
|
362
362
|
" labels=train_labels,\n",
|
{openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/docs/examples/continuous_rc.ipynb
RENAMED
|
@@ -98,18 +98,18 @@
|
|
|
98
98
|
},
|
|
99
99
|
{
|
|
100
100
|
"cell_type": "code",
|
|
101
|
-
"execution_count":
|
|
101
|
+
"execution_count": 4,
|
|
102
102
|
"id": "13d6be2b",
|
|
103
103
|
"metadata": {},
|
|
104
104
|
"outputs": [],
|
|
105
105
|
"source": [
|
|
106
106
|
"esn = orc.forecaster.CESNForecaster(data_dim=U_train.shape[1], res_dim=1000, time_const=40.0)\n",
|
|
107
|
-
"esn, R = orc.forecaster.
|
|
107
|
+
"esn, R = orc.forecaster.train_RCForecaster(model=esn, train_seq=U_train, ts=t_train)"
|
|
108
108
|
]
|
|
109
109
|
},
|
|
110
110
|
{
|
|
111
111
|
"cell_type": "code",
|
|
112
|
-
"execution_count":
|
|
112
|
+
"execution_count": 5,
|
|
113
113
|
"id": "6d3630b8",
|
|
114
114
|
"metadata": {},
|
|
115
115
|
"outputs": [
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
},
|
|
147
147
|
{
|
|
148
148
|
"cell_type": "code",
|
|
149
|
-
"execution_count":
|
|
149
|
+
"execution_count": 6,
|
|
150
150
|
"id": "8e549270",
|
|
151
151
|
"metadata": {},
|
|
152
152
|
"outputs": [],
|
|
@@ -159,7 +159,7 @@
|
|
|
159
159
|
},
|
|
160
160
|
{
|
|
161
161
|
"cell_type": "code",
|
|
162
|
-
"execution_count":
|
|
162
|
+
"execution_count": 7,
|
|
163
163
|
"id": "9aaa840e",
|
|
164
164
|
"metadata": {},
|
|
165
165
|
"outputs": [
|
|
@@ -196,7 +196,7 @@
|
|
|
196
196
|
},
|
|
197
197
|
{
|
|
198
198
|
"cell_type": "code",
|
|
199
|
-
"execution_count":
|
|
199
|
+
"execution_count": 8,
|
|
200
200
|
"id": "ad1c9f18",
|
|
201
201
|
"metadata": {},
|
|
202
202
|
"outputs": [
|
|
@@ -226,7 +226,7 @@
|
|
|
226
226
|
},
|
|
227
227
|
{
|
|
228
228
|
"cell_type": "code",
|
|
229
|
-
"execution_count":
|
|
229
|
+
"execution_count": 9,
|
|
230
230
|
"id": "618df66f",
|
|
231
231
|
"metadata": {},
|
|
232
232
|
"outputs": [
|
|
@@ -190,13 +190,13 @@
|
|
|
190
190
|
},
|
|
191
191
|
{
|
|
192
192
|
"cell_type": "code",
|
|
193
|
-
"execution_count":
|
|
193
|
+
"execution_count": 4,
|
|
194
194
|
"id": "65a44d34",
|
|
195
195
|
"metadata": {},
|
|
196
196
|
"outputs": [],
|
|
197
197
|
"source": [
|
|
198
198
|
"control_model = orc.control.ESNController(data_dim=2, control_dim=1, res_dim=1000)\n",
|
|
199
|
-
"control_model, R = orc.control.
|
|
199
|
+
"control_model, R = orc.control.train_RCController(control_model, outputs_damped[:-1], u[1:])"
|
|
200
200
|
]
|
|
201
201
|
},
|
|
202
202
|
{
|
|
@@ -217,7 +217,7 @@
|
|
|
217
217
|
},
|
|
218
218
|
{
|
|
219
219
|
"cell_type": "code",
|
|
220
|
-
"execution_count":
|
|
220
|
+
"execution_count": 5,
|
|
221
221
|
"id": "28b6b864",
|
|
222
222
|
"metadata": {},
|
|
223
223
|
"outputs": [],
|
|
@@ -257,7 +257,7 @@
|
|
|
257
257
|
},
|
|
258
258
|
{
|
|
259
259
|
"cell_type": "code",
|
|
260
|
-
"execution_count":
|
|
260
|
+
"execution_count": 6,
|
|
261
261
|
"id": "39b5601a",
|
|
262
262
|
"metadata": {},
|
|
263
263
|
"outputs": [],
|
|
@@ -267,7 +267,7 @@
|
|
|
267
267
|
},
|
|
268
268
|
{
|
|
269
269
|
"cell_type": "code",
|
|
270
|
-
"execution_count":
|
|
270
|
+
"execution_count": 7,
|
|
271
271
|
"id": "be2c5103",
|
|
272
272
|
"metadata": {},
|
|
273
273
|
"outputs": [
|
|
@@ -143,7 +143,7 @@
|
|
|
143
143
|
"# init + train ESN\n",
|
|
144
144
|
"NR = 1000\n",
|
|
145
145
|
"esn = orc.forecaster.ESNForecaster(data_dim=3, res_dim=NR, seed=0)\n",
|
|
146
|
-
"esn, R = orc.forecaster.
|
|
146
|
+
"esn, R = orc.forecaster.train_RCForecaster(esn, U_train)"
|
|
147
147
|
]
|
|
148
148
|
},
|
|
149
149
|
{
|
{openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0/docs}/examples/rc_background.ipynb
RENAMED
|
@@ -163,14 +163,14 @@
|
|
|
163
163
|
"class Readout(orc.readouts.ReadoutBase):\n",
|
|
164
164
|
" res_dim: int\n",
|
|
165
165
|
" out_dim: int\n",
|
|
166
|
-
"
|
|
166
|
+
" wout: jnp.ndarray\n",
|
|
167
167
|
" \n",
|
|
168
168
|
" def __init__(self, out_dim, res_dim):\n",
|
|
169
169
|
" super().__init__(out_dim, res_dim)\n",
|
|
170
|
-
" self.
|
|
170
|
+
" self.wout = jnp.zeros((out_dim, res_dim))\n",
|
|
171
171
|
" \n",
|
|
172
172
|
" def readout(self, res_state):\n",
|
|
173
|
-
" return self.
|
|
173
|
+
" return self.wout @ res_state"
|
|
174
174
|
]
|
|
175
175
|
},
|
|
176
176
|
{
|
|
@@ -299,7 +299,7 @@
|
|
|
299
299
|
"# set transient to discard\n",
|
|
300
300
|
"spinup = 200\n",
|
|
301
301
|
"\n",
|
|
302
|
-
"# learn
|
|
302
|
+
"# learn wout\n",
|
|
303
303
|
"readout_mat = ridge_regression(forced_seq[spinup:], target_seq[spinup:], beta=1e-7)"
|
|
304
304
|
]
|
|
305
305
|
},
|
|
@@ -318,10 +318,20 @@
|
|
|
318
318
|
"source": [
|
|
319
319
|
"# define where in the forecaster model we need to update\n",
|
|
320
320
|
"def where(model: Forecaster):\n",
|
|
321
|
-
" return model.readout.
|
|
321
|
+
" return model.readout.wout\n",
|
|
322
322
|
"model = eqx.tree_at(where, model, readout_mat)"
|
|
323
323
|
]
|
|
324
324
|
},
|
|
325
|
+
{
|
|
326
|
+
"cell_type": "code",
|
|
327
|
+
"execution_count": 10,
|
|
328
|
+
"metadata": {},
|
|
329
|
+
"outputs": [],
|
|
330
|
+
"source": [
|
|
331
|
+
"# Alternatively\n",
|
|
332
|
+
"model, forced_seq = orc.forecaster.train_RCForecaster(model, train_seq=U_train, spinup=spinup, beta=1e-7)"
|
|
333
|
+
]
|
|
334
|
+
},
|
|
325
335
|
{
|
|
326
336
|
"cell_type": "markdown",
|
|
327
337
|
"metadata": {},
|
|
@@ -331,7 +341,7 @@
|
|
|
331
341
|
},
|
|
332
342
|
{
|
|
333
343
|
"cell_type": "code",
|
|
334
|
-
"execution_count":
|
|
344
|
+
"execution_count": 11,
|
|
335
345
|
"metadata": {},
|
|
336
346
|
"outputs": [
|
|
337
347
|
{
|
|
@@ -12,12 +12,16 @@ The `DriverBase` class defines the core interface that all driver implementation
|
|
|
12
12
|
|
|
13
13
|
### Key Attributes
|
|
14
14
|
- `res_dim`: Reservoir dimension
|
|
15
|
+
- `chunks`: Number of parallel reservoirs (default `0`, meaning no chunks dimension)
|
|
15
16
|
- `dtype`: JAX array dtype (jnp.float32 or jnp.float64)
|
|
16
17
|
|
|
17
18
|
### Core Methods
|
|
18
19
|
- `advance(proj_vars, res_state)`: Advance single reservoir state by one time step
|
|
19
20
|
- `batch_advance(proj_vars, res_state)`: Advance batch of reservoir states by one time step
|
|
20
21
|
- `__call__(proj_vars, res_state)`: Flexible interface supporting both single and batch updates
|
|
22
|
+
- `default_state()`: Create a zero initial reservoir state with the appropriate shape —
|
|
23
|
+
`(chunks, res_dim)` when `chunks > 0`, or `(res_dim,)` for single-reservoir drivers.
|
|
24
|
+
Used by the unified training functions when no `initial_res_state` is provided.
|
|
21
25
|
|
|
22
26
|
## ParallelESNDriver
|
|
23
27
|
|
|
@@ -142,6 +146,11 @@ class CustomDriver(DriverBase):
|
|
|
142
146
|
### Requirements
|
|
143
147
|
- Inherit from `DriverBase`
|
|
144
148
|
- Implement the abstract `advance()` method
|
|
149
|
+
- Override `default_state()` if your driver uses a non-standard state shape (e.g., a single
|
|
150
|
+
reservoir driver should return `jnp.zeros((res_dim,), dtype=self.dtype)`). The base class
|
|
151
|
+
implementation returns `(chunks, res_dim)` when `chunks > 0` and `(res_dim,)` otherwise.
|
|
152
|
+
The unified training functions (`train_RCForecaster`, etc.) call this method to construct
|
|
153
|
+
the initial reservoir state when none is provided by the caller.
|
|
145
154
|
- Choose your parallel reservoir support level:
|
|
146
155
|
|
|
147
156
|
#### Single Reservoir Only
|
|
@@ -176,9 +176,116 @@ model = CESNForecaster(
|
|
|
176
176
|
)
|
|
177
177
|
```
|
|
178
178
|
|
|
179
|
+
## ESN Controller
|
|
180
|
+
|
|
181
|
+
The `ESNController` implements an Echo State Network for control tasks, where the model tracks a reference trajectory by optimizing a control input sequence.
|
|
182
|
+
|
|
183
|
+
### Basic Usage
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
from orc.control import ESNController, train_ESNController
|
|
187
|
+
import jax.numpy as jnp
|
|
188
|
+
|
|
189
|
+
# Create ESN controller
|
|
190
|
+
model = ESNController(
|
|
191
|
+
data_dim=3, # System input/output dimension
|
|
192
|
+
control_dim=1, # Control input dimension
|
|
193
|
+
res_dim=500, # Reservoir dimension
|
|
194
|
+
seed=42
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
# Train with input and control sequences
|
|
198
|
+
trained_model, res_states = train_ESNController(
|
|
199
|
+
model,
|
|
200
|
+
train_seq, # shape: (seq_len, data_dim)
|
|
201
|
+
control_seq, # shape: (seq_len, control_dim)
|
|
202
|
+
target_seq=target_seq,
|
|
203
|
+
spinup=100,
|
|
204
|
+
beta=8e-8
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
# Compute optimal control to track a reference trajectory
|
|
208
|
+
control_opt = trained_model.compute_control(
|
|
209
|
+
control_seq=initial_guess, # shape: (fcast_len, control_dim)
|
|
210
|
+
res_state=res_states[-1],
|
|
211
|
+
ref_traj=reference # shape: (fcast_len, data_dim)
|
|
212
|
+
)
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Control Penalty Weights
|
|
216
|
+
|
|
217
|
+
The controller optimizes a penalty function with three terms, each weighted by a tunable parameter:
|
|
218
|
+
|
|
219
|
+
- `alpha_1` (default 100): **Trajectory deviation** — penalizes squared error between the controlled forecast and the reference trajectory. Higher values enforce tighter tracking.
|
|
220
|
+
|
|
221
|
+
- `alpha_2` (default 1): **Control magnitude** — penalizes the squared norm of control inputs. Higher values favor smaller control effort.
|
|
222
|
+
|
|
223
|
+
- `alpha_3` (default 5): **Control smoothness** — penalizes the squared norm of consecutive control input differences. Higher values produce smoother control signals.
|
|
224
|
+
|
|
225
|
+
```python
|
|
226
|
+
# Custom penalty weights
|
|
227
|
+
model = ESNController(
|
|
228
|
+
data_dim=3,
|
|
229
|
+
control_dim=1,
|
|
230
|
+
res_dim=500,
|
|
231
|
+
alpha_1=200, # Stricter trajectory tracking
|
|
232
|
+
alpha_2=0.5, # Allow larger control inputs
|
|
233
|
+
alpha_3=10, # Enforce smoother control
|
|
234
|
+
seed=42
|
|
235
|
+
)
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Key Parameters
|
|
239
|
+
|
|
240
|
+
In addition to the standard ESN parameters (`leak_rate`, `bias`, `embedding_scaling`, `Wr_density`, `Wr_spectral_radius`), the controller accepts:
|
|
241
|
+
|
|
242
|
+
- `control_dim`: Dimension of the control input
|
|
243
|
+
- `alpha_1`, `alpha_2`, `alpha_3`: Control penalty weights (see above)
|
|
244
|
+
|
|
245
|
+
For detailed API documentation, see the [Control API Reference](../api/control.md).
|
|
246
|
+
|
|
179
247
|
## Training Functions
|
|
180
248
|
|
|
181
|
-
|
|
249
|
+
All models use ridge regression for training the readout layer. ORC provides unified training functions that work with any model inheriting from the base classes, as well as convenience wrappers for each specific model type.
|
|
250
|
+
|
|
251
|
+
### Unified Training Functions (Recommended)
|
|
252
|
+
|
|
253
|
+
The primary training API uses generic functions that work with any `RCForecasterBase`, `RCClassifierBase`, or `RCControllerBase` subclass, including custom models:
|
|
254
|
+
|
|
255
|
+
```python
|
|
256
|
+
from orc.forecaster import train_RCForecaster
|
|
257
|
+
from orc.classifier import train_RCClassifier
|
|
258
|
+
from orc.control import train_RCController
|
|
259
|
+
|
|
260
|
+
# Forecaster: works with ESNForecaster, CESNForecaster, EnsembleESNForecaster,
|
|
261
|
+
# and any custom RCForecasterBase subclass
|
|
262
|
+
trained_model, res_states = train_RCForecaster(model, train_seq, target_seq=target_seq)
|
|
263
|
+
|
|
264
|
+
# Classifier: works with ESNClassifier and custom RCClassifierBase subclasses
|
|
265
|
+
trained_model = train_RCClassifier(model, train_seqs, labels)
|
|
266
|
+
|
|
267
|
+
# Controller: works with ESNController and custom RCControllerBase subclasses
|
|
268
|
+
trained_model, res_states = train_RCController(model, train_seq, control_seq)
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
For continuous-time models, pass the time vector via `**force_kwargs`:
|
|
272
|
+
|
|
273
|
+
```python
|
|
274
|
+
# CESNForecaster via the unified function
|
|
275
|
+
trained_model, res_states = train_RCForecaster(
|
|
276
|
+
model, train_seq, target_seq=target_seq, ts=t_train
|
|
277
|
+
)
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Model-Specific Convenience Functions
|
|
281
|
+
|
|
282
|
+
The legacy model-specific functions remain available and delegate to the unified functions above:
|
|
283
|
+
|
|
284
|
+
- `train_ESNForecaster` — equivalent to `train_RCForecaster` with an `ESNForecaster` type check
|
|
285
|
+
- `train_CESNForecaster` — equivalent to `train_RCForecaster(..., ts=t_train)` with a `CESNForecaster` type check
|
|
286
|
+
- `train_EnsembleESNForecaster` — equivalent to `train_RCForecaster` with an `EnsembleESNForecaster` type check
|
|
287
|
+
- `train_ESNClassifier` — equivalent to `train_RCClassifier` with an `ESNClassifier` type check
|
|
288
|
+
- `train_ESNController` — equivalent to `train_RCController` with an `ESNController` type check
|
|
182
289
|
|
|
183
290
|
### Training Parameters
|
|
184
291
|
|
|
@@ -187,19 +294,22 @@ Both ESN models use ridge regression for training the readout layer.
|
|
|
187
294
|
|
|
188
295
|
- `beta`: Tikhonov regularization parameter (typically 1e-8 to 1e-6)
|
|
189
296
|
|
|
190
|
-
- `initial_res_state`: Custom initial reservoir state (default:
|
|
297
|
+
- `initial_res_state`: Custom initial reservoir state (default: uses `model.driver.default_state()`)
|
|
191
298
|
|
|
192
299
|
**Memory Management:**
|
|
193
|
-
- `batch_size`: Process parallel reservoirs in batches to reduce memory usage
|
|
300
|
+
- `batch_size`: Process parallel reservoirs in batches to reduce memory usage (available for all three unified functions)
|
|
301
|
+
|
|
302
|
+
**Extra Force Arguments:**
|
|
303
|
+
- `**force_kwargs`: Additional keyword arguments forwarded to `model.force()` (e.g., `ts=t_train` for continuous models)
|
|
194
304
|
|
|
195
305
|
### Advanced Training
|
|
196
306
|
|
|
197
307
|
```python
|
|
198
308
|
# Batched training for memory efficiency with many parallel reservoirs
|
|
199
|
-
trained_model, res_states =
|
|
309
|
+
trained_model, res_states = train_RCForecaster(
|
|
200
310
|
model,
|
|
201
311
|
train_seq,
|
|
202
|
-
target_seq,
|
|
312
|
+
target_seq=target_seq,
|
|
203
313
|
spinup=100,
|
|
204
314
|
beta=1e-7,
|
|
205
315
|
batch_size=10 # Process 10 parallel reservoirs at a time
|
|
@@ -249,9 +359,9 @@ The models module demonstrates the power of ORC's modular design:
|
|
|
249
359
|
To create your own model, follow the ESN pattern:
|
|
250
360
|
|
|
251
361
|
```python
|
|
252
|
-
from orc.
|
|
362
|
+
from orc.forecaster import RCForecasterBase, train_RCForecaster
|
|
253
363
|
from orc.drivers import CustomDriver
|
|
254
|
-
from orc.embeddings import CustomEmbedding
|
|
364
|
+
from orc.embeddings import CustomEmbedding
|
|
255
365
|
from orc.readouts import CustomReadout
|
|
256
366
|
|
|
257
367
|
class CustomForecaster(RCForecasterBase):
|
|
@@ -260,11 +370,22 @@ class CustomForecaster(RCForecasterBase):
|
|
|
260
370
|
driver = CustomDriver(res_dim=res_dim, **kwargs)
|
|
261
371
|
embedding = CustomEmbedding(in_dim=data_dim, res_dim=res_dim, **kwargs)
|
|
262
372
|
readout = CustomReadout(out_dim=data_dim, res_dim=res_dim, **kwargs)
|
|
263
|
-
|
|
373
|
+
|
|
264
374
|
# Initialize base class
|
|
265
375
|
super().__init__(driver, readout, embedding, **kwargs)
|
|
376
|
+
|
|
377
|
+
# Train using the unified function — no model-specific training code needed
|
|
378
|
+
trained_model, res_states = train_RCForecaster(
|
|
379
|
+
CustomForecaster(data_dim=3, res_dim=500),
|
|
380
|
+
train_seq,
|
|
381
|
+
target_seq=target_seq,
|
|
382
|
+
spinup=100,
|
|
383
|
+
beta=8e-8,
|
|
384
|
+
)
|
|
266
385
|
```
|
|
267
386
|
|
|
387
|
+
The unified `train_RCForecaster` function delegates shape handling to the readout's `prepare_train`, `prepare_target`, and `set_wout` methods and the driver's `default_state` method, so custom components that implement those methods integrate automatically with training. See the [Readouts](readouts.md) and [Drivers](drivers.md) user guides for details.
|
|
388
|
+
|
|
268
389
|
## Performance Considerations
|
|
269
390
|
|
|
270
391
|
- Use `jnp.float64` for numerical precision (default)
|
|
@@ -13,13 +13,26 @@ The `ReadoutBase` class defines the core interface that all readout implementati
|
|
|
13
13
|
### Key Attributes
|
|
14
14
|
- `out_dim`: Output dimension
|
|
15
15
|
- `res_dim`: Reservoir dimension
|
|
16
|
+
- `chunks`: Number of parallel reservoirs (default `0`, meaning no chunks dimension)
|
|
16
17
|
- `dtype`: JAX array dtype (jnp.float32 or jnp.float64)
|
|
17
18
|
|
|
18
19
|
### Core Methods
|
|
20
|
+
|
|
21
|
+
**Inference:**
|
|
19
22
|
- `readout(res_state)`: Map a single reservoir state to output
|
|
20
|
-
- `batch_readout(res_state)`: Map multiple reservoir states to outputs efficiently
|
|
23
|
+
- `batch_readout(res_state)`: Map multiple reservoir states to outputs efficiently
|
|
21
24
|
- `__call__(res_state)`: Flexible interface supporting both single and batch inputs
|
|
22
25
|
|
|
26
|
+
**Training interface** (used by `train_RCForecaster`, `train_RCClassifier`, `train_RCController`):
|
|
27
|
+
- `prepare_train(res_seq)`: Prepare reservoir states for ridge regression. Default: identity
|
|
28
|
+
(returns `res_seq` unchanged). Override to apply nonlinear transforms or reshape for
|
|
29
|
+
chunk structure.
|
|
30
|
+
- `prepare_target(target_seq)`: Prepare target sequence for ridge regression. Default:
|
|
31
|
+
identity. Override to reshape for chunk structure (e.g., adding or repeating the chunks axis).
|
|
32
|
+
- `set_wout(cmat)`: Return a **new** readout instance with the updated weight matrix `cmat`
|
|
33
|
+
stored in `wout`. Override if your readout uses a different attribute name for the output
|
|
34
|
+
weights.
|
|
35
|
+
|
|
23
36
|
## ParallelLinearReadout Example
|
|
24
37
|
|
|
25
38
|
The `ParallelLinearReadout` class demonstrates a standard linear transformation from reservoir states to outputs with support for parallel reservoirs.
|
|
@@ -72,7 +85,7 @@ The readout weights (`wout`) are initialized to zero and trained externally usin
|
|
|
72
85
|
|
|
73
86
|
## Custom Readouts
|
|
74
87
|
|
|
75
|
-
The primary purpose of the readout system is to enable you to create your own readout layers tailored to your specific needs. While RC architectures often are trained via regression, this also
|
|
88
|
+
The primary purpose of the readout system is to enable you to create your own readout layers tailored to your specific needs. While RC architectures often are trained via regression, this also provides more flexibility for more complicated readout architectures and training protocols.
|
|
76
89
|
|
|
77
90
|
```python
|
|
78
91
|
from orc.readouts import ReadoutBase
|
|
@@ -80,26 +93,39 @@ import equinox as eqx
|
|
|
80
93
|
import jax.numpy as jnp
|
|
81
94
|
|
|
82
95
|
class CustomReadout(ReadoutBase):
|
|
83
|
-
# Define your parameters
|
|
96
|
+
# Define your parameters — `chunks` is inherited from ReadoutBase
|
|
84
97
|
wout: Array
|
|
85
|
-
|
|
86
|
-
|
|
98
|
+
|
|
87
99
|
def __init__(self, out_dim, res_dim, chunks=1, **kwargs):
|
|
88
|
-
super().__init__(out_dim, res_dim)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
100
|
+
super().__init__(out_dim, res_dim, chunks=chunks)
|
|
101
|
+
# Initialize weights
|
|
102
|
+
self.wout = jnp.zeros((chunks, int(out_dim / chunks), res_dim))
|
|
103
|
+
|
|
93
104
|
def readout(self, res_state):
|
|
94
105
|
# Implement your custom readout logic
|
|
95
|
-
# Apply transformations, nonlinearities, etc.
|
|
96
106
|
transformed_state = your_transformation(res_state)
|
|
97
107
|
return jnp.ravel(eqx.filter_vmap(jnp.matmul)(self.wout, transformed_state))
|
|
108
|
+
|
|
109
|
+
# Training interface — override to integrate with train_RCForecaster etc.
|
|
110
|
+
def prepare_train(self, res_seq):
|
|
111
|
+
# Apply any custom transform and/or reshape for chunk structure
|
|
112
|
+
return your_transformation(res_seq) # shape: (seq_len, chunks, res_dim)
|
|
113
|
+
|
|
114
|
+
def prepare_target(self, target_seq):
|
|
115
|
+
# Reshape target to match chunks structure expected by ridge regression
|
|
116
|
+
return target_seq.reshape(target_seq.shape[0], self.chunks, -1)
|
|
117
|
+
|
|
118
|
+
# set_wout is inherited and works as long as the weight attribute is named `wout`
|
|
98
119
|
```
|
|
99
120
|
|
|
100
121
|
### Requirements for Custom Readouts
|
|
101
122
|
- Inherit from `ReadoutBase`
|
|
102
123
|
- Implement the abstract `readout()` method
|
|
124
|
+
- Do **not** redefine `chunks` as a class attribute — it is inherited from `ReadoutBase`
|
|
125
|
+
- Override `prepare_train`, `prepare_target`, and/or `set_wout` to integrate with the
|
|
126
|
+
unified training functions (`train_RCForecaster`, `train_RCClassifier`,
|
|
127
|
+
`train_RCController`). The base class defaults (identity transforms) are sufficient
|
|
128
|
+
for simple single-reservoir readouts with a `wout` attribute.
|
|
103
129
|
- Choose your parallel reservoir support level:
|
|
104
130
|
|
|
105
131
|
#### Single Reservoir Only
|
|
@@ -137,10 +163,19 @@ def __call__(self, res_state):
|
|
|
137
163
|
## Design Considerations
|
|
138
164
|
|
|
139
165
|
### Training Integration
|
|
140
|
-
- Readout weights are learned separately via ridge regression (see training utilities)
|
|
141
|
-
- The readout layer structure determines the feature space for regression
|
|
142
|
-
- More complex readouts can capture richer output relationships but may require more training data or different training procedures.
|
|
143
166
|
|
|
167
|
+
The unified training functions (`train_RCForecaster`, `train_RCClassifier`,
|
|
168
|
+
`train_RCController`) interact with readout layers entirely through the training interface:
|
|
169
|
+
|
|
170
|
+
1. `prepare_train(res_seq)` — called to transform/reshape reservoir states before ridge
|
|
171
|
+
regression
|
|
172
|
+
2. `prepare_target(target_seq)` — called to reshape targets to match the expected ridge
|
|
173
|
+
regression input
|
|
174
|
+
3. `set_wout(cmat)` — called after solving regression to install the learned weights
|
|
175
|
+
|
|
176
|
+
Custom readouts that override these three methods integrate automatically with training
|
|
177
|
+
without any changes to the training code. Readouts whose `chunks > 0` receive the batched
|
|
178
|
+
ridge regression path; readouts with `chunks == 0` use the standard scalar ridge regression.
|
|
144
179
|
|
|
145
180
|
### Integration with RC Models
|
|
146
181
|
- Readout layers receive reservoir states from drivers
|
{openreservoircomputing-0.1.3a0 → openreservoircomputing-0.2.0}/examples/classification.ipynb
RENAMED
|
@@ -207,7 +207,7 @@
|
|
|
207
207
|
}
|
|
208
208
|
],
|
|
209
209
|
"source": [
|
|
210
|
-
"trained_classifier = orc.classifier.
|
|
210
|
+
"trained_classifier = orc.classifier.train_RCClassifier(\n",
|
|
211
211
|
" classifier,\n",
|
|
212
212
|
" train_seqs=train_seqs,\n",
|
|
213
213
|
" labels=train_labels,\n",
|
|
@@ -245,7 +245,7 @@
|
|
|
245
245
|
"probs = jax.vmap(trained_classifier.classify)(train_seqs)\n",
|
|
246
246
|
"\n",
|
|
247
247
|
"\n",
|
|
248
|
-
"train_preds = jnp.
|
|
248
|
+
"train_preds = jnp.argmax(probs, axis=1)\n",
|
|
249
249
|
"train_acc = jnp.mean(train_preds == train_labels)\n",
|
|
250
250
|
"print(f\"Training accuracy: {train_acc:.1%}\")"
|
|
251
251
|
]
|
|
@@ -277,7 +277,7 @@
|
|
|
277
277
|
"source": [
|
|
278
278
|
"probs = jax.vmap(trained_classifier.classify)(test_seqs)\n",
|
|
279
279
|
"\n",
|
|
280
|
-
"test_preds = jnp.
|
|
280
|
+
"test_preds = jnp.argmax(probs, axis=1)\n",
|
|
281
281
|
"test_acc = jnp.mean(test_preds == test_labels)\n",
|
|
282
282
|
"print(f\"Test accuracy: {test_acc:.1%}\")"
|
|
283
283
|
]
|
|
@@ -356,7 +356,7 @@
|
|
|
356
356
|
" state_repr=\"mean\",\n",
|
|
357
357
|
")\n",
|
|
358
358
|
"\n",
|
|
359
|
-
"trained_mean = orc.classifier.
|
|
359
|
+
"trained_mean = orc.classifier.train_RCClassifier(\n",
|
|
360
360
|
" classifier_mean,\n",
|
|
361
361
|
" train_seqs=train_seqs,\n",
|
|
362
362
|
" labels=train_labels,\n",
|