Skip to main content

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 alpha trap. In glmnet alpha is the mixing parameter and lambda is the penalty strength. In scikit-learn alpha is the penalty strength and l1_ratio is the mixing. Worse, the two objectives are not related by a simple rename: glmnet rescales y to unit variance, which leaves the L2 term carrying a factor of 1/sd(y). glmnetrs.sklearn handles the conversion; the derivation is in docs/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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

glmnet_rs-0.1.0.tar.gz (49.9 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

glmnet_rs-0.1.0-cp39-abi3-win_amd64.whl (229.7 kB view details)

Uploaded CPython 3.9+Windows x86-64

glmnet_rs-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (341.9 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

glmnet_rs-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (334.5 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64

glmnet_rs-0.1.0-cp39-abi3-macosx_11_0_arm64.whl (313.0 kB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

glmnet_rs-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl (324.2 kB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

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

Hashes for glmnet_rs-0.1.0.tar.gz
Algorithm Hash digest
SHA256 69eeea52c48a7591ca596ba4bd68effa15b9086ac70523f538453763bc5ce4ef
MD5 ad8595c26df0c3380cfb5e342d559202
BLAKE2b-256 536219736d1d84884488c65615a1ab76c0b393ae6de1fc8bf79d233334638e9a

See more details on using hashes here.

Provenance

The following attestation bundles were made for glmnet_rs-0.1.0.tar.gz:

Publisher: release.yml on georgeberry/glmnet-rs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for glmnet_rs-0.1.0-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 c53e68edfceab851947ac415b2796b7fc2e612b835b79a4cb8951abda3022f82
MD5 01afbb420fdaa16ec948b77d2c9ecf25
BLAKE2b-256 4aa3c88d8d2527af47db7506c4f8433eab438d6a7ed25ba564a92f3152c5a7b4

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file glmnet_rs-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for glmnet_rs-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 0abeabcbc65b350a1a4a54d2c6b742eaa5231f10a3ca327b85d2766a6430f840
MD5 7805cbff08331fd25e51577976830f33
BLAKE2b-256 b847a82a8aa2ea30859a1ed1f6da1ff1581ed2e07b0958a7651f9acf61211962

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file glmnet_rs-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for glmnet_rs-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 2723a9d11b72131253f3f1d13daf64713f27c7affa6c943c52ac56187a6ed6f8
MD5 28bfd649efc9bfe539cb09f144e4b483
BLAKE2b-256 f2e904e0f7d2284a3e95084e4786a497dff90e1b42a108a8a418073424241434

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file glmnet_rs-0.1.0-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for glmnet_rs-0.1.0-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9ae0ed90dbfd000f3bb848331895c948ecebaffde2e3cfb5e773af2ccd6d71d3
MD5 ab9ee076fdf1024a3da49ced634960fb
BLAKE2b-256 3412bd10609955158da7cc0a9ee5db8d324897a0056428752ff0b4a91fd45096

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file glmnet_rs-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for glmnet_rs-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 7de399854393b732c232ef60616436c49ac64a159e92e771ccfadcd97432038d
MD5 d026d93cbf9e6cdff095757bf35b233f
BLAKE2b-256 c420fbcfe94948ed4b6eaa5c516195216e94a89d1ba052c50e43c60a5b04fdf3

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page