sklears_decomposition/dictionary_learning/
online_dictionary_learning.rs1use scirs2_core::ndarray::Array2;
4use scirs2_core::random::thread_rng;
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7use sklears_core::{
8 error::{Result, SklearsError},
9 traits::{Estimator, Fit, Trained, Transform, Untrained},
10 types::Float,
11};
12
13#[derive(Debug, Clone, Copy)]
15#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
16pub enum OnlineDictLearningAlgorithm {
17 SGD,
19 OnlineKSVD,
21 Adaptive,
23}
24
25#[derive(Debug, Clone)]
27#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
28pub struct OnlineDictLearningConfig {
29 pub n_components: usize,
31 pub learning_rate: Float,
33 pub batch_size: usize,
35 pub algorithm: OnlineDictLearningAlgorithm,
37}
38
39impl Default for OnlineDictLearningConfig {
40 fn default() -> Self {
41 Self {
42 n_components: 100,
43 learning_rate: 0.01,
44 batch_size: 10,
45 algorithm: OnlineDictLearningAlgorithm::SGD,
46 }
47 }
48}
49
50#[derive(Debug, Clone)]
52#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
53pub struct OnlineDictionaryLearning<State = Untrained> {
54 config: OnlineDictLearningConfig,
55 state: std::marker::PhantomData<State>,
56 components_: Option<Array2<Float>>,
58 n_samples_seen_: Option<usize>,
60}
61
62impl OnlineDictionaryLearning<Untrained> {
63 pub fn new(config: OnlineDictLearningConfig) -> Self {
64 Self {
65 config,
66 state: std::marker::PhantomData,
67 components_: None,
68 n_samples_seen_: None,
69 }
70 }
71}
72
73impl OnlineDictionaryLearning<Trained> {
74 pub fn components(&self) -> &Array2<Float> {
76 self.components_.as_ref().expect("Model is trained")
77 }
78
79 pub fn n_samples_seen(&self) -> usize {
81 self.n_samples_seen_.expect("Model is trained")
82 }
83}
84
85impl Estimator for OnlineDictionaryLearning<Untrained> {
86 type Config = OnlineDictLearningConfig;
87 type Error = SklearsError;
88 type Float = Float;
89
90 fn config(&self) -> &Self::Config {
91 &self.config
92 }
93}
94
95impl Fit<Array2<Float>, ()> for OnlineDictionaryLearning<Untrained> {
96 type Fitted = OnlineDictionaryLearning<Trained>;
97
98 fn fit(self, x: &Array2<Float>, _y: &()) -> Result<Self::Fitted> {
99 let (_n_samples, n_features) = x.dim();
100
101 let mut rng = thread_rng();
103 let mut components = Array2::zeros((self.config.n_components, n_features));
104
105 for i in 0..self.config.n_components {
106 for j in 0..n_features {
107 components[[i, j]] = rng.random::<Float>() - 0.5;
108 }
109 }
110
111 Ok(OnlineDictionaryLearning {
112 config: self.config,
113 state: std::marker::PhantomData,
114 components_: Some(components),
115 n_samples_seen_: Some(x.nrows()),
116 })
117 }
118}
119
120impl Transform<Array2<Float>, Array2<Float>> for OnlineDictionaryLearning<Trained> {
121 fn transform(&self, x: &Array2<Float>) -> Result<Array2<Float>> {
122 let (n_samples, _n_features) = x.dim();
123 let codes = Array2::zeros((n_samples, self.config.n_components));
124 Ok(codes)
125 }
126}
127
128pub struct OnlineGradientDescent;
130pub struct OnlineKSvd;
131pub struct AdaptiveDictionaryLearning;
132
133pub type TrainedOnlineDictionaryLearning = OnlineDictionaryLearning<Trained>;