#![deny(
missing_docs,
unsafe_code,
missing_debug_implementations,
missing_copy_implementations,
clippy::missing_panics_doc
)]
use std::ops::Add;
use std::ops::Div;
use std::ops::Mul;
use classification::ClassificationDataSet;
use ndarray::Array1;
use ndarray::Axis;
use num_traits::Float;
pub mod classification;
pub mod dimensionality_reduction;
pub mod metrics;
pub mod regression;
pub mod transformer;
pub trait Estimator<Input> {
type Estimator;
fn fit(&self, input: &Input) -> Option<Self::Estimator>;
}
pub trait Estimatable {
fn prepare_for_estimation<F: Float>(&self) -> Array1<F>;
}
impl<F1: Float> Estimatable for Array1<F1> {
fn prepare_for_estimation<F2: Float>(&self) -> Array1<F2> {
self.map(|v| F2::from(*v).unwrap())
}
}
#[derive(Debug, Clone)]
pub struct SplitDataset<Feature, Label>(
pub Vec<Feature>,
pub Vec<Feature>,
pub Vec<Label>,
pub Vec<Label>,
);
pub fn train_test_split<Feature, Label>(
dataset: ClassificationDataSet<Feature, Label>,
test_size: f64,
) -> (
ClassificationDataSet<Feature, Label>,
ClassificationDataSet<Feature, Label>,
) {
let (train, test): (Vec<_>, Vec<_>) = dataset
.consume_records()
.into_iter()
.partition(|_| rand::random_bool(test_size));
(
ClassificationDataSet::from(train),
ClassificationDataSet::from(test),
)
}
fn iterative_mean<I, F, R>(it: I) -> Option<R>
where
I: IntoIterator<Item = F>,
F: Into<R>,
R: Div<f64, Output = R> + Mul<f64, Output = R> + Add<Output = R> + Default,
{
it.into_iter().enumerate().fold(None, |acc, (i, curr)| {
let idx = i as f64;
let idx_inc_1 = (i + 1) as f64;
let current: R = curr.into();
let scaled_current = current / idx_inc_1;
match acc {
Some(acc) => Some(acc * (idx / idx_inc_1) + scaled_current),
None => Some(scaled_current),
}
})
}
#[cfg(test)]
mod tests {
use ndarray::{arr1, arr2, Array1};
use crate::iterative_mean;
#[test]
fn test_iterative_mean_2darray() {
let arr = arr2(&[[0., 1., 2.], [1., 2., 3.], [2., 3., 4.]]);
let mean: Option<Array1<f64>> =
iterative_mean(arr.rows().into_iter().map(|row| row.to_owned()));
assert!(mean.is_some_and(|m| m.relative_eq(&arr1(&[1.0, 2.0, 3.0]), 1e-4, 1e-2)));
}
#[test]
fn test_iterative_mean_vec() {
let arr: Vec<f64> = vec![0., 1., 2., 3., 4.];
let mean = iterative_mean(arr);
assert_eq!(mean, Some(2.0));
}
}