scirs2_neural/layers/
mod.rs

1//! Neural network layers implementation
2//!
3//! This module provides implementations of various neural network layers
4//! such as dense (fully connected), attention, convolution, pooling, etc.
5//! Layers are the fundamental building blocks of neural networks.
6
7use crate::error::Result;
8use ndarray::{Array, ScalarOperand};
9use num_traits::Float;
10use std::fmt::Debug;
11
12/// Base trait for neural network layers
13///
14/// This trait defines the core interface that all neural network layers must implement.
15/// It supports forward propagation, backpropagation, parameter management, and
16/// training/evaluation mode switching.
17pub trait Layer<F: Float + Debug + ScalarOperand>: Send + Sync {
18    /// Forward pass of the layer
19    ///
20    /// Computes the output of the layer given an input tensor.
21    fn forward(&self, input: &Array<F, ndarray::IxDyn>) -> Result<Array<F, ndarray::IxDyn>>;
22
23    /// Backward pass of the layer to compute gradients
24    ///
25    /// Computes gradients with respect to the layer's input, which is needed
26    /// for backpropagation.
27    fn backward(
28        &self,
29        input: &Array<F, ndarray::IxDyn>,
30        grad_output: &Array<F, ndarray::IxDyn>,
31    ) -> Result<Array<F, ndarray::IxDyn>>;
32
33    /// Update the layer parameters with the given learning rate
34    fn update(&mut self, learningrate: F) -> Result<()>;
35
36    /// Get the layer as a dyn Any for downcasting
37    fn as_any(&self) -> &dyn std::any::Any;
38
39    /// Get the layer as a mutable dyn Any for downcasting
40    fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
41
42    /// Get the parameters of the layer
43    fn params(&self) -> Vec<Array<F, ndarray::IxDyn>> {
44        Vec::new()
45    }
46
47    /// Get the gradients of the layer parameters
48    fn gradients(&self) -> Vec<Array<F, ndarray::IxDyn>> {
49        Vec::new()
50    }
51
52    /// Set the gradients of the layer parameters
53    fn set_gradients(&mut self, _gradients: &[Array<F, ndarray::IxDyn>]) -> Result<()> {
54        Ok(())
55    }
56
57    /// Set the parameters of the layer
58    fn set_params(&mut self, _params: &[Array<F, ndarray::IxDyn>]) -> Result<()> {
59        Ok(())
60    }
61
62    /// Set the layer to training mode (true) or evaluation mode (false)
63    fn set_training(&mut self, _training: bool) {
64        // Default implementation: do nothing
65    }
66
67    /// Get the current training mode
68    fn is_training(&self) -> bool {
69        true // Default implementation: always in training mode
70    }
71
72    /// Get the type of the layer (e.g., "Dense", "Conv2D")
73    fn layer_type(&self) -> &str {
74        "Unknown"
75    }
76
77    /// Get the number of trainable parameters in this layer
78    fn parameter_count(&self) -> usize {
79        0
80    }
81
82    /// Get a detailed description of this layer
83    fn layer_description(&self) -> String {
84        format!("type:{}", self.layer_type())
85    }
86
87    /// Get the input shape if known
88    fn inputshape(&self) -> Option<Vec<usize>> {
89        None
90    }
91
92    /// Get the output shape if known  
93    fn outputshape(&self) -> Option<Vec<usize>> {
94        None
95    }
96
97    /// Get the name of the layer if set
98    fn name(&self) -> Option<&str> {
99        None
100    }
101}
102
103/// Trait for layers with parameters (weights, biases)
104pub trait ParamLayer<F: Float + Debug + ScalarOperand>: Layer<F> {
105    /// Get the parameters of the layer as a vector of arrays
106    fn get_parameters(&self) -> Vec<Array<F, ndarray::IxDyn>>;
107
108    /// Get the gradients of the parameters
109    fn get_gradients(&self) -> Vec<Array<F, ndarray::IxDyn>>;
110
111    /// Set the parameters
112    fn set_parameters(&mut self, params: Vec<Array<F, ndarray::IxDyn>>) -> Result<()>;
113}
114
115/// Information about a layer for visualization purposes
116#[derive(Debug, Clone)]
117pub struct LayerInfo {
118    /// Index of the layer in the sequence
119    pub index: usize,
120    /// Name of the layer
121    pub name: String,
122    /// Type of the layer
123    pub layer_type: String,
124    /// Number of parameters in the layer
125    pub parameter_count: usize,
126    /// Input shape of the layer
127    pub inputshape: Option<Vec<usize>>,
128    /// Output shape of the layer
129    pub outputshape: Option<Vec<usize>>,
130}
131
132/// Sequential container for neural network layers
133///
134/// A Sequential model is a linear stack of layers where data flows through
135/// each layer in order.
136pub struct Sequential<F: Float + Debug + ScalarOperand> {
137    layers: Vec<Box<dyn Layer<F> + Send + Sync>>,
138    training: bool,
139}
140
141impl<F: Float + Debug + ScalarOperand> std::fmt::Debug for Sequential<F> {
142    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
143        f.debug_struct("Sequential")
144            .field("num_layers", &self.layers.len())
145            .field("training", &self.training)
146            .finish()
147    }
148}
149
150impl<F: Float + Debug + ScalarOperand + 'static> Clone for Sequential<F> {
151    fn clone(&self) -> Self {
152        // We can't clone the layers, so we just create an empty Sequential
153        // with the same training flag
154        Self {
155            layers: Vec::new(),
156            training: self.training,
157        }
158    }
159}
160
161impl<F: Float + Debug + ScalarOperand> Default for Sequential<F> {
162    fn default() -> Self {
163        Self::new()
164    }
165}
166
167impl<F: Float + Debug + ScalarOperand> Sequential<F> {
168    /// Create a new Sequential container
169    pub fn new() -> Self {
170        Self {
171            layers: Vec::new(),
172            training: true,
173        }
174    }
175
176    /// Add a layer to the container
177    pub fn add<L: Layer<F> + Send + Sync + 'static>(&mut self, layer: L) {
178        self.layers.push(Box::new(layer));
179    }
180
181    /// Get the number of layers
182    pub fn len(&self) -> usize {
183        self.layers.len()
184    }
185
186    /// Check if there are no layers
187    pub fn is_empty(&self) -> bool {
188        self.layers.is_empty()
189    }
190
191    /// Get total parameter count across all layers
192    pub fn total_parameters(&self) -> usize {
193        self.layers
194            .iter()
195            .map(|layer| layer.parameter_count())
196            .sum()
197    }
198
199    /// Get layer information for visualization purposes
200    pub fn layer_info(&self) -> Vec<LayerInfo> {
201        self.layers
202            .iter()
203            .enumerate()
204            .map(|(i, layer)| LayerInfo {
205                index: i,
206                name: layer.name().unwrap_or(&format!("Layer_{i}")).to_string(),
207                layer_type: layer.layer_type().to_string(),
208                parameter_count: layer.parameter_count(),
209                inputshape: layer.inputshape(),
210                outputshape: layer.outputshape(),
211            })
212            .collect()
213    }
214}
215
216impl<F: Float + Debug + ScalarOperand> Layer<F> for Sequential<F> {
217    fn forward(&self, input: &Array<F, ndarray::IxDyn>) -> Result<Array<F, ndarray::IxDyn>> {
218        let mut output = input.clone();
219        for layer in &self.layers {
220            output = layer.forward(&output)?;
221        }
222        Ok(output)
223    }
224
225    fn backward(
226        &self,
227        _input: &Array<F, ndarray::IxDyn>,
228        grad_output: &Array<F, ndarray::IxDyn>,
229    ) -> Result<Array<F, ndarray::IxDyn>> {
230        // For simplicity, we'll just return the grad_output as-is
231        // A real implementation would propagate through the layers in reverse
232        Ok(grad_output.clone())
233    }
234
235    fn update(&mut self, learningrate: F) -> Result<()> {
236        for layer in &mut self.layers {
237            layer.update(learningrate)?;
238        }
239        Ok(())
240    }
241
242    fn params(&self) -> Vec<Array<F, ndarray::IxDyn>> {
243        let mut params = Vec::new();
244        for layer in &self.layers {
245            params.extend(layer.params());
246        }
247        params
248    }
249
250    fn set_training(&mut self, training: bool) {
251        self.training = training;
252        for layer in &mut self.layers {
253            layer.set_training(training);
254        }
255    }
256
257    fn is_training(&self) -> bool {
258        self.training
259    }
260
261    fn as_any(&self) -> &dyn std::any::Any {
262        self
263    }
264
265    fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
266        self
267    }
268
269    fn layer_type(&self) -> &str {
270        "Sequential"
271    }
272
273    fn parameter_count(&self) -> usize {
274        self.layers
275            .iter()
276            .map(|layer| layer.parameter_count())
277            .sum()
278    }
279}
280
281/// Configuration enum for different types of layers
282#[derive(Debug, Clone)]
283pub enum LayerConfig {
284    /// Dense (fully connected) layer
285    Dense {
286        input_size: usize,
287        output_size: usize,
288        activation: Option<String>,
289    },
290    /// 2D Convolutional layer
291    Conv2D {
292        in_channels: usize,
293        out_channels: usize,
294        kernel_size: (usize, usize),
295    },
296    /// Dropout layer
297    Dropout { rate: f64 },
298}
299
300// Fixed modules
301pub mod conv;
302pub mod dense;
303pub mod dropout;
304pub mod normalization;
305pub mod recurrent;
306
307// Temporarily comment out layer modules that need fixing
308// mod attention;
309// mod embedding;
310// mod regularization;
311
312// Re-export fixed modules
313pub use conv::Conv2D;
314pub use dense::Dense;
315pub use dropout::Dropout;
316pub use normalization::{BatchNorm, LayerNorm};
317pub use recurrent::LSTM;
318
319// Re-export will be added as modules are fixed
320// pub use attention::{AttentionConfig, AttentionMask, MultiHeadAttention, SelfAttention};