一、代码结构

二、训练--tools/train.py

1、设置DDP参数

DDP及其在pytorch中应用_cdknight_happy的专栏-CSDN博客

  pytorch中DDP使用

(1)参数加载

(2)模型转换成DDP模型

(3)训练数据sampler,来使得各个进程上的数据各不相同

(4)分布式模型的保存

2、读取网络结构 :models/YOLOP.py

3、定义损失函数及优化器:core/loss.py    utils/utils.py

4、 网络结构划分、用于单任务训练固定其他网络部分层

 5、初始化学习率,后续在train()中warmup会调整学习率

首先定义一个优化器,定义好优化器以后,就可以给这个优化器绑定一个指数衰减学习率控制器。

 (1) torch.optim.lr_scheduler.LambdaLR

语法:class torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda, last_epoch=-1)

参数:

     optimizer (Optimizer):要更改学习率的优化器,sgd或adam;
     lr_lambda(function or list):根据epoch计算λ \lambdaλ的函数;或者是一个list的这样的   function,分别计算各个parameter groups的学习率更新用到的λ \lambdaλ;
     last_epoch (int):最后一个epoch的index,如果是训练了很多个epoch后中断了,继续训练,这个值就等于加载的模型的epoch。默认为-1表示从头开始训练,即从epoch=1开始。

6、训练 function.py中train函数,读取数据集中数据,调用autodrivedataset.py中

__getitem__函数,返回 input, target, paths, shapes

三、dataset/bdd.py文件 

1、数据读取

该文件继承AutoDriveDataset.py

1、def __getitem__(self, idx)函数根据标签的索引路径读取图片、label、seg_label、line_label。

2、按比例缩放操作:letterbox()图像增加灰边

3、数据增强操作

2、数据增强

utils/utils.py文件

1、random_perspective()放射变换增强

2、augment_hsv()颜色HSV通道增强

3、cutout()

四、models/YOLOP.py文件

 yolop包括三个检测任务,目标检测+可行驶区域检测+车道线检测。

YOLOP = [
[24, 33, 42],   #目标检测层索引, 可行驶区域层索引, 车道线分割层索引
[ -1, Focus, [3, 32, 3]],   #0 通道扩增
[ -1, Conv, [32, 64, 3, 2]],    #1
[ -1, BottleneckCSP, [64, 64, 1]],  #2
[ -1, Conv, [64, 128, 3, 2]],   #3
[ -1, BottleneckCSP, [128, 128, 3]],    #4
[ -1, Conv, [128, 256, 3, 2]],  #5
[ -1, BottleneckCSP, [256, 256, 3]],    #6
[ -1, Conv, [256, 512, 3, 2]],  #7
[ -1, SPP, [512, 512, [5, 9, 13]]],     #8
[ -1, BottleneckCSP, [512, 512, 1, False]],     #9
[ -1, Conv,[512, 256, 1, 1]],   #10
[ -1, Upsample, [None, 2, 'nearest']],  #11
[ [-1, 6], Concat, [1]],    #12
[ -1, BottleneckCSP, [512, 256, 1, False]], #13
[ -1, Conv, [256, 128, 1, 1]],  #14
[ -1, Upsample, [None, 2, 'nearest']],  #15
[ [-1,4], Concat, [1]],   #16  #Encoder网络共享编码器 backbown部分+neck部分

[ -1, BottleneckCSP, [256, 128, 1, False]],     #17 PAN
[ -1, Conv, [128, 128, 3, 2]],      #18
[ [-1, 14], Concat, [1]],       #19
[ -1, BottleneckCSP, [256, 256, 1, False]],     #20
[ -1, Conv, [256, 256, 3, 2]],      #21
[ [-1, 10], Concat, [1]],   #22
[ -1, BottleneckCSP, [512, 512, 1, False]],     #23
[ [17, 20, 23], Detect,  [1, [[3,9,5,11,4,20], [7,18,6,39,12,31], [19,50,38,81,68,157]], [128, 256, 512]]],
# 目标检测头 #24 默认anchor设定
[ 16, Conv, [256, 128, 3, 1]],   #25
[ -1, Upsample, [None, 2, 'nearest']],  #26
[ -1, BottleneckCSP, [128, 64, 1, False]],  #27
[ -1, Conv, [64, 32, 3, 1]],    #28
[ -1, Upsample, [None, 2, 'nearest']],  #29
[ -1, Conv, [32, 16, 3, 1]],    #30
[ -1, BottleneckCSP, [16, 8, 1, False]],    #31
[ -1, Upsample, [None, 2, 'nearest']],  #32
[ -1, Conv, [8, 2, 3, 1]], #33  三次上采样 可行驶区域检测头

[ 16, Conv, [256, 128, 3, 1]],   #34
[ -1, Upsample, [None, 2, 'nearest']],  #35
[ -1, BottleneckCSP, [128, 64, 1, False]],  #36
[ -1, Conv, [64, 32, 3, 1]],    #37
[ -1, Upsample, [None, 2, 'nearest']],  #38
[ -1, Conv, [32, 16, 3, 1]],    #39
[ -1, BottleneckCSP, [16, 8, 1, False]],    #40
[ -1, Upsample, [None, 2, 'nearest']],  #41
[ -1, Conv, [8, 2, 3, 1]] #42 三次上采样 车道线检测头
]

五、损失函数

loss.py postprocess.py

参考:YOLOV5源码解析-损失解释 compute_loss(), build_targtets()_劲草浅躬行-CSDN博客

           yolov5代码详解-build_targets(p, targets, model)_a1874738854的博客-CSDN博客

build_targets思想:

build_targets主要为了拿到所有targets(扩充了周围grids)对应的类别,框,batch中图片数索引和anchor索引,以及具体的anchors。 每个gt按照正样本选取策略,生成相应的5个框,再根据与默认anchor匹配,计算宽高的比例值,根据阈值过滤不相符的框,得到最终正样本。

#[b, a, gj, gi]为shape=54的向量,pi为[4,3,48,80,6]维矩阵,从pi中按照b, a, gj, gi的索引挑出想要的目标,最终为[54,6]维
ps = pi[b, a, gj, gi]  # prediction subset corresponding to targets 。b, a, gj, gi为索引值,在pi中挑选出6列的目标

损失计算:

(1)目标检测损失

predictions[0] 目标检测分支[[4,3,48,80,6],[4,3,24,40,6],[4,3,12,20,6]]。

targets[0] 目标检测标签 [32,6],格式为[batch_num,class,x1,y1,x2,y2]。根据build_targets在每个检测层生成相应的正样本tbox[]。

将每层的预测结果tensor pi根据正样本格式得到ps = pi[b, a, gj, gi]。(不理解)

计算每个检测层预测与正样本之间的ciou坐标损失。

iou = bbox_iou(pbox.T, tbox[i], x1y1x2y2=False, CIoU=True)  # iou(prediction, target)
lbox += (1.0 - iou).mean()  # iou loss 坐标损失

obj损失:

# 正样本(anchor)处保存预测框和gt框的iou,负样本(anchor)处仍然是0,用作obj损失的真值。
tobj[b, a, gj, gi] = (1.0 - model.gr) + model.gr * iou.detach().

cls类别损失:

t = torch.full_like(ps[:, 5:], cn, device=device)  # targets
t[range(n), tcls[i]] = cp# 为正样本分配标签,cp=1,变成onehot类型标枪。
lcls += BCEcls(ps[:, 5:], t)  # BCE# 只有正样本的分类损失

(2)可行驶区域损失

drive_area_seg_predicts = predictions[1].view(-1)
drive_area_seg_targets = targets[1].view(-1)
lseg_da = BCEseg(drive_area_seg_predicts, drive_area_seg_targets)

(3)车道线损失

lane_line_seg_predicts = predictions[2].view(-1)
lane_line_seg_targets = targets[2].view(-1)
lseg_ll = BCEseg(lane_line_seg_predicts, lane_line_seg_targets)

六、单任务训练

train.py

 loss.py

七、训练问题

1、raise AttributeError(name) 报train.py中114行torch.backends.cudnn.deterministic 错误。

解决方法:(1)检查依赖库是否都安装

                  (2)检查代码:我出现的问题是代码不小心被注释。default.py中                    ‘_C.CUDNN.DETERMINISTIC = False’

Logo

为武汉地区的开发者提供学习、交流和合作的平台。社区聚集了众多技术爱好者和专业人士,涵盖了多个领域,包括人工智能、大数据、云计算、区块链等。社区定期举办技术分享、培训和活动,为开发者提供更多的学习和交流机会。

更多推荐