crabbymetrics
  • Home
  • API
    • API Overview
    • Regression And GLMs
    • Survival / Event-Time
    • Causal Inference And Panels
    • Hypothesis Testing And Utilities
    • Transforms
    • Estimation Interfaces
  • Binding Crash Course
  • Regression And GLMs
    • OLS
    • ABC OLS
    • Anytime-Valid Confidence Sequences
    • Ridge
    • Bagged Polynomial Regression
    • Fixed Effects OLS
    • ElasticNet
    • Logit
    • Multinomial Logit
    • Poisson
    • MLE Prediction Interface
    • Survival / Recurrent Events
    • GMM
    • MEstimator Poisson
  • Causal Inference
    • Balancing Weights
    • EPLM
    • Average Derivative
    • Double ML And AIPW
    • Richer Regression
    • TwoSLS
    • Synthetic Control
    • Synthetic DID
    • Horizontal Panel Ridge
    • Matrix Completion
    • Interactive Fixed Effects
    • Staggered Panel Event Study
    • Joint Hypothesis Tests
  • Transforms
    • PCA And Kernel Basis
  • Ablations
    • Variance Estimators
    • Semiparametric Estimator Comparisons
    • Two-Period Semiparametric DID
    • Bridging Finite And Superpopulation
    • Panel Estimator DGP Comparisons
    • Same Root Panel Case Studies
    • Randomized Sketching And Least Squares
  • Optimization
    • Optimizers
    • GMM With Optimizers
  • Ding: First Course
    • Overview And TOC
    • Ch 1 Correlation And Simpson
    • Ch 2 Potential Outcomes
    • Ch 3 CRE And Fisher RT
    • Ch 4 CRE And Neyman
    • Ch 9 Bridging Finite And Superpopulation
    • Ch 11 Propensity Score
    • Ch 12 Double Robust ATE
    • Ch 13 Double Robust ATT
    • Ch 21 Experimental IV
    • Ch 23 Econometric IV
    • Ch 27 Mediation

On this page

  • 1 Where it fits
  • 2 Base-learner objective
  • 3 Implementation walkthrough
  • 4 Diagnostics and inference
  • 5 Performance and resource limits
  • 6 Python API
  • 7 Minimal example
  • 8 summary() contract
  • 9 Resource policy

BaggedPolynomialRegressor

Bagged random-subspace polynomial ridge regression

from _api_doc_utils import *

1 Where it fits

Group: Regression

BaggedPolynomialRegressor is a prediction-only ensemble. Each base learner samples rows and a feature subspace, expands the selected features into monomials of total degree one through \(d\), standardizes those polynomial columns, fits ridge regression, and contributes to the averaged prediction.

For \(k\) selected features, each base learner uses

\[ \binom{k+d}{d}-1 \]

non-intercept polynomial terms. The estimator checks this count and the dense design size before allocation.

2 Base-learner objective

For learner \(b\), let \(I_b\) be its sampled rows and \(J_b\) its sampled feature subset. The implementation enumerates every monomial in \(x_{J_b}\) with total degree from one through \(d\). If \(\phi_b(x)\) is that \(q\)-term vector, it computes in-bag means \(\mu_b\) and population-standard-deviation scales \(s_b\), then fits

\[ (\hat a_b,\hat\gamma_b) = \arg\min_{a,\gamma} \sum_{i\in I_b} \left[ y_i-a-\left\{\frac{\phi_b(x_i)-\mu_b}{s_b}\right\}'\gamma \right]^2 +\lambda\|\gamma\|_2^2. \]

Zero-variance terms retain scale one. The ensemble prediction is the simple average

\[ \hat f(x)=\frac1B\sum_{b=1}^B \left[ \hat a_b+\left\{\frac{\phi_b(x)-\mu_b}{s_b}\right\}'\hat\gamma_b \right]. \]

Rows are sampled with replacement when bootstrap sampling is enabled. Otherwise the learner uses a shuffled subset without replacement. Feature subsets are always sampled without replacement.

3 Implementation walkthrough

The ensemble, polynomial expansion, standardization, ridge solve, and OOB accounting are all implemented in the package.

  1. Before drawing anything, the fit resolves max_features and max_samples, computes \(q=\binom{k+d}{d}-1\) with checked 128-bit arithmetic, and checks both the term limit and the proposed dense design size. It then generates the term specification once for a \(k\)-variable local coordinate system and shares that immutable list across all learners.
  2. Terms are generated degree by degree by a recursion over nondecreasing feature indices. Repeated indices create powers and distinct indices create interactions: for two local variables and degree two, the order is \(x_0,x_1,x_0^2,x_0x_1,x_1^2\). The implementation evaluates each term by starting from ones and multiplying the referenced columns; it does not use a symbolic polynomial library.
  3. One seeded Rust RNG drives the entire ensemble. A bootstrap learner draws max_samples row indices independently with replacement; a nonbootstrap learner shuffles all row indices, truncates, and sorts them. Features are independently shuffled, truncated without replacement, and sorted. Sorting makes stored subspaces deterministic to inspect but does not change the draw.
  4. The learner selects its raw columns, materializes the full in-bag polynomial matrix, and standardizes each term with its in-bag population variance (denominator \(m\), not \(m-1\)). A standard deviation at or below \(10^{-12}\) is replaced by one, so a constant term becomes a centered zero column rather than producing division by zero.
  5. An intercept is prepended and ridge is fit with the same augmented-QR primitive as Ridge: \(\sqrt{\lambda}I\) rows are appended for polynomial slopes, while the intercept is unpenalized. The learner stores its selected original-column indices, shared term list, in-bag means and scales, coefficient vector, and in-bag MSE.
  6. For bootstrap fits, each completed learner immediately predicts all training rows. Its prediction is accumulated only for rows never drawn by that learner. At the end, each covered row’s accumulated prediction is divided by its OOB learner count; MSE and coverage are computed on that covered subset. Duplicate in-bag draws are tracked as one Boolean membership for this purpose.
  7. At prediction time every learner repeats raw-column selection and monomial construction, applies that learner’s own stored centering and scaling, and multiplies by its coefficient vector. The public result is the unweighted arithmetic mean across learners. There is no pruning or coefficient pooling across repeated subspaces.

Two design choices matter statistically. Standardizing inside each bootstrap sample makes the ridge penalty comparable across terms within a learner, but it also makes each learner’s coordinate system sample-dependent. Sharing a term specification is valid because every learner selects exactly \(k\) features and the term indices are local positions; it saves metadata, not polynomial computation.

4 Diagnostics and inference

This is a prediction estimator and has no coefficient-level analytic inference. With bootstrap row sampling, an observation’s out-of-bag prediction averages only learners for which that observation was absent from \(I_b\); the reported OOB MSE is computed over covered observations and the coverage fraction is reported separately. No OOB statistic is produced for sampling without replacement, even if a learner uses fewer than all rows. The OOB MSE is a prediction diagnostic, not a standard error or confidence interval.

5 Performance and resource limits

For \(k\) selected raw features,

\[ q=\binom{k+d}{d}-1 \]

grows combinatorially. One learner stores a dense \(m\times q\) design and costs roughly \(O(mq^2+q^3)\) to fit; prediction costs \(O(nq)\) per learner. Total work is multiplied by \(B\). OOB computation currently asks every bootstrap learner to predict all \(n\) training rows before retaining only uncovered rows.

The implementation rejects \(q>100{,}000\) and any single polynomial design above 50 million cells. These guards prevent the largest allocations but still permit expensive dense fits. Reducing selected features is usually more effective than reducing rows because \(q\) is combinatorial in feature count and degree. Learners are fit serially, and no polynomial matrix is shared across different feature subspaces.

6 Python API

Constructor: cm.BaggedPolynomialRegressor

Use BaggedPolynomialRegressor(n_estimators, degree, max_features, max_samples, bootstrap, penalty, seed), then fit(x, y), predict(x), and summary(). It does not report coefficient standard errors. With bootstrap sampling, summary() reports out-of-bag MSE and coverage.

print(inspect.signature(cm.BaggedPolynomialRegressor))
(n_estimators=50, degree=2, max_features=None, max_samples=None, bootstrap=True, penalty=1.0, seed=42)
display(HTML(html_table(["Public method"], public_methods(cm.BaggedPolynomialRegressor))))
Public method
fit(self, /, x, y)
predict(self, /, x)
summary(self, /)

7 Minimal example

rng = np.random.default_rng(18)
x = rng.normal(size=(320, 6))
y = 0.5 + 0.8 * x[:, 0] * x[:, 1] - 0.4 * x[:, 2] ** 2
y += rng.normal(scale=0.2, size=x.shape[0])

model = cm.BaggedPolynomialRegressor(
    n_estimators=40,
    degree=2,
    max_features=4,
    max_samples=240,
    penalty=0.5,
    seed=18,
)
model.fit(x, y)
print(model.predict(x[:3]))
print(model.summary()["oob_mse"])
[ 0.35052417 -0.18592581 -0.03055871]
0.37199936832351177

8 summary() contract

summary = model.summary()
display(HTML(html_table(["summary() key", "shape"], summary_shape_rows(summary))))
summary() key shape
n_estimators ()
degree ()
max_features ()
max_samples ()
bootstrap ()
penalty ()
seed ()
n_features_in ()
n_terms ()
feature_indices (40, 4)
term_counts (40,)
train_mse (40,)
oob_mse ()
oob_coverage ()
inference_available ()

max_features and max_samples are resolved fitted values rather than possible None constructor values. n_terms is the checked polynomial width per base learner. feature_indices records each random subspace. oob_mse is None when no observation receives an out-of-bag prediction.

9 Resource policy

Polynomial expansion is dense. The implementation rejects more than 100,000 polynomial terms per learner or more than 50 million cells in one polynomial design. Reduce degree, max_features, or max_samples when a guard triggers.