本来是不打算写的, 不过最近看各种东西老是能碰到norm的问题, 所以还是单独记录一下.
BatchNorm
对batch维度做norm, 常见1D和2D.
1D在nlp领域,输入: N,C,L 然后num_features为C的大小,对L做norm
2D在图像处理,输入: N,C,H,W,然后num_features为C,对HW做norm
example:
1D:
1 | In [1]: import torch |
2D类似,不过norm就像字面意思,norm维度变成了2维:
1 | In [20]: x = torch.arange(2*2*2*2, dtype=torch.float).reshape(2,2,2,2) |
BN的batchsize相关
如果模型选择了BN,那么一定得注意batchsize的选择问题,毕竟是batch-wise的norm, 虽然你可以设置batchsize为1, 但那样就等同于instance norm了, BN的作用是对每个batch做normalization, 为了让同batch的分布一致, 可能更适用于分类问题.
conv + BN
conv输出的时候可以带bias, 但是如果后面是BN, 那么bias就可以带可以不带.
因为假设输出为x:
x -> (mean_x, var_x)
x+b -> (mean_x + b, var_x)
所以BN之后:
(x - mean_x) / std_x == (x+b - mean_x - b) / std_x
因此bias带不带没影响.
LDM/Stable Diffusion
最近一直也在调LDM, 其中发现的一个问题就是自己写的时候带了BatchNorm, 但是又考虑到GPU大小问题, batchsize只能设置2.
于是回头看了下CompVis它们的代码, 发现他们的batchsize也是设置的4, 大概也是觉得batchsize太小用BN不合适, 他们norm也是选择了使用groupnorm.
LayerNorm
区别于batchnorm, layernorm是依据你输入的维度来做norm.
更直观的说, 就是从batch里面每次取出一个sample(区别于batchnorm,即not batch-wise), 然后从这个sample里面每次取出instance, 这个instance的大小是自己指定, 然后对这个instance做norm, 然后取下一个instance.
比如下面这个例子, batch大小为2, 设置为layernorm((2,2,2)), 那么每次循环从sample 1取出一个222张量做norm, 同理设置为(2,2), 那么就会取出2*2来做norm, 一个sample结束了之后再取sample 2然后norm.
1 | In [1]: import torch |
InstanceNorm
就像刚刚介绍的, 类似于batchsize为1的BN. 即每次从batch里面取出一个instance, 然后锁Channel, 对HW做norm. 这个norm的作用主要是针对每一个不同的图片来做norm, 所以被运用来风格迁移上.
1 | In [1]: import torch |
GroupNorm
介于InstanceNorm和LayerNorm中间, InstanceNorm是group为channel number的特例, 而layernorm为group为1的特例.
pytorch官方文档也写了
1 | input = torch.randn(20, 6, 10, 10) |
实例:
1 | In [1]: import torch |