YOLO v5、v7、v8 模型优化
- 魔改YOLO
- yaml 文件解读
- 模型选择
- 在线做数据标注
- YOLO算法改进
- YOLOv5
- 更换骨干网络之 SwinTransformer
- 更换骨干网络之 EfficientNet
- 优化上采样方式:轻量化算子CARAFE 替换 传统(最近邻 / 双线性 / 双立方 / 三线性 / 转置卷积)
- 优化空间金字塔池化:SPPF / SimSPPF / ASPP / RFB / SPPCSPC / SPPFCSPC 替换 SPP
- 优化训练策略:SIoU / EIoU / WIoU / Focal_xIoU / MPDIoU 替换 IoU
- 优化激活函数:SiLU、Hardswish、MemoryEfficientMish、FReLU、AconC、MetaAconC 替换 Mish函数
- 优化损失函数:多种类Loss, PolyLoss / VarifocalLoss / GFL / QualityFLoss / FL
- 优化损失函数:改进用于微小目标检测的 Normalized Gaussian Wasserstein Distance
- 引入特征融合网络 BiFPN:提高检测精度和效率
- 引入 YOLOv6 颈部 BiFusion Neck
- 引入注意力机制:在 C3 模块添加添加注意力机制
- 添加【SE】【CBAM】【 ECA 】【CA】
- 添加【SimAM】【CoTAttention】【SKAttention】【DoubleAttention】
- 添加【EffectiveSE】【GlobalContext】【GatherExcite】【MHSA】
- 添加【Triplet】【SpatialGroupEnhance】【NAM】【S2】
- 引入小目标检测:用于低分辨率图像和小物体的新 CNN 模块SPD-Conv
- 引入轻量化卷积 替换 传统卷积
- 引入独立注意力FPN+PAN结构 替换 传统卷积
- 引入 YOLOX 解耦头
- 引入 YOLOv8 的 C2f 模块
- 引入 RepVGG 重参数化模块
- 引入密集连接模块
- 模型剪枝
- 知识蒸馏
- 热力图可视化
- YOLOv7
- 更换骨干网络之 SwinTransformer
- 更换骨干网络之 EfficientNet
- 优化上采样方式:轻量化算子CARAFE 替换 传统(最近邻 / 双线性 / 双立方 / 三线性 / 转置卷积)
- 优化空间金字塔池化:SPPF / SimSPPF / ASPP / RFB / SPPCSPC / SPPFCSPC 替换 SPP
- 优化训练策略:SIoU / EIoU / WIoU / Focal_xIoU / MPDIoU 替换 IoU
- 优化激活函数:SiLU、Hardswish、MemoryEfficientMish、FReLU、AconC、MetaAconC 替换 Mish函数
- 优化标签分配策略:基于TOOD标签分配策略改进
- 优化损失函数:SIoU等结合FocalLoss应用:组成Focal-EIoU|Focal-SIoU|Focal-CIoU|Focal-GIoU、DIoU
- 优化损失函数:Wise-IoU
- 优化特征集成方法:目标检测的渐近特征金字塔网络AsymptoticFPN
- 引入 BiFPN 特征融合网络:提高检测精度和效率
- 引入 YOLOv6 颈部 BiFusion Neck
- 引入小目标检测:用于低分辨率图像和小物体的新 CNN 模块SPD-Conv
- 引入轻量化卷积 替换 传统卷积
- 引入 YOLOX 解耦头
- 引入 YOLOv8 的 C2f 模块
- 引入 RepVGG 重参数化模块
- 引入密集连接模块
- 引入用于小目标检测的归一化高斯 Wasserstein Distance Loss
- 引入Generalized Focal Loss
- 模型剪枝
- 知识蒸馏
- 热力图可视化
- YOLOv8
- 更换主干网络之 VanillaNet
- 更换主干网络之 FasterNet
- 更换骨干网络之 SwinTransformer
- 更换骨干网络之 CReToNeXt
- 更换主干之 MAE
- 更换主干之 QARepNeXt
- 更换主干之 RepLKNet
- 引入注意力机制:在 C2F 模块添加添加注意力机制
- 添加【SE】 【CBAM】【 ECA 】【CA 】
- 添加【SimAM】 【CoTAttention】【SKAttention】【DoubleAttention】
- 添加【EffectiveSE】【GlobalContext】【GatherExcite】【MHSA】
- 添加【Triplet】【SpatialGroupEnhance】【NAM】【S2】
- 添加【ParNet】【CrissCross】【GAM】【ParallelPolarized】【Sequential】
- 引入 RepVGG 重参数化模块
- 引入 SPD-Conv 替换 Conv
- 引入跨空间学习的高效多尺度注意力 Efficient Multi-Scale Attention
- 引入选择性注意力 LSK 模块
- 引入空间通道重组卷积
- 引入轻量级通用上采样算子CARAFE
- 引入全维动态卷积
- 引入 BiFPN 结构
- 引入 Slim-neck
- 引入中心化特征金字塔 EVC 模块
- 引入渐进特征金字塔网络 AFPN 结构
- 引入大目标检测头、小目标检测头
- 引入谷歌 Lion 优化器
- 引入小目标检测结构:CBiF、BiFB
- 优化FPN结构
- 优化损失函数:FocalLoss结合变种IoU套装
- 优化损失函数:Wise-IoU
- 优化损失函数:遮挡损失函数 Repulsion Loss
- 优化卷积:PWConv
- 优化 EfficientRep 结构:结合硬件感知神经网络设计的 Repvgg 的 ConvNet 网络结构
- 优化特征集成方法:目标检测的渐近特征金字塔网络AsymptoticFPN
- 优化检测方法:EfficiCLNMS
魔改YOLO
yaml 文件解读
比如我们用 V8 做一个分类任务,那我们需要看 V8分类模型 的 .yaml 文件。
yolov8-cls.yaml
(ultralytics/models/v8/yolov8-cls.yaml
)
# Parameters
nc: 1000 # 数据集有多少类别
scales: # 调整YOLO模型的深度、宽度和通道数,通过选择不同的规模,可以根据具体的需求来调整模型的大小和性能,从而实现更好的检测结果。
# 网络规模:[深度、宽度和通道数]
n: [0.33, 0.25, 1024] # n: 较小的规模
s: [0.33, 0.50, 1024] # s: 小规模
m: [0.67, 0.75, 1024] # m: 中等规模
l: [1.00, 1.00, 1024] # l: 大规模
x: [1.00, 1.25, 1024] # x: 最大规模
# YOLOv8.0n backbone
backbone:
# [ 从哪层获取输入(-1是上一层,[-1,6]是从上一层和第6层), 模块重复次数, 模块名字(Conv是卷积层), args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2 第 0 层:P1是第1特征层,缩小为输入图像的1/2,64代表输出通道数,3代表卷积核大小k,2代表stride步长
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4 第 1 层:P2是第2特征层,缩小为输入图像的1/4,128代表输出通道数,3代表卷积核大小k,2代表stride步长
- [-1, 3, C2f, [128, True]] 第 2 层:本层是C2f模块,3代表本层重复3次。128代表输出通道数,True表示Bottleneck有shortcut。
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8 P3是第3特征层,缩小为输入图像的1/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16 P4是第4特征层,缩小为输入图像的1/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32 P5是第5特征层,缩小为输入图像的1/32
- [-1, 3, C2f, [1024, True]]
# YOLOv8.0n head
head:
- [-1, 1, Classify, [nc]] # Classify
yaml 文件分为:
- 参数部分:nc(数据集类别数量)、
- 网络结构部分:from(从哪层获取输入), repeats(模块重复次数), module(模块名字), args
- 头部部分
模型选择
在线做数据标注
由于 Labelimg 和 Labelme 安装起来比较麻烦,我们使用在线标注工具make sense:https://www.makesense.ai
准备类别数据集,每添加一个类别文件夹:
在添加标签:
把图中类别标注出来:
点选 Actions -> Export Annotations 导出标注:
数据标注文件:
0 0.329611 0.329853 0.339493 0.259214
0 0.698680 0.656634 0.339493 0.266585
0 0.770694 0.244472 0.318917 0.194103
0 0.813131 0.104423 0.073300 0.063882
类别标签 目标中心点坐标x 目标中心点坐标y 宽度 高度
类别标签:此处的序号是按照Make Sense中的标签"顺序"排列的,0 是第一个类别
YOLO算法改进
YOLO算法改进,无非六方面:
- 更快更强的网络架构
- 更有效的特征集成方法
- 更准确的检测方法
- 更精确的损失函数
- 更有效的标签分配方法
- 更有效的训练方法
YOLOv5
更换骨干网络之 SwinTransformer
更换骨干网络之 EfficientNet
优化上采样方式:轻量化算子CARAFE 替换 传统(最近邻 / 双线性 / 双立方 / 三线性 / 转置卷积)
Yolov5 下采样指的是通过卷积操作将输入特征图的尺寸降低,通常使用步幅大于1的卷积来实现。这样可以增加特征图的感受野,提高检测网络的感知范围和检测速度。
Yolov5 上采样则是通过反卷积或者插值等操作将输入特征图的尺寸扩大,通常用于实现检测网络的输出尺寸与输入尺寸相同,或者用于实现多尺度检测等功能。
在 YOLOv5 中,上采样模块是使用 nn.Upsample 实现的。
具体来说,YOLOv5 中使用的上采样模块包括两种类型:
-
nn.Upsample(scale_factor=2, mode=‘nearest’),这种上采样模块是通过最近邻插值实现的。
它用于将特征图的大小增加一倍,例如在 yolov5s 中将 16x16 特征图上采样到 32x32。
-
nn.ConvTranspose2d(in_channels, out_channels, kernel_size=2, stride=2),这种上采样模块是通过转置卷积实现的。
它用于将特征图的大小增加一倍,并且可以学习更加复杂的上采样方式。在 YOLOv5 中,这种上采样模块在 yolov5m、yolov5l 和 yolov5x 中使用。
优化空间金字塔池化:SPPF / SimSPPF / ASPP / RFB / SPPCSPC / SPPFCSPC 替换 SPP
优化训练策略:SIoU / EIoU / WIoU / Focal_xIoU / MPDIoU 替换 IoU
优化激活函数:SiLU、Hardswish、MemoryEfficientMish、FReLU、AconC、MetaAconC 替换 Mish函数
V5 自带的激活函数代码在:yolo5/utils/activations.py,需要换直接调用即可,不用自己写了:
import torch
import torch.nn as nn
import torch.nn.functional as F
class SiLU(nn.Module):
@staticmethod
def forward(x):
return x * torch.sigmoid(x)
class Hardswish(nn.Module):
@staticmethod
def forward(x):
return x * F.hardtanh(x + 3, 0.0, 6.0) / 6.0 # for TorchScript, CoreML and ONNX
class Mish(nn.Module):
@staticmethod
def forward(x):
return x * F.softplus(x).tanh()
class MemoryEfficientMish(nn.Module):
class F(torch.autograd.Function):
@staticmethod
def forward(ctx, x):
ctx.save_for_backward(x)
return x.mul(torch.tanh(F.softplus(x))) # x * tanh(ln(1 + exp(x)))
@staticmethod
def backward(ctx, grad_output):
x = ctx.saved_tensors[0]
sx = torch.sigmoid(x)
fx = F.softplus(x).tanh()
return grad_output * (fx + x * sx * (1 - fx * fx))
def forward(self, x):
return self.F.apply(x)
class FReLU(nn.Module):
def __init__(self, c1, k=3): # ch_in, kernel
super().__init__()
self.conv = nn.Conv2d(c1, c1, k, 1, 1, groups=c1, bias=False)
self.bn = nn.BatchNorm2d(c1)
def forward(self, x):
return torch.max(x, self.bn(self.conv(x)))
class AconC(nn.Module):
def __init__(self, c1):
super().__init__()
self.p1 = nn.Parameter(torch.randn(1, c1, 1, 1))
self.p2 = nn.Parameter(torch.randn(1, c1, 1, 1))
self.beta = nn.Parameter(torch.ones(1, c1, 1, 1))
def forward(self, x):
dpx = (self.p1 - self.p2) * x
return dpx * torch.sigmoid(self.beta * dpx) + self.p2 * x
class MetaAconC(nn.Module):
def __init__(self, c1, k=1, s=1, r=16): # ch_in, kernel, stride, r
super().__init__()
c2 = max(r, c1 // r)
self.p1 = nn.Parameter(torch.randn(1, c1, 1, 1))
self.p2 = nn.Parameter(torch.randn(1, c1, 1, 1))
self.fc1 = nn.Conv2d(c1, c2, k, s, bias=True)
self.fc2 = nn.Conv2d(c2, c1, k, s, bias=True)
def forward(self, x):
y = x.mean(dim=2, keepdims=True).mean(dim=3, keepdims=True)
beta = torch.sigmoid(self.fc2(self.fc1(y))) # bug patch BN layers removed
dpx = (self.p1 - self.p2) * x
return dpx * torch.sigmoid(beta * dpx) + self.p2 * x
修改网络中的激活函数:yolo5/models/common.py
class Conv(nn.Module):
default_act = nn.SiLU() # 默认激活函数,选择你要更换的激活函数
def __init__(self, c1, c2, k=1, s=1, p=None, g=1, d=1, act=True):
super().__init__()
self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p, d), groups=g, dilation=d, bias=False)
self.bn = nn.BatchNorm2d(c2)
self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()
更换自己想要的激活函数:
default_act = nn.SiLU() # 默认激活函数
default_act = nn.Identity()
default_act = nn.Tanh()
default_act = nn.Sigmoid()
default_act = nn.ReLU()
default_act = nn.LeakyReLU(0.1)
default_act = nn.Hardswish()
default_act = nn.SiLU()
default_act = Mish()
default_act = FReLU(c2)
default_act = AconC(c2)
default_act = MetaAconC(c2)
default_act = SiLU_beta(c2)
default_act = FReLU_noBN_biasFalse(c2)
default_act = FReLU_noBN_biasTrue(c2)
class BottleneckCSP(nn.Module):
def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
super().__init__()
c_ = int(c2 * e) # hidden channels
self.cv1 = Conv(c1, c_, 1, 1)
self.cv2 = nn.Conv2d(c1, c_, 1, 1, bias=False)
self.cv3 = nn.Conv2d(c_, c_, 1, 1, bias=False)
self.cv4 = Conv(2 * c_, c2, 1, 1)
self.bn = nn.BatchNorm2d(2 * c_) # applied to cat(cv2, cv3)
self.act = nn.SiLU() # 选择你要更换的激活函数
优化损失函数:多种类Loss, PolyLoss / VarifocalLoss / GFL / QualityFLoss / FL
优化损失函数:改进用于微小目标检测的 Normalized Gaussian Wasserstein Distance
引入特征融合网络 BiFPN:提高检测精度和效率
引入 YOLOv6 颈部 BiFusion Neck
引入注意力机制:在 C3 模块添加添加注意力机制
添加【SE】【CBAM】【 ECA 】【CA】
添加【SimAM】【CoTAttention】【SKAttention】【DoubleAttention】
添加【EffectiveSE】【GlobalContext】【GatherExcite】【MHSA】
添加【Triplet】【SpatialGroupEnhance】【NAM】【S2】
引入小目标检测:用于低分辨率图像和小物体的新 CNN 模块SPD-Conv
引入轻量化卷积 替换 传统卷积
引入独立注意力FPN+PAN结构 替换 传统卷积
引入 YOLOX 解耦头
引入 YOLOv8 的 C2f 模块
引入 RepVGG 重参数化模块
引入密集连接模块
模型剪枝
知识蒸馏
热力图可视化
YOLOv7
更换骨干网络之 SwinTransformer
更换骨干网络之 EfficientNet
优化上采样方式:轻量化算子CARAFE 替换 传统(最近邻 / 双线性 / 双立方 / 三线性 / 转置卷积)
优化空间金字塔池化:SPPF / SimSPPF / ASPP / RFB / SPPCSPC / SPPFCSPC 替换 SPP
优化训练策略:SIoU / EIoU / WIoU / Focal_xIoU / MPDIoU 替换 IoU
优化激活函数:SiLU、Hardswish、MemoryEfficientMish、FReLU、AconC、MetaAconC 替换 Mish函数
优化标签分配策略:基于TOOD标签分配策略改进
优化损失函数:SIoU等结合FocalLoss应用:组成Focal-EIoU|Focal-SIoU|Focal-CIoU|Focal-GIoU、DIoU
优化损失函数:Wise-IoU
优化特征集成方法:目标检测的渐近特征金字塔网络AsymptoticFPN
引入 BiFPN 特征融合网络:提高检测精度和效率
引入 YOLOv6 颈部 BiFusion Neck
引入小目标检测:用于低分辨率图像和小物体的新 CNN 模块SPD-Conv
引入轻量化卷积 替换 传统卷积
引入 YOLOX 解耦头
引入 YOLOv8 的 C2f 模块
引入 RepVGG 重参数化模块
引入密集连接模块
引入用于小目标检测的归一化高斯 Wasserstein Distance Loss
引入Generalized Focal Loss
模型剪枝
知识蒸馏
热力图可视化