CV02-FCN笔记

目录

一、Convolutionalization 卷积化

二、Upsample 上采样

2.1 Unpool反池化

2.2 Interpolation差值

2.3 Transposed Convolution转置卷积

三、Skip Architecture

3.1 特征融合

3.2 裁剪


FCN原理及实践,记录一些自己认为重要的要点,以免日后遗忘。

原始思路是,去掉全连接层,全部改为卷积操作。保持图片spatial大小做Dense Prediction,就需要做same卷积,也就是加padding。如果一直保持图片spatial大小不变,那么计算量巨大。

FCN的思路是,特征提取阶段图像spatial减小,图像分类阶段把特征通过upsample方式放大到原来图像大小。再通过融合过程中的数据(保持位置信息)来提高推断的准确率。

FCN的三个重点:Convolutionalization卷积化、Upsample上采样、Skip Architecture。

参考实现:https://github.com/wkentaro/pytorch-fcn/tree/master/torchfcn/models

自己的实现:https://github.com/Ascetics/LaneSegmentation/tree/master/nets

一、Convolutionalization 卷积化

原有的分类网络,特征提取阶段用卷积,图像分类阶段用全连接。输入的spatial大小是固定的。

以VGG16为例,输入是固定大小3×224×224,经过5个阶段的卷积、池化(每次spatial缩小一半),最终得到512×7×7的输出。这个512×7×7做flatten以后变成一维向量,再做后面全连接操作,映射到4096个神经元。

FCN特征提取阶段用卷积,不用全连接层,这就是卷积化操作。注意,卷积化得到的是Coarse Output,这并不能将图像放大到原来的大小。FCN的输入是任意大小的。

用FCN改造VGG16,如果输入图像CHW=3×224×224,经过5个阶段的卷积、池化(每次spatial缩小一半),得到512×7×7的输出。然后,不连全连接层,改为继续连接卷积操作。卷积核是7×7的,out_channel=4096,那么经过这个卷积以后得到4096×1×1的输出。考虑维数为1的维度可以移除,这样结果就和VGG16的结果是一样的。

如果输入图像的spatial比224×224更大,那么经过上述过程,最终的输出是4096×H_{m}×W_{m},就变成了下图第二行的情况。输出就变成了一个heatmap,heatmap的大小就是H_{m}×W_{m}

如果输入图像的spatial比224×224更小,那么怎么保证最后输出不小于7×7,不影响后面的卷积操作呢?办法就是第一次卷积加padding=100,这样就保证输出不小于7×7。

二、Upsample 上采样

特征提取也被称为下采样。上采样与其相反,将小的图像上采样变成大的图像。

上采样有三种方法

  1. Unpool反池化
  2. Interpolation差值
  3. Transposed Convolution转置卷积

FCN里面上采样采用Transposed Convolution转置卷积。

2.1 Unpool反池化

Unpool反池化;torch的API为

torch.nn.MaxUnpool1d
torch.nn.MaxUnpool2d
torch.nn.MaxUnpool3d

反池化操作要依赖池化操作。在池化操作的时候,要记录池化数据的位置信息(torch.nn.MaxPool2d里面的return_indices=True),在根据这个位置信息(indices)将池化数据返回到原有位置,上采样的空白位置补0,也就是说反池化只能恢复部分信息。 

 

2.2 Interpolation差值

Interpolation差值;torch的API为

torch.nn.functional.interpolate()

差值就是用已知的点来估计未知点的值。常用线性差值、双线性差值、最近差值等……其中,线性差值就是用两个点之间的斜率来估算中间插入的点。平面上用双线性差值,也就是用周边4个点来估计插入的点,在另外一篇双线性差值博客中单独分析。差值根据斜率计算,因此不需要机器学习。

2.3 Transposed Convolution转置卷积

Transposed Convolution转置卷积;torch的API为

torch.nn.ConvTranspose1d
torch.nn.ConvTranspose2d
torch.nn.ConvTranspose3d

如果想上采样N倍,有多种实现方式。其中一种,就是ConvTranspose2d的参数设置为kernel_size=2N,stride=N,就可以上采样N倍。下面举例就是上采样32倍。

upsample = nn.ConvTranspose2d(
    in_channels=num_class,
    out_channels=num_class,
    kernel_size=64,
    stride=32,
    bias=False
)

先想想卷积可以做全连接操作。如图,输入4×4,经过3×3的卷积,输出2×2。将4×4的输入变成一个16×1的向量,要输出是4×1的向量,那么就是在16×1的向量上乘以一个4×16的矩阵即可,矩阵的元素就是3×3卷积的权重。

 

那么,反过来,输入2×2,能否用一个3×3的卷积操作让输出4×4呢?把输入2×2变成4×1的向量,乘以16×4的矩阵,输出16×1的向量。这个16×4的矩阵元素就来自转置卷积核。

转置卷积只能恢复位置(维度)的大小,但是不能恢复信息,想要恢复信息要通过学习。

三、Skip Architecture

3.1 特征融合

实验发现,如果直接上采样效果不好,原因是多层卷积使位置信息损失太多。解决办法是,将丢失的信息补充进来。特征融合有多种方式,一种是在维度一致的情况直接相加,另一种是在spatial维度一致的情况下对channel进行concatenate。

这里就用到了Skip Architecture来做特征融合,用到的就是直接相加的方式。根据不同的融合内容可以有FCN32s、FCN16s、FCN8s和FCN4s等。这里的NNs表示上采样多少倍进行融合。

FCN32s就是不进行特征融合,直接将卷积结果上采样32倍。

FCN16s就是将卷积结果上采样2倍,加上1/16的卷积结果;融合以后再上采样16倍。

FCN8s就是将卷积结果上采样2倍,加上1/16的卷积结果;融合以后再上采样2倍,加上1/8的卷积结果;融合以后再上采样8倍。

以此类推……

实验结论是FCN8s的效果最好。为什么FCN4s融合了更浅层、信息损失更少的层,结果不应该比FCN4s更好吗?事实上,FCN4s较FCN8s的提高微乎其微,计算量却大大增加。

3.2 裁剪

特征融合实际上就是再做加法,张量加法要求维数一致才能相加。由于卷积、池化和上采样操作,导致融合时张量维数不一致的情况。为此需要对融合的部分进行剪裁,剪裁成维数一致。下表就记录了各层之间维度的计算关系。

表第一列是卷积层。

表第一行是表头,scale之前的表示每层参数,scale之后的表示上采样的模式和剪裁的大小。in表示输入图片大小;K表示该层卷积核大小;S表示该层stride;P表示该层padding大小;out表示该层卷积输出大小;pool表示该层池化输出大小;scale表示下采样是输入的多少分之一;32s、16s、8s表示FCN32s、FCN16s、FCN8s上采样输出大小,32s_crop、16s_crop、8s_crop表示上采样输出应剪裁大小(整数表示剪裁上采样,负数表示剪裁池化输出);

因为下采样只是一般卷积操作,下采样输出与输入的关系是

Out =\frac{In+2\times P-K}{S}+1

上采样采用转置卷积没有padding等,上采样输出与输入的关系是

Out =(In-1)\times S+K

我们以FCN16s为例,说明计算过程。

FCN16s下采样过程。已知下采样所有层的K、S、P、pool的大小,注意下一层输入的大小是上一层pool输出的大小,如果输入为i,经过8层卷积、池化等层,表中scale前面的内容都可以得到。

FCN16s上采样过程。输入\frac{i+6}{32},转置卷积上采样2倍,S=2,K=4,带入上采用公式得到输出是\frac{i+38}{16},spatial大小比pool输出\frac{i+198}{16}小10。pool输出经过1×1卷积使channel与2倍上采样结果一致,pool输出两边各裁剪掉5。裁剪后入2倍上采样大小都是\frac{i+38}{16},相加融合。融合结果转置卷积上采样16倍,S=16,K=32,带入上采样公式输出是i+54,spatial比输入i大54。因此,上采样结果两边各裁剪掉27。

  in K S P out pool scale 32s 32s_crop 16s 16s_crop 8s 8s_crop
conv1 i 3 1 100 i+198 \frac{i+198}{2} \frac{1}{2} i+38 19 i+54 27 i+62 31
conv2 \frac{i+198}{2} 3 1 1 \frac{i+198}{2} \frac{i+198}{4} \frac{1}{4}

↑×32

k=64

s=32

 

↑×16

k=32

s=16

 

↑×8

k=16

s=8

 
conv3 \frac{i+198}{4} 3 1 1 \frac{i+198}{4} \frac{i+198}{8} \frac{1}{8}     \frac{i+54}{8} -9
conv4 \frac{i+198}{8} 3 1 1 \frac{i+198}{8} \frac{i+198}{16} \frac{1}{16}   \frac{i+38}{16} -5 \frac{i+38}{16} -5
conv5 \frac{i+198}{16} 3 1 1 \frac{i+198}{16} \frac{i+198}{32} \frac{1}{32}  

↑×2

k=4

s=2

 

↑×2

k=4

s=2

 
fc6 \frac{i+198}{32} 7 1 0 \frac{i+6}{32} \frac{1}{32}      
fc7 \frac{i+6}{32} 1 1 0 \frac{i+6}{32} \frac{1}{32}      
fc8 \frac{i+6}{32} 1 1 0 \frac{i+6}{32} \frac{1}{32}      

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章