#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use serde::{Deserialize, Serialize};
#[cfg(feature = "dropout")]
use super::layer::Layer;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum LearningRateSchedule {
Constant,
ExponentialDecay {
decay: f32,
},
StepDecay {
drop: f32,
step_size: u64,
},
CosineAnnealing {
lr_min: f32,
t_max: u64,
},
}
impl Default for LearningRateSchedule {
fn default() -> Self {
Self::Constant
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EarlyStoppingConfig {
pub patience: u64,
pub min_delta: f32,
}
impl Default for EarlyStoppingConfig {
fn default() -> Self {
Self {
patience: 10,
min_delta: 1e-4,
}
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct EarlyStoppingState {
pub best_loss: f32,
pub epochs_without_improvement: u64,
pub should_stop: bool,
pub best_weights: Option<Vec<Vec<f32>>>,
pub best_biases: Option<Vec<Vec<f32>>>,
}
impl EarlyStoppingState {
#[must_use]
pub fn new() -> Self {
Self {
best_loss: f32::INFINITY,
epochs_without_improvement: 0,
should_stop: false,
best_weights: None,
best_biases: None,
}
}
}
#[cfg(feature = "dropout")]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DropoutConfig {
pub rate: f32,
pub seed: u64,
}
#[cfg(feature = "dropout")]
impl Default for DropoutConfig {
fn default() -> Self {
Self {
rate: 0.5,
seed: 42,
}
}
}
#[cfg(feature = "dropout")]
#[derive(Debug, Clone, Default)]
pub struct DropoutState {
pub masks: Vec<Vec<bool>>,
pub rng_state: u64,
}
#[cfg(feature = "dropout")]
impl DropoutState {
pub fn generate_masks(&mut self, layers: &[Layer], rate: f32, seed: u64) {
self.rng_state = seed;
self.masks.clear();
for layer in layers {
let mut mask = Vec::with_capacity(layer.output_dim);
for _ in 0..layer.output_dim {
self.rng_state = self.rng_state.wrapping_mul(1103515245).wrapping_add(12345);
let rand_val = (self.rng_state as f32) / (u64::MAX as f32);
mask.push(rand_val > rate);
}
self.masks.push(mask);
}
}
}