【YOLO系列】YOLOv4详解:模型结构、损失函数、训练方法及代码实现

发布于:2025-07-29 ⋅ 阅读:(16) ⋅ 点赞:(0)

YOLOv4详解:模型结构、损失函数、训练方法及代码实现

motivation

YOLO系列作者Joseph Redmon与Alexey Bochkovskiy致力于解决目标检测领域的核心矛盾:精度与速度的平衡。YOLOv4的诞生源于两大需求:

  1. 工业落地:在移动端/边缘设备实现实时检测(>30FPS)
  2. 学术突破:无需昂贵算力(如1080Ti即可训练),在MS COCO数据集达到SOTA

methods

1. 数据加载创新

  • Mosaic数据增强:拼接4张图像,提升小目标检测能力
  • Self-Adversarial Training:对抗训练增强遮挡场景鲁棒性
# Mosaic增强示例(简化版)
def mosaic_augment(imgs):
    output = np.zeros((608,608,3))
    xc, yc = [random.randint(300,500) for _ in range(2)]  # 随机中心点
    indices = [0,1,2,3]  # 4张图索引
    for i, img in enumerate(imgs):
        h,w,_ = img.shape
        if i==0:  # 左上
            output[:yc,:xc] = cv2.resize(img, (xc,yc))
        ... # 其他区域填充
    return output

2. 模型结构
在这里插入图片描述

  • Backbone:CSPDarknet53(跨阶段局部网络)
    • 引入CSP结构降低计算量 C o u t = C i n 2 C_{out}=\frac{C_{in}}{2} Cout=2Cin
  • Neck:SPP + PANet
    • SPP模块:多尺度池化融合特征 f o u t = Concat ( MaxPool k × k ( f i n ) ) , k ∈ { 1 , 5 , 9 , 13 } f_{out} = \text{Concat}( \text{MaxPool}_{k \times k}(f_{in}) ), k \in \{1,5,9,13\} fout=Concat(MaxPoolk×k(fin)),k{1,5,9,13}
    • PANet:双向特征金字塔,增强浅层定位信息
  • Head:解耦头结构
    • 分类/回归任务分离,提升收敛效率

3. 损失函数

  • CIoU Loss:解决边界框回归不均衡问题
    L C I o U = 1 − I o U + ρ 2 ( b , b g t ) c 2 + α v \mathcal{L}_{CIoU} = 1 - IoU + \frac{\rho^2(b,b^{gt})}{c^2} + \alpha v LCIoU=1IoU+c2ρ2(b,bgt)+αv
    其中 v = 4 π 2 ( arctan ⁡ w g t h g t − arctan ⁡ w h ) 2 v=\frac{4}{\pi^2}(\arctan\frac{w^{gt}}{h^{gt}}-\arctan\frac{w}{h})^2 v=π24(arctanhgtwgtarctanhw)2
  • 分类损失:Focal Loss改进版缓解样本不平衡

4. 训练策略

  • 余弦退火调度:学习率动态调整 η t = η m i n + 1 2 ( η m a x − η m i n ) ( 1 + cos ⁡ ( T c u r T m a x π ) ) \eta_t = \eta_{min} + \frac{1}{2}(\eta_{max}-\eta_{min})(1+\cos(\frac{T_{cur}}{T_{max}}\pi)) ηt=ηmin+21(ηmaxηmin)(1+cos(TmaxTcurπ))
  • SAT训练:生成对抗扰动增强决策边界鲁棒性

experiments
模型 AP@0.5 FPS (Tesla V100) 参数量
YOLOv3 55.3% 45 61.5M
YOLOv4 65.7% 62 63.9M
  • 关键突破
    1. 在MS COCO上AP50达65.7%,较v3提升10.4%
    2. Tesla V100实时推理速度62FPS
    3. 使用GIoU替换NMS,误检率降低20%

代码详解(PyTorch核心片段)

CSPDarknet块实现

class CSPBlock(nn.Module):
    def __init__(self, in_c, out_c, n=1):
        super().__init__()
        self.conv1 = Conv(in_c, out_c//2, 1)  # 通道减半
        self.conv2 = Conv(in_c, out_c//2, 1)
        self.bottleneck = nn.Sequential(*[ResBlock(out_c//2) for _ in range(n)])
        
    def forward(self, x):
        x1 = self.conv1(x)
        x2 = self.conv2(x)
        x2 = self.bottleneck(x2)
        return torch.cat([x1, x2], dim=1)  # 通道维度拼接

SPP模块结构

class SPP(nn.Module):
    def __init__(self, pool_sizes=(5,9,13)):
        super().__init__()
        self.pools = nn.ModuleList([
            nn.MaxPool2d(p, stride=1, padding=p//2) 
            for p in pool_sizes
        ])
        
    def forward(self, x):
        features = [x]
        for pool in self.pools:
            features.append(pool(x))
        return torch.cat(features, dim=1)  # 多尺度特征融合

总结

YOLOv4通过架构创新(CSPDarknet53+SPP+PANet)与训练策略革新(Mosaic+SAT),在精度与速度间取得完美平衡。其设计哲学启示后人:

“优秀的工程不是堆砌模块,而是让每个组件在系统中发挥乘法效应”

开源代码见:YOLOv4官方实现


网站公告

今日签到

点亮在社区的每一天
去签到