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 {}