use crate::error::Error;
use crate::neural_network::Tensor;
use crate::neural_network::layers::TrainingParameters;
use crate::neural_network::layers::activation::format_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 Linear {
input_shape: Option<Vec<usize>>,
}
impl Linear {
pub fn new() -> Self {
Linear { input_shape: None }
}
}
impl Default for Linear {
fn default() -> Self {
Self::new()
}
}
impl Layer for Linear {
fn forward(&mut self, input: &Tensor) -> Result<Tensor, Error> {
if input.is_empty() {
return Err(Error::empty_input("input tensor"));
}
self.input_shape = Some(input.shape().to_vec());
Ok(input.clone())
}
fn predict(&self, input: &Tensor) -> Result<Tensor, Error> {
if input.is_empty() {
return Err(Error::empty_input("input tensor"));
}
Ok(input.clone())
}
fn backward(&mut self, grad_output: &Tensor) -> Result<Tensor, Error> {
if let Some(input_shape) = &self.input_shape {
if grad_output.shape() != input_shape.as_slice() {
return Err(Error::shape_mismatch(
input_shape.clone(),
grad_output.shape(),
));
}
Ok(grad_output.clone())
} else {
Err(Error::forward_pass_not_run("Linear"))
}
}
fn layer_type(&self) -> &str {
"Linear"
}
fn output_shape(&self) -> String {
match &self.input_shape {
Some(shape) => format_shape(shape),
None => "Unknown".to_string(),
}
}
no_trainable_parameters_layer_functions!();
}