深度学习pytorch之22种损失函数数学公式和代码定义
深度学习pytorch之19种优化算法(optimizer)解析
深度学习pytorch之4种归一化方法(Normalization)原理公式解析和参数使用
摘要
归一化(Normalization)是提升模型性能、加速训练的重要技巧。归一化方法可以帮助减少梯度消失或爆炸的问题,提升模型的收敛速度,且对最终模型的性能有显著影响。本文将以 PyTorch 为例,介绍4种常见的归一化方法,并详细讲解它们的原理和公式。

Batch Norm:批量归一化,卷积神经网络通用。
Layer Norm:层归一化,适用于 RNN 和 Transformer 模型,在每个样本的所有特征维度上进行归一化。
Instance Norm:实例归一化,适用于风格迁移、Gan、图像生成,每个样本的每个通道独立归一化。
Group Norm:群体归一化,适用于视频处理(时序维度替代批次维度),不依赖于批量大小,通过将通道分成多个组进行归一化。
一、批量归一化(Batch Normalization)
批量归一化(Batch Normalization,简称 BN)是最常见的归一化方法之一。其主要思想是在每一层网络的输入数据上进行归一化,使得输入数据的均值为 0,方差为 1,从而加速训练并减轻梯度消失和爆炸问题。BN 通过对每个小批次(batch)的数据进行归一化,确保神经网络在训练过程中稳定。
原理
对于每个小批次中的数据 X = { x 1 , x 2 , ... , x m } X = \{x_1, x_2, \dots, x_m\} X={x1,x2,...,xm}:
-
计算均值和方差 :
μ B = 1 m ∑ i = 1 m x i \mu_B = \frac{1}{m} \sum_{i=1}^{m} x_i μB=m1i=1∑mxi
σ B 2 = 1 m ∑ i = 1 m ( x i − μ B ) 2 \sigma_B^2 = \frac{1}{m} \sum_{i=1}^{m} (x_i - \mu_B)^2 σB2=m1i=1∑m(xi−μB)2
m 是当前 批次(batch) 中的样本数量,x i x_i xi 是批次中第 i 个样本的输入特征。 -
标准化 :
x ^ i = x i − μ B σ B 2 + ϵ \hat{x}_i = \frac{x_i - \mu_B}{\sqrt{\sigma_B^2 + \epsilon}} x^i=σB2+ϵ xi−μB其中, ϵ \epsilon ϵ 是一个极小的常数,用于防止分母为零。
-
缩放和平移 :
BN 允许网络学习一个缩放因子 γ \gamma γ 和一个平移因子 β \beta β,从而恢复数据的表达能力:
y i = γ x ^ i + β y_i = \gamma \hat{x}_i + \beta yi=γx^i+β
优缺点
- 优点:BN 有助于加速训练过程,避免梯度消失或爆炸,且具有一定的正则化效果。
- 缺点:BN 对批量大小较为敏感,且在 RNN 等时序模型中不适用。
PyTorch 实现
python
torch.nn.BatchNorm1d/2d/3d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
参数:
- num_features:必须指定,表示输入数据的特征维度。比如,对于一个形状为 (batch_size, features) 的输入,num_features 就是 features。
- eps:防止除零错误的一个小常数,默认值为 1e-5。在计算方差时,如果方差过小(接近零),可以避免分母为零的情况。
- momentum:动量因子,用于计算运行时均值和方差的更新速度,默认值为 0.1。较高的 momentum 会使得更新更快,较低的 momentum 会使得均值和方差更加平滑。
- affine:布尔值,默认为 True。如果为 True,会添加可学习的缩放(gamma)和偏移(beta)参数。否则,归一化层只进行归一化操作,而不进行平移和缩放。
- track_running_stats:布尔值,默认值为 True。如果为 True,会追踪整个训练过程中的均值和方差(用于推理阶段)。如果为 False,则每次训练时都会重新计算均值和方差。
python
import torch
import torch.nn as nn
# 使用 Batch Normalization
model = nn.Sequential(
nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1),
nn.BatchNorm2d(32),
nn.ReLU()
)
二、层归一化(Layer Normalization)
层归一化(Layer Normalization,简称 LN)不同于批量归一化,它在每一个样本的所有特征维度上进行归一化,而不是在整个批量上进行归一化。该方法通常用于 RNN 和 Transformer 网络中,因为它能够独立地对每一个样本进行归一化,避免了批量归一化对批量大小的依赖。
原理
对于一个样本 x = { x 1 , x 2 , ... , x n } x = \{x_1, x_2, \dots, x_n\} x={x1,x2,...,xn}:
- 计算均值和方差 :
μ L = 1 n ∑ i = 1 n x i \mu_L = \frac{1}{n} \sum_{i=1}^{n} x_i μL=n1i=1∑nxi
σ L 2 = 1 n ∑ i = 1 n ( x i − μ L ) 2 \sigma_L^2 = \frac{1}{n} \sum_{i=1}^{n} (x_i - \mu_L)^2 σL2=n1i=1∑n(xi−μL)2
公式和BN类似,但BN中m 是当前 批次(batch) 中的样本数量,而LN中n 是每个样本的特征数量,也就是输入数据的 特征维度 ,x i x_i xi 是批次中第 i 个样本的输入特征。
-
标准化 :
x ^ i = x i − μ L σ L 2 + ϵ \hat{x}_i = \frac{x_i - \mu_L}{\sqrt{\sigma_L^2 + \epsilon}} x^i=σL2+ϵ xi−μL -
缩放和平移 :
y i = γ x ^ i + β y_i = \gamma \hat{x}_i + \beta yi=γx^i+β其中 γ \gamma γ 和 β \beta β 是可学习的参数。
优缺点
- 优点:层归一化不依赖于批量大小,适用于需要依赖单样本的模型,如 RNN 和 Transformer。
- 缺点:在卷积神经网络中,通常效果不如 BN,尤其是在处理大规模数据时。
PyTorch 实现
python
torch.nn.LayerNorm(normalized_shape, eps=1e-05, elementwise_affine=True)
参数:
- normalized_shape:必须指定,表示需要进行归一化的维度。对于一维数据,通常就是数据的特征数(num_features);对于多维数据,通常是最后一维的形状(例如,对于形状为 (batch_size, num_channels, height, width) 的输入,normalized_shape 可能是 (num_channels, height, width))。
- eps:防止除零错误的小常数,默认值为 1e-5。
- elementwise_affine:布尔值,默认值为 True。如果为 True,会学习每个特征的可训练缩放(gamma)和偏移(beta)参数。
python
# 使用 Layer Normalization
model = nn.Sequential(
nn.Linear(128, 64),
nn.LayerNorm(64),
nn.ReLU()
)
三、实例归一化(Instance Normalization)
实例归一化(Instance Normalization,简称 IN)是层归一化的一种变种,常用于图像生成任务(如生成对抗网络,GAN)。与层归一化不同,实例归一化是在每一个样本的每一个通道上进行归一化,不依赖于其他样本。
原理
对于样本 x ∈ R C × H × W x \in \mathbb{R}^{C \times H \times W} x∈RC×H×W(C 通道数,H 高度,W 宽度):
-
计算均值和方差 :
μ I N = 1 H × W ∑ i = 1 H ∑ j = 1 W x n c i j \mu_{IN} = \frac{1}{H \times W} \sum_{i=1}^{H} \sum_{j=1}^{W} x_{ncij} μIN=H×W1i=1∑Hj=1∑Wxncij
σ I N 2 = 1 H × W ∑ i = 1 H ∑ j = 1 W ( x n c i j − μ I N ) 2 \sigma_{IN}^2 = \frac{1}{H \times W} \sum_{i=1}^{H} \sum_{j=1}^{W} (x_{ncij} - \mu_{IN})^2 σIN2=H×W1i=1∑Hj=1∑W(xncij−μIN)2 -
标准化 :
x ^ n c i j = x n c i j − μ I N σ I N 2 + ϵ \hat{x}{ncij} = \frac{x{ncij} - \mu_{IN}}{\sqrt{\sigma_{IN}^2 + \epsilon}} x^ncij=σIN2+ϵ xncij−μIN -
缩放和平移 :
y n c i j = γ x ^ n c i j + β y_{ncij} = \gamma \hat{x}_{ncij} + \beta yncij=γx^ncij+β
优缺点
- 优点:实例归一化对于图像风格转换等任务非常有效,能够保留图像的局部特征。
- 缺点:不适用于传统分类任务,其效果通常不如批量归一化。
PyTorch 实现
python
torch.nn.InstanceNorm1d(num_features, eps=1e-05, affine=True, track_running_stats=False)
参数:
- num_features:必须指定,表示输入数据的特征数(例如,形状为 (batch_size, num_features) 的数据)。与 BatchNorm1d 中的 num_features 相同。
- eps:防止除零错误的小常数,默认值为 1e-5。
- affine:布尔值,默认为 True。如果为 True,将会学习可训练的缩放(gamma)和偏移(beta)参数。如果为 False,则不进行缩放和平移。
- track_running_stats:布尔值,默认值为 False。通常,实例归一化在训练和推理阶段的行为是相同的,因此不需要追踪均值和方差。
python
# 使用 Instance Normalization
model = nn.Sequential(
nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1),
nn.InstanceNorm2d(64),
nn.ReLU()
)
四、群体归一化(Group Normalization)
群体归一化(Group Normalization,简称 GN)是批量归一化的一种替代方法,它将特征通道分为多个组,在每一组内进行归一化。GN 不依赖于批量大小,因此特别适合在小批量或者批量大小变化较大的场景下使用。
原理
假设每个样本有 C C C 个通道,我们将通道分成 G G G组,每组有 C G = C / G C_G = C/G CG=C/G个通道。对于每一组的特征 x g ∈ R C G × H × W x_g \in \mathbb{R}^{C_G \times H \times W} xg∈RCG×H×W,进行如下归一化:
-
计算均值和方差 :
μ G = 1 C G × H × W ∑ i = 1 C G ∑ j = 1 H ∑ k = 1 W x i j k \mu_G = \frac{1}{C_G \times H \times W} \sum_{i=1}^{C_G} \sum_{j=1}^{H} \sum_{k=1}^{W} x_{ijk} μG=CG×H×W1i=1∑CGj=1∑Hk=1∑Wxijk
σ G 2 = 1 C G × H × W ∑ i = 1 C G ∑ j = 1 H ∑ k = 1 W ( x i j k − μ G ) 2 \sigma_G^2 = \frac{1}{C_G \times H \times W} \sum_{i=1}^{C_G} \sum_{j=1}^{H} \sum_{k=1}^{W} (x_{ijk} - \mu_G)^2 σG2=CG×H×W1i=1∑CGj=1∑Hk=1∑W(xijk−μG)2 -
标准化 :
x ^ i j k = x i j k − μ G σ G 2 + ϵ \hat{x}{ijk} = \frac{x{ijk} - \mu_G}{\sqrt{\sigma_G^2 + \epsilon}} x^ijk=σG2+ϵ xijk−μG -
缩放和平移 :
y i j k = γ x ^ i j k + β y_{ijk} = \gamma \hat{x}_{ijk} + \beta yijk=γx^ijk+β
优缺点
- 优点:GN 不依赖于批量大小,适用于小批量训练,非常适合检测和分割任务。
- 缺点:通常在卷积神经网络(CNN)中,批量归一化的效果通常比群体归一化要好。
PyTorch 实现
python
torch.nn.GroupNorm(num_groups, num_channels, eps=1e-05, affine=True)
- num_groups:必须指定,表示将输入通道分成多少组进行归一化。例如,num_groups=4 表示将通道数分成 4 组,每组的通道数为 num_channels / num_groups。
- num_channels:必须指定,表示输入的通道数。它应该与输入数据的通道维度匹配。
- eps:防止除零错误的小常数,默认值为 1e-5。
- affine:布尔值,默认值为 True。如果为 True,将会学习可训练的缩放(gamma)和偏移(beta)参数;如果为 False,则不进行缩放和偏移。
python
# 使用 Group Normalization
model = nn.Sequential(
nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1),
nn.GroupNorm(32, 64), # 32 groups, each with 2 channels
nn.ReLU()
)