YOLOv4詳解:模型結構、損失函數、訓練方法及代碼實現
motivation
YOLO系列作者Joseph Redmon與Alexey Bochkovskiy致力于解決目標檢測領域的核心矛盾:精度與速度的平衡。YOLOv4的誕生源于兩大需求:
- 工業落地:在移動端/邊緣設備實現實時檢測(>30FPS)
- 學術突破:無需昂貴算力(如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.shapeif i==0: # 左上output[:yc,:xc] = cv2.resize(img, (xc,yc))... # 其他區域填充return output
2. 模型結構
- Backbone:CSPDarknet53(跨階段局部網絡)
- 引入CSP結構降低計算量Cout=Cin2C_{out}=\frac{C_{in}}{2}Cout?=2Cin??
- Neck:SPP + PANet
- SPP模塊:多尺度池化融合特征 fout=Concat(MaxPoolk×k(fin)),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:解決邊界框回歸不均衡問題
LCIoU=1?IoU+ρ2(b,bgt)c2+αv\mathcal{L}_{CIoU} = 1 - IoU + \frac{\rho^2(b,b^{gt})}{c^2} + \alpha v LCIoU?=1?IoU+c2ρ2(b,bgt)?+αv
其中v=4π2(arctan?wgthgt?arctan?wh)2v=\frac{4}{\pi^2}(\arctan\frac{w^{gt}}{h^{gt}}-\arctan\frac{w}{h})^2v=π24?(arctanhgtwgt??arctanhw?)2 - 分類損失:Focal Loss改進版緩解樣本不平衡
4. 訓練策略
- 余弦退火調度:學習率動態調整 ηt=ηmin+12(ηmax?ηmin)(1+cos?(TcurTmaxπ))\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(Tmax?Tcur??π))
- SAT訓練:生成對抗擾動增強決策邊界魯棒性
experiments
模型 | AP@0.5 | FPS (Tesla V100) | 參數量 |
---|---|---|---|
YOLOv3 | 55.3% | 45 | 61.5M |
YOLOv4 | 65.7% | 62 | 63.9M |
- 關鍵突破:
- 在MS COCO上AP50達65.7%,較v3提升10.4%
- Tesla V100實時推理速度62FPS
- 使用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官方實現