在深度神经网络的领域下,卷积神经网络(Convolutional Neural Networks,以下简称CNN )是最为成功的DNN的应用之一,CNN广泛应用于图像识别领域,它也可以应用于NLP领域。
我们在图像处理中,往往把图像表示为像素的向量,比如一个1000×1000的图像,可以表示为一个 1 0 6 10^{6} 106的向量。在前面学习提到的神经网络中,如果隐藏层数目与输入层一样,即也是 1 0 6 10^{6} 106时,那么输入层到隐含层的参数个数为 1 0 6 × 1 0 6 10^{6}×10^{6} 106×106= 1 0 12 10^{12} 1012,这样参数就太多了,基本没法训练。
因此,我们如果想通过神经网络进行图像处理,必须考虑的问题就是,如何减少训练参数数量以加快收敛速度。CNN就是来解决这一难题的有效手段,它到底使用了哪些 m a g i c t r i c k s magic \;tricks magictricks 呢?我们赶紧进入CNN的学习之旅吧!
CNN最早是Yann LeCun在1998年提出来的,他首次简单展示了一个实例:应用反向传播和基于梯度的学习方法,来训练卷积神经网络。这对文档识别非常有效,尤其对邮政编码识别效果极好,因此这些方法在邮政服务中被广泛用于邮政编码识别。然而它并不能扩展到更具有挑战、更复杂的数据。数字非常容易识别,但识别也是有局限性的。
于是在 2012 年,Alex Krizhevsky 提出了一种现代化的卷积神经网络。他提出的网络,我们一般称为 AlexNet。但他的网络和 Yann LeCun 提出的卷积神经网络相比,看上去并没有多大差异。它们只是扩展的更大更深。更重要的一部分是它们可以充分利用大量数据可得到的图像(ImageNet 数据集),同时也充分发挥了 GPU 并行计算能力的优势。
因AlexNet在ImageNet数据集上的出色表现(拿下了当年大赛的第一名,且精度提高了好几个百分点),卷积神经网络开始大火,得到广泛的应用。
我们以LeCun在1998年发表的论文中,提到的LeNet-5的结构为例进行分析:
图中是一个字母识别的CNN模型,可以看出最左边的“K”的图像就是我们的输入层,这里我们输入的为灰度图(一个由0~255的数字组成的矩阵);
接下来箭头所指的是卷积操作,将输入层的矩阵,进行卷积之后,得到新的矩阵 。这一层我们称之为卷积层,我们可以先观看下面的动态图提前了解一下它到底干了些啥,后面会详细解剖此过程;
在卷积层之后,进行的是子采样(subsampling 或 downsampling)操作,当然我们更为常见的叫法是池化(pooling)操作(个人觉得子采样更好理解有木有-.-),卷积层经过池化之后,同样也是生成几个小矩阵,特征维度进一步缩小,这一层我们称之为池化层,同样可以先看看下面的动态图,之后再详细展开说明;
“卷积层+池化层”的组合,可以在隐藏层出现多次,当然,我们也可以灵活使用“卷积层+卷积层”,或者“卷积层+卷积层+池化层”的组合,这些在构建模型时没有限制,根据项目的实际需要,可自行配置,不过最常见的还是卷积层+池化层的组合。
在若干“卷积层+池化层”的组合之后,是全连接层(Fully Connected Lay,简称FC),它把上一层得到的所有矩阵,展开(reshape)成一个一维列向量,然后再喂给Softmax激活函数(或其他函数),最终的输出就是我们预测它是哪一个字母(我猜测这里应该就是一个26维的one-hot向量)。
个人感受:
在之前学习集成学习的stacking框架的时候,有人说“stacking和神经网络一样,都属于表示学习(representation learning)”,即从原始的特征空间中,使用一定的手段,提取出有效的特征,然后进行训练。这一做法既提升了模型预测的精度,又降低了特征的维度,缩短了训练时长。
现在看来,CNN就是完美地发扬了这一理念啊,前面不断地进行卷积+池化,为的就是展开得到关键特征向量,然后喂给最后的全连接层。为了防止过拟合,我们在全连接层应该尽量选用比较简单的模型,如Softmax进行多分类预测。
2019/7/1补充:
[我们知道,机器学习的实质过程就是 从原始样本提取出由关键特征表示的列向量,再把这个列向量喂给学习器进行训练,当损失最小时,对应的模型参数,即为我们求解的模型。
站在这个角度,卷积神经网络的做法也就好理解了,原始样本(image)是以矩阵的形式存储的,如果直接展开成一维向量,那么作者认为会损失了数据的结构信息,换句话来说,原始样本自带的结构,在作者看来也是一个重要的特征!
但是图片的特征维度太高了,训练起来速度会很慢,那么有没有什么办法,既可以降维,又可以提取出样本的结构信息呢?作者便提出卷积(之后再激活)加池化的神经网络思想,卷积和池化其实换另一种表达更加贴切,filtering(+ReLU) and downsampling 。最终可以将原始的图片样本,转换成一个列向量,交给学习器训练。]
关于卷积层的分层,有两种不同的观点:
(1)卷积层是由复杂的、三个阶段的子层组成的
(2)卷积层是简单的,仅仅是包含卷积运算,这是目前流行的观点
下面这张图可以完整诠释上面这一段话的过程。
我们人眼观测到的图像,是根据物体的反光得到的,那么在计算机中,图像是如何存储与表达的呢?
我们可以将上述的输入矩阵,从左到右,从上到下展开成一个很长的列向量,喂给一个分类器(如SVM)进行训练,也可以取得不错的预测准确率,但是这样的话,会失去平面结构的信息,为保留该结构信息,通常选择矩阵的表示方式。
当然,真实世界中,我们看到更多的是彩色图像,即基于RGB颜色模型生成的图像。相信大家在小时候都知道,三原色指的是红绿蓝,这三种颜色以不同比例叠加在一起,可以生成各种各样的颜色。
基于这个原理,我们在计算机中,存储“彩色图像”,就需要用到三个矩阵,三个矩阵叠加在一起,即可表示任何一张图像,如下图所示:
在进行识别“数字长方体”之前,我们必须清楚这么一个概念,即我们的模型,必须要满足不变性。
所谓的不变性,就是一个图像中的一个物体,不管在图像中的什么位置,还是经过旋转、缩放、光线明暗变化等操作变换,都可以被我们的模型识别为同一个物体!
为了理解卷积神经网络对于这些不变性特点所作出的突出贡献,我们先用不具备不变性特点的前馈神经网络来进行对比。
以灰度图(width=4,height=4,depth=1)来举例,在下图中,黄色圆表示值为0的像素点,黑色圆表示值为1的像素点,我们知道不管这个“横折”出现在图片中的什么位置,它都应该被视作是相同的“横折”。
若训练前馈神经网络来完成该任务,那么原图像的三维张量将会被摊平成一个向量,即(4, 4, 1)的图片会被展成维度为16的向量作为网络的输入层。再经过几层不同节点个数的隐藏层,最终输出两个节点,分别表示“有横折的概率”和“没有横折的概率”,如下图所示:
下面我们以十六进制对图片中的每一个像素点(pixel)进行编号。如果仅仅使用右侧那四组物体位于中间的训练数据来训练网络时,网络就只会对编号为5,6,9,a的节点的权重进行调节。若让该网络识别位于右下角的“横折”时,则无法识别。
【 解决办法 】:使用大量的、物体位于不同位置的图像数据进行前馈神经网络的训练,另外加深隐藏层的数目,从而扩大网络学习这些变体的能力。
【 缺点 】:这么做的确可行,但是效率十分低下,因为同一个“横折”,只是处在图像中的位置不同,但实际上还是同一个东西啊。那为什么相同的东西在位置变了之后还要重新学习呢?有没有什么方法可以让我们在某个位置所学到的规律也运用在其他的位置?换句话说,我们希望能在不同的位置使用相同的权重进行学习。
卷积神经网络就是让权重在不同位置共享的神经网络,如何理解这句话,请继续往下看。
在卷积神经网络中,我们先选择一个固定大小的局部区域,然后用这个局部区域去扫描整张图片。 局部区域所圈起来的所有节点会被连接到下一层的同一个节点上。
2019/7/1补充:
[有的地方,将局部连接这个性质,称为稀疏交互(Sparse Interaction)。在前馈神经网络中,任意一对输入与输出神经元之间都产生交互,形成稠密的连接结构;而在卷积神经网络中,卷积核的尺度远小于输入的维度,这样每个输出神经元仅与上一层特定局域区域内的神经元存在连接。
具体来讲,假如网络中相邻两层分别具有 m m m和 n n n个神经元,那么全连接网络中的权值参数矩阵的参数个数为 n × m n×m n×m;对于稀疏交互的卷积网络,如果卷积核的元素数为 k k k,那么该层的参数总量为 n × k n×k n×k。
在实际应用中,一般k值远小于m即可取得不错的效果,并且优化过程的时间也减少了几个数量级,过拟合的情况也得到了改善。]
为了更好的和前馈神经网络做比较,我们依然把这些以矩阵排列的节点展成向量的形式,并进行编号。下图展示了被红色方框所圈中编号为0,1,4,5的节点是如何通过 w 1 , w 2 , w 3 , w 4 w_1,w_2,w_3,w_4 w1,w2,w3,w4连接到下一层的节点0上的。
这个带有权重的红色方框就叫做 filter 或 kernel 或 feature detector(特征探测器) 。filter 的大小叫做 filter size,下面所展示的 filter size 为 2x2: [ w 1 w 2 w 3 w 4 ] \left[ \begin{array}{ll}{w_{1}} & {w_{2}} \\ {w_{3}} & {w_{4}}\end{array}\right] [w1w3w2w4] 在下一层中,定义第0个节点的值为 y 0 y_0 y0,它等于被圈中的小矩阵与 filter 矩阵对应位置元素相乘之后的累加和,当然,必不可少的还要加上一个 bias 项(理由在前面的文章中解释过),具体计算式如下: y 0 = x 0 ∗ w 1 + x 1 ∗ w 2 + x 4 ∗ w 3 + x 5 ∗ w 4 + b 0 y 0 = [ w 1 w 2 w 3 w 4 ] ⋅ [ x 0 x 1 x 4 x 5 ] + b 0 \begin{array}{l}{y_{0}=x_{0} * w_{1}+x_{1} * w_{2}+x_{4} * w_{3}+x_{5} * w_{4}+b_{0}} \\\\ {y_{0}=\left[ \begin{array}{llll}{w_{1}} & {w_{2}} & {w_{3}} & {w_{4}}\end{array}\right] \cdot \left[ \begin{array}{c} {x_{0}} \\ {x_{1}} \\ {x_{4}} \\ {x_{5}}\end{array}\right]+b_{0}}\end{array} y0=x0∗w1+x1∗w2+x4∗w3+x5∗w4+b0y0=[w1w2w3w4]⋅⎣⎢⎢⎡x0x1x4x5⎦⎥⎥⎤+b0
稀疏交互(局部连接)的物理意义
通常图像、文本、语音等现实世界中的数据都具有局部的特征结构,我们可以先学习局部的特征,再将局部的特征组合起来,形成更复杂和抽象的特征。以人脸识别为例,最深层(靠近输出层)的神经元可以检测出各个角度的边缘特征,位于中间层的神经元,可以将边缘特征组合起来,得到鼻子、嘴巴、眼睛等复杂特征;位于
当 filter 扫到样本矩阵中的其他位置时,计算输出节点 y i y_i yi 时, w 1 , w 2 , w 3 , w 4 , b 0 w_1,w_2,w_3,w_4,b_0 w1,w2,w3,w4,b0都是共用的。
参数共享的物理意义,就是我们前面提到的不变性,即一个图像中的某个物体,不管它处于什么位置,还是经过了旋转、缩放、光线明暗变换等操作,都可以被模型识别为同一个物体。
上一小节的介绍中,我们为了理解方便,所以把输入矩阵换成了列向量的形式,卷积之后的矩阵,也展开成了列向量的形式,前面说过,向量表达会丢失了平面结构信息,因此我们依然以矩阵的方式来排列它们,如下图所示:
经过卷积操作之后,生成的新矩阵,我们一般称为 Feature Map 或者 Convolved Feature.
经过前面的学习,我们已经知道了depth=1的灰度图,应该如何进行卷积操作了,那么对于更常见的3 channels的RGB图,如何进行卷积呢?
不妨想象一下,你的面前放着一个三阶魔方,如果你还是像刚才那样,用一个 2×2 的 filter 进行扫描,我们的filter只能在一个平面上移动,那你每次只能扫描到其中的一层,另外的两层,你没办法同时扫描到。
解决办法很简单,我们增加 filter 的 depth 即可,即在原来的 filter 的底下,再增加两个 2×2 的 权重矩阵,即我们现在的 filter size 变成了(2,2,3),在空间中也变成了一个长方体了。
另外需要再提一下的是, filter 的每一层的权重矩阵是共享的,但是层与层之间的权重矩阵是不共享的,即 filter 由三个大小相同但是值不同的权重矩阵组成。 如下面所示: [ w r 1 w r 2 w r 3 w r 4 ] , [ w g 1 w g 2 w g 3 w g 4 ] , [ w b 1 w b 2 w b 3 w b 4 ] \left[ \begin{array}{cc}{w_{r 1}} & {w_{r 2}} \\ {w_{r 3}} & {w_{r 4}}\end{array}\right], \left[ \begin{array}{cc}{w_{g 1}} & {w_{g 2}} \\ {w_{g 3}} & {w_{g 4}}\end{array}\right], \left[ \begin{array}{cc}{w_{b 1}} & {w_{b 2}} \\ {w_{b 3}} & {w_{b 4}}\end{array}\right] [wr1wr3wr2wr4],[wg1wg3wg2wg4],[wb1wb3wb2wb4]
举例:一个(2,2,3)的filter,对RGB图片的第一个局部区域进行卷积计算的式子为:
y 0 = x r 0 ∗ w r 1 + x r 1 ∗ w r 2 + x r 4 ∗ w r 3 + x r 5 ∗ w r 4 y_{0}=x_{r 0} * w_{r 1}+x_{r 1} * w_{r 2}+x_{r 4} * w_{r 3}+x_{r 5} * w_{r 4} y0=xr0∗wr1+xr1∗wr2+xr4∗wr3+xr5∗wr4
+ x g 0 ∗ w g 1 + x g 1 ∗ w g 2 + x g 4 ∗ w g 3 + x g 5 ∗ w g 4 \;\;\;\;\;+\;x_{g 0} * w_{g 1}+x_{g 1} * w_{g 2}+x_{g 4} * w_{g 3}+x_{g 5} * w_{g 4} +xg0∗wg1+xg1∗wg2+xg4∗wg3+xg5∗wg4
+ x b 0 ∗ w b 1 + x b 1 ∗ w b 2 + x b 4 ∗ w b 3 + x b 5 ∗ w b 4 + b i a s \;\;\;\;\;\;\;\;\;\;\;\;\;\;+\;x_{b 0} * w_{b 1}+x_{b 1} * w_{b 2}+x_{b 4} * w_{b 3}+x_{b 5} * w_{b 4}+bias +xb0∗wb1+xb1∗wb2+xb4∗wb3+xb5∗wb4+bias
向量化表达即为:
y 0 = [ w r 1 w r 2 w r 3 w r 4 ] ⋅ [ x r 0 x r 1 x r 4 x r 5 ] y_{0}=\left[\begin{array}{llll}{w_{r 1}} & {w_{r 2}} & {w_{r 3}} & {w_{r 4}}\end{array}\right] \cdot\left[\begin{array}{c}{x_{r 0}} \\ {x_{r 1}} \\ {x_{r 4}} \\ {x_{r 5}}\end{array}\right] y0=[wr1wr2wr3wr4]⋅⎣⎢⎢⎡xr0xr1xr4xr5⎦⎥⎥⎤
+ [ w g 1 w g 2 w g 3 w g 4 ] ⋅ [ x g 0 x g 1 x g 4 x g 5 ] \;\;\;\;+\left[\begin{array}{llll}{w_{g 1}} & {w_{g 2}} & {w_{g 3}} & {w_{g 4}}\end{array}\right] \cdot\left[\begin{array}{c}{x_{g 0}} \\ {x_{g 1}} \\ {x_{g 4}} \\ {x_{g 5}}\end{array}\right] +[wg1wg2wg3wg4]⋅⎣⎢⎢⎡xg0xg1xg4xg5⎦⎥⎥⎤
+ [ w b 1 w b 2 w b 3 w b 4 ] ⋅ [ x b 0 x b 1 x b 4 x b 5 ] + b i a s \;\;\;\;\;\;\;\;\;\;\;\;\;\;\;+\left[\begin{array}{llll}{w_{b 1}} & {w_{b 2}} & {w_{b 3}} & {w_{b 4}}\end{array}\right] \cdot\left[\begin{array}{c}{x_{b 0}} \\ {x_{b 1}} \\ {x_{b 4}} \\ {x_{b 5}}\end{array}\right]+bias +[wb1wb2wb3wb4]⋅⎣⎢⎢⎡xb0xb1xb4xb5⎦⎥⎥⎤+bias
也就是说,原始样本为一个空间中的立方体,经过一个卷积核卷积之后,随后生成的是一个二维空间的矩阵!!!
最后观察下方动态图来直观理解depth维的卷积过程:
我们可能会想,4×4 的图像经过 2×2的 filter 卷积之后变成了 3×3 的图像,如果每次卷积之后都会缩小一圈的话,那不是经过若干次卷积之后,我们的图像变得越来越小了?
Zero padding就是用来解决这个问题的,它的作用就是控制 Feature Map 的输出尺寸,同时避免原始图像的边缘侧信息被一步步舍弃的问题。
例如,下面黄色区域是一个4x4的图像,我们在其边缘进行 Zero padding 一圈之后,再用3x3的 filter 进行卷积,最终得到的Feature Map的尺寸,将依旧是 4×4 。
通常大家都想要在卷积时保持图片的原始尺寸,常常选择3x3的filter和填充为1的zero padding,或5x5的filter和填充为2的zero padding。
另外,3x3的filter可以考虑像素点与其距离为1的所有其他像素点之间的关系,而5x5的filter则是可以考虑像素点与其距离在2以内的所有其他像素点的关系,因此,3x3 和 5x5 是卷积核的常用尺寸!
【拓展】卷积之后的 Feature Map 的 Size 计算方法
假设输入的图像 Size 为 (origin_width,origin_height),卷积之后的 Feature Map 的 Size 为(new_width,new_height),其实计算new_width和new_height的方式是一样的,这里以new_width为例进行分析:
【公式不在于记忆,而在于理解,下面是公式的具体理解过程】
首先呢,我们要计算 filter 可以在水平方向滑动的范围:
(1) x_range = origin_width + 2×padding_width - filter_width
公式很好理解,图像的原始宽度,加上我们零填充的宽度(因为是左右两边都要填充,所以要乘以2),于是得到了卷积之前的图像宽度,然后再减去卷积核 filter 的宽度,得到的就是我们可以水平滑动的总长度 x_range。
计算出可以滑动的总长度之后,我们用该值除以滑动的步长 stride,不就计算出来可以滑动的总次数了吗?然后在加上第一个不需要滑动也存在的输出节点之后,就可以得到最终 Feature Map 的 new_width 了,如下所示:
(2) new_width = x_range / stride + 1
最终,我们来一个大合并,Feature Map的尺寸计算公式如下:
(3) output_size = (input_size + 2×padding_size − filter_size)/stride+1
用上面的例子代入计算,input_size 为(3,3), padding_size 为1,filter_size 为(3,3),stride 为1,最终的 output_size 为:
o u t p u t _ s i z e = ( ( ( 4 + 2 ∗ 1 − 3 ) / 1 + 1 ) , ( ( 4 + 2 ∗ 1 − 3 ) / 1 + 1 ) ) = ( 4 , 4 ) output\_size =( ((4+2*1-3)/1 +1), ((4+2*1-3)/1 +1) ) = (4,4) output_size=(((4+2∗1−3)/1+1),((4+2∗1−3)/1+1))=(4,4)
经过前面几个小节的学习,我们已经知道了filter是如何工作的,那么你一定很好奇,Feature Map对应的图像,到底是什么样子的呢?
下面我们进行展示,不同参数设置下的 filter 对原始图像进行卷积之后,所生成的Feature Map的图像。
原始图像:
不同参数的 filter 卷积之后的图像:(面试可能会聊不同filter的作用是什么?)
滤波器可以从原始的像素特征中抽取某些特征,如:边缘、角度、形状等,以sobel算子为例:
K v = [ − 1 0 + 1 − 2 0 + 2 − 1 0 + 1 ] K h = [ + 1 + 2 + 1 0 0 0 − 1 − 2 − 1 ] \mathbf{K}_{v}=\left[\begin{array}{rrr}{-1} & {0} & {+1} \\ {-2} & {0} & {+2} \\ {-1} & {0} & {+1}\end{array}\right] \quad \mathbf{K}_{h}=\left[\begin{array}{ccc}{+1} & {+2} & {+1} \\ {0} & {0} & {0} \\ {-1} & {-2} & {-1}\end{array}\right] Kv=⎣⎡−1−2−1000+1+2+1⎦⎤Kh=⎣⎡+10−1+20−2+10−1⎦⎤
其中 K v \mathbf K_v Kv表示检测垂直边缘的滤波器,它沿着水平方向做卷积; K h \mathbf K_h Kh表示检测水平边缘的滤波器,它沿着垂直的方向做卷积。
原始灰度图:
经过 K v \mathbf K_v Kv卷积之后:
经过 K y \mathbf K_y Ky卷积之后:
举上面的例子呢,是希望能够更直观地理解 f i l t e r filter filter 被称为滤波器的原因。
个人学习感受,卷积核 filter 的训练,实际上就是根据我们想要识别什么 target ,然后用大量的图像数据进行训练,最终得到一个可以过滤掉与 target 无关的像素点,留下与 target 相关的像素点的 filter !最终教会神经网络模型,它应该以什么的方式,来“观察”图像。
还有一点值得说明的是,上面的两个例子,是在第一次卷积之后,Feature Map 的输出图像,这个时候我们还是可以看清原图的形状和轮廓的,不过随着卷积操作的不断深入,越里面的卷积层,所抓取的信息越来越抽象,解释性越来越弱。 比如说,下面这个手写体数字识别的例子:
每个 filter 可以抓取探测特定的形状的存在。 假如我们要探测下图的长方框形状时,可以用4个 filter 去探测4个基础“零件”。
因此,我们在实际进行CNN的训练中,一般需要设置多个不同的 filter。不同的 filters 扫描过后可得到不同特点的 Feature Maps 。 每增加一个 filter,就意味着你想让网络多抓取一个特征。
由此一来,我们卷积层的输出,将不再是一个平面上的矩阵,而是一个空间中的长方体! 如下图所示:
在前面的讲解中,我们已经使用了一个 filter 进行了扫描,得到了卷积层中,最上层的黄色矩阵,这里分别用了紫色的filter、蓝色的filter、棕色的 filter再次进行扫描,依次生成了紫、蓝、棕色的矩阵,最终得到的是一个长方体!
卷积层的输入是长方体,输出也是长方体,这个长方体可以作为新的输入,送给下一个卷积层进行处理。
【拓展】卷积之后的 “长方体” 的 Size 计算方法
其实上面的图已经很形象的展示了,width 和 height 的计算方法还是不变的,depth 的值,其实就是 filter 的个数 ,这一点也毋庸置疑了,附上一张cs231n上的总结。
像前面学过的深度神经网络一样,我们把上一层的输入加权求和之后,会进行一个激活操作,当时推荐的是ReLU激活函数,然后再将值传给下一层。这种非线性的转换,有利于提升网络的稳健性,并防止过拟合。
同样,我们在卷积神经网络中,对于得到的Feature Maps(多个卷积后的特征矩阵),也要进行非线性转换(ReLU函数),它是一个 element-wise 的操作,对 Feature Map 矩阵中的每一个元素进行ReLU激活。
为什么叫非线性转换呢?大家可不要学着学着就忘了,本文的前面有过详细的图解,我们卷积层的每一个元素,都是上一层的矩阵中的某几个和 filter 中的每一个元素进行加权求和,最后再加上一个bias项得到,这不就是一个线性转换的过程吗?咱们再把这个值喂给ReLU函数,最终我们得到的值,和上一层的矩阵中的那几个元素,就不再具有线性对应关系了,所以这就叫做非线性转换呀~
附上一张经典图解释上述的过程:
在前面所说的 卷积 + ReLU 操作之后,还会有一个 pooling 操作,一般有 max pooling 和 average pooling,这里以最受欢迎的 max pooling 为例进行说明。
其实 max pooling 的原理很简单,将整个图像划分出若干个大小相等并且无重叠部分的小块,每一个小块只取其中最大的数字,再舍弃掉其他的节点,并保持原来的平面结构输出,如下图所示:
需要注意的是,max pooling 操作在不同 depth 的平面上是独立执行的,即每次只能从当前平面内的某一小块中选择最大值,并舍弃当前小块内的其他节点,如下图所示:
【问题】max pooling 到底有什么作用?节点信息被舍弃后,难道没有什么影响吗?
从直觉上来说,我们人类在观察某张图片的时候,只有特定区域的像素点对于我们而言是有效的,而图像中其他的像素点,实际上是冗余信息,对于我们的判断起不了什么作用。max pooling 的主要功能是 downsampling,就是用来去除 Feature Map 中的冗余信息(或者说像素点、特征)。
如下图所示,我们输入的是三个 4×4 矩阵可知,它们代表的都是一个物体(横折),只是出现的位置不同,那么我们期望,模型最终学习到的特征,应该尽可能一致。之后我们用一个 2×2 的 filter 分别对三个输入矩阵进行扫描,生成的每一个 Feature Map 都是一个 3×3 的矩阵。此时我们再用 3×3 的 max pooling kernel 对 Feature Map 进行 pooling 操作的话,每一个 Feature Map 的最终输出都是 3 ,符合我们的期望效果。
上面的例子,粗略地展示了 max pooling 可以用来剔除冗余信息的作用,当然,实际情况肯定比这更加复杂,我们不用 max pooling 操作,最终肯定也可以让神经网络学习并判断图像中是否有“横折”,但是计算的代价比较大,max pooling 虽然是一种近似效果,但是减少了训练的参数,甚至还起到了一定的防止过拟合的效果!
当然咯, max pooling 并不是有百利而无一害,也有可能出现这么一种情况,某些周边信息对我们想要抓取的概念是否存在的判定也有一定的影响,但是被我们给过滤掉了。
当抓取到足以识别图像的特征之后,接下来就是如何进行分类。全连接层(简称FC),这一层负责处理输入内容(该输入可能是卷积层、ReLU 层或是池化层的输出),并最终输出一个 N 维向量,N 是该程序必须选择的分类数量。
我在这一开始有一个错误的认识,我以为全连接层,就是把前面卷积、池化得到的长方体,平摊成一列长向量,然后再喂给一个分类函数(如Softmax)进行分类的预测,这个想法不太正确,我们所说的全连接层,不是说只有一层神经网络,而是一个全连接的神经网络(前馈神经网络),它的输入是前面说的长向量,经过前馈神经网络训练,最终得到模型的输出。
下面这个图,就十分简单而形象地展示了CNN的整个预测过程:
多啰嗦几句,讲到全连接层这里,它其实也呼应了我在文章前面谈到的感受,卷积神经网络的前面很多层网络,它的核心功能就是特征提取,最后简单几层网络用来模型的预测与输出,全连接层的神经网络一般比较简单,不会太深,我也提到过,太复杂的话,就会导致整个神经网络过拟合了!