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