当前位置:   article > 正文

YOLOv9全流程保姆级跑通教程!从训练到验证再到推理!一文读懂YOLOv9!!!_yolov9 训练

yolov9 训练

YOLOv9全流程保姆级跑通教程!从训练到验证再到推理!一文读懂YOLOv9!!

YOLOv9原文链接戳这里,原文全文翻译请关注B站Ai学术叫叫首er

B站全文戳这里!

详细的改进教程以及源码,戳这!戳这!!戳这!!!B站:AI学术叫叫兽 源码在相簿的链接中,动态中也有链接,感谢支持!祝科研遥遥领先!


详细的改进教程以及源码,戳这!戳这!!戳这!!!B站:AI学术叫叫兽 源码在相簿的链接中,动态中也有链接,感谢支持!祝科研遥遥领先!
截止到发稿时,B站YOLOv9最新改进系列的源码包,已更新了11种的改进!自己排列组合2-4种后,考虑位置不同后可排列组合上千种!!专注AI学术,关注B站博主:Ai学术叫叫兽er!

1简介

本文是全新的SOTA模型YOLOv9的全部使用教程,需要注意的是YOLOv9发布时间为2024年2月21日,截至最近的日期也没有过去几天,从其实验结果上来看,其效果无论是精度和参数量都要大于过去的一些实时检测模型,其主要创新点是两个分别是提出了Programmable Gradient Information​​(PGI)的结构以及全新的主干Generalized ELAN(GELAN)

接下来本文将会手把手指导各位家人们如何使用自定义数据集训练YOLOv9模型,以及获取数据集/训练/推理/验证/调参and导出实验结果用于对比分析等,全文干货!各位自行分段实操!!!

以下为相关绘图:
在这里插入图片描述
图3.PGI及相关网络架构和方法。
(a)路径聚合网络(PAN))[37],(b)可逆列(RevCol)[3],(c)传统深度监督,以及(d)我们提出的可编程梯度信息(PGI)。 PGI主要由三个部分组成:(1)主分支:用于推理的架构,(2)辅助可逆分支:生成可靠的梯度,为主分支提供向后传输,(3)多级辅助信息:控制主分支 学习可规划的多层次语义信息

在这里插入图片描述GELAN 的架构:(a) CSPNet [64]、(b) ELAN [65] 和 © 提出的 GELAN。 我们模仿CSPNet,将ELAN扩展为GELAN,可以支持任何计算块。

在这里插入图片描述PlainNet、ResNet、CSPNet、GELAN在不同深度处随机初始权重输出的特征图(可视化结果)。 100 层后,ResNet 开始产生足以混淆对象信息的前馈输出。 我们提出的 GELAN 直到第 150 层仍然可以保留相当完整的信息,并且直到第 200 层仍然具有足够的辨别力。

2 环境搭建

云服务器环境搭建三秒完成教程,戳这!戳这!!戳这!!!B站:AI学术叫叫兽 源码在相簿的链接中,动态中也有链接,感谢支持!祝科研遥遥领先!

3 官方模型下载

下载网址(官方)

4 模型训练

分别有三个模型训练的文件,建议选择第二个即可!

train.py:主分支

train_dual.py:一个辅助分支+一个主分支。

triple_branch.py:2个辅助分支+1个主分支

YOLOv9.yaml如下所示:

# YOLOv9
 
# parameters
nc: 80  # number of classes
depth_multiple: 1.0  # model depth multiple
width_multiple: 1.0  # layer channel multiple
#activation: nn.LeakyReLU(0.1)
#activation: nn.ReLU()
 
# anchors
anchors: 3
 
# YOLOv9 backbone
backbone:
  [
   [-1, 1, Silence, []],
   # conv down
   [-1, 1, Conv, [64, 3, 2]],  # 1-P1/2
   # conv down
   [-1, 1, Conv, [128, 3, 2]],  # 2-P2/4
   # elan-1 block
   [-1, 1, RepNCSPELAN4, [256, 128, 64, 1]],  # 3
   # conv down
   [-1, 1, Conv, [256, 3, 2]],  # 4-P3/8
   # elan-2 block
   [-1, 1, RepNCSPELAN4, [512, 256, 128, 1]],  # 5
   # conv down
   [-1, 1, Conv, [512, 3, 2]],  # 6-P4/16
   # elan-2 block
   [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]],  # 7
   # conv down
   [-1, 1, Conv, [512, 3, 2]],  # 8-P5/32
   # elan-2 block
   [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]],  # 9
  ]
 
# YOLOv9 head
head:
  [
   # elan-spp block
   [-1, 1, SPPELAN, [512, 256]],  # 10
 
   # up-concat merge
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 7], 1, Concat, [1]],  # cat backbone P4
 
   # elan-2 block
   [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]],  # 13
 
   # up-concat merge
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 5], 1, Concat, [1]],  # cat backbone P3
 
   # elan-2 block
   [-1, 1, RepNCSPELAN4, [256, 256, 128, 1]],  # 16 (P3/8-small)
 
   # conv-down merge
   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 13], 1, Concat, [1]],  # cat head P4
 
   # elan-2 block
   [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]],  # 19 (P4/16-medium)
 
   # conv-down merge
   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 10], 1, Concat, [1]],  # cat head P5
 
   # elan-2 block
   [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]],  # 22 (P5/32-large)
   
   # routing
   [5, 1, CBLinear, [[256]]], # 23
   [7, 1, CBLinear, [[256, 512]]], # 24
   [9, 1, CBLinear, [[256, 512, 512]]], # 25
   
   # conv down
   [0, 1, Conv, [64, 3, 2]],  # 26-P1/2
 
   # conv down
   [-1, 1, Conv, [128, 3, 2]],  # 27-P2/4
 
   # elan-1 block
   [-1, 1, RepNCSPELAN4, [256, 128, 64, 1]],  # 28
 
   # conv down fuse
   [-1, 1, Conv, [256, 3, 2]],  # 29-P3/8
   [[23, 24, 25, -1], 1, CBFuse, [[0, 0, 0]]], # 30  
 
   # elan-2 block
   [-1, 1, RepNCSPELAN4, [512, 256, 128, 1]],  # 31
 
   # conv down fuse
   [-1, 1, Conv, [512, 3, 2]],  # 32-P4/16
   [[24, 25, -1], 1, CBFuse, [[1, 1]]], # 33 
 
   # elan-2 block
   [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]],  # 34
 
   # conv down fuse
   [-1, 1, Conv, [512, 3, 2]],  # 35-P5/32
   [[25, -1], 1, CBFuse, [[2]]], # 36
 
   # elan-2 block
   [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]],  # 37
 
   # detect
   [[31, 34, 37, 16, 19, 22], 1, DualDDetect, [nc]],  # DualDDetect(A3, A4, A5, P3, P4, P5)
  ]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108

需要注意的是,目前v9暂时不支持修改网络的深度和宽度(如下两行),默认均为1.0!

depth_multiple: 1.0  # model depth multiple
width_multiple: 1.0  # layer channel multiple
  • 1
  • 2

5 下载数据集

测试数据集我们采用coco128数据,可以官方下载,也可以找我要(B站:Ai学术叫叫兽er 链接戳这私信即可

6 数据集路径配置

path: ../datasets/coco128 # dataset root dir
train: images/train2017 # train images (relative to 'path') 128 images
val: images/train2017 # val images (relative to 'path') 128 images
test: # test images (optional)

  • 1
  • 2
  • 3
  • 4
  • 5

数据集路径配置如上所示,文字在技术操作方面总是感觉苍白无力,为此我专门录制相关视频教程放到了B站
详细路径教程视频演示在B站(B站:Ai学术叫叫兽er 链接戳这私信即可

详细如何配置路径以及路径的学习看我的配套视频即可(B站:Ai学术叫叫兽er 链接戳这私信即可

7 模型训练

在这里插入图片描述
选择train_dual,py进行训练

训练指令为:

python train_dual.py
  • 1

8 模型参数

总参数如下:

def parse_opt(known=False):
    parser = argparse.ArgumentParser()
    # parser.add_argument('--weights', type=str, default=ROOT / 'yolo.pt', help='initial weights path')
    # parser.add_argument('--cfg', type=str, default='', help='model.yaml path')
    parser.add_argument('--weights', type=str, default='', help='initial weights path')
    parser.add_argument('--cfg', type=str, default='yolov9.yaml', help='model.yaml path')
    parser.add_argument('--data', type=str, default=ROOT / 'data/coco128.yaml', help='dataset.yaml path')
    parser.add_argument('--hyp', type=str, default=ROOT / 'data/hyps/hyp.scratch-high.yaml', help='hyperparameters path')
    parser.add_argument('--epochs', type=int, default=100, help='total training epochs')
    parser.add_argument('--batch-size', type=int, default=1, help='total batch size for all GPUs, -1 for autobatch')
    parser.add_argument('--imgsz', '--img', '--img-size', type=int, default=64, help='train, val image size (pixels)')
    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('--noval', action='store_true', help='only validate final epoch')
    parser.add_argument('--noautoanchor', action='store_true', help='disable AutoAnchor')
    parser.add_argument('--noplots', action='store_true', help='save no plot files')
    parser.add_argument('--evolve', type=int, nargs='?', const=300, help='evolve hyperparameters for x generations')
    parser.add_argument('--bucket', type=str, default='', help='gsutil bucket')
    parser.add_argument('--cache', type=str, nargs='?', const='ram', help='image --cache ram/disk')
    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('--optimizer', type=str, choices=['SGD', 'Adam', 'AdamW', 'LION'], default='SGD', help='optimizer')
    parser.add_argument('--sync-bn', action='store_true', help='use SyncBatchNorm, only available in DDP mode')
    parser.add_argument('--workers', type=int, default=0, help='max dataloader workers (per RANK in DDP mode)')
    parser.add_argument('--project', default=ROOT / 'runs/train', help='save to project/name')
    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('--cos-lr', action='store_true', help='cosine LR scheduler')
    parser.add_argument('--flat-cos-lr', action='store_true', help='flat cosine LR scheduler')
    parser.add_argument('--fixed-lr', action='store_true', help='fixed LR scheduler')
    parser.add_argument('--label-smoothing', type=float, default=0.0, help='Label smoothing epsilon')
    parser.add_argument('--patience', type=int, default=100, help='EarlyStopping patience (epochs without improvement)')
    parser.add_argument('--freeze', nargs='+', type=int, default=[0], help='Freeze layers: backbone=10, first3=0 1 2')
    parser.add_argument('--save-period', type=int, default=-1, help='Save checkpoint every x epochs (disabled if < 1)')
    parser.add_argument('--seed', type=int, default=0, help='Global training seed')
    parser.add_argument('--local_rank', type=int, default=-1, help='Automatic DDP Multi-GPU argument, do not modify')
    parser.add_argument('--min-items', type=int, default=0, help='Experimental')
    parser.add_argument('--close-mosaic', type=int, default=0, help='Experimental')

    # Logger arguments
    parser.add_argument('--entity', default=None, help='Entity')
    parser.add_argument('--upload_dataset', nargs='?', const=True, default=False, help='Upload data, "val" option')
    parser.add_argument('--bbox_interval', type=int, default=-1, help='Set bounding-box image logging interval')
    parser.add_argument('--artifact_alias', type=str, default='latest', help='Version of dataset artifact to use')

    return parser.parse_known_args()[0] if known else parser.parse_args()


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

一般需要调整的参数分析,如下:
1.训练权重,选择自己需要加载的权重,或者直接使用默认的即可。

  parser.add_argument('--weights', type=str, default='', help='initial weights path')
  • 1

2.训练模型,选择需训练的模型,跑YOLOv9原模型的则不需要改变。

 parser.add_argument('--cfg', type=str, default='yolov9-seg.yaml', help='model.yaml path')
  • 1

3.数据路径,视频组详解,

parser.add_argument('--data', type=str, default=ROOT / 'data/coco128.yaml', help='dataset.yaml path')
  • 1

4.迭代次数,默认100,实际则需要收敛为止。

 parser.add_argument('--epochs', type=int, default=100, help='total training epochs')
  • 1

5.batch-size, 默认16,根据自身电脑配置选择

parser.add_argument('--batch-size', type=int, default=1, help='total batch size for all GPUs, -1 for autobatch')
  • 1

6.image-size,默认640,建议采用默认的即可!

 parser.add_argument('--imgsz', '--img', '--img-size', type=int, default=64, help='train, val image size (pixels)')
  • 1

7.device,选择GPU或者CPU训练,选GPU!CPU训练太慢。

    parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
  • 1

8.resume,是否选择继续上次中止的训练进程继续进行,默认为否。

    parser.add_argument('--resume', nargs='?', const=True, default=False, help='resume most recent training')
  • 1

大家跑实验基本上就需要考虑上述参数更改即可。

9训练结果及导出

训练模型的路径如下所示:
yolov9/runs/train/exp/weights

exp文件中会自动生成resualt.csv文件,将其导出,用于绘制相关图表,绘图教程见我B站吧——戳这!戳这!!戳这!!!!

结语

行文至此,基本结束,剩下的就看各位小伙伴的炼丹运气了!本专栏目前为新开的,后期我会根据各种最新的前沿顶会进行论文复现,也会对一些老的改进机制进行补充,遥遥领先了家人们!!!YOLOv9全网最新改进系列(炼丹炉)戳这!戳这!!戳这!!!!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/678423
推荐阅读
相关标签
  

闽ICP备14008679号