甲乙小朋友的房子

甲乙小朋友很笨,但甲乙小朋友不会放弃

0%

深度学习算法-卷积网络

一般来说,图片是非常大的。至少有\(n\times n\times 3\)的像素,即有这么多特征。 对于小尺寸的图片问题,也许我们用深度神经网络的结构可以较为简单的解决一定的问题。但是当应用在大尺寸的图片上,输入规模将变得十分庞大,使用神经网络将会有非常多的参数需要去学习,这个时候神经网络就不再适用。

卷积神经网络在计算机视觉问题上是一个非常好的网络结构。

概述

图像识别过程

当我们给定一个"X"的图案,计算机怎么识别这个图案就是“X”呢?一个可能的办法就是计算机存储一张标准的“X”图案,然后把需要识别的未知图案跟标准"X"图案进行比对,如果二者一致,则判定未知图案即是一个"X"图案。

而且即便未知图案可能有一些平移或稍稍变形,依然能辨别出它是一个X图案。如此,CNN是把未知图案和标准X图案一个局部一个局部的对比,如下图所示:

而未知图案的局部和标准X图案的局部一个一个比对时的计算过程,便是卷积操作。卷积计算结果为1表示匹配,否则不匹配。

图像边缘检测

卷积运算是卷积神经网络的基本组成部分。下面以边缘检测的例子来介绍卷积运算。

所谓边缘检测,在下面的图中,分别通过垂直边缘检测和水平边缘检测得到不同的结果:

垂直边缘检测:

假设对于一个 6×6 大小的图片(以数字表示),以及一个 3×3 大小的 filter(卷积核) 进行卷积运算,以“∗”符号表示。图片和垂直边缘检测器分别如左和中矩阵所示:

filter 不断地和其大小相同的部分做【对应元素的乘法运算并求和】,最终得到的数字相当于新图片的一个像素值,如右矩阵所示,最终得到一个 4×4 大小的图片。

边缘检测的原理:

以一个有一条垂直边缘线的简单图片来说明。通过垂直边缘 filter 我们得到的最终结果图片可以明显地将边缘和非边缘区分出来:

卷积运算提供了一个方便的方法来检测图像中的边缘,成为卷积神经网络中重要的一部分。

多种边缘检测:

垂直和水平边缘检测

更复杂的filter

对于复杂的图片,我们可以直接将filter中的数字直接看作是需要学习的参数,其可以学习到对于图片检测相比上面filter更好的更复杂的filter,如相对于水平和垂直检测器,我们训练的 filter 参数也许可以知道不同角度的边缘。

通过卷积运算,在卷积神经网络中通过反向传播算法,可以学习到相应于目标结果的filter,将其应用于整个图片,输出其提取到的所有有用的特征。

卷积网络结构

本节主要来自参考文献CNN笔记:通俗理解卷积神经网络

cs231n课程里给出了卷积神经网络各个层级结构,如下图:

img

图中CNN要做的事情是:给定一张图片,是车还是马未知,是什么车也未知,现在需要模型判断这张图片里具体是一个什么东西,总之输出一个结果:如果是车,那是什么车。

上图的网络结构为:

  • 最左边是数据输入层,对数据做一些处理,比如去均值(把输入数据各个维度都中心化为0,避免数据过多偏差,影响训练效果)、归一化(把所有的数据都归一到同样的范围)、PCA/白化等等。CNN只对训练集做“去均值”这一步。
  • 中间是
    • CONV:卷积计算层,线性乘积求和。
    • ReLU:激励层,上文2.2节中有提到:ReLU是激活函数的一种。
    • POOL:池化层,简言之,即取区域平均或最大。
  • 最右边是
    • FC:全连接层

这几个部分中,卷积计算层是CNN的核心,下文将重点阐述。

接下来,我们详细介绍一下这几个部分。

卷积网络结构

卷积网络结构如下所示:

1
2
3
4
5

输入层 --> 卷积计算层 --> 激励层 --> 池化层
--> 卷积计算层 --> 激励层 --> 池化层
--> ...
-->全连接层

卷积网络中一个典型层包括三级:卷积计算层、激励层(探测层)和池化层。

通过上一步的卷积运算,然后经过了激活函数,我们将此时的输入会输入池化层。

卷积层:并行计算多个卷积,产生一组线性激活响应;

激励层(探测层)(detector stage):每个线性激活响应会通过一个非线性激活函数;

池化层:我们使用池化(pooling)函数来进一步调整这一层的输出。

卷积计算层

卷积计算层最重要的就是卷积运算。接下来我们介绍卷积运算。

卷积运算

假设我们在用激光传感器追踪宇宙飞船的位置,\(t\)时刻位置在\(x(t)\)

为了更好地估计,我们将时间越近的测量给予更高的权重\(w(a)\),其中\(a\)表示测量结果距当前的时间间隔,那么:

\[s(t)=\int x(a)w(t-a)da = (x*w)(t)\]

tips: \(a\):距离当前时间的间隔; \(x(a)\)\(a\)时刻,飞船位置,\(x\)也叫输入 \(w(t-a)\)\(t-a\)时刻,也就是a秒前,飞船的权重,也是一种概率密度,叫做核函数

离散形式的卷积是: \[s(t)=(x*w)(t)=\sum_{\alpha=-\infty}^{\infty}x(a)w(t-a)\]

二维形式的卷积(我们定义核为K):

\[S(i,j)=(I*K)(i,j)=\sum_m \sum_n I(m,n)K(i-m,j-n)\]

卷积是可交换的,也可写作:

\[S(i,j)=(K*I)(i,j)=\sum_m \sum_n I(i-m,j-n)K(m,n)\]

出现上面可交换的原因是:我们将核的相对输入进行了翻转,也相当于一种变量替换;

然而,在许多神经网络中采用的是互相关函数(cross-correlation)

\[S(i,j)=(I*K)(i,j)=\sum_m \sum_n I(i+m,j+n)K(m,n)\]

这个是不可交换的。

在数学定义上,矩阵的卷积(convolution)操作为首先将卷积核同时在水平和垂直方向上进行翻转,构成一个卷积核的镜像,然后使用该镜像再和前面的矩阵进行移动相乘求和操作。如下面例子所示:

在深度学习中,我们称为的卷积运算实则没有卷积核变换为镜像的这一步操作,因为在权重学习的角度,变换是没有必要的。深度学习的卷积操作在数学上准确度来说称为互相关(cross-correlation)。

一般来说,图像领域的卷积用的就是互相关函数。参考文献CNN笔记:通俗理解卷积神经网络对卷积的定义是:对图像(不同的数据窗口数据)和滤波矩阵(一组固定的权重:因为每个神经元的多个权重固定,所以又可以看做一个恒定的滤波器filter)做内积(逐个元素相乘再求和)的操作就是所谓的『卷积』操作,也是卷积神经网络的名字来源。


卷积计算层

举个具体的例子。比如下图中,图中左边部分是原始输入数据,图中中间部分是滤波器filter(有个高大上的名字叫卷积核),图中右边是输出的新的二维数据。

即将下面 两个矩阵对应位置先相乘,后相加:

\[*\] \[=\]

在CNN中,滤波器filter(带着一组固定权重的神经元)对局部输入数据进行卷积计算。每计算完一个数据窗口内的局部数据后,数据窗口不断平移滑动,直到计算完所有数据。这个过程中,有这么几个参数:

Depth-深度

神经元个数,决定输出的depth厚度。同时代表滤波器个数。

Stride-步长

决定滑动多少步可以到边缘。

以s表示stride的大小,那么在进行卷积运算后,图片的变化为:\(n×n –> ⌊\frac{n+2p−f}{s}+1⌋×⌊\frac{n+2p−f}{s}+1⌋\)

注意,在当padding≠1时,若移动的窗口落在图片外面时,则不要再进行相乘的操作,丢弃边缘的数值信息,所以输出图片的最终维度为向下取整

Padding-填充值

在外围边缘补充若干圈0,方便从初始位置以步长为单位可以刚好滑到末尾位置,通俗地讲就是为了总长能被步长整除。

没有Padding的缺点 :

  1. 每次卷积操作,图片会缩小; 就前面的例子来说,6×6 大小的图片,经过 3×3 大小的 filter,缩小成了 4×4 大小 。图片:n×n –> (n−f+1)×(n−f+1)
  2. 角落和边缘位置的像素进行卷积运算的次数少,可能会丢失有用信息。 其中,n表示图片的长或宽的大小,f表示filter的长或宽的大小。

有Padding :

  1. 为了解决上面的两个缺点,我们在进行卷积运算前为图片加padding,包围角落和边缘的像素,使得通过filter的卷积运算后,图片大小不变,也不会丢失角落和边沿的信息。

以p表示 Padding 的值,则输入n×n大小的图片,最终得到的图片大小为 (n+2p−f+1)×(n+2p−f+1),为使图片大小保持不变,需根据filter的大小调整p的值。

卷积计算的过程

对于灰色图像中,卷积核和图像均是二维的。而应用于彩色图像中,因为图片有R、G、B三个颜色通道,所以此时的卷积核应为三维卷积核

单个卷积核应用于图片时,提取图片特定的特征,不同的卷积核提取不同的特征。如两个大小均为3×3×3 的卷积核分别提取图片的垂直边缘和水平边缘。

由图可知,最终提取到彩色图片的垂直特征图和水平特征图,得到有2个通道的4×4大小的特征图片。

这张gif诠释了三维、两个卷积核的卷积过程:

输入图像:三维

卷积核W0和W1:分别都是三维

可以看到:

  • 两个神经元,即depth=2,意味着有两个滤波器。
  • 数据窗口每次移动两个步长取3*3的局部数据,即stride=2。
  • zero-padding=1。

然后分别以两个滤波器filter为轴滑动数组进行卷积计算,得到两组不同的结果。

​ 如果初看上图,可能不一定能立马理解啥意思,但结合上文的内容后,理解这个动图已经不是很困难的事情:

  • 蓝色输入(**7*7*3**中,7*7代表图像的像素/长宽,3代表R、G、B 三个颜色通道)
  • 红色是两个不同的滤波器Filter w0、Filter w1
  • 绿色则是两个不同的输出,每一个格子都等于一次滤波窗口内的内积和(RGB三通道相加)

​ 随着左边数据窗口的平移滑动,滤波器Filter w0 / Filter w1对不同的局部数据进行卷积计算。如果这一部分看不明白,可以继续看CNN笔记:通俗理解卷积神经网络,这里讲的非常详细。

单层卷积网络

和普通的神经网络单层前向传播的过程类似,卷积神经网络也是一个先由输入和权重及偏置做线性运算,然后得到的结果输入一个激活函数中,得到最终的输出:

\[z^{[1]}=w^{[1]}a^{[0]}+b^{[1]}\]

\[a^{[1]}=g(z^{[1]})\]

不同点是在卷积神经网络中,权重和输入进行的是卷积运算。

单层卷积的参数个数:

在一个卷积层中,如果我们有10个 3×3×3 大小的卷积核,那么加上每个卷积核对应的偏置,则对于一个卷积层,我们共有的参数个数为:

\[(3×3×3+1)×10=280\]

无论图片大小是多少,该例子中的卷积层参数个数一直都是280个,相对于普通的神经网络,卷积神经网络的参数个数要少很多。

多层卷积网络

多层卷积构成卷积神经网络,下面是一个卷积神经网络的例子:

激励层

几种不同的激活函数\(g(x)\)

  • sigmoid:

    \[a = \frac{1}{1+e^{-z}}\]

    导数:\(a′=a(1−a)\)

  • tanh:

    \[a = \frac{e^z - e^{-z}}{e^z + e{-z}}\]

    导数:\(a′=1−a2\)

  • ReLU(修正线性单元): \[a=max(0,z)\]

  • Leaky ReLU: \[a=max(0.01z,z)\]

激活函数的选择

sigmoid函数和tanh函数比较:

  • 隐藏层:tanh函数的表现要好于sigmoid函数,因为tanh取值范围为[−1,+1],输出分布在0值的附近,均值为0,从隐藏层到输出层数据起到了归一化(均值为0)的效果。
  • 输出层:对于二分类任务的输出取值为{0,1},故一般会选择sigmoid函数。

然而sigmoid和tanh函数在当|z|很大的时候,梯度会很小,在依据梯度的算法中,更新在后期会变得很慢。在实际应用中,要使|z|尽可能的落在0值附近。

ReLU弥补了前两者的缺陷,当z>0时,梯度始终为1,从而提高神经网络基于梯度算法的运算速度。然而当z<0时,梯度一直为0,但是实际的运用中,该缺陷的影响不是很大。

Leaky ReLU保证在z<0的时候,梯度仍然不为0。

在选择激活函数的时候,如果在不知道该选什么的时候就选择ReLU,当然也没有固定答案,要依据实际问题在交叉验证集合中进行验证分析。

池化层

池化函数

使用某一位置的相邻输出的总体统计特征来代替网络再该位置的输出。

最大池化函数:给出相邻矩形区域内的最大值。

在最大池化中,有一组超参数需要进行调整,其中,$f \(表示池化的大小,\)s$表示步长。

  • 池化前:\(n×n\)
  • 池化后:\(⌊\frac{n+2p−f}{s}+1⌋×⌊\frac{n+2p−f}{s}+1⌋\)

此外还有平均池化、最小池化等等。注意,池化层没有需要学习的参数。

池化的用途

池化函数帮助输入近似不变:即当我们对输入进行少量平移时,经过池化函数后的大多数输出并不会发生改变。通俗地说就是——为了让我们的网络具有平移不变形(我的理解是无论输入轻微旋转或平移,输出都不变),我们引入池化这个骚操作来达到这个目的。

例如下图所示的例子。上图是一个网络,下图是一个网络,每个网络的下层是非线性输出,上层是最大池化输出。下图的非线性输出是通过向右平移一个像素得到的。我们可以发现,池化层的输出只有一半发生了改变,这是因为最大池化单元只对周围的最大值较敏感,而不是精确的位置。

当我们只关心某个特征是否出现(比如是否有眼睛),而不关心它的具体位置时,局部平移不变性是一个非常有用的性质。

对空间区域进行池化产生了平移不变性。下图是一种学习不变性的实例:反映的是池化的旋转不变性,对于输入手写5,有三个滤波器分别检测选择不同角度的手写5。当滤波器和对应的手写5匹配时,滤波器会得到一个较大的激活值,然后池化会选择得到最大的激活值,无论手写5是怎样的旋转的。

总的来说就是:通过卷积后,为了引入不变性,同时防止过拟合问题或欠拟合问题、降低计算量,我们常进行池化处理。

卷积网络的优势

我们先说一下卷积网络的概念:卷积神经网络(Convolutional Neural Networks)的卷积操作是通过可训练的滤波器对上一层的输出进行卷积求和,然后添加上偏移量经过激活函数,得到了特征映射图作为下一层的输入。卷积操作相对于传统神经网络主要有稀疏链接、权值共享和等变表达的特性。

卷积通过三个重要思想来帮助改进机器学习系统:稀疏交互、参数共享、等变表示。

与普通的全连接神经网络相比,卷积神经网络的参数更少。如图中的例子,卷积神经网络仅有6×(5×5+1)=156个参数,而普通的全连接网络有3072×4704≈14M个参数。

稀疏交互

对于一张图像来说,输入图像可能包含上千万像素点。但我们可以通过只占用几十或几百的核来检测一些小的但有意义的特征,例如图像边缘。即——在每一层中,每个输出值只取决于少量的输入,也就是稀疏交互。

下图是一种稀疏连接的例子,从下往上看,我们强调了一个输入单元\(x_3\)以及\(s\)中受该单元影响的输出单元。这个是当\(s\)由核宽度为3的卷积产生的,只有3个输出受到了\(x\)的影响:

从另一个角度,从上往下看,这次我们抢到了一个输出单元\(s_3\)以及\(x\)中影响该单元的输入单元。这些单元被称为\(s_3\)接受域

从深层的网络来看,我们可以看到尽管连接稀疏,但处在更深层的单元可以间接地连接到全部或大部分输入图像中。

参数共享

一个特征检测器(filter)对图片的一部分有用的同时也有可能对图片的另外一部分有用。

因为核的每一个元素都作用在输入的每一个位置上,因此卷积运算会导致用于一个输入的权重也会被绑定在其它权重上。这样的参数共享保证了我们只需要学习一个参数集合,而不是对每一个位置都需要学习一个单独的参数集合。如下图所示,黑色箭头表示两个不同模型中使用了特殊的参数连接。灰色箭头表示它用了黑色箭头的参数。其实就是一个\(x\)只有一个参数,但这个参数被用于了多个下一层。

对于卷积,参数共享的特殊形式使得神经网络层具有对平移等变的性质:先平移后卷积=先卷积后平移。

边缘检测的例子

如图所示,我们使用每个像素减去左边相邻像素形成的。这其实就是一种最简单的卷积。

训练卷积神经网络

我们将训练集输入到卷积神经网络中,对网络进行训练。利用梯度下降(Adam、momentum等优化算法)最小化代价函数来寻找网络最优的参数。

复杂度

卷积网络的时间复杂度

单个卷积层的时间复杂度

\[O(M^2 K^2 C_{in}C_{out})\]

  • M : 每个卷积核输出特征图(feature map)的边长
    • 输出特征图尺寸本身又由输入矩阵尺寸 X 、卷积核尺寸K、填充大小Padding、步长Stride 这四个参数所决定,表示如下: \[M = (X - K + 2 * Padding) / Stride + 1\]
  • K : 每个卷积核的边长
  • Cin : 每个卷积核的通道数,也即输入通道数,也即上一层的输出通道数
  • Cout : 本卷积层具有的卷积核个数,也即输出通道数

卷积神经网络整体的时间复杂度

\[O\sum_{l = 1}^D(M^2_l K_l ^2 C_{l-1}C_{l})\]

  • D : 网络深度

卷积网络的空间复杂度

\[O(\sum_{l = 1}^D K_l^2 C_{l - 1}C_l)\]

  • 与输入数据大小无关
  • 当我们需要裁剪模型时,由于卷积核的尺寸通常已经很小,而网络的深度又与模型的能力紧密相关,不宜过多削减,因此模型裁剪通常最先下手的地方就是通道数

参考文献

  1. 深度学习
  2. 达观数据深度学习
  3. 深度学习笔记(一)卷积神经网络(Convolutional Neural Networks)
  4. CNN笔记:通俗理解卷积神经网络
  5. 卷积神经网络的复杂度分析