CNN是非常经典的用于图片识别的一种神经网络架构。在CNN提出以前,用NN进行图片识别是一项艰巨的任务,若直接把图片按像素值展开作为网络的输入,会造成参数数量非常大,减少计算量的一种方法是人工提取特征,但这样做又失去了NN的优势。CNN则根据图片识别任务的特殊性简化了网络架构,减少了参数,取得了很好的效果。
图片识别任务有三个特点:
当我们识别一张图片是不是鸟的图片时,我们希望提取的特征可能包括鸟嘴、爪子、尾巴等,而这些特征只是图片的一小部分,我们没有必要把整张图片的所有像素点与负责提取某个特征的神经元相连。
当我们识别一张图片是不是鸟的图片时,鸟嘴、爪子、尾巴等特征可能出现在图片的任何位置,上图两张图片中的鸟嘴虽然位置不同,但应该都可以使用相同的神经元进行提取,也就是说我们用一组参数(与某个神经元相连)可以从图片的不同部分提取出相同的特征。
最后就是,当我们对一张图片中的像素点按照某种规则进行采样时,并不会影响我们对整张图片的识别。比如我们去掉一张图片中的奇数行像素点和偶数列像素点,并不会影响我们对图片的识别,而图片大小却变成了原来的四分之一,这样可以有效减少参数。
CNN架构就是基于以上三个特点提出的。卷积层对应前两个特点,池化层对应第三个特点。当我们进行了一系列的卷积和池化操作后,提取出的特征再作为一个全连接网络的输入,最后得到分类结果。
可以看到,卷积层含有多个filter,每个filter大小都是相同的,且filter中的参数就是我们需要学习的权重。可以看出,每个filter都可以看作是对一个小区域的特征识别(这里是33)。
每个filter按一定的stride沿图片移动,得到的卷积值形成一个新的矩阵。从图片中可以看到,若把filter1作为提取“右斜线”的神经元的权重的话,那么它可以从图片的不同位置探测到“右斜线”特征。
把每个filter当作一个神经元的权重的话,我们可以很方便地将CNN与Fully-connected NN做比较。
可以看到,当我们把一张图片的像素展开向量作为网络输入的时候,33的filter对应的神经元实际上只有9个权重分别与图片的1、2、3、7、8、9、13、14、15号像素点相连,而不是与全部的1~16号像素点相连,这大大减少了参数的数量。
当filter沿图片移动的时候,新的神经元的权重依然是之前的9个参数,只是连接的像素点变成了2、3、4、8、9、10、14、15、16。这实际上就是所谓的参数共享,进一步减少了参数数量。
而Max Pooling层在各个filter得到的结果基础上又进一步减少了参数数量。
具体的参数数量有多少呢?我们看一个实际操作的例子:
输入是12828的图片,1表示像素只表示黑白,若是彩色则有RGB三个channel。
第一个卷积层有25个33的filter,因此一共有2533=225个参数。卷积后的结果是252626的张量。
第一个池化层是22的,因此池化后结果为251313的张量。
第二个卷积层有50个2533的filter,因此一共有502533=11250个参数。卷积后的结果是501111的张量。
第二个池化层是22的,因此池化后结果为5055的张量。
这里需要理解清楚的是,filter可以是多层的。如上图所示,彩色图片是有RGB三个channel的,因此我们的filter就是333的。这个filter在图片上平移时每个卷积实际上是计算三层卷积的和,也就是27个乘积的和。这一点理解清楚了,卷积网络的参数个数就一目了然了。
说了这么多CNN的简单之处,它到底可以从图片中学到什么呢?
CNN学到了什么东西呢?最直接的想法是把各个层的输出还原成图片就行了呗,第一层确实如此,因为是直接把33的像素区域进行某种处理得到的特征,但第二个卷积层的输出呢,因为其输入并不是像素点,而是某些由多个像素点变换得到的点,因此输出可能并不是一个可以看出明确意义的特征。
这里采用的方法是,我们固定网络的权重,设定目标为某一个filter得到的输出矩阵的元素和最大(也就是这个提取特征的神经元被激活的程度最大),然后不断调整输入来达到这个目标。这样最后得到的就可以视作这个神经元提取出的特征。
可以看到,这些特征图片具有某种有规律性的纹路,但是我们并不能明确看出这些特征代表的意义,也就是说,其实机器理解图片的方式很可能和人类不太相同。
另一个更加明显的例子是手写数字识别:
上述图片分别表示数字的特征,这在人类看来就是一片雪花,但是把这样的图片作为输入喂给CNN,输出分类结果就是,这说明CNN也是容易受到欺骗的。
网友评论