神经网络与机器学习第9章 卷积神经网络
神经网络与机器学习
第9章 卷积神经网络


在机器视觉和其他很多问题上,卷积神经网络取得了当前最好的效果,它的成功促使我们思考一个问题,卷积神经网络为什么会这么有效?本章将学习卷积神经网络背后的奥秘。

Hubel和Weisel庆祝获得1981年诺贝尔生理医学奖
上世纪60年代,Hubel和Weisel等人通过对猫视觉皮层细胞的研究,提出了感受野这个概念,他们发现研究视网膜神经节细胞的方法,把微电极插到初级视皮层的神经细胞里面去,然后用小光点一点点地在视网膜上探测,看它落到视网膜的哪些地方才能引起所记录的神经细胞发放模式的变化,以及发生的是什么样的变化,并把视网膜上的这些地方标出来,这样就可以得出这些细胞的感受野的相应结构。他们发现,初级视皮层有一块1毫米见方的区域,其中所有神经细胞的感受野都集中在视觉空间的某个区域里,并且相邻细胞的最优朝向在 0°~180°的范围内有规则地连续变化。有趣的是,在厚度为 2mm的垂直范围内,每个细胞的最优朝向都是一样的,他们称之为"朝向功能柱"。另外,初级视皮层里的细胞有的对来自左眼的刺激反应猛烈,有的则对来自右眼的刺激反应猛烈。它们各自靠近成群,并且在厚度为 2mm的垂直范围内每个细胞的主宰眼也完全一样。他们还发现,左眼主宰还是右眼主宰的细胞群也是交替排列的,组成了他们所谓的"眼优势功能柱"。

眼优势功能柱
到80年代,Fukushima在感受野概念的基础之上提出了神经认知机的概念,可以看作是卷积神经网络的第一个实现网络,神经认知机将一个视觉模式分解成许多子模式(特征),然后进入分层递阶式相连的特征平面进行处理,它试图将视觉系统模型化,使其能够在即使物体有位移或轻微变形的时候,也能完成识别。通常神经认知机包含两类神经元,即承担特征提取的采样元和抗变形的卷积元,采样元中涉及两个重要参数,即感受野与阈值参数,前者确定输入连接的数目,后者则控制对特征子模式的反应程度。卷积神经网络可以看作是神经认知机的推广形式,神经认知机是卷积神经网络的一种特例。
真正意义上的卷积神经网络 CNN是由纽约大学的Yann LeCun于1998年提出。CNN本质上是一个多层感知机,其成功的原因关键在于它所采用的局部连接和共享权值的方式,一方面减少了的权值的数量使得网络易于优化,另一方面降低了过拟合的风险。CNN是神经网络中的一种,它的权值共享网络结构使之更类似于生物神经网络,降低了网络模型的复杂度,减少了权值的数量。该优点在网络的输入是多维图像时表现的更为明显,使图像可以直接作为网络的输入,避免了传统识别算法中复杂的特征提取和数据重建过程。在二维图像处理上有众多优势,如网络能自行抽取图像特征包括颜色、纹理、形状及图像的拓扑结构;在处理二维图像问题上,特别是识别位移、缩放及其它形式扭曲不变性的应用上具有良好的鲁棒性和运算效率等。
CNN是一个前馈式神经网络,能从一个二维图像中提取其拓扑结构,采用反向传播算法来优化网络结构,求解网络中的未知参数。CNN本身可以采用不同的神经元和学习规则的组合形式。CNN具有一些传统技术所没有的优点:良好的容错能力、并行处理能力和自学习能力,可处理环境信息复杂,背景知识不清楚,推理规则不明确情况下的问题,允许样品有较大的缺损、畸变,运行速度快,自适应性能好,具有较高的分辨率。它是通过结构重组和减少权值将特征抽取功能融合进多层感知器,省略识别前复杂的图像特征抽取过程。CNN的泛化能力要显著优于其它方法,卷积神经网络已被应用于模式分类,物体检测和物体识别等方面。
CNN可以用来识别位移、缩放及其它形式扭曲不变性的二维或三维图像。CNN的特征提取层参数是通过训练数据学习得到的,所以其避免了人工特征提取,而是从训练数据中进行学习;其次同一特征图的神经元共享权值,减少了网络参数,这也是卷积网络相对于全连接网络的一大优势。共享局部权值这一特殊结构更接近于真实的生物神经网络使CNN在图像处理、语音识别领域有着独特的优越性,另一方面权值共享同时降低了网络的复杂性,且多维输入信号(语音、图像)可以直接输入网络的特点避免了特征提取和分类过程中数据重排的过程。
CNN是一种深度的监督学习下的机器学习模型,具有极强的适应性,善于挖掘数据局部特征,提取全局训练特征和分类,它的权值共享结构网络使之更类似于生物神经网络,在模式识别各个领域都取得了很好的成果。

卷积网络发展历史
作业:阅读文献
Asifullah Khan, Anabia Sohail, Umme Zahoora, Aqsa Saeed Qureshi,A Survey of the Recent Architectures of Deep Convolutional Neural Networks,arXiv:1901.06032,2020
翻译
https://blog.csdn.net/Ai_Smith/article/details/102948140
§9.1 数字图像处理基础
人类的90%信息来源于眼睛的图像,然而由于计算机的发展,模拟图像转为数字图像,进行编码,更加便于传输和存储,这个过程中由于信息的损失,因此图像需要增强和复原,以便于更加容易地辨别各种探测器所拍摄的图像,也需要对应图像进行分割和描述,这也是机器视觉的前期环节之一。
Matlab中单色图像表示为一个矩阵
\[f(m,n)=\begin{bmatrix} f(1,1) & \cdots & f(1,N)\\ \vdots & \ddots & \vdots\\ f(M,1) & \cdots & f(M,N) \end{bmatrix}\]
$0 \leq f(m,n) \leq G-1$成为像素,其大小表示亮度,数值化表示称为灰度级,M,N,G一般用2的整数幂次表示。这也是为何图像常用256*256,128*128等等表述。那么如果一副灰度级图像大小N*N,灰度级为$m$,则存储它需要比特数
N ×N ×m
256*256的$2^m=256$灰度级则是
256×256×8=2097152
2M左右。
彩色图像RGB,就是三原色red,blue,green,三种颜色的亮度值各自存在各自的图像矩阵中,所以彩色图像的格式是M ×N ×3,按此推论,视频就是再加上一维。
卷积
线性时不变系统中卷积我们都知道,系统传递函数能够完全刻画系统特征,系统输出输入关系
\[y(t)=\int x(\tau)g(t-\tau)d\tau\]
$g(t-\tau)$就是反折,平移。
离散化系统卷积,设两个向量$x,g$长度分别是m,n,则y是长度为 m+n-1 且第 k 个元素为
\[y(k)=\sum_i x(i)g(k-i+1)\]
+1为了Matlab的下标开始而已,无他,如果从0开始下标,则无+1。
y(1) = x(1)*g(1)
y(2) = x(1)*g(2)+x(2)*g(1)
y(3) = x(1)*g(3)+x(2)*g(2)+x(3)*g(1)
$\vdots$
这样就是全卷积
x = [-1 2 3 -2 0 1 2];
g = [2 4 -1 1];
>> y = conv(x,g)
y = -2 0 15 5 -9 7 6 7 -1 2
>> y = conv(x,g,'same')%与x长度相同
y =15 5 -9 7 6 7 -1
>> y = conv(x,g,'valid')%凡是补零的都剔除
y =5 -9 7 6
我们知道时域卷积,频域就是Fourier变换相乘
\[y(t)=\int g(t-\tau)x(\tau)d\tau\rightarrow Y(\omega)=X(\omega)G(\omega)\]
因此我们可以说系统频域函数$G(\omega)$在频域对应输入信号频域$X(\omega)$进行特定的频域成分进行了修改,所以称为对于信号进行了滤波。
推而广之,二维图像则需要二维卷积
\[y(\alpha,\beta)=\int x(u,v)g(\alpha -u,\beta -v)dudv\]
离散二维卷积是
\[y(j,k)=\sum_p\sum_q x(p,q)g(j-p+1,k-q+1)\]
同一维卷积一样,$g(p,q)$就是对于图像进行二维滤波,我们称之为卷积核,有称为卷积模板,卷积算子,等等。
例子:Sobel 求边运算利用二维卷积来检测图像的边和其他二维数据。创建并绘制一个内部高度等于 1 的二维台座。
A = zeros(10);
A(3:7,3:7) = ones(5);
mesh(A)

二维台座
首先求 A 的各行与向量 u 的卷积,然后求卷积结果的各行与向量 v 的卷积。卷积提取台座的水平边。
u = [1 0 -1]';
v = [1 2 1];
Ch = conv2(u,v,A);
mesh(Ch)

水平梯度提取边缘
要提取台座的垂直边,请反转与 u 和 v 的卷积顺序。
Cv = conv2(v,u,A);
mesh(Cv)

垂直梯度提取边缘
计算并绘制台座的组合边。
figure
mesh(sqrt(Ch.^2 + Cv.^2))

组合边缘
注意上面一个像素就是一个方格表示。
最小的卷积模板是$\begin{bmatrix} -1 & +1 \end{bmatrix}$,或者$\begin{bmatrix} -1\\ +1 \end{bmatrix}$,表示沿着x轴或y轴,计算相邻两个像素的差。这是因为对于图像二维函数
\[\frac{\partial f(x,y)}{\partial x}=\lim_{\epsilon\rightarrow 0}\frac{f(x+\epsilon,y)-f(x,y)}{\epsilon}\rightarrow f(x+1,y)-f(x,y)\]
\[\frac{\partial f(x,y)}{\partial y}=\lim_{\epsilon\rightarrow 0}\frac{f(x,y+\epsilon)-f(x,y)}{\epsilon}\rightarrow f(x+1,y)-f(x,y)\]
像素为离散值,最小$\epsilon$取1,那么沿着两个方向的离散差分就变成了上面所示公式,那么对应的卷积模板$\begin{bmatrix} -1 & +1 \end{bmatrix}$和$\begin{bmatrix} -1\\ +1 \end{bmatrix}$。
$f(x,y)$点的梯度,是此点变化率最大的方向,其幅值是函数最大变化率
\[M(x,y)=\sqrt{\left(\frac{\partial f(x,y)}{\partial x}\right)^2+\left(\frac{\partial f(x,y)}{\partial y}\right)^2}\]
这样计算量太大,所以近似为
\[M(x,y)=\left | \frac{\partial f(x,y)}{\partial x}\right |+\left | \frac{\partial f(x,y)}{\partial y} \right |\]
>> X=imread('mandi.tif');
>> imshow(X)
figure
>> Y=conv2([-1 1],X);
>> imshow(Y)


最小卷积模板求一阶差分
一维信号平均化即低通滤波,比如连续3个灰度值的平均视为一个灰度
\[f(x_k)=\frac{f(x_{k-1})+f(x_k)+f(x_{k+1})}{3}\]
推广到梯度上,当前像素与前后的差值的平均可以当成梯度的估计
\[\triangledown f(x_k)=\frac{f(x_{k+1})-f(x_k)+f(x_k)-f(x_{k-1})}{2}=\frac{f(x_{k+1})-f(x_{k-1})}{2}\]
如果将上面像素平均值再移植到梯度平均上得到
\[\triangledown f(x_k)=\frac{f(x_{k+2})+f(x_{k+1})-f(x_{k-1})-f(x_{k-2})}{6}\]
可见
\[\begin{bmatrix} -\frac{1}{6} & -\frac{1}{6} & 0 & \frac{1}{6} & \frac{1}{6} \end{bmatrix}\]
把平滑和一阶差分合成了一个卷积模板。
>> Y=conv2([-1 -1 0 1 1]/6,X);
>> imshow(Y)
很可怕,牙齿都差分出来了。

平滑+差分
索贝尔算子(Sobel operator)主要用于获得数字图像的一阶梯度,是一种离散性差分算子。它是prewitt算子的改进形式,改进之处在于sobel算子认为,邻域的像素对当前像素产生的影响不是等价的,所以距离不同的像素具有不同的权值,对算子结果产生的影响也不同。一般来说,距离越远,产生的影响越小。图像处理中认为,灰度值变化剧烈的地方就是边缘。那么如何判断灰度值变化?如何度量"剧烈"?Sobel算子就对这些问题做了自己的规范,而且命名为sobel算子,就是对一副图像的输入到输出边缘信息的整个处理过程。
以后我们会遇到很多卷积模板,都是有其来源,这里我们将Sobel算子如何产生的做一下简单总结。
http://blog.sciencenet.cn/blog-425437-776050.html
http://blog.sciencenet.cn/blog-425437-1139187.html
数字图像使用的二维卷积模板应该同时具有光滑和差分运算的功能,最小的就是的卷积模板,应该具有这样的形式
\[\begin{bmatrix} w_{1,1} & w_{1,2} & w_{1,3}\\ w_{2,1} & w_{2,2} & w_{2,3}\\ w_{3,1} & w_{3,2} & w_{3,3} \end{bmatrix}\]
如何设计呢?先选择一个计算列,再选择一个计算行,应该满足
第一:$\triangledown f(x_k)$应该是$\triangledown f(y_k)$旋转90度,计算得到值记录在中心像素上;
第二:像素左右权值应该相同,因此左右两列应该相同
\[\begin{bmatrix} w_{1,1} & w_{1,2} & w_{1,1}\\ w_{2,1} & w_{2,2} & w_{2,1}\\ w_{3,1} & w_{3,2} & w_{3,1} \end{bmatrix}\]
第三: 为了计算差分,中心像素点上下应该相同权重,且相反符号
\[\begin{bmatrix} w_{1,1} & w_{1,2} & w_{1,1}\\ w_{2,1} & w_{2,2} & w_{2,1}\\ -w_{1,1} & -w_{1,2} & -w_{1,1} \end{bmatrix}\]
第四:零响应,那么所有权值之和为0,得到$w_{2,2}=-2w_{2,1}$
\[\begin{bmatrix} w_{1,1} & w_{1,2} & w_{1,1}\\ w_{2,1} & -2w_{2,1} & w_{2,1}\\ -w_{1,1} & -w_{1,2} & -w_{1,1} \end{bmatrix}\]
第5:信号光滑时,列的方向差分计算,希望每一列的都是0输出,因此$w_{2,1}=0$
\[\begin{bmatrix} w_{1,1} & w_{1,2} & w_{1,1}\\ 0 & 0 & 0\\ -w_{1,1} & -w_{1,2} & -w_{1,1} \end{bmatrix}\]
第六:所有的权值都除以$w_{1,1}$,发现只有一个参数K
\[\begin{bmatrix} 1& K & 1\\ 0 & 0 & 0\\ -1 & -K & -1 \end{bmatrix}\]
取K=2的话,得到两个方向的Sobel算子
\[Gx=\begin{bmatrix} 1& 2 & 1\\ 0 & 0 & 0\\ -1 & -2 & -1 \end{bmatrix}\],\[Gy=\begin{bmatrix} 1& 0 & -1\\ 2 & 0 & -2\\ 1 & 0& -1 \end{bmatrix}\]
上面是一种解释。下面提出者Sobel自己的解释,大家可以查找如下资料进行详细解读。
http://blog.sciencenet.cn/blog-425437-776050.html
http://blog.sciencenet.cn/blog-425437-1139187.html
Sobel算子具有严格的数学基础,主要关键点在于:
1)笛卡尔网格(Cartesian grid);
2)前向差分(Forward-difference);
3)距离反比的4方向对梯度加权;
4)城市距离(City-block distance)。曼哈顿距离又称"城市街区距离(city block distance)",其正式意义为L1距离,度量方法是数据之间的绝对差的和.例如在平面上,坐标(x1,y1)的 i 点与坐标(x2,y2)的 j 点的曼哈顿距离为:
d(i,j) = |X1 - X2| + |Y1 - Y2|
如果改用欧式距离,就不难得到Frei和Chen(1991)提出的边缘检测器了,教科书上的一些经典滤波器,其实也都有它的计算模型,而不是人为的随意构建,如高斯(Gaussian)滤波器,拉普拉斯(Laplacian)滤波器,LoG滤波器等。
*********************
Gx=[1.0 2.0 1.0;0.0 0.0 0.0;-1.0 -2.0 -1.0];
Gy=[-1.0 0.0 1.0;-2.0 0.0 2.0;-1.0 0.0 1.0];
img=imread('moon.tif');
%image=rgb2gray(img);
subplot(2,2,1);
imshow(image);
title('原图');
gradx=conv2(Gx,image,'full');
gradx=abs(gradx); %计算图像的sobel垂直梯度
subplot(2,2,2);
imshow(gradx,[]);
title('图像的sobel垂直梯度');
grady=conv2(Gy,image,'full');
grady=abs(grady); %计算图像的sobel水平梯度
subplot(2,2,3);
imshow(grady,[]);
title('图像的sobel水平梯度');
grad=gradx+grady; %得到图像的sobel梯度
subplot(2,2,4);
imshow(grad,[]);
title('图像的sobel梯度');
******************************

§9.2 卷积神经网络的组成
典型的卷积神经网络(Convolutional Neural Network)CNN中,开始几层都是卷积和下采样的交替,然后在最后一些层(靠近输出层的),都是全连接一维网络。卷积神经网络采用三种基本概念:局部感受野(local receptive fields),共享权值(shared weights)和池化(pooling,也有称为混合,或者subsample,下采样),我们逐个看。
首先数学定义离散二维卷积为
\[Y(j,k)=G*X=\sum_p\sum_q G(p,q)X(j-p,k-q)\]
但是卷积神经网络的卷积定义为
\[Y(j,k)=G*X=\sum_p\sum_q G(p,q)X(j+p,k+q)\]



举个例子如下,图中的输入是一个二维的3x4的矩阵,而卷积核是一个2x2的矩阵。这里我们假设卷积是一次移动一个像素来卷积的,那么首先我们对输入的左上角2x2局部和卷积核卷积,即各个位置的元素相乘再相加,得到的输出矩阵Y的Y(0,0)元素值为
\[Y(0,0)=\sum_p\sum_q G(p,q)X(p,q) =aw+bx+ey+fz\]
接着我们将输入的局部向右平移一个像素
\[Y(0,1)=\sum_p\sum_q G(p,q)X(p,1+q) =bw+cx+fy+gz\]
我们一般选择不补零的卷积方式,那么设G的维数是$P \times Q$,图像X是$M \times N$的,那么卷积之后的矩阵Y的维数是$(M-P+1) \times (N-Q+1)$。


局部感受野
在之前的全连接层的网络中,输入被描绘成纵向排列的神经元,但在一个卷积网络中,把输入看作是28×28的方形排列的神经元,其值对应于我们用作输入的像素强度。

和通常⼀样,我们把输⼊像素连接到⼀个隐藏神经元层。但是我们不会把每个输⼊像素连接到每个隐藏神经元。相反,我们只是把输⼊图像进⾏⼩的,局部区域的连接。说的确切⼀点,第⼀个隐藏层中的每个神经元会连接到⼀个输⼊神经元的⼀个⼩区域,例如,⼀个5×5 的区域,对应于25 个输⼊像素。所以对于⼀个特定的隐藏神经元,我们可能有看起来像这样的连接:

这个输出图像的区域被称为隐藏神经元的局部感受野。它是输出像上的一个小窗口。每个连接学习一个权重。而隐藏神经元同时也学习一个总的偏置。你可以把这个特定的隐藏神经元看作是在学习分析它的局部感受野。然后在整个输出图像上移动局部感受野。对于每个局部感受野,在第一个隐藏层中有一个不同的隐藏神经元。为了正确说明,让我们从左上⻆开始一个局部感受野:

然后我们往右移动局部感受野,连接到第二个隐藏神经元:

如此重复,构建起第⼀个隐藏层。注意如果我们有⼀个28 × 28 的输⼊图像,5 × 5 的局部感受野,那么隐藏层中就会有24 × 24 个神经元。这是因为在抵达右边(或者底部)的输⼊图像之前,我们只能把局部感受野横向移动23 个神经元(或者往下23 个神经元)。显⽰的局部感受野每次移动⼀个像素。实际上,有时候会使⽤不同的跨距。例如,我可以往右(或下)移动2 个像素的局部感受野,这种情况下我们使⽤了2 个跨距。在这章⾥我们⼤部分时候会固定使⽤1 的跨距,但是值得知道⼈们有时⽤不同的跨距试验2。

共享权重和偏置
每个隐藏神经元具有⼀个偏置和连接到它的局部感受野的5×5 权重, 24 × 24 隐藏神经元中的每⼀个使⽤相同的权重和偏置。具体来说,对于隐藏的j行k列的神经元,其输出为
\[f(W*a+b)=f(\sum_{l=0}^4 \sum_{m=0}^{4}w_{l,m}a_{j+l,k+m}+b)\]
这意味着第⼀个隐藏层的所有神经元检测完全相同的特征3,只是在输⼊图像的不同位置。要明⽩为什么是这个道理,把权重和偏置设想成隐藏神经元可以挑选的东西,例如,在⼀个特定的局部感受野的垂直边缘。这种能⼒在图像的其它位置也很可能是有⽤的。因此,在图像中应⽤相同的特征检测器是⾮常有⽤的。⽤稍微更抽象的术语,卷积⽹络能很好地适应图像的平移不变性:例如稍稍移动⼀幅猫的图像,它仍然是⼀幅猫的图像。
因为这个原因,我们有时候把从输⼊层到隐藏层的映射称为⼀个特征映射。我们把定义特征映射的权重称为共享权重。我们把以这种⽅式定义特征映射的偏置称为共享偏置。共享权重和偏置经常被称为⼀个卷积核或者滤波器。在⽂献中,⼈们有时以稍微不同的⽅式使⽤这些术语,稍后我们会看⼀些具体的例⼦。
⽬前我描述的⽹络结构只能检测⼀种局部特征的类型。为了完成图像识别我们需要超过⼀个的特征映射。所以⼀个完整的卷积层由⼏个不同的特征映射组成:

在这个例⼦中,有3 个特征映射。每个特征映射定义为⼀个5× 5 共享权重和单个共享偏置的集合。其结果是⽹络能够检测3 种不同的特征,每个特征都在整个图像中可检测。然⽽,在实践中卷积⽹络可能使⽤很多(也许多得多)的特征映射。⼀种早期的识别MNIST 数字的卷积⽹络,LeNet-5,使⽤6 个特征映射,每个关联到⼀个5 × 5 的局部感受野。后⾯要开发的例⼦⾥,我们将使⽤具有20 和40 个特征映射的卷积层。
卷积到底怎么就提取了图像的特征?更好理解特征的⼯作成果。如果你感兴趣,我建议从Matthew Zeiler 和Rob Fergus 的Visualizing and Understanding Convolutional Networks(2013)论⽂ 开始。
https://arxiv.org/pdf/1311.2901.pdf

共享权重和偏置的另一个很大的优点是,它极大减少了参与的卷积网络的参数。对于每个特征映射我们需要 25 = 5×5 个共享权重,加上一个共享偏置。所以每个特征映射需要 26 个参数。如果我们有 20 个特征映射,那么总共有 20×26 = 520 个参数来定义卷积层。作为对比,假设我们神经网络的第一层为全连接层,隐层含有 30 个神经元,那么总共有28×28×30 个权重,加上额外的 30 个偏置,共有 23 550 个参数。换句话说,这个全连接的层有多达 40 倍于卷积层的参数。当然,我们不能真正做⼀个参数数量之间的直接⽐较,因为这两个模型的本质是不同的。但是,直观地,使⽤卷积层的平移不变性似乎很可能减少全连接模型中达到同样性能的参数数量。反过来,这将导致更快的卷积模型的训练,并最终,将有助于我们使⽤卷积层建⽴深度⽹络。
池化
池化层(子 采样,下采样,降采样等等)通常紧接着在卷积层之后使用。它要做的是简化从卷积层输出的信息,同时具有抗噪音的作用。池化层有两种常用的方式:均匀池化(mean-pooling)和最大值池化(max-pooling)。它要做的是简化从卷积层输出的信息详细地说,⼀个池化层取得从卷积层输出的每⼀个特征映射并且从它们准备⼀个凝缩的特征映射。例如,混合层的每个单元可能概括了前⼀层的⼀个(⽐如)2× 2 的区域。作为⼀个具体的例⼦,⼀个常⻅的混合的程序被称为最⼤值混合(max-pooling)。在最⼤值混合中,⼀个混合单元简单地输出其2 × 2 输⼊区域的最⼤激活值,正如下图说明的:

最大值池化:取这4个数值中最大的一个作为下采样的值。
均匀池化:起到模糊平均的作用,4个数值求和平均作为下采样的值(可认为池化核的值为0.25)
注意既然从卷积层有24×24 个神经元输出,混合后我们得到12×12 个神经元。
正如上⾯提到的,卷积层通常包含超过⼀个特征映射。我们将最⼤值混合分别应⽤于每⼀个特征映射。所以如果有三个特征映射,组合在⼀起的卷积层和最⼤值池化层看起来像这样:

综合在⼀起: 我们现在可以把这些思想都放在⼀起来构建⼀个完整的卷积神经⽹络。它和我们刚看到的架构相似,但是有额外的⼀层10 个输出神经元,对应于10 个可能的MNIST 数字('0','1','2' 等)

这个⽹络从28×28 个输⼊神经元开始,这些神经元⽤于对MNIST 图像的像素强度进⾏编码。接着的是⼀个卷积层,使⽤⼀个5×5 局部感受野和3 个特征映射。其结果是⼀个3×24×24 隐藏特征神经元层。下⼀步是⼀个最⼤值混合层,⽤于2 × 2 区域,遍及3 个特征映射。结果是⼀个3 ×12× 12 隐藏特征神经元层。⽹络中最后连接的层是⼀个全连接层。更确切地说,这⼀层将最⼤值混合层的每⼀个神经元连接到每⼀个输出神经元。这个全连接结构和我们之前章节中使⽤的相同。
这个卷积架构和之前章节中使⽤的架构相当不同。但是总体的描述是相似的:⼀个由很多简单的单元构成的⽹络,这些单元的⾏为由它们的权重和偏置确定。⽽总体的⽬标仍然是⼀样的:⽤训练数据来训练⽹络的权重和偏置,使得⽹络可以胜任分类输⼊数字。特别的,正如本书中前⾯那样,我们将⽤随即梯度下降和反向传播训练我们的⽹络。这⼤部分按照前⾯章节中完全相同的⽅式来处理。然⽽,我们确实需要对反向传播程序做些修改。原因是我们之前的反向传播的推导是针对全连接层的⽹络。
https://www.cnblogs.com/pinard/p/6489633.html
§9.3 卷积神经网络前向传导

如上图所示的前向传导:
输入层:$28\times 28$的图像A
第1层卷积层:经过$K^{(1)}=6$个$5\times 5$卷积模板$W_k^{(1)}$,$k=1,2,\cdots,K$,则变成了$K^{(1)}$个特征矩阵图(feature map)$a_k^{(1)}$,数学形式为
\[c_k^{(1)}=A\times W_k^{(1)}+b_k^{(1)}\]
卷积之后作为神经元输入 $n_k^{(1)}=c_k^{(1)}$
神经元输出 $a_k^{(1)}=f(n_k^{(1)})$

对于传统全连接层,每个输入单元影响了所有的输出单元。
对于卷积层,每个输入单元只影响了?个输出单元(核尺寸为$5\times 5$时)

第2层池化层:也叫下采样层,比如池化窗口为$2\times 2$(max),那么变成了$12\times 12$的池化矩阵(pooling map)$a_k^{(2)}$,还是共$K^{(1)}$个,数学形式为
\[n_k^{(2)}=\beta_k^{(2)}down(a_k^{(1)})+b_k^{(2)}\]
神经元输出 $a_k^{(2)}=f(n_k^{(2)})$
平移近似不变性:当输入做出了少量的平移时,最大池化能够获得输出的近似不变性。即:当输入平移一个微小的量时,经过最大池化的输出近似不变。

第3层卷积层:再次卷积,$K^{(1)}$个池化矩阵(pooling map)$a_k^{(2)}$,经过$5\times 5$卷积模板,生成$K^{(3)}$个$8\times 8$的特征矩阵
\[c_k^{(3)}=\sum_{j=1}^K a_j^{(2)}\times W_{k,j}^{(3)}+b_{k,j}^{(3)}\]
卷积之后作为神经元输入 $n_k^{(3)}=c_k^{(3)}$
神经元输出 $a_k^{(3)}=f(n_k^{(3)})$

在卷积神经网络中,虽然卷积层每个输出单元只依赖于少量的直接输入单元,但是它可能间接依赖于大部分的间接输入单元。处在卷积网络更深层的单元,其接受域(即影响它的神经元)要比处在浅层的单元的接受域更大。
第4层池化层:也叫下采样层,比如池化窗口为$2\times 2$(max),那么变成了$4\times 4$的池化矩阵(pooling map)$a_k^{(4)}$,共$K^{(3)}$个,数学形式为
\[n_k^{(4)}=\beta_k^{(4)}down(a_k^{(3)})+b_k^{(4)}\]
神经元输出 $a_k^{(4)}=f(n_k^{(4)})$
第5层全连接层: $a_k^{(4)}$依次排成列向量,作为全连接层的输入,这和我们前面的前馈网络一样。

§9.4 卷积神经网络的后向传播算法

全连接网络
再次回顾全连接网络的前向和后向算法
网络前向计算
\[\left\{\begin{matrix}
a^0=p\\
n^{m+1}=W^{m+1}a^m+b^{m+1}\\
a^{m+1}=f^{m+1}(W^{m+1}a^m+b^{m+1}),m=0,1,\cdots,M-1\\
a=a^M
\end{matrix}\right.\]
后向传播算法
\[\left\{\begin{matrix}
\delta^M=-2(t-a)\odot \dot{f}^m(n^M)\\
\delta^m=(W^{m+1})^T\delta^{m+1}\odot \dot{f}^m(n^m),m=M-1,M-2,\cdots,2,1\\
\dot{f}^m(n^m)=\begin{bmatrix}
\dot{f}^m(n_1^m)\\
\dot{f}^m(n_2^m)\\
\vdots\\
\dot{f}^m(n_s^m)
\end{bmatrix}
\end{matrix}\right.\]
网络参数随机梯度法更新(学习率$\alpha$)
\[\left\{\begin{matrix}
W^m(k+1)=W^m(k)-\alpha\delta^m(a^{m-1})^T\\
b^m(k+1)=b^m(k)-\alpha\delta^m
\end{matrix}\right.\]
https://www.cnblogs.com/pinard/p/6494810.html
http://huaxiaozhuan.com/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/chapters/5_CNN.html
卷积神经网络不是全连接网络,那么上面的后向传播算法需要进行修改。
1)池化层没有激活函数,这个问题倒比较好解决,我们可以令池化层的激活函数为$f(n)=n$,即激活后就是自己本身。这样池化层激活函数的导数为1.
2)池化层在前向传播的时候,对输入进行了压缩,那么我们现在需要向前反向推导$\delta^{m-1}$。
3) 卷积层是通过张量卷积,或者说若干个矩阵卷积求和而得的当前层的输出,这样在卷积层反向传播的时候,上一层的$\delta^{m-1}$递推计算方法肯定有所不同。
4)对于卷积层,由于权矩阵W使用的运算是卷积,那么从$\delta^m$推导出该层的所有卷积核的权系数矩阵W和偏置b的方式也不同。
从上面可以看出,问题1比较好解决,但是问题2,3,4就需要好好的动一番脑筋了,而问题2,3,4也是解决CNN反向传播算法的关键所在。需要注意的是,由于卷积层可以有多个卷积核,各个卷积核的处理方法是完全相同且独立的,为了简化算法公式的复杂度,下面提到卷积核都是卷积层中若干卷积核中的一个。
§9.4.1已知池化层的,推导上一隐藏层的
我们首先解决上面的问题2,如果已知池化层的$\delta^m$,推导上一隐藏层的$\delta^{m-1}$。
在前向传播算法时,池化层一般我们会用MAX或者Average对输入进行池化,池化的区域大小已知。现在我们反过来,要从缩小后的误差$\delta^m$,还原前一次较大区域对应的误差。
在反向传播时,我们首先会把$\delta^m$的所有子矩阵矩阵大小还原成池化之前的大小,然后如果是MAX,则把$\delta^m$的所有子矩阵的各个池化局域的值放在之前做前向传播算法得到最大值的位置。如果是Average,则把$\delta^m$的所有子矩阵的各个池化局域的值取平均后放在还原后的子矩阵位置。这个过程一般叫做上采样(upsample)。
用一个例子可以很方便的表示:假设我们的池化核大小是2x2。$\delta^m$的第k个子矩阵为
\[\delta_k^m=\begin{bmatrix}
2 & 8\\
4 & 6
\end{bmatrix}\]
池化核大小是2x2,因此应该是从4x4矩阵池化来的,将之还原
\[\begin{bmatrix}
0 & 0 & 0 & 0\\
0 & 2 & 8 & 0\\
0 & 4 & 6 & 0\\
0 & 0 & 0 & 0
\end{bmatrix}\]
如果和max汇池,那么我们需要之前记录的最大值位置,将之还原
\[\begin{bmatrix}
2 & 0 & 0 & 0\\
0 & 0 & 0 & 8\\
0 & 4 & 0 & 0\\
0 & 0 & 6 & 0
\end{bmatrix}\]
如果平均汇池
\[\begin{bmatrix}
0.5 & 0.5 & 2 & 2\\
0.5 & 0.5 & 2 & 2\\
1 & 1 & 1.5 & 1.5\\
1 & 1 & 1.5 & 1.5
\end{bmatrix}\]
那么已知$\delta^m$,就得到了上一层的敏感度
\[\delta_k^{m-1}=\frac{\partial F}{\partial n_k^{m-1}}=(\frac{\partial n_k^m}{\partial n_k^{m-1}})^T\frac{\partial F}{\partial n_k^m}=unsample(\delta_k^m)\odot\dot{f}^m(n_k^{m-1})\]
$unsample$完成把误差矩阵放大和重新分配的功能。
§9.4.2已知卷积层的$\delta^m$,推导上一隐藏层的$\delta^{m-1}$
卷积层神经元输出
\[a^{(m)}=f(n^{(m)})=f(a^{(m-1)}*W^{(m)}+b^{(m)})\]
\[n^{(m)}=a^{(m-1)}*W^{(m)}+b^{(m)}=f(n^{(m-1)}*W^{(m)}+b^{(m)})\]
那么依据链式法则
\[\delta_k^{(m-1)}=\frac{\partial F}{\partial n^{(m-1)}}=(\frac{\partial n^{(m)}}{\partial n^{(m-1)}})^T\frac{\partial F}{\partial n^{(m)}}=(\frac{\partial n^{(m)}}{\partial ^{(m-1)}})^T\delta^{(m)}\]
\[\delta_k^{(m-1)}=(\frac{\partial n^{(m)}}{\partial ^{(m-1)}})^T\delta^{(m)}=\delta^{(m)}*rot180(W^{(m)})\odot \dot{f}^m(n^{(m-1)})\]
上面卷积和$rot180(W^{(m)})$旋转180度是怎么来得呢?下面以一个简单的例子进行说明。为简易起见,设$b^{(m)}=0$
\[n^{(m)}=a^{(m-1)}*W^{(m)} \]
我们设如下的矩阵卷积关系
\[\begin{bmatrix}
a_{11} & a_{12} & a_{13}\\
a_{21} & a_{22} & a_{23}\\
a_{31} & a_{32} & a_{33}
\end{bmatrix}*\begin{bmatrix}
w_{11} & w_{12}\\
w_{21} & w_{22}
\end{bmatrix}=\begin{bmatrix}
n_{11} & n_{12}\\
n_{21} & n_{22}
\end{bmatrix}\]
\[n_{11}=a_{11}w_{11}+a_{12}w_{12}+a_{21}w_{21}+a_{22}w_{22}\\
n_{12}=a_{12}w_{11}+a_{13}w_{12}+a_{22}w_{21}+a_{23}w_{22}\\
n_{21}=a_{21}w_{11}+a_{22}w_{12}+a_{31}w_{21}+a_{32}w_{22}\\
n_{22}=a_{22}w_{11}+a_{23}w_{12}+a_{32}w_{21}+a_{33}w_{22}\]
那么导数
\[\triangledown a^{(m-1)}=\frac{\partial F}{\partial a^{(m-1)}}=(\frac{\partial n^{(m)}}{\partial a^{(m-1)}})^T\frac{\partial F}{\partial n^{(m)}}=(\frac{\partial n^{(m)}}{\partial a^{(m-1)}})^T\delta^{(m)}\]
设对应$n^{(m)}$敏感度矩阵
\[\begin{bmatrix}
\delta_{11} & \delta_{12}\\
\delta_{21} & \delta_{22}
\end{bmatrix}\]
因此按照上面关系得到
\[\triangledown a_{11}=\delta_{11}w_{11}\\
\triangledown a_{12}=\delta_{11}w_{12}+\delta_{12}w_{11}\\
\triangledown a_{13}=\delta_{12}w_{12}\\
\triangledown a_{21}=\delta_{11}w_{21}+\delta_{21}w_{11}\\
\triangledown a_{22}=\delta_{11}w_{22}+\delta_{12}w_{21}+\delta_{21}w_{12}+\delta_{22}w_{11}\\
\triangledown a_{23}=\delta_{12}w_{22}+\delta_{22}w_{12}\\
\triangledown a_{31}=\delta_{21}w_{21}\\
\triangledown a_{32}=\delta_{21}w_{22}+\delta_{22}w_{21}\\
\triangledown a_{33}=\delta_{22}w_{22}\]
\[\begin{bmatrix}
a_{11} & a_{12} & a_{13} \\
a_{21} & a_{22} & a_{23}\\
a_{31} & a_{32} & a_{33}
\end{bmatrix}=\begin{bmatrix}
0 & 0 & 0 & 0\\
0 & \delta_{11} & \delta_{12} & 0\\
0 & \delta_{21} & \delta_{22} & 0\\
0 & 0 & 0 & 0
\end{bmatrix}*\begin{bmatrix}
w_{22} & w_{21}\\
w_{12} & w_{11}
\end{bmatrix}\]
$rot180(W^{(m)})$就是这样得到的。
§9.4.2已知卷积层的$\delta^m$,该层权系数组成的核和偏置向量的梯度
如上讨论,全连接层权系数和偏置梯度按照第6章方法求出,池化层没有,不需要求出,只有卷积层有权系数组成的核和偏置向量。
\[n^{(m)}=a^{(m-1)}*W^{(m)}+b^{(m)}\]
所以
\[\frac{\partial F}{\partial W^{(m)}}=a^{(m-1)}*\delta^{(m)}\]
这里卷积是不需要翻转的,只是层内求导。比如还是上面的卷积例子
\[\begin{bmatrix}
a_{11} & a_{12} & a_{13}\\
a_{21} & a_{22} & a_{23}\\
a_{31} & a_{32} & a_{33}
\end{bmatrix}*\begin{bmatrix}
w_{11} & w_{12}\\
w_{21} & w_{22}
\end{bmatrix}=\begin{bmatrix}
n_{11} & n_{12}\\
n_{21} & n_{22}
\end{bmatrix}\]
\[n_{11}=a_{11}w_{11}+a_{12}w_{12}+a_{21}w_{21}+a_{22}w_{22}+b\\
n_{12}=a_{12}w_{11}+a_{13}w_{12}+a_{22}w_{21}+a_{23}w_{22}+b\\
n_{21}=a_{21}w_{11}+a_{22}w_{12}+a_{31}w_{21}+a_{32}w_{22}+b\\
n_{22}=a_{22}w_{11}+a_{23}w_{12}+a_{32}w_{21}+a_{33}w_{22}+b\]
那么导数
\[\frac{\partial F}{\partial W^{(m)}}=\begin{bmatrix}
a_{11} & a_{12} & a_{13}\\
a_{21} & a_{22} & a_{23} \\
a_{31} & a_{32} & a_{33}
\end{bmatrix}*\begin{bmatrix}
\delta_{11} & \delta_{12}\\
\delta_{21} & \delta_{22}
\end{bmatrix}\]
可以看出不需要翻转。
同样地对应偏置向量,非常简单就是把各个$\delta^{(m)}$子矩阵进行分项求和,比如上面,因为这些卷积后面都加同一个偏置
\[\frac{\partial F}{\partial b^{(m)}}=\sum_{i,j}[\delta^{(m)}]_{i,j}=\delta_{11}+\delta_{12}+\delta_{21}+\delta_{22}\]
算法总结
输入:P个图片,层数M,给定隐藏层的神经元类型,定义卷积核大小K,维度F,步幅S,确定池化大小和类型,学习率和训练次数。
-
初始化各层权矩阵$W^{(m)}$和偏置向量$b^{(m)}$
-
每次训练,for 1—Max times
For 每个图片$i=1\rightarrow P$
前向传播全连接层 $a^{(i,m)}=f(n^{(i,m)})=f(W^{(m)}a^{(i,m-1)}+b^{(m)})$
前向传播卷积层$a^{(i,m)}=f(n^{(i,m)})=f(a^{(i,m-1)}*W^{(m)}+b^{(m)})$
前向传播池化层 $a^{(i,m)}=pooling(n^{(i,m)})$
输出层:$a^{(i,M)}=softmax(n^{(i,M)})=softmax(W^{(M)}*a^{(i,M-1)}+b^{(M)})$
3) 反向传播
先通过损失函数计算输出层的敏感度$\delta^{(i,M)}$
全连接层:$\delta^{i,m}=(W^{m+1})^T\delta^{i,m+1}\odot \dot{f}^m(n^{i,m})$
卷积层: $\delta^{i,m}=\delta^{i,m+1}*rot180(W^{m+1})\odot \dot{f}^m(n^{i,m})$
池化层:$\delta^{i,m}=unsample(\delta^{i,m+1})\odot \dot{f}^m(n^{i,m})$
4) 更新
全连接层
\[\left\{\begin{matrix}
W^m(k+1)=W^m(k)-\alpha\sum_{i=1}^p\delta^{i,m}(a^{i,m-1})^T\\
b^m(k+1)=b^m(k)-\alpha\sum_{i=1}^p\delta^{i,m}
\end{matrix}\right.\]
卷积层每个卷积核(模板)
\[\left\{\begin{matrix}
W^m(k+1)=W^m(k)-\alpha\sum_{i=1}^p (a^{i,m-1}*\delta^{i,m})\\
b^m(k+1)=b^m(k)-\alpha\sum_{i=1}^p\sum_{j,k}(\delta^{i,m})_{j,k}
\end{matrix}\right.\]
§9.4 卷积神经网络程序与例子
https://blog.csdn.net/hoho1151191150/article/details/79714691

下面对各层做简要的说明:
1、 卷积层:无padding,步幅 stride 设置为 1,激活函数选择ReLU函数
2、 池化层:无padding,池化类型只实现 'average' 方法
3、 展铺层:为方便计算设计的层,属于预先分配的内存空间,作为全连接层的输入
4、 全连接层:激活函数为Sigmoid函数
5、 输出层:分类函数选择Softmax函数,代价函数选择交叉熵代价函数+L2正则化
由于变量过多,将cnn设计为一个结构体,包含的成员变量有
1、cnn.layer:网络结构的定义,元胞数组;
2、cnn.z:每一层的带权输入,元胞数组;
3、cnn.a:每一层的输出,元胞数组;
4、cnn.delta::每一层的误差敏感项,元胞数组;
5、cnn.weights:每一层的权重。元胞数组;
6、cnn.biases:每一层的偏置,元胞数组;
7、cnn.nabla_w:权重的梯度,元胞数组;
8、cnn.nabla_b:偏置的梯度,元胞数组;
9、其他一些超参数
这样每一层包含7个量:带权输入(z zz),输出(a aa),误差(δ \deltaδ),权重(W WW),偏置(b bb),权重梯度(∇ W \nabla W∇W),偏置梯度(∇ b \nabla b∇b)。并不是每一层都实际需要这7个量,不需要的层将其设置为空数组即可。
loadMnistDataScript; %加载数据
ntrain = size(training_data_label,2);
mini_batch_size = 100;
cnn.eta = 1;
cnn.lambda = 5;
ntrain = size(training_data_label,2);
mini_batch_size = 100;
cnn.ntrain = ntrain;
accuracy = zeros(1,50);
cnn.layer = {
% input layer: 'input', mini_size, [height,width] of image
{'input',mini_batch_size,[28,28]};
% convlution layer: 'conv', kernel_number, [height,width] of kernel
{'conv',20,[9,9]};
% pooling layer: 'pool', pooling_type, [height,width] of pooling area
{'pool','mean',[2,2]};
% flatten layer: 'flat', a layer for pre-allocated memory
{'flat'};
% full connect layer: 'full', neuron number
{'full',100};
{'full',100};
% output layer: 'output', neuron number
{'output',10};
};
tic
cnn = cnn_initialize(cnn);
max_iter = 20000;
ik = 0;
disp('采用有放回的训练方法')
disp(['每次计算随机选取 ',num2str(mini_batch_size), ' 个样本进行计算'])
disp(['共计算 ',num2str(max_iter),' 次,相当于全部数据迭代 ', ...
num2str(max_iter/(size(training_data,3)/mini_batch_size)),'次'])
for in = 1:max_iter
pos = randi(ntrain-mini_batch_size);
x = training_data(:,:,pos+1:pos+mini_batch_size);
y = training_data_label(:,pos+1:pos+mini_batch_size);
cnn = cnn_feedforward(cnn,x);
cnn = cnn_backpropagation2(cnn,y);
if mod(in,100) == 0
disp(['迭代次数:',num2str(in)]);
end
if mod(in,1000) == 0
ik = ik + 1;
accuracy(ik) = cnn_evaluate(cnn,validation_data,validation_data_label)*100;
disp(['validtion accuracy: ',num2str(accuracy(ik)), '%']);
end
end
toc
plot(accuracy,'r','LineWidth',1.5)
grid on
title(['1+2网络结构,测试数据最高识别率为: ,',num2str(max(accuracy)),'%']);
xlabel('迭代次数: X1000');
ylabel('精度');
cnn_evaluate(cnn,test_data,test_data_label)



浙公网安备 33010602011771号