如何理解卷积神经网络(CNN)中的卷积和池化?

题主在学习ML的过程中发现,在CNN的诸多教程与论文当中对卷积和池化的介绍都不如其他方面直观和易于理解,这个领域对我来说一直是一个黑箱,除了能简单掌握…
关注者
614
被浏览
897,871

31 个回答

要说明这个问题,首先要从计算机视觉中的“Hello World”问题说起: MNIST手写数字的分类 。给定图像,将其分类。

来自MNIST数据集的图片样本

MNIST数据集中的每个图像都是28x28像素,包含一个居中的灰度数字。

什么是卷积?

首先,介绍一下什么是卷积神经网络。

它是使用卷积层(Convolutional layers)的神经网络,基于卷积的数学运算。

卷积层由一组滤波器组成,滤波器可以视为二维数字矩阵。这是一个示例3x3滤波器:

我们可以将滤波器与输入图像进行卷积来产生输出图像,那么什么是卷积操作呢?具体的步骤如下:

  1. 在图像的某个位置上覆盖滤波器;
  2. 将滤波器中的值与图像中的对应像素的值相乘;
  3. 把上面的乘积加起来,得到的和是输出图像中目标像素的值;
  4. 对图像的所有位置重复此操作。

这个4步描述有点抽象,所以让我们举个例子吧。看下面的4x4灰度图像和3x3滤波器:

图像中的数字表示像素亮度,0是黑色,255是白色。我们将对输入图像和滤波器进行卷积,生成2x2输出图像。

首先,让我们将滤镜覆盖在图片的左上角:

接下来,我们在重叠的图像和滤波器元素之间逐个进行乘法运算,按照从左向右、从上到下的顺序。

把最右列的乘积结果全部相加,得到:

由于滤波器覆盖在输入图像的左上角,因此目标像素是输出图像的左上角像素:

用同样的方式处理图像剩下的区域:

求卷积有何用?

看完了基本概念,你可能会有疑问,对图像求卷积有什么用吗?

我们在前文中使用的那个3x3滤波器,通常称为垂直**索伯滤波器**(Sobel filter):


看看用它来处理知名的Lena照片会得到什么:

看出来了吗?其实, 索伯滤波器是是边缘检测器

现在可以解释卷积操作的用处了:用输出图像中更亮的像素表示原始图像中存在的边缘。

你能看出为什么边缘检测图像可能比原始图像更有用吗?

回想一下MNIST手写数字分类问题。在MNIST上训练的CNN可以找到某个特定的数字。比如发现数字1,可以通过使用边缘检测发现图像上两个突出的垂直边缘。

通常,卷积有助于我们找到特定的局部图像特征(如边缘),用在后面的网络中。

填充

在上面的处理过程中,我们用3x3滤波器对4x4输入图像执行卷积,输出了一个2x2图像。

通常,我们希望输出图像与输入图像的大小相同。因此需要在图像周围添加零,让我们可以在更多位置叠加过滤器。3x3滤波器需要在边缘多填充1个像素。


这种方法称之为“相同”填充,因为输入和输出具有相同的大小。而不使用任何填充称为“有效”填充。

池化

图像中的相邻像素倾向于具有相似的值,因此通常卷积层相邻的输出像素也具有相似的值。这意味着,卷积层输出中包含的大部分信息都是冗余的。

如果我们使用边缘检测滤波器并在某个位置找到强边缘,那么我们也可能会在距离这个像素1个偏移的位置找到相对较强的边缘。但是它们都一样是边缘,我们并没有找到任何新东西。

池化层解决了这个问题。这个网络层所做的就是通过减小输入的大小降低输出值的数量。

池化一般通过简单的最大值、最小值或平均值操作完成。以下是池大小为2的最大池层的示例:

刚写完相关的文章,转载一部分过来。

来自自己的专栏: 当我们在谈论数据挖掘 - 知乎专栏

CNN 其实可以看作 DNN 的一种特殊形式。它跟传统 DNN 标志性的区别在于两点,Convolution Kernel 以及 Pooling。

Convolution Kernel

卷积

说起卷积,一般我们我们接触过的都是一维信号的卷积,也就是

y[n]=x[n]\ast h[n]=\sum_k x[k]h[n-k]

在信号处理中, x[n] 是输入信号, h[n] 是单位响应。于是输出信号 y[n] 就是输入信号 x[n] 的延迟响应的叠加。这也就是一维卷积本质:加权叠加/积分。

那么对于二维信号,比如图像,卷积的公式就是

y[m,n]=x[m,n]\ast h[m,n]=\sum_j \sum_i x[i,j]h[m-i,n-j]

假设现在 Convolution Kernel 大小是 3\times 3 ,我们就可以化简上式为

看公式不太容易明白,我们画个图看看,假如 Convolution Kernel 如下图

那么,从 Input Image 到 Output Image 的变化如下

可以看出,其实二维卷积一样也是加权叠加/积分。需要注意的是,其中 Convolution Kernel 进行了水平和竖直方向的翻转。

Convolution Kernel 的意义

Convolution Kernel 其实在图像处理中并不是新事物,Sobel 算子等一系列滤波算子,一直都在被用于边缘检测等工作中,只是以前被称为 Filter。做图像处理的同学应该有印象。

Convolution Kernel 具有的一个属性就是局部性。即它只关注局部特征,局部的程度取决于 Convolution Kernel 的大小。比如用 Sobel 算子进行边缘检测,本质就是比较图像邻近像素的相似性。

也可以从另外一个角度理解 Convolution Kernel 的意义。学过信号处理的同学应该记得,时域卷积对应频域相乘。所以原图像与 Convolution Kernel 的卷积,其实对频域信息进行选择。比如,图像中的边缘和轮廓属于是高频信息,图像中某区域强度的综合考量属于低频信息。在传统图像处理里,这是指导设计 Convolution Kernel 的一个重要方面。

CNN 的 Convolution Kernel

CNN 中的 Convolution Kernel 跟传统的 Convolution Kernel 本质没有什么不同。仍然以图像为例,Convolution Kernel 依次与 Input 不同位置的图像块做卷积,得到 Output,如下图。

同时,CNN 有一些它独特的地方,比如各种定义:

  1. CNN 可以看作是 DNN 的一种简化形式,即这里 Convolution Kernel 中的每一个权值就可以看成是 DNN 中的 w ,且与 DNN 一样,会多一个参数 Bias b
  2. 一个 Convolution Kernel 在与 Input 不同区域做卷积时,它的参数是固定不变的。放在 DNN 的框架中理解,就是对同一层 Layer 中的神经元而言,它们的 w b 是相同的,只是所连接的节点在改变。因此在 CNN 里,这叫做 Shared Weights and Biases
  3. 在 CNN 中,Convolution Kernel 可能是高维的。假如输入是 m \times n \times k 维的,那么一般 Convolution Kernel 就会选择为 d \times d \times k 维,也就是与输入的 Depth 一致
  4. 最重要的一点,在 CNN 中,Convolution Kernel 的权值不需要提前设计,而是跟 DNN 一样利用 GD 来优化,我们只需要初始化
  5. 如上面所说,其实 Convolution Kernel 卷积后得到的会是原图的某些特征(如边缘信息),所以在 CNN 中,Convolution Kernel 卷积得到的 Layer 称作 Feature Map
  6. 一般 CNN 中两层之间会含有多个 Convolution Kernel,目的是学习出 Input 的不同特征,对应得到多个 Feature Map。又由于 Convolution Kernel 中的参数是通过 GD 优化得到而非我们设定的,于是初始化就显得格外重要了

Pooling

Pooling 的本质,其实是采样。Pooling 对于输入的 Feature Map,选择某种方式对其进行压缩。如下图,表示的就是对 Feature Map 2 \times 2 邻域内的值,选择最大值输出到下一层,这叫做 Max Pooling。于是一个 2N \times 2N 的 Feature Map 被压缩到了 N \times N

除此之外,还有Mean-Pooling,Stochastic-Pooling 等。它们的具体实现如名称所示,具体选择哪一个则取决于具体的任务。

Pooling 的意义,主要有两点:

  1. 其中一个显而易见,就是减少参数。通过对 Feature Map 降维,有效减少后续层需要的参数
  2. 另一个则是 Translation Invariance。它表示对于 Input,当其中像素在邻域发生微小位移时,Pooling Layer 的输出是不变的。这就使网络的鲁棒性增强了,有一定抗扰动的作用

回答里的公式太难用了。。对 CNN 还有想要更多了解的可以参考原专栏文章:

当我们在谈论 Deep Learning:CNN 其常见架构(上)