[转置卷积(一)] 搞懂转置卷积的计算

这篇具有很好参考价值的文章主要介绍了[转置卷积(一)] 搞懂转置卷积的计算。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

文章首发于https://zhaodongyu-ak47.github.io/Transposed_Convolution/

最近做了一些转置卷积的部署工作,最开始搞的时候其实有点晕头转向的,总是在用卷积的计算方式反过来理解转置卷积,尤其是padding部分和stride部分,搞得我头更大了。

现在也算是了解了具体工作机制以及加速方式,在这里整理总结一下。欢迎留言、指正 😃

0、参考文档

先敬上各位大佬的文档,这对我非常非常有帮助!

tf.keras.layers.Conv2DTranspose

What is Transposed Convolutional Layer?

一文搞懂反卷积,转置卷积

Up-sampling with Transposed Convolution

转置卷积(Transpose Convolution)

conv_transpose depth-wise优化技巧

图解转置卷积,我分别在conv_arithmetic和What is Transposed Convolutional Layer里看到,感觉后者更容易理解。

1、转置卷积是什么?

1.1 定义

转置卷积有时候也被称为反卷积,我个人认为反卷积有很强的误导性,因为这并不是卷积的逆运算,还是叫转置卷积比较好。

转置卷积在深度学习中表示为卷积的一个逆向过程,可以根据卷积核大小和输出的大小,恢复卷积前的feature map尺寸,而不是恢复原始值。

如果将卷积表示为y=Cx,转置卷积则是将的输入输出互换:x = CTy

其中, CT表示矩阵转置。

详细定义这里就不仔细介绍了,上文里的各个参考文档里说的都很明白。

1.2 需要注意

总结一下我认为的最重要的(最开始纠结了很久的)几个点:

  • 转置卷积不是恢复原始值,而是恢复原始尺寸(所以不要试图从卷积的逆运算角度考虑)

  • padding方式和卷积的padding是不一样的,转置卷积的实际padding是k-p-1

  • stride在这里用途不是跳几个数,而是用于判断填充几个0

  • 用公式法直接计算的话,首先对卷积核做中心对称操作(矩阵旋转180°)

  • 不考虑性能的话,直接按照转置卷积定义写。反之,一定要优化,不然慢得很。

The table below summarizes the two convolutions, standard and transposed.

Conv Type Operation Zero Insertions Padding Stride Output Size
Standard Downsampling 0 p s (i+2p-k)/s+1
Transposed Upsampling (s-1) (k-p-1) 1 (i-1)*s+k-2p

2、转置卷积的计算

2.1 从最简单的开始

conv_transpose有一种最直接的计算方式:首先对卷积核做中心对称操作(矩阵旋转180°),并对输入feature map进行插0,然后把旋转后的卷积核和插0后的feature map进行卷积操作


现在假设输入的feature map是3x3大小,kernel size是3x3大小,stride为1, padding为0,即:

input_sz:     3
kernel_sz =   3
stride =      1
padding_sz =  0

写一段torch代码计算一下:

import torch
X = torch.Tensor([[[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]])
K = torch.Tensor([[[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]])
Y = torch.nn.functional.conv_transpose2d(X, K, stride=1, padding=0)
print(Y)

得到输出结果:

tensor([[[[  1.,   4.,  10.,  12.,   9.],
          [  8.,  26.,  56.,  54.,  36.],
          [ 30.,  84., 165., 144.,  90.],
          [ 56., 134., 236., 186., 108.],
          [ 49., 112., 190., 144.,  81.]]]])

计算过程:

(1) 对输入X进行处理,插入(s-1)的0,做(k-p-1)的padding

在这个例子中,s=1,则无需插入0,只进行(k-p-1)=(3-0-1)=2的padding。输入X则转化为

[ 1 2 3 4 5 6 7 8 9 ] − > [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 3 0 0 0 0 4 5 6 0 0 0 0 7 8 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ] \begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{bmatrix} -> \begin{bmatrix} 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & 2 & 3 & 0 & 0 \\ 0 & 0 & 4 & 5 & 6 & 0 & 0 \\ 0 & 0 & 7 & 8 & 9 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 \\0 & 0 & 0 & 0 & 0 & 0 & 0 \end{bmatrix} 147258369 > 0000000000000000147000025800003690000000000000000

(2) 对卷积核K进行中心对称操作

卷积核K则转化为为
[ 1 2 3 4 5 6 7 8 9 ] − > [ 9 8 7 6 5 4 3 2 1 ] \begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{bmatrix} -> \begin{bmatrix} 9 & 8 & 7 \\ 6 & 5 & 4 \\ 3 & 2 & 1 \end{bmatrix} 147258369 > 963852741

(3) 进行卷积计算
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 3 0 0 0 0 4 5 6 0 0 0 0 7 8 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ] ∗ [ 9 8 7 6 5 4 3 2 1 ] = [ 1 4 10 12 9 8 26 56 54 36 30 84 165 144 90 56 134 236 186 108 49 112 190 144 81 ] \begin{bmatrix} 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & 2 & 3 & 0 & 0 \\ 0 & 0 & 4 & 5 & 6 & 0 & 0 \\ 0 & 0 & 7 & 8 & 9 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 \\0 & 0 & 0 & 0 & 0 & 0 & 0 \end{bmatrix} * \begin{bmatrix} 9 & 8 & 7 \\ 6 & 5 & 4 \\ 3 & 2 & 1 \end{bmatrix} = \begin{bmatrix} 1 & 4 & 10 & 12 & 9 \\ 8 & 26 & 56 & 54 & 36 \\ 30 & 84 & 165 & 144 & 90 \\ 56 & 134 & 236 & 186 & 108 \\ 49 & 112 & 190 & 144 & 81 \end{bmatrix} 0000000000000000147000025800003690000000000000000 963852741 = 1830564942684134112105616523619012541441861449369010881

(4) gif图解

[转置卷积(一)] 搞懂转置卷积的计算

2.2 考虑stride

我个人建议不要用卷积的stride来理解转置卷积的stride,stride在这里用途不是跳几个数,而是用于判断填充几个0。


现在假设输入的feature map是3x3大小,kernel size是3x3大小,stride为2, padding为0,即:

input_sz:     3
kernel_sz =   3
stride =      2
padding_sz =  0

同样,写一段torch代码计算一下:

import torch
X = torch.Tensor([[[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]])
K = torch.Tensor([[[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]])
Y = torch.nn.functional.conv_transpose2d(X, K, stride=2, padding=0)
print(Y)

得到输出结果:

tensor([[[[  1.,   2.,   5.,   4.,   9.,   6.,   9.],
          [  4.,   5.,  14.,  10.,  24.,  15.,  18.],
          [ 11.,  16.,  40.,  26.,  60.,  36.,  45.],
          [ 16.,  20.,  44.,  25.,  54.,  30.,  36.],
          [ 35.,  46., 100.,  56., 120.,  66.,  81.],
          [ 28.,  35.,  74.,  40.,  84.,  45.,  54.],
          [ 49.,  56., 119.,  64., 135.,  72.,  81.]]]])

计算过程:

(1) 对输入X进行处理,插入(s-1)的0,做(k-p-1)的padding

在这个例子中,s=2,需插入1个0,进行(k-p-1)=(3-0-1)=2的padding。输入X则转化为

[ 1 2 3 4 5 6 7 8 9 ] − > [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 2 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 5 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 7 0 8 0 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ] \begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{bmatrix} -> \begin{bmatrix} 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 & 2 & 0 & 3 & 0 & 0 \\0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 4 & 0 & 5 & 0 & 6 & 0 & 0 \\0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 7 & 0 & 8 & 0 & 9 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \end{bmatrix} 147258369 > 000000000000000000001040700000000000002050800000000000003060900000000000000000000

(2) 对卷积核K进行中心对称操作

卷积核K则转化为为
[ 1 2 3 4 5 6 7 8 9 ] − > [ 9 8 7 6 5 4 3 2 1 ] \begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{bmatrix} -> \begin{bmatrix} 9 & 8 & 7 \\ 6 & 5 & 4 \\ 3 & 2 & 1 \end{bmatrix} 147258369 > 963852741

(3) 进行卷积计算
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 2 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 5 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 7 0 8 0 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ] ∗ [ 9 8 7 6 5 4 3 2 1 ] = [ 1 2 5 4 9 6 9 4 5 14 10 24 15 18 11 16 40 26 60 36 45 16 20 44 25 54 30 36 35 46 100 56 120 66 81 28 35 74 40 84 45 54 49 56 119 64 135 72 81 ] \begin{bmatrix} 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 & 2 & 0 & 3 & 0 & 0 \\0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 4 & 0 & 5 & 0 & 6 & 0 & 0 \\0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 7 & 0 & 8 & 0 & 9 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \end{bmatrix}* \begin{bmatrix} 9 & 8 & 7 \\ 6 & 5 & 4 \\ 3 & 2 & 1 \end{bmatrix} = \begin{bmatrix} 1 & 2 & 5 & 4 & 9 & 6 & 9\\ 4 & 5 & 14 & 10 & 24 & 15 & 18\\ 11 & 16 & 40 & 26 & 60 & 36 & 45\\ 16 & 20 & 44 & 25 & 54 & 30 & 36\\ 35 & 46 & 100 & 56 & 120 & 66 & 81\\ 28 & 35 & 74 & 40 & 84 & 45 & 54\\ 49 & 56 & 119 & 64 & 135 & 72 & 81 \end{bmatrix} 000000000000000000001040700000000000002050800000000000003060900000000000000000000 963852741 = 141116352849251620463556514404410074119410262556406492460541208413561536306645729184536815481

(4) gif图解

[转置卷积(一)] 搞懂转置卷积的计算

2.3 考虑padding

我最开始在padding这里疑惑了好一会儿,老是在从卷积的角度想转置卷积的padding。就很疑惑,怎么padding越大,计算结果的feature map越小呢?

后来也不想具体物理含义了,直接认为转置卷积的实际paddingk-p-1,万事大吉。


实际上,tensorflow的padding计算还是有点差异的,除了上面所说的计算,在计算padding的时候还有一个专门针对转置卷积的offset,这可能会导致 左右/上下 的padding数不一致。

为什么这么做呢?个人认为要从转置卷积的目的来看————还原原始feature map的尺寸。

本文暂不考虑这种情况,感兴趣的可以查看tensorflow源码。


现在假设输入的feature map是3x3大小,kernel size是3x3大小,stride为1, padding为1,即:

input_sz:     3
kernel_sz =   3
stride =      1
padding_sz =  1

写一段torch代码计算一下:

import torch
X = torch.Tensor([[[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]])
K = torch.Tensor([[[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]])
Y = torch.nn.functional.conv_transpose2d(X, K, stride=1, padding=1)
print(Y)

得到输出结果:

tensor([[[[ 26.,  56.,  54.],
          [ 84., 165., 144.],
          [134., 236., 186.]]]])

计算过程:

(1) 对输入X进行处理,插入(s-1)的0,做(k-p-1)的padding

在这个例子中,s=1,则无需插入0,只进行(k-p-1)=(3-1-1)=1的padding。输入X则转化为

[ 1 2 3 4 5 6 7 8 9 ] − > [ 0 0 0 0 0 0 1 2 3 0 0 4 5 6 0 0 7 8 9 0 0 0 0 0 0 ] \begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{bmatrix} -> \begin{bmatrix} 0 & 0 & 0 & 0 & 0 \\ 0 & 1 & 2 & 3 & 0 \\ 0 & 4 & 5 & 6 & 0 \\ 0 & 7 & 8 & 9 & 0 \\ 0 & 0 & 0 & 0 & 0 \end{bmatrix} 147258369 > 0000001470025800369000000

(2) 对卷积核K进行中心对称操作

卷积核K则转化为为

[ 1 2 3 4 5 6 7 8 9 ] − > [ 9 8 7 6 5 4 3 2 1 ] \begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{bmatrix} -> \begin{bmatrix} 9 & 8 & 7 \\ 6 & 5 & 4 \\ 3 & 2 & 1 \end{bmatrix} 147258369 > 963852741

(3) 进行卷积计算
[ 0 0 0 0 0 0 1 2 3 0 0 4 5 6 0 0 7 8 9 0 0 0 0 0 0 ] ∗ [ 9 8 7 6 5 4 3 2 1 ] = [ 26 56 54 84 165 144 134 236 186 ] \begin{bmatrix} 0 & 0 & 0 & 0 & 0 \\ 0 & 1 & 2 & 3 & 0 \\ 0 & 4 & 5 & 6 & 0 \\ 0 & 7 & 8 & 9 & 0 \\ 0 & 0 & 0 & 0 & 0 \end{bmatrix}* \begin{bmatrix} 9 & 8 & 7 \\ 6 & 5 & 4 \\ 3 & 2 & 1 \end{bmatrix} = \begin{bmatrix} 26 & 56 & 54\\ 84 & 165 & 144 \\ 134 & 236 & 186\end{bmatrix} 0000001470025800369000000 963852741 = 26841345616523654144186

(4) gif图解

[转置卷积(一)] 搞懂转置卷积的计算

2.4 考虑dilation

这里就不考虑了,和卷积一样的,很容易理解。


3 转置卷积的加速

篇幅有限,转置卷积的加速工作就放到下一篇 转置卷积(二) 对转置卷积进行加速 吧


本文用图参考了aqeelanwar的代码,非常感谢。

图像压缩用了iloveimg,非常好用~文章来源地址https://www.toymoban.com/news/detail-438240.html

到了这里,关于[转置卷积(一)] 搞懂转置卷积的计算的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [SS]语义分割_转置卷积

    转置卷积(Transposed Convolution) 抽丝剥茧,带你理解转置卷积(反卷积)  目录 一、概念 1、定义  2、运算步骤 二、常见参数         转置卷积(Transposed Convolution),也被称为反卷积(Deconvolution)或逆卷积(Inverse Convolution),是一种卷积神经网络中常用的操作。转置卷

    2024年01月22日
    浏览(36)
  • PyTorch 中的转置卷积 ConvTranspose2d

    现有的关于转置卷积的介绍大多流于表面,并未详细的说明这一操作内部具体的操作流程。由于转置卷积的设计主要是为了对标标准卷积,所以其实现流程与标准卷积基本相反,所以内部的操作逻辑并不直观。其按照卷积的相反逻辑的参数设置方式,这种反逻辑的形式使得我

    2024年02月17日
    浏览(46)
  • 上采样(最近邻插值、双线性插值法、反池化、转置卷积)

    一般图像分割的时候,需要对图像进行像素级别的分类,因此在卷积提取到抽象特征后需要通过上采样将feature map还原到原图大小,在FCN和U-net等网络中都提到了上采样的操作,这里会一些上采样的方法进行总结。 最简单的图像缩放算法就是最近邻插值,也称作零阶插值,就

    2024年02月05日
    浏览(66)
  • 改进YOLO系列:YOLOv5结合转置卷积,实现小目标涨点

    该函数是用来进行转置卷积的,它主要做了这几件事:首先,对输入的feature map进行padding操作,得到新的feature map;然后,随机初始化一定尺寸的卷积核;最后,用随机初始化的一定尺寸的卷积核在新的feature map上进行卷积操作。 补充一下,卷积核确实是随机初始的,但是后

    2023年04月09日
    浏览(47)
  • Yolov5更换上采样方式( 最近邻 / 双线性 / 双立方 / 三线性 / 转置卷积) (新增对比试验组)

    🌟想了解YOLO系列算法更多教程欢迎订阅我的专栏🌟 对于基础薄弱的同学来说,推荐阅读《目标检测蓝皮书》📘,里面涵盖了丰富的目标检测实用知识,是你迅速掌握目标检测的理想选择! 如果想了解 YOLOv5 和 YOLOv7 系列算法的训练和改进,可以关注专栏《YOLOv5/v7 改进实战

    2024年02月07日
    浏览(53)
  • 【深度学习】特征图的上采样(nn.Upsample)和转置卷积(nn.ConvTranspose2d) | pytorch

    这次就不废话了,我想赶在10点前回去洗头(现在9.17,还差一篇文章) 该函数有四个参数: 参数的介绍如下: 稍微翻译一下: 参数: 1)size(int或Tuple[int]或Tuple[int,int]或Tupple[int,int,int],可选):输出空间大小 2)scale_factor(float或Tuple[floot]或Tuple[floot,float]或Tuple[floo

    2023年04月08日
    浏览(46)
  • 向量转置在计算机视觉中的应用

    计算机视觉(Computer Vision)是一门研究如何让计算机理解和理解图像和视频的科学。在过去的几十年里,计算机视觉已经取得了显著的进展,从简单的图像处理任务到复杂的视觉定位、目标识别和场景理解等复杂任务。向量转置(Vector Transpose)是一种常用的数学操作,在计算机视

    2024年02月20日
    浏览(36)
  • 一文搞懂隐私计算

    隐私计算(Privacy computing)是指在保证数据不对外泄露的前提下,由两个或多个参与方联合完成数据分析计算相关技术的统称。 隐私计算作为跨学科技术,以密码学为核心理论, 结合了大数据、人工智能、区块链等多领域知识。其这些技术路线中,以安全多方计算为代表的基

    2024年02月07日
    浏览(48)
  • 输入一个3×4的矩阵,计算并输出该矩阵的转置矩阵。(每个数据占三位,右对齐输出)

       三更灯火五更鸡,正是男儿读书时,咱们话不多说给小伙伴们带来这道题的解析和思路;   这道题让我们计算并输出该矩阵的转置矩阵,在这里我先向大家解释一下什么是 转置矩阵 根据这个图片不难看出每行的第一个变成了每列的第一个,简单一点说就是第一行的数字放

    2024年02月05日
    浏览(70)
  • 卷积计算加速方法--分块卷积

      当卷积的输入太大导致内存不够用时,考虑将一大块卷积分成多个小块分别进行卷积,相当于将原始输入分成几个小的输入经过同一组卷积核分别卷积,其中每块小的输入都是原始输入的子集,每块之间互不影响,最后将结果合并,实现分块卷积的输出结果与整个输入卷

    2024年02月11日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包