因为电脑配置比较差(NVIDIA Geforce MX230,2G),就不想自己尝试训练 SSD,但是五一假期马上要结束了,避免再见导师时被追问进度,还是硬着头皮试试看了。
我用的图像是肠镜图片,目的是检测其上是否有LST肿瘤(也就是病变区域)。对于存在LST的图像,希望返回有边界框标注病变区域的图片,对于正常图像则返回原图。
所以接下来的内容将存在LST的图像记为病变图像,否则为正常图像。数据集情况如下:
批次 | 正常图像 | 病变图像 |
---|---|---|
01 | 181张 | 162张 |
02 | 61张 | 109张 |
一共 513 张图像(大概率就是这个数量少导致我第一次训练+预测失败)。
我是90%的参考了该up主的配置,Anaconda + cuda10.0 + cudnn7.4.1.5 + torch1.2.0 + torchvision0.4.0,亲测可用奥。
深度学习环境配置-Anaconda以及pytorch1.2.0的环境配置
剩下的10%就是我用的 Pycharm 而不是 VS,视频教程真的超贴心了,下面是文字版的教程。
神经网络学习小记录48——windows下的torch=1.2.0环境配置
在上一篇文章末尾已介绍了数据集如何转换为可供训练 SSD 使用的格式,这里再简单记录一下。
voc2ssd.py
生成索引文件按照 VOCdevkit 的格式,在 VOC2007 下有三个文件夹:
正常图像的标签文件中没有目标信息,而病变图像标签文件中的目标信息至少为1个,比如:
划重点啦!!!如何获取索引文件
在 ImageSets
目录下有个 Main
文件夹,包含:
test.txt、teain.txt、trainval.txt、val.txt
均用于存放图像文件和标签文件的索引内容。
然后在根目录下的 voc2ssd.py
,我们需要按照自己的需求设置测试集的比例,我是打算用 20% 的图作为测试集,也就是 103 张图。修改部分为:
然后运行根目录下的 voc2ssd.py
来生成 test.txt、teain.txt、trainval.txt、val.txt
四个文件。
因为我用的是 Pycharm,所以直接运行子目录下的
voc2ssd.py
会报错:FileNotFoundError: [WinError 3] 系统找不到指定的路径。: './VOCdevkit/VOC2007/Annotations'
最直接的解决办法是把
voc2ssd.py
放到根目录下去运行,然后就可以得到我们需要的索引文件了。
voc_annotation.py
生成用于训练的文件用于训练的 txt 文件有三个:
2007_test.txt、2007_train.txt、2007_val.txt
。
需要用到的代码是 voc_annotation.py
,需要修改的地方如下图红框标注:
开始训练之前需要按照自己的数据集修改一些参数,具体如下。
config.py
文件train.py
文件训练好的权重会保存在 logs
目录下。下图是生成的部分权值文件。
ssd.py
文件ssd.py
文件predict.py
文件运行后输入图像名称 img/101001.jpg
,放一个预测成功的图。
由于配置问题、或参数设置,训练可能以各种原因失败,我第一次训练就以显存不足结束了,可能是没训练好,或者数据集太少或者…,预测时病变图像也不显示预测框,然后就开始各种百度需要修改哪些参数,好在第二次训练慢悠悠地成功结束了,预测图至少也有预测框了。
第一次没有修改原代码的学习率、epoch等参数,之后训练失败,根据 显存不足和预测图像不显示预测框 这两点查了些解决方式:
第二次训练就很随意的盲改了参数,如下:
参数 | 修改前 | 修改后 |
---|---|---|
nets/ssd.py 中:detect() 的参数 nms_thresh |
0.45 | 0.35 |
nets/ssd.py 中:get_ssd() 的参数 confidence |
0.5 | 0.4 |
nets/ssd.py 中:get_ssd() 的参数 nms_iou |
0.45 | 0.35 |
utils/box_utils.py 中:nms() 的参数 overlap |
0.5 | 0.3 |
train.py 中:MultiBoxLoss 的参数 overlap_thresh |
0.5 | 0.3 |
train.py 中:batch_size & epoch |
16, 50 | 8, 30 |
train.py 中:batch_size & epoch |
8, 50,100 | 4, 30, 60 |
这些参数就是凭感觉改的,如果有不对的地方请各位指出来。
今天写到这里差不多了,good night。
——————————————————————————————————————————
——————————————————————————————————————————
来补充内容了。既然能够成功预测一张图,那么对一个测试集的预测效果能达到什么程度才是我们主要关心的问题,所以我尝试着进行批量预测,并计算 mAP 值。
predict.py
文件修改的目的是为了能进行整个测试集的批量预测,所以我们需要遍历测试集并对每一张图进行预测。修改后的代码如下:
from PIL import Image
from ssd import SSD
from tqdm import tqdm
import os
ssd = SSD()
# 这部分用于单张图片预测
# while True:
# img = input('Input image filename:')
# try:
# image = Image.open(img)
# except:
# print('Open Error! Try again!')
# continue
# else:
# r_image = ssd.detect_image(image)
# r_image.save("img.jpg")
# r_image.show()
# 以下用于批量预测
image_ids = open('VOCdevkit/VOC2007/ImageSets/Main/test.txt').read().strip().split()
for image_id in tqdm(image_ids): # 遍历测试图像
image_path = "./VOCdevkit/VOC2007/JPEGImages/" + image_id + ".jpg" # 原图像的存储路径
try:
image = Image.open(image_path)
except:
print('Open Error! Try again!')
continue
else:
r_image = ssd.detect_image(image) # 使用网络进行预测
image_results_path = "./image_results/" # 创建用于存放预测好的图像的文件夹
if not os.path.exists(image_results_path):
os.mkdir(image_results_path)
r_image.save(os.path.join(image_results_path, image_id+".jpg")) # 存储图像
运行该文件后,在根目录下会出现 image_results
文件夹,存放的就是预测好的图像。
有了测试集的预测结果后,我们就可以着手计算该模型的 mAP,所以首先需要将测试集图像中的真实框以及预测框信息提取出来。
get_gt_txt.py
获取测试集的真实框这个没有需要修改的地方,直接运行即可。
get_dr_txt.py
获取测试集的预测框同上,不需修改,直接运行即可。
当上述两个文件运行完毕后,根目录下会出现 input
文件夹:
detection-results
存放预测框信息detection-results
存放真实框信息images-optional
存放测试集图像,通过get_dr_txt.py
生成,可有可无,作用是在计算mAP时能够可视化图像。get_map.py
计算mAP这个没有需要修改的地方,直接运行即可。运行后在根目录下会出现 results
文件夹,存放各种评估指标的可视化图。由于我的数据集只有一个类别 LST,因此每类指标下只有一幅图。
最终获得了 m A P = 83.79 mAP=83.79% mAP=83.79,好像也不算太低,感觉再调整下参数然后多训练几次可能还会增加。
最后,希望大家努力发现我的错误。
——————————————————————————————————————————
——————————————————————————————————————————
补充内容。
看了一遍预测好的图像,发现标注的预测框有点问题,如果一张图有多个目标的话,预测框框之间可能会相互重叠,这样看起来就有那么一丝丝不爽,比如:
所以本着不能完美但要努力追求完美的想法,我决定改一改框框的标注:
具体修改部分在根目录下 ssd.py --> detect_image(self, image)
然后昨晚上又训练了一次,将 epoch
增加到了 80,结果!!!预测的 mAP 值居然下降了 7% 多,心痛啊 /(ㄒoㄒ)/~~
但感觉模型还是有些改善,loss 的波动没有那么剧烈了,继续努力叭~