精华内容
下载资源
问答
  • batch normalizationlayer normalization 在RNN(LSTM、GRU)上的TensorFlow实现;运行无误,示例为mnist手写体识别
  • Layer Normalization

    2020-08-14 18:02:48
    Layer Normalization 训练最先进的深度神经网络是计算成本很高的。减少训练时间的一种方法是对神经元的活动进行归一化。最近引入的一种称为批量归一化的技术,使用一个神经元的输入在一个mini-batch的训练案例上的...

    Layer Normalization

    训练最先进的深度神经网络是计算成本很高的。减少训练时间的一种方法是对神经元的活动进行归一化。最近引入的一种称为批量归一化的技术,使用一个神经元的输入在一个mini-batch的训练案例上的分布来计算均值和方差,然后用这些均值和方差来归一化该神经元在每个训练案例上的输入。这大大缩短了前馈神经网络的训练时间。然而,批归一化的效果取决于小批量的大小,如何将其应用到循环神经网络中并不明显。在本文中,我们将批归一化移植到层归一化中,通过在单个训练案例上计算层中所有神经元输入的总和,计算用于归一化的均值和方差。与批归一化一样,我们也给每个神经元提供自己的自适应偏置和增益,这些偏置和增益是在归一化之后但在非线性之前应用的。与批归一化不同的是,层归一化在训练和测试时执行完全相同的计算。通过在每个时间步长分别计算归一化统计,它也可以直接应用于循环神经网络。层归一化对稳定循环网络中的隐藏状态动态非常有效。经验上,我们表明,与之前发表的技术相比,层归一化可以大幅缩短训练时间。

    1 Introduction

    在计算机视觉[Krizhevsky等人,2012]和语音处理[Hinton等人,2012]中,用某种版本的随机梯度下降法训练的深度神经网络已被证明在各种监督学习任务上大大优于以前的方法。但是最先进的深度神经网络通常需要很多天的训练。通过在不同的机器上计算训练案例的不同子集的梯度,或者将神经网络本身拆分在许多机器上,可以加快学习速度[Dean等人,2012],但这可能需要大量的通信和复杂的软件。随着并行化程度的增加,它也往往会导致收益迅速降低。一个正交的方法是修改神经网前向通道中执行的计算,以使学习更容易。最近,有人提出了批量归一化[Ioffe和Szegedy,2015],通过在深度神经网络中加入额外的归一化阶段来减少训练时间。归一化使用其在整个训练数据中的平均值和标准差对每个加总输入进行标准化。使用批量归一化训练的前馈神经网络即使使用简单的SGD也能更快地收敛。除了训练时间的改善外,来自批次统计的随机性还可以作为训练过程中的正则化器。

    尽管它很简单,但批量归一化需要运行输入统计量之和的平均值。在具有固定深度的前馈网络中,为每个隐藏层分别存储统计数据是直接的。然而,循环神经网络(RNN)中循环神经元的输入求和往往随着序列的长度而变化,因此将批归一化应用于RNN似乎需要对不同的时间步长进行不同的统计。此外,批归一化不能应用于在线学习任务或极大规模的分布式模型,因为在这些模型中,minibatches必须很小。

    本文介绍了层归一化,这是一种简单的归一化方法,可以提高各种神经网络模型的训练速度。与批归一化不同的是,所提出的方法直接从隐藏层内神经元的输入相加估计归一化统计量,所以归一化不会在训练案例之间引入任何新的依赖关系。我们表明,层归一化对RNNs有很好的效果,并且改善了现有几种RNN模型的训练时间和泛化性能

    2 Background

    前馈神经网络是一个从输入模式x到输出向量y的非线性映射。 考虑一个深度feed-forward,神经网络中的第l个隐藏层,让 a l a^l al是该层神经元输入之和的向量表示。通过线性映射计算求和输入,权重矩阵 W l W^l Wl和自下而上的输入 h l h^l hl给出如下。

    在这里插入图片描述

    其中 f ( ⋅ ) f(\cdot) f()是一个element-wise非线性函数, w i l w_i^l wil是第i个隐藏单元的输入权重, b i l b_i^l bil为标量偏置参数。神经网络中的参数采用基于梯度的优化算法进行学习,梯度通过反向传播计算。

    深度学习的挑战之一是,相对于一层中的权重的梯度高度依赖于前一层中神经元的输出,尤其是当这些输出以高度相关的方式变化时。批量归一化[Ioffe和Szegedy,2015]被提出来减少这种不理想的 “协方差”。该方法对每个隐藏单元在训练案例上的输入之和进行归一化。具体来说,对于第l层的第i个求和输入,批归一化方法根据数据分布下的方差对求和输入进行重新标定。

    在这里插入图片描述

    其中, a ‾ i l \overline a^l_i ail为第l层第i个隐藏单元的归一化输入和, g i g_i gi为非线性激活函数前的增益参数,对归一化激活进行缩放。注意,期望值是在整个训练数据分布下的。准确地计算式(2)中的期望值通常是不切实际的,因为它需要通过当前权重集的整个训练数据集进行正向传递。取而代之的是, μ \mu μ σ \sigma σ是使用当前小批量的经验样本来估计的。这就对mini-batch的大小进行了限制,而且很难应用于循环神经网络

    3 Layer normalization

    我们现在考虑层归一化方法,它是为了克服批归一化的缺点。

    请注意,一层输出的变化往往会引起下一层输入之和的高度相关变化,特别是对于输出可能变化很大的ReLU单元。这说明 "协方差 "问题可以通过固定各层内求和输入的均值和方差来减少。因此,我们对同一层中所有隐藏单元的层归一化统计计算如下。

    在这里插入图片描述

    其中H表示层中隐藏单元的数量。式(2)与式(3)的区别在于,在层规范化下,一层中的所有隐藏单元共享相同的规范化项 μ \mu μ σ \sigma σ ,但不同的训练案例具有不同的规范化项。与批处理规范化不同,层规范化不会对小批量的大小施加任何约束,它可以用于批量大小为1的纯在线状态

    小批量的大小施加任何约束,它可以用于批量大小为1的纯在线状态**。

    展开全文
  • 详说各种 Normalization Batch Normalization 是 Sergey 等人于2015年在 Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift 中提出的一种归一化方法。 在开始讨论之前...

    详说各种 Normalization

    Batch Normalization 是 Sergey 等人于2015年在 Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift 中提出的一种归一化方法。

    在开始讨论之前, 我们需要先探讨一个问题, 对于深度神经网络而言, 什么样的输入是一个好的输入,或者说什么样的输入可以又快又好的训练模型? 通常我们希望输入的数据能够满足独立同分布,并且我们希望数据能分布在激活函数梯度较大的范围之内。可是在深度神经网络中,底层的参数更新会对高层的输入分布产生很大的影响,也就是说即使一开始我们的数据满足了要求,可是随着网络的传递,数据也会发生变化,不能满足要求。作者称这个现象叫 internal covariate shift。为了解决这个问题,作者提出了 Batch Normalization。

    1. 什么是 Batch Normalization?

    直接借用原文中的一副图来说明 Batch Normalization 的过程。
    其中 x i x_i xi 为输入数据, μ β \mu_\beta μβ 为对一个 batch 的输入数据取平均值, σ β 2 \sigma^2_\beta σβ2 为方差, x i ^ \hat{x_i} xi^ 是归一化之后的输入数据,其满足均值为 0 0 0, 方差为 1 1 1 , 是一个标准正太分布。 其中 ϵ \epsilon ϵ 是一个很小的正数,仅仅是为了保证分母不为零。第四个方程是在 x i ^ \hat{x_i} xi^ 基础上做了一个 γ \gamma γ 倍的缩放 和 β \beta β 的偏移。而这里的 γ \gamma γ β \beta β 是超参数,也就是需要通过训练来的学习。

    [外链图片转存失败(img-tris7bWL-1566919964464)(2019-08-25-20-19-06.png)]

    对于整个 Batch Normalization 的过程应该是非常清晰的,就是将输入的数据进行归一化,使其服从均值为 0 0 0, 方差为 1 1 1 的分布。这样使得输入具有相同的均值和方差,固定了每一层的输入分布,从而加速网络的收敛。可能令人费解的是 为什么要进行第四个方程的操作?这里需要结合激活函数来说,比如对于 sigmoid 激活函数,归一化之后的数据输入 sigmoid 激活函数,会使数据落在近乎线性的区域(红色标记的区域仅仅是一个示意,并不严谨),这个区域里 sigmoid 激活函数近乎于一个线性函数,实质上并不能起到非线性的作用,这样就不能起到拟合复杂系统的作用,当拟合能力弱了之后自然训练的结果也不会好。

    那如何解决,作者通过第四步的操作,来解决这个问题。作者希望通过第四部将符合标准正态分布的数据变换回其原本的分布。
    在这里插入图片描述

    也许有人说又变回去了,那前面那些不是白整了吗?当然不是。下面的说法也许不够严谨,但是也可以说明这个问题,比如下面两批数据是同分布的,但是显然数据的结构并不相同,第二批数据明显更不容易过拟合。
    在这里插入图片描述

    2. Batch Normalization 有什么作用?

    • a. 缓解梯度消失,可以增大 learning rate, 使训练更快收敛。
    • b. 简化调参,网络更稳定。在调参时,学习率调得过大容易出现震荡于不收敛,而 BN 抑制了参数微小变化随网络加深而被放大的问题,因此对于参数变化的适应能力更强。
    • c. 更不容易过拟合, 因此可以替代 dropout,或者少用 dropout,可以减少 L2 正则化的权重,同时可以减少 argument 的操作,可以不用太操心 initialization 的操作。

    3. Batch Normalization 放在什么位置?

    通常我们按照如下的位置:

    Conv -> Batch Norm -> ReLU -> Pooling

    当然也有人尝试如下的放置方法
    Conv -> ReLU -> Batch Norm -> Pooling

    后来有人证明(参考论文Rethinking the Usage of Batch Normalization and Dropout in the Training ofDeep Neural Networks):我们不应该把Batch Normalization放在ReLU之前,因为ReLU的非负响应会使权值层更新的方式不太理想。

    4. Test 的时候均值和方差哪里来?

    训练的时候我们每个 batch 都有均值和方差,可是 test 的时候呢?比如我就 test 一张图片。。。通常我们直接拿最后一次训练的时候的均值和方差。所以在实际应用时,需要计算并保存均值和方差信息。

    5. 常用的 Normalization 方式有哪些?

    5.1 Batch Normalization

    Batch Normalization 上面已经介绍过了, 这里仅仅总结一下它的一些特性。

    • batch normalization 和 batch size 紧密相关,当 batch size 比较小时,并不能得到好的统计数据,效果也就大打折扣。
    • batch normalization 是以神经元为单位,计算每个神经元的所有输入的均值和方差
    • batch normalization 需要存储均值和方差信息
    • batch normalization 常用在固定深度的神经网络中, 比如 CNN
    • batch normalization 对于深度不固定的网络, 比如 RNN, 通常计算会比较复杂

    5.2 Layer Nornalization

    Layer Normalization 是 Jimmy Lei Ba 等人(等人里面包括 Hinton)于 2016年 在 Layer Normalization 中提出的一种 normalization 的方法。
    顾名思义,batch normalization 针对每个神经元的输入进行统计,而 layer normalization 则是在每个训练的样本下, 针对每个 layer 中的所有神经元的输入进行统计,得到的均值和方差作为一个规范,对该层的所有输入进行相同的规范化操作。

    Layer Normalization 的特点如下。

    • layer normalization 同一层的均值和方差相同, 不同的输入样本有不同的均值和方差
    • layer normalization 训练和测试的时候进行相同的操作,不需要存储统计信息
    • layer normalization 可以用于RNN, 或者是 batch size 较小的场合
    • layer normalization 对于相似度较大的特征, 会降低模型的表示能力,此时 batch normalization 更优。

    对比 batch normalization 和 layer normalization, 目前 batch normalization 使用更广,对于较大batch size的时候,batch normalization 的表现比 layer normalization好很多, 但是 layer normalization 具有更好适用性。

    5.3 Weight Normalization

    前面的 BN 和 LN 都是针对输入数据进行的 normalization, 而 WN 则是针对 weight 来进行归一化。WN不依赖于输入数据的分布,故可应用于mini-batch较小的情景且可用于动态网络结构。此外,WN还避免了LN中对每一层使用同一个规范化公式的不足。三种规范化方式尽管对输入数据的尺度化(scale)来源不同,但其本质上都实现了数据的规范化操作。

    5.4 Instance Normalization

    Instance Normalization(IN) 是 Dmitry Ulyanov 等人在 2016 年于 Instance Normalization: The Missing Ingredient for Fast Stylization 中提出的一种归一化方式。

    在 GAN 和 style transfer 的任务中,目前的 IN 要好于 BN,IN 主要用于对单张图像的单个通道的数据做处理,而 BN 主要是对整个 Bacth 的数据做处理。由于BN在训练时每个 batch 的均值和方差会由于 shuffle 都会改变,所以可以理解为一种数据增强,而 IN 可以理解为对数据做一个归一化的操作。

    更多可以参考 Batch normalization和Instance normalization的对比?

    5.5 Group Normalization

    Group Normalization 是何凯明等人于 2018 年于 Group Normalization 提出的一种 normalization 方式。Group Normalization(GN)是针对Batch Normalization(BN)在batch size较小时错误率较高而提出的改进算法,因为BN层的计算结果依赖当前 batch 的数据,当 batch size 较小时(比如2、4这样),该 batch 数据的均值和方差的代表性较差,因此对最后的结果影响也较大。GN 根据通道进行分组,然后在每个组内做归一化,计算器均值和方差,从而不受批次中样本数量的约束。这里将通道分为 G 组,G 是一个超参数,通常默认为 32。

    如下图所示,随着 batch size 越来越小,BN 层所计算的统计信息的可靠性越来越差,这样就容易导致最后错误率的上升;而在 batch size 较大时则没有明显的差别。虽然在分类算法中一般的 GPU 显存都能 cover 住较大的 batch 设置,但是在目标检测、分割以及视频相关的算法中,由于输入图像较大、维度多样以及算法本身原因等,batch size 一般都设置比较小,所以 GN 对于这种类型算法的改进应该比较明显。

    [外链图片转存失败(img-K1Cc0Pca-1566919964466)(2019-08-27-22-52-42.png)]

    通过下面的对比图可以清晰的看到,GN 是介于 LN 和 IN直接的一种归一化方式。可以看出BN的计算和 batch size 相关(蓝色区域为计算均值和方差的单元),而 LN、BN 和 GN 的计算和 batch size 无关。同时 LN 和 IN 都可以看作是 GN 的特殊情况(LN是group=C时候的GN,IN是group=1时候的GN)。

    在这里插入图片描述

    上图中,从C方向看过去是指一个个通道,从N看过去是一张张图片。每6个竖着排列的小正方体组成的长方体代表一张图片的一个feature map。蓝色的方块是一起进行Normalization的部分。由此就可以很清楚的看出,Batch Normalization是指6张图片中的每一张图片的同一个通道一起进行Normalization操作。而Instance Normalization是指单张图片的单个通道单独进行Noramlization操作。

    更多内容可以参考全面解读Group Normalization-(吴育昕-何恺明)

    展开全文
  • PyTorch框架学习十八——Layer Normalization、Instance Normalization、Group Normalization一、为什么要标准化?二、BN、LN、IN、GN的异同三、Layer Normalization四、Instance Normalization五、Group ...

    PyTorch框架学习十八——Layer Normalization、Instance Normalization、Group Normalization

    上次笔记介绍了Batch Normalization以及它在PyTorch中的使用:https://blog.csdn.net/qq_40467656/article/details/108375181

    这次笔记将介绍由BN引发的其他标准化层,它们各自适用于不同的应用场景,分别是适用于变长网络的Layer Normalization;适用于图像生成的Instance Normalization;适用于小mini-batch的Group Normalization。

    一、为什么要标准化?

    这个在上次BN的笔记中介绍过,本意是为了解决ICS问题,即随着网络层数加深,数据分布异常(很小或很大),从而导致训练困难。详情回顾:https://blog.csdn.net/qq_40467656/article/details/108375181

    二、BN、LN、IN、GN的异同

    • :都做了标准化的工作。
    • :均值和方差的求取方式不一样,即选择的计算区域不一样,这个可以看完下一小节的详细介绍回过来看,可能会更能理解。

    三、Layer Normalization

    LN提出的起因是因为BN不适用于变长的网络,如RNN,这部分的内容还没有接触过,但是可以简单理解为这种网络的神经元个数是会变化的,不是一样的,如下图所示:
    在这里插入图片描述
    ps:注意这里的横轴不是数据样本个数,只是代表这层网络层神经元可能会变为5/3/4个,在每种个数的情况下,样本数还是一个batchsize的大小。

    第一次可能有五个特征,计算得到五个均值和方差,而第二轮计算时,网络层的神经元变为3个,而BN里计算均值和方差是需要用到之前的结果的,这里之前的五个均值方差就对应不了三个特征,所以BN在这种情况下是不适用的。

    那么LN是怎么计算均值和方差的呢?以一维的情况为例:
    在这里插入图片描述
    之所以称为Layer Norm,就是对该层的数据求均值和方差,不再按照特征那个维度去求,每个样本都单独求其均值方差,可以理解为逐样本的求取方式。

    二维三维的情况类似,如下图所示:
    在这里插入图片描述
    在这里插入图片描述

    LN需要注意的地方:

    • 不再有running_mean和running_var
    • gamma和beta为逐元素的

    LN在PyTorch中的实现:

    torch.nn.LayerNorm(normalized_shape: Union[int, List[int], torch.Size], eps: float = 1e-05, elementwise_affine: bool = True)
    

    参数如下所示:
    在这里插入图片描述

    1. normalized_shape:(int/list/torch.Size)该层的特征维度,即要被标准化的维度。
    2. eps:分母修正项。
    3. elementwise_affine:是否需要affine transform,这里也提醒你是逐元素的仿射变换。

    下面看一个PyTorch实现的例子:

    import torch
    import numpy as np
    import torch.nn as nn
    import sys, os
    hello_pytorch_DIR = os.path.abspath(os.path.dirname(__file__)+os.path.sep+".."+os.path.sep+"..")
    sys.path.append(hello_pytorch_DIR)
    from tools.common_tools import set_seed
    
    set_seed(1)  # 设置随机种子
    
    # ======================================== nn.layer norm
    flag = 1
    # flag = 0
    if flag:
        batch_size = 8
        num_features = 3
    
        features_shape = (3, 4)
    
        feature_map = torch.ones(features_shape)  # 2D
        feature_maps = torch.stack([feature_map * (i + 1) for i in range(num_features)], dim=0)  # 3D
        feature_maps_bs = torch.stack([feature_maps for i in range(batch_size)], dim=0)  # 4D
    
        # feature_maps_bs shape is [8, 3, 3, 4],  B * C * H * W
        ln = nn.LayerNorm(feature_maps_bs.size()[1:], elementwise_affine=True)
        # ln = nn.LayerNorm(feature_maps_bs.size()[1:], elementwise_affine=False)
        # ln = nn.LayerNorm([3, 3, 4])
        # ln = nn.LayerNorm([3, 3])
    
        output = ln(feature_maps_bs)
    
        print("Layer Normalization")
        print(ln.weight.shape)
        print(feature_maps_bs[0, ...])
        print(output[0, ...])
    

    结果如下:

    Layer Normalization
    torch.Size([3, 3, 4])
    tensor([[[1., 1., 1., 1.],
             [1., 1., 1., 1.],
             [1., 1., 1., 1.]],
    
            [[2., 2., 2., 2.],
             [2., 2., 2., 2.],
             [2., 2., 2., 2.]],
    
            [[3., 3., 3., 3.],
             [3., 3., 3., 3.],
             [3., 3., 3., 3.]]])
    tensor([[[-1.2247, -1.2247, -1.2247, -1.2247],
             [-1.2247, -1.2247, -1.2247, -1.2247],
             [-1.2247, -1.2247, -1.2247, -1.2247]],
    
            [[ 0.0000,  0.0000,  0.0000,  0.0000],
             [ 0.0000,  0.0000,  0.0000,  0.0000],
             [ 0.0000,  0.0000,  0.0000,  0.0000]],
    
            [[ 1.2247,  1.2247,  1.2247,  1.2247],
             [ 1.2247,  1.2247,  1.2247,  1.2247],
             [ 1.2247,  1.2247,  1.2247,  1.2247]]], grad_fn=<SelectBackward>)
    

    这边只打印了第一个数据的结果,它的均值是2,所以中间一个3×4的特征标准化之后全为0。

    四、Instance Normalization

    IN层的提出是因为在图像生成任务中,一个batch里的图像的风格可能不尽相同,不能通过BN的计算方式去将各个风格的特征混为一谈,所以BN在这种情况下会不适用。

    那么,IN层的计算方式的思路是逐Instance(channel)地计算均值和方差,如下图所示:
    在这里插入图片描述
    它是每一个样本每一个特征都去计算均值方差然后标准化。

    IN层在PyTorch中的实现如下所示:(以二维为例)

    torch.nn.InstanceNorm2d(num_features: int, eps: float = 1e-05, momentum: float = 0.1, affine: bool = False, track_running_stats: bool = False)
    

    参数如下所示:
    在这里插入图片描述

    1. num_features:一个样本特征的数量。
    2. eps:分母修正项。
    3. momentum:指数加权平均求均值方差。
    4. affine:是否仿射变换,默认False。
    5. track_running_stats:是否追踪batch,使得统计结果更具全局性,一般训练时是需要追踪,测试时不追踪,使用固定的均值方差,默认False(测试)。

    看一个IN的例子:

    flag = 1
    # flag = 0
    if flag:
    
        batch_size = 3
        num_features = 3
        momentum = 0.3
    
        features_shape = (2, 2)
    
        feature_map = torch.ones(features_shape)    # 2D
        feature_maps = torch.stack([feature_map * (i + 1) for i in range(num_features)], dim=0)  # 3D
        feature_maps_bs = torch.stack([feature_maps for i in range(batch_size)], dim=0)  # 4D
    
        print("Instance Normalization")
        print("input data:\n{} shape is {}".format(feature_maps_bs, feature_maps_bs.shape))
    
        instance_n = nn.InstanceNorm2d(num_features=num_features, momentum=momentum, affine=True, track_running_stats=True)
    
        for i in range(1):
            outputs = instance_n(feature_maps_bs)
    
            print(outputs)
            print("\niter:{}, running_mean.shape: {}".format(i, instance_n.running_mean.shape))
            print("iter:{}, running_var.shape: {}".format(i, instance_n.running_var.shape))
            print("iter:{}, weight.shape: {}".format(i, instance_n.weight.shape))
            print("iter:{}, bias.shape: {}".format(i, instance_n.bias.shape))
    

    结果如下:

    Instance Normalization
    input data:
    tensor([[[[1., 1.],
              [1., 1.]],
    
             [[2., 2.],
              [2., 2.]],
    
             [[3., 3.],
              [3., 3.]]],
    
    
            [[[1., 1.],
              [1., 1.]],
    
             [[2., 2.],
              [2., 2.]],
    
             [[3., 3.],
              [3., 3.]]],
    
    
            [[[1., 1.],
              [1., 1.]],
    
             [[2., 2.],
              [2., 2.]],
    
             [[3., 3.],
              [3., 3.]]]]) shape is torch.Size([3, 3, 2, 2])
    tensor([[[[0., 0.],
              [0., 0.]],
    
             [[0., 0.],
              [0., 0.]],
    
             [[0., 0.],
              [0., 0.]]],
    
    
            [[[0., 0.],
              [0., 0.]],
    
             [[0., 0.],
              [0., 0.]],
    
             [[0., 0.],
              [0., 0.]]],
    
    
            [[[0., 0.],
              [0., 0.]],
    
             [[0., 0.],
              [0., 0.]],
    
             [[0., 0.],
              [0., 0.]]]], grad_fn=<ViewBackward>)
    
    iter:0, running_mean.shape: torch.Size([3])
    iter:0, running_var.shape: torch.Size([3])
    iter:0, weight.shape: torch.Size([3])
    iter:0, bias.shape: torch.Size([3])
    

    五、Group Normalization

    GN的提出是因为,随着如今数据样本变得越来越大,以现有的GPU能力可能只能放置比较小的mini-batch,而一个batch比较少的数据的话,使用BN可能计算得到的均值和方差就有较大的偏差,估计的值不准,所以BN在小mini-batch的场景下不适用。

    那么GN的计算思路就是:数据样本不够,通道(特征)数来凑,其如下所示:
    在这里插入图片描述

    图中所示是将一个样本的两个特征划分为一个group,这里只是为了说明GN的原理,实际上特征数是很多的,比如256,那么我们分为两组的话,一组有128个特征通道,数量还是比较可观的,在这样的分组下对每一组单独求取均值方差然后标准化。

    注意:

    • 不再有running_mean和running_var,与LN一致。
    • gamma和beta为逐通道的。

    应用场景:大模型,小batch size的任务。

    GN在PyTorch中的实现如下:

    torch.nn.GroupNorm(num_groups: int, num_channels: int, eps: float = 1e-05, affine: bool = True)
    

    参数如下所示:

    在这里插入图片描述

    1. num_groups:分组数。
    2. num_channels:通道数。
    3. eps:同上。
    4. affine:是否仿射变换。

    下面看一个例子:

    flag = 1
    # flag = 0
    if flag:
    
        batch_size = 2
        num_features = 4
        num_groups = 2   # 3 Expected number of channels in input to be divisible by num_groups
    
        features_shape = (2, 2)
    
        feature_map = torch.ones(features_shape)    # 2D
        feature_maps = torch.stack([feature_map * (i + 1) for i in range(num_features)], dim=0)  # 3D
        feature_maps_bs = torch.stack([feature_maps * (i + 1) for i in range(batch_size)], dim=0)  # 4D
    
        gn = nn.GroupNorm(num_groups, num_features)
        outputs = gn(feature_maps_bs)
    
        print("Group Normalization")
        print(gn.weight.shape)
        print(outputs[0])
    

    结果如下:

    Group Normalization
    torch.Size([4])
    tensor([[[-1.0000, -1.0000],
             [-1.0000, -1.0000]],
    
            [[ 1.0000,  1.0000],
             [ 1.0000,  1.0000]],
    
            [[-1.0000, -1.0000],
             [-1.0000, -1.0000]],
    
            [[ 1.0000,  1.0000],
             [ 1.0000,  1.0000]]], grad_fn=<SelectBackward>)
    

    最后放一张BN、LN、IN和GN的计算方式示例图,帮助理解:
    在这里插入图片描述

    展开全文
  • 关于batch normalizationlayer normalization的理解

    千次阅读 多人点赞 2020-06-27 23:38:48
    在深度学习中经常看到batch normalization的使用,在Bert模型里面经常看到layer normalization的使用。它们都是归一化的方法,具体的作用和区别以及为何能够work,我认为需要有一个很好的理解。因此,在参考了一些...

    目录

    一、batch normalization和layer normalization的动机

    二、BN和LN的框架原理

    2.1BN和LN的具体操作原理

    2.2BN和LN的优点和不足

    2.3BN和LN的不同

    2.4BN和LN的实例代码展示

    三、Bert、Transformer中为何使用的是LN而很少使用BN

    3.1第一个解释

    3.2第二个解释


            在深度学习中经常看到batch normalization的使用,在Bert模型里面经常看到layer normalization的使用。它们都是归一化的方法,具体的作用和区别以及为何能够work,我认为需要有一个很好的理解。因此,在参考了一些资料形成了这篇博客。

    一、batch normalization和layer normalization的动机

    batch normalization和layer normalization,顾名思义其实也就是对数据做归一化处理——也就是对数据以某个角度或者层面做0均值1方差的处理。

              在机器学习和深度学习中,有一个共识:独立同分布的数据可以简化模型的训练以及提升模型的预测能力——这是通过训练数据获得的模型能够在测试集获得好的效果的一个基本保障。也就是说我们在使用机器学习和深度学习的时候,会把数据尽可能的做一个独立同分布的处理,用来加快模型的训练速度和提升模型的性能。说到这里就不得不提一下——白化whitening。

    白化whitening

    什么是白化呢?就是对数据进行如下的2个操作:

    1、去除数据之间的关联性,使之满足独立这个条件;2、使得特征具有相同的均值和方差,就是同分布。

    以上就是白化,具体的算法有PCA降维白化,参考博文——机器学习(七)白化whitening

    首先看看,深度学习中的一个经典问题。Internal Covariate Shift——内部变量偏移

    Internal Covariate Shift——内部变量偏移

    深度学习这种包含很多隐层的网络结构,在训练过程中,因为各层参数不停在变化。另一方面,深度神经网络一般都是很多层的叠加,每一层的参数更新都会导致上层的输入数据在输出时分布规律发生了变化,并且这个差异会随着网络深度增大而增大——这就是Internal Covariate Shift。它会导致什么样的问题呢?

    每个神经元的输入数据不再是独立同分布的了,那么:

    1. 上层参数需要不断适应新的输入数据分布,降低学习速度
    2. 下层输入的变化可能趋向于变大或者变小,导致上层落入饱和区。反向传播时低层神经网络的梯度消失,这是训练深层神经网络收敛越来越慢的本质原因——梯度消失。

    BN把每层神经网络任意神经元这个输入值的分布强行拉回到均值为0方差为1的标准正态分布,其实就是把越来越偏的分布强制拉回比较标准的分布。这样让梯度变大,避免梯度消失问题产生,而且梯度变大意味着学习收敛速度快,能大大加快训练速度。经过BN后,目前大部分Activation的值落入非线性函数的线性区内,其对应的导数远离导数饱和区,这样来加速训练收敛过程。

    这就是在深度学习中使用BN的一个原因和动机,当然使用LN也是同样的以不同的方式来达到相似的效果。

    对于为何BN能起作用这个问题,有不同的观点。有人认为BN能够减少ICS问题,但是有人发布论文说并没有直接的证据表明BN能够稳定数据分布的稳定性,同时也不能减少ICS。作者认为起作用的原因是由于:An empirical analysis of the optimization of deep network loss surfaces

    1、BN层让损失函数更平滑

    2、BN更有利于梯度下降,使得梯度不会出现过大或者过小的梯度值。

    二、BN和LN的框架原理

    2.1BN和LN的具体操作原理

    BN一般怎么使用呢?原论文的作者是建议把BN放在激活函数之前,但是后面有人建议放在之后,效果都差不太多。

    图片来自博文——Batch Normalization详解

    以上就是在一些神经网络中,BN的插入位置。

    下面来看看具体的BN公式和流程。现在假设batch size为m,那么在前向传播过程中每个节点就有m个输出。则有如下计算方式:

    变换后某个神经元的激活x形成了均值为0,方差为1的正态分布,目的是把值往后续要进行的非线性变换的线性区拉动,增大导数值,增强反向传播信息流动性,加快训练收敛速度。但是这样会导致网络表达能力下降,为了防止这一点,每个神经元增加两个调节参数(scale和shift),这两个参数是通过训练来学习到的,用来对变换后的激活反变换,使得网络表达能力增强,即对变换后的激活进行如下的scale和shift操作,这其实是变换的反操作:

    BN不同,LN是针对深度网络的某一层的所有神经元的输入按以下公式进行normalize操作——来自博客:Layer Normalization

    1)计算各层的期望μ和标注差σ

    l表示第l个隐藏层,H表示该层的节点数,a表示某一个节点在激活前的值,即a=w*x。

    2)标准化

    g和b分别表示增益和偏置参数,可以纳入训练随样本一群训练。

    3)加入激活函数输出

    2.2BN和LN的优点和不足

    BN具有一些什么样的优点呢?

    a、加快神经网络的训练时间。BN强行拉平了数据分布,它可以让收敛速度更快。使得总的训练时间更短。

    b、容忍更高的学习率(learning rate)和初始化权重更容易。对于深层网络来说,权重的初始化要求是很高的,而BN能够动态的调整数据分布,因此初始化的要求就不像以前那么严格了。

    c、可以支持更多的损失函数。有些损失函数在一定的业务场景下表现的很差,就是因为输入落入了激活函数的死亡区域——饱和区域。而BN的本质作用就是可以重新拉正数据分布,避免输入落入饱和区域,从而减缓梯度消失的问题。

    d、提供了一点正则化的作用,可能使得结果更好。BN在一定的程度上起到了dropout的作用,因此在适用BN的网络中可以不用dropout来实现。

    那么BN的不足呢?

    a、BN对于batch_size的大小还是比较敏感的,batch_size很小的时候,其梯度不够稳定,效果反而不好。

    b、BN对于序列网络,RNN、lstm等模型的效果并不好

     

    针对以上BN的不足,主要是BN应用到RNN、LSTM等网络上效果不好的缺点,研究人员提出了LN。在继承了BN的优点上,还有另外2个优点:

    1、LN能够很好的应用在RNN、lstm等类似的网络上。

    2、LN是针对一层网络所有的神经元做数据归一化,因此对batch_size的大小并不敏感。

    2.3BN和LN的不同

    从原理操作上来讲,BN针对的是同一个batch内的所有数据,而LN则是针对单个样本。另外,从特征维度来说,BN是对同一batch内的数据的同一纬度做归一化,因此有多少维度就有多少个均值和方差;而LN则是对单个样本的所有维度来做归一化,因此一个batch中就有batch_size个均值和方差。借用知乎上的一张图——batchNormalization与layerNormalization的区别——来说明:

    preview

    简单的来说就是BN和LN进行处理的方向不同。对于BN来说,batch_size大小不同,那么它对应的BN出来的mean和std都是变化的,上图中batch_size=3,均值是mean=3,std=3(第0维度),当batch_size不是3的时候,那么均值和方差就会改变;而LN随着batch_size的不同对应单条样本的均值和方差不同——————BN对batch比较敏感,batch_size不能太小;LN则是独立于batch_size的———就可以这么理解。

    2.4BN和LN的实例代码展示

    直接上代码:

    import torch
    from torch.nn import BatchNorm1d
    from torch.nn import LayerNorm
    
    
    def show_difference_BN_LN():
        input = torch.tensor([[4.0, 3.0, 2.0],
                              [3.0, 3.0, 2.0],
                              [2.0, 2.0, 2.0]
                              ])
        print(input)
        print(input.size())
    
        BN = BatchNorm1d(input.size()[1]) #`C` from an expected input of size (N, C, L)` or :math:`L` from input of size :math:`(N, L)`
        BN_output = BN(input)
        print('BN_output:')
        print(BN_output)
        print('BN_output.size()',BN_output.size())
        print('*'*20)
    
        LN = LayerNorm(input.size()[1:]) #normalized_shape (int or list or torch.Size): input shape from an expected input
        LN_output = LN(input)
        print('LN_output:')
        print( LN_output)
        print('LN_output.size()', LN_output.size())
    
        print('#' * 40)
    
        input_text = torch.tensor([
            [[1.0, 4.0, 7.0],
             [0.0, 2.0, 4.0]
             ],
            [[1.0, 3.0, 6.0],
             [2.0, 3.0, 1.0]
             ]
        ])
    
        print(input_text)
        print(input_text.size())
    
        BN = BatchNorm1d(2)#`C` from an expected input of size (N, C, L)` or :math:`L` from input of size :math:`(N, L)`
        BN_output = BN(input_text)
        print('BN_output:')
        print( BN_output)
        print('BN_output.size()', BN_output.size())
        print('*' * 20)
    
        # LN = LayerNorm(input_text.size()[1:])
        LN = LayerNorm(3)
        LN_output = LN(input_text)
        print('LN_output:')
        print( LN_output)
        print('LN_output.size()', LN_output.size())
    
    
    if __name__ == '__main__':
        show_difference_BN_LN()

    结果如下:

    上图中,第一个torch.Size([3, 3])输入的结果用红色框表上的出现0的地方,和我想的一样,然后蓝色框出现的0不理解。

    第二个输入torch.Size([2, 2, 3])的结果LN的输出出现0的地方很好理解,符合LN均值归一化;BN则是没有太看懂!有理解很清楚的人可以讲解一下!万分感谢!这个细节我还没有理解到位——表示好难。。。。。。。。

     

    三、Bert、Transformer中为何使用的是LN而很少使用BN

    其实这个问题是一个比较难的问题,我个人理解也是很有限的。参阅了很多资料,比较能接受2个解释。

    3.1第一个解释

    我们先把这个问题转化一下,因为Bert和Transformer基本都是应用到了NLP任务上。所以可以这样问:

    为何CV数据任务上很少用LN,用BN的比较多,而NLP上应用LN是比较多的?

    我们用文本数据句话来说明BN和LN的操作区别。

    我是中国人我爱中国

    武汉抗疫非常成功0

    大家好才是真的好0

    人工智能很火000

    上面的4条文本数据组成了一个batch的数据,那么BN的操作的时候

    就会把4条文本相同位置的字来做归一化处理,例如:我、武、大、人

    我认为这里就破坏了一句话内在语义的联系。

    而LN则是针对每一句话做归一化处理。例如:我是中国人我爱中国——归一化处理后,一句话内每个字之间的联系并没有破坏。从这个角度看,LN就比较适合NLP任务,也就是bert和Transformer用的比较多。

     

    3.2第二个解释

    1、layer normalization 有助于得到一个球体空间中符合0均值1方差高斯分布的 embedding, batch normalization不具备这个功能。

    2、layer normalization可以对transformer学习过程中由于多词条embedding累加可能带来的“尺度”问题施加约束,相当于对表达每个词一词多义的空间施加了约束,有效降低模型方差。batch normalization也不具备这个功能。

    NLP和CV的任务差别:

    图像数据是自然界客观存在的,像素的组织形式已经包含了“信息”

    NLP数据则是又embedding开始的,这个embedding并不是客观存在的,它是由我们设计的网络学习出来的。

    通过layer normalization得到的embedding是 以坐标原点为中心,1为标准差,越往外越稀疏的球体空间中。这个正是我们理想的数据分布。

    另外一词多义的表示中——简单来说,每个词有一片相对独立的小空间,通过在这个小空间中产生一个小的偏移来达到表示一词多义的效果。transformer每一层都做了这件事,也就是在不断调整每个词在空间中的位置。这个调整就可以由layer normalization 来实现,batch normalization是做不到的。

     

     

    参考文章

    batchNormalization与layerNormalization的区别

    NLP中 batch normalization与 layer normalization

    transformer 为什么使用 layer normalization,而不是其他的归一化方法?

    展开全文
  • 关于tensorflow中layernormalization

    千次阅读 2020-04-22 18:16:41
    众所周知循环神经网络不是十分适合LayerNormalization 关于LayerNormalization:https://blog.csdn.net/liuxiao214/article/details/81037416 LN中同层神经元输入拥有相同的均值和方差,不同的输入样本有不同的均值...
  • torch.nn.LayerNorm( normalized_shape, eps=1e-05, elementwise_affine=True) 参数介绍: normalized_shape 输入尺寸 (多大的内容进行归一化)【默认是靠右的几个size(后面实例会说明)】 ...
  • NLP中的Layer Normalization

    2021-10-02 20:30:13
    最近在学习pytorch的模型训练过程,...这两个函数还是比较好理解的,Dropout层我们也比较熟悉,但在NLP领域中BN(Batch Normalization)层不是很常见,通常我们使用layer nomalization,所以就学习了一下。 Batch ...
  • Layer Normalization原理介绍

    千次阅读 2019-07-23 20:53:58
    前面介绍了Batch Normalization的原理,我们知道,BN层在CNN中可以加速模型的训练,并防止模型过拟合和梯度消失。但是,如果将BN层直接应用在RNN中可不可行呢,原则上也是可以的,但是会出现一些问题,因为我们知道...
  • 原论文:《Layer Normalization》 目的:消除 Covariate Shift 问题 论文以几何的视角对 Layer Normalization 在生成线性模型(Generalized Linear Models, GLM)上的效果进行了数学上的分析,值得读一下。 论文最后...
  • 1. 概述 机器学习领域有个很重要的假设:IID独立同分布假设,就是假设训练数据和测试数据是满足相同分布的,这是通过训练...会直接固定梯度下降的方向,导致很难更新 参考 常用的 Normalization 方法:BN、LN、IN、GN
  • Normalization 到底是在做什么 Batch Normalization 如何做 3.1 前向神经网络中的 BN 3.2 CNN 网络中的 BN 3.3 Batch Norm 的四大罪状 局限 1:如果 Batch Size 太小,则 BN 效果明显下降。 局限 2:对于有些...
  • ImportError: cannot import name 'LayerNormalization' from 'tensorflow.python.keras.layers.normalization' 根据网上很多种方法都解决不了,然后呢我就把最新的keras 2.6.0版本换成了旧版(2.0.0) 安装...
  • 解决过拟合的方法和代码实现,已经写过Dropout层,L1 L2正则化,提前终止训练,上一篇文章写了Batch Normalization,本篇将介绍另一个NormalizationLayer Normalization. 1.Batch Normalization的缺陷(为何要使用...
  • ’ gamma ‘和’ beta ‘将跨越’ axis '中指定的’输入’轴,并且输入的这一部分的形状必须完全定义 layer = tf.keras.layers.LayerNormalization(axis=[1, 2, 3]) layer.build([5, 20, 30, 40]) print(layer.beta...
  • 我想用在keras中用layerNorm,因为我的代码实现是tf.keras的这种写法,所以导致keras_layer_normalization这个包并不能很好的使用。 然后我尝试了tf.contrib.layer.layer_norm,报错。 解决方法 这里给出一个比较...
  • 在 Bert 等 Transformer 模型中,主要的 Normalization 方法是 Layer Normalization,所以很自然就能想到将对应的 β 和 γ 变成输入条件的函数,来控制 Transformer 模型的生成行为,这就是 Conditional Layer ...
  • 对于LN而言,我看到别人有将begin_norm_axis设置为-1的,也就是说仅在最后一维上进行Layer Normalization,我不是很理解为什么可以这么做。 另外,两个函数似乎都需要设置scope,否则会发生命名空间冲突的问题。 ...
  • 本篇博客总结几种归一化办法,并给出相应计算公式和代码。 1、综述 1.1 论文链接 ...1、Batch Normalization ...2、Layer Normalizaiton https://arxiv.org/pdf/1607.06450v1.pdf 3、Instance Normalization h...
  • 层标准化详解(Layer Normalization

    千次阅读 2020-05-17 19:18:57
    Batch Normalization使用mini-batch的均值和标准差对深度神经网络的隐藏层输入附加标准化操作,可有效地提升训练速度。对于前向神经网络应用Batch Norm,使用简单SGD优化器,训练速度也能有较大提升。 BN的效果...
  • LayerLayer Normalization反向传播x的梯度计算,g和b都非常好计算 x的梯度计算的公式为 代码为,可以调用float[] bp = bpG( new float[]{ 1,2,3, }, new float[]{ 1,1,2, }, new float[]{ 1,1,1 }); ...
  • BN将每个通道的所有数据进行归一化 LN将每个数据的所有... layerNorm在通道方向上,对CHW归一化,主要对RNN作用明显; 在上图中每个颜色表示一个训练样本,每个样本都有自己的长度。BN是按与y轴平行的方向计算...
  • Layer Normalization翻译

    2019-05-17 14:46:43
    最近引入的称为批量归一化(batch normalization)的技术使用在一小批训练样例中对神经元的加权输入的分布来计算均值和方差,然后将其用于在每个训练样例中对该神经元的加权输入进行归一化。这显着减少了前馈神经...
  • [paper] Layer Normalization

    千次阅读 2018-09-12 23:40:44
    Layer Normalization Abstract 目前效果最好的深度学习网络计算代价昂贵。减少训练时间的方法之一是规范化神经元的激活。Batch Normalization 使用了这一思路,用mini-batch的均值和方差来规范化,这极大的减少了...
  • 在Transformer模型中,使用到了Layer Normalization思想,来源于论文#论文来源# 为了方便介绍其原理,此处对Batch NormalizationLayer Normalization进行对比。 两个算法都使用均值和标准方差对数据进行标准化...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 18,302
精华内容 7,320
关键字:

layernormalization