torsh_nn/layers/normalization/
mod.rs1pub mod advanced;
57pub mod batch;
58pub mod common;
59pub mod instance;
60pub mod layer_group;
61pub mod weight_based;
62
63pub use common::{unbiased_variance, utils, NormalizationConfig, NormalizationStats, RunningStats};
65
66pub use batch::{
68 BatchNorm1d, BatchNorm2d, BatchNorm3d, BatchRenorm2d, BatchRenormSchedule, SyncBatchNorm2d,
69 VirtualBatchNorm2d,
70};
71
72pub use instance::{InstanceNorm1d, InstanceNorm2d, InstanceNorm3d};
74
75pub use layer_group::{GroupNorm, LayerNorm, RMSNorm};
77
78pub use weight_based::{SpectralNorm, WeightNorm, WeightStandardization};
80
81pub use advanced::SwitchableNorm2d;
83
84pub use BatchNorm2d as BatchNorm;
86pub use GroupNorm as GN;
87pub use InstanceNorm2d as InstanceNorm;
88pub use LayerNorm as LN;
89
90pub struct NormalizationFactory;
92
93impl NormalizationFactory {
94 pub fn batch_norm(num_features: usize) -> torsh_core::error::Result<BatchNorm2d> {
96 BatchNorm2d::new(num_features)
97 }
98
99 pub fn layer_norm(normalized_shape: Vec<usize>) -> torsh_core::error::Result<LayerNorm> {
101 LayerNorm::new(normalized_shape)
102 }
103
104 pub fn group_norm(
106 num_groups: usize,
107 num_channels: usize,
108 ) -> torsh_core::error::Result<GroupNorm> {
109 GroupNorm::new(num_groups, num_channels)
110 }
111
112 pub fn instance_norm(num_features: usize) -> torsh_core::error::Result<InstanceNorm2d> {
114 InstanceNorm2d::new(num_features)
115 }
116
117 pub fn switchable_norm(num_features: usize) -> torsh_core::error::Result<SwitchableNorm2d> {
119 SwitchableNorm2d::new(num_features)
120 }
121
122 pub fn rms_norm(normalized_shape: Vec<usize>) -> torsh_core::error::Result<RMSNorm> {
124 RMSNorm::new(normalized_shape)
125 }
126
127 pub fn batch_norm_training(num_features: usize) -> torsh_core::error::Result<BatchNorm2d> {
129 BatchNorm2d::with_config(num_features, NormalizationConfig::training())
130 }
131
132 pub fn batch_norm_inference(num_features: usize) -> torsh_core::error::Result<BatchNorm2d> {
134 BatchNorm2d::with_config(num_features, NormalizationConfig::inference())
135 }
136
137 pub fn layer_norm_non_affine(
139 normalized_shape: Vec<usize>,
140 ) -> torsh_core::error::Result<LayerNorm> {
141 LayerNorm::with_config(normalized_shape, NormalizationConfig::non_affine())
142 }
143}
144
145pub struct NormalizationPresets;
147
148impl NormalizationPresets {
149 pub fn resnet_batch_norm(num_features: usize) -> torsh_core::error::Result<BatchNorm2d> {
151 BatchNorm2d::with_config(num_features, NormalizationConfig::with_momentum(0.1))
152 }
153
154 pub fn transformer_layer_norm(hidden_size: usize) -> torsh_core::error::Result<LayerNorm> {
156 LayerNorm::with_config(vec![hidden_size], NormalizationConfig::with_eps(1e-12))
157 }
158
159 pub fn style_transfer_instance_norm(
161 num_features: usize,
162 ) -> torsh_core::error::Result<InstanceNorm2d> {
163 InstanceNorm2d::with_config(num_features, NormalizationConfig::non_affine())
164 }
165
166 pub fn small_batch_group_norm(num_channels: usize) -> torsh_core::error::Result<GroupNorm> {
168 let num_groups = if num_channels >= 32 { 32 } else { num_channels };
169 GroupNorm::new(num_groups, num_channels)
170 }
171
172 pub fn llama_rms_norm(hidden_size: usize) -> torsh_core::error::Result<RMSNorm> {
174 RMSNorm::with_config(vec![hidden_size], 1e-6, true)
175 }
176
177 pub fn gpt_rms_norm(hidden_size: usize) -> torsh_core::error::Result<RMSNorm> {
179 RMSNorm::with_config(vec![hidden_size], 1e-5, true)
180 }
181}
182
183#[cfg(test)]
184mod tests {
185 use super::*;
186 use crate::Module;
187 use torsh_tensor::creation::zeros;
188
189 #[test]
190 fn test_normalization_factory() {
191 let bn =
193 NormalizationFactory::batch_norm(64).expect("Normalization Factory should succeed");
194 assert_eq!(bn.num_features(), 64);
195
196 let ln = NormalizationFactory::layer_norm(vec![128])
197 .expect("Normalization Factory should succeed");
198 assert_eq!(ln.normalized_shape(), &[128]);
199
200 let gn =
201 NormalizationFactory::group_norm(8, 64).expect("Normalization Factory should succeed");
202 assert_eq!(gn.num_groups(), 8);
203 assert_eq!(gn.num_channels(), 64);
204
205 let inn =
206 NormalizationFactory::instance_norm(32).expect("Normalization Factory should succeed");
207 assert_eq!(inn.num_features(), 32);
208
209 let sn = NormalizationFactory::switchable_norm(16)
210 .expect("Normalization Factory should succeed");
211 assert_eq!(sn.num_features(), 16);
212 }
213
214 #[test]
215 fn test_normalization_presets() {
216 let resnet_bn = NormalizationPresets::resnet_batch_norm(64)
218 .expect("Normalization Presets should succeed");
219 assert_eq!(resnet_bn.momentum(), 0.1);
220
221 let transformer_ln = NormalizationPresets::transformer_layer_norm(768)
222 .expect("Normalization Presets should succeed");
223 assert_eq!(transformer_ln.eps(), 1e-12);
224
225 let style_in = NormalizationPresets::style_transfer_instance_norm(64)
226 .expect("Normalization Presets should succeed");
227 assert!(style_in.parameters().is_empty());
229
230 let small_batch_gn = NormalizationPresets::small_batch_group_norm(64)
231 .expect("Normalization Presets should succeed");
232 assert_eq!(small_batch_gn.num_groups(), 32);
233 }
234
235 #[test]
236 fn test_module_integration() {
237 let input_2d = zeros(&[4, 64]).expect("zeros should succeed");
239 let input_4d = zeros(&[4, 64, 32, 32]).expect("zeros should succeed");
240
241 let bn2d = BatchNorm2d::new(64).expect("Batch Norm2d should succeed");
243 assert!(bn2d.forward(&input_4d).is_ok());
244
245 let bn1d = BatchNorm1d::new(64).expect("Batch Norm1d should succeed");
247 assert!(bn1d.forward(&input_2d).is_ok());
248
249 let ln = LayerNorm::new(vec![64]).expect("Layer Norm should succeed");
251 assert!(ln.forward(&input_2d).is_ok());
252
253 let gn = GroupNorm::new(8, 64).expect("Group Norm should succeed");
255 assert!(gn.forward(&input_4d).is_ok());
256
257 let in2d = InstanceNorm2d::new(64).expect("Instance Norm2d should succeed");
259 assert!(in2d.forward(&input_4d).is_ok());
260 }
261
262 #[test]
263 fn test_backward_compatibility_aliases() {
264 let bn = BatchNorm::new(32).expect("Batch Norm should succeed");
266 assert_eq!(bn.num_features(), 32);
267
268 let ln = LN::new(vec![128]).expect("LN should succeed");
269 assert_eq!(ln.normalized_shape(), &[128]);
270
271 let gn = GN::new(4, 32).expect("GN should succeed");
272 assert_eq!(gn.num_groups(), 4);
273
274 let inn = InstanceNorm::new(16).expect("Instance Norm should succeed");
275 assert_eq!(inn.num_features(), 16);
276 }
277
278 #[test]
279 fn test_configuration_variants() {
280 let training_config = NormalizationConfig::training();
282 assert!(training_config.track_running_stats);
283 assert!(training_config.affine);
284
285 let inference_config = NormalizationConfig::inference();
286 assert!(!inference_config.track_running_stats);
287
288 let non_affine_config = NormalizationConfig::non_affine();
289 assert!(!non_affine_config.affine);
290
291 let custom_eps_config = NormalizationConfig::with_eps(1e-8);
292 assert_eq!(custom_eps_config.eps, 1e-8);
293
294 let custom_momentum_config = NormalizationConfig::with_momentum(0.05);
295 assert_eq!(custom_momentum_config.momentum, 0.05);
296 }
297}