pub struct LayerNorm<F: Float + Debug> { /* private fields */ }
Expand description
Layer Normalization layer
Implements layer normalization as described in “Layer Normalization” by Ba, Kiros, and Hinton. It normalizes the inputs across the last dimension and applies learnable scale and shift parameters.
§Examples
use scirs2_neural::layers::{LayerNorm, Layer};
use ndarray::{Array, Array3};
use rand::rngs::SmallRng;
use rand::SeedableRng;
// Create a layer normalization layer for a 64-dimensional feature space
let mut rng = SmallRng::seed_from_u64(42);
let layer_norm = LayerNorm::new(64, 1e-5, &mut rng).unwrap();
// Forward pass with a batch of 2 samples, sequence length 3
let batch_size = 2;
let seq_len = 3;
let d_model = 64;
let input = Array3::<f64>::from_elem((batch_size, seq_len, d_model), 0.1).into_dyn();
let output = layer_norm.forward(&input).unwrap();
// Output shape should match input shape
assert_eq!(output.shape(), input.shape());
Implementations§
Source§impl<F: Float + Debug + ScalarOperand + 'static> LayerNorm<F>
impl<F: Float + Debug + ScalarOperand + 'static> LayerNorm<F>
Sourcepub fn new<R: Rng>(
normalized_shape: usize,
eps: f64,
_rng: &mut R,
) -> Result<Self>
pub fn new<R: Rng>( normalized_shape: usize, eps: f64, _rng: &mut R, ) -> Result<Self>
Create a new layer normalization layer
§Arguments
normalized_shape
- Shape of the input features to normalize overeps
- Small constant added for numerical stabilityrng
- Random number generator for initialization
§Returns
- A new layer normalization layer
Examples found in repository?
examples/model_serialization_example.rs (line 37)
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10 println!("Model Serialization Example");
11
12 // Initialize random number generator
13 let mut rng = SmallRng::seed_from_u64(42);
14
15 // 1. Create a simple neural network model
16 let mut model = Sequential::new();
17
18 // Add layers
19 let input_dim = 784; // MNIST image size: 28x28 = 784
20 let hidden_dim_1 = 256;
21 let hidden_dim_2 = 128;
22 let output_dim = 10; // 10 classes for digits 0-9
23
24 // Input layer to first hidden layer
25 let dense1 = Dense::new(input_dim, hidden_dim_1, Some("relu"), &mut rng)?;
26 model.add_layer(dense1);
27
28 // Dropout for regularization
29 let dropout1 = Dropout::new(0.2, &mut rng)?;
30 model.add_layer(dropout1);
31
32 // First hidden layer to second hidden layer
33 let dense2 = Dense::new(hidden_dim_1, hidden_dim_2, Some("relu"), &mut rng)?;
34 model.add_layer(dense2);
35
36 // Layer normalization
37 let layer_norm = LayerNorm::new(hidden_dim_2, 1e-5, &mut rng)?;
38 model.add_layer(layer_norm);
39
40 // Second hidden layer to output layer
41 let dense3 = Dense::new(hidden_dim_2, output_dim, Some("softmax"), &mut rng)?;
42 model.add_layer(dense3);
43
44 println!(
45 "Created a neural network with {} layers",
46 model.num_layers()
47 );
48
49 // 2. Test the model with some dummy input
50 let batch_size = 2;
51 let input = Array2::<f32>::from_elem((batch_size, input_dim), 0.1);
52 let output = model.forward(&input.clone().into_dyn())?;
53
54 println!("Model output shape: {:?}", output.shape());
55 println!("First few output values:");
56 for i in 0..batch_size {
57 print!("Sample {}: [ ", i);
58 for j in 0..5 {
59 // Print first 5 values
60 print!("{:.6} ", output[[i, j]]);
61 }
62 println!("... ]");
63 }
64
65 // 3. Save the model to a file
66 let model_path = Path::new("mnist_model.json");
67 serialization::save_model(&model, model_path, SerializationFormat::JSON)?;
68
69 println!("\nModel saved to {}", model_path.display());
70
71 // 4. Load the model from the file
72 let loaded_model = serialization::load_model::<f32, _>(model_path, SerializationFormat::JSON)?;
73
74 println!(
75 "Model loaded successfully with {} layers",
76 loaded_model.num_layers()
77 );
78
79 // 5. Test the loaded model with the same input
80 let loaded_output = loaded_model.forward(&input.into_dyn())?;
81
82 println!("\nLoaded model output shape: {:?}", loaded_output.shape());
83 println!("First few output values:");
84 for i in 0..batch_size {
85 print!("Sample {}: [ ", i);
86 for j in 0..5 {
87 // Print first 5 values
88 print!("{:.6} ", loaded_output[[i, j]]);
89 }
90 println!("... ]");
91 }
92
93 // 6. Compare original and loaded model outputs
94 let mut max_diff = 0.0;
95 for i in 0..batch_size {
96 for j in 0..output_dim {
97 let diff = (output[[i, j]] - loaded_output[[i, j]]).abs();
98 if diff > max_diff {
99 max_diff = diff;
100 }
101 }
102 }
103
104 println!(
105 "\nMaximum difference between original and loaded model outputs: {:.6}",
106 max_diff
107 );
108
109 if max_diff < 1e-6 {
110 println!("Models are identical! Serialization and deserialization worked correctly.");
111 } else {
112 println!("Warning: There are differences between the original and loaded models.");
113 println!(
114 "This might be due to numerical precision issues or a problem with serialization."
115 );
116 }
117
118 Ok(())
119}
Sourcepub fn normalized_shape(&self) -> usize
pub fn normalized_shape(&self) -> usize
Get the normalized shape
Trait Implementations§
Source§impl<F: Float + Debug + ScalarOperand + 'static> Layer<F> for LayerNorm<F>
impl<F: Float + Debug + ScalarOperand + 'static> Layer<F> for LayerNorm<F>
Source§fn as_any_mut(&mut self) -> &mut dyn Any
fn as_any_mut(&mut self) -> &mut dyn Any
Get the layer as a mutable dyn Any for downcasting Read more
Source§fn forward(&self, input: &Array<F, IxDyn>) -> Result<Array<F, IxDyn>>
fn forward(&self, input: &Array<F, IxDyn>) -> Result<Array<F, IxDyn>>
Forward pass of the layer Read more
Source§fn backward(
&self,
input: &Array<F, IxDyn>,
grad_output: &Array<F, IxDyn>,
) -> Result<Array<F, IxDyn>>
fn backward( &self, input: &Array<F, IxDyn>, grad_output: &Array<F, IxDyn>, ) -> Result<Array<F, IxDyn>>
Backward pass of the layer to compute gradients Read more
Source§fn update(&mut self, learning_rate: F) -> Result<()>
fn update(&mut self, learning_rate: F) -> Result<()>
Update the layer parameters with the given gradients Read more
Source§fn gradients(&self) -> Vec<Array<F, IxDyn>> ⓘ
fn gradients(&self) -> Vec<Array<F, IxDyn>> ⓘ
Get the gradients of the layer parameters Read more
Source§fn set_gradients(&mut self, _gradients: &[Array<F, IxDyn>]) -> Result<()>
fn set_gradients(&mut self, _gradients: &[Array<F, IxDyn>]) -> Result<()>
Set the gradients of the layer parameters Read more
Source§fn set_params(&mut self, _params: &[Array<F, IxDyn>]) -> Result<()>
fn set_params(&mut self, _params: &[Array<F, IxDyn>]) -> Result<()>
Set the parameters of the layer Read more
Source§fn set_training(&mut self, _training: bool)
fn set_training(&mut self, _training: bool)
Set the layer to training mode (true) or evaluation mode (false) Read more
Source§fn is_training(&self) -> bool
fn is_training(&self) -> bool
Get the current training mode Read more
Source§fn layer_type(&self) -> &str
fn layer_type(&self) -> &str
Get the type of the layer (e.g., “Dense”, “Conv2D”) Read more
Source§fn parameter_count(&self) -> usize
fn parameter_count(&self) -> usize
Get the number of trainable parameters in this layer Read more
Source§fn layer_description(&self) -> String
fn layer_description(&self) -> String
Get a detailed description of this layer Read more
Source§impl<F: Float + Debug + ScalarOperand + 'static> ParamLayer<F> for LayerNorm<F>
impl<F: Float + Debug + ScalarOperand + 'static> ParamLayer<F> for LayerNorm<F>
Auto Trait Implementations§
impl<F> Freeze for LayerNorm<F>where
F: Freeze,
impl<F> RefUnwindSafe for LayerNorm<F>where
F: RefUnwindSafe,
impl<F> Send for LayerNorm<F>
impl<F> Sync for LayerNorm<F>
impl<F> Unpin for LayerNorm<F>where
F: Unpin,
impl<F> UnwindSafe for LayerNorm<F>where
F: UnwindSafe + RefUnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
Converts
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
Converts
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more