【Pytorch】Transposed Convolution

在这里插入图片描述

文章目录

  • 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

输入
请添加图片描述

输出
请添加图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【改进YOLOv8】车辆测距预警系统:融合空间和通道重建卷积SCConv改进YOLOv8

1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 研究背景与意义&#xff1a; 随着交通工具的普及和道路交通的不断增加&#xff0c;车辆安全问题日益凸显。特别是在高速公路等高速道路上&#xff0c;车辆之间的距离和速度差异较…

java-两个列表进行比较,判断那些是需要新增的、删除的、和更新的

文章目录 前言两个列表进行比较&#xff0c;判断那些是需要新增的、删除的、和更新的 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&#xff0c;实…

计算机网络编程 | 并发服务器代码实现(多进程/多线程)

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…

深入了解空号检测API:提升通信效率的关键

引言 随着通信技术的不断发展&#xff0c;人们对于通信效率的要求也越来越高。在通信过程中&#xff0c;空号检测是一个非常重要的环节&#xff0c;它可以帮助我们避免无效的通信&#xff0c;提高通信效率。而空号检测API则是实现空号检测功能的重要工具。 空号检测API 空号…

Seata Server与Nacos Server搭建(商城7)

一、Nacos简介 &#xff08;一&#xff09;Nacos是什么 1、Nacos是 Dynamic Naming and Configuration Service的首字母简称&#xff0c;相较之下&#xff0c;它更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。 2、Nacos 帮助您发现、配置和管理微服务。Nacos…

【seata】 seata整合nacos + springcloud alibaba 真保姆级教程 解决各种坑点

前言&#xff1a; 坑点太多了&#xff0c;以至于需要单独写篇博客记录一下。 网上教程五花八门且不声明版本&#xff0c;文档不对应以及seata本身的bug&#xff0c;就造成了部署时各种踩坑&#xff0c;如果你和博主一样&#xff0c;已经又恰好很久没碰过nacos了&#xff0c;那可…

pandas读取Excel表指定数值 计算总和

题目要求&#xff1a;在一个文件夹里面有424个Excel表格&#xff0c;每个表格中都是统一的&#xff0c;如下图。要求计算所有表格中金额的总和。 上代码&#xff1a; import os import glob import pandas as pd# 指定文件夹路径 folder_path C:\\Users\\Administrator\\Desk…

Java—基于SpringBootWeb的综合小案例(智能学习辅助系统)

简介&#xff1a;这篇帖子是小编在看哔哩哔哩网课是的一个小案例&#xff0c;来自于黑马程序员&#xff0c;我觉得他们的课讲的很好&#xff0c;而且这个案例很有实用性&#xff0c;就在看视频的基础上&#xff0c;边温故知新&#xff0c;边实现了这个代码&#xff0c;在一些重…

Three.js中文网1-12入门案例

Three.js中文网 <template><div id"webgl"></div> </template><script setup> import * as THREE from three; import { OrbitControls } from three/addons/controls/OrbitControls.js;// 创建3D场景对象Scene const scene new THR…

【Axure RP9】动态面板使用------案例:包括轮播图和多方式登入及左侧菜单栏案例

目录 一 动态面板简介 1.1 动态面板是什么 二 轮播图 2.1 轮播图是什么 2.2 轮播图应用场景 2.3 制作实播图 三 多方式登入 3.1多方式登入是什么 3.3 多方式登入实现 四 左侧菜单栏 4.1左侧菜单栏是什么 4.2 左侧菜单栏实现 一 动态面板简介 1.1 动态面板是什么…

配置VRRP负载分担示例

一、组网需求&#xff1a; HostA和HostC通过Switch双归属到SwitchA和SwitchB。为减轻SwitchA上数据流量的承载压力&#xff0c;HostA以SwitchA为默认网关接入Internet&#xff0c;SwitchB作为备份网关&#xff1b;HostC以SwitchB为默认网关接入Internet&#xff0c;SwitchA作为…

【教程】从零开始的ORB-SLAM3的安装与配置

引言 最近项目需求需要接触vslam&#xff0c;博主选择从ORB-SLAM3下手并且记录下安装的基本流程。不得不说&#xff0c;这安装流程就像二大娘的裹脚布。 大致环境前提&#xff1a;Ubuntu20.04 一、ORB-SLAM3的源码下载 1、首先&#xff0c;为了方便管理文件&#xff0c;我们…

【infiniband】ibdump抓包

ibdump用于捕获和转储InfiniBand网络的流量。 这种工具通常用于调试和分析InfiniBand网络问题&#xff0c;包括性能瓶颈和配置错误。ibdump工具在Mellanox InfiniBand环境中较为常用&#xff0c;现由NVIDIA提供支持。 使用ibdump的基本步骤 请注意&#xff0c;您需要在安装了…

MATLAB六轴机械臂机器人的动力学分析

1、概述 动力学以牛顿第二定律为核心&#xff0c;这个定律指出了力、加速度、质量三者间的关系。 质点动力学有两类基本问题&#xff1a; 一是已知作用于质点上的力&#xff0c;求质点的运动&#xff0c;这个就是正动力学。 二是已知质点的运动&#xff0c;求作用于质点上的力…

SpringMVC-02

SpringMVC-02 SSM 框架集成与测试环境配置添加源代码 SSM 框架集成与测试 环境配置 IDEA 下创建项⽬ 创建Maven对应的Web项⽬ 配置 pom.xml 2.1. 修改 JDK 版本 <properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><mav…

【Matlab】如何使用MATLAB可视化二重积分(附完整MATLAB代码)

可视化二重积分 前言正文完整代码代码实现可视化结果 前言 二重积分是指在二维空间中对函数进行积分。二重积分的公式如下&#xff1a; ∫ a b ∫ c d f ( x , y ) d x d y ∫_a^b ∫_c^d f(x, y) dx dy ∫ab​∫cd​f(x,y)dxdy 其中&#xff0c; a a a 和 b b b 是 x x x…

maven打包插件maven-jar-plugin与spring-boot-maven-plugin

maven几种打包插件介绍 文章目录 &#x1f50a;1.spring-boot-maven-plugin打包后效果 &#x1f4d5;2.maven-jar-plugin打包后效果&#x1f58a;️最后总结 &#x1f50a;1.spring-boot-maven-plugin <plugins><plugin><groupId>org.springframework.boot&…

每日一题SQL

以下题目来源微信公众号【SQL数据库开发】 1、编写一个 SQL 查询来实现分数排名。如果两个分数相同&#xff0c;则两个分数排名&#xff08;Rank&#xff09;相同。请注意&#xff0c;平分后的下一个名次应该是下一个连续的整数值。换句话说&#xff0c;名次之间不应该有“间隔…

HTML5+CSS3+JS小实例:自适应瀑布流布局

实例:自适应瀑布流布局 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport" content=&quo…

九、 SpringBoot项目部署、项目打包、运行

5.5.1 项目打包 步骤1&#xff1a; 添加项目的pom.xml插件&#xff1b;在pom.xml要显式的加入插件spring-boot-maven-plugin&#xff0c;否则无法产生 jar 清单文件&#xff0c;导致打出来的 jar 无法使用命令运行&#xff1b; <build> <plugins> <!-- 打j…