🧠 具体讲解神经网络中的转置卷积(Transposed Convolution)


🧭 1. 转置卷积的动机:为什么我们需要它?

标准卷积通常会降低特征图的空间尺寸(比如从 64x64 → 32x32),这对于提取高级特征很有用。但在某些任务中,比如:

  • 图像生成(如 GAN)
  • 图像分割(如 U-Net 的解码器)
  • 上采样(upsampling)

我们需要把特征图的尺寸还原回来(比如从 32x32 → 64x64),而且希望这个还原是可学习的,也就是说参数可训练。

这时候就需要 转置卷积(也叫反卷积、fractionally strided convolution)。


🧱 2. 什么是转置卷积?直觉理解

我们先从标准卷积的矩阵乘法视角出发来看。

标准卷积可以被视为:
y=Kx y = Kx y=Kx
其中 KKK 是一个稀疏的矩阵(由卷积核扩展而来)。

那么转置卷积就是这个线性变换的转置矩阵乘法

转置卷积是:
x=KTy x = K^T y x=KTy

直觉上:

  • 标准卷积:压缩/整合信息
  • 转置卷积:扩展/重建信息

🧮 3. 数学公式和计算流程

设输入特征图大小为 Cin×Hin×WinC_{in} \times H_{in} \times W_{in}Cin×Hin×Win
卷积核大小为 K×KK \times KK×K,步长为 SSS,padding 为 PPP,输出通道数为 CoutC_{out}Cout

标准卷积输出尺寸计算:

Hout=⌊Hin+2P−KS⌋+1 H_{out} = \left\lfloor \frac{H_{in} + 2P - K}{S} \right\rfloor + 1 Hout=SHin+2PK+1

转置卷积输出尺寸计算:

Hout=(Hin−1)⋅S−2P+K H_{out} = (H_{in} - 1) \cdot S - 2P + K Hout=(Hin1)S2P+K

你可以看到,转置卷积公式中是乘而不是除,所以它有上采样的效果。


🔄 4. 转置卷积是怎么运作的?图示直觉(描述)

  1. 在输入之间插入空格(步长为 2 就在像素间插入 1 个零)
  2. 在这个“稀疏图像”上进行普通卷积
  3. 因为插入了零,卷积核扫描时会“扩大视野”,从而生成更大的输出

这种方式又叫 “fractionally strided convolution”(因为它“模拟”了小于 1 的步长)


🧠 5. 与标准卷积的反向传播的关系

这其实是转置卷积名字的由来!

  • 在实现标准卷积的 反向传播 时,梯度传播过程中的某一步就需要一个类似转置卷积的操作来“还原”梯度。
  • 这也是为什么 PyTorch 中 ConvTranspose2dConv2d 的“梯度反向过程”的实现。

所以:

转置卷积并不是“把卷积反过来”,而是在反向传播中自然出现的操作。


📦 6. PyTorch 实现

import torch
import torch.nn as nn

# 转置卷积层:输入通道3,输出通道16,kernel_size=3,stride=2,padding=1
conv_transpose = nn.ConvTranspose2d(in_channels=3, out_channels=16, kernel_size=3, stride=2, padding=1, output_padding=1)

x = torch.randn(1, 3, 32, 32)
y = conv_transpose(x)
print(y.shape)  # torch.Size([1, 16, 64, 64])

注意:

output_padding 是为了调节输出大小(因为整数除法/乘法可能不是精确反转)

转置卷积参数量和普通卷积一样:Cin×Cout×K2C_{in} \times C_{out} \times K^2Cin×Cout×K2

🔁 7. 参数与输出尺寸公式总结

对于 ConvTranspose2d,输出大小计算公式为:

Hout=(Hin−1)⋅S−2P+K+output_padding H_{out} = (H_{in} - 1) \cdot S - 2P + K + \text{output\_padding} Hout=(Hin1)S2P+K+output_padding

这里:

  • HinH_{in}Hin:输入高度
  • SSS:stride(步长)
  • PPP:padding
  • KKK:kernel size(卷积核大小)
  • output_padding:用于解决无法精确还原的边界问题

🔬 8. 转置卷积 vs 上采样+卷积

我们也可以用非转置卷积实现上采样 + 卷积操作:

import torch.nn.functional as F

x = torch.randn(1, 3, 32, 32)
x_up = F.interpolate(x, scale_factor=2, mode='nearest')  # 最近邻上采样
conv = nn.Conv2d(3, 16, kernel_size=3, padding=1)
y = conv(x_up)

区别在于:

方法可学习参数是否精确上采样计算效率
转置卷积✅ 是✅ 是✅ 快
上采样 + 卷积✅ 是✅ 是较慢,但更可控

💣 9. 转置卷积的常见问题:Checkerboard Artifacts

因为卷积核在插值时可能导致像素间不均匀的覆盖区域,转置卷积有时会出现“棋盘格伪影”。

🛠️ 解决方式:

  • 使用 上采样 + 卷积 替代
  • 使用更小的 kernel 和 stride
  • 加强正则化,或使用 PixelShuffle 等替代方式

🧪 10. 实际应用:U-Net 解码器

在 U-Net 的上采样阶段,我们希望将低分辨率特征图还原为高分辨率(最终恢复为原图大小)。

self.upconv = nn.ConvTranspose2d(64, 32, kernel_size=2, stride=2)

然后 concat encoder 输出 + decoder 输出,再继续卷积。

转置卷积在这一步:

  • 学习“如何恢复图像细节”
  • 与 skip connection 保持 spatial 对齐
  • 输出最终的分割图像或生成图像
Logo

脑启社区是一个专注类脑智能领域的开发者社区。欢迎加入社区,共建类脑智能生态。社区为开发者提供了丰富的开源类脑工具软件、类脑算法模型及数据集、类脑知识库、类脑技术培训课程以及类脑应用案例等资源。

更多推荐