use rustorch::optim::{AdaGrad, Adam, Optimizer, RMSprop, SGD};
use rustorch::tensor::Tensor;
#[test]
fn test_sgd_optimizer() {
let mut sgd = SGD::new(0.01);
assert_eq!(sgd.learning_rate(), 0.01);
let param = Tensor::ones(&[1]);
let grad = Tensor::ones(&[1]);
sgd.step(¶m, &grad);
let expected = 1.0 - 0.01; assert!((param.item() - expected).abs() < 1e-6);
}
#[test]
fn test_sgd_with_weight_decay() {
let mut sgd = SGD::with_weight_decay(0.01, 0.9, 0.001);
let param = Tensor::ones(&[1]);
let grad = Tensor::ones(&[1]);
sgd.step(¶m, &grad);
let expected = 1.0 - 0.01 * 1.001; assert!((param.item() - expected).abs() < 1e-6);
}
#[test]
fn test_adam_optimizer() {
let mut adam = Adam::new(0.001, 0.9, 0.999, 1e-8);
assert_eq!(adam.learning_rate(), 0.001);
let param = Tensor::ones(&[1]);
let grad = Tensor::ones(&[1]);
let original_value = param.item();
adam.step(¶m, &grad);
assert_ne!(param.item(), original_value);
}
#[test]
fn test_adam_with_weight_decay() {
let mut adam = Adam::with_weight_decay(0.001, 0.9, 0.999, 1e-8, 0.01);
let param = Tensor::ones(&[1]);
let grad = Tensor::ones(&[1]);
let original_value = param.item();
adam.step(¶m, &grad);
assert_ne!(param.item(), original_value);
}
#[test]
fn test_rmsprop_optimizer() {
let mut rmsprop = RMSprop::new(0.01, 0.99, 1e-8);
assert_eq!(rmsprop.learning_rate(), 0.01);
let param = Tensor::ones(&[1]);
let grad = Tensor::ones(&[1]);
let original_value = param.item();
rmsprop.step(¶m, &grad);
assert_ne!(param.item(), original_value);
}
#[test]
fn test_rmsprop_with_momentum() {
let mut rmsprop = RMSprop::with_momentum(0.01, 0.99, 1e-8, 0.9);
let param = Tensor::ones(&[1]);
let grad = Tensor::ones(&[1]);
let original_value = param.item();
rmsprop.step(¶m, &grad);
assert_ne!(param.item(), original_value);
}
#[test]
fn test_rmsprop_centered() {
let mut rmsprop = RMSprop::centered(0.01, 0.99, 1e-8, true);
let param = Tensor::ones(&[1]);
let grad = Tensor::ones(&[1]);
let original_value = param.item();
rmsprop.step(¶m, &grad);
assert_ne!(param.item(), original_value);
}
#[test]
fn test_adagrad_optimizer() {
let mut adagrad = AdaGrad::new(0.01, 1e-10);
assert_eq!(adagrad.learning_rate(), 0.01);
let param = Tensor::ones(&[1]);
let grad = Tensor::ones(&[1]);
let original_value = param.item();
adagrad.step(¶m, &grad);
assert_ne!(param.item(), original_value);
}
#[test]
fn test_adagrad_with_weight_decay() {
let mut adagrad = AdaGrad::with_weight_decay(0.01, 1e-10, 0.001);
let param = Tensor::ones(&[1]);
let grad = Tensor::ones(&[1]);
let original_value = param.item();
adagrad.step(¶m, &grad);
assert_ne!(param.item(), original_value);
}
#[test]
fn test_adagrad_with_initial_accumulator() {
let mut adagrad = AdaGrad::with_initial_accumulator(0.01, 1e-10, 0.1);
let param = Tensor::ones(&[1]);
let grad = Tensor::ones(&[1]);
let original_value = param.item();
adagrad.step(¶m, &grad);
assert_ne!(param.item(), original_value);
}
#[test]
fn test_optimizer_state_dict() {
let mut sgd = SGD::new(0.01);
let state = sgd.state_dict();
assert_eq!(state.get("learning_rate"), Some(&0.01));
assert_eq!(state.get("momentum"), Some(&0.0));
sgd.set_learning_rate(0.001);
sgd.load_state_dict(state);
assert_eq!(sgd.learning_rate(), 0.01);
}
#[test]
fn test_multiple_step_convergence() {
let mut sgd = SGD::new(0.1);
let param = Tensor::zeros(&[1]);
for _ in 0..50 {
let grad_value = 2.0 * (param.item() - 2.0);
let grad = Tensor::from_vec(vec![grad_value], vec![1]);
sgd.step(¶m, &grad);
}
assert!((param.item() - 2.0).abs() < 0.1);
}
#[test]
fn test_learning_rate_modification() {
let mut optimizers: Vec<Box<dyn Optimizer>> = vec![
Box::new(SGD::new(0.01)),
Box::new(Adam::new(0.001, 0.9, 0.999, 1e-8)),
Box::new(RMSprop::new(0.01, 0.99, 1e-8)),
Box::new(AdaGrad::new(0.01, 1e-10)),
];
for optimizer in &mut optimizers {
optimizer.set_learning_rate(0.005);
assert_eq!(optimizer.learning_rate(), 0.005);
}
}