Struct Dropout

Source
pub struct Dropout<F: Float + Debug + Send + Sync> { /* private fields */ }
Expand description

Dropout layer

During training, randomly sets input elements to zero with probability p. During inference, scales the output by 1/(1-p) to maintain the expected value.

§Examples

use scirs2_neural::layers::{Dropout, Layer};
use ndarray::{Array, Array2};
use rand::rngs::SmallRng;
use rand::SeedableRng;

// Create a dropout layer with 0.5 dropout probability
let mut rng = SmallRng::seed_from_u64(42);
let dropout = Dropout::new(0.5, &mut rng).unwrap();

// Forward pass with a batch of 2 samples, 10 features
let batch_size = 2;
let features = 10;
let input = Array2::<f64>::from_elem((batch_size, features), 1.0).into_dyn();

// Forward pass in training mode (some values will be dropped)
let output = dropout.forward(&input).unwrap();

// Output shape should match input shape
assert_eq!(output.shape(), input.shape());

Implementations§

Source§

impl<F: Float + Debug + ScalarOperand + Send + Sync + 'static> Dropout<F>

Source

pub fn new<R: Rng + 'static + Clone + Send + Sync>( p: f64, rng: &mut R, ) -> Result<Self>

Create a new dropout layer

§Arguments
  • p - Dropout probability (0.0 to 1.0)
  • rng - Random number generator
§Returns
  • A new dropout layer
Examples found in repository?
examples/model_evaluation_example.rs (line 54)
43    fn build(&self) -> Result<Self::Model> {
44        let mut model = Sequential::new();
45
46        let mut rng = SmallRng::seed_from_u64(42);
47        model.add(Dense::<F>::new(
48            self.input_dim,
49            self.hidden_dim,
50            Some("relu"),
51            &mut rng,
52        )?);
53
54        model.add(Dropout::<F>::new(0.2, &mut rng)?);
55
56        model.add(Dense::<F>::new(
57            self.hidden_dim,
58            self.output_dim,
59            None,
60            &mut rng,
61        )?);
62
63        Ok(model)
64    }
More examples
Hide additional examples
examples/image_classification_complete.rs (line 165)
151fn build_cnn_model(
152    input_channels: usize,
153    num_classes: usize,
154    rng: &mut SmallRng,
155) -> Result<Sequential<f32>> {
156    let mut model = Sequential::new();
157
158    // First convolutional block
159    model.add(Dense::new(
160        input_channels * 32 * 32,
161        512,
162        Some("relu"),
163        rng,
164    )?);
165    model.add(Dropout::new(0.25, rng)?);
166
167    // Hidden layers
168    model.add(Dense::new(512, 256, Some("relu"), rng)?);
169    model.add(Dropout::new(0.25, rng)?);
170
171    model.add(Dense::new(256, 128, Some("relu"), rng)?);
172    model.add(Dropout::new(0.25, rng)?);
173
174    // Output layer
175    model.add(Dense::new(128, num_classes, Some("softmax"), rng)?);
176
177    Ok(model)
178}
examples/model_architecture_visualization.rs (line 98)
91fn create_mlp_model(rng: &mut SmallRng) -> Result<Sequential<f32>> {
92    let mut model = Sequential::new();
93
94    // Hidden layers with decreasing sizes
95    let dense1 = Dense::new(784, 512, Some("relu"), rng)?;
96    model.add_layer(dense1);
97
98    let dropout1 = Dropout::new(0.2, rng)?;
99    model.add_layer(dropout1);
100
101    let dense2 = Dense::new(512, 256, Some("relu"), rng)?;
102    model.add_layer(dense2);
103
104    let dense3 = Dense::new(256, 128, Some("relu"), rng)?;
105    model.add_layer(dense3);
106
107    let dropout2 = Dropout::new(0.3, rng)?;
108    model.add_layer(dropout2);
109
110    // Output layer
111    let dense4 = Dense::new(128, 10, Some("softmax"), rng)?;
112    model.add_layer(dense4);
113
114    Ok(model)
115}
116
117// Create a simple CNN model for MNIST
118fn create_cnn_model(rng: &mut SmallRng) -> Result<Sequential<f32>> {
119    let mut model = Sequential::new();
120
121    // First convolutional block
122    let conv1 = Conv2D::new(
123        1,                      // input channels
124        32,                     // output channels
125        (3, 3),                 // kernel size
126        (1, 1),                 // stride
127        PaddingMode::Custom(1), // padding mode
128        rng,
129    )?;
130    model.add_layer(conv1);
131
132    let batch_norm1 = BatchNorm::new(32, 0.99, 1e-5, rng)?;
133    model.add_layer(batch_norm1);
134
135    // Second convolutional block
136    let conv2 = Conv2D::new(
137        32,                     // input channels
138        64,                     // output channels
139        (3, 3),                 // kernel size
140        (2, 2),                 // stride (downsampling)
141        PaddingMode::Custom(1), // padding mode
142        rng,
143    )?;
144    model.add_layer(conv2);
145
146    let batch_norm2 = BatchNorm::new(64, 0.99, 1e-5, rng)?;
147    model.add_layer(batch_norm2);
148
149    let dropout1 = Dropout::new(0.25, rng)?;
150    model.add_layer(dropout1);
151
152    // Flatten for fully connected layers - commented out as Flatten is not available
153    // let flatten = Flatten::new()?;
154    // model.add_layer(flatten);
155
156    // Dense layers
157    let dense1 = Dense::new(64 * 14 * 14, 128, Some("relu"), rng)?;
158    model.add_layer(dense1);
159
160    let dropout2 = Dropout::new(0.5, rng)?;
161    model.add_layer(dropout2);
162
163    // Output layer
164    let dense2 = Dense::new(128, 10, Some("softmax"), rng)?;
165    model.add_layer(dense2);
166
167    Ok(model)
168}
examples/improved_model_serialization.rs (line 26)
13fn create_xor_model(rng: &mut SmallRng) -> Result<Sequential<f32>> {
14    let mut model = Sequential::new();
15
16    // XOR problem requires a hidden layer
17    let input_dim = 2;
18    let hidden_dim = 4;
19    let output_dim = 1;
20
21    // Input to hidden layer with ReLU activation
22    let dense1 = Dense::new(input_dim, hidden_dim, Some("relu"), rng)?;
23    model.add_layer(dense1);
24
25    // Optional dropout for regularization (low rate as XOR is small)
26    let dropout = Dropout::new(0.1, rng)?;
27    model.add_layer(dropout);
28
29    // Hidden to output layer with sigmoid activation (binary output)
30    let dense2 = Dense::new(hidden_dim, output_dim, Some("sigmoid"), rng)?;
31    model.add_layer(dense2);
32
33    Ok(model)
34}
examples/advanced_training_example.rs (line 37)
20fn create_regression_model<
21    F: Float + Debug + ScalarOperand + Send + Sync + FromPrimitive + 'static,
22>(
23    input_dim: usize,
24    hidden_dim: usize,
25    output_dim: usize,
26) -> Result<Sequential<F>> {
27    let mut model = Sequential::new();
28
29    // Create RNG for initializing layers
30    let mut rng = SmallRng::seed_from_u64(42);
31
32    // First dense layer with ReLU activation
33    let dense1 = Dense::new(input_dim, hidden_dim, Some("relu"), &mut rng)?;
34    model.add(dense1);
35
36    // Dropout layer for regularization
37    let dropout1 = Dropout::new(0.2, &mut rng)?;
38    model.add(dropout1);
39
40    // Second dense layer with ReLU activation
41    let dense2 = Dense::new(hidden_dim, hidden_dim / 2, Some("relu"), &mut rng)?;
42    model.add(dense2);
43
44    // Another dropout layer
45    let dropout2 = Dropout::new(0.2, &mut rng)?;
46    model.add(dropout2);
47
48    // Output layer with no activation
49    let dense3 = Dense::new(hidden_dim / 2, output_dim, None, &mut rng)?;
50    model.add(dense3);
51
52    Ok(model)
53}
examples/text_classification_complete.rs (line 336)
313fn build_text_model(
314    _vocab_size: usize,
315    embedding_dim: usize,
316    hidden_dim: usize,
317    num_classes: usize,
318    max_length: usize,
319    rng: &mut SmallRng,
320) -> StdResult<Sequential<f32>> {
321    let mut model = Sequential::new();
322
323    // Note: This is a simplified version since our Sequential model expects specific layer types
324    // In a real implementation, we'd need specialized text layers
325
326    // Flatten the input tokens and use dense layers to simulate embedding and LSTM processing
327    let input_size = max_length; // Each token position
328
329    // Simulate embedding layer with dense transformation
330    model.add(Dense::new(
331        input_size,
332        embedding_dim * 2,
333        Some("relu"),
334        rng,
335    )?);
336    model.add(Dropout::new(0.1, rng)?);
337
338    // Simulate LSTM processing with dense layers
339    model.add(Dense::new(
340        embedding_dim * 2,
341        hidden_dim,
342        Some("tanh"),
343        rng,
344    )?);
345    model.add(Dropout::new(0.2, rng)?);
346
347    // Add attention-like mechanism with another dense layer
348    model.add(Dense::new(hidden_dim, hidden_dim / 2, Some("relu"), rng)?);
349    model.add(Dropout::new(0.2, rng)?);
350
351    // Classification head
352    model.add(Dense::new(
353        hidden_dim / 2,
354        num_classes,
355        Some("softmax"),
356        rng,
357    )?);
358
359    Ok(model)
360}
361
362/// Build an advanced text model with attention
363fn build_attention_text_model(
364    _vocab_size: usize,
365    embedding_dim: usize,
366    hidden_dim: usize,
367    num_classes: usize,
368    max_length: usize,
369    rng: &mut SmallRng,
370) -> StdResult<Sequential<f32>> {
371    let mut model = Sequential::new();
372
373    // Simplified attention-based model using dense layers
374    let input_size = max_length;
375
376    // Multi-layer processing to simulate transformer-like behavior
377    model.add(Dense::new(input_size, embedding_dim, Some("relu"), rng)?);
378    model.add(Dropout::new(0.1, rng)?);
379
380    // Simulate self-attention with dense layers
381    model.add(Dense::new(embedding_dim, hidden_dim, Some("relu"), rng)?);
382    model.add(Dropout::new(0.1, rng)?);
383
384    // Second attention layer
385    model.add(Dense::new(hidden_dim, hidden_dim, Some("relu"), rng)?);
386    model.add(Dropout::new(0.1, rng)?);
387
388    // Global pooling simulation
389    model.add(Dense::new(hidden_dim, hidden_dim / 2, Some("relu"), rng)?);
390    model.add(Dropout::new(0.2, rng)?);
391
392    // Classification head
393    model.add(Dense::new(
394        hidden_dim / 2,
395        num_classes,
396        Some("softmax"),
397        rng,
398    )?);
399
400    Ok(model)
401}
Source

pub fn set_training(&mut self, training: bool)

Set the training mode

In training mode, elements are randomly dropped. In inference mode, all elements are kept but scaled.

Examples found in repository?
examples/dropout_example.rs (line 163)
7fn main() -> Result<(), Box<dyn std::error::Error>> {
8    println!("Dropout Example");
9
10    // Initialize random number generator with a fixed seed for reproducibility
11    let mut rng = SmallRng::seed_from_u64(42);
12
13    // 1. Example: Simple dropout on a vector
14    println!("\nExample 1: Simple dropout on a vector");
15
16    // Create a vector of ones
17    let n_features = 20;
18    let input = Array2::<f32>::from_elem((1, n_features), 1.0);
19
20    // Create a dropout layer with dropout probability 0.5
21    let dropout = Dropout::new(0.5, &mut rng)?;
22
23    // Apply dropout in training mode
24    let output = dropout.forward(&input.into_dyn())?;
25
26    // Count elements that were dropped
27    let mut dropped_count = 0;
28    for i in 0..n_features {
29        let val = output.slice(ndarray::s![0, i]).into_scalar();
30        if *val == 0.0 {
31            dropped_count += 1;
32        }
33    }
34
35    // Print results
36    println!("Input: Array of {} ones", n_features);
37    println!(
38        "Output after dropout (p=0.5): {} elements dropped",
39        dropped_count
40    );
41    println!(
42        "Dropout rate: {:.2}%",
43        (dropped_count as f32 / n_features as f32) * 100.0
44    );
45
46    // 2. Example: Using dropout in a neural network to prevent overfitting
47    println!("\nExample 2: Using dropout in a simple neural network");
48
49    // Create a simple neural network with dropout
50    // 1. Create dense layer (input -> hidden)
51    let input_dim = 10;
52    let hidden_dim = 100;
53    let output_dim = 2;
54    let dense1 = Dense::new(input_dim, hidden_dim, Some("relu"), &mut rng)?;
55
56    // 2. Create dropout layer (after first dense layer)
57    let dropout1 = Dropout::new(0.2, &mut rng)?;
58
59    // 3. Create second dense layer (hidden -> output)
60    let dense2 = Dense::new(hidden_dim, output_dim, None, &mut rng)?;
61
62    // Generate a random input
63    let batch_size = 16;
64    let mut input_data = Array2::<f32>::zeros((batch_size, input_dim));
65    for i in 0..batch_size {
66        for j in 0..input_dim {
67            input_data[[i, j]] = rng.random_range(-1.0..1.0);
68        }
69    }
70
71    // Forward pass through the network with dropout
72    println!("Running forward pass with dropout...");
73    let hidden_output = dense1.forward(&input_data.clone().into_dyn())?;
74    let hidden_dropped = dropout1.forward(&hidden_output)?;
75    let final_output = dense2.forward(&hidden_dropped)?;
76
77    println!("Input shape: {:?}", input_data.shape());
78    println!("Hidden layer shape: {:?}", hidden_output.shape());
79    println!("Output shape: {:?}", final_output.shape());
80
81    // 3. Example: Dropout in a CNN architecture
82    println!("\nExample 3: Dropout in a CNN architecture");
83
84    // Create a sample CNN architecture with dropout
85
86    // 1. Create convolutional layer
87    let in_channels = 3; // RGB input
88    let out_channels = 16;
89    let conv1 = Conv2D::new(
90        in_channels,
91        out_channels,
92        (3, 3),
93        (1, 1),
94        PaddingMode::Same,
95        &mut rng,
96    )?;
97
98    // 2. Create batch normalization layer
99    let bn1 = BatchNorm::new(out_channels, 0.9, 1e-5, &mut rng)?;
100
101    // 3. Create dropout layer for spatial dropout (dropping entire feature maps)
102    let dropout_conv = Dropout::new(0.25, &mut rng)?;
103
104    // 4. Create flattened dense layer
105    let height = 32;
106    let width = 32;
107    let flattened_size = out_channels * height * width;
108    let dense3 = Dense::new(flattened_size, output_dim, None, &mut rng)?;
109
110    // Generate random input image
111    let mut image_input = Array4::<f32>::zeros((batch_size, in_channels, height, width));
112    for n in 0..batch_size {
113        for c in 0..in_channels {
114            for h in 0..height {
115                for w in 0..width {
116                    image_input[[n, c, h, w]] = rng.random_range(-1.0..1.0);
117                }
118            }
119        }
120    }
121
122    // Forward pass through CNN with dropout
123    println!("Running forward pass through CNN with dropout...");
124    let conv_output = conv1.forward(&image_input.clone().into_dyn())?;
125    let bn_output = bn1.forward(&conv_output)?;
126    let dropout_output = dropout_conv.forward(&bn_output)?;
127
128    // Reshape for dense layer (flatten spatial and channel dimensions)
129    let mut flattened = Array2::<f32>::zeros((batch_size, flattened_size));
130    for n in 0..batch_size {
131        let mut idx = 0;
132        for c in 0..out_channels {
133            for h in 0..height {
134                for w in 0..width {
135                    flattened[[n, idx]] =
136                        *dropout_output.slice(ndarray::s![n, c, h, w]).into_scalar();
137                    idx += 1;
138                }
139            }
140        }
141    }
142
143    let cnn_output = dense3.forward(&flattened.into_dyn())?;
144
145    println!("CNN output shape: {:?}", cnn_output.shape());
146
147    // 4. Example: Switching between training and inference modes
148    println!("\nExample 4: Switching between training and inference modes");
149
150    // Create dropout layer with p=0.5
151    let mut switchable_dropout = Dropout::new(0.5, &mut rng)?;
152
153    // Create some input data
154    let test_input = Array2::<f32>::from_elem((1, 10), 1.0);
155
156    // Training mode (default)
157    let training_output = switchable_dropout.forward(&test_input.clone().into_dyn())?;
158
159    // Count non-zero elements in training mode
160    let training_nonzero = training_output.iter().filter(|&&x| x != 0.0).count();
161
162    // Switch to inference mode
163    switchable_dropout.set_training(false);
164    let inference_output = switchable_dropout.forward(&test_input.clone().into_dyn())?;
165
166    // Count non-zero elements in inference mode
167    let inference_nonzero = inference_output.iter().filter(|&&x| x != 0.0).count();
168
169    println!("Training mode: {} of 10 elements kept", training_nonzero);
170    println!("Inference mode: {} of 10 elements kept", inference_nonzero);
171
172    // In inference mode, all elements should be preserved
173    assert_eq!(inference_nonzero, 10);
174
175    println!("\nDropout implementation demonstration completed successfully!");
176
177    Ok(())
178}
Source

pub fn p(&self) -> f64

Get the dropout probability

Source

pub fn is_training(&self) -> bool

Get the training mode

Trait Implementations§

Source§

impl<F: Float + Debug + Send + Sync> Clone for Dropout<F>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

const fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<F: Float + Debug + Send + Sync> Debug for Dropout<F>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<F: Float + Debug + ScalarOperand + Send + Sync + 'static> Layer<F> for Dropout<F>

Source§

fn as_any(&self) -> &dyn Any

Get the layer as a dyn Any for downcasting Read more
Source§

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>>

Forward pass of the layer Read more
Source§

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<()>

Update the layer parameters with the given gradients Read more
Source§

fn layer_type(&self) -> &str

Get the type of the layer (e.g., “Dense”, “Conv2D”) Read more
Source§

fn parameter_count(&self) -> usize

Get the number of trainable parameters in this layer Read more
Source§

fn layer_description(&self) -> String

Get a detailed description of this layer Read more
Source§

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

Get the current training mode Read more
Source§

fn params(&self) -> Vec<Array<F, IxDyn>>

Get the parameters of the layer Read more
Source§

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<()>

Set the gradients of the layer parameters Read more
Source§

fn set_params(&mut self, _params: &[Array<F, IxDyn>]) -> Result<()>

Set the parameters of the layer Read more

Auto Trait Implementations§

§

impl<F> Freeze for Dropout<F>
where F: Freeze,

§

impl<F> RefUnwindSafe for Dropout<F>
where F: RefUnwindSafe,

§

impl<F> Send for Dropout<F>

§

impl<F> Sync for Dropout<F>

§

impl<F> Unpin for Dropout<F>
where F: Unpin,

§

impl<F> UnwindSafe for Dropout<F>
where F: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

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
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V