Sparse Identification of Nonlinear Dynamics with SHallow REcurrent Decoder Networks
SINDy-SHRED learns low-dimensional latent dynamics from sparse sensor measurements and decodes those dynamics back into full spatiotemporal fields. It combines SHRED-style sequence encoding and reconstruction with SINDy-based sparse equation discovery, so the learned latent trajectories can be forecast with interpretable governing equations.
- Encodes sparse sensor histories with GRU layers.
- Reconstructs high-dimensional fields with a shallow decoder network.
- Regularizes training with SINDy terms in the latent space.
- Discovers post-hoc symbolic latent dynamics with PySINDy.
- Supports first-order systems,
z' = f(z), and second-order systems,z'' = f(z, z'). - Provides threshold search for sparse, stable SINDy models.
Example applications include sea surface temperature forecasting, flow over a cylinder, isotropic turbulence, pendulum video prediction, and synthetic PDE systems.
The accompanying preprint is available on arXiv:
Sparse identification of nonlinear dynamics and Koopman operators with Shallow Recurrent Decoder Networks
https://arxiv.org/abs/2501.13329
SINDy-SHRED requires Python 3.9 or newer. Install PyTorch first so that you get the correct build for your CPU or GPU, then install the package.
Choose the command that matches your hardware. If you are using an NVIDIA GPU, check your supported CUDA version with nvidia-smi.
# CUDA 12.8
pip install torch --index-url https://download.pytorch.org/whl/cu128
# CUDA 12.4
pip install torch --index-url https://download.pytorch.org/whl/cu124
# CPU only
pip install torchVerify the install:
python -c "import torch; print(torch.cuda.is_available()); print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'CPU')"git clone https://github.com/gaoliyao/sindy-shred.git
cd sindy-shred
pip install -e ".[notebooks]"For uv users:
git clone https://github.com/gaoliyao/sindy-shred.git
cd sindy-shred
uv venv .venv
source .venv/bin/activate
uv pip install torch --index-url https://download.pytorch.org/whl/cu128
uv pip install -e ".[notebooks]"For conda users:
git clone https://github.com/gaoliyao/sindy-shred.git
cd sindy-shred
conda create -n sindyshred python=3.11
conda activate sindyshred
pip install torch --index-url https://download.pytorch.org/whl/cu128
pip install -e ".[notebooks]"Confirm the package imports:
python -c "import torch, pysindy, sindy_shred; print('SINDy-SHRED ready')"Place datasets in the Data/ directory. Example data are available here:
https://drive.google.com/file/d/1IrKFsYEcUL8xxZ0PUSLC3VrpTvVneDhj/view?usp=sharing
The repository includes notebooks for the FitzHugh-Nagumo example, sea surface temperature data, and flow over a cylinder.
Run a notebook locally:
jupyter lab notebooks/fitzhugh_nagumo.ipynbOr open the hosted Colab notebook:
The high-level SINDySHRED class handles scaling, sensor-window construction, model training, latent equation discovery, and decoding.
from sindy_shred import SINDySHRED
model = SINDySHRED(
latent_dim=3,
poly_order=2,
hidden_layers=2,
l1=350,
l2=400,
dropout=0.1,
batch_size=128,
num_epochs=200,
lr=1e-3,
threshold=0.05,
sindy_regularization=10.0,
)
model.fit(
num_sensors=3,
dt=1 / 52,
x_to_fit=data, # shape: (time, space)
lags=52,
train_length=1000,
validate_length=30,
sensor_locations=sensor_locations,
)
model.sindy_identify(threshold=0.05, plot_result=True)
z_pred = model.sindy_predict(split="train", init_from="last")
forecast_scaled = model.shred_decode(z_pred)
forecast = model.forecast(n_steps=100, return_scaled=False)Useful methods:
| Method | Purpose |
|---|---|
fit(...) |
Train the SHRED encoder-decoder with SINDy regularization. |
sindy_identify(...) |
Discover sparse latent dynamics from trained GRU trajectories. |
auto_tune_threshold(...) |
Search for a sparse, stable SINDy threshold. |
sindy_predict(...) |
Simulate the discovered latent dynamics. |
shred_decode(...) |
Decode latent trajectories into scaled physical states. |
forecast(...) |
Predict latent dynamics, decode them, and optionally invert scaling. |
sensor_recon(...) |
Reconstruct full states directly from sparse sensor inputs. |
For custom training loops or experiments, use the underlying network and utilities directly:
from sindy_shred import sindy
from sindy_shred.sindy_shred_net import SINDy_SHRED_net, fit
library_dim = sindy.library_size(
n=latent_dim,
poly_order=poly_order,
use_sine=False,
include_constant=True,
)
net = SINDy_SHRED_net(
input_size=num_sensors,
output_size=state_dim,
hidden_size=latent_dim,
hidden_layers=2,
l1=350,
l2=400,
dropout=0.1,
library_dim=library_dim,
poly_order=poly_order,
include_sine=False,
dt=dt,
).to(device)
validation_errors = fit(
net,
train_dataset,
valid_dataset,
batch_size=128,
num_epochs=600,
lr=1e-3,
threshold=0.25,
sindy_regularization=10.0,
)| Notebook | Description |
|---|---|
notebooks/fitzhugh_nagumo.ipynb |
End-to-end synthetic FitzHugh-Nagumo workflow. |
notebooks/sea_surface_temperature.ipynb |
Sea surface temperature reconstruction and forecasting. |
notebooks/flow_over_cylinder.ipynb |
Flow-over-cylinder reconstruction and latent forecasting. |
Notebook outputs are written under notebooks/results/.
| Module | Description |
|---|---|
sindy_shred.sindy_shred |
High-level SINDySHRED workflow class. |
sindy_shred.sindy_shred_net |
Core PyTorch network and training routine. |
sindy_shred.sindy |
SINDy library construction and sparse dynamics helpers. |
sindy_shred.miosr_utils |
MIOSR-based sparse model utilities. |
sindy_shred.processdata |
Data loading and preprocessing helpers. |
sindy_shred.plotting |
Plotting utilities for latent dynamics and reconstructions. |
sindy_shred.utils |
Device selection and dataset wrappers. |
If you use SINDy-SHRED in your research, please cite:
@misc{gao2025sparse,
title={Sparse identification of nonlinear dynamics and Koopman operators with Shallow Recurrent Decoder Networks},
author={Mars Liyao Gao and Jan P. Williams and J. Nathan Kutz},
year={2025},
eprint={2501.13329},
archivePrefix={arXiv},
primaryClass={cs.LG},
url={https://arxiv.org/abs/2501.13329}
}This project is released under the MIT License. See LICENSE.