Abstract:当前神经网络层之前的神经网络层的参数变化,引起神经网络每一层输入数据的分布产生了变化,这使得训练一个深度神经网络(DeepNeural Networks)变得复杂。这样就要求使用更小的学习率,参数初始化也需要更为谨慎的设置。并且由于非线性饱和(注:如sigmoid**函数的非线性饱和问题),训练一个深度神经网络会非常困难。我们称这个现象为:internal covariate shif;同时利用归一化层输入解决这个问题。

/*这里介绍一个术语Internal Covariate Shift

由于在训练时某一层的参数的更新改变后,会导致该层网络的输出(下一层的输入)的分布是变化的,这样使得训练DNN很复杂。这使得我们必须使用较小的学习率及较好的权重初值,这样会导致训练很慢,同时也导致使用saturating nonlinearities(饱和非线性) **函数(如sigmoid,正负两边都会饱和)时训练很困难。这种现象我们称为“internal covariate shift”,解决这种问题我们normalizing(归一化)网络层的输入。*/

我们将归一化层输入作为神经网络的结构,并且对每一个小批量训练数据执行这一操作。Batch Normalization(BN) 能使用更高的学习率,并且不需要过多的注重参数初始化问题。BN 的过程与正则化相似,在某些情况下可以去除Dropout。将BN应用到一个state-of-the-art的图片分类模型中时,使用BN只要1/14的训练次数就能够达到同样的精度。使用含有BN神经网络模型能提升现有最好的ImageNet分类结果:在top-5 验证集中达到4.9%的错误率(测试集为4.8%),超出了人类的分类精度。

 

1 Introduction

  深度学习极大的促进了许多领域的发展,如视觉、语音以及其他领域。随机梯度下降法(SGD)已经证明能够有效的训练深度神经网络,并且在SGD中加入momentum和Adgrad变量也达到了最好的性能。SGD优化参数 θ 来最小化损失函数

论文-阅读翻译理解笔记-Batch Normalization Accelerating Deep Network Training by Reducing Inter

,其中X1…N 为训练数据集。在使用SGD时,每次迭代我们使用一个大小为m的小批量数据X1…m。通过计算

论文-阅读翻译理解笔记-Batch Normalization Accelerating Deep Network Training by Reducing Inter

来逼近损失函数关于权值的梯度。在迭代过程中使用小批量数据相比使用一个样本有几个好处。首先,由小批量数据计算而来的损失函数梯度是由整个训练数据集的损失函数梯度的估计。并且随着小批量数据大小的增加,其性能会越好。其次,由于现代计算平台的并行性,小批量训练会比单个样例训练更高效。

  尽管随机梯度下降法简单有效,但却需要谨慎的调整模型的参数,特别是在优化过程中加入学习率和参数初始化方式的选择。每一层的输入都会受之前所有层的参数影响,并且随着网络越深,即使参数的变化很小也为对每一层的输入产生很大的影响。这使得训练一个网络变得十分复杂。

神经网络层输入分布的改变,使得神经网络层必须不停的适应新的数据分布。当一个学习系统的输入数据分布产生变化,我们称这种现象为:Experience Covariate Shift. 解决这种现象的典型方法是领域适应。然而,Covariate Shift的概念的适用性能够从整个学习系统扩展到该系统的一部分,比如一个子网络或者其中的一层。考虑一个网络计算

论文-阅读翻译理解笔记-Batch Normalization Accelerating Deep Network Training by Reducing Inter

来逼近损失函数关于权值的梯度。在迭代过程中使用小批量数据相比使用一个样本有几个好处。首先,由小批量数据计算而来的损失函数梯度是由整个训练数据集的损失函数梯度的估计。并且随着小批量数据大小的增加,其性能会越好。其次,由于现代计算平台的并行性,小批量训练会比单个样例训练更高效。

  尽管随机梯度下降法简单有效,但却需要谨慎的调整模型的参数,特别是在优化过程中加入学习率和参数初始化方式的选择。每一层的输入都会受之前所有层的参数影响,并且随着网络越深,即使参数的变化很小也为对每一层的输入产生很大的影响。这使得训练一个网络变得十分复杂。

神经网络层输入分布的改变,使得神经网络层必须不停的适应新的数据分布。当一个学习系统的输入数据分布产生变化,我们称这种现象为:Experience Covariate Shift. 解决这种现象的典型方法是领域适应。然而,Covariate Shift的概念的适用性能够从整个学习系统扩展到该系统的一部分,比如一个子网络或者其中的一层。考虑一个网络计算

论文-阅读翻译理解笔记-Batch Normalization Accelerating Deep Network Training by Reducing Inter

其中 F1 和 F2 是任意的变换函数。通过学习参数 θ1 和 θ2 来最小化 ll 。θ2 的学习:如果 X=F1(u,θ1 为子网络的输入,那么

论文-阅读翻译理解笔记-Batch Normalization Accelerating Deep Network Training by Reducing Inter

则 θ2 的更新为 (m:批量数据的样本数;α :学习率)

论文-阅读翻译理解笔记-Batch Normalization Accelerating Deep Network Training by Reducing Inter

因此,输入数据分布相同这一特性,使得子网络更容易训练。这与训练数据和测试数据有相同的分布是相似的。因此保持X的分布不变是有利的。这样,θ2 就不需要为了弥补 X 的分布的改变而重新进行调整。

  保持一个子网络的输入数据分布不变,对该子网络以外的隐藏层也有积极的作用。考虑一层**函数为sigmoid函数的神经网络层 z=g(Wu+b),其中 u为该层的输入,权值矩阵 W 和偏置 b 为该层需要学习的参数,g(x)=1/1+exp(−x). 随着 |x| 的增大,g′(x)趋向0 (因为g(x)→1g(x)→1)。这意味着在 x=Wu+b 的每一维中除了绝对值较小的,其他的流向 uu 的误差会消失,同时模型的训练变得很缓慢。而同时 x 是由 W,b 以及该层以下的全部神经网络层的参数决定的,所有在训练期间改变这些参数有可能使x 中许多维偏移到非线性饱和端,从而降低了收敛速度。并且这个影响会随着网络层数的增加而加剧。在实际中非线性饱和端问题以及梯度弥散问题经常用ReLU,合适的初始化以及较小的学习率。如果我们能够确保非线性输入的数据分布更稳当的话,那么出现非线性饱和端问题的概率则会更小,并且能够加速网络的训练。

  我们称在训练深度神经网络的过程中,网络内部节点的分布发生变换这一现象为,Internal CovariateShift.。而消除这个现象能够加速网络的训练。我们提出了Batch Normalization ,通过减少依赖参数缩放和初始化,进而缓解Internal Covariate Shift,并动态的加速深度神经网络的训练速度。BN允许使用更高的学习率,而不会有发散的风险。进一步的,BN能够正则化模型,并且不需要Dropout。最后,BN能够使用s型**函数,同时不会陷入饱和端。

  在4.2小节我们将BN加入一个分类模型,该模型在ImageNet中的表现最好。结果显示BN只需要使用之前的7%训练数次,就能够达到该模型的分类精度,并且最终能够明显的提高分类精度。通过利用嵌有BN 的已训练好的模型,我们获得top-5的错误率,这超出了在ImageNet 的已知分类精度。

2 TowardsReducing Internal Covariate Shift

  我们将 Internal Covariate Shift 定义为:在神经网络的训练过程中,由于参数改变,而引起的神经网络**值分布的改变。我们通过缓解 Internal Covariate Shift 来提高训练。在训练的过程中保持神经网络层输入的分布不变,来提高训练数据。我们已经知道,在训练的过程中加入白化处理能,如0均值1方差化和去相关化,能够加速模型的收敛。当每一层的输入来自该层之前的神经网络层,对于每一层的输入来说很容易获得相同的白化。通过对每一层的输入进行白化处理,我们能够保持输入的分布,从而消除 Internal Covariate Shift 的病态影响。

我们可以在每一步的训练中白化**值,也可以通过直接调整模型的结构或者依照**值来修改优化函数的参数进行白化。然而,如果这些方法在优化步骤中执行,那么在更新参数的时候,必须先计算归一化后的**值的误差,这降低了梯度下降法的效果。(个人理解:归一化不能在求的**值之后进行,不然流到下一层参数的误差值会越来越小,从而影响模型的学习,也就是梯度弥散问题。)举个例子,考虑一层神经网络层, u 为输入, b 为偏置值。并且对该神经网络层的**值减均值归一化:x^=x−E[x] ,其中 x=u+b,χ={x1...N}为由训练数据集生成的该神经网络层输入的一个集合(训练数据集 XX 前向传播到该层),E[x]=1N∑Ni=1xi。如果 bb 的梯度与 E[x] 无关,有 b←b+∇b,∇b∝−∂l/∂x^。则 u+(b+∇b)−E[u+(b+∇b)]=u+b−E[u+b](注:=x−E[x])。因此当归一化和参数 bb 的更新同时进行的时候,会使该神经网络层的输出没有变化,进一步的导致损失函数的值没有变化。随着训练的继续,b一直在增长而损失函数的值却一直不变。当归一化操作不仅中心化**值,同时对其进行缩放,这个现象会更严重。在初步的实验中我们观察到,如果归一化参数不在梯度下降中计算的话,会使模型参数膨胀。

上述方法的问题在于,梯度下降没有考虑归一化的情况。为了处理该问题,我们要确保对于任何参数,神经网络都由期望分布产生**值。这样就能使模型参数的损失函数梯度都把归一化的情况考虑进去。与之前的例子相同,向量 x 为一层神经网络层的输入,χ 为由训练数据集生成的该神经网络层输入的一个集合。那么归一化操作为

论文-阅读翻译理解笔记-Batch Normalization Accelerating Deep Network Training by Reducing Inter

该归一化操作不仅考虑了 xx ,同时还考虑了所有的训练样本 χ 。如果 xx 是由其他层产生的,那么 χ 中的所有样例都依赖于 θ 。对于反向传播算法,我们就需要计算

论文-阅读翻译理解笔记-Batch Normalization Accelerating Deep Network Training by Reducing Inter

如果忽略了后面那一项,就会出现之前描述的模型参数膨胀问题。根据这个框架,白化操作的计算量非常大。因为白化需要计算协方差矩阵 Cov[x]=Ex∈χ[xxT]−E[x]E[xT]、协方差矩阵的负平方根来产生白化**值 Cov[x]−1/2(x−E[x])以及归一化相对于的梯度。这就驱使我们寻找一种可微,并且在参数更新的时候不需要对整个训练数据集进行分析的神经网络层输入归一化方法。

前人的一些方法,如利用统计学计算单个训练样本,或者在用于图像处理的神经网络中,根据不同的局部区域选择不同的特征图。然而,由于去掉了**值的绝对值缩放,而改变了网络的表征能力。我们希望通过同时考虑单个训练样本和整个训练样本集的统计信息来归一化**值,从而在网络中保留更多的信息。

3 Normalization via Mini-Batch Statistics

  因为对于每一层的输入进行白化花费较高,并且也不是处处可微,所有我们做了两个必要的简化。第一是,我们对标量特征进行单独的进行零均值一方差归一化,来代替白化同时对层的输入和输出同时进行归一化。对于有 dd 维输入 x=(x(1)...x(d)) 的神经网络层,我们将利用下试归一化每一维:

论文-阅读翻译理解笔记-Batch Normalization Accelerating Deep Network Training by Reducing Inter

上式中的期望和方差由训练数据集计算得到。根据LeCun 的一篇论文,该归一化能够加速收敛,甚至是特征之间没有相关性。

  简单的归一化神经网络层的输入,可能会改变该层的表征能力。例如,对 sigmoid 函数的输入进行归一化,会使归一化后的输入趋向 s 型函数的线性端。为了避免这样的情况出现,我们确保穿插在网络内部的变换能够表示同样的变换。为了达到这样的目的,我们对每一个**值 x(k) 都引入一对参数 γ(k)和β(k),这两个参数能够缩放和平移归一化后的输入:(打个比方,比如我网络中间某一层学习到特征数据本身就分布在S型**函数的两侧,你强制把它给我归一化处理、标准差也限制在了1,把数据变换成分布于s函数的中间部分,这样就相当于我这一层网络所学习到的特征分布被你搞坏了,这可怎么办?于是文献使出了一招惊天地泣鬼神的招式:变换重构,引入了可学习参数γ、β,这就是算法关键之处

论文-阅读翻译理解笔记-Batch Normalization Accelerating Deep Network Training by Reducing Inter

论文-阅读翻译理解笔记-Batch Normalization Accelerating Deep Network Training by Reducing Inter

这两个参数与模型原始的参数一起学习,并恢复了模型的表征能力,可以恢复出原始的某一层所学习的特征的。当 ,就能够求得原来的**值。 

神经网络的训练是基于整个训练数据集的,在batch的设置中,我们可以用整个训练数据集来归一化**值。但是,当我们使用随机梯度下降法的时候这一选择是不实际的。因此我们做了第二个简化:在随机梯度下降中我们采用mini-batch的方式,这样我们就能够通过每个mini-batch为每个**值计算出对应的均值和方差。通过这样的方式,归一化所需统计信息就能够完全被考虑到梯度下降中去。利用mini-batch就能计算每一维**值的方差,而不是计算所有**值的协方差矩阵。如果是计算协方差矩阵的话,batch的数量可能比**值向量的大小还要小,这样就会产生奇异协方差矩阵。

假设有一个mini-batch B,其大小为 m 。因为是对**值的每一维进行归一化,所有我们只考虑其中的一个**值 x(k),同时在下文中忽略 k。那么在一个mini-batch中我们有 m 个**值,

B={x1...m}.

x^1...m为归一化后的值,同时 y1...m为 x^1...m的线性变换。于是有BN变换:

BNγ,β:x1...m→y1...m

算法1为BN变换,其中 ε是一个常数(趋于0),为了保证计算方差时的稳定性

论文-阅读翻译理解笔记-Batch Normalization Accelerating Deep Network Training by Reducing Inter

论文-阅读翻译理解笔记-Batch Normalization Accelerating Deep Network Training by Reducing Inter

论文-阅读翻译理解笔记-Batch Normalization Accelerating Deep Network Training by Reducing Inter

BN变换能被加入网络中,并对任何的**值执行BN变换。在等式 y=BNγ,β(x) 中,我们引入了两个需要学习的参数 γ,β。但需要注意的是,BN变换不仅仅与单个训练样本相关,也与mini-batch中的其他训练样本有关。由缩放和平移变换而来的 y 作为下一层的输入。虽然归一化**值 x^ 被包含在BN变换中,但却是非常重要的存在。由于mini-batch中的样本都来自同一个分布,因此在忽略 ε 的情况下, x^x^ 中的每一个元素都为0均值1方差分布。即。每个x^(k)可看做含有线性变换以及原始网络其他操作的子网络的输入。子网络的输入保持着相同的均值和方差,并允许归一化后不同的 x^(k)之间的联合概率分布在训练过程中可变。我们希望这一归一化能够加速子网的训练,并最终加速整个网络的训练。

在训练过程中我们需要计算流过BN变换的误差,同时也要计算BN变换中涉及到的参数的误差。利用链式规则:

论文-阅读翻译理解笔记-Batch Normalization Accelerating Deep Network Training by Reducing Inter

论文-阅读翻译理解笔记-Batch Normalization Accelerating Deep Network Training by Reducing Inter

个人理解:因为方差是由mini-batch中的每一个样本计算而来的,所有求方差的梯度时候必须考虑到所有的样本,即有前面的求和。)

论文-阅读翻译理解笔记-Batch Normalization Accelerating Deep Network Training by Reducing Inter

论文-阅读翻译理解笔记-Batch Normalization Accelerating Deep Network Training by Reducing Inter

个人理解:,因为均值是由mini-batch中的每一个样本计算而来的,所有求方差的梯度时候必须考虑到所有的样本,即有前面的求和;另外由于方差的计算需要用到均值也就有了加号后面的项。)

论文-阅读翻译理解笔记-Batch Normalization Accelerating Deep Network Training by Reducing Inter

论文-阅读翻译理解笔记-Batch Normalization Accelerating Deep Network Training by Reducing Inter

(个人理解:,因为x^ix^i、方差和均值均与 xixi 有关,所以求其梯度时必须考虑上述三个变量。)

 

因此BN变换是将归一化**值引入神经网络的一种可微变换。这确保了网络可训练性,以及神经网络层能够持续学习输入数据分布。从而能够减少Internal Covariate Shift发生,同时加速网络的训练。进一步的,将学习好的仿射变换应用到归一化**值中,能够允许BN变换比表示同样的变换,进而保存神经网络的表征能力。  

附:为什么减均值、白化可以加快训练呢,这里做一个简单地说明

首先,图像数据是高度相关的,假设其分布如下图a所示(简化为2维)。由于初始化的时候,我们的参数一般都是0均值的,因此开始的拟合y=Wx+b,基本过原点附近,如图b红色虚线。因此,网络需要经过多次学习才能逐步达到如紫色实线的拟合,即收敛的比较慢。如果我们对输入数据先作减均值操作,如图c,显然可以加快学习。更进一步的,我们对数据再进行去相关操作,使得数据更加容易区分,这样又会加快训练,如图d。

论文-阅读翻译理解笔记-Batch Normalization Accelerating Deep Network Training by Reducing Inter

白化的方式有好几种,常用的有PCA白化

 

即对数据进行PCA降维操作之后,在进行方差归一化。这样数据基本满足0均值、单位方差、弱相关性。如果考虑对每一层数据都使用白化操作,但分析认为这是不可取的。因为白化需要计算协方差矩阵、求逆等操作,计算量很大,此外,反向传播时,白化操作不一处处可导

我们知道网络一旦train起来,那么参数就要发生更新,除了图像数据输入层的数据外(因为输入层数据,我们已经人为的为每个样本归一化),后面网络每一层的输入数据分布是一直在发生变化的,因为在训练的时候,前面层训练参数的更新将导致后面层输入数据分布的变化。以网络第二层为例:网络的第二层输入,是由第一层的参数和input计算得到的,而第一层的参数在整个训练过程中一直在变化,因此必然会引起后面每一层输入数据分布的改变。我们把网络中间层在训练过程中,数据分布的改变就是前面提到的“Internal Covariate Shift”术语。Paper所提出的BN算法,就是要解决在训练过程中,中间层数据分布发生改变的情况,于是就有了BatchNormalization,这个算法的诞生。

 

BN的应用:BN可以应用于一个神经网络的任何神经元上。把BN变换,置于网络**函数层的前面。在没有采用BN的时候,**函数层是这样的:

 

也就是我们希望一个**函数,比如s型函数s(x)的自变量x是经过BN处理后的结果。因此前向传导的计算公式就应该是:

其实因为偏置参数b经过BN层后其实是没有用的,最后也会被均值归一化,当然BN层后面还有个β参数作为偏置项,所以b这个参数就可以不用了。因此最后把BN层和**函数层就变成了:

BN层是对于每个神经元做归一化处理,甚至只需要对某一个神经元进行归一化,而不是对一整层网络的神经元进行归一化。既然BN是对单个神经元的运算,那么比方说在CNN中卷积层上要怎么搞?假如某一层卷积层有6个特征图,每个特征图的大小是100*100,这样就相当于这一层网络有6*100*100个神经元,如果采用BN,就会有6*100*100个参数γ、β,这样岂不是太恐怖了。因此卷积层上的BN使用,其实也是使用了类似权值共享的策略,把一整张特征图当做一个神经元进行处理。

 

卷积神经网络经过卷积后得到的是一系列的特征图,如果min-batch sizes为m,那么网络某一层输入数据可以表示为四维矩阵(m,f,p,q),m为min-batchsizes,f为特征图个数,p、q分别为特征图的宽高。在cnn中我们可以把每个特征图看成是一个特征处理(一个神经元),因此在使用Batch Normalization,mini-batch size 的大小就是:m*p*q,于是对于每个特征图都只有一对可学习参数:γ、β。说白了吧,这就是相当于求取所有样本所对应的一个特征图的所有神经元的平均值、方差,然后对这个特征图神经元做归一化。

 

 

BN使用:

Learning Rate

论文中应该给出的是稍大,而不是无限大。

事实上,你要是给个比较大的学习率,还是会导致目标函数发散。

包括在训练后期,你要不把学习率降低量级,训练有很大可能从函数谷面跑飞过去了。(亲测)

个人推测,应该是、、被均衡后,量级得到收缩,允许稍大的学习率存在。

二阶近似优化方案,ADADELTA以及RMSPROP,免除人工干扰学习率的困扰。

Dropout

从我实际测试来看,非常不鼓励扔掉Dropout

Batch Norm根本压不住大模型在训练后期的过拟合。

我甚至还是保留着50%的Dropout,速度也还不错。

Dropout的两个作用:稀疏与动态平均,不仅从数值上抑制过拟合。

在表征训练方面,也有一定的regularize效果。

编程技巧

BN有两种写法,合并式和分离式。

Caffe master branch采用的是分离式写法,CONV层扔掉bias,接一个BN层,再接一个带bias的SCALE层。

我个人更推崇合并式写法,这样在深度网络定义文件中,可以不用眼花缭乱。

从执行速度来看,合并式写法需要多算一步bias

分离式写法,在切换层传播时,OS需要执行多个函数,在底层(比如栈)调度上会浪费一点时间。

可以说,各有优劣。默认推荐https://github.com/ducha-aiki/caffe的合并式写法。

分离式写法,见官方master branch

代码

默认实现在我的Dragon框架下,只提供GPU代码,Caffe稍作修改即可,CPU也稍作修改即可。

(注意dragon_copy和caffe的是相反的)

https://github.com/neopenx/Dragon/blob/master/Dragon/layer_include/common_layers.hpp

https://github.com/neopenx/Dragon/blob/master/Dragon/layer_src/batch_norm_layer.cpp

(forward、backward是错的,参考cu文件里的写法)

https://github.com/neopenx/Dragon/blob/master/Dragon/layer_src/batch_norm.cu

还有proto

message BatchNormParameter{

   optional bool use_global_stats=1 [default=true];

   optional float decay=3 [default=0.95];

   optional float eps=2 [default=1e-10];

}

 

 

message LayerParameter{

   .......

   optional BatchNormParameter batch_norm_param=xxx;

   .......

}

 精度eps推荐1e-10,1e-5在cifar10中已经过大了。

Caffe的BN实现:https://github.com/ducha-aiki/caffe/tree/bn

cxxnet的BN实现:https://github.com/antinucleon/cxxnet

初始化

论文里没说,https://github.com/ducha-aiki/caffe/blob/elu/examples/BN-nator.ipynb中给出的方案是:

为常数0.0000001,为常数1.0000001

我测了几次,发现用0和1的效果好像随机出来不是很好,推测是精度问题?还是我人品太差了?

全局统计测试

论文默认推荐是开启全局统计测试,也就是记录每次batch的均值和方差。

在测试的时候,用累积和的期望值。无偏估计的系数可以忽略,意义不大。

我与ducha-aiki的方案不同之处,在于用blob[4]记录总batch数量,

在训练的时候,利用:

(均值*数量+新值)/(数量+1)来更新

在测试的时候,直接copy过来,然后做norm。

在cifar10测试中,我发现,对于batch为100的验证集,精度会比不做全局统计差很多。

可能是,训练次数过低,导致的全局统计值不是很稳定。

在追加了一定训练次数之后,在cifar10 quick epoch12时,

差距仍然达到了8%,(66% vs74%)。

所以不推荐在测试数据充裕的情况下,做全局统计测试,往往会得到不好的结果。(写论文注意)

相反,对于实际使用的时候,测试数据就几个,这时候做一做效果还是可以的。

不过还是看人品,没准就偏移大了,不准了,这大概是Batch Norm唯一不好的地方吧。

—————————————————————————————————————————————————

在epoch达到60后,这种方法的测试精度已经退化到40%了。

仔细想了一下,发现做纯平均是错的,因为前后更新的重要度不一样。

一般我们认为,最新更新的比较重要。

所以改用ducha-aiki的movingaverage decay的方案。

设置decay=0.95

每次更新的时候,最新量0.95+0.05*history,这种平均比纯平均期望意义更大。

后者在训练末期,数值体系已经被纯平均搞得崩溃了。

使用这种滑动平均期望后,默认的验证和测试,开启全局统计就没问题了。

随机抖动

使用Batch Norm之后,每次跑程序的时候,在初期,训练似然和验证精度都有很大的变化。

有时候特别好,有时候特别差,相当不稳定。

推测应该是normalize之后,放大了随机初始化的差异问题,这个在写代码debug的时候需要注意。

多测几次,不要误判为bug

适用范围

https://github.com/ducha-aiki/caffe/blob/elu/examples/BN-nator.ipynb中,

我们可以看到,所有CONV和INNER_PRODUCT层都是可以做Batch Norm的。

实际测试的时候,因为波动、以及层数少的问题,没发现什么异常。

用法如下(不要像**函数那样用成in-place)

layer{

   name:"bn1"

   type:"BatchNorm"

   bottom:"conv1"

   top:"bn1"

}

—————————————————————————————————————————————————

由于INNER_PRODUCT层后一般习惯接DROPOUT,而且INNER_PRODUCT一般处于反向链式

前端,所以INNER_PRODUCT上的Batch Norm可能显得多余,我用浅层模型没有测出来较大的差异。

计算代价

注意论文中的:

在实现的时候,是可以优化的,主要是提取公因子,x_norm.diff、-1/m,以及sqrt(..)项都可以提出来。

具体需要仔细琢磨,x_norm.diff计算出来之后,下面那几段收缩、扩展的代码,相当经典。

尽管如此,BatchNorm的计算代价还是相当大的,我觉得比卷积层还大。

所以CPU党可以不用尝试了,逐层Batch Norm实在是太慢了。论文-阅读翻译理解笔记-Batch Normalization Accelerating Deep Network Training by Reducing Inter

相关文章:

  • 2021-12-18
  • 2022-12-23
  • 2021-08-31
  • 2021-12-29
  • 2021-08-18
  • 2021-12-19
猜你喜欢
  • 2021-08-24
  • 2021-08-12
  • 2021-05-09
  • 2021-09-29
  • 2021-09-12
  • 2022-12-23
  • 2021-12-28
相关资源
相似解决方案