1 项目介绍及环境配置
下载yolov5 tags 5.0源码,https://github.com/ultralytics/yolov5/tree/v5.0,解压
Pycharm 中创建conda虚拟环境
激活conda虚拟环境
根据作者提供的requirements.txt文件,pip install -r requirements.txt
如果作者没有提供requirement.txt文件,根据报错信息,手动安装缺少的库
2 利用yolov5进行预测[detect.py]
2.1 先run起来,直观感受
在pycharm中直接run detect.py,报错信息如下:
解决方案:model/common.py里面去找到这个SPPF的类,把它拷过来到你这个Tags5的model/common.py里面,这样你的代码就也有这个类了,还要引入一个warnings包就行了!
有的同学找不到SPPF这个类,那我现在直接粘贴在这里,你们只需要复制到你们的common.py里面即可,记得把import warnings放在上面去:
import warnings
class SPPF(nn.Module):
# Spatial Pyramid Pooling - Fast (SPPF) layer for YOLOv5 by Glenn Jocher
def __init__(self, c1, c2, k=5): # equivalent to SPP(k=(5, 9, 13))
super().__init__()
c_ = c1 // 2 # hidden channels
self.cv1 = Conv(c1, c_, 1, 1)
self.cv2 = Conv(c_ * 4, c2, 1, 1)
self.m = nn.MaxPool2d(kernel_size=k, stride=1, padding=k // 2)
def forward(self, x):
x = self.cv1(x)
with warnings.catch_warnings():
warnings.simplefilter('ignore') # suppress torch 1.9.0 max_pool2d() warning
y1 = self.m(x)
y2 = self.m(y1)
return self.cv2(torch.cat([x, y1, y2, self.m(y2)], 1))
Note:运行过程中可能还会有很多其他错误,具体遇到了可自寻查询。
运行完之后,可以看到run/detect/exp2目录生成了对应的识别结果
2.2 detect.py 中各参数介绍解释
2.2.1 weight参数
weights 参数用于指定网络模型,默认设置的是 yolov5s.pt, 如果想要使用其他网络模型,可以打开 GitHub 的 YOLOv5 官方开源项目,在 Release 中找到对应版本的模型进行下载,如下图所示:
https://github.com/ultralytics/yolov5/releases
下载好之后放到根目录,同时把这里改成对应的模型名
2.2.2 source参数
source 参数用于给网络模型指定输入,可以对图片,视频等进行目标检测
default值 | 检测对象 |
---|---|
data/images | images 文件夹下的所有图片 |
data/images/bus.jpg | images 文件夹下的 bus.jpg |
data/video/demo.mp4 | video 文件夹下的所有视频 |
0 | 调用笔记本摄像头 |
1 | 调用 USB 摄像头 |
Note: 当我们对视频进行目标检测时,通常会在运行时调用 view-img 参数,从而能够实时查看视频每一帧的检测效果。
2.2.3 img-size参数
这个 img-size 参数用于将图片缩放后放入神经网络模型中,通过训练确定标注框的位置,然后将标注框等比例缩放,画在原图片上,因此输入图片的尺寸和输出图片的尺寸相同,未发生改变。在 GitHub 的 YOLOv5 官方开源项目的 Release 中,我们可以看到不同 .pt 模型所对应的 img-size ,例如,由于 yolov5s.pt 模型是在 640 分辨率下进行训练的,所以使用该模型时应将 img-size 设为 640 。
2.2.4 conf-thres参数
这个 conf-thres 参数用于设置置信度,当检测目标的概率大于 default 默认值时,就会在图片中被标注出来。
- default = 0.25:检测目标的概率大于 0.25 时,就会在图片中被标注出来
- default = 0:无论检测目标的概率多少,图片中所有的检测框都 会 被标注出来
- default = 1:无论检测目标的概率多少,图片中所有的检测框都 不 被标注出来
2.2.5 iou-thres参数
这个 iou-thres 参数是交并比阈值,交并比大于 default 阈值的将被视作同一个物体,需要 nms 选取最佳框,小于 default 阈值的则被视作不同物体,不需要做处理,下面的说明可能有点绕口,大家可以看补充的图~
- iou-thres 值 越大 ,则容易将 同一物体 的不同预测结果当成对 多个物体 的不同预测结果,导致同一物品出现了多个预测结果
- iou-thres 值 越小 ,则容易将 多个物体 的不同预测结果当成对 同一物体 的不同预测结果,导致不同物品只出现一个预测结果
同一 Person 有三个框,若要选择最佳的框,可采用 IoU 的方法选取与真实标注框交并比最大的那个框。
IoU计算公式
IoU示例
2.2.6 device参数
这个 device 参数用于选择代码运行所使用的设备,例如 cuda 或者 cpu ,若 default 默认值为空,则会自动检测。
parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
2.2.7 view-img参数
parser.add_argument('--view-img', action='store_true', help='display results')
这个 view-img 参数没有 default 默认值,只有 action 值,若在终端运行时指定了这个参数,就被设置为 True,从而能在运行过程中实时显示图片或者视频的检测结果,若在终端运行时未指定这个参数,则被设置为 False 。
通常借助 view-img 参数来实时查看视频的检测情况
2.2.8 save-txt参数
parser.add_argument('--save-txt', action='store_true', help='save results to *.txt')
这个 save-txt 参数用于将检测结果保存为 txt 文件,具体的参数设置与运行效果如下图所示:
指定save-txt参数之后,可以看到runs/exp3/labels目录下生成了yolo格式的文本标注文件
2.2.9 *save-conf参数
这个 save-conf 参数用于确认是否以 .txt 格式保存目标的置信度,必须与 save-txt 参数配合使用,具体如图所示:
parser.add_argument('--save-conf', action='store_true', help='save confidences in --save-txt labels')
可以看到生成的txt文件后面多了一列置信度
2.2.10 *nosave参数
这个 nosave 参数用于不对预测结果进行保存,但仍会生成空的 exp 文件夹,我们平时对 nosave 调用不多,但如果在对视频进行检测时,将其与 view-img 配合使用,就可以不用保存很多 txt 文件啦~
2.2.11 classes参数
这个 classes 参数用于指定想要检测的类别,如果只想检测 人 这个类别,我们可以调用 --classes 0 ,具体运行效果如下图所示:
可以看到在检测的图片中只是识别到了人
2.2.12 *agnostic-nms参数
这个 agnostic-nms 参数是增强版的 nms ,可以提高检测框框右上角的置信度,具体可分别对图像添加–agnostic-nms和不添加这个参数进行输出对比
2.2.13 *augment参数
这个 augment 参数也是用于增强的,同样可以提高检测框框右上角的置信度,具体可分别对图像添加–agnostic-nms和不添加这个参数进行输出对比
2.2.14 update参数
这个 update 参数用于对所有模型进行 strip_optimizer 操作,去除 .pt 文件中的优化器等不必要的信息。
2.2.15 project参数
这个 project 参数就是我们预测结果保存的路径。
2.2.16 name参数
这个 name 参数就是我们预测结果保存的文件夹名字。
2.2.17 exist-ok参数
这个 exist-ok 参数用于确认本次预测结果是否保存在原来的文件夹,如果调用这个参数,那么本次预测结果会保存在 name 指定的文件夹中,如果未调用这个参数,则将保存在自动新建的文件夹中
2.2.18 断点调试
3 训练yolov5神经网络[train.py]
3.0 先run起来,直观感受
3.1 train.py 参数介绍和解释
train.py 中参数如下
parser = argparse.ArgumentParser()
parser.add_argument('--weights', type=str, default='yolov5s.pt', help='initial weights path')
parser.add_argument('--cfg', type=str, default='', help='model.yaml path')
parser.add_argument('--data', type=str, default='data/coco128.yaml', help='data.yaml path')
parser.add_argument('--hyp', type=str, default='data/hyp.scratch.yaml', help='hyperparameters path')
parser.add_argument('--epochs', type=int, default=300)
parser.add_argument('--batch-size', type=int, default=16, help='total batch size for all GPUs')
parser.add_argument('--img-size', nargs='+', type=int, default=[640, 640], help='[train, test] image sizes')
parser.add_argument('--rect', action='store_true', help='rectangular training')
parser.add_argument('--resume', nargs='?', const=True, default=False, help='resume most recent training')
parser.add_argument('--nosave', action='store_true', help='only save final checkpoint')
parser.add_argument('--notest', action='store_true', help='only test final epoch')
parser.add_argument('--noautoanchor', action='store_true', help='disable autoanchor check')
parser.add_argument('--evolve', action='store_true', help='evolve hyperparameters')
parser.add_argument('--bucket', type=str, default='', help='gsutil bucket')
parser.add_argument('--cache-images', action='store_true', help='cache images for faster training')
parser.add_argument('--image-weights', action='store_true', help='use weighted image selection for training')
parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
parser.add_argument('--multi-scale', action='store_true', help='vary img-size +/- 50%%')
parser.add_argument('--single-cls', action='store_true', help='train multi-class data as single-class')
parser.add_argument('--adam', action='store_true', help='use torch.optim.Adam() optimizer')
parser.add_argument('--sync-bn', action='store_true', help='use SyncBatchNorm, only available in DDP mode')
parser.add_argument('--local_rank', type=int, default=-1, help='DDP parameter, do not modify')
parser.add_argument('--workers', type=int, default=8, help='maximum number of dataloader workers')
parser.add_argument('--project', default='runs/train', help='save to project/name')
parser.add_argument('--entity', default=None, help='W&B entity')
parser.add_argument('--name', default='exp', help='save to project/name')
parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
parser.add_argument('--quad', action='store_true', help='quad dataloader')
parser.add_argument('--linear-lr', action='store_true', help='linear LR')
parser.add_argument('--label-smoothing', type=float, default=0.0, help='Label smoothing epsilon')
parser.add_argument('--upload_dataset', action='store_true', help='Upload dataset as W&B artifact table')
parser.add_argument('--bbox_interval', type=int, default=-1, help='Set bounding-box image logging interval for W&B')
parser.add_argument('--save_period', type=int, default=-1, help='Log model after every "save_period" epoch')
parser.add_argument('--artifact_alias', type=str, default="latest", help='version of dataset artifact to be used')
opt = parser.parse_args()
下面对这34个参数进行逐一讲解
3.1.1 weights参数
这个 weights 参数用于指定网络模型,其 default 默认设置为 yolov5s.pt 模型,也可设置为 yolov5m.pt、yolov5l.pt、yolov5x.pt 等官方预训练权重文件,代码运行后会自动下载这些模型,并将其保存在项目的根目录下。如果大家觉得下载速度慢,也可以去 GitHub 提供的 YOLOv5 官方开源项目中下载,点击【Release】就可以跳转对应页面下载 .pt 模型啦!
【补充】当 default 设置为空时,代码运行后将从头开始训练,这个过程可能会比较漫长
3.1.2 cfg参数
这个 cfg 参数用于指定模型配置文件的路径,YOLOv5 官方开源项目的 Tags 5.0 源码提供了 4 个模型配置文件,配置文件中指定了部分参数信息和 backbone 的结构信息,如下图所示,值得注意的是,如果已经使用 weight 参数加载了预训练权重文件,就可以不使用该参数,因为训练时将直接使用预训练权重文件中保存的模型结构。
3.1.3 data参数
这个 data 参数用于指定数据集配置文件的路径,YOLOv5 官方开源项目的 Tags 5.0 源码提供了 4 个数据集配置文件,配置文件中存放了数据集的类别和路径信息,如下图所示,如果代码运行后没有检测到数据集,会自动下载 COCO128 数据集,当然也可以自行下载。
3.1.4 hpy参数
这个 hyp 参数用于指定超参数配置文件的路径,YOLOv5 官方开源项目的 Tags 5.0 源码提供了 2 个超参数配置文件,配置文件中存放了大量的参数信息,具体如图所示,简单来说, hyp.scratch.yaml 存放了从头开始训练 COCO 数据集模型时需要考虑的的常见超参数,而 hyp.finetune.yaml 则存放了对 VOC 数据集进行微调时需要考虑的常见超参数。
3.1.5 epochs参数
这个 epochs 参数用于指定训练的迭代轮数,默认设置为 default = 300 轮,表示将整个训练集训练 300 次。
parser.add_argument('--epochs', type=int, default=300)
3.1.6 batch-size参数
这个 batch-size 参数用于指定训练批量的大小,默认设置为 16 ,表示每次都从训练集中取 16 个训练样本放入模型进行训练。
【补充】当 default 设置为 -1 时,代码运行后将自动调节 batch-size 的大小。
parser.add_argument('--batch-size', type=int, default=16, help='total batch size for all GPUs')
3.1.7 img-size参数
这个 img-size 参数用于指定模型训练和测试时输入图片的尺寸大小,默认设置为 640 × 640,使用不同 .pt 模型时需要对这个参数进行调整,我们可以打开 GitHub 提供的 YOLOv5 官方开源项目,点击【Release】进入对应页面,如下图所示。
3.1.8 rect参数
这个 rect 参数用于确定是否用矩阵推理的方式去训练模型,矩阵推理将不再要求训练图片为正方形,在训练过程中能够对输入的矩形图片进行预处理,在保持原高宽比的基础上进行 resize 和填充,从而加速模型训练,减少信息冗余。
parser.add_argument('--rect', action='store_true', help='rectangular training')
【补充】为了让大家能够更加直观地感受到方形推理和矩阵推理的区别,我在下面贴了土堆视频教程的截图,请看!
左边方形推理,右边矩阵推理,矩阵推理少了很多不必要的填充
3.1.9 resume参数
这个 resume 参数用于确定是否进行断点续训,也就是从上一个训练任务中断的地方继续训练,直至训练完成,默认值为 False ,如果想采用断点续训的方式,不仅要将 default 设置为 True ,还应该指定使用哪个训练过的模型,具体的命令可参考下面这行:
python train.py --resume D:\Downloads\yolov5-5.0\runs\train\exp\weights\last.pt
parser.add_argument('--resume', nargs='?', const=True, default=False, help='resume most recent training')
3.1.10 nosave参数
这个 nosave 参数用于确认是否只保存最后一轮训练的 .pt 权重文件,默认是关闭的,保存 best.pt 和 last.pt 两个权重文件。
parser.add_argument('--nosave', action='store_true', help='only save final checkpoint')
3.1.11 notest参数
这个 notest 参数用于确认是否只在最后一轮训练进行测试,默认是关闭的。
parser.add_argument('--notest', action='store_true', help='only test final epoch')
3.1.12 noautoanchor参数
这个 noautoanchor 参数用于确认是否禁用自动计算锚框的功能,默认是禁用的,如果大家想更加深入了解这个参数的作用,可以去搜索 锚点 和 锚框 ,也可以看我在本节开头推荐的知乎文章,里面介绍得比较详细,点击【这里】就可以直接跳转哟~
parser.add_argument('--noautoanchor', action='store_true', help='disable autoanchor check')
3.1.13 *evolve参数
这个 evolve 参数用于确认是否使用超参数优化算法进行自动调参,默认是关闭的,建议大家不要动这个参数。如果大家想更加深入了解这个参数的作用, 可以看我在本节开头推荐的知乎文章,里面介绍得比较详细,点击【这里】就可以直接跳转哟~(我 CV 我自己)
parser.add_argument('--evolve', action='store_true', help='evolve hyperparameters')
【补充】YOLOv5 使用遗传超参数进化,YOLOv5 提供的默认参数是通过在 COCO 数据集上使用超参数进化得来的,如下图所示:
3.1.14 *bucker参数
这个 bucket 参数用于在谷歌云盘中下载或者上传数据,现在不怎么使用。
3.1.15 cache-images参数
这个 cache-images 参数用于确定是否提前将数据集图片缓存到内存,加快数据加载和训练速度,默认值为 False ,开启这个参数后就会缓存图片,从而更好地训练模型。
3.1.16 image-weights参数
这个 image-weights 参数用于确认是否对数据集图片进行加权训练,主要为了解决样本不平衡的问题,默认值为 False ,开启这个参数后就会对上一轮训练效果不好的图片,在下一轮训练中增加一些权重。
3.1.17 device参数
这个 device 参数用于选择训练使用的设备处理器,例如 GPU 或 CPU ,若 default 默认值为空,则代码会自动检测,除此之外,还存在下面这几种情况:
- 设备没有 GPU ,只能使用 CPU 训练:python train.py --device cpu
- 设备有单个 GPU ,使用单个 GPU 训练:python train.py --device 0
- 设备有多个 GPU ,使用单个 GPU 训练:python train.py --device 0(使用第 1 张 GPU 训练)
- 设备有多个 GPU ,使用多个 GPU 训练:python train.py --device 0, 1, 2(使用第 1,2,3 张 GPU 训练)
3.1.18 multi-scale参数
这个 multi-scale 参数用于确认是否启用多尺度训练,多尺度训练是指设置多种图片输入尺度,训练时每隔一定 iterations 就随机选取其中一种尺度进行训练,这样训练出来的模型具有更强的鲁棒性,默认是关闭的,开启这个参数后,训练过程中每次输入图片都会放大或者缩小 50% 。
3.1.19 single-cls参数
这个 single-cls 参数用于设定训练数据集是单类别还是多类别,默认值为 False,也就是多类别。
3.1.20 adam参数
这个 adam 参数用于确定训练过程中是否使用 Adam 优化器,如果不开启这个参数,则会使用 随机梯度下降 。
3.1.21 sync-bn参数
这个 sync-bn 参数用于确定是否开启跨卡 同步批量归一化 (Synchronized Batch Normalization),默认是关闭的,开启这个参数后就可以使用 SyncBatchNorm 多 GPU 进行分布式训练。
3.1.22 *local_rank参数
这个 local_rank 参数用于 DistributedDataParallel 单机多卡训练,是 DDP 参数,单 GPU 设备不需要设置。
3.1.23 workers参数
这个 workers 参数用于设置 Dataloader 使用的最大 numworkers(加载和处理数据的线程数),默认值为 8 ,建议改为 0 ,表示不使用多线程,只使用主线程进行数据加载和处理。
3.1.24 project参数
这个 project 参数用于指定训练好的模型的保存路径,默认在 runs / train ,如下图所示。
3.1.25 *entity参数
这个 entity 参数表示在线可视化工具 wandb ,类似于 tensorboard ,使用不多。
3.1.26 name参数
这个 name 参数用于指定保存模型的文件夹名,默认为 exp ,如下图所示。
3.1.27 exist-ok参数
这个 exist-ok 参数用于确定是否覆盖同名的训练结果保存路径,默认是关闭的,表示不覆盖,每次预测结果都被保存在自动新建的文件夹中,例如 exp1、exp2 等文件夹。开启这个参数后,本次预测结果将被保存在 name 指定的文件夹中,通常是 exp 文件夹。
3.1.28 quad参数
这个 quad 参数用于确认是否使用 quad dataloader 数据加载器,默认是关闭的,quad dataloader 可以并行地从磁盘中读取和处理多个图像,并将其打包成四个图像,从而减少数据读取和预处理的时间,提高数据加载的效率。
3.1.29 linear-lr参数
这个 linear-lr 参数用于对学习速率进行调整,默认值为 False ,通过余弦函数来降低学习率,生效后按照线性方式调整学习率。
3.1.30 label-smoothing参数
这个 label-smoothing 参数用于对标签进行平滑处理,防止在分类算法过程中产生过拟合问题,默认是关闭的。
3.1.31 upload_dataset参数
这个 upload_dataset 参数用于确认是否将 dataset 上传到 wandb tabel ,默认值为 False ,开启这个参数后,数据集将作为交互式 dsviz 表,可在浏览器中查看、查询、筛选和分析数据集。调用这个参数时,可以选择是否传递参数:
- 调用 --upload_dataset 参数,但没有传递参数,则表示上传数据集
- 调用 --upload_dataset 参数,并且有传递参数 val ,则表示上传 val 数据集
3.1.32 bbox-interval参数
这个 bbox_interval 参数用于设置界框图像记录间隔,即指定在训练过程中每隔多少个 epoch 记录一次带有边界框的图片,默认是关闭的。可使用命令行:python train.py --bbox_interval n( n > 0 时表示每隔 n 个 epoch 记录;n <= 0 时表示关闭 bbox_interval )。
3.1.33 save_period参数
这个 save_period 参数用于设置每隔多少个 epoch 保存一次训练权重,默认是关闭的,可使用命令行:python train.py --save_period n( n > 0 时表示每隔 n 个 epoch 保存;n <= 0 时表示关闭 save_period,只保存 best 和 last 权重 )。
3.1.34 artifact_alias参数
这个 artifact_alias 参数用于指定要使用的数据集工件的版本别名
【补充】在 YOLOv5 的 Tags5 版本中,artifact_alias 参数的功能尚未实现,因此这个参数没有用
3.1.35 断点调试查看参数
3.2 本地训练yolov5(本地只有CPU)
3.3 利用云端GPU训练yolov5
在本地run了train.py 之后,可以发现这里生成了best.pt和last.pt
4 制作和训练自己的数据集
关于如何获得训练数据集,大致有以下几种方式:
- 获取 PyTorch 官网或者其他网站提供的数据集,例如 VOC 数据集和 COCO 数据集等,进行标注
- 自己获取数据集,手动进行 人工标注
- 自己获取数据集,借助已经训练好的模型进行 半人工标注
- 获取仿真数据集,可借助 训练 GAN 网络 或者 数字图像处理 等方式获取仿真数据集
【补充】如果大家想要进一步了解数字图像处理,可以 Google 搜索 synthetic data object detection github 。
我们可以根据 GitHub 提供的 YOLOv5 官方开源项目中 Wiki 下的【Train Custom Data】学习如何自制数据集并训练。
4.1 自制数据集
步骤一:准备 images
我们需要从网上下载若干图片用于制作数据集,我主要选取的是包含汽车、自行车和人等元素的图片,如下图所示。
步骤二:在线标注数据集
我们需要对这些图片进行标注,可以借助 CVAT 或者 Make Sense 等网站在线标注,这里我选用的是 Make Sense 网站。
【操作1】将准备的 images 上传到 Make Sense 网站。「makesense.ai」
【操作2】预先添加 labels ,可以使用 + 逐个添加标签,也可以使用 Load labels from file 一次性添加标签。
【操作3】使用矩形框标注物体
步骤三:导出图片的标注文件
我们需要将图片的标注导出,在 Actions 中选择 Export Annotations,导出为包含 YOLO 格式文件的压缩包。
导出后下载到本地,我们可以看到对应的txt文件
4.2 训练数据集
【操作1】我们需要将前面得到 images 和 labels 相关文件存储到项目中的对应位置,同时还要编写 mydata.yaml 数据集配置文件:
【注意】在 mydata.yaml 数据集配置文件中,classes names 的顺序要与我们在 Make Sense 官网添加的 labels 顺序相同。
【操作2】我们需要将 train.py 文件中 --data 参数的默认值修改为 mydata.yaml 文件的路径,然后运行 train.py 文件:
修改玩陈之后,直接run train.py,可以看到已经可以正常训练
操作到这里,如果大家的 best.pt 训练到位,那么在指定的文件夹下就能看到被标注好的图片啦 (๑•̀ㅂ•́)و✧ 可惜我只训练了 18 轮,训练效果还没出来 /(ㄒoㄒ)/~~ 大家如果有兴趣的话可以尽可能训练完 300 轮,然后看看标注效果