sklears_decomposition/dictionary_learning/
dictionary_initialization.rs1use scirs2_core::ndarray::Array2;
4use scirs2_core::random::thread_rng;
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7use sklears_core::{error::Result, types::Float};
8
9#[derive(Debug, Clone, Copy)]
11#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12pub enum InitializationStrategy {
13 Random,
14 DataDriven,
15 Orthogonal,
16 SVD,
17}
18
19#[derive(Debug, Clone)]
21#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
22pub struct InitializationConfig {
23 pub strategy: InitializationStrategy,
24 pub scale: Float,
25 pub normalize: bool,
26}
27
28impl Default for InitializationConfig {
29 fn default() -> Self {
30 Self {
31 strategy: InitializationStrategy::Random,
32 scale: 1.0,
33 normalize: true,
34 }
35 }
36}
37
38#[derive(Debug, Clone)]
40#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
41pub struct DictionaryInitializer {
42 config: InitializationConfig,
43}
44
45#[derive(Debug, Clone)]
47#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
48pub struct RandomInitializer {
49 scale: Float,
50}
51
52#[derive(Debug, Clone)]
54#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
55pub struct DataDrivenInitializer {
56 normalize: bool,
57}
58
59#[derive(Debug, Clone)]
61#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
62pub struct OrthogonalInitializer {
63 scale: Float,
64}
65
66impl DictionaryInitializer {
67 pub fn new(config: InitializationConfig) -> Self {
68 Self { config }
69 }
70
71 pub fn initialize(
72 &self,
73 n_atoms: usize,
74 n_features: usize,
75 _data: Option<&Array2<Float>>,
76 ) -> Result<Array2<Float>> {
77 let mut rng = thread_rng();
78 let mut dictionary = Array2::zeros((n_atoms, n_features));
79
80 for i in 0..n_atoms {
82 for j in 0..n_features {
83 dictionary[[i, j]] = (rng.random::<Float>() - 0.5) * 2.0 * self.config.scale;
84 }
85 }
86
87 if self.config.normalize {
88 for mut row in dictionary.rows_mut() {
90 let norm = row.mapv(|x| x * x).sum().sqrt();
91 if norm > 0.0 {
92 row.mapv_inplace(|x| x / norm);
93 }
94 }
95 }
96
97 Ok(dictionary)
98 }
99}