Ultralytics:解读CBLinear模块

Ultralytics:解读CBLinear模块

前言

相关介绍

Ultralytics 简介

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

前提条件

  • 熟悉Python、Pytorch

实验环境

bash 复制代码
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 中的某些跨层连接结构。


代码实现

python 复制代码
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 可以灵活指定每个分支的输出通道数,适应不同任务需求(如目标检测中的分类头、回归头等)。

初始化参数

参数 类型 说明
c1 int 输入特征图的通道数
c2s listint 各分支的输出通道数列表,长度表示分支数
k int 卷积核大小(默认 1)
s int 卷积步长(默认 1)
p int | None 填充,若为 None 则自动计算
g int 分组卷积的组数(默认 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]

使用示例

python 复制代码
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

流程示意图

#mermaid-svg-TrFRx0DEs44YgqHK{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-TrFRx0DEs44YgqHK .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-TrFRx0DEs44YgqHK .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-TrFRx0DEs44YgqHK .error-icon{fill:#552222;}#mermaid-svg-TrFRx0DEs44YgqHK .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-TrFRx0DEs44YgqHK .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-TrFRx0DEs44YgqHK .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-TrFRx0DEs44YgqHK .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-TrFRx0DEs44YgqHK .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-TrFRx0DEs44YgqHK .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-TrFRx0DEs44YgqHK .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-TrFRx0DEs44YgqHK .marker{fill:#333333;stroke:#333333;}#mermaid-svg-TrFRx0DEs44YgqHK .marker.cross{stroke:#333333;}#mermaid-svg-TrFRx0DEs44YgqHK svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-TrFRx0DEs44YgqHK p{margin:0;}#mermaid-svg-TrFRx0DEs44YgqHK .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-TrFRx0DEs44YgqHK .cluster-label text{fill:#333;}#mermaid-svg-TrFRx0DEs44YgqHK .cluster-label span{color:#333;}#mermaid-svg-TrFRx0DEs44YgqHK .cluster-label span p{background-color:transparent;}#mermaid-svg-TrFRx0DEs44YgqHK .label text,#mermaid-svg-TrFRx0DEs44YgqHK span{fill:#333;color:#333;}#mermaid-svg-TrFRx0DEs44YgqHK .node rect,#mermaid-svg-TrFRx0DEs44YgqHK .node circle,#mermaid-svg-TrFRx0DEs44YgqHK .node ellipse,#mermaid-svg-TrFRx0DEs44YgqHK .node polygon,#mermaid-svg-TrFRx0DEs44YgqHK .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-TrFRx0DEs44YgqHK .rough-node .label text,#mermaid-svg-TrFRx0DEs44YgqHK .node .label text,#mermaid-svg-TrFRx0DEs44YgqHK .image-shape .label,#mermaid-svg-TrFRx0DEs44YgqHK .icon-shape .label{text-anchor:middle;}#mermaid-svg-TrFRx0DEs44YgqHK .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-TrFRx0DEs44YgqHK .rough-node .label,#mermaid-svg-TrFRx0DEs44YgqHK .node .label,#mermaid-svg-TrFRx0DEs44YgqHK .image-shape .label,#mermaid-svg-TrFRx0DEs44YgqHK .icon-shape .label{text-align:center;}#mermaid-svg-TrFRx0DEs44YgqHK .node.clickable{cursor:pointer;}#mermaid-svg-TrFRx0DEs44YgqHK .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-TrFRx0DEs44YgqHK .arrowheadPath{fill:#333333;}#mermaid-svg-TrFRx0DEs44YgqHK .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-TrFRx0DEs44YgqHK .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-TrFRx0DEs44YgqHK .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TrFRx0DEs44YgqHK .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-TrFRx0DEs44YgqHK .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TrFRx0DEs44YgqHK .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-TrFRx0DEs44YgqHK .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-TrFRx0DEs44YgqHK .cluster text{fill:#333;}#mermaid-svg-TrFRx0DEs44YgqHK .cluster span{color:#333;}#mermaid-svg-TrFRx0DEs44YgqHK div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-TrFRx0DEs44YgqHK .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-TrFRx0DEs44YgqHK rect.text{fill:none;stroke-width:0;}#mermaid-svg-TrFRx0DEs44YgqHK .icon-shape,#mermaid-svg-TrFRx0DEs44YgqHK .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TrFRx0DEs44YgqHK .icon-shape p,#mermaid-svg-TrFRx0DEs44YgqHK .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-TrFRx0DEs44YgqHK .icon-shape .label rect,#mermaid-svg-TrFRx0DEs44YgqHK .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TrFRx0DEs44YgqHK .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-TrFRx0DEs44YgqHK .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-TrFRx0DEs44YgqHK :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 输入 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, c2s0, H, W)
分支 1 (B, c2s1, 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

相关推荐
NeoGressAI外贸数字化11 分钟前
IOR新规9月18日生效:Form 5106六项资料自查清单
人工智能
auto_go17 分钟前
Python 实战指南(7)——账本动不动就崩?先把“魔法字符串”和“裸报错”干掉
python
Beyond_System|系统之外18 分钟前
【学编程】Python基础编程题100道(21-60)
开发语言·python·算法
根目录下的猫33 分钟前
RK3588适配的轻量级AI模型推荐
人工智能·后端·python·目标检测
weixin_66844 分钟前
Cursor 插件使用说明:Linear 与 Figma
人工智能·cursor
wno7041 小时前
Spring Security权限控制
java·python·spring
wshzd1 小时前
LLM之Agent(六十八)|PI(七)构建测试与开发流程
人工智能
H0311169851 小时前
App竞品数据平台功能梳理:月狐数据、七麦数据、点点数据
人工智能
YOLO数据集集合2 小时前
高铁轨道紧固件损坏检测数据集 | 高铁巡检 紧固件缺陷 轨道安全9093期
人工智能·目标检测·计算机视觉·目标跟踪·轨道·铁轨紧固件·铁轨
冬奇Lab2 小时前
一天一个开源项目(第223篇):TeamAI-CLI —— 腾讯开源的团队级 AI Agent 中间层,让每个人的 AI 能力变成团队共享能力
人工智能·开源·资讯