Neural Symbolic Regression engine: GRU policy + REINFORCE + lambda-sweep Pareto front
Project description
nsr-engine
Neural Symbolic Regression engine: a GRU policy trained with risk-seeking REINFORCE (Petersen et al. 2021) that discovers closed-form mathematical expressions from data.
Single-objective training is turned into a Pareto front by sweeping a complexity penalty λ over a log-spaced grid and pooling all discovered expressions.
Install
pip install nsr-engine # core (numpy, pandas, torch)
pip install "nsr-engine[sympy]" # + sympy for human-readable formulas
pip install "nsr-engine[memmap,sympy]" # + pyarrow for out-of-core fit_memmap
From source:
git clone https://github.com/kpapmath/nsr-engine
cd nsr-engine
pip install -e ".[sympy,memmap,dev]"
Quick start
import pandas as pd
import numpy as np
from nsr_engine import NSREngine
rng = np.random.default_rng(0)
n = 5000
a = rng.standard_normal(n)
b = rng.standard_normal(n)
X = pd.DataFrame({"a": a, "b": b})
y = pd.Series(0.5 * a + 0.3 * b + 0.05 * rng.standard_normal(n))
engine = NSREngine(
n_lambda=8, # number of lambda values to sweep
n_iters=300, # REINFORCE iterations per lambda
batch_size=64, # expressions sampled per iteration
max_len=10, # maximum token sequence length
score_metric="mse", # "mse", "rmse", "mae", "mape", "mbd", "r2", or "adjusted_r2"
random_state=42,
)
front = engine.fit(X, y)
print(front.to_frame())
print("elbow formula:", front.elbow().equation)
Full pipeline example
The repository includes a runnable end-to-end pipeline that generates data or loads a CSV, optionally runs holdout, K-fold, or time-series validation, trains the engine, prints the Pareto front, and selects the elbow formula.
python main.py
The example wrapper and package module entry point are equivalent:
python examples/full_pipeline.py
python -m nsr_engine.main
By default the example uses the entire dataset for the final fit
(--validation-mode none). Add --validation-mode sequential for a single
chronological train/test split:
python main.py --validation-mode sequential --train-frac 0.8 --test-frac 0.2
K-fold, expanding-window, walk-forward, and blocked time-series validation are also available:
python main.py --validation-mode k-fold --folds 5
python main.py --validation-mode expanding-window --folds 5
python main.py --validation-mode walk-forward --folds 5
python main.py --validation-mode blocked-time-series --folds 5
Validation modes:
| Mode | Behavior |
|---|---|
none |
Fit the final Pareto front on all rows. This is the default. |
sequential |
Chronological single train/test split; past rows train, immediately subsequent rows test. |
holdout |
Single train/test split like sequential, but may be randomized with --shuffle. |
k-fold |
K-fold validation; folds are ordered by default and randomized only with --shuffle. |
expanding-window |
Expanding-window time-series validation; each fold adds more historical rows to training. |
walk-forward |
Alias-style walk-forward mode using the same expanding training window behavior. |
blocked-time-series |
Contiguous non-overlapping train/validation blocks; each validation block immediately follows its training block. |
For a quicker smoke run:
python main.py --iters 20 --lambdas 3 --rows 1000
To run on your own CSV data, provide the target column and optionally a comma-separated feature list:
python main.py --input-csv data.csv --target-col y --feature-cols a,b,c
After installation, the same CLI is available as:
nsr-engine
nsr-engine --help
Every command-line input, with its default and available options, is documented in the CLI reference.
Pipeline case examples
Functional examples for each distinct pipeline path are split into standalone
scripts. See docs/pipeline_examples.md for the full summary.
python examples/generated_train_test.py
python examples/generated_validation.py
python examples/csv_input.py
python examples/custom_metric_library.py
python examples/cached_run.py
python examples/memmap_out_of_core.py
The defaults are small CPU-sized smoke examples; increase --iters,
--lambdas, and --rows for stronger searches.
Token grammar
| Type | Tokens |
|---|---|
| Binary ops | + - * / |
| Unary ops | square abs log (default) |
| Constants | -1.0 -0.5 0.5 1.0 2.0 |
| Variables | column names of input X |
Sequences are in prefix (Polish) notation; the arity-tracking constraint guarantees every sampled sequence is a valid, complete expression tree.
The default unary set is square, abs, log. Many more are available on
opt-in via unary_ops=[...] (or --unary-ops): sqrt, cbrt, exp,
log10, log2, sin, cos, tan, sinh, cosh, tanh, arcsin,
arccos, arctan, arcsinh, arctanh, sigmoid, neg, sign, cube, and
reciprocal. See the CLI reference
for the full list and each operator's numeric behavior.
Out-of-core training
For datasets too large to fit in RAM, build a MemmapDataset from Parquet files and use fit_memmap:
from nsr_engine.memmap_store import build_memmap_dataset
store = build_memmap_dataset(
files=list(Path("data/").glob("*.parquet")),
feature_cols=["a", "b", "c"],
target_col="y",
memmap_path=Path("cache/train.mmap"),
)
front = engine.fit_memmap(store, train_lo=0, train_hi=store.n_rows)
Key parameters
| Parameter | Default | Description |
|---|---|---|
n_lambda |
10 | Lambda grid size |
lambda_min / lambda_max |
1e-4 / 1e-1 | Lambda sweep range |
n_iters |
200 | REINFORCE iters per lambda |
batch_size |
64 | Expressions per iteration |
max_len |
15 | Max token sequence length |
elite_frac |
0.05 | Risk-seeking quantile ε |
entropy_weight |
0.005 | Entropy bonus coefficient |
standardize |
True | Z-score features before training |
affine_reward |
True | Score residuals after a least-squares affine fit |
score_metric |
"mse" |
Accuracy metric: "mse", "rmse", "mae", "mape", "mbd", "r2", or "adjusted_r2" |
cache_dir |
None | Cache lambda runs to disk (JSON) |
Scoring metrics
score_metric controls how expressions are ranked after the optional affine
fit b0 + b1 * expression.
| Value | Meaning | Direction |
|---|---|---|
"mse" |
Mean squared error | Lower is better |
"rmse" |
Root mean squared error | Lower is better |
"mae" |
Mean absolute error | Lower is better |
"mape" |
Mean absolute percentage error, reported as percent | Lower is better |
"mbd" |
Absolute mean bias deviation | Lower is better |
"r2" |
Coefficient of determination | Higher is better |
"adjusted_r2" |
Adjusted R squared using one effective predictor | Higher is better |
For r2 and adjusted_r2, front.to_frame() reports the actual R squared
value while Pareto dominance maximizes it internally.
Reference
Petersen et al. (2021). Deep Symbolic Regression: Recovering Mathematical Expressions from Data via Risk-Seeking Policy Gradients. ICLR 2021.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nsr_engine-0.2.0.tar.gz.
File metadata
- Download URL: nsr_engine-0.2.0.tar.gz
- Upload date:
- Size: 33.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cc8559aba385e6ee74740bcada36265bbc2dcdd30e9d86566e8c91e0ea1cf72b
|
|
| MD5 |
360428588e62741cbbf95085754cd1ac
|
|
| BLAKE2b-256 |
4d71b3bd2c843d733e10ab627b5593c1a70d00b19933fc3820ede8a074d53590
|
Provenance
The following attestation bundles were made for nsr_engine-0.2.0.tar.gz:
Publisher:
publish.yml on kpapmath/nsr-engine
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nsr_engine-0.2.0.tar.gz -
Subject digest:
cc8559aba385e6ee74740bcada36265bbc2dcdd30e9d86566e8c91e0ea1cf72b - Sigstore transparency entry: 2180987269
- Sigstore integration time:
-
Permalink:
kpapmath/nsr-engine@434f09c84bab33951f1c759cafb6d2e54c2b5e38 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/kpapmath
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@434f09c84bab33951f1c759cafb6d2e54c2b5e38 -
Trigger Event:
release
-
Statement type:
File details
Details for the file nsr_engine-0.2.0-py3-none-any.whl.
File metadata
- Download URL: nsr_engine-0.2.0-py3-none-any.whl
- Upload date:
- Size: 31.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
13deb4ceca7f03b2e3f7bce821f6e1aff2dbc0a3aafa3015d389c99cc08a83cb
|
|
| MD5 |
ede4ef75f82e35da755b75f328d58337
|
|
| BLAKE2b-256 |
fac212686a7e2097a57695de21da4c00889060b3a039a0c3ff531ca90b505afd
|
Provenance
The following attestation bundles were made for nsr_engine-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on kpapmath/nsr-engine
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nsr_engine-0.2.0-py3-none-any.whl -
Subject digest:
13deb4ceca7f03b2e3f7bce821f6e1aff2dbc0a3aafa3015d389c99cc08a83cb - Sigstore transparency entry: 2180987319
- Sigstore integration time:
-
Permalink:
kpapmath/nsr-engine@434f09c84bab33951f1c759cafb6d2e54c2b5e38 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/kpapmath
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@434f09c84bab33951f1c759cafb6d2e54c2b5e38 -
Trigger Event:
release
-
Statement type: