[深度学习] Normalization 模型
原标题:[深度学习] Normalization 模型
原文来自:CSDN 原文链接:https://blog.csdn.net/zwqjoy/article/details/91546307
BatchNormalization的出现无疑是广大AI调参侠的福音,将大家从繁琐的权重初始化、学习率调节中释放出来。它不仅能够大大加快收敛速度,还自带正则化功能,是Google 2015年提出的。
如何理解BatchNorm?
请参考论文:Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift
从论文名字可以看出,BN是用来解决“Internal Covariate Shift”问题的,那么首先得理解什么是“Internal Covariate Shift”?
机器学习的一个重要的假设是:数据是独立同分布的。训练集合测试集的数据是同分布的,这样模型才有好的泛化效果。神经网络其实也是在学习这个分布。在这个假设前提下,一旦我们知道了(x,y)的联合分布,很多问题就能通过条件概率P(x|y)P(x|y)计算出来了。但是在实际训练过程中,数据经过前一个隐藏层向后一个隐藏层传播(线性+非线性运算),分布通常会发生变化(作者称之为Internal Covariate Shift),这会导致网络学习变慢。我们从两个方面来稍微理解一下这个问题。
论文首先说明Mini-Batch SGD相对于One Example SGD的两个优势:梯度更新方向更准确;并行计算速度快;(本文作者:为什么要说这些?因为BatchNorm是基于Mini-Batch SGD的,所以先夸下Mini-Batch SGD),然后吐槽SGD训练的缺点:超参数调起来很麻烦。(本文作者:作者隐含意思是用BN就能解决很多SGD的缺点)
接着引入covariate shift的概念:如果ML系统实例集合<X,Y>中的输入值X的分布老是变,这不符合IID假设啊,那您怎么让我稳定的学规律啊,这不得引入迁移学习才能搞定吗,我们的ML系统还得去学习怎么迎合这种分布变化啊。
对于深度学习这种包含很多隐层的网络结构,在训练过程中,因为各层参数老在变,所以每个隐层都会面临covariate shift的问题,也就是在训练过程中,隐层的输入分布老是变来变去,这就是所谓的“Internal Covariate Shift”,Internal指的是深层网络的隐层,是发生在网络内部的事情,而不是covariate shift问题只发生在输入层。
一方面:我们现在只看两个隐藏层(隐藏层A和隐藏层B)之间的传播。第一轮,来自A的数据经过线性操作和激活函数后到达B,反向传播时,B层为了学习到这个分布(满足A的需求),调整了权重W1。接着又进行第二轮传播了,A数据一到B,A说,现在需求变了,要这样这样。B一脸懵,盘算了一下,发现前面的白学了,没办法,换个方向重来,就这样,A一直在变,B就得跟着变,来来回回磨合,这听起来就是个非常耗时的工作。就好比A说今天要吃汤圆,B和好了面粉,准备了调料,A又说我要吃饭,虽然在B的不懈努力下A最后能吃上饭,但如果一开始A就告诉B我要吃饭不是更快一点?,网络越深,这个问题就越严重。
BatchNorm的本质思想
BatchNorm的基本思想:能不能让每个隐层节点的激活输入分布固定下来呢?这样就避免了“Internal Covariate Shift”问题了。BatchNormalization就是解决这两个问题的。首先,它将隐藏层的输入强行变换为同一分布(解决了第一个问题),这个分布就是正态分布(解决了第二个问题)。
其实一句话就是:对于每个隐层神经元,把逐渐向非线性函数映射后向取值区间极限饱和区靠拢的输入分布强制拉回到均值为0方差为1的比较标准的正态分布,使得非线性变换函数的输入值落入对输入比较敏感的区域,以此避免梯度消失问题。因为梯度一直都能保持比较大的状态,所以很明显对神经网络的参数调整效率比较高,就是变动大,就是说向损失函数最优值迈动的步子大,也就是说收敛地快。NB说到底就是这么个机制,方法很简单,道理很深刻。
我们用sigmoid为例来说明一下。假设两层传播之间可表示为 z=g(Wu+b) 其中g是sigmoid函数,我们令 x=Wu+b
那么:
计算下梯度:
我们关注一下中间那一项,是sigmoid函数的导数,它的分布所示,可见随着x不断增大,该项趋近于0,这也就意味着整个梯度趋近于0,进入饱和区了,导致的结果就是收敛变慢!要想加快收敛怎么办,把x拉到靠近0的位置就行了,这里导数值最大。
它的具体做法所示。对每一个Mini-Batch的所有样本的每一维特征,计算两个统计量:均值和方差,然后做一个归一化操作,这样就变成了正态分布了。但是只这样做也有问题,首先,谁说数据一定是正态分布的,偏正态不行吗?第二,把数据全部拉到接近0的位置,sigmoid不就接近于一个线性函数了吗,没有起到激活的作用啊(线性激活函数+线性操作等价于一层线性操作)。
上面是对BN的抽象分析和解释,具体在Mini-Batch SGD下做BN怎么做?其实论文里面这块写得很清楚也容易理解。为了保证这篇文章完整性,这里简单说明下。
假设对于一个深层神经网络来说,其中两层结构如下:
要对每个隐层神经元的激活值做BN,可以想象成每个隐层又加上了一层BN操作层,它位于X=WU+B激活值获得之后,非线性函数变换之前,其图示如下:
对于Mini-Batch SGD来说,一次训练过程里面包含m个训练实例,其具体BN操作就是对于隐层内每个神经元的激活值来说,进行如下变换:
要注意,这里t层某个神经元的x(k)不是指原始输入,就是说不是t-1层每个神经元的输出,而是t层这个神经元的激活x=WU+B,这里的U才是t-1层神经元的输出。
变换的意思是:某个神经元对应的原始的激活x通过减去mini-Batch内m个实例获得的m个激活x求得的均值E(x)并除以求得的方差Var(x)来进行转换。
上文说过经过这个变换后某个神经元的激活x形成了均值为0,方差为1的正态分布,目的是把值往后续要进行的非线性变换的线性区拉动,增大导数值,增强反向传播信息流动性,加快训练收敛速度。
为了解决这两个问题,作者又做了一步操作,引入了两个参数gamma和beta(图中的最后一步), 这两个参数是在训练过程中学习的!但是这样会导致网络表达能力下降,为了防止这一点,每个神经元增加两个调节参数(scale和shift),这两个参数是通过训练来学习到的,用来对变换后的激活反变换,使得网络表达能力增强,即对变换后的激活进行如下的scale和shift操作,这其实是变换的反操作:
BN其具体操作流程,如论文中描述的一样:
上面说了一下训练过程。那么预测的时候呢?假如只预测一个样本,一个样本的均值…方差…怎么算?没意义是吧。事实上,预测的时候用的是全局的均值和方差,这个全局的均值和方差是怎么得到的呢?很简单,训练过程中记录下每个Mini-Batch的均值和方差,求个期望就是全局的均值和方差了。
BatchNorm为什么NB呢,关键还是效果好。不仅仅极大提升了训练速度,收敛过程大大加快,还能增加分类效果,一种解释是这是类似于Dropout的一种防止过拟合的正则化表达方式,所以不用Dropout也能达到相当的效果。另外调参过程也简单多了,对于初始化要求没那么高,而且可以使用大的学习率等。总而言之,经过这么简单的变换,带来的好处多得很,这也是为何现在BN这么快流行起来的原因。
BatchNormalization简直是个救世主啊,它令调参工作变得从未如此容易,让调参侠们不费吹灰之力,谈笑间到达收敛的彼岸。但毛主席曾经说过,万物都是辩证的,它同样存在两个问题:
对batch_size非常敏感。BatchNormalization的一个重要出发点是保持每层输入的数据同分布。回想下开始那个独立同分布的假设。假如取的batch_size很小,那显然有些Mini-Batch的数据分布就很可能与整个数据集的分布不一致了,又出现了那个问题,数据分布不一致,这就等于说没起到同分布的作用了,或者说同分布得不充分。实验也证明,batch_size取得大一点, 数据shuffle的好一点,BatchNormalization的效果就越好。
不能很方便地用于RNN。这其实是第一个问题的引申。我们再来看一下Figure 6中的均值和方差的计算公式。对所有样本求均值。对于图片这类等长的输入来说,这很容易操作,在每个维度加加除除就可以了,因为维度总是一致的。而对于不等长的文本来说,RNN中的每个time step共享了同一组权重。在应用BatchNormalization时,这就要求对每个time step的batch_size个输入计算一个均值和方差。那么问题就来了,假如有一个句子S非常长,那就意味着对S而言,总会有个time_step的batch_size为1,均值方差没意义,这就导致了BatchNormalization在RNN上无用武之地了。
为了避免这两个问题,LayerNormalization就应运而生了。
LayerNormalization的主要变化在于:
不再对Mini-Batch中的N的样本在各个维度做归一化,而是针对同一层的所有神经元做归一化。归一化公式为:
其中,H指的是一层神经网络的神经元个数。我们再回想下BatchNormalization,其实它是在每个神经元上对batch_size个数据做归一化,每个神经元的均值和方差均不相同。而LayerNormalization则是对所有神经元做一个归一化,这就跟batch_size无关了。哪怕batch_size为1,这里的均值和方差只和神经元的个数有关系(如果读到这里仍然感到不是特别清楚,再读两遍,还困惑也没关系,待会看)。
测试的时候可以直接利用LN,所以训练时不用保存均值和方差,这节省了内存空间。
两种方式的区别。假设有N个样本,每个样本的特征维度为4,图中每个小圆代表一个特征,特征1,特征2等等,特征4。BatchNormalization是在N个同一特征(如特征1)上求均值和方差,这里要对每个特征求1次,共4次。对照一下上面说的,万一有个样本有5个特征,是不是就没法玩了。LayerNormalization呢,别的样本都和我没啥关系,有多少个特征我把这些特征求个均值方差就好了。这也就是为什么一个叫”批归一化“,另一个叫”层归一化“了。理解了这一点,也就理解了为什么Transformer中使用LN而不是BN。
当然BatchNormalization也不是吃素的,虽然它在处理不等长序列上存在天生的缺陷,但是除此之外,它的效果都要好于其他Normalization方式(比如LN,WN,IN)。直觉上,BN貌似更好理解一点,LN似乎有种胡子眉毛一把抓的感觉。
免责声明:本文来自互联网新闻客户端自媒体,不代表本网的观点和立场。
合作及投稿邮箱:E-mail:editor@tusaishared.com
上一篇:[深度学习] 深度可分离卷积
热门资源
Python 爬虫(二)...
所谓爬虫就是模拟客户端发送网络请求,获取网络响...
TensorFlow从1到2...
原文第四篇中,我们介绍了官方的入门案例MNIST,功...
TensorFlow从1到2...
“回归”这个词,既是Regression算法的名称,也代表...
机器学习中的熵、...
熵 (entropy) 这一词最初来源于热力学。1948年,克...
TensorFlow2.0(10...
前面的博客中我们说过,在加载数据和预处理数据时...
智能在线
400-630-6780
聆听.建议反馈
E-mail: support@tusaishared.com