跳至主要内容

批归一化:原理与 TensorFlow 实现

批归一化对小批次输入进行标准化,以稳定并加速神经网络训练。
· 15分钟 阅读

使用 AI 探索

训练深层神经网络常常面临梯度消失或爆炸以及内部协变量偏移等挑战。这些因素会显著放慢训练速度,并削弱网络的有效学习能力。所幸,我们可以通过归一化技术来应对这些问题。

在众多归一化方法中,批归一化最为流行,已成为许多深度学习架构中的标准组件。它有助于更快收敛、提升训练稳定性,并改善泛化表现。

在本教程中,我们将解释批归一化的概念、其数学工作机制,以及如何使用 TensorFlow 和 Keras 实现它。

如果您想用 Keras 学习神经网络基础,请查看这门课程:Python 深度学习入门。

什么是机器学习中的归一化?

归一化是机器学习中一个关键的预处理步骤,旨在对输入数据进行标准化。

常见的归一化技术包括最小-最大缩放、z 分数标准化以及对数变换等,通常用于将特征重新缩放到一致的范围或分布。这些方法有助于减轻离群值的影响、改善收敛,并确保特征之间的公平比较。

对输入数据进行归一化对于有效训练模型至关重要,因为它能确保所有特征对学习过程的贡献相当。若不做归一化,尺度或方差较大的特征可能主导优化过程,从而导致模型表现不佳。

归一化通过将所有特征带到相近的尺度,使模型能够从数据中学习有意义的模式和关系。

若想总体了解归一化,请查看这篇教程:机器学习中的归一化是什么。

深度学习训练的挑战

训练深层神经网络会遇到多种挑战,可能阻碍收敛与泛化:

  1. 内部协变量偏移:当输入数据经过多层传递时,激活分布会发生变化,使模型难以适应并高效学习。
  2. 梯度消失与爆炸:深层网络在反向传播中可能出现梯度过小或过大,导致无法有效更新权重。
  3. 对初始化敏感:网络的初始权重会显著影响训练过程,不良初始化可能导致收敛缓慢甚至训练失败。

批归一化通过在每个小批次内对激活进行归一化来应对这些挑战,从而帮助稳定训练过程并提升模型表现。

什么是批归一化?

批归一化是一种在深度神经网络训练中,对小批次内某一层的激活进行归一化的技术。

其做法是为小批次中每个特征计算激活的均值和方差,然后利用这些统计量对激活进行归一化。

随后,通过可学习参数对归一化后的激活进行缩放和平移,使模型能够适应最优的激活分布。

batch normalization
AI

来源:Yintai Ma 和 Diego Klabjan。

批归一化通常在层的线性变换之后(例如,全连接层中的矩阵乘法或卷积层中的卷积操作之后)、非线性激活函数(如 ReLU)之前应用。

批归一化的关键组成包括:

  1. 小批次统计量:对小批次中每个特征的激活计算均值与方差。
  2. 归一化:用小批次的均值进行中心化,并除以小批次的标准差来归一化激活。
  3. 缩放与平移:引入可学习参数(γ 与 β)对归一化后的激活进行缩放和平移,使模型能够学习到最优的激活分布。

为什么要使用批归一化?

训练深层神经网络时,我们面临的挑战之一是内部协变量偏移。随着前面各层权重不断更新,某一层的激活(输出)分布在训练过程中会发生变化。这样的偏移会让训练变得困难且缓慢。

批归一化通过在每个小批次内对激活进行归一化,降低了这种偏移,使后续层的输入更稳定、更一致。

激活归一化使得使用更大学习率也能更快收敛,并降低了模型对初始化选择的敏感性。

此外,它带来一定的正则化效应,通过减少模型对特定激活模式的依赖来防止过拟合。

这些优势的结合使批归一化成为训练更稳健深度学习模型的有力工具。若想进一步了解如何构建稳健模型,请查看这门课程:机器学习监控概念。

批归一化背后的数学

既然我们已经理解了批归一化的“为何”,接下来看看它的“如何”。

批归一化在训练阶段与推理阶段的工作方式不同,下面分别说明各阶段的数学细节。

训练阶段的批归一化

先从归一化步骤开始。我们首先为小批次中每个特征计算均值与方差。以下是计算均值与方差的公式。

随后使用均值与方差对激活进行归一化。可用下式,其中 ε(小写 epsilon)是为数值稳定性而加入的微小常数:

完成归一化后,进入缩放与平移步骤。利用可学习参数 γ 与 β,我们按以下公式对归一化后的激活进行平移(与缩放):

这些参数使模型能够学习到最优的激活分布。

推理阶段的批归一化

在推理阶段,我们用训练期间计算得到的运行统计量(均值与方差)替代批统计量。运行统计量通常通过带动量因子的滑动平均进行更新。

计算运行均值与方差可使用以下两个公式,其中 α 为动量因子,用于控制运行统计量的更新速率:

运行均值与方差会作为模型参数存储,并在推理时用于归一化。训练期间学得的缩放与平移参数(γ 与 β)也会在推理时使用。

接下来,让我们学习如何使用 TensorFlow 实现批归一化。

TensorFlow 中的批归一化

先导入所需的库:

import tensorflow as tf 
from tensorflow import keras

接着加载 MNIST 数据集,该数据集包含 60,000 张训练图像与 10,000 张手写数字测试图像。我们使用 keras.datasets.mnist.load_data() 函数加载数据集,并将其拆分为训练数据 (x_train, y_train) 与测试数据 (x_test, y_test):

# Load the MNIST dataset
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()

为预处理数据,我们执行以下步骤:

  • 将训练与测试图像重塑为 (num_samples, 28, 28, 1) 的形状,其中 num_samples 为图像数量,每张图像是 28x28 的单通道灰度图。
  • 将像素值除以 255.0,把数值缩放到 0 到 1 之间。
  • 使用 keras.utils.to_categorical() 将训练与测试标签转换为分类格式,即将整数标签转换为独热编码向量。
# Preprocess the data
x_train = x_train.reshape((60000, 28, 28, 1)) / 255.0  # Reshape and normalize training images
x_test = x_test.reshape((10000, 28, 28, 1)) / 255.0    # Reshape and normalize test images
y_train = keras.utils.to_categorical(y_train)         # Convert training labels to categorical format
y_test = keras.utils.to_categorical(y_test)           # Convert test labels to categorical format

现在进入下一步:定义模型架构。我们将执行以下步骤:

  • 使用 keras.Sequential API 定义模型架构,该 API 允许按顺序堆叠各层。
  • 模型由用于特征提取的卷积层(Conv2D)组成,之后接批归一化层(BatchNormalization)对激活进行归一化。
  • 使用最大池化(MaxPooling2D)对特征图进行下采样。
  • 在传入全连接层之前对特征图进行展平(Flatten)。
  • 最后的全连接层含 10 个单元并使用 softmax 激活,对应 10 个数字类别。
# Define the model architecture
model = keras.Sequential([
    keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
    keras.layers.BatchNormalization(),
    keras.layers.Conv2D(64, (3, 3), activation='relu'),
    keras.layers.BatchNormalization(),
    keras.layers.MaxPooling2D((2, 2)),
    keras.layers.Flatten(),
    keras.layers.Dense(128, activation='relu'),
    keras.layers.BatchNormalization(),
    keras.layers.Dense(10, activation='softmax')
])

接下来使用 .compile() 方法编译模型,指定优化器、损失函数与评估指标。我们将使用:

  • Adam 优化器('adam')。
  • 分类交叉熵损失('categorical_crossentropy'),因为这是一个多类别分类任务。
  • 准确率('accuracy')作为评估指标来衡量模型表现。
# Compile the model
model.compile(optimizer='adam',
              loss='categorical_crossentropy',
              metrics=['accuracy'])

接着使用 .fit() 方法训练模型:

  • 指定训练数据 (x_train, y_train)、批大小、训练轮数(epochs)以及验证数据 (x_test, y_test)。
  • batch_size 决定每次梯度更新所用的样本数。
  • epochs 指定模型遍历整个训练数据的次数。
  • 验证数据用于在训练过程中评估模型在未见数据上的表现。
# Train the model
model.fit(x_train, y_train, batch_size=128, epochs=5, validation_data=(x_test, y_test))

按上述步骤并在模型架构中加入批归一化层,我们可以在 MNIST 数据集上高效训练模型,受益于激活归一化与更稳定的训练过程。

既然已经了解了批归一化及其实现方法,让我们来看看它带来的好处。

实现注意事项

现在更深入地探讨在深度学习架构中实现批归一化的实践要点。

在神经网络中的放置位置

将批归一化层策略性地放置在网络中最为有效。通常,其位于线性变换之后(如卷积或全连接层)与非线性激活函数之前。

在卷积网络中,这意味着把批归一化放在每个卷积层之后、激活函数之前。

同样地,在全连接网络中,常见做法是在每个隐藏层的线性变换之后、激活函数之前加入批归一化。

批归一化层的放置会影响模型的性能与训练动态。为特定网络架构找到最优配置可能需要一定实验。

批大小的影响

训练时使用的批大小会影响批归一化的效果。更大的批大小能够更准确地估计批统计量(均值与方差),从而带来更好的归一化与更稳定的训练。

但增大批大小也会提升内存消耗与计算需求,是否可行取决于可用的硬件资源。

在确保批统计量足够可靠的同时,需要在批大小与计算可行性之间取得平衡。

正则化效应及其影响

由于小批次统计量带来的噪声,批归一化天然具有一定的正则化效应。由批统计量引入的随机性起到了正则化的作用,可减少过拟合并提升泛化。

然而,这种正则化效应可能会与其他正则化技术(如 dropout 或 L2 正则化)相互作用。

使用批归一化时,需要权衡不同正则化方法之间的配合,适当调整以避免过度正则化或性能下降。

通过实验并监测模型在验证集上的表现,有助于在使用批归一化时找到合适的正则化平衡。

批归一化的局限与挑战

尽管批归一化非常有用,但仍存在一些需要注意的局限与挑战。

在非卷积架构中的批归一化

批归一化最初为卷积神经网络(CNN)设计,并在该领域尤为成功。

然而,在非卷积架构(如循环神经网络 RNN 或 Transformer)中的效果可能受限。

RNN 的序列特性与 Transformer 的注意力机制会使批归一化的应用更为棘手。

对于这些架构,层归一化或实例归一化等替代方法可能更为合适。

小批大小与推理阶段表现

批归一化依赖训练期间计算的批统计量来归一化激活。当批大小较小时,批统计量可能不够可靠,给归一化过程引入噪声或不稳定性。

这可能导致次优表现,甚至带来训练困难,尤其是在受内存限制而缩小批大小的情况下。

在推理阶段,批归一化使用训练期间得到的运行统计量,而这可能无法准确代表单个样本或小批次的统计特性。由此带来的训练与推理分布不匹配,可能影响模型表现。

批归一化的缺点与权衡

在训练期间,批归一化需要计算批统计量并执行归一化操作,会引入额外的计算开销。对于大模型或大数据集,这会增加内存需求与训练时间。

对于某些数据类型或任务,归一化过程可能会扭曲重要信息或抹除有意义的变化,从而使批归一化并不适用。

例如,在涉及细粒度细节或精确空间信息的任务(如分割或定位)中,批归一化可能产生不利影响。

批归一化带来的正则化效应有时会与其他正则化技术(如 dropout)以意想不到的方式相互作用,需要仔细调参与权衡。

如何缓解批归一化的局限

尽管存在局限与挑战,批归一化仍是深度学习中广泛使用且行之有效的技术。研究者与从业者持续探索应对这些问题、改进原始方法的途径。

以下是缓解批归一化局限的几种思路:

  • 自适应批归一化:根据每个样本的特定特征来调整批统计量,有助于缓解小批大小带来的问题。
  • 虚拟批归一化:使用包含多个批次样本的“虚拟批”来计算归一化统计量,从而提升归一化过程的稳定性与可靠性。
  • 混合归一化技术:将批归一化与其他方法(如层归一化或实例归一化)结合,帮助解决特定架构或任务下的局限。

批归一化的变体与扩展

下面介绍一些批归一化的变体与扩展,也可用于缓解批归一化可能带来的挑战。

层归一化

层归一化在层内跨所有通道的激活上进行操作,而非沿批维度归一化。

它基于为批中每个独立样本计算的均值与方差来归一化激活。

层归一化对循环神经网络(RNN)以及批大小较小或可变的场景尤其有用。

组归一化

组归一化将通道划分为若干组,并在每组内计算归一化统计量。

它在层归一化与批归一化之间取得平衡,通过对通道子集进行联合归一化来实现。

在批大小受限的情形(如内存受限环境或处理高分辨率图像时),组归一化效果良好。

实例归一化

实例归一化对批中每个样本的每个通道分别进行归一化。

它常用于风格迁移与图像生成任务,其目标是在保留风格信息的同时归一化内容。

在这类应用中,实例归一化已被证明能提升生成图像的质量与稳定性。

批重归一化

批重归一化通过在归一化过程中引入额外纠正项来扩展批归一化。

其目标是缓解批统计量与总体统计量之间的不一致,尤其是在批大小较小时。

批重归一化有助于稳定训练并提升模型的泛化能力,特别是在批大小受限的场景中。

权重归一化

权重归一化通过重新参数化神经网络的权重,将权重的幅度与方向解耦。

它通过用权重的欧几里得范数对权重进行归一化,并引入可学习的缩放参数来实现。

权重归一化可以与批归一化配合使用,或作为一种替代的归一化方法。

在某些情形下,它被证明能改善优化问题的条件数,并加速收敛。

这些批归一化的变体与扩展为应对特定挑战、改进深度学习模型的训练与性能提供了更多工具与方法。每种变体各有优势与考量,选择哪一种取决于任务需求、模型架构以及可用计算资源。

结论

批归一化已成为深度学习中的关键技术,为训练深层神经网络带来了显著益处。

通过在小批次内归一化激活,我们可以缓解内部协变量偏移、改善收敛并增强泛化。作为初入行或成长中的数据从业者,请牢记以下要点:

  • 在深度学习模型中引入批归一化层,以提升训练稳定性与性能。
  • 尝试不同的批归一化放置位置,并监测其对模型表现的影响。
  • 持续关注归一化技术的最新研究与进展,以便在项目中采用最有效的方法。

如果您希望成为机器学习工程师,可参考这个包含 12 门课程的职业路径:机器学习工程师。

作者

Rajesh Kumar

我是一名数据科学内容写作者,热衷于创作与 AI/ML/DS 相关的内容。我也会探索新的 AI 工具并撰写相关文章。

主题