glmnet's elastic-net coordinate descent, ported to Rust
Project description
glmnet-rs
A port of glmnet's elastic-net coordinate descent to Rust, with a Python front end.
Ported from glmnetpp (the C++17 core of R glmnet >= 4.1), not the legacy
Fortran, and validated against R glmnet 5.0.
Status: Gaussian, two-class binomial (logistic), and Poisson (dense X),
plus sparse X for Gaussian and binomial (CSC). Cross-validation, summaries,
and R-style plots are implemented. ~90 parity fixtures pass at ~1e-14 relative
error with iteration counts (npasses) identical to R — the sparse ones against
R's own sparse path — and coefficients match R to ~1e-13 on real long/wide
datasets (see datasets/). What's still missing (multinomial, Cox,
relax, offsets, sparse Poisson, …) is tracked in
docs/ROADMAP.md; porting notes are in
docs/PORTING.md.
Example: examples/glmnet_demo.ipynb is a runnable
tour on two real datasets — Wine Quality (long, gaussian) and Leukemia gene
expression (wide, binomial) — covering the path, cross-validation, plots, and
prediction.
Layout
crates/glmnet-core/ pure Rust kernels (no Python, no C)
crates/glmnet-py/ PyO3 bindings, deliberately thin
python/glmnetrs/ the user-facing package
scripts/gen_fixtures.R generates the R reference fixtures
tests/fixtures/ committed R glmnet output (tests run without R)
Two APIs, one solver
Faithful to R — the lambda path is the primitive, because it is what the algorithm actually computes:
from glmnetrs import glmnet
path = glmnet(X, y, alpha=1.0) # alpha = elastic-net mixing (1 = lasso)
path.lambda_ # (lmu,) descending
path.beta # (p, lmu)
path.coef(s=0.05) # interpolated, as in R's coef(fit, s=)
path.predict(X, s=0.05)
path.df # nonzeros per lambda
# logistic regression, same path object
lpath = glmnet(X, y01, family="binomial")
lpath.predict(X, s=0.05, type="response") # class-1 probability
# poisson counts
ppath = glmnet(X, counts, family="poisson")
ppath.predict(X, s=0.05, type="response") # expected count, exp(eta)
# sparse X (gaussian): pass a scipy sparse matrix, never densified
import scipy.sparse as sp
spath = glmnet(sp.csc_matrix(X), y) # ~20x faster when p >> n and sparse
# cross-validation to pick lambda (matches R's cv.glmnet)
from glmnetrs import cv_glmnet
cv = cv_glmnet(X, y, family="gaussian", type_measure="mse", nfolds=10)
cv.lambda_min, cv.lambda_1se
cv.predict(X, s="lambda.1se")
# summaries, like R's print()
print(path) # Df / %Dev / Lambda table
print(cv) # lambda.min / lambda.1se with measure and SE
path.to_frame() # optional pandas DataFrame
# plots, like R's plot.glmnet / plot.cv.glmnet (needs matplotlib)
path.plot(xvar="lambda") # coefficient paths, Df on the top axis
cv.plot() # CV curve with error bars + min/1se lines
scikit-learn compatible, using scikit-learn's meaning of alpha:
from glmnetrs.sklearn import ElasticNet, Lasso, LogisticRegression
m = ElasticNet(alpha=0.1, l1_ratio=0.7).fit(X, y) # alpha = penalty strength
m.coef_, m.intercept_
clf = LogisticRegression(C=1.0, penalty="l2").fit(X, y01)
clf.predict_proba(X)
The
alphatrap. In glmnetalphais the mixing parameter andlambdais the penalty strength. In scikit-learnalphais the penalty strength andl1_ratiois the mixing. Worse, the two objectives are not related by a simple rename: glmnet rescalesyto unit variance, which leaves the L2 term carrying a factor of1/sd(y).glmnetrs.sklearnhandles the conversion; the derivation is indocs/PORTING.md.
Develop
cargo test -p glmnet-core --release # parity against committed fixtures
maturin develop --release --uv # build the extension
python -m pytest tests/test_python.py # end-to-end + sklearn agreement
Rscript scripts/gen_fixtures.R # regenerate Gaussian fixtures (needs R + glmnet)
Rscript scripts/gen_fixtures_binomial.R # regenerate binomial fixtures
Rscript scripts/gen_fixtures_poisson.R # regenerate Poisson fixtures
Rscript scripts/gen_fixtures_sparse.R # regenerate sparse Gaussian fixtures (needs Matrix)
Rscript scripts/gen_fixtures_sparse_glm.R # regenerate sparse binomial/poisson fixtures
python scripts/bench.py # wall-clock vs R glmnet on identical data
python scripts/compare_datasets.py # coefficients + timing vs R on real datasets
cargo run --release -p glmnet-core --example bench_core # pure-core timings
Performance
Full-path wall clock vs R glmnet on identical data (Apple Silicon): Gaussian
runs at ~0.6–0.85x of R, two-class logistic at ~0.7–1.1x (faster than R when
n >> p). glmnet's compiled core is heavily tuned Eigen/SIMD, so
parity-to-1.5x-slower is the expected range for a pure-Rust port. Inner products
use four-accumulator reductions (matrix::dot4) that vectorize; see
docs/PORTING.md.
License
GPL-2.0-only, matching upstream glmnet.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file glmnet_rs-0.1.0.tar.gz.
File metadata
- Download URL: glmnet_rs-0.1.0.tar.gz
- Upload date:
- Size: 49.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
69eeea52c48a7591ca596ba4bd68effa15b9086ac70523f538453763bc5ce4ef
|
|
| MD5 |
ad8595c26df0c3380cfb5e342d559202
|
|
| BLAKE2b-256 |
536219736d1d84884488c65615a1ab76c0b393ae6de1fc8bf79d233334638e9a
|
Provenance
The following attestation bundles were made for glmnet_rs-0.1.0.tar.gz:
Publisher:
release.yml on georgeberry/glmnet-rs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
glmnet_rs-0.1.0.tar.gz -
Subject digest:
69eeea52c48a7591ca596ba4bd68effa15b9086ac70523f538453763bc5ce4ef - Sigstore transparency entry: 2187698959
- Sigstore integration time:
-
Permalink:
georgeberry/glmnet-rs@6744ea017a1bbb20247f65aa68b6fe5dec067c8a -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/georgeberry
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6744ea017a1bbb20247f65aa68b6fe5dec067c8a -
Trigger Event:
push
-
Statement type:
File details
Details for the file glmnet_rs-0.1.0-cp39-abi3-win_amd64.whl.
File metadata
- Download URL: glmnet_rs-0.1.0-cp39-abi3-win_amd64.whl
- Upload date:
- Size: 229.7 kB
- Tags: CPython 3.9+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c53e68edfceab851947ac415b2796b7fc2e612b835b79a4cb8951abda3022f82
|
|
| MD5 |
01afbb420fdaa16ec948b77d2c9ecf25
|
|
| BLAKE2b-256 |
4aa3c88d8d2527af47db7506c4f8433eab438d6a7ed25ba564a92f3152c5a7b4
|
Provenance
The following attestation bundles were made for glmnet_rs-0.1.0-cp39-abi3-win_amd64.whl:
Publisher:
release.yml on georgeberry/glmnet-rs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
glmnet_rs-0.1.0-cp39-abi3-win_amd64.whl -
Subject digest:
c53e68edfceab851947ac415b2796b7fc2e612b835b79a4cb8951abda3022f82 - Sigstore transparency entry: 2187698979
- Sigstore integration time:
-
Permalink:
georgeberry/glmnet-rs@6744ea017a1bbb20247f65aa68b6fe5dec067c8a -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/georgeberry
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6744ea017a1bbb20247f65aa68b6fe5dec067c8a -
Trigger Event:
push
-
Statement type:
File details
Details for the file glmnet_rs-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: glmnet_rs-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 341.9 kB
- Tags: CPython 3.9+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0abeabcbc65b350a1a4a54d2c6b742eaa5231f10a3ca327b85d2766a6430f840
|
|
| MD5 |
7805cbff08331fd25e51577976830f33
|
|
| BLAKE2b-256 |
b847a82a8aa2ea30859a1ed1f6da1ff1581ed2e07b0958a7651f9acf61211962
|
Provenance
The following attestation bundles were made for glmnet_rs-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release.yml on georgeberry/glmnet-rs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
glmnet_rs-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
0abeabcbc65b350a1a4a54d2c6b742eaa5231f10a3ca327b85d2766a6430f840 - Sigstore transparency entry: 2187698965
- Sigstore integration time:
-
Permalink:
georgeberry/glmnet-rs@6744ea017a1bbb20247f65aa68b6fe5dec067c8a -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/georgeberry
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6744ea017a1bbb20247f65aa68b6fe5dec067c8a -
Trigger Event:
push
-
Statement type:
File details
Details for the file glmnet_rs-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: glmnet_rs-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 334.5 kB
- Tags: CPython 3.9+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2723a9d11b72131253f3f1d13daf64713f27c7affa6c943c52ac56187a6ed6f8
|
|
| MD5 |
28bfd649efc9bfe539cb09f144e4b483
|
|
| BLAKE2b-256 |
f2e904e0f7d2284a3e95084e4786a497dff90e1b42a108a8a418073424241434
|
Provenance
The following attestation bundles were made for glmnet_rs-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
release.yml on georgeberry/glmnet-rs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
glmnet_rs-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
2723a9d11b72131253f3f1d13daf64713f27c7affa6c943c52ac56187a6ed6f8 - Sigstore transparency entry: 2187698975
- Sigstore integration time:
-
Permalink:
georgeberry/glmnet-rs@6744ea017a1bbb20247f65aa68b6fe5dec067c8a -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/georgeberry
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6744ea017a1bbb20247f65aa68b6fe5dec067c8a -
Trigger Event:
push
-
Statement type:
File details
Details for the file glmnet_rs-0.1.0-cp39-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: glmnet_rs-0.1.0-cp39-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 313.0 kB
- Tags: CPython 3.9+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9ae0ed90dbfd000f3bb848331895c948ecebaffde2e3cfb5e773af2ccd6d71d3
|
|
| MD5 |
ab9ee076fdf1024a3da49ced634960fb
|
|
| BLAKE2b-256 |
3412bd10609955158da7cc0a9ee5db8d324897a0056428752ff0b4a91fd45096
|
Provenance
The following attestation bundles were made for glmnet_rs-0.1.0-cp39-abi3-macosx_11_0_arm64.whl:
Publisher:
release.yml on georgeberry/glmnet-rs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
glmnet_rs-0.1.0-cp39-abi3-macosx_11_0_arm64.whl -
Subject digest:
9ae0ed90dbfd000f3bb848331895c948ecebaffde2e3cfb5e773af2ccd6d71d3 - Sigstore transparency entry: 2187698990
- Sigstore integration time:
-
Permalink:
georgeberry/glmnet-rs@6744ea017a1bbb20247f65aa68b6fe5dec067c8a -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/georgeberry
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6744ea017a1bbb20247f65aa68b6fe5dec067c8a -
Trigger Event:
push
-
Statement type:
File details
Details for the file glmnet_rs-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: glmnet_rs-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 324.2 kB
- Tags: CPython 3.9+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7de399854393b732c232ef60616436c49ac64a159e92e771ccfadcd97432038d
|
|
| MD5 |
d026d93cbf9e6cdff095757bf35b233f
|
|
| BLAKE2b-256 |
c420fbcfe94948ed4b6eaa5c516195216e94a89d1ba052c50e43c60a5b04fdf3
|
Provenance
The following attestation bundles were made for glmnet_rs-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl:
Publisher:
release.yml on georgeberry/glmnet-rs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
glmnet_rs-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl -
Subject digest:
7de399854393b732c232ef60616436c49ac64a159e92e771ccfadcd97432038d - Sigstore transparency entry: 2187698969
- Sigstore integration time:
-
Permalink:
georgeberry/glmnet-rs@6744ea017a1bbb20247f65aa68b6fe5dec067c8a -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/georgeberry
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6744ea017a1bbb20247f65aa68b6fe5dec067c8a -
Trigger Event:
push
-
Statement type: