use crate::activations::Activation;
use crate::error::Result;
use scirs2_core::ndarray::{Array, Zip};
use scirs2_core::numeric::{Float, NumAssign};
use std::fmt::Debug;
#[derive(Debug, Clone, Copy)]
pub struct Sigmoid;
impl Sigmoid {
pub fn new() -> Self {
Self
}
}
impl Default for Sigmoid {
fn default() -> Self {
Self::new()
}
}
impl<F: Float + Debug + NumAssign> Activation<F> for Sigmoid {
fn forward(
&self,
input: &Array<F, scirs2_core::ndarray::IxDyn>,
) -> Result<Array<F, scirs2_core::ndarray::IxDyn>> {
let one = F::one();
let mut output = input.clone();
Zip::from(&mut output).for_each(|x| {
*x = one / (one + (-*x).exp());
});
Ok(output)
}
fn backward(
&self,
grad_output: &Array<F, scirs2_core::ndarray::IxDyn>,
output: &Array<F, scirs2_core::ndarray::IxDyn>,
) -> Result<Array<F, scirs2_core::ndarray::IxDyn>> {
let one = F::one();
let mut grad_input = Array::zeros(output.raw_dim());
Zip::from(&mut grad_input)
.and(grad_output)
.and(output)
.for_each(|grad_in, &grad_out, &out| {
*grad_in = grad_out * out * (one - out);
});
Ok(grad_input)
}
}