Skip to content

PySR

Multi-population evolutionary search returning a complexity/error Pareto front.

algorithm
pysr
score
NMSE min
cost
medium
derivatives
finite_diff
equation form
EVOLUTION REGRESSION
data layout
grid tabular

Usage

import kd

dataset = kd.load_burgers()
model = kd.Model(algorithm="pysr")
model.fit(dataset)
print(model.best_expr_)

Main parameters

Parameter Default Resume Description
niterations 40 resume-safe PySR's internal GP iterations per fit; the facade generations parameter maps here, and on a resume it is the number of further iterations the new segment runs from the archived populations.
population_size 33 init-only Members per PySR population.
populations 15 init-only Number of PySR populations.
maxsize 20 init-only Maximum generated expression size.
All fields of PySRConfig
Field Type Default
terms tuple[str, ...] ('u', 'u_x', 'u_xx', 'mul(u, u_x)')
seed int 0
niterations int 40
population_size int 33
populations int 15
maxsize int 20
binary_operators tuple[str, ...] ('+', '-', '*', '/')
unary_operators tuple[str, ...] ('sin', 'cos', 'exp', 'log')
extra_pysr_kwargs dict[str, Any] \| None None

The KD wrapper

PySR is a third-party package, installed separately, and its authors document the search itself. The points below are specific to driving it from KD.

One fit per run. PySR performs one batch search and returns its whole hall of fame, so a KD run has a single iteration rather than a curve across generations. A resumed run (resume_from) continues that search from the populations and hall of fame stored in the checkpoint; the resuming model's generations is the number of further PySR iterations the new segment runs.

On a PDE dataset it regresses over KD's term library. PySRConfig.terms is the set of candidate term columns handed to PySR, in KD's function-call notation. The constants PySR fits are stripped off, leaving the structural terms for KD to refit.

On a table it keeps the expression whole. Hand fit() a kd.TabularDataset and KD runs PySR in its tabular mode: the columns are the feature columns of the table, so terms comes from the dataset rather than from the configuration, and the expression PySR returns is kept intact, fitted constants and all.

The operators are configurable in either mode. binary_operators and unary_operators define the operators PySR may combine its columns with, and both are read from the configuration regardless of which kind of dataset it was handed.

best_score_ is computed by KD. PySR's own loss is not returned. The selected expression is refitted by least squares on the data of that run, and the NMSE of that refit is the score, where lower is better. On a table that refit is a single outer coefficient, so the score measures the shape of the expression rather than the expression as written. The refit coefficients arrive on result_.final_eval.coefficients, and on result_.equation alongside the terms they belong to; best_expr_ itself is the structural expression on a PDE dataset, and PySR's own expression, constants included, on a table.

The full front is returned with the result. Every hall-of-fame entry that converts to KD's notation is kept, and model.result_.pareto_front() returns them as typed entries: the expression in KD notation, PySR's own two axes as complexity and loss, and on a tabular run the outer coefficient fitted for that entry as scale. The series behind them stay on model.result_.recorder under the same names, pareto_nmse among them, which is KD's independent re-score of each entry.

Anything else PySR accepts goes through extra_pysr_kwargs, unchanged.

References

Cranmer (2023). "Interpretable machine learning for science with PySR and SymbolicRegression.jl". arXiv:2305.01582. Paper

Documentation: ai.damtp.cam.ac.uk/pysr

Code: MilesCranmer/PySR