Skip to main content

rsoselect

tests PyPI Python License

Variable selection with the ridge selection operator (RSO) for linear, partially linear, and generalized partially linear models.

Ridge regression with an individual penalty per coefficient can select variables: if the penalty on a coefficient goes to infinity, that coefficient is exactly zero. RSO puts a budget on the inverse penalties and lets the data decide where to spend it (Wu, 2021). The same idea, applied to the inverse bandwidths of a kernel smoother, selects nonparametric predictors as well, so linear and nonlinear predictors are chosen in one optimization problem (Lu et al., 2024; Lu, Hu and Wu, 2025).

model class paper
y = Xβ + ε RSO Wu (2021), Technometrics
y = Xβ + f(Z) + ε PLM Lu, Dong, Hu and Wu (2024), JCGS
g(E[y]) = Xβ + f(Z) GPLM Lu, Hu and Wu (2025), Journal of Nonparametric Statistics

Installation

pip install rsoselect                # core
pip install "rsoselect[sklearn]"     # with scikit-learn integration

From source:

git clone https://github.com/luyouhanzju/rsoselect.git
cd rsoselect
pip install -e .

Requires Python 3.9+, NumPy and SciPy. scikit-learn is optional (needed only for criterion="cv" and for using RSO inside sklearn pipelines).

Quick start

from rsoselect import RSO, PLM, GPLM

# Linear model: drop-in replacement for sklearn's Ridge
m = RSO().fit(X, y)
m.support_          # selected predictors (boolean mask)
m.coef_, m.intercept_
m.predict(X_new)

# Partially linear model: X enters linearly, Z nonparametrically
m = PLM().fit(X, Z, y)
m.support_x_, m.support_z_
m.predict(X_new, Z_new)

# Generalized partially linear model (binomial, poisson or gaussian)
m = GPLM(family="binomial").fit(X, Z, y)
m.predict(X_new, Z_new)        # probabilities
m.predict_eta(X_new, Z_new)    # linear predictor

How it works

For a budget τ, RSO solves

min over gamma:   RSS( beta(gamma) )
subject to:       gamma_k >= 0,  sum_k gamma_k = tau

beta(gamma) = argmin_b  (1/n) ||y - X b||^2 + sum_k b_k^2 / gamma_k

so γk = 0 gives βk = 0 exactly. In the PLM and GPLM the nonparametric part is a kernel smoother with inverse bandwidths λj under a second budget ∑λj = τ2; λj = 0 removes Zj. The GPLM is fit by local scoring, and (γ, λ) minimize the negative log-likelihood. All three models are optimized by the same modified coordinate descent (rsoselect.mcd).

The budgets are tuned over a grid:

model criteria (default first)
RSO "profile_bic" (OLS refit on the selected set), "naive_bic", "cv", "loo"
PLM "profile_bic" (local linear refit, eq. 10), "naive_bic" (eq. 7)
GPLM "refit_bic" (eq. 5.17), "naive_bic" (eq. 4.11)

For time series, use RSO(criterion="cv", cv=TimeSeriesSplit(5)).

criterion="loo" is the closed-form leave-one-out error (PRESS), e_i / (1 - h_ii) with H the hat matrix of the reported fit. It costs one fit per budget and needs no scikit-learn. It holds gamma fixed at the full-sample estimate, so it is optimistic relative to exact leave-one-out, which is RSO(criterion="cv", cv=LeaveOneOut()) (one fit per observation and budget). Like AIC, LOO targets prediction error and may keep a few more variables than BIC.

Stochastic discount factors (MSRR)

Ridge estimates of SDF weights minimize mean((1 - F @ lam)**2) + penalty, where F holds the factor returns (T x P). That is a regression of a vector of ones on F with no intercept, so RSO applies directly, and "loo" gives leave-one-period-out selection of the budget:

P = F_train.shape[1]
z = 10.0 ** np.arange(-10, 4)      # ridge penalties, e.g. Kelly et al.'s grid
m = RSO(criterion="loo", taus=P / z, fit_intercept=False, standardize=False,
        refit=False)
m.fit(F_train, np.ones(len(F_train)))
lam = m.coef_                      # SDF / portfolio weights, zero for dropped factors
r_sdf = F_test @ lam               # out-of-sample SDF portfolio returns

Keep fit_intercept=False: an intercept would absorb the vector of ones and set every weight to zero. With uniform gamma, the RSO penalty is (P / tau) * lam @ lam, so taus = P / z puts the budgets on the same scale as a ridge penalty z (the default taus assume standardized columns and are too small for raw returns). P / m.tau_ is the ridge-equivalent penalty of the selected budget.

Main parameters

RSO

parameter default meaning
tau None fixed budget; None tunes over taus
taus p * logspace(0.05, 50, 30) candidate budgets (X standardized)
criterion "profile_bic" how tau is chosen
refit True final coefficients by OLS on the selected predictors
select_threshold 1e-2 gamma_k above this means selected

PLM / GPLM

parameter default meaning
taus1, taus2 log grids (12 x 8 / 8 x 5) budgets for gamma and lambda
criterion see table above how the budgets are chosen
refit True final fit without the ridge penalty on the selected model
family (GPLM) "binomial" "binomial", "poisson", "gaussian"
max_sweeps 5 / 9 coordinate descent passes

Shared optimizer settings: grid=(0, .2, .5, .8, 1), tol=1e-4, standardize=True. After fitting, path_ holds every budget on the grid with its gamma, lambda, selected sets and criterion values, which is enough to draw solution paths.

Reproducing the published results

The defaults implement the estimators as written in the papers. Setting r_compat=True reproduces the original R implementation used for the numerical results in the papers; the test suite checks this line by line against ports of the R functions. The two modes differ in:

default r_compat=True
local constant kernel product Gaussian exp(-(sum_j lambda_j abs(dz_j))^2)
GPLM weights in the beta step W sqrt(W / sum W)
GPLM weights in the smoother sample weights w_k unweighted
GPLM BIC -2 loglik + log(n) df -loglik + log(n) df
GPLM refit bandwidths selected lambda uniform over selected predictors
standardization X scaled, Z centered and scaled none

Tests

pip install -e ".[test]"
pytest

References

If you use this package, please cite:

@article{wu2021ridge,
  author  = {Wu, Yichao},
  title   = {Can't Ridge Regression Perform Variable Selection?},
  journal = {Technometrics},
  volume  = {63},
  number  = {2},
  pages   = {263--271},
  year    = {2021},
  doi     = {10.1080/00401706.2020.1791254}
}

@article{lu2024plm,
  author  = {Lu, Youhan and Dong, Yushen and Hu, Juan and Wu, Yichao},
  title   = {A Unified Approach to Variable Selection for Partially Linear Models},
  journal = {Journal of Computational and Graphical Statistics},
  volume  = {33},
  number  = {1},
  year    = {2024},
  doi     = {10.1080/10618600.2023.2216254}
}

@article{lu2025gplm,
  author  = {Lu, Youhan and Hu, Juan and Wu, Yichao},
  title   = {A New Approach to Select Linear and Nonparametric Predictors Simultaneously
             for Generalised Partially Linear Models},
  journal = {Journal of Nonparametric Statistics},
  volume  = {37},
  number  = {4},
  pages   = {1298--1316},
  year    = {2025},
  doi     = {10.1080/10485252.2025.2556412}
}

An R implementation of linear RSO by other authors is available on CRAN as RSO.

License

BSD 3-Clause. See LICENSE.

Metadata

Release files for rsoselect 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for rsoselect 0.3.0
File Size Uploaded Provenance
rsoselect-0.3.0.tar.gz 28.4 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for rsoselect 0.3.0
File Interpreter ABI Platform
rsoselect-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 52.9 kB

Release files / rsoselect-0.3.0.tar.gz

Download URL rsoselect-0.3.0.tar.gz
Size 28.4 kB
Tags Source
SHA-256 checksum
How to use checksums
31f24b6f5a5dd7853cd5bf121df9ebafc7a44d4467bbf0dbe799a5d4eb93c07f
BLAKE2b-256 checksum
How to use checksums
b3335d6805d922393289361eba4e75be376c1b61c195f5fb2cd81be241f55626
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Release files / rsoselect-0.3.0-py3-none-any.whl

Download URL rsoselect-0.3.0-py3-none-any.whl
Size 24.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7bfbd51e87cc0423645234fb78b223e184c052c05037e3757a0cb767a92b24ed
BLAKE2b-256 checksum
How to use checksums
bd331c7530742f6934aea1de8cf1708b7324d081597159512fbef23cacbab49d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Security for rsoselect 0.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for rsoselect-0.3.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page