use rill_ml::evaluate::{
BinaryClassificationSample, RegressionSample, evaluate_binary_classification,
evaluate_regression, evaluate_regression_with_steps,
};
use rill_ml::metrics::{Accuracy, Mae, Mse};
use rill_ml::models::{BaselineConfig, MeanRegressor};
#[test]
fn progressive_regression_predicts_before_learning() {
let mut model = MeanRegressor::new(BaselineConfig::default()).unwrap();
let mut mae = Mae::default();
let samples = vec![
RegressionSample {
features: vec![],
target: 10.0,
},
RegressionSample {
features: vec![],
target: 20.0,
},
RegressionSample {
features: vec![],
target: 30.0,
},
];
let (final_mae, steps) = evaluate_regression_with_steps(&mut model, &mut mae, samples).unwrap();
assert!((final_mae.unwrap() - 35.0 / 3.0).abs() < 1e-9);
assert_eq!(steps.len(), 3);
let errors: Vec<f64> = steps.iter().map(|s| s.metric_value.unwrap()).collect();
assert!((errors[0] - 10.0).abs() < 1e-9);
assert!((errors[1] - 10.0).abs() < 1e-9);
assert!((errors[2] - 35.0 / 3.0).abs() < 1e-9);
}
#[test]
fn progressive_regression_with_mse() {
let mut model = MeanRegressor::new(BaselineConfig::default()).unwrap();
let mut mse = Mse::default();
let samples = vec![
RegressionSample {
features: vec![],
target: 2.0,
},
RegressionSample {
features: vec![],
target: 4.0,
},
];
let final_mse = evaluate_regression(&mut model, &mut mse, samples).unwrap();
assert!((final_mse.unwrap() - 4.0).abs() < 1e-9);
}
#[test]
fn progressive_classification_tracks_accuracy() {
use rill_ml::models::{LogisticRegression, LogisticRegressionConfig};
use rill_ml::optim::{Optimizer, SgdConfig};
let d = 1;
let mut model = LogisticRegression::new(
d,
LogisticRegressionConfig {
optimizer: Optimizer::sgd(
d,
SgdConfig {
learning_rate: 0.5,
l2: 0.0,
},
)
.unwrap(),
loss: Default::default(),
},
)
.unwrap();
let mut accuracy = Accuracy::default();
let samples: Vec<BinaryClassificationSample> = (0..200)
.map(|i| BinaryClassificationSample {
features: vec![if i % 2 == 0 { 1.0 } else { -1.0 }],
target: i % 2 == 0,
})
.collect();
let final_acc = evaluate_binary_classification(&mut model, &mut accuracy, samples).unwrap();
assert!(
final_acc.unwrap() > 0.8,
"accuracy should be high after learning, got {:?}",
final_acc
);
}
#[test]
fn progressive_steps_record_index_sequence() {
let mut model = MeanRegressor::new(BaselineConfig::default()).unwrap();
let mut mae = Mae::default();
let samples: Vec<RegressionSample> = (0..10)
.map(|i| RegressionSample {
features: vec![],
target: i as f64,
})
.collect();
let (_, steps) = evaluate_regression_with_steps(&mut model, &mut mae, samples).unwrap();
for (i, step) in steps.iter().enumerate() {
assert_eq!(step.index, i);
}
}
#[test]
fn progressive_empty_stream_returns_none() {
let mut model = MeanRegressor::new(BaselineConfig::default()).unwrap();
let mut mae = Mae::default();
let samples: Vec<RegressionSample> = vec![];
let result = evaluate_regression(&mut model, &mut mae, samples).unwrap();
assert!(result.is_none());
}