YOLOv5入门实践(3)——手把手教你划分自己的数据集

简介: YOLOv5入门实践(3)——手把手教你划分自己的数据集

前言

上一篇我们学习了如何利用labelimg标注自己的数据集,下一步就是该对这些数据集进行划分了。面对繁杂的数据集,如果手动划分的话不仅麻烦而且不能保证随机性。本篇文章就来手把手教你利用代码,自动将自己的数据集划分为训练集、验证集和测试集。一起来学习吧!

前期回顾:

YOLOv5入门实践(1)——手把手带你环境配置搭建

YOLOv5入门实践(2)——手把手教你利用labelimg标注数据集


  🍀本人YOLOv5源码详解系列:  

YOLOv5源码逐行超详细注释与解读(1)——项目目录结构解析

YOLOv5源码逐行超详细注释与解读(2)——推理部分detect.py

YOLOv5源码逐行超详细注释与解读(3)——训练部分train.py

YOLOv5源码逐行超详细注释与解读(4)——验证部分val(test).py

YOLOv5源码逐行超详细注释与解读(5)——配置文件yolov5s.yaml

YOLOv5源码逐行超详细注释与解读(6)——网络结构(1)yolo.py

YOLOv5源码逐行超详细注释与解读(7)——网络结构(2)common.py


一、训练集、测试集、验证集介绍

我们通常把训练的数据分为三个文件夹:训练集、测试集和验证集

我们来举一个栗子:模型的训练与学习,类似于老师教学生学知识的过程。

  • 1、训练集(train set):用于训练模型以及确定参数。相当于老师教学生知识的过程。
  • 2、验证集(validation set):用于确定网络结构以及调整模型的超参数。相当于月考等小测验,用于学生对学习的查漏补缺。
  • 3、测试集(test set):用于检验模型的泛化能力。相当于大考,上战场一样,真正的去检验学生的学习效果。

参数(parameters):指由模型通过学习得到的变量,如权重和偏置。

超参数(hyperparameters):指根据经验进行设定的参数,如迭代次数,隐层的层数,每层神经元的个数,学习率等。


二、准备自己的数据集

第1步:在YOLOv5项目下创建对应文件夹

在YOLOv5项目目录下创建datasets文件夹(名字自定义),接着在该文件夹下新建Annotationsimages文件夹。

  • Annotations:存放标注的标签文件
  • images:存放需要打标签的图片文件

如下图所示:


 第2步:打开labelimg开始标注数据集

使用教程可以看我的上一篇介绍: YOLOv5入门实践(2)——手把手教你利用labelimg标注数据集

标注后Annotations文件夹下面为xml文件,如下图所示:

images文件夹是我们的数据集图片,格式为jpg,如下图所示:


第3步:创建保存划分后数据集的文件夹

创建一个名为ImageSets的文件夹(名字自定义),用来保存一会儿划分好的训练集、测试集和验证集。


准备工作的注意事项:

  • 所有训练所需的图像存于一个目录,所有训练所需的标签存于一个目录。
  • 图像文件与标签文件都统一的格式。
  • 图像名与标签名一一对应。

三、划分的代码及讲解

完成以上工作我们就可以来进行数据集的划分啦!

第1步:创建split.py

在YOLOv5项目目录下创建split.py项目。


第2步:将数据集打乱顺序

通过上面我们知道,数据集有imagesAnnotations这两个文件,我们需要把这两个文件绑定,然后将其打乱顺序。

首先设置空列表,将for循环读取这两个文件的每个数据放入对应表中,再将这两个文件通过zip()函数绑定,计算总长度。

def split_data(file_path,xml_path, new_file_path, train_rate, val_rate, test_rate):
    each_class_image = []
    each_class_label = []
    for image in os.listdir(file_path):
        each_class_image.append(image)
    for label in os.listdir(xml_path):
        each_class_label.append(label)
    data=list(zip(each_class_image,each_class_label))
    total = len(each_class_image)

然后用random.shuffle()函数打乱顺序,再将两个列表解绑。

    random.shuffle(data)
    each_class_image,each_class_label=zip(*data)

第3步:按照确定好的比例将两个列表元素分割

分别获取train、val、test这三个文件夹对应的图片和标签。

    train_images = each_class_image[0:int(train_rate * total)]
    val_images = each_class_image[int(train_rate * total):int((train_rate + val_rate) * total)]
    test_images = each_class_image[int((train_rate + val_rate) * total):]
    train_labels = each_class_label[0:int(train_rate * total)]
    val_labels = each_class_label[int(train_rate * total):int((train_rate + val_rate) * total)]
    test_labels = each_class_label[int((train_rate + val_rate) * total):]

第4步:在本地生成文件夹,将划分好的数据集分别保存

接下来就是设置相应的路径保存格式,将图片和标签对应保存下来。

 for image in train_images:
        print(image)
        old_path = file_path + '/' + image
        new_path1 = new_file_path + '/' + 'train' + '/' + 'images'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + image
        shutil.copy(old_path, new_path)
    for label in train_labels:
        print(label)
        old_path = xml_path + '/' + label
        new_path1 = new_file_path + '/' + 'train' + '/' + 'labels'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + label
        shutil.copy(old_path, new_path)
    for image in val_images:
        old_path = file_path + '/' + image
        new_path1 = new_file_path + '/' + 'val' + '/' + 'images'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + image
        shutil.copy(old_path, new_path)
    for label in val_labels:
        old_path = xml_path + '/' + label
        new_path1 = new_file_path + '/' + 'val' + '/' + 'labels'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + label
        shutil.copy(old_path, new_path)
    for image in test_images:
        old_path = file_path + '/' + image
        new_path1 = new_file_path + '/' + 'test' + '/' + 'images'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + image
        shutil.copy(old_path, new_path)
    for label in test_labels:
        old_path = xml_path + '/' + label
        new_path1 = new_file_path + '/' + 'test' + '/' + 'labels'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + label
        shutil.copy(old_path, new_path)

第5步:设置路径并设置划分比例

这里要设置的有三个:

  • file_path:图片所在位置,就是image文件夹
  • xml_path:标签所在位置,就是Annotation文件夹
  • new_file_path:划分后三个文件的保存位置,就是ImageSets文件夹
if __name__ == '__main__':
    file_path = "D:\yolov5-6.1\datasets\image"
    xml_path = "D:\yolov5-6.1\datasets\Annotation"
    new_file_path = "D:\yolov5-6.1\datasets\ImageSets"
    split_data(file_path,xml_path, new_file_path, train_rate=0.7, val_rate=0.1, test_rate=0.2)

最后一行是设置划分比例,这里的比例分配大家可以随便划分,我选取的是7:1:2。

至此,我们的数据集就划分好了。

来运行一下看看效果吧:

我们可以看到,数据集图片和标签已经划分成了train、val和test三个文件夹。

比例也符合7:1:2


split.py完整代码

import os
import shutil
import random
random.seed(0)
def split_data(file_path,xml_path, new_file_path, train_rate, val_rate, test_rate):
    each_class_image = []
    each_class_label = []
    for image in os.listdir(file_path):
        each_class_image.append(image)
    for label in os.listdir(xml_path):
        each_class_label.append(label)
    data=list(zip(each_class_image,each_class_label))
    total = len(each_class_image)
    random.shuffle(data)
    each_class_image,each_class_label=zip(*data)
    train_images = each_class_image[0:int(train_rate * total)]
    val_images = each_class_image[int(train_rate * total):int((train_rate + val_rate) * total)]
    test_images = each_class_image[int((train_rate + val_rate) * total):]
    train_labels = each_class_label[0:int(train_rate * total)]
    val_labels = each_class_label[int(train_rate * total):int((train_rate + val_rate) * total)]
    test_labels = each_class_label[int((train_rate + val_rate) * total):]
    for image in train_images:
        print(image)
        old_path = file_path + '/' + image
        new_path1 = new_file_path + '/' + 'train' + '/' + 'images'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + image
        shutil.copy(old_path, new_path)
    for label in train_labels:
        print(label)
        old_path = xml_path + '/' + label
        new_path1 = new_file_path + '/' + 'train' + '/' + 'labels'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + label
        shutil.copy(old_path, new_path)
    for image in val_images:
        old_path = file_path + '/' + image
        new_path1 = new_file_path + '/' + 'val' + '/' + 'images'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + image
        shutil.copy(old_path, new_path)
    for label in val_labels:
        old_path = xml_path + '/' + label
        new_path1 = new_file_path + '/' + 'val' + '/' + 'labels'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + label
        shutil.copy(old_path, new_path)
    for image in test_images:
        old_path = file_path + '/' + image
        new_path1 = new_file_path + '/' + 'test' + '/' + 'images'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + image
        shutil.copy(old_path, new_path)
    for label in test_labels:
        old_path = xml_path + '/' + label
        new_path1 = new_file_path + '/' + 'test' + '/' + 'labels'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + label
        shutil.copy(old_path, new_path)
if __name__ == '__main__':
    file_path = "D:\yolov5-6.1\datasets\image"
    xml_path = "D:\yolov5-6.1\datasets\Annotation"
    new_file_path = "D:\yolov5-6.1\datasets\ImageSets"
    split_data(file_path,xml_path, new_file_path, train_rate=0.7, val_rate=0.1, test_rate=0.2)

本文参考:

三天玩转yolo——数据集格式转化及训练集和验证集划分 - 知乎 (zhihu.com)

【yolov5】将标注好的数据集进行划分(附完整可运行python代码)

相关文章
|
编解码 缓存 并行计算
YOLOv5入门实践(4)——手把手教你训练自己的数据集
YOLOv5入门实践(4)——手把手教你训练自己的数据集
2245 0
YOLOv5入门实践(4)——手把手教你训练自己的数据集
|
机器学习/深度学习 并行计算 计算机视觉
YOLOv5入门实践(5)——从零开始,手把手教你训练自己的目标检测模型(包含pyqt5界面)
YOLOv5入门实践(5)——从零开始,手把手教你训练自己的目标检测模型(包含pyqt5界面)
7037 1
YOLOv5入门实践(5)——从零开始,手把手教你训练自己的目标检测模型(包含pyqt5界面)
|
5月前
|
机器学习/深度学习 数据可视化 TensorFlow
【手把手教学】如何可视化YOLOv8深度学习的网络结构并保存
【手把手教学】如何可视化YOLOv8深度学习的网络结构并保存
|
6月前
|
机器学习/深度学习 数据可视化
模型性能评价实战
模型性能评价实战
|
6月前
|
机器学习/深度学习 存储 算法
【轻量化:实操】动手实现神经网络中的裁枝操作(附演示代码&yolo系列)
【轻量化:实操】动手实现神经网络中的裁枝操作(附演示代码&yolo系列)
189 1
|
XML 计算机视觉 数据格式
YOLOv5入门实践(2)——手把手教你利用labelimg标注数据集
YOLOv5入门实践(2)——手把手教你利用labelimg标注数据集
6867 1
YOLOv5入门实践(2)——手把手教你利用labelimg标注数据集
|
机器学习/深度学习 计算机视觉 Python
手把手带你调参Yolo v5 (v6.2)(推理)(一)
手把手带你调参Yolo v5 (v6.2)(推理)
手把手带你调参Yolo v5 (v6.2)(推理)(一)
|
机器学习/深度学习 自然语言处理
小白总结Transformer模型要点(一)(下)
本文主要总结了Transformer模型的要点,包含模型架构各部分组成和原理、常见问题汇总、模型具体实现和相关拓展学习。
小白总结Transformer模型要点(一)(下)
|
机器学习/深度学习 自然语言处理
小白总结Transformer模型要点(二)(上)
本文主要总结了Transformer模型的要点,包含模型架构各部分组成和原理、常见问题汇总、模型具体实现和相关拓展学习。
小白总结Transformer模型要点(二)(上)
|
机器学习/深度学习 自然语言处理 并行计算
小白总结Transformer模型要点(一)(上)
本文主要总结了Transformer模型的要点,包含模型架构各部分组成和原理、常见问题汇总、模型具体实现和相关拓展学习。
小白总结Transformer模型要点(一)(上)
下一篇
无影云桌面