简介
一些关于卷积的笔记
从MLP到CNN
网络结构

如图1所示,一个卷积神经网络由若干卷积层、Pooling层、全连接层组成。你可以构建各种不同的卷积神经网络,它的常用架构模式为:
1
| INPUT -> [[CONV]*N -> POOL?]*M -> [FC]*K
|
也就是N个卷积层叠加,然后(可选)叠加一个Pooling层,重复这个结构M次,最后叠加K个全连接层。
对于图1展示的卷积神经网络:
1
| INPUT -> CONV -> POOL -> CONV -> POOL -> FC -> FC
|
按照上述模式可以表示为:
1
| INPUT -> [[CONV]*1 -> POOL]*2 -> [FC]*2
|
也就是:N=1, M=2, K=2
三维的层结构
从图1我们可以发现卷积神经网络的层结构和全连接神经网络的层结构有很大不同。全连接神经网络每层的神经元是按照一维排列的,也就是排成一条线的样子;而卷积神经网络每层的神经元是按照三维排列的,也就是排成一个长方体的样子,有宽度、高度和深度。
对于图1展示的神经网络,我们看到输入层的宽度和高度对应于输入图像的宽度和高度,而它的深度为1。接着,第一个卷积层对这幅图像进行了卷积操作(后面我们会讲如何计算卷积),得到了三个Feature Map。这里的"3"可能是让很多初学者迷惑的地方,实际上,就是这个卷积层包含三个Filter,也就是三套参数,每个Filter都可以把原始输入图像卷积得到一个Feature Map,三个Filter就可以得到三个Feature Map。至于一个卷积层可以有多少个Filter,那是可以自由设定的。也就是说,卷积层的Filter个数也是一个超参数。我们可以把Feature Map可以看做是通过卷积变换提取到的图像特征,三个Filter就对原始图像提取出三组不同的特征,也就是得到了三个Feature Map,也称做三个通道(channel)。
继续观察图1,在第一个卷积层之后,Pooling层对三个Feature Map做了下采样(后面我们会讲如何计算下采样),得到了三个更小的Feature Map。接着,是第二个卷积层,它有5个Filter。每个Fitler都把前面下采样之后的3个**Feature Map卷积在一起,得到一个新的Feature Map。这样,5个Filter就得到了5个Feature Map。接着,是第二个Pooling,继续对5个Feature Map进行下采样**,得到了5个更小的Feature Map。
图1所示网络的最后两层是全连接层。第一个全连接层的每个神经元,和上一层5个Feature Map中的每个神经元相连,第二个全连接层(也就是输出层)的每个神经元,则和第一个全连接层的每个神经元相连,这样得到了整个网络的输出。
Forward计算
假设有一个5×5的图像,使用一个3×3的filter进行卷积,想得到一个3×3的Feature Map,如下所示:
符号 |
说明 |
符号 |
说明 |
xi,j |
Image第 i 行第 j 列元素 |
wm,n |
Filter第 m 行第 n 列权重 |
ai,j |
Feature Map的第 i 行第 j 列元素 |
wb |
Filter的偏置项 |
f(⋅) |
激活函数, 本例f为relu函数 |
|
|
使用下列公式计算卷积:
ai,j=f(m=0∑2n=0∑2wm,nxi+m,j+n+wb)
对于Feature Map左上角元素a0,0来说,其卷积计算方法为:
a0,0=f(m=0∑2n=0∑2wm,nxm+0,n+0+wb)=reluw0,0x0,0+w0,1x0,1+w0,2x0,2+w1,0x1,0+w1,1x1,1+w1,2x1,2+w2,0x2,0+w2,1x2,1+w2,2x2,2+wb=relu1+0+1+0+1+0+0+0+1+0=relu(4)=4
接下来,Feature Map的元素a0,1的卷积计算方法为:
a0,0=f(m=0∑2n=0∑2wm,nxm+0,n+1+wb)=reluw0,0x0,1+w0,1x0,2+w0,2x0,3+w1,0x1,1+w1,1x1,2+w1,2x1,3+w2,0x2,1+w2,1x2,2+w2,2x2,3+wb=relu1+0+0+0+1+0+0+0+1+0=relu(3)=3
可以依次计算出Feature Map中所有元素的值。下面的动画显示了整个Feature Map的计算过程:
步幅
上面的计算中, 步幅(Stride)为1, 步幅可以设为大于1的数, 例如, 当步幅为2时, Feature Map计算如下:
Feature Map的WF×HF 由下面式子计算
WFHF=(WI−WK+2P)/S+1=(HI−HK+2P)/S+1
输入图像 |
输出图像 |
Kernel大小 |
步幅 |
Padding |
WI×HI |
WF×HF |
WK×HK |
S |
P |
Zero Padding 是指在原始图像周围补几圈0, 如果P是1,那么就补1圈0
深度(通道数)
卷积前的图像深度为D,那么相应的filter的深度也必须为D。我们扩展一下式1,得到了深度大于1的卷积计算公式:
ai,j=f(d=0∑D−1m=0∑F−1n=0∑F−1wd,m,nxd,i+m,j+n+wb)(式4)
D是深度, F是卷积核大小
注意, 输入图像的深度是D, 卷积核的深度也对应是D, 但是1个卷积核的输出只有1层. 例如下图中演示的输入是深度为2的图像, 对应的卷积核深度也是2, 最后输出深度为1的图像
多个卷积核
一个卷积核对应一层输出, 多个卷积核对应多层输出, 卷积后Feature Map的深度和卷积核的个数是相同的.
卷积
数学中的卷积
对于函数f:Rn→R和g:Rn→R, 定义 f 和 g 的卷积如下
(f∗g)(x)=∫f(t)g(x−t)dt
对于离散情况有
(f∗g)(n)=k∑f(k)g(n−k)
对于二维张量有
(f∗g)(i,j)=m∑n∑f(m,n)g(i−m,j−n)
CNN中的卷积
CNN中的卷积在数学中叫做互相关(cross-correlation)
对于函数f:Rn→R和g:Rn→R, 定义 f 和 g 的互相关函数如下
(f⋆g)(x)=∫f(t)g(x+t)dt
对于离散情况有
(f⋆g)(n)=k∑f(k)g(n+k)
对于二维张量有
(f⋆g)(i,j)=m∑n∑f(m,n)g(i+m,j+n)
与CNN的卷积对应, 上式中 f 对应于卷积核(filter), g 对应于输入图像.
Pooling
Pooling(池化)的主要作用是下采样, 通过去掉Feature Map中不重要的样本, 进一步减少参数数量. Pooling的方法很多, 常用的有 Max Pooling, Mean Pooling
Max Pooling
与卷积层类似,Pooling运算符由⼀个固定形状的窗⼝组成,该窗⼝根据其步幅⼤⼩在输⼊的所有区域上滑动, 为固定形状窗⼝(有时称为汇聚窗⼝)遍历的每个位置计算⼀个输出。
ai,j=max⎩⎨⎧xi+0,j+0,xi+1,j+0,⋮xi+M,j+0,xi+0,j+1,xi+1,j+1,⋮xi+M,j+1,⋯,⋯,⋱⋯,xi+0,j+N,xi+1,j+N,⋮xi+M,j+N⎭⎬⎫
其中 M×N 是固定窗口的大小
Note: 与卷积(互相关)操作不同的是, 池化操作是对Feature Maps的每一层分别进行池化, 如果Feature Maps有n层, 那么池化得到的结果也是n层.
例如在下图中, 输入是一个单层的4×4的图像, 经过窗口大小为2×2, 步长为2的池化操作后得到一个单层的输出.
池化操作的输入和输出的大小也满足前面卷积(互相关)的输入输出的公式
WFHF=(WI−Ww+2P)/S+1=(HI−Hw+2P)/S+1
输入图像 |
输出图像 |
窗口大小 |
步幅 |
Padding |
WI×HI |
WF×HF |
Ww×Hw |
S |
P |
参数训练
1
| INPUT -> [[CONV]*N -> POOL?]*M -> [FC]*K
|
需要训练的部分是
- 卷积层中的卷积核的参数
- 全连接层中的变换矩阵
LeNet-5
LeNet是最早发布的卷积神经网络之⼀, 这个模型是由AT&T贝尔实验室的研究员Yann LeCun在1989年提出的(并以其命名), 目的是识别图像中的手写数字.

经过多年的努力, 1998年在论文Gradient-Based Learning Applied to Document Recognition中正式提出的LeNet-5成为第一个广为人知的CNN

卷积的矩阵乘法
普通卷积的计算, 移动窗口
036147258input∗[1324]kernel=[27573767]output
卷积可以转换成矩阵乘法
27375767output=100021000200301043210402003000430004Doubly Block-Toeplitz matrix012−345−678input
Doubly Block-Toeplitz (DBT) matrix
构造 Toepliz 矩阵
036147258input∗[1324]kernel=[2757376747]output
增加一行
2737475767output=100002100002100302104302104302004300004300004Doubly Block-Toeplitz matrix012−345−678input
关于卷积的计算复杂度
number of multiplications for one output pixelin_channels×kernel_size×number of output pixelsout_size×out_chennels