Batch Normalization: 原理及细节

觉得有用的话,欢迎一起讨论相互学习~Follow Me

为了标准化这些值,我们首先需要计算出批数据中的平均值,如果你仔细看这些代码,你会发现这不是对输入的批数据计算平均值,而是对任意一个特定层的在传入非线性函数之前的输出求平均值。然后将其通过非线性函数后传递给下一层作为输入。

我们将平均值表示为\(\mu_B\),是所有\(x_i\) 值得和然后除以\(x_i\) 的个数\(m\)。
\[
\mu_B \leftarrow \frac{1}{m}\sum_{i=1}^m x_i
\]

然后我们需要计算方差或者均方差,用\(\sigma_{B}^{2}\)表示。如果你不熟悉数理统计,简单来说就是将每个\(x_i\)的值将其减去这个批次的平均值(先前我们计算过这个值并且用\(\mu_B\)表示)。这就是我们所说的对该值的偏差。我们将结果平方以得到平方偏差。将批次中所有数据的平方偏差求和再除以数值的个数即\(m\),所得的这个平均值叫做平方偏差。
\[
\sigma_{B}^{2} \leftarrow \frac{1}{m}\sum_{i=1}^m (x_i - \mu_B)^2
\]

一旦我们有了均值和方差,我们就可以用下面的方程对数据进行归一化。对于每个值,我们将其减去平均值并处以标准差(几乎是)。(你可能多次听说过标准偏差,但如果你没有研究统计数据,你可能不知道标准偏差实际上是均方差的平方根.)

\[
\hat{x_i} \leftarrow \frac{x_i - \mu_B}{\sqrt{\sigma_{B}^{2} + \epsilon}}
\]

上面我们说的是几乎是标准偏差,这是因为该批次的实际标准偏差是\(\sqrt{\sigma_{B}^{2}}\),但是在我们的方程式中我们在分母的位置的平方根号中加入了一个很小的数\(\epsilon\)。这个\(\epsilon\)可以是任意一个很小的正数,在我们的代码中,我们使用值0.001.这个操作是为了确保我们不会试图使用0作为除数,但实际上他也的确为每个批次稍微增加了一点方差。

为什么增加方差?根据统计学上说法,这是有道理的,因为即使我们一次对一个批次进行标准化,我们也正在尝试估计总体训练集合上的分布,而总体方差高于从该总体中抽取的任何样本的方差,因此每批增加差异有助于将其考虑在内。

此时,我们已经得到了一个归一化的值,即 \(\hat{x_i}\) 。但我们不是直接使用它,而是将它乘以一个伽玛值 \(\gamma\),然后添加一个\(\beta\)。 \(\gamma\) 和 \(\beta\) 都是网络的可学习参数,分别用于缩放和移位归一化值。因为它们就像权重一样可以学习,所以它们可以在训练过程中为网络提供一些额外的旋钮,以帮助网络更好的学习。
\[
y_i \leftarrow \gamma \hat{x_i} + \beta
\]

我们现在有了神经层批量标准化后最终的输出,我们可以将其传递给非线性激活函数例如:sigmoid, tanh, ReLU, Leaky ReLU等等。在原始批量标准化论文中Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift. 他们提到可能会出现希望在非线性之后而不是之前执行批量标准化,但实际上实践中很难找到像这样的用途。

05-12 10:09