PyTorch 中的转置卷积 ConvTranspose2d

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

convtranspose2d,# Pytorch实践,pytorch,深度学习,cnn,计算机视觉,神经网络

PyTorch 中的转置卷积 ConvTranspose2d

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

torch.nn.ConvTranspose2d(in_channels, out_channels, kernel_size, stride=1, padding=0, output_padding=0, groups=1, bias=True, dilation=1, padding_mode='zeros', device=None, dtype=None)

This module can be seen as the gradient of Conv2d with respect to its input. It is also known as a fractionally-strided convolution or a deconvolution (although it is not an actual deconvolution operation as it does not compute a true inverse of convolution). For more information, see the visualizations here and the Deconvolutional Networks paper.

这里面涉及到了多个参数,包括 in_channels, out_channels, kernel_size, groups=1, bias=True, dilation=1, padding_mode='zeros', device=None, dtype=None 这样的一看就可以理解对的参数,也有一些实际情况和我们想的并不一致的参数 stride=1, padding=0, output_padding=0

首先要明确的一点,由于转置卷积可以看做是标准卷积的相反流程(虽然细节处理不同,并非真正的转置),考虑到标准卷积的直观性,所以我们可以从对应的标准卷积的角度去理解转置卷积的参数含义。即反着来看参数的作用。对于相同的参数设置,转置卷积输出和输出的形状,一般与标准卷积的输入和输出一致。

对于 2d 形式,我们分别设置 kernel_size, stride, padding, output_padding k , s , p , p o k, s, p, p_o k,s,p,po

  • 输入形状为 ( N , C i , H i , W i ) (N, C_i, H_i, W_i) (N,Ci,Hi,Wi) 或者为 ( C i , H i , W i ) (C_i, H_i, W_i) (Ci,Hi,Wi)
  • 输出形状为 ( N , C o , H o , W o ) (N, C_o, H_o, W_o) (N,Co,Ho,Wo) 或者为 ( C o , H o , W o ) (C_o, H_o, W_o) (Co,Ho,Wo)
  • 卷积权重形状为 ( C i , C o / / G , k [ 0 ] , k [ 1 ] ) (C_i, C_o//G, k[0], k[1]) (Ci,Co//G,k[0],k[1])
  • 卷积偏置形状为 ( C o ) (C_o) (Co)
  • H o = ( H i − 1 ) × s [ 0 ] − 2 p [ 0 ] + d [ 0 ] × ( k [ 0 ] − 1 ) + p o [ 0 ] + 1 H_o = (H_i - 1) \times s[0] - 2p[0] + d[0] \times (k[0] - 1) + p_o[0] + 1 Ho=(Hi1)×s[0]2p[0]+d[0]×(k[0]1)+po[0]+1
  • W o = ( W i − 1 ) × s [ 1 ] − 2 p [ 1 ] + d [ 1 ] × ( k [ 1 ] − 1 ) + p o [ 1 ] + 1 W_o = (W_i - 1) \times s[1] - 2p[1] + d[1] \times (k[1] - 1) + p_o[1] + 1 Wo=(Wi1)×s[1]2p[1]+d[1]×(k[1]1)+po[1]+1

转置卷积的过程

总体而言,结合对应的标准卷积,转置卷积的计算可以拆分为两部分:调整形状和局部聚合。这里的介绍可以结合 A guide to convolution arithmetic for deep learning 中提供的图示进行理解。

k = 3 , s = 1 , p = 0 k=3,s=1,p=0 k=3,s=1,p=0 k = 3 , s = 2 , p = 0 k=3,s=2,p=0 k=3,s=2,p=0
convtranspose2d,# Pytorch实践,pytorch,深度学习,cnn,计算机视觉,神经网络 convtranspose2d,# Pytorch实践,pytorch,深度学习,cnn,计算机视觉,神经网络
k = 4 , s = 1 , p = 2 k=4,s=1,p=2 k=4,s=1,p=2 k = 3 , s = 1 , p = 1 k=3,s=1,p=1 k=3,s=1,p=1
convtranspose2d,# Pytorch实践,pytorch,深度学习,cnn,计算机视觉,神经网络 convtranspose2d,# Pytorch实践,pytorch,深度学习,cnn,计算机视觉,神经网络
k = 3 , s = 2 , p = 1 k=3,s=2,p=1 k=3,s=2,p=1 k = 3 , s = 2 , p = 1 , p o = 1 k=3,s=2,p=1,p_o=1 k=3,s=2,p=1,po=1
convtranspose2d,# Pytorch实践,pytorch,深度学习,cnn,计算机视觉,神经网络 convtranspose2d,# Pytorch实践,pytorch,深度学习,cnn,计算机视觉,神经网络

调整形状

实际上,转置卷积最难理解的还是这一步。

对输入使用 stride 处理,注意,转置卷积的 stride 并不同于标准卷积,而是在各个输入元素之间插入 s − 1 s-1 s1 个 0。这样的设定,可以使得转置卷积的输入数据,就像是转置卷积的输出数据通过标准卷积经过这样的 stride 滑动后得到的一样。那些转置卷积的输入数据中间插进去的 0,实际上就是这种标准卷积因为步长的设定而被跳过的输出。

而且另外一点需要注意,为了确保对卷积输入输出运算过程形状的对应性,所以 在卷积核滑动之前,须要在输入的四边上进行 padding,这里默认 padding 的值与卷积核的形状有关,即四边的 padding 为 ( k [ 0 ] − 1 , k [ 1 ] − 1 , k [ 0 ] − 1 , k [ 1 ] − 1 ) (k[0]-1, k[1]-1, k[0]-1, k[1]-1) (k[0]1,k[1]1,k[0]1,k[1]1)

这里需要强调的是,不论如何,转置卷积的本质还是卷积,仍然是对输入的局部聚合。所以如果不考虑 padding 和插 0 的情况,输出必然要比输入的尺寸要小。

所以当 s = ( 1 , 1 ) s=(1,1) s=(1,1) 的时候,输入需要 padding 才能够实现输出尺寸的增大。

  1. p [ ⋆ ] = 0 p[\star]=0 p[]=0:这是转置卷积的默认情况,此时转置卷积会对输入进行隐式的 padding,如前所述为 ( k [ 0 ] − 1 , k [ 1 ] − 1 , k [ 0 ] − 1 , k [ 1 ] − 1 ) (k[0]-1, k[1]-1, k[0]-1, k[1]-1) (k[0]1,k[1]1,k[0]1,k[1]1)
  2. p [ ⋆ ] > 1 p[\star] > 1 p[]>1:相当于是标准卷积 p [ ⋆ ] > 1 p[\star] > 1 p[]>1 的时候。在其他参数不变的时候,标准卷积的输出会相对扩大,对应回来,也就是转置卷积的输出应该相对缩小。于是我们可以看到, p p p 实际上起到一个反向调整的作用,即在默认的隐式 padding 上减去转置卷积设置中的 p p p。因而实际的隐式 padding 会变为 ( k [ 0 ] − 1 − p [ 0 ] , k [ 1 ] − 1 − p [ 1 ] , k [ 0 ] − 1 − p [ 0 ] , k [ 1 ] − 1 − p [ 1 ] ) (k[0]-1-p[0], k[1]-1-p[1], k[0]-1-p[0], k[1]-1-p[1]) (k[0]1p[0],k[1]1p[1],k[0]1p[0],k[1]1p[1])

[!important] p p p 的取值范围
结合上面的推理,进一步可以推测出转置卷积中对 p p p 的限制。

  • 首先必须大于等于 0,所以左边界为 0。
  • 对于右侧边界,必须要保证一点,即经过默认 padding 调整后的输入,在使用 p p p 剪裁后剩下的必须大于等于 k [ 0 ] × k [ 1 ] k[0] \times k[1] k[0]×k[1],也就是卷积操作必须有效。所以可以推算出,最大值为 k [ 0 ] − 1 + ( H i − k [ 0 ] ) / / 2 k[0]-1+(H_i-k[0])//2 k[0]1+(Hik[0])//2 k [ 1 ] − 1 + ( W i − k [ 1 ] ) / / 2 k[1]-1+(W_i-k[1])//2 k[1]1+(Wik[1])//2

[!questions] 操作顺序
此处可能有一个问题,究竟是“先将隐式 padding 使用 p p p 处理后再卷积?”还是“先基于默认隐式 padding 卷积后再使用 p p p 来剪裁数据?”从实际效果上来看二者是一样的。所以问题不大。

这里有一个额外的参数 p o p_o po 也非常重要。在原始文档中提到,这一参数主要的用处是为了保证在 s [ ⋆ ] > 0 s[\star]>0 s[]>0 的时候可以在形状上对齐标准卷积

对于标准卷积而言,如果 s [ ⋆ ] > 0 s[\star]>0 s[]>0,则同一种输出形状可以存在多种输入相形状。所以转置卷积通过用户指定的参数来消除这种不确定性,从而明确输出形状的具体尺寸。如果输出形状不合适,可以使用这一参数来进行单边的补齐。注意,这一参数仅是作用于单边,对于 2D 情况,在 H 和 W 轴的末端上补 0。

另外,虽然文档提到“Note that output_padding is only used to find output shape, but does not actually add zero-padding to output.”,但是从实际效果来看,就是 0 的补齐,文档这一句话应该是在强调内部实现并非直接补 0。

局部聚合

使用卷积核在插 0 后的输入上滑动从而获得初步的输出。要注意,这里的 stride 参数并不会影响转置卷积本身卷积核的滑动,可以认为转置卷积核步长始终为 1。

使用标准卷积实现转置卷积

如果单纯使用框架自带的卷积函数,标准卷积只能实现 s = 1 s=1 s=1 的转置卷积。而且在使用相同的卷积参数的时候,需要注意的是卷积权重的索引顺序。从 PyTorch 中的转置卷积详解——全网最细 中我们可以知道,如果使用相同的卷积权重,标准卷积与转置卷积的权重索引方式不同,需要进行 .flip(dim=*) 来调整。

典型案例为:

# 1-D
In [59]: a = torch.arange(0, 3, 1).float().reshape(1, 1, 3)

In [60]: b = torch.arange(3, 6, 1).float().reshape(1, 1, 3)

In [65]: F.conv_transpose1d(a, b, stride=1, padding=0, output_padding=0)
Out[65]: tensor([[[ 0.,  3., 10., 13., 10.]]])

In [66]: F.conv1d(a, b.transpose(0, 1).flip(-1), stride=1, padding=2)
Out[66]: tensor([[[ 0.,  3., 10., 13., 10.]]])

# 2-D
In [67]: a = torch.arange(0, 9, 1).float().reshape(1, 1, 3, 3)

In [68]: b = torch.arange(3, 12, 1).float().reshape(1, 1, 3, 3)

In [69]: F.conv_transpose2d(a, b, stride=1, padding=0, output_padding=0)
Out[69]:
tensor([[[[  0.,   3.,  10.,  13.,  10.],
          [  9.,  30.,  65.,  62.,  41.],
          [ 36.,  99., 192., 165., 102.],
          [ 63., 150., 263., 206., 119.],
          [ 54., 123., 208., 157.,  88.]]]])

In [71]: F.conv2d(a, b.transpose(0, 1).flip(-1).flip(-2), stride=1, padding=2)
Out[71]:
tensor([[[[  0.,   3.,  10.,  13.,  10.],
          [  9.,  30.,  65.,  62.,  41.],
          [ 36.,  99., 192., 165., 102.],
          [ 63., 150., 263., 206., 119.],
          [ 54., 123., 208., 157.,  88.]]]])

[!important] 标准卷积与转置卷积共用权重需要注意的地方
PyTorch 中标准卷积与转置卷积的权重形状中,输入输出维度恰好相反,所以相同的权重需要进行额外交换轴的操作,即上面代码中 .transpose(0, 1) 处理。文章来源地址https://www.toymoban.com/news/detail-585154.html

参考链接

  • PyTorch 中的转置卷积详解——全网最细
  • 官方文档
  • A guide to convolution arithmetic for deep learning

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

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

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

相关文章

  • 矩阵的转置T和共轭转置H

    矩阵 G G G 的转置 G T G^T G T 和共轭转置 G H G^H G H 在数学中表示不同的操作: 转置 G T G^T G T : 转置是指将矩阵的行和列互换得到的新矩阵。 对于实数矩阵,转置是指将矩阵中的行变为相应的列。 对于复数矩阵,转置同样是将矩阵中的行变为相应的列。 在转置中,并不改变矩

    2024年02月03日
    浏览(42)
  • 矩阵的转置

    题目: 给你一个二维整数数组 matrix , 返回 matrix 的 转置矩阵 。 示例 1:

    2024年02月12日
    浏览(30)
  • 【python】python求解矩阵的转置(详细讲解)

    👉博__主👈:米码收割机 👉技__能👈:C++/Python语言 👉公众号👈:测试开发自动化【获取源码+商业合作】 👉荣__誉👈:阿里云博客专家博主、51CTO技术博主 👉专__注👈:专注主流机器人、人工智能等相关领域的开发、测试技术。 求一个矩阵的转置 示例1: 输入:[[1, 2

    2024年02月06日
    浏览(33)
  • C++数据结构 矩阵的转置、镜像及旋转

    C++ 中的矩阵是一种二维数组,用于存储数值数据。矩阵可以用于存储图像数据,以及科学和工程计算中的数据。 常用于以下场景: 数学运算:矩阵乘法、行列式计算、特征值分解等。 图像处理:图像缩放、旋转、颜色变换等。 矩阵分析:因子分析、主成分分析、协方差分

    2024年02月11日
    浏览(41)
  • C语言:写一个函数,实现3*3矩阵的转置(指针)

    分析:     在主函数 main 中,定义一个 3x3 的整型数组 a,并定义一个指向整型数组的指针 p。然后通过循环结构和 scanf 函数,从标准输入中读取用户输入的 3x3 矩阵的值,并存储到数组 a 中。     接下来,调用 move 函数,传递给它整型数组 a 的地址,即 a 数组的首地址。

    2024年02月05日
    浏览(33)
  • C语言之实现矩阵(3行3列)的转置(即行列互换)

    例如:输入下面的矩阵: 100 200 300 400 500 600 700 800 900 程序输出: 100 400 700 200 500 800 300 600 900 代码如下所示: 输出结果如下所示:

    2024年02月11日
    浏览(64)
  • 数据结构·练习·三元组表法实现稀疏矩阵的转置

    一、问题描述 一个mxn的矩阵A,它的转置矩阵B是一个nxm矩阵,且A[i][j]=B[j][i],0=i=m-1,0=j=n-1,即A的行是B的列,A的列是B的行。 用三元组表对稀疏矩阵进行压缩存储,再进行时间复杂度O(n)的快速转置,最后输出稀疏矩阵。 其中m=4,n=5 二、算法概述 1、问题分析 1)压缩 2)转置

    2024年02月04日
    浏览(35)
  • 5.利用matlab完成 符号矩阵的转置和 符号方阵的幂运算(matlab程序)

    1. 简述        Matlab符号运算中的矩阵转置 转置向量或矩阵 B = A.\\\' B = transpose(A) 说明 B = A.\\\' 返回 A 的非共轭转置,即每个元素的行和列索引都会互换。如果 A 包含复数元素,则 A.\\\' 不会影响虚部符号。例如,如果 A(3,2) 是 1+2i 且 B = A.\\\',则元素 B(2,3) 也是 1+2i。 B = transpose(A) 是执

    2024年02月13日
    浏览(31)
  • 反卷积通俗详细解析与nn.ConvTranspose2d重要参数解释

    传统的卷积通常是将大图片卷积成一张小图片,而反卷积就是反过来,将一张小图片变成大图片 。 但这有什么用呢?其实有用,例如,在生成网络(GAN)中,我们是给网络一个向量,然后生成一张图片 所以我们需要想办法把这个向量一直扩,最终扩到图片的的大小。 在了解反

    2024年02月02日
    浏览(33)
  • MATLAB:矩阵 矩阵的秩,矩阵的逆矩阵,矩阵的转置,矩阵每个元素减一,矩阵元素变换

    1.矩阵 A=[1,2,3;4,5,6;7,8,9]/A=[1 2 3;4 5 6;7 8 9](分号与空格用于区分每行之间的元素,分号区分行)   2.矩阵每个元素减一 B=A-1 3.矩阵元素变换 需要某一行或者某一列为0,可以用“:”代表一行 如A(:,3)代表第三列赋值为零    A( 3,:)代表第三行赋值为零     4.矩阵的秩

    2024年02月11日
    浏览(39)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包