Skip to main content

sklears_decomposition/dictionary_learning/
convergence_monitoring.rs

1//! Convergence monitoring and optimization utilities
2
3use scirs2_core::ndarray::Array1;
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6use sklears_core::types::Float;
7
8/// Convergence configuration
9#[derive(Debug, Clone)]
10#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11pub struct ConvergenceConfig {
12    pub tol: Float,
13    pub max_iter: usize,
14    pub window_size: usize,
15}
16
17impl Default for ConvergenceConfig {
18    fn default() -> Self {
19        Self {
20            tol: 1e-6,
21            max_iter: 1000,
22            window_size: 10,
23        }
24    }
25}
26
27/// Convergence result
28#[derive(Debug, Clone)]
29#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
30pub struct ConvergenceResult {
31    pub converged: bool,
32    pub n_iter: usize,
33    pub final_error: Float,
34}
35
36/// Optimization metrics
37#[derive(Debug, Clone)]
38#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
39pub struct OptimizationMetrics {
40    pub objective_values: Array1<Float>,
41    pub gradient_norms: Array1<Float>,
42    pub step_sizes: Array1<Float>,
43}
44
45/// Learning curve data
46#[derive(Debug, Clone)]
47#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
48pub struct LearningCurve {
49    pub iterations: Array1<Float>,
50    pub training_errors: Array1<Float>,
51    pub validation_errors: Option<Array1<Float>>,
52}
53
54/// Convergence monitor
55#[derive(Debug, Clone)]
56#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
57pub struct ConvergenceMonitor {
58    config: ConvergenceConfig,
59    error_history: Vec<Float>,
60}
61
62impl ConvergenceMonitor {
63    pub fn new(config: ConvergenceConfig) -> Self {
64        Self {
65            config,
66            error_history: Vec::new(),
67        }
68    }
69
70    pub fn check_convergence(&mut self, error: Float, iteration: usize) -> ConvergenceResult {
71        self.error_history.push(error);
72
73        let converged = if self.error_history.len() > 1 {
74            let prev_error = self.error_history[self.error_history.len() - 2];
75            (prev_error - error).abs() < self.config.tol
76        } else {
77            false
78        };
79
80        ConvergenceResult {
81            converged: converged || iteration >= self.config.max_iter,
82            n_iter: iteration,
83            final_error: error,
84        }
85    }
86}