Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Model Selection

Train/test splitting and cross-validation. Mirrors sklearn.model_selection. Live in datarust::model_selection.

train_test_split

Split X and y into train and test subsets.

#![allow(unused)]
fn main() {
use datarust::model_selection::{train_test_split, TrainTestSplit};

// Quick split with defaults (25% test, shuffled):
let (x_tr, x_te, y_tr, y_te) = train_test_split(&x, &y)?;

// Or configure via the builder:
let (x_tr, x_te, y_tr, y_te) = TrainTestSplit::new()
    .with_test_size(0.2)        // fraction in (0, 1)
    .with_shuffle(true)
    .with_random_state(42)      // deterministic seed
    .split(&x, &y)?;
}

The split requires at least two samples. Fractional test sizes round up, so a 25% test share uses two rows when the dataset contains five rows.

KFold

K-fold cross-validation. Each sample serves as the test set exactly once.

#![allow(unused)]
fn main() {
use datarust::model_selection::KFold;

let cv = KFold::new()
    .with_n_splits(5)
    .with_shuffle(true)
    .with_random_state(42);

for (train_idx, test_idx) in cv.split(n_samples)? {
    let x_train = x.select_rows(&train_idx)?;
    let x_test = x.select_rows(&test_idx)?;
    // ...
}
}

StratifiedKFold

Approximately preserves class balance across folds. It accepts two or more non-negative integer-valued classes, including gapped labels such as {2, 5, 9}. Essential for imbalanced classification.

#![allow(unused)]
fn main() {
use datarust::model_selection::StratifiedKFold;

let cv = StratifiedKFold::new().with_n_splits(5);

for (train_idx, test_idx) in cv.split(&y)? {  // note: takes y, not n_samples
    // each fold has roughly the same class ratio as the full dataset
}
}

cross_val_score

Evaluate any Predictor + Clone estimator by K-fold cross-validation with a user-supplied scorer.

#![allow(unused)]
fn main() {
use datarust::model_selection::{cross_val_score, KFold};
use datarust::linear_model::LinearRegression;
use datarust::metrics::regression::r2_score;

let cv = KFold::new().with_n_splits(5);
let scores = cross_val_score(&LinearRegression::new(), &x, &y, &cv, r2_score)?;
// scores.len() == 5, one R² per fold
}

For classification, pass accuracy_score instead:

#![allow(unused)]
fn main() {
use datarust::linear_model::LogisticRegression;
use datarust::metrics::classification::accuracy_score;

let scores = cross_val_score(&LogisticRegression::new(), &x, &y, &cv, accuracy_score)?;
}

The scorer is any closure Fn(&[f64], &[f64]) -> Result<f64>, so you can pass custom metrics too.