The batch normalization primitive performs a forward or backward batch normalization operation on 0D, 2D, or 3D spatial data.
The batch normalization operation is defined by the following formulas. We show formulas only for 2D spatial data which are straightforward to generalize to cases of higher and lower dimensions. Variable names follow the standard Naming Conventions.
\[ dst(n, c, h, w) = \gamma(c) \cdot \frac{src(n, c, h, w) - \mu(c)} {\sqrt{\sigma(c) + \varepsilon}} + \beta(c), \]
where
When mean and variance are computed at a run-time the following formulas are used:
The \(\gamma(c)\) and \(\beta(c)\) tensors are considered learnable.
In training mode the primitive also optionally supports fusion with ReLU activation applied to the result (see mkldnn_fuse_norm_relu flag).
workspace
memory as one extra output. This memory is required to compute the backward propagation. When the primitive is executed with propagation kind mkldnn_forward_inference, the workspace is not produced. Behaviour would be the same as creating a batch normalization primitive with ReLU as a post-op (see section below).The backward propagation computes \(diff\_src(n, c, h, w)\), \(diff\_\gamma(c)^*\), and \(diff\_\beta(c)^*\) based on \(diff\_dst(n, c, h, w)\), \(src(n, c, h, w)\), \(\mu(c)\), \(\sigma(c)\), \(\gamma(c) ^*\), and \(\beta(c) ^*\).
The tensors marked with an asterisk are used only when the primitive is configured to use \(\gamma(c)\), and \(\beta(c)\) (i.e., mkldnn_use_scaleshift is set).
Depending on the flags and propagation kind, the batch normalization primitive requires different inputs and outputs. For clarity, the summary table is shown below.
TODO: add?
flags
parameter that is passed to the operation descriptor initialization function (e.g., mkldnn::batch_normalization_forward::desc::desc()). Multiple flags can be set using the bitwise OR operator (|
).src
and dst
are assumed to be the same, and in the API are typically referred as data
(e.g., see data_desc
in mkldnn::batch_normalization_forward::desc::desc()). The same holds for diff_src
and diff_dst
. The corresponding memory descriptors are referred to as diff_data_desc
.src
can be used as input and output for forward propagation, and diff_dst
can be used as input and output for backward propagation. In case of in-place operation, the original data will be overwritten.workspace
, that should be passed during the backward propagation.The operation supports the following combinations of data types:
Propagation | Source / Destination | Mea |
---|---|---|
forward / backward | f32 | f32 |
forward | f16 | f32 |
forward | s8 | f32 |
The mean ( \(\mu\)) and variance ( \(\sigma\)) are separate 1D tensors of size \(C\).
The format of the corresponding memory object must be mkldnn_x (mkldnn_a).
If used, the scale ( \(\gamma\)) and shift ( \(\beta\)) are combined in a single 2D tensor of shape \(2 \times C\).
The format of the corresponding memory object must be mkldnn_nc (mkldnn_ab).
Like other CNN primitives, the batch normalization primitive expects data to be \(N \times C \times SP_n \times \cdots \times SP_0\) tensor.
The batch normalization primitive is optimized for the following memory formats:
Spatial | Logical tensor | Imp |
---|---|---|
0D | NC | mkldnn_nc (mkldnn_ab) |
2D | NCHW | mkldnn_nchw (mkldnn_abcd), mkldnn_nhwc (mkldnn_acdb), optimized^ |
3D | NCDHW | mkldnn_ncdhw (mkldnn_abcde), mkldnn_ndhwc (mkldnn_acdeb), optimized^ |
Here optimized^ means the format that comes out of any preceding compute-intensive primitive.
Post-ops and attributes enable you to modify the behavior of the batch normalization primitive by chaining certain operations after the batch normalization operation. The following post-ops are supported by batch normalization primitives:
Propagation | Type | Operation | Des |
---|---|---|---|
forward | post-op | eltwise | Applies an Eltwise operation to the result (currently only mkldnn_eltwise_relu algorithm is supported) |
workspace
that is required to compute backward propagation correctly. Hence, in case of training one should use the mkldnn_fuse_norm_relu directly.src
, diff_dst
, and diff_src
(the format of the diff_dst
and diff_src
are always the same because of the API). Different formats are functionally supported but lead to highly suboptimal performance.