Model-Structured Neural Networks for the modeling, control and estimation of physical systems.
Documentation • Getting Started • Applications • Guide for AI assistants
nnodely (read the nn as an m: Modely) builds neural networks whose structure is the physics. Instead of a black box, you write the model the way you would write the equations: FIR filters on past samples, local models scheduled by a fuzzy variable, derivatives, integrators, ODE solvers. The data only has to find the coefficients.
- Structure first. Every block has a physical meaning, so the trained network stays interpretable.
- Little data. Structural priors do the heavy lifting, so a few recordings are often enough.
- Generalization. A model that respects the physics behaves in scenarios it never saw during training.
- Real time. Small networks, exported to Keras or ONNX for deployment.
- Any backend. Built on Keras 3: the same model runs on TensorFlow, PyTorch or JAX.
nnodely is not a replacement for general-purpose deep-learning frameworks. It is a structured layer on top of them, purpose-built for physical systems.
pip install "nnodely[torch]" # or [tensorflow], or [jax]
pip install "nnodely[torch,onnx]" # + ONNX exportPick the backend with KERAS_BACKEND (TensorFlow if unset) before importing nnodely:
export KERAS_BACKEND=torchA mass-spring-damper, m ẍ = −k x − c ẋ + F, learned as its own discrete-time structure: the next position is a filter over the last positions plus a gain on the current force.
import numpy as np
from nnodely import DataLoader, Fir, Input, Modely, Output, set_seed
set_seed(0) # the same data and initial weights, so the same results, on every run
# Simulate the system: in practice, these are your measurements
dt, m, k, c = 0.05, 1.0, 2.0, 0.5
force = np.repeat(np.random.uniform(-1.0, 1.0, 60), 50)
position, velocity = np.zeros(3000), np.zeros(3000)
for t in range(2999):
velocity[t + 1] = velocity[t] + dt * (-k * position[t] - c * velocity[t] + force[t]) / m
position[t + 1] = position[t] + dt * velocity[t + 1]
# The structure: x[t+1] = FIR(x[t-4..t]) + FIR(F[t])
x, F = Input("x"), Input("F")
x_next = Output("x_next", Fir(out_features=1)([x.sw(5)]) + Fir(out_features=1)([F.last()]))
model = Modely("mass_spring_damper", inputs=[x, F], outputs=[x_next])
model.minimize("next_position", x_next, x.next())
model.build()
# Train with the nnodely console, then score the model
data = DataLoader(model, source={"x": position, "F": force})
model.train(data, epochs=100, batch_size=64, lr=1e-2, printer="nnodely")
model.validate(data)validate() reports the loss next to RMSE, FIT, R² and the other indicators a
system-identification report is read for, and can plot them.
| Blocks | |
|---|---|
| Signals | Input with sample windows (sw, last, next), Output, Parameter, Constant, arithmetic on streams |
| Structured layers | Fir [1], Linear, LocalModel [1] [3] [4] [5], Fuzzify [2], EquationLearner [6], Interpolation, BatchNorm |
| Calculus | Derivative w.r.t. inputs or time, for physics-informed [7] and Sobolev [8] training · Integrate · Ode (Euler, midpoint, Heun, RK4) · OdeNet (neural ODEs, adaptive Dormand-Prince, hybrid events) |
| Recurrence | rollback for multi-step prediction, Loop and Roll for rollouts over whole trajectories |
| Data | DataLoader from dicts, DataFrames or CSV folders, multiple simulations, sequences, masks, normalization |
| Workflow | train with any Keras optimizer and loss · validate with system-identification metrics and plots · model composition · save/load, Keras and ONNX export, interactive HTML graphs |
Every block is documented, with runnable examples, in the User Guide.
Structure of the repository
nnodely/
├── src/nnodely/
│ ├── core/ # Modely, DataLoader, streams, graph, validation
│ ├── layers/ # every block of the table above
│ └── utils/ # printers, plots, seeding
├── docs/ # documentation, built on Read the Docs
├── tests/ # unit and integration tests, run on all three backends
├── imgs/ # images used in the README and the documentation
└── NNODELY_AI_GUIDE.md # reference for AI coding assistantsThe repository ships
NNODELY_AI_GUIDE.md,
a reference written for LLMs and coding agents rather than for people. It is
dense on purpose and covers what an assistant needs to produce working code on
the first attempt:
- the hard rules of the library: lifecycle order, how objectives and targets work, naming and weight sharing, and the behaviors that fail silently;
- a table that maps physical concepts and equations to nnodely blocks;
- the shape convention
(*dim, time, *seq)and how windows and sequences are aligned by theDataLoader; - exact signatures of every block, of
Modelyand ofDataLoader; - when to use
rollback,Loop,Roll,OdeorOdeNet, and how to align their training data; - which models can be saved or exported to Keras and ONNX, on which backend;
- common error messages with their fix, runnable recipes, and a checklist to review generated code.
To use it, give the assistant the guide together with a description of the system you want to model:
<contents of NNODELY_AI_GUIDE.md>
Using nnodely, write a model of a DC motor: the angular velocity w follows
J dw/dt = K i - b w, with J, K and b unknown. I have CSV files with columns
time, current, omega sampled at 1 kHz. Identify J, K and b.
Agents that can read URLs can fetch the raw file directly from
https://raw.githubusercontent.com/tonegas/nnodely/main/NNODELY_AI_GUIDE.md.
Every behavior the guide marks as verified was checked against the code, so
keep it in sync when the API changes.
nnodely 2.0 is a rewrite on Keras 3: the model is a Modely built from its
inputs and outputs, trained on a DataLoader, and runs on TensorFlow, PyTorch
or JAX. The
CHANGELOG
maps every 1.x call to its 2.0 counterpart. Models saved with 1.x cannot be
loaded by 2.0; to keep using them, pin pip install "nnodely<2".
Contributions and collaborations are welcome: open an issue for questions and ideas, or a pull request for a new feature or a fix. See CONTRIBUTING.md to set up the development environment.
nnodely is released under the MIT License.
[1] Mauro Da Lio, Daniele Bortoluzzi, Gastone Pietro Rosati Papini. (2019). Modelling longitudinal vehicle dynamics with neural networks. Vehicle System Dynamics. https://doi.org/10.1080/00423114.2019.1638947 (look the [code])
[2] Alice Plebe, Mauro Da Lio, Daniele Bortoluzzi. (2019). On Reliable Neural Network Sensorimotor Control in Autonomous Vehicles. IEEE Transaction on Intelligent Transportation System. https://doi.org/10.1109/TITS.2019.2896375
[3] Mauro Da Lio, Riccardo Donà, Gastone Pietro Rosati Papini, Francesco Biral, Henrik Svensson. (2020). A Mental Simulation Approach for Learning Neural-Network Predictive Control (in Self-Driving Cars). IEEE Access. https://doi.org/10.1109/ACCESS.2020.3032780 (look the [code])
[4] Edoardo Pagot, Mattia Piccinini, Enrico Bertolazzi, Francesco Biral. (2023). Fast Planning and Tracking of Complex Autonomous Parking Maneuvers With Optimal Control and Pseudo-Neural Networks. IEEE Access. https://doi.org/10.1109/ACCESS.2023.3330431 (look the [code])
[5] Mattia Piccinini, Sebastiano Taddei, Matteo Larcher, Mattia Piazza, Francesco Biral. (2023). A Physics-Driven Artificial Agent for Online Time-Optimal Vehicle Motion Planning and Control. IEEE Access. https://doi.org/10.1109/ACCESS.2023.3274836 (look [code basic] and [code extended])
[6] Hector Perez-Villeda, Justus Piater, Matteo Saveriano. (2023). Learning and extrapolation of robotic skills using task-parameterized equation learner networks. Robotics and Autonomous Systems. https://doi.org/10.1016/j.robot.2022.104309 (look the [code])
[7] M. Raissi. P. Perdikaris b, G.E. Karniadakis a. (2019). Physics-informed neural networks: A deep learning framework for solving forward and inverse problems involving nonlinear partial differential equations Journal of Computational Physics. https://doi.org/10.1016/j.jcp.2018.10.045 (look the [example Burger's equation])
[8] Wojciech Marian Czarnecki, Simon Osindero, Max Jaderberg, Grzegorz Świrszcz, Razvan Pascanu. (2017). Sobolev Training for Neural Networks. arXiv. https://doi.org/10.48550/arXiv.1706.04859 (look the [code])
[9] Mattia Piccinini, Matteo Zumerle, Johannes Betz, Gastone Pietro Rosati Papini. (2025). A Road Friction-Aware Anti-Lock Braking System Based on Model-Structured Neural Networks. IEEE Open Journal of Intelligent Transportation Systems. https://doi.org/10.1109/OJITS.2025.3563347 (look at the [code])
[10] Mauro Da Lio, Mattia Piccinini, Francesco Biral. (2023). Robust and Sample-Efficient Estimation of Vehicle Lateral Velocity Using Neural Networks With Explainable Structure Informed by Kinematic Principles. IEEE Transactions on Intelligent Transportation Systems. https://doi.org/10.1109/TITS.2023.3303776