如何理解数据归一化处理(Normalization)
1. 场景
在学习利用 Tensorflow 构建网络结构时,一般会在每个层计算完成后对结果进行归一化处理(Normalization),让后再将结果传给下一层。例如下面的例子:
G_model = tf.keras.Sequential([
# 第一层
# input: 100 vector
# output: 7x7x256 vector
layers.Dense(7*7*256, use_bias=False, input_shape=(100,)),
# BN (batch normalization)
layers.BatchNormalization(),
# ReLU
layers.LeakyReLU(),
layers.Reshape((7, 7, 256)),
# 第二层
# input:7x7x256 vector
# output:7x7x128 vector
layers.Conv2DTranspose(128, 5, 1, use_bias=False, padding="same"),
# BN
layers.BatchNormalization(),
# ReLU
layers.LeakyReLU(),
# 第三层
# ......
])
那 BatchNormalization() 的具体算法和作用是什么?
2. 为什么要进行归一化处理?
在机器学习领域中,不同评价指标(即特征向量中的不同特征就是所述的不同评价指标)往往具有不同的量纲和量纲单位,这样的情况会影响到数据分析的结果,
为了消除指标之间的量纲影响,需要进行数据标准化处理,以解决数据指标之间的可比性。原始数据经过数据标准化处理后,各指标处于同一数量级,适合进行综合对比评价。其中,最典型的就是数据的归一化处理。 引用连接
在机器学习过程中,会使用包括多个维度的向量来表示研究的对象,但每个维度值的量纲和数据范围可能差别很大。例如,描述对象是房子,其维度包括(价格,年限,经度,纬度…)等,价格维度的值可能是500000元~20000000元,而年限值范围1~50年,位置经度范围值是[-180,180]。为了能消除不同量纲和值域之间的差别,实现不是通过具体数值,而是通过相对特征来标识目标对象各个维度的目的,所以需要引入归一化操作对数据进行处理。
归一化处理最基本的操作就是两点,首先是统一原点位置,从几何上看就是将所有维度值的大小关系都转移成相对原点的大小,即各个维度的中心都拽到原点上;其二,是将所有维度的值从绝对大小变成相对大小,即数值范围是[0,1]或[-1, 1]之间。
通过上面两个步骤,所有不同维度的数值都统一到了用相同量纲和值域范围表示抽象特征的空间中,以便神经网络进行训练和学习。
3. 归一化算法
批量归一化的目的是在神经网络的训练过程中,将每一层的输入或输出数据标准化,使其具有均值为 0、方差为 1 的分布。它能帮助加速模型的收敛、稳定训练过程,并减少梯度消失或梯度爆炸的问题。
具体算法流程:
对于输入一组数据 X ,Batch Normalization 的标准化步骤如下:
-
计算均值:对于每一层的输出(或输入),在当前 mini-batch 中计算每个特征的均值。其中, m 是 mini-batch 的样本数, x i x_i xi 是该批次中第 i 个样本的特征值。
μ B = 1 m ∑ i = 1 m x i \mu_B = \frac{1}{m} \sum_{i=1}^{m} x_i μB=m1i=1∑mxi利用均值进行 x i − μ B x_i - \mu_B xi−μB 计算,就将该维度上所有的值都位移到以 0 为中心的坐标两端,实现原点的统一。
-
计算方差:接下来,计算 mini-batch 中每个特征的方差:
σ 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
方差是各个维度上,每个点距离原点的平均距离,以便后面实现值域的统一。
-
标准化:将输入特征标准化,使其具有零均值和单位方差。其中, ϵ \epsilon ϵ 是一个很小的常数,防止除以 0。
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
执行完标准化后,所有维度的数据值就都转换到 均值为 0、方差为 1 的分布 上。
-
缩放和平移(可学习参数):在归一化后,Batch Normalization 引入了两个可学习的参数 γ \gamma γ 和 β \beta β ,分别用于对标准化后的值进行缩放和平移:
y i = γ x ^ i + β y_i = \gamma \hat{x}_i + \beta yi=γx^i+β
其中, γ \gamma γ 控制缩放, β \beta β 控制平移。这两个参数使得神经网络能够重新获得归一化之前的分布特性,如果这是优化所需的。
4. 例子说明
为了更好地理解 Batch Normalization,我们通过一个简单的例子来演示它的工作流程。假设我们有一个小批次(mini-batch)的数据,批量归一化会按照以下步骤进行标准化。例子说明:
我们有一个 3 个样本组成的 mini-batch,每个样本有 2 个特征,形状为 3 × 2 3 \times 2 3×2。假设我们的输入数据为:
X = [ 1 2 3 4 5 6 ] \mathbf{X} = \begin{bmatrix} 1 & 2 \\ 3 & 4 \\ 5 & 6 \end{bmatrix} X= 135246
假设我们要对每个特征进行批量归一化。Batch Normalization 的步骤:
-
计算每个特征的均值:对于每个特征,我们在 mini-batch 中计算其均值:
μ B = 1 m ∑ i = 1 m x i \mu_B = \frac{1}{m} \sum_{i=1}^{m} x_i μB=m1i=1∑mxi
• 第一列(特征 1)的均值: μ 1 = 1 + 3 + 5 3 = 3 \mu_{1} = \frac{1 + 3 + 5}{3} = 3 μ1=31+3+5=3
• 第二列(特征 2)的均值: μ 2 = 2 + 4 + 6 3 = 4 \mu_{2} = \frac{2 + 4 + 6}{3} = 4 μ2=32+4+6=4所以,均值向量为: μ B = [ 3 4 ] \mu_B = \begin{bmatrix} 3 \\ 4 \end{bmatrix} μB=[34]
-
计算每个特征的方差:接下来,我们计算每个特征在 mini-batch 中的方差:
σ 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• 第一列(特征 1)的方差:
σ 1 2 = ( 1 − 3 ) 2 + ( 3 − 3 ) 2 + ( 5 − 3 ) 2 3 = 4 + 0 + 4 3 = 8 3 ≈ 2.67 \sigma_{1}^2 = \frac{(1 - 3)^2 + (3 - 3)^2 + (5 - 3)^2}{3} = \frac{4 + 0 + 4}{3} = \frac{8}{3} \approx 2.67 σ12=3(1−3)2+(3−3)2+(5−3)2=34+0+4=38≈2.67
• 第二列(特征 2)的方差:
σ 2 2 = ( 2 − 4 ) 2 + ( 4 − 4 ) 2 + ( 6 − 4 ) 2 3 = 4 + 0 + 4 3 = 8 3 ≈ 2.67 \sigma_{2}^2 = \frac{(2 - 4)^2 + (4 - 4)^2 + (6 - 4)^2}{3} = \frac{4 + 0 + 4}{3} = \frac{8}{3} \approx 2.67 σ22=3(2−4)2+(4−4)2+(6−4)2=34+0+4=38≈2.67
所以,方差向量为: σ B 2 = [ 2.67 2.67 ] \sigma_B^2 = \begin{bmatrix} 2.67 \\ 2.67 \end{bmatrix} σB2=[2.672.67]
-
进行标准化:将输入特征标准化,使其具有均值为 0、方差为 1 的分布:
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 ϵ 是一个很小的常数(如 1 0 − 7 10^{-7} 10−7),用于防止除以零。假设 ϵ = 0 \epsilon = 0 ϵ=0 ,我们继续计算:
• 第一列的标准化:
x ^ 1 = 1 − 3 2.67 = − 2 1.63 ≈ − 1.23 , 3 − 3 2.67 = 0 , 5 − 3 2.67 = 2 1.63 ≈ 1.23 \hat{x}_{1} = \frac{1 - 3}{\sqrt{2.67}} = \frac{-2}{1.63} \approx -1.23, \quad \frac{3 - 3}{\sqrt{2.67}} = 0, \quad \frac{5 - 3}{\sqrt{2.67}} = \frac{2}{1.63} \approx 1.23 x^1=2.671−3=1.63−2≈−1.23,2.673−3=0,2.675−3=1.632≈1.23
• 第二列的标准化:
x ^ 2 = 2 − 4 2.67 = − 2 1.63 ≈ − 1.23 , 4 − 4 2.67 = 0 , 6 − 4 2.67 = 2 1.63 ≈ 1.23 \hat{x}_{2} = \frac{2 - 4}{\sqrt{2.67}} = \frac{-2}{1.63} \approx -1.23, \quad \frac{4 - 4}{\sqrt{2.67}} = 0, \quad \frac{6 - 4}{\sqrt{2.67}} = \frac{2}{1.63} \approx 1.23 x^2=2.672−4=1.63−2≈−1.23,2.674−4=0,2.676−4=1.632≈1.23
标准化后的结果:
X ^ = [ − 1.23 − 1.23 0 0 1.23 1.23 ] \hat{\mathbf{X}} = \begin{bmatrix} -1.23 & -1.23 \\ 0 & 0 \\ 1.23 & 1.23 \end{bmatrix} X^= −1.2301.23−1.2301.23 -
缩放和平移(可选):接着,Batch Normalization 会引入两个可学习的参数 \gamma 和 \beta 对标准化后的值进行缩放和平移:
y i = γ x ^ i + β y_i = \gamma \hat{x}_i + \beta yi=γx^i+β
• 如果 γ = 1 \gamma = 1 γ=1 且 β = 0 \beta = 0 β=0 (默认初始化),则保持原样不变。
• 如果 γ \gamma γ 和 β \beta β 有其他值,它们会调整数据的分布。例如,若 γ = 2 \gamma = 2 γ=2 且 β = 1 \beta = 1 β=1 ,则: y i = 2 x ^ i + 1 y_i = 2 \hat{x}_i + 1 yi=2x^i+1
最终输出为:
y = [ 2 × ( − 1.23 ) + 1 2 × ( − 1.23 ) + 1 2 × 0 + 1 2 × 0 + 1 2 × 1.23 + 1 2 × 1.23 + 1 ] = [ − 1.46 − 1.46 1 1 3.46 3.46 ] y = \begin{bmatrix} 2 \times (-1.23) + 1 & 2 \times (-1.23) + 1 \\ 2 \times 0 + 1 & 2 \times 0 + 1 \\ 2 \times 1.23 + 1 & 2 \times 1.23 + 1 \end{bmatrix} = \begin{bmatrix} -1.46 & -1.46 \\ 1 & 1 \\ 3.46 & 3.46 \end{bmatrix} y= 2×(−1.23)+12×0+12×1.23+12×(−1.23)+12×0+12×1.23+1 = −1.4613.46−1.4613.46
5. 作用和优势:
-
稳定模型训练:通过对每一层的输入进行标准化,Batch Normalization 减少了输入数据的偏移和尺度变化,使得模型训练更加稳定。神经网络的训练过程中,输入数据和每一层的激活输出会随着深度增加而发生变化。这种变化有时会导致网络内部的激活值分布不稳定,使得训练变得困难。归一化通过调整数据的分布,使得每层输出保持在一个稳定的范围内,避免数据分布的剧烈变化。
- 如果数据在网络传递时发生显著变化,后续层的梯度可能变得极小(梯度消失问题),或是极大(梯度爆炸问题),导致训练难以进行。
- 归一化使得每层的输入保持在一个更可控的范围内,保证网络的训练更加平稳和高效。
-
防止梯度消失或梯度爆炸:在深层神经网络中,梯度消失和梯度爆炸是两个常见问题,尤其是在使用梯度下降优化的过程中。这两个问题会导致模型无法有效更新权重,训练失败。标准化后的输入使得模型在反向传播时,梯度的变化不会因为输入数据的大小或分布问题而导致梯度消失或梯度爆炸问题。
- 归一化保证了数据的尺度在合理范围内,使得梯度的变化更加平滑,不会过大或过小,避免了梯度消失和爆炸的情况。
- 通过归一化,网络每层的输入输出都保持在一个相对一致的尺度上,这让反向传播过程中的梯度更新更加稳定。
-
加速模型收敛:归一化有助于提升网络的收敛速度,减少训练所需的迭代次数。通过将数据标准化为均值为 0、方差为 1 的分布,归一化减少了输入数据的偏移和缩放效应,减小了神经网络对初始权重选择的依赖。Batch Normalization 能够让模型更快地接近最优解,减少训练时间,进而提高模型的收敛速度。
- 当输入数据经过归一化后,网络的激活函数(如 ReLU、Sigmoid)可以更快地收敛到最优解,从而减少训练时间。
- 不需要对学习率做过多调整,归一化让模型能够在较大的学习率下稳定地训练。
更形象化的理解可以参考文章:机器学习笔记:为什么要对数据进行归一化处理
-
减少对初始化的依赖:在没有归一化的网络中,权重的初始化会对训练结果产生很大的影响。权重初始化不当可能导致网络无法训练或者需要调整复杂的超参数。在有 Batch Normalization 的情况下,模型对参数的初始值变得不那么敏感,这降低了模型初始化的复杂度。
- 归一化减少了模型对初始权重选择的敏感性,使得即使使用较简单的权重初始化策略,网络也能够有效训练。
- 因为归一化会对每层的输出进行调整,即使初始权重值有所偏差,归一化层也能够纠正这些偏差。
-
减少过拟合: 虽然归一化并不是直接的正则化方法,但它间接地可以帮助减少过拟合。在 Batch Normalization 的过程中,每个 mini-batch 的归一化操作引入了一定的噪声,这在一定程度上类似于正则化,能够减少模型过拟合。
- 每次训练时 mini-batch 之间的差异会导致网络输入数据的细微变化,从而给模型带来一定的正则化效果,防止模型过度拟合训练数据。
-
使激活函数更有效: 激活函数(如 ReLU、Sigmoid 等)通常对输入数据的范围有较强的依赖。例如,ReLU 函数在负值部分会直接输出 0,而 Sigmoid 函数在非常大的或非常小的输入时会饱和。归一化可以让输入保持在激活函数的有效工作区间,从而增强激活函数的效果。
- 归一化使得数据输入范围在每一层保持适中,避免过大的输入使得激活函数进入饱和区域,提升激活函数的工作效率。