『教程』Batch Normalization 层介绍html
知乎:详解深度学习中的Normalization,BN/LN/WNpython
独立同分布的数据能够简化常规机器学习模型的训练、提高机器学习模型的预测能力网络
去除特征之间的相关性 —> 独立;框架
使得全部特征具备相同的均值和方差 —> 同分布。dom
深度神经网络涉及到不少层的叠加,而每一层的参数更新会致使上层的输入数据分布发生变化,经过层层叠加,高层(抽象程度高)的输入分布变化会很是剧烈,这就使得高层须要不断去从新适应底层的数据更新机器学习
Google 将这一现象总结为 Internal Covariate Shif:ide
统计机器学习中的一个经典假设是“源空间(source domain)和目标空间(target domain)的数据分布(distribution)是一致的”。若是不一致,那么就出现了新的机器学习问题,如 transfer learning / domain adaptation 等。函数
而 covariate shift 就是分布不一致假设之下的一个分支问题,它是指源空间和目标空间的条件几率是一致的,可是其边缘几率不一样,即:对全部
,post
可是学习
你们细想便会发现,的确,对于神经网络的各层输出,因为它们通过了层内操做做用,各层的输入信号的分布显然不一样,并且差别会随着网络深度增大而增大,但是它们所能“指示”的样本标记(label)仍然是不变的,这便符合了covariate shift的定义。因为是对层间信号的分析,也便是“internal”的来由。
问题描述简而言之,每一个神经元的输入数据再也不是“独立同分布”。
其一,上层参数须要不断适应新的输入数据分布,下降学习速度。
其二,下层输入的变化可能趋向于变大或者变小,致使上层落入饱和区,使得学习过早中止。
其三,每层的更新都会影响到其它层,所以每层的参数更新策略须要尽量的谨慎。
咱们以神经网络中的一个普通神经元为例。神经元接收一组输入向量
经过某种运算后,输出一个标量值:
因为 ICS 问题的存在, 对于某一特定层,不一样批次的输入 的分布可能相差很大。
要解决独立同分布的问题,“理论正确”的方法就是对每一层的数据都进行白化操做。然而标准的白化操做代价高昂,特别是咱们还但愿白化操做是可微的,保证白化操做能够经过反向传播来更新梯度。
在将 送给神经元以前,先对其作平移和伸缩变换, 将
的分布规范化成在固定区间范围的标准分布。
通用变换框架就以下所示:
(1) 是平移参数(shift parameter),
是缩放参数(scale parameter)。经过这两个参数进行 shift 和 scale 变换:
获得的数据符合均值为 0、方差为 1 的标准分布。
(2) 是再平移参数(re-shift parameter),
是再缩放参数(re-scale parameter)。将 上一步获得的
进一步变换为:
最终获得的数据符合均值为 、方差为
的分布。
第一次变换获得均值为 0、方差为 1 的标准分布,表达能力有限,下层神经元可能很努力地在学习,但不论其如何变化,其输出的结果在交给上层神经元进行处理以前,将被粗暴地从新调整到这一固定范围。为了更好的应用底层神经网络的学习结果,咱们将规范化后的数据进行再平移和再缩放,使得每一个神经元对应的输入范围是针对该神经元量身定制的一个肯定范围(均值为 、方差为
)。rescale 和 reshift 的参数都是可学习的,这就使得 Normalization 层能够学习如何去适应底层的学习结果。
除了充分利用底层学习的能力,另外一方面的重要意义在于保证得到非线性的表达能力。
Sigmoid 等激活函数在神经网络中有着重要做用,经过区分饱和区和非饱和区,使得神经网络的数据变换具备了非线性计算能力。而第一步的规范化会将几乎全部数据映射到激活函数的非饱和区(线性区),仅利用到了线性变化能力,从而下降了神经网络的表达能力。而进行再变换,则能够将数据从线性区变换到非线性区,恢复模型的表达能力。
不添加正则化, 的均值取决于下层神经网络的复杂关联;添加本层后,取值
仅由
来肯定,去除了与下层计算的密切耦合。新参数很容易经过梯度降低来学习,简化了神经网络的训练。
a)BN的实际做用
标准白化操做的目的是“独立同分布”。独立就不说了,暂不考虑。变换为均值为 、方差为
的分布,也并非严格的同分布,只是映射到了一个肯定的区间范围而已(因此,这个问题仍然有研究空间)。
另外有人提出:BN其优点并不是解决了独立同分布的问题(实际上它也没解决),其最大意义在于解决了梯度弥散问题,见论文:How Does Batch Normalization Help Optimization?(知乎上的一篇阅读笔记:为何Batch Normalization那么有用?)。文章结论以下:
其做用为防止梯度爆炸或弥散、能够提升训练时模型对于不一样超参(学习率、初始化)的鲁棒性、可让大部分的激活函数可以远离其饱和区域。
b) BN对小批次训练效果很差
当单个小批次(minibatch)的数据不能表明整个数据的分布时,BN的表现就会不尽如人意,这意味着忘记将输入随机打乱顺序的状况下使用批归一化是很危险的,实际上batch太小的时候就不太适合开放BN的可训练性。具体讨论见论文:Batch Normalization: Accelerating Deep Network Training by Reducing。
使用 BN 的目的就是为了保证每批数据的分布稳定,使用全局统计量反而违背了这个初衷;
BN 的做者认为在训练时采用移动平都可能会与梯度优化存在冲突
BatchNorm:batch方向作归一化,算N*H*W的均值
LayerNorm:channel方向作归一化,算C*H*W的均值
InstanceNorm:一个channel内作归一化,算H*W的均值
GroupNorm:将channel方向分group,而后每一个group内作归一化,算(C//G)*H*W的均值
https://zhuanlan.zhihu.com/p/69659844
于2015年由 Google 提出,BN 独立地规范化每个层不一样批次的 ,但规范化的参数是一个 mini-batch 的一阶统计量和二阶统计量。这就要求 每个 mini-batch 的统计量是总体统计量的近似估计,或者说每个 mini-batch 彼此之间,以及和总体数据,都应该是近似同分布的。分布差距较小的 mini-batch 能够看作是为规范化操做和模型训练引入了噪声,能够增长模型的鲁棒性;但若是每一个 mini-batch的原始分布差异很大,那么不一样 mini-batch 的数据将会进行不同的数据变换,这就增长了模型训练的难度。训练时,网络会记录每个batch滑动平均的均值和方差,训练结束的时候这四个参数就固定了供测试时直接加载使用。
BN 比较适用的场景是:每一个 mini-batch 比较大,数据分布比较接近。在进行训练以前,要作好充分的 shuffle,不然效果会差不少。
另外,因为 BN 须要在运行过程当中统计每一个 mini-batch 的一阶统计量和二阶统计量,所以不适用于 动态的网络结构 和 RNN 网络。不过,也有研究者专门提出了适用于 RNN 的 BN 使用方法,这里先不展开了。
LN 针对单个训练样本进行,不依赖于其余数据,所以能够避免 BN 中受 mini-batch 数据分布影响的问题,能够用于 小 mini-batch 场景、动态网络场景和 RNN,特别是天然语言处理领域。此外,LN 不须要保存 mini-batch 的均值和方差,节省了额外的存储空间。
可是,BN 的转换是针对单个神经元可训练的——不一样神经元的输入通过再平移和再缩放后分布在不一样的区间,而 LN 对于一整层的神经元训练获得同一个转换——全部的输入都在同一个区间范围内。若是不一样输入特征不属于类似的类别(好比颜色和大小),那么 LN 的处理可能会下降模型的表达能力。
在GAN和style transfer的任务中,目前的IN norm要好于BN,IN主要用于对单张图像的数据作处理,而BN主要是对Bacth的数据作处理。因为BN在训练时每一个batch的均值和方差会因为shuffle都会改变,因此能够理解为一种数据加强,而IN能够理解为对数据作一个归一化的操做。
换句话说,BN的计算是要受其余样本影响的,因为每一个batch的均值和标准差不稳定,对于单个数据而言,相对因而引入了噪声,但在分类这种问题上,结果和数据的总体分布有关系,所以须要经过BN得到数据的总体分布。而instance norm的信息都是来自于自身的图片,至关于对全局信息作了一次整合和调整,在图像转换这种问题上,BN得到的总体信息不会带来任何收益,带来的噪声反而会弱化实例之间的独立性:这类生成式方法,每张图片本身的风格比较独立不该该与batch中其余的样本产生太大联系。
group normalization是2018年3月份何恺明大神的又一力做,优化了BN在比较小的mini-batch状况下表现不太好的劣势。批量维度进行归一化会带来一些问题——批量统计估算不许确致使批量变小时,BN 的偏差会迅速增长。在训练大型网络和将特征转移到计算机视觉任务中(包括检测、分割和视频),内存消耗限制了只能使用小批量的BN。事实上,GN的极端状况就是LN和IN,分别对应G等于C和G等于1。
tf实现并不复杂,以下
def GroupNorm(x,G=16,eps=1e-5): N,H,W,C=x.shape x=tf.reshape(x,[tf.cast(N,tf.int32), tf.cast(H,tf.int32), tf.cast(W,tf.int32), tf.cast(G,tf.int32), tf.cast(C//G,tf.int32)]) mean,var=tf.nn.moments(x,[1,2,4],keep_dims=True) x=(x-mean)/tf.sqrt(var+eps) x=tf.reshape(x,[tf.cast(N,tf.int32), tf.cast(H,tf.int32), tf.cast(W,tf.int32), tf.cast(C,tf.int32)]) gamma = tf.Variable(tf.ones(shape=[1,1,1,tf.cast(C,tf.int32)]), name="gamma") beta = tf.Variable(tf.zeros(shape=[1,1,1,tf.cast(C,tf.int32)]), name="beta") return x*gamma+beta
在深度学习没有火起来以前,提取特征一般是使用SIFT,HOG和GIST特征,这些特征有一个共性,都具备按group表示的特性,每个group由相同种类直方图的构建而成,这些特征一般是对在每一个直方图(histogram)或每一个方向(orientation)上进行组归一化(group-wise norm)而获得。
从深度学习上来说,彻底能够认为卷积提取的特征是一种非结构化的特征或者向量,拿网络的第一层卷积为例,卷积层中的的卷积核filter1和此卷积核的其余通过transform过的版本filter2(transform能够是horizontal flipping等),在同一张图像上学习到的特征应该是具备相同的分布,那么,具备相同的特征能够被分到同一个group中,按照我的理解,每一层有不少的卷积核,这些核学习到的特征并不彻底是独立的,某些特征具备相同的分布,所以能够被group。