发布时间:2023-03-23 文章分类:电脑基础 投稿人:樱花 字号: 默认 | | 超大 打印

视频链接:https://www.bilibili.com/video/BV1J3411C7zd?vd_source=a0d4f7000e77468aec70dc618794d26f
代码:https://github.com/WZMIAOMIAO/deep-learning-for-image-processing

FCN是2015年提出的首个端对端的针对像素级预测的全卷积网络。
如今的pytorch实现的FCN都是基于ResNet-50的backbone,不是论文中的VGG16,且使用的是空洞卷积(也叫膨胀卷积)

pytorch官方实现的FCN网络结构图

FCN全卷积网络理解及代码实现(来自pytorch官方实现)
博主github:https://github.com/WZMIAOMIAO/deep-learning-for-image-processing/tree/master/pytorch_segmentation/fcn

一、相比以前网络的巨大提升:

FCN全卷积网络理解及代码实现(来自pytorch官方实现)

二、传统使用池化层最后得到的其实是一个长度为1000的向量:

FCN全卷积网络理解及代码实现(来自pytorch官方实现)
而换为卷积层之后,最后得到的是1000通道的2D图像,可以可视化为heat map图。

三、回顾VGG16

一般说的vgg16是D
FCN全卷积网络理解及代码实现(来自pytorch官方实现)
全连接操作前后:77512(通道)
FCN全卷积网络理解及代码实现(来自pytorch官方实现)










\color{red}{【假设忽略偏置】}

全连接FC1计算:计算对应某一个结点的输出,将该节点与上一层某一个结点的权重与输入对应节点数值相乘,再求和

下层使用7*7的卷积核、stride=1,4096个卷积核的一个卷积层








F
C
1









\color{red}{一个卷积核和FC1一个节点参数量一样}
FC1
,一共4096个卷积核,FC也是4096个节点。
















4096







4096





\color{red}{【不忽略偏置的正常卷积操作,4096个卷积核应该有4096个偏置项】}
40964096

FCN全卷积网络理解及代码实现(来自pytorch官方实现)

PS:全连接层

全连接层的输入是一维数组,多维数组需先进行Flatten进行一维化处理,然后连接全连接层。全连接层的每一个结点都与上一层的所有结点相连,用来把前边提取到的特征综合起来。由于其全相连的特性,一般全连接层的参数也是最多的。全连接图结构如下:
FCN全卷积网络理解及代码实现(来自pytorch官方实现)
其中,x1、x2、x3为全连接层的输入,a1、a2、a3为输出,有
FCN全卷积网络理解及代码实现(来自pytorch官方实现)

全连接层参数计算

权值参数=输入一维数组大小*全连接层输出结点数
偏置参数b=全连接层输出结点数

eg:
输入有[5044]个神经元结点,输出有500个结点,则一共需要5044*500=400000个权值参数W和500个偏置参数b

卷积和全连接层

卷积跟全连接都是一个点乘的操作,区别在于卷积是作用在一个局部的区域,而全连接是对于整个输入而言,那么只要把卷积作用的区域扩大为整个输入,那就变成全连接了,我就不给出形式化定义了。所以我们只需要把卷积核变成跟输入的一个map的大小一样就可以了,这样的话就相当于使得卷积跟全连接层的参数一样多。
eg:输入是224x224x3 的图像,假设经过变换之后最后一层是[7x7x512]的,那么传统的方法应该将其展平成为一个7x7x512长度的一层,然后做全连接层,假设全连接层为4096×1000层的(假设有1000个分类结果)。 那么用1×1卷积核怎么做呢,因为1×1卷积核相当于在不同channel之间做线性变换,所以:

先选择7×7的卷积核,输出层特征层数为4096层,这样得到一个[1×1×4096]层的
然后再选择用1×1卷积核,输出层数为1000层,这样得到一个[1×1×1000]层这样就搞定了。

四、FCN-32s、16s、8s的区别

FCN全卷积网络理解及代码实现(来自pytorch官方实现)
上采样倍率为32的模型对应的就是FCN-32s,16s、8s同理。

FCN-32s

FCN原论文中backbone的第一个卷积层padding=100,为了防止图片过小(例如192192)后面的卷积层会报错。
如果图片小于32
32的话在卷积过程就会报错。
但是没必要设置,只要输入图片大小大于32*32,我们就可以将padding设置为3。
FCN全卷积网络理解及代码实现(来自pytorch官方实现)
对于FCN-32s

之后特征图经过一个softmax处理就能得到针对每一个pixel的预测类别。
前面的backbone使用的是vgg16的预训练权重,整个结构十分简单,但是效果还是非常不错的。
FCN全卷积网络理解及代码实现(来自pytorch官方实现)
其实这里的转置卷积在原论文中其实是将参数给冻结住了,冻结住意味着其实它就是一个简单的双线性卷积了。

FCN-16s

FCN全卷积网络理解及代码实现(来自pytorch官方实现)

FC6、FC7、Conv2d核32s的一样。
不同点:



F
C
N

16
s






m
a
x
p
o
o
l
4




\color{red}{【FCN-16s中融合了来自maxpool4的信息】}
FCN16smaxpool4

须知:vgg16经过mxpool3之后特征图大小下采样率为8,经过maxpool4后下采样率为16。
FCN全卷积网络理解及代码实现(来自pytorch官方实现)

FCN-8s

FCN全卷积网络理解及代码实现(来自pytorch官方实现)

不同点:








F
C
N

16
s

F
C
N

8
s












F
C
N
32
s
















\color{red}{【由此可见,FCN-16s和FCN-8s融合了一个底层的信息;而FCN32s是最简单的,它没有融合底层信息】}
FCN16sFCN8sFCN32s
在网上看到最多的是FCN-32的实现。

五、损失计算

FCN全卷积网络理解及代码实现(来自pytorch官方实现)
针对每一个pixel都会去计算它所对应的一个Cross Entropy Loss,然后将所有pixel的交叉熵损失进行一个求平均操作就得到了一个我们网络的最终的一个损失

六、语义分割评价指标

FCN全卷积网络理解及代码实现(来自pytorch官方实现)

见前言:语义分割前沿

七、代码实现

FCN全卷积网络理解及代码实现(来自pytorch官方实现)
ResNet-50中先经过conv1 7*7的一个卷积








\color{red}{不同的地方:}

Bottleneck1:

FCN全卷积网络理解及代码实现(来自pytorch官方实现)
Bottleneck2:
FCN全卷积网络理解及代码实现(来自pytorch官方实现)
接下来通过FCN Head模块:33卷积层缩小通道为原来的1/4【2048-512】,再通过一个dropout和一个11卷积层,这里11卷积层调整特征层的channel为分割类别中的类别个数。
最后经过双线性插值还原特征图大小到原图。【图例:输入480
480,上采样也到480*480】
FCN全卷积网络理解及代码实现(来自pytorch官方实现)

layer3中引出的一条FCN Head,官方回答:为了防止误差梯度没法传递到网络浅层,这里就引入了一个辅助分类器。和google net中辅助分类器是差不多的。
训练的时候是可以使用辅助分类器件的【可用可不用,都可以试一下】,但是最后去预测或者部署到正式环境的时候只用主干的output,不用aux output。
FCN全卷积网络理解及代码实现(来自pytorch官方实现)
up主的代码地址:https://github.com/WZMIAOMIAO/deep-learning-for-image-processing/tree/master/pytorch_segmentation/fcn