解读Batch Normalization

本文转载自:http://blog.csdn.net/shuzfan/article/details/50723877

本次所讲的内容为Batch Normalization,简称BN,来源于《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》,是一篇很好的paper。

1-Motivation

作者认为:网络训练过程中参数不断改变导致后续每一层输入的分布也发生变化,而学习的过程又要使每一层适应输入的分布,因此我们不得不降低学习率、小心地初始化。作者将分布发生变化称之为 internal covariate shift

大家应该都知道,我们一般在训练网络的时会将输入减去均值,还有些人甚至会对输入做白化等操作,目的是为了加快训练。为什么减均值、白化可以加快训练呢,这里做一个简单地说明:

首先,图像数据是高度相关的,假设其分布如下图a所示(简化为2维)。由于初始化的时候,我们的参数一般都是0均值的,因此开始的拟合y=Wx+b,基本过原点附近,如图b红色虚线。因此,网络需要经过多次学习才能逐步达到如紫色实线的拟合,即收敛的比较慢。如果我们对输入数据先作减均值操作,如图c,显然可以加快学习。更进一步的,我们对数据再进行去相关操作,使得数据更加容易区分,这样又会加快训练,如图d。 
这里写图片描述

白化的方式有好几种,常用的有PCA白化:即对数据进行PCA操作之后,在进行方差归一化。这样数据基本满足0均值、单位方差、弱相关性。作者首先考虑,对每一层数据都使用白化操作,但分析认为这是不可取的。因为白化需要计算协方差矩阵、求逆等操作,计算量很大,此外,反向传播时,白化操作不一定可导。于是,作者采用下面的Normalization方法。

2-Normalization via Mini-Batch Statistics

数据归一化方法很简单,就是要让数据具有0均值和单位方差,如下式: 
这里写图片描述 
但是作者又说如果简单的这么干,会降低层的表达能力。比如下图,在使用sigmoid激活函数的时候,如果把数据限制到0均值单位方差,那么相当于只使用了激活函数中近似线性的部分,这显然会降低模型表达能力。 
这里写图片描述

为此,作者又为BN增加了2个参数,用来保持模型的表达能力。 
于是最后的输出为: 
这里写图片描述 
上述公式中用到了均值E和方差Var,需要注意的是理想情况下E和Var应该是针对整个数据集的,但显然这是不现实的。因此,作者做了简化,用一个Batch的均值和方差作为对整个数据集均值和方差的估计。 
整个BN的算法如下: 
这里写图片描述 
求导的过程也非常简单,有兴趣地可以自己再推导一遍或者直接参见原文。

测试

实际测试网络的时候,我们依然会应用下面的式子: 
这里写图片描述 
特别注意: 这里的均值和方差已经不是针对某一个Batch了,而是针对整个数据集而言。因此,在训练过程中除了正常的前向传播和反向求导之外,我们还要记录每一个Batch的均值和方差,以便训练完成之后按照下式计算整体的均值和方差: 
这里写图片描述

BN before or after Activation

作者在文章中说应该把BN放在激活函数之前,这是因为Wx+b具有更加一致和非稀疏的分布。但是也有人做实验表明放在激活函数后面效果更好。这是实验链接,里面有很多有意思的对比实验:https://github.com/ducha-aiki/caffenet-benchmark

3-Experiments

作者在文章中也做了很多实验对比,我这里就简单说明2个。 
下图a说明,BN可以加速训练。图b和c则分别展示了训练过程中输入数据分布的变化情况。 
这里写图片描述

下表是一个实验结果的对比,需要注意的是在使用BN的过程中,作者发现Sigmoid激活函数比Relu效果要好。 
这里写图片描述

### Batch Normalization 的详细解读 #### 什么是 Batch NormalizationBatch Normalization 是一种用于加速深度神经网络训练的技术,最初由 Google 提出并发表在论文《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》中[^1]。其核心目标是通过减少内部协变量偏移(Internal Covariate Shift),使模型能够更高效地完成训练。 #### 内部协变量偏移是什么? 在深度神经网络的训练过程中,每一层的输入数据分布会随着前面层权重的变化而发生改变。这种现象称为 **内部协变量偏移**。由于各层需要不断适应前一层输出的数据分布变化,因此增加了优化难度,导致训练速度变慢甚至难以收敛[^2]。 #### Batch Normalization 的工作原理 Batch Normalization 主要通过对每一批次(mini-batch)的数据进行归一化操作来解决上述问题。具体来说: 1. 对于某一层的激活值 $ x^{(k)} $,计算该批次内的均值 $\mu_B$ 和方差 $\sigma_B^2$: $$ \mu_B = \frac{1}{m} \sum_{i=1}^m x_i^{(k)} $$ $$ \sigma_B^2 = \frac{1}{m} \sum_{i=1}^m (x_i^{(k)} - \mu_B)^2 $$ 2. 使用这些统计量对原始数据进行归一化处理: $$ \hat{x}_i^{(k)} = \frac{x_i^{(k)} - \mu_B}{\sqrt{\sigma_B^2 + \epsilon}} $$ 这里 $\epsilon$ 是一个小常数,用来防止分母为零的情况[^3]。 3. 归一化之后,为了保留数据本身的信息表达能力,引入两个可学习参数 $\gamma$ 和 $\beta$ 来重新缩放和平移数据: $$ y_i^{(k)} = \gamma \cdot \hat{x}_i^{(k)} + \beta $$ 这一过程不仅减少了内部协变量偏移的影响,还增强了模型的学习灵活性。 #### Batch Normalization 的作用 - 加速训练:通过稳定中间层的输入分布,使得梯度下降更加平稳,从而加快收敛速度。 - 减少超参敏感性:允许使用更高的学习率,并降低对初始化条件的要求。 - 正则化效果:由于每次 mini-batch 中的统计数据存在一定的随机性,BN 可以起到类似于 Dropout 的正则化作用,帮助缓解过拟合问题。 #### 测试阶段如何应用 Batch Normalization? 在测试阶段,不再依赖当前 batch 数据的均值和方差,而是采用整个训练集中估计得到的整体均值和方差来进行归一化。这样可以确保预测结果的一致性和稳定性。 ```python import torch.nn as nn class MyModel(nn.Module): def __init__(self, input_size, hidden_size, output_size): super(MyModel, self).__init__() self.fc1 = nn.Linear(input_size, hidden_size) self.bn1 = nn.BatchNorm1d(hidden_size) # 添加 BN 层 self.relu = nn.ReLU() self.fc2 = nn.Linear(hidden_size, output_size) def forward(self, x): out = self.fc1(x) out = self.bn1(out) # 应用 BN 处理 out = self.relu(out) out = self.fc2(out) return out ``` 以上是一个简单的 PyTorch 实现示例,展示了如何将 Batch Normalization 集成到神经网络架构中。 --- ####
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值