Skip to content

Quickstart

Install beamfeat, fit a model and read what it prints. Every example runs as shown, and the outputs are from real runs. The Getting started tutorial covers the same ground in a notebook.

Install

pip install beamfeat              # core: numpy, scikit-learn, joblib
pip install "beamfeat[units]"     # + pint, for dimensional analysis
pip install "beamfeat[display]"   # + sympy, for to_sympy() and latex()
pip install "beamfeat[all]"       # + both, pandas and the test dependencies

See Installation for running the test suite or reproducing the benchmarks.

Sixty seconds to a vetted equation

import numpy as np
from beamfeat import BeamFeatRegressor

rng = np.random.default_rng(0)
X = rng.uniform(1, 6, (400, 4))
y = X[:, 0] * X[:, 1] + rng.normal(0, 0.05, 400)

model = BeamFeatRegressor(max_depth=2, beam_width=25, random_state=0).fit(X, y)
print(model.equation())
print(model.fdr_controlled_)
y = 0.9999*(x0 * x1) - 0.003943   [1 of 25 certified terms; parsimony=None prints all 25]
True

Three things matter. equation() is the fitted model itself — evaluate it on raw feature values and you reproduce predict(). fdr_controlled_ states whether the features carry the false-discovery-rate guarantee; check it before treating them as statistically vetted. And the suffix says that those two do not describe the same set of terms; Reading a fit explains it.

That last point has an attribute as well as a suffix, because a script never reads the printed string:

print(model.fdr_controlled_, "|", model.fdr_scope_)
True | screened set

fdr_controlled_ says whether there is a guarantee. fdr_scope_ says what it is over: "screened set" when the printed terms were pruned from a larger certified set, "printed equation" when the guarantee covers the terms you are looking at, None when there is no guarantee to scope. Branch on fdr_scope_, not on the equation text.

Column names flow into formulas

Fit on a DataFrame and formulas use your names:

import pandas as pd

df = pd.DataFrame({"mass": rng.uniform(1, 5, 300),
                   "vol":  rng.uniform(1, 5, 300)})
target = df["mass"] / df["vol"] + rng.normal(0, 0.02, 300)
print(BeamFeatRegressor(random_state=0).fit(df, target).formulas())
['(mass / vol)']

Classification

BeamFeatClassifier prints the log-odds of the positive class, whose zero level set is the decision boundary:

from beamfeat import BeamFeatClassifier

labels = (X[:, 0] * X[:, 1] > X[:, 2] * X[:, 3]).astype(int)
clf = BeamFeatClassifier(max_depth=2, random_state=0).fit(X, labels)
print(clf.equation(max_terms=3))
logit P(y = 1) = 1.678*((x0 / x2) - log(x3)) - 0.1561*((x2 * x3) - (x0 * x1)) - 1.014*((x2 / x1) + (x3 / x0)) + 1.101   [20 of 50 certified terms; parsimony=None prints all 50; parsimony_alpha=0.05 prints 2]

The fitted equation has 20 terms; max_terms=3 displays the three with the largest standardised coefficients and holds the rest at their training mean. With parsimony_alpha=0.05 the model itself has two terms, and its accuracy on 2,000 new rows is about the same, 0.981 against 0.979:

short = BeamFeatClassifier(max_depth=2, random_state=0, parsimony_alpha=0.05).fit(X, labels)
print(short.equation())
logit P(y = 1) = - 0.526*((x2 * x3) - (x0 * x1)) - 1.005*((x2 / x0) + (x3 / x1)) + 2.455   [2 of 50 certified terms; parsimony=None prints all 50]

Next

  • Choosing a setting: the default for prediction, parsimony_alpha for a short equation, input_test for an equation whose every column was tested, and the options for tall data, switches and weak terms.
  • User guide: reading a fit, the printed equation, the search options, data and prediction, and screening another tool's equation.
  • Tutorials: four notebooks with real outputs.
  • Statistical guarantees: what the guarantee covers, and what was measured.