还是torch的学习啊~~~~ 

一,归一化层概述

归一化技术对于训练深度神经网络非常重要。

它们的主要作用是让模型的中间层的输入分布稳定在合适的范围,加快模型训练过程的收敛速度,并提升模型对输入变动的抗干扰能力。

各种归一化层使用的公式都是一样的,如下所示:

其中的  和  是可学习的参数。注意到,当 恰好取标准差,恰好取均值时,归一化层刚好是一个恒等变换。这就能够保证归一化层在最坏的情况下,可学习为一个恒等变换,不会给模型带来负面影响。

本文节选自 eat pytorch in 20 days 的 《5-2,模型层》前半部分。公众号后台回复关键词:pytorch,获取本文全部源代码和吃货本货BiliBili视频讲解哦🍉🍉

二,BatchNorm和LayerNorm的差别?

pytorch中内置的归一化层包括 nn.BatchNorm2d(1d), nn.LayerNorm, nn.GroupNorm, nn.InstanceNorm2d 等等。

其中最常用的是BatchNorm2d(1d)和LayerNorm。

不同的归一化层的差异主要是计算均值和方差时候参与计算的数据不一样。

BatchNorm是在样本维度进行归一化(一个批次内不同样本的相同特征计算均值和方差),而LayerNorm是在特征维度进行归一化(同一个样本的不同特征计算均值和方差)。

BatchNorm常用于结构化数据(BatchNorm1D)和图片数据(BatchNorm2D),LayerNorm常用于文本数据。

import torch 
from torch import nn 

batch_size, channel, height, width = 32, 16, 128, 128

tensor = torch.arange(0,32*16*128*128).view(32,16,128,128).float() 

bn = nn.BatchNorm2d(num_features=channel,affine=False)
bn_out = bn(tensor)


channel_mean = torch.mean(bn_out[:,0,:,:]) 
channel_std = torch.std(bn_out[:,0,:,:])
print("channel mean:",channel_mean.item())
print("channel std:",channel_std.item())
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
channel mean: 1.1920928955078125e-07
channel std: 1.0000009536743164
  • 1.
  • 2.
import torch 
from torch import nn 

batch_size, sequence, features = 32, 100, 2048
tensor = torch.arange(0,32*100*2048).view(32,100,2048).float() 

ln = nn.LayerNorm(normalized_shape=[features],
                  elementwise_affine = False)

ln_out = ln(tensor)

token_mean = torch.mean(ln_out[0,0,:]) 
token_std = torch.std(ln_out[0,0,:])
print("token_mean:",token_mean.item())
print("token_mean:",token_std.item())
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
token_mean: -5.8673322200775146e-08
token_mean: 1.0002442598342896
  • 1.
  • 2.

三,为什么不同类型的数据要使用不同的归一化层?

  • 结构化数据通常使用BatchNorm1D归一化 【结构化数据的主要区分度来自每个样本特征在全体样本中的排序,将全部样本的某个特征都进行相同的放大缩小平移操作,样本间的区分度基本保持不变,所以结构化数据可以做BatchNorm,但LayerNorm会打乱全体样本根据某个特征的排序关系,引起区分度下降】

pytorch中的各种归一化层_pytorch

  • 图片数据最常用的是BatchNorm2D,有些场景也会用LayerNorm,GroupNorm或者InstanceNorm【图片数据的主要区分度来自图片中的纹理结构,所以图片数据的归一化一定要在图片的宽高方向上操作以保持纹理结构,此外在Batch维度上操作还能够引入少许的正则化,对提升精度有进一步的帮助。】

pytorch中的各种归一化层_深度学习_02

  • 文本数据一般都使用LayerNorm归一化 【文本数据的主要区分度来自于词向量(Embedding向量)的方向,所以文本数据的归一化一定要在 特征(通道)维度上操作 以保持 词向量方向不变。此外文本数据还有一个重要的特点是不同样本的序列长度往往不一样,所以不可以在Sequence和Batch维度上做归一化,否则将不可避免地将padding位置对应的向量和普通的词向混合起来进行归一,这会让变成padding对应的向量变成非零向量,从而对梯度产生不合预期的影响。即使做特殊处理让padding位置的向量不参与归一化保持为0值,由于样本间序列长度的差异,也会造成参与运算的归一的数据量在不同样本和批次间剧烈波动,不利于模型的稳定学习。】

pytorch中的各种归一化层_数据_03


 

  • 有论文提出了一种可自适应学习的归一化:SwitchableNorm,可应用于各种场景且有一定的效果提升。【SwitchableNorm是将BN、LN、IN结合,赋予权重,让网络自己去学习归一化层应该使用什么方法。参考论文:https://arxiv.org/pdf/1806.10779.pdf】

四,BatchNorm补充问题

(1)BatchNorm放在激活函数前还是激活函数后?

原始论文认为将BatchNorm放在激活函数前效果较好,后面的研究一般认为将BatchNorm放在激活函数之后更好。

(2)BatchNorm在训练过程和推理过程的逻辑是否一样?

不一样!训练过程BatchNorm的均值和方差和根据mini-batch中的数据估计的,而推理过程中BatchNorm的均值和方差是用的训练过程中的全体样本估计的。因此预测过程是稳定的,相同的样本不会因为所在批次的差异得到不同的结果,但训练过程中则会受到批次中其他样本的影响所以有正则化效果。

(3)BatchNorm的精度效果与batch_size大小有何关系?

如果受到GPU内存限制,不得不使用很小的batch_size,训练阶段时使用的mini-batch上的均值和方差的估计和预测阶段时使用的全体样本上的均值和方差的估计差异可能会较大,效果会变差。这时候,可以尝试LayerNorm或者GroupNorm等归一化方法。

完事~~