前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >YOLOv5超详细的入门级教程(训练篇)(二)——VOC2007模型复现

YOLOv5超详细的入门级教程(训练篇)(二)——VOC2007模型复现

作者头像
润森
发布2022-08-18 10:14:28
1.3K0
发布2022-08-18 10:14:28
举报
文章被收录于专栏:毛利学Python

Pytorch-YOLOv5

经过的学习后,明白了训练模型的全套流程,现在我们的问题是如何提升模型的性能?非常重要的一个环节便是数据集,一个好的数据集对于模型性能是至关重要的。我们首先利用VOC2007数据集来对模型进行复现

利用VOC2007对模型进行训练

下载VOC2007数据集

  • 首先,附上VOC数据集下载链接。我们选择的是VOC2007数据集,可以看到现在最新版本的数据集是VOC2012,数量也多了很多。需要下载训练集和测试集:

- TIPS:用迅雷下载速度起飞哦!!!(之前我只下载了训练集,在这里补下测试集)

- 将两个压缩文件在同一级目录下解压到当前文件夹,两个压缩包的内容会合并在VOCdevkit

- 恍然大悟,原来加上了测试集之后,VOC2007数据集就是正常人能理解的排序了。当看到训练集中第一个图片000005.jpg时云里雾里。

转换为YOLO标注格式的文件

  • 这时我们对于VOC2007数据集有了进一步的理解,有以下文件:

我们做的时目标检测任务,而且不是人的动作识别(具有人体部位的数据)(layout是做这个任务的)所以上述的SegmentationClass,SegmentationObject,Layout,Segmentation文件夹我们都不需要。- 在data目录下,放入VOCdevkit(包括了一整个VOC2007数据集),在相同的文件夹内创建voc2yolo.py,内容如下,并运行

代码语言:javascript
复制
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
 
# 这里就体现出来了咱们在1.2步骤的时候我说的尽量按照那个目录名进行操作的优势,
# 在这可以剩下很多去修改名称的精力
# sets=[('2012', 'train'), ('2012', 'val'), ('2007', 'train'), ('2007', 'val'), ('2007', 'test')]
sets=[ ('2007', 'train'), ('2007', 'val'), ('2007', 'test')]  # 我只用了VOC2007
 
classes = ["aeroplane", "bicycle", "bird", "boat", "bottle",
           "bus", "car", "cat", "chair", "cow",
           "diningtable", "dog", "horse", "motorbike", "person",
           "pottedplant", "sheep", "sofa", "train", "tvmonitor"]
#classes = ["face"]  # 修改为自己的label
 
def convert(size, box):
    dw = 1./(size[0])  # 有的人运行这个脚本可能报错,说不能除以0什么的,你可以变成dw = 1./((size[0])+0.1)
    dh = 1./(size[1])  # 有的人运行这个脚本可能报错,说不能除以0什么的,你可以变成dh = 1./((size[0])+0.1)
    x = (box[0] + box[1])/2.0 - 1
    y = (box[2] + box[3])/2.0 - 1
    w = box[1] - box[0]
    h = box[3] - box[2]
    x = x*dw
    w = w*dw
    y = y*dh
    h = h*dh
    return (x,y,w,h)
 
def convert_annotation(year, image_id):
    in_file = open('VOCdevkit/VOC%s/Annotations/%s.xml'%(year, image_id))
    out_file = open('VOCdevkit/VOC%s/labels/%s.txt'%(year, image_id), 'w')
    tree=ET.parse(in_file)
    root = tree.getroot()
    size = root.find('size')
    w = int(size.find('width').text)
    h = int(size.find('height').text)
 
    for obj in root.iter('object'):
        difficult = obj.find('difficult').text
        cls = obj.find('name').text
        if cls not in classes or int(difficult)==1:
            continue
        cls_id = classes.index(cls)
        xmlbox = obj.find('bndbox')
        b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))
        bb = convert((w,h), b)
        out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
 
wd = getcwd()
 
for year, image_set in sets:
    if not os.path.exists('VOCdevkit/VOC%s/labels/'%(year)):
        os.makedirs('VOCdevkit/VOC%s/labels/'%(year))
    image_ids = open('VOCdevkit/VOC%s/ImageSets/Main/%s.txt'%(year, image_set)).read().strip().split()
    list_file = open('%s_%s.txt'%(year, image_set), 'w')
    for image_id in image_ids:
        list_file.write('%s/VOCdevkit/VOC%s/JPEGImages/%s.jpg\n'%(wd, year, image_id))
        convert_annotation(year, image_id)
    list_file.close()
 
# 这块是路径拼接,暂时用不上,先都注释了
# os.system("cat 2007_train.txt 2007_val.txt 2012_train.txt 2012_val.txt > train.txt")
# os.system("cat 2007_train.txt 2007_val.txt 2007_test.txt 2012_train.txt 2012_val.txt > train.all.txt")

可以看到生成了三个数据集的路径txt文件,和label文件夹。

修改配置文件

还是原来的步骤,我们继续巩固以下~

1. 修改voc.yaml文件

这里我们直接修改voc.yaml的文件,可以看到还有coco.yaml文件,其实就是你的数据集的配置文件罢了!!

代码语言:javascript
复制
# PASCAL VOC dataset http://host.robots.ox.ac.uk/pascal/VOC/
# Download command: bash ./data/get_voc.sh
# Train command: python train.py --data voc.yaml
# Default dataset location is next to /yolov5:
#   /parent_folder
#     /VOC
#     /yolov5
 
 
# train and val data as 1) directory: path/images/, 2) file: path/images.txt, or 3) list: [path1/images/, path2/images/]
train: F:\AI\datasets\VOC2007\VOCdevkit\VOC2007\2007_train.txt
val: F:\AI\datasets\VOC2007\VOCdevkit\VOC2007\2007_val.txt
 
# number of classes
nc: 20
 
# class names
names: ['aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat', 'chair', 'cow', 'diningtable', 'dog',
        'horse', 'motorbike', 'person', 'pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor']

可以看到博主把常用数据集都放在了一个路径里,整理在一起!!值得学习

2.修改yolov5s.yaml文件

该文件需要修改的地方是第2行nc的个数,需要改成自己数据集类别的个数,对于VOC数据集改成20。

3. 修改train.py

其他的一些超参数自行修改即可。

出现了的问题

  1. 发现原博主的数据路径用的是/,但是在win下用的是\,所以找不到label(可能是这个原因) 把voc2yolo.py中最后的代码修改为
代码语言:javascript
复制
 list_file.write('%s/VOCdevkit/VOC%s/JPEGImages/%s.jpg\n'%(wd, year, image_id))
 换成
  list_file.write('%s\VOCdevkit\VOC%s\JPEGImages\%s.jpg\n'%(wd, year, image_id))

  1. 但是发现还是找不到label,我们把将里面所有txt文件复制到 [ VOCdevkit\VOC2007\JPEGImages ]中即可。1. 这时,常规错误出现了

这类报错原因是显卡内存太小了,一次装不下太多的图片,因此可以通过–batch-size调整每个批次样本的个数,默认值是16。报错后可以调整为8试试,如果还是报错,再调整为4试试,如果还是报错,那请找一把锤子,瞄准电脑主机箱用力地砸下去…我的batch-size已经改成1了伙计们。。那下一个教程咱们就利用远程服务器来进行模型训练吧!~

解决之前的一些疑惑?

PASCAL_VOC中的正负样本

  • Main文件夹下可以看到很多的txt文件,作用是什么呢?就是分出test集、train集和val集。还有一个trainval集(train+val和合集嘛) 刚打开的时候发现有84个txt文件,其中有四个不带前缀,剩下的80个呢分别对应了VOC中的20个类别的四个数据集txt文件。

traintesttrainvalval里面的内容如下,就是很常规的划分数据集:

- 但是在那20个类别的数据对应的traintest…文件中,除了划分数据之外,还做了正负样本的标注

  • 这个1-1所代表的正负样本究竟是什么呢?
    • 在机器学习中,数据预处理一般包括数据清洗数据集成数据采样。而正负样本涉及到了数据采样的问题,因此后面也提一下。- 简单来说,和概率论中类似,一般我们看一个问题时,只关注一个事件(希望它发生或者成功,并对其进行分析计算),而正样本就是属于我们关注的这一类别的样本,负样本就是指不属于该类别的样本。- 一般来说,比如我们训练分类器时,希望样本中正负样本的比例是接近于1:1的。因为如果正样本占比很大(比如90%)或者负样本占比远超正样本,那么训练结果可想而知,获得的分类器在测试中的效果会很差。(这也得出了为什么我们在中的检测器效果很差的原因,60张图片全是奇奇怪怪的正样本)

数据采样平衡

所以在进行数据采样时,如何解决数据不平衡的问题呢?

1.过采样(over-sampling)

这是一种较为直接的办法,即通过随机复制少数类来增加其中的实例数量,从而可增加样本中少数类的代表性。

2.欠采样(under-sampling)

这种方法也比较直接,即通过随机消除占多数类的样本来平衡类分布,直到多数类和少数类实现平衡。

3.获取更多样本

上面的两种方法比较直接方便,但也存在弊端,比如过采样可能会导致过拟合,欠采样可能无法很好地利用有限的数据(这也可能会造成过拟合)。因此最好还是获取更多的样本来补充,我认为主要有下面两种方法:

  1. 采集 例如在海贼王漫画的样本中,我们要进行20x20大小的海贼检测,那么为了获取尽可能多的负样本,我们可以截取一张1000x1000大小的海王类图像,将其拆分为20x20大小的片段加入到负样本中(即50x50地进行分割)。1. 生成 为了获得更多负样本,我们也可将前面1000x1000的海王类图像先拆分为10x10大小,这就比之前多出了4倍的负样本图像。不过要注意的是,为了保持大小的一致,还需进一步将其拉伸至20x20的大小。当然,其实不需要从体积上达到这么大的比例,关键是像素尺寸的匹配

References

  1. 手把手教会使用YOLOv5训练VOC2007数据集 皇天不负有心人,在我想要探索的时候已经有好心人把路摸索好了,可以愉快的跟随前人的经验!(这个博主的帖子非常的清晰)1. PASCAL VOC数据集分析1. machine learning笔记:数据采样之正样本和负样本 通俗易懂,但是网站总是出bug啊,网页五光十色的。。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-10-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小刘IT教程 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Pytorch-YOLOv5
  • 利用VOC2007对模型进行训练
    • 下载VOC2007数据集
      • 转换为YOLO标注格式的文件
        • 修改配置文件
          • 1. 修改voc.yaml文件
          • 2.修改yolov5s.yaml文件
          • 3. 修改train.py
        • 出现了的问题
        • 解决之前的一些疑惑?
          • PASCAL_VOC中的正负样本
            • 数据采样平衡
              • 1.过采样(over-sampling)
              • 2.欠采样(under-sampling)
              • 3.获取更多样本
          • References
          相关产品与服务
          图像识别
          腾讯云图像识别基于深度学习等人工智能技术,提供车辆,物体及场景等检测和识别服务, 已上线产品子功能包含车辆识别,商品识别,宠物识别,文件封识别等,更多功能接口敬请期待。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档