Skip to content

Federated strategies

In an ESN only the linear readout is trained, so federated learning reduces to learning a shared (or combinable) readout across clients whose reservoirs may or may not share the same structure.

flowchart LR
  subgraph clients["Clients (data stays local)"]
    c1["Client 1<br/>A₁, B₁"]
    c2["Client 2<br/>A₂, B₂"]
    ck["Client K<br/>A_K, B_K"]
  end
  c1 --> S["Server<br/>A = ΣAₖ, B = ΣBₖ<br/>solve (A+βI)Wᵀ = B"]
  c2 --> S
  ck --> S
  S -. "broadcast W_out" .-> clients

Shared reservoir

Exact federated ridge

Each client computes the ridge sufficient statistics of its local data and sends only those; the server sums and solves once. Mathematically identical to pooled training, in a single communication round.

from esnfed import federated, topologies, datasets, metrics

parts = datasets.partition_iid(u_tr, y_tr, n_clients=10)
W = topologies.random_reservoir(200, density=0.1, rng=0)
clients, ref = federated.make_shared_clients(W, parts, esn_kwargs=dict(washout=100))

W_out = federated.federated_ridge(clients, ref)

Verified

A unit test asserts federated_ridge equals centralized training to within 1e-9. The privacy gain (raw data stays local) costs nothing in accuracy.

Federated ridge holds its accuracy as the federation grows, while local-only training degrades (interactive — see the gallery for more):

Iterative FedAvg

For comparison, the readout can also be trained with iterative FedAvg:

W_out, history = federated.fedavg(clients, ref, u_te, y_te, rounds=100)

On reservoir readouts this converges slowly (the state covariance is ill-conditioned) — which is exactly why the closed-form federated_ridge is preferred.

Heterogeneous reservoirs

When clients hold different reservoirs, parameters are incommensurable. Two options:

# 1) Prediction ensemble — combine outputs, no parameter averaging
het = federated.make_heterogeneous_clients(reservoirs, parts, esn_kwargs=...)
federated.train_local(het)
pred = federated.ensemble_predict(het, u_te)

# 2) Structural alignment — interpolate reservoirs toward a shared target,
#    then parameter aggregation becomes valid again
records = federated.structural_alignment(local_reservoirs, target, parts, u_te, y_te)

Finding from the research

Under structural heterogeneity the ensemble is robust and beats local-only training; parameter aggregation only becomes competitive once the reservoirs are nearly identical. On real, non-stationary financial data, local-only training collapses while federated ridge stays accurate.

See the API reference.