使用Yolov4训练自己的数据集(cyq)

一、什么是Yolov4?

因个人对Yolov4的理解不够清晰和深刻,如果片面的来说明会导致读者产生误解,所以理论部分建议大家看一些更权威的论文或者博客,知乎文章等,比如:

睿智的目标检测30——Pytorch搭建YoloV4目标检测平台-CSDN博客
https://blog.csdn.net/weixin_44791964/article/details/106214657
本实验基于代码Github开源代码:
bubbliiiing/yolov4-pytorch: 这是一个YoloV4-pytorch的源码,可以用于训练自己的模型。 (github.com)
https://github.com/bubbliiiing/yolov4-pytorch

二、数据准备
实践是检验真理的唯一标准,话不多说,上手实操,首先我们选用的是飞桨AI Studio星河社区的水果分类目标检测VOC数据集(说白了就是手机摄像头坏了人也懒)

水果分类目标检测VOC数据集_数据集-飞桨AI Studio星河社区 (baidu.com)
https://aistudio.baidu.com/datasetdetail/92360


这个数据集主要有dragon fruit,snake fruit,pineapple(火龙果、蛇果、菠萝)三种水果的图片共计200张,数据集图片和标签是分开的,比较方便(懒就是懒,你还方便上了)

1.划分数据集


项目的主干结构如上图,数据集的命名其实已经很清楚了,就是Annotations文件夹放标签,ImageSets文件夹放图片,如果是自己找的标注的图片,标注完成后最好一个Annotations文件夹放标签,一个ImageSets文件夹放图片(便于后期对应),然后统一格式命名(用Python实现即可),示例如下(只是结构示例,并非真实可靠数据集,娱乐所作):          
# 设置源文件夹和目标文件夹
source_folder = '这里是需要转换的文件夹路径'
target_folder = '这里是转换输出的文件夹路径'
 
# 检查目标文件夹是否存在,如果不存在则创建
if not os.path.exists(target_folder):
    os.makedirs(target_folder)
 
# 遍历源文件夹中的所有文件
for file_name in os.listdir(source_folder):
    if file_name.endswith('.png'):
        # 读取PNG图片
        img_path = os.path.join(source_folder, file_name)
        img = Image.open(img_path)
 
        # 转换为JPEG
        rgb_im = img.convert('RGB')
 
        # 保存JPEG图片
        target_file_name = file_name[:-4] + '.jpg'
        target_img_path = os.path.join(target_folder, target_file_name)
        rgb_im.save(target_img_path, 'JPEG')
 
        # 删除原始PNG图片
        os.remove(img_path)
 
print("转换并删除原始PNG图片完成!")

2.处理数据集
如果是自己找的图片,并使用labelImg标注的话,这里有一些小tips,绿框框住的部分选择PascalVOC,这样标签文件会是xml格式,如果选择yolo标签文件是txt格式,不方便后续项目的进行。

这一步简单来说就是把训练自己的数据集时xml标签文件放入VOCdevkit文件夹下的VOC2007文件夹下的Annotation文件夹中,jpg图片文件放在VOCdevkit文件夹下的VOC2007文件夹下的JPEGImages文件夹中即可,如图所示:

voc_annotation.py里面有一些参数需要设置,分别是annotation_mode、classes_path、trainval_percent、train_percent、VOCdevkit_path,第一次训练可以仅修改classes_path。

classes_path        = 'model_data/cls_classes.txt'
classes_path用于指向检测类别所对应的txt,训练自己的数据集时,可以自己建立一个cls_classes.txt(或者你想要的名字都可),里面写自己所需要区分的类别。以我的数据集为例,我用的cls_classes.txt为:

就是想要检测的类别是什么就写什么,但要和数据集的类别一致,比如数据集的类别是苹果和椰子,cls_classes.txt里写类别是榴莲和菠萝,这样肯定是不合理的。

三、环境准备
1.环境内容
电脑硬件配置:

设备名称    BBBQL
处理器    11th Gen Intel(R) Core(TM) i7-11700 @ 2.50GHz   2.50 GHz
机带 RAM    16.0 GB (15.9 GB 可用)
显卡 NVIDIA GeForce RTX 2060 6G(如果用Cuda跑得用N卡,也就是大家说的英伟达的显卡)

电脑软件配置:

PyCharm 2024.1 (Professional Edition)(喜欢vscode用vscode,喜欢命令行用命令行,看个人喜好,此处仅提供具体环境作为参照)

Anaconda3-2024.02-1-Windows-x86_64 (有Conda不用挨个找不同Python安装了)

2.环境配置
python 3.9

Package                 Version
----------------------- ------------
absl-py                 2.1.0
bigtree                 0.17.0
chardet                 5.2.0
colorama                0.4.6
contourpy               1.2.1
cycler                  0.12.1
filelock                3.13.4
fonttools               4.51.0
fsspec                  2024.3.1
graphviz                0.20.3
grpcio                  1.62.1
h5py                    3.11.0
importlib_metadata      7.1.0
importlib_resources     6.4.0
install                 1.3.5
Jinja2                  3.1.3
kiwisolver              1.4.5
Markdown                3.6
MarkupSafe              2.1.5
matplotlib              3.8.4
mpmath                  1.3.0
networkx                3.2.1
numpy                   1.26.4
opencv-python           4.9.0.80
packaging               24.0
Pillow                  9.5.0
pip                     23.3.1
protobuf                5.26.1
pydot                   2.0.0
pyparsing               3.1.2
python-dateutil         2.9.0.post0
scipy                   1.13.0
setuptools              68.2.2
six                     1.16.0
sympy                   1.12
tensorboard             2.16.2
tensorboard-data-server 0.7.2
torch                   2.2.1+cu121
torchaudio              2.2.1+cu121
torchvision             0.17.1+cu121
tqdm                    4.66.2
typing_extensions       4.11.0
Werkzeug                3.0.2
wheel                   0.41.2
zipp                    3.18.1
同样,此处仅提供具体环境作为参照,便于训练自己数据集时复现。

下面以Pycharm专业版(社区版也一样)为例,手把手复现环境搭建(个人习惯,习惯性环境隔离,每个项目一个解释器):

第一步,打开设置,点击“项目”下的“Python解释器”选项(英文差用了中文插件,见谅);

第二步,点击“添加解释器”然后选择“添加本地解释器”;

第三步,点击“Conda环境”,“创造新环境”,环境名称喜欢什么用什么(用中文会伤心的OK),Python版本我选择的3.9,因为很多教程都是3.6版本的感觉麻烦还是用稍微新一点的版本了。

中场休息,如果上一步,没有安装Anaconda的同学就不一定能到Conda环境这一步了,如果说没有安装的可以参考下面的Anaconda安装教程,conda国内镜像源可加可不加,因为不少conda国内镜像源不能正常工作了,安装的时候记得勾选“Add Anaconda3 to the system PATH environment variable",这样就直接添加到系统环境变量了,不用手动配置环境变量


第四步,成功创建完新的虚拟环境之后,设置里就会直接显示并使用新的环境了,这时候点击“应用”,然后点“确定”,正常会自动切换虚拟环境。

第五步,点击左下角“终端”图标,打开就是新环境,如果创建环境之前是之前的虚拟环境的话需要手动激活,或者重启终端,也可以在终端手动创建conda环境并激活,来去自如,激活命令示例:


3.安装依赖
养成好习惯,有requirements.txt先看requirements.txt,这里是把所需要的包都罗列出来了,如果只想用CPU训练数据集和预测,可以直接安装,如果是想要GPU和Cuda训练和预测数据集,记得删除torch和torchvision那两行,不然后面会搞事情,具体是什么事情的后面会提到。

第一步,既然有了requirements.txt,在终端直接无脑输入,

pip install -r requirements.txt
这里如果真无脑输入了,会不会发现少点什么,当然是我们老生常谈的Pip换源

常用Pip国内镜像源:

清华:https://pypi.tuna.tsinghua.edu.cn/simple/
阿里云:http://mirrors.aliyun.com/pypi/simple/
中国科技大学:https://pypi.mirrors.ustc.edu.cn/simple/
华中科技大学:http://pypi.hustunique.com/simple/
上海交通大学:https://mirror.sjtu.edu.cn/pypi/web/simple/
豆瓣:http://pypi.douban.com/simple/
国内开源镜像网站集合汇总(最全,可用) - 知乎 (zhihu.com)
https://zhuanlan.zhihu.com/p/609597886
注: 新版ubuntu系统要求使用https源。

一般来说,镜像源没有最快,只有更快(相对而言)用法示例如下:

pip install <安装包> -i <镜像源>
 
pip install -r requirements.txt -i http://mirrors.aliyun.com/pypi/simple/
然后其余的库缺啥补啥,方法跟上面一样,比如我下了tqdm,h5py等库,用了镜像都很快,如果要用CUDA,这一步先不要下载下面这三个库。

torch 
torchaudio
torchvision 
如果真的相信自己的CPU足够强大可以直接用cpu版本的PyTorch(自行配置镜像源)

pip install torch==2.2.1 torchvision==0.17.1 torchaudio==2.2.1 --index-url https://download.pytorch.org/whl/cpu
其他CPU版本的Pytorch下载命令:

Previous PyTorch Versions | PyTorch
https://pytorch.org/get-started/previous-versions/

第二步,既然都用上PyTorch了,那么CUDA肯定是要用的咯,那么安装CUDA是必不可少的一步

先看自己的电脑支持什么最高版本的CUDA,右键打开“NVIDIA设置”(红框部分)->选择“NVIDIA控制面板”->选择左下角的系统信息->组件

比如我的电脑最高是可以支持12.4版本的CUDA的,知道最高支持版本之后,我们就可以在小于等于该版本的CUDA中选择了。

如果觉得上述步骤麻烦不好操作,在显卡驱动正确安装的前提下可以直接用命令行(Win+R召唤运行,然后输入CMD),然后在命令行输入:

nvidia-smi.exe


这里会直接显示显卡支持的最高的CUDA版本,同样知道最高支持版本之后,我们就可以在小于等于该版本的CUDA中选择了。

Windows安装CUDA ,还需要下载一些其他的东西:

(1)CUDA toolkit(toolkit就是指工具包)

 官方教程:(可能需要魔法)
Installation Guide Windows :: CUDA Toolkit Documentation
https://docs.nvidia.com/cuda/cuda-installation-guide-microsoft-windows/index.html

(2)cuDNN

 官方教程:(可能需要魔法)

Installation Guide :: NVIDIA Deep Learning cuDNN Documentation
https://docs.nvidia.com/deeplearning/sdk/cudnn-install/index.html#installwindows

(3)Visual Studio2022(使用C++的桌面开发,这里我已经安装过了,为了截张图重新走了遍安装流程)


这里由于CUDA安装教程过长,占用太多篇幅可能会比较枯燥乏味(实在是懒得写了哈哈哈哈哈哈哈哈哈),建议直接搜索相关教程,或者参考一些比较详细的博客,例如:

win11下安装Cuda和Cudnn(pytorch+GPU环境安装),保姆级教程!!!_cudnn-windows-x86_64-8.7.0.84_cuda11-archive-CSDN博客
https://blog.csdn.net/qq_36623004/article/details/127228147

Pytorch、CUDA和cuDNN的安装图文详解win11(解决版本匹配问题) - 知乎 (zhihu.com)
https://zhuanlan.zhihu.com/p/641832733

CUDA安装及环境配置——最新详细版-CSDN博客
https://blog.csdn.net/chen565884393/article/details/127905428
第三步,检查CUDA是否安装成功,老办法(Win+R召唤运行,然后输入CMD),然后在命令行输入:

nvcc -V


出现了你的CUDA版本信息,说明安装成功了。要是还想测试一下能不能用,CUDA也有测试工具测着玩,我的安装路径是:

C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.1\extras\demo_suite

具体路径看用的人安装的路径,在demo_suite文件夹执行CMD,或者也可以在命令行跳到这个文件夹都可,查询一下本机的gpu设备,输入:

deviceQuery


再来测试一下带宽,输入

bandwidthTest


能看出结果都是PASS,说明一切运行正常

第四步,安装CUDA版本的torch,torchaudio,torchvision三个库

命令如下(如果网速尚可不要用镜像,因为镜像源总是下成CPU版本的Pytorch):

这里以Windows,CUDA 12.1,PyTorch 2.2.1版为例:

# CUDA 12.1
pip install torch==2.2.1 torchvision==0.17.1 torchaudio==2.2.1 --index-url https://download.pytorch.org/whl/cu121
找到适合自己CUDA版本的PyTorch版本下载即可,可选版本很多:

再贴一遍PyTorch下载命令链接:
Previous PyTorch Versions | PyTorch
https://pytorch.org/get-started/previous-versions/


第五步,在Python里测试下载好的CUDA版本的PyTorch是否可用

一个简单的测试代码,瞎写的:

import torch
import torchaudio
import torchvision
print(torch.__version__) #输出torch版本
print(torchaudio.__version__) #输出torchaudio版本
print(torchvision.__version__) #输出torchvision版本
print(torch.cuda.is_available())  # 如果这个命令返回True,那么PyTorch可以使用CUDA
正确的CUDA版本PyTorch输出结果:

错误的CPU版本PyTorch输出结果:(仅为打印出来的示例,具体是否输出内容是这些我也忘了)

也有PyTorch不完全是CUDA版本的情况:(torchvision明显是cpu版本,总之是坑,谨记避雷!)

到此为止,我们前期的环境准备流程基本结束。

四、训练数据
1.运行voc_annotation.py
处理数据集修改了classes_path并对应自己的类别文件就可以直接运行,输出结果示例如下:

这个代码的主要作用如下:

设置处理模式 (annotation_mode):

根据设定的模式,可以只生成数据集的划分文件(例如训练集、验证集),或者同时生成这些划分并且创建包含具体标注信息的文本文件。
设定类别信息 (classes_path):

指定一个文件,该文件包含了数据集中所有目标的类别名称,用于区分不同的物体。
数据集划分比例 (trainval_percent 和 train_percent):

设定训练集和验证集的数量比例,以及它们两者与测试集的数量比例。
处理VOC数据集:

从标注文件(XML文件)中提取出目标的类别和对应的边界框(bounding box)坐标。
根据提供的类别信息和标注,包括目标的难易程度(difficult),生成特定于训练的文本文件,这些文件包含了用于训练目标检测模型的必要信息。
输出的文件格式通常是一个图片文件的路径,后面跟着该图片中所有标注对象的类别索引和边界框坐标。
自动化标注文件创建与数据集划分:

自动生成用于训练、验证和测试的数据划分文件(如train.txt, val.txt, test.txt)。
这样可以简化后续模型训练时的数据准备工作,因为模型可以直接读取这些划分文件来获取必要的训练和验证数据。
统计信息输出:

在处理完毕后,代码还会输出一些统计信息,比如每个类别的目标数量,以及提醒信息,例如如果训练集的数量较小或者某些类别没有目标。
总而言之,这段代码的主要作用是从标注的XML文件中提取出目标检测任务所需的信息,并自动创建相应的训练、验证和测试划分文件,方便进行后续的模型训练和评估工作。

2.运行train.py
这个train.py代码可以改的参数很多,第一次训练咱们化繁为简,成功了再谈改进,如果CUDA成功安装了并安装了CUDA版本的PyTorch就把Cuda参数设置为True,用cpu可以不管,然后classes_path参数修改为自己定义好类别的txt文件;

yolo.py也需要修改相关函数:

注意,train.py文件中有个重要参数,mode_path主干权值文件,一般是使用现成的训练好的权值文件yolo4_weights.pth和yolo4_voc_weights.pth;

我第一次训练(批次(epoch)=100)的时候使用的主干权值文件是yolo4_weights.pth,

第二次训练进(批次(epoch)=100),用了我自己训练的权值文件(fruit_weights)作为主干权值,

第三次训练(批次(epoch)=300),用了我自己训练的权值文件(fruitv2_weights)作为主干权值,可以看到,性能提升非常大。

总之其实可以老老实实用yolo4_weights.pth等现成的权值文件多训练几百个批次(epoch),主干权值文件能不动尽量不动。(注:不改变原代码函数的情况下200张图片100个批次2060显卡跑满的话一个小时左右就跑完了)

UnFreeze_Epoch模型总共训练的批次(epoch)数参数的话,如果对数据集没什么信心可以设置个20-30批次左右看输出内容,如果输出各项指标一直是0就可以直接结束,改进数据集了。

训练期间会输出模型性能的统计数据,包括不同类别(dragon fruit 和 snake fruit)的平均精度(AP)和平均精度均值(mAP),以及它们对应的分数阈值、F1-分数、召回率和精确率。

这个代码主要作用如下:

准备阶段:

设置是否使用GPU。
初始化随机种子以确保结果可复现。
设置是否使用分布式训练。
定义模型需要检测的类别。
加载预定义的YOLO模型的锚点(anchors),用于指导模型预测目标大小。
加载图像数据和标签数据的路径。
模型配置:

加载模型架构,可以选择加载预训练权重以此来初始化模型,或者从头开始训练。
设置输入图像的尺寸。
根据是否进行冻结训练(只训练模型的部分层,其他层保持不变),设置不同的训练策略,例如学习率和训练轮次(Epoch)。
数据增强:

使用了Mosaic和Mixup等数据增强技术,可以在训练中生成更多样化的训练样本。
编译模型:

根据设置的学习率、优化器类型(如SGD或Adam)、以及是否使用Focal Loss或iou损失等选项,配置模型的优化器。
设置学习率衰减策略。
训练流程:

分两个阶段进行训练:冻结训练(只训练模型顶层,主干网络被冻结)和解冻训练(训练所有层)。
在每个阶段,会根据实际数据集的大小动态调整训练时的批量大小(Batch Size)和学习率。
逐轮次(Epoch)进行训练,每轮次结束后可能保存模型权重,并可以选择性地对验证集进行评估,以监控模型性能。
记录和评估:

将训练过程中的损失值和经过验证集评估得到的性能指标记录下来。
总结来说,这段代码用于训练Yolo目标检测模型,涉及到了数据准备、数据增强、模型配置、训练流程以及性能评估等关键步骤。

训练完的权值文件默认保存在log文件夹下,log文件夹下的best_epoch_weights.pth就是我们训练好的权值文件,示例如下:

3.运行predict.py
训练好我们要用的权值文件以后,先修改yolo.py代码,model_path换成自己训练好的权值文件;

yolo.py还有个不明显但是训练自己数据集后必须要更改的地方,onnx_path同样改成训练好的权值文件,classes_path应该不用多说,改成自己设置好的类别txt文件。

yolo.py总会报两个错误,但我没明白原因,反正不影响预测啥的,直接无视:

然后修改predict.py里的图片输入路径,不改也不甚要紧,然后用找来的图片来测试训练好的数据集权值文件效果。

如果PyTorch版本比较新,在predict.py运行时可能会弹出警告:

D:\Python\yolov4\utils\utils_bbox.py:88: UserWarning: The torch.cuda.*DtypeTensor constructors are no longer recommended. It's best to use methods such as torch.tensor(data, dtype=*, device='cuda') to create tensors. (Triggered internally at C:\actionsrunner\_work\pytorch\pytorch\builder\windows\pytorch\torch\csrc\tensor\python_tensor.cpp:85.) anchor_w = FloatTensor(scaled_anchors).index_select(1, LongTensor([0])) Traceback (most recent call last): File "D:\Python\yolov4\predict.py", line 95, in <module> r_image = yolo.detect_image(image, crop = crop, count=count) File "D:\Python\yolov4\yolo.py", line 207, in detect_image label_size = draw.textsize(label, font) AttributeError: 'ImageDraw' object has no attribute 'textsize'

 我的解决办法是直接修改了utils_bbox.py这个代码中的几行问题代码,修改如下(注释掉了原代码):

            #----------------------------------------------------------#
            #   按照网格格式生成先验框的宽高
            #   batch_size,3,13,13
            #----------------------------------------------------------#
            # anchor_w = FloatTensor(scaled_anchors).index_select(1, LongTensor([0]))
            anchor_w = torch.tensor(scaled_anchors, dtype=torch.float, device='cuda').index_select(1, torch.tensor([0],
                                                                                                                   dtype=torch.long,
                                                                                                                   device='cuda'))
            # anchor_h = FloatTensor(scaled_anchors).index_select(1, LongTensor([1]))
            anchor_h = torch.tensor(scaled_anchors, dtype=torch.float, device='cuda').index_select(1, torch.tensor([1],
                                                                                                                   dtype=torch.long,
                                                                                                                   device='cuda'))
 
            anchor_w = anchor_w.repeat(batch_size, 1).repeat(1, 1, input_height * input_width).view(w.shape)
            anchor_h = anchor_h.repeat(batch_size, 1).repeat(1, 1, input_height * input_width).view(h.shape)
 
            #----------------------------------------------------------#
            #   利用预测结果对先验框进行调整
            #   首先调整先验框的中心,从先验框中心向右下角偏移
            #   再调整先验框的宽高。
            #----------------------------------------------------------#
            # pred_boxes          = FloatTensor(prediction[..., :4].shape)
            pred_boxes = torch.zeros(prediction[..., :4].shape, dtype=torch.float, device='cuda')
            pred_boxes[..., 0]  = x.data + grid_x
            pred_boxes[..., 1]  = y.data + grid_y
            pred_boxes[..., 2]  = torch.exp(w.data) * anchor_w
            pred_boxes[..., 3]  = torch.exp(h.data) * anchor_h


在使用CPU的情况下,如果Pillow库是直接安装的,没有指定版本,也会报类似的错误:

Traceback (most recent call last):   File "D:\py\yolov4-pytorch-master\predict.py", line 96, in <module>     r_image = yolo.detect_image(image, crop=crop, count=count)   File "D:\py\yolov4-pytorch-master\yolo.py", line 212, in detect_image     label_size = draw.textsize(label, font) AttributeError: 'ImageDraw' object has no attribute 'textsize'

解决方法也很简单,卸载新版Pillow库 ,

pip uninstall pillow
 然后按照要求指定安装老版本的Pillow==8.2.0即可。

pip install Pillow==8.2.0


五、成果展示
最后给你们看一下我训练好的权值文件的成果吧,哈哈,快要0点了,1500流量券马上拿不到了,不写了。

1.图片测试


第一张菠萝图片:

第二张菠萝图片:

2.epoch_loss 损失曲线图
图中有四条线,分别用不同颜色标识:

红色实线表示训练损失(train loss)。

橙色实线表示验证损失(val loss)。

绿色虚线表示平滑后的训练损失(smooth train loss)。

蓝色虚线表示平滑后的验证损失(smooth val loss)。

横轴标记为“Epoch”,范围从0到300。

纵轴标记为“Loss”,范围从0.04到0.12左右。

3.epoch_map 平均精度曲线图
红色曲线代表“train_map”随“Epoch”变化的趋势。

横轴标记为“Epoch”,范围从0延伸至300。

纵轴标记为“mAP”,范围从0到1.0。

4.不同类别“精确度-召回率曲线”下的平均精度(mAP)图

  • 21
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值