Layer Normalization学习笔记

原论文:《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:RDRD,向量 α \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=1Dzi,    σ=D1i=1D(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

参考链接:

猜你喜欢

转载自blog.csdn.net/qq_29695701/article/details/102629161