BatchNorm和LayerNorm

 

一、BatchNorm

论文:Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift

从论文名字就可以看出,BatchNorm技术是用来加速网络训练的,手段就是通过“Reducing Internal Covariate Shift(减小内部协变量偏移)”,什么叫做“Internal Covariate Shift”呢? 看一下下图所示的sigmoid函数图:

BatchNorm和LayerNorm_第1张图片 sigmoid激活函数

可以看出当x值在0附近时,其导数较大,靠近两边时导数很小。而在深度神经网络中,如果不加以约束,则激活函数的输入值很容易向两边偏移,导致导数变小,这样会使得网络训练变慢,而且逐层累乘后还会产生梯度消失现象。所以normalization的作用相当于数据在经过每层时都将它拉回为一个统一分布。batch normalization过程如下:

BatchNorm和LayerNorm_第2张图片

其中xi是线性激活值。首先求出均值和方差,之后再减去均值、除以方差。参数\epsilon应该是为了防止因为方差接近0而使得除以0无限大的问题,所以在pytorch中\epsilon是一个比较小的值(1e-5)。为了防止网络表达性下降,又在normaliza只后添加一个逆变换,即将x乘以一个缩放值\gamma并加上一个偏移量\beta,其中\gamma\beta都是可学习参数。

因此,normalization其实更像是另一个神经网络层,因为有可学习参数存在,但是参数量相对来说是极少的,与线性变换中y=wx+b的b参数量一致,为神经元个数。

另外,也有实验表明batch normalization放在非线性激活层之后也有同样甚至更好的加速效果,这样的话似乎上述原理很难解释为什么BatchNorm能够加速训练,毕竟Normalization都是与激活函数无关的,这里有一个更容易理解的解释:BatchNorm为什么能缓解梯度消失问题

BatchNorm的缺点:

1.需要较大的batch以体现整体数据分布

2.训练阶段需要保存每个batch的均值和方差,以求出整体均值和方差在infrence阶段使用

3.不适用于可变长序列的训练,如RNN

一、LayerNorm

LayerNorm克服了以上BatchNorm的缺点,在特征维度进行归一化,对每个Batch有一个均值和方差,因此不依赖于batch大小,即使batch为1也能使用。

LayerNorm只是归一化的维度与BatchNorm有所区别,但是其他区别不大。LayerNorm中也存在\gamma\beta可学习参数,并且\gamma\beta是在特征维度进行,而不是在Batch维度。

例如,input是batch×seq_len×hidden,则Layer首先在hidden维度求出batch×seq_len个标准差和均值,再使用它们进行归一化,但\gamma\beta只有hidden个,因此LayerNorm归一化之后的缩放是再特征维度上进行。

使用numpy实现LayerNorm:

a=array([[[-0.66676328, -0.95822262,  1.2951657 ,  0.67924618],
        [-0.46616455, -0.39398589,  1.95926177,  2.36355916],
        [-0.39897415,  0.80353481, -1.46488175,  0.55339737]],

       [[-0.66223895, -0.16435625, -1.96494932, -1.07376919],
        [ 1.30338369, -0.19603094, -1.43136723, -1.0207508 ],
        [ 0.8452505 , -0.08878595, -0.5211611 ,  0.10511936]]])
u=np.mean(a, axis=(2,))
s = np.std(a, axis=(2,))

y = a-u[...,None]
y = y/s[...,None]
print(y)

########################输出###################################
array([[[-0.80954074, -1.12241971,  1.29657224,  0.63538821],
        [-1.0214588 , -0.96610083,  0.83874033,  1.14881929],
        [-0.30472338,  1.04125172, -1.49779981,  0.76127147]],

       [[ 0.46047519,  1.21440667, -1.51218696, -0.16269489],
        [ 1.56757537,  0.13400543, -1.04708279, -0.65449801],
        [ 1.53885365, -0.35203004, -1.2273397 ,  0.04051609]]])

Pytorch的LayerNorm:

import torch.nn.functional as F

input = torch.tensor(a)
y = F.layer_norm(input,(4,))
print(y)

#####################输出################
tensor([[[-0.8095, -1.1224,  1.2966,  0.6354],
         [-1.0215, -0.9661,  0.8387,  1.1488],
         [-0.3047,  1.0412, -1.4978,  0.7613]],

        [[ 0.4605,  1.2144, -1.5122, -0.1627],
         [ 1.5676,  0.1340, -1.0471, -0.6545],
         [ 1.5388, -0.3520, -1.2273,  0.0405]]])

Pytorch LayerNorm添加缩放:

的确是只在特征维度进行缩放了。

w = torch.tensor([1,1,2,2])
b = torch.tensor([1,1,1,1])
y = F.layer_norm(input,(4,),w,b)
print(y)

#########################输出######################
tensor([[[ 0.1905, -0.1224,  3.5931,  2.2708],
         [-0.0215,  0.0339,  2.6775,  3.2976],
         [ 0.6953,  2.0412, -1.9956,  2.5225]],

        [[ 1.4605,  2.2144, -2.0243,  0.6746],
         [ 2.5676,  1.1340, -1.0942, -0.3090],
         [ 2.5388,  0.6480, -1.4546,  1.0810]]])

 

你可能感兴趣的:(NLP)