PySR best vs accuracy: Why the Selected Equation Can Change

PySR’s results table marks one equation as the pick, yet another row has a lower loss. Why did it choose that one, and can you change the rule without rerunning the search?

PySR best vs accuracy: Why the Selected Equation Can Change
TLDR
  • PySR searches for equations, then selects a candidate for default predictions.
  • With the default logarithmic scoring, best maximizes score among candidates whose loss is at most 1.5 times the minimum.
  • You can change the selection strategy after fitting without launching a new search.

Best does not mean shortest, and accuracy means lowest loss

PySR performs symbolic regression: it searches for readable mathematical expressions rather than returning predictions alone. Once it has candidates, model_selection determines the default prediction equation.

The API reference defines accuracy as choosing the candidate with minimum loss. The default best strategy first limits the eligible candidates, then compares the improvement obtained for added complexity.

The selection implementation makes the boundary precise: eligible losses are less than or equal to 1.5 times the minimum. Under default logarithmic scoring, score measures the reduction in log loss per increase in complexity between successive candidates. Neither the shortest expression nor the smallest loss must win.

The same candidates can produce two different picks

This illustrative table uses invented candidate losses and complexities, with scores calculated using the default log formula. It is not output from a PySR run.

CandidateComplexityLossScore, rounded
A11.000
B30.121.060
C50.100.091

The eligibility threshold is 0.15. Best selects B because it has the higher score among B and C; accuracy selects C because its loss is lowest. The last reduction in error buys relatively little improvement for the extra complexity.

This describes the default log-scoring path. If the result has no score column, the implementation falls back to accuracy. Custom losses and a changed loss_scale need to be interpreted with that distinction in mind.

Read the pick marker, then compare predictions

The options documentation identifies the arrow in the printed pick column as the selected equation. Inspect model.equations_ for the candidate formulas, loss and complexity instead of assuming the last row is the current prediction model.

Given an already fitted model and validation inputs X_valid that were not used for fitting, this example obtains predictions from both strategies:

model.model_selection = "best"
print(model)
pred_best = model.predict(X_valid)

model.model_selection = "accuracy"
print(model)
pred_accuracy = model.predict(X_valid)

No new search is started here. The quickstart permits changing the strategy after fitting and describes exports such as sympy() for working with the resulting expression.

The tuning guide recommends using only necessary operators and constraining their combinations and nesting. Those decisions shape which expressions can be found; a final selection setting cannot substitute for a suitable search space.

maxsize limits equation complexity. By default, operators, constants and variables each contribute one, so complexity is not the character count of the printed formula. Changing those costs changes how expressions are evaluated.

Selection also needs evidence beyond training fit. The scikit-learn validation guide explains why performance on training data cannot establish generalization. Use validation data for candidate choices and reserve a separate test set for the final assessment.

Best is a default trade-off rule. Inspect why a candidate was selected, then evaluate whether its formula remains useful on data outside the search.