参考 cs231n的课程笔记ConvNet notes来入门一下卷积神经网络
什么是卷积
参考 我对卷积的理解这篇文章, 可以对卷积有更深的认识, 在图像的识别上我们常用的是离散卷积, 离散卷积的本质就是输入信号和系统响应的加权叠加
, 如果变量是时间, 就是在时间轴上的加权叠加, 这样就会有了时间累积效应(信号在不同时间点的具有相关性), 在CNN中我们的输入信号是图片(矩阵), 我们的系统响应就是卷积核
, 对于图像的卷积操作我认为就是关于位置上的一个加权求和, 这样就使得输出矩阵的像素点依然具有相关性(因为原图像的像素点之间也具有相关性), 如下图所示
在上图中, 绿色为输入原始图像, 黄色的为卷积核, 粉色为输出
关于图像卷积的一个 演示
卷积神经网络
和神经网络相似, 卷积神经网络也是由神经元组成,神经元中有具有学习能力的权重和偏差。每个神经元都得到一些输入数据,进行内积运算后再进行激活函数运算, 整个网络依旧是一个可导的评分函数该函数的输入是原始的图像像素,输出是不同类别的评分。在最后一层往往是全连接层,网络依旧有一个损失函数(比如SVM或Softmax),并且在神经网络中我们实现的各种技巧和要点依旧适用于卷积神经网络。
- 神经网络结构 : 在该结构中, 输入是一个向量,然后在一系列的隐层中对它做变换, 如果一个尺寸为200x200x3的图像,采用全连接方式会让每个神经元包含200x200x3=120,000个权重值, 这种全连接方式效率低下,大量的参数也很快会导致网络过拟合。
卷积网络结构 : 卷积神经网络结构将它的神经元都排列成3个维度(宽、高和深度), 每一层都将三维的输入数据变化为三维神经元激活函数的输出数据, 红色的输入层装的是图像,宽度和高度就是图像的宽度和高度,它的深度是3, 代表了红、绿、蓝3种颜色通道
- 与神经网络不同的是, 卷积神经网络针对输入全部是图像的情况,将结构调整为三维排列的神经元(宽度、高度和深度), 注意, 这里的深度指的是激活数据体的第三个维度,而不是整个网络的深度,整个网络的深度指的是网络的层数, 在卷积神经网络结构的最后部分将会把全尺寸的图像压缩为包含分类评分的一个向量,向量是在深度方向排列的。
卷积网络中的层
卷积神经网络主要由三种类型的层构成:卷积层CONV
,汇聚层POOL
和全连接层FC
(全连接层和常规神经网络中的一样), 网络中的每个层使用一个可以微分的函数将激活数据从一个层传递到另一个层, 如下图所示:
卷积层
卷积层是构建卷积神经网络的核心层,它产生了网络中大部分的计算量。卷积层的参数是有一些可学习的滤波器集合构成的, 每个滤波器的宽度和高度都比较小,但是深度和输入数据一致。
如上图,
卷积神经网络第一层的卷积核的尺寸是
5x5x3
(宽高都是5像素,深度是3是因为对应图像的颜色通道), 卷积核就相当于一个滤波器, 其中神经元的参数$w$是一个75维的参数向量(5x5x3), 加上一个偏置项$b$, 其中参数向量$w$(也就是卷积核)包含了某些类型的视觉特征在前向传播的时候,让每个滤波器都在输入数据的宽度和高度上做离散卷积运算(卷积运算本质上就是在滤波器和输入数据的局部区域间做点积运算$w^Tx$),然后滑动计算整个滤波器和输入数据每一处的卷积得到2维的激活图(activation map), 其大小为[28*28], (32-5+1=28,如第一个图所示), 激活图给出了在每个空间位置处滤波器的输出
在每个卷积层上有多个卷积核,每个卷积核都会生成一个不同的二维激活图, 将这些激活映射在深度方向上层叠起来就生成了输出数据, 如下所示:
- 假设我们有6个卷积核, 最后就会得到一个[6*28*28]的输出数据(步长为1)
局部连接
在处理图像这样的高维度输入时,让每个神经元都与前一层中的所有神经元进行全连接是不现实的。相反,我们让每个神经元只与输入数据的一个局部区域连接, 该局部区域的空间大小叫做神经元的感受野(receptive field)
,它的尺寸是一个超参数, 其实就是卷积核的空间尺寸, 注意, 在连接空间上是局部的(宽高),但是在深度上总是和输入数据的深度一致。比如:
假设输入数据体尺寸为[32x32x3](比如CIFAR-10的RGB图像),如果感受野(或滤波器尺寸)是5x5,那么卷积层中的每个神经元会有输入数据体中[5x5x3]区域的权重,共5x5x3=75个权重(还要加一个偏差参数)。注意这个连接在深度维度上的大小必须为3,和输入数据体的深度一致
假设输入数据体的尺寸是[16x16x20],感受野尺寸是3x3,那么卷积层中每个神经元和输入数据体就有3x3x20=180个连接。在空间上连接是局部的(3x3),但是在深度上是和输入数据体一致的(20)
也就是说, 神经元的参数向量的中参数的个数只和
卷积核大小k*k(等价于感受野的大小)
和输入数据的维数n有关
, $w$中的参数个数为[k*k*n]
左图:红色部分的是输入数据(比如CIFAR-10中的图像),蓝色的部分是第一个卷积层中的神经元。卷积层中的每个神经元都只是与输入数据的一个局部空间相连, 但是与输入数据的局部区域中所有深度维度上的数据全部相连(所有颜色通道), 图中的卷积层在深度方向上有5个神经元, 但是它们都接受输入数据的同一块区域, 即感受野相同
右图:在卷积层中的神经元和神经网络中介绍的神经元保持一致,还是计算权重和输入的内积,加上偏置然后进行激活函数运算,唯一不同的是它们的连接被限制在一个局部空间
卷积层输出的空间排列
3个超参数控制着输出数据体的尺寸:
深度(depth)
输出数据体的深度是和局部连接的神经元的个数有关的, 由于这一部分神经元连接相同的感受野, 每个神经元都会输出一个二维的激活图(activation map), 我们将这些沿着深度方向排列、感受野相同的神经元集合称为深度列(depth column)步长(stride)
在滑动卷积的过程中, 必须指定步长, 这直接关系到输出数据体的空间大小(深度除外), 步长为n就是每次移动n个像素, 同一深度切片中邻近神经元的感受野中心之间的距离零填充(zero-padding)
如果我们要保证输入数据体和输出控制体在空间上保持一致, 那么在卷积运算的时候, 必须在边缘填充0
下面我们用一个例子来看一下这三个超参数是怎么影响输出数据体的空间尺寸的
假设局部感受野为正方形且尺寸为[3x3], 这样我们从一个维度上去分析尺寸就可以了, 如图所示输入的空间尺寸为[7x7], 神经元的权重是[1,0,-1],显示在图的右上角,偏差值为0。这些权重是被所有黄色的神经元共享的, 神经元的感受野尺寸F=3,输入尺寸W=5,零填充P=1
在左一图中步长$S=1$, 每次计算向右移动1个像素点, 最终输出尺寸为(5-3+2)/1+1=5, 由于使用了
零填充
使得输入和输出尺寸一样, 一般说来,当步长$S=1$时,零填充的值是$P=(F-1)/2$,这样就能保证输入和输出数据体有相同的空间尺寸。在左二图中步长$S=2$, 每次计算向右移动2个像素点, 最终输出尺寸为(5-3+2)/2+1=5
注意, 当步长S=3时是无法使用的,因为它无法整齐地穿过数据体。从等式上来说,因为(5-3+2)=4是不能被3整除的, 也就是说步长的选择是有限制的, 必须使得神经元整齐对称地滑过输入数据体。
那么我们总结一下计算输出数据体在空间上的尺寸的公式:
假设输入数据体尺寸为$W$,卷积层中神经元的感受野尺寸为$F$,步长为$S$, 零填充的数量$P$, 假设输入数组的空间形状是正方形, 输出数据体的空间尺寸(正方形)为
$$\frac{W-F+2P}{S}+1$$
- 深度的维数就是该卷积层的
卷积核
的个数(the number of filters)
参数共享
在 ImageNet Classification with Deep Convolutional Neural Networks中, 输入图像的尺寸是[227x227x3], 第一个卷积层神经元使用的感受野尺寸$F=11$,步长$S=4$,不使用零填充$P=0$, 那么输出空间的尺寸为(227 - 11)/4 + 1 = 55, 又由于卷积层的深度$K=96$,则卷积层的输出数据体尺寸为[55x55x96], 这样产生的55x55x96=290400个神经元中,每个都和输入数据体中一个尺寸为[11x11x3]的区域全连接, 在深度列上的96个神经元都是与输入数据体中同一个[11x11x3]区域连接,但是权重不同, 每个神经元有11x11x3=364个参数和1个偏差, 最终得到290400x364=105,705,600个参数, 这显然是一个参数灾难, 参数共享
就是解决这一问题的
参数共享
基于一个假设, 如果一个特征(卷积核包含特征)在计算某个空间位置$(x,y)$的时候有用,那么它在计算另一个不同位置$(x’,y’)$的时候也有用, 那么我们就可以共享这个特征, 如果将深度维度上一个单独的2维切片看做深度切片(depth slice), 我们把同一深度的平面叫做深度切片(depth slice),那么同一个切片应该共享同一组权重和偏置。比如卷积层的输出数据体尺寸为[55x55x96]有96个深度切片,每个尺寸为[55x55], 在每个深度切片
上的神经元都使用同样的权重和偏差, 由于每个神经元的感受野大小为[11x11x3], 所以在每个深度切片上只会会产生[11x11x3]个参数, 96个深度切片一共产生96x11x11x3=34848个不同的权重,或34944个参数(+96个偏差)。
在反向传播的时候,都要计算每个神经元对它的权重的梯度,但是需要把同一个深度切片上的所有神经元对权重的梯度累加,这样就得到了对共享权重的梯度。这样,每个切片只更新一个权重集。
如果在一个深度切片中的所有权重都使用同一个权重向量,那么卷积层的前向传播在每个深度切片中可以看做是在计算神经元权重和输入数据体的卷积
- 上图就是学习得到的96个滤波器, 这96个滤波器的尺寸都是[11x11x3],在一个深度切片中,每个滤波器都被55x55个神经元共享。
注意
- 参数共享的假设是有道理的:如果在图像某些地方探测到一个水平的边界是很重要的,那么在其他一些地方也会同样是有用的,这是因为图像结构具有平移不变性。所以在卷积层的输出数据体的55x55个不同位置中,就没有必要重新学习去探测一个水平边界了
注意, 有时候参数共享假设可能并不适用,特别是当卷积神经网络的输入图像是一些明确的中心结构时候, 这时候我们就应该期望在图片的不同位置学习到完全不同的特征, 比如输入图像是人脸,人脸一般都处于图片中心, 你可能期望学习到不同的特征(比如眼睛特征或者头发特征), 这些特征也许在图片的不同位置, 这时就应该打破参数共享的限制, 在同一个深度切片中使用局部参数不一致的卷积核, 这时将该层称为局部连接层(Locally-Connected Layer)
卷积层参数:
- 输入数据体的尺寸为$W_1 \times H_1 \times D_1$
- 4个超参数:
- 滤波器的数量$K$
- 滤波器的空间尺寸$F$
- 步长$S$
- 零填充数量$P$
- 输出数据体的尺寸为$W_2 \times H_2 \times D_2$,其中:
- $W_2 = (W_1 - F + 2P)/S + 1$
- $H_2 = (H_1 - F + 2P)/S + 1$
- $D_2 = K$
- 参数共享,每个滤波器包含$F \cdot F \cdot D_1$个权重,卷积层一共有$(F \cdot F \cdot D_1) \cdot K$个权重和$K$个偏置。
- 在输出数据体中,第$d$个深度切片(空间尺寸是$W_2 \times H_2$),用第$d$个滤波器和输入数据进行有效卷积运算的结果(使用步长$S$),最后在加上第$d$个偏差。
- 对这些超参数,常见的设置是$F = 3, S = 1, P = 1$
扩展阅读:
- 反向传播:卷积操作的反向传播(同时对于数据和权重)还是一个卷积(但是是和空间上翻转的滤波器)
- 1x1卷积: Network in Network比如,如果输入是[32x32x3],那么1x1卷积就是在高效地进行3维点积(因为输入深度是3个通道)
- 扩张卷积 : Multi-Scale Context Aggregation by Dilated Convolutions, 在某个维度上滤波器w的尺寸是3,那么计算输入x的方式是:$w[0]*x[0] + w[1]*x[1] + w[2]*x[2]$,此时扩张为0。如果扩张为1,那么计算为: $w[0]*x[0] + w[1]*x[2] + w[2]*x[4]$
汇聚层
在连续的卷积层之间会周期性地插入一个汇聚层(Pooling), 通过采样的方式逐渐降低数据体的空间尺寸,这样的话就能减少网络中参数的数量,使得计算资源耗费变少,也能有效控制过拟合。
汇聚层参数
如图所示,
- 输入空间尺寸: $W_1 \times H_1 \times D_1=[ 224 \times 224 \times 64]$
- 两个超参数: 空间大小$F=2$, 步长$S=2$
输出空间尺寸$W_2 \times H_2 \times D_2=[ 112 \times 112 \times 64]$
其中,
$W_2 = (W_1 - F)/S + 1=(224-2)/2+1=112$
$H_2 = (H_1 - F)/S + 1=(224-2)/2+1=112$
$D_2 = D_1=64$
在汇聚层中很少使用零填充
- 没有引入其他超参数
如图所示,
Pooling层通常采用Max操作, 对输入数据体的每一个深度切片独立进行操作,改变它的空间尺寸
最常见的形式是汇聚层使用尺寸2x2的滤波器,以步长为2来对每个深度切片进行降采样,将其中75%的激活信息都丢掉
每个MAX操作是从4个数字中取最大值, 也就是在深度切片中某个2x2的区域
空间尺寸减半, 深度保持不变
在实践中,最大汇聚层通常只有两种形式:
- 重叠汇聚(overlapping pooling): $F = 3, S = 2$
- 无重叠汇聚(overlapping pooling)更常用: $F = 2, S = 2$
普通汇聚
除了最大汇聚, 还有平均汇聚(average pooling)或L-2范式汇聚(L2-norm pooling), 平均汇聚历史上比较常用,但是现在已经很少使用了, 因为实践证明,最大汇聚的效果比平均汇聚要好, 对更大感受野进行汇聚需要的汇聚尺寸也更大,而且往往对网络有破坏性。
反向传播
$max(x, y)$反向传播相当于将梯度只沿最大的数回传。因此,在向前传播经过汇聚层的时候,通常会把池中最大元素的索引记录下来(有时这个也叫作道岔(switches)),这样在反向传播的时候梯度的路由就很高效
不使用汇聚层
Striving for Simplicity: The All Convolutional Net提出使用一种只有重复的卷积层组成的结构,抛弃汇聚层。通过在卷积层中使用更大的步长来降低数据体的尺寸。有发现认为,在训练一个良好的生成模型时,弃用汇聚层也是很重要的。比如变化自编码器(VAEs:variational autoencoders)和生成性对抗网络(GANs:generative adversarial networks)。现在看起来,未来的卷积网络结构中,无汇聚层的结构不太可能扮演重要的角色
归一化层
在卷积神经网络的结构中,提出了很多不同类型的归一化层,有时候是为了实现在生物大脑中观测到的抑制机制。但是这些层渐渐都不再流行,因为实践证明它们的效果即使存在,也是极其有限的。对于不同类型的归一化层,可以看看Alex Krizhevsky的关于 cuda-convnet library API 的讨论。
全连接层
在全连接层中,神经元对于前一层中的所有激活数据是全部连接的,这个常规神经网络中一样。具体请看 Neural Network和 Neural Network in Practice
全连接层转化为卷积层
全连接层和卷积层之间唯一的不同就是卷积层中的神经元只与输入数据中的一个局部区域连接,并且在深度切片中的神经元共享参数, 所以将卷积层看作是全连接层的一个特殊情况, 由于局部连接, 将全连接层的权重矩阵某些块设置为0, 因为参数共享, 使得权重矩阵中的大部分块是相等的, 这样看来任一卷积层就是一个全连接层, 只是参数矩阵比较特殊罢了
在实际中更加有用的是全连接层转化为卷积层:
上图是Alexnet
卷积神经网络的结构, 由图可知, 输入是224x224x3的图像,一系列的卷积层和汇聚层将图像数据变为尺寸为7x7x512的激活数据体, AlexNet使用了两个尺寸为4096的全连接层,最后一个有1000个神经元的全连接层用于计算分类评分, 我们可以将这3个全连接层中的任意一个转化为卷积层:
- 针对第一个连接区域是[7x7x512]的全连接层,令其滤波器尺寸为$F=7$,这样输出数据体就为[1x1x4096]
- 针对第二个全连接层,令其滤波器尺寸为$F=1$,这样输出数据体为[1x1x4096]。
- 对最后一个全连接层也令其滤波器尺寸为$F=1$,最终输出为[1x1x1000]
实际操作中,每次这样的变换都需要把全连接层的权重$W$重塑成卷积层的滤波器的优势:
我们将全连接层转化为卷积层之后, 让卷积网络在一张更大的输入图片上滑动就会得到得到多个输出,每个输出可以代表对每个区域的评分, 通过这样的转化可以让我们在向前传播的过程中一次性地把一张更大的图片的不同区域都分别带入到卷积网络,得到对于每个区域的得分, 举个例子:
如果我们想让224x224尺寸的浮窗,以步长为32在384x384的图片上滑动,把每个经停的位置都带入卷积网络,最后得到6x6个位置的类别得分。因为如果224x224的输入图片经过卷积层和汇聚层之后得到了[7x7x512]的数组,那么,384x384的大图片直接经过同样的卷积层和汇聚层之后会得到[12x12x512]的数组(因为途径5个汇聚层,尺寸变为384/2/2/2/2/2 = 12)。然后再经过上面由3个全连接层转化得到的3个卷积层,最终得到[6x6x1000]的输出(因为(12 - 7)/1 + 1 = 6)。这个结果正是浮窗在原图经停的6x6个位置的得分, 相较于使用被转化前的原始卷积神经网络对所有36个位置进行迭代计算,使用转化后的卷积神经网络进行一次前向传播计算要高效得多,因为36次计算都在共享计算资源。
在实践中经常使用,一次来获得更好的结果。比如,通常将一张图像尺寸变得更大,然后使用变换后的卷积神经网络来对空间上很多不同位置进行评价得到分类评分,然后在求这些分值的平均值
用iPython来进行转换的 演示 Net Surgery
CNN架构
卷积神经网络通常是由三种层构成:卷积层CONV
,汇聚层POOL
(除非特别说明,一般就是最大值汇聚)和全连接层FC
, ReLU激活函数
也应该算是是一层,它逐元素地进行激活函数操作。
层的排列规律
卷积神经网络最常见的形式就是将一些卷积层和ReLU层放在一起,其后紧跟汇聚层,然后重复如此直到图像在空间上被缩小到一个足够小的尺寸,在某个地方过渡成成全连接层也较为常见。最后的全连接层得到输出,比如分类评分等。
$$INPUT \Rightarrow [[CONV \Rightarrow RELU]*N \Rightarrow POOL?]*M \Rightarrow [FC \Rightarrow RELU]*K \Rightarrow FC$$
上式中,
*
指的是重复次数POOL?
指的是一个可选的汇聚层- $N >=0,N<=3,M>=0,K>=0,K<3$
常见的网络结构规律:
$$INPUT \Rightarrow FC$$
- 实现一个线性分类器,此处N = M = K = 0。
$$INPUT \Rightarrow CONV \Rightarrow RELU \Rightarrow FC$$
$$INPUT \Rightarrow [CONV \Rightarrow RELU \Rightarrow POOL]*2 \Rightarrow FC \Rightarrow RELU \Rightarrow FC$$
- 此处在每个汇聚层之间有一个卷积层。
$$INPUT \Rightarrow [CONV \Rightarrow RELU \Rightarrow CONV \Rightarrow RELU \Rightarrow POOL]*3 \Rightarrow [FC \Rightarrow RELU]*2 \Rightarrow FC$$
- 此处每个汇聚层前有两个卷积层,这个思路适用于更大更深的网络,因为在执行具有破坏性的汇聚操作前,多重的卷积层可以从输入数据中学习到更多的复杂特征
最好选择带有小滤波器的卷积层组合,而不是用一个带有大的滤波器的卷积层。前者可以表达出输入数据中更多个强力特征,使用的参数也更少。唯一的不足是,在进行反向传播时,中间的卷积层可能会导致占用更多的内存。
层的尺寸设置规律
输入层(包含图像的)应该能够多次被2整除。常用数字包括32(比如CIFAR-10),64,96(比如STL-10)或224(比如ImageNet卷积神经网络),384和512。
卷积层应该使用小尺寸滤波器(比如3x3或最多5x5),使用步长$S=1$, 还有一点非常重要,就是对输入数据进行零填充,这样卷积层就不会改变输入数据在空间维度上的尺寸。如果必须使用更大的滤波器尺寸(比如7x7之类),通常只用在第一个面对原始图像的卷积层上。
汇聚层负责对输入数据的空间维度进行降采样。最常用的设置是用用2x2感受野(即$F=2$)的最大值汇聚,步长为2($S=2$)。另一个不那么常用的设置是使用3x3的感受野,步长为2。最大值汇聚的感受野尺寸很少有超过3的,因为汇聚操作过于激烈,易造成数据信息丢失过多
- 步长为1可以让空间维度的降采样全部由汇聚层负责,卷积层只负责对输入数据体的深度进行变换
- 使用零填充除了前面提到的可以让卷积层的输出数据保持和输入数据在空间维度的不变,还可以提高算法性能。如果卷积层值进行卷积而不进行零填充,那么数据体的尺寸就会略微减小,那么图像边缘的信息就会过快地损失掉。
拓展阅读
-
- 第一个成功的卷积神经网络应用,是Yann LeCun在上世纪90年代实现的。
- 最著名还是被应用在识别数字和邮政编码等的LeNet结构
-
- AlexNet卷积神经网络在计算机视觉领域中受到欢迎,它由Alex Krizhevsky,Ilya Sutskever和Geoff Hinton实现
- AlexNet在2012年的ImageNet ILSVRC 竞赛中夺冠,性能远远超出第二名(16%的top5错误率,第二名是26%的top5错误率)
- 网络的结构和LeNet非常类似,但是更深更大,并且使用了层叠的卷积层来获取特征
-
- Matthew Zeiler和Rob Fergus发明的网络在ILSVRC 2013比赛中夺冠,它被称为 ZFNet(Zeiler & Fergus Net的简称)
- 通过修改结构中的超参数来实现对AlexNet的改良,具体说来就是增加了中间卷积层的尺寸,让第一层的步长和滤波器尺寸更小
-
- ILSVRC 2014的胜利者是谷歌的Szeged等实现的卷积神经网络
- 实现了一个奠基模块,它能够显著地减少网络中参数的数量(AlexNet中有60M,该网络中只有4M)
- 论文中没有使用卷积神经网络顶部使用全连接层,而是使用了一个平均汇聚,把大量不是很重要的参数都去除掉了
- GooLeNet还有几种改进的版本,最新的一个是Inception-v4
-
- ILSVRC 2014的第二名是Karen Simonyan和 Andrew Zisserman实现的卷积神经网络,现在称其为VGGNet
- 展示出网络的深度是算法优良性能的关键部分
- 最好的网络包含了16个卷积/全连接层, 网络的结构非常一致,从头到尾全部使用的是3x3的卷积和2x2的汇聚
- VGGNet不好的一点是它耗费更多计算资源,并且使用了更多的参数,导致更多的内存占用, 其中绝大多数的参数都是来自于第一个全连接层。后来发现这些全连接层即使被去除,对于性能也没有什么影响,这样就显著降低了参数数量
-
- 残差网络(Residual Network)是ILSVRC2015的胜利者,由何恺明等实现
- 使用了特殊的跳跃链接,大量使用了 批量归一化(batch normalization)
- 最后没有使用全连接层
- 何恺明的的 演讲 和 PPT
- Torch重现网络的实验
- 对原始结构做一些优化,可以看论文 Identity Mappings in Deep Residual Networks
- State of the art ResNets in Torch7
以上部分内容引自 智能单元