說明
LayerNorm中不會(huì)像BatchNorm那樣跟蹤統(tǒng)計(jì)全局的均值方差,因此train()和eval()對(duì)LayerNorm沒有影響。
LayerNorm參數(shù)
torch.nn.LayerNorm(
normalized_shape: Union[int, List[int], torch.Size],
eps: float = 1e-05,
elementwise_affine: bool = True)
normalized_shape
如果傳入整數(shù),比如4,則被看做只有一個(gè)整數(shù)的list,此時(shí)LayerNorm會(huì)對(duì)輸入的最后一維進(jìn)行歸一化,這個(gè)int值需要和輸入的最后一維一樣大。
假設(shè)此時(shí)輸入的數(shù)據(jù)維度是[3, 4],則對(duì)3個(gè)長度為4的向量求均值方差,得到3個(gè)均值和3個(gè)方差,分別對(duì)這3行進(jìn)行歸一化(每一行的4個(gè)數(shù)字都是均值為0,方差為1);LayerNorm中的weight和bias也分別包含4個(gè)數(shù)字,重復(fù)使用3次,對(duì)每一行進(jìn)行仿射變換(仿射變換即乘以weight中對(duì)應(yīng)的數(shù)字后,然后加bias中對(duì)應(yīng)的數(shù)字),并會(huì)在反向傳播時(shí)得到學(xué)習(xí)。
如果輸入的是個(gè)list或者torch.Size,比如[3, 4]或torch.Size([3, 4]),則會(huì)對(duì)網(wǎng)絡(luò)最后的兩維進(jìn)行歸一化,且要求輸入數(shù)據(jù)的最后兩維尺寸也是[3, 4]。
假設(shè)此時(shí)輸入的數(shù)據(jù)維度也是[3, 4],首先對(duì)這12個(gè)數(shù)字求均值和方差,然后歸一化這個(gè)12個(gè)數(shù)字;weight和bias也分別包含12個(gè)數(shù)字,分別對(duì)12個(gè)歸一化后的數(shù)字進(jìn)行仿射變換(仿射變換即乘以weight中對(duì)應(yīng)的數(shù)字后,然后加bias中對(duì)應(yīng)的數(shù)字),并會(huì)在反向傳播時(shí)得到學(xué)習(xí)。
假設(shè)此時(shí)輸入的數(shù)據(jù)維度是[N, 3, 4],則對(duì)著N個(gè)[3,4]做和上述一樣的操作,只是此時(shí)做仿射變換時(shí),weight和bias被重復(fù)用了N次。
假設(shè)此時(shí)輸入的數(shù)據(jù)維度是[N, T, 3, 4],也是一樣的,維度可以更多。
注意:顯然LayerNorm中weight和bias的shape就是傳入的normalized_shape。
eps
歸一化時(shí)加在分母上防止除零。
elementwise_affine
如果設(shè)為False,則LayerNorm層不含有任何可學(xué)習(xí)參數(shù)。
如果設(shè)為True(默認(rèn)是True)則會(huì)包含可學(xué)習(xí)參數(shù)weight和bias,用于仿射變換,即對(duì)輸入數(shù)據(jù)歸一化到均值0方差1后,乘以weight,即bias。
LayerNorm前向傳播(以normalized_shape為一個(gè)int舉例)
1、如下所示輸入數(shù)據(jù)的shape是(3, 4),此時(shí)normalized_shape傳入4(輸入維度最后一維的size),則沿著最后一維(沿著最后一維的意思就是對(duì)最后一維的數(shù)據(jù)進(jìn)行操作)
并用這兩個(gè)結(jié)果把batch沿著最后一維歸一化,使其均值為0,方差為1。歸一化公式用到了eps(),即
tensor = torch.FloatTensor([[1, 2, 4, 1],
[6, 3, 2, 4],
[2, 4, 6, 1]])

[[-0.8165, 0.0000, 1.6330, -0.8165],
[ 1.5213, -0.5071, -1.1832, 0.1690],
[-0.6509, 0.3906, 1.4321, -1.1717]]
2、如果elementwise_affine==True,則對(duì)歸一化后的batch進(jìn)行仿射變換,即乘以模塊內(nèi)部的weight(初值是[1., 1., 1., 1.])然后加上模塊內(nèi)部的bias(初值是[0., 0., 0., 0.]),這兩個(gè)變量會(huì)在反向傳播時(shí)得到更新。
3、如果elementwise_affine==False,則LayerNorm中不含有weight和bias兩個(gè)變量,只做歸一化,不會(huì)進(jìn)行仿射變換。
總結(jié)
在使用LayerNorm時(shí),通常只需要指定normalized_shape就可以了。
補(bǔ)充:【Pytorch】F.layer_norm和nn.LayerNorm到底有什么區(qū)別?
背景
最近在做視頻方向,處理的是時(shí)序特征,就想著能不能用Batch Normalization來做視頻特征BN層?在網(wǎng)上查閱資料發(fā)現(xiàn),時(shí)序特征并不能用Batch Normalization,因?yàn)橐粋€(gè)batch中的序列有長有短。
此外,BN 的一個(gè)缺點(diǎn)是需要較大的 batchsize 才能合理估訓(xùn)練數(shù)據(jù)的均值和方差,這導(dǎo)致內(nèi)存很可能不夠用,同時(shí)它也很難應(yīng)用在訓(xùn)練數(shù)據(jù)長度不同的 RNN 模型上。
Layer Normalization (LN) 的一個(gè)優(yōu)勢是不需要批訓(xùn)練,在單條數(shù)據(jù)內(nèi)部就能歸一化。
對(duì)于RNN等時(shí)序模型,有時(shí)候同一個(gè)batch內(nèi)部的訓(xùn)練實(shí)例長度不一(不同長度的句子),則不同的時(shí)態(tài)下需要保存不同的統(tǒng)計(jì)量,無法正確使用BN層,只能使用Layer Normalization。
查閱Layer Normalization(下述LN)后發(fā)現(xiàn),這東西有兩種用法,一個(gè)是F.layer_norm,一個(gè)是torch.nn.LayerNorm,本文探究他們的區(qū)別。
F.layer_norm
用法
F.layer_norm(x, normalized_shape, self.weight.expand(normalized_shape), self.bias.expand(normalized_shape))
其中:
x是輸入的Tensor
normalized_shape是要?dú)w一化的維度,可以是x的后若干維度
self.weight.expand(normalized_shape),可選參數(shù),自定義的weight
self.bias.expand(normalized_shape),可選參數(shù),自定義的bias
示例
很容易看出來,跟F.normalize基本一樣,沒有可學(xué)習(xí)的參數(shù),或者自定義參數(shù)。具體使用示例如下:
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]]])
添加縮放:
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]]])
nn.LayerNorm
用法
torch.nn.LayerNorm(
normalized_shape: Union[int, List[int], torch.Size],
eps: float = 1e-05,
elementwise_affine: bool = True)
normalized_shape: 輸入尺寸, [∗×normalized_shape[0]×normalized_shape[1]×…×normalized_shape[−1]]
eps: 為保證數(shù)值穩(wěn)定性(分母不能趨近或取0),給分母加上的值。默認(rèn)為1e-5。
elementwise_affine: 布爾值,當(dāng)設(shè)為true,給該層添加可學(xué)習(xí)的仿射變換參數(shù)。
示例
elementwise_affine如果設(shè)為False,則LayerNorm層不含有任何可學(xué)習(xí)參數(shù)。
如果設(shè)為True(默認(rèn)是True)則會(huì)包含可學(xué)習(xí)參數(shù)weight和bias,用于仿射變換,即對(duì)輸入數(shù)據(jù)歸一化到均值0方差1后,乘以weight,即bias。
import torch
input = torch.randn(2,3,2,2)
import torch.nn as nn
#取消仿射變換要寫成
#m = nn.LayerNorm(input.size()[1:], elementwise_affine=False)
m1 = nn.LayerNorm(input.size()[1:])#input.size()[1:]為torch.Size([3, 2, 2])
output1 = m1(input)
#只normalize后兩個(gè)維度
m2 = nn.LayerNorm([2,2])
output2 = m2(input)
#只normalize最后一個(gè)維度
m3 = nn.LayerNorm(2)
output3 = m3(input)
總結(jié)
F.layer_norm中沒有可學(xué)習(xí)參數(shù),而nn.LayerNorm有可學(xué)習(xí)參數(shù)。當(dāng)elementwise_affine設(shè)為False時(shí),nn.LayerNorm退化為F.layer_norm。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
您可能感興趣的文章:- pytorch固定BN層參數(shù)的操作
- pytorch 如何自定義卷積核權(quán)值參數(shù)
- pytorch交叉熵?fù)p失函數(shù)的weight參數(shù)的使用
- Pytorch 統(tǒng)計(jì)模型參數(shù)量的操作 param.numel()
- pytorch 一行代碼查看網(wǎng)絡(luò)參數(shù)總量的實(shí)現(xiàn)
- pytorch查看網(wǎng)絡(luò)參數(shù)顯存占用量等操作
- pytorch 優(yōu)化器(optim)不同參數(shù)組,不同學(xué)習(xí)率設(shè)置的操作