YOLOv7出来也有一段时间了,在刚出来的时候我就抢先体验了一把,当时主要是就是尝尝鲜,没有实际项目落地,所以也就没有去用很多数据集,也没有对模型进行评估计算,在前面的系列博文里面已经做了记录,感兴趣的话可以去看下:
《基于yolov4作者最新力作yolov7目标检测模型实现火点烟雾检测》
相信很多从事目标检测任务的人来说一定对于YOLO是很不陌生的,对于新出来的模型大多都保持着一定的新鲜感,新鲜事物早体验呗。前段时间感觉也是应接不暇了,先是美团技术团队提出来了yolov6,也就间隔一周的时间吧,yolov7就出来的,当然了,两者的优化思路是不一样的,可以根据自身的实际业务场景需求来进行选择即可,也未必说越新的模型就会越好。
还记得第一次接触到目标检测类任务的时候很不知所措,即使是拿到开源的项目也很难说能够顺利调试跑起来,一方面是可能项目本身迭代的过程中有问题遗留了、版本不兼容了等等;另一方面就是自己的实践经验不足,所以新领域新模型新任务可能会踩很多坑进去。
写这篇文章的最大的初衷就是想要基于作者开源的项目详细出一篇操作使用教程,这里不涉及对于YOLOv7原理的讲解,感兴趣的话可以看看论文,这个可能更有用一点。之前自己的尝鲜写的一篇文章对于初学者新手来说并不很好上手,所以这篇文章也算是从内容细节角度对YOLOv7使用的补充说明。除此之外还有一个原因就是之前也有在网上看到过一些平台、公众号发的YOLOv7什么从零开始的教程,我对照着操作了一下发现按照教程里面的说明根本跑不起来,连最基本的数据集构建形式都不对,真心怀疑作者或者是那些转发的人真的有自己去按照这个发的教程实地操作过吗?我给平台和公众号都留言提问了,我以为能够得到答复不管是否与问题有关毕竟是做技术的公众号或者是平台,结果换来的却是留言被屏蔽折叠了。。。。这种操作着实是很无语,想了下与其纠结这些不如自己发个教程,真正是可以被复制操作的操作教程。
首先给出来论文地址。前面也说了,想要仔细了解作者的网络的设计思想和YOLOv7模型的原理部分可以先去看看作者前不久刚发表的论文,本文主要是重实践操作。
《YOLOv7: Trainable bag-of-freebies sets new state-of-the-art for real-time object detectors》
官方作者开源的项目地址在这里。
现在已经突破了4K的star量了,不得不说真的强啊!
简单的介绍就到这里,接下来开始步入正题,首先从git仓库下载作者提供的项目源码。
1、开源项目下载
如下图所示,一共有两种方式可供下载
这里之所以区分开为两种方式下载,是因为一些比较热门或者大型项目或者是更新频率比较高的项目作者在开发到某个阶段的时候都会发布出来一个可用的稳定版本也就是tag这里,我一般下载开源项目使用的话会偏向于下载作者releas的稳定版本使用;当然了,如果不在意这些细节的话也可以直接点击Code之后下载zip源码包,此时下载下来的源码包会是最新的代码,也就是说:方式二获取到的代码版本>=方式一获取到的代码版本。到底使用哪个完全看自己的选择和需求。我这里选择的是tag里面的稳定版本。
点击tag,进入新的页面,地址在这里。
之后点击Download进入到下载页面。
下载页面如下,地址在这里。
下载红框选择的源码包即可。下载好后截图如下:
我是在windows10下面操作的,本地解压缩后,截图如下所示:
一共包含12个项目文件。到此处,项目下载处理工作就已经全部结束了。接下来就是数据集构建解析部分了。
2、数据集构建
本文使用到的数据集来自于网络采集,需要检测的目标对象是牛耳朵上面的标牌,样例数据如下所示:
首先在当前项目目录下创建新的目录0000,之所以用这种临时数字作为目录名是因为方便辨识,之后处理完数据集后就可以直接删除掉了。创建好后项目截图如下所示:
进入0000目录,分别创建:JPEGImages/、labels/、xmls三个目录,顾名思义,分别用来存放:图像数据集、yolo标注数据集和xml原始标注文件数据。如下所示:
接下来我们分别看下三个目录的数据。
JPEGImages/目录截图如下所示:
xmls/目录截图如下所示:
labels/目录截图如下所示:
到这里数据集的准备工作就结束了,接下来就是数据集划分处理了。
这里我在自己跑通YOLOv7项目对比发现,YOLOv7其实和之前发表的YOLOv6所用的数据集格式是相同的,所以为了方便使用项目,我写了个数据集划分处理的脚本makeDataset.py放在项目统计目录下即可,如下所示:
红框选中的是我们自己新增的部分,0000目录是原始数据集存放目录,makeDataset.py是训练集-测试集划分模块。我默认设定90%的数据集用于模型的训练,其余的用于模型测试,可以根据自己的需求修改都是可以的。
这里给出来makeDataset源码:
#!usr/bin/env python
# encoding:utf-8
from __future__ import division
"""
__Author__:沂水寒城
功能: 拆分原始的数据集为 训练集-测试集,训练集和测试集不交叉
"""
import os
import json
import random
import shutil
def splitDataset(dataDir="0000/", saveDir="dataset/", train_ratio=0.9):
"""
划分数据集
"""
pic_ids_list = [
one.split(".")[0].strip() for one in os.listdir(dataDir + "JPEGImages/")
]
print("pic_ids_list_length: ", len(pic_ids_list))
train_num = int(train_ratio * len(pic_ids_list))
train_list = random.sample(pic_ids_list, train_num)
test_list = [one for one in pic_ids_list if one not in train_list]
print("train_list_length: ", len(train_list))
print("test_list_length: ", len(test_list))
# 创建存储目录-训练集
trainImgDir = saveDir + "images/train/"
trainTxtDir = saveDir + "labels/train/"
if not os.path.exists(trainImgDir):
os.makedirs(trainImgDir)
if not os.path.exists(trainTxtDir):
os.makedirs(trainTxtDir)
for one_id in train_list:
shutil.move(
dataDir + "JPEGImages/" + one_id + ".jpg", trainImgDir + one_id + ".jpg"
)
shutil.move(
dataDir + "labels/" + one_id + ".txt", trainTxtDir + one_id + ".txt"
)
print(
"================================Train Dataset Build Success================================"
)
# 创建存储目录-测试集
testImgDir = saveDir + "images/test/"
testTxtDir = saveDir + "labels/test/"
if not os.path.exists(testImgDir):
os.makedirs(testImgDir)
if not os.path.exists(testTxtDir):
os.makedirs(testTxtDir)
for one_id in test_list:
shutil.move(dataDir + "JPEGImages/" + one_id + ".jpg", testImgDir + one_id + ".jpg")
shutil.move(dataDir + "labels/" + one_id + ".txt", testTxtDir + one_id + ".txt")
print(
"================================Test Dataset Build Success================================"
)
if __name__ == "__main__":
print(
"========================================Loading splitDataset========================================"
)
splitDataset(dataDir="0000/", saveDir="dataset/", train_ratio=0.9)
终端执行makeDataset.py,输出如下所示:
执行结束后会自动创建新的数据集目录dataset,如下所示:
进入dataset目录,截图如下所示:
其中:
images目录用于存储图像数据
labels目录用于存储标注文件数据
整体结果如下所示:
dataset-images-test
| |
| -train
|
labels-test
|
-train
进入images目录如下所示:
进入test目录如下所示:
进入train目录如下所示:
接下来进入labels目录,如下所示:
进入test目录如下所示:
进入train目录如下所示:
train(301)—test(34)这与前面终端输出结果数据相对应。
到这里我们的数据集准备——>数据集创建工作就已经全部结束了。
3、模型开发训练
前两部分完成以后就可以开始修改对应的参数配置来进行自己的数据集上面的模型训练开发了,因为我没有GPU资源,只能使用CPU资源来进行计算,所以这里我选择的模型是yolov7-tiny,这个相较于其他型号的模型来说参数量和计算量更小。
本质上来讲,训练自己的模型可以从头开始训练也可以基于官方公开的预训练模型来进行微调,重头训练的话花费的时间会更多,精度可能也不好因为有很多超参数要调试才行没有那么多的精力和时间去做,所以这里我选择的是基于预训练模型进行微调,可以从这个页面下载模型:
红框就是我自己下载的模型,选择的是最小的型号。
接下来就需要编写自己的训练yaml配置文件了,官方提供的coco数据集的yaml配置文件默认都存放在data目录下,进入到data目录下截图如下所示:
coco.yaml如下所示:
# COCO 2017 dataset http://cocodataset.org
# download command/URL (optional)
download: bash ./scripts/get_coco.sh
# train and val data as 1) directory: path/images/, 2) file: path/images.txt, or 3) list: [path1/images/, path2/images/]
train: ./coco/train2017.txt # 118287 images
val: ./coco/val2017.txt # 5000 images
test: ./coco/test-dev2017.txt # 20288 of 40670 images, submit to https://competitions.codalab.org/competitions/20794
# number of classes
nc: 80
# class names
names: [ 'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light',
'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow',
'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee',
'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard',
'tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple',
'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch',
'potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone',
'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear',
'hair drier', 'toothbrush' ]
我们可以仿照着写自己的就好,我创建的是niuer.yaml,如下所示:
niuer.yaml内容如下所示:
相比于官方提供的coco.yaml来说,我删除了不必要的注释信息精简了格式,总体只需要三部分的内容:
a、数据集的路径
b、类别数目
c、目标清单列表
创建完成后就可以修改模型的yaml文件了,原始项目的模型yaml文件默认存放在cfg/deploy/目录下面,进入到该目录下,截图如下所示:
选择自己所需要的型号的模型的yaml文件打开修改,这里我是用的是tiny版本的。yolov7-tiny-silu.yaml如下所示:
# parameters
nc: 80 # number of classes
depth_multiple: 1.0 # model depth multiple
width_multiple: 1.0 # layer channel multiple
# anchors
anchors:
- [10,13, 16,30, 33,23] # P3/8
- [30,61, 62,45, 59,119] # P4/16
- [116,90, 156,198, 373,326] # P5/32
# YOLOv7-tiny backbone
backbone:
# [from, number, module, args]
[[-1, 1, Conv, [32, 3, 2]], # 0-P1/2
[-1, 1, Conv, [64, 3, 2]], # 1-P2/4
[-1, 1, Conv, [32, 1, 1]],
[-2, 1, Conv, [32, 1, 1]],
[-1, 1, Conv, [32, 3, 1]],
[-1, 1, Conv, [32, 3, 1]],
[[-1, -2, -3, -4], 1, Concat, [1]],
[-1, 1, Conv, [64, 1, 1]], # 7
[-1, 1, MP, []], # 8-P3/8
[-1, 1, Conv, [64, 1, 1]],
[-2, 1, Conv, [64, 1, 1]],
[-1, 1, Conv, [64, 3, 1]],
[-1, 1, Conv, [64, 3, 1]],
[[-1, -2, -3, -4], 1, Concat, [1]],
[-1, 1, Conv, [128, 1, 1]], # 14
[-1, 1, MP, []], # 15-P4/16
[-1, 1, Conv, [128, 1, 1]],
[-2, 1, Conv, [128, 1, 1]],
[-1, 1, Conv, [128, 3, 1]],
[-1, 1, Conv, [128, 3, 1]],
[[-1, -2, -3, -4], 1, Concat, [1]],
[-1, 1, Conv, [256, 1, 1]], # 21
[-1, 1, MP, []], # 22-P5/32
[-1, 1, Conv, [256, 1, 1]],
[-2, 1, Conv, [256, 1, 1]],
[-1, 1, Conv, [256, 3, 1]],
[-1, 1, Conv, [256, 3, 1]],
[[-1, -2, -3, -4], 1, Concat, [1]],
[-1, 1, Conv, [512, 1, 1]], # 28
]
# YOLOv7-tiny head
head:
[[-1, 1, Conv, [256, 1, 1]],
[-2, 1, Conv, [256, 1, 1]],
[-1, 1, SP, [5]],
[-2, 1, SP, [9]],
[-3, 1, SP, [13]],
[[-1, -2, -3, -4], 1, Concat, [1]],
[-1, 1, Conv, [256, 1, 1]],
[[-1, -7], 1, Concat, [1]],
[-1, 1, Conv, [256, 1, 1]], # 37
[-1, 1, Conv, [128, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[21, 1, Conv, [128, 1, 1]], # route backbone P4
[[-1, -2], 1, Concat, [1]],
[-1, 1, Conv, [64, 1, 1]],
[-2, 1, Conv, [64, 1, 1]],
[-1, 1, Conv, [64, 3, 1]],
[-1, 1, Conv, [64, 3, 1]],
[[-1, -2, -3, -4], 1, Concat, [1]],
[-1, 1, Conv, [128, 1, 1]], # 47
[-1, 1, Conv, [64, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[14, 1, Conv, [64, 1, 1]], # route backbone P3
[[-1, -2], 1, Concat, [1]],
[-1, 1, Conv, [32, 1, 1]],
[-2, 1, Conv, [32, 1, 1]],
[-1, 1, Conv, [32, 3, 1]],
[-1, 1, Conv, [32, 3, 1]],
[[-1, -2, -3, -4], 1, Concat, [1]],
[-1, 1, Conv, [64, 1, 1]], # 57
[-1, 1, Conv, [128, 3, 2]],
[[-1, 47], 1, Concat, [1]],
[-1, 1, Conv, [64, 1, 1]],
[-2, 1, Conv, [64, 1, 1]],
[-1, 1, Conv, [64, 3, 1]],
[-1, 1, Conv, [64, 3, 1]],
[[-1, -2, -3, -4], 1, Concat, [1]],
[-1, 1, Conv, [128, 1, 1]], # 65
[-1, 1, Conv, [256, 3, 2]],
[[-1, 37], 1, Concat, [1]],
[-1, 1, Conv, [128, 1, 1]],
[-2, 1, Conv, [128, 1, 1]],
[-1, 1, Conv, [128, 3, 1]],
[-1, 1, Conv, [128, 3, 1]],
[[-1, -2, -3, -4], 1, Concat, [1]],
[-1, 1, Conv, [256, 1, 1]], # 73
[57, 1, Conv, [128, 3, 1]],
[65, 1, Conv, [256, 3, 1]],
[73, 1, Conv, [512, 3, 1]],
[[74,75,76], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
]
一般来说只需要修改nc,也就是类别数目即可,别的参数初步先不需要怎么动。这里我的数据集只有1种目标对象,所以修改如下:
模型训练所需要的超参数配置文件默认存放在data目录下,如下所示:
tiny版本对应的yaml文件为hyp.scratch.tiny.yaml,如下所示:
lr0: 0.01 # initial learning rate (SGD=1E-2, Adam=1E-3)
lrf: 0.01 # final OneCycleLR learning rate (lr0 * lrf)
momentum: 0.937 # SGD momentum/Adam beta1
weight_decay: 0.0005 # optimizer weight decay 5e-4
warmup_epochs: 3.0 # warmup epochs (fractions ok)
warmup_momentum: 0.8 # warmup initial momentum
warmup_bias_lr: 0.1 # warmup initial bias lr
box: 0.05 # box loss gain
cls: 0.5 # cls loss gain
cls_pw: 1.0 # cls BCELoss positive_weight
obj: 1.0 # obj loss gain (scale with pixels)
obj_pw: 1.0 # obj BCELoss positive_weight
iou_t: 0.20 # IoU training threshold
anchor_t: 4.0 # anchor-multiple threshold
fl_gamma: 0.0 # focal loss gamma (efficientDet default gamma=1.5)
hsv_h: 0.015 # image HSV-Hue augmentation (fraction)
hsv_s: 0.7 # image HSV-Saturation augmentation (fraction)
hsv_v: 0.4 # image HSV-Value augmentation (fraction)
degrees: 0.0 # image rotation (+/- deg)
translate: 0.1 # image translation (+/- fraction)
scale: 0.5 # image scale (+/- gain)
shear: 0.0 # image shear (+/- deg)
perspective: 0.0 # image perspective (+/- fraction), range 0-0.001
flipud: 0.0 # image flip up-down (probability)
fliplr: 0.5 # image flip left-right (probability)
mosaic: 1.0 # image mosaic (probability)
mixup: 0.05 # image mixup (probability)
copy_paste: 0.0 # image copy paste (probability)
paste_in: 0.05 # image copy paste (probability)
初步学习使用的话可以先不修改,这些在后期调参的时候会用到,这里我直接使用默认参数配置。
完成这些操作后就可以修改训练模块train.py,执行训练了。主要修改的部分在
if __name__ == '__main__':
这句代码后面。为了使用方便,我这里做了一些修改工作,如下所示:
我把需要修改的参数都给提取罗列出来了不需要再那么多的代码里面找来找去,只需要修改我上面的变量值即可。
另外,我在训练的时候报错如下:
报错详情如下:
RuntimeError: Attempting to deserialize object on a CUDA device but torch.cuda.is_available() is False. If you are running on a CPU-only machine, please use torch.load with map_location=torch.device('cpu') to map your storages to the CPU.
这个报错说白了就是在CPU训练模式下,加载预训练权重文件的时候报错的,因为这时候需要显示地指定cpu加载才行,于是我修改了代码,如下:
在这里加入了判断,兼容了cpu和gpu两种训练模式。
修改报错后,重新训练,看到输出的这么一大堆信息的时候我一度认为训练成功跑起来了,如下:
结果又又又报错了,如下所示:
报错详情如下:
BrokenPipeError: [Errno 32] Broken pipe
一顿百度,找到了解决方案:
这个是windows下多线程的问题,把多线程换成单线程就可以了。
定位到问题发生模块在utils/datasets.py,打开该模块后,直接ctrl+F,搜索如下信息:
torch.utils.data.DataLoader
定位到了83行,如下所示:
将87行内容,num_workers值修改为0,保存即可,如下所示:
之后重新执行train.py模块启动模型训练。这次终于成功跑起来了,如下所示:
资源占用如下所示:
当前项目截图如下所示:
runs为模型训练过程中权重等数据的存储目录。进入runs如下所示:
进入train如下所示:
每一次运行报错再次启动都会重新创建一个exp目录,后缀会依次递增。进入最新目录截图如下所示:
weights目录是模型权重的存储目录,进入weights截图如下所示:
默认设定的是100次的迭代计算。
看下混淆矩阵,因为这里我们是单目标检测,所以混淆矩阵就相当于是二分类:
F1曲线(用于找到模型的最佳score阈值):
精确度曲线:
召回率曲线:
PR曲线:
可以看出来:检测识别的效果还是很好的。
模型结果指标数据:
100次迭代计算输出:
0/99 0G 0.08645 0.02109 0 0.1075 21 640 0.1316 0.1667 0.05215 0.01419 0.1187 0.01549 0
1/99 0G 0.07425 0.0143 0 0.08855 22 640 0.09285 0.1621 0.03091 0.009984 0.1028 0.0151 0
2/99 0G 0.06819 0.01275 0 0.08094 13 640 0.1224 0.6667 0.1063 0.02592 0.09379 0.01552 0
3/99 0G 0.06039 0.01239 0 0.07278 16 640 0.607 0.7083 0.6347 0.2695 0.09059 0.01422 0
4/99 0G 0.05559 0.01155 0 0.06714 22 640 0.6782 0.7917 0.6511 0.1883 0.09351 0.01164 0
5/99 0G 0.05053 0.01077 0 0.0613 20 640 0.9989 0.75 0.8682 0.5465 0.08279 0.01145 0
6/99 0G 0.04722 0.00985 0 0.05707 17 640 0.8326 0.8333 0.8599 0.4325 0.07511 0.01165 0
7/99 0G 0.04488 0.009128 0 0.054 17 640 0.8811 0.618 0.8112 0.1873 0.07467 0.011 0
8/99 0G 0.04992 0.008219 0 0.05814 17 640 0.7237 0.8732 0.8679 0.4222 0.0738 0.01156 0
9/99 0G 0.04696 0.008613 0 0.05557 20 640 0.9333 0.5831 0.8237 0.3091 0.07597 0.01119 0
10/99 0G 0.04695 0.008877 0 0.05583 15 640 1 0.4562 0.7159 0.3098 0.07727 0.01142 0
11/99 0G 0.04495 0.009201 0 0.05415 19 640 0.8947 0.708 0.8565 0.4405 0.06773 0.01188 0
12/99 0G 0.041 0.008533 0 0.04954 13 640 0.8053 0.875 0.8975 0.504 0.07316 0.01061 0
13/99 0G 0.04185 0.008655 0 0.0505 8 640 0.8468 0.9583 0.9474 0.6442 0.06655 0.01095 0
14/99 0G 0.03833 0.00922 0 0.04755 23 640 0.8799 0.9167 0.9322 0.5691 0.06899 0.01023 0
15/99 0G 0.0385 0.008392 0 0.04689 27 640 0.9196 1 0.9799 0.7191 0.0659 0.01057 0
16/99 0G 0.03746 0.008487 0 0.04595 20 640 1 0.9989 0.9951 0.5919 0.06961 0.00971 0
17/99 0G 0.03358 0.007715 0 0.0413 17 640 0.9231 1 0.9782 0.6687 0.06801 0.009243 0
18/99 0G 0.03469 0.007757 0 0.04245 17 640 0.8888 1 0.9857 0.6962 0.06664 0.009126 0
19/99 0G 0.03891 0.007384 0 0.04629 13 640 0.9165 0.9151 0.9683 0.6942 0.07167 0.008562 0
20/99 0G 0.03341 0.007338 0 0.04074 15 640 0.9999 1 0.9951 0.6178 0.06388 0.008745 0
21/99 0G 0.03309 0.00712 0 0.04021 19 640 1 0.9581 0.9906 0.4566 0.06662 0.008792 0
22/99 0G 0.03108 0.007027 0 0.03811 12 640 0.9231 0.9997 0.9772 0.5566 0.06053 0.008572 0
23/99 0G 0.0308 0.007174 0 0.03798 12 640 0.9998 1 0.9951 0.7559 0.05631 0.008735 0
24/99 0G 0.03142 0.007236 0 0.03865 19 640 0.9998 1 0.9951 0.6692 0.05503 0.008945 0
25/99 0G 0.03478 0.007464 0 0.04224 11 640 0.9231 0.9997 0.989 0.7802 0.05774 0.009384 0
26/99 0G 0.0365 0.007349 0 0.04385 18 640 0.8328 0.8333 0.8836 0.4577 0.06091 0.008671 0
27/99 0G 0.0341 0.007164 0 0.04126 20 640 0.9583 0.958 0.9878 0.4116 0.06685 0.008755 0
28/99 0G 0.03703 0.00709 0 0.04412 19 640 0.9597 1 0.9935 0.6888 0.05661 0.008824 0
29/99 0G 0.03433 0.007063 0 0.04139 17 640 1 0.9996 0.9951 0.5953 0.0602 0.008255 0
30/99 0G 0.03485 0.007211 0 0.04206 22 640 0.92 0.958 0.9753 0.584 0.05793 0.007916 0
31/99 0G 0.03329 0.007254 0 0.04054 21 640 0.9999 1 0.9951 0.7042 0.05681 0.007966 0
32/99 0G 0.03125 0.00786 0 0.03911 22 640 0.9999 1 0.9952 0.7568 0.05928 0.007284 0
33/99 0G 0.03193 0.007066 0 0.039 17 640 0.9999 1 0.9952 0.7773 0.05714 0.007892 0
34/99 0G 0.02773 0.006793 0 0.03453 16 640 0.96 1 0.9904 0.8012 0.05402 0.007608 0
35/99 0G 0.0293 0.007126 0 0.03643 18 640 1 1 0.9952 0.7726 0.05394 0.007457 0
36/99 0G 0.03043 0.00702 0 0.03745 17 640 1 1 0.9952 0.7329 0.04932 0.007579 0
37/99 0G 0.02925 0.006435 0 0.03568 14 640 0.9999 1 0.9952 0.6977 0.0503 0.007968 0
38/99 0G 0.02686 0.006439 0 0.0333 11 640 1 1 0.9952 0.8362 0.04803 0.008053 0
39/99 0G 0.02749 0.006792 0 0.03428 18 640 0.9999 1 0.9952 0.7249 0.0484 0.008273 0
40/99 0G 0.02841 0.006806 0 0.03522 19 640 0.9998 1 0.9953 0.7464 0.04826 0.007672 0
41/99 0G 0.02737 0.006376 0 0.03375 17 640 0.8746 0.875 0.9341 0.575 0.05707 0.007859 0
42/99 0G 0.03425 0.006874 0 0.04112 15 640 1 1 0.9954 0.6918 0.04879 0.008522 0
43/99 0G 0.02923 0.006797 0 0.03603 18 640 0.96 1 0.9937 0.7065 0.04774 0.007688 0
44/99 0G 0.0299 0.006504 0 0.0364 14 640 1 0.9999 0.9954 0.7592 0.04981 0.008118 0
45/99 0G 0.02879 0.007006 0 0.0358 16 640 0.9999 1 0.9954 0.7742 0.04913 0.007718 0
46/99 0G 0.02725 0.006798 0 0.03405 13 640 0.9999 1 0.9954 0.7273 0.04678 0.007715 0
47/99 0G 0.02942 0.006903 0 0.03633 22 640 1 1 0.9953 0.7607 0.04437 0.007802 0
48/99 0G 0.0257 0.00718 0 0.03288 24 640 1 1 0.9952 0.7488 0.04486 0.007831 0
49/99 0G 0.0274 0.00674 0 0.03414 16 640 0.9999 1 0.9953 0.7407 0.04439 0.007823 0
50/99 0G 0.02644 0.006724 0 0.03317 14 640 0.9999 1 0.9954 0.8482 0.04071 0.007581 0
51/99 0G 0.02581 0.006213 0 0.03202 10 640 1 1 0.9954 0.816 0.04281 0.007705 0
52/99 0G 0.02359 0.006992 0 0.03058 18 640 1 1 0.9954 0.8604 0.03255 0.008439 0
53/99 0G 0.02393 0.006942 0 0.03088 21 640 1 1 0.9955 0.8642 0.03305 0.007995 0
54/99 0G 0.02203 0.007255 0 0.02929 23 640 1 1 0.9955 0.8587 0.03032 0.008071 0
55/99 0G 0.02139 0.006785 0 0.02817 10 640 1 1 0.9955 0.8869 0.0299 0.00762 0
56/99 0G 0.02232 0.006676 0 0.029 11 640 1 1 0.9956 0.8487 0.03179 0.007302 0
57/99 0G 0.02199 0.006501 0 0.02849 18 640 1 1 0.9956 0.8947 0.02997 0.006732 0
58/99 0G 0.0203 0.00691 0 0.02721 21 640 1 1 0.9956 0.8894 0.02956 0.006285 0
59/99 0G 0.02032 0.006013 0 0.02634 18 640 0.9999 1 0.9956 0.895 0.02968 0.005989 0
60/99 0G 0.01971 0.006415 0 0.02612 15 640 1 1 0.9957 0.8855 0.0283 0.005833 0
61/99 0G 0.01886 0.006243 0 0.0251 15 640 0.9999 1 0.9957 0.8863 0.02836 0.005427 0
62/99 0G 0.01866 0.005752 0 0.02441 12 640 1 1 0.9956 0.8727 0.03066 0.005088 0
63/99 0G 0.0173 0.005166 0 0.02247 7 640 1 1 0.9956 0.9077 0.0299 0.004827 0
64/99 0G 0.01837 0.0058 0 0.02417 16 640 0.9999 1 0.9956 0.8771 0.03165 0.004784 0
65/99 0G 0.01754 0.005237 0 0.02278 13 640 0.9999 1 0.9958 0.9042 0.02821 0.005012 0
66/99 0G 0.01677 0.00601 0 0.02278 14 640 1 1 0.9958 0.9129 0.02833 0.004743 0
67/99 0G 0.01704 0.005926 0 0.02296 15 640 1 1 0.9957 0.8731 0.02821 0.004747 0
68/99 0G 0.01823 0.005314 0 0.02354 13 640 0.9999 1 0.9958 0.869 0.0296 0.004604 0
69/99 0G 0.01615 0.005362 0 0.02151 16 640 0.9999 1 0.9958 0.8795 0.02833 0.004512 0
70/99 0G 0.01602 0.005604 0 0.02162 21 640 1 0.9999 0.9958 0.9032 0.02666 0.004343 0
71/99 0G 0.01572 0.005379 0 0.0211 22 640 1 1 0.9958 0.8962 0.02728 0.004219 0
72/99 0G 0.01486 0.005087 0 0.01995 13 640 1 1 0.9958 0.9119 0.02647 0.004087 0
73/99 0G 0.01542 0.004972 0 0.02039 16 640 1 1 0.9958 0.9166 0.02592 0.004002 0
74/99 0G 0.01433 0.005106 0 0.01943 21 640 1 1 0.9958 0.934 0.0255 0.004025 0
75/99 0G 0.01361 0.00529 0 0.0189 20 640 1 1 0.9959 0.9441 0.02405 0.003928 0
76/99 0G 0.0129 0.004545 0 0.01745 15 640 0.9999 1 0.9958 0.9326 0.02385 0.003876 0
77/99 0G 0.01242 0.004843 0 0.01726 18 640 1 1 0.9958 0.9328 0.0239 0.003851 0
78/99 0G 0.01263 0.005073 0 0.01771 19 640 1 1 0.9957 0.9485 0.024 0.003696 0
79/99 0G 0.01177 0.004769 0 0.01654 23 640 1 1 0.9957 0.9387 0.02324 0.003642 0
80/99 0G 0.01226 0.004614 0 0.01687 10 640 0.9999 1 0.9958 0.9424 0.02323 0.00361 0
81/99 0G 0.01122 0.004606 0 0.01582 18 640 1 1 0.9958 0.9498 0.023 0.003545 0
82/99 0G 0.01084 0.004422 0 0.01526 12 640 1 1 0.9958 0.9594 0.02283 0.003506 0
83/99 0G 0.01122 0.004561 0 0.01578 16 640 0.9999 1 0.9959 0.9541 0.02255 0.003443 0
84/99 0G 0.01085 0.004742 0 0.01559 20 640 1 1 0.9959 0.9448 0.0221 0.00344 0
85/99 0G 0.01078 0.004391 0 0.01517 16 640 1 1 0.9959 0.9513 0.02194 0.003411 0
86/99 0G 0.01064 0.004382 0 0.01502 20 640 1 1 0.9959 0.9561 0.02182 0.003396 0
87/99 0G 0.01091 0.004461 0 0.01537 20 640 1 1 0.9959 0.9571 0.02182 0.003385 0
88/99 0G 0.01089 0.00456 0 0.01545 11 640 1 1 0.9959 0.9578 0.0214 0.003448 0
89/99 0G 0.01091 0.004312 0 0.01522 16 640 1 1 0.9959 0.9624 0.02072 0.003512 0
90/99 0G 0.01038 0.004264 0 0.01464 11 640 1 1 0.9959 0.9582 0.01999 0.003566 0
91/99 0G 0.01118 0.004709 0 0.01589 22 640 1 1 0.9959 0.9574 0.01936 0.0036 0
92/99 0G 0.01076 0.004586 0 0.01535 25 640 1 1 0.9959 0.9581 0.01895 0.003642 0
93/99 0G 0.01049 0.005233 0 0.01572 10 640 1 1 0.9959 0.9611 0.01883 0.003617 0
94/99 0G 0.01045 0.004639 0 0.01509 21 640 1 1 0.9959 0.9574 0.01872 0.003617 0
95/99 0G 0.01009 0.004873 0 0.01496 12 640 0.9999 1 0.9959 0.9673 0.01849 0.003629 0
96/99 0G 0.01067 0.004641 0 0.01531 15 640 1 1 0.9958 0.958 0.01823 0.003663 0
97/99 0G 0.01042 0.004466 0 0.01489 19 640 1 1 0.9959 0.958 0.01798 0.003696 0
98/99 0G 0.01102 0.004842 0 0.01587 21 640 1 1 0.9958 0.9581 0.01783 0.003703 0
99/99 0G 0.01014 0.004716 0 0.01485 13 640 0.9999 1 0.9958 0.9581 0.01773 0.003693 0
训练结束终端输出截图如下所示:
每个batch模型还会存储下载图像检测效果,随机选取一些看下:
因为我前面设置的是batchsize大小是16,所以这里面的图中包含的都是16张子图数据。
到这里模型的开发训练工作就全部结束了,之后就可以对模型进行测试了。
4、模型测试分析
训练完成后就得到了训练好的模型权重数据了,之后就可以离线加载训练好的模型记性预测分析了,这里需要需要detect.py模块的内容,如下所示:
可以看到:我保持了与train.py相同的风格,将需要修改的参数都提取罗列了出来,方便自己使用。这里为了方便我直接复制最初划分得到的测试数据集到同级目录下用于测试。项目截图如下所示:
终端执行detect.py模块,输出截图如下所示:
测试的结果会默认存储到runs目录下面,此时进入runs目录,截图如下所示:
detect目录即为测试结果的存储目录。进入detect目录截图如下所示:
进入exp目录,截图如下所示:
labels目录存储的是模型的检测计算结果,如下所示:
测试数据集共有34张图片,这里与之正好对应起来。
随机打开一个,内容如下:
我们随机看几张测试的效果,如下所示:
虽然只有几百张的图片,但是感觉YOLOv7的检测效果是很好的,尤其是目标边框边界的处理,检测框基本都是恰到好处的框住了所需要的目标对象。有意思,后面可以多研究看看。
到这里,基于YOLOv7来基于自己的数据集构建训练模型、调用离线权重文件来进行图像测试识别的完整流程就全部结束了,写了好长的时间,准备了大量的截图素材,希望是一份清晰明了的YOLOv7实战教程,有问题欢迎留言咨询。
版权归原作者 Together_CZ 所有, 如有侵权,请联系我们删除。