原论文:《Layer Normalization》
目的:消除 Covariate Shift 问题
论文以几何的视角对 Layer Normalization 在生成线性模型(Generalized Linear Models, GLM)上的效果进行了数学上的分析,值得读一下。
论文最后补充了一些LN的应用,可以在使用的时候作参考。
说明:
Layer Normalization 是对 Batch Normalization 的改进:
Batch Normalization 对属于同一个Batch中的数据长度要求是相同的,不适合处理序列型的数据。所以它在NLP领域的RNN上效果并不显著,但在CV领域的CNN上效果显著。
Layer Normalization 的改进点在于:对指定层中神经元的输出进行操作,统计该层所有神经元输出的均值和方差,然后再对这一层的输出进行 Normalization 的操作。它在CV领域的CNN上效果并不显著,但在NLP领域的RNN上效果显著。
数学公式
定义 Layer Normalization 是一个函数映射: L N : R D → R D LN: \mathbb{R}^D \rightarrow \mathbb{R}^D LN:RD→RD,向量 α \pmb{\alpha} ααα 与 β \pmb{\beta} βββ 是可学习的参数:
L N ( z ; α , β ) = z − μ σ ⊙ α + β μ = 1 D ∑ i = 1 D z i , σ = 1 D ∑ i = 1 D ( z i − μ ) 2 + ϵ , LN(\pmb{z};\pmb{\alpha},\pmb{\beta})=\frac{\pmb{z}-\mu}{\sigma}\odot \pmb{\alpha} + \pmb{\beta} \\ \mu=\frac{1}{D}\sum^D_{i=1}z_i, \space \space \space \space \sigma=\sqrt{\frac{1}{D}\sum^D_{i=1}(z_i-\mu)^2 +\epsilon}, LN(zzz;ααα,βββ)=σzzz−μ⊙ααα+βββμ=D1i=1∑Dzi, σ=D1i=1∑D(zi−μ)2+ϵ,
其中 ⊙ \odot ⊙ 是 Hadamard 乘积。
代码(Pytorch)
import torch
import torch.nn as nn
class LayerNorm(nn.Module):
def __init__(self, hidden_size, eps=1e-12):
super(LayerNorm, self).__init__()
self.weight = nn.Parameter(torch.ones(hidden_size))
self.bias = nn.Parameter(torch.zeros(hidden_size))
self.variance_epsilon = eps
def forward(self, x):
# x 的最后一维代表相应层的神经元数量。
u = x.mean(-1, keepdim=True)
s = (x - u).pow(2).mean(-1, keepdim=True)
x = (x - u) / torch.sqrt(s + self.variance_epsilon)
return self.weight * x + self.bias
x.mean(-1, keepdim=True)
是对张量 x \pmb{x} xxx 的最后一维求平均,下面举例说明:
>>> b = torch.randn(3,4,5)
>>> b
tensor([[[-0.3968, -0.3811, 0.3955, -0.4742, 0.0691],
[-2.9539, 0.3107, -0.0400, 1.2068, 0.0339],
[ 1.6077, 1.4081, -0.2140, -0.4642, -1.2632],
[-0.5868, -0.8731, 1.9066, 1.1660, 0.9461]],
[[ 0.6410, -0.3203, -0.6459, 1.4890, 0.2520],
[-2.4112, 0.9095, 0.5199, -0.7084, 1.1000],
[ 0.6031, 2.0735, 0.2750, 0.2774, 1.7539],
[-0.3330, 0.5383, 0.0666, 0.3683, 1.2680]],
[[ 0.2595, -0.0831, -1.1680, 0.9514, -0.4719],
[-0.8601, -0.4811, 1.7969, 0.1297, -1.1031],
[ 1.4512, -2.1718, 1.0916, -1.8542, -1.4614],
[ 0.3722, -0.6037, 0.0523, 0.8142, -0.6698]]])
>>> b.mean(-1, keepdim=True)
tensor([[[-0.1575],
[-0.2885],
[ 0.2149],
[ 0.5117]],
[[ 0.2832],
[-0.1180],
[ 0.9966],
[ 0.3816]],
[[-0.1024],
[-0.1035],
[-0.5889],
[-0.0070]]])
>>> # 其中一个例子:(-0.3968-0.3811+0.3955-0.4742+0.0691)/5 = -0.1575
参考链接: