NLRS: Non-Standard Linear Regression Methods with Sparsity
A Python Library for Non-Standard Linear Regression Methods with Sparsity.
The source code is available on GitHub.
Description
The nlrs library formulates linear regression and support vector regression (SVR) as convex optimization problems with a range of regularizers: the sparsity-inducing Lasso and Elastic Net, as well as the non-sparse Ridge.
Built on the Python-embedded modeling language CVXPY, nlrs complements scikit-learn by adding modeling constraints, loss functions, and adaptive penalties that scikit-learn does not cover. Because the problems are solved through CVXPY, nlrs interfaces natively with open-source solvers such as ECOS, OSQP, Clarabel, and SCS, as well as commercial ones such as CPLEX and Gurobi.
Key capabilities
- Adaptive penalties: models support
adaptive=True, which scales \(\ell_1\) or \(\ell_2\) penalties by inverse-magnitude weights of the form \(\omega_j = 1/|\hat\beta_j|^{\gamma}\) with \(\gamma > 0\) (often \(\gamma = 1\)), where \(\hat\beta\) comes from a previous fit, for example a linear regression orRidgeCV. Note that the \(\ell_2\) variants shrink the coefficients but do not yield sparse solutions. For combinedl1_l2penalties, the adaptive weights apply to the \(\ell_1\) component only. - Constraints:
positive=Truerestricts all estimated coefficients to \(\geq 0\). - Multi-task regression:
MultiTaskRegressorsupports grouped shrinkage (Lasso, Elastic Net, SVR) by applying the mixed \(\ell_{2,1}\) norm, so that feature relevance is assessed jointly across all target variables. - scikit-learn compatibility: all models inherit from
BaseEstimatorandRegressorMixinand are designed to work with scikit-learn cross-validation, pipelines, and grid search.
Documentation
Read the documentation on GitLab Pages.
Installation
You can install nlrs locally by cloning the repository and installing it via pip:
git clone https://github.com/trholy/nlrs
cd nlrs
pip install .
Methods
The formulations below represent the objectives minimized via CVXPY.
Standard linear models (nlrs.linear_model.linear)
LinearRegression
- Loss: \(\vert\vert X \beta - y \vert\vert_2^2\)
- Constraints:
fit_intercept,positive=True
Lasso
- Loss: \(\frac{1}{2n} \vert\vert X \beta - y \vert\vert_2^2\)
- Penalties:
- \(\ell_1\)-penalty: \(\alpha \cdot \vert\vert \beta \vert\vert_1\)
- Adaptive \(\ell_1\)-penalty: \(\alpha \cdot \sum_{j=1}^{p} \omega_j | \beta_j |\)
Ridge
- Loss: \(\vert\vert X \beta - y \vert\vert_2^2\)
- Penalties:
- \(\ell_2\)-penalty: \(\alpha \cdot \vert\vert \beta \vert\vert_2^2\)
- Adaptive \(\ell_2\)-penalty: \(\alpha \cdot \sum_{j=1}^{p} \omega_j \beta_j^2\)
ElasticNet
- Loss: \(\frac{1}{2n} \vert\vert X \beta - y \vert\vert_2^2\)
- Penalties: combines \(\ell_1\) (scaled by \(\alpha \cdot \ell_1\text{-ratio}\)) and \(\ell_2\) (scaled by \(\tfrac{1}{2} \cdot \alpha \cdot (1 - \ell_1\text{-ratio})\)), i.e. with \(\rho = \ell_1\text{-ratio}\):
MultiTaskRegressor
- Loss functions:
squared_error,epsilon_insensitive,squared_epsilon_insensitive,huber,quantile,mae(alias:mean_absolute_error). - Penalties: for a coefficient matrix \(B\) (features × tasks), the \(\ell_{2,1}\) penalty \(\sum_j \|B_{j\cdot}\|_2\) sums the \(\ell_2\) norms of the rows, i.e. of each feature's coefficients across all tasks. This removes a feature from all tasks jointly.
- Adaptive weights: not supported for multi-task regression.
Support vector machines (nlrs.linear_model.svm)
LinearSVR
Uses the epsilon-insensitive loss \(L_\epsilon(r)=\max(0,|r|-\epsilon)\): residuals with \(|r|\le\epsilon\) incur zero loss.
- Loss functions: all losses from
nlrs.objectives.losses.get_loss_exprare supported:squared_error,sum_squares,epsilon_insensitive,squared_epsilon_insensitive,huber,quantile,mae(aliasmean_absolute_error). Withsquared_error, the model is effectively a penalized least-squares regression rather than an SVR. - Penalties: \(\ell_1\), \(\ell_2\), and elastic net penalties are built in. Adaptive weights apply to a pure \(\ell_1\) or \(\ell_2\) penalty; for the combined \(\ell_1\ell_2\) penalty, only the \(\ell_1\) part is weighted.
- A note on the intercept:
nlrs.linear_model.svm.LinearSVRdoes not regularize the intercept, whereas scikit-learn and liblinear do regularize the intercept feature (intercept_scaling).
Project structure
./
├── .gitignore
├── .gitlab-ci.yml
├── LICENSE
├── README.md
├── THIRD_PARTY_LICENSES.txt
├── docs
│ ├── linear_model
│ │ ├── base.md
│ │ ├── linear.md
│ │ └── svm.md
│ ├── objectives
│ │ ├── losses.md
│ │ └── regularizers.md
│ ├── solvers
│ │ └── base.md
│ └── utils
│ ├── selection.md
│ └── validation.md
├── examples
│ ├── adaptive_lasso.py
│ ├── multitask_lasso.py
│ └── multitask_svr.py
├── mkdocs.yml
├── pyproject.toml
├── setup.py
├── src
│ └── nlrs
│ ├── __init__.py
│ ├── linear_model
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── linear.py
│ │ └── svm.py
│ ├── objectives
│ │ ├── __init__.py
│ │ ├── losses.py
│ │ └── regularizers.py
│ ├── solvers
│ │ ├── __init__.py
│ │ └── base.py
│ └── utils
│ ├── __init__.py
│ ├── selection.py
│ └── validation.py
└── tests
├── test_AdaptiveWeights.py
├── test_adaptive.py
├── test_adaptive_advanced.py
├── test_collinear.py
├── test_edge_cases.py
├── test_linear.py
├── test_losses.py
├── test_multitask.py
├── test_multitask_advanced.py
├── test_regularizers.py
├── test_sklearn_compat.py
├── test_svm.py
└── test_validation.py
License
This project is licensed under the MIT License. See the LICENSE file for more details.