【Pytorch】Transposed Convolution

news2024/9/24 17:18:09

在这里插入图片描述

文章目录

  • 1 卷积
  • 2 反/逆卷积
  • 3 MaxUnpool / ConvTranspose
  • 4 encoder-decoder
  • 5 可视化

学习参考来自:

  • 详解逆卷积操作–Up-sampling with Transposed Convolution

  • PyTorch使用记录

  • https://github.com/naokishibuya/deep-learning/blob/master/python/transposed_convolution.ipynb

1 卷积

输入
在这里插入图片描述
卷积核

在这里插入图片描述

步长为 1,卷起来形式如下

在这里插入图片描述
输出的每个结果和输入的 9 个数值有关系

更直观的写成如下展开的矩阵乘形式

在这里插入图片描述

在这里插入图片描述
填零和 stride 与 kernel size 有关

2 反/逆卷积

相比逆卷积 (Deconvolution),转置卷积 (Transposed Convolution) 是一个更为合适的叫法

上述过程反过来,输入的一个数值与输出的 9 个数值有关

在这里插入图片描述

把原来的 W W W 转置一下即可实现该功能,当然转置后的 W W W 也是需要去学习更新的

在这里插入图片描述

矩阵乘可以看到,输入的每个值影响到了输出的 9 个值

3 MaxUnpool / ConvTranspose

搞个代码简单的看看效果

"maxpool"
m = nn.MaxPool2d(kernel_size=2, stride=2, padding=0, return_indices=True)
input_data = torch.tensor([[[
    [1, 2, 8, 7],
    [3, 4, 6, 5],
    [9, 10, 16, 15],
    [13, 14, 12, 11]
]]], dtype=torch.float32)
print(input_data.shape)  # torch.Size([1, 1, 4, 4])

out, indices = m(input_data)
print(out, "\n", indices)

output

tensor([[[[ 4.,  8.],
          [14., 16.]]]]) 
 tensor([[[[ 5,  2],
          [13, 10]]]])

在这里插入图片描述

"maxuppooling"
n = nn.MaxUnpool2d(kernel_size=2, stride=2, padding=0)
out = n(out, indices, output_size=input_data.size())
print(out)

output

tensor([[[[ 0.,  0.,  8.,  0.],
          [ 0.,  4.,  0.,  0.],
          [ 0.,  0., 16.,  0.],
          [ 0., 14.,  0.,  0.]]]])

在这里插入图片描述

在使用 MaxUnpool 的时候要特别注意, 需要在 maxpool 的时候保存 indices. 否则会报错

下面看看其在网络中的简单应用

import torch.nn as nn
import torch

"MaxUnpool"
class ConvDAE(nn.Module):
    def __init__(self):
        super().__init__()
        # input: batch x 3 x 32 x 32 -> output: batch x 16 x 16 x 16
        self.encoder = nn.Sequential(
            nn.Conv2d(3, 16, 3, stride=1, padding=1),  # batch x 16 x 32 x 32
            nn.ReLU(),
            nn.BatchNorm2d(16),
            nn.MaxPool2d(2, stride=2, return_indices=True)
        )
        self.unpool = nn.MaxUnpool2d(2, stride=2, padding=0)
        self.decoder = nn.Sequential(
            nn.ConvTranspose2d(16, 16, 3, stride=2, padding=1, output_padding=1),
            nn.ReLU(),
            nn.BatchNorm2d(16),
            nn.ConvTranspose2d(16, 3, 3, stride=1, padding=1, output_padding=0),
            nn.ReLU()
        )
    def forward(self, x):
        out, indices = self.encoder(x)  # torch.Size([1, 16, 16, 16])
        out = self.unpool(out, indices)  # torch.Size([1, 16, 32, 32])
        out = self.decoder(out)  # torch.Size([1, 3, 64, 64])
        return out
if __name__ == "__main__":
    DAE = ConvDAE()
    x = torch.randn((1, 3, 32, 32))
    DAE(x)

网络结构比较简单,encoder 降低图片分辨率至 1/2,通道数不变

unpool 反 max pooling 恢复图片分辨率

decoder 反卷积提升图片分辨率

4 encoder-decoder

再看一个稍微复杂的 encoder-decoder 结构

class autoencoder(nn.Module):
    def __init__(self):
        super(autoencoder, self).__init__()
        # -------
        # encode
        # -------
        self.encode1 = nn.Sequential(
            # 第一层
            nn.Conv1d(kernel_size=25, in_channels=1, out_channels=32, stride=1, padding=12), # (1,784)->(32,784)
            nn.BatchNorm1d(32), # 加上BN的结果
            nn.ReLU(),
            nn.MaxPool1d(kernel_size=3, stride=3, padding=1, return_indices=True), # (32,784)->(32,262)
        )
        self.encode2 = nn.Sequential(
            # 第二层
            nn.Conv1d(kernel_size=25, in_channels=32, out_channels=64, stride=1, padding=12), # (32,262)->(64,262)
            nn.BatchNorm1d(64),
            nn.ReLU(),
            nn.MaxPool1d(kernel_size=3, stride=3, padding=1, return_indices=True), # (batchsize,64,262)->(batchsize,64,88)
        )
        self.encode3 = nn.Sequential(
            nn.Linear(in_features=88*64, out_features=1024),
            nn.Linear(in_features=1024, out_features=30)
        )
        # -------
        # decode
        # -------
        self.unpooling1 = nn.MaxUnpool1d(kernel_size=3, stride=3, padding=1) # (batchsize,64,262)<-(batchsize,64,88)
        self.unpooling2 = nn.MaxUnpool1d(kernel_size=3, stride=3, padding=1) # (32,784)<-(32,262)
        self.decode1 = nn.Sequential(
            # 第一层
            nn.ReLU(),
            nn.BatchNorm1d(64),
            nn.ConvTranspose1d(kernel_size=25, in_channels=64, out_channels=32, stride=1, padding=12), # (32,262)<-(64,262)
        )
            # 第二层
        self.decode2 = nn.Sequential(
            nn.ReLU(),
            nn.BatchNorm1d(32), # 加上BN的结果
            nn.ConvTranspose1d(kernel_size=25, in_channels=32, out_channels=1, stride=1, padding=12), # (1,784)<-(32,784)
        )
        self.decode3 = nn.Sequential(
            nn.Linear(in_features=30, out_features=1024),
            nn.Linear(in_features=1024, out_features=88*64)
        )
    def forward(self, x):
        # encode
        x = x.view(x.size(0),1,-1) # 将图片摊平 torch.Size([1, 1, 784])
        x,indices1 = self.encode1(x) # 卷积层 torch.Size([1, 32, 262])
        x,indices2 = self.encode2(x) # 卷积层 torch.Size([1, 64, 88])
        x = x.view(x.size(0), -1) # 展开 torch.Size([1, 5632])
        x = self.encode3(x) # 全连接层 torch.Size([1, 30])
        # decode
        x = self.decode3(x) # torch.Size([1, 5632])
        x = x.view(x.size(0), 64, 88)  # torch.Size([1, 64, 88])
        x = self.unpooling1(x, indices2)  # torch.Size([1, 64, 262])
        x = self.decode1(x)  # torch.Size([1, 32, 262])
        x = self.unpooling2(x, indices1) # torch.Size([1, 32, 784])
        x = self.decode2(x)  # torch.Size([1, 1, 784])
        return x


if __name__ == "__main__":
    x = torch.randn((1, 1, 28, 28))
    autoencoder = autoencoder()
    autoencoder(x)

结构草图如下所示

请添加图片描述

主要展示的是 nn.ConvTransposenn.MaxUnpool 的运用,nn.MaxUnpool 要记得 indices

应用主要是 1d,2d 同理可以拓展

5 可视化

简单的实验,输入 MNIST 原始图片,conv+max pooling 下采样,maxunpooling+transposed conv 回原图,看看效果

载入相关库,载入数据集

import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
import numpy as np
import cv2
import matplotlib.pyplot as plt
# Device configuration
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# Hyper-parameters
num_epochs = 5
batch_size = 100
learning_rate = 0.001

# MNIST dataset
train_dataset = torchvision.datasets.MNIST(root='./',
                                           train=True,
                                           transform=transforms.ToTensor(),
                                           download=True)
test_dataset = torchvision.datasets.MNIST(root='./',
                                          train=False,
                                          transform=transforms.ToTensor())
# Data loader
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
                                           batch_size=batch_size,
                                           shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
                                          batch_size=batch_size,
                                          shuffle=False)

图像可视化的前期工作

def imshow(img):
    npimg = img.numpy()
    plt.imshow(np.transpose(npimg, (1, 2, 0)))

搭建神经网络,及其初始化

# 搭建网络
class CNNMNIST(nn.Module):
    def __init__(self):
        super(CNNMNIST,self).__init__()
        self.conv1 = nn.Conv2d(in_channels=1,out_channels=1,kernel_size=3,stride=1,padding=0)
        self.pool1 = nn.MaxPool2d(kernel_size=2,stride=2,padding=0,return_indices=True)
        self.unpool1 = nn.MaxUnpool2d(kernel_size=2,stride=2,padding=0)
        self.unconv1 = nn.ConvTranspose2d(in_channels=1, out_channels=1, kernel_size=3, stride=1, padding=0)
    def forward(self,x):
        # encode
        out = self.conv1(x)  # torch.Size([100, 1, 26, 26])
        out,indices = self.pool1(out)  # torch.Size([100, 1, 13, 13])
        # deocde
        out = self.unpool1(out,indices,output_size=out1.size())  # torch.Size([100, 1, 26, 26])
        out = self.unconv1(out)  # torch.Size([100, 1, 28, 28])
        return out

# 网络的初始化
model = CNNMNIST().to(device)
print(model)

output

CNNMNIST(
  (conv1): Conv2d(1, 1, kernel_size=(3, 3), stride=(1, 1))
  (pool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (unpool1): MaxUnpool2d(kernel_size=(2, 2), stride=(2, 2), padding=(0, 0))
  (unconv1): ConvTranspose2d(1, 1, kernel_size=(3, 3), stride=(1, 1))
)

网络训练与保存

# 定义优化器和损失函数
criterion = nn.MSELoss(reduction='mean')
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
# 进行训练
model.train()
total_step = len(train_loader)
for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(train_loader):
        # Move tensors to the configured device
        images = images.to(device)
        # Forward pass
        outputs = model(images)
        loss = criterion(outputs, images)
        # Backward and optimize
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        if (i+1) % 100 == 0:
            # 计算Loss
            print('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}'.format
                  (epoch+1, num_epochs, i+1, total_step, loss.item()))
                  
"save model"
torch.save(model, "model.pkl")

output

Epoch [1/5], Step [100/600], Loss: 0.0764
Epoch [1/5], Step [200/600], Loss: 0.0549
Epoch [1/5], Step [300/600], Loss: 0.0457
Epoch [1/5], Step [400/600], Loss: 0.0468
Epoch [1/5], Step [500/600], Loss: 0.0443
Epoch [1/5], Step [600/600], Loss: 0.0452
Epoch [2/5], Step [100/600], Loss: 0.0445
Epoch [2/5], Step [200/600], Loss: 0.0427
Epoch [2/5], Step [300/600], Loss: 0.0407
Epoch [2/5], Step [400/600], Loss: 0.0432
Epoch [2/5], Step [500/600], Loss: 0.0414
Epoch [2/5], Step [600/600], Loss: 0.0413
Epoch [3/5], Step [100/600], Loss: 0.0415
Epoch [3/5], Step [200/600], Loss: 0.0420
Epoch [3/5], Step [300/600], Loss: 0.0425
Epoch [3/5], Step [400/600], Loss: 0.0413
Epoch [3/5], Step [500/600], Loss: 0.0416
Epoch [3/5], Step [600/600], Loss: 0.0414
Epoch [4/5], Step [100/600], Loss: 0.0401
Epoch [4/5], Step [200/600], Loss: 0.0409
Epoch [4/5], Step [300/600], Loss: 0.0418
Epoch [4/5], Step [400/600], Loss: 0.0412
Epoch [4/5], Step [500/600], Loss: 0.0407
Epoch [4/5], Step [600/600], Loss: 0.0405
Epoch [5/5], Step [100/600], Loss: 0.0411
Epoch [5/5], Step [200/600], Loss: 0.0412
Epoch [5/5], Step [300/600], Loss: 0.0406
Epoch [5/5], Step [400/600], Loss: 0.0407
Epoch [5/5], Step [500/600], Loss: 0.0409
Epoch [5/5], Step [600/600], Loss: 0.0401

模型载入,可视化结果

"load model"
model = torch.load("model.pkl")

"visual"
dataiter = iter(train_loader)
images, lables = dataiter.next()

imshow(torchvision.utils.make_grid(images, nrow=10))
plt.show()

images = images.to(device)

# Forward pass
outputs = model(images)
imshow(torchvision.utils.make_grid(outputs.cpu().squeeze(0), nrow=10))
plt.show()

MNIST 多图的可视化,可以借鉴借鉴,核心代码为 torchvision.utils.make_grid

部分输入
请添加图片描述
部分输出
请添加图片描述

换成纯卷积的失真率更少

class CNNMNIST(nn.Module):
    def __init__(self):
        super(CNNMNIST,self).__init__()
        self.conv1 = nn.Conv2d(in_channels=1,out_channels=1,kernel_size=3,stride=1,padding=0)
        self.conv2 = nn.Conv2d(in_channels=1,out_channels=1,kernel_size=2,stride=2,padding=0)
        self.unconv1 = nn.ConvTranspose2d(in_channels=1, out_channels=1, kernel_size=2, stride=2, padding=0)
        self.unconv2 = nn.ConvTranspose2d(in_channels=1, out_channels=1, kernel_size=3, stride=1, padding=0)
    def forward(self,x):
        # encode
        out = self.conv1(x)  # torch.Size([100, 1, 26, 26])
		out = self.conv2(out)  # torch.Size([100, 1, 13, 13])
        # deocde
        out = self.unconv1(out)  # torch.Size([100, 1, 26, 26])
        out = self.unconv2(out)  # torch.Size([100, 1, 28, 28])
        return out

输入
请添加图片描述

输出
请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1312842.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DDD、SOA、微服务和微内核

DDD、SOA、微服务和微内核&#xff0c;看到经常有人把这几个概念拿出来一起讲。事实上&#xff0c;DDD和其他三个不是一个维度的东西。 DDD其实特别好理解&#xff0c;DDD就是领域来驱动设计嘛&#xff0c;是一种设计思想。很容易又和OOA、OOD和OOP来比较了。这个回头再说。 SO…

世微 AP9166 DC-DC降压IC 18V 2A同步降压转换器

600KHz&#xff0c;18V&#xff0c;2A同步降压转换器 概述 AP9166是一款完全集成的效率2A同步整流降压转换器。AP9166运行在宽输出电流上以高效率 负载范围。此设备提供两个操作模式、PWM控制和PFM模式切换控制&#xff0c;允许更宽范围的高效率 负载AP9166至少需要现成标准的…

JVM的内存分区以及垃圾收集

1.JVM的内存分区 1.1方法区 方法区(永久代&#xff09;主要用来存储已在虚拟机加载的类的信息、常量、静态变量以及即时编译器编译后的代码信息。该区域是被线程共享的。 1.2虚拟机栈 虚拟机栈也就是我们平时说的栈内存&#xff0c;它是为java方法服务的。每个方法在执行的…

mysql踩坑

关于安装 1报错&#xff1a;ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client具体代码如下&#xff1a; import mysql from "mysql"//连接数据库 const dbmysql.createPool({h…

计算机视觉技术在智慧城市建设中的应用

计算机视觉技术在智慧城市建设中的应用 随着城市化进程的不断推进&#xff0c;更多的人们选择在城市生活、工作和娱乐。面对快速增长的人口和日益复杂的城市环境&#xff0c;很多城市开始探索智慧城市的建设。智慧城市的核心就是将现代信息技术应用于城市管理中&#xff0c;以…

gitlab下载,离线安装

目录 1.下载 2.安装 3.配置 4.启动 5.登录 参考&#xff1a; 1.下载 根据服务器操作系统版本&#xff0c;下载对应的RPM包。 gitlab官网&#xff1a; The DevSecOps Platform | GitLab rpm包官网下载地址: gitlab/gitlab-ce - Results in gitlab/gitlab-ce 国内镜像地…

阿里云人工智能平台PAI多篇论文入选EMNLP 2023

近期&#xff0c;阿里云人工智能平台PAI主导的多篇论文在EMNLP2023上入选。EMNLP是人工智能自然语言处理领域的顶级国际会议&#xff0c;聚焦于自然语言处理技术在各个应用场景的学术研究&#xff0c;尤其重视自然语言处理的实证研究。该会议曾推动了预训练语言模型、文本挖掘、…

vue中element-ui日期选择组件el-date-picker 清空所选时间,会将model绑定的值设置为null 问题 及 限制起止日期范围

一、问题 在Vue中使用Element UI的日期选择组件 <el-date-picker>&#xff0c;当你清空所选时间时&#xff0c;组件会将绑定的 v-model 值设置为 null。这是日期选择器的预设行为&#xff0c;它将清空所选日期后将其视为 null。但有时后端不允许日期传空。 因此&#xff…

Java 线程运行方法和原理

线程运行 原理 栈与栈帧&#xff1a; Java 虚拟机栈会为每个启动的线程分配一块栈内存&#xff0c;其中存储着栈帧&#xff08;Frame&#xff09; 每个栈由多个栈帧组成&#xff0c;栈帧对应调用方法&#xff08;函数&#xff09;所占用的内存每个栈只有一个活动栈&#xf…

羊大师解读,血压波动

羊大师解读&#xff0c;血压波动 血压是身体健康的一个重要指标&#xff0c;但有时候我们会发现血压存在着波动的情况。血压波动的原因有很多&#xff0c;包括生活方式、遗传因素、药物影响等等。本文小编羊大师将为大家详细介绍血压波动的原因&#xff0c;以及预防和管理血压…

无脑利用API实现文心一言AI对话功能?(附代码)

前言&#xff1a;在当今数字化的时代&#xff0c;人工智能&#xff08;AI&#xff09;技术正在不断演进&#xff0c;为开发者提供了丰富的工具和资源。其中&#xff0c;API&#xff08;应用程序接口&#xff09;成为构建强大AI应用的关键组成部分之一。本文将介绍如何利用API来…

git的分支的使用,创建分支,合并分支,删除分支,合并冲突,分支管理策略,bug分支,强制删除分支

GIT | 分支 文章目录 GIT | 分支创建分支合并分支删除分支合并冲突分支管理策略bug分支强制删除分支 创建分支 查看当前本地仓库中有哪些分支 git branchHEAD所指向的分支就是当前正在工作的分支 cat .git/HEAD创建一个分支 git branch dev创建好了&#xff0c;但是目前还是…

计算机组成原理—中央处理器CPU

文章目录 CPU的功能与架构CPU的组成运算器控制器 指令执行过程指令流程指令执行方案 数据通路单总线结构专用通路结构 硬布线控制器设计硬布线执行流程硬布线CU内部怎么设计微操作的组合电路 总结 微程序控制器设计微程序的基本理念微程序的基本结构 微指令设计微程序CU设计 指…

使用代理IP时的并发请求是什么意思?

很多做过数据采集的技术们应该都有所了解&#xff0c;在选择代理IP时会有一个并发请求的参数&#xff0c;这个参数是什么意思呢&#xff1f;可能有很多新手不是很了解&#xff0c;其实代理IP的并发请求就是指同时发送多个请求到目标服务器&#xff0c;以提高请求的效率和速度。…

嵌入式系统挑战赛题目---递归方法实现字符串反转函数

一、题目要求 递归函数是一种在函数内容调用自身的函数。它通过将复杂的问题分解成更小的子问题来解决。递归函数通常包含两部分&#xff1a;基本情况和递归调用。请使用递归方法实现字符串反转的C语言函数。 请根据要求在begin、end间完成代码&#xff0c;不要改变代码中其他…

开具实习证明:在线实习项目介绍

大数据在线实习项目&#xff0c;是在线上为学生提供实习经验的项目。我们希望能够帮助想要在毕业后从事数据科学类工作的学生更加顺利地适应从教室到职场的转换&#xff1b;也帮助那些在工作中需要处理数据、实现数据价值的其他职能的从业者高效快速地掌握每天都能用起来的数据…

3、Kafka 线上集群部署方案怎么做?

文章目录 1、操作系统的选择1.1、I/O 模型的使用1.2、数据网络传输效率1.3、社区支持度 2、磁盘的选择3、磁盘容量的规划3.1、举例思考本问题&#xff1a;3.2、计算一下&#xff1a;3.3、规划磁盘容量时你需要考虑下面这几个元素&#xff1a; 4、带宽规划4.1、计算 总结 1、操作…

CSS基础面试题

介绍一下标准css盒子模型与低版本IE的盒子模型&#xff1f; 标准盒子模型&#xff1a;宽度内容的宽度&#xff08;content&#xff09; border padding margin 低版本IE盒子模型&#xff1a;宽度内容宽度&#xff08;contentborderpadding&#xff09; margin box-sizing 属性…

Java架构师-数据机构与算法实战(第一篇)

数学知识回顾 指数 指数函数是重要的基本初等函数之一。一般地&#xff0c;ya^x函数(a为常数且以a>0&#xff0c;a≠1)叫做指数函数&#xff0c;函数的定义域是 R 。注意&#xff0c;在指数函数的定义表达式中&#xff0c;在a^x前的系数必须是数1&#xff0c;自变量x必须在…

网易市值超过美团成为中国市值第四大互联网公司 |魔法半周报

我有魔法✨为你劈开信息大海❗ 高效获取AIGC的热门事件&#x1f525;&#xff0c;更新AIGC的最新动态&#xff0c;生成相应的魔法简报&#xff0c;节省阅读时间&#x1f47b; &#x1f525;资讯预览 网易市值超过美团成为中国市值第四大互联网公司 百度文心一言插件商城正式上…