Ultralytics:解读CBLinear模块

在这里插入图片描述

前言

相关介绍

Ultralytics 简介

Ultralytics 基于多年的计算机视觉和人工智能基础研究,创建了最先进的 (SOTA) YOLO 模型。我们的模型不断更新性能和灵活性,快速、准确且易于使用。他们擅长对象检测、跟踪、实例分割、语义分割、图像分类和姿势估计任务。

前提条件

  • 熟悉Python、Pytorch

实验环境

Package                  Version
------------------------ ------------
Python                   3.11.8
absl-py                  2.4.0
accelerate               1.13.0
annotated-doc            0.0.4
anyio                    4.13.0
calflops                 0.3.2
certifi                  2026.4.22
charset-normalizer       3.4.7
click                    8.3.3
colorama                 0.4.6
contourpy                1.3.3
cycler                   0.12.1
filelock                 3.29.0
flatbuffers              25.12.19
fonttools                4.62.1
fsspec                   2026.4.0
grpcio                   1.80.0
h11                      0.16.0
hf-xet                   1.5.0
httpcore                 1.0.9
httpx                    0.28.1
huggingface_hub          1.14.0
idna                     3.15
Jinja2                   3.1.6
kiwisolver               1.5.0
Markdown                 3.10.2
markdown-it-py           4.2.0
MarkupSafe               3.0.3
matplotlib               3.10.9
mdurl                    0.1.2
ml_dtypes                0.5.0
mpmath                   1.3.0
networkx                 3.6.1
numpy                    1.26.4
nvidia-cublas-cu12       12.8.3.14
nvidia-cuda-cupti-cu12   12.8.57
nvidia-cuda-nvrtc-cu12   12.8.61
nvidia-cuda-runtime-cu12 12.8.57
nvidia-cudnn-cu12        9.7.1.26
nvidia-cufft-cu12        11.3.3.41
nvidia-cufile-cu12       1.13.0.11
nvidia-curand-cu12       10.3.9.55
nvidia-cusolver-cu12     11.7.2.55
nvidia-cusparse-cu12     12.5.7.53
nvidia-cusparselt-cu12   0.6.3
nvidia-nccl-cu12         2.26.2
nvidia-nvjitlink-cu12    12.8.61
nvidia-nvtx-cu12         12.8.55
onnx                     1.19.0
onnxruntime-gpu          1.26.0
onnxslim                 0.1.94
opencv-python            4.6.0.66
packaging                26.2
pillow                   12.2.0
pip                      24.0
polars                   1.40.1
polars-runtime-32        1.40.1
protobuf                 7.34.1
psutil                   7.2.2
pycocotools              2.0.11
Pygments                 2.20.0
pyparsing                3.3.2
python-dateutil          2.9.0.post0
PyYAML                   6.0.3
regex                    2026.5.9
requests                 2.34.1
rich                     15.0.0
safetensors              0.7.0
scipy                    1.16.0
setuptools               65.5.0
shellingham              1.5.4
six                      1.17.0
sympy                    1.14.0
tabulate                 0.10.0
tensorboard              2.20.0
tensorboard-data-server  0.7.2
tokenizers               0.22.2
torch                    2.7.1+cu128
torchaudio               2.7.1+cu128
torchvision              0.22.1+cu128
tqdm                     4.67.3
transformers             5.8.1
triton                   3.3.1
typer                    0.25.1
typing_extensions        4.15.0
ultralytics              8.4.58
ultralytics-thop         2.0.19
urllib3                  2.7.0
Werkzeug                 3.1.8

CBLinear(多分支卷积模块)

CBLinear 是一个用于生成 多个不同通道数的特征图 的卷积模块。它通过一个共享的卷积层同时输出总通道数为 sum(c2s) 的特征图,然后按指定的通道尺寸列表 c2s 沿通道维度拆分为多个张量。这种设计在需要 多任务输出多尺度特征分支 的网络中非常有用,例如 YOLOv9 中的某些跨层连接结构。


代码实现

import cv2
import math
import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
import matplotlib.pyplot as plt

def autopad(k, p=None, d=1):  # kernel, padding, dilation
    """Pad to 'same' shape outputs."""
    if d > 1:
        k = d * (k - 1) + 1 if isinstance(k, int) else [d * (x - 1) + 1 for x in k]  # actual kernel-size
    if p is None:
        p = k // 2 if isinstance(k, int) else [x // 2 for x in k]  # auto-pad
    return p

class CBLinear(nn.Module):
    """CBLinear."""

    def __init__(self, c1: int, c2s: list[int], k: int = 1, s: int = 1, p: int | None = None, g: int = 1):
        """Initialize CBLinear module.

        Args:
            c1 (int): Input channels.
            c2s (list[int]): List of output channel sizes.
            k (int): Kernel size.
            s (int): Stride.
            p (int | None): Padding.
            g (int): Groups.
        """
        super().__init__()
        self.c2s = c2s
        self.conv = nn.Conv2d(c1, sum(c2s), k, s, autopad(k, p), groups=g, bias=True)

    def forward(self, x: torch.Tensor) -> list[torch.Tensor]:
        """Forward pass through CBLinear layer."""
        return self.conv(x).split(self.c2s, dim=1)

功能

  • 多输出分支:将输入特征通过一个卷积层,生成总通道数为 sum(c2s) 的特征图,然后按照 c2s 列表中的数值,沿通道维拆分成多个张量。
  • 共享卷积权重:所有分支共享同一个卷积核,减少参数量,同时能够并行计算。
  • 灵活配置:通过 c2s 可以灵活指定每个分支的输出通道数,适应不同任务需求(如目标检测中的分类头、回归头等)。

初始化参数

参数类型说明
c1int输入特征图的通道数
c2slist[int]各分支的输出通道数列表,长度表示分支数
kint卷积核大小(默认 1)
sint卷积步长(默认 1)
pint | None填充,若为 None 则自动计算
gint分组卷积的组数(默认 1)
  • 卷积层 self.conv 的输出通道数为 sum(c2s),偏置 bias=True
  • 填充 p 通过 autopad 自动计算(保持输出尺寸不变)。

前向方法

  • forward(x):输入 x 形状 [B, c1, H, W],返回一个张量列表,每个张量形状为 [B, c2_i, H, W],其中 c2_i 对应 c2s[i]

使用示例

if __name__ == '__main__':
    # 1. 随机输入
    B, c1, H, W = 2, 16, 32, 32
    x = torch.randn(B, c1, H, W)

    # 2. 定义各分支输出通道数
    c2s = [8, 16, 32]  # 三个分支

    # 3. 创建 CBLinear 模块
    cbl = CBLinear(c1=c1, c2s=c2s, k=3, s=1)

    # 4. 前向传播
    with torch.no_grad():
        outputs = cbl(x)  # outputs 是一个长度为3的列表

    print("输入形状:", x.shape)  # [2, 16, 32, 32]
    for i, out in enumerate(outputs):
        print(f"分支 {i} 输出形状:", out.shape)  # [2, 8, 32, 32], [2, 16, 32, 32], [2, 32, 32, 32]
    print("总参数量:", sum(p.numel() for p in cbl.parameters()))

输出示例

输入形状: torch.Size([2, 16, 32, 32])
分支 0 输出形状: torch.Size([2, 8, 32, 32])
分支 1 输出形状: torch.Size([2, 16, 32, 32])
分支 2 输出形状: torch.Size([2, 32, 32, 32])
总参数量: 16*56*9 + 56 = 8120

流程示意图

输入 x (B, c1, H, W)

Conv2d: c1 → sum(c2s), k, s, p

输出 (B, sum(c2s), H, W)

split(dim=1, split_sizes=c2s)

分支 0 (B, c2s[0], H, W)

分支 1 (B, c2s[1], H, W)

...

分支 n-1 (B, c2s[-1], H, W)


代码解读

  • __init__
    • 存储 c2s 列表供 forward 使用。
    • 创建 nn.Conv2d,输出通道数为 sum(c2s),其他参数(核大小、步长、填充、分组)透传。
    • 使用 autopad 自动计算填充,保证输出空间尺寸不变(除非步长不为 1)。
  • forward
    • 对输入 x 应用卷积,得到总输出。
    • 使用 torch.split 沿通道维(dim=1)按 c2s 拆分,返回张量列表。

注意事项

  1. 输出通道总和sum(c2s) 必须与卷积层的输出通道数一致(实际上代码直接使用该值,因此无冲突)。
  2. 空间尺寸变化:若步长 s 不为 1,则所有分支的空间尺寸会同步缩小(步长共享),且填充自动调整。
  3. 权重共享:所有分支共享同一个卷积核,这意味着它们提取的是相同的底层特征,只是输出通道数不同。如果希望各分支独立学习,应使用多个卷积层。
  4. 应用场景:常用于需要同时输出不同维度特征(如多个检测头)的网络结构,例如 YOLOv9 中的某些模块。

优缺点

优点
  1. 参数高效:共享卷积权重,相比多个独立卷积层,参数量大幅减少。
  2. 计算高效:一次卷积即可生成所有分支输出,计算量远低于多次卷积。
  3. 灵活配置:通过 c2s 可任意调整各分支的通道数,适应多任务或多尺度需求。
  4. 易于集成:与普通 Conv 接口相似,可直接替换标准卷积层。
缺点
  1. 表达能力受限:所有分支共享相同的卷积核,无法针对每个分支学习独立的特征变换。
  2. 输出尺寸绑定:所有分支共享相同的空间尺寸(由步长决定),无法分别控制不同分支的分辨率。
  3. 分组卷积的限制g 参数作用于整个卷积,所有分支共享相同的分组数,若各分支需要不同分组则无法实现。

在 YOLOv9 等网络结构中,CBLinear 常用于高效地生成多个特征分支,以便后续进行不同的处理(如不同尺度的检测)。使用时需权衡共享权重带来的效率提升与表达能力下降之间的关系。若任务对分支独立性要求较高,可考虑使用多个独立卷积代替。

参考文献

[1] https://docs.ultralytics.com/
[2] https://github.com/ultralytics/ultralytics.git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FriendshipT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值