一、背景意义

2015年在深度学习领域,有一篇非常值得学习的一篇文献:《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》。

BN算法目前已经被大量的应用,最新的文献算法很多都会引用这个算法,进行网络训练,可见其强大之处。

背景主要概括成如下几个方面:

  • 随机梯度下降是现在深度网络训练的主流方法(此方法是高效的)
  • 随机梯度下降需要人为设置大量参数,比如学习率、参数初始化、权重衰减系数、Drop out比例等。
  • 这些参数的选择对训练结果至关重要,且很敏感会很大的影响结果。尝试成本较大。

二、BN算法的价值

  • 初始学习率可以较大,训练速度飙涨。

    以前还需要慢慢调整学习率,甚至在网络训练到一半的时候,还需要想着学习率进一步调小的比例选择多少比较合适,现在可以采用初始很大的学习率。

  • 学习率的衰减速度也很大。

    因为这个算法收敛很快。当然这个算法即使你选择了较小的学习率,也比以前的收敛速度快,因为它具有快速训练收敛的特性;

  • 不用去设置过拟合中drop out、L2正则项参数的选择问题

    采用BN算法后,你可以移除这两项了参数,或者可以选择更小的L2正则约束参数了

    因为BN具有提高网络泛化能力的特性;

  • 不需要使用使用局部响应归一化层

    (局部响应归一化是Alexnet网络用到的方法,搞视觉的估计比较熟悉),因为BN本身就是一个归一化网络层;

  • 可以把训练数据彻底打乱

    防止每批训练的时候,某一个样本都经常被挑选到

    文献说这个可以提高1%的精度

三、思考

问题:归一化的意义

在神经网络训练开始前,都要对输入数据做一个归一化处理,那么具体为什么需要归一化呢?归一化后有什么好处呢?原因在于:

  • 从训练和测试的角度来说:神经网络学习过程本质就是为了学习数据分布,一旦训练数据与测试数据的分布不同,那么网络的泛化能力也大大降低;

  • 从训练中不同的batch来说:一旦每批训练数据的分布各不相同(batch 梯度下降),那么网络就要在每次迭代都去学习适应不同的分布,这样将会大大降低网络的训练速度,这也正是为什么我们需要对数据都要做一个归一化预处理的原因。

  • 从网络结构敏感性来说:想要让输入尽可能的在权重和偏移作用下能输出一个使得激活层比较敏感的值,也就是说这个输出值最好能处在一个不是非常大的值,这也就是归一化的原因之一

  • 对于网络深度来说1:对于深度网络的训练是一个复杂的过程,只要网络的前面几层发生微小的改变,那么后面几层就会被累积放大下去。一旦网络某一层的输入数据的分布发生改变,那么这一层网络就需要去适应学习这个新的数据分布,所以如果训练过程中,训练数据的分布一直在发生变化,那么将会影响网络的训练速度。

  • 对于网络深度来说2:网络在训练过程中,参数就要发生更新,除了输入层的数据外(因为输入层数据,我们已经人为的为每个样本归一化),后面网络每一层的输入数据分布是一直在发生变化的(因为前面一层的参数已经变化,相对于之前的结果已经变化了,属于不同的分布了),因为在训练的时候,前面层训练参数的更新将导致后面层输入数据分布的变化。以网络第二层为例:网络的第二层输入,是由第一层的参数和input计算得到的,而第一层的参数在整个训练过程中一直在变化,因此必然会引起后面每一层输入数据分布的改变。我们把网络中间层在训练过程中,数据分布的改变称之为:“Internal Covariate Shift”。Paper所提出的算法,就是要解决在训练过程中,中间层数据分布发生改变的情况,于是就有了Batch Normalization,这个牛逼算法的诞生。

四、初识BN(Batch Normalization)

2.1 BN概述

  • BN(Batch Normalization)也属于网络的一层。

    就像激活函数层、卷积层、全连接层、池化层一样,在前面我们提到网络除了输出层外,其它层因为低层网络在训练的时候更新了参数,而引起后面层输入数据分布的变化。这个时候我们可能就会想,如果在每一层输入的时候,再加个预处理操作那该有多好啊,比如网络第三层输入数据 X 3 X_3 X3( X 3 X_3 X3表示网络第三层的输入数据)把它归一化至:均值0、方差为1,然后再输入第三层计算,这样我们就可以解决前面所提到的“Internal Covariate Shift”的问题了。

而事实上,paper的算法本质原理就是这样:在网络的每一层输入的时候,又插入了一个归一化层,也就是先做一个归一化处理,然后再进入网络的下一层。不过文献归一化层,可不像我们想象的那么简单,它是一个可学习、有参数的网络层。

2.2 预处理操作选择

说到神经网络输入数据预处理,最好的算法莫过于白化预处理。然而

  • 白化计算量太大了,很不划算

  • 白化不是处处可微的

所以在深度学习中,其实很少用到白化。经过白化预处理后,数据满足条件:

  • 特征之间的相关性降低,这个就相当于pca;
  • 数据均值、标准差归一化,也就是使得每一维特征均值为0,标准差为1

如果数据特征维数比较大,要进行PCA,也就是实现白化的第1个要求,是需要计算特征向量,计算量非常大,于是为了简化计算,作者忽略了第1个要求,仅仅使用了下面的公式进行预处理,也就是近似白化预处理:
x ^ ( k ) = x ( k ) − E [ x ( k ) ] Var ⁡ [ x ( k ) ] \widehat{x}^{(k)}=\frac{x^{(k)}-\mathrm{E}\left[x^{(k)}\right]}{\sqrt{\operatorname{Var}\left[x^{(k)}\right]}} x (k)=Var[x(k)] x(k)E[x(k)]
公式简单粗糙,但是依旧很牛逼。因此后面我们也将用这个公式,对某一个层网络的输入数据做一个归一化处理。需要注意的是,我们训练过程中采用batch随机梯度下降,上面的 E [ x ( k ) ] \mathrm{E}\left[x^{(k)}\right] E[x(k)]指的是每一批训练数据神经元 x k x_k xk的平均值;然后分母就是每一批数据神经元 x k x_k xk激活度的一个标准差了。

五、BN算法实现

5.1 BN算法概述

经过前面简单介绍,这个时候可能我们会想当然的以为:好像很简单的样子,不就是在网络中间层数据做一个归一化处理嘛,这么简单的想法,为什么之前没人用呢?然而其实实现起来并不是那么简单的。

5.2 实现难点

其实如果是仅仅使用上面的归一化公式,对网络某一层的输出数据做归一化,然后送入网络下一层,这样是会影响到本层网络所学习到的特征的。

举例叙述:

网络中间某一层 A A A学习到特征数据本身就分布在激活函数 F F F的两侧,在做强制归一化处理的时候、标准差也限制在了1,可能把数据变换成分布于激活函数不敏感的部分

这样就相当于我下一层网络所学习到的特征分布被搞坏了,于是文献使出了一招惊天地泣鬼神的招式:变换重构。

5.3 数学表达

其引入了可学习参数 γ \gamma γ β \beta β,针对归一化后的值进行再一次的变换重构,这就是算法关键之处:
y ( k ) = γ ( k ) x ^ ( k ) + β ( k ) y^{(k)}=\gamma^{(k)} \widehat{x}^{(k)}+\beta^{(k)} y(k)=γ(k)x (k)+β(k)
每一个神经元xk都会有一对这样的参数γ、β。这样就有如下推导:
W h e n : { γ ( k ) = Var ⁡ [ x ( k ) ] β ( k ) = E [ x ( k ) ] y ( k ) = γ ( k ) x ^ ( k ) + β ( k ) x ^ ( k ) = x ( k ) − E [ x ( k ) ] Var ⁡ [ x ( k ) ] S o : y ( k ) = γ ( k ) x ^ ( k ) + β ( k ) = γ ( k ) x ( k ) − E [ x ( k ) ] Var ⁡ [ x ( k ) ] + β ( k ) = x ( k ) \begin{aligned} When&: \begin{cases} \gamma^{(k)}&=\sqrt{\operatorname{Var}\left[x^{(k)}\right]} \\ \beta^{(k)}&=\mathrm{E}\left[x^{(k)}\right]\\ y^{(k)}&=\gamma^{(k)} \widehat{x}^{(k)}+\beta^{(k)}\\ \widehat{x}^{(k)}&=\frac{x^{(k)}-\mathrm{E}\left[x^{(k)}\right]}{\sqrt{\operatorname{Var}\left[x^{(k)}\right]}}\\ \end{cases}\\ So: y^{(k)}&=\gamma^{(k)} \widehat{x}^{(k)}+\beta^{(k)}\\ &=\gamma^{(k)}\frac{x^{(k)}-\mathrm{E}\left[x^{(k)}\right]}{\sqrt{\operatorname{Var}\left[x^{(k)}\right]}}+\beta^{(k)}\\ &=x^{(k)} \end{aligned} WhenSo:y(k):γ(k)β(k)y(k)x (k)=Var[x(k)] =E[x(k)]=γ(k)x (k)+β(k)=Var[x(k)] x(k)E[x(k)]=γ(k)x (k)+β(k)=γ(k)Var[x(k)] x(k)E[x(k)]+β(k)=x(k)
所以是可以恢复出原始的某一层所学到的特征的。因此我们引入了这个可学习重构参数 γ \gamma γ β \beta β,让我们的网络可以学习恢复出原始网络所要学习的特征分布。最后Batch Normalization网络层的前向传导过程公式就是:
m i n i   b a t c h   m e a n : μ B ← 1 m ∑ i = 1 m x i m i n i   b a t c h   v a r i a n c e : σ B 2 ← 1 m ∑ i = 1 m ( x i − μ B ) 2 n o r m a l i z e : x ^ i ← x i − μ B σ B 2 + ϵ s c a l e   a n d   s h i f t : y i ← γ x ^ i + β ≡ B N γ , β ( x i ) \begin{aligned} mini\ batch\ mean&:\mu_{\mathcal{B}} \leftarrow \frac{1}{m} \sum_{i=1}^{m} x_{i} \\ mini\ batch\ variance&:\sigma_{\mathcal{B}}^{2} \leftarrow \frac{1}{m} \sum_{i=1}^{m}\left(x_{i}-\mu_{\mathcal{B}}\right)^{2} \\ normalize&:\widehat{x}_{i} \leftarrow \frac{x_{i}-\mu_{\mathcal{B}}}{\sqrt{\sigma_{\mathcal{B}}^{2}+\epsilon}} \\ scale \ and\ shift&:y_{i} \leftarrow \gamma \widehat{x}_{i}+\beta \equiv \mathrm{BN}_{\gamma, \beta}\left(x_{i}\right) \\ \end{aligned} mini batch meanmini batch variancenormalizescale and shift:μBm1i=1mxi:σB2m1i=1m(xiμB)2:x iσB2+ϵ xiμB:yiγx i+βBNγ,β(xi)
上面的公式中 m m m指的是mini-batch size

5.4 源码实现

这里用伪代码实现一下

x_m = mean(X) #计算均值
x_std = std(X) #计算标准差
X_normed = (X - m) / (std + epsilon) #归一化
out = gamma * X_normed + beta #重构变换

六、实战使用

6.1 测试过程中的BN

可能学完了上面的算法,你只是知道它的一个训练过程,一个网络一旦训练完了,就没有了min-batch这个概念了。测试阶段我们一般只输入一个测试样本,看看结果而已。因此测试样本,前向传导的时候,上面的均值 μ \mu μ、标准差 σ \sigma σ应该怎么操作?有如下两个点:

  • 网络一旦训练完毕,参数都是固定的,这个时候即使是每批训练样本进入网络,那么BN层计算的均值 μ \mu μ、和标准差 σ \sigma σ都是固定不变的。
  • 训练的时候会记录训练集中每一个mini-batch的均值 μ B \mu_{\mathcal{B}} μB,标准差 σ B 2 \sigma_{\mathcal{B}}^{2} σB2然后用来推测出测试集中应该用于归一化测试集输入数据的均值 μ \mu μ,标准差 σ \sigma σ

推测方法如下:

  • 对于均值来说直接计算所有mini-batch的记录的本次batch均值 μ β \mu_\beta μβ的平均值

  • 对于标准偏差采用每个mini-batch标准差 σ β \sigma_\beta σβ的无偏估计

  • 以此推断出来的均值和标准差来作为测试样本所需要的均值、标准差

  • 最后测试阶段的均值 μ \mu μ、和标准差 σ \sigma σ计算公式如下:

E [ x ] ← E B [ μ B ] Var ⁡ [ x ] ← m m − 1 E B [ σ B 2 ] \begin{aligned}\mathrm{E}[x] \leftarrow& \mathrm{E}_{\mathcal{B}}\left[\mu_{\mathcal{B}}\right] \\\operatorname{Var}[x] \leftarrow& \frac{m}{m-1} \mathrm{E}_{\mathcal{B}}\left[\sigma_{\mathcal{B}}^{2}\right]\end{aligned} E[x]Var[x]EB[μB]m1mEB[σB2]

最后测试阶段,BN的使用公式就是:
y = γ x ^ + β y = γ x − E [ x ] Var ⁡ [ x ] + ϵ + β y = γ x Var ⁡ ( x ) + ϵ + ( β − γ E ( x ) Var ⁡ ( x ) + ϵ ) \begin{aligned} y&=\gamma \widehat{x}+\beta\\ y&=\gamma \frac{x-\mathrm{E}[x]}{\sqrt{\operatorname{Var}[x]+\epsilon}}+\beta\\ y&=\frac{\gamma x}{\sqrt{\operatorname{Var}(x)+\epsilon}}+\left(\beta-\frac{\gamma E(x)}{\sqrt{\operatorname{Var}(x)+\epsilon}}\right) \end{aligned} yyy=γx +β=γVar[x]+ϵ xE[x]+β=Var(x)+ϵ γx+(βVar(x)+ϵ γE(x))

6.2 BN使用问题

根据文献说,BN可以应用于一个神经网络的任何神经元上。文献主要是把BN变换,置于网络激活函数层的前面。在没有采用BN的时候,激活函数层是这样的:
z = g ( W u + b ) z=g(Wu+b) z=g(Wu+b)
也就是我们希望一个激活函数的输入是经过BN处理后的结果。因此前向传导的计算公式就应该是:

z = g ( B N ( W u + b ) ) z=g(BN(Wu+b)) z=g(BN(Wu+b))
其实因为偏置参数b经过BN层后其实是没有用的,最后也会被均值归一化,当然BN层后面还有个 β \beta β参数作为偏置项,所以b这个参数就可以不用了。因此最后把BN层+激活函数层就变成了:

z = g ( B N ( W u ) ) z=g(BN(Wu)) z=g(BN(Wu))

七、BN的反向传播

BN层的反向传播相比于普通层要略微复杂一些,首先给出论文中的公式,对其中省略的步骤在下面会给出细致的推导过程。

文中公式:
( 1 ) ∂ ℓ ∂ x ^ i = ∂ ℓ ∂ y i ⋅ γ ( 2 ) ∂ ℓ ∂ σ B 2 = ∑ i = 1 m ∂ ℓ ∂ x ^ i ⋅ ( x i − μ B ) ⋅ − 1 2 ( σ B 2 + ϵ ) − 3 / 2 ( 3 ) ∂ ℓ ∂ μ B = ( ∑ i = 1 m ∂ ℓ ∂ x ^ i ⋅ − 1 σ B 2 + ϵ ) + ∂ ℓ ∂ σ B 2 ⋅ ∑ i = 1 m − 2 ( x i − μ B ) m ( 4 ) ∂ ℓ ∂ x i = ∂ ℓ ∂ x ^ i ⋅ 1 σ B 2 + ϵ + ∂ ℓ ∂ σ B 2 ⋅ 2 ( x i − μ B ) m + ∂ ℓ ∂ μ B ⋅ 1 m ( 5 ) ∂ ℓ ∂ γ = ∑ i = 1 m ∂ ℓ ∂ y i ⋅ x ^ i ( 6 ) ∂ ℓ ∂ β = ∑ i = 1 m ∂ ℓ ∂ y i \begin{aligned} (1)\quad\frac{\partial \ell}{\partial \widehat{x}_{i}} &=\frac{\partial \ell}{\partial y_{i}} \cdot \gamma \\ (2)\quad\frac{\partial \ell}{\partial \sigma_{\mathcal{B}}^{2}} &=\sum_{i=1}^{m} \frac{\partial \ell}{\partial \widehat{x}_{i}} \cdot\left(x_{i}-\mu_{\mathcal{B}}\right) \cdot \frac{-1}{2}\left(\sigma_{\mathcal{B}}^{2}+\epsilon\right)^{-3 / 2} \\ (3)\quad\frac{\partial \ell}{\partial \mu_{\mathcal{B}}} &=\left(\sum_{i=1}^{m} \frac{\partial \ell}{\partial \widehat{x}_{i}} \cdot \frac{-1}{\sqrt{\sigma_{\mathcal{B}}^{2}+\epsilon}}\right)+\frac{\partial \ell}{\partial \sigma_{\mathcal{B}}^{2}} \cdot \frac{\sum_{i=1}^{m}-2\left(x_{i}-\mu_{\mathcal{B}}\right)}{m} \\ (4)\quad\frac{\partial \ell}{\partial x_{i}} &=\frac{\partial \ell}{\partial \widehat{x}_{i}} \cdot \frac{1}{\sqrt{\sigma_{\mathcal{B}}^{2}+\epsilon}}+\frac{\partial \ell}{\partial \sigma_{\mathcal{B}}^{2}} \cdot \frac{2\left(x_{i}-\mu_{\mathcal{B}}\right)}{m}+\frac{\partial \ell}{\partial \mu_{\mathcal{B}}} \cdot \frac{1}{m} \\ (5)\quad\frac{\partial \ell}{\partial \gamma} &=\sum_{i=1}^{m} \frac{\partial \ell}{\partial y_{i}} \cdot \widehat{x}_{i} \\ (6)\quad\frac{\partial \ell}{\partial \beta} &=\sum_{i=1}^{m} \frac{\partial \ell}{\partial y_{i}} \end{aligned} (1)x i(2)σB2(3)μB(4)xi(5)γ(6)β=yiγ=i=1mx i(xiμB)21(σB2+ϵ)3/2=(i=1mx iσB2+ϵ 1)+σB2mi=1m2(xiμB)=x iσB2+ϵ 1+σB2m2(xiμB)+μBm1=i=1myix i=i=1myi
对于公式(1):

因为:
y i = γ ⋅ x ^ i + β 且 x ^ i 仅 仅 与 y i 有 关 \begin{aligned} y_i=\gamma \cdot \widehat{x}_i+\beta\\ 且 \widehat{x}_i仅仅与y_i有关 \end{aligned} yi=γx i+βx iyi
所以:
x ^ i = ( y i − β ) γ ∂ ℓ ∂ x ^ i = ∂ ℓ ∂ y i 1 γ = ∂ ℓ ∂ y i ⋅ γ \begin{aligned} \widehat{x}_i&=\frac{ (y_i-\beta)}{\gamma}\\ \frac{\partial \ell}{\partial \widehat{x}_{i}} &=\frac{\partial \ell}{\partial y_{i}\frac{1}{\gamma}} =\frac{\partial \ell}{\partial y_{i}} \cdot \gamma \end{aligned} x ix i=γ(yiβ)=yiγ1=yiγ

对于公式(2):

首先替换求导:
∂ l ∂ σ B 2 = ∂ l ∂ X ^ ∂ X ^ ∂ σ B 2 = ∑ i = 1 m ∂ l ∂ x ^ i ∂ x ^ i ∂ σ B 2 \begin{aligned} \frac{\partial l}{\partial \sigma_{\mathcal{B}}^{2}} &=\frac{\partial l}{\partial \hat{X}} \frac{\partial \hat{X}}{\partial \sigma_{\mathcal{B}}^{2}}=\sum_{i=1}^{m} \frac{\partial l}{\partial \widehat{x}_{i}} \frac{\partial \widehat{x}_{i}}{\partial \sigma_{B}^{2}} \end{aligned} σB2l=X^lσB2X^=i=1mx ilσB2x i
备注: X ^ \hat{X} X^为归一化后的整个矩阵,包含所有的 x ^ i \widehat{x}_{i} x i

然后又因为:
x ^ i = x i − μ B σ B 2 + ϵ \begin{aligned} \widehat{x}_{i} = \frac{x_{i}-\mu_{\mathcal{B}}}{\sqrt{\sigma_{\mathcal{B}}^{2}+\epsilon}} \end{aligned} x i=σB2+ϵ xiμB
得到:
∂ x ^ i ∂ σ B 2 = ( x i − μ B ) − 1 2 ( σ B 2 + ϵ ) − 3 2 \frac{\partial \widehat{x}_{i}}{\partial \sigma_{\mathcal{B}}^{2}} =\left(x_{i}-\mu_{\mathcal{B}}\right) \frac{-1}{2}\left(\sigma_{\mathcal{B}}^{2}+\epsilon\right)^{\frac{-3}{2}} σB2x i=(xiμB)21(σB2+ϵ)23
备注:上面这里把 σ B 2 \sigma_{\mathcal{B}}^{2} σB2 看成一个整体

所以:
∂ ℓ ∂ σ B 2 = ∑ i = 1 m ∂ ℓ ∂ x ^ i ⋅ ( x i − μ B ) ⋅ − 1 2 ( σ B 2 + ϵ ) − 3 / 2 \begin{aligned} \frac{\partial \ell}{\partial \sigma_{\mathcal{B}}^{2}} &= \sum_{i=1}^{m} \frac{\partial \ell}{\partial \widehat{x}_{i}} \cdot\left(x_{i}-\mu_{\mathcal{B}}\right) \cdot \frac{-1}{2}\left(\sigma_{\mathcal{B}}^{2}+\epsilon\right)^{-3 / 2} \end{aligned} σB2=i=1mx i(xiμB)21(σB2+ϵ)3/2

对于公式(3):

因为:
σ B 2 = 1 m ∑ i = 1 m ( x i − μ B ) 2 \sigma_{\mathcal{B}}^{2}= \frac{1}{m} \sum_{i=1}^{m}\left(x_{i}-\mu_{\mathcal{B}}\right)^{2} σB2=m1i=1m(xiμB)2
所以:
∂ σ B 2 ∂ μ B = − 1 m ∑ i = 1 m 2 ( x i − μ B ) \frac{\partial \sigma_{\mathcal{B}}^{2}}{\partial \mu_{\mathcal{B}}} =\frac{-1}{m}\sum_{i=1}^{m} 2\left(x_{i}-\mu_{\mathcal{B}}\right) μBσB2=m1i=1m2(xiμB)
因为:
x ^ i = x i − μ B σ B 2 + ϵ \widehat{x}_{i} = \frac{x_{i}-\mu_{\mathcal{B}}}{\sqrt{\sigma_{\mathcal{B}}^{2}+\epsilon}} x i=σB2+ϵ xiμB
所以:
∂ x i ^ ∂ μ B = − 1 σ B 2 + ϵ \frac{\partial \hat{x_{i}}}{\partial \mu_{\mathcal{B}}} =\frac{-1}{\sqrt{\sigma_{\mathcal{B}}^{2}+\epsilon}} μBxi^=σB2+ϵ 1
因为 ℓ \ell 是关于 σ B 2 \sigma_{\mathcal{B}}^{2} σB2 X ^ \widehat{X} X 的函数,使用如下定理:

z = f ( u , v ) , u = ϕ ( x , y ) , v = ψ ( x , y ) z=f(u, v), u=\phi(x, y),v=\psi(x, y) z=f(u,v),u=ϕ(x,y),v=ψ(x,y)复合得到的函数为 z = f [ ϕ ( x , y ) , ψ ( x , y ) ] z=f[\phi(x, y), \psi(x, y)] z=f[ϕ(x,y),ψ(x,y)],如果 u = ϕ ( x , y ) , v = ψ ( x , y ) u=\phi(x, y),v=\psi(x, y) u=ϕ(x,y),v=ψ(x,y)都在点 ( x , y ) (x,y) (x,y)处对 x x x以及对 y y y有偏导函数 z z z的偏导可以写成如下形式
∂ z ∂ x = ∂ z ∂ u ∂ u ∂ x + ∂ z ∂ v ∂ v ∂ x ∂ z ∂ y = ∂ z ∂ u ∂ u ∂ y + ∂ z ∂ v ∂ v ∂ y \begin{array}{l} \frac{\partial z}{\partial x}=\frac{\partial z}{\partial u} \frac{\partial u}{\partial x}+\frac{\partial z}{\partial v} \frac{\partial v}{\partial x} \\ \frac{\partial z}{\partial y}=\frac{\partial z}{\partial u} \frac{\partial u}{\partial y}+\frac{\partial z}{\partial v} \frac{\partial v}{\partial y} \end{array} xz=uzxu+vzxvyz=uzyu+vzyv

所以有如下形式的拆分:
∂ ℓ ∂ μ B = ∂ ℓ ∂ X ^ ∂ X ^ ∂ μ B + ∂ ℓ ∂ σ B 2 ∂ σ B 2 ∂ μ B = ∑ i = 1 m ∂ ℓ ∂ x ^ i ∂ x ^ i ∂ μ B + ∂ ℓ ∂ σ B 2 ∂ σ B 2 ∂ μ B \begin{aligned} \frac{\partial \ell}{\partial \mu_{\mathcal{B}}} &=\frac{\partial \ell}{\partial \widehat{X}} \frac{\partial \widehat{X}}{\partial \mu_{\mathcal{B}}}+\frac{\partial \ell}{\partial \sigma_{\mathcal{B}}^{2}} \frac{\partial \sigma_{\mathcal{B}}^{2}}{\partial \mu_{B}}=\sum_{i=1}^{m} \frac{\partial \ell}{\partial \widehat{x}_{i}} \frac{\partial \widehat{x}_{i}}{\partial \mu_{\mathcal{B}}}+\frac{\partial \ell}{\partial \sigma_{\mathcal{B}}^{2}} \frac{\partial \sigma_{\mathcal{B}}^{2}}{\partial \mu_{\mathcal{B}}} \end{aligned} μB=X μBX +σB2μBσB2=i=1mx iμBx i+σB2μBσB2
所以最终结果可以写为:
∂ ℓ ∂ μ B = ( ∑ i = 1 m ∂ ℓ ∂ x ^ i ⋅ − 1 σ B 2 + ϵ ) + ∂ ℓ ∂ σ B 2 ⋅ ∑ i = 1 m − 2 ( x i − μ B ) m \frac{\partial \ell}{\partial \mu_{\mathcal{B}}} =\left(\sum_{i=1}^{m} \frac{\partial \ell}{\partial \widehat{x}_{i}} \cdot \frac{-1}{\sqrt{\sigma_{\mathcal{B}}^{2}+\epsilon}}\right)+\frac{\partial \ell}{\partial \sigma_{\mathcal{B}}^{2}} \cdot \frac{\sum_{i=1}^{m}-2\left(x_{i}-\mu_{\mathcal{B}}\right)}{m} μB=(i=1mx iσB2+ϵ 1)+σB2mi=1m2(xiμB)

对于公式(4):

因为:
x ^ i = x i − μ B σ B 2 + ϵ \begin{aligned} \widehat{x}_{i} = \frac{x_{i}-\mu_{\mathcal{B}}}{\sqrt{\sigma_{\mathcal{B}}^{2}+\epsilon}} \end{aligned} x i=σB2+ϵ xiμB
所以:
∂ x ^ i ∂ x i = 1 σ B 2 + ϵ \frac{\partial \widehat{x}_{i}}{\partial x_{i}}=\frac{1}{\sqrt{\sigma_{\mathcal{B}}^{2}+\epsilon}} xix i=σB2+ϵ 1
因为:
σ B 2 = 1 m ∑ i = 1 m ( x i − μ B ) 2 \sigma_{\mathcal{B}}^{2} = \frac{1}{m} \sum_{i=1}^{m}\left(x_{i}-\mu_{\mathcal{B}}\right)^{2} σB2=m1i=1m(xiμB)2
所以:
∂ σ B 2 ∂ x i = 2 m ( x i − μ B ) ( 1 − 1 m ) + 2 m ∑ k = 1 , k ≠ i m ( x i − μ B ) ( − 1 m ) = 2 m ( x i − μ B ) + 2 m ∑ k = 1 m ( x i − μ B ) ( − 1 m ) = 2 ( x i − μ B ) m \begin{aligned} \frac{\partial \sigma_{\mathcal{B}}^{2}}{\partial x_{i}}&=\frac{2}{m}\left(x_{i}-\mu_{\mathcal{B}}\right)\left(1-\frac{1}{m}\right)+\frac{2}{m} \sum_{k=1, k \neq i}^{m}\left(x_{i}-\mu_{\mathcal{B}}\right)\left(-\frac{1}{m}\right) \\ &=\frac{2}{m}\left(x_{i}-\mu_{\mathcal{B}}\right)+\frac{2}{m} \sum_{k=1}^{m}\left(x_{i}-\mu_{\mathcal{B}}\right)\left(-\frac{1}{m}\right) \\ &=\frac{2\left(x_{i}-\mu_{\mathcal{B}}\right)}{m} \end{aligned} xiσB2=m2(xiμB)(1m1)+m2k=1,k=im(xiμB)(m1)=m2(xiμB)+m2k=1m(xiμB)(m1)=m2(xiμB)
因为:
μ B = 1 m ∑ i = 1 m x i \mu_{\mathcal{B}} = \frac{1}{m} \sum_{i=1}^{m} x_{i} μB=m1i=1mxi
所以:
μ B ∂ x i = 1 m \frac{\mu_{\mathcal{B}}}{\partial x_{i}}=\frac{1}{m} xiμB=m1
最后因为 ℓ \ell 是关于 x ^ i , μ B , σ B 2 \widehat{x}_i,\mu_{\mathcal{B}},\sigma_{\mathcal{B}}^{2} x i,μB,σB2的函数,这三个变量又是关于 x i x_i xi的函数

所以最终结果通过三个分离的变量求偏导的和为:
∂ l ∂ x i = ∂ l ∂ x ^ i ∂ x i ^ ∂ x i + ∂ l ∂ σ B 2 ∂ σ B 2 ∂ x i + ∂ l ∂ μ B ∂ μ B ∂ x i = ∂ ℓ ∂ x ^ i ⋅ 1 σ B 2 + ϵ + ∂ ℓ ∂ σ B 2 ⋅ 2 ( x i − μ B ) m + ∂ ℓ ∂ μ B ⋅ 1 m \begin{aligned} \frac{\partial l}{\partial x_{i}}&=\frac{\partial l}{\partial \hat{x}_{i}} \frac{\partial \hat{x_{i}}}{\partial x_{i}}+\frac{\partial l}{\partial \sigma_{\mathcal{B}}^{2}} \frac{\partial \sigma_{\mathcal{B}}^{2}}{\partial x_{i}}+\frac{\partial l}{\partial \mu_{\mathcal{B}}} \frac{\partial \mu_{\mathcal{B}}}{\partial x_{i}}\\ &=\frac{\partial \ell}{\partial \widehat{x}_{i}} \cdot \frac{1}{\sqrt{\sigma_{\mathcal{B}}^{2}+\epsilon}}+\frac{\partial \ell}{\partial \sigma_{\mathcal{B}}^{2}} \cdot \frac{2\left(x_{i}-\mu_{\mathcal{B}}\right)}{m}+\frac{\partial \ell}{\partial \mu_{\mathcal{B}}} \cdot \frac{1}{m} \end{aligned} xil=x^ilxixi^+σB2lxiσB2+μBlxiμB=x iσB2+ϵ 1+σB2m2(xiμB)+μBm1

对于公式(5):

因为:
y i = γ x ^ i + β y_{i} = \gamma \widehat{x}_{i}+\beta yi=γx i+β
通过之前的定理 ℓ \ell 是一个有关于 y 1 , y 2 , ⋯   , y m y_1,y_2,\cdots,y_m y1,y2,,ym的函数,并且 y 1 , y 2 , ⋯   , y m y_1,y_2,\cdots,y_m y1,y2,,ym都是 γ \gamma γ的函数

所以:
∂ L ∂ γ = ∑ i m ∂ L ∂ y i ∂ y i ∂ γ \frac{\partial L}{\partial \gamma} =\sum_{i}^{m} \frac{\partial L}{\partial y_{i}} \frac{\partial y_{i}}{\partial \gamma} γL=imyiLγyi

所以最终结果:
∂ L ∂ γ = ∑ i m ∂ L ∂ y i ∂ y i ∂ γ = ∑ i m ∂ L ∂ y i x ^ i \begin{aligned} \frac{\partial L}{\partial \gamma} &=\sum_{i}^{m} \frac{\partial L}{\partial y_{i}} \frac{\partial y_{i}}{\partial \gamma} \\ &=\sum_{i}^{m} \frac{\partial L}{\partial y_{i}} \widehat{x}_{i} \end{aligned} γL=imyiLγyi=imyiLx i

对于公式(6):

因为:
y i = γ x ^ i + β y_{i} = \gamma \widehat{x}_{i}+\beta yi=γx i+β
通过之前的定理 ℓ \ell 是一个有关于 y 1 , y 2 , ⋯   , y m y_1,y_2,\cdots,y_m y1,y2,,ym的函数,并且 y 1 , y 2 , ⋯   , y m y_1,y_2,\cdots,y_m y1,y2,,ym都是 β \beta β的函数

所以:
∂ ℓ ∂ β = ∑ i m ∂ ℓ ∂ y i ∂ y i ∂ β \frac{\partial \ell}{\partial \beta} =\sum_{i}^{m} \frac{\partial \ell}{\partial y_{i}} \frac{\partial y_{i}}{\partial \beta} β=imyiβyi
所以最终结果:
∂ ℓ ∂ β = ∑ i m ∂ ℓ ∂ y i ∂ y i ∂ β = ∑ i m ∂ ℓ ∂ y i \begin{aligned} \frac{\partial \ell}{\partial \beta} &=\sum_{i}^{m} \frac{\partial \ell}{\partial y_{i}} \frac{\partial y_{i}}{\partial \beta} \\ &=\sum_{i}^{m} \frac{\partial \ell}{\partial y_{i}} \end{aligned} β=imyiβyi=imyi

八、Batch Normalization在CNN中的使用

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

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

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)

LAST、参考文献

(深度学习(二十九)Batch Normalization 学习笔记_hjimce的专栏-CSDN博客

《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》

《Spatial Transformer Networks》

https://github.com/fchollet/keras

Batch Normalization梯度反向传播推导_ycsun的博客-CSDN博客_bn反向传播推导

Batch Normalization学习笔记及其实现 - 知乎

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐