Pytorch库中的torch.nn.LayerNorm模块,它是一种在自然语言处理中广泛应用的正规化技术。LayerNorm通过对输入数据进行归一化处理,可以提高模型的鲁棒性和泛化能力。具体体现如下两个方面:
1、将数据归一化至同一量级,解决数据间的可比性问题,如果量级不一样,那么网络可能解读错误。
2、归一化之后,寻求最优解的过程会变得平缓,可以更快的收敛到最优解
函数原型:
torch.nn.LayerNorm(
normalized_shape: Union[int, List[int], torch.Size],
eps: float = 1e-05,
elementwise_affine: bool = True)
第一个参数:normalized_shape
normalized_shape为一个整数:(那么需要要求传入的tensor最后一个维度的大小需要跟这个整数相等)
如果传入整数,比如5,则被看做只有一个整数的list,此时LayerNorm会对输入的最后一维进行归一化,这个int值需要和输入的最后一维一样大。
假设此时输入的数据维度是[3, 5],则对3个长度为5的向量求均值方差,得到3个均值和3个方差,分别对这3行进行归一化(每一行的5个数字都是均值为0,方差为1);LayerNorm中的weight和bias也分别包含5个数字,重复使用3次,对每一行进行仿射变换(仿射变换即乘以weight中对应的数字后,然后加bias中对应的数字),并会在反向传播时得到学习。
normalized_shape为两个整数:(那么需要要求传入的tensor最后两个维度的大小需要跟这两个整数相等)
如果输入的是个list或者torch.Size,比如[3, 5]或torch.Size([3, 5]),则会对网络最后的两维进行归一化,且要求输入数据的最后两维尺寸也是[3, 5]。
假设此时输入的数据维度也是[3, 5],首先对这15个数字求均值和方差,然后归一化这个15个数字;weight和bias也分别包含15个数字,分别对15个归一化后的数字进行仿射变换(仿射变换即乘以weight中对应的数字后,然后加bias中对应的数字),并会在反向传播时得到学习。
假设此时输入的数据维度是[N, 3, 5],则对这N个[3,5]做上述一样的操作,只是此时做仿射变换时,weight和bias被重复用了N次。
假设此时输入的数据维度是[N, T, 3, 5],也是一样的,维度可以更多。
注意:显然LayerNorm中weight和bias的shape就是传入的normalized_shape。
第二个参数:eps
归一化时加在分母上防止除零
第三个参数:elementwise_affine
如果设为False,则LayerNorm层不含有任何可学习参数。
如果设为True(默认是True)则会包含可学习参数weight和bias,用于仿射变换,即对输入数据归一化到均值0方差1后,乘以weight,即bias。
import torch
import torch.nn as nn
# 创建输入数据
input_data = torch.randn(4, 6)
print(input_data)
print(input_data.size())
# 创建LayerNorm层
#对最后一个维度进行归一化
layer_norm1 = nn.LayerNorm(6)
#对两个维度同时归一化
layer_norm2 = nn.LayerNorm([4,6])
# 进行LayerNorm处理
output1 = layer_norm1(input_data)
output2 = layer_norm2(input_data)
print(output1)
print(output2)
输出:
tensor([[ 1.4415, 0.1733, -1.2644, -2.7267, -0.0138, -0.0792],
[ 2.0240, 0.8238, -0.4269, -0.2043, -1.8146, 0.5594],
[ 1.2774, -0.7218, 0.3526, 1.6711, 0.0966, 0.4277],
[ 0.7997, 0.1011, 0.5100, 0.7205, -0.5538, -0.2981]])
torch.Size([4, 6])
tensor([[ 1.4260, 0.4501, -0.6563, -1.7816, 0.3061, 0.2558],
[ 1.5704, 0.5591, -0.4948, -0.3072, -1.6640, 0.3363],
[ 0.9737, -1.5872, -0.2109, 1.4780, -0.5389, -0.1147],
[ 1.1532, -0.2205, 0.5835, 0.9975, -1.5082, -1.0055]],
grad_fn=<NativeLayerNormBackward>)
tensor([[ 1.2579, 0.0510, -1.3174, -2.7092, -0.1271, -0.1894],
[ 1.8123, 0.6701, -0.5204, -0.3085, -1.8410, 0.4184],
[ 1.1018, -0.8010, 0.2216, 1.4765, -0.0221, 0.2930],
[ 0.6471, -0.0178, 0.3713, 0.5717, -0.6411, -0.3977]],
grad_fn=<NativeLayerNormBackward>)
对以上代码layer_norm1 = nn.LayerNorm(6)和数据[1.4415, 0.1733, -1.2644, -2.7267, -0.0138, -0.0792](第一行进行归一化)进行验证
inputx = [1.4415, 0.1733, -1.2644, -2.7267, -0.0138, -0.0792]
inputx_mean=np.mean(inputx) #只在维度C上计算均值,计算后维度为N*L*1
inputx_std=np.std(inputx)
verify_ln_y=(inputx-inputx_mean)/(inputx_std+1e-5)
print(verify_ln_y)
输出:
[ 1.42599035 0.45006366 -0.65629954 -1.78159335 0.3060833 0.25575559]
参考:
Pytorch——BatchNorm层和LayerNorm层的参数含义以及应用理解 - Circle_Wang - 博客园 (cnblogs.com)