Batch Normalization的来源
简化版的Convolutional Layer
X(l+1)=f(Yl)=f(3d_conv(Xl,F)+b)
f 是激活函数,一般是
Leaky或者
ReLU,早年比较火的
sigmoid(x)=1/(1−e−x)函数因为计算量大(要计算
e−x),效果不好(容易出现梯度消失)已经基本不用。
但对于
y=sigmoid(x) ,
y 的均值为0,如果不考虑计算量,将来可以研究研究。
为了保持书写习惯,下文用
W 表示卷积核。
下面分析中假设卷积核数量为1,
Xl的深度为1,3d卷积
3d_conv 换成 2d卷积
conv2。
梯度消失的问题
在神经网络很深的情况下,数据向前传播的时候经常容易进入饱和区(不过感觉用
Leaky 或者
ReLU 作为激活函数这个问题不大),对数据进行规范化,使其满足(至少看起来满足)高斯分布,可以避免进入饱和区而出现梯度消失的问题。
相关文章:
详解深度学习中的Normalization,BN/LN/WN
什么是批标准化 (Batch Normalization)
Batch Normalization阅读笔记
Normalization的变体
最基本的数据规范化
对输入进行规范化。若
X 是
N×N 的矩阵。
μ=N21i=0∑N−1j=0∑N−1xi,j
σ2=N21i=0∑N−1j=0∑N−1(xi,j−μ)2
σ=σ2
=N1i=0∑N−1j=0∑N−1(xi,j−μ)2
X^={σX−μσ̸=0Xσ=0
批规范化
一小批(Batch)的数据平均化的规范化。吸取了mini batch-SGD的思路,为的应该是增加数据的样本空间,记Batch数为
m,Batch Normalization的均值为
μ′
μ=m1i∈m∑μi,σ=m1i∈m∑σi
X^={σX−μσ̸=0Xσ=0
问题来了,如果
σ=0,那说明全部的数据都是
μ=0,这样的数据我们训练它有啥意义?这个且排除掉,得到
X^=σX−μ
有论文说
m 应该取32。64,128,256等数也应该试试看。也有论文说
m 过大的话效果可能会较差。
在Yolo中,默认的输入尺寸是416×416(浮点数),一级中最多有256个3×3的卷积核,一个卷积结果需要的内存存储量为416×416×256÷1024÷1024=42.25MB,如果
m=32,
X^的内存需求为1352MB≈1.32GB。
但深度网络中,不见得上面计算的
X^ 未必是我们想要的,所以要有机会对其进行修正。
Y=γX^+β
初始值
γ0=1,β0=0
加了Batch Normalization的卷积层
Batch Normalization放在哪里
放在卷积之后,激活之前,即从原来的
Yl=conv2(Xl,W)+b
变成
Yl=Y=γZ^l+β=γl(σlconv2(Xl,W)−μl)+βl
这里
b 被忽略,合并到
β 里面了。且暂不考虑
σ=0 的情况。
增加一个变量
Zl,
Zl=conv2(Xl,W)。
前向传播算法
为简单考虑,
Xl的通道数为1,唯一卷积核为
Wl 。卷积层的输出
Xl+1=f(Yl)=f(γl(σlconv2(Xl,Wl)−μl)+βl)
反向传播算法
已知
dXl+1,也就是
Xl+1的导数,求以下值:
dXl ,为了往后面一层继续传播,使
xi,j←xi,j−η⋅dxi,j
dWl ,为了更新本层的卷积参数,使
wi,j←wi,j−η⋅dwi,j
dγl ,
dβl 为了更新本层的规范化参数
dXl+1 准确讲应该是
ΔXl+1ΔE , 而
dXl=ΔXlΔE=ΔXl+1ΔE⋅ΔXlΔXl+1
因此,
dYl=dXl+1⋅f′(Y)。
我们从
dYl 开始。
dγl 和
dβl 的推导
dγl=dYl⋅ΔγlΔYl=dYl⋅X^l
在实际系统中,
X^ ,
dYl 为
N×N 矩阵,
γ 和
β 为浮点数(不是数组也不是矩阵)
后续的更新计算中,也希望有使
γ←γ−η⋅dγ 的形式。,因此需要有
dγl 从
N×N 矩阵到浮点数的转换方式。Understanding the backward pass through Batch Normalization Layer中用的算法是
dγl=∑i∑jx^i,jl⋅dyi,jl ,(和推导过程不同)
类似地,
dβl=∑i∑jdyi,jl。
dXl 的推导
显然,
∂Yl/∂Z^=γl。
又有
dXl=dYl⋅∂Z^l∂Yl⋅∂Xl∂Z^l=dYl⋅γl⋅∂Xl∂Z^l
变成了计算
∂Z^l/∂Xl 的问题了,先计算
∂Z^l/∂Zl 。
Z^=σZ−μ
对于Batch Normalizaiton ,
μ=m1i∈m∑N21j∈N∑k∈N∑zj,k(i)
σ=m1i∈m∑N1j∈N∑k∈N∑(zj,k(i)−μ)2
即
σ=m1i∈m∑N1j∈N∑k∈N∑∣∣∣zj,k(i)−μ∣∣∣
Z 的变化会引起
μ 和
σ 变化,我们需要计算
μ 和
σ 的导数值。但目前的这个
σ 是有绝对值号的,不可导。给它做一点小小的处理:
σ=m1i∈m∑N1j∈N∑k∈N∑(zj,k(i)−μ)2+ϵ
ϵ 是一个很小的常数,通常取值1.0e-8可以,这样
σ 的值基本不会改变,但可导了。
∂σ∂Z^=σ21,∂μ∂Z^∗=−σ1
接着求
∂σ/∂Z 和
∂μ/∂Z
考虑到Batch Normalizaiton中一个batch中的训练样本相互独立,因此
∂zi,j∂μ=m⋅N21
记
ti,j=zi,j−μ ,
σ(ti,j)=m⋅Nti,j2+ϵ
,
σ′(ti,j)=m⋅N⋅ti,j2+ϵ
ti,j≈m⋅N⋅σzi,j−μ
因此,
∂Z∂σ=m⋅N⋅σ1⋅RN×N
∂μ∂σ=m⋅N⋅σ−1⋅RN×N
∂Z∂Z^=∂Z∂Z^∗+∂σ∂Z^⋅∂Z∂σ+∂σ∂Z^⋅∂μ∂σ⋅∂Z∂μ+∂μ∂Z^∗⋅∂Z∂μ=σ1+σ21⋅m⋅N⋅σ1+σ21⋅(m⋅N⋅σ−1)⋅m⋅N21+(−σ1)⋅m⋅N21=σ1⋅RN×N+m⋅N⋅σ1⋅(σ21−m⋅N2σ21−N1)⋅RN×N
RN×N 是元素全为1的
N×N矩阵。
在Yolo中,
N 通常为416以上的值,
σ接近0.1的倍数,当
m 取32时,式子的第二项和第一项相比几乎可以忽略不计。因此,我认为
∂Z^/∂Z=1/σ⋅RN×N即可。减少很多计算量。
中间的推导可能有错误,不过不影响最终的结论。
卷积部分的计算
见我之前写的文章 卷积神经网络CNN的前向和后向传播(二)
其他
Batch Normalization部分,借一张图,来自Understanding the backward pass through Batch Normalization Layer