Tensorflow2.0之BatchNorm层

Tensorflow2.0之BatchNorm层

简介:

卷积神经网络的出现,网络参数量大大减低,使得几十层的深层网络成为可能。然而,在残差网络出现之前,网络的加深使得网络训练变得非常不稳定,甚至出现网络长时间不更新甚至不收敛的现象,同时网络对超参数比较敏感,超参数的微量扰动也会导致网络的训练轨迹完全改变。

2015 年,Google 研究人员Sergey Ioffe 等提出了一种参数标准化(Normalize)的手段,并基于参数标准化设计了Batch Nomalization(简写为BatchNorm,或BN)层 [6]。BN 层的提出,使得网络的超参数的设定更加自由,比如更大的学习率、更随意的网络初始化等,同时网络的收敛速度更快,性能也更好。BN 层提出后便广泛地应用在各种深度网络模型
上,卷积层、BN 层、ReLU 层、池化层一度成为网络模型的标配单元块,通过堆叠Conv-BN-ReLU-Pooling 方式往往可以获得不错的模型性能。

为什么我们需要BN层?

考虑 Sigmoid 激活函数和它的梯度分布,如下图 10.39 所示,Sigmoid 函数在𝑥 ∈−2 2 区间的导数值在 . .2 区间分布;当𝑥 > 2 或𝑥 < −2时,Sigmoid 函数的导数变得很小,逼近于0,从而容易出现梯度弥散现象。为了避免因为输入较大或者较小而导致Sigmoid 函数出现梯度弥散现象,将函数输入𝑥标准化映射到0 附近的一段较小区间将变得非常重要,可以从图看到,通过标准化重映射后,值被映射在0 附近,此处的导数值不至于过小,从而不容易出现梯度弥散现象。这是使用标准化手段受益的一个例子。

在这里插入图片描述

我们再看另一个例子。考虑2 个输入节点的线性模型,如图 下图所示:

ℒ = 𝑎 = 𝑥1𝑤1 + 𝑥2𝑤2 + b

讨论如下2 种输入分布下的优化问题:
❑ 输入𝑥1 ∈[1,10] ,𝑥2 ∈[1,10]
❑ 输入𝑥1 ∈ [1,10],𝑥2 ∈[100,1000]

由于模型相对简单,可以绘制出2 种𝑥1、𝑥2下,函数的损失等高线图,图b是𝑥1 ∈[1,10]
、𝑥2 ∈[100,1000] 时的某条优化轨迹线示意,图©是𝑥1 ∈ [1,10]、𝑥2 ∈[1,10]
时的某条优化轨迹线示意,图中的圆环中心即为全局极值点

在这里插入图片描述
考虑到:
在这里插入图片描述
当𝑥1、𝑥2输入分布相近时, 𝜕ℒ / 𝜕𝑤1、𝜕ℒ / 𝜕𝑤2偏导数值相当,函数的优化轨迹如图 10.40©所示;当𝑥1、𝑥2输入分布差距较大时,比如𝑥1 ≪ 𝑥2,则
𝜕ℒ / 𝜕𝑤1 << 𝜕ℒ / 𝜕𝑤2
损失函数等势线在𝑤2轴更加陡峭,某条可能的优化轨迹如图 (b)所示。对比2 条优化轨迹线可以观察到,𝑥1、𝑥2分布相近时图 10.40©中收敛更加快速,优化轨迹更理想。
通过上述的2 个例子,我们能够经验性归纳出:网络层输入𝑥分布相近,并且分布在较小范围内时(如0 附近),更有利于函数的优化。那么如何保证输入𝑥的分布相近呢?数据标准化可以实现此目的,通过数据标准化操作可以将数据𝑥映射到𝑥̂:
在这里插入图片描述
其中 μ r 、 σ r 2 \mu_r、\sigma_r^2 μrσr2来自统计的所有数据的均值和方差,𝜖是为防止出现除0 错误而设置的较小数
字,如1 e − 8。
在基于 Batch 的训练阶段,如何获取每个网络层所有输入的统计数据 μ r 、 σ r 2 \mu_r、\sigma_r^2 μrσr2呢?考虑Batch 内部的均值𝜇𝐵和方差𝜎𝐵2:
在这里插入图片描述
可以视为近似于𝜇𝑟、𝜎𝑟2,其中𝑚为Batch 样本数。因此,在训练阶段,通过
在这里插入图片描述
标准化输入,并记录每个Batch 的统计数据𝜇𝐵、𝜎𝐵2,用于统计真实的全局 μ r 、 σ r 2 \mu_r、\sigma_r^2 μrσr2
在测试阶段,根据记录的每个Batch 的𝜇𝐵、𝜎𝐵2估计出所有训练数据的𝜇𝑟、𝜎𝑟2,按着train那个一模一样的公式进行计算将每层的输入标准化。

上述的标准化运算并没有引入额外的待优化变量,𝜇𝑟、𝜎𝑟2和𝜇𝐵、𝜎𝐵2均由统计得到,不需要参与梯度更新。实际上,为了提高BN 层的表达能力,BN 层作者引入了“scale and shift”技巧,将𝑥̂变量在此映射变换:
在这里插入图片描述
其中𝛾参数实现对标准化后的𝑥̂再次进行缩放,𝛽参数实现对标准化的𝑥̂进行平移,不同的是,𝛾、𝛽参数均由反向传播算法自动优化,实现网络层“按需”缩放平移数据的分布的目的

BN层实现

在 TensorFlow 中,通过**layers.BatchNormalization()**类可以非常方便地实现BN 层:

# 创建BN 层
layer=layers.BatchNormalization()

与全连接层、卷积层不同,BN 层的训练阶段和测试阶段的行为不同,需要通过设置training 标志位来区分训练模式还是测试模式。

以 LeNet-5 的网络模型为例,在卷积层后添加BN 层,代码如下:
network = Sequential([ # 网络容器
layers.Conv2D(6,kernel_size=3,strides=1),

# 插入BN 层
layers.BatchNormalization(),
layers.MaxPooling2D(pool_size=2,strides=2),
layers.ReLU(),
layers.Conv2D(16,kernel_size=3,strides=1),
# 插入BN 层
layers.BatchNormalization(),
layers.MaxPooling2D(pool_size=2,strides=2),
layers.ReLU(),
layers.Flatten(),
layers.Dense(120, activation='relu'),
# 此处也可以插入BN 层
layers.Dense(84, activation='relu'),
# 此处也可以插入BN 层
layers.Dense(10)
])

在训练阶段,需要设置网络的参数training=True 以区分BN 层是训练还是测试模型,代码如下:

with tf.GradientTape() as tape:
	# 插入通道维度
	x = tf.expand_dims(x,axis=3)
	# 前向计算,设置计算模式,[b, 784] => [b, 10]
	out = network(x, training=True)
	```
	在测试阶段,需要设置training=False,避免BN 层采用错误的行为,代码如下:
	
```python
for x,y in db_test: # 遍历测试集
	# 插入通道维度
	x = tf.expand_dims(x,axis=3)
	# 前向计算,测试模式
	out = network(x, training=False)
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值