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
该文件继承AutoDriveDataset.py
1、def __getitem__(self, idx)函数根据标签的索引路径读取图片、label、seg_label、line_label。
2、按比例缩放操作:letterbox()图像增加灰边
3、数据增强操作
utils/utils.py文件
1、random_perspective()放射变换增强
2、augment_hsv()颜色HSV通道增强
3、cutout()
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’