GSConv和VoVGSCSP


def channel_shuffle(x, groups: int = 2):
    """通道洗牌(ShuffleNet 风格)。若不能整除 groups 则直接返回原张量。"""
    b, c, h, w = x.size()
    if groups <= 1 or c % groups != 0:
        return x
    x = x.view(b, groups, c // groups, h, w)
    x = x.transpose(1, 2).contiguous()
    return x.view(b, c, h, w)


class GSConv(nn.Module):
    """
    轻量化 GSConv
    签名:GSConv(c1, c2, k=3, s=1, act=True)
    在 YOLO YAML 中写法示例: [-1, 1, GSConv, [256, 3, 1]]
    """
    def __init__(self, c1, c2, k: int = 3, s: int = 1, act: bool = True):
        super().__init__()
        # 将输出通道分为 fast 和 cheap 两路
        c_fast = c2 // 2
        c_cheap = c2 - c_fast

        # 快速路径:1x1 conv(支持 stride)
        self.cv_fast = Conv(c1, c_fast, k=1, s=s, act=act)

        # 便宜路径:1x1 -> depthwise 3x3
        self.cv_pw = Conv(c1, c_cheap, k=1, s=1, act=act)
        self.cv_dw = nn.Sequential(
            nn.Conv2d(c_cheap, c_cheap, k, s, autopad(k), groups=c_cheap, bias=False),
            nn.BatchNorm2d(c_cheap),
            nn.SiLU(inplace=True) if act else nn.Identity()
        )

        # 只有当 c2 可被 2 整除时才做 shuffle
        self.groups = 2 if c2 % 2 == 0 else 1

    def forward(self, x):
        y1 = self.cv_fast(x)
        y2 = self.cv_dw(self.cv_pw(x))
        y = torch.cat([y1, y2], dim=1)
        if self.groups > 1:
            y = channel_shuffle(y, self.groups)
        return y


class VoVGSCSP(nn.Module):
    """
    VoVNet 风格 + GSConv + CSP 变体
    签名:VoVGSCSP(c1, c2, n=1, shortcut=True, e=0.5)
    YAML 中使用示例:
      - [-1, 2, VoVGSCSP, [256]]             # 只传 c2,n/shortcut/e 使用默认值
      - [-1, 2, VoVGSCSP, [512, 3, False, 0.5]]
    说明:
      - c1 由构建器自动传入(前一层输出通道)
      - c2 必填,表示模块最终输出通道
      - n:右支 GSConv 层数(默认1)
      - shortcut:当 c1==c2 且为 True 时将添加输入残差
      - e:expansion 比例,用于计算中间通道 c_ = max(1, int(c2*e))
    """
    def __init__(self, c1, c2, n: int = 1, shortcut: bool = True, e: float = 0.5):
        super().__init__()
        # 中间隐藏通道,避免为0
        c_ = max(1, int(c2 * e))

        # 两路分流(CSP)
        self.cv_short = Conv(c1, c_, 1, 1)    # 快捷/残差分支(保留低开销信息)
        self.cv_main = Conv(c1, c_, 1, 1)     # 主分支进入 GSConv 堆叠

        # 右支:n 个 GSConv
        self.gs_blocks = nn.ModuleList([GSConv(c_, c_, k=3, s=1, act=True) for _ in range(n)])

        # OSA 风格聚合:把初始 right + 各层输出 concat,再 conv 回 c_
        self.agg = Conv((n + 1) * c_, c_, 1, 1)

        # 最终融合:concat(shortcut_branch, agg) -> conv -> 输出 c2
        self.out_conv = Conv(2 * c_, c2, 1, 1)

        # 是否加残差(只有当输入输出通道一致且用户开启 shortcut)
        self.use_res = shortcut and (c1 == c2)

    def forward(self, x):
        sc = self.cv_short(x)       # shortcut 分支
        y = self.cv_main(x)         # 主分支初始
        feats = [y]
        for m in self.gs_blocks:
            y = m(y)
            feats.append(y)
        y = torch.cat(feats, dim=1)
        y = self.agg(y)
        out = self.out_conv(torch.cat([y, sc], dim=1))
        return out + x if self.use_res else out

 

✅ GSConv 模块逻辑检查

  • 通道混洗 (channel_shuffle)

    • 目的是让分组卷积后的特征互相“交流”,避免信息隔离。

    • 必须保证输出通道数 c2 能被 groups 整除(默认 2)。

    • ✅ 如果你设置 GSConv(256, 256)GSConv(128, 256),都是偶数通道,不会出错。

  • DWConv + PWConv

    • DWConv: 深度可分离卷积(只在通道内卷积,降低 FLOPs);

    • PWConv: 1x1 卷积(跨通道整合)。

    • ✅ 这个组合跟 ShuffleNet 思路一致,能轻量化。

  • 激活函数

    • 默认用 YOLO 的 SiLU,兼容性 OK。

  • 依赖

    • 用到 autopad(k)(YOLO 的自动 padding),所以和 YOLO11 框架兼容。

 

✅ VoVGSCSP 模块逻辑检查

核心思想:

  1. 输入 → Conv 降通道 → 分两路

    • 一路直接走(残差/shortcut);

    • 一路进入 GSConv 堆叠

  2. 堆叠多层 GSConv → 聚合

    • 借鉴 VoVNet 的 OSA:把多个中间层的输出拼接,再卷积融合。

  3. Concat 两路 → Conv 融合 → 输出

 

🔹 1. GSConv(Ghost Shuffle Convolution)

核心思想:轻量化卷积
👉 结合了 GhostConvShuffleNet 的思路,用 深度卷积 + 点卷积 再加上 通道混洗 来减少计算量但保持特征表达能力。

结构流程

  1. DWConv (Depthwise Convolution)

    • 每个通道独立卷积,计算量大幅下降。

    • 如果输入 256 通道,DWConv 就是 256 个 3x3 卷积,而不是标准卷积那样 256x256 个。

  2. PWConv (Pointwise Convolution, 1x1)

    • 跨通道的整合,把 DWConv 产生的“弱特征”组合成“强特征”。

  3. Channel Shuffle (通道混洗)

    • 避免分组卷积带来的“通道隔离”问题,让信息在不同组之间流动。

    • 类似 ShuffleNet 的 trick。

好处

✅ 轻量化:相比标准卷积,参数量和 FLOPs 更少;
✅ 特征交互:通道混洗提升表达能力;
✅ 适合小模型(如 YOLO11n、YOLO11s)或算力有限的设备(边缘端、移动端)。


🔹 2. VoVGSCSP(VoVNet + GSConv + CSP)

核心思想:高效骨干特征提取
👉 这是一个融合结构,把 VoVNet(并行卷积 + 一次性拼接输出)CSP(Cross Stage Partial) 框架结合起来,同时用 GSConv 来进一步轻量化。

结构流程

  1. CSP(Cross Stage Partial)

    • 将特征分为两部分:一部分直接走捷径(shortcut),另一部分进入深度卷积堆叠。

    • 这样能降低计算量,同时保持梯度流动。

  2. VoVNet Block

    • 一种类似 ResNet 的改进结构,但是所有中间层的输出都会被拼接(concat)到最后输出。

    • 比 ResNet 更高效,特征表达能力更强。

  3. GSConv 替代普通卷积

    • 在 CSP 和 VoVNet 的基础模块中用 GSConv 替代普通卷积块。

    • 相当于进一步“轻量化”。

好处

✅ 兼顾速度与精度:比普通 CSPBlock 更快,精度下降有限;
✅ 高效特征融合:VoVNet 的拼接方式让浅层和深层特征结合得更好;
✅ 可替换 CSPDarkNet 的部分结构,用于 backbone 或 neck。


🔹 在 YOLO11 里的作用

  • GSConv
    通常用来替换 ConvC3 模块(尤其是在 Neck 部分),目的是减少参数量和推理耗时。

  • VoVGSCSP
    通常作为 Backbone 的中间层(类似 C3/C2f 替代品),它可以在保证特征表达能力的同时减轻模型规模。

    • 例如,把 YOLO11 里原来的 C3k2C2PSA 替换成 VoVGSCSP,就能得到一个更轻量的变体。


🔹 总结对比

模块用途特点适用位置
GSConv 轻量化卷积 DWConv + PWConv + 通道混洗 Neck / 替换 Conv
VoVGSCSP 高效特征提取块 VoVNet 拼接 + CSP + GSConv Backbone / 替换 C3

✅ 修改要点

  1. Backbone 部分

    • GSConv 替换了部分 Conv,提升轻量化和特征提取能力。

    • VoVGSCSP 替换了 C3k2,增强特征聚合能力。

  2. Head 部分

    • 把一些降通道 Conv 换成 GSConv

    • 主要的聚合层 (C3k2) 换成 VoVGSCSP,保持语义一致性。

 

生成的yaml文件:

 

# YOLO11 + 自定义模块融合版
nc: 80
scales:
  n: [0.50, 0.25, 1024]

# Backbone
backbone:
  - [-1, 1, Conv, [64, 3, 2]]        # 0-P1/2
  - [-1, 1, Conv, [128, 3, 2]]       # 1-P2/4
  - [-1, 2, VoVGSCSP, [256]]         # 2 自定义替换C3k2
  - [-1, 1, Conv, [256, 3, 2]]       # 3-P3/8
  - [-1, 2, VoVGSCSP, [512]]         # 4 自定义替换C3k2
  - [-1, 1, Conv, [512, 3, 2]]       # 5-P4/16
  - [-1, 2, VoVGSCSP, [512]]         # 6 自定义替换C3k2
  - [-1, 1, Conv, [1024, 3, 2]]      # 7-P5/32
  - [-1, 2, VoVGSCSP, [1024]]        # 8 自定义替换C3k2
  - [-1, 1, SPPF, [1024, 5]]         # 9
  - [-1, 2, C2PSA, [1024]]           # 10
  - [-1, 1, CoTAttention, [1024]]    # 11 Backbone末端

# Head
head:
  # P5 -> P4 上采样融合
  - [-1, 1, CARAFE, [1024, 512, 2]]  # 12 上采样2x
  - [[-1, 6], 1, Concat, [1]]        # 13 concat CARAFE + P4
  - [-1, 2, GSConv, [512]]           # 14 降通道
  - [-1, 1, CoTAttention, [512]]     # 15

  # P4 -> P3 上采样融合
  - [-1, 1, CARAFE, [512, 256, 2]]   # 16 上采样2x
  - [[-1, 4], 1, Concat, [1]]        # 17 concat CARAFE + P3
  - [-1, 2, GSConv, [256]]           # 18 降通道
  - [-1, 1, CoTAttention, [256]]     # 19

  # P3 -> P4 下采样融合
  - [-1, 1, GSConv, [256, 3, 2]]     # 20 下采样2x
  - [[-1, 15], 1, Concat, [1]]       # 21 concat 下采样 + P4上采样
  - [-1, 2, GSConv, [512]]           # 22 降通道
  - [-1, 1, CoTAttention, [512]]     # 23

  # P4 -> P5 下采样融合
  - [-1, 1, GSConv, [512, 3, 2]]     # 24 下采样2x
  - [[-1, 11], 1, Concat, [1]]       # 25 concat 下采样 + P5 backbone
  - [-1, 2, GSConv, [1024]]          # 26 降通道
  - [-1, 1, CoTAttention, [1024]]    # 27

  # Detect层
  - [[19, 23, 27], 1, Detect, [nc]]  # 28 Detect(P3, P4, P5)

 

posted @ 2025-08-26 17:52  次花椒的喵酱  阅读(26)  评论(0)    收藏  举报