Batch Norm学习笔记

本人小白一枚,本篇主要作用是学习总结和后续方便查看,综合多种资料,如有侵权,联系我,定及时删除~

提出:
该概念是何凯明大神在2015年提出resnet中大量使用的一种结构而被熟知的,按照作者的意思,这是一种非常牛的算法,而且经过后人验证,效果的确很好,尤其是在数据量比较大的时候,所以现在基本上已经是深度学习的标配了。因为最近学习了下resnet。就看到批标准化了,顺带将最近看的东西进行梳理和总结,方便后续自己复习查看(发现之前学的东西,整理不到位,很多都忘记了,还要重新学习,浪费很多时间)

首先,在神经网络的反向传播的过程中,较为广泛使用的参数更新的方法就是梯度下降法,由于批量梯度下降法用到所有的样本,计算量较大,而随机梯度下降法每次只考虑一个样本,又很容易受到某些不好样本的干扰,从而偏离了正常的应有的路线,因此,有了mini-batch批量梯度下降这种折中的方法,可以得到更加准确的梯度,并行速度快。batch-norm的提出也是基于mini-batch的。

很多统计学习方法都是基于假设:源空间和目标空间的数据分布一致,如若不一致,存在方法:transfer learning, domain adaptaion。

其中一种假设不成立的情况:当存在covariate shift时,即此时源空间和目标空间的条件概率一致,但是边缘概率不同,这种解释可以理解:神经网络各层的输出,由于层内参数不断变化的作用,分布与各层的输入信号不同,并且差异越来越大,但是他们最终指示的标签是一致的。

虽然可以有上面两种方法解决,但是我们想,为什么不从根本上就切断这种不良的变化呢,因此想到了batch-norm的方法。

p.s:一个epoch指的是训练集中的所有样本被训练完,一个step/iteration指的是神经网络的权重更新一次。

方法具体做什么?
对深度学习稍微有了解的都知道,白化是一种较为常见的规范化的方法,但是白化由于需要考虑到某个样本的各层输入以及所有样本的各层输入,所以会带来过高的计算代价和运算时间,因此,一种很自然的方法就是对mini-batch上的样本进行均值和方差的规范化。

在每次梯度下降时候,通过mini-batch来对相应的activation(一般是非线性的激活函数前面)进行规范化的操作,使得结果(输出信号的各个维度)都满足均值为0,方差为1的正态分布(对于图像来讲,上面所说的每个维度,指的是channel维度)。

~~~说下为什么是channel的维度:像卷基层这样的权值共享层,wx+b的均值和方差是对整张map上面求的,每一层有大小:batch_size * channel * height * width, 对共计:batch_size * height * width 个像素点统计均值和方差,所以一共有channel组参数。~~~

bn 的位置(即在哪里处理)?
如若放在每层的激活函数后面对数据进行归一化,在训练的初期由于分界面还在剧烈的变化,计算出来的参数不够稳定,所以采用在激活前初始化。
标准化流程
伪代码如下:
算法流程

其中,参数gammabeta是可以学习的参数,主要作用是增加函数的表达能力,因为bn的作用是把函数限制在0值附近,对应激活函数的线性区域,但是要是都是线性的话,深层网络的表达能力就降低了(因为多层线性与一层线性可以等效,此时深层就没有什么意义了)

上面算法中各个变量的计算如下(主要由链式法则来求解):
各参数计算过程

训练时候,可以采用统计每个mini-batch的样本的均值和方差,那么在测试的时候呢,测试的时候样本是逐个被送进来的,可不是成批次的,这时候也不能对每个样本算吧,然后在减去均值和方差,就变成了0了,完全没有意义了。所以测试时候使用的是训练时候得到的均值与方差的期望。在训练的最后一个epoch,对这一个epoch所有的训练样本均值和标准差进行统计,在测试的时候,用训练样本的标准差的期望和均值的期望来对测试数据归一化:
此时有:
这里写图片描述
这里写图片描述

从理论上来讲,bn的作用:
1.减少internal convariance shift
2.减少梯度消失的风险

bn表现出来的作用:
1.克服深度学习深度网络难以训练的弊病。可以减少坏的初始化的影响,可以防止梯度弥散,可以缓解,甚至解决在神经网络训练时遇到收敛慢或者梯度爆炸等无法训练的状况。加快模型的收敛速度(sigmoid更可能在非饱和区,梯度相对更大一些,收敛更快),提高模型精度。
2.可以使用更高的学习率,每层的尺度不一致,同一层不同维度的尺度也不一致,这些都会导致需要不同的学习率,所以通常选取这些学习率中最小的才可以保证损失函数下降,因此很慢,引入bn之后,可以选取较大的学习率和较大的衰减速度。
3.移除或者使用较低的dropout,因为导致过拟合的位置通常都是在数据的边界处,如果初始的权重已经落在了数据的内部,此时过拟合可以缓解。
4.降低L2权重的衰减系数
5.取消局部响应归一化层,因为batch-norm本身就相当于一个归一化网络。
6.减少epoch的次数,减少图像的扭曲的使用,由于epoch的降低,所以需要输入数据少一些扭曲。

我的小疑问以及解答:参数这里写图片描述这里写图片描述的引入,把函数又从线性区挪走了,岂不是白折腾了?
博客:http://blog.csdn.net/malefactor/article/details/51476961
给出了解答:通过BN,如果非线性函数都利用线性部分的性质,多层线性函数变换时深层是没有意义的,因为多层线性网络跟一层线性网络是等价的。意味着网络的表达能力下降了。所以BN为了保证非线性的获得,对变换后的满足均值为0方差为1的x又进行了scale加上shift操作(y=scale*x+shift),每个神经元增加了两个参数scale和shift参数,这两个参数是通过训练学习到的,意思是通过scale和shift把这个值从标准正态分布左移或者由移一点并长胖一点或者变瘦一点,每个实例挪动的程度不一样,这样等价于非线性函数的值从正中心周围的线性区往非线性区动了动。核心思想应该是想找到一个线性和非线性的较好平衡点,既能享受非线性的较强表达能力的好处,又避免太靠非线性区两头使得网络收敛速度太慢。而且这样可以让神经网络自己去学着使用和修改这个扩展参数这里写图片描述 , 和平移参数 β, 这样神经网络就能自己慢慢琢磨出前面的 normalization 操作到底有没有起到优化的作用, 如果没有起到作用, 我就使用 gamma 和 belt 来抵消一些 normalization 的操作.

代码
input_shape = self.input_shape
reduction_axes = list(range(len(input_shape)))
del reduction_axes[self.axis]
broadcast_shape = [1] * len(input_shape)
broadcast_shape[self.axis] = input_shape[self.axis]
if train:
m = K.mean(X, axis=reduction_axes)
brodcast_m = K.reshape(m, broadcast_shape)
std = K.mean(K.square(X - brodcast_m) + self.epsilon, axis=reduction_axes)
std = K.sqrt(std)
brodcast_std = K.reshape(std, broadcast_shape)
mean_update = self.momentum * self.running_mean + (1-self.momentum) * m
std_update = self.momentum * self.running_std + (1-self.momentum) * std
self.updates = [(self.running_mean, mean_update),
(self.running_std, std_update)]
X_normed = (X - brodcast_m) / (brodcast_std + self.epsilon)
else:
brodcast_m = K.reshape(self.running_mean, broadcast_shape)
brodcast_std = K.reshape(self.running_std, broadcast_shape)
X_normed = ((X - brodcast_m) /
(brodcast_std + self.epsilon))
out = K.reshape(self.gamma, broadcast_shape) * X_normed + K.reshape(self.beta, broadcast_shape)

参考
论文:
batchnorm论文
博客:
http://blog.csdn.net/u012816943/article/details/51691868
http://blog.csdn.net/malefactor/article/details/51476961
http://blog.csdn.net/hjimce/article/details/50866313
https://zhuanlan.zhihu.com/p/24810318

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值