Ultralytics:解读DWConvTranspose2d模块

在这里插入图片描述

前言

相关介绍

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

DWConvTranspose2d(深度可分离转置卷积)

DWConvTranspose2d 是对 nn.ConvTranspose2d 的简单封装,通过设置分组数 groups = gcd(c1, c2) 实现深度可分离的转置卷积(Depthwise Transpose Convolution)。它常用于生成模型(如 GAN、VAE)或语义分割中的上采样操作,可在扩大特征图尺寸的同时大幅降低参数量。


代码实现

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

class DWConvTranspose2d(nn.ConvTranspose2d):
    """Depth-wise transpose convolution module."""

    def __init__(self, c1, c2, k=1, s=1, p1=0, p2=0):
        """Initialize depth-wise transpose convolution with given parameters.

        Args:
            c1 (int): Number of input channels.
            c2 (int): Number of output channels.
            k (int): Kernel size.
            s (int): Stride.
            p1 (int): Padding.
            p2 (int): Output padding.
        """
        super().__init__(c1, c2, k, s, p1, p2, groups=math.gcd(c1, c2))

功能

  • 深度可分离转置卷积:将标准转置卷积的分组数设为 gcd(c1, c2),使得每个输出通道仅与部分输入通道相关联,减少参数。
  • 与普通转置卷积的参数量对比
    • 标准转置卷积: k 2 ⋅ c 1 ⋅ c 2 k^2 \cdot c_1 \cdot c_2 k2c1c2
    • 深度转置卷积(当 g=c1c2c1 的倍数): k 2 ⋅ c 1 k^2 \cdot c_1 k2c1
  • 输出尺寸变化:根据转置卷积的公式,输出尺寸 H o u t = ( H i n − 1 ) ⋅ s − 2 ⋅ p 1 + k + p 2 H_{out} = (H_{in}-1) \cdot s - 2 \cdot p_1 + k + p_2 Hout=(Hin1)s2p1+k+p2,宽度同理。
  • 无 BN 与激活:与 Conv 系列不同,该模块仅包含卷积操作,不附加批归一化和激活函数,使用者可根据需求自行添加。

初始化参数

参数类型说明
c1int输入通道数
c2int输出通道数
kint卷积核大小(默认 1)
sint步长(默认 1)
p1int填充(默认 0)
p2int输出填充(默认 0)

DWConv 类似,分组数 g = gcd(c1, c2),当 c2c1 的整数倍时,g = c1,实现真正的深度卷积(每个输入通道独立生成输出通道)。


与标准转置卷积的区别

特性标准转置卷积 (nn.ConvTranspose2d)深度转置卷积 (DWConvTranspose2d)
分组数 g默认 1gcd(c1, c2)(通常为 c1
参数量 k 2 ⋅ c 1 ⋅ c 2 k^2 \cdot c_1 \cdot c_2 k2c1c2 k 2 ⋅ c 1 k^2 \cdot c_1 k2c1(当 g=c1
计算量较大较小
通道混合所有通道混合仅分组内混合

使用示例

在这里插入图片描述

if __name__ == '__main__':
    # 1. 读取图像
    img_path = "cat_640x640.png"
    img_bgr = cv2.imread(img_path)
    if img_bgr is None:
        raise FileNotFoundError(f"图片 {img_path} 不存在!")

    # 2. 转为张量 (1,3,640,640)
    img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
    img_tensor = torch.from_numpy(img_rgb).float().permute(2, 0, 1).unsqueeze(0)

    # 3. 创建 DWConvTranspose2d 层:输入3通道,输出16通道,核3×3,步长2,填充1,输出填充0
    #    步长2使尺寸翻倍(上采样),注意转置卷积的填充公式
    dw_transpose = DWConvTranspose2d(c1=3, c2=16, k=3, s=2, p1=1, p2=0)

    # 4. 前向传播
    with torch.no_grad():
        out = dw_transpose(img_tensor)
    print("输出形状:", out.shape)  # 计算:(640-1)*2 - 2*1 + 3 + 0 = 1278+3? 实际应为 1281? 需核对公式

    # 重新计算:H_out = (H_in - 1)*s - 2*p1 + k + p2 = (640-1)*2 -2*1 +3 +0 = 1278 -2 +3 = 1279? 实际上公式是 (H_in-1)*s -2*p1 + k + p2,代入得 (640-1)*2 -2*1 +3 = 1278 -2 +3 = 1279? 但通常用 (H_in -1)*s - 2*p1 + dilation*(k-1) + 1 + p2,对于转置卷积,通常用 nn.ConvTranspose2d 的输出尺寸:H_out = (H_in - 1)*s - 2*padding + dilation*(kernel_size-1) + output_padding + 1。这里未给 dilation,默认为1。所以 H_out = (640-1)*2 -2*1 + 1*(3-1) + 0 + 1 = 1278 -2 +2 +1 = 1279? 再检查:标准公式:H_out = (H_in -1)*stride - 2*padding + dilation*(kernel_size-1) + output_padding + 1。所以 H_out = 639*2 -2 +2 +0 +1 = 1278 -2 +2 +1 = 1279? 实际上 1278-2=1276, +2=1278, +1=1279。但通常希望上采样2倍,即 640 -> 1280,这里得到1279,是因为填充选择导致不对称。若设置 p1=1, p2=1 可得到1280。为了演示,我们选择 p1=1, p2=1。
    # 修改参数为 p1=1, p2=1 得到 (640-1)*2 -2 +2 +1 = 1280
    # 下面重新创建
    dw_transpose = DWConvTranspose2d(c1=3, c2=16, k=3, s=2, p1=1, p2=1)
    with torch.no_grad():
        out = dw_transpose(img_tensor)
    print("输出形状 (调整后):", out.shape)  # torch.Size([1, 16, 1280, 1280])

    # 5. 可视化第一个通道(需下采样或裁剪以显示,因为尺寸变大)
    feat_map = out[0, 0, :, :].cpu().numpy()
    # 归一化到 0~255
    feat_map = (feat_map - feat_map.min()) / (feat_map.max() - feat_map.min() + 1e-8)
    feat_map = (feat_map * 255).astype(np.uint8)

    # 为便于显示,将特征图缩放到与原始图像相近尺寸(或保持原样,但显示时可能太大)
    # 这里我们直接显示(matplotlib会自动缩放)
    plt.figure(figsize=(10, 5))
    plt.subplot(1, 2, 1)
    plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
    plt.title("Original (640x640)")
    plt.axis("off")

    plt.subplot(1, 2, 2)
    plt.imshow(feat_map, cmap='gray')
    plt.title("DWConvTranspose2d (1280x1280, Ch0)")
    plt.axis("off")

    plt.tight_layout()
    plt.savefig("dwconvtranspose_output.png", dpi=150)
    # plt.show()
    print("可视化已保存为 dwconvtranspose_output.png")

在这里插入图片描述
输出示例

输出形状: torch.Size([1, 16, 1279, 1279])
输出形状 (调整后): torch.Size([1, 16, 1280, 1280])
可视化已保存为 dwconvtranspose_output.png

流程示意图

在这里插入图片描述


代码解读

__init__ 方法
  • 直接调用父类 nn.ConvTranspose2d 的构造函数,传入 groups=math.gcd(c1, c2)
  • 父类会创建对应的转置卷积层,分组数被设置,实现深度分离效果。
DWConv 的异同
  • 相同点:都使用 gcd 作为分组数,目标都是减少参数。
  • 不同点:
    • DWConv 继承自 Conv,包含 BN 和激活。
    • DWConvTranspose2d 继承自 nn.ConvTranspose2d无 BN 和激活,纯粹是一个卷积层。
    • 使用场景不同:前者用于特征提取(下采样/同尺寸),后者用于上采样。
转置卷积输出尺寸计算

给定输入尺寸 H i n H_{in} Hin,输出尺寸为:
H o u t = ( H i n − 1 ) ⋅ s − 2 ⋅ p 1 + k + p 2 H_{out} = (H_{in} - 1) \cdot s - 2 \cdot p_1 + k + p_2 Hout=(Hin1)s2p1+k+p2
其中 k k k 为核大小, s s s 为步长, p 1 p_1 p1 为填充, p 2 p_2 p2 为输出填充。
本模块未引入膨胀(dilation=1),若有需要可扩展。


注意事项

  1. 无 BN 和激活:该模块仅做卷积,不附加归一化或非线性,使用时需在外部添加(如 nn.BatchNorm2dnn.ReLU),否则网络可能难以训练。
  2. 参数选择技巧
    • 若希望输出尺寸为输入尺寸的 s 倍(例如 s=2 实现 2× 上采样),通常设置 p1 = k//2p2 = k%2 以保持对齐。
    • 对于奇数核(如 k=3s=2),推荐 p1=1, p2=1 得到 H_out = 2*H_in(如 640 → 1280)。
  3. 分组数限制groups 必须能同时整除 c1c2gcd 保证这一点,但当 gcd=1 时退化为标准转置卷积,节省效果消失。
  4. ConvTranspose2d 的兼容性:由于继承自 nn.ConvTranspose2d,所有父类参数(如 dilation, bias 等)均可通过 *args, **kwargs 扩展,但本实现未暴露,需要修改源码。
  5. 适用场景:生成对抗网络(GAN)中的上采样层、语义分割的解码器、自编码器等。

优缺点

优点
  1. 参数量和计算量大幅减少
    g=c1 时,参数量从 k 2 ⋅ c 1 ⋅ c 2 k^2 \cdot c_1 \cdot c_2 k2c1c2 降至 k 2 ⋅ c 1 k^2 \cdot c_1 k2c1,节省了 c 2 c_2 c2 倍,适合轻量级上采样。

  2. 结构简单,易于使用
    直接继承 nn.ConvTranspose2d,无需额外封装,可无缝替换原有转置卷积。

  3. 内存友好
    分组操作减少了中间计算量,降低显存占用,适合大尺寸输入。

缺点
  1. 表达能力受限
    缺少通道间的混合(因分组),上采样后的特征图可能不够丰富,需配合后续 1×1 卷积增强。

  2. 无内置归一化与激活
    使用者需手动添加 BN 和激活,增加了设计步骤,且若忘记添加可能影响训练收敛。

  3. 参数调整较复杂
    转置卷积的填充、输出填充需要精确计算,否则尺寸不对齐,尤其当核大小和步长不匹配时,容易产生棋盘效应(checkerboard artifacts)。

  4. 硬件加速受限
    分组转置卷积在部分深度学习框架中的实现可能不如标准转置卷积优化,尤其在 GPU 上性能提升不明显。


在 YOLOv8 中,转置卷积通常用于特征金字塔的上采样路径(如 nn.Upsample + 卷积),DWConvTranspose2d 可作为轻量替代,但需注意与 BN/激活的搭配以及尺寸对齐。

参考文献

[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、付费专栏及课程。

余额充值