batchnormlization、layer normalization通俗理解

 本文用举例的方式通俗地讲解了batchnormlization原理,是我觉得比较好理解的方式,比单纯公式好懂得多。

总体功能

将相同channel(特征)的数据进行归一化处理,也就是平移和缩放,让所有特征的量纲(特征值波动范围)差不多一致,可以让所有特征都能发挥作用,满足了glorot条件,有利于训练。

比如我一个特征A的值在0~255之间波动,另一个特征B的值0~1之间波动,那么我的模型去学习A特征带来loss减小的收益是远高于B特征的,因为A特征量纲比较大,对loss的影响也经常B大,模型会致力于去学习A特征,可以使loss降低地更快,带来地收益高,就导致B特征得不到充足的学习,导致最终结果变得不好。

光说可能太过抽象了,我们来举一个例子就好理解多了:实际上处理也就两步

比如我有一个batch(B)中有两张图像,每一张图像由RGB三个特征图组成(这一维度也叫channel即C),图像宽度为W高度为H,

那么一轮输入的size即为:

(B,C,W,H)也就是(2,3,W,H)

我们此时要归一化的话,按channel分为3组(传入batchnorm的数据的第二维默认为channel,所以RGB其实就是不同的特征,想让谁作为特征就放在第二维),每一组都是

(B,1,W,H) --》三张图像的R特征

(B,1,W,H) --》三张图像的G特征

(B,1,W,H) --》三张图像的B特征

处理第一步:进行z-score放缩

作用:将输入数据的均值平移至0点,并将输入数据的方差放缩至1

 接着上面的例子:

比如对于R特征,我有(B,1,W,H)也就是B*W*H个点是属于R特征的(B个图每个图都有一个R特征图,每张图上有W*H个点,所以就是B*W*H个点是属于R特征的)

求这B*W*H个点的均值,对应上图的式子1

求这B*W*H个点的方差,对应上图的式子2

B*W*H个点同时减去均值,再除以方差的根号,对应上图的式子3,这步就是在归一化,z-score放缩。

对G和B特征也是同理

处理第二步:带参数的平移放缩

作用:第二阶段相当于在零均值的基础上再进行小规模的变换使其能适应模型,γ和β是属于模型的参数(也就是可以随着反向传播和梯度下降进行跟新的参数,require_grad=True),是可以跟着向前和向后的传播来进行修改的,能够达到生成一个适应模型的修正变换

公式:
        new_x=γ*x+β

x是每一个元素

  接着第一步:

我们经过第一步,的到了处理过后的RGB特征,总体数据还是(B,C,W,H)

为(B,1,W,H) --》三张图像的R特征 分配1个γ1和β1

(B,1,W,H) --》三张图像的G特征 分配1个γ2和β2

(B,1,W,H) --》三张图像的B特征 分配1个γ3和β3

以R为例子,B*W*H个点同时乘以相同的γ1,再加上相同的β1,即可得到放缩后的结果,γ1和β1都是数,不是数组,比如γ1为3,β1为2。

对G和B特征也是同理

至此bn的操作就完成了

我们可以得出一些结论

1.bn对属于相同的特征的值做加减乘除操作都是都是相同的,比如n1,n2都属于特征1,比如n1+100,n2也必须加上100,n1除以100,n2也必须除以100,这才能保证特征的一个整体分布不会被打乱,也就是各个特征间的相对位置不能有变化。

2.bn层并不会改变输入数据的size,因为只是对数据做了平移和放缩,也就是仿射变换

3.操作的两步本质都是平移和放缩,是一样的

4.第一步C组均值和方差,第二步有C组γ和β,官网也有提到

γ and β are learnable parameter vectors of size C (where C is the number of features or channels of the input).

γ和β是大小为C的可学习参数向量(其中C是输入的特征或通道的数量)。

 pytorch的batchnorm的1d,2d,3d的区别

可处理的数据维度不同

1d

  • Input: (N, C)(N,C) or (N, C, L)(N,C,L), where NN is the batch size, CC is the number of features or channels, and LL is the sequence length

  • Output: (N, C)(N,C) or (N, C, L)(N,C,L) (same shape as input)

2d

  • Input: (N, C, H, W)(N,C,H,W)

  • Output: (N, C, H, W)(N,C,H,W) (same shape as input)

3d

以此类推

都是以N为1个样本单位,也就是参加bn的数量为N,如果第一维为batch_size那就意思是以他为单位进行归一化。

maxpool和bn有很多相似之处,比如1d,2d,3d,1d就是channel后面还有0维或者1维,2d就是后面还有两维,以此类推。

batchnorm的参数

torch.nn. BatchNorm2d ( num_features , eps 1e05 , 

momentum 0.1 , affine True , track_running_stats True , 

device None , dtype None )

num_features:

最重要的参数当然还是num_features也就是特征的数量(一共有多少特征),搭配卷积使用时,先卷积后bn,那当然是和out_channel相同。

affine :

是否加入第二阶段,也就是是否使用γ和β再生产对角矩阵进行仿射变换

 momentum:默认0.1

在计算running_mean/var时会用到,用sample_var 无偏和上一轮的running_mean/var来合成新的running_mean/var,momentum是这次的样本值,一般要epoch越大,momentum要越小,降低后面的波动幅度,增加稳定性。
在这里插入图片描述

 注意点:

 也就是不同于传统优化器类中使用的动量和传统的动量概念,这里的动量是momentum是乘在新值上面的,在本文中就是momentum*running_mean/var,而传统动量中这个参数momentum应该是乘以上一轮的running_mean/var的.

eps:默认 1e-5

 就是这个数


track_running_stats:

如官方文档所说

如果track_running_stats被设置为False,那么这个层就不会保留运行估计值,而在评估时也会使用批量统计。

首先是moudle.training 参数

这个参数是由model.train()或model.eval()决定的,当调用model.train(),则所有模型的training参数都会变为True,这个参数会搭配batchnorm和dropout来使用。

训练阶段:

当track_running_stats=True,running_mean和running_var会跟踪不同batch数据的mean和variance,但是仍然是用每个batch的mean和variance做normalization
当track_running_stats=False,此时running_mean和running_var不跟踪不同batch数据的statistics,但是仍然用每个batch的mean和variance做normalization


测试阶段:

当track_running_stats=True,则使用训练阶段跟踪估计的running_mean和running_var做normalization
当track_running_stats=False,训练阶段没有跟踪不同batch数据的statistics,因此使用每个batch的mean和variance做normalization
 

总结:track_running_stats这个参数就是一直使用默认的True参数就完事了,这种才是正常的使用方法

track_running_stats教程

track_running_stats教程带trainning

layer normalization

batch normalization与layer normalization的区别

二者做归一化的数据不同

举例:

layer normalization比如我有数据(3,4,5),normalized_shape为(4,5),那么我使用layer normalization有3个均值和方差,一个batch里的所有元素共用1个均值和方差。

二者效果的差别

LN比BN效果更好,

BN比LN计算更快

过程:

同batchnorm,第一步也是进行0均值化,第二部进行仿射变换,这里是逐元素的仿射变换,与batchnorm不同。

参数:

CLASStorch.nn.LayerNorm(normalized_shapeeps=1e-05elementwise_affine=Truedevice=Nonedtype=None)

1.normalized_shape (int or list or torch.Size

后面的哪些维度作为一个整体进行归一化

normalized_shape 必须是shape的后几维度,比如:
我有(N, C, H, W),那么我输入可以为[N,C,H,W],[C,H,W],[H,W],[W]

如果为[N,C,H,W]那么就是所有的元素一起归一化,1均值,1方差

[C,H,W]分为N个单位进行归一化,N均值,N方差,是图像领域常用的归一化手段。此时

也可以填入数字,数字的话只能是最后一维,如填入W,w=input.shape[-1]

2.elementwise_affine

进行逐元素的仿射变换,每个元素都有自己独立的γ和β,公式还是
        new_x=γ*x+β

(可读)归一化与仿射变换的关系

仿射变换教程
线性变换: 就是矩阵乘法(这点很重要)

数据平移:矩阵加减法
仿射变换:线性变换(矩阵乘法)+平移(矩阵加减法),式子如下图)。对于数据的仿射变换并不会影响数据分布

归一化是仿射变换的特例: 归一化是一个特征同时加上某个数,且同时乘以某个数,此时的线性变换矩阵为对角矩阵,除了对角线其他位置元素都为0,可以保证每一列都乘以某一个数,且其他特征无法对特征造成影响,因为权重都为0。


普通放射变换: 普通放射变换的变换矩阵就不一定是对角矩阵了,意味着不同的特征可能发生权重相加的交互,但本质上还是线性变换,数据特征得分布都是不变的

归一化实际上是一种特殊的仿射变换,仿射变换又通过线性层,线性层是仿射变换,conv1d,conv2d不是仿射变换。

放射变换实际上就是conv,linear在做的事,携程new_x=x*a+b
归一化时w为对角矩阵,可以保证每一列的乘以的值是一样的(对角矩阵等于对batch的相同位置的逐元素相乘)
线性层时w可不为对角矩阵,都是进行仿射变换

将归一化看成特殊的线性层,线性层就是pytorch中的仿射变换的实现方式

        bn的两个阶段:第一阶段和第二阶段实际都是逐元素乘法和加法,可以用对角矩阵来实现,当然也可以直接逐元素相乘不用对角矩阵都是一个道理。
 

什么时候用到无偏估计的var,什么时候用到有偏估计的var

这里的var算的是一个batch的var,也就是方差,1个特征1个var,组成var的1行n列的矩阵
有三个var要辨析:
sample_var 无偏
sample_var 有偏
running_var
其实无偏估计的var就是对整体也就是所有数据的猜测,有偏则是对样本内数据方差的精确计算。
这也就比较好理解下面了:
sample_var 有偏:在对这一轮的样本进行Z-zero归一化时,使用的是有偏的var进行归一化

sample_var 无偏:无偏用于计算running_var ,就是不断地修改优化所有样本的var,所以每一个batch的无偏用来猜测整体的var,通过每个batch的预测的整合来达到对所有样本var的估计。

running_var:即所有样本的var的在目前的估计,会随着bn层的使用(对batch的sample_var 无偏的计算)而不断更新。

SYNCBATCHNORM

https://zhuanlan.zhihu.com/p/555881100

我对SYNCBATCHNORM的理解实际上就还是batchnorm,只不过数据都分散开了,比如我有4个GPU,每个GPU batchsize为2,那么我计算batchnorm其实是按batchsize为8进行计算的,也就是8个batch合体计算,就是这么直接。

使用convert_sync_batchnorm成员函数可以将所有batchnorm转换为同步。

我觉得利用这个特性数据同步可以有更大的发展空间,不用再为bn层烦恼

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值