在看 ladder network(https://arxiv.org/pdf/1507.02672v2.pdf) 时初次遇到batch normalization(BN). 文中说BN能加速收敛等好处,但是并不理解,然后就在网上搜了些关于BN的资料。
看了知乎上关于深度学习中 Batch Normalization为什么效果好? 和优快云上一个关于Batch Normalization 的学习笔记,总算对BN有一定的了解了。这里只是总结一下BN的具体操作流程,对于BN更深层次的理解,为什么要BN,BN是否真的有效也还在持续学习和实验中。
BN就是在神经网络的训练过程中对每层的输入数据加一个标准化处理。
传统的神经网络,只是在将样本xx输入输入层之前对xx进行标准化处理(减均值,除标准差),以降低样本间的差异性。BN是在此基础上,不仅仅只对输入层的输入数据xx进行标准化,还对每个隐藏层的输入进行标准化。
标准化后的xx乘以权值矩阵Wh1Wh1加上偏置bh1bh1得到第一层的输入wh1x+bh1wh1x+bh1,经过激活函数得到h1=ReLU(wh1x+bh1)h1=ReLU(wh1x+bh1),然而加入BN后, h1h1的计算流程如虚线框所示:
1. 矩阵xx先经过Wh1Wh1的线性变换后得到s1s1 (注:因为减去batch的平均值μBμB后,bb的作用会被抵消掉,所提没必要加入bb了)
-
将s1s1再减去batch的平均值μBμB,并除以batch的标准差σ2B+ϵ−−−−−√σB2+ϵ得到s2s2. ϵϵ是为了避免除数为0时所使用的微小正数。
其中μB=1m∑mi=0Wh1xiμB=1m∑i=0mWh1xi
σ2B=1m∑mi=0(Wh1xi−μB)2σB2=1m∑i=0m(Wh1xi−μB)2
(注:由于这样做后s2s2基本会被限制在正态分布下,使得网络的表达能力下降。为解决该问题,引入两个新的参数:γγ,ββ. γγ和ββ是在训练时网络自己学习得到的。) -
将s2s2乘以γγ调整数值大小,再加上ββ增加偏移后得到s3s3
-
s3s3经过激活函数后得到h1h1
需要注意的是,上述的计算方法用于在训练过程中。在测试时,所使用的μμ和σ2σ2是整个训练集的均值μpμp和方差σ2pσp2. 整个训练集的均值μpμp和方差σ2pσp2的值通常是在训练的同时用移动平均法来计算的.
在看具体代码之前,先来看两个求平均值函数的用法:
mean, variance = tf.nn.moments(x, axes, name=None, keep_dims=False)
这个函数的输入参数x表示样本,形如[batchsize, height, width, kernels]
axes表示在哪个维度上求解,是个list
函数输出均值和方差
'''
batch = np.array(np.random.randint(1, 100, [10, 5]))开始这里没有定义数据类型,batch的dtype=int64,导致后面sess.run([mm,vv])时老报InvalidArgumentError错误,原因是tf.nn.moments中的计算要求参数是float的
'''
batch = np.array(np.random.randint(1, 100, [10, 5]),dtype=np.float64)
mm, vv=tf.nn.moments(batch,axes=[0])#按维度0求均值和方差
#mm, vv=tf.nn.moments(batch,axes=[0,1])求所有数据的平均值和方差
sess = tf.Session()
print batch
print sess.run([mm, vv])#一定要注意参数类型
sess.close()
输出结果:
[[ 53. 9. 67