1 转置卷积

1.1 概念

转置卷积(Transposed Convolution),也被称为解卷积(Deconvolution)或反卷积(尽管严格数学定义上并不是真正的反卷积操作),是深度学习中实现上采样的关键技术之一。

转置卷积的核心思想:通过把输入特征图中的每个元素“展开”到更大的空间,再利用卷积核进行加权叠加,从而实现可学习的上采样。

在语义分割(如FCN、Unet)、GAN以及图像超分辨率等任务中,网络需要将低分辨率的特征图恢复到高分辨率,转置卷积就是用来完成这一“放大”过程的核心模块。

1.2 转置卷积的工作原理

对于普通卷积(下采样),输出尺寸公式:O = \frac{N+2P-K}{s}+1(N是输入大小)很多人误以为转置卷积=普通卷积的逆操作,实际上不是,它是把普通卷积看成矩阵乘法,然后把矩阵转置。

//观察下面示例:

转置卷积拿输入的每一个像素值分别于正个卷积核相乘,生成一个与卷积核尺寸相同的局部矩阵,再把这4个局部矩阵按照输入的相对位置(步长)摆放,重叠部分直接相加。

为什么能放大尺寸?

  • 普通卷积:stride↑,跳得越远,输出尺寸变小;
  • 转置卷积:stride↑,元素之间插入更多间隔,输出尺寸变大。—— 在输入的相邻像素之间插入Stride-1个零。
  • 输出尺寸计算

    转置卷积输出尺寸:O = (N-1)\times S-2P+K+OutputPadding

1.3 矩阵数学关系(为什么叫“转置”?)

  • 对于普通卷积,假设展平后的输入矢量X(长度16),输出Y(长度4)。我们可以构造一个稀疏变换矩阵  C_{4\times16}:$Y = C \cdot X$。
  • 若要从长度为 4 的矢量 Y 映射回长度为16 的空间矢量 X^{'}:最自然的操作就是乘以C的转置矩阵 {C^{T}}_{16\times4}: X^{'} = C^{T} \cdot Y
  1. 矩阵转置改变的是参数的对应拓扑结构与传播方向,使得低维空间能映射回高维空间;
  2. 注意:{C^{T}}只是改变了形状,它并不是C的逆矩阵,因此转置卷积是“维度恢复”,而非“数值还原”。


2 代码实现

2.1 基本操作 

import torch
from torch import nn
from d2l import torch as d2l

下面的 trans_conv默认stride=1、padding=0,对输入矩阵和卷积核矩阵计算出 Y 的尺寸。

def trans_conv(X, K):
    h, w = K.shape
    Y = torch.zeros((X.shape[0] + h - 1, X.shape[1] + w - 1))
    for i in range(X.shape[0]):
        for j in range(X.shape[1]):
            Y[i: i + h, j: j + w] += X[i, j] * K
    return Y

转置卷积通过kernal“广播”输入元素,从而产生大于输入的输出。下面代码实现了基本的二维转置卷积运算。

X = torch.tensor([[0.0, 1.0], [2.0, 3.0]])
K = torch.tensor([[0.0, 1.0], [2.0, 3.0]])
trans_conv(X, K)

当输入 X 和卷积核 K 都是四维张量时,我们可以使用高级API获取相同结果:

# 重塑张量形状(N,C,H,W)
X, K = X.reshape(1, 1, 2, 2), K.reshape(1, 1, 2, 2)
# 创建转置卷积层
tconv = nn.ConvTranspose2d(1, 1, kernel_size=2, bias=False)
# 将我们自定义的卷积核K直接赋值给转置卷积层的权重参数,这样转置卷积就使用我们指定的核来进行运算
tconv.weight.data = K
tconv(X)

2.2 填充、步幅和多通道

与常规卷积不同,在转置卷积中,填充被应用于输出(常规卷积将填充应用于输入)。 例如,当将高和宽两侧的填充数指定为1时,转置卷积的输出中将删除第一和最后的行与列。

tconv = nn.ConvTranspose2d(1, 1, kernel_size=2, padding=1, bias=False)
tconv.weight.data = K
tconv(X)

在转置卷积中,步幅被指定为中间结果(输出),而不是输入。 使用上图中相同输入和卷积核张量,将步幅从1更改为2会增加中间张量的高和权重,因此输出张量在下图中。

​

下面通过代码验证步幅为2的转置卷积的输出。

tconv = nn.ConvTranspose2d(1, 1, kernel_size=2, stride=2, bias=False)
tconv.weight.data = K
tconv(X)

​

对于多个输入和输出通道,转置卷积与常规卷积以相同方式运作。 假设输入有C_{i}个通道,且转置卷积为每个输入通道分配了一个{k_h}\times k_w的卷积核张量。 当指定多个输出通道时,每个输出通道将有一个c_i \times {k_h}\times k_w 的卷积核。

X = torch.rand(size=(1, 10, 16, 16))
conv = nn.Conv2d(10, 20, kernel_size=5, padding=2, stride=3)
tconv = nn.ConvTranspose2d(20, 10, kernel_size=5, padding=2, stride=3)
tconv(conv(X)).shape == X.shape

如果我们将 X 代入卷积层 f 来输出 Y=f(X),并创建一个与 f 具有相同的超参数、但输出通道数量是 X 中通道数的转置卷积层 g ,那么的g(Y) 形状将与 X 相同。

​

2.3 数学本质:为什么叫“转置”? 

(1)定义标准卷积示例(用普通滑动窗口),(X_{3 \times 3}、K_{2 \times 2},输出Y应是2×2的矩阵):

X = torch.arange(9.0).reshape(3, 3)
K = torch.tensor([[1.0, 2.0], [3.0, 4.0]])
Y = d2l.corr2d(X, K)
Y

​

(2)用“矩阵乘法”重构标准卷积——构造一个形状为 (4, 9) 的稀疏权重矩阵 W。这个矩阵的每一行,都对应着卷积核在 X 的不同位置滑动时所作用的权重。。

def kernel2matrix(K):
    k, W = torch.zeros(5), torch.zeros((4, 9))
    k[:2], k[3:5] = K[0, :], K[1, :]
    W[0, :5], W[1, 1:6], W[2, 3:8], W[3, 4:] = k, k, k, k
    return W

W = kernel2matrix(K)
W

  • 第一行$[1, 2, 0, 3, 4, 0, 0, 0, 0]$ 与 $\mathbf{x}$ 相乘,正好取出了 $X$ 左上角的$2 \times 2$ 区域 $(0, 1, 3, 4)$,乘以 $K$ 的元素再求和,得到第一个输出27;

  • 同理,第二、三、四行分别对应卷积核滑动到右上方、左下方、右下方的计算。

此时,卷积的前向传播可以完美等价为矩阵乘法:$\mathbf{y} = W \mathbf{x}$

Y == torch.matmul(W, X.reshape(-1)).reshape(2, 2)

其中 $\mathbf{x}$ 是 $9 \times 1$ 的向量,$W$ 是$4 \times 9$ 的矩阵,输出 $\mathbf{y}$ 是 $4 \times 1$ 的向量(重新 reshape(2, 2) 之后就和第一步的结果完全一致)。

(3)转置卷积 = 乘以转置矩阵 $W^T$

现在,我们要实现反向的上采样,把一个 $2 \times 2$的特征图(展平为长为 4 的向量$\mathbf{y}$)恢复/放大到 $3 \times 3$的尺寸(展平为长为 9 的向量 $\mathbf{z}$)。

如果我们直接把权重矩阵$W$进行转置,得到$W^T$,它的形状就变成了 $(9, 4)$:$\mathbf{z} = W^T \mathbf{y}$

  • $W^T$ 的维度是$(9, 4)$,$\mathbf{y}$ 的维度是 $(4, 1)$,相乘后得到 $\mathbf{z}$的维度是 $(9, 1)$。

  • 重新变形成 $(3, 3)$ 后,就得到了一个 $3 \times 3$ 的图像!

Z = trans_conv(Y, K)
Z == torch.matmul(W.T, Y.reshape(-1)).reshape(3, 3)

上面代码验证了:调用转置卷积函数 trans_conv(Y, K) 的结果,与直接执行矩阵乘法 W.T @ Y 完全一致 。


总结

转置卷积不是卷积的逆运算,而是一种通过学习参数实现上采样的卷积操作。它通过将输入元素扩散到更大的空间并进行重叠累加,实现从低分辨率特征图恢复高分辨率特征图。


拓展-上采样和下采样

下面简单介绍以下上采样(Upsampling)和下采样(Downsampling)。

在深度学习(尤其是计算机视觉中的语义分割、目标检测、超分辨率等)以及数字信号处理中,上采样 和 下采样 是两种相反但相辅相成的核心图像操作。

简单来说:

  • 下采样:缩小图像(降低分辨率),提取高层特征,减少计算量。

  • 上采样:放大图像(提高分辨率),恢复空间细节,还原像素级预测。

一、下采样:特征提取与降维

(1)核心作用
  • 扩大感受野(Receptive Field):让深层网络中的一个神经元能够“看到”更大范围的输入像素,从而捕获全局语义信息(例如“这是一张人在开车的图片”)。

  • 降低计算量与内存占用:通过缩小特征图(Feature Map)的宽高尺寸,指数级减少后续卷积运算的浮点数(FLOPs)。

  • 增强平移不变性(Translation Invariance):对目标的微小位置变化不敏感,提升模型的泛化能力。

(2)常见实现方式
  • ① 最大池化(Max Pooling)

  • 原理:在指定的窗口(如 $2 \times 2$)内提取最大值。

  • 特点:保留最显著的特征(如边缘、纹理亮 zone),丢失背景细节;无任何可训练参数,计算极快。

  • ② 平均池化(Average Pooling)

  • 原理:在指定窗口内计算平均值。

  • 特点:保留全局背景信息的平滑过渡,但容易模糊边缘特征;同样无参数。

  • ③ 带步长的卷积(Strided Convolution)

  • 原理:使用步长(Stride)大于 1 的卷积核(如 Stride=2)。

  • 特点:可学习的下采样。网络可以自行学习应该保留哪些特征、丢弃哪些噪声,在现代网络(如 ResNet)中越来越常用来替代传统的池化层。

二、 上采样:尺寸恢复与重

在语义分割(UNet、FCN等)和图像生成(GAN等)中,编码器(Encoder)经过多次下采样后特征图尺寸变得很小,必须依靠上采样在解码器(Decoder)中逐步还原到原图尺寸,才能对每一个像素进行类别预测。

(1)常见实现方式
① 传统插值法(Interpolation)—— 无参数

这类方法不需要学习权重,直接根据周边像素计算新像素值,计算开销极低。

  • 最近邻插值(Nearest Neighbor Interpolation): 直接将距离新像素最近的原像素值填入。速度最快,但会产生明显的“锯齿/马赛克”效应。

  • 双线性插值(Bilinear Interpolation): 根据周围 4 个最近像素点进行线性加权平均。图像比最近邻更平滑,是深度学习中最常用的无参数上采样方式。

  • 双三次插值(Bicubic Interpolation): 利用周围 16 个像素点进行高阶多项式插值。边缘最平滑,但计算成本比双线性插值更高。

② 转置卷积 / 反卷积(Transposed Convolution)—— 有参数
  • 原理:它是卷积的逆向空间运算。通过在输入特征图的元素之间补充零值(Paddings/Strides),然后应用可学习的卷积核进行标准卷积操作。

  • 优点:参数可学习,网络能自适应地学习如何“放大”特征图并恢复细节。

  • 缺点:如果参数未调优,容易产生棋盘效应(Checkerboard Artifacts)(图像上出现网格状的纹理噪点)。

③ 床垫/反池化(Unpooling)—— 配合 Max Pooling 矩阵
  • 原理:在下采样使用 Max Pooling 时,记录下最大值在窗口内的位置索引(Max Unpooling Indices);在上采样时,将特征值填回原索引位置,其余位置补 0。

  • 特点:经典网络 SegNet 采用了此方案,能极好地保存边缘结构信息,且不需要增加额外的训练参数。

④ PixelShuffle(Sub-Pixel Convolution / 像素重组)
  • 原理:多用于图像超分辨率领域(如 ESPCN)。将通道维度的特征图进行重排,组合拼接到空间维度(宽高)上(例如:把 $C \times H \times W$的特征图重排为 $\frac{C}{r^2} \times rH \times rW$)。

  • 优点:避免了棋盘效应,重建质量极高,计算效率优异。

更多推荐