Batch Normalization
简单的说,BN可以在不影响精度的情况下加速神经网络的训练收敛,具体的实现也比较简单,但是就可解释性来说依旧众说纷纭,有一个说法是加入了一定的噪音,因为对于不同的Batch来讲,它的分布有可能机器不同,在归一化之后又限定了数据的范围,当然这是其中一种说法,像原论文提出是为了减少内部协变量转移,后来有人指出其实并没有做到这件事(炼丹嘛~),无论怎么样,BN这个技术目前使用的比较多,而且效果比较好,暂且为功能性使用来讲不去深究内部原因。
简单来说,BN是把一个批次的数据,在特征维度间进行归一化。举个例子来说,假设一个集体中的个人有身高体重发量三个维度,那么BN会分别在不同样本间的身高、体重、发量三个方面进行归一化。分为以下两步:
第一步:主要是计算输入批次的均值和方差,然后把数据归一化到均值为0,方差为1的数据分布。
第二步(可选):第二步会有一个反归一化,因为不一定均值为0,方差为1的分布就是好的,γ和β是两个可学习参数,用于控制方差和均值的转移。(这一步在设置BN代码中可选是否有可训练的参数)
使用
- 全连接层和卷积层输出上,激活函数前
- 全连接层输入上,作用在特征维度
- 卷积层输入上,作用在通道维
验证
这里简单使用torch中自带的来验证
import torch import torch.nn as nn #随机生成数据张量 feature = torch.randn(3,5) #batch_num, dim_num #设置BN函数 bn = nn.BatchNorm1d(5, affine=False) #打印原来的张量的平均值 sum_tensor = feature.mean(dim=0) print(feature) print(f'归一化之前的均值{sum_tensor},方差:{feature.var(dim=0)}') #打印归一化后的平均值和方差 out = bn(feature) sum_out = out.mean(dim=0) print(out) print(f'归一化之后的均值{sum_out},方差:{out.var(dim=0)}')
这里可以看到均值均近似为0,不过不知道为什么方差为都近似等于1.5;nn.BatchNorm1d有很多变种和参数可选。
Layer Normalization
当输入样本间长度不一时,需要对样本进行padding,而padding的值在BN归一化时会引入很大的偏差。所以这时候应该使用LN效果会好一点,在以后轨迹数据方面可能要多使用的时LN。
需要注意的是,BN中训练时需要累计moving_mean和moving_var两个变量,所以BN中有4个参数。而LN只要累计两个参数即可。
在公式方面,LN和BN并无太多差别。
验证
import torch import torch.nn as nn feature = torch.randn(5,3) print(feature) print(f'层归一化之前的均值{feature.sum(dim=1)},方差:{feature.var(dim=1)}') ln = nn.LayerNorm(normalized_shape=[3], elementwise_affine=False) out = ln(feature) print(out) print(f'层归一化之后的均值{out.sum(dim=1)},方差:{out.var(dim=1)}')
这里值得注意的是normalized_shape的设置,要从最后一个维度往前进行设置,且不是设置序号而是维度的大小,并且仅设置最后一个维度比较符合对一个单独的样本之间不同的维度进行归一化。
可以看到,每一个样本不同维度见进行了归一化,目前来讲,可以大概把shape当作一个两维的,即一个batch_size,dim_size,这样只对最后一维归一即可。
参考:https://cdn.modb.pro/db/488021
标签:多种,区别,BN,方差,feature,dim,归一化,out From: https://www.cnblogs.com/HOI-Yzy/p/16803781.html