esnfed 1.0.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.
- esnfed-1.0.0/.gitignore +56 -0
- esnfed-1.0.0/LICENSE +21 -0
- esnfed-1.0.0/PKG-INFO +187 -0
- esnfed-1.0.0/README.md +146 -0
- esnfed-1.0.0/esnfed/__init__.py +31 -0
- esnfed-1.0.0/esnfed/data/ted_spread.csv +8854 -0
- esnfed-1.0.0/esnfed/datasets.py +270 -0
- esnfed-1.0.0/esnfed/esn.py +195 -0
- esnfed-1.0.0/esnfed/federated.py +296 -0
- esnfed-1.0.0/esnfed/interop.py +109 -0
- esnfed-1.0.0/esnfed/metrics.py +38 -0
- esnfed-1.0.0/esnfed/py.typed +0 -0
- esnfed-1.0.0/esnfed/topologies.py +132 -0
- esnfed-1.0.0/pyproject.toml +93 -0
- esnfed-1.0.0/tests/test_datasets.py +103 -0
- esnfed-1.0.0/tests/test_esn.py +72 -0
- esnfed-1.0.0/tests/test_federated.py +117 -0
- esnfed-1.0.0/tests/test_flower.py +31 -0
- esnfed-1.0.0/tests/test_interop.py +51 -0
- esnfed-1.0.0/tests/test_topologies.py +58 -0
esnfed-1.0.0/.gitignore
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# LaTeX build artifacts
|
|
2
|
+
*.aux
|
|
3
|
+
*.bbl
|
|
4
|
+
*.bcf
|
|
5
|
+
*.blg
|
|
6
|
+
*.fdb_latexmk
|
|
7
|
+
*.fls
|
|
8
|
+
*.log
|
|
9
|
+
*.out
|
|
10
|
+
*.run.xml
|
|
11
|
+
*.synctex.gz
|
|
12
|
+
*.toc
|
|
13
|
+
*.lof
|
|
14
|
+
*.lot
|
|
15
|
+
*.nav
|
|
16
|
+
*.snm
|
|
17
|
+
*.vrb
|
|
18
|
+
memoria/memoria.pdf
|
|
19
|
+
|
|
20
|
+
# Python
|
|
21
|
+
__pycache__/
|
|
22
|
+
*.py[cod]
|
|
23
|
+
*.pyo
|
|
24
|
+
.venv/
|
|
25
|
+
venv/
|
|
26
|
+
env/
|
|
27
|
+
*.egg-info/
|
|
28
|
+
dist/
|
|
29
|
+
build/
|
|
30
|
+
.ipynb_checkpoints/
|
|
31
|
+
*.pyc
|
|
32
|
+
.pytest_cache/
|
|
33
|
+
|
|
34
|
+
# Data (may be large/licensed)
|
|
35
|
+
datos/crudos/
|
|
36
|
+
datos/procesados/
|
|
37
|
+
!datos/crudos/.gitkeep
|
|
38
|
+
!datos/procesados/.gitkeep
|
|
39
|
+
|
|
40
|
+
# Generated outputs
|
|
41
|
+
salidas/
|
|
42
|
+
!salidas/.gitkeep
|
|
43
|
+
|
|
44
|
+
# OS
|
|
45
|
+
.DS_Store
|
|
46
|
+
Thumbs.db
|
|
47
|
+
desktop.ini
|
|
48
|
+
|
|
49
|
+
# Editors
|
|
50
|
+
.vscode/
|
|
51
|
+
.idea/
|
|
52
|
+
*.swp
|
|
53
|
+
*.swo
|
|
54
|
+
|
|
55
|
+
# Claude Code
|
|
56
|
+
.claude/
|
esnfed-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dairon Andres Benites Aldaz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
esnfed-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: esnfed
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Echo State Networks for Federated Learning: reservoirs, topologies and federated strategies
|
|
5
|
+
Project-URL: Homepage, https://github.com/daibeal/tfg-inf
|
|
6
|
+
Project-URL: Repository, https://github.com/daibeal/tfg-inf
|
|
7
|
+
Project-URL: Issues, https://github.com/daibeal/tfg-inf/issues
|
|
8
|
+
Author-email: Dairon Andres Benites Aldaz <dairon.aldaz@gmail.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: echo state networks,ensemble learning,federated learning,machine learning,recurrent neural networks,reservoir computing,time series
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.9
|
|
25
|
+
Requires-Dist: networkx>=3.0
|
|
26
|
+
Requires-Dist: numpy>=1.21
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: build>=1.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: twine>=4.0; extra == 'dev'
|
|
31
|
+
Provides-Extra: experiments
|
|
32
|
+
Requires-Dist: matplotlib>=3.5; extra == 'experiments'
|
|
33
|
+
Requires-Dist: pandas>=1.3; extra == 'experiments'
|
|
34
|
+
Requires-Dist: scikit-learn>=1.0; extra == 'experiments'
|
|
35
|
+
Requires-Dist: scipy>=1.7; extra == 'experiments'
|
|
36
|
+
Provides-Extra: flower
|
|
37
|
+
Requires-Dist: flwr>=1.7; extra == 'flower'
|
|
38
|
+
Provides-Extra: reservoirpy
|
|
39
|
+
Requires-Dist: reservoirpy>=0.3; extra == 'reservoirpy'
|
|
40
|
+
Description-Content-Type: text/markdown
|
|
41
|
+
|
|
42
|
+
# esnfed — a federated reservoir computing toolkit
|
|
43
|
+
|
|
44
|
+
`esnfed` is a small, dependency-light Python library for training **Echo State
|
|
45
|
+
Networks** (reservoir computing) in a **federated** setting — where several
|
|
46
|
+
parties jointly train a model without sharing their raw data. It accompanies the
|
|
47
|
+
Final Degree Project *Ensemble of Recurrent Networks for Federated Learning*
|
|
48
|
+
(ETSINF, Universitat Politècnica de València).
|
|
49
|
+
|
|
50
|
+
The core library depends only on **NumPy** and **NetworkX**.
|
|
51
|
+
|
|
52
|
+
> **Why this and not ReservoirPy?** [ReservoirPy](https://reservoirpy.readthedocs.io)
|
|
53
|
+
> is the mature, full-featured library for *building and tuning* reservoir
|
|
54
|
+
> computing models, and `esnfed` does **not** try to replace it. `esnfed`
|
|
55
|
+
> focuses on the part ReservoirPy does not cover: **federating** reservoir
|
|
56
|
+
> models across parties. You can design a reservoir in ReservoirPy and federate
|
|
57
|
+
> it here in one line (see *Interoperability* below).
|
|
58
|
+
|
|
59
|
+
## Features
|
|
60
|
+
|
|
61
|
+
- **Echo State Network** with leaky-integrator neurons and a closed-form ridge
|
|
62
|
+
readout (`EchoStateNetwork`).
|
|
63
|
+
- **Federated strategies**:
|
|
64
|
+
- `federated_ridge` — *exact* federated training for a shared reservoir
|
|
65
|
+
(clients exchange only ridge sufficient statistics; provably equal to pooled
|
|
66
|
+
training, in one communication round);
|
|
67
|
+
- `fedavg` — iterative FedAvg on the readout;
|
|
68
|
+
- `ensemble_predict` — prediction ensemble for *heterogeneous* reservoirs;
|
|
69
|
+
- `structural_alignment` — interpolate reservoirs toward a shared structure.
|
|
70
|
+
- **Reservoir topologies**: Erdős–Rényi, small-world, scale-free, ring.
|
|
71
|
+
- **Data**: synthetic benchmarks (NARMA-10, Mackey-Glass, Lorenz) **and** real
|
|
72
|
+
data — a bundled counterparty-risk series (the TED spread) plus generic
|
|
73
|
+
loaders (`from_array`, `load_csv`, `load_fred`).
|
|
74
|
+
- **Interoperability**: adapters for [ReservoirPy](https://reservoirpy.readthedocs.io)
|
|
75
|
+
reservoirs and an example integration with the
|
|
76
|
+
[Flower](https://flower.ai) federated-learning framework.
|
|
77
|
+
|
|
78
|
+
## Installation
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
pip install esnfed # core (numpy + networkx)
|
|
82
|
+
pip install "esnfed[experiments]" # + matplotlib/pandas/scipy/scikit-learn
|
|
83
|
+
pip install "esnfed[reservoirpy]" # + ReservoirPy interop
|
|
84
|
+
pip install "esnfed[flower]" # + Flower integration
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Quick start
|
|
88
|
+
|
|
89
|
+
### Federated counterparty-risk forecasting (real data)
|
|
90
|
+
|
|
91
|
+
Several institutions jointly forecast the **TED spread** (a classic gauge of
|
|
92
|
+
interbank/counterparty credit risk) without sharing their data. Exact federated
|
|
93
|
+
ridge equals pooled training in a single round:
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
from esnfed import datasets, federated, topologies, metrics
|
|
97
|
+
|
|
98
|
+
u, y = datasets.load_ted_spread() # bundled real series (FRED)
|
|
99
|
+
u_tr, y_tr, u_te, y_te = datasets.split(u, y, 0.7)
|
|
100
|
+
parts = datasets.partition_iid(u_tr, y_tr, n_clients=8) # 8 "institutions"
|
|
101
|
+
|
|
102
|
+
W = topologies.random_reservoir(200, density=0.1, rng=0)
|
|
103
|
+
esn_kw = dict(spectral_radius=0.9, leaking_rate=0.5, washout=100, ridge=1e-6)
|
|
104
|
+
clients, ref = federated.make_shared_clients(W, parts, input_seed=0, esn_kwargs=esn_kw)
|
|
105
|
+
|
|
106
|
+
W_out = federated.federated_ridge(clients, ref) # one round, exact, private
|
|
107
|
+
Z_test = ref.harvest(u_te)[ref.washout:]
|
|
108
|
+
print("federated NRMSE:", metrics.nrmse(y_te[ref.washout:], Z_test @ W_out))
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Need another series? `datasets.load_fred("BAMLH0A0HYM2")` pulls a high-yield
|
|
112
|
+
credit spread from FRED; `datasets.from_array(my_series)` or
|
|
113
|
+
`datasets.load_csv("my.csv")` turn any series into a forecasting task.
|
|
114
|
+
|
|
115
|
+
### Train a single ESN
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
import numpy as np
|
|
119
|
+
from esnfed import EchoStateNetwork, datasets, topologies, metrics
|
|
120
|
+
|
|
121
|
+
u, y = datasets.narma10(3000, rng=0)
|
|
122
|
+
u_tr, y_tr, u_te, y_te = datasets.split(u, y)
|
|
123
|
+
W = topologies.random_reservoir(200, density=0.1, rng=0)
|
|
124
|
+
esn = EchoStateNetwork(1, 1, W, spectral_radius=0.9, washout=100).fit(u_tr, y_tr)
|
|
125
|
+
print("NRMSE:", metrics.nrmse(y_te[100:], esn.predict(u_te)[100:]))
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Interoperability
|
|
129
|
+
|
|
130
|
+
### ReservoirPy — design there, federate here
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
from reservoirpy.nodes import Reservoir
|
|
134
|
+
from esnfed import interop, datasets, federated
|
|
135
|
+
|
|
136
|
+
res = Reservoir(200, sr=0.9, lr=0.5, input_dim=1) # design/tune in ReservoirPy
|
|
137
|
+
esn = interop.to_esn(res, n_inputs=1) # -> esnfed EchoStateNetwork
|
|
138
|
+
W = interop.reservoir_matrix(res) # ... then federate it
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Flower — a real FL framework
|
|
142
|
+
|
|
143
|
+
`examples/flower_federated_ridge.py` shows the exact federated-ridge scheme as a
|
|
144
|
+
Flower `NumPyClient` + custom `Strategy`: each client's `fit` returns its ridge
|
|
145
|
+
sufficient statistics and the server sums them and solves once. The Flower-routed
|
|
146
|
+
result is identical to `federated_ridge` to numerical precision.
|
|
147
|
+
|
|
148
|
+
## Modules
|
|
149
|
+
|
|
150
|
+
| Module | Contents |
|
|
151
|
+
|--------|----------|
|
|
152
|
+
| `esnfed.esn` | `EchoStateNetwork`, ridge helpers |
|
|
153
|
+
| `esnfed.topologies` | reservoir generators + `graph_metrics` |
|
|
154
|
+
| `esnfed.datasets` | NARMA-10, Mackey-Glass, Lorenz; `from_array`, `load_csv`, `load_ted_spread`, `load_fred` |
|
|
155
|
+
| `esnfed.metrics` | `nrmse`, `rmse`, `mse`, `r2_score` |
|
|
156
|
+
| `esnfed.federated` | `Client`, `federated_ridge`, `fedavg`, `ensemble_predict`, `structural_alignment` |
|
|
157
|
+
| `esnfed.interop` | ReservoirPy adapters (`to_esn`, `reservoir_matrix`) |
|
|
158
|
+
|
|
159
|
+
## Reproducing the research experiments
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
pip install -e ".[experiments,reservoirpy,flower]"
|
|
163
|
+
python -m pytest # 37 tests
|
|
164
|
+
python experiments/run_all.py # synthetic-benchmark figures and tables
|
|
165
|
+
python experiments/exp6_finance.py # federated counterparty-risk (TED spread)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Data attribution
|
|
169
|
+
|
|
170
|
+
The bundled TED spread is sourced from the Federal Reserve Bank of St. Louis
|
|
171
|
+
(FRED, series `TEDRATE`) and is used for demonstration under FRED's terms.
|
|
172
|
+
|
|
173
|
+
## Citation
|
|
174
|
+
|
|
175
|
+
```bibtex
|
|
176
|
+
@thesis{benites2026esnfed,
|
|
177
|
+
author = {Benites Aldaz, Dairon Andres},
|
|
178
|
+
title = {Ensemble of Recurrent Networks for Federated Learning},
|
|
179
|
+
school = {Universitat Politecnica de Valencia (ETSINF)},
|
|
180
|
+
year = {2026},
|
|
181
|
+
type = {Bachelor's thesis},
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## License
|
|
186
|
+
|
|
187
|
+
MIT — see [LICENSE](LICENSE).
|
esnfed-1.0.0/README.md
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# esnfed — a federated reservoir computing toolkit
|
|
2
|
+
|
|
3
|
+
`esnfed` is a small, dependency-light Python library for training **Echo State
|
|
4
|
+
Networks** (reservoir computing) in a **federated** setting — where several
|
|
5
|
+
parties jointly train a model without sharing their raw data. It accompanies the
|
|
6
|
+
Final Degree Project *Ensemble of Recurrent Networks for Federated Learning*
|
|
7
|
+
(ETSINF, Universitat Politècnica de València).
|
|
8
|
+
|
|
9
|
+
The core library depends only on **NumPy** and **NetworkX**.
|
|
10
|
+
|
|
11
|
+
> **Why this and not ReservoirPy?** [ReservoirPy](https://reservoirpy.readthedocs.io)
|
|
12
|
+
> is the mature, full-featured library for *building and tuning* reservoir
|
|
13
|
+
> computing models, and `esnfed` does **not** try to replace it. `esnfed`
|
|
14
|
+
> focuses on the part ReservoirPy does not cover: **federating** reservoir
|
|
15
|
+
> models across parties. You can design a reservoir in ReservoirPy and federate
|
|
16
|
+
> it here in one line (see *Interoperability* below).
|
|
17
|
+
|
|
18
|
+
## Features
|
|
19
|
+
|
|
20
|
+
- **Echo State Network** with leaky-integrator neurons and a closed-form ridge
|
|
21
|
+
readout (`EchoStateNetwork`).
|
|
22
|
+
- **Federated strategies**:
|
|
23
|
+
- `federated_ridge` — *exact* federated training for a shared reservoir
|
|
24
|
+
(clients exchange only ridge sufficient statistics; provably equal to pooled
|
|
25
|
+
training, in one communication round);
|
|
26
|
+
- `fedavg` — iterative FedAvg on the readout;
|
|
27
|
+
- `ensemble_predict` — prediction ensemble for *heterogeneous* reservoirs;
|
|
28
|
+
- `structural_alignment` — interpolate reservoirs toward a shared structure.
|
|
29
|
+
- **Reservoir topologies**: Erdős–Rényi, small-world, scale-free, ring.
|
|
30
|
+
- **Data**: synthetic benchmarks (NARMA-10, Mackey-Glass, Lorenz) **and** real
|
|
31
|
+
data — a bundled counterparty-risk series (the TED spread) plus generic
|
|
32
|
+
loaders (`from_array`, `load_csv`, `load_fred`).
|
|
33
|
+
- **Interoperability**: adapters for [ReservoirPy](https://reservoirpy.readthedocs.io)
|
|
34
|
+
reservoirs and an example integration with the
|
|
35
|
+
[Flower](https://flower.ai) federated-learning framework.
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install esnfed # core (numpy + networkx)
|
|
41
|
+
pip install "esnfed[experiments]" # + matplotlib/pandas/scipy/scikit-learn
|
|
42
|
+
pip install "esnfed[reservoirpy]" # + ReservoirPy interop
|
|
43
|
+
pip install "esnfed[flower]" # + Flower integration
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Quick start
|
|
47
|
+
|
|
48
|
+
### Federated counterparty-risk forecasting (real data)
|
|
49
|
+
|
|
50
|
+
Several institutions jointly forecast the **TED spread** (a classic gauge of
|
|
51
|
+
interbank/counterparty credit risk) without sharing their data. Exact federated
|
|
52
|
+
ridge equals pooled training in a single round:
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from esnfed import datasets, federated, topologies, metrics
|
|
56
|
+
|
|
57
|
+
u, y = datasets.load_ted_spread() # bundled real series (FRED)
|
|
58
|
+
u_tr, y_tr, u_te, y_te = datasets.split(u, y, 0.7)
|
|
59
|
+
parts = datasets.partition_iid(u_tr, y_tr, n_clients=8) # 8 "institutions"
|
|
60
|
+
|
|
61
|
+
W = topologies.random_reservoir(200, density=0.1, rng=0)
|
|
62
|
+
esn_kw = dict(spectral_radius=0.9, leaking_rate=0.5, washout=100, ridge=1e-6)
|
|
63
|
+
clients, ref = federated.make_shared_clients(W, parts, input_seed=0, esn_kwargs=esn_kw)
|
|
64
|
+
|
|
65
|
+
W_out = federated.federated_ridge(clients, ref) # one round, exact, private
|
|
66
|
+
Z_test = ref.harvest(u_te)[ref.washout:]
|
|
67
|
+
print("federated NRMSE:", metrics.nrmse(y_te[ref.washout:], Z_test @ W_out))
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Need another series? `datasets.load_fred("BAMLH0A0HYM2")` pulls a high-yield
|
|
71
|
+
credit spread from FRED; `datasets.from_array(my_series)` or
|
|
72
|
+
`datasets.load_csv("my.csv")` turn any series into a forecasting task.
|
|
73
|
+
|
|
74
|
+
### Train a single ESN
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
import numpy as np
|
|
78
|
+
from esnfed import EchoStateNetwork, datasets, topologies, metrics
|
|
79
|
+
|
|
80
|
+
u, y = datasets.narma10(3000, rng=0)
|
|
81
|
+
u_tr, y_tr, u_te, y_te = datasets.split(u, y)
|
|
82
|
+
W = topologies.random_reservoir(200, density=0.1, rng=0)
|
|
83
|
+
esn = EchoStateNetwork(1, 1, W, spectral_radius=0.9, washout=100).fit(u_tr, y_tr)
|
|
84
|
+
print("NRMSE:", metrics.nrmse(y_te[100:], esn.predict(u_te)[100:]))
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Interoperability
|
|
88
|
+
|
|
89
|
+
### ReservoirPy — design there, federate here
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from reservoirpy.nodes import Reservoir
|
|
93
|
+
from esnfed import interop, datasets, federated
|
|
94
|
+
|
|
95
|
+
res = Reservoir(200, sr=0.9, lr=0.5, input_dim=1) # design/tune in ReservoirPy
|
|
96
|
+
esn = interop.to_esn(res, n_inputs=1) # -> esnfed EchoStateNetwork
|
|
97
|
+
W = interop.reservoir_matrix(res) # ... then federate it
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Flower — a real FL framework
|
|
101
|
+
|
|
102
|
+
`examples/flower_federated_ridge.py` shows the exact federated-ridge scheme as a
|
|
103
|
+
Flower `NumPyClient` + custom `Strategy`: each client's `fit` returns its ridge
|
|
104
|
+
sufficient statistics and the server sums them and solves once. The Flower-routed
|
|
105
|
+
result is identical to `federated_ridge` to numerical precision.
|
|
106
|
+
|
|
107
|
+
## Modules
|
|
108
|
+
|
|
109
|
+
| Module | Contents |
|
|
110
|
+
|--------|----------|
|
|
111
|
+
| `esnfed.esn` | `EchoStateNetwork`, ridge helpers |
|
|
112
|
+
| `esnfed.topologies` | reservoir generators + `graph_metrics` |
|
|
113
|
+
| `esnfed.datasets` | NARMA-10, Mackey-Glass, Lorenz; `from_array`, `load_csv`, `load_ted_spread`, `load_fred` |
|
|
114
|
+
| `esnfed.metrics` | `nrmse`, `rmse`, `mse`, `r2_score` |
|
|
115
|
+
| `esnfed.federated` | `Client`, `federated_ridge`, `fedavg`, `ensemble_predict`, `structural_alignment` |
|
|
116
|
+
| `esnfed.interop` | ReservoirPy adapters (`to_esn`, `reservoir_matrix`) |
|
|
117
|
+
|
|
118
|
+
## Reproducing the research experiments
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
pip install -e ".[experiments,reservoirpy,flower]"
|
|
122
|
+
python -m pytest # 37 tests
|
|
123
|
+
python experiments/run_all.py # synthetic-benchmark figures and tables
|
|
124
|
+
python experiments/exp6_finance.py # federated counterparty-risk (TED spread)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Data attribution
|
|
128
|
+
|
|
129
|
+
The bundled TED spread is sourced from the Federal Reserve Bank of St. Louis
|
|
130
|
+
(FRED, series `TEDRATE`) and is used for demonstration under FRED's terms.
|
|
131
|
+
|
|
132
|
+
## Citation
|
|
133
|
+
|
|
134
|
+
```bibtex
|
|
135
|
+
@thesis{benites2026esnfed,
|
|
136
|
+
author = {Benites Aldaz, Dairon Andres},
|
|
137
|
+
title = {Ensemble of Recurrent Networks for Federated Learning},
|
|
138
|
+
school = {Universitat Politecnica de Valencia (ETSINF)},
|
|
139
|
+
year = {2026},
|
|
140
|
+
type = {Bachelor's thesis},
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## License
|
|
145
|
+
|
|
146
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""esnfed - Echo State Networks for Federated Learning.
|
|
2
|
+
|
|
3
|
+
A small, dependency-light research library accompanying the Final Degree Project
|
|
4
|
+
*Ensemble of Recurrent Networks for Federated Learning* (ETSINF, UPV).
|
|
5
|
+
|
|
6
|
+
Modules
|
|
7
|
+
-------
|
|
8
|
+
esn Echo State Network (reservoir + ridge readout).
|
|
9
|
+
topologies Reservoir topology generators (random, small-world, scale-free, ring).
|
|
10
|
+
datasets Benchmark sequential tasks (NARMA-10, Mackey-Glass, Lorenz, sine).
|
|
11
|
+
metrics Error metrics (NRMSE, MSE, memory capacity).
|
|
12
|
+
federated Federated strategies (FedAvg, exact federated ridge, ensemble, alignment).
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from .esn import EchoStateNetwork
|
|
16
|
+
from .metrics import nrmse, mse, rmse
|
|
17
|
+
from . import topologies, datasets, federated, metrics, interop
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"EchoStateNetwork",
|
|
21
|
+
"nrmse",
|
|
22
|
+
"mse",
|
|
23
|
+
"rmse",
|
|
24
|
+
"topologies",
|
|
25
|
+
"datasets",
|
|
26
|
+
"federated",
|
|
27
|
+
"metrics",
|
|
28
|
+
"interop",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
__version__ = "1.0.0"
|