1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//! Upsampling layers that enlarge the spatial axes by a whole-number factor
//!
//! [`UpSampling1D`], [`UpSampling2D`], and [`UpSampling3D`] multiply the extent of each spatial
//! axis by its factor. The batch axis and the channel axis pass through unchanged. Under the
//! crate's channels-last layout a rank-4 input is `[batch, height, width, channels]`, so
//! [`UpSampling2D`] acts on axes 1 and 2
//!
//! No layer in the family holds a parameter. Each one caches the shape of the most recent
//! forward input, because the backward pass needs that shape to restore it
//!
//! The family is the decoder counterpart of the pooling family. A pooling layer divides a
//! spatial extent, and an upsampling layer multiplies it back. An autoencoder or a segmentation
//! decoder pairs each pooling stage with 1 upsampling stage of the same factor
//!
//! [`Factor2D`] and [`Factor3D`] carry the per-axis factors. Both constructors take
//! `impl Into<..>`, so a call site passes a plain integer or a plain tuple. [`UpSampling1D`]
//! takes a plain integer, because a rank-3 input has only 1 spatial axis
//!
//! Only [`UpSampling2D`] takes an [`Interpolation`]
/// Resize kernels shared by every upsampling layer
pub
/// 1D upsampling layer
/// 2D upsampling layer
/// 3D upsampling layer
pub use UpSampling1D;
pub use UpSampling2D;
pub use UpSampling3D;
/// How [`UpSampling2D`] fills the new positions
///
/// [`Interpolation::Nearest`] repeats each input position, which is the default and the only
/// mode of the 1D and 3D layers. Every other mode resamples with a separable kernel, so a new
/// position takes a weighted sum of its neighbors
///
/// The weights of 1 output position always sum to 1. Near an edge, the kernel reaches past
/// the input, so the layer rescales the remaining weights to keep that sum
///
/// # Examples
///
/// ```rust
/// use rustyml::neural_network::layers::{Interpolation, UpSampling2D};
///
/// // Repeat each pixel into a 2x2 block
/// let blocky = UpSampling2D::new(2, Interpolation::Nearest).unwrap();
///
/// // Blend each new pixel from its neighbors instead
/// let smooth = UpSampling2D::new(2, Interpolation::Bilinear).unwrap();
/// ```
/// The upsampling factors of a rank-4 layer, as 1 whole number per spatial axis
///
/// [`UpSampling2D::new`] takes `impl Into<Factor2D>`. There are 2 forms:
///
/// - an integer `n` multiplies both spatial axes by `n`
/// - a pair `(height, width)` names the factor of each axis
///
/// # Examples
///
/// ```rust
/// use rustyml::neural_network::layers::{Interpolation, UpSampling2D};
///
/// // Twice the height and twice the width
/// let square = UpSampling2D::new(2, Interpolation::Nearest).unwrap();
///
/// // Twice the height and 3 times the width
/// let uneven = UpSampling2D::new((2, 3), Interpolation::Nearest).unwrap();
/// ```
;
/// The upsampling factors of a rank-5 layer, as 1 whole number per spatial axis
///
/// [`UpSampling3D::new`] takes `impl Into<Factor3D>`. There are 2 forms:
///
/// - an integer `n` multiplies all 3 spatial axes by `n`
/// - a triple `(dim1, dim2, dim3)` names the factor of each axis
///
/// # Examples
///
/// ```rust
/// use rustyml::neural_network::layers::UpSampling3D;
///
/// // Twice the extent on all 3 spatial axes
/// let cube = UpSampling3D::new(2).unwrap();
///
/// // A different factor on each axis
/// let uneven = UpSampling3D::new((1, 2, 4)).unwrap();
/// ```
;