inferust 0.1.22

Statistical modeling for Rust - OLS/WLS regression, GLM, survival analysis, ARIMA/VAR, nonparametric tests, and more. A statsmodels-style library.
Documentation
//! Parity tests for Ridge/Lasso/ElasticNet against statsmodels'
//! `OLS.fit_regularized`.
//!
//! statsmodels' default `fit_regularized(alpha=scalar)` penalizes every
//! column of the design matrix, including the intercept. inferust never
//! penalizes the intercept (the scikit-learn/glmnet convention; see
//! `src/regression/regularized.rs` module docs), so the fixtures were
//! generated by passing statsmodels a per-column alpha *vector* with `0` in
//! the intercept's slot. With that adjustment, statsmodels' coordinate
//! descent / closed-form ridge solver and inferust's solve the same exact
//! objective and were independently confirmed to agree to ~1e-13 on this
//! dataset, so the tolerances below are tight.

mod common;

use common::{as_f64, as_f64_vec, assert_parity, check_vec, load_fixture, xy};
use inferust::regression::{ElasticNet, Lasso, Ridge};

fn feature_names(k: usize) -> Vec<String> {
    (1..=k).map(|i| format!("x{i}")).collect()
}

#[test]
fn parity_ridge_small() {
    let fx = load_fixture("ridge_small");
    let (x, y) = xy(&fx);
    let k = x[0].len();
    let alpha = as_f64(&fx["alpha"]);

    let result = Ridge::new(alpha)
        .with_feature_names(feature_names(k))
        .fit(&x, &y)
        .expect("Ridge fit failed");

    assert_parity(
        "ridge_small",
        vec![check_vec(
            "params",
            &result.coefficients,
            &as_f64_vec(&fx["params"]),
            1e-6,
        )],
    );
}

#[test]
fn parity_lasso_small() {
    let fx = load_fixture("lasso_small");
    let (x, y) = xy(&fx);
    let k = x[0].len();
    let alpha = as_f64(&fx["alpha"]);

    let result = Lasso::new(alpha)
        .with_feature_names(feature_names(k))
        .fit(&x, &y)
        .expect("Lasso fit failed");

    assert_parity(
        "lasso_small",
        vec![check_vec(
            "params",
            &result.coefficients,
            &as_f64_vec(&fx["params"]),
            1e-5,
        )],
    );
}

#[test]
fn parity_elastic_net_small() {
    let fx = load_fixture("elastic_net_small");
    let (x, y) = xy(&fx);
    let k = x[0].len();
    let alpha = as_f64(&fx["alpha"]);
    let l1_ratio = as_f64(&fx["l1_ratio"]);

    let result = ElasticNet::new(alpha, l1_ratio)
        .with_feature_names(feature_names(k))
        .fit(&x, &y)
        .expect("ElasticNet fit failed");

    assert_parity(
        "elastic_net_small",
        vec![check_vec(
            "params",
            &result.coefficients,
            &as_f64_vec(&fx["params"]),
            1e-5,
        )],
    );
}