使用AutoDecoder自动解码器实现简单MNIST特征向量提取

这篇具有很好参考价值的文章主要介绍了使用AutoDecoder自动解码器实现简单MNIST特征向量提取。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

AutoDecoder

自动解码器(AD)是论文"DeepSDF: Learning Continuous Signed Distance Functions for Shape Representation" 中使用的一种方法,与传统编码-解码结构不同,AD无编码器,仅有一个解码器。解码器实现特征向量(隐向量)与图片之间的转换

在训练过程中同时优化特征向量与神经网络参数。如果训练集有N张图片,特征向量长度为n,神经网络参数为m,那么待训练参数共有N*n+m个。

训练完成之后,任给一个特征向量,输入解码器,则可得到一张图片。

DeepSDF原文更为复杂,使用AD生成带符号的最小距离场,进而实现3D形状的生成。DeepSDF原文还有一个针对MNIST手写数据集的简单的案例,但是没有给出源代码,难以上手。笔者在Github上找到了一个具体实现代码https://github.com/alexeybokhovkin/DeepSDF,在此基础上作了一些修改完善,撰写了这篇博客,以作记录,希望对读者有所帮助。
使用AutoDecoder自动解码器实现简单MNIST特征向量提取,人工智能,算法,pytorch,经验分享,深度学习

代码

项目共有四个文件,dataset.py用于定义数据集,evaluate.py用于评估训练后的神经网络,network.py用于定义神经网络结构,train.py用于训练神经网络
使用AutoDecoder自动解码器实现简单MNIST特征向量提取,人工智能,算法,pytorch,经验分享,深度学习

1 dataset.py

用于导入MNIST数据集(或FashionMNIST)数据集,如果本地没有则会从互联网下载

import torchvision
from torch.utils.data.dataset import Dataset

# A wrapper dataset over MNIST to return images and indices
class DatasetMNIST(Dataset):

    def __init__(self, root_dir, latent_size, transform=None):
        mnist = torchvision.datasets.FashionMNIST(root=root_dir, train=True,download=True)
        self.data = mnist.train_data.float()/255.0

    def __len__(self):
        return len(self.data)

    def __getitem__(self, index):
        image = self.data[index]

        return image.flatten(), index

2 network.py

定义了一个全连接神经网络,输入特征向量,输出图片(展平为向量)。为了便于观察结果,输入的特征向量维数为2。需要注意的是,特征向量也作为被训练参数,共N*n个元素。

import torch
import torch.nn as nn
import torch.nn.init as init

# Autodecoder structure
class AD(nn.Module):
    def __init__(self, image_size=784, z_dim=2, data_shape=60000):
        super(AD, self).__init__()
        self.decoder = nn.Sequential(
            nn.Linear(z_dim, 128),
            nn.ReLU(True),
            nn.Linear(128, 256),
            nn.ReLU(True),
            nn.Linear(256, 512),
            nn.ReLU(True), nn.Linear(512, 28 * 28), nn.Tanh())
        
        self.latent_vectors = nn.Parameter(torch.FloatTensor(data_shape, z_dim))
        
        init.xavier_normal(self.latent_vectors)
    
    def forward(self, ind):
        x = self.latent_vectors[ind]
        return self.decoder(x)
    
    def predict(self, x):
        return self.decoder(x)

3 train.py

使用Adams训练神经网络,batch_size=128num_epochs=250。训练只需几分钟,完成后保存为model.pth文件,以供调用

import os
import numpy as np
import torch
import torch.nn as nn
from torchvision.utils import save_image
from dataset import DatasetMNIST
from network import AD
from tqdm import tqdm

# Hyper-parameters
image_width = 28
image_size = image_width*image_width
h_dim = 512
num_epochs = 250
batch_size = 128
learning_rate = 1e-3
latent_size = 2

if __name__ == "__main__":
    os.environ['CUDA_VISIBLE_DEVICES'] = '0'

    # Create a directory if not exists
    sample_dir = 'samples'
    os.makedirs(sample_dir, exist_ok=True)

    dataset = DatasetMNIST(root_dir='./data', latent_size=latent_size)

    # Data loader
    data_loader = torch.utils.data.DataLoader(dataset=dataset,
                                            batch_size=batch_size,
                                            shuffle=True)

    model = AD(image_size=image_size, z_dim=latent_size, data_shape=60000).cuda()

    # recusntruction loss
    criterion = nn.MSELoss()
    optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

    model.train()
    for epoch in range(num_epochs):
        tq = tqdm(total=len(data_loader))
        tq.set_description('Epoch {}'.format(epoch))
        for i, (x, ind) in enumerate(data_loader):
            # Forward pass
            x = x.cuda()
            x_reconst = model(ind)

            loss = criterion(x_reconst, x)

            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

            tq.update()
            tq.set_postfix(loss='{:.3f}'.format(loss.item()))

        if epoch%5 == 0:
            with torch.no_grad():
                # Visualize 2D latent space
                steps = 50
                bound = 0.8
                size = image_width
                out = torch.zeros(size=(steps * size, steps * size))

                for i, l1 in enumerate(np.linspace(-bound, bound, steps)):
                    for j, l2 in enumerate(np.linspace(-bound, bound, steps)):
                        vector = torch.tensor([l1, l2]).to(dtype=torch.float32).cuda()
                        out_ = model.predict(vector)
                        out[i * size:(i + 1) * size, j * size:(j + 1)
                            * size] = out_.view(size, size)
                save_image(out, os.path.join(
                    sample_dir, 'latent_space-{}.png'.format(epoch + 1)))


    # save model
    torch.save(model, 'model.pth')

4 evaluate.py

加载训练好的模型,遍历特征向量[l1,l2],使用解码器生成对应的图像,保存为latent_space-eval.png

将所有训练集的特征向量[l1,l2]绘制在一张图上,保存为latent_space-distribution.png

最后将两张图片拼接得到latent_space-merged.png

import os
import torch
import numpy as np
from torchvision.utils import save_image
from train import image_width

if __name__ == "__main__":
    # Create a directory if not exists
    sample_dir = 'samples'
    os.makedirs(sample_dir, exist_ok=True)

    # 选择GPU或CPU
    device = torch.device(
        "cuda") if torch.cuda.is_available() else torch.device("cpu")

    # 从文件加载已经训练完成的模型
    model = torch.load('model.pth', map_location=device)
    model.eval()  # 设置模型为evaluation状态

    print(model)

    # Visualize 2D latent space
    steps = 50
    bound = 0.8
    size = image_width
    out_grid = torch.zeros(size=(steps * size, steps * size))

    for i, l1 in enumerate(np.linspace(-bound, bound, steps)):
        for j, l2 in enumerate(np.linspace(-bound, bound, steps)):
            vector = torch.tensor([l1, l2]).to(dtype=torch.float32).cuda()
            out_ = model.predict(vector)
            out_grid[i * size:(i + 1) * size, j * size:(j + 1)
                * size] = out_.view(size, size)
    save_image(out_grid, os.path.join(
        sample_dir, 'latent_space-eval.png'))
    
    out_dist = torch.zeros(size=(steps * size, steps * size))

    latent_vectors_scaled=model.latent_vectors.cpu().detach().numpy()
    latent_vectors_scaled=np.clip(latent_vectors_scaled, -bound+0.005, bound-0.005)
    latent_vectors_scaled = ((latent_vectors_scaled+bound)/(2.0*bound)*steps*size*1.0)

    for i in range(len(latent_vectors_scaled)):
        l1=round(latent_vectors_scaled[i][0])
        l2=round(latent_vectors_scaled[i][1])
        out_dist[l1, l2]=1.0
        out_dist[l1-1, l2]=1.0
        out_dist[l1+1, l2]=1.0
        out_dist[l1, l2-1]=1.0
        out_dist[l1-1, l2-1]=1.0
        out_dist[l1+1, l2-1]=1.0
        out_dist[l1, l2+1]=1.0
        out_dist[l1-1, l2+1]=1.0
        out_dist[l1+1, l2+1]=1.0

    save_image(out_dist, os.path.join(
    sample_dir, 'latent_space-distribution.png'))

    out_merged = torch.cat((out_grid, out_dist), dim=1)
    save_image(out_merged, os.path.join(
    sample_dir, 'latent_space-merged.png'))

    print(model.latent_vectors.max(), model.latent_vectors.min())

结果

训练前遍历特征向量绘制得到解码后的图片:
使用AutoDecoder自动解码器实现简单MNIST特征向量提取,人工智能,算法,pytorch,经验分享,深度学习
epoch=16, 遍历特征向量绘制得到解码后的图片:

使用AutoDecoder自动解码器实现简单MNIST特征向量提取,人工智能,算法,pytorch,经验分享,深度学习
epoch=101, 遍历特征向量绘制得到解码后的图片:
使用AutoDecoder自动解码器实现简单MNIST特征向量提取,人工智能,算法,pytorch,经验分享,深度学习epoch=250, 遍历特征向量绘制得到解码后的图片:
使用AutoDecoder自动解码器实现简单MNIST特征向量提取,人工智能,算法,pytorch,经验分享,深度学习训练样本分布如下:
使用AutoDecoder自动解码器实现简单MNIST特征向量提取,人工智能,算法,pytorch,经验分享,深度学习

结论

(1) AD事实上是一种特征提取方法,本文从数据集中提取了一个2D特征,在2D平面内重构出了原始数据集。在实际使用中,特征向量是一个高维向量,效果会更好。
(2) 特征向量的分布近似于一个正态分布,但是不同类别之间存在鸿沟
(3)AD的本质是对图片数据进行压缩,图片公有信息蕴含于神经网络参数中,个体信息蕴含于特征向量。文章来源地址https://www.toymoban.com/news/detail-786417.html

到了这里,关于使用AutoDecoder自动解码器实现简单MNIST特征向量提取的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • SpringBoot项目整合OpenFeign、实现动态IP+URL请求、自定义(编码器\解码器)

    OpenFeign 是Spring Cloud在Feign的基础上支持了SpringMVC的注解,如@RequestMapping等等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中. 启动类加上注解: @EnableDiscoveryClient 动态URL 工具类: FeignUtils.class

    2024年02月02日
    浏览(51)
  • 【LabVIEW FPGA入门】LabVIEW FPGA实现I2S解码器

            该示例演示了如何使用 LabVIEW FPGA 解码 I²S 信号。该代码可用于大多数支持高速数字输入的LabVIEW FPGA 目标(例如R 系列、CompactRIO)。I²S 用于对系统和组件内的数字音频数据进行编码。例如,MP3 播放器或 DVD 播放器内部的数字音频通常使用 I²S 协议进行通信。   

    2024年01月17日
    浏览(43)
  • 解码器 | 基于 Transformers 的编码器-解码器模型

    基于 transformer 的编码器-解码器模型是 表征学习 和 模型架构 这两个领域多年研究成果的结晶。本文简要介绍了神经编码器-解码器模型的历史,更多背景知识,建议读者阅读由 Sebastion Ruder 撰写的这篇精彩 博文。此外,建议读者对 自注意力 (self-attention) 架构 有一个基本了解

    2024年02月08日
    浏览(49)
  • Netty编解码器,Netty自定义编解码器解决粘包拆包问题,Netty编解码器的执行过程详解

    当Netty发送或者接收一个消息的时候,就会发生一次数据转换。入站消息会被解码(从字节转换为另一种格式,比如java对象);出站消息会被编码成字节。 Netty 提供一系列实用的编解码器,他们都实现了 ChannelInboundHadnler 或者 ChannelOutboundHandler 接口。在这些类中,channelRead 方

    2023年04月23日
    浏览(44)
  • 【计算机视觉 | 目标检测】术语理解9:AIGC的理解,对比学习,解码器,Mask解码器,耦合蒸馏,半耦合,图像编码器和组合解码器的耦合优化

    AIGC指的是使用人工智能技术自动生成的各类数字内容,包括文本、图像、音频、视频等。它利用机器学习模型进行智能化内容生成。 主要的技术手段包括: 自然语言生成(NLG):使用RNN、GPT等语言模型生成文本。 生成对抗网络(GAN):使用GAN生成高质量图片。 自动语音合成(TTS):使用

    2024年02月04日
    浏览(67)
  • 编码器 | 基于 Transformers 的编码器-解码器模型

    基于 transformer 的编码器-解码器模型是 表征学习 和 模型架构 这两个领域多年研究成果的结晶。本文简要介绍了神经编码器-解码器模型的历史,更多背景知识,建议读者阅读由 Sebastion Ruder 撰写的这篇精彩 博文。此外,建议读者对 自注意力 (self-attention) 架构 有一个基本了解

    2024年02月08日
    浏览(61)
  • 【Transformer系列(1)】encoder(编码器)和decoder(解码器)

    前言 这个专栏我们开始学习transformer,自推出以来transformer在深度学习中占有重要地位,不仅在NLP领域,在CV领域中也被广泛应用,尤其是2021年,transformer在CV领域可谓大杀四方。 在论文的学习之前,我们先来介绍一些专业术语。本篇就让我们先来认识一下encoder和decoder吧!

    2024年03月25日
    浏览(61)
  • 【Netty】Netty 解码器(十二)

    回顾Netty系列文章: Netty 概述(一) Netty 架构设计(二) Netty Channel 概述(三) Netty ChannelHandler(四) ChannelPipeline源码分析(五) 字节缓冲区 ByteBuf (六)(上) 字节缓冲区 ByteBuf(七)(下) Netty 如何实现零拷贝(八) Netty 程序引导类(九) Reactor 模型(十) 工作原理

    2024年02月07日
    浏览(54)
  • 22.Netty源码之解码器

    https://mp.weixin.qq.com/s/526p5f9fgtZu7yYq5j7LiQ Netty 常用解码器类型: ByteToMessageDecoder/ReplayingDecoder 将字节流解码为消息对象; MessageToMessageDecoder 将一种消息类型解码为另外一种消息类型。 自定义一次解码器ByteToMessageDecoder解码器,如果读到的字节大小为4,那么认为读取到了1个完整的数

    2024年02月14日
    浏览(46)
  • 23.Netty源码之内置解码器

    在前两节课我们介绍了 TCP 拆包/粘包的问题,以及如何使用 Netty 实现自定义协议的编解码。可以看到,网络通信的底层实现,Netty 都已经帮我们封装好了,我们只需要扩展 ChannelHandler 实现自定义的编解码逻辑即可。 更加人性化的是,Netty 提供了很多开箱即用的解码器,这些

    2024年02月13日
    浏览(34)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包