3.9.转置卷积

转置卷积

​ 目前为止,在卷积神经网络层中,通常会减少下采样输入图像的空间维度(高和宽)。然而如果输入和输出图像的空间维度相同,在以像素级分类的语义分割中将会很方便:输出像素所处的通道维可以保有输入像素在同一位置上的分类结果。

​ 为了实现这一点,可以使用另一种类型的卷积神经网络层,它可以增加上采样中间层特征图的空间维度,用于逆转下采样导致的空间尺寸减少。

1.基本操作

在这里插入图片描述

​ 假设有一个 n h × n w n_h\times n_w nh×nw的输入张量和一个 k h × k w k_h\times k_w kh×kw的卷积核,一步幅为1滑动卷积核窗口,每行 n w n_w nw次,每列 n h n_h nh次,共产生 n h n w n_hn_w nhnw个结果,每个中间结果都是 ( n h + k h ) − 1 × ( n w + k w − 1 ) (n_h+k_h)-1\times(n_w+k_w-1) (nh+kh)1×(nw+kw1)的张量,初始化为0。

​ 输入张量中的每个元素乘以卷积核,得到一个 k h × k w k_h\times k_w kh×kw张量,替换中间张量的一部分。最后所有中间结果相加得到最终结果。
Y [ i : i + h , j : j + w ] + = X [ i , j ] ⋅ K Y[i:i+h,j:j+w] += X[i,j]\cdot K Y[i:i+h,j:j+w]+=X[i,j]K

为什么称为转置?

​ 对于卷积 Y = X @ W Y =X@ W Y=X@W,可以对 W W W构造一个 V V V,使得卷积等价于矩阵乘法 Y ′ = V X ′ Y' = VX' Y=VX,这里 Y ′ , X ′ Y',X' Y,X Y , X Y,X Y,X对应的向量版本。

​ 也就是说如果 Y ′ Y' Y长为 n n n, X ′ X' X长为 m m m,则 V V V的形状为 n × m n\times m n×m,转置之后 V T V^T VT的形状变为 m × n m\times n m×n,则X和Y的形状也交换了。

​ 那么转置卷积等价于 Y ′ = V T X ′ Y'=V^T X' Y=VTX,如果卷积将输入从 ( h , w ) (h,w) (h,w)变成了 ( h ′ , w ′ ) (h',w') (h,w),同样超参数的转置卷积则从 ( h ′ , w ′ ) (h',w') (h,w)变成 ( h , w ) (h,w) (h,w)

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

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


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

X, K = X.reshape(1, 1, 2, 2), K.reshape(1, 1, 2, 2)
# nn库自带的转置卷积函数,超参数很明显
tconv = nn.ConvTranspose2d(1, 1, kernel_size=2, bias=False)
tconv.weight.data = K
print(tconv(X))

2.填充、步幅和多通道

2.1 填充

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

'''填充、步幅和多通道'''
# 填充是对输出进行填充
tconv = nn.ConvTranspose2d(1, 1, kernel_size=2, padding=1, bias=False)
tconv.weight.data = K
print('填充:',tconv(X))

在这里插入图片描述

​ 输出反而变小了

2.2 步幅

在这里插入图片描述

tconv = nn.ConvTranspose2d(1, 1, kernel_size=2, stride=2, bias=False)
tconv.weight.data = K
print('步幅为2:',tconv(X))

2.3 多输入输出通道

​ 与常规卷积类似的,假设输入有 c i c_i ci个通道,且转置卷积为每个输入通道分配了一个 k h × k w k_h\times k_w kh×kw的卷积张量,指定多个输出通道时,每个输出通道将有一个 c i × k h × k w c_i\times k_h\times k_w ci×kh×kw的卷积核

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

'''多输入输出通道'''
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 # True

3.与矩阵乘法的联系

13.10. 转置卷积 — 动手学深度学习 2.0.0 documentation (d2l.ai)

之前有写过了,大概就是卷积操作可以使用矩阵乘法实现。

4.关于填充、步幅的补充

在这里插入图片描述

​ 输入矩阵填充,核矩阵上下左右翻转后做正常卷积(填充0、步幅1)

在这里插入图片描述

在这里插入图片描述

​ s=2时,行和列之间插入一行或已列

​ p=0.则填充k-1=2-1=1。

形状换算

​ 输入高(宽)为n,核k,填充p,步幅s,那么对于转置卷积:
n ′ = s n + k − 2 p − s n'=sn +k-2p-s n=sn+k2ps
​ 如果想让高宽成倍增加,那么 k = 2 p + s k=2p+s k=2p+s

​ 回忆一下,对于卷积:
n ′ = ⌊ ( n − k − 2 p + s ) / s ⌋ → n ≥ s n ′ + k − 2 p − s n'=\lfloor(n-k-2p+s)/s\rfloor \rightarrow n\ge sn'+k-2p-s n=⌊(nk2p+s)/snsn+k2ps
​ 转置卷积不是反卷积,反卷积是指卷积的逆运算:
i f   Y = c o n v ( X , K ) , t h e n   X = d e c o n v ( Y , K ) if\ Y=conv(X,K), then\ X=deconv(Y,K) if Y=conv(X,K),then X=deconv(Y,K)
​ 转置卷积本质上依旧是卷积,只是矩阵形式上的变化相反。

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值