Skip to main content

somatize_study/partition/
kfold.rs

1//! `k` folds over the samples, each held out in turn.
2
3use super::dealing::{assemble, checked, deal, ordering};
4use super::{Fold, Partition, PartitionError};
5use crate::Samples;
6use std::fmt;
7
8/// The plain cut: the samples in `k` parts, each one held out while the rest
9/// train.
10///
11/// `LeaveOneOut` is this with `k = n`, and a holdout of one part in `k` is its
12/// fold 0. Neither earns a scheme of its own — a scheme that is a parameter is
13/// a name you have to remember for nothing.
14///
15/// ```
16/// use somatize_study::{KFold, Samples};
17///
18/// let folds = KFold { k: 5, shuffle: Some(0) }.folds(&Samples::of(100))?;
19/// assert_eq!(folds.len(), 5);
20/// # Ok::<(), somatize_study::PartitionError>(())
21/// ```
22#[derive(Debug, Clone, PartialEq, Eq, Hash)]
23pub struct KFold {
24    /// How many folds.
25    pub k: usize,
26    /// The seed, or `None` for the order they came in.
27    ///
28    /// The seed both switches shuffling on and makes it repeatable, so
29    /// "shuffled but not reproducible" is a state that cannot be written down.
30    pub shuffle: Option<u64>,
31}
32
33impl KFold {
34    /// The folds, in order. It uses neither the classes nor the groups.
35    pub fn folds(&self, samples: &Samples) -> Result<Vec<Fold>, PartitionError> {
36        let n = samples.n();
37        checked(self.k, n)?;
38        Ok(assemble(n, deal(&ordering(n, self.shuffle), self.k)))
39    }
40}
41
42impl fmt::Display for KFold {
43    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44        super::scheme(f, "kfold", self.k, self.shuffle)
45    }
46}
47
48impl From<KFold> for Partition {
49    fn from(cut: KFold) -> Self {
50        Self::KFold(cut)
51    }
52}