CVAE-GAN——生成0-9数字图像(Pytorch+mnist)

1、简介

  • CVAE-GAN(Conditional Variational Autoencoder Generative Adversarial Network)是一种混合型生成模型,结合了条件变分自编码器(CVAE)和生成对抗网络(GAN)的思想。
  • 在CVAE-GAN中,CVAE的编码器和解码器被结合在一起,作为GAN的生成器,用于学习数据的潜在表示和生成数据。同时,GAN的判别器帮助训练生成器生成更逼真的数据。
  • CVAE-GAN的工作方式如下:
    • 编码器(Encoder):接收输入数据和条件信息,并将其映射到潜在空间中的潜在表示。
    • 解码器(Decoder/Generator):接收从潜在空间中采样的潜在表示和条件信息,并生成与条件信息相关的数据样本。
    • 判别器(Discriminator):接收真实样本和生成样本(包括条件信息),并尝试将它们区分开来。
    • 损失函数:CVAE-GAN的损失函数通常包括两部分:一部分是CVAE的重构损失,用于确保生成数据与输入数据相似;另一部分是GAN的对抗损失,用于鼓励生成数据与真实数据分布相匹配。
  • CVAE-GAN通过结合CVAE和GAN的优点,既可以学习数据的潜在表示,又可以生成高质量的数据样本,并且可以通过条件信息控制生成过程。这种结合使得CVAE-GAN在诸如图像生成、图像编辑等任务中具有很好的表现。
  • 本文利用CVAE-GAN,输入数字图像和对应的标签。训练后,生成0-9数字图像。
    • (epoch=10)
    • (epoch=20)
    • (epoch=30)
    • (epoch=40)
    • (epoch=50)

2、代码

2.1、生成器(Genration.py)

  • import torch
    import torch.nn as nn
    import torch.nn.functional as F
    
    
    # 变分自编码器
    class CVAE(nn.Module):
        def __init__(self, input_size, num_classes):
            super(CVAE, self).__init__()
            self.num_classes = num_classes  # 标签数量
            self.input_size = input_size
            self.potential_size = 64  # 潜在空间大小
    
            # 编码器层
            self.fc1 = nn.Linear(self.input_size + self.num_classes, 512)  # 编码器输入层
            self.fc2 = nn.Linear(512, self.potential_size)
            self.fc3 = nn.Linear(512, self.potential_size)
    
            # 解码器层
            self.fc4 = nn.Linear(self.potential_size + self.num_classes, 512)  # 解码器输入层
            self.fc5 = nn.Linear(512, self.input_size)  # 解码器输出层
    
        # 编码器部分
        def encode(self, x):
            x = F.relu(self.fc1(x))  # 编码器的隐藏表示
            mu = self.fc2(x)  # 潜在空间均值
            log_var = self.fc3(x)  # 潜在空间对数方差
            return mu, log_var
    
        # 重参数化技巧
        def reparameterize(self, mu, log_var):  # 从编码器输出的均值和对数方差中采样得到潜在变量z
            std = torch.exp(0.5 * log_var)  # 计算标准差
            eps = torch.randn_like(std)  # 从标准正态分布中采样得到随机噪声
            return mu + eps * std  # 根据重参数化公式计算潜在变量z
    
        # 解码器部分
        def decode(self, z):
            z = F.relu(self.fc4(z))  # 将潜在变量 z 解码为重构图像
            return torch.sigmoid(self.fc5(z))  # 将隐藏表示映射回输入图像大小,并应用 sigmoid 激活函数,以产生重构图像
    
        # 前向传播
        def forward(self, x, y):  # 输入图像 x,标签 y 通过编码器和解码器,得到重构图像和潜在变量的均值和对数方差
            x = torch.cat([x, y], dim=1)
            mu, log_var = self.encode(x)
            z = self.reparameterize(mu, log_var)
            z = torch.cat([z, y], dim=1)
            return self.decode(z), mu, log_var
    
        # 使用重构损失和 KL 散度作为损失函数
        def generator_loss(self, recon_x, x, mu, log_var):  # 参数:重构的图像、原始图像、潜在变量的均值、潜在变量的对数方差
            MSE = F.mse_loss(recon_x, x.view(-1, self.input_size), reduction='sum')  # 计算重构图像 recon_x 和原始图像 x 之间的均方误差
            KLD = -0.5 * torch.sum(1 + log_var - mu.pow(2) - log_var.exp())  # 计算潜在变量的KL散度
            return MSE + KLD  # 返回二进制交叉熵损失和 KLD 损失的总和作为最终的损失值

2.2、判别器(Discriminator.py)

  • import torch
    import torch.nn as nn
    import torch.nn.functional as F
    
    
    # 定义判别器类
    class Discriminator(nn.Module):
        def __init__(self, input_size, num_classes):
            super(Discriminator, self).__init__()
            self.num_classes = num_classes  # 标签数量
            self.input_size = input_size
    
            # 判别器层
            self.fc1 = nn.Linear(self.input_size + self.num_classes, 512)
            self.fc2 = nn.Linear(512, 256)
            self.fc3 = nn.Linear(256, 1)
    
        def forward(self, x):
            x = F.relu(self.fc1(x))
            x = F.relu(self.fc2(x))
            return torch.sigmoid(self.fc3(x))

2.3、训练(train.py)

  • from Discriminator import Discriminator
    from Genration import CVAE
    import torch
    import torch.optim as optim
    import torchvision
    import torch.nn.functional as F
    from torchvision.utils import save_image
    
    
    # 生成0-9数字
    def sample_images(epoch):
        with torch.no_grad():  # 上下文管理器,确保在该上下文中不会进行梯度计算。因为在这里只是生成样本而不需要梯度
            number = 10
            # 生成标签
            sample_labels = torch.arange(10).long().to(device)  # 0-9的标签
            sample_labels_onehot = F.one_hot(sample_labels, num_classes=10).float()
            # 生成随机噪声
            sample = torch.randn(number, latent_size).to(device)  # 生成一个形状为 (64, latent_size) 的张量,其中包含从标准正态分布中采样的随机数
            sample = torch.cat([sample, sample_labels_onehot], dim=1)  # 连接图片和标签
    
            sample = cvae_model.decode(sample).cpu()  # 将随机样本输入到解码器中,解码器将其映射为图像
            save_image(sample.view(number, 1, 28, 28), f'sample{epoch}.png', nrow=int(number / 2))  # 将生成的图像保存为文件
    
    
    def generator_loss(recon_x, x, mu, log_var, discriminator_output):
        mse_loss = F.mse_loss(recon_x, x.view(-1, input_size), reduction='sum')  # 计算重构图像 recon_x 和原始图像 x 之间的均方误差
        kld_loss = -0.5 * torch.sum(1 + log_var - mu.pow(2) - log_var.exp())
        gan_loss = F.binary_cross_entropy(discriminator_output, torch.ones_like(discriminator_output))
        return mse_loss + kld_loss + gan_loss
    
    
    def discriminator_loss_acc(real_output, fake_output):
        # 损失
        real_loss = F.binary_cross_entropy(real_output, torch.ones_like(real_output))
        fake_loss = F.binary_cross_entropy(fake_output, torch.zeros_like(fake_output))
        total_loss = real_loss + fake_loss
        # 精度
        real_pred = torch.round(real_output)
        fake_pred = torch.round(fake_output)
        real_acc = (real_pred == 1).sum().item() / real_output.numel()
        fake_acc = (fake_pred == 0).sum().item() / fake_output.numel()
        total_acc = (real_acc + fake_acc) / 2
        return total_loss, total_acc
    
    
    if __name__ == '__main__':
        batch_size = 512  # 批次大小
        epochs = 50  # 学习周期
        sample_interval = 10  # 保存结果的周期
        learning_rate = 0.001  # 学习率
        input_size = 784  # 输入大小
        num_classes = 10  # 标签数量
        latent_size = 64  # 噪声大小
    
        # 载入 MNIST 数据集中的图片进行训练
        transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor()])  # 将图像转换为张量
    
        train_dataset = torchvision.datasets.MNIST(
            root="~/torch_datasets", train=True, transform=transform, download=True
        )  # 加载 MNIST 数据集的训练集,设置路径、转换和下载为 True
    
        train_loader = torch.utils.data.DataLoader(
            train_dataset, batch_size=batch_size, shuffle=True
        )  # 创建一个数据加载器,用于加载训练数据,设置批处理大小和是否随机打乱数据
    
        # 配置要在哪个设备上运行
        device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    
        cvae_model = CVAE(input_size, num_classes).to(device)
        dis_model = Discriminator(input_size, num_classes).to(device)
    
        optimizer_cvae = optim.Adam(cvae_model.parameters(), lr=learning_rate)
        optimizer_dis = optim.Adam(dis_model.parameters(), lr=learning_rate)
    
        for epoch in range(epochs):
            generator_loss_total = 0
            discriminator_loss_total = 0
            discriminator_acc_total = 0
            for batch_idx, (data, labels) in enumerate(train_loader):
                data = data.to(device)
                data = data.view(-1, input_size)
    
                labels = F.one_hot(labels, num_classes).float().to(device)
    
                # 更新判别器
                optimizer_dis.zero_grad()
    
                recon_batch, _, _ = cvae_model(data, labels)  # 生成虚假数据
                fake_data = torch.cat([recon_batch, labels], dim=1)
                real_data = torch.cat([data, labels], dim=1)
    
                fake_output = dis_model(fake_data)
                real_output = dis_model(real_data)
    
                d_loss, d_acc = discriminator_loss_acc(real_output, fake_output)  # 计算判别器损失和精度
                d_loss.backward()
                optimizer_dis.step()  # 更新模型参数
    
                # 更新生成器
                optimizer_cvae.zero_grad()
    
                recon_batch, mu, log_var = cvae_model(data, labels)
                fake_data = torch.cat([recon_batch, labels], dim=1)
                fake_output = dis_model(fake_data)
    
                g_loss = generator_loss(recon_batch, data, mu, log_var, fake_output)
                g_loss.backward()
                optimizer_cvae.step()
    
                generator_loss_total += g_loss.item()
                discriminator_loss_total += d_loss.item()
                discriminator_acc_total += d_acc
    
            generator_loss_avg = generator_loss_total / len(train_loader)
            discriminator_loss_avg = discriminator_loss_total / len(train_loader)
            discriminator_acc_avg = discriminator_acc_total / len(train_loader)
    
            print('Epoch [{}/{}], Generator Loss: {:.3f}, Discriminator Loss: {:.3f}, Discriminator Acc: {:.2f}%'.format(
                epoch + 1, epochs, generator_loss_avg, discriminator_loss_avg, discriminator_acc_avg * 100))
    
            if (epoch + 1) % sample_interval == 0:
                sample_images(epoch + 1)

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

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

相关文章

我的C++奇迹之旅相遇:支持函数重载的原理

文章目录 📝前言🌠 C支持函数重载的原理:名字修饰(name Mangling)🌉不同编译器不同函数名修饰规则 🌠Windows下名字修饰规则🚩总结 📝前言 函数重载概念 函数重载:是函数的一种特殊…

加密/ 解密 PDF:使用Python为PDF文档设置、移除密码

在数字化时代,文档的安全性变得越来越重要。特别是对于包含敏感信息的PDF文件,确保其不被未经授权的人员访问或修改是至关重要的。本文将介绍如何使用Python在PDF文档中设置密码,以及如何移除已经设置的密码。 目录 PDF加密基础知识 Pytho…

大话设计模式之建造者模式

建造者模式(Builder Pattern)是一种创建型设计模式,旨在通过将复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。 在建造者模式中,通常包含以下几个角色: Director(指挥…

新增收货地址

目录 🧂1.创建controller层 🥓2.创建service层 🌭3.注意细节 🍿4.避免dao数据暴漏 1.创建controller层 controller不做逻辑操作,只接受前端的数据 1.添加Api设置swagger模块名称2.RestController以json形式返回…

java计算机网络(一)-- url,tcp,udp,socket

网络编程: 计算机网络 计算机网络指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统、网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。 网络协议…

C#.net8创建webapi,使用SqlSugar,仓储模式,DTO,服务层,控制层的综合应用(企业级)

本文源码地址: https://download.csdn.net/download/u012563853/89036104 源码中,也有详细的注释说明。 代码总览: 这是一个综合性比较强的文章,需要有一定的基础,没有基础的人,看了后,会全面的了解一下,有基础的人,看了后会加强认识,更加的巩固,直接在项目中去应…

vue3全局控制Element plus所有组件的文字大小

项目框架vue-右上角有控制全文的文字大小 实现&#xff1a; 只能控制element组件的文字及输入框等大小变化&#xff0c;如果是自行添加div,text, span之类的控制不了。 配置流程 APP.vue 使用element的provide&#xff0c;包含app <el-config-provider :locale"loca…

mybatis的基于注解和xml的两种实现方式详解

文章简介 本文介绍了springbootmybatis实现数据库操作的两种实现方式&#xff0c;经测试均可运行使用。整体而言注解更加简便&#xff0c;但面对一些复杂查询&#xff0c;可能需要使用到注解方式。 注解方式 pom依赖&#xff1a; <dependencies><!--连接数据库--&…

Wasm初上手

总之也是为了扩宽技术面吧。。。我也不知道为什么就想试试了&#xff0c;就酱。 参考阅读&#xff1a;极客时间《WebAssembly入门课》 安装wasm的编译器Emscripten。Emscripten 是一个“源到源”语言编译器工具集&#xff0c;这个工具集可以将 C/C 代码编译成对应 JavaScript 代…

冒泡排序---算法

1、算法概念 冒泡排序&#xff1a;它重复地走访要排序的数列&#xff0c;一次比较两个元素&#xff0c;如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换&#xff0c;也就是说该数列已经排序完成。这个算法越小的元素会经由交换慢慢“浮”到…

Linux企业级别日志的查找

企业级别日志的查找 查看mysql数据库的日志错误日志&#xff08;Error Log&#xff09;查询日志&#xff08;General Query Log&#xff09;慢查询日志&#xff08;Slow Query Log&#xff09;事务日志&#xff08;Transaction Log&#xff09;二进制日志&#xff08;Binary Lo…

python-tkinter程序的带包发布pyinstaller的使用闭坑

一、pyinstaller 不是内部或外部命令 1、安装pyinstaller 安装的时候一定注意别少了install后的er&#xff0c;pyinstaller,否则会安装成其他的程序的。安装的指令如下&#xff1a; pip install pyinstaller2、配置运行环境 首先找到你的python的安装目录&#xff0c;这个我…

Web APIs知识点讲解(阶段六)

BOM- 操作浏览器 一.Window对象 1. 依托 BOM 对象实现对历史、地址、浏览器信息的操作或获取2. 具备利用本地存储实现学生信息表案例的能力 1.BOM(浏览器对象模型) BOM(Browser Object Model ) 是浏览器对象模型 window 是浏览器内置中的全局对象&#xff0c;我们所学习的所…

论文笔记:基于多粒度信息融合的社交媒体多模态假新闻检测

整理了ICMR2023 Multi-modal Fake News Detection on Social Media via Multi-grained Information Fusion&#xff09;论文的阅读笔记 背景模型实验 背景 在假新闻检测领域&#xff0c;目前的方法主要集中在文本和视觉特征的集成上&#xff0c;但不能有效地利用细粒度和粗粒度…

C# 学习第五弹——语句

一、if语句 —简单if语句 —if else 语句 —if else if else 语句 1、简单if语句 if&#xff08;表达式&#xff09;{语句} &#xff08;1&#xff09;表达式必须使用圆括号括起来&#xff1b; &#xff08;2&#xff09;表达式&#xff1a;关系表达式或逻辑表达…

Express

可以方便、快速创建Web网站的服务器&#xff08;提供web网页资源&#xff09;或API接口服务器&#xff08;提供API接口&#xff09; app.get(请求URL&#xff0c;function(req,res)>{}) //req:请求对象&#xff08;包括请求属性和方法&#xff09; //res:响应对象&#xff…

【python】常用函数汇总(持续更新……)

文章目录 【numpy.exp()】返回e的幂次方&#xff0c;e是一个常数为2.71828【np.dot()】矩阵相乘【np.linalg.inv()】矩阵求逆 【numpy.exp()】返回e的幂次方&#xff0c;e是一个常数为2.71828 举例&#xff1a;numpy.exp() 【np.dot()】矩阵相乘 【要点】 1、前者的列数后者…

suno让音乐行业一夜变天,如何快速体验suno一键生成音乐?

随着AI的应用变广&#xff0c;各类AI程序已逐渐普及。AI已逐渐深入到人们的工作生活方方面面。而AI涉及的行业也越来越多&#xff0c;从最初的写作&#xff0c;到医疗教育&#xff0c;再到现在的音乐。 Suno是一个专业高质量的AI歌曲和音乐创作平台&#xff0c;用户只需输入简…

Vue ElementPlus Form、Form-item 表单

Form 表单 由输入框、选择器、单选框、多选框等控件组成&#xff0c;用以收集、校验、提交数据&#xff0c;组件升级采用了 flex 布局&#xff0c;以替代旧版本的 float 布局。 典型表单 包括各种表单项&#xff0c;比如输入框、选择器、开关、单选框、多选框等。 在 Form 组件…

打造高效安全的电池管理 | 基于ACM32 MCU的两轮车充电桩方案

前 言 随着城市化进程的加快、人们生活水平的提高和节能环保理念的普及&#xff0c;越来越多的人选择了电动车作为代步工具&#xff0c;而两轮电动车的出行半径较短&#xff0c;需要频繁充电&#xff0c;因此在城市中设置两轮车充电桩就非常有必要了。城市中的充电桩不仅能解决…