部分内容摘自:http://www.2cto.com/kf/201604/503146.html
代码和模型:https://github.com/BVLC/caffe/wiki/Model-Zoo#fcn
算法使用示例代码:https://github.com/SHUCV/digit
论文:Shelhamer E, Long J, Darrell T. Fully Convolutional Networks for Semantic Segmentation[J]. 2014, 79(10):1337-1342.
论文算法概述
全卷积网络(FCN)进行像素级的分类从而高效的解决了语义级别的图像分割(semantic segmentation)问题。与经典的CNN在卷积层之后使用全连接层得到固定长度的特征向量进行分类不同,FCN可以接受任意尺寸的输入图像,采用反卷积层对最后一个卷积层的feature map进行上采样, 使它恢复到输入图像相同的尺寸,从而可以对每个像素都产生了一个预测, 同时也保留了原始输入图像中的空间信息, 最后在上采样的特征图上进行逐像素分类。论文中逐像素计算softmax分类的损失, 相当于每一个像素对应一个训练样本。
Longjon用于语义分割所采用的全卷积网络(FCN)的结构示意图, 在Alexnet基础上, 最后的channel=4096的feature map经过一个1x1的卷积层, 变为channel=21的feature map, 然后经过上采样和crop(由于步长(stride)不为一的卷积层和池化层产生的特征图(feature map)大小会有一些向下取整操作, 导致最后的feature map大小与原图不是严格的倍数关系,crop层进行裁剪), 变为与输入图像同样大小的channel=21的feature map, 也就是图中的pixel-wise prediction。 在Longjon的试验中一共有20个语义类别, 加上背景类别每个像素应该有21个softmax预测类, 因此pixel-wise prediction中channel=21。
细节记录
dense prediction
这里通过upsampling得到dense prediction,作者研究过3种方案:
-
1、shift-and-stitch:设原图与FCN所得输 出图之间的降采样因子是f,那么对于原图的每个f x f的区域(不重叠),“shift the input x pixels to the right and y pixels down for every (x,y) ,0 < x,y < f.” 把这个f x f区域对应的output作为此时区域中心点像素对应的output,这样就对每个f x f的区域得到了f^2个output,也就是每个像素都能对应一个output,所以成为了dense prediction。
-
2、filter rarefaction:就是放大CNN网络中的subsampling层的filter的尺寸,得到新的filter:其中s是subsampling的滑动步长,这个新filter的滑动步长要设为1,这样的话,subsampling就没有缩小图像尺寸,最后可以得到dense prediction。
以上两种方法作者都没有采用,主要是因为这两种方法都是trad-off的,原因是:对于第二种方法, 下采样的功能被减弱,使得更细节的信息能被filter看到,但是receptive fileds会相对变小,可能会损失全局信息,且会对卷积层引入更多运算。对于第一种方法,虽然receptive fileds没有变小,但是由于原图被划分成f x f的区域输入网络,使得filters无法感受更精细的信息。
- 3、重点方法:反卷积层->pixel wise->bp parameters->实现把conv的前传和反传过程对调一下即可。这里upsampling的操作可以看成是反卷积(deconvolutional),卷积运算的参数和CNN的参数一样是在训练FCN模型的过程中通过bp算法学习得到。
fusion prediction
以上是对CNN的结果做处理,得到了dense prediction,而作者在试验中发现,得到的分割结果比较粗糙,所以考虑加入更多前层的细节信息,也就是把倒数第几层的输出和最后的输出做一个fusion,实际上也就是加和。这样就得到第二行和第三行的结果,实验表明,这样的分割结果更细致更准确。在逐层fusion的过程中,做到第三行再往下,结果又会变差,所以作者做到这里就停了。可以看到如上三行的对应的结果:
问题&解决办法
-
1.如何做pixelwise的prediction? 传统的网络是subsampling的,对应的输出尺寸会降低,要想做pixel wise prediction,必须保证输出尺寸。
解决办法: (1) 对传统网络如AlexNet,VGG等的最后全连接层变成卷积层。例如VGG16中第一个全连接层是25088x4096的,将之解释为512x7x7x4096的卷积核,则如果在一个更大的输入图像上进行卷积操作(上图的下半部分),原来输出4096维feature的节点处(上图的上半部分),就会输出一个coarse feature map。这样做的好处是,能够很好的利用已经训练好的supervised pre-training的网络,不用像已有的方法那样,从头到尾训练,只需要fine-tuning即可,训练efficient。 (2) 加In-network upsampling layer。对中间得到的feature map做bilinear上采样,就是反卷积层。实现把conv的前传和反传过程对调一下即可。
-
2.如何refine,得到更好的结果?upsampling中步长是32,输入为3x500x500的时候,输出是544x544,边缘很不好,并且limit the scale of detail of the upsampling output。
解决办法:采用skip layer的方法,在浅层处减小upsampling的步长,得到的fine layer 和 高层得到的coarse layer做融合,然后再upsampling得到输出。这种做法兼顾local和global信息,即文中说的combining what and where,取得了不错的效果提升。FCN-32s为59.4,FCN-16s提升到了62.4,FCN-8s提升到62.7。可以看出效果还是很明显的。
-
3.训练细节
- 用AlexNet,VGG16或者GoogleNet训练好的模型做初始化,在这个基础上做fine-tuning,全部都fine-tuning。
- 采用whole image做训练,不进行patch wise sampling。实验证明直接用全图已经很effective and efficient。
- 对class score的卷积层做全零初始化。随机初始化在性能和收敛上没有优势。
优缺点
优点:
- 训练一个end-to-end的FCN模型,利用卷积神经网络的很强的学习能力,得到较准确的结果,以前的基于CNN的方法都是要对输入或者输出做一些处理,才能得到最终结果。
- 直接使用现有的CNN网络,如AlexNet, VGG16, GoogLeNet,只需在末尾加上upsampling,参数的学习还是利用CNN本身的反向传播原理,”whole image training is effective and efficient.”
- 不限制输入图片的尺寸,不要求图片集中所有图片都是同样尺寸,只需在最后upsampling时按原图被subsampling的比例缩放回来,最后都会输出一张与原图大小一致的dense prediction map。
缺点:
- 容易丢失小目标。
总结
全卷积,基本思想是一直卷积到最后加个反卷积使特征图大小与输入图像一致。而最终的反卷积的输出通道数对应着要分割目标的类别数,相当与对每个像素做多分类。(但这样没有考虑到像素之间的关系,精度也相对比较低。)