:此文仅为博主学习YOLO11所记个人笔记,文末有参考文章,侵删。
阅读本文最好具备机器学习相关基础知识,比如了解基础神经网络、损失函数。

YOLO11

一、对比与改进

在这里插入图片描述
在这里插入图片描述

  • 增强的特征提取:改进了骨干和颈部架构,增强了特征提取能力,提高了物体检测的精确度。
  • 优化的效率和速度:更快的处理速度,保持准确性和性能之间的平衡。
  • 更高的准确性与更少的参数:YOLO11m在COCO数据集上实现了更高的均值平均精度(mAP),同时使用比YOLOv8m少22%的参数,使其在不妥协准确性的情况下更加计算高效。
  • 环境适应性强:在多种环境中部署,包括边缘设备、云平台以及支持NVIDIA GPU的系统。
  • 支持广泛的任务:物体检测、实例分割、图像分类、姿态估计和旋转目标检测(OBB)

二、指标

predict\actual 1 0
1 TP(true positive) FP(false positive)
0 FN(false negative) TN(true negative)

精确率(Precision) P = T P T P + F P P=\frac{TP}{TP+FP} P=TP+FPTP (预测正确的正例/预测所有的正例)

召回率(Recall) R = T P T P + F N R=\frac{TP}{TP+FN} R=TP+FNTP (预测正确的正例/实际所有的正例)

均值平均精度(mAP)

均值平均精度(mean Average Precision,mAP):综合考虑了精确率(Precision)和召回率(Recall)的表现。

计算步骤

  1. 对每个类别,计算不同置信度阈值下的精确率(Precision)和召回率(Recall)。
  2. 绘制 Precision-Recall 曲线。
  3. 计算曲线下的面积,得到该类别的平均精确率(AP)
  4. 对所有类别的 AP 取平均值,得到 mAP。

平均精确率(Average Precision,AP)

  • 平滑曲线下的面积: A P = ∫ 0 1 P ( r )   d r AP=\int_0^1 P(r) \, dr AP=01P(r)dr

  • 离散形式: 1 N pos ∑ k = 1 n P ( k ) ⋅ rel ( k ) \frac{1}{N_{\text{pos}}} \sum_{k=1}^n P(k) \cdot \text{rel}(k) Npos1k=1nP(k)rel(k)

    N p o s N_{pos} Npos:所有正样本的个数, r e l ( k ) rel(k) rel(k):第 k k k个样本是否是正样本(1/0)

公式
m A P = 1 N ∑ i = 1 N A P i ( N :类别个数) mAP=\frac{1}{N} \sum_{i=1}^N AP_i(N:类别个数) mAP=N1i=1NAPiN:类别个数)

并交比(IoU)

并交比(Intersection over Union, IoU) :用于衡量两个区域重叠程度的指标。

评估预测框(Prediction)与真实框(Ground Truth)的匹配精度。

定义为预测区域(Prediction)与真实区域(Ground Truth)的交集面积与并集面积的比值。

计算步骤:

预测框坐标: ( x 1 , y 1 , x 2 , y 2 ) (x_1,y_1,x_2,y_2) (x1,y1,x2,y2)

真实框坐标: ( x 1 ′ , y 1 ′ , x 2 ′ , y 2 ′ ) (x_1^′,y_1^′,x_2^′,y_2^′) (x1,y1,x2,y2)

1.计算交集面积:
Intersection = max ⁡ ( 0 , min ⁡ ( x 2 , x 2 ′ ) − max ⁡ ( x 1 , x 1 ′ ) ) × max ⁡ ( 0 , min ⁡ ( y 2 , y 2 ′ ) − max ⁡ ( y 1 , y 1 ′ ) ) \begin{aligned} \text{Intersection} &= \max(0, \min(x_2, x_2') - \max(x_1, x_1')) \\ &\quad \times \max(0, \min(y_2, y_2') - \max(y_1, y_1')) \end{aligned} Intersection=max(0,min(x2,x2)max(x1,x1))×max(0,min(y2,y2)max(y1,y1))
2.计算并集面积: 预测框面积 + 真实框面积 - 交集面积
Union = ( x 2 − x 1 ) ( y 2 − y 1 ) + ( x 2 ′ − x 1 ′ ) ( y 2 ′ − y 1 ′ ) − Intersection \text{Union} = (x_2 - x_1)(y_2 - y_1) + (x_2' - x_1')(y_2' - y_1') - \text{Intersection} Union=(x2x1)(y2y1)+(x2x1)(y2y1)Intersection
3.计算 IoU:
IoU = Intersection Union (范围 [0, 1]) \text{IoU} = \frac{\text{Intersection}}{\text{Union}} \quad \text{(范围 [0, 1])} IoU=UnionIntersection(范围 [0, 1])

三、网络架构和各模块介绍

在这里插入图片描述

变化:

  • 相比较于YOLOv8模型,其将CF2模块改成C3K2,同时在SPPF模块后面添加了一个C2PSA模块。
  • 将YOLOv10的head思想引入到YOLO11的head中,使用深度可分离的方法,减少冗余计算,提高效率。

1.CBS模块

CBS:Conv + BN +SiLU

该块被命名为Conv块,通过2D卷积层,然后是2D批归一化层,最后是SiLU激活函数。

Silu激活函数:

在这里插入图片描述

BN:Batch Normalization(批归一化)

对每一批(batch)输入数据进行归一化处理,使其均值(mean)为0、方差(variance)为1,避免内部协变量偏移(Internal Covariate Shift),加速模型收敛。

公式:

1.输入数据: x ∈ R B × C × H × W ( B = 批大小, C = 通道数, H = 高度, W = 宽度) x \in \mathbb{R}^{B \times C \times H \times W}(B=批大小,C=通道数,H=高度,W=宽度) xRB×C×H×WB=批大小,C=通道数,H=高度,W=宽度)

2.对每个通道 c c c 独立计算均值和方差:
μ c = 1 B ⋅ H ⋅ W ∑ b = 1 B ∑ h = 1 H ∑ w = 1 W x b , c , h , w , σ c 2 = 1 B ⋅ H ⋅ W ∑ b = 1 B ∑ h = 1 H ∑ w = 1 W ( x b , c , h , w − μ c ) 2 \mu_c = \frac{1}{B \cdot H \cdot W} \sum_{b=1}^{B} \sum_{h=1}^{H} \sum_{w=1}^{W} x_{b,c,h,w}, \sigma_c^2 = \frac{1}{B \cdot H \cdot W} \sum_{b=1}^{B} \sum_{h=1}^{H} \sum_{w=1}^{W} (x_{b,c,h,w} - \mu_c)^2 μc=BHW1b=1Bh=1Hw=1Wxb,c,h,wσc2=BHW1b=1Bh=1Hw=1W(xb,c,h,wμc)2
3.标准化: ϵ \epsilon ϵ 为极小常数(如 1e-5),防止除零。
x ^ b , c , h , w = x b , c , h , w − μ c σ c 2 + ϵ \hat{x}_{b,c,h,w} = \frac{x_{b,c,h,w} - \mu_c}{\sqrt{\sigma_c^2 + \epsilon}} x^b,c,h,w=σc2+ϵ xb,c,h,wμc
4.可学习的缩放与偏移: γ c \gamma_c γc(缩放)和 β c \beta_c βc(偏移)为可训练参数,每个通道独立。
y b , c , h , w = γ c ⋅ x ^ b , c , h , w + β c y_{b,c,h,w} = \gamma_c \cdot \hat{x}_{b,c,h,w} + \beta_c yb,c,h,w=γcx^b,c,h,w+βc

γ γ γ β β β 的本质:是模型对标准化分布的“修正参数”,赋予网络在标准化基础上自由调整分布形态的能力。

缩放参数 γ γ γ(Gamma):调整归一化后的数据的方差(分布宽度)。

  • γ γ γ>1:放大特征幅度,增强某些重要特征的贡献。
  • γ γ γ<1:缩小特征幅度,抑制噪声或冗余特征。

偏移参数 β β β(Beta):调整归一化后的数据的均值(分布中心)。

  • β β β>0:将分布向右平移,保留正向激活的优势。
  • β β β<0:将分布向左平移,适应负向激活的需求。

网络架构图:

实现代码:

# conv.py
class Conv(nn.Module):
    """标准卷积块(ch_in, ch_out, kernel, stride, padding, groups, dilation, activation)."""
    default_act = nn.SiLU()  # 默认激活函数SiLu

    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, d=1, act=True):
        super().__init__()
        # 定义卷积层 conv
        self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p, d), groups=g, dilation=d, bias=False)
        # 定义批量归一化层 bn
        self.bn = nn.BatchNorm2d(c2)
        # 根据act参数确定激活函数
        self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()

    def forward(self, x):
        # 对输入特征图x进行处理先卷积,再归一化,再激活函数
        return self.act(self.bn(self.conv(x)))

autopad(k, p, d):根据kd的值,自动填充p的值,即padding加边。

  • stride=1 时:输出特征图尺寸与输入相同(即 H_out = H_in)。
  • stride>1 时:填充值适配下采样需求(如 s=2 时精确减半分辨率)。

在网络架构中:

# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
  • 输入:-1表示来自前一层的输出,这里是初始为输入图像。
  • 重复:1
  • 模块:标准卷积层。
  • 参数:[64, 3, 2]对应(c2, k, s)(输出通道、卷积核大小、步长)。
    • 输出通道:64*0.25=16width=0.25
    • 卷积核 :3x3
    • 步长 2(下采样到 1/2 分辨率)
  • 输出分辨率:P1/2(输入尺寸的 1/2)。

P1/2 的含义:表示特征图的层级(Stage)和相对输入图像的下采样比例。

P1:表示这是第 1 个阶段的输出特征图(Stage 1)。

/2:表示当前特征图的分辨率是输入图像的 1/2(即下采样 2 倍)。(例如,输入图像大小为 640x640,则 P1/2 的特征图大小为 320x320。)

2.Bottleneck模块

先减少通道数(降维),然后再增加通道数。使总参数量减少,减少计算量。

在这里插入图片描述

标准瓶颈块结构(Bottleneck):两个卷积层+(可选)跳转连接(Shortcut),减少计算量并保持梯度流动。

网络架构图:

在这里插入图片描述

实现代码:

# block.py
class Bottleneck(nn.Module):
    """标准瓶颈块"""
    def __init__(self, c1, c2, shortcut=True, g=1, k=(3, 3), e=0.5):
        super().__init__()
        c_ = int(c2 * e)  # 隐藏层通道数
        # 第一个卷积 cv1:一般降维
        self.cv1 = Conv(c1, c_, k[0], 1)
        # 第二个卷积 cv2:恢复原始维度
        self.cv2 = Conv(c_, c2, k[1], 1, g=g)
        # 当输入输出通道数一致启用跳转连接
        self.add = shortcut and c1 == c2

    def forward(self, x):
        # 如果true启用跳转连接
        return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))
BottleneckCSP 模块

跨阶段部分网络(CSP)结构。将特征图分为两部分,一部分通过一系列瓶颈层,另一部分直接连接到输出,增强梯度多样性并减少计算量。

网络架构:

Input: c1
cv1: c1->c_*e
cv2: c1->c_*e
m:n x Bottleneck
cv3: c_*e->c_*e
Identity or Conv
Concat
BN + SiLU
cv4: 2*c_*e->c2
Output: c2

Identity or Conv:恒等映射(Identity)或卷积(Conv)操作。

源代码:self.cv2 = nn.Conv2d(c1, c_, 1, 1, bias=False)

  • Identity:当 c1 == c_cv2 是简单的通道对齐(无实际计算需求)。
  • Conv:当 c1 != c_ 或需要特征变换时(如降维、升维)。

代码实现:

# block.py
class BottleneckCSP(nn.Module):
    def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):
        super().__init__()
        c_ = int(c2 * e)  # 隐藏通道数
        self.cv1 = Conv(c1, c_, 1, 1) # 分支1的初始卷积
        self.cv2 = nn.Conv2d(c1, c_, 1, 1, bias=False) # 分支2的初始卷积
        self.cv3 = nn.Conv2d(c_, c_, 1, 1, bias=False) # 分支1的末端卷积
        self.cv4 = Conv(2 * c_, c2, 1, 1) # 合并后的输出卷积
        self.bn = nn.BatchNorm2d(2 * c_) # 合并后特征归一化
        self.act = nn.SiLU() # 激活函数
        self.m = nn.Sequential(*(Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n))) # 定义包含n个瓶颈层的序列 m

    def forward(self, x):
        y1 = self.cv3(self.m(self.cv1(x))) # 分支1:经过Bottleneck堆叠
        y2 = self.cv2(x) # 分支2:直接卷积
        # 合并:cat([y1, y2]) → BN → SiLU → cv4
        return self.cv4(self.act(self.bn(torch.cat((y1, y2), 1))))

3.C3K2模块(C2f)

C2F:跨阶段部分聚焦,CSP-Focus。包含一个CBS块,将输出分成两半(其中通道被划分),它们通过一系列’n’瓶颈层进行处理,最后将每个层输出与最后的CBS块相连。这有助于增强特征图连接,而无需冗余信息。

C3K2:处理主干不同阶段的特征提取。继承于C2F模块。

CSP 瓶颈的一个更快更高效的变体,使用两个卷积层代替一个大的卷积层,从而加快了特征提取的速度。

c3k这个参数为FALSE的时候,C3K2模块就是C2F模块,也就是说它的Bottleneck是普通的Bottleneck;反之当它为TRUE的时候,将Bottleneck模块替换成C3k模块。

网络架构:C2f和C3K2
在这里插入图片描述

代码实现:

# block.py
class C3k2(C2f):
    def __init__(self, c1, c2, n=1, c3k=False, e=0.5, g=1, shortcut=True):
        super().__init__(c1, c2, n, shortcut, g, e)
        self.m = nn.ModuleList(
            # c3k==true 用C3k模块,false用Bottleneck模块
            C3k(self.c, self.c, 2, shortcut, g) if c3k else Bottleneck(self.c, self.c, shortcut, g) for _ in range(n)
        )
class C2f(nn.Module):
    """用2个卷积层实现更快的CSP瓶颈"""
    def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5):
        super().__init__()
        self.c = int(c2 * e)  # 隐藏通道数
        # 两阶段卷积
        self.cv1 = Conv(c1, 2 * self.c, 1, 1) # 将输入特征图通道数扩展为两倍,为后续分割做准备
        self.cv2 = Conv((2 + n) * self.c, c2, 1)  # 融合多分支特征(原始特征 + n 个 Bottleneck 的输出)
        # 瓶颈块
        self.m = nn.ModuleList(Bottleneck(self.c, self.c, shortcut, g, k=((3, 3), (3, 3)), e=1.0) for _ in range(n))

    def forward(self, x):
        y = list(self.cv1(x).chunk(2, 1)) # 将cv1的输出沿通道维度分成两部分得到y[0] 和 y[1]
        y.extend(m(y[-1]) for m in self.m) # 对y的最后一个张量依次通过n个Bottleneck
        # 最终 y 包含 2 + n 个张量
        return self.cv2(torch.cat(y, 1)) # 沿通道维度拼接所有特征后通过cv2

在网络架构中:

scales: 
  # [depth, width, max_channels]
  n: [0.50, 0.25, 1024]
    ...
# [from, repeats, module, args]
- [-1, 2, C3k2, [256, False, 0.25]] # 2
  • 输入:-1(第 1 层的输出)。
  • 重复:2*0.50=1次(因 depth=0.5 缩放)。
  • 参数:[256, False, 0.25]对应(c2, c3k, e)
    • 输出通道:256*0.25=64(因width=0.25
    • c3k=False:不使用 C3k 模块,而是使用 Bottleneck
    • e=0.25:隐藏层通道扩展因子为 0.25(hidden_channels = c2 * e = 256 * 0.25 = 64)。
  • 输出分辨率:与输入相同。
C3k模块(C3)

C3k 是一个更灵活的瓶颈模块,允许自定义核大小。继承于C3模块。

对于提取图像中更详细的特征非常有用。

网络架构:

在这里插入图片描述

代码实现:

# block.py
class C3k(C3):
    def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5, k=3):
        super().__init__(c1, c2, n, shortcut, g, e)
        c_ = int(c2 * e)  # 隐藏层通道数
        # self.m = nn.Sequential(*(RepBottleneck(c_, c_, shortcut, g, k=(k, k), e=1.0) for _ in range(n)))
        self.m = nn.Sequential(*(Bottleneck(c_, c_, shortcut, g, k=(k, k), e=1.0) for _ in range(n))) # 构建包含一系列瓶颈层的序列

# self.m = nn.Sequential(*(RepBottleneck(...)):可选的模块初始化方式,表示可以使用 RepBottleneck(可重参数化的瓶颈模块)

重参数化

  • 训练阶段:使用多分支复杂结构(如并联的 3x3 卷积、1x1 卷积 + BN)。
  • 推理阶段:将多分支合并为单个卷积层,保持输出一致但速度更快。

RepBottleneck:训练更慢但推理更快。

  • 训练时:多分支结构增强特征提取能力。
  • 推理时:合并为单分支,减少计算量,提升速度。
class C3(nn.Module):
    """用3个卷积层的CSP瓶颈"""
    def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):
        super().__init__()
        c_ = int(c2 * e)  # 隐藏层通道数
        self.cv1 = Conv(c1, c_, 1, 1)  # 分支1:经过n瓶颈
        self.cv2 = Conv(c1, c_, 1, 1) # 分支2
        self.cv3 = Conv(2 * c_, c2, 1)  # 合并分支后进行卷积
        self.m = nn.Sequential(*(Bottleneck(c_, c_, shortcut, g, k=((1, 1), (3, 3)), e=1.0) for _ in range(n)))

    def forward(self, x):
        return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), 1))

4.SPPF模块

SPPF(Spatial Pyramid Pooling Fast,快速空间金字塔池化):旨在以不同的尺度汇集图像不同区域的特征,将不同尺度的特征图通过多级池化融合,增强模型对多尺度目标的感知能力,特别是小物体。

使用多个最大池化操作(具有不同的内核大小)来聚合多尺度上下文信息。

网络架构图:

在这里插入图片描述

代码实现:

# block.py
class SPPF(nn.Module):
    def __init__(self, c1, c2, k=5):
        """
        This module is equivalent to SPP(k=(5, 9, 13)).
        """
        super().__init__()
        c_ = c1 // 2  # 隐藏层通道数
        self.cv1 = Conv(c1, c_, 1, 1) # 降维
        self.cv2 = Conv(c_ * 4, c2, 1, 1) # 升维+融合
        self.m = nn.MaxPool2d(kernel_size=k, stride=1, padding=k // 2) # 多级池化

    def forward(self, x):
        y = [self.cv1(x)]
        y.extend(self.m(y[-1]) for _ in range(3))
        return self.cv2(torch.cat(y, 1))

多级池化(self.m:使用固定大小的池化核重复堆叠,模拟更大感受野,而计算量更少。

源代码:self.m = nn.MaxPool2d(kernel_size=k, stride=1, padding=k // 2)

  • y1 = 5×5池化
  • y2 = 5×5池化(y1) → 等效9×9感受野
  • y3 = 5×5池化(y2) → 等效13×13感受野

padding=k // 2:保持输入和输出的空间尺寸不变,避免因尺寸收缩丢失边缘信息。

在网络架构中:

- [-1, 1, SPPF, [1024, 5]] # 9
  • 输入:-1(前一层的输出)。
  • 重复:1
  • 参数:[1024, 5]对应(c2, k)
    • 输出通道:1024*0.25=256(因width=0.25
    • 池化核大小 5x5
  • 输出分辨率:与输入相同。

5.C2PSA模块

C2PSA(跨阶段部分空间注意力):引入了注意力机制,通过强调特征图中的空间相关性,提高了模型对图像中重要区域的关注度。

扩展了C2f,引入PSA( Position-Sensitive Attention)块。

选择性地添加残差结构(shortcut)以优化梯度传播和网络训练效果。

使用FFN 可以将输入特征映射到更高维的空间,捕获输入特征的复杂非线性关系,允许模型学习更丰富的特征表示。

网络架构图:

代码实现:

# block.py
class C2PSA(nn.Module):
    """
    这个模块本质上与PSA模块相同,但经过重构,允许堆叠更多PSABlock模块。
    """
    def __init__(self, c1, c2, n=1, e=0.5):
        super().__init__()
        assert c1 == c2 # 检查输入通道数 c1 和输出通道数 c2 是否相等
        self.c = int(c1 * e) # 隐藏层通道数
        self.cv1 = Conv(c1, 2 * self.c, 1, 1) # 1x1 cv1:将输入特征图通道扩展为两倍,为后续分割做准备(split)
        self.cv2 = Conv(2 * self.c, c1, 1) # 1x1 cv2:融合双分支特征(原始分支 + 注意力分支)
        # 注意力模块
        self.m = nn.Sequential(*(PSABlock(self.c, attn_ratio=0.5, num_heads=self.c // 64) for _ in range(n))) #由 n 个 PSABlock 组成的序列,每个块处理 self.c 通道的输入

    def forward(self, x):
        a, b = self.cv1(x).split((self.c, self.c), dim=1) # 通道分割为两部分
        b = self.m(b) # 对分支b进行n次PSABlock处理
        return self.cv2(torch.cat((a, b), 1)) # 拼接后融合

assert c1 == c2断言代码,强制检查某个条件是否为真。检查输入通道数 c1 和输出通道数 c2 是否相等。

C2PSA 模块要求输入和输出的通道数 必须相同(即 c1 == c2)。

类似的:残差网络(ResNet)要求跳转连接(shortcut)和主分支的输出通道相同,否则需要 1x1 卷积调整维度

在网络架构中:

- [-1, 2, C2PSA, [1024]] # 10
  • 输入:-1(前一层的输出)。
  • 重复:2*0.50=1次(因 depth=0.5 缩放)。
  • 参数:[1024]对应c2输出通道 1024*0.25=256(因width=0.25
  • 输出分辨率:与输入相同。
PSA模块

PSABlock:结合注意力机制(Attention)与卷积前馈网络(FFN)的轻量级特征增强模块。

  • 通过注意力机制(Attention)建模全局特征关系。
  • 通过卷积前馈网络(FFN)补充局部细节。
  • 残差连接:可选是否使用跳跃连接(shortcut)稳定训练并缓解梯度消失。

代码实现:

class PSABlock(nn.Module):
    def __init__(self, c, attn_ratio=0.5, num_heads=4, shortcut=True) -> None:
        '''
        初始化参数:
            c:输入/输出通道数(保持维度一致), 
            attn_ratio:注意力机制中键值对通道的压缩比例, 
            num_heads:多头注意力的头数, 
            shortcut:是否启用残差连接。
        '''
        super().__init__()

        self.attn = Attention(c, attn_ratio=attn_ratio, num_heads=num_heads) # 注意力层
        self.ffn = nn.Sequential(Conv(c, c * 2, 1), Conv(c * 2, c, 1, act=False)) # 前馈网络
        self.add = shortcut

    def forward(self, x):
        x = x + self.attn(x) if self.add else self.attn(x) # 注意力分支 + 残差
        x = x + self.ffn(x) if self.add else self.ffn(x) # FFN分支 + 残差
        return x
Attention模块

具体代码细节此处不细讲。

Attention模块: 基于卷积的多头自注意力模块。

功能:对输入特征图进行空间-通道混合注意力计算。

实现:Attention(c, attn_ratio, num_heads)

  1. 通道分割:按 attn_ratio 将输入通道分为 QueryKey/Value
  2. 多头注意力:将特征图划分为 num_heads 组,分别计算注意力权重。
  3. 特征融合:加权聚合全局上下文信息。

输出:与输入同维度的增强特征。

FFN模块

FFN:卷积前馈网络。

提供非线性变换能力,增强局部特征表达。

Input
Conv
Conv
Output

结构:Conv(c → 2c → c)

  • 第一层:1×1卷积扩展通道(c → 2c),通常搭配激活函数(如SiLU)。
  • 第二层:1×1卷积压缩通道(2c → c),无激活函数(act=False)。

代码实现:self.ffn = nn.Sequential(Conv(c, c * 2, 1), Conv(c * 2, c, 1, act=False))

四、网络架构各部位介绍

1.head:检测和多尺度预测

YOLO11使用多尺度预测头来检测不同大小的物体。头部使用由backboneneck生成的特征图输出三种不同尺度(低、中、高)的检测框。

检测头从三个特征图(通常来自P3、P4和P5)输出预测,对应于图像中的不同粒度级别。这种方法确保了小物体被更精细地检测到(P3),而较大的物体被更高级别的特征捕获(P5)。

网络架构图:

检测和分类的卷积是解耦的(decoupled)

在这里插入图片描述

与YOLOv8的区别:YOLO11在head部分的cls分支上使用深度可分离卷积,降低计算量。

耦合头(Coupled Head)和解耦头(Decoupled Head):区别在于如何处理分类(Class)和回归(Box)任务的特征学习。

(分类关注语义,回归关注位置)

代码实现:

ch:输入通道数列表(如 [256, 512, 1024] 对应不同尺度的特征图)。

c2:回归分支的中间通道数(用于边界框预测)。

c3:分类分支的中间通道数(用于类别预测)。

# head.py->class Detect
self.cv2 = nn.ModuleList(
    nn.Sequential(
        Conv(x, c2, 3),     # 特征提取:调整通道数 [x → c2]
        Conv(c2, c2, 3),    # 进一步特征细化 [c2 → c2]
        nn.Conv2d(c2, 4 * self.reg_max, 1) # 输出回归参数 [c2 → 4*reg_max]
    ) for x in ch 
) # 回归分支
self.cv3 = nn.ModuleList(
    nn.Sequential(
        nn.Sequential(
            DWConv(x, x, 3),      # 深度可分离卷积 [x → x]
            Conv(x, c3, 1)        # 通道扩展 [x → c3]
        ),
        nn.Sequential(
            DWConv(c3, c3, 3),    # 二次空间特征提取 [c3 → c3]
            Conv(c3, c3, 1)       # 通道调整 [c3 → c3]
        ),
        nn.Conv2d(c3, self.nc, 1), # 分类输出 [c3 → nc]
    ) for x in ch
) # 分类分支

self.cv2 回归分支分析

两阶段卷积:先通过两次 Conv 提取高质量特征,再映射到高维回归参数。

离散化输出:将连续回归问题转化为分类问题,提升小目标检测精度。

  • 形状:[B, 4 * self.reg_max, H, W]B:Batch Size(批量大小),H, W:特征图的高度和宽度)
  • 含义:
    • 4 对应边界框的四个偏移量(中心点x/y、宽度w、高度h)。
    • self.reg_max 表示每个偏移量的离散化概率分布(如用Softmax转换为16个区间的概率)。
    • 后续通过 Distribution Focal Loss 学习偏移量的概率分布,再积分得到最终坐标。

self.cv3分类分支分析

深度可分离卷积:减少计算量,保留空间信息(适合分类任务)。

先保持输入通道(DWConv),再扩展至 c3

最终使用1×1卷积压缩到类别数,轻量化输出,避免冗余计算。

  • 形状:[B, self.nc, H, W]
  • 含义:每个空间位置输出 self.nc 维向量,表示各类别的得分。

DWConv代码实现:

DWConv:深度可分离卷积。执行深度可分离卷积,其中每个输入通道单独进行卷积。

class DWConv(Conv):
    """Depth-wise convolution."""
    def __init__(self, c1, c2, k=1, s=1, d=1, act=True):  
        # 将 groups 参数设置为 c1 和 c2 的最大公约数,从而实现按通道分组卷积
        super().__init__(c1, c2, k, s, g=math.gcd(c1, c2), d=d, act=act)

分割头部(Segment)、姿态估计头部(Pose)均继承自Detect,这里不赘述。

其余网络架构中的backboneneck部分,博主学累了或许后续会补充= =
关于YOLO11官方配置文件.yaml文件详解可以看这篇文章:
2. YOLO11网络结构详细解析(以n版本为例)_yolov11网络结构图-CSDN博客

五、损失函数

Loss 计算包括 2 个分支: 分类和回归分支。

  • 分类分支依然采用 BCE Loss。
  • 回归分支使用了 Distribution Focal Loss(DFL Reg_max默认为16)+ CIoU Loss。

1.分类损失(Class Loss)

衡量预测类别与真实类别的差异。

  • 使用二元交叉熵损失(BCE Loss)
  • 对每个锚点(Anchor)的多标签分类独立计算。

公式:二元交叉熵损失(BCE Loss)
L class = − ∑ i = 1 N ( y i log ⁡ ( p i ) + ( 1 − y i ) log ⁡ ( 1 − p i ) ) L_{\text{class}} = -\sum_{i=1}^{N} \left( y_i \log(p_i) + (1-y_i) \log(1-p_i) \right) Lclass=i=1N(yilog(pi)+(1yi)log(1pi))

  • y i y_i yi: 真实标签 (0或1)
  • p i p_i pi: 预测概率 (sigmoid输出)

2.边界框回归损失(Box Loss)

优化预测框的位置和尺寸。

  • Distribution Focal Loss (DFL):将边界框偏移量(中心点x/y、宽/高)建模为离散化概率分布(reg_max区间),通过Softmax和积分得到连续值。
  • CIoU Loss:考虑重叠区域、中心点距离和宽高比。

DFL公式:
L DFL = − ∑ k = 1 reg_max ( y k log ⁡ ( p k ) + ( 1 − y k ) log ⁡ ( 1 − p k ) ) L_{\text{DFL}} = -\sum_{k=1}^{\text{reg\_max}} \left( y_k \log(p_k) + (1-y_k) \log(1-p_k) \right) LDFL=k=1reg_max(yklog(pk)+(1yk)log(1pk))

  • y k y_k yk: 目标分布 (如高斯分布)
  • p k p_k pk: 预测分布 (softmax归一化)

CIoU:return iou - (rho2 / c2 + v * alpha)

将两个框最小能包住它们的“外接矩形”称为“convex box”,用它的宽和高来改进IoU的计算。

  • GIoU在 IoU 基础上根据“外接矩形”对空白区域进行惩罚,从而在没有交集时训练效果更好。
  • DloU还会计算两个框中心点之间的距离,与外接矩形对角线距离比较,用距离来惩罚。
  • CIoU在 DIoU 的基础上再加上长宽比等因素,进一步提高回归精度。

参考文章

超详细!YOLO11模型架构详解、性能对比_yolov11-CSDN博客

2. YOLO11网络结构详细解析(以n版本为例)_yolov11网络结构图-CSDN博客

《双模态检测系列 一》一文看懂YOLO11(系列进化史+网络结构+源码目录)_yolov11多模态-CSDN博客

YOLO11全解析:从原理到实战,全流程体验下一代目标检测-CSDN博客

YOLO11 沉浸式讲解 YOLOV11网络结构以及代码剖析-CSDN博客

计算机视觉——YOLO11原理代码分块解读与模型基准对比测试_yolo11代码解析-CSDN博客

Ultralytics YOLO11 -Ultralytics YOLO 文档

YOLOv11小白的进击之路(六)创新YOLO的iou及损失函数时的源码分析_yolov11 iou-CSDN博客

计算机视觉——YOLO11原理代码分块解读与模型基准对比测试_yolo11代码解析-CSDN博客

Ultralytics YOLO11 -Ultralytics YOLO 文档

YOLOv11小白的进击之路(六)创新YOLO的iou及损失函数时的源码分析_yolov11 iou-CSDN博客

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐