深度学习的目的不是搭建怎样的模型,而是在准确的前提下,用尽可能精简的模型来学习训练数据集的分布。因此,深度学习作为数据驱动的方法,对数据集的要求高。在概率论与数理统计中独立同分布是大家最喜欢的条件,但在深度学习中数据往往都不是独立同分布的,比如当数据为图片时,相邻像素点具有相关性,减少数据的相关性的方法有PCA等;Normlization则是将数据变换成 同分布。
1). torch.nn.BatchNorm1d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True, device=None, dtype=None)
1d表示序列数据,对整个batch中的数据计算均值和方差,参数说明如下:
num_features :输入特征(通道)数
eps :常数(避免分母为零)。
momentum :动态均值和动态方差所使用的动量。 x ^ new = ( 1 − \hat{x}_{\text {new }}=(1- x^new =(1− momentum ) × x ^ + ) \times \hat{x}+ )×x^+ momentum × x t \times x_{t} ×xt,其中X是统计估计,Xt是当前的观察值。
affine :是否添加可学习的放射变换。
track_running_stats :“True”,表示记录训练过程中的均值和方差
输入 :(N,C)或(N,C,L),其中N为batchsize,C为num_channels,L为len_sequence。
输出 :与输入相同
# With Learnable Parameters
m = nn.BatchNorm1d(100)
# Without Learnable Parameters
m = nn.BatchNorm1d(100, affine=False)
input = torch.randn(20, 100)
output = m(input)
2). torch.nn.BatchNorm2d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True, device=None, dtype=None)
对图像数据的BatchNorm ,参数说明与计算方法同BatchNorm1d。
输入 :(N,C,H,W),其中N为batchsize,C为num_channels,H为图片的高,W为图片的宽。
输出 :与输入相同。
# With Learnable Parameters
m = nn.BatchNorm2d(100)
# Without Learnable Parameters
m = nn.BatchNorm2d(100, affine=False)
input = torch.randn(20, 100, 35, 45)
output = m(input)
3). torch.nn.BatchNorm3d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True, device=None, dtype=None)
对3D数据的BatchNorm,参数说明同BatchNorm2d。
输入 :(N,C,D,H,W),其中N为batchsize,C为num_channels,D,H,W为数据的三个维度。
输出 :与输入相同。
# With Learnable Parameters
m = nn.BatchNorm3d(100)
# Without Learnable Parameters
m = nn.BatchNorm3d(100, affine=False)
input = torch.randn(20, 100, 35, 45, 10)
output = m(input)
torch.nn.LazyBatchNorm1d(eps=1e-05, momentum=0.1, affine=True, track_running_stats=True, device=None, dtype=None)
相比BatchNorm1d多增加了一个”延迟模块“,延迟初始化参数。对应的还有LazyBatchNorm2d 和 LazyBatchNorm3d。
torch.nn.SyncBatchNorm(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True, process_group=None, device=None, dtype=None)
官方文档的解释:The mean and standard-deviation are calculated per-dimension over all mini-batches of the same process groups. 也就是说计算同一步的所有mini_batch的均值方差,我的理解如下:
当使用 N N N个GPU训练时,使用BatchNorm只能计算每个设备输入数据的均值和方差。使用SyncBatchNorm则计算 N ∗ B a t c h S i z e N*BatchSize N∗BatchSize 个数据计算均值和方差。SyncBatchNorm就是Pytorch提供的具有同步能力的BN层。
torch.nn.GroupNorm(num_groups, num_channels, eps=1e-05, affine=True, device=None, dtype=None)
num_groups :channel分出来的组数
BatchNorm是对每一个channel进行均值和方差的计算,GroupNorm则是将channel分为几组计算均值和方差,比如说有6个通道,分为3组。
torch.nn.InstanceNorm1d(num_features, eps=1e-05, momentum=0.1, affine=False, track_running_stats=False, device=None, dtype=None)
BatchNorm是对整个batch的每个channel计算均值和方差,InstanceNorm表示对batch中的每个数据的每个channel,分别计算均值和方差。与BatchNorm一样他也有相应的 torch.nn.InstanceNorm2d 和 torch.nn.InstanceNorm3d。
参考 LazyBatchNorm,只是将整个batch计算均值和方差改为分别计算每个数据的均值和方差。
torch.nn.LayerNorm(normalized_shape, eps=1e-05, elementwise_affine=True, device=None, dtype=None)
normalized:为list或int或torch.Size,如果输入为int则这个数等于input的最后一维;list和torch.Size时一般为(C, H, W)。
LayerNorm :计算每个样本的所有通道的均值和方差。
torch.nn.LocalResponseNorm(size, alpha=0.0001, beta=0.75, k=1.0)
size:用于归一化的通道数
alpha:乘积因子
beta:指数
k:附加因子
b c = a c ( k + α n ∑ c ′ = max ( 0 , c − n / 2 ) min ( N − 1 , c + n / 2 ) a c ′ 2 ) − β b_{c}=a_{c}\left(k+\frac{\alpha}{n} \sum_{c^{\prime}=\max (0, c-n / 2)}^{\min (N-1, c+n / 2)} a_{c^{\prime}}^{2}\right)^{-\beta} bc=ac⎝⎛k+nαc′=max(0,c−n/2)∑min(N−1,c+n/2)ac′2⎠⎞−β
以一个batch的图像数据 ( N , C , H , W ) (N,C,H,W) (N,C,H,W)为例。
BatchNorm:在batch上对 ( N , H , W ) (N,H,W) (N,H,W)做归一化,对小batchsize效果不好,当batchsize太小时,计算的均值和方差不足以代表整个数据分布;
GroupNorm:将channel分组,然后对每个组再做归一化,也就是对 ( ( C / / G ) , H , W ) ((C//G),H,W) ((C//G),H,W)进行归一化;
InstanceNorm:对于每一个channel内归一化,也就是对 ( H , W ) (H,W) (H,W)进行归一化,用在风格化迁移,保持每个图像实例之间的独立;
LayerNorm:在channel上对,对 ( C , H , W ) (C,H,W) (C,H,W)做归一化,主要对RNN作用明显。
上述方法都是减去均值除以标准差,再进行线性变换,不同点在于计算均值和标准差的公式
y = x − E [ x ] Var [ x ] + ϵ ∗ γ + β y=\frac{x-\mathrm{E}[x]}{\sqrt{\operatorname{Var}[x]+\epsilon}} * \gamma+\beta y=Var[x]+ϵx−E[x]∗γ+β
BatchNorm的均值与标准差
μ c ( x ) = 1 N H W ∑ n = 1 N ∑ h = 1 H ∑ w = 1 W x n c h w \mu_{c}(x)=\frac{1}{N H W} \sum_{n=1}^{N} \sum_{h=1}^{H} \sum_{w=1}^{W} x_{n c h w} μc(x)=NHW1n=1∑Nh=1∑Hw=1∑Wxnchw
σ c ( x ) = 1 N H W ∑ n = 1 N ∑ h = 1 H ∑ w = 1 W ( x n c h w − μ c ( x ) ) 2 + ϵ \sigma_{c}(x)=\sqrt{\frac{1}{N H W} \sum_{n=1}^{N} \sum_{h=1}^{H} \sum_{w=1}^{W}\left(x_{n c h w}-\mu_{c}(x)\right)^{2}+\epsilon} σc(x)=NHW1n=1∑Nh=1∑Hw=1∑W(xnchw−μc(x))2+ϵ
GroupNorm的均值与标准差
μ n g ( x ) = 1 ( C / G ) H W ∑ c = g C / G ( g + 1 ) C / G ∑ h = 1 H ∑ w = 1 W x n c h w \mu_{n g}(x)=\frac{1}{(C / G) H W} \sum_{c=g C / G}^{(g+1) C / G} \sum_{h=1}^{H} \sum_{w=1}^{W} x_{n c h w} μng(x)=(C/G)HW1c=gC/G∑(g+1)C/Gh=1∑Hw=1∑Wxnchw
σ n g ( x ) = 1 ( C / G ) H W ∑ c = g C / G ( g + 1 ) C / G ∑ h = 1 H ∑ w = 1 W ( x n c h w − μ n g ( x ) ) 2 + ϵ \sigma_{n g}(x)=\sqrt{\frac{1}{(C / G) H W} \sum_{c=g C / G}^{(g+1) C / G} \sum_{h=1}^{H} \sum_{w=1}^{W}\left(x_{n c h w}-\mu_{n g}(x)\right)^{2}+\epsilon} σng(x)=(C/G)HW1c=gC/G∑(g+1)C/Gh=1∑Hw=1∑W(xnchw−μng(x))2+ϵ
InstanceNorm的均值与标准差
μ n c ( x ) = 1 H W ∑ h = 1 H ∑ w = 1 W x n c h w \mu_{n c}(x)=\frac{1}{H W} \sum_{h=1}^{H} \sum_{w=1}^{W} x_{n c h w} μnc(x)=HW1h=1∑Hw=1∑Wxnchw
σ n c ( x ) = 1 H W ∑ h = 1 H ∑ w = 1 W ( x n c h w − μ n c ( x ) ) 2 + ϵ \sigma_{n c}(x)=\sqrt{\frac{1}{H W} \sum_{h=1}^{H} \sum_{w=1}^{W}\left(x_{n c h w}-\mu_{n c}(x)\right)^{2}+\epsilon} σnc(x)=HW1h=1∑Hw=1∑W(xnchw−μnc(x))2+ϵ
LayerNorm的均值与方差
μ n ( x ) = 1 C H W ∑ c = 1 C ∑ h = 1 H ∑ w = 1 W x n c h w \mu_{n}(x)=\frac{1}{C H W} \sum_{c=1}^{C} \sum_{h=1}^{H} \sum_{w=1}^{W} x_{n c h w} μn(x)=CHW1c=1∑Ch=1∑Hw=1∑Wxnchw
σ n ( x ) = 1 C H W ∑ c = 1 C ∑ h = 1 H ∑ w = 1 W ( x n c h w − μ n ( x ) ) 2 + ϵ \sigma_{n}(x)=\sqrt{\frac{1}{C H W} \sum_{c=1}^{C} \sum_{h=1}^{H} \sum_{w=1}^{W}\left(x_{n c h w}-\mu_{n}(x)\right)^{2}+\epsilon} σn(x)=CHW1c=1∑Ch=1∑Hw=1∑W(xnchw−μn(x))2+ϵ
1). BatchNorm:
import torch
import torch.nn as nn
input = torch.randn(5,3,16,16)*100
BN = nn.BatchNorm2d(num_features=3, eps=1e-05, momentum=0, affine=False, track_running_stats=False)
def BN_custom(input):
# 变形(3, 5*16*16)
input1 = input.permute(1,0,2,3).contiguous().view(3, -1)
# 均值(每一个通道均值)
mu = input1.mean(dim=1).view(1,3,1,1)
# 标准差(每一个通道标准差)
std = input1.std(dim=1, unbiased=False).view(1,3,1,1)
output = (input-mu) / (std.pow(2)+1e-05).pow(1/2)
return output
err = BN(input) - BN_custom(input)
print(err.abs().sum())
输出:tensor(9.7361e-05)。
误差的一范数为9.7361e-05可以认为方法正确。
2).GroupNorm: 把相邻的通道分为一组
import torch
import torch.nn as nn
input = torch.randn(5,6,16,16)*100
GN = nn.GroupNorm(3, 6, eps=1e-05, affine=False)
def GN_custom(input):
# 变形(5, 3, 2*16*16)
input1 = input.view(5, 3, -1)
# 均值(5, 3, 1)
mu = input1.mean(dim=-1).reshape(5, 3, -1)
# 标准差(5, 3, 1)
std = input1.std(dim=-1, unbiased=False).reshape(5, 3, -1)
output = (input1-mu) / (std.pow(2)+1e-05).pow(1/2)
output = output.reshape(5, 6, 16, 16)
return output
err = GN(input) - GN_custom(input)
print(err.abs().sum())
输出:tensor(0.0003)。
误差的一范数为0.0003可以认为方法正确。
3).InstanceNorm:
import torch
import torch.nn as nn
input = torch.randn(5, 3, 16, 16)
IN = nn.InstanceNorm2d(num_features=3, eps=1e-05, momentum=0, affine=False, track_running_stats=False)
def IN_custom(input):
# 变形(5*3, 256)
input1 = input.view(15, -1)
# 均值
mu = input1.mean(dim=1).view(5, 3, 1, 1)
# 标准差
std = input1.std(dim=1, unbiased=False).view(5, 3, 1, 1)
output = (input - mu)/(std.pow(2) + 1e-05).pow(1/2)
return output
err = IN(input) - IN_custom(input)
print(err.abs().sum())
输出:tensor(0.0002)。
误差的一范数为0.0002可以认为方法正确。
4). LayerNorm:
import torch
import torch.nn as nn
input = torch.randn(5, 3, 16, 16)
LN = nn.LayerNorm(normalized_shape=[3,16,16], eps=1e-05, elementwise_affine=False)
def LN_custom(input):
# 变形(5, 3*16*16)
input1 = input.view(5, -1)
# 均值
mu = input1.mean(dim=1).view(5, 1, 1, 1)
# 标准差
std = input1.std(dim=1, unbiased=False).view(5, 1, 1, 1)
output = (input-mu)/(std.pow(2) + 1e-05).pow(1/2)
return output
err = LN(input) - LN_custom(input)
print(err.abs().sum())
输出:tensor(0.0001)。
误差的一范数为0.0001可以认为方法正确。