The layer normalization primitive performs a forward or backward layer normalization operation on 2-5D data tensor.
The layer normalization operation performs normalization over the last logical axis of data tensor and is defined by the following formulas. We show formulas only for 3D data which are straightforward to generalize to cases of higher dimensions. Variable names follow the standard Naming Conventions.
\[ dst(t, n, c) = \gamma(c) \cdot \frac{src(t, n, c) - \mu(t, n)} {\sqrt{\sigma^2(t, n) + \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.
The backward propagation computes \(diff\_src(t, n, c)\), \(diff\_\gamma(c)^*\), and \(diff\_\beta(c)^*\) based on \(diff\_dst(t, n, c)\), \(src(t, n, c)\), \(\mu(t, n)\), \(\sigma^2(t, n)\), \(\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., dnnl_use_scaleshift is set).
Depending on the flags and propagation kind, the layer normalization primitive requires different inputs and outputs. For clarity, the summary table is shown below.
Propagation | Flag | Input | Out |
---|---|---|---|
forward inference | src | dst | |
forward inference | S | src, scaleshift | dst |
forward inference | G | src, mean, variance, scaleshift | dst |
forward training | src | dst, mean, variance | |
forward training | S | src, scaleshift | dst, mean, variance |
forward training | G | src, mean, variance, scaleshift | dst |
backward data | src, mean, variance, diff_dst | diff_src | |
backward data & weights | S | src, mean, variance, diff_dst, scaleshift | diff_src, diff_scaleshift |
flags
parameter that is passed to the operation descriptor initialization function (e.g., dnnl::layer_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 dnnl::layer_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.The operation supports the following combinations of data types:
Propagation | Source / Destination | Mea |
---|---|---|
forward / backward | f32 | f32 |
The mean ( \(\mu\)) and variance ( \(\sigma^2\)) are separate tensors with number of dimensions equal to ( \(data\_ndims - 1\)) and size \((data\_dim[0], data\_dim[1], ..., data\_dim[ndims - 2]).\)
Corresponding memory object can have arbitrary memory format. Unless mean and variance are computed at runtime and not exposed (i.e. propagation kind is dnnl_forward_inference and dnnl_use_global_stats is not set), user should provide memory descriptor for statistics when initializing layer normalization descriptor. For best performance it is adviced to use memory format that follows the data memory format, i.e. data format is dnnl_tnc, best performance can be expected for statistics with dnnl_tn format and suboptimal for statistics with dnnl_nc format.
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 dnnl_nc (dnnl_ab).
Layer normalization primitive works with arbitrary data tensor, however it was designed for RNN data tensors(i.e. dnnl_nc, dnnl_tnc, dnnl_ldnc). Unlike CNN data tensors, RNN data tensors have a single feature dimension. Layer normalization performs normalization over the last logical dimension (feature dimension for RNN tensors) across non-feature dimensions.
The layer normalization primitive is optimized for the following memory formats:
Logical tensor | Imp |
---|---|
NC | dnnl_nc (dnnl_ab) |
TNC | dnnl_tnc (dnnl_abc), dnnl_ntc (dnnl_bac) |
LDNC | dnnl_ldnc (dnnl_abcd) |
src
, dst
, diff_src
, diff_dst
) use memory formats for which last logical axis is the last in the physical memory layout.mean
/variance
use memory format that follows the data memory format, i.e. data format is dnnl_tnc, best performance can be expected for statistics with dnnl_tn and suboptimal for statistics with dnnl_nc format.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.