use crate::nn::module::Module;
use crate::tensor::Tensor;
use crate::error::Result;
use ndarray::IxDyn;
use ndarray_rand::rand_distr::Uniform;
use ndarray_rand::RandomExt;
pub struct Linear {
pub weights: Tensor,
pub bias: Tensor,
}
impl Linear {
pub fn new(in_features: usize, out_features: usize) -> Self {
let limit = (2.0 / in_features as f32).sqrt();
let weights_data = ndarray::ArrayD::random(
IxDyn(&[in_features, out_features]),
Uniform::new(-limit, limit),
);
let weights = Tensor::new(weights_data, true);
let bias = Tensor::zeros(&[1, out_features], true);
Self { weights, bias }
}
}
impl Module for Linear {
fn forward(&self, inputs: &Tensor) -> Result<Tensor> {
let dot_product = inputs.dot(&self.weights)?;
let final_output = &dot_product + &self.bias;
Ok(final_output)
}
fn parameters(&self) -> Vec<Tensor> {
vec![self.weights.clone(), self.bias.clone()]
}
}