从 X 入门Pytorch——BN、LN、IN、GN 四种归一化层的代码使用和原理


2024.2.27 更正一下LN的使用方法

前言

在训练神经网络时,往往需要标准化(Normalization)输入数据,使得网络的训练更加快速和有效,然而SGD等学习算法会在训练中不断改变网络的参数,隐含层的激活值的分布会因此发生变化,而这一种变化就称为内协变量偏移(Internal Covariate Shift,ICS)

为了减轻ICS问题,Nomalization固定激活函数的输入变量的均值和方差(Nomalization后接激活函数),使得网络的训练更快。其计算方式大白话如下:将输入的数据,按照一定维度进行统计,得到数据的均值和方差,然后对数据结合均值和方差进行计算,将其变化为服从均值为0,方差为1的高斯分布,这样有助于加快网络训练速度。同时为了降低由于数据变化导致降低模型的表达能力,Nomalization提供了两个参数,用来对数据进行仿射变换,让这些数据靠近原始数据(最极限情况是这两个参数又将变换后的数据变为原来的数据)。

以下图片清晰的给出了不同归一化层的区别:

在这里插入图片描述

我当时见过另外一种图,较为抽象,一直没太看懂,当时看到这个图,醍醐灌顶,一下就都通了。

1 Batch Normalization(2015年提出)

Pytorch官网解释

BatchNorm2d

原理

针对输入到BN层的数据X,对所有 batch单个通道做归一化,每个通道都分别做一次,公式如下:
y = x − E [ x ] V a r [ x ] + ϵ ∗ γ + β \mathrm{y}=\frac{\mathrm{x}-\mathrm{E}[\mathrm{x}]}{\sqrt{\mathrm{Var}[\mathrm{x}]+\epsilon}} * \gamma+\beta y=Var[x]+ϵ xE[x]γ+β
其中:

  • E [ x ] \mathrm{E}[\mathrm{x}] E[x] 是向量x的均值
  • V a r [ x ] \mathrm{Var}[\mathrm{x}] Var[x] 是向量x的方差
  • ϵ \epsilon ϵ 为很小的常数,通常为0.00001,防止分母为0
  • γ \gamma γ 为仿射变换参数,模型可学习
  • β \beta β 为放射变换参数,模型可学习

公式中gama之前的数据就是标准化后的数据,满足均值为0,方差为1的高斯分布,便于加快网络训练速度。
但是标准化有可能会降低模型的表达能力,因为网络中的某些隐藏层很有可能就是血需要输入数据是非标准分布的,因此提供gama和beta进行学习,用于恢复网络的表达能力。

Pytorch代码

torch.nn.BatchNorm2d(num_features, eps=1e-5, momentum=0.1, affine=True, track_running_stats=True)
  • num_features: 传入的通道数
  • eps:常数 ϵ \epsilon ϵ, 默认为0.00001
  • monentum:动量参数,用来控制均值和方差的更新
  • affine:仿射变换的开关:默认打开
    • 如果 affine=False,则 γ \gamma γ=1, β \beta β=0,参数不能学习
    • 如果 affine=True, 则 γ \gamma γ, β \beta β可学习
  • track_running_stats: 如果为 True,则统计跟踪 batch 的个数,记录在 num_batches_tracked 中,一般不用管。

示例

import torch
import torch.nn as nn

input = torch.randn(20, 6, 10, 10)
m = nn.BatchNorm2d(6) 

y = m(input)
print(y.shape)

out:
torch.Size([20, 6, 10, 10])

本文介绍的四种归一化层都不改变输入数据的维度大小!!

2 Layer Normalization(2016年提出)

Pytorch官网解释

LayerNorm

原理

针对输入到LN层的数据X,对单个Batch中的所有通道数据做归一化,然后每个batch都单独做一次,公式如下:
y = x − E [ x ] V a r [ x ] + ϵ ∗ γ + β \mathrm{y}=\frac{\mathrm{x}-\mathrm{E}[\mathrm{x}]}{\sqrt{\mathrm{Var}[\mathrm{x}]+\epsilon}} * \gamma+\beta y=Var[x]+ϵ xE[x]γ+β
参照Batch Normalization公式和最上面的图进行理解,就是针对不同维度的数据进行标准化,其他的没变。Transformer中使用的就是LayerNorm。

Pytorch代码

torch.nn.LayerNorm(normalized_shape, eps=1e-5, elementwise_affine=True)
  • normalized_shape: 输入数据的维度(除了batch维度),例:数据维度【16, 64, 256, 256】 传入的normalized_shape维度为【64, 256, 256】。
  • eps: 常数,默认值为0.00001
  • elementwise_affine:仿射变换的开关:默认打开
    • 如果 elementwise_affine=False,则 γ \gamma γ=1, β \beta β=0,参数不能学习
    • 如果 elementwise_affine=True, 则 γ \gamma γ, β \beta β可学习

示例

import torch
import torch.nn as nn

ln = nn.LayerNorm([64, 256, 256])
x = torch.randn(16, 64, 256, 256)
y = ln(x)
print(y.shape)

out:
torch.Size([16, 64, 256, 256])

我也是最近才用了这个,因为要事先传入维度大小(C,H,W),所以使用的时候没有BN那么方便,如果想用,需要提前自己计算一下数据到LN这里的维度是多少,然后进行实例化才可以。
2024.2.27更正:
在这里插入图片描述

3 Instance Normalization(2017年提出)

Pytorch官方解释

InstanceNorm2d

原理

针对输入到IN层的数据X,对单个Batch中的单个通道数据做归一化,然后每个batch每个通道单独做一次,公式如下:
y = x − E [ x ] V a r [ x ] + ϵ ∗ γ + β \mathrm{y}=\frac{\mathrm{x}-\mathrm{E}[\mathrm{x}]}{\sqrt{\mathrm{Var}[\mathrm{x}]+\epsilon}} * \gamma+\beta y=Var[x]+ϵ xE[x]γ+β
公式还是那个公式,理解还是那个理解,请看明白最上面的那种图,就清楚了。

Pytorch代码

torch.nn.InstanceNorm2d(num_features, eps=1e-05, momentum=0.1, affine=False, track_running_stats=False)
  • num_features: 是通道数
  • eps:常数 ϵ \epsilon ϵ, 默认为0.00001
  • monentum:动量参数,用来控制均值和方差的更新
  • affine:仿射变换的开关:默认关闭
    • 如果 affine=False,则 γ \gamma γ=1, β \beta β=0,参数不能学习
    • 如果affine=True, 则 γ \gamma γ, β \beta β可学习

示例

# Without Learnable Parameters
m = nn.InstanceNorm2d(100)
# With Learnable Parameters
m = nn.InstanceNorm2d(100, affine=True)
input = torch.randn(20, 100, 35, 45)
output = m(input)
print(output.shape)

out:
torch.Size([20, 100, 35, 45])

这个初始化只需要传入通道数即可,和BN的实例化方法一样,便于使用!

4 Group Normalization(2018年提出)

Pytorch官方解释

GroupNoem

原理

针对输入到GN层的数据X,对单个Batch中的多个通道数据(一组数据)做归一化,然后每个batch每组数据单独做一次,公式如下:
y = x − E [ x ] V a r [ x ] + ϵ ∗ γ + β \mathrm{y}=\frac{\mathrm{x}-\mathrm{E}[\mathrm{x}]}{\sqrt{\mathrm{Var}[\mathrm{x}]+\epsilon}} * \gamma+\beta y=Var[x]+ϵ xE[x]γ+β
公式还是那个公式,理解还是那个理解,请看明白最上面的那种图,就清楚了。
不是我偷懒,实际情况是,Pytorch官网给出的四个公式也就是一样的!

Pytorch代码

torch.nn.GroupNorm(num_groups, num_channels, eps=1e-05, affine=True)
  • num_groups: 需要将Batch中的通道分为几组
  • num_channels: 传入的数据通道数
  • eps:常数 ϵ \epsilon ϵ, 默认为0.00001
  • affine:仿射变换的开关:默认打开
    • 如果 affine=False,则 γ \gamma γ=1, β \beta β=0,参数不能学习
    • 如果affine=True, 则 γ \gamma γ, β \beta β可学习

示例

import torch
import torch.nn as nn

input = torch.randn(20, 6, 10, 10)

m3 = nn.GroupNorm(3, 6)  # 分成3组
m6 = nn.GroupNorm(6, 6)   # 分成6组,这个就和IN一样了
m1 = nn.GroupNorm(1, 6)  # 分成1组,这个就和LN一样了

y1 = m1(input)
y3 = m3(input)
y6 = m6(input)
print(y1.shape)
print(y3.shape)
print(y6.shape)

out:
torch.Size([20, 6, 10, 10])
torch.Size([20, 6, 10, 10])
torch.Size([20, 6, 10, 10])

参考:

https://blog.youkuaiyun.com/qq_33236581/article/details/124016573
https://zhuanlan.zhihu.com/p/470260895

如果感觉有用,就及时收藏点赞,否则后期又要翻找,跟着我,一步一步学CV

<think>嗯,我现在要详细了解一下深度学习中的各种归一化方法及其原理。用户需要理解底原理具体实现,所以我得先回忆一下常见的归一化技术,比如批归一化(Batch Normalization)、归一化(Layer Normalization)、实例归一化(Instance Normalization)、组归一化(Group Normalization)等等。可能还有其他的,比如权重归一化或者谱归一化,不过这些可能不是同一类的,需要区分清楚。 首先,批归一化(BN)应该是最经典的。我记得BN是在训练过程中对每个小批量数据进行归一化,也就是对每个神经元的输入进行标准化,使其均值0,方差1,然后通过可学习的参数缩放平移。这样做的好处是可以减少内部协变量偏移,加速训练,允许更大的学习率,还有一定的正则化效果。不过具体实现的时候,BN在训练测试阶段是不一样的,测试阶段使用的是移动平均的均值方差。这部分需要详细解释。 然后是归一化(LN),它跟BN不同,是针对单个样本的所有神经元进行归一化。也就是说,在同一个内,对同一个样本的所有激活值计算均值方差,然后应用缩放偏移。LN不依赖于批量大小,所以在小批量或者动态批量情况下表现更好,比如在RNN中常用。不过它的原理BN有什么本质区别呢?可能是在归一化的维度上不同,BN是在批处理其他维度(比如通道、高、宽)上进行归一化,而LN是在通道、高、宽之外的维度,比如特征维度? 接下来是实例归一化(IN),它主要用于生成对抗网络或者风格迁移任务。IN是对每个样本的每个通道单独进行归一化,也就是在(H,W)维度上计算均值方差。这样做的目的是保持每个实例的独立性,可能有助于保留实例的样式信息。比如在风格迁移中,保留内容的结构但改变风格,IN可以更好地规范化每个样本的样式。 组归一化(GN)则是将通道分成若干组,对每个样本的每个组进行归一化。GN在批量较小时效果比BN好,因为BN在批量很小时性能下降,而GN不依赖批量大小。例如在目标检测或视频处理中,可能因为内存限制只能使用小批量,这时候GN更合适。组归一化的分组策略如何影响性能呢?可能更多的组数让归一化更细致,但计算量也会增加。 另外,还有权重归一化(Weight Normalization)谱归一化(Spectral Normalization)。权重归一化是通过对权重向量进行重参数化,将其分解为方向幅度,这样可以加速训练收敛。谱归一化则主要用于GAN中,通过约束权重矩阵的谱范数来稳定训练,防止判别器过强。不过用户可能更关注的是输入或激活的归一化,所以可能需要先重点讲前面几种。 现在需要理清楚这些归一化方法各自适用的场景、数学公式以及实现方式。比如BN的公式是对每个通道在N、H、W维度上计算均值方差,而LN是在C、H、W维度上。需要明确各个方法在张量上的操作维度。 对于具体实现,每个归一化方法在框架中的实现可能不同,但大体步骤都是计算统计量,归一化,然后缩放平移。例如在PyTorch中,这些归一化层都有对应的实现,如torch.nn.BatchNorm2d、LayerNorm等,它们的参数输入形状有关。 可能还需要比较不同归一化的优缺点。比如BN的问题在于对批量大小的依赖,当批量很小时,估计的均值方差不准确,影响效果。而LNINGN则不受批量大小的影响。另外,BN在卷积网络中使用时,是按通道进行的,即每个通道有自己的均值方差参数,而LN可能是在所有通道上计算统计量? 比如对于四维张量(N, C, H, W),BN是在每个通道上,对N、H、W这三个维度计算均值方差,得到C个均值方差。而LN则是在每个样本上,对C、H、W这三个维度计算均值方差,得到N个均值方差。这样LN的参数数量可能与BN不同,比如缩放参数如果是每个通道的话,BN的缩放参数是C个,而LN可能也是C个?或者LN的缩放参数是针对整个的特征? 可能这里需要更仔细的数学公式来区分。例如,对于BN,假设输入为x,形状是(N, C, H, W),那么对于每个通道c,计算该通道在所有样本、所有空间位置的均值μ_c方差σ_c²。归一化后的x是 (x - μ_c)/sqrt(σ_c² + ε),然后乘以γ_cβ_c,每个通道有自己的γβ。 而LN则是对每个样本n,计算该样本所有通道空间位置的均值μ_n方差σ_n²。归一化后的x是 (x - μ_n)/sqrt(σ_n² + ε),然后乘以γβ。不过这里γβ的维度可能与输入有关,比如如果LN应用于最后的特征维度,可能γβ的长度是C*H*W?或者在图像处理中,如果使用LN,通常可能是在通道维度上进行归一化,比如对每个样本的每个通道的HW进行归一化?或者可能LN在图像中的使用较少,而更多用于NLP中的Transformer,这时候特征维度是不同的。 这部分可能需要查阅资料确认。例如,在Transformer中,LN通常应用于每个样本的特征向量,即在最后一个维度上计算均值方差。例如,输入的形状是(batch_size, seq_length, d_model),LN会在每个样本的每个位置上(即对d_model维度)计算均值方差,所以对于每个位置的特征向量进行归一化。而在图像处理中,LN可能对每个样本的所有元素(C、H、W)计算均值方差,即归一化的维度是CHW。这时候γβ的参数数量是C*H*W,但这样可能参数过多,所以实际中可能LN在图像中的使用可能需要调整,或者有不同的实现方式。 可能用户提到的归一化方法主要是BNLNINGN,需要分别详细解释它们的数学原理、操作维度、适用场景、具体实现以及优缺点。此外,可能还需要提到它们如何影响梯度流,为什么能加速训练,以及正则化效果是如何产生的(比如BN在训练时由于小批量的噪声带来的随机性,类似于Dropout的效果)。 在具体实现上,比如在PyTorch中,BN的实现会维护一个running_meanrunning_var,通过动量更新,而训练测试时的模式不同。其他归一化方法可能不需要维护全局统计量,比如LNINGN在测试时训练时的计算方式相同,因为它们不依赖于批量统计。 另外,可能需要注意归一化的位置,比如是在激活函数之前还是之后。通常BN是在卷积之后、激活函数之前应用,但有些研究也探讨不同的位置带来的影响。 总结起来,我需要分步骤介绍每个归一化方法,包括: 1. 方法名称(如批归一化) 2. 提出背景(解决什么问题) 3. 数学公式及操作维度 4. 训练测试阶段的差异(如有) 5. 具体实现方式(如参数数量,在框架中的使用) 6. 优缺点及适用场景 这样用户能逐步理解各个归一化的原理应用。同时,需要确保公式的格式正确,使用$$...$$$...$,并且用中文清晰解释。</think>以下是深度学习中的主要归一化方法及其原理的详细说明,按结构分解析: --- ### 一、批归一化(Batch Normalization, BN) #### 1. **提出背景** - 解决**内部协变量偏移**(每输入分布随训练变化),加速训练并允许更大的学习率。 #### 2. **数学原理** - 对每个**通道**的输入进行归一化(针对卷积网络): $$ \mu_c = \frac{1}{NHW}\sum_{n=1}^N \sum_{h=1}^H \sum_{w=1}^W x_{n,c,h,w} $$ $$ \sigma_c^2 = \frac{1}{NHW}\sum_{n=1}^N \sum_{h=1}^H \sum_{w=1}^W (x_{n,c,h,w} - \mu_c)^2 $$ $$ \hat{x}_{n,c,h,w} = \frac{x_{n,c,h,w} - \mu_c}{\sqrt{\sigma_c^2 + \epsilon}} $$ $$ y_{n,c,h,w} = \gamma_c \hat{x}_{n,c,h,w} + \beta_c $$ - $\gamma_c$$\beta_c$为可学习的缩放偏移参数。 #### 3. **实现细节** - **训练阶段**:计算当前批量的均值方差。 - **测试阶段**:使用训练时累积的移动平均统计量。 - **参数数量**:每通道一对$\gamma$$\beta$,共$2C$个参数。 #### 4. **优缺点** - **优点**:加速训练、缓解梯度消失/爆炸、轻微正则化。 - **缺点**:依赖批量大小(小批量效果差),不适用于动态网络(如RNN)。 --- ### 二、归一化(Layer Normalization, LN) #### 1. **提出背景** - 解决BN对批量大小的依赖,适用于RNNTransformer。 #### 2. **数学原理** - 对每个**样本**的所有特征进行归一化: $$ \mu_n = \frac{1}{CHW}\sum_{c=1}^C \sum_{h=1}^H \sum_{w=1}^W x_{n,c,h,w} $$ $$ \sigma_n^2 = \frac{1}{CHW}\sum_{c=1}^C \sum_{h=1}^H \sum_{w=1}^W (x_{n,c,h,w} - \mu_n)^2 $$ $$ \hat{x}_{n,c,h,w} = \frac{x_{n,c,h,w} - \mu_n}{\sqrt{\sigma_n^2 + \epsilon}} $$ $$ y_{n,c,h,w} = \gamma \hat{x}_{n,c,h,w} + \beta $$ - $\gamma$$\beta$为整个的参数。 #### 3. **实现细节** - 训练测试逻辑一致,无需存储统计量。 - **参数数量**:每一对$\gamma$$\beta$,共2个参数。 #### 4. **优缺点** - **优点**:独立于批量大小,适合序列模型。 - **缺点**:对卷积网络效果弱于BN。 --- ### 三、实例归一化(Instance Normalization, IN) #### 1. **提出背景** - 用于图像生成任务(如风格迁移),保持实例间独立性。 #### 2. **数学原理** - 对每个**样本的每个通道**单独归一化: $$ \mu_{n,c} = \frac{1}{HW}\sum_{h=1}^H \sum_{w=1}^W x_{n,c,h,w} $$ $$ \sigma_{n,c}^2 = \frac{1}{HW}\sum_{h=1}^H \sum_{w=1}^W (x_{n,c,h,w} - \mu_{n,c})^2 $$ $$ \hat{x}_{n,c,h,w} = \frac{x_{n,c,h,w} - \mu_{n,c}}{\sqrt{\sigma_{n,c}^2 + \epsilon}} $$ $$ y_{n,c,h,w} = \gamma_c \hat{x}_{n,c,h,w} + \beta_c $$ #### 3. **实现细节** - 参数数量与BN相同($2C$个参数)。 #### 4. **优缺点** - **优点**:保留实例的样式信息。 - **缺点**:不适用于分类任务。 --- ### 四、组归一化(Group Normalization, GN) #### 1. **提出背景** - 在小批量场景下替代BN(如目标检测)。 #### 2. **数学原理** - 将通道分为$G$组,每组单独归一化: $$ \mu_{n,g} = \frac{1}{(C/G)HW}\sum_{c \in g} \sum_{h=1}^H \sum_{w=1}^W x_{n,c,h,w} $$ $$ \sigma_{n,g}^2 = \frac{1}{(C/G)HW}\sum_{c \in g} \sum_{h=1}^H \sum_{w=1}^W (x_{n,c,h,w} - \mu_{n,g})^2 $$ $$ \hat{x}_{n,c,h,w} = \frac{x_{n,c,h,w} - \mu_{n,g}}{\sqrt{\sigma_{n,g}^2 + \epsilon}} $$ $$ y_{n,c,h,w} = \gamma_c \hat{x}_{n,c,h,w} + \beta_c $$ #### 3. **实现细节** - 分组数$G$为超参数(通常设为32)。 #### 4. **优缺点** - **优点**:在小批量下表现稳定。 - **缺点**:需手动调参分组数。 --- ### 五、其他归一化 1. **权重归一化(Weight Normalization)** - 对权重矩阵重参数化:$w = \frac{g}{\|v\|}v$,加速收敛。 2. **谱归一化(Spectral Normalization)** - 约束权重矩阵的谱范数,用于稳定GAN训练。 --- ### 六、对比总结 | 方法 | 归一化维度 | 适用场景 | 依赖批量大小 | |------------|-----------------------|------------------------|--------------| | Batch Norm | (N, H, W) | 卷积网络 | 是 | | Layer Norm | (C, H, W) | RNN/Transformer | 否 | | Instance | (H, W) | 图像生成 | 否 | | Group Norm | 通道分组 | 小批量任务(如检测) | 否 | --- ### 七、核心作用 1. **稳定训练**:通过约束输入分布,缓解梯度异常。 2. **加速收敛**:允许更大学习率。 3. **轻微正则化**:噪声来自小批量统计(如BN)。 代码实现(以PyTorch为例): ```python # BN(卷积网络) bn = nn.BatchNorm2d(num_features=C) # LN(Transformer) ln = nn.LayerNorm(normalized_shape=d_model) # GN(目标检测) gn = nn.GroupNorm(num_groups=G, num_channels=C) ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Philo`

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值