手把手调参最新 YOLOv7 模型 训练部分 - 最新版本(二)
YOLO系列模型在目标检测领域有着十分重要的地位,随着版本不停的迭代,模型的性能在不断地提升,源码提供的功能也越来越多,那么如何使用源码就显得十分的重要,接下来我会通过文章带大家手把手去了解Yolov7(最新版本)的每一个参数的含义,并且通过具体的图片例子让大家明白每个参数改动将会给网络带来哪些影响。
这篇文章讲解的是 关于 YOLOv7最新版本 的训练部分参数解析
想了解 YOLOv5-v6.2 版本参数的同学可以关注这篇文章:手把手调参Yolo v5 (v6.2)训练部分代码
官方YOLOv7 项目地址:https://github.com/WongKinYiu/yolov7
进入仓库 可以查看项目目前提供的最新版本
我选择的代码是main分支版本
在配置Conda环境后就可以进入项目了,可以通过作者提供的requirements.txt文件进行快速安装。
即在终端中键入如下指令:
pip install -r requirements.txt
requirements.txt文件里面有一些包被注释掉了,这些包是做一些额外的操作时候用的,不安装并不会影响训练和测试;
这里介绍一下官方给提供的训练方式,我们平时都是在Pycharm中点击“运行”按钮去训练模型,其实还可以通过命令行的方式去训练,训练后的结果会自动保存到runs/detect路径下;其实在这条指令后面还可以加上一些参数,具体怎么加后面会详细说明。
python train.py --workers 8 --device 0 --batch-size 32 --data data/coco.yaml --img 640 640 --cfg cfg/training/yolov7.yaml --weights '' --name yolov7 --hyp data/hyp.scratch.p5.yaml
首先还是打开根目录下的train.py,如下
parser = argparse.ArgumentParser()
parser.add_argument('--weights', type=str, default='yolo7.pt', help='initial weights path')
parser.add_argument('--cfg', type=str, default='', help='model.yaml path')
parser.add_argument('--data', type=str, default='data/coco.yaml', help='data.yaml path')
parser.add_argument('--hyp', type=str, default='data/hyp.scratch.p5.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')
parser.add_argument('--freeze', nargs='+', type=int, default=[0], help='Freeze layers: backbone of yolov7=50, first3=0 1 2')
opt = parser.parse_args()
parser.add_argument('--weights', type=str, default='yolo7.pt', help='initial weights path')
指定预训练权重路径;如果这里设置为空的话,就是自己从头开始进行训练;官方有提供预训练权重
parser.add_argument('--cfg', type=str, default='', help='model.yaml path')
指定模型配置文件路径的;源码里面提供了几个配置文件,配置文件里面指定了一些参数信息和backbone的结构信息。
parser.add_argument('--data', type=str, default='data/coco.yaml', help='data.yaml path')
数据集对应的参数文件;里面主要存放数据集的类别和路径信息。
parser.add_argument('--hyp', type=str, default='data/hyp.scratch.p5.yaml', help='hyperparameters path')
指定超参数文件的路径;超参数里面包含了大量的参数信息,提供了4个
parser.add_argument('--epochs', type=int, default=300)
训练的轮数;默认为300轮,显示效果是0-299
parser.add_argument('--batch-size', type=int, default=16, help='total batch size for all GPUs')
每批次的输入数据量;default=-1将时自动调节batchsize大小
这里说一下 epoch、batchsize、iteration三者之间的联系
1、batchsize是批次大小,假如取batchsize=24,则表示每次训练时在训练集中取24个训练样本进行训练。
2、iteration是迭代次数,1个iteration就等于一次使用24(batchsize大小)个样本进行训练。
3、epoch:1个epoch就等于使用训练集中全部样本训练1次。
parser.add_argument('--img-size', nargs='+', type=int, default=[640, 640], help='[train, test] image sizes')
训练集和测试集图片的像素大小;输入默认640*640,可以进行适当的调整,这样才能达到好的效果。
parser.add_argument('--rect', action='store_true', help='rectangular training')
是否采用矩阵推理的方式去训练模型;
所谓矩阵推理就是不再要求你训练的图片是正方形了;矩阵推理会加速模型的推理过程,减少一些冗余信息。
下图分别是方形推理方式和矩阵推理方式
parser.add_argument('--resume', nargs='?', const=True, default=False, help='resume most recent training')
断点续训:即是否在之前训练的一个模型基础上继续训练,default 值默认是 false;如果想采用断点续训的方式,这里我推荐一种写法,即首先将default=False 改为 default=True
随后在终端中键入如下指令
python train.py --resume D:\Pycharm_Projects\yolov7\runs\train\exp19\weights\last.pt
D:\Pycharm_Projects\yolov7\runs\train\exp19\weights\last.pt为你上一次中断时保存的pt文件路径
输入指令后就可以看到模型是继续从上次结束时开始训练的
parser.add_argument('--nosave', action='store_true', help='only save final checkpoint')
是否只保存最后一轮的pt文件;我们默认是保存best.pt和last.pt两个的
parser.add_argument('--notest', action='store_true', help='only test final epoch')
只在最后一轮测试;正常情况下每个epoch都会计算mAP,但如果开启了这个参数,那么就只在最后一轮上进行测试,不建议开启
parser.add_argument('--noautoanchor', action='store_true', help='disable autoanchor check')
是否禁用自动锚框;默认是开启的,自动锚点的好处是可以简化训练过程;
yolov7中预先设定了一下锚定框,这些锚框是针对coco数据集的,其他目标检测也适用,可以在models/yolov7.文件中查看,例如如图所示,这些框针对的图片大小是640640。这是默认的anchor大小。需要注意的是在目标检测任务中,一般使用大特征图上去检测小目标,因为大特征图含有更多小目标信息,因此大特征图上的anchor数值通常设置为小数值,小特征图检测大目标,因此小特征图上anchor数值设置较大。
在yolov7 中自动锚定框选项,训练开始前,会自动计算数据集标注信息针对默认锚定框的最佳召回率,当最佳召回率大于等于0.98时,则不需要更新锚定框;如果最佳召回率小于0.98,则需要重新计算符合此数据集的锚定框。
在parse_opt设置了默认自动计算锚框选项,如果不想自动计算,可以设置这个,建议不要改动。
parser.add_argument('--evolve', action='store_true', help='evolve hyperparameters')
遗传超参数进化;yolov7使用遗传超参数进化,提供的默认参数是通过在COCO数据集上使用超参数进化得来的(也就是下图这些参数)。由于超参数进化会耗费大量的资源和时间,所以建议大家不要动这个参数。
遗传算法是利用种群搜索技术将种群作为一组问题解,通过对当前种群施加类似生物遗传环境因素的选择、交叉、变异等一系列的遗传操作来产生新一代的种群,并逐步使种群优化到包含近似最优解的状态,遗传算法调优能够求出优化问题的全局最优解,优化结果与初始条件无关,算法独立于求解域,具有较强的鲁棒性,适合于求解复杂的优化问题,应用较为广泛。
parser.add_argument('--bucket', type=str, default='', help='gsutil bucket')
谷歌云盘;通过这个参数可以下载谷歌云盘上的一些东西,但是现在没必要使用了
parser.add_argument('--cache-images', action='store_true', help='cache images for faster training')
是否提前缓存图片到内存,以加快训练速度,默认False;开启这个参数就会对图片进行缓存,从而更好的训练模型。
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%%')
是否启用多尺度训练,默认是不开启的;多尺度训练是指设置几种不同的图片输入尺度,训练时每隔一定iterations随机选取一种尺度训练,这样训练出来的模型鲁棒性更强。
多尺度训练在比赛中经常可以看到他身影,是被证明了有效提高性能的方式。输入图片的尺寸对检测模型的性能影响很大,在基础网络部分常常会生成比原图小数十倍的特征图,导致小物体的特征描述不容易被检测网络捕捉。通过输入更大、更多尺寸的图片进行训练,能够在一定程度上提高检测模型对物体大小的鲁棒性。
parser.add_argument('--single-cls', action='store_true', help='train multi-class data as single-class')
设定训练数据集是单类别还是多类别;默认为 false多类别
parser.add_argument(‘–adam’, action=‘store_true’, help=‘use torch.optim.Adam() optimizer’)
选择使用 Adam 优化器
parser.add_argument('--sync-bn', action='store_true', help='use SyncBatchNorm, only available in DDP mode')
是否开启跨卡同步BN;开启参数后即可使用 SyncBatchNorm多 GPU 进行分布式训练
parser.add_argument('--local_rank', type=int, default=-1, help='DDP parameter, do not modify')
DDP参数,请勿修改
parser.add_argument('--workers', type=int, default=8, help='maximum number of dataloader workers')
最大worker数量;
parser.add_argument('--project', default='runs/train', help='save to project/name')
指定训练好的模型的保存路径;默认在runs/train
parser.add_argument('--entity', default=None, help='W&B entity')
wandb 库对应的东西;
parser.add_argument('--name', default='exp', help='save to project/name')
设定保存的模型文件夹名,默认在exp;
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')
用于调整学习率;含义是通过余弦函数来降低学习率。
使用梯度下降算法来优化目标函数的时候,当越来越接近Loss值的全局最小值时,学习率应该变得更小来使得模型尽可能接近这一点,而余弦退火可以通过余弦函数来降低学习率。
parser.add_argument('--label-smoothing', type=float, default=0.0, help='Label smoothing epsilon')
是否对标签进行平滑处理,默认是不启用的;
在训练样本中,我们并不能保证所有sample都标注正确,如果某个样本标注错误,就可能产生负面印象,如果我们有办法“告诉”模型,样本的标签不一定正确,那么训练出来的模型对于少量的样本错误就会有“免疫力”采用随机化的标签作为训练数据时,损失函数有1-ε的概率与上面的式子相同,比如说告诉模型只有0.95概率是那个标签。
parser.add_argument('--upload_dataset', action='store_true', help='Upload dataset as W&B artifact table')
wandb 库对应的东西。
是否上传dataset到wandb tabel(将数据集作为交互式 dsviz表 在浏览器中查看、查询、筛选和分析数据集) 默认False
parser.add_argument('--bbox_interval', type=int, default=-1, help='Set bounding-box image logging interval for W&B')
wandb 库对应的东西,可以忽略。
设置界框图像记录间隔 Set bounding-box image logging interval for W&B 默认-1
parser.add_argument('--save_period', type=int, default=-1, help='Log model after every "save_period" epoch')
用于设置多少个epoch保存一下checkpoint,int 型,默认为 -1。
parser.add_argument('--artifact_alias', type=str, default="latest", help='version of dataset artifact to be used')
表示还未实现的内容,忽略即可
arser.add_argument('--freeze', nargs='+', type=int, default=[0], help='Freeze layers: backbone of yolov7=50, first3=0 1 2')
冻结层:yolov7=50 的Backbone
有问题欢迎大家指正