之前用RFBNet进行目标检测,采用的数据集是VOC2007和VOC2012。最近用在自己的数据集进行训练,由于我的数据集格式跟VOC格式不一样,根据网上的经验,我就开始将自己的数据集制作成VOC格式的方便训练。但自己的数据集和标准的数据集质量真心不能比,有很多问题,花费了好多时间在数据处理上。。。
我遇到的问题主要是数据集的问题,而RFBNet是基于SSD的,所以SSD的如果出现这个问题大概率是一样的,当然其他目标检测网络也可以参考。

训练自己数据集

loss=nan问题
在制作完自己数据集后,训练RFBNet的时候,出现loss_l=nan的情况。

同时还出现RuntimeWarning:

Code/RFBNet-pytorch0.4.0/utils/box_utils.py:84: RuntimeWarning: invalid value encountered in true_dividereturn area_i / (area_a[:, np.newaxis] + area_b - area_i)

说明在代码的utils/box_utils.py的match_iou方法返回值中除法遇到了除数为0的情况。

解决方法
在网上查了一番,发现大家也都遇到类似的情况。
出现nan情况一般有以下集中可能:

  1. 数据问题,例如目标检测中可能出现bbox位置为(0,0),可能xmin>xmax
  2. 网络结构问题
  3. 训练问题等

在逼乎上某一大佬根据他自己经验给出一回答,将batch_size 调成1,shuffle调成False,查看到底哪些数据存在问题。受他启发,我也进行检查,将train_RFB.py中batch_size 调成1,shuffle调成False,ngpu、num_workers调成1,发现网络只是在某一iteration的时候出现loss=nan,所以基本确定是数据集的问题。


确定了是数据集的问题,还得确定是数据集的哪里出现了问题。这个过程实在是有点大海捞针的感觉,我试过将xml中bndbox值转成int,因为VOC中坐标值都是Int,object的name中特殊的字符映射到正常的字符等等。。。但这些都没能解决问题。

就在今天早上,读到一篇[微信推送]帮了我大忙。里面讲到bndbox的iou计算问题,其中有xmax-xmin,ymax-ymin。我就猜想会不会是这个问题。于是我先在VOC2007中检测是否存xmin>xmax的情况,结果发现没有!
然后我又在我的数据集中查找,结果发现,我去,1万条数据中有2000多条存在xmin>xmax!!!

检测xmin>xmax程序

import os
import xml.etree.ElementTree as ET
xml_dir = './Annotations'
def compare_min_max(xml_dir):xmls = os.listdir(xml_dir)xmls.sort()flag = 0count = 0for xml in xmls:xml_path = os.path.join(xml_dir, xml)tree = ET.parse(xml_path)root = tree.getroot()for elem in root.findall('object'):xmin = elem.find('bndbox').find('xmin').textymin = elem.find('bndbox').find('ymin').textxmax = elem.find('bndbox').find('xmax').textymax = elem.find('bndbox').find('ymax').textif int(ymin) > int(ymax) or int(xmin) > int(xmax):print('min > max in file:',xml_path)flag = 1if flag == 1:count += 1flag = 0print('{} files that min > max'.format(count))print('finish comparision...')if __name__ == '__main__':compare_min_max(xml_dir)

在发现自己数据集存在这个问题后,我就重新制作了一遍数据集,这次数据集没有出现xmin(ymin)>xmax(ymax)的情况了。

制作数据集程序

##将数据集中img和rext中的信息转成VOC annotation的 xml格式
import os
import cv2
import io
import pandas as pdimg_path = r'./JPEGImages'
rect_path = r'./rect'
xml_path = r'./Annotations'#read images ,get image's w,h c and name
def read_image(filename):img = cv2.imread(filename)h, w, c = img.shapebasename = os.path.basename(filename)return h, w, c, basename#读取rect的txt中第一个空行之前的内容
def file_reader(filename):with open(filename) as f:for line in f:if line and line != '\n':yield lineelse:break
#获取目标字符类别以及bbox
def get_object_bbox(filename):bbox = []data = io.StringIO(''.join(file_reader(filename)))dataframe = pd.read_csv(data, skiprows=2, header=None)for row in dataframe.iterrows():if isinstance(row[1][2], str):row[1][2] = row[1][2].strip() #delete space in stringr = [row[1][2],row[1][5], row[1][6], row[1][7], row[1][8]]bbox.append(r)return bbox #shape(n,5) n number of bndboxes, each bndbox has the form[object, xmin, ymin,xmax,ymax]def write_xml(h, w, c, bbox, basename):front, extend = os.path.splitext(basename)front += '.xml'full_path = os.path.join(xml_path, front)with open(full_path,'w') as f:f.write('<annotation>\n')f.write('    <folder>OHWME</folder>\n')f.write('    <filename>' + str(basename) + '</filename>\n')f.write('    <source>\n')f.write('        <database>MyDataBase</database>\n')f.write('        <annotation>PASCAL VOC2007</annotation>\n')f.write('        <image>f</image>\n')f.write('    </source>\n')f.write('    <size>\n')f.write('        <width>' + str(w) + '</width>\n')f.write('        <height>' + str(h) + '</height>\n')f.write('        <depth>' + str(c) + '</depth>\n')f.write('    </size>\n')f.write('    <segmented>0</segmented>\n')for b in bbox:object = b[0]if object == '/':object = r'\backslash'if object == '.':object = r'\dot'xmin = b[1]ymin = b[2]xmax = b[3]ymax = b[4]f.write('    <object>\n')f.write('        <name>' + str(object) + '</name>\n')f.write('        <pose>Unspecified</pose>\n')f.write('        <truncated>0</truncated>\n')f.write('        <difficult>0</difficult>\n')f.write('        <bndbox>\n')##avoid xmin,ymin > xmax,ymaxif int(xmin) > int(xmax): xmax, xmin = xmin, xmaxif int(ymin) > int(ymax):ymax, ymin = ymin, ymax#avoid (0,0) which would probaly result in nanif int(xmin) < 1:f.write('            <xmin>' + str(int(xmin + 1)) + '</xmin>\n')else:f.write('            <xmin>' + str(int(xmin)) + '</xmin>\n')if int(ymin) < 1:f.write('            <ymin>' + str(int(ymin + 1)) + '</ymin>\n')else:f.write('            <ymin>' + str(int(ymin)) + '</ymin>\n')if int(xmax < 1):f.write('            <xmax>' + str(int(xmax + 1)) + '</xmax>\n')else:f.write('            <xmax>' + str(int(xmax)) + '</xmax>\n')if int(ymax < 1):f.write('            <ymax>' + str(int(ymax + 1)) + '</ymax>\n')else:f.write('            <ymax>' + str(int(ymax)) + '</ymax>\n')f.write('        </bndbox>\n')f.write('    </object>\n')f.write('</annotation>')if __name__ == '__main__':img_names = os.listdir(img_path)rect_names = os.listdir(rect_path)img_names.sort()rect_names.sort()for img_name, rect_name in zip(img_names, rect_names):full_image_path = os.path.join(img_path, img_name)full_rect_path = os.path.join(rect_path, rect_name)h, w, c, basename = read_image(full_image_path)bbox = get_object_bbox(full_rect_path)print('writing {}\\{}.xml'.format(xml_path,os.path.splitext(basename)[0]))write_xml(h, w, c, bbox, basename)

训练结果
重新制作数据集后,训练过程如下:


从图中可以看出loss_l L已经正常并且开始下降,说明数据集格式正确了,结果由于网络还在训练,所以还没有test结果,但至少说明开始正确训练了,至于mAP能有多少还得调参哈哈哈(请叫我调参侠)。

总结

目标检测中若遇到loss为nan的情况,
首先,检查数据集格式问题。如bbox的xmin,ymin是否大于xmax,ymax,或者坐标是否存在为0的情况。
其次,检查网络结构是否存在问题。
还有,训练的方法是否有问题。

希望我的经验能帮助遇到类似问题的朋友,少掉点头发,少走点弯路。

参考

https://www.zhihu.com/question/49346370
https://mp.weixin.qq.com/s/TMRDhDrf5rRRFIdGGL8Uhg

目标检测--RFBNet训练自己制作数据集出现loss=nan问题的解决方法相关推荐

  1. 深度学习实战(七)——目标检测API训练自己的数据集(R-FCN数据集制作+训练+测试)

    TensorFlow提供的网络结构的预训练权重:https://cloud.tencent.com/developer/article/1006123 将voc数据集转换成.tfrecord格式供te ...

  2. 【全网最详细yolov6】yoloV6调试记录(含训练自己的数据集及常见报错及解决方法)--持续更新ing

    本文手把手教你如何调试最新的yolov6,复现运行COCO2017及训练自己的数据集,目前该项目刚发布,BUG会比较多,调起来一般不会那么顺利,本文含windows+ubuntu,并给出了一些常见问题 ...

  3. paddledet 训练旋转目标检测 ppyoloe-r 训练自己的数据集

    1.数据转换 labelme2coco,原来是labelme标注的points 通过opencv转为4个坐标 # encoding=utf-8 import argparse import colle ...

  4. YOLO目标检测,训练自己的数据集(识别海参)

    向AI转型的程序员都关注了这个号

  5. [数据集][VOC][目标检测]河道垃圾水面漂浮物数据集目标检测可用yolo训练-1304张介绍

    数据集格式:Pascal VOC格式(不包含分割路径的txt文件和yolo格式的txt文件,仅仅包含jpg图片和对应的xml) 图片数量(jpg文件个数):1304 标注数量(xml文件个数):130 ...

  6. 目标检测任务中常用的数据集格式(voc、coco、yolo)

    在目标检测任务中,常见的数据集格式有三种,分别为voc(xml).coco(json).yolo(txt). 一.Pascal VOC Pascal VOC数据集是目标检测的常用的大规模数据集之一,从 ...

  7. 浙江大学 | 深度域自适应和小目标检测挑战、技术和数据集:调研

    来源:专知本文为论文,建议阅读5分钟 本文对域自适应目标检测(DDA-OD)和小目标检测(tiny OD)两大检测方向进行全面调研,详细介绍了代表性算法.涨点技术和相关数据集. 论文标题: A Sur ...

  8. YOLOV3目标检测模型训练实例

    YOLOV3目标检测 从零开始学习使用keras-yolov3进行图片的目标检测,比较详细地记录了准备以及训练过程,提供一个信号灯的目标检测模型训练实例,并提供相关代码与训练集. DEMO测试 YOL ...

  9. 基于mmdetection 旋转目标检测(OBB detection)+DOTA数据集自定义数据集+配docker

    这两周得益于组里的任务需求,肝了一个遥感类的飞机旋转框目标检测,在给定的4096*4096的大尺度分辨率图片上去识别检测飞机. 经过模型检测后输出结果图如下图所示: 可以看到最终的结果还是不错的,通过 ...

最新文章

  1. php 多人游戏_「谁会是下一个王者农药」云服务器如何搭建游戏服务器?
  2. 域名转发与域名解析有什么区别?
  3. Java源码分析之HashMap(JDK1.8)
  4. 语音控制 python_用Python编程实现语音控制电脑
  5. 一些iis配置相关报错的参考
  6. PHP中如何实现 “在页面中一边执行一边输出” 的效果
  7. 异常-根据错误类型捕获异常
  8. 全网爆红!全新洗脑神曲:程序员Disco
  9. Git cherry-pick后再merge出现一个“奇怪”的现象
  10. mysql account locked_ORA-28000: the account is locked用户锁定问题排查解决
  11. RedisTemplate存数据时指定过期时间
  12. sqlserver之创建视图
  13. python 将图像变为矢量图(可字符和序列化)
  14. 谷歌浏览器如何在不登录的情况下保存书签
  15. matlab 非支配排序,NSGA-II快速非支配排序算法理解
  16. spring boot+thymeleaf+layui实现后台管理系统界面
  17. WebRTC和APP互通连麦直播
  18. tomcat启动失败!‘Staring Tomcat v8.0 Server at localhost' has encountered a problem. failed to start
  19. 微信小程序正则表达式截取_微信小程序实现简单input正则表达式验证功能示例...
  20. QUALCOMM MDM9X15 LCD初始化流程

热门文章

  1. 如何设置计算机自动连接宽带,宽带自动连接设置,教您电脑怎么设置宽带自动连接...
  2. ZOJ 3426 HDU 3719 Snooker Referee
  3. 加薪不如发奖金? 穆穆-movno1
  4. 移动拨号上网开热点(不是360开热点,而是使用电脑自带的热点功能)详解
  5. android 装饰着模式,Android与设计模式——装饰者(Decorator)模式
  6. 三级管作为控制12V直流电机的开关
  7. 《给青年的十二封信》1-谈读书—朱光潜
  8. html报告致谢,论文致谢优秀范文(精选10篇)
  9. python怎么保存文件视频教程_python3将视频流保存为本地视频文件
  10. 计算机组成原理第二章笔记---计算机进化与性能