文章目录
- 1 概述
- 2 几种normalization的方法
- 2.1 Batch Norm
- 2.2 Layer Norm
- 2.3 Instance Norm
- 2.4 Group Norm
- 3 效果对比
- 参考文献
1 概述
Group Nomralization的提出是为了解决一张GPU上能容纳的batch_size很小,导致模型训练效果显著变差的问题。随着深度学习的快速发展,我们所使用的模型越来越大了,这也就导致了在训练时,一个batch所占用的显存越来越大了,也i就导致了一张卡上的batch_size会很小,最终导致了模型最终效果大幅变差。这里之所以强调一张卡,并不是因为穷,而是因为batch normalization在计算batch的mean和variance的时候,只能是以一张卡上的batch_size为单位去算的,多卡之间不会对此进行通信。
如下图所示,batch normalization的效果受batch size的影响很大,但是group nomalization完全不受batch size的影响(其计算压根就和batch没关系),效果也不逊色于batch normalization,而且batch size越小,优势越大。
2 几种normalization的方法
normalization是为了解决Internal Covariate Shift以及梯度弥散和爆炸的问题,这两个都是深度学习模型中非常关键的问题,因此normalization这步是逃不掉的。说到这里了,不妨说两句Internal Covariate Shift是个啥,我个人最直观的理解就是,模型的输入经过一层层的计算之后,每一层的输入的数据分布是不一样的,这就导致了结果的不准确,covariate shift现象的解释这篇博客很形象地举例说明了这个问题,这里点到为止。
目前主流的有四种normalization的方法,分别是Batch Norm,Layer Norm,Instance Norm以及Group Norm,其操作其实都很简明易懂。下图是这四种方法主要区别的一个对比示意图。下面会详细说一说这几种方法。
2.1 Batch Norm
假设我们的输入是一个shape为(N,C,H,W)的向量,其中N表示Batch size的大小,C表示channel数量,H为height,W为width。那么Batch Norm就会在整个batch的每个channel上计算一次均值和方差,并对每个channel进行归一化。
其详细计算过程为
要再次强调的是,上面的计算都是在每个channel上进行的,有几个channel就会算出几个均值和方差。另外值得一提的是,这里有一个γ\gammaγ和β\betaβ,他们是模型可以学习的参数。并不是模型的每一层都需要进行归一化,当γ=σ2+ϵ\gamma = \sqrt{\sigma^2 + \epsilon}γ=σ2+ϵ,且 β=μ\beta = \muβ=μ时,就还原成了没有归一化的数据。ϵ\epsilonϵ是为了预防分母为0而加的一个很小的数。
不过这里有个问题就是inference的时候该咋办,inference的时候如果时计算输入数据的均值和方差的话,那岂不是我一张一张图片输入和多张图片一起输入的结果还不一样了。放心,inference的时候,Batch Norm用的均值和方差时训练时候,记录下来的整个训练数据的均值和方差的期望。
2.2 Layer Norm
Layer Norm的目的和本文开头所讲的Group Norm的目的是一样的。不过它的做法比较极端,它是在一个数据的所有channel上计算均值和方差的,这干想想也有点问题,不同channel代表的特征是不同的,把他们归一化到同一个均值和方差上,未免有些强人所难。
这是group norm的一种极端形式,当group的大小刚好等于C时,就是Layer Norm了。
2.3 Instance Norm
Instance Norm和Layer Norm对着干,它也知道不同意义的channel不能一起归一化,于是就干脆用一条数据一个channel上的数据进行归一化。不过这也过于极端,一条数据一个channel上计算出来的均值和方差,未免有些不太靠谱,难以表征这个channel的数据分布。
这也是group norm的一种极端形式,当group的大小刚好等于1时,就是Instance Norm了。
2.4 Group Norm
Group Norm是个和事佬,设置了一个叫做group的东西,取一部分的channels作为一个group进行归一化,既不得罪Layer Norm,也不得罪Instance Norm,因为一些经典的,比如SIFT和HOG这样的特征,的确是以group为单位的。事实也证明,这个和事佬做的很成功。
Group Norm的代码也很简单,只需要短短几行就可以了
def GroupNorm(x, gamma, beta, G, eps=1e−5):# x: input features with shape [N,C,H,W]# gamma, beta: scale and offset, with shape [1,C,1,1]# G: number of groups for GNN, C, H, W = x.shapex = tf.reshape(x, [N, G, C // G, H, W])mean, var = tf.nn.moments(x, [2, 3, 4], keep dims=True)x = (x − mean) / tf.sqrt(var + eps)x = tf.reshape(x, [N, C, H, W])return x ∗ gamma + beta
另一个好处就是,它在inference时不需要依赖训练时的均值和方差。
3 效果对比
(1)相同batch size,不同normalization
当batch size都是32时,Batch Norm的效果时最好的,Group Norm其次,Layer Norm和Instance Norm就没有什么竞争力了,可以忽略不计了。
(2)不同batch size,Batch Norm和Group Norm对比
当batch size比较大时,Batch Norm是占优势的,但当batch size变小时,Batch Norm的效果就越来越差了。而Group Norm的效果不受batch size的影响。
(3)Group Norm在不同Group size下的表现
当只有一个group时,Group Norm就变成了Layer Norm,当每个group只有一个channel时,就变成了Instance Norm。实验证明,group的大小在32或者16个channel左右时比较优的一个值,一般的框架中默认的都是32。
Group Norm虽然解决了单卡batch size小时模型表现部好的问题,但是也带来了一个需要调节的超参数group size。这也意味着要做更多的实验。
参考文献
[1] Group Normalization
[2] Group Normalization (Paper Explained)
[3] Implementing Batch Normalization in Python