赞
踩
@(深度学习)
在前面我们讲述了DNN的模型与前向反向传播算法。而在DNN大类中,卷积神经网络(Convolutional Neural Networks,以下简称CNN)是最为成功的DNN特例之一。CNN广泛的应用于图像识别,当然现在也应用于NLP等其他领域,本文我们就对CNN的模型结构做一个总结。
首先我们来看看CNN的基本结构。一个常见的CNN例子如下图:
图中是一个图形识别的CNN模型。可以看出最左边的船的图像就是我们的输入层,计算机理解为输入若干个矩阵,这点和DNN基本相同。
接着是卷积层(Convolution Layer),这个是CNN特有的,我们后面专门来讲。卷积层的激活函数使用的是ReLU。我们在DNN中介绍过ReLU的激活函数,它其实很简单,就是 R e L U ( x ) = m a x ( 0 , x ) ReLU(x) = max(0,x) ReLU(x)=max(0,x)。在卷积层后面是池化层(Pooling layer),这个也是CNN特有的,我们后面也会专门来讲。需要注意的是,池化层没有激活函数。
卷积层+池化层的组合可以在隐藏层出现很多次,上图中出现两次。而实际上这个次数是根据模型的需要而来的。当然我们也可以灵活使用使用卷积层+卷积层,或者卷积层+卷积层+池化层的组合,这些在构建模型的时候没有限制。但是最常见的CNN都是若干卷积层+池化层的组合,如上图中的CNN结构。
在若干卷积层+池化层后面是全连接层(Fully Connected Layer, 简称FC),全连接层其实就是我们前面讲的DNN结构,只是输出层使用了Softmax激活函数来做图像识别的分类,这点我们在DNN中也有讲述。
从上面CNN的模型描述可以看出,CNN相对于DNN,比较特殊的是卷积层和池化层,如果我们熟悉DNN,只要把卷积层和池化层的原理搞清楚了,那么搞清楚CNN就容易很多了。
首先,我们去学习卷积层的模型原理,在学习卷积层的模型原理前,我们需要了解什么是卷积,以及CNN中的卷积是什么样子的。
大家学习数学时都有学过卷积的知识,微积分中卷积的表达式为: S ( t ) = ∫ x ( t − a ) w ( a ) d a S(t) = \int x(t-a)w(a) da S(t)=∫x(t−a)w(a)da
离散形式是: s ( t ) = ∑ a x ( t − a ) w ( a ) s(t) = \sum\limits_ax(t-a)w(a) s(t)=a∑x(t−a)w(a)
这个式子如果用矩阵表示可以为: s ( t ) = ( X ∗ W ) ( t ) s(t)=(X*W)(t) s(t)=(X∗W)(t)
其中星号表示卷积。
如果是二维的卷积,则表示式为: s ( i , j ) = ( X ∗ W ) ( i , j ) = ∑ m ∑ n x ( i − m , j − n ) w ( m , n ) s(i,j)=(X*W)(i,j) = \sum\limits_m \sum\limits_n x(i-m,j-n) w(m,n) s(i,j)=(X∗W)(i,j)=m∑n∑x(i−m,j−n)w(m,n)
在CNN中,虽然我们也是说卷积,但是我们的卷积公式和严格意义数学中的定义稍有不同,比如对于二维的卷积,定义为: s ( i , j ) = ( X ∗ W ) ( i , j ) = ∑ m ∑ n x ( i + m , j + n ) w ( m , n ) s(i,j)=(X*W)(i,j) = \sum\limits_m \sum\limits_n x(i+m,j+n) w(m,n) s(i,j)=(X∗W)(i,j)=m∑n∑x(i+m,j+n)w(m,n)
这个式子虽然从数学上讲不是严格意义上的卷积,但是大牛们都这么叫了,那么我们也跟着这么叫了。后面讲的CNN的卷积都是指的上面的最后一个式子。
其中,我们叫W为我们的卷积核,而X则为我们的输入。如果X是一个二维输入的矩阵,而W也是一个二维的矩阵。但是如果X是多维张量,那么W也是一个多维的张量。
有了卷积的基本知识,我们现在来看看CNN中的卷积,假如是对图像卷积,回想我们的上一节的卷积公式,其实就是对输入的图像的不同局部的矩阵和卷积核矩阵各个位置的元素相乘,然后相加得到。
举个例子如下,图中的输入是一个二维的3x4的矩阵,而卷积核是一个2x2的矩阵。这里我们假设卷积是一次移动一个像素来卷积的,那么首先我们对输入的左上角2x2局部和卷积核卷积,即各个位置的元素相乘再相加,得到的输出矩阵S的 S 00 S_{00} S00的元素,值为 a w + b x + e y + f z aw+bx+ey+fz aw+bx+ey+fz。接着我们将输入的局部向右平移一个像素,现在是(b,c,f,g)四个元素构成的矩阵和卷积核来卷积,这样我们得到了输出矩阵S的 S 01 S_{01} S01的元素,同样的方法,我们可以得到输出矩阵S的 S 02 , S 10 , S 11 , S 12 S_{02},S_{10},S_{11}, S_{12} S02,S10,S11,S12的元素。
最终我们得到卷积输出的矩阵为一个2x3的矩阵S。
再举一个动态的卷积过程的例子如下:
我们有下面这个绿色的5x5输入矩阵,卷积核是一个下面这个黄色的3x3的矩阵。卷积的步幅是一个像素。则卷积的过程如下面的动图。卷积的结果是一个3x3的矩阵。
假设图像大小为NN矩阵,卷积核的尺寸为KK矩阵,图像边缘像素填充:P,卷积的步伐为S,那么经过一层这样的卷积后出来的图像为:W=(N-K+2P)/S+1
上面举的例子都是二维的输入,卷积的过程比较简单,那么如果输入是多维的呢?比如在前面一组卷积层+池化层的输出是3个矩阵,这3个矩阵作为输入呢,那么我们怎么去卷积呢?又比如输入的是对应RGB的彩色图像,即是三个分布对应R,G和B的矩阵呢?
在斯坦福大学的cs231n的课程上,有一个动态的例子,链接在这。建议大家对照着例子中的动图看下面的讲解。
大家打开这个例子可以看到,这里面输入是3个7x7的矩阵。实际上原输入是3个5x5的矩阵。只是在原来的输入周围加上了1的padding,即将周围都填充一圈的0,变成了3个7x7的矩阵。
例子里面使用了两个卷积核,我们先关注于卷积核W0。和上面的例子相比,由于输入是3个7x7的矩阵,或者说是7x7x3的张量,则我们对应的卷积核W0也必须最后一维是3的张量,这里卷积核W0的单个子矩阵维度为3x3。( 原图channel数和卷积核最厚一维维数相同,卷积核的个数是即模板的个数,比如4个1/4圆确定一个圆形)那么卷积核W0实际上是一个3x3x3的张量。同时和上面的例子比,这里的步幅为2,也就是每次卷积后会移动2个像素的位置。
最终的卷积过程和上面的2维矩阵类似,上面是矩阵的卷积,即两个矩阵对应位置的元素相乘后相加。这里是张量的卷积,即两个张量的3个子矩阵卷积后,再把卷积的结果相加后再加上偏倚b。
7x7x3的张量和3x3x3的卷积核张量W0卷积的结果是一个3x3的矩阵。由于我们有两个卷积核W0和W1,因此最后卷积的结果是两个3x3的矩阵。或者说卷积的结果是一个3x3x2的张量。
仔细回味下卷积的过程,输入是7x7x3的张量,卷积核是两个3x3x3的张量。卷积步幅为2,最后得到了输出是3x3x2的张量。如果把上面的卷积过程用数学公式表达出来就是:
s
(
i
,
j
)
=
(
X
∗
W
)
(
i
,
j
)
+
b
=
∑
k
=
1
n
_
i
n
(
X
k
∗
W
k
)
(
i
,
j
)
+
b
s(i,j)=(X*W)(i,j) + b = \sum\limits_{k=1}^{n\_in}(X_k*W_k)(i,j) +b
s(i,j)=(X∗W)(i,j)+b=k=1∑n_in(Xk∗Wk)(i,j)+b
其中,
n
_
i
n
n\_in
n_in为输入矩阵的个数,或者是张量的最后一维的维数。
X
k
X_k
Xk代表第k个输入矩阵(channel个)。
W
k
W_k
Wk代表卷积核的第k个子卷积核矩阵。
s
(
i
,
j
)
s(i,j)
s(i,j)即卷积核
W
W
W对应的输出矩阵的对应位置元素的值。
通过上面的例子,相信大家对CNN的卷积层的卷积过程有了一定的了解。
对于卷积后的输出,一般会通过ReLU激活函数,将输出的张量中的小于0的位置对应的元素值都变为0。
对图像的每个像素进行编号,用
x
i
,
j
x_{i,j}
xi,j表示图像的第行第列元素;用
w
m
,
n
w_{m,n}
wm,n表示filter第m行第n列权重,用
w
b
w_b
wb表示filter的偏置项;用
a
i
,
j
a_{i,j}
ai,j表示Feature Map的第i行第j列元素;用
f
f
f表示激活函数(这个例子选择relu函数作为激活函数)。使用下列公式计算卷积:
a
i
,
j
=
f
(
∑
m
=
0
2
∑
n
=
0
2
w
m
,
n
x
i
+
m
,
j
+
n
+
w
b
)
a_{i,j}=f(\sum_{m=0}^{2}\sum_{n=0}^{2}w_{m,n}x_{i+m,j+n}+w_{b})
ai,j=f(m=0∑2n=0∑2wm,nxi+m,j+n+wb)
如果卷积前的图像深度为D,那么相应的filter的深度也必须为D。我们扩展一下上式,得到了深度大于1的卷积计算公式:
a
d
,
i
,
j
=
f
(
∑
d
=
0
D
−
1
∑
m
=
0
F
−
1
∑
n
=
0
F
−
1
w
d
,
m
,
n
x
d
,
i
+
m
,
j
+
n
+
w
b
)
a_{d,i,j}=f(\sum_{d=0}^{D-1}\sum_{m=0}^{F-1}\sum_{n=0}^{F-1}w_{d,m,n}x_{d,i+m,j+n}+w_{b})
ad,i,j=f(d=0∑D−1m=0∑F−1n=0∑F−1wd,m,nxd,i+m,j+n+wb)
W2是卷积后Feature Map的宽度;W1是卷积前图像的宽度;F是filter的宽度;P是Zero Padding数量,Zero Padding。D是深度(卷积核个数);F是卷积核filter的矩阵维数;
w
d
,
m
,
n
w_{d,m,n}
wd,m,n表示filter的第d层第m行第n列权重;
a
d
,
i
,
j
a_{d,i,j}
ad,i,j表示Feature Map图像的第d层第i行第j列像素。
每个卷积层可以有多个filter。每个filter和原始图像进行卷积后,都可以得到一个Feature Map。因此,卷积后Feature Map的深度(个数)和卷积层的filter个数是相同的。
相比卷积层的复杂,池化层则要简单的多。 池化,就是对输入张量的各个子矩阵进行压缩。假如是2x2的池化,那么就将子矩阵的每2x2个元素变成一个元素,如果是3x3的池化,那么就将子矩阵的每3x3个元素变成一个元素,这样输入矩阵的维度就变小了。
要想将输入子矩阵的每nxn个元素变成一个元素,那么需要一个池化标准。 常见的池化标准有2个,MAX或者是Average。即取对应区域的最大值或者平均值作为池化后的元素值。
下面这个例子采用取最大值的池化方法。同时采用的是2x2的池化。步幅为2。
首先对红色2x2区域进行池化,由于此2x2区域的最大值为6.那么对应的池化输出位置的值为6,由于步幅为2,此时移动到绿色的位置去进行池化,输出的最大值为8.同样的方法,可以得到黄色区域和蓝色区域的输出值。最终,我们的输入4x4的矩阵在池化后变成了2x2的矩阵。进行了压缩。
理解了CNN模型中的卷积层和池化层,就基本理解了CNN的基本原理,后面再去理解CNN模型的前向传播算法和反向传播算法就容易了。下一篇我们就来讨论CNN模型的前向传播算法。
在卷积神经网络(CNN)模型结构中,我们对CNN的模型结构做了总结,这里我们就在CNN的模型基础上,看看CNN的前向传播算法是什么样子的。重点会和传统的DNN比较讨论。
CNN的结构,包括输出层,若干的卷积层+ReLU激活函数,若干的池化层,DNN全连接层,以及最后的用Softmax激活函数的输出层。这里我们用一个彩色的汽车样本的图像识别再从感官上回顾下CNN的结构。图中的CONV即为卷积层,POOL即为池化层,而FC即为DNN全连接层,包括了我们上面最后的用Softmax激活函数的输出层。
从上图可以看出,要理顺CNN的前向传播算法,重点是输入层的前向传播,卷积层的前向传播以及池化层的前向传播。而DNN全连接层和用Softmax激活函数的输出层的前向传播算法我们在讲DNN时已经讲到了。
CNN前向传播算法的第一步:输入层对应的卷积层,以图像识别为例。
先考虑最简单的,样本都是二维的黑白图片。这样输入层
X
X
X就是一个矩阵,矩阵的值等于图片的各个像素位置的值。这时和卷积层相连的卷积核
W
W
W就也是矩阵。
如果样本都是有RGB的彩色图片,这样输入 X X X就是3个矩阵,即分别对应R,G和B的矩阵,或者说是一个张量。这时和卷积层相连的卷积核 W W W就也是张量,对应的最后一维的维度为3.即每个卷积核都是3个子矩阵组成。
同样的方法,对于3D的彩色图片之类的样本,我们的输入 X X X可以是4维,5维的张量,那么对应的卷积核 W W W也是个高维的张量。
不管维度多高,对于我们的输入,前向传播的过程可以表示为: a 2 = σ ( z 2 ) = σ ( a 1 ∗ W 2 + b 2 ) a^2= \sigma(z^2) = \sigma(a^1*W^2 +b^2) a2=σ(z2)=σ(a1∗W2+b2)
其中,上标代表层数,星号代表卷积,而b代表我们的偏倚, σ \sigma σ为激活函数,这里一般都是ReLU。
和DNN的前向传播比较一下,其实形式非常的像,只是我们这儿是张量的卷积,而不是矩阵的乘法。同时由于 W W W是张量,那么同样的位置, W W W参数的个数就比DNN多很多了。
为了简化我们的描述,本文后面如果没有特殊说明,我们都默认输入是3维的张量,即用RBG可以表示的彩色图片。
这里需要我们自己定义的CNN模型参数是:
1) 卷积核个数K,对应的输入层的输出,或者说第二层卷积层的对应的输入为K个。
2) 卷积核中每个子矩阵的的大小,一般都用方矩阵,比如FxF的子矩阵。
3) 填充padding(以下简称P),我们卷积的时候,为了可以更好的识别边缘,一般都会在输入矩阵在周围加上若干圈的0再进行卷积,加多少圈则P为多少。
4) 步幅stride(以下简称S),即在卷积过程中每次移动的像素距离大小。
这些参数我们在上一篇都有讲述。
假设隐藏层的输出是M个矩阵对应(对应卷积核数)的三维张量,则输出到卷积层的卷积核也是M个子矩阵对应的三维张量。这时表达式和输入层的很像,也是 a l = σ ( z l ) = σ ( a l − 1 ∗ W l + b l ) a^l= \sigma(z^l) = \sigma(a^{l-1}*W^l +b^l) al=σ(zl)=σ(al−1∗Wl+bl)
其中,上标代表层数,星号代表卷积,而b代表我们的偏倚, σ \sigma σ为激活函数,这里一般都是ReLU。
也可以写成M个子矩阵子矩阵卷积后对应位置相加的形式,即: a l = σ ( z l ) = σ ( ∑ k = 1 M z k l ) = σ ( ∑ k = 1 M a k l − 1 ∗ W k l + b l ) a^l= \sigma(z^l) = \sigma(\sum\limits_{k=1}^{M}z_k^l) = \sigma(\sum\limits_{k=1}^{M}a_k^{l-1}*W_k^l +b^l) al=σ(zl)=σ(k=1∑Mzkl)=σ(k=1∑Makl−1∗Wkl+bl)
和上一节唯一的区别仅仅在于,这里的输入是隐藏层来的,而不是我们输入的原始图片样本形成的矩阵。
需要我们定义的CNN模型参数也和上一节一样,这里我们需要定义卷积核的个数K,卷积核子矩阵的维度F,填充大小P以及步幅S。
池化层的处理逻辑是比较简单的,我们的目的就是对输入的矩阵进行缩小概括。比如输入的若干矩阵是NxN维的,而我们的池化大小是kxk的区域,则输出的矩阵都是 N k × N k \frac{N}{k} \times \frac{N}{k} kN×kN维的。
这里需要需要我们定义的CNN模型参数是:
1)池化区域的大小k
2)池化的标准,一般是MAX或者Average。
由于全连接层就是普通的DNN模型结构,因此我们可以直接使用DNN的前向传播算法逻辑,即: a l = σ ( z l ) = σ ( W l a l − 1 + b l ) a^l = \sigma(z^l) = \sigma(W^la^{l-1} + b^l) al=σ(zl)=σ(Wlal−1+bl)
这里的激活函数一般是sigmoid或者tanh。
经过了若干全连接层之后,最后的一层为Softmax输出层。此时输出层和普通的全连接层唯一的区别是,激活函数是softmax函数。
这里需要需要我们定义的CNN模型参数是:
1)全连接层的激活函数
2)全连接层各层神经元的个数
有了上面的基础,我们现在总结下CNN的前向传播算法。
输入:1个图片样本,CNN模型的层数L和所有隐藏层的类型,对于卷积层,要定义卷积核的大小K,卷积核子矩阵的维度F,填充大小P,步幅S。对于池化层,要定义池化区域大小k和池化标准(MAX或Average),对于全连接层,要定义全连接层的激活函数(输出层除外)和各层的神经元个数。
输出:CNN模型的输出 a L a^L aL
1) 根据输入层的填充大小P,填充原始图片的边缘,得到输入张量 a 1 a^1 a1。
2)初始化所有隐藏层的参数 W , b W,b W,b
3)for l l l=2 to L − 1 L-1 L−1:
a) 如果第 l l l层是卷积层,则输出为 a l = R e L U ( z l ) = R e L U ( a l − 1 ∗ W l + b l ) a^l= ReLU(z^l) = ReLU(a^{l-1}*W^l +b^l) al=ReLU(zl)=ReLU(al−1∗Wl+bl)
b) 如果第 l l l层是池化层,则输出为 a l = p o o l ( a l − 1 ) a^l= pool(a^{l-1}) al=pool(al−1), 这里的pool指按照池化区域大小k和池化标准将输入张量缩小的过程。
c) 如果第 l l l层是全连接层,则输出为 a l = σ ( z l ) = σ ( W l a l − 1 + b l ) a^l= \sigma(z^l) = \sigma(W^la^{l-1} +b^l) al=σ(zl)=σ(Wlal−1+bl)
4)对于输出层第L层: a L = s o f t m a x ( z L ) = s o f t m a x ( W L a L − 1 + b L ) a^L= softmax(z^L) = softmax(W^La^{L-1} +b^L) aL=softmax(zL)=softmax(WLaL−1+bL)
以上就是CNN前向传播算法的过程总结。有了CNN前向传播算法的基础,我们后面再来理解CNN的反向传播算法就简单多了。下一篇我们来讨论CNN的反向传播算法。
在卷积神经网络(CNN)前向传播算法中,我们对CNN的前向传播算法做了总结,基于CNN前向传播算法的基础,我们下面就对CNN的反向传播算法做一个总结。在阅读本文前,建议先研究DNN的反向传播算法:深度神经网络(DNN)反向传播算法(BP)
我们首先回顾DNN的反向传播算法。在DNN中,我们是首先计算出输出层的 δ L \delta^L δL: δ L = ∂ J ( W , b ) ∂ z L = ∂ J ( W , b ) ∂ a L ⊙ σ ′ ( z L ) \delta^L = \frac{\partial J(W,b)}{\partial z^L} = \frac{\partial J(W,b)}{\partial a^L}\odot \sigma^{'}(z^L) δL=∂zL∂J(W,b)=∂aL∂J(W,b)⊙σ′(zL)
利用数学归纳法,用 δ l + 1 \delta^{l+1} δl+1的值一步步的向前求出第l层的 δ l \delta^l δl,表达式为: δ l = ( ∂ z l + 1 ∂ z l ) T δ l + 1 = ( W l + 1 ) T δ l + 1 ⊙ σ ′ ( z l ) \delta^{l} = (\frac{\partial z^{l+1}}{\partial z^{l}})^T\delta^{l+1} = (W^{l+1})^T\delta^{l+1}\odot \sigma^{'}(z^l) δl=(∂zl∂zl+1)Tδl+1=(Wl+1)Tδl+1⊙σ′(zl)
有了 δ l \delta^l δl的表达式,从而求出 W , b W,b W,b的梯度表达式: ∂ J ( W , b ) ∂ W l = δ l ( a l − 1 ) T \frac{\partial J(W,b)}{\partial W^l} = \delta^{l}(a^{l-1})^T ∂Wl∂J(W,b)=δl(al−1)T ∂ J ( W , b , x , y ) ∂ b l = = δ l \frac{\partial J(W,b,x,y)}{\partial b^l} = = \delta^{l} ∂bl∂J(W,b,x,y)==δl
有了 W , b W,b W,b梯度表达式,就可以用梯度下降法来优化 W , b W,b W,b,求出最终的所有 W , b W,b W,b的值。
现在我们想把同样的思想用到CNN中,很明显,CNN有些不同的地方,不能直接去套用DNN的反向传播算法的公式。
要套用DNN的反向传播算法到CNN,有几个问题需要解决:
1)池化层没有激活函数,这个问题倒比较好解决,我们可以令池化层的激活函数为 σ ( z ) = z \sigma(z) = z σ(z)=z,即激活后就是自己本身。这样池化层激活函数的导数为1.
2)池化层在前向传播的时候,对输入进行了压缩,那么我们现在需要向前反向推导 δ l − 1 \delta^{l-1} δl−1,这个推导方法和DNN完全不同。
3) 卷积层是通过张量卷积,或者说若干个矩阵卷积求和而得的当前层的输出,这和DNN很不相同,DNN的全连接层是直接进行矩阵乘法得到当前层的输出。这样在卷积层反向传播的时候,上一层的 δ l − 1 \delta^{l-1} δl−1递推计算方法肯定有所不同。
4)对于卷积层,由于 W W W使用的运算是卷积,那么从 δ l \delta^l δl推导出该层的所有卷积核的 W , b W,b W,b的方式也不同。
从上面可以看出,问题1比较好解决,但是问题2,3,4就需要好好的动一番脑筋了,而问题2,3,4也是解决CNN反向传播算法的关键所在。另外大家要注意到的是,DNN中的 a l , z l a_l,z_l al,zl都只是一个向量,而我们CNN中的 a l , z l a_l,z_l al,zl都是一个张量,这个张量是三维的,即由若干个输入的子矩阵组成。
下面我们就针对问题2,3,4来一步步研究CNN的反向传播算法。
在研究过程中,需要注意的是,由于卷积层可以有多个卷积核,各个卷积核的处理方法是完全相同且独立的,为了简化算法公式的复杂度,我们下面提到卷积核都是卷积层中若干卷积核中的一个。
我们首先解决上面的问题2,如果已知池化层的 δ l \delta^l δl,推导出上一隐藏层的 δ l − 1 \delta^{l-1} δl−1。
在前向传播算法时,池化层一般我们会用MAX或者Average对输入进行池化,池化的区域大小已知。现在我们反过来,要从缩小后的误差 δ l \delta^l δl,还原前一次较大区域对应的误差。
在反向传播时,我们首先会把 δ l \delta^l δl的所有子矩阵矩阵大小还原成池化之前的大小,然后如果是MAX,则把 δ l \delta^l δl的所有子矩阵的各个池化局域的值放在之前做前向传播算法得到最大值的位置。如果是Average,则把 δ l \delta^l δl的所有子矩阵的各个池化局域的值取平均后放在还原后的子矩阵位置。这个过程一般叫做upsample。
用一个例子可以很方便的表示:假设我们的池化区域大小是2x2。
δ
l
\delta^l
δl的第k个子矩阵为:
δ
k
l
=
(
2
8
4
6
)
\delta_k^l = \left(
由于池化区域为2x2,我们先讲
δ
k
l
\delta_k^l
δkl做还原,即变成:
(
0
0
0
0
0
2
8
0
0
4
6
0
0
0
0
0
)
\left(
如果是MAX,假设我们之前在前向传播时记录的最大值位置分别是左上,右下,右上,左下,则转换后的矩阵为:
(
2
0
0
0
0
0
0
8
0
4
0
0
0
0
6
0
)
\left(
如果是Average,则进行平均:转换后的矩阵为:
(
0.5
0.5
2
2
0.5
0.5
2
2
1
1
1.5
1.5
1
1
1.5
1.5
)
\left(
这样我们就得到了上一层 $\frac{\partial J(W,b)}{\partial a_k^{l-1}} 的 值 , 要 得 到 的值,要得到 的值,要得到\delta_k^{l-1} : : : δ k l − 1 = ( ∂ a k l − 1 ∂ z k l − 1 ) T ∂ J ( W , b ) ∂ a k l − 1 = u p s a m p l e ( δ k l ) ⊙ σ ′ ( z k l − 1 ) \delta_k^{l-1} = (\frac{\partial a_k^{l-1}}{\partial z_k^{l-1}})^T\frac{\partial J(W,b)}{\partial a_k^{l-1}} = upsample(\delta_k^l) \odot \sigma^{'}(z_k^{l-1}) δkl−1=(∂zkl−1∂akl−1)T∂akl−1∂J(W,b)=upsample(δkl)⊙σ′(zkl−1)$
其中,upsample函数完成了池化误差矩阵放大与误差重新分配的逻辑。
我们概括下,对于张量 δ l − 1 \delta^{l-1} δl−1,我们有: δ l − 1 = u p s a m p l e ( δ l ) ⊙ σ ′ ( z l − 1 ) \delta^{l-1} = upsample(\delta^l) \odot \sigma^{'}(z^{l-1}) δl−1=upsample(δl)⊙σ′(zl−1)
对于卷积层的反向传播,我们首先回忆下卷积层的前向传播公式: a l = σ ( z l ) = σ ( a l − 1 ∗ W l + b l ) a^l= \sigma(z^l) = \sigma(a^{l-1}*W^l +b^l) al=σ(zl)=σ(al−1∗Wl+bl)
其中 n _ i n n\_in n_in为上一隐藏层的输入子矩阵个数。
在DNN中,我们知道 δ l − 1 \delta^{l-1} δl−1和 δ l \delta^{l} δl的递推关系为: δ l = ∂ J ( W , b ) ∂ z l = ( ∂ z l + 1 ∂ z l ) T ∂ J ( W , b ) ∂ z l + 1 = ( ∂ z l + 1 ∂ z l ) T δ l + 1 \delta^{l} = \frac{\partial J(W,b)}{\partial z^l} =(\frac{\partial z^{l+1}}{\partial z^{l}})^T \frac{\partial J(W,b)}{\partial z^{l+1}} =(\frac{\partial z^{l+1}}{\partial z^{l}})^T\delta^{l+1} δl=∂zl∂J(W,b)=(∂zl∂zl+1)T∂zl+1∂J(W,b)=(∂zl∂zl+1)Tδl+1
因此要推导出 δ l − 1 \delta^{l-1} δl−1和 δ l \delta^{l} δl的递推关系,必须计算 ∂ z l ∂ z l − 1 \frac{\partial z^{l}}{\partial z^{l-1}} ∂zl−1∂zl的梯度表达式。
注意到 z l z^{l} zl和 z l − 1 z^{l-1} zl−1的关系为: z l = a l − 1 ∗ W l + b l = σ ( z l − 1 ) ∗ W l + b l z^l = a^{l-1}*W^l +b^l =\sigma(z^{l-1})*W^l +b^l zl=al−1∗Wl+bl=σ(zl−1)∗Wl+bl
因此我们有: δ l − 1 = ( ∂ z l ∂ z l − 1 ) T δ l = δ l ∗ r o t 180 ( W l ) ⊙ σ ′ ( z l − 1 ) \delta^{l-1} = (\frac{\partial z^{l}}{\partial z^{l-1}})^T\delta^{l} = \delta^{l}*rot180(W^{l}) \odot \sigma^{'}(z^{l-1}) δl−1=(∂zl−1∂zl)Tδl=δl∗rot180(Wl)⊙σ′(zl−1)
这里的式子其实和DNN的类似,区别在于对于含有卷积的式子求导时,卷积核被旋转了180度。即式子中的 r o t 180 ( ) rot180() rot180(),翻转180度的意思是上下翻转一次,接着左右翻转一次。在DNN中这里只是矩阵的转置。那么为什么呢?由于这里都是张量,直接推演参数太多了。我们以一个简单的例子说明为啥这里求导后卷积核要翻转。
假设我们 l − 1 l-1 l−1层的输出 a l − 1 a^{l-1} al−1是一个3x3矩阵,第 l l l层的卷积核 W l W^l Wl是一个2x2矩阵,采用1像素的步幅,则输出 z l z^{l} zl是一个2x2的矩阵。我们简化 b l 都 是 0 b^l都是0 bl都是0,则有 a l − 1 ∗ W l = z l a^{l-1}*W^l = z^{l} al−1∗Wl=zl
我们列出
a
,
W
,
z
a,W,z
a,W,z的矩阵表达式如下:
(
a
11
a
12
a
13
a
21
a
22
a
23
a
31
a
32
a
33
)
∗
(
w
11
w
12
w
21
w
22
)
=
(
z
11
z
12
z
21
z
22
)
\left(
利用卷积的定义,很容易得出: z 11 = a 11 w 11 + a 12 w 12 + a 21 w 21 + a 22 w 22 z_{11} = a_{11}w_{11} + a_{12}w_{12} + a_{21}w_{21} + a_{22}w_{22} z11=a11w11+a12w12+a21w21+a22w22 z 12 = a 12 w 11 + a 13 w 12 + a 22 w 21 + a 23 w 22 z_{12} = a_{12}w_{11} + a_{13}w_{12} + a_{22}w_{21} + a_{23}w_{22} z12=a12w11+a13w12+a22w21+a23w22 z 21 = a 21 w 11 + a 22 w 12 + a 31 w 21 + a 32 w 22 z_{21} = a_{21}w_{11} + a_{22}w_{12} + a_{31}w_{21} + a_{32}w_{22} z21=a21w11+a22w12+a31w21+a32w22 z 22 = a 22 w 11 + a 23 w 12 + a 32 w 21 + a 33 w 22 z_{22} = a_{22}w_{11} + a_{23}w_{12} + a_{32}w_{21} + a_{33}w_{22} z22=a22w11+a23w12+a32w21+a33w22
接着我们模拟反向求导: ∇ a l − 1 = ∂ J ( W , b ) ∂ a l − 1 = ( ∂ z l ∂ a l − 1 ) T ∂ J ( W , b ) ∂ z l = ( ∂ z l ∂ a l − 1 ) T δ l \nabla a^{l-1} = \frac{\partial J(W,b)}{\partial a^{l-1}} = ( \frac{\partial z^{l}}{\partial a^{l-1}})^T\frac{\partial J(W,b)}{\partial z^{l}} =(\frac{\partial z^{l}}{\partial a^{l-1}})^T \delta^{l} ∇al−1=∂al−1∂J(W,b)=(∂al−1∂zl)T∂zl∂J(W,b)=(∂al−1∂zl)Tδl
从上式可以看出,对于 a l − 1 a^{l-1} al−1的梯度误差 ∇ a l − 1 \nabla a^{l-1} ∇al−1,等于第 l l l层的梯度误差乘以 ∂ z l ∂ a l − 1 \frac{\partial z^{l}}{\partial a^{l-1}} ∂al−1∂zl,而 ∂ z l ∂ a l − 1 \frac{\partial z^{l}}{\partial a^{l-1}} ∂al−1∂zl对应上面的例子中相关联的 w w w的值。假设我们的 z z z矩阵对应的反向传播误差是 δ 11 , δ 12 , δ 21 , δ 22 \delta_{11}, \delta_{12}, \delta_{21}, \delta_{22} δ11,δ12,δ21,δ22组成的2x2矩阵,则利用上面梯度的式子和4个等式,我们可以分别写出 ∇ a l − 1 \nabla a^{l-1} ∇al−1的9个标量的梯度。
比如对于 a 11 a_{11} a11的梯度,由于在4个等式中 a 11 a_{11} a11只和 z 11 z_{11} z11有乘积关系,从而我们有: ∇ a 11 = δ 11 w 11 \nabla a_{11} = \delta_{11}w_{11} ∇a11=δ11w11
对于 a 12 a_{12} a12的梯度,由于在4个等式中 a 12 a_{12} a12和 z 12 , z 11 z_{12},z_{11} z12,z11有乘积关系,从而我们有: ∇ a 12 = δ 11 w 12 + δ 12 w 11 \nabla a_{12} = \delta_{11}w_{12} + \delta_{12}w_{11} ∇a12=δ11w12+δ12w11
同样的道理我们得到: ∇ a 13 = δ 12 w 12 \nabla a_{13} = \delta_{12}w_{12} ∇a13=δ12w12 ∇ a 21 = δ 11 w 21 + δ 21 w 11 \nabla a_{21} = \delta_{11}w_{21} + \delta_{21}w_{11} ∇a21=δ11w21+δ21w11 ∇ a 22 = δ 11 w 22 + δ 12 w 21 + δ 21 w 12 + δ 22 w 11 \nabla a_{22} = \delta_{11}w_{22} + \delta_{12}w_{21} + \delta_{21}w_{12} + \delta_{22}w_{11} ∇a22=δ11w22+δ12w21+δ21w12+δ22w11 ∇ a 23 = δ 12 w 22 + δ 22 w 12 \nabla a_{23} = \delta_{12}w_{22} + \delta_{22}w_{12} ∇a23=δ12w22+δ22w12 ∇ a 31 = δ 21 w 21 \nabla a_{31} = \delta_{21}w_{21} ∇a31=δ21w21 ∇ a 32 = δ 21 w 22 + δ 22 w 21 \nabla a_{32} = \delta_{21}w_{22} + \delta_{22}w_{21} ∇a32=δ21w22+δ22w21 ∇ a 33 = δ 22 w 22 \nabla a_{33} = \delta_{22}w_{22} ∇a33=δ22w22
这上面9个式子其实可以用一个矩阵卷积的形式表示,即:
(
0
0
0
0
0
δ
11
δ
12
0
0
δ
21
δ
22
0
0
0
0
0
)
∗
(
w
22
w
21
w
12
w
11
)
=
(
∇
a
11
∇
a
12
∇
a
13
∇
a
21
∇
a
22
∇
a
23
∇
a
31
∇
a
32
∇
a
33
)
\left(
为了符合梯度计算,我们在误差矩阵周围填充了一圈0,此时我们将卷积核翻转后和反向传播的梯度误差进行卷积,就得到了前一次的梯度误差。这个例子直观的介绍了为什么对含有卷积的式子反向传播时,卷积核要翻转180度的原因。
以上就是卷积层的误差反向传播过程。
好了,我们现在已经可以递推出每一层的梯度误差 δ l \delta^l δl了,对于全连接层,可以按DNN的反向传播算法求该层 W , b W,b W,b的梯度,而池化层并没有 W , b W,b W,b,也不用求 W , b W,b W,b的梯度。只有卷积层的 W , b W,b W,b需要求出。
注意到卷积层 z z z和 W , b W,b W,b的关系为: z l = a l − 1 ∗ W l + b z^l = a^{l-1}*W^l +b zl=al−1∗Wl+b
因此我们有: ∂ J ( W , b ) ∂ W l = a l − 1 ∗ δ l \frac{\partial J(W,b)}{\partial W^{l}}=a^{l-1} *\delta^l ∂Wl∂J(W,b)=al−1∗δl
注意到此时卷积核并没有反转,主要是此时是层内的求导,而不是反向传播到上一层的求导。具体过程我们可以分析一下。
和第4节一样的一个简化的例子,这里输入是矩阵,不是张量,那么对于第l层,某个个卷积核矩阵W的导数可以表示如下: ∂ J ( W , b ) ∂ W p q l = ∑ i ∑ j ( δ i j l a i + p − 1 , j + q − 1 l − 1 ) \frac{\partial J(W,b)}{\partial W_{pq}^{l}} = \sum\limits_i\sum\limits_j(\delta_{ij}^la_{i+p-1,j+q-1}^{l-1}) ∂Wpql∂J(W,b)=i∑j∑(δijlai+p−1,j+q−1l−1)
假设我们输入 a a a是4x4的矩阵,卷积核 W W W是3x3的矩阵,输出 z z z是2x2的矩阵,那么反向传播的 z z z的梯度误差 δ \delta δ也是2x2的矩阵。
那么根据上面的式子,我们有: ∂ J ( W , b ) ∂ W 11 l = a 11 δ 11 + a 12 δ 12 + a 21 δ 21 + a 22 δ 22 \frac{\partial J(W,b)}{\partial W_{11}^{l}} = a_{11}\delta_{11} + a_{12}\delta_{12} + a_{21}\delta_{21} + a_{22}\delta_{22} ∂W11l∂J(W,b)=a11δ11+a12δ12+a21δ21+a22δ22
∂ J ( W , b ) ∂ W 12 l = a 12 δ 11 + a 13 δ 12 + a 22 δ 21 + a 23 δ 22 \frac{\partial J(W,b)}{\partial W_{12}^{l}} = a_{12}\delta_{11} + a_{13}\delta_{12} + a_{22}\delta_{21} + a_{23}\delta_{22} ∂W12l∂J(W,b)=a12δ11+a13δ12+a22δ21+a23δ22
∂ J ( W , b ) ∂ W 13 l = a 13 δ 11 + a 14 δ 12 + a 23 δ 21 + a 24 δ 22 \frac{\partial J(W,b)}{\partial W_{13}^{l}} = a_{13}\delta_{11} + a_{14}\delta_{12} + a_{23}\delta_{21} + a_{24}\delta_{22} ∂W13l∂J(W,b)=a13δ11+a14δ12+a23δ21+a24δ22
∂ J ( W , b ) ∂ W 21 l = a 21 δ 11 + a 22 δ 12 + a 31 δ 21 + a 32 δ 22 \frac{\partial J(W,b)}{\partial W_{21}^{l}} = a_{21}\delta_{11} + a_{22}\delta_{12} + a_{31}\delta_{21} + a_{32}\delta_{22} ∂W21l∂J(W,b)=a21δ11+a22δ12+a31δ21+a32δ22
最终我们可以一共得到9个式子。整理成矩阵形式后可得:
∂
J
(
W
,
b
)
∂
W
l
=
(
a
11
a
12
a
13
a
14
a
21
a
22
a
23
a
24
a
31
a
32
a
33
a
34
a
41
a
42
a
43
a
44
)
∗
(
δ
11
δ
12
δ
21
δ
22
)
\frac{\partial J(W,b)}{\partial W^{l}} =\left(
从而可以清楚的看到这次我们为什么没有反转的原因。
而对于b,则稍微有些特殊,因为 δ l \delta^l δl是高维张量,而 b b b只是一个向量,不能像DNN那样直接和 δ l \delta^l δl相等。通常的做法是将 δ l \delta^l δl的各个子矩阵的项分别求和,得到一个误差向量,即为 b b b的梯度: ∂ J ( W , b ) ∂ b l = ∑ u , v ( δ l ) u , v \frac{\partial J(W,b)}{\partial b^{l}} = \sum\limits_{u,v}(\delta^l)_{u,v} ∂bl∂J(W,b)=u,v∑(δl)u,v
现在我们总结下CNN的反向传播算法,以最基本的批量梯度下降法为例来描述反向传播算法。
输入:m个图片样本,CNN模型的层数L和所有隐藏层的类型,对于卷积层,要定义卷积核的大小K,卷积核子矩阵的维度F,填充大小P,步幅S。对于池化层,要定义池化区域大小k和池化标准(MAX或Average),对于全连接层,要定义全连接层的激活函数(输出层除外)和各层的神经元个数。梯度迭代参数迭代步长 α \alpha α,最大迭代次数MAX与停止迭代阈值 ϵ \epsilon ϵ
输出:CNN模型各隐藏层与输出层的 W , b W,b W,b
1) 初始化各隐藏层与输出层的各 W , b W,b W,b的值为一个随机值。
2)for iter to 1 to MAX:
2-1) for i =1 to m:
a) 将CNN输入 a 1 a^1 a1设置为 x i x_i xi对应的张量
b) for l l l=2 to L-1,根据下面3种情况进行前向传播算法计算:
b-1) 如果当前是全连接层:则有 a i , l = σ ( z i , l ) = σ ( W l a i , l − 1 + b l ) a^{i,l} = \sigma(z^{i,l}) = \sigma(W^la^{i,l-1} + b^{l}) ai,l=σ(zi,l)=σ(Wlai,l−1+bl)
b-2) 如果当前是卷积层:则有 a i , l = σ ( z i , l ) = σ ( W l ∗ a i , l − 1 + b l ) a^{i,l} = \sigma(z^{i,l}) = \sigma(W^l*a^{i,l-1} + b^{l}) ai,l=σ(zi,l)=σ(Wl∗ai,l−1+bl)
b-3) 如果当前是池化层:则有$ a^{i,l}= pool(a^{i,l-1})$, 这里的pool指按照池化区域大小k和池化标准将输入张量缩小的过程。
c) 对于输出层第L层: $ a^{i,L}= softmax(z^{i,L}) = softmax(W{L}a{i,L-1} +b^{L})$
c) 通过损失函数计算输出层的 δ i , L \delta^{i,L} δi,L
d) for l l l= L-1 to 2, 根据下面3种情况进行进行反向传播算法计算:
d-1) 如果当前是全连接层: δ i , l = ( W l + 1 ) T δ i , l + 1 ⊙ σ ′ ( z i , l ) \delta^{i,l} = (W^{l+1})^T\delta^{i,l+1}\odot \sigma^{'}(z^{i,l}) δi,l=(Wl+1)Tδi,l+1⊙σ′(zi,l)
d-2) 如果当前是卷积层:$\delta^{i,l} = \delta{i,l+1}*rot180(W{l+1}) \odot \sigma{'}(z{i,l}) $
d-3) 如果当前是池化层: δ i , l = u p s a m p l e ( δ i , l + 1 ) ⊙ σ ′ ( z i , l ) \delta^{i,l} = upsample(\delta^{i,l+1}) \odot \sigma^{'}(z^{i,l}) δi,l=upsample(δi,l+1)⊙σ′(zi,l)
2-2) for l l l = 2 to L,根据下面2种情况更新第 l l l层的 W l , b l W^l,b^l Wl,bl:
2-2-1) 如果当前是全连接层:$W^l = W^l -\alpha \sum\limits_{i=1}^m \delta{i,l}(a{i, l-1})^T $, b l = b l − α ∑ i = 1 m δ i , l b^l = b^l -\alpha \sum\limits_{i=1}^m \delta^{i,l} bl=bl−αi=1∑mδi,l
2-2-2) 如果当前是卷积层,对于每一个卷积核有:$W^l = W^l -\alpha \sum\limits_{i=1}^m a^{i, l-1}*\delta^{i,l} $, b l = b l − α ∑ i = 1 m ∑ u , v ( δ i , l ) u , v b^l = b^l -\alpha \sum\limits_{i=1}^m \sum\limits_{u,v}(\delta^{i,l})_{u,v} bl=bl−αi=1∑mu,v∑(δi,l)u,v
2-3) 如果所有 W , b W,b W,b的变化值都小于停止迭代阈值 ϵ \epsilon ϵ,则跳出迭代循环到步骤3。
3) 输出各隐藏层与输出层的线性关系系数矩阵 W W W和偏倚向量 b b b。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。