出处:
《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》
IID假设:
独立同分布假设:训练数据和测试数据的分布相同是训练的模型能够在测试集上获得好效果的保障
而BN就是使得在训练过程中每一层的输入都保持相同的分布
再者,随着网络的加深,训练变得更加困难,收敛越来越慢,而BN、ReLU、残差结构本质上都是为了解决这个问题的
ICS
从论文名字看BN只要是为了解决ICS问题,Internal Covariate Shift
Covariate Shift的概念:如果ML系统实例集合<X,Y>中的输入值X的分布老是变,这不符合IID假设,网络模型很难稳定的学规律
在训练过程中,隐层的输入分布老是变来变去,这就是所谓的“Internal Covariate Shift”,Internal指的是深层网络的隐层,是发生在网络内部的事情,而不是covariate shift问题只发生在输入层。
BN本质
因为深层神经网络在做非线性变换前的激活输入值随着网络深度加深或者在训练过程中,其分布逐渐发生偏移或者变动,之所以训练收敛慢,一般是整体分布逐渐往非线性函数的取值区间的上下限两端靠近(对于Sigmoid函数来说,意味着激活输入值WU+B是大的负值或正值),所以这导致反向传播时低层神经网络的梯度消失,这是训练深层神经网络收敛越来越慢的本质原因
BN的本质是对于每个隐层神经元,把逐渐向非线性函数映射后向取值区间极限饱和区靠拢的输入分布强制拉回到均值为0方差为1的比较标准的正态分布,使得非线性变换函数的输入值落入对输入比较敏感的区域,以此避免梯度消失问题。
因为梯度能保持比较大的状态,所以对神经网络的参数调整效率比较高,也就是说收敛地快,经过BN后,目前大部分Activation的值落入非线性函数的线性区内,其对应的导数远离导数饱和区,这样来加速训练收敛过程。
训练中的BN
对于Mini-batch SGD来说,这里x指的是W*input+b,变换公式是:
变换后某个神经元的激活x形成了均值为0,方差为1的正态分布,目的是把值往后续要进行的非线性变换的线性区拉动,增大导数值,增强反向传播信息流动性,加快训练收敛速度。但是这样会导致网络表达能力下降
所以,增加两个学习来的参数,用来对变换后的激活反变换,使得网络表达能力增强
在训练过程中,只能计算当前batch样本上的mean和var。但是我们做的normalization是对于整个输入样本空间,因此需要对每个batch的mean, var做指数加权平均来将batch上的mean和var近似成整个样本空间上的mean和var.
训练过程
测试时的操作
在训练结束后,网络的mean和std就固定住了,对于pytorch,执行model.eval()
因为测试时计算batch的均值方差不适合(单样本的时候),因此会直接拿训练过程中对整个样本空间估算的mean和var直接来用。
BN的优点,为什么有效?
- 不仅仅极大提升了训练速度,收敛过程大大加快;
- 还能增加分类效果,一种解释是这是类似于Dropout的一种防止过拟合的正则化表达方式,所以不用Dropout也能达到相当的效果;
- 另外调参过程也简单多了,对于初始化要求没那么高,而且可以使用大的学习率等
《How Does Batch Normalization Help Optimization?》中的结论:
BN可以防止梯度爆炸或弥散、可以提高训练时模型对于不同超参(学习率、初始化)的鲁棒性、可以让大部分的激活函数能够远离其饱和区域
BN能够work的真正原因在于BN重新改变了优化问题,使得优化空间变得非常平滑。
很多normalization的方法都可以达到BN的效果,甚至更好
BN与过拟合
BN并不能阻止过拟合,在某些情况下可以抑制
BN的本意是为了加速训练和收敛过程,而不是过拟合
在训练中,BN的使用使得一个mini-batch中的所有样本都被关联在了一起,一个batch数据中每张图片对应的输出都受到一个batch所有数据影响,这样相当于一个间接的数据增强,达到防止过拟合作用.