Pytorch_复现DHSNet过程、问题记录
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,如下图
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.分阶段训练:
- 训练vgg+fc
- 训练vgg+fc+RCL4
- 训练vgg+fc+RCL3
- 训练vgg+fc+RCL2
- 训练vgg+fc+RCL1
- 训练整体模型
最终用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 |
七、其他
想起来了再补充
上一篇: Centos7安装Kibana