pub mod adagrad;
pub mod adam;
pub mod ema;
pub mod lion;
pub mod lookahead;
pub mod radam;
pub mod rmsprop;
pub mod schedule;
pub mod sgd;
pub mod state;
pub use adagrad::{Adadelta, Adagrad};
pub use adam::{Adam, AdamW};
pub use ema::Ema;
pub use lion::Lion;
pub use lookahead::Lookahead;
pub use radam::RAdam;
pub use rmsprop::RMSprop;
pub use schedule::{Constant, CosineAnnealing, LrSchedule, OneCycle, StepDecay, Warmup};
pub use sgd::SGD;
pub use state::OptimizerState;
use crate::error::Result;
use crate::nn::Param;
const NORM_EPS: f32 = 1e-6;
pub trait Optimizer {
fn step(&mut self);
fn parameters(&self) -> &[Param];
fn lr(&self) -> f32;
fn set_lr(&mut self, lr: f32);
fn state(&self) -> OptimizerState;
fn load_state(&mut self, state: OptimizerState) -> Result<()>;
fn zero_grad(&self) {
for param in self.parameters() {
param.zero_grad();
}
}
fn gradients_are_finite(&self) -> bool {
self.parameters()
.iter()
.filter_map(|p| p.grad())
.all(|g| g.is_finite())
}
}
pub fn clip_grad_norm(params: &[Param], max_norm: f32) -> f32 {
let total: f32 = params
.iter()
.filter_map(|p| p.grad())
.map(|g| g.square().sum().item())
.sum::<f32>()
.sqrt();
if total > max_norm {
let scale = max_norm / (total + NORM_EPS);
for param in params {
if let Some(grad) = param.grad() {
param.set_grad(grad.mul_scalar(scale));
}
}
}
total
}
pub fn clip_grad_value(params: &[Param], max_value: f32) {
for param in params {
if let Some(grad) = param.grad() {
param.set_grad(grad.clamp(-max_value, max_value));
}
}
}