use learning::optim::{Optimizable, OptimAlgorithm};
use linalg::vector::Vector;
use linalg::matrix::Matrix;
pub struct GradientDesc {
pub alpha: f64,
pub iters: usize,
}
impl Default for GradientDesc {
fn default() -> GradientDesc {
GradientDesc {
alpha: 0.3,
iters: 100,
}
}
}
impl GradientDesc {
pub fn new(alpha: f64, iters: usize) -> GradientDesc {
GradientDesc {
alpha: alpha,
iters: iters,
}
}
}
impl<M: Optimizable> OptimAlgorithm<M> for GradientDesc {
fn optimize(&self,
model: &M,
start: &[f64],
inputs: &M::Inputs,
targets: &M::Targets)
-> Vec<f64> {
let mut optimizing_val = Vector::new(start.to_vec());
for _ in 0..self.iters {
optimizing_val = &optimizing_val -
Vector::new(model.compute_grad(&optimizing_val.data()[..],
inputs,
targets)
.1) * self.alpha;
}
optimizing_val.into_vec()
}
}
pub struct StochasticGD {
pub alpha: f64,
pub mu: f64,
pub iters: usize,
}
impl Default for StochasticGD {
fn default() -> StochasticGD {
StochasticGD {
alpha: 0.1,
mu: 0.1,
iters: 20,
}
}
}
impl StochasticGD {
pub fn new(alpha: f64, mu: f64, iters: usize) -> StochasticGD {
StochasticGD {
alpha: alpha,
mu: mu,
iters: iters,
}
}
}
impl<M: Optimizable<Inputs = Matrix<f64>, Targets = Matrix<f64>>> OptimAlgorithm<M> for StochasticGD {
fn optimize(&self, model: &M, start: &[f64], inputs: &M::Inputs, targets: &M::Targets) -> Vec<f64> {
let (_, vec_data) = model.compute_grad(start,
&inputs.select_rows(&[0]),
&targets.select_rows(&[0]));
let grad = Vector::new(vec_data);
let mut delta_w = grad * self.alpha;
let mut optimizing_val = Vector::new(start.to_vec()) - &delta_w * self.mu;
for _ in 0..self.iters {
for i in 1..inputs.rows() {
let (_, vec_data) = model.compute_grad(&optimizing_val.data()[..],
&inputs.select_rows(&[i]),
&targets.select_rows(&[i]));
delta_w = Vector::new(vec_data) * self.mu + &delta_w * self.alpha;
optimizing_val = &optimizing_val - &delta_w * self.mu;
}
}
optimizing_val.into_vec()
}
}