1. nn.LayerNorm函数
nn.LayerNorm(normalized_shape, eps=1e-05, elementwise_affine=True, device=None, dtype=None)
- normalized_shape:归一化的维度
- eps:加在方差上的数字,避免分母为0,default=1e-5
- elementwise_affine:bool,True的话会有一个默认的affine参数,即上述公式中的
和
,前者开始为1,后者为0,二者均可学习随着训练过程而变化,default=True
2. LayerNorm在Transformer中的应用
在transformer中一般采用LayerNorm,LayerNorm也是归一化的一种方法,与BatchNorm不同的是它是对每单个batch进行的归一化,而batchnorm是对所有batch一起进行归一化的
在Transformer中,给定输入tensor[seq_length, batch_size, d_model],其中seq_length为序列长度,batch_size为batch大小,d_model为embedding的维度,如下所示,我们有多个batch,其中第一个batch的序列长度为3,包括“I, Love, You”,他们的词向量维度均为6,在LayerNorm的时候,分别对“I”,“Love”,“You”向量进行归一化,即相同颜色的数字
2.1 LayerNorm的官方实现
下面代码展示了nn.LayerNorm的官方使用
1 | import torch.nn as nn |
2.2 LayerNorm的自定义实现
下面代码展示了nn.LayerNorm的自定义实现
1 | import torch.nn as nn |
3. nn.LayerNorm的底层逻辑
根据上述例子我们可以了解到LayerNorm的归一化底层逻辑,给定LayerNorm归一化维度,他会将输入tensor的最后几个维度进行整体归一化。什么意思呢?假设我们的输入为(1, 3, 4, 4)的变量,并对其进行LayerNorm,这里我们展示两个例子
注意:这里的例子只是帮助理解LayerNorm函数的用法,并不是说四维tensor就要按照下面两种方式处理,正常来说,CNN中很少用LayerNorm
如下图所示,左边为第一种归一化方法,对所有channel所有像素计算;右边为第二种归一化方法,对所有channel的每个像素分别计算
- 计算一个batch中所有channel中所有参数的均值和方差,然后进行归一化,即(3, 5, 5)
- 计算一个batch中所有channel中的每一个参数的均值和方差进行归一化,即(3, 1, 1),计算25次
3.1 第一种计算
直接给出计算代码
注意:输入为(1, 3, 4, 4),layernorm的normalized_shape为[3, 5, 5],也就是说对后三维度进行归一化操作
1 | import torch.nn as nn |
当然如果要灵活的进行操作,可以将tensor提前resize以下,这样LayerNorm就不需要传入list列表了,比如这里将输入resize为[1, 3*4*4],这样初始化LayerNorm(3*4*4)即可,等操作完成后再resize回来
3.2 第二种计算
直接给出计算代码
注意:我们的输入是(1, 3, 4, 4),如果要完成第二种方法,我们layernorm只需要提供一个参数,即norm = nn.LayerNorm(3),但是如果只提供一个参数,默认为对最后一维进行归一化,所以我们需要将输入进行变化,即变为(1, 4, 4, 3)。
1 | import torch.nn as nn |