深度学习pytorch之22种损失函数数学公式和代码定义
深度学习pytorch之19种优化算法(optimizer)解析
深度学习pytorch之4种归一化方法(Normalization)原理公式解析和参数使用
归一化(Normalization)是提升模型性能、加速训练的重要技巧。归一化方法可以帮助减少梯度消失或爆炸的问题,提升模型的收敛速度,且对最终模型的性能有显著影响。本文将以 PyTorch 为例,介绍4种常见的归一化方法,并详细讲解它们的原理和公式。
Layer Norm:层归一化,适用于 RNN 和 Transformer 模型,在每个样本的所有特征维度上进行归一化。
Instance Norm:实例归一化,适用于风格迁移、Gan、图像生成,每个样本的每个通道独立归一化。
Group Norm:群体归一化,适用于视频处理(时序维度替代批次维度),不依赖于批量大小,通过将通道分成多个组进行归一化。
批量归一化(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+β
torch.nn.BatchNorm1d/2d/3d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
参数:
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,简称 LN)不同于批量归一化,它在每一个样本的所有特征维度上进行归一化,而不是在整个批量上进行归一化。该方法通常用于 RNN 和 Transformer 网络中,因为它能够独立地对每一个样本进行归一化,避免了批量归一化对批量大小的依赖。
对于一个样本 x = { x 1 , x 2 , … , x n } x = \{x_1, x_2, \dots, x_n\} x={x1,x2,…,xn}:
公式和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 β 是可学习的参数。
torch.nn.LayerNorm(normalized_shape, eps=1e-05, elementwise_affine=True)
参数:
# 使用 Layer Normalization
model = nn.Sequential(
nn.Linear(128, 64),
nn.LayerNorm(64),
nn.ReLU()
)
实例归一化(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+β
torch.nn.InstanceNorm1d(num_features, eps=1e-05, affine=True, track_running_stats=False)
参数:
# 使用 Instance Normalization
model = nn.Sequential(
nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1),
nn.InstanceNorm2d(64),
nn.ReLU()
)
群体归一化(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+β
torch.nn.GroupNorm(num_groups, num_channels, eps=1e-05, affine=True)
# 使用 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()
)