use crate::error::Error;
use crate::neural_network::Tensor;
use crate::neural_network::layers::TrainingParameters;
use crate::neural_network::layers::activation::{Activation, format_output_shape};
use crate::neural_network::layers::layer_weight::LayerWeight;
use crate::neural_network::layers::no_trainable_parameters_layer_functions;
use crate::neural_network::traits::Layer;
#[derive(Debug)]
pub struct Sigmoid {
output_cache: Option<Tensor>,
}
impl Sigmoid {
pub fn new() -> Self {
Sigmoid { output_cache: None }
}
}
impl Default for Sigmoid {
fn default() -> Self {
Self::new()
}
}
impl Layer for Sigmoid {
fn forward(&mut self, input: &Tensor) -> Result<Tensor, Error> {
if input.is_empty() {
return Err(Error::empty_input("input tensor"));
}
let output = Activation::Sigmoid.forward(input)?;
self.output_cache = Some(output.clone());
Ok(output)
}
fn predict(&self, input: &Tensor) -> Result<Tensor, Error> {
if input.is_empty() {
return Err(Error::empty_input("input tensor"));
}
Activation::Sigmoid.forward(input)
}
fn backward(&mut self, grad_output: &Tensor) -> Result<Tensor, Error> {
if let Some(output) = &self.output_cache {
if grad_output.shape() != output.shape() {
return Err(Error::shape_mismatch(output.shape(), grad_output.shape()));
}
Activation::Sigmoid.backward(output, grad_output)
} else {
Err(Error::forward_pass_not_run("Sigmoid"))
}
}
fn layer_type(&self) -> &str {
"Sigmoid"
}
fn output_shape(&self) -> String {
format_output_shape(&self.output_cache)
}
no_trainable_parameters_layer_functions!();
}