用YOLOv3跑自己数据集时遇到的那些坑及填坑总结

前几天在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 <module>
    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<torch::autograd::Variable, std::allocator<torch::autograd::Variable> > const&) + 0x734 (0x7f1336759654 in /root/anaconda3/lib/python3.7/site-packages/torch/lib/libtorch_python.so)
frame #2: <unknown function> + 0x7bed8a (0x7f1336747d8a in /root/anaconda3/lib/python3.7/site-packages/torch/lib/libtorch_python.so)
frame #3: <unknown function> + 0x210ba4 (0x7f1336199ba4 in /root/anaconda3/lib/python3.7/site-packages/torch/lib/libtorch_python.so)
<omitting python frames>
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。。。。。。。。。

这个问题嘛==
我再看看,暂时还没解决。。。。。。
先写这些哈,如果有朋友遇到我一样的情况,也算有个参考,谢谢

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值