(七)转置卷积

本文详细介绍了转置卷积的概念,包括其在语义分割任务中的应用,以及如何通过numpy和PyTorch实现。讨论了stride、padding、dilation和多通道对输出尺寸的影响,并通过实例展示了计算过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


欢迎访问个人网络日志🌹🌹知行空间🌹🌹


1.基础情况介绍

在语义分割任务使用的网络结构中,除了使用卷积神经网络进行降采样,为了恢复图像的大小,还需要使用转置卷积。转置卷积被称为transposed convolutionfractionally-strided convolution也有些地方称为deconvolution。转置卷积只是恢复的feature map的空间尺寸并不等同于卷积的逆运算,所以称之为deconvolution是不合适的。

为了简化介绍,假设通道channle=1,对于 n h × n ω n_h\times n_\omega nh×nω的输入和 k h × k ω k_h \times k_\omega kh×kω的卷积核,对于stride=1, padding=0的转置卷积,其计算过程为,将 k h × k ω k_h \times k_\omega kh×kω的卷积核在的输入的每一行每一列上滑动,得到 n h n ω n_h n_\omega nhnω个中间结果,每个中间结果的空间尺寸为 ( n h + k h − 1 ) × ( n ω + k ω − 1 ) (n_h + k_h - 1) \times (n_\omega + k_\omega - 1) (nh+kh1)×(nω+kω1),其值初时化为0,然后对于输入中的每个元素,与卷积核相乘得到 k h × k ω k_h \times k_\omega kh×kω的结果替换掉 ( n h + k h − 1 ) × ( n ω + k ω − 1 ) (n_h + k_h - 1) \times (n_\omega + k_\omega - 1) (nh+kh1)×(nω+kω1)矩阵中的对应部分,最后将所有的中间结果相加得到最后的输出

在这里插入图片描述

使用numpy数组实现上述过程为:

import numpy as np
X = np.array([[0.0, 1.0], [2.0, 3.0]])
K = np.array([[0.0, 1.0], [2.0, 3.0]])
def trans_conv(X, K):
    K = K.reshape((2,2))
    X = X.reshape((2, 2))
    h, w = X.shape
    kh, kw = K.shape
    o = np.zeros((h + kh - 1, w + kw - 1))
    for i in range(h):
        for j in range(w):
            o[i : i + h, j : j + w] += X[i][j] * K
    return o
    
trans_conv(X, K)
"""output
array([[ 0.,  0.,  1.],
       [ 0.,  4.,  6.],
       [ 4., 12.,  9.]])
"""

可见程序的输出与上图计算过程的结果一致。

借用pytorch中的ConvTranspose2d实现的计算的过程为:

import torch
import torch.nn as nn

X = torch.tensor([[0.0, 1.0], [2.0, 3.0]])
K = torch.tensor([[0.0, 1.0], [2.0, 3.0]])
X, K = X.reshape(1, 1, 2, 2), K.reshape(1, 1, 2, 2)
tconv = nn.ConvTranspose2d(1, 1, kernel_size=2, bias=False)
tconv.weight.data = K
tconv(X)
"""output
tensor([[[[ 0.,  0.,  1.],
          [ 0.,  4.,  6.],
          [ 4., 12.,  9.]]]], grad_fn=<SlowConvTranspose2DBackward>)
"""

可见这三个地方计算的结果是一致的。

2.使用paddding/stride/dilation/多通道时

2.1 stride

stride表示的是卷积核在输出张量上滑动的步长,前面的例子中使用的是stride=1的场景,在使用stride时,输出张量的空间尺寸 o h o_h oh o ω o_\omega oω的计算方式为 o h = ( n h − 1 ) × s t r i d e + ( k h − 1 ) + 1 o_h = (n_h - 1)\times stride + (k_h - 1) + 1 oh=(nh1)×stride+(kh1)+1, 如下图:

在这里插入图片描述

如上图中 n h = n ω = 3 , k h = k ω = 2 n_h=n_\omega =3, k_h=k_\omega = 2 nh=nω=3,kh=kω=2,则 o h = o ω = 6 o_h=o_\omega = 6 oh=oω=6

使用pytorch验证上述计算过程,则

X = torch.range(0, 8).reshape((1, 1, 3,3))
K = torch.range(0, 3).reshape((1, 1, 2,2))
tconv = nn.ConvTranspose2d(1, 1, kernel_size=2, stride=2, bias=False)
tconv.weight.data = K
Y = tconv(X)
print(Y.shape)
print(Y)

"""output
torch.Size([1, 1, 6, 6])
tensor([[[[ 0.,  0.,  0.,  1.,  0.,  2.],
          [ 0.,  0.,  2.,  3.,  4.,  6.],
          [ 0.,  3.,  0.,  4.,  0.,  5.],
          [ 6.,  9.,  8., 12., 10., 15.],
          [ 0.,  6.,  0.,  7.,  0.,  8.],
          [12., 18., 14., 21., 16., 24.]]]],
       grad_fn=<SlowConvTranspose2DBackward>)
"""

2.2 padding

padding是在transpose convolution计算过程中作用在输出张量上面的,因此计算结束后需要裁剪掉padding的大小。

如 (2.1)[###2.1 stride]中的例子,假设padding=1,则输出张量的最外围一圈将被裁剪掉,如下图:

在这里插入图片描述

此时
o h = ( n h − 1 ) × s t r i d e + ( k h − 1 ) + 1 − 2 × p a d d i n g o_h = (n_h - 1)\times stride + (k_h - 1) + 1 - 2\times padding oh=(nh1)×stride+(kh1)+12×padding
使用pytorch ConvTranspose2d API时,只需要加入padding=1参数即可,

X = torch.range(0, 8).reshape((1, 1, 3,3))
K = torch.range(0, 3).reshape((1, 1, 2,2))
tconv = nn.ConvTranspose2d(1, 1, kernel_size=2, padding=1, stride=2, bias=False)
tconv.weight.data = K
Y = tconv(X)
print(Y.shape)
print(Y)
"""output
torch.Size([1, 1, 4, 4])
tensor([[[[ 0.,  2.,  3.,  4.],
          [ 3.,  0.,  4.,  0.],
          [ 9.,  8., 12., 10.],
          [ 6.,  0.,  7.,  0.]]]], grad_fn=<SlowConvTranspose2DBackward>)
"""

此外还有output_padding,这个是对转置卷积后输出的张量进行的扩充,这会增大输出张量的尺寸,不过pytorch ConvTranspose2d API的实现只对输出张量的一边(H,W较大的那一边)进行了扩充,因此其对输出张量空间尺寸的影响为:

o h = ( n h − 1 ) × s t r i d e + ( k h − 1 ) + 1 − 2 × p a d d i n g + o u t p u t _ p a d d i n g o_h = (n_h - 1)\times stride + (k_h - 1) + 1 - 2\times padding + output\_padding oh=(nh1)×stride+(kh1)+12×padding+output_padding

2.3 dilation

dilation即扩张卷积,卷积核中存在空洞,因此也称空洞卷积。如下图是dilation=2dilated convolution

在这里插入图片描述

Transposed Convolution中使用dilation时,输出的空间尺寸计算可参考下图:

在这里插入图片描述

由上图可得:

o h = ( n h − 1 ) × s t r i d e + d i l a t i o n × ( k h − 1 ) + 1 − 2 × p a d d i n g o_h = (n_h - 1)\times stride + dilation\times (k_h - 1) + 1 - 2\times padding oh=(nh1)×stride+dilation×(kh1)+12×padding

o h = 2 × 2 + 2 × 1 + 1 = 7 o_h = 2 \times 2 + 2 \times 1 + 1 = 7 oh=2×2+2×1+1=7

使用pytorch验证上图中的例子,可得

X = torch.range(0, 8).reshape((1, 1, 3,3))
K = torch.range(0, 3).reshape((1, 1, 2,2))
tconv = nn.ConvTranspose2d(1, 1, kernel_size=2, dilation=2, stride=2, bias=False)
tconv.weight.data = K
Y = tconv(X)
print(Y.shape)
print(Y)

"""output
torch.Size([1, 1, 7, 7])
tensor([[[[ 0.,  0.,  0.,  0.,  1.,  0.,  2.],
          [ 0.,  0.,  0.,  0.,  0.,  0.,  0.],
          [ 0.,  0.,  5.,  0., 11.,  0., 11.],
          [ 0.,  0.,  0.,  0.,  0.,  0.,  0.],
          [ 6.,  0., 23.,  0., 29.,  0., 23.],
          [ 0.,  0.,  0.,  0.,  0.,  0.,  0.],
          [12.,  0., 32.,  0., 37.,  0., 24.]]]],
       grad_fn=<SlowConvTranspose2DBackward>)
"""

综上,对于由padding/stride/dilation/output_padding时,输出张量的计算方式为:

o h = ( n h − 1 ) × s t r i d e + d i l a t i o n × ( k h − 1 ) + 1 − 2 × p a d d i n g + o u t p u t _ p a d d i n g o_h = (n_h - 1)\times stride + dilation\times(k_h - 1) + 1 - 2\times padding + output\_padding oh=(nh1)×stride+dilation×(kh1)+12×padding+output_padding

2.4 multi-channles

同常规的卷积操作,转置卷积对多通道的处理,同样是将每个卷积核在输入张量的各个维度上进行卷积,然后在将各个维度上的卷积结果相加求和即可。

如下代码示例,可见最后的输出正是两个通道上卷积结果求和所得:

X = torch.tensor([[[0.0, 1.0], [2.0, 3.0]],[[0.0, 1.0], [2.0, 3.0]]])
K = torch.tensor([[[0.0, 1.0], [2.0, 3.0]],[[0.0, 1.0], [2.0, 3.0]]])
X, K = X.reshape(1, 2, 2, 2), K.reshape(2, 1, 2, 2)
tconv = nn.ConvTranspose2d(2, 1, kernel_size=2, bias=False)
tconv.weight.data = K
tconv(X)
"""output
tensor([[[[ 0.,  0.,  2.],
          [ 0.,  8., 12.],
          [ 8., 24., 18.]]]], grad_fn=<SlowConvTranspose2DBackward>)
"""

参考资料


欢迎访问个人网络日志🌹🌹知行空间🌹🌹


<think>好的,用户让我介绍一下“卷积”。首先,我需要回顾之前的对话历史,看看用户之前问了什么,以便更好地理解他们的需求。用户之前要求讲解神经网络算法,我给出了一个详细的回答,涵盖了基本概念、历史、核心组件、数学原理、常见类型、优缺点、应用场景以及学习建议。现在用户接着问“卷积”,明显是希望深入理解卷积神经网络中的角色,特别是卷积神经网络(CNN)部分。 首先,我需要确认用户对卷积的理解程度。因为他们在之前的问题中已经接触过CNN,所以可能已经知道卷积在图像处理中的应用,但需要更基础的解释。考虑到用户可能对数学概念不太熟悉,我需要从基础开始,逐步深入,同时保持清晰的结构。 接下来,我应该定义卷积,包括数学中的定义和在神经网络中的具体应用。数学中的卷积涉及积分或求和,但在CNN中,卷积更多是指离散的二维操作,用于图像处理。需要解释卷积操作的基本步骤:卷积核在输入数据上滑动,进行元素乘法和求和。 然后,要解释卷积的核心作用,比如局部感知、参数共享、平移不变性,这些都是CNN的优势所在。同时,需要对比全连接层的缺点,突出卷积层的优势,比如减少参数数量,提高计算效率。 还需要介绍卷积核的类型,比如边缘检测的Sobel、高斯模糊,以及学习得到的卷积核。这部分可以通过示例来说明,帮助用户直观理解不同卷积核的效果。 在数学公式部分,要给出离散卷积的公式,并用LaTeX格式正确呈现,注意用户之前的系统级指令要求独立公式用$$...$$。同时,解释每个符号的意义,比如输入矩阵、卷积核、输出特征图等。 此外,需要讨论卷积操作的三个关键参数:步长、填充和膨胀卷积。这些参数影响了输出尺寸和感受野,对于实际应用非常重要。要举例说明不同步长和填充方式的效果,比如“SAME”填充和“VALID”填充的区别。 在应用场景方面,除了图像处理,还应提到其他领域,如自然语言处理和时间序列分析,展示卷积的广泛适用性。同时,指出卷积的局限性,比如对非局部模式的处理不足,为后续可能的问题(如Transformer模型)做铺垫。 最后,总结卷积的重要性,并邀请用户进一步提问,确保他们理解并有可能深入探讨相关主题。整个过程中,要保持语言简洁,结构清晰,避免使用过于专业的术语,必要时用比喻或示例帮助理解。 现在检查是否需要补充内容。用户可能需要了解为什么卷积在图像处理中如此有效,可以强调局部特征提取的能力,类似于人类视觉系统。另外,可能需要提到池化层的作用,但用户的问题是卷积,所以可以简要提及,但不过多展开。 需要确保数学公式正确,比如二维离散卷积的公式是否正确,是否遗漏了求和的范围。同时,检查激活函数是否在卷积层之后应用,比如ReLU,这点在介绍CNN时应该提到,但当前问题主要关注卷积操作本身,可能不需要深入激活函数的部分。 最后,确保回答符合用户之前的格式要求:使用中文,行内公式用$...$,独立公式用$$...$$,结构清晰,分步骤讲解。同时,保持口语化,避免生硬,让用户容易理解。</think>好的!以下是关于**卷积(Convolution)**的详细讲解,从数学定义到实际应用逐步展开: --- ### **一、卷积的数学定义** **卷积**是数学中的一种运算,用于描述两个函数(或信号)之间的相互作用关系。 - **连续形式**:两个函数$f(t)$和$g(t)$的卷积为: $$ (f * g)(t) = \int_{-\infty}^{\infty} f(\tau) g(t - \tau) d\tau $$ - **离散形式**:两个序列$f[n]$和$g[n]$的卷积为: $$ (f * g)[n] = \sum_{k=-\infty}^{\infty} f[k] \cdot g[n - k] $$ **直观理解**:将一个函数“翻转并滑动”后与另一个函数逐点相乘并求和,用于提取两个信号的重叠特征。 --- ### **二、卷积神经网络中的核心作用** 在**卷积神经网络(CNN)**中,卷积操作被改造为一种高效的局部特征提取工具,核心特点包括: 1. **局部感知**:每个神经元仅连接输入数据的局部区域(如3×3像素),减少参数量。 2. **参数共享**:同一卷积核在输入的不同位置重复使用,增强平移不变性。 3. **层次化特征提取**:浅层卷积捕捉边缘、纹理,深层卷积组合成复杂模式(如物体部件)。 --- ### **三、卷积操作的具体步骤(以图像为例)** 1. **输入数据**:一张图像(如尺寸$H \times W \times C$,$C$为通道数)。 2. **卷积核(滤波器)**:一个可学习的权重矩阵(如3×3×C)。 3. **计算过程**: - 卷积核在输入图像上逐位置滑动(步长可调)。 - 每个位置进行**点乘后求和**,得到输出特征图的一个值。 - 最终生成新的特征图(尺寸由输入尺寸、步长、填充决定)。 **数学表示(二维离散卷积)**: $$ \text{输出}[i,j] = \sum_{m=0}^{k_h-1} \sum_{n=0}^{k_w-1} \text{输入}[i+m, j+n] \cdot \text{卷积核}[m, n] + b $$ 其中$k_h, k_w$为卷积核的高和宽,$b$为偏置项。 --- ### **四、卷积的关键参数** 1. **步长(Stride)**:卷积核每次滑动的距离。 - 步长=1:输出尺寸接近输入;步长=2:输出尺寸减半。 2. **填充(Padding)**:在输入边缘补零以控制输出尺寸。 - **"SAME"填充**:保持输出尺寸与输入一致。 - **"VALID"填充**:不填充,输出尺寸减小。 3. **膨胀卷积(Dilated Convolution)**: - 通过间隔采样扩大感受野(如空洞卷积),不增加参数量。 --- ### **五、卷积核的常见类型** 1. **边缘检测**:如Sobel算子(水平/垂直边缘): $$ \text{水平边缘检测核} = \begin{bmatrix} -1 & 0 & 1 \\ -2 & 0 & 2 \\ -1 & 0 & 1 \end{bmatrix} $$ 2. **模糊滤波**:如高斯核(平滑噪声): $$ \frac{1}{16} \begin{bmatrix} 1 & 2 & 1 \\ 2 & 4 & 2 \\ 1 & 2 & 1 \end{bmatrix} $$ 3. **学习得到的核**:在训练中自动优化,适应任务需求(如识别纹理、形状)。 --- ### **六、卷积的扩展形式** 1. **1D卷积**:处理序列数据(如音频、文本),提取局部时间模式。 2. **3D卷积**:处理视频或体数据(如CT扫描),捕捉时空特征。 3. **深度可分离卷积**:将标准卷积分解为深度卷积+逐点卷积,大幅减少计算量(用于MobileNet等轻量模型)。 --- ### **卷积的应用场景** 1. **图像处理**: - 边缘检测、去噪、锐化。 - 物体识别(CNN中的卷积层)。 2. **自然语言处理**: - 文本分类(1D卷积提取词序列特征)。 3. **时间序列预测**: - 提取局部时间模式(如股票价格波动)。 --- ### **八、卷积的局限性** 1. **固定几何结构**:对旋转、缩放等变换敏感(需通过数据增强或更复杂模型缓解)。 2. **局部性限制**:难以直接建模长距离依赖(需结合注意力机制等)。 --- ### **代码示例(PyTorch实现)** ```python import torch import torch.nn as nn # 定义卷积层:输入通道3,输出通道16,卷积核3x3,步长1,填充1 conv_layer = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=3, stride=1, padding=1) # 输入数据:批量大小4,通道3,高32,宽32 input_data = torch.randn(4, 3, 32, 32) # 前向传播 output = conv_layer(input_data) print(output.shape) # 输出尺寸:[4, 16, 32, 32] ``` --- ### **总结** 卷积通过局部连接和参数共享,高效提取数据的空间或时序特征,是深度学习的核心操作之一。理解其数学原理和实现细节,是掌握CNN及扩展模型的关键!如果需要进一步探讨具体变体(如转置卷积、分组卷积),欢迎提问~
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值