Skip to content

API reference

Estimators

Bases: RegressorMixin, _BeamFeatBase

Constructs features, then fits a linear model on them.

The linear model is the point: its coefficients combine with the feature formulas to give a closed-form expression for the fitted relationship, available via :meth:equation.

Parameters:

Name Type Description Default
alpha float

Ridge regularisation strength for the downstream model.

1.0

Other arguments match :class:BeamFeatTransformer.

Attributes:

Name Type Description
features_

Selected expressions.

feature_formulas_

Their formula strings.

model_

The fitted downstream linear model.

coef_

Coefficients of the downstream model.

intercept_

Intercept of the downstream model.

equation(precision=4, max_terms=None)

Return the fitted model as a readable closed-form equation.

Parameters:

Name Type Description Default
precision int

Decimal places for the coefficients.

4
max_terms int | None

If set, include only the largest-magnitude terms.

None

Returns:

Type Description
str

A string such as y = 2.1043*(a * b) - 0.5120*log(c) + 3.9910.

fit(X, y)

Construct features and fit the downstream model.

predict(X)

Predict using the constructed features and fitted model.

Bases: ClassifierMixin, _BeamFeatBase

Constructs features, then fits a logistic model on them.

Parameters:

Name Type Description Default
C float

Inverse regularisation strength for the downstream model.

1.0

Other arguments match :class:BeamFeatTransformer.

Attributes:

Name Type Description
features_

Selected expressions.

classes_

Class labels seen during fit.

model_

The fitted downstream logistic model.

decision_function(X)

Return the model's decision scores.

equation(precision=4, max_terms=None)

Return the fitted classifier as a readable log-odds equation.

For binary problems the single line gives the log-odds of the positive class (classes_[1]): logit P(y = c1) = ..., so the decision boundary is the zero level set of the right-hand side. For multiclass problems one line is returned per class; these are the softmax scores of the fitted multinomial model, and the predicted class is the argmax across lines.

Parameters:

Name Type Description Default
precision int

Decimal places for the coefficients.

4
max_terms int | None

If set, include only the largest-magnitude terms per line.

None

fit(X, y)

Construct features and fit the downstream classifier.

predict(X)

Predict class labels.

predict_proba(X)

Predict class probabilities.

Bases: TransformerMixin, _BeamFeatBase

Constructs and selects features, for use inside a pipeline.

Parameters:

Name Type Description Default
scorer str | Scorer

Scoring strategy for the search. A name ("correlation", "mutual_information", "gradient_boosting") or a :class:~beamfeat.scoring.Scorer instance.

'correlation'
selector str | Selector | None

FDR-controlled selector, or None to keep the search output unfiltered. A name ("permutation", "knockoff") or a :class:~beamfeat.selection.Selector instance.

'permutation'
problem_type str

"regression" or "classification". Determines how the scorer and selector treat the target.

'regression'
max_depth int

Maximum expression depth.

2
beam_width int

Expressions retained at each search depth.

50
max_features int | None

Cap on features returned by the search, before selection.

None
target_fdr float

Nominal false discovery rate for the selector.

0.1
unary_ops tuple[str, ...]

Unary operators to apply.

DEFAULT_UNARY
binary_ops tuple[str, ...]

Binary operators to apply.

DEFAULT_BINARY
redundancy_threshold float

Absolute correlation above which a candidate is treated as a duplicate.

0.95
include_originals bool

Whether input columns compete alongside constructed expressions.

True
units dict[str, Any] | None

Optional mapping of input column name to pint quantity. Supplying units restricts the search to dimensionally valid expressions.

None
random_state int | None

Seed. Fitting is deterministic given this.

0
verbose int

If positive, log search progress.

0

Attributes:

Name Type Description
features_

Selected :class:~beamfeat.expression.Node expressions.

feature_formulas_

Their formula strings.

search_result_

The :class:~beamfeat.search.SearchResult.

selection_result_

The :class:~beamfeat.selection.SelectionResult, or None if no selector was used.

n_features_out_

Number of features produced.

fit(X, y=None)

Construct and select features from the training data.

Parameters:

Name Type Description Default
X

(n_samples, n_features) training data.

required
y

Target. Required, since both search and selection are supervised.

None

Returns:

Type Description

self.

transform(X)

Evaluate the selected expressions on new data.

Selection

False-discovery-rate controlled feature selection.

Feature construction proposes far more candidates than any dataset can support, so selection is where spurious features are either excluded or silently admitted. This module provides selectors that control the false discovery rate — the expected proportion of selected features that are spurious — and is explicit about the assumptions under which each guarantee holds.

:class:PermutationSelector (default) An exact permutation test of marginal association, corrected for multiplicity. The test statistic is a fixed function of the data (|Pearson correlation| for regression, eta-squared for classification), so permuting the target yields exact p-values for the null hypothesis that a feature is marginally independent of the target (Phipson & Smyth, 2010). Multiplicity is handled by Benjamini-Hochberg, valid under positive regression dependence, or Benjamini-Yekutieli, valid under arbitrary dependence (Benjamini & Yekutieli, 2001). This class defaults to the former; the estimators default to the latter, since engineered candidates share parents and positive dependence cannot be assumed.

The marginal null composes correctly with constructed features: two
near-duplicate expressions of one true signal are *both* genuinely
associated with the target, so selecting both is not a false discovery
under this null. De-duplication is the job of the redundancy pass, not
the error-control procedure.

:class:KnockoffSelector The knockoff filter. Two constructions are provided and routed automatically:

- **Fixed-X** (Barber & Candès, 2015), used when ``n >= 2p``. Treats the
  design as fixed and makes *no distributional assumption about the
  features* — deterministic engineered columns are fine. The guarantee
  requires the linear model ``y = X beta + noise`` with Gaussian,
  homoskedastic noise. On near-singular designs the construction remains
  valid but its power degrades toward zero, because the knockoffs become
  nearly identical to the originals.
- **Model-X Gaussian** (Candès et al., 2018), used when ``n < 2p``.
  Requires the features to be jointly Gaussian, which engineered
  features are not; a warning is recorded when the design is visibly
  degenerate.

Selective inference caveat. Every guarantee above is for testing a candidate set that is fixed before seeing the data used for testing. If candidates were chosen by a search on the same data — chosen, in part, because they correlate with this sample's target — the p-values are optimistically biased and the nominal FDR is not guaranteed. The estimators in :mod:beamfeat.estimators therefore hold out a split of the training data for selection by default; see selection_holdout.

References

Barber, R. F. & Candès, E. J. (2015). Controlling the false discovery rate via knockoffs. Annals of Statistics, 43(5), 2055-2085.

Benjamini, Y. & Hochberg, Y. (1995). Controlling the false discovery rate. JRSS-B, 57(1), 289-300.

Benjamini, Y. & Yekutieli, D. (2001). The control of the false discovery rate in multiple testing under dependency. Annals of Statistics, 29(4), 1165-1188.

Candès, E., Fan, Y., Janson, L. & Lv, J. (2018). Panning for gold: model-X knockoffs. JRSS-B, 80(3), 551-577.

Phipson, B. & Smyth, G. K. (2010). Permutation p-values should never be zero. Stat. Appl. Genet. Mol. Biol., 9(1), Article 39.

KnockoffSelector

Bases: Selector

Knockoff filter with automatic fixed-X / model-X routing.

Fixed-X (Barber & Candès, 2015) is used when n >= 2p. The design is treated as fixed, so no assumption about the distribution of the features is required — deterministic engineered columns are admissible. The finite-sample FDR guarantee (with offset=1) requires the linear model y = X beta + eps with i.i.d. Gaussian noise. On a near-singular design the construction is still valid but the equicorrelated s shrinks toward zero, the knockoffs become nearly identical to the originals, and power degrades toward zero; a warning records this.

Model-X Gaussian (Candès et al., 2018) is used when n < 2p, where the fixed-X construction does not exist. It requires the features to be jointly Gaussian, an assumption engineered features violate; a warning is recorded when the design is visibly degenerate. Prefer :class:PermutationSelector in that regime.

Power and the offset. offset=1 requires (1 + #negatives)/#positives <= target_fdr, unsatisfiable with fewer than 1/target_fdr features regardless of signal; measured on a 25-feature Gaussian design at level 0.1, offset=1 recovered almost nothing while offset=0 recovered everything. offset=1 remains the default because it is the stated finite-sample guarantee; a warning fires when the design is too narrow for it.

Parameters:

Name Type Description Default
target_fdr float

Nominal false discovery rate.

0.1
problem_type ProblemType

"regression" or "classification". The fixed-X guarantee is stated for regression; classification uses the same machinery heuristically and records a warning.

'regression'
random_state int | None

Seed (used by the model-X sampler and the orthogonal complement basis).

0
offset Offset

1 for knockoff+ (default), 0 for the modified-FDR filter.

1
shrinkage float

Ridge term added to the covariance diagonal for numerical stability.

1e-06
construction Literal['auto', 'fixed', 'gaussian']

"auto" (default), "fixed", or "gaussian".

'auto'
warn_on_violation bool

Whether to check assumptions and record findings.

True

PermutationSelector

Bases: Selector

Exact permutation test of marginal association, with FDR correction.

Statistic. For regression, the absolute Pearson correlation between each feature and the target; for classification, eta-squared (the between-class share of each feature's variance). Both are fixed functions of (X_j, y), which is the condition for a permutation test to be exact: comparing the observed statistic to the same statistic computed on (X_j, pi(y)) over random permutations pi yields a valid p-value for the null that X_j is marginally independent of y, via the add-one estimator (1 + #exceedances) / (B + 1) (Phipson & Smyth, 2010). Statistics that re-tune themselves on the observed target — a cross-validated lasso penalty, for instance — do not satisfy this condition unless the tuning is repeated inside every permutation.

What the null means for constructed features. Marginal independence is the appropriate null here: an expression that genuinely co-varies with the target is a true discovery even if another selected expression carries the same information. Redundancy among true discoveries is resolved by the redundancy pass in the search, not by the error-control procedure.

Multiplicity. Benjamini-Hochberg by default, which controls FDR under positive regression dependence; set correction="by" for the Benjamini-Yekutieli procedure, valid under arbitrary dependence at the cost of a log(m)-factor in power.

Resolution. The smallest attainable p-value is 1/(B + 1), and Benjamini-Hochberg requires the leading feature to reach target_fdr / m. B therefore must be at least m / target_fdr - 1 for selection to be possible at all, and one further null exceedance doubles the requirement. When auto_permutations is on (default), B is raised to ceil(2 m / target_fdr) — satisfiable with headroom for a single exceedance — capped at max_permutations. Because the statistic is a single matrix product, even B = 100000 costs well under a second at typical sizes.

Parameters:

Name Type Description Default
target_fdr float

Nominal false discovery rate.

0.1
problem_type ProblemType

"regression" or "classification".

'regression'
random_state int | None

Seed for the permutation draws.

0
n_permutations int

Minimum number of permutations.

2000
auto_permutations bool

Raise B to the satisfiability bound when needed.

True
max_permutations int

Hard cap on B.

100000
correction Literal['bh', 'by']

"bh" (Benjamini-Hochberg, default) or "by" (Benjamini-Yekutieli, arbitrary dependence).

'bh'

SelectionResult dataclass

Outcome of a selection run.

Attributes:

Name Type Description
selected ndarray

Indices of the selected features, ascending.

statistics ndarray

Importance statistic per feature. For the permutation selector this is 1 - p_value so that larger is better; for knockoffs it is the antisymmetric statistic W.

p_values ndarray | None

Exact permutation p-values, where the method produces them.

threshold float

The data-dependent cut applied to :attr:statistics. inf means nothing met the criterion.

target_fdr float

The nominal FDR level requested.

n_candidates int

Number of features considered.

method str

Name of the selector used.

warnings_raised list[str]

Assumption or configuration issues detected.

n_selected property

Number of features selected.

mask()

Boolean mask over the candidate features.

summary()

Human-readable summary of the run.

Selector

Bases: ABC

Base class for FDR-controlled selectors.

select(features, target) abstractmethod

Select features controlling the FDR at :attr:target_fdr.

knockoff_threshold(statistics, target_fdr, offset=1)

Data-dependent threshold of the knockoff filter.

Finds the smallest positive cut t at which (offset + #{W_j <= -t}) / #{W_j >= t} <= target_fdr. offset=1 gives knockoff+ (finite-sample FDR control); offset=0 controls a modified FDR.

make_selector(selector, target_fdr=0.1, problem_type='regression', random_state=0, **kwargs)

Resolve a selector name or instance into a :class:Selector.

Guided beam search for feature construction.

Parameters:

Name Type Description Default
scorer str | Scorer

Scoring strategy. Either a name ("correlation", "mutual_information", "gradient_boosting", or an alias such as "mi") or a :class:~beamfeat.scoring.Scorer instance. Defaults to "correlation", which is the only choice cheap enough for wide beams; see :class:~beamfeat.scoring.GradientBoostingScorer for the tradeoff.

'correlation'
problem_type ProblemType

"regression" or "classification".

'regression'
max_depth int

Maximum expression depth. Depth 1 permits single transforms and pairwise combinations of inputs; each further depth composes on the results of the last.

2
beam_width int

Expressions retained at each depth. This is the parameter that bounds cost: total work is roughly max_depth * beam_width * n_operators, rather than compounding.

50
max_features int | None

Maximum features returned. Defaults to beam_width.

None
unary_ops Sequence[str]

Unary operators to apply. Defaults to log, sqrt, reciprocal, square, and abs.

DEFAULT_UNARY
binary_ops Sequence[str]

Binary operators to apply. Defaults to mul, div, add, sub.

DEFAULT_BINARY
redundancy_threshold float

Absolute correlation above which a candidate is considered a duplicate of one already in the beam and dropped.

0.95
include_originals bool

Whether input columns are eligible for the final result alongside constructed expressions.

True
max_candidates_per_depth int

Hard ceiling on candidates constructed at one depth, as a guard against a wide beam and many operators producing an unaffordable round. Candidates beyond the ceiling are not proposed; the beam is traversed in score order so the truncation falls on the least promising parents.

200000
random_state int | None

Seed passed to the scorer. Search itself is deterministic.

0
verbose int

If positive, log progress at each depth.

0

Attributes:

Name Type Description
result_ SearchResult | None

:class:SearchResult from the most recent :meth:run.

run(data, target, columns=None, units=None, evaluator=None)

Execute the search.

Parameters:

Name Type Description Default
data Any

Mapping of column name to array, or a 2-D array. Ignored if evaluator is supplied.

required
target ndarray

Target vector, one entry per row.

required
columns Sequence[str] | None

Column names, when data is a 2-D array.

None
units dict[str, Any] | None

Optional mapping of column name to pint quantity. Supplying units restricts the search to dimensionally valid expressions.

None
evaluator Evaluator | None

A pre-built :class:~beamfeat.expression.Evaluator, to reuse a warm cache across runs.

None

Returns:

Name Type Description
A SearchResult

class:SearchResult. Also stored on :attr:result_.

Expressions

Lazily evaluates nodes against a data matrix, caching by structural key.

The cache is bounded and least-recently-used. Leaf columns are pinned and never evicted, since they are the base of every expression. Intermediate results are evicted under memory pressure and recomputed if needed again.

Numerical failures are recorded in :attr:log and reported by returning None from :meth:evaluate; they never propagate as exceptions and are never silently discarded.

Parameters:

Name Type Description Default
data Mapping[str, ndarray] | ndarray

Mapping of column name to 1-D array, or a 2-D array with columns supplied separately.

required
columns Sequence[str] | None

Column names, required when data is a 2-D array.

None
units Mapping[str, Any] | None

Optional mapping of column name to pint quantity.

None
dtype dtype | type

Working dtype. Defaults to float64; float32 halves memory but makes overflow substantially more likely in deep expressions.

float64
cache_size int

Maximum number of non-leaf arrays held in the cache.

4096
variance_tol float

Results with variance below this are excluded as constant.

1e-10

columns property

Names of the available input columns.

dtype property

Working dtype for evaluation.

n_rows property

Number of rows in the data.

cache_info()

Return current cache occupancy and capacity.

clear_cache()

Evict all cached intermediate results. Leaves are retained.

evaluate(node, apply_filters=True)

Compute the values of node, using and updating the cache.

Parameters:

Name Type Description Default
node Node

The expression to evaluate.

required
apply_filters bool

Whether to apply the search-time admissibility filters — zero variance, and the operators' domain predicates. These express whether a candidate is worth exploring, and they are data-dependent: a column that varies across a training set may be constant within some subset of it. At transform time that must not change the result, so :meth:transform_values passes False and computes the expression unconditionally. Genuine numerical failures (overflow, non-finite results) are still caught either way.

True

Returns:

Type Description
ndarray | None

A 1-D array of length :attr:n_rows, or None if the node was

ndarray | None

excluded. When None is returned, the reason is appended to

ndarray | None

attr:log.

evaluate_many(nodes)

Evaluate several nodes, returning only those that survived.

Parameters:

Name Type Description Default
nodes Sequence[Node]

Expressions to evaluate.

required

Returns:

Type Description
list[Node]

A tuple of (surviving nodes, matrix with one column per surviving

ndarray

node in the same order). If nothing survives, the matrix has shape

tuple[list[Node], ndarray]

(n_rows, 0).

leaf_nodes()

Return leaf nodes for every input column, with units attached.

transform_values(node)

Compute node without applying search-time admissibility filters.

Use this when replaying an already-selected expression on new data. Applying the search filters here would make the output depend on which rows are present — a subset in which some column happens to be constant would silently yield a different answer than the full data.

Returns:

Type Description
ndarray | None

The computed values, or None if the expression genuinely cannot

ndarray | None

be evaluated (overflow, or a non-finite result).