Normorlize和Normalization源于正态分布(Normal Distribution),也称为高斯分布(Gaussian Distribution)。因此,一般的Normalization方法是对输入的样本求得一个均值,然后用均值
求得样本的方差
,然后对输入的样本进行归一化,归一化的样本数据服从均值为
、方差
的正态分布。另外也有采用MinMaxScaler的方法对输入的样本进行归一化的,即把样本的数值通过线性投影到[0,1]范围中。而Batch Norm和Layer Norm一般采取前面这种方法对样本数据进行归一化。
网上已经很多博客对Batch Norm和Layer Norm展开解读,本文将不会重点介绍其中的归一化方法,而是记录自己对这两种方法的一些理解和思考。如果您感兴趣,非常期待您的讨论。其中此博客对Batch Norm的解读是比较好的,也得到了大家的认可;而此博客对Layer Norm的解读也比较好。如果您对这两个Norm还没有什么了解的话建议优先阅读一下这两篇博客。
假设输入的图像shape记为[N, C, H, W]。那么C就是图像领域中的通道数,N是图片的个数,H和W是图像的尺寸。通道数也称之为特征图(Feature Map)。例如,在RGB这样的配色方案中,一张图片(64×64)的通道数为3,分别为红色通道、绿色通道和蓝色通道,每个通道的大小(即H×W)为64×64。如果有100张这样的图片,那么这些图片的shape就是[100, 3, 64, 64]。
图中已经很形象直观地说明了这四种Norm方法的区别。有人认为(H,W)画成图中立方体的不好理解,其实不然,(H,W)是一个二维矩阵,但本质上可以把它拉成一个向量,例如,3×3的矩阵可以reshape成为1×9矩阵,但实际上已经和向量差不多了。也就是说,把(H,W)理解成为一个向量可能更加方便对这个图的理解。
所以我认为Batch Norm就是利用单个通道呈现的多个样本实现Normalization,然后对Normalization做线性变换。而Layer Norm就是利用单个样本的多个通道实现Normalization。当然,这是在图像领域上的理解。
我在很多博文中看到下面的代码:
def Batchnorm_simple_for_train(x, gamma, beta, bn_param):
"""
param:x : 输入数据,设shape(B,L)
param:gama : 缩放因子 γ
param:beta : 平移因子 β
param:bn_param : batchnorm所需要的一些参数
eps : 接近0的数,防止分母出现0
momentum : 动量参数,一般为0.9, 0.99, 0.999
running_mean :滑动平均的方式计算新的均值,训练时计算,为测试数据做准备
running_var : 滑动平均的方式计算新的方差,训练时计算,为测试数据做准备
"""
running_mean = bn_param['running_mean'] #shape = [B]
running_var = bn_param['running_var'] #shape = [B]
results = 0. # 建立一个新的变量
x_mean=x.mean(axis=0) # 计算x的均值
x_var=x.var(axis=0) # 计算方差
x_normalized=(x-x_mean)/np.sqrt(x_var+eps) # 归一化
results = gamma * x_normalized + beta # 缩放平移
running_mean = momentum * running_mean + (1 - momentum) * x_mean
running_var = momentum * running_var + (1 - momentum) * x_var
#记录新的值
bn_param['running_mean'] = running_mean
bn_param['running_var'] = running_var
return results , bn_param
我很好奇,为什么会有像running_mean, running_var那样的变量,而在实现Batch Norm中的伪代码中没有体现。如果我只是对一组图片做一次Batch Norm,这样的变量是否是必需的呢?这个疑问,我一直找不到答案,希望朋友们看到能够在我的博客留言您的解答。我想尝试对Batch Norm和Layer Norm进行实现(单纯地实现,而不是用于训练),然后对比这两种方法的区别。但在实现的过程中,我不知道running_mean, running_var那样的变量是否为必须的。
在自然语言处理中,我们常常会遇到RNN,而基于RNN的模型,也一般会用到Layer Norm。那么用于做归一化的图像数据和序列数据,有什么不一样呢?我认为其中最大的不同之处就是序列数据的长度和图像数据的尺寸是不一样的,这里的不一样不是说序列是一维的、图像是二维的(揣摩一下实际上图像也可以从二维矩阵拉成一维向量),而是说这个一维的序列向量的长度是不一致的,有些长有些短,但是图像数据就不一样,经过对齐预处理后的图像数据,它们的尺寸都是一样的。序列长度的不一致,就说明RNN的深度不是固定的。
既然Batch Norm和Layer Norm是可比的,那么它们就会有相同之处,那么同样对于输入的数据shape记为[N, C, H, W],我是这样理解这几个符号的意思的:其中N是序列样本的个数;C是一个序列的多个表示通道,比如一个通道用来描述词向量,一个通道用来描述独热编码(这个比如不是很好,个人理解);H和W则不适合用于表示文本数据,因为序列长度不是固定的。如下图所示。
Batch Norm有两个缺点:一是当batch size很小时计算得到的均值和方差无法反映全局的统计分布导致效果变差,二是无法很好处理序列长度不一致的问题。有人认为,Layer Norm是一个独立于batch size的方法,所以无论样本数多少都不会影响参与Layer Norm计算的数据量,从而解决Batch Norm的两个问题。但是我有点小小的疑问,batch size与Layer Norm是如何独立的?如果batch size不一样,显然所得到的归一化结果肯定也会不一样,那为什么说它们是独立的呢?特别是在CNN模型中,如果我用了Layer Norm,难道真的无论样本数多少都不会影响参与Layer Norm计算的数据量吗?
Batch Norm和Layer Norm都是比较常用的Normalization方法,二者各有优缺点,没有绝对的好坏之分。根据大家的总结,当在CNN模型时,建议优先尝试使用Batch Norm,而在RNN模型时,建议优先使用Layer Norm。以上均是我的个人理解和疑问,不一定正确,如果您知道答案请大胆献言,我将感激不尽。