为什么要归一化
问题
-
量纲差异:不同特征的单位或数值范围差异大(如年龄0-100,收入0-100000),导致模型偏向学习数值大的特征,导致梯度不平衡,导致梯度爆炸,要将尺度减少到能处理的范围,需要使不同特征对模型的影响权重一致。
-
梯度不稳定:未经归一化的数据会导致损失函数的等高线呈“狭长形”,梯度下降方向震荡,收敛缓慢(如下图示)。
-
激活函数饱和:如Sigmoid在输入绝对值较大时梯度接近0,导致参数更新停滞。
解决
- 加速收敛:使优化路径更平缓,减少迭代次数,优化算法(如梯度下降)在归一化后的数据上更易找到最优解。
- 提升模型泛化能力:避免某些特征主导学习过程。
- 兼容正则化:L1/L2正则化对尺度敏感,归一化后惩罚项更公平。
- 防止数值溢出:避免计算过程中出现极大或极小值导致的计算错误。
数学定义
归一化是对原始数据进行线性或非线性变换,使其符合特定分布或数值范围。
xnorm=缩放因子x−基准值
主要方法:
标准化(Z-Score Normalization)
xnorm=σx−μ其中{μ=n1∑i=1nxiσ=n1∑i=1n(xi−μ)2
-
-
效果:数据分布均值为0,标准差为1(适合大多数场景)。
-
适用场景:特征分布近似正态分布,或存在异常值。
-
优点:对异常值不敏感(因标准差考虑了数据离散程度)。
-
缺点:若数据存在显著偏态(如长尾分布),可能仍需其他处理。
最小-最大归一化(Min-Max Scaling)
xscaled=xmax−xminx−xmin或xscaled∈[a,b]=a+xmax−xmin(x−xmin)(b−a)
鲁棒归一化(Robust Scaling)
xrobust=IQRx−median其中{median=数据中位数IQR=Q3−Q1(75%分位数−25%分位数)
- 效果
- 以中位数为基准,缩放因子为IQR,减少异常值影响。
- 输出数据范围不固定,但分布更鲁棒。
- 适用场景
- 数据存在显著异常值或长尾分布(如收入数据)。
- 需要保留数据分布形态但避免异常值干扰。
- 优点:抗异常值能力强。
- 缺点:输出范围不固定,可能需后续处理。
**批归一化(Batch Normalization)**最常使用
y=γ⋅σB2+ϵx−μB+β其中⎩⎨⎧μB=m1∑i=1mxi(mini-batch均值)σB2=m1∑i=1m(xi−μB)2(mini-batch方差)γ,β:可学习的缩放与偏移参数ϵ:防除零小常数(如10−5)
-
作用
- 加速训练:允许使用更大的学习率,收敛速度提升数倍。
- 缓解梯度问题:通过稳定数据分布,减轻梯度消失/爆炸。
- 降低过拟合:轻微的正则化效果(因mini-batch引入噪声)。
- 减少对初始化的敏感度:网络对权重初值的选择更鲁棒。
-
位置:通常在全连接层或卷积层后、激活函数前使用。
-
BN的局限性:
- 依赖Batch Size:极小batch下效果差,可考虑Group Normalization替代。
- 序列模型中的挑战:RNN/Temporal CNN需特殊设计(如沿时间步累积统计量)。
- 推理-训练差异:移动平均可能引入轻微偏差。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| //输入 → 卷积层 → BN层 → ReLU → 输出 import torch.nn as nn
class ConvBlock(nn.Module): def __init__(self, in_channels, out_channels): super().__init__() self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1) self.bn = nn.BatchNorm2d(out_channels) self.relu = nn.ReLU()
def forward(self, x): x = self.conv(x) x = self.bn(x) x = self.relu(x) return x
|
Batch Normalization (“batch norm”) explained”)