趋近智
批标准化(BatchNorm或BN)是一种强大的技术,旨在改进深度神经网络 (neural network)的训练。它解决了一个可能阻碍深度网络训练的常见问题:随着训练的进行,中间层激活值分布的变化。通过稳定这些分布,BatchNorm通常能带来更快的收敛,允许使用更高的学习率,甚至能提供有益的正则化 (regularization)作用。
设想训练一个深度网络。随着早期层中的权重 (weight)通过梯度下降 (gradient descent)进行更新,这些层的输出(它们成为后续层的输入)会发生变化。这些输入的分布(均值和方差)在训练期间会显著偏移。这种现象被原始BatchNorm论文的作者称为内部协变量偏移。他们认为,迫使后续层持续适应这些变化的分布会减慢训练速度,很像试图击中一个移动的目标。
尽管内部协变量偏移是BatchNorm有效性的唯一原因尚有争议,但其实际好处显而易见。BatchNorm似乎能使优化过程更平稳,防止梯度变得过大或过小,并降低对细致权重初始化的依赖。
BatchNorm在激活函数 (activation function)作用之前对前一层的输出进行标准化。重要的是,这种标准化是在训练期间按小批量进行的。对于给定层和一小批数据,BatchNorm执行以下步骤:
计算小批量均值: 计算小批量中每个特征/通道的激活值均值。设小批量为 ,其中 是批次中第 个样本的特定神经元的激活值。均值 为:
计算小批量方差: 计算小批量中每个特征/通道的激活值方差。方差 为:
标准化: 使用小批量均值和方差标准化每个激活值 。为了数值稳定性(避免除以零),方差中添加了一个小常数 (epsilon)。
经过此步骤后,小批量内的激活值 在每个特征维度上将近似具有零均值和单位方差。
缩放与偏移: 仅仅标准化可能会限制层的表示能力。例如,如果后面跟着Sigmoid激活函数,强制其输入具有零均值和单位方差会将其限制在其线性区域。为克服这一点,BatchNorm为每个特征/通道引入了两个可学习参数 (parameter):一个缩放参数 (gamma) 和一个偏移参数 (beta)。这些参数使得网络能够为标准化后的激活值学习出最佳的缩放和偏移量:
网络在反向传播 (backpropagation)过程中学习 和 ,就像学习网络权重 (weight)一样。如果最佳变换是恒等变换,网络可以学习 和 。通常,它会学习有助于优化过程的值。
Batch Normalization层在训练期间对单个特征维度小批量数据的操作流程。计算均值 () 和方差 (),激活值 () 被标准化 (),最后进行缩放 () 和偏移 () 以生成输出 ()。
在推断阶段(训练后对新数据进行预测时),我们可能逐个处理样本,或者批次大小可能不同。我们不能依赖于对可能不存在或大小不同的批次计算统计量。相反,我们使用固定的总体统计量。
在训练期间,框架通常会跟踪所有小批量中遇到的均值和方差的运行估计(移动平均值)。设这些值为 和 。在推断时,这些固定值用于标准化:
可学习参数 (parameter) 和 会按照训练期间确定的值使用:
这确保了推断时的输出是确定性的。
为何要这样做?BatchNorm通常会带来显著的优势:
BatchNorm层通常插入在线性层或卷积层及其后续激活函数 (activation function)之间。
BatchNorm1d(标准化发生在每个特征的批次维度上)。BatchNorm2d(标准化发生在每个通道的批次、高度和宽度维度上)。以下是如何在PyTorch中向简单的层序列添加 BatchNorm1d 的例子:
import torch
import torch.nn as nn
# 示例维度
input_features = 128
hidden_units = 64
output_features = 10
model = nn.Sequential(
nn.Linear(input_features, hidden_units),
# 在激活函数前应用BatchNorm
nn.BatchNorm1d(hidden_units),
nn.ReLU(),
nn.Linear(hidden_units, output_features)
# 通常在最终输出层前不使用BatchNorm,
# 特别是如果后面使用Softmax或Sigmoid等激活函数。
)
# 使用随机数据进行前向传播示例(批大小 = 32)
dummy_input = torch.randn(32, input_features)
output = model(dummy_input)
print(f"Model Output Shape: {output.shape}")
# 预期输出形状:torch.Size([32, 10])
# 打印模型结构以查看层
print(model)
# 预期输出:
# Sequential(
# (0): Linear(in_features=128, out_features=64, bias=True)
# (1): BatchNorm1d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
# (2): ReLU()
# (3): Linear(in_features=64, out_features=10, bias=True)
# )
在此PyTorch示例中,nn.BatchNorm1d(hidden_units) 添加在第一个线性层之后。请注意,num_features 参数 (parameter)对应于前一层输出的数量。affine=True 参数表示应包含可学习的 和 参数(这是默认设置)。track_running_stats=True 确保维护均值和方差的移动平均值,这对于评估/推断期间(model.eval())的正确行为至关重要。
尽管BatchNorm引入了计算统计量和应用变换的额外计算,但这种开销通常可以通过其提供的更快的收敛和更高的稳定性得到充分补偿,使其成为许多现代深度学习 (deep learning)架构中的标准组成部分。
这部分内容有帮助吗?
© 2026 ApX Machine LearningAI伦理与透明度•