一点就分享系列(实践篇5-下篇)持续迭代!依旧全网首发—Yolov5项目爆肝升级High-level集结!逐一任务介绍,附赠模型通用修改方法和部署教程。

动机——停止魔改吧!

最近回归检测等经典任务的更新,因为最近接触了很多生成类、比较前沿的任务,比如数字人等包含多模态(cv\nlp\tts\音视频合等),恰好这些我都涉略,但是过程中也发现了很多现在的LOW-LEVEL任务其实都需要High-level作为基础组件算法,所以这并不是矛盾的,是相辅相成的,在当今只会检测、分类、分割等经典的算法,已经无法满足现在的需求了,因此我的开源项目升级维护的同时我会把重心放在一些新的方向上,旨在完成2022年SOTA的high-level的CV任务,参考了 V7和YOLO-POSE等将该开源项目升级,完成检测、分类、分割、关键点回归的任务。目前已经基本完成了,有兴趣的可以先GIT测试反馈,具体说明和后续会慢慢调试完善,核心东西还是GIT项目,所以先发布下,可以先看README。结束本周辛苦的工作,刚看V5官方也发了,下周见朋友们

火速迭代中,有问题可以留言,会及时修复,项目由于大量更新难免存在小问题,欢迎反馈,另外有虚拟人,动捕的朋友请联系我请教交流下技术。

Yolov5_research_PLUS项目地址:https://github.com/positive666/yolov5_research.git

 - 最新的yoloV5工程风格精简融合High-level任务:完成先进的检测器、分类器、分割、关键点检测功能集成,删除额外的三方库依赖。
 
 - 实时的v5代码更新改动&&v7的适配(每周更新一次,无更新则同步官方代码优化)
 
 - 早期集成的attention、self-attention维护和调试
 
 - 额外的网络结构和Tricks补充
 
 - 通用修改方式总结和不断补充,修改任意模型等自主修改
 
 - Deepstream部署SDK和Tensorrt多种转换方式(旧版GIT未更新)

一点就分享系列(实践篇6——上篇) yolov8文章添加传送门

一点就分享系列(实践篇5-上篇)

一点就分享系列(实践篇5-下篇)

一、项目说明和使用

快速学会如何修改YOLO思路和技巧

保持了V5实时的改动,主要是代码优化,还在不停迭代中,详情可移步GIT,代码风格保持V5的基本架构,便于使用,所以其实你可以下载官方的版本,然后同时下载我这套版本,基于我这套修改或者基于官方这套修改也可以,后面会说为什么要这么做,先放出干货:
在2021年我的第一篇YOLO5文章中,已经介绍过通用修改方式了,现在精炼一下,授人以鱼不如授人以渔,明白了这个自己DIY就好了,不需要看任何的参考。

  1. 定制化的算子函数在common.py中定义,函数名加入到yolo.py中的到parse_model(d, ch)的函数解析列表中(这步根据你的定义的输入和输出通道数,自己把握)

  2. 在设计yaml中,遇到通道不匹配的问题,一般是两个原因:

  1. 因为yaml的通道数要看你的模型有没有做缩放,也就是比如yolov5S在YAML里的通道数是减半了,可能导致输入和输入的通道数不匹配,所以要看好你改的模型是否有宽和高上的缩放.
  2. 设计的算子通道数输出和下一层输入不匹配,或者存在Concat等操作,具体要自己调试(比如做BIFPN的时候就会遇到这类情况,是个辛苦活)
  1. 定制化的Head部分在yolo.py中定义,如果存在特殊结构,初始化的结构时候需要在yolo.py中的class DetectionModel(BaseModel):加入判断需要额外的初始化定义函数。(往往no attribute “xx” —stride等报错于此有关),举例比如解耦头判断是否是ifistance判断下,然后初始化Head部分的权重参数。

  2. 添加的结构中如果有可学习的权重参数,需要加入在utils/torch_utils.py 中的smart_optimizer函数中加入到优化器迭(参考我的GIT即可)
    验证:设计好后需要验证:python models/yolo.py只能验证你的模型是否定义正确和正常解析 只能验证前面1、2条,然后需要使用训练命令迭代几次以上正常无报错训练即可。

  3. 训练中如果出现NAN或者不收敛,在保证代码没低级错误的前提下,确认你当前使用的是哪个hyp的yaml:

调整超参数(比如:调整超参数data/hyps/xxx.yaml 中的lrf,当前版本和官方V5版本一样,默认在data/hyps/hyp.scratch-low.yaml的Lrf是0.01,可以需要改成0.2)
修改模型大小和宽高(比如:s上不适用,可能M/L/XL等P5 、P6模型上使用)
检测算子的代码计算
结合第下面第6条

  1. 有比较难训练的模型,比如带有多个自注意力的可能不仅要调整超参数,还需要分阶段训练(例如:可以先只训练1层的swin-transformerv2然后观察是否存在问题,然后生成一个预训练权重,去微调更复杂的结构,因为过程中很可能发生梯度爆炸或者消失。不过V2改进了这个现象,可以看我之前的一篇关于swinV2的理解)

  2. 对于做任意一个多任务的核心修改思路:从代码改动层面来说,主要是数据处理读取,增强的部分(augmentations.py、dataloaders.py、general.py、plots.py),HEDA部分,LOSS部分(metric.py、loss.py)、算子部分(common.py/yolo.py),最后是训练、推理、验证等直接使用的脚本。

总结:前五条是基本修改方法,后面是引申的一些问题和解决方案,并不能应对所有情况!

然后告诉大家为什么开始说最好同时下载官方的新版本和我GIT的版本:

  1. 其实我的版本和官方实时整合好并且调试好的,我每周会看下改动,然后合并验证,基本做到了实时融合!所以你完全可以使用我的版本在此基础上修改,没必要浪费过多时间。
  2. 当你想自己动手修改的时候,你可以使用我的项目进行补充和修改,在这过程中可能会发生你无法解决的问题,比如训练精度下降的问题,你可以同样数据集使用V5原版对比检查来看看结果是否一致,官方你总信得过吧!否则就是你的改动引起了问题。

写到这里有点感慨,从2020年到2022年,折腾两年好像对于工作业务也没什么帮助,后来想了下也正常,工业界其实没有那么需要这种研究性质的改进工作,算是留住自己热衷这行的初心吧(声明:从无任何收费、无任何宣传群),后续我会继续业余时间保持更新和一些新颖的idea添加,同时重心会转向GAN、数字孪生等业务上,也会分享给大家。

这是当前的目录,每个分支使用上是独立的:如分割、关键点检测、分类等独立的部分是放在各自命名的文件夹内使用。

yolov5_research
│   pose  
│   └─────   ##关键点检测
│   ...   
│
│   segment
│   └─────    ## 分割
|   classify
│   └─────     ##分类
│   utils
│   └───── .
|         .           .
|                     .
|            	     . segment      ##分割的数据处理操作部分
│     
|       .
|       .      ##其余为检测核心代码和通用部分

单机多卡训练:

使用DistributedDataParallel,多个进程只进行倒数传播,每个GPU都进行一次梯度求导和参数更新,这比DataParallel的方式更高效,因为DataParalledl只有一个主GPU进行参数更新,所以需要各个子进程调用的GPU传递倒数到主GPU后,才会更新参数給各个GPU,所以这会比DistributedDataParallel每个GPU直接进行参数更新要慢很多。
–nproc_per_node: 作为GPU的使用数量节点数
–batch:总batch-size ,然后除以Node数量 ,平均给每个GPU。

python -m torch.distributed.run --nproc_per_node 2 train.py --batch 64 --data coco.yaml --weights yolov5s.pt --device 0,1

多机多卡训练:

#主机
python -m torch.distributed.run --nproc_per_node G --nnodes N --node_rank 0 --master_addr "192.168.1.1" --master_port 1234 train.py --batch 64 --data coco.yaml --cfg yolov5s.yaml --weights ''
#多个副机
python -m torch.distributed.run --nproc_per_node G --nnodes N --node_rank R --master_addr "192.168.1.1" --master_port 1234 train.py --batch 64 --data coco.yaml --cfg yolov5s.yaml --weights ''

–master_port:端口号
master_addr:主进程ip地址
G:每个机器的GPU数量
N:机器数量
R:子机器序号

1.检测篇

python train.py --data <your data yaml>  --cfg  <your model yaml> --weights <weights path>  --batch-size 128    --hyp   <hyps yaml>  --batch-size <numbers>  

notes:
其中后置的几个参数说明下:

“–swin_float” :,这个是由于里面的矩阵点乘不支持half半精度,所以要转成float,不过后面随着swinv2出了我会改成官方的版本,目前是老版本。

“–aux_ota_loss” for aux- head only . Such "models/v7_cfg/training/yolov7x6x.yaml, (P6-model) ,you can create aux -head models.目前是来自于yolov7的P6大模型才具备辅助分支。命令中加入目前需要配合带有辅助分支模块的结构,可选择models/v7_cfg/training/中P6的V7结构,并且确保超参里的ota_loss为1,可直接选择V7的超参yaml 。

“–ota_loss” :在data/hyp/中的超参yaml最后一行,默认关闭为0,开启为1

运行脚本——重参数模型重构成推理版本

python reparameterization.py --weights <yolov7.pt,yolov7e6e.pt…> --name --save_file models/v7_cfg/deploy --cfg <model.yaml>

这里遇到无法加载权重的问题,可能是我的版本去掉了Reorg这个模块,所以如果你读取原始的预权重这个地方可能会报错,这里提供两个方式解决:
1.使用脚本置换掉浅层权重,这个是完全没问题的.
2.后续我会上传新的权重.

2.姿态篇

数据集COCO关键点
关键点数据集构建,基于 YOLO-Pose Multi-person Pose estimation mode,详情点击进入我github拿数据集和预训练权重训练。

  1. YOLO-POSE是bottom-up的方法,在每个head上多预测了关键点的属性(17个),核心是OKS的指标优化,这里并没有走常规的heat-map热力图的方式作LOSS,即作者使用的是直接回归关键点方式,进行LOSS设计,那么就和检测同理,我们要考虑尺度不变形,因此OKS的LOSS:每个单独的关键点计算OKS,并累加到一起,
  2. 使用二值交叉熵去预测每一个点的置信度。
  3. 不同于top-down,所以点的预测是不会受制于BOX的约束,即在遮挡情况下,也会完整预测到对应的关键点,即使该点会出现在BOX外面,如图所示。
    在这里插入图片描述

这里来让我们看下代码,loss在我github中,的utils/loss.py的ComputeLoss_Kpt函数中:

在这里插入图片描述

sigmas = torch.tensor([.26, .25, .25, .35, .35, .79, .79, .72, .72, .62, .62, 1.07, 1.07, .87, .87, .89, .89], device=device) / 10.0   #17个点的方差
if self.kpt_label:
                    #Direct kpt prediction 取预测的点坐标和置信度
                    pkpt_x = ps[:, 6::3] * 2. - 0.5
                    pkpt_y = ps[:, 7::3] * 2. - 0.5
                    pkpt_score = ps[:, 8::3]
                    #mask
                    kpt_mask = (tkpt[i][:, 0::2] != 0)   #取真值只要是非0的就置为True,此时就变成了一个mask矩阵,非0的都是可见的关键点
                    lkptv += self.BCEcls(pkpt_score, kpt_mask.float()) #计算关键点置信度损失
                    #l2 distance based loss  计算L2距离
                    lkpt += (((pkpt-tkpt[i])*kpt_mask)**2).mean()  #Try to make this loss based on distance instead of ordinary difference
                    #oks based loss  基于OKS公式计算,不懂得看下上面OKS公式就明白了
                    d = (pkpt_x-tkpt[i][:,0::2])**2 + (pkpt_y-tkpt[i][:,1::2])**2
                    s = torch.prod(tbox[i][:,-2:], dim=1, keepdim=True)
                    kpt_loss_factor = (torch.sum(kpt_mask != 0) + torch.sum(kpt_mask == 0))/torch.sum(kpt_mask != 0)
                    lkpt += kpt_loss_factor*((1 - torch.exp(-d/(s*(4*sigmas**2)+1e-9)))*kpt_mask).mean()
```python

yolov5_research
│ pose
│ └─────(key point detect code )
│ …

coco_kpts(your data yaml path name )
│ images
│ annotations/**.json
| labels
│ └─────train2017
│ │ └───
| | └───
| | ’
| | .
│ └─val2017
| └───
| └───
| .
| .
| train2017.txt
| val2017.txt

### 推理
```python
python pose/detect.py --weights pose/pose_weights/yolov7-w6-pose.pt  --source  data/images/bus.jpg   --kpt-label 

训练

  python pose/train.py --data  data/coco_kpts.yaml  --cfg  pose/cfg/yolov7-w6-pose.yaml weights yolov7-w6-person.pt --img 960  --kpt-label --hyp data/hyps/hyp.pose.yaml

注意:还是老问题,这里V7的大模型用第一层是Reorg你可以用,也可以换成 Conv, [64, 6, 2, 2]]

分割、分类是V5的官方版本,这里暂时不做过多叙述,看情况会补充详细说明…

3.分割篇

#推理
python segment/predict.py --weights yolov5s-seg.pt --source 0           
#训练
python segment/train.py --data coco128-seg.yaml --weights yolov5s-seg.pt --img 640  # from pretrained           

4.分类篇

Train

# Single-GPU
python classify/train.py --model yolov5s-cls.pt --data cifar100 --epochs 5 --img 224 --batch 128

# Multi-GPU DDP
python -m torch.distributed.run --nproc_per_node 4 --master_port 1 classify/train.py --model yolov5s-cls.pt --data imagenet --epochs 5 --img 224 --device 0,1,2,3

二、 Deepstream&Tensorrt——算法应用的终点是部署!

这部分是纯C++的,是我2021年在GIT开源的工作,包含了检测、人脸识别、OCR的SDK,这个基本也是当时全网首发开源的部署一套的SDK了,偏向工程业务可能学生党基本用不到,不过我觉得后续还是整理下打算更新出来6.0的版本

猜你喜欢

转载自blog.csdn.net/weixin_44119362/article/details/126895964