linfa_reduction/diffusion_map/
hyperparams.rs

1use crate::{DiffusionMap, ReductionError};
2use linfa::{param_guard::TransformGuard, ParamGuard};
3
4/// Diffusion map hyperparameters
5///
6/// The diffusion map algorithms has only two explicit hyperparameter. The first is the stepsize.
7/// As the algorithm calculates the closeness of points after a number of steps taken in the
8/// diffusion graph, a larger step size introduces a more global behaviour of the projection while
9/// a smaller one (especially one) just projects close obserations closely together.
10/// The second parameter is the embedding size and defines the target dimensionality.
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct DiffusionMapValidParams {
13    steps: usize,
14    embedding_size: usize,
15}
16
17impl DiffusionMapValidParams {
18    pub fn steps(&self) -> usize {
19        self.steps
20    }
21
22    pub fn embedding_size(&self) -> usize {
23        self.embedding_size
24    }
25}
26
27/// Diffusion map hyperparameters
28///
29/// The diffusion map algorithms has only two explicit hyperparameter. The first is the stepsize.
30/// As the algorithm calculates the closeness of points after a number of steps taken in the
31/// diffusion graph, a larger step size introduces a more global behaviour of the projection while
32/// a smaller one (especially one) just projects close obserations closely together.
33/// The second parameter is the embedding size and defines the target dimensionality.
34#[derive(Debug, Clone, PartialEq, Eq)]
35pub struct DiffusionMapParams(DiffusionMapValidParams);
36
37impl DiffusionMapParams {
38    /// Set the number of steps in the diffusion operator
39    ///
40    /// The diffusion map algorithm expresses the transition probability with a kernel matrix and
41    /// then takes multiple steps along the diffusion operator. In practice scales the
42    /// eigenvalues of the decomposition exponentially with the number of steps.
43    pub fn steps(mut self, steps: usize) -> Self {
44        self.0.steps = steps;
45
46        self
47    }
48
49    pub fn embedding_size(mut self, embedding_size: usize) -> Self {
50        self.0.embedding_size = embedding_size;
51
52        self
53    }
54
55    /// Creates the set of default parameters
56    ///
57    /// # Parameters
58    ///
59    /// * `embedding_size`: the number of dimensions in the projection
60    ///
61    /// # Returns
62    ///
63    /// Parameter set with number of steps = 1
64    pub fn new(embedding_size: usize) -> DiffusionMapParams {
65        Self(DiffusionMapValidParams {
66            steps: 1,
67            embedding_size,
68        })
69    }
70}
71
72impl Default for DiffusionMapParams {
73    fn default() -> Self {
74        Self::new(2)
75    }
76}
77
78impl<F> DiffusionMap<F> {
79    pub fn params(embedding_size: usize) -> DiffusionMapParams {
80        DiffusionMapParams::new(embedding_size)
81    }
82}
83
84impl ParamGuard for DiffusionMapParams {
85    type Checked = DiffusionMapValidParams;
86    type Error = ReductionError;
87
88    fn check_ref(&self) -> Result<&Self::Checked, Self::Error> {
89        if self.0.steps == 0 {
90            Err(ReductionError::StepsZero)
91        } else if self.0.embedding_size == 0 {
92            Err(ReductionError::EmbeddingTooSmall(self.0.embedding_size))
93        } else {
94            Ok(&self.0)
95        }
96    }
97
98    fn check(self) -> Result<Self::Checked, Self::Error> {
99        self.check_ref()?;
100        Ok(self.0)
101    }
102}
103impl TransformGuard for DiffusionMapParams {}