这里的
ε
ε
ε一般取
1
e
−
5
1e-5
1e−5;
γ
γ
γ和
β
β
β是可学习的参数,用于放缩和平移(对于一些可能需要的通道)。
- 用途:加快深度网络的收敛。不断调整神经网络的中间输出,使整个神经网络各层的中间输出值更加稳定。
- 使用:常常使用在卷积层/全连接层之后,激活层之前。
- 计算:对一个batch中的每个通道的数据进行归一化。
- 注意:BN在训练和测试中是不一样的,在训练的时候使用的是一个batch的均值和方差。测试的时候输入只有一个样本,均值和方差实效,因此使用的是全局的均值和方差。(全局的均值和方差是在训练的时候根据batch的均值和方差计算的)
一般用于全连接层
- torch.nn.BatchNorm1d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True, device=None, dtype=None)
num_feature:特征纬度或通道纬度。input中的C
affine:是否使用仿射变换(
γ
γ
γ和
β
β
β)
input:(N,C)or(N,C,L)
output:(N,C)or(N,C,L)
ps:BatchNorm初始化的参数只能是C
x = torch.randn(2,3,4) m = nn.BatchNorm1d(3,affine=False) y = m(x) print(x,'n',y) # tensor([[[-0.8819, 0.0585, -0.7125, -1.1646], # [ 0.1591, 0.1896, 0.1864, -0.6797], # [-1.7054, -0.3885, -1.7914, 0.5889]], # [[ 0.2212, -0.2304, -0.9944, 0.1616], # [ 0.8937, -0.5305, -0.2229, 1.1992], # [-0.5296, -1.1449, -3.2007, 0.4042]]]) # tensor([[[-0.8385, 0.9573, -0.5151, -1.3784], # [ 0.0161, 0.0663, 0.0610, -1.3659], # [-0.6243, 0.4951, -0.6974, 1.3258]], # [[ 1.2681, 0.4057, -1.0534, 1.1543], # [ 1.2262, -1.1200, -0.6133, 1.7296], # [ 0.3752, -0.1479, -1.8953, 1.1688]]])
- 手动实现
mean_x = torch.mean(x,(0,2),keepdim=True) std_x = torch.std(x,(0,2),unbiased=False,keepdim=True) # 这里使用的是有偏估计(/n) print((x-mean_x)/(std_x+1e-5)) # tensor([[[-0.5311, 1.1169, 1.1878, -1.2081], # [ 2.2561, -0.1970, -0.0815, -0.3926], # [ 0.5843, 0.4214, -0.9679, 0.4934]], # [[-0.0491, 0.1452, 0.9649, -1.6264], # [ 0.1291, -1.1903, 0.4930, -1.0168], # [-0.1586, -1.8564, 1.6716, -0.1878]]])1.2.2 二维BN
一般用于图像,卷积之后
- torch.nn.BatchNorm2d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True, device=None, dtype=None)
num_features:通道C
input:(N,C,H,W)
output:(N,C,H,W)
x = torch.randn(2,3,1,2) m = nn.BatchNorm2d(3,affine=False) y = m(x) # 手动实现 mean_x = torch.mean(x,(0,2,3),keepdim=True) std_x = torch.std(x,(0,2,3),unbiased=False,keepdim=True) # 这里使用的是有偏估计(/n) our_y = (x-mean_x)/(std_x+1e-5) print(x,'nn',y,'nn',our_y) # tensor([[[[-1.2855, -0.0998]], # [[-0.2634, -0.5707]], # [[-0.1303, -0.1027]]], # [[[ 1.0351, -2.0135]], # [[-0.9063, 0.6899]], # [[ 0.6535, -0.7200]]]]) # tensor([[[[-5.9828e-01, 4.2302e-01]], # [[-1.3754e-03, -5.1765e-01]], # [[-1.1366e-01, -5.7076e-02]]], # [[[ 1.4006e+00, -1.2253e+00]], # [[-1.0816e+00, 1.6006e+00]], # [[ 1.4941e+00, -1.3234e+00]]]]) # tensor([[[[-5.9827e-01, 4.2302e-01]], # [[-1.3754e-03, -5.1765e-01]], # [[-1.1366e-01, -5.7076e-02]]], # [[[ 1.4006e+00, -1.2253e+00]], # [[-1.0816e+00, 1.6006e+00]], # [[ 1.4941e+00, -1.3234e+00]]]])2. LayerNorm 2.1 理论
- 用途:一般在nlp中对每一个样本中的每一个step的embedding进行归一化。
- 计算:每个样本中每个step的embedding的均值和方差。
- 注意:在nlp中很少使用BN的原因是每个序列的长度不一致,无法执行
- torch.nn.LayerNorm(normalized_shape, eps=1e-05, elementwise_affine=True, device=None, dtype=None):
input: (N, *)
output: (N, *)
ps:这里的normalized_shape指需要归一化的纬度,这里可以是输入的最后一维(int)或几维(tuple)。pytorch中的LayerNorm功能更强大,可以对多维归一化。
- 对embedding归一化
# torch.nn API x = torch.randn(2,3,4) LN = nn.LayerNorm(4,elementwise_affine=False) y = LN(x) # 手动实现 eps = 1e-5 mean_x = torch.mean(x,-1,keepdim=True) std_x = torch.std(x,-1,keepdim=True,unbiased=False) our_y = (x-mean_x)/(std_x+eps) print(y,'nn',our_y) # tensor([[[-0.5195, 0.2833, 1.4638, -1.2276], # [-0.4572, 1.7077, -0.4097, -0.8407], # [-0.7291, 1.0108, 0.9562, -1.2379]], # [[ 1.3917, 0.4969, -0.8172, -1.0715], # [ 0.2225, 1.4955, -1.2042, -0.5137], # [ 0.6254, 1.2349, -1.3505, -0.5099]]]) # tensor([[[-0.5195, 0.2833, 1.4638, -1.2276], # [-0.4572, 1.7077, -0.4097, -0.8407], # [-0.7291, 1.0108, 0.9562, -1.2379]], # [[ 1.3918, 0.4969, -0.8172, -1.0715], # [ 0.2225, 1.4955, -1.2042, -0.5137], # [ 0.6254, 1.2349, -1.3505, -0.5099]]])
- 多个纬度进行归一化
LN2 = nn.LayerNorm((3,4),elementwise_affine=False) y = LN2(x) mean_x = torch.mean(x,(-2,-1),keepdim=True) std_x = torch.std(x,(-2,-1),keepdim=True,unbiased=False) our_y = (x-mean_x)/(std_x+eps) print(y,'nn',our_y) # tensor([[[-0.1499, 0.5653, 1.6169, -0.7807], # [-0.3967, 0.6294, -0.3742, -0.5785], # [-1.1202, 1.2359, 1.1620, -1.8093]], # [[ 1.1521, 0.7635, 0.1929, 0.0825], # [ 0.3066, 2.0505, -1.6479, -0.7018], # [-0.1889, 0.1627, -1.3286, -0.8437]]]) # tensor([[[-0.1499, 0.5653, 1.6169, -0.7807], # [-0.3967, 0.6294, -0.3742, -0.5785], # [-1.1202, 1.2359, 1.1620, -1.8092]], # [[ 1.1520, 0.7635, 0.1929, 0.0825], # [ 0.3066, 2.0505, -1.6478, -0.7018], # [-0.1889, 0.1627, -1.3286, -0.8437]]])



