Skip to main content

sklears_decomposition/dictionary_learning/
dictionary_initialization.rs

1//! Dictionary initialization strategies
2
3use 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/// Initialization strategies
10#[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/// Initialization configuration
20#[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/// Dictionary initializer
39#[derive(Debug, Clone)]
40#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
41pub struct DictionaryInitializer {
42    config: InitializationConfig,
43}
44
45/// Random initializer
46#[derive(Debug, Clone)]
47#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
48pub struct RandomInitializer {
49    scale: Float,
50}
51
52/// Data-driven initializer
53#[derive(Debug, Clone)]
54#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
55pub struct DataDrivenInitializer {
56    normalize: bool,
57}
58
59/// Orthogonal initializer
60#[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        // Simple random initialization
81        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            // Normalize atoms
89            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}