深度学习之卷积神经网络
引言
卷积神经网络其实是全连接神经网络的一个简化版,CNN通常用在图像识别上面。通常把图像当成矩阵来看待,而机器就告诉你这个图片的内容是什么,下图是一只鸟。
为什么用CNN来识别图像
为什么要用CNN呢,因为直接用全连接神经网络来识别图像效率不高
部分模式比整个图像小得多。
可能在第一个隐藏层中有某个神经元是检测有没有鸟嘴这样的模式,如果检测到了,它就会有一个很大的输出,交给后面的神经元来决定这是否为一只鸟。但是检测鸟嘴其实是不需要整张图片的,它只需要检测上面红框框出来的很小的区域就知道这是否是一个鸟嘴。
因此,只需要把这一小部分给这个神经元,这样和整个神经网络相比只需要更少的参数来做这件事情。
同样的模式可以出现在不同的位置。
但是像鸟嘴这个模式可能会出现在图像的不同位置,而它们的形状是一样的,用同一组参数的同一个神经元就可以检测出来。
上图,左上角的鸟嘴和出现在中间的鸟嘴是一样的,这样只需要一个专门检测鸟嘴的神经元即可,不需要给不同的位置不同的神经元来检测。
缩小图像(subsampling)并不会改变图像里面的内容
这里的缩小图像做法是例如拿掉奇数列和偶数行,变成原来大小的1/4,还是可以看出来里面是什么东西。
这三个理由都是为了使神经网络的参数变少。
CNN的架构
如上图,假定这是识别这幅图像里的内容是猫还是狗。
输入图像,然后经过卷积层(Convolution Layer),再通过最大值池化(Max Pooling),反复进行这两个步骤。最后进行Flatten,然后再丢到全连接网络中,最后得到分类结果。
要注意的是上面的整套从输入到输出是可以同时一起训练的。
卷积考虑了部分模式比整个图像小得多和同样的模式可以出现在不同的位置这两个特性,而最大值池化考虑了最后一个缩小图像并不会改变图像里面的内容性质。
接下来看一下卷积这件事情
Convolution
假设输入的图像是由6x6矩阵所表示的,然后再卷积层中有一组Filter(过滤器),每个Filter就是一个矩阵,里面的参数是学出来的,像全连接网络的权重那样。
假设我们已经知道了这些参数,并且Filter的大小是3x3,该大小是可以自己设计的。假设你设计的是3x3,说明你认为这些模式(比如说鸟嘴)的大小是小于3x3的,它们可以用3x3的Filter识别出来。
现在假设我们有一个Filter,它的数值是这样,那这个Filter怎么用在这个图像上呢,把这个Filter放在图像的左上角。
这个Filter中的9个值和它框住的图像中的9个值进行矩阵内积(inner product)运算,得到的结果是。
接下来会移动这个框框位置,移动的距离叫stride,假设这里stride=1
就会变成上面这样,然后得到的结果是,假设stride=2,就是往右移动两格,得到的结果就是
这里假设我们把stride设成1,然后我们依次移动并计算,最后算出来的结果是这样:
如果你仔细观察这个Filter,会发现它的特定是斜对角线上的值都是1,所以它检测的模式是是否存在斜对角都是1的模式。
如果符合这个模式,那么它们的内积运算的结果就会比较大。
我们可以发现,左上角和左下角的值都比较大,也就说明在原来6x6的图像中,左上角和左下角的位置符合这个模式。
并且同样的模式出现在该图中不同的位置。这就是同样的模式可以出现在不同的位置。
这里假设我们还有一个Filter2,它的参数是这样的。
假设它的stride也设成1,我们用蓝框表示这个Filter,它的处理过程和Filter1是一模一样的,只不过输出的值不一样。
最后会得到一个不同的输出值。经过这两个Filter之后,得到的东西叫做Feature Map。
可以把Feature Map想象成另外一张4x4的图像,并且新的图像每个像素有多个值来描述它。原来的6x6图像只有一个数值(0或1)来描述。
在我们的例子中,每个像素都有两个数值来描述。如果有500个Filter,那么就会有500个数值来描述一个像素。
上面我们的例子是黑白图像,只是通过灰度值来描述。那么如果是彩色图像呢,彩色图像的每个像素会有3个数值(r,g,b)来描述。
彩色图像和黑白图像唯一的不同就是Filter不一样,现在彩色图像的Filter是3x3x3的立方体,3个3x3的矩阵,就有27个参数。
上面我们为什么说卷积是全连接的一个简化版呢?
我们把上面的图像经过卷积后得到的输出想象成下面全连接网络的输出(绿框标注的)
把下面全连接网络的输出当成把Feature Map拉直(变成一维),就可以发现卷积是全连接的简化版?怎么说,继续往下看吧。
我们做卷积的时候,把Filter放到左上角,进行矩阵内积后,得到输出3。这件事情可以想象成是把6x6的二维图像矩阵,拉直变成36x1的一维矩阵,如上图右所示。
那么这个Fitler放到左上角,得到3等同于现在有一个神经元,这个神经元只连接到这36个输出的1,2,3,7,8,9,13,14,15的位置,它只连接了9个输入
而连接了这9个输入的权值,就是这个Filter中的9个值!
因为每个神经元只连接到部分的输入,所以参数量可以变少很多,所以说卷积是全连接的简化版本。卷积没有全连接,卷积是部分连接。
假设把Filter移动一格,对应全连接那边就会有第二个神经元,它的输出是,它也只连接了9个输入,但是我们可以发现它和第一个神经元存在共享的权值,上图可以用右边连接到神经元连线的颜色来区分。同样的颜色代表权值是一样的。
因为我们用的是同一个Filter,只是移动到不同的位置(输入就可能不一样,这样可能会得到不同的输出),这个Filter里面的值还是不变的,也就是权值参数不变。
这说明参数甚至还可以更少!
Max Pooling
现在从Filter1和Filter2中得到两个矩阵,而Max Pooling做的事情是把矩阵中的元素分组,比如4个一组,每个组里面选最大的。
比如上图做红色左上角那个分组中3最大,就把3留下来。
最后得到:
还有一种叫做Average Pooling的就是求组内元素的均值。
那么做了Max Pooling之后,就会得到更小的图像矩阵。
Convolution和Max Pooling可以重复做多次,可以把它们的结果又丢到Convolution中去,然后又可以得到新的Max Pooling结果…
每个像素用几个数值代表有几个channel。
做完这些之后,接下来做的事情是Flatten。
Flatten
它做的事情是把上面两个过程得到的输出矩阵拉直变成一维的。
然后就丢到全连接神经网络中。
分析神经网络的结果
在我们训练完一个神经网络后我们该如何分析它所得到的结果。
假设给机器这个图片,它可能会说这是球鞋,也可能会说是美洲狮。PUMA的标志中有个美洲狮!
所以我们想要分析下网络的结果。有很多不同的方式,下面举几个例子。
可以把第一层的Filter的参数拿出来,看现在网络得到什么样的东西。
上面的一些Filter是检测有有没有某种条纹的模式,下面的一些Filter是检测有没有某种颜色的存在。
但通常只有第一层的Filter可以拿出来看,因为后面层的Filter是拿前面层的输出作为输入的。要考虑第一层的Filter才知道后面的Filter在做什么。
但是可以用别的方式来分析它。
比如把某个神经元拿出来,把某个Filter在某个位置的输出拿出来。然后把这些图像都丢到神经元中去,看它什么时候**值最大。
就知道这个神经元在做什么。
白框就是这个Filter所看的区域,因为它是一个高层的Filter,所以看的范围也比较广,可以看到第一行对应的Filter可能是在检测人的上半身。
还有其他分析的方法。
假设我们训练了一个数字识别网络,我们想知道第二层的Filter做的事情是什么。
假设第K个Filter的输出是11x11的矩阵。
我们定义了第k个Filter的**程度这么一个东西。
这个**程度就是把所有的数值加起来,然后用表示第k个filter的**程度。
接下来想找一个28x28的矩阵所描述的图像x
,丢到这个网络后得到的的值最大者,得到。
这件事情可以用梯度下降来做,只要能计算即可是矩阵中行列所表示的元素值。
我们要找一个,能使得最大。
然后得到的结果时这样的,这里只取了12个filter。
这些图的意思是,如果把这个图丢到网络中会使得第一个filter的**程度最强。
也可以分析全连接网络的部分。
就是看能不能找到一张图像使得某个隐藏层的神经元输出最大。
假设得到的结果时这样,我们都看不懂就对了。
那如果把最后一层的神经元拿出来会得到什么样的结果,我们能看到数字吗?
实际结果我们还是看不懂!
比如机器觉得第一张图片99.99%是零。
还有一种我们看的懂的方式是用一个类似马赛克的东西不停的遮住图像中的某块,看遮住哪块机器就无法正确分类,就可以知道机器主要观察的是哪部分。
比如上图左遮住了狗的眼睛和鼻子部分,下面对应的图片蓝块区域说的是遮住这部分就分辨不出来。这就合理一些了。上面识别汽车轮胎,把轮胎那部分区域遮住就当然分辨不出来了。