跳至主要內容

卷积神经网络(CNN)

原创Xenny约 2515 字大约 10 分钟深度学习深度学习神经网络CNN

卷积神经网络(CNN)

  • 卷积神经网络(Convolutional Neural Networks, CNN)是深度学习中一种重要的神经网络结构,特别适用于处理图像相关的机器学习问题。CNN通过模拟人脑视觉皮层对图像的处理机制,自动提取图像中的特征,从而实现对图像的识别和理解。

    在传统的MLP中,网络被简单的分为了表现层(特征提取)和决策层(输出),而在CNN中网络被进一步细分,以便能够更好的提取图像中的局部特征,具体分层结构为

    1. 输入层:输入信息;
    2. 卷积层:提取图像底层特征;
    3. 池化层:减少数据维度,防止过拟合;
    4. 全连接层:汇总图像底层特征和信息;
    5. 输出层:根据输入进行决策输出预测值。

输入层

  • 这里要做的工作便是将图片转为矩阵即代码中的张量,具体做法则是一些图像预处理技术,不是CNN的重点。

卷积层

卷积

  • 卷积,和加法与乘法一样,是数学中的一种运算方式,我们用*来代表卷积符号(所以我们都是用\cdot代表乘法),即函数ff和函数gg的卷积为fgf*g,具体运算为

    (fg)(n)=+(f(τ)g(nτ))dτ (f*g)(n) = \int_{-\infty}^{+\infty}(f(\tau)g(n-\tau))\mathrm{d}\tau

    如果f,gf,g不是连续的而是离散的函数,则卷积运算为

    (fg)(n)=τ=+f(τ)g(nτ) (f*g)(n) = \sum_{\tau=-\infty}^{+\infty}f(\tau)g(n-\tau)

  • 那么卷积运算的实际意义是什么呢,一般来说卷积处理的两个函数的叠加,或者说是把gg函数叠加至ff函数上对ff函数的影响。

    例如我们小学时候学过的水池放水/排水问题,放水进水池的流速与时间相关,记为f(t)f(t),则TT时刻的水池内水量将为(初始为0)

    0Tf(t)dt \int_0^T{f(t)\mathrm{d}t}

    此时另一边排水的流速与水池内水量和时间均有关,记为Vg(t)V\cdot g(t),代表初始时刻水池水量VV在经过tt时间后剩余水量。则如果我们要计算这个水池在TT时刻的水量便是(fg)(T)(f*g)(T)

    0Tf(t)g(Tt)dt \int_0^T{f(t)g(T-t)\mathrm{d}t}

  • 从这里可以看出卷积便是将gg函数叠加到ff函数后再查看输出,但是问题是为什么不是f(t)g(t)f(t)g(t)的积分而是f(t)g(Tt)f(t)g(T-t)的积分呢?

    当然这是因为在这个问题中我们定义的gg函数是水量经过tt时刻后的剩余比例,那为什么在卷积中我们不是定义f(t)g(t)f(t)g(t)的积分呢?我们可以把换一个问题,例如水池不再排水,而是在放水口再加了一个阀门使得tt时刻实际进入水池的水量为f(t)g(t)f(t)g(t),此时TT时刻水池水量为

    0Tf(t)g(t)dt \int_0^T{f(t)g(t)\mathrm{d}t}

    那为什么这个不是卷积呢?

    进行这个提问的目的是用来进一步描述卷积的本质含义,卷积符号并不是只是为了将这一串积分式子简写为*而提出的,它关注的是对于一个输入函数ff,再没有任何干扰的情况下输出为ff的积分。而如果引入一个响应函数gg,它将对ff的输出值产生影响,我们要计算的便是将引入gg后的最终输出,显然最早进入的输入值将会被gg影响的时间更长,故单位时刻的输入的最终输出为f(t)g(Tt)f(t)g(T-t)

    也就是说,在我们的第一个问题中,tt时刻放进来的水最终对结果产生的影响是和持续时间有关的,我们关系的是时间(总时间)和输入(放水量)得到的结果,我们称之为卷积。

    而在第二个问题中,实际上我们的输入可以简化为h(t)=f(t)g(t)h(t) = f(t)g(t)tt时刻放入的水对最终结果的影响只和输入有关(即只和tt有关),这不是卷积。

  • 明白了这一点后,我们再来从另一个方面考虑卷积。在数学上,定义一种运算法则除了能够简写式子外,更重要的是这个运算方式它本身的性质,例如交换律、结合律等等,而卷积中的f(t)g(Tt)f(t)g(T-t)(这个操作称为反转)便是为了使得卷积这个运算法则能够满足其他运算。

    总而言之,对于一个固定的信号引入一个时间(或者叫动态影响)相关的处理函数,此时计算某个时刻的输出便是卷积。最后放一个Wikipedia上的卷积例子

    t时刻函数的重叠面积
    t时刻函数的重叠面积

图像处理

  • 那CNN中的卷积到底是在卷什么呢?

    对于一张图片,我们可以获得一个像素矩阵,也就是我们的输入信号ff,而此时我们便需要一个处理函数gg来计算二者的卷积。在图像处理中,我们将gg叫做卷积核。通过计算fgf*g我们将得到一个新的图像矩阵进行下一步运算

  • 那么这到底是在干嘛?

    在传统方法处理图像时,我们会将图像展开成一维向量,此时引发的问题是在二位图中相邻的像素在一维中相隔很远。

    平坦化
    平坦化

    可以看出上图平坦化之后本来相距很近的1和4距离变长,此时这些数据间的关联性将丢失。

    而卷积的目的便是尽可能的保留特征,例如对于上图,我们选择

    [14141414] \begin{bmatrix} \frac{1}{4}&\frac{1}{4}\\\\ \frac{1}{4}&\frac{1}{4} \end{bmatrix}

    作为卷积核进行卷积,则我们将得到。

    卷积化
    卷积化
  • 这里我们使用均值对原图进行卷积化,效果便是最终矩阵的每个值都是原始矩阵的4个值加权均值,也就是实现了缩放,不仅能够保留邻域内的像素关联信息,还能够减少网络参数,防止过拟合。

    但是,引入卷积就是为了缩放一下图片?

    如果只是为了处理一下大小的话我们没必要引入卷积这个概念,卷积最重要的工作是特征提取,而像素缩放只是保留领域像素特征的其中一种。通过更改卷积核中的权重,我们能够提取像素邻域中不同的特征。

填充

  • 虽然我们发现使用卷积也能减少参数防止过拟合,但是在CNN中我们不使用卷积来干这件事,因为这里的缩放会导致边缘特征被弱化,所以在卷积时我们会加上相应的填充,例如对于上图,我们将变成

    填充
    填充

    这里我们对图片上部和左边填充一个单位使得卷积之后大小不变,这里我们会发现因为卷积核大小是偶数,填充时只能填充两边,所以在选择卷积核时一般选择奇数宽高的矩阵(因为卷积带来的尺寸缩减是n1n-1nn为卷积核宽/高,填充带来的尺寸扩充是2k2k,所以需要选择奇数宽高)。

感受野

  • 对卷积邻域的一个量化词,在实际CNN中,我们通常会用多个卷积来对数据进行处理,所以最终得到的特征输出图中的每个数据并不一定只代表上一次卷积时卷积核大小的邻居数据特征,例如上面例子中一次卷积,则每个数据对应输入图像3x3的区域,即感受野为3x3

    但若经过两层3x3的卷积,则最终一个数据将对应原始输入中5x5的区域,即感受野为5x5。也就代表输出特征图中的一个像素点将包含更多的图像信息。

示例

  • 例如我们想提取图片中的轮廓信息

    原图
    原图
    结果
    卷积化
    卷积化
  • 卷积最大的好处便是保留了图像的空间信息,使得每个领域的特征得到有效提取,模型能够学习到更多的有效信息。

池化层

  • 在卷积层中我们关注的是特征提取,而在池化层中我们则是考虑怎么缩小维度,有时候如果图片很大,或者在卷积层生成了多个特征图,此时我们将用池化层来进行减少尺寸。

    实际上池化层的流程和卷积层类似,选定一个子区域(类似卷积核)平移扫描特征图对每个子区域做最大值、最小值或均值保留,实现压缩效果。

  • 和卷积层一样,池化层也可以包含多次操作来达到想要的效果,并且在实际使用时会交替使用卷积层和池化层来对输入进行处理。

全连接层

  • 这部分的内容就和MLP是一样的,通过神经网络和激活函数得到最终输出。

  • 对于CNN,相比一般神经网络的有点便是对数据经过不同的卷积处理使得特征更为明显,同时引入权值共享等技术使网络参数大大减少,网络结构变得更简单,泛化能力更强。