一:创新点
YOLO_v5的网络结构和YOLO_v4几乎完全一致,可以理解为YOLO_v5是YOLO_v4的更工程化的源码实现。因此,还不了解YOLO_v4的小伙伴可以移步到yolov4讲解。
YOLO_v5源码一直在维护、更新,所以可读性很强。下面我展示一下整体流程图:
后面将k3、k4、k5分层输入检测头,和YOLO_v3一样。
二:模型重点(具体请看上文链接)
- 数据增强Mosaic
- CIOU
- PAN
- CSPBlock
三:损失函数设计
首先我贴出源码,如下:
可见,源码中的重点就是self.build_targets(p, targets)
函数,用来生成target,这个后面讲解。分析一下主程序,不难发现,损失函数由三大部分构成:
- bbox回归损失,源码中使用的CIOU
- 置信度损失,对于正样本使用pred_box和gt_box的iou作为target,对于负样本则为0。使用的二值交叉熵计算损失。
- 分类损失,也是二值交叉熵计算损失。源码中设置了标签平滑,pos_label=0.95,neg_label=0.05,但是源码中设置了eps=0,所以实际没有执行平滑操作。这里还有一点值得一提,就是
nn.BCEWithLogitsLoss()
中的pos_weight
参数,设置它可以缓解正样本不均衡的情况,官方文档如下:
pos_weight (Tensor, optional): a weight of positive examples.
Must be a vector with length equal to the number of classes.
接下来,我重点讲解一下self.build_targets(p, targets)
中的内容,先看如下源码:
下面,我分步骤讲解标签生成过程:
- 假设target是
[16 6]
,维度代表着(batch, cls, cx, cy, w, h),生成新的targets[3 16 7]
,也就是给每个target都分配三个anchor,用于后面的操作 - 将target中的[:, -2:]即w、h乘以
gain
(缩放尺度),将原图中归一化的gt_box投射到feature_map中 - 将每个target中的gt_box和所有尺度的anchor进行长宽比计算,anchor_wh/gt_wh和gt_wh/anchor_wh取最大值,如果小于设定的阈值,则保留,否则剔除。
- 因为上述的这种机制,会导致一个target在当前的feature_map上没有anchor匹配,其实也是一种尺度筛选的升级版本(scalse assignment)
- 给target分配好了满足尺度的anchor(或未分配),再将gt_center所在的cell的上、下、左、右侧的cell中靠近gt_center的两个方向的cell也分配和当前target相同的标签,除了gt_center;加了偏移不同外 ,都相同。也就是对targets进行了扩展,gt_center所在cell的附近cell也有资格当正样本了,这点和yolov3大大不同。这么做可以提高recall。
- 最后就是简单的分配,最后
return (target_box,target_label,index)