欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Pytorch_复现DHSNet过程、问题记录

程序员文章站 2024-01-15 19:50:58
...

Salient object detection 显著性目标检测
2019.3.11~3.22 期间复现DHSNet
由于是第一次复现显著性目标检测算法,有很多东西需要边学边写,且中间尝试了Encoder_Decoder模型并且进行了训练,所以用了将近两周,时间比较长,过程、工作、问题记录如下。

一、论文

论文标题:DHSNet: Deep Hierarchical Saliency Network for Salient Object Detection
论文链接:http://xueshu.baidu.com/usercenter/paper/show?paperid=82824289b92ac32d34f059e3125212b4&site=xueshu_se
发表在2016年的CVPR上

二、Dataset

1.下载显著性目标检测常用的几个数据集:

DUT-OMRON
MSRA10K
ECSSD
PASCAL-S
HKU-IS

2.构建用于训练DHSNet的数据集

论文中使用的训练集组成如下:

We randomly selected 6,000 images from MSRA10K dataset and 3,500 images from DUT-OMRON dataset as the training set, and another 800 images from MSRA10K and 468 images from DUT-OMRON as the validation set.

写python脚本实现数据集的构建,分别对DUT-OMRON和MSRA10K做如下操作:

1.生成范围在[0, 单个数据集样本数]之间的不重复随机数作为图片编号,用random.sample()实现
2.将样本从原始文件夹转移到新文件夹中,用shutil.move()实现

参考链接:python 指定范围内随机生成不重复的n个数
https://blog.csdn.net/u012063507/article/details/79270594

3.实现自己的Dataset类

(1)继承torch.utils.data.Dataset,重写下面三个方法

	def __init__():	
	
	def __getitem__():

	def __len__():

(2)需要实现的transforms:
A.resize成224*224大小
B.每个通道值除以255
C.减去mean,除以std

参考了几个网址:
1.PyTorch载入图片后ToTensor解读
https://www.cnblogs.com/ocean1100/p/9494640.html
2.Pytorch之深入torchvision.transforms.ToTensor与ToPILImage https://blog.csdn.net/qq_37385726/article/details/81811466
3.管文龙师兄的github,学着用PIL.Image实现resize,使用numpy实现归一化,然后使用torch.from_numpy()创建张量
https://github.com/GuanWenlong/DHSNet-PyTorch
4.涉及numpy array, tensor,pil_image之间的转换,参考了下面几个网址
https://blog.csdn.net/yskyskyer123/article/details/80707038

三、构建网络

DHSNet分成两个部分:用于提取特征的GV-CNN 和 用于优化/修复saliency map的HRCNN,如下图
Pytorch_复现DHSNet过程、问题记录

A.vgg16_bn.features输出的尺寸问题

DHSNet的前半部分用的就是vgg16的features部分
原始VGG中,输入一张[3, 224, 224]的图片,vgg16_bn.features的输出尺寸为[512, 14, 14]
而在DHSNet中,去掉了features部分的最后一个池化层,vgg16_bn.features的输出尺寸变为[512, 28, 28]

B. DHSNet中的全连接层尺寸

vgg16_bn.features的输出尺寸为[batch_size, 512, 28, 28]
先view成[batch_size, 512x28x28]的二维张量
再通过全连接层,变为[batch_size, 784]的二维张量(注意784 = 28x28)
之后reshape成[batch_size, 1, 28, 28]大小

C.抽取vgg16提取的各尺寸feature map

pytorch提供训练好的vgg16_bn模型,整体由两部分构成:features和classifier。features是一个整体,用Sequential()定义,不能直接获取Conv1_2,Conv2_2,Conv3_3,Conv4_3和Conv5_3所输出的feature map。有两个办法:1.使用register hook, 2.重新定义vgg网络,中间留出接口

重新定义网络时
(1)使用如下语句来打印vgg的结构,打印出来的内容包括每个Sequential和layer

    model = torchvision.models.vgg16_bn(pretrained=True)
    for item in model.modules():
        print(item)

(2)Conv1_2,Conv2_2,Conv3_3,Conv4_3,Conv5_3这五个部分,每个部分使用一个nn.Sequential来集合各个Conv2d,ReLU,BatchNorm2d层,而不是将整个vgg16.features部分用一个Sequential集合起来。这样方便在前向传播中留出feature maps的接口。
(3)定义好网络后需要复制预训练模型的参数,参考管文龙师兄github,用到的方法有
list.expand()
isinstance()
sequential.children()
要注意,只需复制Conv2d的参数,包括weight和bias两部分

D.构建RCL

对recurrent neural network已经不太记得了,重新查了一下,对自己写RCL还是有点摸不着头脑。参考管文龙师兄的github,发现自己对RCL的理解不太对。RCL并不是纯粹的RNN,而是recurrent convolutional layers,单步的计算并不是通过torch.nn.Linear实现的,也不能调用torch.nn.RNN,而是循环地进行同一个卷积运算,这里弄懂之后就好写了。

四、pytorch实现计算MAE和F-Measure

1.使用自适应阈值对saliency map进行二值化处理
2.TP TN FP FN的概念和pytorch代码实现
3.precision recall accuracy的概念
4.F-measure统筹考虑precision和recall,beta的平方常设置为0.3
5.网络训练的初期,saliency map中很容易没有预测为正的像素点,TP=0 FP=0很常见,此时F-measure=nan,需要进行特殊处理
6.MAE的公式
参考链接:
1.显著性目标检测模型评价指标(一)——平均绝对误差:Mean Absolute Error(MAE)
https://blog.csdn.net/stupidautofan/article/details/79556087
2.显著性目标检测模型评价指标(二)——PR曲线
https://blog.csdn.net/StupidAutofan/article/details/79583531
3.显著性目标检测模型评价指标(三)——F-measure
https://blog.csdn.net/StupidAutofan/article/details/79583450

五、训练网络

训练过程中validation_loss总是震荡,尝试了两种训练思路,效果都不是很好。一开始没有用paper中所说的数据集,而是只用DUT-OMRON,后来换用paper所说的数据集(更大一些),训练效果稍好,但是仍不好训练。
A.整体训练
B.分阶段训练:

  1. 训练vgg+fc
  2. 训练vgg+fc+RCL4
  3. 训练vgg+fc+RCL3
  4. 训练vgg+fc+RCL2
  5. 训练vgg+fc+RCL1
  6. 训练整体模型
    最终用paper中的数据集训练,采用分阶段训练的方法,最终f-measure在测试集上能达到0.8左右

六、预测并输出结果

对整个ECSSD、PASCAL-S数据集进行测试

ECSSD PASCAL-S
F-measure=0.78 F-measure=0.63
MAE=0.101 MAE=0.21

七、其他

想起来了再补充