[Tensorflow] Batch Normalization实现

批量归一化(Batch Normalization, BN)在TensorFlow中的实现带来了诸多优势,包括允许使用更大学习率、消除对dropout的依赖以及初始化时的自由度。本文详细介绍了`tf.nn.batch_normalization`的使用,`tf.nn.moments`计算平均数和方差,以及BN层的放置顺序。通过在Mnist数据集上的实验对比,展示了BN层如何显著提高训练速度,加快约3倍,且与论文中BN对Inception模型的加速效果相当。" 82188570,1407999,理解FusionCharts Free:双Y轴组合图的XML解析,"['数据可视化', '图表库', 'XML解析', '前端开发']
摘要由CSDN通过智能技术生成

bn的优势:

(1)更大的学习率(传统方法太大的learning rate容易导致梯度explode/vanish,或者get stuck in poor local)
(2)不再需要dropout

(3)less careful about initialization

但是BN不仅仅加BN层,还要修改以下的东西才能更快:
(1)learning rate 赋予更大的初值,且下降得更快。(比如将learning rate从0.0015扩大5倍到0.0075,下降快6倍)
(2)Remove Droupout
(3)Reduce L2 weight decay。(比如每次除5)
(4)Remove LRN
(5、6)其他。。看论文
ResNet 有用到BN,其在CIFAR-10网络中参数为:
20,34,44,56层使用:
learning rate=0.1,在32k和48k iterations时/10。
l2 weght decay=1e-4
110层使用:0.01learning rat用于warm up training,直到training error小于80%。

一、tf.nn.batch_normalization

Tensorflow 提供了Batch Normalization的API。但是,这个API很灵活,灵活的后果就是我们需要自己去定义所有的参数。
(比如,提供给此API的Tensor,居然需要我们自己去计算mean和variance)

tf.nn.batch_normalization(
  x,                #Tensor,对它执行BN操作
  mean,             #Tensor,一般为x的平均数,float32。
  variance,         #Tensor,一般为x的方差,float32。
  offset,           #Tensor,beta值,BN的shift操作。一般初始为0
  scale,            #Tensor,gamma值,BN的scale操作。一般初始为1
  variance_epsilon, #float。小的实数防止除0出现。
  name=None
)
"""
返回值(Tensor): 
  y= (x-mean)/sqrt(variance^2+variance_epsilon)*scale+offset。
  
但是mean和variance需要自己提前计算,
而tensorflow又提供了另一个API来计算mean和variance。(当然我们也可以自己瞎搞一个)
"""
这个API完全按照论文的思路设计,且更加灵活(比如mean和variance可以设置为其他值而不是x的均值和方差,beta和gamma也是如此)。
(见下图):

二、Tensor平均数和方差计算tf.nn.moments

  由于上述的API需要手动计算mean和variance,所以就用到了这个API。
tf.nn.moments(
  x,              #Tensor,要计算mean和variance的变量
  axes,           #要处理的维度。BN一般就是所有的维度。即[d for d in range(len(x.get_shape())]
  shift=None, 
  name=None, 
  keep_dims=False
)


三、例子

import tensorflow as tf
sess=tf.Session()
x=tf.constant([[1,5],[10,100]],dtype=tf.float32)
#维度
axes=[d for d in range(len(x.get_shape()))]
#beta gamma参数
beta= tf.get_variable("beta",shape=[],initializer=tf.constant_initializer(0.0))
gamma=tf.get_variable("gamma",shape=[],initializer=tf.constant_initializer(1.0))
sess.run(tf.global_variables_initializer())
#计算mean和variance,并执行BN操作
x_mean,x_variance=tf.nn.moments(x,axes)
y=tf.nn.batch_normalization(x,x_mean,x_variance,beta,gamma,1e-10,"bn")
#查看最终值
y_mean,y_variance=tf.nn.moments(y,axes)
x_val,xm_val,xv_val,y_val,ym_val,yv_val=sess.run([x,x_mean,x_variance,y,y_mean,y_variance])
print("*********执行BN前的Variable x:************")
print("x=%s\n x mean=%s\n x variance=%s" %(x_val,xm_val,xv_val))
print("*********执行BN后的Variable y:************")
print("y=%s \n y mean=%s\n y variance=%s" %(y_val,ym_val,yv_val))

执行结果为:
*********执行BN前的Variable x:************
x=[[   1.    5.]
 [  10.  100.]]
 x mean=29.0
 x variance=1690.5
*********执行BN后的Variable y:************
y=[[-0.68100518 -0.58371872]
 [-0.46211064  1.72683454]] 
 y mean=0.0
 y variance=1.0

可知道x经过BN处理后得到y,y的均值为0,方差变成1了(beta为0,gamma为1时)。
这里我们可以修改下beta和gamma的初始值,则y的平均值会变成beta,方差会变成gamma^2。

四、BN层放置顺序

   BN网络中,一个卷积层或全连接层中,对于输入x,有3步中间操作:BN操作、weight操作、ReLu操作。这三种操作的顺序该怎么排列。
   原论文的说法是:在Any layer previously received x as input, now received BN(x),但一个卷积层中的子层呢?
   对于2*con16 =》 2*conv32=》2*conv64=》fc-10 在MNIST中试了下三种顺序:
  (1) x -> bn -> weight -> relu
  (2) x -> bn -> relu -> weight
  (3) x -> weight ->bn -> relu
   最后发现效果都挺好的,可能是这个数据集太简单了,有待以后继续测试。。。
   不过在Resnet 1k网络中,第2种方法比第3种效果更好(在有shortcut的情况)。
论文地址:https://arxiv.org/pdf/1603.05027.pdf

五、BN在Mnist效果对比

由于Mnist太简单,正常CNN网络加不加BN层效果不明显。
所以我们需要给网络模型增加训练难度:把ReLu替换成Sigmoid。
(使用Sigmoid会让训练无比的慢,起码慢了百八十倍了~我一开始还以为网络出问题了。。ReLu真的强大!)
其他参数
TensorFlow中的Batch Normalization(批量归一化)是一种用于训练深度神经网络的技术。它通过对每个小批量样本的输入进行归一化,使得网络的每个层都能够更稳定地学习和收敛。 Batch Normalization的作用是使输入数据的均值接近0,方差接近1。这样做的好处是可以加速网络的训练过程,并且提高模型的泛化能力。在深度神经网络中,由于每层之间的输入分布会发生变化,导致网络的学习过程变得困难。Batch Normalization通过对每个小批量样本进行归一化,可以缓解这个问题。 在TensorFlow中,可以使用`tf.keras.layers.BatchNormalization`层来实现Batch Normalization。该层可以在模型中插入,用于对输入进行归一化处理。以下是一个示例代码: ```python import tensorflow as tf model = tf.keras.Sequential([ tf.keras.layers.Dense(64, activation='relu'), tf.keras.layers.BatchNormalization(), tf.keras.layers.Dense(10, activation='softmax') ]) # 编译和训练模型 model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) model.fit(x_train, y_train, epochs=10, batch_size=32) ``` 上述代码中,`tf.keras.layers.BatchNormalization`层被插入到了Dense层之后,用于对Dense层的输出进行归一化处理。然后,模型经过编译和训练,可以进行后续的预测和评估操作。 通过使用Batch Normalization,可以显著提高深度神经网络的训练速度和性能。它是一种常用的正则化技术,被广泛应用于深度学习模型中。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值