【人工智能】使用yolov7和youlov8以及re-detr模型实现安全帽检测

CSDN 2024-06-15 11:31:07 阅读 53

1 问题描述

数据集共包括40000张训练图像和1000张测试图像,每张训练图像对应 xml标注文件:

在这里插入图片描述

共包含3类:0:‘head’, 1:‘helmet’, 2:‘person’ 提交格式要求,提交名为pred_result.txt的文件:每一行代表一个目标,每一行内容分别表示 图像名 置信度 xmin ymin xmax ymax 类别

![[Pasted image 20240113144435.png]]

2 数据准备

2.1 数据加载

解压项目提供的数据:

!unzip /home/aistudio/data/data126280/HelmetDetection.zip -d /home/aistudio

更改文件位置:

%cd /home/aistudio%mv data/data126280/helmet/train/annotations work/dataset/Annotations%mv data/data126280/helmet/train/images work/dataset/JPEGImages

文件目录结构如下:

dataset/ dataset/ ├── annotations/ --> ├── Annotations/ ├── images/ ├── JPEGImages/

2.2 数据预处理

训练数据预处理和增强操作:

MixupImage: mixup_epoch=-1:应用 Mixup 数据增强,这是一种通过混合两个图像来生成新的训练样本的技术。mixup_epoch=-1 表示在所有训练周期中都应用 Mixup。 RandomDistort: 随机扭曲图像,增加训练数据的多样性。 RandomExpand: 随机扩展图像,通过填充值 [123.675, 116.28, 103.53] 进行填充。有助于增加模型对输入图像边界的鲁棒性。 RandomCrop: 随机裁剪图像,增加训练数据的多样性。 RandomHorizontalFlip: 随机水平翻转图像,增加训练数据的多样性。 BatchRandomResize: 随机调整图像尺寸,可选择多个目标尺寸 [320, 352, 384, 416, 448, 480, 512, 544, 576, 608],并使用随机的插值方法。 Normalize: 将图像进行标准化,使用均值 [0.485, 0.456, 0.406] 和标准差 [0.229, 0.224, 0.225] 进行归一化。

train_transforms = T.Compose([ T.MixupImage(mixup_epoch=-1), T.RandomDistort(), T.RandomExpand(im_padding_value=[123.675, 116.28, 103.53]), T.RandomCrop(), T.RandomHorizontalFlip(), T.BatchRandomResize( target_sizes=[320, 352, 384, 416, 448, 480, 512, 544, 576, 608], interp='RANDOM'), T.Normalize( mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])])eval_transforms = T.Compose([ T.Resize( target_size=480, interp='CUBIC'), T.Normalize( mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])])

划分训练集和验证集的比例为:0.85:0.15

!paddlex --split_dataset --format voc --dataset_dir /home/aistudio/work/dataset --val_value 0.15

得到文件:

labels.txt,val_list.txt,train_list.txt

定义训练集和验证集:

train_dataset = pdx.datasets.VOCDetection( data_dir='/home/aistudio/work/dataset', file_list='/home/aistudio/work/dataset/train_list.txt', label_list='/home/aistudio/work/dataset/labels.txt', transforms=train_transforms, shuffle=True)eval_dataset = pdx.datasets.VOCDetection( data_dir='/home/aistudio/work/dataset', file_list='/home/aistudio/work/dataset/val_list.txt', label_list='/home/aistudio/work/dataset/labels.txt', transforms=eval_transforms, shuffle=False)

3 模型选择

由于PaddleX有大量的有关目标检测的集成模型可供选择,所以本次实验采用PaddleX库进行训练。版本:python=3.7 PaddlePaddle=2.4.0

!pip install paddlex!pip install --user --upgrade pyarrow==11.0.0

本次实验分别选取了yolov3yolov7yolov8rt-detr四种模型进行训练,并挑选出训练情况相对较好的模型进行进一步的优化,以下是模型的初步训练过程。

3.1yolov7的训练

V7的模型架构:

在这里插入图片描述

V7的改进:

模型结构重参数化:𝑉7 将模型重参数化引入到网络架构中网络架构改进:𝑉7在 𝑉4 和 𝑉5的基础上做了一些改进,性能得到了提高损失函数:𝑉7 的损失函数也有所改进,以更好地平衡分类损失和定位损失

V7的训练过程:

step1 安装PaddleYOLO-Develop文件

!unzip /home/aistudio/PaddleYOLO-develop.zip -d /home/aistudio%cd PaddleYOLO-develop/!pip install -r requirements.txt --user

step2 将数据集的格式转换为coco

!python /home/aistudio/PaddleYOLO-develop/tools/x2coco.py\ --dataset_type voc\ --voc_anno_dir /home/aistudio/helmet/train\ --voc_anno_list /home/aistudio/helmet/train/train_list.txt\ --voc_label_list /home/aistudio/helmet/train/labels.txt\ --voc_out_name /home/aistudio/helmet/train/coco.json

注:此处的文件目录结构与上述数据准备时的文件目录不同,因为此处为预训练时的数据准备,并非最终结果的文件存放目录。

此处文件目录结构如下:

/helmet/train/ ├── Annotations/ ├── JPEGmages/ ├── coco.json ├── labels.txt ├── train_list.txt ├── val_list.txt

step3 更改训练数据集路径、参数文件等

runtime.yaml:save_dir: /home/aistudio/outputcoco_detection.yaml:metric: COCOnum_classes: 3TrainDataset: name: COCODataSet image_dir: /home/aistudio/helmet/train/JPEGImages anno_path: /home/aistudio/helmet/train/coco.json dataset_dir: /home/aistudio/helmet/train data_fields: ['image', 'gt_bbox', 'gt_class', 'is_crowd']EvalDataset: name: COCODataSet image_dir: /home/aistudio/helmet/test/JPEGImages anno_path: /home/aistudio/helmet/test/coco.json dataset_dir: /home/aistudio/helmet/test allow_empty: true

训练参数如下:

在这里插入图片描述

模型训练过程:

!python /home/aistudio/PaddleYOLO-develop/tools/train.py -c /home/aistudio/PaddleYOLO-develop/configs/yolov7/yolov7_l_300e_coco.yml --use_vdl=True --vdl_log_dir=/home/aistudio/work --eval

![[Pasted image 20240113173819.png|300]]

模型训练结果:

在训练十次后模型平均精确度仅达到8%,而模型的平均召回率也只有12.9%,及时在调整学习率从0.0004到0.007后,结果依旧不好,由于比赛的时间限制,此处放弃yolov7模型的继续调参和训练。

3.2 yolov8的训练

yolov8的训练过程和yolov7相似,仅需要在训练时修改模型权重文件和具体的参数信息。

训练参数:

![[Pasted image 20240113175203.png|400]]

训练过程:

!python /home/aistudio/PaddleYOLO-develop/tools/train.py -c /home/aistudio/PaddleYOLO-develop/configs/yolov8/yolov8_s_500e_coco.yml --use_vdl=True --vdl_log_dir=/home/aistudio/work --eval

![[Pasted image 20240113181656.png|400]]

训练结果:

![[Pasted image 20240113174636.png|700]]

yolov8的训练相较于yolov7的表现更好一些,但是在训练30次后,在IoU 阈值从 0.50 到 0.95 范围内,模型平均精确度为20.7%,而模型的平均召回率为40%,效果依旧不是很好,所以由于无法找到一个合适的学习率大小来适应数据集和模型,此处也没有再继续训练yolov8模型。

3.3 re-detr的训练

RT-DETR模型结构:

在这里插入图片描述

YOLO 检测器有个较大的待改进点是需要 NMS 后处理,其通常难以优化且不够鲁棒,因此检测器的速度存在延迟。为避免该问题,将目光移向了不需要 NMS 后处理的 DETR,一种基于 Transformer 的端到端目标检测器。然而,相比于 YOLO 系列检测器,DETR 系列检测器的速度要慢的多,这使得"无需 NMS "并未在速度上体现出优势。上述问题促使我们针对实时的端到端检测器进行探索,旨在基于 DETR 的优秀架构设计一个全新的实时检测器,从根源上解决 NMS 对实时检测器带来的速度延迟问题。

由此,飞桨正式推出了——RT-DETR (Real-Time DEtection TRansformer) ,一种基于 DETR 架构的实时端到端检测器,其在速度和精度上取得了 SOTA 性能。

论文地址:https://arxiv.org/abs/2304.08069

训练参数:

![[Pasted image 20240113184114.png|400]]

训练过程:

!python /home/aistudio/PaddleYOLO-develop/tools/train.py -c /home/aistudio/PaddleYOLO-develop/configs/rtdetr/rtdetr_r101vd_6x_coco.yml --use_vdl=True --vdl_log_dir=/home/aistudio/work --eval

训练结果:

在这里插入图片描述

RE-DETR模型的训练结果相比于yolov7和yolov8的结果更好,同样在10个epoch的情况下,在IoU 阈值从 0.50 到 0.95 范围内,模型的平均精确度为37%,而模型的平均召回率为40%,说明此次的学习率值选取更适合模型和训练集,使用该模型的score结果为31.2,分数也不是很高,在提高epoch到70后,模型最终的分数为51.3

3.4 yolov3的训练

𝑉3 采用了称之为 𝐷𝑎𝑟𝑘𝑛𝑒𝑡 − 53 的网络结构(多尺度网络,含有 53 个卷积层),借鉴了残差网 络的做法,在一些层之间设置了快捷链路 𝑉3 借鉴特征金字塔 𝐹𝑃𝑁 概念,预测三个不同尺度的框,每个尺度上预测 3 个框。

Backbone 部分采用了 Darknet-53 网络,这是一个深度卷积神经网络, 用于从输入图像中提取特征 Neck 部分采用了特征金字塔网络 结构,用于将 Backbone 部分输出 的特征图进行多尺度特征融合 这样每个尺度的特征图都包含了 丰富的语义信息和空间信息。这 些融合后的特征图被用于后续的 目标检测任务。

![[Pasted image 20240113184955.png]]

𝑌𝑂𝐿𝑂𝑉3 的三个基本组件: 𝐶𝐵𝐿、 𝑅𝑒𝑠 𝑢𝑛𝑖𝑡、 𝑅𝑒𝑠X

𝐶𝐵𝐿: 𝑌𝑜𝑙𝑜𝑣3 网络结构中的最小组件,由 𝐶𝑜𝑛𝑣 + 𝐵𝑛 + 𝐿𝑒𝑎𝑘𝑦_𝑟𝑒𝑙𝑢 三者组成𝑅𝑒𝑠 𝑢𝑛𝑖𝑡: 借鉴 𝑅𝑒𝑠𝑁𝑒𝑡 网络中的残差结构,让网络可以构建的更深𝑅𝑒𝑠𝑋:由一个 𝐶𝐵𝐿 和 𝑋 个残差组件构成,是 𝑉3 中的大组件。每个 𝑅𝑒𝑠 模块前 面的𝐶𝐵𝐿 都起到下采样的作用,第一个特征图下采样 32 倍,第二个特征图下采 样 16 倍,第三个 8 倍。

模型的训练参数:

在这里插入图片描述

模型的训练过程:

# YOLO检测模型的预置anchor生成anchors = train_dataset.cluster_yolo_anchor(num_anchors=9, image_size=480)anchor_masks = [[6, 7, 8], [3, 4, 5], [0, 1, 2]]# 初始化模型,并进行训练num_classes = len(train_dataset.labels)model = pdx.det.YOLOv3( num_classes=num_classes, backbone='DarkNet53', anchors=anchors.tolist() if isinstance(anchors, np.ndarray) else anchors, anchor_masks=[[6, 7, 8], [3, 4, 5], [0, 1, 2]], label_smooth=True, ignore_threshold=0.6)model.train( num_epochs=10, # 训练轮次 train_dataset=train_dataset, # 训练数据 eval_dataset=eval_dataset, # 验证数据 train_batch_size=16, # 批大小 pretrain_weights='COCO', # 预训练权重,刚开始训练的时候取消该注释,注释resume_checkpoint learning_rate=0.005 / 12, # 学习率 warmup_steps=500, # 预热步数 warmup_start_lr=0.0, # 预热起始学习率 save_interval_epochs=5, # 每5个轮次保存一次,有验证数据时,自动评估 lr_decay_epochs=[85, 135], # step学习率衰减 save_dir='output/yolov3_darknet53', # 保存路径 #resume_checkpoint='output/yolov3_darknet53', # 断点继续训练 use_vdl=True) # 其用visuadl进行可视化训练记录

模型的训练结果:

在这里插入图片描述

通过上图可以看到,在训练过程中,head类的Ap达到90.10、helmet类的AP达到94.18、person类的AP为0.91。说明此次数据集中的person标注有问题,造成训练过程person的训练效果极差,在翻阅标注文档后,发现存在的问题是:几乎没有几张图片标注了person这一类别,这直接导致了person类训练的程度不足。 不过yolov3的训练效果远远好于之前的模型训练,可能是由于学习率选取的更为恰当,在时间相对紧迫的情况下,继续优化yolov3。

在这里插入图片描述

上图分别为训练集全类别、head类别、helmat类别和person类别的预测错误原因分析图

分析图表展示了7条Precision-Recall(PR)曲线,每一条曲线表示的Average Precision (AP)比它左边那条高,原因是逐步放宽了评估要求。以helmet类为例,各条PR曲线的评估要求解释如下:

C75: 在IoU设置为0.75时的PR曲线, AP为0.578。C50: 在IoU设置为0.5时的PR曲线,AP为0.942。C50与C75之间的白色区域面积代表将IoU从0.75放宽至0.5带来的AP增益。Loc: 在IoU设置为0.1时的PR曲线,AP为0.961。Loc与C50之间的蓝色区域面积代表将IoU从0.5放宽至0.1带来的AP增益。蓝色区域面积越大,表示越多的检测框位置不够精准。Sim: 在Loc的基础上,如果检测框与真值框的类别不相同,但两者同属于一个亚类,则不认为该检测框是错误的,在这种评估要求下的PR曲线, AP为0.966。Sim与Loc之间的红色区域面积越大,表示子类间的混淆程度越高。Oth: 在Sim的基础上,如果检测框与真值框的亚类不相同,则不认为该检测框是错误的,在这种评估要求下的PR曲线,AP为0.966。Oth与Sim之间的绿色区域面积越大,表示亚类间的混淆程度越高。BG: 在Oth的基础上,背景区域上的检测框不认为是错误的,在这种评估要求下的PR曲线,AP为0.980。BG与Oth之间的紫色区域面积越大,表示背景区域被误检的数量越多。FN: 在BG的基础上,漏检的真值框不认为是错误的,在这种评估要求下的PR曲线,AP为1.00。FN与BG之间的橙色区域面积越大,表示漏检的真值框数量越多。

从分析图表中可以看出,head、helmet两类检测效果较好,但仍然存在漏检的情况,特别是person存在很大的漏检问题;此外,通过helmet中C75指标可以看出,其相对于C50的0.942而言有些差了,因此定位性能有待进一步提高。为进一步理解造成这些问题的原因,将验证集上的预测结果进行了可视化,然后发现数据集标注存在以下问题:本数据集主要考虑到头部和安全帽的检测,因此在人检测时,有个图片中标注了,而有的图片中没有标注,从而导致学习失效,引发person漏检。head与helmet大多数情况标注较好,但由于部分拍摄角度导致有的图片中的head和helmet发生重叠以及太小导致学习有困难。

预测文件导出:

# Path to the trained modelmodel_path = '/home/aistudio/model/inference_model/inference_model'# Path to the test images foldertest_folder = '/home/aistudio/work/test/JPEGImages'# Output file for predictionsoutput_file = 'pred_result.txt'# Load the modelmodel = pdx.load_model(model_path)# Open the output file in append modewith open(output_file, 'a') as f: # Iterate over images in the test folder for image_name in os.listdir(test_folder): image_path = os.path.join(test_folder, image_name) # Read the image img = cv2.imread(image_path) # Predict result = model.predict(img) # Write predictions to the output file for dt in result: cname, bbox, score = dt['category'], dt['bbox'], dt['score'] # Map class label if cname == 'head': clabel = '0' elif cname == 'helmet': clabel = '1' elif cname == 'person': clabel = '2' else: clabel = 'Unknown' # Remove '.jpg' from image name image_name_without_extension = os.path.splitext(image_name)[0] # Write the prediction to the file line = f"{ image_name_without_extension} { score:.4f} { bbox[0]:.2f} { bbox[1]:.2f} { bbox[2]+bbox[0]:.2f} { bbox[3]+bbox[1]:.2f} { clabel}\n" # 调整写入文件的格式 #line = f"{image_name_without_extension} {score:.4f} {int(bbox[0])} {int(bbox[1])} {int(bbox[2]+bbox[0])} {int(bbox[3]+bbox[1])} {clabel}\n" f.write(line)print(f"Predictions saved to { output_file}")

4 模型优化

4.1 模型改进

在epoch为10的基础上对以上五个模型进行了初步的探索,由于yolov3在初步表现上效果更好,模型的学习率更有效,所以接下来的模型优化部分以yolov3为基础,进行优化。

相较于二阶段检测模型,单阶段检测模型的精度略低但是速度更快。考虑到是部署到GPU端,本案例选择单阶段检测模型YOLOV3作为基线模型,其骨干网络选择DarkNet53。训练完成后,模型在验证集上的精度如下:

在这里插入图片描述

考虑到定位问题,通过尝试放大图片,不同的网络结构以及定位的优化策略: 利用cluster_yolo_anchor生成聚类的anchor或开启iou_aware。

模型训练过程:

num_classes = len(train_dataset.labels)model = pdx.det.PPYOLOv2( num_classes=num_classes, backbone='ResNet50_vd_dcn', label_smooth=True, use_iou_aware=True)

在这里插入图片描述

在不断调整参数后,模型评估结果:

model = pdx.load_model('/home/aistudio/model/inference_model/inference_model')eval_dataset = pdx.datasets.VOCDetection( data_dir='/home/aistudio/work/test', file_list='/home/aistudio/work/test/val_list.txt', label_list='/home/aistudio/work/test/labels.txt', transforms=eval_transforms)metrics, evaluate_details = model.evaluate(eval_dataset, batch_size=8, return_details=True)gt = evaluate_details['gt']bbox = evaluate_details['bbox']pdx.det.coco_error_analysis(gt=gt, pred_bbox=bbox, save_dir='/home/aistudio/output/test/z')

模型预测:

%matplotlib inlineimport matplotlib.pyplot as plt # plt 用于显示图片import numpy as npimport cv2import ossave_dir='/home/aistudio/'pdx.det.visualize(img_path, result, save_dir=save_dir)path,filename = os.path.split(img_path)output_path = os.path.join(save_dir,"visualize_"+filename)pic = cv2.imread(output_path)pic = cv2.cvtColor(pic, cv2.COLOR_BGR2RGB)plt.imshow(pic)plt.axis('off') # 不显示坐标轴plt.show()

在这里插入图片描述

最终得到模型PPYOLOV2的精度如下:

在这里插入图片描述

4.2 优化结果

从结果图中可以看出:

C75指标效果明显改善,定位更加准确:从0.361提升到0.388。其中BG到FN的差距从0.1降低到了0.01,说明漏检情况有所改善。其中Loc与Sim的差距**从0.06降低到了0.05,说明混淆程度也下降了。

本项目优化整体分析可归纳为以下几点:

通过选用适当更优的骨干网络可以改善漏检的情况,因此漏检方面的优化可以考虑先从骨干网络替换上开始——当然必要的数据清洗也是不可缺少的,要是数据集本身漏标,则会从根本上影响模型的学习。通过放大图像,可以对一些中小目标的物体检测起到一定的优化作用。通过聚类anchor以及iou_aware等操作可以提高模型的定位能力,直接体现是再高Iou上也能有更好的表现。

优化进展说明

1.通过选择更好的backbone作为特征提取的骨干网络可以提高识别率、降低漏检率。2.缩放适当的图像大小可以提高模型的识别率,但是存在一定的阈值——当图像大小到某一个阈值时会导致精度下降。 一般图像大小选择(YOLO系列):320,480, 608。一般图像如果较大,物体也比较大,可以较为放心的缩小图像大小再进行相关的训练和预测。物体较小,不易缩小,可以适当的裁剪划分原图或放大,并处理对应的标注数据,再进行训练。 3.通过cluster_yolo_anchor生成当前网络输入图像大小下拟合数据集的预置anchors,利用新生成的anchors替换原来的默认anchor,使得模型预测定位上框选位置更准确。4.通过PPYOLO两个实验,一个使用iou_aware,一个不是使用iou_aware而采用聚类得到的anchor提高定位能力;分析数据发现在定位信息优化上,iou_aware在当前数据集上表现更好,但推理时间也有所提升。5.通过PPYOLO两个实验,一个使用label_smooth,一个不使用,分析出使用label_smooth可以让模型在验证集上表现更好了。

5 实验总结

最终结果:

在这里插入图片描述

最终得分:65.9046

在此次安全帽比赛中,我尝试使用了五种不同的模型分别是yolov2、yolov3、yolov7、yolov8和re-detr五种模型,开始时我分别对五种模型进行了10个epoch的测试,没想到我报以最大希望的yolov7和yolov8的效果却远远没有达到我的预期,这让我非常的疑惑,我在两天的时间内反复调试yolov7和yolov8的学习率和anchor等相关参数,但是始终没有得到一个满意的结果,我搜集了很多资料,却没有一个能够让实验顺利进行下去。但是回顾这两天的时间,我翻阅paddle的帮助文档,了解了更多有关yolov7和yolov8的模型架构、性能和改进方面的知识,即使我在训练的结果不如意,但是学到的知识也是一种收获。由于比赛时间的紧迫性,我放弃了对yolov7和yolov8的训练和调参,这也是此次比赛的一个遗憾,在未来有时间的日子里,我希望能够找到原因,尝试用更多更新的模型进行训练。

关于re-detr的模型认知源于飞桨的一篇微信推文,我在上面了解到了这个号称比yolov8“更快更强”的模型,但是在此次的训练中他的表现力还是没有得到充分的发挥,我也希望能够在以后的学习中进一步去了解这个模型。

最终的预测模型使用的是yolov3和yolov2,通过适当更优的骨干网络、缩放适当的图像大小、聚类anchor以及iou_aware等操作完成了最终的实验,在此次实验过程中,我更加了解了yolo的使用步骤,全身心的投入到了模型训练和优化的过程中,虽然最后的结果并不是很完美,中间的处理过程也有待改进,但是我觉得我已经做了三天内能做的最大努力,为此,我想感谢我自己,也想感谢老师给我此次机会,不断地去提升和突破自己。

在人工智能的这门课学习过程中,我从曾经只知道如何去训练模型,到如今知道如何去改进模型,我认为这是我在这门课中最大的收获,正如赵老师所说,我希望未来,我能学会如何去发明模型,虽然目前距离目标还是很遥远,但是我会继续努力,在深度学习和人工智能的路上继续前进。在最后的训练过程中,我也渐渐明白其实此次比赛的意义并不是最后提交上去的分数,而是在紧张的时间中不断学习新的知识,发掘自己的潜能,在长时间的训练后得到一个非常差的结果时,更是对个人心态的锻炼,就像学习的意义远不止为了获得高分成绩,而是运用知识解决问题,问题也不仅是习题册上的问题,更是生活中的问题。一门课程虽不能迸发巨大的力量,却能让做学问的意义更加明确,让我们知道为何而学。课程的尽头不是知识的尽头,今日所学日后定会再次相见,感谢相遇。



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。