前几天在CSDN上看见别的大神在用YOLOv3运行自己的口罩数据集,于是我也心血来潮,开(jian)心(nan)地复制粘贴跑了起来。
原大神的数据集和代码我在学校服务器上都能正常运行,没毛病,可是当我开始扩充原作者的数据集时,问题就开始爆发了。
环境:
1、Pytorch 1.4.0
2、anaconda 3
3、opencv-python 3.4.2
4、CUDA 10.2
5、 显卡驱动版本号440
1、扩充的口罩数据集是来自于开源数据集,总共拿到3k+张,经手动数据清洗后得到2k+张数据集,然后输入
python train.py --data-cfg data/rbc.data --cfg cfg/yolov3-tiny.cfg --epochs 100
出现第一个问题:File Not Found
首先请先排查路径是否错误
路径不能包含中文,不能包含特殊字符,如果是Windows操作系统,请注意是否是有转义字符,如C:/User/Desktop在路径中需写成C://User//Desktop
如果确认了路径没错,文件真是存在,那就是你的图片读取出错了
以下代码用于检查文件是否可以读入,如果不可以读入将输出不能打开的文件名字,也可以直接删除打不开的文件:
import os
import cv2
i = 0;j = 0;bad = [] # bad中存放的就是所有打不开的图片的名字,i,j分别为哨兵
# 运行时请将以下两个路径替换成自己的,一个是图片路径,一个是图片对应的标注文件
paths = '/home/user/Desktop/Object_Dete_Masking-master/data/Annotations/'
images = os.listdir('/home/user/Desktop/Object_Dete_Masking-master/data/images/')
for image in images:
i +=1
try:
img = cv2.imread(images+ image)
# 尝试是否可以读取,如果可以读取,就输出图片的维度,及已读取到第多少张图片
# 然后转到下一张图片
print(img.shape)
print(i)
except AttributeError:
bad.append(image)
j +=1
print('The Error Number is '+ str(j))
for badimage in bad:
try:
# 这三行代码将直接删除打不开的图片及其对应的标注
# os.remove(paths + badimage)
# badimage = badimage.split('.')[0] + '.xml'
# os.remove(paths + badimage)
except FileNotFoundError:# 如果图片文件不存在,请更新train.txt
print(badimage)
print("ALL DONE") # 最终输出ALL DONE
2、经过上述一番操作,我的2k+数据集已经被筛掉了大半,我觉得这下终于解决了数据集问题,一定可以完美运行了!于是我信心满满的输入
python train.py --data-cfg data/rbc.data --cfg cfg/yolov3-tiny.cfg --epochs 100
果不其然,第二个问题马上出现了
cv2.error: OpenCV(4.1.2) /io/opencv/modules/core/src/copy.cpp:1170:
error: (-215:Assertion failed)
top >= 0 && bottom >= 0 && left >= 0 &&right >= 0&& _src.dims()<= 2
in function 'copyMakeBorder'
这个问题是由于在datasets.py中的letterbox导致
datasets.py中的letterbox方法在计算负边框尺寸时,如果矩形框训练(rectangle_training)被设置为True时,对cv2.copyMakeBorder的调用将引发异常。
在YOLOv3的train.py的源代码中,矩形框训练rectangle_training参数是被默认设置为False的。
# 在train.py的147行:
# Dataset
dataset = LoadImagesAndLabels(train_path,
img_size,
batch_size,
augment=True,
rect=False) # rect参数被默认设置为False
而rect参数在test.py中被设置为True:
在test.py的第47行:
# Dataloader
dataset = LoadImagesAndLabels(test_path, img_size, batch_size) #注意rect =缺省情况下为true
所以解决办法就是把test.py的第47行改为:
# Dataloader
dataset = LoadImagesAndLabels(test_path, img_size, batch_size,rect = False)
果不其然,第二个问题得以解决!!!
这下一定没问题了!!
我开开心心的输入train命令
python train.py --data-cfg data/rbc.data --cfg cfg/yolov3-tiny.cfg --epochs 100
激动的搓手手
在解决好这个问题后,我再次输入命令,终于成功开始训练!但是,你以为这就结束了??NONONO!
在进行完第一个epoch的训练后,第三个问题马上出现了
报错信息如下:
Traceback (most recent call last):
File "train.py", line 432, in
train() # train normally
File "train.py", line 268, in train
pred = model(imgs)
File "/root/anaconda3/lib/python3.7/site-packages/torch/nn/modules/module.py", line 541, in
__call__
result = self.forward(*input, **kwargs)
File "/root/anaconda3/lib/python3.7/site-packages/torch/nn/parallel/distributed.py", line 459, in forward
self.reducer.prepare_for_backward([])
RuntimeError: Expected to have finished reduction in the prior iteration before starting a new one. This error indicates that your module has parameters that were not used in producing loss. You can enable unused parameter detection by (1) passing the keyword argument `find_unused_parameters=True` to `torch.nn.parallel.DistributedDataParallel`; (2) making sure all `forward` function outputs participate in calculating loss. If you already have done the above two steps, then the distributed data parallel module wasn't able to locate the output tensors in the return value of your module's `forward` function. Please include the loss function and the structure of the return value of `forward` of your module when reporting this issue (e.g. list, dict, iterable). (prepare_for_backward at /pytorch/torch/csrc/distributed/c10d/reducer.cpp:518)
frame #0: c10::Error::Error(c10::SourceLocation, std::string const&) + 0x33 (0x7f1331504813 in /root/anaconda3/lib/python3.7/site-packages/torch/lib/libc10.so)
frame #1: c10d::Reducer::prepare_for_backward(std::vector > const&) + 0x734 (0x7f1336759654 in /root/anaconda3/lib/python3.7/site-packages/torch/lib/libtorch_python.so)
frame #2: + 0x7bed8a (0x7f1336747d8a in /root/anaconda3/lib/python3.7/site-packages/torch/lib/libtorch_python.so)
frame #3: + 0x210ba4 (0x7f1336199ba4 in /root/anaconda3/lib/python3.7/site-packages/torch/lib/libtorch_python.so)
frame #29: __libc_start_main + 0xe7 (0x7f133a464b97 in /lib/x86_64-linux-gnu/libc.so.6)
我左看右看,上看下看,没看明白这是个什么错误,好像是代码有问题?不可能,大神怎么会有错呢!肯定是我太累了!出现幻觉了!于是我决定休息一下,打开了全球最大的同性交友网站代码学习网站:GitHub,仔细查了这个奇形怪状的问题。经过我的多方探讨(找人死皮赖脸的问),总结出以下几种可能导致该错误的答案:
1、图片还是有问题
2、batch_size、accumulate参数、训练集的总图片数都应该是GPU的整倍数
如果不是整倍数,就会导致这个错误。如accumulate设为2,但是GPU有8张,2不是8的整倍数,就会导致出错。
batch_size参数在cfg文件夹下的yolov3-tiny.cfg文件中
accumulate参数可以在命令行中给定
3、训练集的总数最好是偶数不是奇数,否则也可能导致这个错误。
在我被困扰了三天后,上述几个问题终于全部解决,真是太为难我胖虎了~
看着从0.01逐渐升高到0.05的mAP,看着慢慢迭代的epoch,我开心的露出了姨母笑
奈何九九八十一难,你以为这就完了?NONONO!
还有最后一难,segmentation fault!
这个bug有时会被莫名触发,导致训练停止。最可怕的是报错信息只有一句segmentation fault。。。。。。。。。
这个问题嘛==
我再看看,暂时还没解决。。。。。。
先写这些哈,如果有朋友遇到我一样的情况,也算有个参考,谢谢