卷积神经网络入门

传统神经网络模型不能很好适应整张2维图片。比如一张 32×32×3(长32-宽32-RGB) 的彩色图片,在传统模型中第一层输入为了读入整张图片就需要 32×32×3 = 3072 个神经元,也就是有 3027 组参数,在这个简单的小图数据集(比如 CIFAR-10)好像看上去还能接受,但是一旦图片变成 200×200 的分辨率,就有 120,000 组参数了,这显然是训练时难以接受的。

卷积神经网络入门

目录

*以下所有图片援引自 Stanford CS231n


CNN 结构概述

传统神经网络模型不能很好适应整张2维图片。比如一张 32×32×3(长32-宽32-RGB) 的彩色图片,在传统模型中第一层输入为了读入整张图片就需要 32×32×3 = 3072 个神经元,也就是有 3027 组参数,在这个简单的小图数据集(比如 CIFAR-10)好像看上去还能接受,但是一旦图片变成 200×200 的分辨率,就有 120,000 组参数了,这显然是训练时难以接受的。

不同于传统神经网络中的每一层都是一维,CNN 中每层是三维的:width, height, depth. 那么刚才提到的 32×32×3 的 CIFAR-10 图片在 CNN 中的输入层就是 32×32×3 的,而下一层中的每个神经元都是由上一层中的一块区域传递而来(这就和传统模型的全连接不同了)。最后一层输出层则是 1×10,表示着 10 种分类的 score。

cnn-tutorial-01

左图中是三层的全连接型神经网络。右图是 CNN,红色层是原始图片,层与层之间做了一个 3D 到 3D 的映射。

ConvNet 用到的各种网络层

通过上面的概述,简单的 ConvNet 其实就是一组网络层序列,其中主要用到的类型有:卷积层(Convolutional Layer), 池化层(Pooling Layer), 全连接层(Fully-Connected Layer)。这些层堆叠在一起就构成了简单的 ConvNet。

拿 CIFAR-10 作数据集的模型为例,一个比较简单的模型的架构是【输入-卷积-ReLU-池化-全连接】:

  • 输入层 [32×32×3] 是原始图像,长32,宽32,有3个色彩通道。
  • 卷积层中每一个卷积核与输入层中的区域作点积,如果我们用8个卷积核,那么得到的结果就是 [32×32×8]。
  • 激活层采用 ReLU 函数,它不会改变卷积的大小,结果依然是 [32×32×8]。
  • 池化层进行了一个下采样操作,它不会改变深度,但是长与宽因为采样操作被缩小了,结果变成了 [16×16×8]。
  • 全连接层用来计算结果,其中的每一个神经元都会与上层中的所有神经元相连,在 CIFAR-10 中,其结果变成了 [1×10],表达了每种分类的置信度。

所以,通过一层层的计算,CNN 将输入的图像转换成了我们需要的 class score。值得注意的是,其中有的层是携带参数的(如卷积层、全连接层),而有的是没有参数的(激活层、池化层)

cnn-tutorial-02

以上是一个简单的 ConvNet,有着 [((Conv+ReLU)×2+Pool)×3+FC] 的结构,是一种小型的 VGG Net。这里由于3D卷积不好表示,就将深度切分成 10 张图片了。

Convolutional Layer 卷积层

卷积层里的参数其实是一组可学习的卷积核/过滤器(filter),每个卷积核贯穿了输入层的深度,比如一个 ConvNet 第一层的 5×5×3 的卷积核就代表着其宽高均为 5,且深度为 3(即输入的原始图像的 3 个颜色通道)。在前向传播过程中,卷积核沿着图像的长与宽进行扫描,将每个扫描区域的像素点与卷积核中的相应位置参数进行点积,得到平面大小不变,深度变为 1 的点积结果,即一个二维图,表示着该卷积核对每个位置的响应。最后把每个卷积核对输入层的卷积结果沿着深度维度堆叠到一起,构成了一个三维的结果。

举个例子,输入层是一张 [32×32×3] 的图片,如果卷积核的大小(filter size/receptive field)是 5×5,那么它就有 5×5×3=75 个参数(这里不算 bias)。如果第一层卷积层有 8 个卷积核,那么最后的结果就是 [32×32×8]。

cnn-tutorial-03

左图中的红色块是输入的原始图片 [32×32×3](CIFAR-10),卷积层中有 5 个卷积核,得到的蓝色结果就是 [32×32×5]。右图表示的是卷积核与卷积区域之间的计算方式,这与经典神经元并无二致,只是现在的连通区域被限定在了一个固定的大小(卷积核大小)里。

卷积层结果的大小与以下三个超参数有关:卷积核个数(depth)步长(stride)零填充(zero-padding)

  • 卷积核个数决定了输出结果的深度,每一个深度上的神经元对原图都有着不同的相应(可能是边缘朝向,也可能是色彩偏好)。
  • 步长指的是卷积核在输入上每次移动的距离。当步长为 1 时,每次移动 1 个像素,得到的结果和输入一样大(宽高);当步长大于 1 时,得到的结果比输入小;当步长小于 1 时,得到的结果比输入大。
  • 零填充指的是某些时候我们要在原图周围填充一些 0,这能方便我们调节平面的大小(通常遇到的情况是用这种方法使输入图片变成宽高相等)。

假设输入的大小是 \(W\),卷积核大小是 \(F\),步长为 \(S\),零填充的大小为 \(P\)。则输出的大小是 \((W-F+2P)/S+1\)。例如输入为 7×7,卷积核大小为 3×3,步长为 1,零填充为 0 时,输出就是 5×5,步长为 2 时,输出就是 3×3。

cnn-tutorial-04

上图讨论了输入为 5×1,卷积核大小为 3,零填充为 1 时的情况。左图是步长为 1 时,结果为 5×1,中图是步长为 2 时,结果为 3×1。最右侧的图是卷积核内部参数(无 bias)。灰色是输入层,黄色是卷积层结果。

在上面的例子中(左图),输入大小是 5,输出大小恰好也是 5,这是我们喜欢的结果。如果没有零填充的话,输出大小将会变为 3。简单推导出步长为 1 时,让输出与输入大小相等的公式:\(P=\frac{F-1}{2}\)。这是一个非常常用的技巧,之后会讨论到其中的细节。

步长其实也是有限制的,对于一个大小为 10 的输入和大小为 3 的卷积核,如果步长为 2 就会出现输出大小为 \((W-F+2P)/2+1=4.5\) 的情况,这显然是不合法的。一些深度学习的框架里会对步长做检查,此时就会抛出异常。

接下来看一个例子(点击 toggle movement 控制播放),图中的深度由于不好表示依然是被划分成一张张的图。输入宽 \(W=5\),高为 \(H=5\),深度为 \(D=3\),零填充大小为 \(P=1\),卷积核个数为 \(K=2\),卷积核大小为 \(F=3\),步长为 \(S=2\),所以输出的平面大小为 \((W-F+2P)/S+1=3\)。

Pooling Layer 池化层

在之前的 ConvNet 结构中我们看到往往有个全连接层,为了减少参数量,我们希望最后一个卷积层用尽可能小的体积包含尽可能多的信息。如何减小卷积的体积呢?我们在卷积层之间加入池化层(Pooling Layer),逐渐减小卷积的空间体积,这同时也会避免过拟合。对上一层输出的每一个深度切片,通过取区域最大值的方法缩减宽高,而深度依然保持不变。最常见的例子就是用 2×2 的过滤器以 2 为步长进行区域最大值选取。对于一个池化区域而言,其大小为 4,而最大值只有一个,所以 \(\frac{3}{4}\) 的值会被抛弃。更一般化来说,池化层应当:

  • 输入卷积大小为 \(W_1 \times H_1 \times D_1\)
  • 需要两个超参数:
    • 区域大小(spatial extent) \(F\)
    • 步长(stride) \(S\)
  • 输出结果的大小为 \(W_2 \times H_2 \times D_2\),其中:
    • \(W_2=(W_1-F)/S+1\)
    • \(H_2=(H_1-F)/S+1\)
    • \(D_2=D_1\)
  • 不具有学习性,没有响应的参数
  • 一般在池化层中不使用零填充

值得注意的是 \(F=2,3\), \(S=2\) 是两组经验参数,\(F\) 过大的话会对采样结果造成很不利的影响。除了最大池化层,也可以应用其他一些函数,比如取平均、取L2范数等。但是最近的研究表明,最大池化层表现更胜一筹。

cnn-tutorial-05

池化层对输入卷积的每一个深度的切片做了一个下采样的操作。左图中输入大小为 [224×224×64],通过大小为 2,步长为 2 的过滤器池化后,输出变成了 [112×112×64],其深度没有发生变化。右图中是最常用的最大池化层对于一个 4×4 输入的池化过程

不使用池化层其实也能做到削减卷积大小,只要在卷积中将步长调大,自然平面大小就变小,如 VAEs, GANs 等。但池化层依然是一种主流做法,且收效甚好。

Fully-Connected Layer 全连接层

全连接层中的每一个神经元都与上一层中的所有激活结果完全连接,与经典神经网络模型差别不大,这里不再做赘述。

ConvNet 常见架构

层级结构

最为常见的层级模式就是多个 Conv-ReLU 后接 Pool,再依此重复堆叠,直到图像被转化成较小的尺寸,最后通常再自然地接入全连接层。一般而言,最为常见的 ConvNet 有着这样的结构模式:
Input → [Conv → ReLU]*N → Pool?]*M → [FC → ReLU]*K → FC

其中 * 表示重复,Pool? 表示该处池化是可选层。通常情况下,N,K应当不超过3。

层内大小参数

层内也是有部分超参数需要设置的。

输入层的大小应当能被 2 整除多次。比如 32(如 CIFAR-10), 64, 96(如 STL-10), 224(如 ImageNet Common ConvNets), 384 或 512.

卷积层的卷积核应当小。通常选择 [3×3] 或者 [5×5](只有在最初的卷积层上才会使用更大的卷积核,如 [7×7])。之前讨论过利用 \(P=\frac{F-1}{2}\),使得图像大小不发生改变。

池化层负责下采样操作。通常选择 [2×2] 作为池化区域,步长设为 2。


简单的介绍就到此为止了,以下是一些常用的模型:

  • LeNet.
  • AlexNet.
  • ZF Net.
  • GoogLeNet.
  • VGGNet.
  • ResNet.