CNN是专门用来处理具有类似网格结构的数据的神经网络,本博客将总结对CNN的原理进行初步的学习和总结,参考的博客主要有:
Jason大神的 https://machinelearningmastery.com/crash-course-convolutional-neural-networks/
刘建平大神的https://www.cnblogs.com/pinard/p/6483207.html
张雨石大神的https://blog.csdn.net/stdcoutzyx/article/details/41596663
szx_spark大牛的https://www.cnblogs.com/szxspark/p/8439066.html系列
以及《深度学习》花书,自己的理解比较少,多是对这些大牛的博客的一个摘抄总结,当做自己的一个备忘。等之后工作中用到了,有的新的感悟了,再来更新。
目录
CNN的基本结构
卷积层
池化层
全连接层
CNN的实例
CNN之一维卷积、二维卷积、三维卷积详解
一维卷积
二维卷积
三维卷积
CNN的使用技巧
CNN的前向传播算法
CNN的反向传播算法
CNN有三种类型的层,卷积层、池化层和全连接层。
卷积层(Convolution Layer),这个是CNN特有的。
在卷积层后面是池化层(Pooling layer),这个也是CNN特有的,需要注意的是,池化层没有激活函数。
卷积层+池化层的组合可以在隐藏层出现很多次,这个次数是根据模型的需要而来的。当然我们也可以灵活使用卷积层+卷积层,或者卷积层+卷积层+池化层的组合,这些在构建模型的时候没有限制。但是最常见的CNN都是若干卷积层+池化层的组合。
在若干卷积层+池化层后面是全连接层(Fully Connected Layer, 简称FC),全连接层其实就是我们前面讲的DNN结构,只是输出层使用了Softmax激活函数来做图像识别的分类,这点我们在DNN中也有讲述。
在图像处理中,往往把图像表示为像素的向量,比如一个1000×1000的图像,可以表示为一个1000000的向量。如果在全连接神经网络中,如果隐含层数目与输入层一样,即也是1000000时,那么输入层到隐含层的参数数据为1000000×1000000=10^12,这样就太多了,基本没法训练。所以图像处理要想练成神经网络大法,必先减少参数加快速度。
卷积神经网络有两种神器可以降低参数数目,第一种神器叫做局部感知野。一般认为人对外界的认知是从局部到全局的,而图像的空间联系也是局部的像素联系较为紧密,而距离较远的像素相关性则较弱。因而,每个神经元其实没有必要对全局图像进行感知,只需要对局部进行感知,然后在更高层将局部的信息综合起来就得到了全局的信息。假如每个神经元只和10×10个像素值相连,那么权值数据为1000000×100个参数,减少为原来的万分之一。而那10×10个像素值对应的10×10个参数,其实就相当于卷积操作。
但其实这样的话参数仍然过多,那么就启动第二级神器,即权值共享。在上面的局部连接中,每个神经元都对应100个参数,一共1000000个神经元,如果这1000000个神经元的100个参数都是相等的,那么参数数目就变为100了。
怎么理解权值共享呢?我们可以把这100个参数(也就是卷积操作)看成是提取特征的方式,该方式与位置无关。这其中隐含的原理则是:图像的一部分的统计特性与其他部分是一样的。这也意味着我们在这一部分学习的特征也能用在另一部分上,所以对于这个图像上的所有位置,我们都能使用同样的学习特征。
更直观一些,当从一个大尺寸图像中随机选取一小块,比如说 8x8 作为样本,并且从这个小块样本中学习到了一些特征,这时我们可以把从这个 8x8 样本中学习到的特征作为探测器,应用到这个图像的任意地方中去。特别是,我们可以用从 8x8 样本中所学习到的特征跟原本的大尺寸图像作卷积,从而对这个大尺寸图像上的任一位置获得一个不同特征的激活值。
卷积的例子可以配合动态的卷积过程来理解:
多维的例子在这: http://cs231n.github.io/assets/conv-demo/index.html
这里面输入是3个7x7的矩阵。实际上原输入是3个5x5的矩阵。只是在原来的输入周围加上了1的padding,即将周围都填充一圈的0,变成了3个7x7的矩阵。这里用到了Zero Padding,每次激活时过滤器在前一层输入上移动的距离称为步幅,如果前一层的大小不能被过滤器接收场的大小和步幅的大小完全整除,那么接收场可能会尝试读取输入特征图的边缘。在这种情况下,可以使用诸如零填充之类的技术来发明用于读取的感知字段的模拟输入。
例子里面使用了两个卷积核,我们先关注于卷积核W0。和上面的例子相比,由于输入是3个7x7的矩阵,或者说是7x7x3的张量,则我们对应的卷积核W0也必须最后一维是3的张量,这里卷积核W0的单个子矩阵维度为3x3。那么卷积核W0实际上是一个3x3x3的张量。同时和上面的例子比,这里的步幅为2,也就是每次卷积后会移动2个像素的位置。
最终的卷积过程和上面的2维矩阵类似,上面是矩阵的卷积,即两个矩阵对应位置的元素相乘后相加。这里是张量的卷积,即两个张量的3个子矩阵卷积后,再把卷积的结果相加后再加上偏倚b。
7x7x3的张量和3x3x3的卷积核张量W0卷积的结果是一个3x3的矩阵。由于我们有两个卷积核W0和W1,因此最后卷积的结果是两个3x3的矩阵。或者说卷积的结果是一个3x3x2的张量。
仔细回味下卷积的过程,输入是7x7x3的张量,卷积核是两个3x3x3的张量。卷积步幅为2,最后得到了输出是3x3x2的张量。如果把上面的卷积过程用数学公式表达出来就是:
其中,n_in为输入矩阵的个数,或者是张量的最后一维的维数。Xk代表第k个输入矩阵。Wk代表卷积核的第k个子卷积核矩阵。s(i,j)即卷积核W对应的输出矩阵的对应位置元素的值。
对于卷积后的输出,一般会通过ReLU激活函数,将输出的张量中的小于0的位置对应的元素值都变为0。
在实际应用中,往往使用多层卷积,然后再使用全连接层进行训练,多层卷积的目的是一层卷积学到的特征往往是局部的,层数越高,学到的特征就越全局化。
在通过卷积获得了特征 (features) 之后,下一步我们希望利用这些特征去做分类。理论上讲,人们可以用所有提取得到的特征去训练分类器,例如 softmax 分类器,但这样做面临计算量的挑战。例如:对于一个 96X96 像素的图像,假设我们已经学习得到了400个定义在8X8输入上的特征,每一个特征和图像卷积都会得到一个 (96 − 8 + 1) × (96 − 8 + 1) = 7921 维的卷积特征,由于有 400 个特征,所以每个样例 (example) 都会得到一个 7921 × 400 = 3,168,400 维的卷积特征向量。学习一个拥有超过 3 百万特征输入的分类器十分不便,并且容易出现过拟合 (over-fitting)。
池化层就是对输入张量的各个子矩阵进行压缩。假如是2x2的池化,那么就将子矩阵的每2x2个元素变成一个元素,如果是3x3的池化,那么就将子矩阵的每3x3个元素变成一个元素,这样输入矩阵的维度就变小了。
下面这个例子采用取最大值的池化方法。同时采用的是2x2的池化。步幅为2。
首先对红色2x2区域进行池化,由于此2x2区域的最大值为6.那么对应的池化输出位置的值为6,由于步幅为2,此时移动到绿色的位置去进行池化,输出的最大值为8.同样的方法,可以得到黄色区域和蓝色区域的输出值。最终,我们的输入4x4的矩阵在池化后变成了2x2的矩阵。进行了压缩。
它们也有一个感受野,通常比卷积层小得多。而且,对于每次激活移动感受野的输入的步幅或数量通常等于感受野的大小以避免任何重叠。池化层通常非常简单,取输入值的平均值或最大值以创建自己的特征映射。
全连接层就是前馈神经网络层。这层可以具有非线性激活函数如softmax激活,以便输出类预测的概率。
在卷积和池化层执行特征提取和合并之后,在网络末端使用全连接层。它用于创建最终的非线性特征组合,并用于通过网络进行预测。
假设我们有一个灰度图像的数据集。每个图像具有32像素宽和32像素高的相同尺寸,并且像素值在0到255之间,也就是32x32x1或1024像素值的矩阵。
图像输入数据表示为宽度*高度*通道的三维矩阵。如果我们在示例中使用彩色图像,我们将有3个通道用于红色,绿色和蓝色像素值,例如32x32x3。
我们定义了一个卷积层,其中包含10个滤波器和一个5像素宽,5像素高,步长为1的感知域。
因为每个滤波器一次只能从(即“看”)5×5(25)像素输入,我们可以计算每个滤波器需要25 + 1个输入权重(偏置输入加1)。
以步幅宽度1在输入图像数据上拖动5×5感受野将导致每个图像具有28×28(32-5+1 = 28)个输出值或784个不同激活的特征图。
我们有10个滤镜,因此将为一个图像创建10个不同的28×28特征映射或7,840个输出。
最后,我们知道每个滤波器有26个输入,10个滤波器和28×28输出值来计算每个滤波器,因此我们的卷积层总共有26x10x28x28或203,840个“连接”。
卷积层还利用非线性传递函数作为激活的一部分,ReLU激活函数是常用的默认值。
我们定义了一个具有感知字段的池化层,其宽度为2个输入,高度为2个输入。我们还使用2的步幅来确保没有重叠。
这导致特征映射的大小是输入要素映射的一半。从10个不同的28×28特征映射作为输入到10个不同的14×14特征映射作为输出。
我们将对每个感知字段使用max()操作,以便激活是最大输入值。
最后,我们可以将方形特征映射平坦化为传统的平坦完全连接层。
我们可以用200个隐藏神经元定义完全连接的层,每个神经元具有10x14x14输入连接,或者每个神经元具有1960 + 1个权重。这一层共有392,200个连接和权重。
我们可以使用sigmoid或softmax传递函数直接输出类值的概率。
来自博客https://www.cnblogs.com/szxspark/p/8445406.html
图中的输入的数据维度为8,过滤器的维度为5。与二维卷积类似,卷积后输出的数据维度为8−5+1=4。
如果过滤器数量仍为1,输入数据的channel数量变为16,即输入数据维度为8×16。这里channel的概念相当于自然语言处理中的embedding,而该输入数据代表8个单词,其中每个单词的词向量维度大小为16。在这种情况下,过滤器的维度由5变为5×16,最终输出的数据维度仍为4。
如果过滤器数量为n,那么输出的数据维度就变为4×n。
一维卷积常用于序列模型,自然语言处理领域。
图中的输入的数据维度为14×14,过滤器大小为5×5,二者做卷积,输出的数据维度为10×10(14−5+1=10)。
上述内容没有引入channel的概念,也可以说channel的数量为1。如果将二维卷积中输入的channel的数量变为3,即输入的数据维度变为(14×14×3)。由于卷积操作中过滤器的channel数量必须与输入数据的channel数量相同,过滤器大小也变为5×5×3。在卷积的过程中,过滤器与数据在channel方向分别卷积,之后将卷积后的数值相加,即执行10×10次3个数值相加的操作,最终输出的数据维度为10×10。
以上都是在过滤器数量为1的情况下所进行的讨论。如果将过滤器的数量增加至16,即16个大小为10×10×3的过滤器,最终输出的数据维度就变为10×10×16。可以理解为分别执行每个过滤器的卷积操作,最后将每个卷积的输出在第三个维度(channel 维度)上进行拼接。
二维卷积常用于计算机视觉、图像处理领域。
这里采用代数的方式对三维卷积进行介绍,具体思想与一维卷积、二维卷积相同。
假设输入数据的大小为a1×a2×a3,channel数为c,过滤器大小为f,即过滤器维度为f×f×f×c(一般不写channel的维度),过滤器数量为n。
基于上述情况,三维卷积最终的输出为(a1−f+1)×(a2−f+1)×(a3−f+1)×n。该公式对于一维卷积、二维卷积仍然有效,只有去掉不相干的输入数据维度就行。
三维卷积常用于医学领域(CT影响),视频处理领域(检测动作及人物行为)。
笔、面试的时候常考到的知识点,计算卷积之后的输出维度
在卷积操作中,过滤器(又称核)的大小通常为奇数,如3x3,5x5。这样的好处有两点:在特征图(二维卷积)中就会存在一个中心像素点。有一个中心像素点会十分方便,便于指出过滤器的位置;在没有padding的情况下,经过卷积操作,输出的数据维度会减少。以二维卷积为例,输入大小 n×n,过滤器大小f×f,卷积后输出的大小为(n−f+1)×(n−f+1)。为了避免这种情况发生,可以采取padding操作,padding的长度为p,由于在二维情况下,上下左右都“添加”长度为p的数据。构造新的输入大小为(n+2p)×(n+2p) , 卷积后的输出变为(n+2p−f+1)×(n+2p−f+1)。如果有多个卷积核,则在输出上又要乘以卷积核的数目。如果想使卷积操作不缩减数据的维度,那么p的大小应为(f−1)/2,其中f是过滤器的大小,该值如果为奇数,会在原始数据上对称padding,否则,就会出现向上padding 1个,向下padding 2个,向左padding 1个,向右padding 2个的情况,破坏原始数据结构。
卷积中的步长大小为s,指过滤器在输入数据上,水平/竖直方向上每次移动的步长,在Padding 公式的基础上,最终卷积输出的维度大小为:
⌊⌋符号指向下取整,在python 中为floor地板除操作。
https://www.cnblogs.com/pinard/p/6494810.html 参考刘建平大牛的博客,很清晰地讲了CNN进行反向传播算法时与DNN不同的几个问题,以及这些问题是如何解决的。