内部协变量漂移描述了训练期间层输入分布的变化,这会阻碍学习过程。批量归一化(BN)旨在通过对每个小批次的层输入进行归一化来减轻此问题。前向传播过程中这种归一化的计算方法将被分析。其主要思路是获取给定小批次中到达批量归一化层的激活值,并对其进行转换,使其具有近似零均值和单位方差。这种标准化对于每个特征或通道都是独立进行的。然而,简单地强制零均值和单位方差可能会限制层的表示能力。因此,BN 为每个特征引入了两个可学习的参数,$ \gamma $(伽马)和 $ \beta $(贝塔),它们允许网络对归一化后的值进行缩放和平移。这表示网络可以学习 下一 层的输入的最佳缩放和均值。考虑一个包含激活值的小批次 $ \mathcal{B} = {x_1, x_2, ..., x_m} $,用于特定特征(例如,小批次中 $ m $ 个不同示例的单个神经元的输出)。批量归一化前向传播包含以下步骤:计算小批次均值($ \mu_{\mathcal{B}} $): 计算该特征在小批次中的激活值平均值。 $$ \mu_{\mathcal{B}} = \frac{1}{m} \sum_{i=1}^{m} x_i $$计算小批次方差($ \sigma^2_{\mathcal{B}} $): 计算该特征在小批次中的激活值方差。 $$ \sigma^2_{\mathcal{B}} = \frac{1}{m} \sum_{i=1}^{m} (x_i - \mu_{\mathcal{B}})^2 $$归一化($ \hat{x}_i $): 使用计算出的均值和方差归一化小批次中的每个激活值 $ x_i $。在方差的平方根内添加一个小的常数 $ \epsilon $(伊普西隆,例如 $ 1e-5 $)以确保数值稳定性,防止方差非常小时出现除以零的情况。 $$ \hat{x}i = \frac{x_i - \mu{\mathcal{B}}}{\sqrt{\sigma^2_{\mathcal{B}} + \epsilon}} $$ 此步骤后,小批次的归一化激活值 $ \hat{x}_i $ 将具有接近 0 的均值和接近 1 的方差。缩放和平移($ y_i $): 使用可学习的参数 $ \gamma $ 和 $ \beta $ 转换归一化的激活值 $ \hat{x}_i $。这些参数会进行初始化(通常分别设为 1 和 0),并在反向传播期间像其他网络权重一样进行更新。 $$ y_i = \gamma \hat{x}_i + \beta $$ 输出 $ y_i $ 是批量归一化层针对输入激活值 $ x_i $ 的最终结果,它会被传递到后续层(通常后接非线性激活函数)。digraph G { rankdir=LR; node [shape=box, style=rounded, fontname="sans-serif", color="#adb5bd", fontcolor="#495057"]; edge [fontname="sans-serif", color="#868e96", fontcolor="#495057"]; subgraph cluster_batch { label = "小批次输入 (x)"; style=dashed; color="#ced4da"; x1 [label="x₁"]; x2 [label="x₂"]; xdot [label="..."]; xm [label="xₘ"]; } subgraph cluster_calc { label = "计算统计量"; style=dashed; color="#ced4da"; calc_mean [label="计算均值\n(μ_B)", shape=ellipse, color="#74c0fc"]; calc_var [label="计算方差\n(σ²_B)", shape=ellipse, color="#74c0fc"]; } subgraph cluster_transform { label = "转换"; style=dashed; color="#ced4da"; normalize [label="归一化\n(使用 μ_B, σ²_B + ε)", shape=diamond, color="#63e6be"]; scale_shift [label="缩放 (γ) 和平移 (β)\nyᵢ = γx̂ᵢ + β", shape=diamond, color="#ffc078"]; } subgraph cluster_output { label = "输出 (y)"; style=dashed; color="#ced4da"; y1 [label="y₁"]; y2 [label="y₂"]; ydot [label="..."]; ym [label="yₘ"]; } {x1, x2, xdot, xm} -> calc_mean [style=invis]; {x1, x2, xdot, xm} -> calc_var [style=invis]; calc_mean -> normalize [label="μ_B", style=dashed]; calc_var -> normalize [label="σ²_B", style=dashed]; normalize -> scale_shift [label="x̂ᵢ"]; scale_shift -> {y1, y2, ydot, ym} [style=invis]; // 连接单个输入到处理过程 x1 -> normalize [lhead=cluster_transform, style=dotted, arrowhead=none]; x2 -> normalize [lhead=cluster_transform, style=dotted, arrowhead=none]; xm -> normalize [lhead=cluster_transform, style=dotted, arrowhead=none]; normalize -> y1 [ltail=cluster_transform, style=dotted, arrowhead=none]; normalize -> y2 [ltail=cluster_transform, style=dotted, arrowhead=none]; normalize -> ym [ltail=cluster_transform, style=dotted, arrowhead=none]; } 批量归一化前向传播对小批次中单个特征的处理流程。输入 $x_i$ 用于计算小批次统计量($ \mu_{\mathcal{B}}, \sigma^2_{\mathcal{B}} $),然后将每个 $x_i$ 归一化为 $ \hat{x}_i $。最后,可学习参数 $ \gamma $ 和 $ \beta $ 对 $ \hat{x}_i $ 进行缩放和平移,得到输出 $y_i$。需记住,$ \gamma $ 和 $ \beta $ 是 每个特征 分别学习的。如果全连接层有 $ N $ 个输出神经元,则会有 $ N $ 对 $ (\gamma, \beta) $。如果卷积层有 $ C $ 个输出通道,则会有 $ C $ 对 $ (\gamma, \beta) $ 用于对每个通道的批次、高度和宽度维度进行归一化。这个过程确保了训练期间下一层的输入具有稳定的分布,由学习到的 $ \gamma $ 和 $ \beta $ 参数控制,这极大地有助于稳定并加速训练过程。