为什么要归一化

问题

  • 量纲差异:不同特征的单位或数值范围差异大(如年龄0-100,收入0-100000),导致模型偏向学习数值大的特征,导致梯度不平衡,导致梯度爆炸,要将尺度减少到能处理的范围,需要使不同特征对模型的影响权重一致。

  • 梯度不稳定:未经归一化的数据会导致损失函数的等高线呈“狭长形”,梯度下降方向震荡,收敛缓慢(如下图示)。

  • 激活函数饱和:如Sigmoid在输入绝对值较大时梯度接近0,导致参数更新停滞。

解决

  • 加速收敛:使优化路径更平缓,减少迭代次数,优化算法(如梯度下降)在归一化后的数据上更易找到最优解。
  • 提升模型泛化能力:避免某些特征主导学习过程。
  • 兼容正则化:L1/L2正则化对尺度敏感,归一化后惩罚项更公平。
  • 防止数值溢出:避免计算过程中出现极大或极小值导致的计算错误。

数学定义

归一化是对原始数据进行线性或非线性变换,使其符合特定分布或数值范围。

xnorm=x基准值缩放因子x_{\text{norm}} = \frac{x - \text{基准值}}{\text{缩放因子}}

  • 基准值:如均值、最小值、中位数等。

  • 缩放因子:如标准差、极差(最大值-最小值)、四分位距等。

主要方法:

标准化(Z-Score Normalization)

xnorm=xμσ其中{μ=1ni=1nxiσ=1ni=1n(xiμ)2x_{\text{norm}} = \frac{x - \mu}{\sigma} \quad \text{其中} \quad \begin{cases} \mu = \frac{1}{n}\sum_{i=1}^n x_i \\ \sigma = \sqrt{\frac{1}{n}\sum_{i=1}^n (x_i - \mu)^2} \end{cases}

    • μ:数据均值
    • σ:数据标准差
  • 效果:数据分布均值为0,标准差为1(适合大多数场景)。

  • 适用场景:特征分布近似正态分布,或存在异常值。

  • 优点:对异常值不敏感(因标准差考虑了数据离散程度)。

  • 缺点:若数据存在显著偏态(如长尾分布),可能仍需其他处理。

最小-最大归一化(Min-Max Scaling)

xscaled=xxminxmaxxminxscaled[a,b]=a+(xxmin)(ba)xmaxxminx_{\text{scaled}} = \frac{x - x_{\min}}{x_{\max} - x_{\min}} \quad \text{或} \quad x_{\text{scaled}} \in [a,b] = a + \frac{(x - x_{\min})(b - a)}{x_{\max} - x_{\min}}

  • 可自定义输出范围,如将结果映射到[0,1]或[-1,1]。

  • 数据严格限定在固定区间内。

  • 若存在异常值,会导致大部分数据压缩在狭窄范围内。

  • 适用场景

    • 特征边界明确(如图像像素值固定为0-255)。
    • 无显著异常值的均匀分布数据。
  • 优点:直观易解释。

  • 缺点:对异常值敏感(一个极端值会压缩其他数据)。

鲁棒归一化(Robust Scaling)

xrobust=xmedianIQR其中{median=数据中位数IQR=Q3Q1(75%分位数25%分位数)x_{\text{robust}} = \frac{x - \text{median}}{IQR} \quad \text{其中} \quad \begin{cases} \text{median} = \text{数据中位数} \\ IQR = Q_3 - Q_1 \quad (75\% \text{分位数} - 25\% \text{分位数}) \end{cases}

  • 效果
    • 以中位数为基准,缩放因子为IQR,减少异常值影响。
    • 输出数据范围不固定,但分布更鲁棒。
  • 适用场景
    • 数据存在显著异常值或长尾分布(如收入数据)。
    • 需要保留数据分布形态但避免异常值干扰。
  • 优点:抗异常值能力强。
  • 缺点:输出范围不固定,可能需后续处理。

**批归一化(Batch Normalization)**最常使用

y=γxμBσB2+ϵ+β其中{μB=1mi=1mxi(mini-batch均值)σB2=1mi=1m(xiμB)2(mini-batch方差)γ,β:可学习的缩放与偏移参数ϵ:防除零小常数(如105y = \gamma \cdot \frac{x - \mu_B}{\sqrt{\sigma_B^2 + \epsilon}} + \beta \quad \text{其中} \quad \begin{cases} \mu_B = \frac{1}{m}\sum_{i=1}^m x_i \quad (\text{mini-batch均值}) \\ \sigma_B^2 = \frac{1}{m}\sum_{i=1}^m (x_i - \mu_B)^2 \quad (\text{mini-batch方差}) \\ \gamma, \beta: \text{可学习的缩放与偏移参数} \\ \epsilon: \text{防除零小常数(如} 10^{-5}\text{)} \end{cases}

  • 作用

    • 加速训练:允许使用更大的学习率,收敛速度提升数倍。
    • 缓解梯度问题:通过稳定数据分布,减轻梯度消失/爆炸。
    • 降低过拟合:轻微的正则化效果(因mini-batch引入噪声)。
    • 减少对初始化的敏感度:网络对权重初值的选择更鲁棒。
  • 位置:通常在全连接层或卷积层后、激活函数前使用。

  • BN的局限性

    1. 依赖Batch Size:极小batch下效果差,可考虑Group Normalization替代。
    2. 序列模型中的挑战:RNN/Temporal CNN需特殊设计(如沿时间步累积统计量)。
    3. 推理-训练差异:移动平均可能引入轻微偏差。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//输入 → 卷积层 → BN层 → ReLU → 输出
import torch.nn as nn

# 定义带有BN的卷积块
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) # BN层
self.relu = nn.ReLU()

def forward(self, x):
x = self.conv(x)
x = self.bn(x) # 在激活函数前应用BN
x = self.relu(x)
return x

Batch Normalization (“batch norm”) explained”)