use crate::error::Error;
use crate::neural_network::Tensor;
use crate::neural_network::layers::TrainingParameters;
use crate::neural_network::layers::layer_weight::LayerWeight;
use crate::neural_network::layers::no_trainable_parameters_layer_functions;
use crate::neural_network::layers::regularization::mode_dependent_layer_set_training;
use crate::neural_network::layers::regularization::mode_dependent_layer_trait;
use crate::neural_network::layers::regularization::validation::{
validate_input_shape, validate_stddev,
};
use crate::neural_network::traits::Layer;
use ndarray_rand::RandomExt;
use ndarray_rand::rand::rngs::StdRng;
use ndarray_rand::rand_distr::Normal;
#[derive(Debug)]
pub struct GaussianNoise {
stddev: f32,
input_shape: Vec<usize>,
training: bool,
rng: StdRng,
}
impl GaussianNoise {
pub fn new(stddev: f32, input_shape: Vec<usize>) -> Result<Self, Error> {
validate_stddev(stddev)?;
let rng = crate::random::make_rng(None);
Ok(GaussianNoise {
stddev,
input_shape,
training: true,
rng,
})
}
pub fn with_random_state(mut self, random_state: u64) -> Self {
self.rng = crate::random::make_rng(Some(random_state));
self
}
mode_dependent_layer_set_training!();
}
impl Layer for GaussianNoise {
fn forward(&mut self, input: &Tensor) -> Result<Tensor, Error> {
validate_input_shape(input.shape(), &self.input_shape)?;
if !self.training || self.stddev == 0.0 {
return Ok(input.clone());
}
let noise = Tensor::random_using(
input.raw_dim(),
Normal::new(0.0, self.stddev).unwrap(),
&mut self.rng,
);
let output = input + &noise;
Ok(output)
}
fn predict(&self, input: &Tensor) -> Result<Tensor, Error> {
validate_input_shape(input.shape(), &self.input_shape)?;
Ok(input.clone())
}
fn backward(&mut self, grad_output: &Tensor) -> Result<Tensor, Error> {
Ok(grad_output.clone())
}
fn layer_type(&self) -> &str {
"GaussianNoise"
}
fn output_shape(&self) -> String {
if self.input_shape.is_empty() {
String::from("Unknown")
} else {
format!(
"({})",
self.input_shape
.iter()
.map(|x| x.to_string())
.collect::<Vec<_>>()
.join(", ")
)
}
}
no_trainable_parameters_layer_functions!();
mode_dependent_layer_trait!();
}