本周讲述了CNN的基础。从边界检测引入卷积运算,并将2D卷积运算延伸到3D中的multi-filter,最后以LeNet-5架构为例整体介绍了CNN。

1- Convolutional Neural Networks

1.1- Computer Vision

计算机视觉(computer vision)是因deep learing而快速发展的领域之一,并促进了自动驾驶、人脸识别等应用的发展以及更多的全新应用(而这些在几年前还是不可能的),计算机视觉的发展也为其他领域如语音识别提供了思路。

计算机视觉的例子:

  • Image classification
  • Object detection
  • Neural Style transfer

Xnip2018-07-01_15-33-03

计算机视觉的一个挑战:图片数据转换的特征向量太大。比如一张1000x1000像素的图片,转化成向量则有1000x1000x3=3百万个输入属性。这将导致

  • Neural Network的结构十分复杂,参数很多,容易产生过拟合;
  • 庞大的计算量。

这正是卷积神经网络(convolutional neural network, CNN)要解决的。

1.2- Edge Detection Example

Convolution opteration(卷积运算)是convolutional neural network的重要基石之一。

Edge Detection分为:

  • vertical edges
  • horizontal edges

Xnip2018-07-01_17-11-29

举例:Vertical edge detection vertical edge detection可以用卷积运算实现。比如检测一张6x6像素的灰度图片的vertical edge,设计一个3x3的矩阵(称之为filter或kernel),让原始图片和filter矩阵做卷积运算(convolution),得到一个4x4的图片。 具体的做法是,将filter矩阵贴到原始矩阵上(从左到右从上到下),依次可以贴出4x4种情况。让原始矩阵与filter重合的部分做element wise的乘积运算再求和,所得的值作为4x4矩阵对应元素的值。如下图是第一个元素的计算方法,以此类推。

Xnip2018-07-01_17-20-14

下面是一个动图展示了卷积操作:

Convolution_schematic

使用卷积做边缘检测的解释:

Xnip2018-07-01_17-25-02

如上图,通过filter卷积运算后,右边的矩阵会出现一条中间的空白,代表了边缘所在的位置。

我的理解:filter矩阵很有意思,它是左右堆成且只相反,如果不是边缘(即像素值比较均匀),经过filter运算后的点(相当于做了加权平均)基本被抵消为0。如果filte在边缘处运算,会造成明显的不平衡,即显示出边缘所在。

这里的卷积,本质上是图片的某个区域与filter的内积,而内积反应的是相似性。所以用一个1,0,-1的filter找到的就是和气相似的区域,即垂直边缘。

关于卷积,参考资料:卷积的理解

1.3- More Edge Detection

  1. 亮到暗与暗到亮

以vertical edge detection为例,亮到暗与暗到亮会形成两种不同的检测结果,如下图使用相同的filter,分别得到30和-30的边界:

Xnip2018-07-01_17-39-56

因此,根据生成的边界的正负,可以得知边界的类型

  1. horizontal edge detection 类似,将filter做一个转置,即得到了horizontal edge detection的filter

Xnip2018-07-01_17-44-33

一个稍复杂的horizontal edge detection,左边是由亮到暗,右边是由暗到亮:

Xnip2018-07-01_17-46-23

通过正负,可以得知30表示左边的水平边界是positive edge,即亮到暗,而-30则表示右半部分则是negative edge,即暗到亮。

  1. filter的选择 除了上面的-1,0,1的filter外,还有其他类型的filter,它们加强了中心点的权重,使得算法更健壮,比如:
  1. 算法学习filter 与人工设置filter对应,也可以通过算法训练出一个filter,即将filter看成参数,使用反向传播算法学习(后续会介绍)。而且不仅限于vertical和horizontal,算法还可以学习出各种角度的filter。

1.4- Padding

为了构建deep neural network,对基本卷积操作的一个改进就是padding。

问题:通过filter卷积运算后的矩阵维度会比原矩阵变小了,比如一个6x6的矩阵经过3x3的filter卷积运算后,只有4x4的维度了。一般的,对于一个\(n\times n\)的矩阵,经过\(f\times f\)的filter运算后是\((n-f+1)\times (n-f+1)\)维。这造成两个缺陷:

  • 图片运算后被缩小了(shrink output),如果neural network层数较多,可能会缩小的很严重,因为每一层都会缩一次。
  • 边界上的像素被运算的次数要小于中心的像素,比如左上角的像素只会参与一次卷积运算。丢失了图片边缘的信息。

解决的办法是padding,即在原始矩阵围一圈(通常用0填充)。比如对于3x3的fitler,把原始图片矩阵上下左右各padding一个单位(padding=1),一个6x6的矩阵padding后变成了8x8的矩阵,卷积后还是6x6的矩阵。

Padding (图片来源:http://kyonhuang.top/Andrew-Ng-Deep-Learning-notes/#/Convolutional_Neural_Networks/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C)

考虑到是否padding,卷积运算分为了两种:

  • Valid convolutions 即没有padding
  • Same convolutions 有padding,使得输出矩阵和输入矩阵保持相同的大小

在计算机视觉领域,filter的大小f通常取奇数通常取奇数,为了保证输出矩阵大小不变,padding的大小则是:\(p=\frac{f-1}{2}\)

1.5- Strided Convolutions

前面的例子,在做卷积的时候,filter每次移动的距离是1,而Stride convolution允许移动的距离大于1,比如下图设置的stride是2:

结果矩阵中,第一个元素的计算是取左上角9个元素(图中蓝色部分)和filter运算,得到91

Xnip2018-07-01_20-35-54

然后直接向右移动两格(图中蓝色部分)做卷积运算,得到第二个元素100:

Xnip2018-07-01_20-36-54

以此类推:

Xnip2018-07-01_20-39-42

很显然,结果矩阵比原矩阵要小,变成了只有3x3的矩阵。

如果原矩阵大小是\(n \times n \),padding是\(p\),filter矩阵大小是\(f \times f\),stride是\(s\),则可以计算结果矩阵的大小是:\(\biggl\lfloor \frac{n+2p-f}{s}+1 \biggr\rfloor \times \biggl\lfloor \frac{n+2p-f}{s}+1 \biggr\rfloor\)

关于卷积和互相关(cross-correlation)的说明: 严格来说,前面介绍的卷积和数学上的卷积定义有所差别。数学上的卷积,在乘积求和之前要先把filter矩阵沿着反斜对角线旋转一下,如下图:

Xnip2018-07-02_08-17-37

做旋转的好处是,可以使得卷积操作满足结合律。

但在machine learing语境中,由于filter基本是垂直或水平的,旋转与否影响不大,故习惯上还是将cross-correlation称作convolution。

参考资料:卷积与互相关的一点探讨

1.6- Convolutions Over Volume

前面介绍的卷积都是应用在二维灰度图片上,现在将卷积应用于三维上(比如RGB图片)

  1. RGB图片卷积运算的例子:

Xnip2018-07-02_08-58-16

RGB图片需要用三个矩阵叠加,分别表示RGB三种颜色。原始图片的size是6x6x3,图片的本身的尺寸6x6称作height和width,而叠加的层数成为channel(这里RGB构成的channel为3),对应的filter也需要三层,即filter的channel要与原始图片的channel一样

运算规则是,RGB的每一个channel和filter每一个channel先做卷积,然后将每个channel的卷积加总,作为结果矩阵的对应元素值,如下图:

Xnip2018-07-02_09-06-33

依次类推:

Xnip2018-07-02_09-09-25

如果仅关注一种颜色(比如红色)的边界,则可以将filter中绿色和蓝色层的矩阵设置为全零矩阵。如果RGB三种颜色的边界都考虑,则将filter三层设置为一样的矩阵。

  1. Multi filters

Multi filters是构建CNN的重要思想。如果我们不只想检测水平和垂直边界,比如还想检测45度,甚至70度的边界呢?换句话说,如何同时应用多个filter呢

可以这样思考,图片分别应用了两个filter,比如一个是水平filter、一个是垂直filter,分别得到两个目标矩阵,都是一层channel;然后这两个矩阵叠一起就变成了一个2层channel的矩阵,如下图:

Xnip2018-07-02_09-25-52

输出矩阵的channel数则与应用的filter的个数一样

multi-filter使得算法可以学习出多种feature。如果把一个filter整体看成基本神经网络中的参数w的话,那么multi-filter就相当于多个w。在基本神经网络中,我们也有W的行数和输出矩阵的行数一样,这一点类似filter个数和输出矩阵的channel的关系。

另外一张RGB图片,可以认为天然的被拆分成3个feature。

综上所述,你可以同时应用多个filter,并且每个filter又有多个channel,在这个基础上就可以实现CNN了。

1.7- One Layer of a Convolutional Network

一个单层的卷积神经网络例子如下:

One-Layer-of-a-Convolutional-Network (图片来源:http://kyonhuang.top/Andrew-Ng-Deep-Learning-notes/#/Convolutional_Neural_Networks/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C?id=%E5%8D%95%E5%B1%82%E5%8D%B7%E7%A7%AF%E7%BD%91%E7%BB%9C)

输入一张RGB图片,经过两个filter得到卷积,在卷积结果上加上偏移b1和b2,再应用activation function,得到输出层。

下面是动画演示,很形象:

对比基本的Neural Network,可以发现filter类似于参数\(W^{[1]}\)。

而卷积运算在加上后的b,即,也可以看做是原图像和filter上每个元素的线性组合,这也类似于基本Neural Network中计算z的过程:\(z^{[1]}=W^{[1]}a^{[0]} + b^{[1]}\)

每一个channel可以理解为普通NN中的一个实数w。

参数个数 问:如果一个layer有10个filter,每个filter是3x3x3,本层一共有多少参数? 答:一个filter有27个参数,再加上一个bias参数b,一个filter对应28个参数,10个filter一共280个参数。

与基本NN不同,CNN的参数个数并不随输入增大(共享参数的原因,后面会介绍),无论是1000x1000像素的图片,还是5000x5000像素的图片,CNN的参数都可以是一样的值。CNN极大的减少了parameter的个数,不会随着图片的像素数增加而增加,降低了overfitting

符号总结(符号和维度顺序惯例):

  • \(l\):表示CNN的层数是第\(l\)层,用上标\([l]\)标记哪一层的参数。
  • \(f^{[l]}\):filter的大小,即filter矩阵的长或宽,一般长宽相等。
  • \(p^{[l]}\):padding的大小
  • \(s^{[l]}\):stride步长
  • \(n_C^{[l]}\):输出的channel数,也是当前层filter的个数,下一层filter的channel数
  • \(n_H^{[l]}\):图片矩阵的height
  • \(n_W^{[l]}\):图片矩阵的width

对\([l]\)层来说:

  • 输入维度是:\(n_H^{[l-1]} \times n_W^{[l-1]} \times n_C^{[l-1]}\)
  • 输出维度是:\(n_H^{[l]} \times n_W^{[l]} \times n_C^{[l]}\)
  • 单个filter的维度是:\(f^{[l]} \times f^{[l]} \times n_C^{[l-1]}\) (注意:本层filter的channel和上一层输出的channel一样)
  • 所有filter(\(n_C^{[l-1]} \)个)组成当前layer的Weight:\(f^{[l]} \times f^{[l]} \times n_C^{[l-1]} \times n_C^{[l]} \)
  • bias的维度是:\(1 \times 1 \times 1 \times n_C^{[l]}\)
  • activations(\(a^{[l]}\))的维度和输出维度一样:\(n_H^{[l]} \times n_W^{[l]} \times n_C^{[l]}\)
  • 对于batch gradient,考虑到样本数\(m\),则\(A^{[l]}\)的维度是\(m \times n_H^{[l]} \times n_W^{[l]} \times n_C^{[l]}\),编程实践上也采用这个顺序的维度。

根据之前的公式,有输出height、width和输入的关系如下:

\[n_H^{[l]} = \biggl\lfloor \frac{n_H^{[l-1]}+2p^{[l]}-f^{[l]}}{s^{[l]}}+1 \biggr\rfloor\] \[n_W^{[l]} = \biggl\lfloor \frac{n_W^{[l-1]}+2p^{[l]}-f^{[l]}}{s^{[l]}}+1 \biggr\rfloor\]

1.8- Simple Convolutional Network Example

下图是一个简单CNN网络的例子:

Xnip2018-07-04_08-28-33

  • 输入图片是39x39x3的维度。
  • 最后的输出volume,unroll成一个vector,再通过logistic或softmax函数处理,实现分类。
  • 一般而言,图片的height \(n_H^{[l]}\) 和width \(n_W^{[l]}\)随着层数的增加逐渐降低,但channel \(n_C^{[l]}\)逐渐增加

Type of layer in a converlutional netwrok(ConvNet):

  • Convolution (CONV)
  • Pooling (POOL)
  • Fully connected (FC)

1.9- Pooling Layers

  1. 除了卷积层(convolutional layers)外,卷积网络(ConvNets)还经常用池化层(pooling layers),主要好处是:
    • 降低表示的大小,加快计算速度。
    • 提高feature的鲁棒性。

pooling可分为max pooling和average pooling。

  1. Max pooling

下图是max pooling的示意图:

Xnip2018-07-04_08-45-20

Max pooling的过程是,将原矩阵分成若干个分区(如上图四种颜色标记),每个分区内选择最大值,代表这个分区,组成一个新的矩阵。 上面的例子的作用结果(尤其是矩阵大小),也相当于一个作用了一个卷积filter,其大小是2x2,stride为2的。即:\(f=2\),\(s=2\),之前推导的filter大小公式也适用。因此max pooling也用\(f\)和\(s\)等作为其参数,但需要注意,对max pooling而言,这些参数是超参

与卷积相比,max pooling并没有一个filter,或者说这个filter是一个全1矩阵,和重叠的矩阵元素相乘,然后取元素最大值,从这点看和卷积操作也是统一的。

下图是一个f=3, s=1的max pooling例子:

Xnip2018-07-04_08-59-04

Xnip2018-07-04_09-00-06

类似的,max pooling也是支持channel的,但与卷积不同,输出的channel和输入的channel数目是一样的(卷积输出channel总是一层,卷积相当于计算后的channel做了叠加,max pooling的channel之间互相独立)。

Xnip2018-07-04_09-15-12

关于max pooling的直觉解释: 元素较大的值,可能是卷积过程中提取到的某些特征(比如边界),而max pooling则在压缩了矩阵大小的情况下,保留每个分区内最大的输出,即保留了提取的特征。但理论上还没有证明max pooling的原理,max pooling应用的原因是在实践中效果很好。

  1. Average pooling

与max pooling的不同仅在于最后取的是分区内的平均值,而不是最大值。比如:

Xnip2018-07-04_09-20-10

另外,Average pooling不如max pooling那么常用。

  1. pooling总结:
    • 超参:
    • f:filter size(通常选择f=2,s=2,实现对一张图片的shrink,长宽都shrink了一半)
    • s:stride
    • 选择max还是average pooling
    • p:padding,几乎不会用到(因为pooling本身就是一个shrink的过程),或设置为0. * pooling没有需要学习的参数,只有超参。

1.10- CNN Example

前面已经了解了CNN需要的模块,下面通过一个例子介绍CNN网络:LeNet-5架构(与原论文略有修改),用来识别数字。 LeNet-5原版可参考论文:http://yann.lecun.com/exdb/publis/pdf/lecun-98.pdf

LeNet-5架构如下:

Xnip2018-07-04_21-11-41

  • 通常Conv Layer和Pooling Layer合在一起算一个layer,因为pooling layer并没有参数训练
  • 常见的结构:Conv ==> Pool ==> Conv ==> Pool ==> FC ==> FC ==> softmax
  • 最终还会用FC层(全连接层),与一般NN的处理一样;并在输出层,应用softmax得到10个数字的概率。
  • 在整个网络中,Height和Width是逐渐递减的,但channel和filter是递增的。
  • 关于CNN如何选择超参:可以参考论文的经验。

整个例子的参数个数如下:

  Activation shape Activation Size #parameters
Input: (32, 32, 3) 3072 0
CONV1(f=5, s=1) (28, 28, 6) 4704 156 (=5*5*6+6)
POOL1 (14, 14, 6) 1176 0
CONV2(f=5, s=1) (10, 10, 16) 1600 416 (=5*5*16+16)
POOL2 (5, 5, 16) 400 0
FC3 (120, 1) 120 48120 (=120*400+120)
FC4 (84, 1) 84 10164 (=84*120+84)
Softmax (10, 1) 10 850 (=10*84+10)
  • pooling layer没有参数
  • CONV layer的参数相比FC的parameter会少很多。
  • activation size递减 (activation size总是和feature相等的,feature一直在缩减)

1.11- Why Convolutions?

CONV Layer相比一般神经网络的全连接层的优势:

  • 参数共享(parameter sharing) 以上一节的例子为例,如果在第一层就用FC的话,参数可达4704*3070 + 4704个,这个数字已经膨胀到了1400万,而这还仅是训练一个只有32*32像素的小图片。 而CONV Layer只有156个参数。 参数共享为什么可行呢?一个feature检测器,即filter(比如垂直边界检测)在图片的一个地方适用,也很可能在图片的其他地方适用(我的理解:在这一点上很像transfering learning或multi-task learning)。这种共享不仅在底层feature有用,也在高层feature有用(比如检测眼睛)。

  • 稀疏连接(sparsity of connections) 稀疏连接是指,输出中的每个单元仅和输入的一个小分区相关,比如输出的左上角的像素仅仅由输入左上角的9个像素决定(假设filter大小是3*3),而其他输入都不会影响。

基于上述的特点,CNN网络可以使用较少的参数,使用较少的训练数据,并且不容易overfitting。 另外CNN也特别适合捕捉平移不变形(Translation Invariance)

附:直观展示CNN网络:http://scs.ryerson.ca/~aharley/vis/

-------------------------

本文采用 知识共享署名 4.0 国际许可协议(CC-BY 4.0)进行许可。转载请注明来源:https://imshuai.com/deeplearning-ai-notes-course4-week1 欢迎指正或在下方评论。