写在前面:
最近在读FCN的论文,整理一下自己看文献得到的想法,记录一下。主要是想敦促一下自己整理一下知识。知识来源的话基本都会附链接。内容比较乱,只是想从原文里提取出来一些个人认为比较关键的知识点。由于很多东西作为小白和数学渣渣的我也没有完全理解透,所以只是做一个思路的整理。
本文只是将原文的一些主要的、个人觉得有意义的工作整理了出来,只能通过本文了解到FCN的一些大概,若是想在细节上研究请参考大佬们的理解和原文。
原论文链接:https://arxiv.org/pdf/1411.4038.pdf
总体理解:
首先FCN是应用在语义分割领域内的经典结构。在当时的主要优势是具有端到端的训练方式,另一方面,可以接受任何尺寸的数据输入,并输出相应大小的输出。(在原文的摘要里提到)。作者说FCN到底有多优秀,这些就没必要赘述了,毕竟不优秀也不会成为语义分割领域内的经典框架,那FCN到底优秀在哪儿?
个人之见:
一、FCN与CNN之间的联系与区别
用于分类的“传统”CNN由卷积层,池化层,全连接层构成。图像以矩阵的形式输入,经过不断的卷积和池化,尺寸逐渐缩小(文中称之为subsampling),最后将提取到的 高层的(higher layers)、粗糙的(coarse)、语义(semantic)信息输入进全连接层,经过处理得到特征向量,继续处理能够得到表示当前图片类别的类别向量,进而判别当前输入图像的类别。
而对于语义分割任务来说,单纯知道输入图像整体的场景类别(用词可能不当,个人习惯。)是不够的。语义分割任务的理想目的是能够得到输入图像的每一个像素的类别,也即像素级预测。FCN的作者的大概……可能……是觉得,既然需要每一个像素都预测一个类别,那就不要把经过卷积池化操作得到的特征图变成特征向量了(由全连接层得到,一维向量),就直接把提取到的特征图继续输出出来,然后在特征图上预测不好么?
既然将特征图转变成特征向量的工作是由全连接层完成的,那么就修改全连接层的工作,让它继续输出特征图就ok了嘛(当然只是说说简单而已)。FCN的作者将最后的全连接层都改成了卷积层,这样可以继续保持特征图的输出,其他的网络结构并没有变化(在最开始没变化而已,之后会添加一些结构,用以让网络更好地实现dense prediction)。简单理解一下的话,假如保持原来的全连接层的维度,4096,即经过下图的第一个全连层输出的应该是一个4096维的向量,设置该层卷积核的尺寸为1×1,卷积核的深度仍然为4096,这样就将原来输入进来的特征图还是以原尺寸输出(在步长为1的情况下),只是深度变成了4096。这样就保证了特征图的二维属性(原文中称最后的结果为heatmap),继而保留了空间特征,而非将它们都变成了一维的特征向量。其实暂且可以简单理解为一张标注好的图像(当然,要针对该特征图进行预测(比如后接softmax)之后才能得到类别结果,另外此时的尺寸也依旧是经过了卷积池化的结果,尺寸还没有通过upsampling进行恢复)。
在这里插入一个原文提到的接受域(receptive fields)的概念,原文中的解释对于我来说有点晦涩难懂。。其实简单理解就是在经过了卷积池化的处理后,最后得到的feature map上的一个点,在原图像上对应的区域,就是这个点的receptive fields。不过我这憨批也不知道它到底表示了啥深意。
二、上采样(反卷积)
PS:原文中对该部分的功能也提到了一些其他的算法,不过并没有采用,因为效果都没有反卷积好,所以我也就没提。
通过将全连接层修改成卷积层,将一些比较经典的分类网络结构(如AlexNet、VGG-16)等修改成了其FCN的版本。原文中主要讲的还是VGG-16的版本。在修改完了之后,当前的结构就输出的不是一维的特征向量了,而是二维的heatmap了。但是目前来说,这个heatmap尺寸还是太小了,不足以完成像素级的预测任务。所以作者想把heatmap的尺寸变大。
上图中,21表示PASCAL VOC数据集的21个类别(包含背景),也即经过此层后,输出的特征图应该是具有21个通道的,每个通道表示了在其对应类别上的分类结果。之后红色箭头部分的操作,表示网络结构中的upsampling操作,即上采样(此处也可称为反卷积)。直观感受就是通过了反卷积操作,将当前的尺寸较小的heatmap变成跟输入图片尺寸一样的,即可实现对原图像的在像素级上的dense prediction。
原文中对反卷积的描述为:
大致意思就是,以 f (f为整数时)为因子的反卷积相当于是以 1/f (自然是小数咯)做正常卷积。其实这么说的话还是有点奇怪。所以还是决定找一些更贴近我更能理解的“人话”来理解一下。
反卷积具体步骤如下:
1 首先是将卷积核反转(并不是转置,而是上下左右方向进行递序操作)。
2 再将卷积结果作为输入,做补0扩充操作,即往每一个元素后面补0.这一步是根据步长来的,对于每个元素沿着步长方向补(步长-1)个0。例如,步长为1就不用补0了。
3 在扩充后的输入基础上再对整体补0。以原始输入的shape作为输出,按照前面介绍的卷积padding规则,计算pading的补0的位置及个数,得到补0的位置及个数,得到补0的位置要上下和左右各自颠倒一下。
4 将补0后的卷积结果作为真正的输入,反转后的卷积核为filter,进行步长为1的卷积操作。
上述原文链接:https://blog.csdn.net/chengqiuming/article/details/80299432
参考大佬们对反卷积原理的具体解释:
https://www.zhihu.com/question/48279880
https://blog.csdn.net/sinat_29957455/article/details/85558870
以上大佬们都对反卷积从数学原理到流程都进行了介绍。我肯定没人家说的好,就不一点一点截取了。
只是记录一点自己曾经在理解上的误区,csdn博客的https://blog.csdn.net/sinat_29957455/article/details/85558870大佬在文末也提及了。反卷积中的stride与正常卷积中的stride并不一样。
正常卷积中的stride表示每次计算,卷积核移动的像素数;
而反卷积中的stride表示在原图像上插入的0的个数(个数n = stride - 1)。
三、skip architecture(跳级结构??)
不知道咋翻译了,不过大致意思也就这样了。
论文中,作者认为,在通过网络结构提取特征的过程中,有两种information:一种是higher、coarse、semantic的,另一种是lower、finer、appearance的。这两种都具有一定的空间特征。原文提到,通过skip architecture将这两种信息结合起来,可以同时在局部预测和全局预测上都有提升。。
原文中讲述这部分是怎么来的呢。。先上图吧。。
(图中的黄色大致翻译为……池化和预测层表示成栅格,中间层即卷积层表示成竖线。。这句话我研究半天才看明白是对图里的东西解释一些而已……)反正原文的话我没理解得太透。。毕竟英语渣。
下图是知乎上的大佬的图:https://zhuanlan.zhihu.com/p/31428783
作者一开始直接就在预测结果之后进行了上采样,就得到了第一行的操作。此处是进行了32倍的上采样。发现效果一般。。不尽如人意。
所以后面就想要结合一下前面几层的信息,实现跨层信息的结合,也就是skip architecture。所以就一共出现了三个版本。
强调一点是,FCN的skip结构跨层融合信息时,采用了 相加 的方式。与U-Net有明显的不同。
来自同一个知乎大佬(文中也有对反卷积的工作做了解释):
- 对于FCN-32s,直接对pool5 feature进行32倍上采样获得32x upsampled feature,再对32x upsampled feature每个点做softmax prediction获得32x upsampled feature prediction(即分割图)。
- 对于FCN-16s,首先对pool5 feature进行2倍上采样获得2x upsampled feature,再把pool4 feature和2x upsampled feature逐点相加,然后对相加的feature进行16倍上采样,并softmax prediction,获得16x upsampled feature prediction。
- 对于FCN-8s,首先进行pool4+2x upsampled feature逐点相加,然后又进行pool3+2x upsampled逐点相加,即进行更多次特征融合。具体过程与16s类似,不再赘述。
对比图:
剩下的内容就是对训练、测试一部分的叙述了,主要是结果展示一样的工作。。对于我这种。。随便看看就行了~~