use std::collections::LinkedList;
pub trait Layer {
fn input_count(&self) -> usize;
fn output_count(&self) -> usize;
fn output(&self, &[f32]) -> Vec<f32>;
#[allow(unused_variables)]
fn delta_from_outputs(&self, delta: &[f32], outputs: &[f32]) -> Option<Vec<f32>> {
None
}
#[allow(unused_variables)]
fn delta_from_inputs(&self, delta: &[f32], inputs: &[f32]) -> Option<Vec<f32>> {
None
}
fn delta(&self, delta: &[f32], inputs: &[f32], outputs: &[f32]) -> Vec<f32> {
self.delta_from_outputs(delta, outputs).or(self.delta_from_inputs(delta, inputs)).unwrap()
}
fn derivw(&self, &[f32]) -> Option<Vec<f32>> {
None
}
}
pub trait WeightedLayer: Layer {
fn weight_count(&self) -> usize;
fn neuron_count(&self) -> usize;
fn weights_mut(&mut self) -> Option<&mut Vec<f32>>;
fn bias_mut(&mut self) -> Option<&mut Vec<f32>>;
fn update(&mut self, weight_updates: &[f32], bias_updates: &[f32]) {
if let Some(weights) = self.weights_mut() {
for (w, dw) in weights.iter_mut().zip(weight_updates) {
*w += *dw;
}
}
if let Some(biases) = self.bias_mut() {
for (b, db) in biases.iter_mut().zip(bias_updates) {
*b += *db;
}
}
}
}
pub trait LossFunction {
fn loss1(&self, f32, f32) -> f32;
fn loss(&self, preds: &[f32], targets: &[f32]) -> Vec<f32> {
let mut loss = Vec::new();
for (p, t) in preds.iter().zip(targets) {
loss.push(self.loss1(*p, *t));
}
loss
}
}
pub trait DifferentiableLossFunction: LossFunction {
fn deriv1(&self, f32, f32) -> f32;
fn deriv(&self, preds: &[f32], targets: &[f32]) -> Vec<f32> {
let mut derivs = Vec::new();
for (p, t) in preds.iter().zip(targets) {
derivs.push(self.deriv1(*p, *t));
}
derivs
}
}
pub trait SupervisedTrainer {
fn train(&self, layers: &mut LinkedList<Box<WeightedLayer>>, inputs: &[f32], targets: &[f32]);
}