码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 教你基于MindSpore用DCGAN生成漫画头像


    本教程将使用动漫头像数据集来训练一个生成式对抗网络,接着使用该网络生成动漫头像图片。
    合集 - 人工智能(30)
    1.简单4步,带你用华为云MetaStudio制作数字人短片06-052.【AI应用开发全流程】使用AscendCL开发板完成模型推理06-053.使用Python实现深度学习模型:序列到序列模型(Seq2Seq)06-064.无需搭建环境,零门槛带你体验Open-Sora文生视频应用06-065.一文教你在MindSpore中实现A2C算法训练06-076.代码高手的过节秘籍:CodeArt Snap帮写代码,灵感弹指间实现06-077.星火闪耀,与AI同行丨华为开发者大会2024社区活动重磅上线!06-118.基于Ascend C的FlashAttention算子性能优化最佳实践06-129.快速识别你家的猫猫狗狗,教你用ModelBox开发AI萌宠应用06-1310.首批!华为云盘古研发大模型通过代码大模型评估,获当前最高等级06-1311.详解联邦学习中的异构模型集成与协同训练技术06-1912.养猪大户必备!教你用ModelBox开发一个AI数猪应用06-2013.【重磅】华为云盘古大模型5.0,正式发布!06-2214.【HDC 2024】探索、交流、成长,华为云助力开发者成就星辰大海梦想06-2415.大模型重塑软件开发,华为云AI原生应用架构设计与实践分享06-2516.基于Python和TensorFlow实现BERT模型应用06-2617.如何玩转云端文生视频、0码构建AI应用?华为云专家来揭秘06-2718.深度解读昇腾CANN多流并行技术,提高硬件资源利用率07-0219.一文为你深度解析LLaMA2模型架构07-0420.结合RNN与Transformer双重优点,深度解析大语言模型RWKV07-0521.万字长文解析AI Agent技术原理和应用07-0822.深度解读昇腾CANN内存复用技术,降低网络内存占用07-09
    23.教你基于MindSpore用DCGAN生成漫画头像07-10
    24.零代码教你安装部署Stable Diffusion 3,一键生成高质量图像07-1225.深度解读昇腾CANN模型下沉技术,提升模型调度性能07-1526.田间地头“有智慧”,华为云助力盈禾嘉田打造病虫害防治新模式07-1627.基于MindSpore实现BERT对话情绪识别07-1628.降低大模型推理87%时延!华为云论文入选顶会USENIX ATC'2407-1929.【毕业季】给你的职场首秀加点“码力”:零码创建专属AI Agent07-1930.程序员必备开发神器:领取云主机,零码创建专属AI Agent07-24
    收起

    本文分享自华为云社区《【昇思25天学习打卡营打卡指南-第二十天】DCGAN生成漫画头像》,作者:JeffDing。

    DCGAN生成漫画头像

    在下面的教程中,我们将通过示例代码说明DCGAN网络如何设置网络、优化器、如何计算损失函数以及如何初始化模型权重。在本教程中,使用的动漫头像数据集共有70,171张动漫头像图片,图片大小均为96*96。

    GAN基础原理

    这部分原理介绍参考GAN图像生成。

    DCGAN原理

    DCGAN(深度卷积对抗生成网络,Deep Convolutional Generative Adversarial Networks)是GAN的直接扩展。不同之处在于,DCGAN会分别在判别器和生成器中使用卷积和转置卷积层。

    它最早由Radford等人在论文Unsupervised Representation Learning With Deep Convolutional Generative Adversarial Networks中进行描述。判别器由分层的卷积层、BatchNorm层和LeakyReLU激活层组成。输入是3x64x64的图像,输出是该图像为真图像的概率。生成器则是由转置卷积层、BatchNorm层和ReLU激活层组成。输入是标准正态分布中提取出的隐向量𝑧,输出是3x64x64的RGB图像。

     

    本教程将使用动漫头像数据集来训练一个生成式对抗网络,接着使用该网络生成动漫头像图片。

    数据准备与处理

    首先我们将数据集下载到指定目录下并解压。示例代码如下:

    from download import download
    
    url = "https://download.mindspore.cn/dataset/Faces/faces.zip"
    
    path = download(url, "./faces", kind="zip", replace=True)

    数据处理

    首先为执行过程定义一些输入:

    复制代码
    batch_size = 128          # 批量大小
    image_size = 64           # 训练图像空间大小
    nc = 3                    # 图像彩色通道数
    nz = 100                  # 隐向量的长度
    ngf = 64                  # 特征图在生成器中的大小
    ndf = 64                  # 特征图在判别器中的大小
    num_epochs = 3           # 训练周期数
    lr = 0.0002               # 学习率
    beta1 = 0.5               # Adam优化器的beta1超参数
    复制代码

    定义create_dataset_imagenet函数对数据进行处理和增强操作。

    复制代码
    import numpy as np
    import mindspore.dataset as ds
    import mindspore.dataset.vision as vision
    
    def create_dataset_imagenet(dataset_path):
        """数据加载"""
        dataset = ds.ImageFolderDataset(dataset_path,
                                        num_parallel_workers=4,
                                        shuffle=True,
                                        decode=True)
    
        # 数据增强操作
        transforms = [
            vision.Resize(image_size),
            vision.CenterCrop(image_size),
            vision.HWC2CHW(),
            lambda x: ((x / 255).astype("float32"))
        ]
    
        # 数据映射操作
        dataset = dataset.project('image')
        dataset = dataset.map(transforms, 'image')
    
        # 批量操作
        dataset = dataset.batch(batch_size)
        return dataset
    
    dataset = create_dataset_imagenet('./faces')
    复制代码

    通过create_dict_iterator函数将数据转换成字典迭代器,然后使用matplotlib模块可视化部分训练数据。

    复制代码
    import matplotlib.pyplot as plt
    
    def plot_data(data):
        # 可视化部分训练数据
        plt.figure(figsize=(10, 3), dpi=140)
        for i, image in enumerate(data[0][:30], 1):
            plt.subplot(3, 10, i)
            plt.axis("off")
            plt.imshow(image.transpose(1, 2, 0))
        plt.show()
    
    sample_data = next(dataset.create_tuple_iterator(output_numpy=True))
    plot_data(sample_data)
    复制代码

    image.png

    构造网络

    当处理完数据后,就可以来进行网络的搭建了。按照DCGAN论文中的描述,所有模型权重均应从mean为0,sigma为0.02的正态分布中随机初始化。

    生成器

    生成器G的功能是将隐向量z映射到数据空间。由于数据是图像,这一过程也会创建与真实图像大小相同的 RGB 图像。在实践场景中,该功能是通过一系列Conv2dTranspose转置卷积层来完成的,每个层都与BatchNorm2d层和ReLu激活层配对,输出数据会经过tanh函数,使其返回[-1,1]的数据范围内。

    DCGAN论文生成图像如下所示:

    image.png

    图片来源:Unsupervised Representation Learning With Deep Convolutional Generative Adversarial Networks.

    我们通过输入部分中设置的nz、ngf和nc来影响代码中的生成器结构。nz是隐向量z的长度,ngf与通过生成器传播的特征图的大小有关,nc是输出图像中的通道数。

    以下是生成器的代码实现:

    复制代码
    import mindspore as ms
    from mindspore import nn, ops
    from mindspore.common.initializer import Normal
    
    weight_init = Normal(mean=0, sigma=0.02)
    gamma_init = Normal(mean=1, sigma=0.02)
    
    class Generator(nn.Cell):
        """DCGAN网络生成器"""
    
        def __init__(self):
            super(Generator, self).__init__()
            self.generator = nn.SequentialCell(
                nn.Conv2dTranspose(nz, ngf * 8, 4, 1, 'valid', weight_init=weight_init),
                nn.BatchNorm2d(ngf * 8, gamma_init=gamma_init),
                nn.ReLU(),
                nn.Conv2dTranspose(ngf * 8, ngf * 4, 4, 2, 'pad', 1, weight_init=weight_init),
                nn.BatchNorm2d(ngf * 4, gamma_init=gamma_init),
                nn.ReLU(),
                nn.Conv2dTranspose(ngf * 4, ngf * 2, 4, 2, 'pad', 1, weight_init=weight_init),
                nn.BatchNorm2d(ngf * 2, gamma_init=gamma_init),
                nn.ReLU(),
                nn.Conv2dTranspose(ngf * 2, ngf, 4, 2, 'pad', 1, weight_init=weight_init),
                nn.BatchNorm2d(ngf, gamma_init=gamma_init),
                nn.ReLU(),
                nn.Conv2dTranspose(ngf, nc, 4, 2, 'pad', 1, weight_init=weight_init),
                nn.Tanh()
                )
    
        def construct(self, x):
            return self.generator(x)
    
    generator = Generator()
    复制代码

    判别器

    如前所述,判别器D是一个二分类网络模型,输出判定该图像为真实图的概率。通过一系列的Conv2d、BatchNorm2d和LeakyReLU层对其进行处理,最后通过Sigmoid激活函数得到最终概率。

    DCGAN论文提到,使用卷积而不是通过池化来进行下采样是一个好方法,因为它可以让网络学习自己的池化特征。

    判别器的代码实现如下:

    复制代码
    class Discriminator(nn.Cell):
        """DCGAN网络判别器"""
    
        def __init__(self):
            super(Discriminator, self).__init__()
            self.discriminator = nn.SequentialCell(
                nn.Conv2d(nc, ndf, 4, 2, 'pad', 1, weight_init=weight_init),
                nn.LeakyReLU(0.2),
                nn.Conv2d(ndf, ndf * 2, 4, 2, 'pad', 1, weight_init=weight_init),
                nn.BatchNorm2d(ngf * 2, gamma_init=gamma_init),
                nn.LeakyReLU(0.2),
                nn.Conv2d(ndf * 2, ndf * 4, 4, 2, 'pad', 1, weight_init=weight_init),
                nn.BatchNorm2d(ngf * 4, gamma_init=gamma_init),
                nn.LeakyReLU(0.2),
                nn.Conv2d(ndf * 4, ndf * 8, 4, 2, 'pad', 1, weight_init=weight_init),
                nn.BatchNorm2d(ngf * 8, gamma_init=gamma_init),
                nn.LeakyReLU(0.2),
                nn.Conv2d(ndf * 8, 1, 4, 1, 'valid', weight_init=weight_init),
                )
            self.adv_layer = nn.Sigmoid()
    
        def construct(self, x):
            out = self.discriminator(x)
            out = out.reshape(out.shape[0], -1)
            return self.adv_layer(out)
    
    discriminator = Discriminator()
    复制代码

    模型训练

    损失函数

    当定义了D和G后,接下来将使用MindSpore中定义的二进制交叉熵损失函数BCELoss。

    # 定义损失函数
    adversarial_loss = nn.BCELoss(reduction='mean')

    优化器

    这里设置了两个单独的优化器,一个用于D,另一个用于G。这两个都是lr = 0.0002和beta1 = 0.5的Adam优化器。

    复制代码
    # 为生成器和判别器设置优化器
    optimizer_D = nn.Adam(discriminator.trainable_params(), learning_rate=lr, beta1=beta1)
    optimizer_G = nn.Adam(generator.trainable_params(), learning_rate=lr, beta1=beta1)
    optimizer_G.update_parameters_name('optim_g.')
    optimizer_D.update_parameters_name('optim_d.')
    复制代码

    训练模型

    训练分为两个主要部分:训练判别器和训练生成器。

    • 训练判别器

    训练判别器的目的是最大程度地提高判别图像真伪的概率。按照Goodfellow的方法,是希望通过提高其随机梯度来更新判别器,所以我们要最大化logD(x)+log(1−D(G(z))的值。

    • 训练生成器

    如DCGAN论文所述,我们希望通过最小化log(1−D(G(z)))来训练生成器,以产生更好的虚假图像。

    在这两个部分中,分别获取训练过程中的损失,并在每个周期结束时进行统计,将fixed_noise批量推送到生成器中,以直观地跟踪G的训练进度。

    下面实现模型训练正向逻辑:

    复制代码
    def generator_forward(real_imgs, valid):
        # 将噪声采样为发生器的输入
        z = ops.standard_normal((real_imgs.shape[0], nz, 1, 1))
    
        # 生成一批图像
        gen_imgs = generator(z)
    
        # 损失衡量发生器绕过判别器的能力
        g_loss = adversarial_loss(discriminator(gen_imgs), valid)
    
        return g_loss, gen_imgs
    
    def discriminator_forward(real_imgs, gen_imgs, valid, fake):
        # 衡量鉴别器从生成的样本中对真实样本进行分类的能力
        real_loss = adversarial_loss(discriminator(real_imgs), valid)
        fake_loss = adversarial_loss(discriminator(gen_imgs), fake)
        d_loss = (real_loss + fake_loss) / 2
        return d_loss
    
    grad_generator_fn = ms.value_and_grad(generator_forward, None,
                                          optimizer_G.parameters,
                                          has_aux=True)
    grad_discriminator_fn = ms.value_and_grad(discriminator_forward, None,
                                              optimizer_D.parameters)
    
    @ms.jit
    def train_step(imgs):
        valid = ops.ones((imgs.shape[0], 1), mindspore.float32)
        fake = ops.zeros((imgs.shape[0], 1), mindspore.float32)
    
        (g_loss, gen_imgs), g_grads = grad_generator_fn(imgs, valid)
        optimizer_G(g_grads)
        d_loss, d_grads = grad_discriminator_fn(imgs, gen_imgs, valid, fake)
        optimizer_D(d_grads)
    
        return g_loss, d_loss, gen_imgs
    复制代码

    循环训练网络,每经过50次迭代,就收集生成器和判别器的损失,以便于后面绘制训练过程中损失函数的图像。

    复制代码
    import mindspore
    
    G_losses = []
    D_losses = []
    image_list = []
    
    total = dataset.get_dataset_size()
    for epoch in range(num_epochs):
        generator.set_train()
        discriminator.set_train()
        # 为每轮训练读入数据
        for i, (imgs, ) in enumerate(dataset.create_tuple_iterator()):
            g_loss, d_loss, gen_imgs = train_step(imgs)
            if i % 100 == 0 or i == total - 1:
                # 输出训练记录
                print('[%2d/%d][%3d/%d]   Loss_D:%7.4f  Loss_G:%7.4f' % (
                    epoch + 1, num_epochs, i + 1, total, d_loss.asnumpy(), g_loss.asnumpy()))
            D_losses.append(d_loss.asnumpy())
            G_losses.append(g_loss.asnumpy())
    
        # 每个epoch结束后,使用生成器生成一组图片
        generator.set_train(False)
        fixed_noise = ops.standard_normal((batch_size, nz, 1, 1))
        img = generator(fixed_noise)
        image_list.append(img.transpose(0, 2, 3, 1).asnumpy())
    
        # 保存网络模型参数为ckpt文件
        mindspore.save_checkpoint(generator, "./generator.ckpt")
        mindspore.save_checkpoint(discriminator, "./discriminator.ckpt")
    复制代码

    结果展示

    运行下面代码,描绘D和G损失与训练迭代的关系图:

    复制代码
    plt.figure(figsize=(10, 5))
    plt.title("Generator and Discriminator Loss During Training")
    plt.plot(G_losses, label="G", color='blue')
    plt.plot(D_losses, label="D", color='orange')
    plt.xlabel("iterations")
    plt.ylabel("Loss")
    plt.legend()
    plt.show()
    复制代码

    image.png

    可视化训练过程中通过隐向量fixed_noise生成的图像。

    复制代码
    import matplotlib.pyplot as plt
    import matplotlib.animation as animation
    
    def showGif(image_list):
        show_list = []
        fig = plt.figure(figsize=(8, 3), dpi=120)
        for epoch in range(len(image_list)):
            images = []
            for i in range(3):
                row = np.concatenate((image_list[epoch][i * 8:(i + 1) * 8]), axis=1)
                images.append(row)
            img = np.clip(np.concatenate((images[:]), axis=0), 0, 1)
            plt.axis("off")
            show_list.append([plt.imshow(img)])
    
        ani = animation.ArtistAnimation(fig, show_list, interval=1000, repeat_delay=1000, blit=True)
        ani.save('./dcgan.gif', writer='pillow', fps=1)
    
    showGif(image_list)
    复制代码

    image.png

    从上面的图像可以看出,随着训练次数的增多,图像质量也越来越好。如果增大训练周期数,当num_epochs达到50以上时,生成的动漫头像图片与数据集中的较为相似,下面我们通过加载生成器网络模型参数文件来生成图像,代码如下:

    复制代码
    # 从文件中获取模型参数并加载到网络中
    mindspore.load_checkpoint("./generator.ckpt", generator)
    
    fixed_noise = ops.standard_normal((batch_size, nz, 1, 1))
    img64 = generator(fixed_noise).transpose(0, 2, 3, 1).asnumpy()
    
    fig = plt.figure(figsize=(8, 3), dpi=120)
    images = []
    for i in range(3):
        images.append(np.concatenate((img64[i * 8:(i + 1) * 8]), axis=1))
    img = np.clip(np.concatenate((images[:]), axis=0), 0, 1)
    plt.axis("off")
    plt.imshow(img)
    plt.show()
    复制代码

    image.png

     

    点击关注,第一时间了解华为云新鲜技术~

     

  • 相关阅读:
    防疫流调溯源0.03先批量读取exel中的内容
    DVWA 靶场之 Command Injection(命令执行)middle&high
    RabbitMQ学习笔记
    Kubernetes-进阶(Pod生命周期/调度/控制器,Ingress代理,数据存储PV/PVC)
    排序算法(未完)
    《nginx》三、nginx负载均衡
    207. 课程表
    Java 修饰符2
    lamp环境搭建(kali,docker,ubuntu)
    C++ move()排序函数用法详解(深入了解,一文学会)
  • 原文地址:https://www.cnblogs.com/huaweiyun/p/18293366
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号