转置卷积(Transposed Convolution)

2023-11-18


前言

转置卷积(Transposed Convolution) 在语义分割或者对抗神经网络(GAN)中比较常见,其主要作用就是做上采样(UpSampling)。在有些地方转置卷积又被称作fractionally-strided convolution或者deconvolution,但deconvolution具有误导性,不建议使用。对于转置卷积需要注意的是:

  • 转置卷积不是卷积的逆运算、不是逆运算、不是逆运算(重要的事情说三遍)
  • 转置卷积也是卷积

本文主要介绍转置卷积是如何计算的,关于转置卷积详细内容可以参考下面的文章:

不想看文章的可以看下我在bilibili上录的视频:


卷积操作

首先回顾下普通卷积,下图以stride=1,padding=0,kernel_size=3为例,假设输入特征图大小是4x4的(假设输入输出都是单通道),通过卷积后得到的特征图大小为2x2。一般使用卷积的情况中,要么特征图变小(stride > 1),要么保持不变(stride = 1),当然也可以通过四周padding让特征图变大但没有意义。关于卷积的详细介绍可以参考我之前的博文
在这里插入图片描述


转置卷积操作

转置卷积刚刚说了,主要作用就是起到上采样的作用。但转置卷积不是卷积的逆运算(一般卷积操作是不可逆的),它只能恢复到原来的大小(shape)数值与原来不同。转置卷积的运算步骤可以归为以下几步:

  • 在输入特征图元素间填充s-1行、列0(其中s表示转置卷积的步距)
  • 在输入特征图四周填充k-p-1行、列0(其中k表示转置卷积的kernel_size大小,p为转置卷积的padding,注意这里的padding和卷积操作中有些不同)
  • 将卷积核参数上下、左右翻转
  • 做正常卷积运算(填充0,步距1)

下面假设输入的特征图大小为2x2(假设输入输出都为单通道),通过转置卷积后得到4x4大小的特征图。这里使用的转置卷积核大小为k=3,stride=1,padding=0的情况(忽略偏执bias)。

  • 首先在元素间填充s-1=0行、列0(等于0不用填充)
  • 然后在特征图四周填充k-p-1=2行、列0
  • 接着对卷积核参数进行上下、左右翻转
  • 最后做正常卷积(填充0,步距1)

在这里插入图片描述

下图展示了转置卷积中不同s和p的情况:

s=1, p=0, k=3
s=2, p=0, k=3
s=2, p=1, k=3

转置卷积操作后特征图的大小可以通过如下公式计算:
H o u t = ( H i n − 1 ) × s t r i d e [ 0 ] − 2 × p a d d i n g [ 0 ] + k e r n e l _ s i z e [ 0 ] W o u t = ( W i n − 1 ) × s t r i d e [ 1 ] − 2 × p a d d i n g [ 1 ] + k e r n e l _ s i z e [ 1 ] H_{out} =(H_{in}-1) \times {\rm stride[0]} - 2 \times {\rm padding[0]}+ {\rm kernel \_ size[0]} \\ W_{out} =(W_{in}-1) \times {\rm stride[1]} - 2 \times {\rm padding[1]}+ {\rm kernel \_ size[1]} Hout=(Hin1)×stride[0]2×padding[0]+kernel_size[0]Wout=(Win1)×stride[1]2×padding[1]+kernel_size[1]
其中stride[0]表示高度方向的stride,padding[0]表示高度方向的padding,kernel_size[0]表示高度方向的kernel_size,索引[1]都表示宽度方向上的。通过上面公式可以看出padding越大,输出的特征矩阵高、宽越小,你可以理解为正向卷积过程中进行了padding然后得到了特征图,现在使用转置卷积还原到原来高、宽后要把之前的padding减掉。


Pytorch中的转置卷积参数

pytorch官方关于转置卷积ConvTranspose2d的文档:https://pytorch.org/docs/stable/generated/torch.nn.ConvTranspose2d.html

官方原话:
Applies a 2D transposed convolution operator over an input image composed of several input planes.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).

官方对转置卷积使用到的参数介绍:

在这里插入图片描述上面讲的例子中已经介绍了in_channels, out_channels, kernel_size, stride, padding这几个参数了,在官方提供的方法中还有:

  • output_padding:在计算得到的输出特征图的高、宽方向各填充几行或列0(注意,这里只是在上下以及左右的一侧one side填充,并不是两侧都填充,有兴趣自己做个实验看下),默认为0不使用。
  • groups:当使用到组卷积时才会用到的参数,默认为1即普通卷积。
  • bias:是否使用偏执bias,默认为True使用。
  • dilation:当使用到空洞卷积(膨胀卷积)时才会使用到的参数,默认为1即普通卷积。

输出特征图宽、高计算:
H o u t = ( H i n − 1 ) × s t r i d e [ 0 ] − 2 × p a d d i n g [ 0 ] + d i l a t i o n [ 0 ] × ( k e r n e l _ s i z e [ 0 ] − 1 ) + o u t p u t _ p a d d i n g [ 0 ] + 1 W o u t = ( W i n − 1 ) × s t r i d e [ 1 ] − 2 × p a d d i n g [ 1 ] + d i l a t i o n [ 1 ] × ( k e r n e l _ s i z e [ 1 ] − 1 ) + o u t p u t _ p a d d i n g [ 1 ] + 1 H_{out} =(H_{in}-1) \times {\rm stride[0]} - 2 \times {\rm padding[0]}+ {\rm dilation[0]} \times ({\rm kernel \_ size[0]}-1) + {\rm output\_padding[0]}+1 \\ W_{out} =(W_{in}-1) \times {\rm stride[1]} - 2 \times {\rm padding[1]}+ {\rm dilation[1]} \times ({\rm kernel \_ size[1]}-1) + {\rm output\_padding[1]}+1 Hout=(Hin1)×stride[0]2×padding[0]+dilation[0]×(kernel_size[0]1)+output_padding[0]+1Wout=(Win1)×stride[1]2×padding[1]+dilation[1]×(kernel_size[1]1)+output_padding[1]+1


Pytorch转置卷积实验

下面使用Pytorch框架来模拟s=1, p=0, k=3的转置卷积操作:
在这里插入图片描述

在代码中transposed_conv_official函数是使用官方的转置卷积进行计算,transposed_conv_self函数是按照上面讲的步骤自己对输入特征图进行填充并通过卷积得到的结果。

import torch
import torch.nn as nn


def transposed_conv_official():
    feature_map = torch.as_tensor([[1, 0],
                                   [2, 1]], dtype=torch.float32).reshape([1, 1, 2, 2])
    print(feature_map)
    trans_conv = nn.ConvTranspose2d(in_channels=1, out_channels=1,
                                    kernel_size=3, stride=1, bias=False)
    trans_conv.load_state_dict({"weight": torch.as_tensor([[1, 0, 1],
                                                           [0, 1, 1],
                                                           [1, 0, 0]], dtype=torch.float32).reshape([1, 1, 3, 3])})
    print(trans_conv.weight)
    output = trans_conv(feature_map)
    print(output)


def transposed_conv_self():
    feature_map = torch.as_tensor([[0, 0, 0, 0, 0, 0],
                                   [0, 0, 0, 0, 0, 0],
                                   [0, 0, 1, 0, 0, 0],
                                   [0, 0, 2, 1, 0, 0],
                                   [0, 0, 0, 0, 0, 0],
                                   [0, 0, 0, 0, 0, 0]], dtype=torch.float32).reshape([1, 1, 6, 6])
    print(feature_map)
    conv = nn.Conv2d(in_channels=1, out_channels=1,
                     kernel_size=3, stride=1, bias=False)
    conv.load_state_dict({"weight": torch.as_tensor([[0, 0, 1],
                                                     [1, 1, 0],
                                                     [1, 0, 1]], dtype=torch.float32).reshape([1, 1, 3, 3])})
    print(conv.weight)
    output = conv(feature_map)
    print(output)


def main():
    transposed_conv_official()
    print("---------------")
    transposed_conv_self()


if __name__ == '__main__':
    main()

终端输出:

tensor([[[[1., 0.],
          [2., 1.]]]])
Parameter containing:
tensor([[[[1., 0., 1.],
          [0., 1., 1.],
          [1., 0., 0.]]]], requires_grad=True)
tensor([[[[1., 0., 1., 0.],
          [2., 2., 3., 1.],
          [1., 2., 3., 1.],
          [2., 1., 0., 0.]]]], grad_fn=<SlowConvTranspose2DBackward>)
---------------
tensor([[[[0., 0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0., 0.],
          [0., 0., 1., 0., 0., 0.],
          [0., 0., 2., 1., 0., 0.],
          [0., 0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0., 0.]]]])
Parameter containing:
tensor([[[[0., 0., 1.],
          [1., 1., 0.],
          [1., 0., 1.]]]], requires_grad=True)
tensor([[[[1., 0., 1., 0.],
          [2., 2., 3., 1.],
          [1., 2., 3., 1.],
          [2., 1., 0., 0.]]]], grad_fn=<ThnnConv2DBackward>)

Process finished with exit code 0

通过对比能够发现,官方转置卷积的结果,和我们自己实现的转置卷积结果是一样的。对于其他的情况大家可以自己动手做做实验。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

转置卷积(Transposed Convolution) 的相关文章

  • PyTorch - 参数不变

    为了了解 pytorch 的工作原理 我尝试对多元正态分布中的一些参数进行最大似然估计 然而 它似乎不适用于任何协方差相关的参数 所以我的问题是 为什么这段代码不起作用 import torch def make covariance ma
  • Cuda和pytorch内存使用情况

    我在用Cuda and Pytorch 1 4 0 当我尝试增加batch size 我遇到以下错误 CUDA out of memory Tried to allocate 20 00 MiB GPU 0 4 00 GiB total c
  • pytorch通过易失性变量反向传播错误

    我试图通过多次向后传递迭代来运行它并在每个步骤更新输入 从而最小化相对于某个目标的一些输入 第一遍运行成功 但在第二遍时出现以下错误 RuntimeError element 0 of variables tuple is volatile
  • Pytorch:了解 nn.Module 类内部如何工作

    一般来说 一个nn Module可以由子类继承 如下所示 def init weights m if type m nn Linear torch nn init xavier uniform m weight class LinearRe
  • 为什么测试时一定要用DataParallel?

    在GPU上训练 num gpus设置为1 device ids list range num gpus model NestedUNet opt num channel 2 to device model nn DataParallel m
  • 在pytorch张量中过滤数据

    我有一个张量X like 0 1 0 5 1 0 0 1 2 0 我想实现一个名为的函数filter positive 它可以将正数据过滤成新的张量并返回原始张量的索引 例如 new tensor index filter positive
  • 一次热编码期间出现 RunTimeError

    我有一个数据集 其中类值以 1 步从 2 到 2 i e 2 1 0 1 2 其中 9 标识未标记的数据 使用一种热编码 self one hot encode labels 我收到以下错误 RuntimeError index 1 is
  • torch.mm、torch.matmul 和 torch.mul 有什么区别?

    阅读完 pytorch 文档后 我仍然需要帮助来理解之间的区别torch mm torch matmul and torch mul 由于我不完全理解它们 所以我无法简明地解释这一点 B torch tensor 1 1207 0 3137
  • pytorch 中的 keras.layers.Masking 相当于什么?

    我有时间序列序列 我需要通过将零填充到矩阵中并在 keras 中使用 keras layers Masking 来将序列的长度固定为一个数字 我可以忽略这些填充的零以进行进一步的计算 我想知道它怎么可能在 Pytorch 中完成 要么我需要
  • 使 CUDA 内存不足

    我正在尝试训练网络 但我明白了 我将批量大小设置为 300 并收到此错误 但即使我将其减少到 100 我仍然收到此错误 更令人沮丧的是 在 1200 个图像上运行 10 epoch 大约需要 40 分钟 有什么建议吗 错了 我怎样才能加快这
  • 如何计算 CNN 第一个线性层的维度

    目前 我正在使用 CNN 其中附加了一个完全连接的层 并且我正在使用尺寸为 32x32 的 3 通道图像 我想知道是否有一个一致的公式可以用来计算第一个线性层的输入尺寸和最后一个卷积 最大池层的输入 我希望能够计算第一个线性层的尺寸 仅给出
  • 将 Keras (Tensorflow) 卷积神经网络转换为 PyTorch 卷积网络?

    Keras 和 PyTorch 使用不同的参数进行填充 Keras 需要输入字符串 而 PyTorch 使用数字 有什么区别 如何将一个转换为另一个 哪些代码在任一框架中获得相同的结果 PyTorch 还采用参数 in channels o
  • Pytorch Tensor 如何获取元素索引? [复制]

    这个问题在这里已经有答案了 我有 2 个名为x and list它们的定义如下 x torch tensor 3 list torch tensor 1 2 3 4 5 现在我想获取元素的索引x from list 预期输出是一个整数 2
  • pytorch 的 IDE 自动完成

    我正在使用 Visual Studio 代码 最近尝试了风筝 这两者似乎都没有 pytorch 的自动完成功能 这些工具可以吗 如果没有 有人可以推荐一个可以的编辑器吗 谢谢你 使用Pycharmhttps www jetbrains co
  • PyTorch 中的连接张量

    我有一个张量叫做data形状的 128 4 150 150 其中 128 是批量大小 4 是通道数 最后 2 个维度是高度和宽度 我有另一个张量叫做fake形状的 128 1 150 150 我想放弃最后一个list array从第 2 维
  • PyTorch 中的交叉熵

    交叉熵公式 但为什么下面给出loss 0 7437代替loss 0 since 1 log 1 0 import torch import torch nn as nn from torch autograd import Variable
  • Pytorch 与 joblib 的 autograd 问题

    将 pytorch 的 autograd 与 joblib 混合似乎存在问题 我需要并行获取大量样本的梯度 Joblib 与 pytorch 的其他方面配合良好 但是 与 autograd 混合时会出现错误 我做了一个非常小的例子 显示串行
  • 样本()和r样本()有什么区别?

    当我从 PyTorch 中的发行版中采样时 两者sample and rsample似乎给出了类似的结果 import torch seaborn as sns x torch distributions Normal torch tens
  • TensorFlow 相当于 PyTorch 的 Transforms.Normalize()

    我正在尝试推断最初在 PyTorch 中构建的 TFLite 模型 我一直在遵循PyTorch 实现 https github com leoxiaobin deep high resolution net pytorch blob 1ee
  • BertForSequenceClassification 是否在 CLS 向量上进行分类?

    我正在使用抱脸变压器 https huggingface co transformers index html使用 PyTorch 打包和 BERT 我正在尝试进行 4 向情感分类并正在使用BertFor序列分类 https hugging

随机推荐

  • String类详解

    目录 一 创建字符串的四种方式 1 直接赋值 2 通过构造方法创建对象 3 通过字符数组创建对象 4 通过String类的静态方法valueOf 任意数据类型 gt 转为字符串 二 字符串比较相等 equals方法 equalsIgnore
  • ICMP协议Ping方法的Python实现解析

    ICMP协议Ping方法的Python实现解析 说明 本代码适合Windows 没有在其他系统下进行测试 参考对象为https github com samuel python ping 流程 选择目标网址 解析对方ip地址 构造数据报 添
  • KVM 虚拟机的热迁移

    热迁移 顾名思义在虚拟机不关机的情况下将KVM虚拟机进行迁移 准备工作 两台KVM虚拟机 一台nfs虚拟机 centos7 4系统 主机 IP地址 主机名 KVM01 10 00 11 kvm01 KVM02 10 0 0 12 kvm02
  • SSM简单项目

    暑假项目实训花了2个星期做的项目 前台完成了大部分 后台做了一点点 其中主要运用了ssm框架技术 layui前端技术 拦截器 阿里云支付宝接口 阿里云短信验证接口 layui轮播图 流加载 分页 表单 表格等技术 访问网站 http www
  • 明智而审慎地使用多重继承——条款40

    当多重继承 multiple inheritance MI 进入设计景框 程序有可能从一个以上的base classes继承相同名称 如函数 typedef等等 那会导致较多的歧义机会 例如 class BorrowableItem 图书馆
  • 《unix环境高级编程》--- 进程环境

    终止码 main中返回一个整型值与用该值调用exit是等价的 include
  • jemalloc C++实践

    jemalloc是一种通用的malloc 3 实现 优点是避免内存碎片和可伸缩并发支持 下载源码 wget https github com jemalloc jemalloc releases download 5 2 1 jemallo
  • IA-YOLO项目中DIP模块的初级解读

    IA YOLO项目源自论文Image Adaptive YOLO for Object Detection in Adverse Weather Conditions 其提出端到端方式联合学习CNN PP和YOLOv3 这确保了CNN PP
  • mysql篇---windows环境

    1 windows环境下的mysql忘记密码了会很麻烦 试了好多种攻略都不行 只得重装 所以安装好后 要找个记事本写root密码 2 如果重装的话 直接到mysql官网 下载最新版 https dev mysql com downloads
  • 区块链:如何学习区块链技术?

    To strive to seek to find and not to yield 奋斗 探索 寻求 永不屈服 1 中本聪的关于比特币的白皮书 英文原版 Bitcoin A Peer to Peer Electronic Cash Sys
  • c++用vector先按学生的年级排序,再按学生的分数排序算法

    VectorSort cpp 定义控制台应用程序的入口点 include stdafx h include stdio h include string h include
  • PDF各种编辑方法(页码重排、解密、导入书签、导入注释、合并)

    目录 一 PDF重排页码 二 PDF解密 三 PDF导入和导出书签 四 PDF导入和导出注释 五 PDF合并 一 PDF重排页码 操作流程 如下图所示 打开 福昕高级PDF编辑器 gt 打开待处理的PDF文件 gt 点击软件界面左侧第二个图
  • js循环数组实现模糊匹配

  • Linux 下rm删除命令提示 /bin/rm: argument list too long的解决办法

    假设我们要删除文件夹test test下有很多文件 如果我们使用rm test 命令进行删除 则会出现 bin rm argument list too long无法删除的报错提示 报错提示原因 文件夹下的文件数目过多 命令行过长所致 解决
  • vue项目中引入高德地图

    近期在用vue做一个环保类的项目 要求使用高德地图 原生js api官方案例比较多 对于新手友好 但是在vue项目中加载是一个难以解决的问题 而专门为vue使用高德地图诞生的 vue AMap 组件听起来很美好 但由于需要学习高德原生语法和
  • Redis基础数据结构——有序集合

    Redis基础数据结构 有序集合 redis的有序集合zset类似于Java的SoretedSet和HashMap的结合体 一方面它是一个set 可以保证内部value的唯一性 另一方面它可以给每个value赋予一个score 代表这个sc
  • 100天精通Python(进阶篇)——第36天:Python读写XML文件

    文章目录 一 XML基础概述 1 XML是什么 2 XML的特点及作用 3 XML文件格式 二 Python解析XML文件 1 ElementTree 方式 2 DOM 方式 三 Python写入XML文件 四 Python更新XML文件
  • 硬刚ChatGPT!文心一言能否为百度止颓?中国版ChatGPT“狂飙”的机会在哪儿?

    虽然 ChatGPT 在我的生活中已经出现很久了 但最近我才慢慢跟上了新时代的步伐 今天我想借此话题简单地分享一下OpenAi的看法 以下回答来自ChatGPT的回答 文心一言能否为百度止颓 文心一言是一种文学创作技法 可以用于表达思想感情
  • SSD目标检测流程深入理解

    前言 SSD是经典的一阶目标检测网络框架 特点是速度快 网络简洁 主要思想 1 数据增强 包括光学变换和几何变换 2 网络骨架 SSD在VGG基础上延伸了4个卷积模块 生成不同尺度的特征图 3 PriorBox与多层特征图 在不同尺度设置预
  • 转置卷积(Transposed Convolution)

    文章目录 前言 卷积操作 转置卷积操作 Pytorch中的转置卷积参数 Pytorch转置卷积实验 前言 转置卷积 Transposed Convolution 在语义分割或者对抗神经网络 GAN 中比较常见 其主要作用就是做上采样 UpS